1//NOTE repurposed from /views/Activate/PassportTransfer,
2// with a lot of logic from /lib/useInviter
4//TODO display "you may now _close this window_" cta after calling a flow cb
5//TODO make sure we also call failure cb if we get closed prematurely
7import React, { useState, useCallback } from 'react';
8import { Grid, Text, ErrorText, H4 } from 'indigo-react';
9import cn from 'classnames';
10import ob from 'urbit-ob';
11import { toBN } from 'web3-utils';
13import { useNetwork } from 'store/network';
14import { useWallet } from 'store/wallet';
16import * as wg from 'lib/walletgen';
17import * as tank from 'lib/tank';
18import { GAS_LIMITS } from 'lib/constants';
21 sendSignedTransaction,
22 waitForTransactionConfirm,
25import useGasPrice from 'lib/useGasPrice';
26import useLifecycle from 'lib/useLifecycle';
27import useBlockWindowClose from 'lib/useBlockWindowClose';
28import { useFlowCommand } from 'lib/flowCommand';
29import { hasReceived, sendMail } from 'lib/inviteMail';
30import { safeToWei } from 'lib/lib';
32import LoadingBar from 'components/LoadingBar';
33import { RestartButton } from 'components/Buttons';
34import NeedFundsNotice from 'components/NeedFundsNotice';
36import * as az from 'azimuth-js';
38const labelForProgress = progress => {
40 return 'Checking sanity...';
41 } else if (progress <= 0.2) {
42 return 'Generating invite...';
43 } else if (progress <= 0.3) {
44 return 'Building transaction...';
45 } else if (progress <= 0.4) {
46 return 'Signing transaction...';
47 } else if (progress <= 0.5) {
48 return 'Funding transaction...';
49 } else if (progress <= 0.7) {
50 return 'Sending transaction...';
51 } else if (progress <= 0.9) {
52 return 'Sending invite email...';
58export default function JustInvite({ className, resetActivateRouter }) {
59 const { wallet, walletType, walletHdPath, authToken } = useWallet();
60 const flow = useFlowCommand();
61 const { web3, contracts, networkType } = useNetwork();
62 const { gasPrice } = useGasPrice();
63 const [generalError, setGeneralError] = useState();
64 const [progress, setProgress] = useState(0);
65 const [needFunds, setNeedFunds] = useState(null);
67 useBlockWindowClose();
72 // return setProcesss(state);
74 // return setNeedFunds(value);
76 // return setNeedFunds(false);
78 // console.error(`Unknown update: ${type}`);
82 const sendInvite = useCallback(async () => {
83 setGeneralError(false);
86 const _contracts = contracts.getOrElse(null);
87 const _web3 = web3.getOrElse(null);
88 const _wallet = wallet.getOrElse(null);
89 const _authToken = authToken.getOrElse(null);
90 if (!_contracts || !_web3 || !_wallet || !_authToken) {
91 // not using need because we want a custom error
92 throw new Error('Internal Error: Missing Contracts/Web3/Wallet');
95 const _as = ob.patp2dec(flow.as);
96 const _ship = ob.patp2dec(flow.ship);
97 const _email = flow.email;
99 console.log('xx checking email');
100 // check if email not invited before
101 if (await hasReceived(_email)) {
103 `This email (${_email}) has already received an invite.`
108 console.log('xx checking owner', _wallet.address, _as);
109 // check if logged in with flow.as's owner
110 //TODO we could move this check to the login screen
111 if (!(await az.azimuth.isOwner(_contracts, _as, _wallet.address))) {
112 throw new Error(`You are not logged in as ${flow.as}'s owner.'`);
116 // generate invite code + address
117 const { ticket, owner } = await wg.generateTemporaryDeterministicWallet(
123 // generate invite tx
124 const inviteTx = az.delegatedSending.sendPoint(
133 const signedTx = await signTransaction({
138 chainId: await _web3.eth.net.getId(),
139 nonce: await _web3.eth.getTransactionCount(_wallet.address),
141 gasPrice: gasPrice.toFixed(), // expects string gwei
142 gasLimit: GAS_LIMITS.GIFT_PLANET.toFixed(),
144 const rawTx = hexify(signedTx.serialize());
148 const totalCost = toBN(GAS_LIMITS.GIFT_PLANET).mul(toBN(gasPrice));
149 const tankWasUsed = await tank.ensureFundsFor(
154 safeToWei(totalCost, 'gwei'),
156 (address, minBalance, balance) =>
157 setNeedFunds({ address, minBalance, balance }),
158 () => setNeedFunds(undefined)
162 // send and await transaction
163 const txHash = await sendSignedTransaction(_web3, signedTx, tankWasUsed);
164 await waitForTransactionConfirm(_web3, txHash);
168 //NOTE we could chuck a "pls join group-name" message in here
169 await sendMail(_email, ticket, flow.as, '', rawTx);
172 // some generic error
173 setGeneralError(error);
191 const goToRestart = useCallback(() => {
195 const renderAdditionalInfo = () => {
197 console.log(generalError);
199 typeof generalError === 'string'
201 : generalError.message || 'Something went wrong!';
204 <Grid.Item full className="mt8">
205 <ErrorText>{msg}</ErrorText>
212 onClick={goToRestart}>
221 <Grid.Item full as={NeedFundsNotice} className="mt8" {...needFunds} />
225 // if (progress < 1.0) {
227 // <Grid.Item full as={WarningBox} className="mt8">
228 // Never give your Master Ticket to anyone
237 <Grid className={cn(className, 'auto-rows-min')}>
238 <Grid.Item full as={H4}>
239 {labelForProgress(progress)}
242 <Grid.Item full as={Grid} className="mt3" gap={3}>
243 <Grid.Item full as={LoadingBar} progress={progress} />
245 <Text className="f5 green4">
246 This process can take up to 5 minutes to complete. Don't close
247 this page until the process is complete.
252 {renderAdditionalInfo()}
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list