on master help sign in
feat: implement invite claiming tx, whole flow works
6468405Matt Condon (shrugs)
src/components/WarningBox.js+1−1
@@ -5,7 +5,7 @@ import { Flex, Text } from 'indigo-react';
5export default function WarningBox({ className, children }) {
5export default function WarningBox({ className, children }) {
6 return (
6 return (
7 <Flex className={cn('bg-red1 pv3 ph4', className)} align="center">
7 <Flex className={cn('bg-red1 pv3 ph4', className)} align="center">
8− <Text className="f5 red3">{children}</Text>
8+ <Text className="f6 fw-bold red3">{children}</Text>
9 </Flex>
9 </Flex>
10 );
10 );
11}
11}
src/indigo-react/components/Typography.js+1−1
@@ -14,7 +14,7 @@ export const H5 = typeWith('h5');
14export const H6 = typeWith('h6');
14export const H6 = typeWith('h6');
15export const Caption = typeWith('caption');
15export const Caption = typeWith('caption');
16export const P = typeWith('p');
16export const P = typeWith('p');
17−export const B = typeWith('b');
17+export const B = typeWith('b', 'fw-bold');
18
18
19export const Breadcrumb = typeWith('span', 'f6');
19export const Breadcrumb = typeWith('span', 'f6');
20export const Text = typeWith('span');
20export const Text = typeWith('span');
src/lib/invite.js+57−106
@@ -1,4 +1,4 @@
1−import { Just, Nothing } from 'folktale/maybe';
1+import { Just } from 'folktale/maybe';
2import Tx from 'ethereumjs-tx';
2import Tx from 'ethereumjs-tx';
3
3
4import * as azimuth from 'azimuth-js';
4import * as azimuth from 'azimuth-js';
@@ -9,8 +9,7 @@ import * as tank from './tank';
9import JSZip from 'jszip';
9import JSZip from 'jszip';
10import saveAs from 'file-saver';
10import saveAs from 'file-saver';
11
11
12−import { sendSignedTransaction } from './txn';
12+import { sendSignedTransaction, hexify } from './txn';
13−import { BRIDGE_ERROR } from './error';
14import { attemptNetworkSeedDerivation } from './keys';
13import { attemptNetworkSeedDerivation } from './keys';
15import { addHexPrefix, WALLET_TYPES } from './wallet';
14import { addHexPrefix, WALLET_TYPES } from './wallet';
16
15
@@ -32,36 +31,36 @@ const WALLET_STATES = {
32
31
33const TRANSACTION_STATES = {
32const TRANSACTION_STATES = {
34 GENERATING: {
33 GENERATING: {
35− label: 'Generating transactions',
34+ label: 'Generating Transactions...',
36− pct: '0%',
35+ progress: 0.0,
37 },
36 },
38 SIGNING: {
37 SIGNING: {
39− label: 'Signing transactions',
38+ label: 'Signing Transactions...',
40− pct: '15%',
39+ progress: 0.15,
41 },
40 },
42 FUNDING_INVITE: {
41 FUNDING_INVITE: {
43− label: 'Funding invite wallet',
42+ label: 'Funding Invite Wallet...',
44− pct: '30%',
43+ progress: 0.3,
45 },
44 },
46 CLAIMING: {
45 CLAIMING: {
47− label: 'Claiming invite',
46+ label: 'Claiming Invite...',
48− pct: '55%',
47+ progress: 0.55,
49 },
48 },
50 FUNDING_RECIPIENT: {
49 FUNDING_RECIPIENT: {
51− label: 'Funding recipient wallet',
50+ label: 'Funding Recipient Wallet...',
52− pct: '65%',
51+ progress: 0.65,
53 },
52 },
54 CONFIGURING: {
53 CONFIGURING: {
55− label: 'Configuring planet',
54+ label: 'Configuring Point...',
56− pct: '85%',
55+ progress: 0.85,
57 },
56 },
58 CLEANING: {
57 CLEANING: {
59− label: 'Cleaning up',
58+ label: 'Cleaning Up...',
60− pct: '95%',
59+ progress: 0.95,
61 },
60 },
62 DONE: {
61 DONE: {
63 label: 'Done',
62 label: 'Done',
64− pct: '100%',
63+ progress: 1.0,
65 },
64 },
66};
65};
67
66
@@ -102,93 +101,61 @@ async function downloadWallet(paper) {
102 });
101 });
103}
102}
104
103
105−async function startTransactions(args) {
104+async function claimPointFromInvite({
106− let {
105+ inviteWallet,
107− realPointM,
106+ wallet,
107+ point,
108− web3: web3M,
108+ web3,
109− contracts: contractsM,
109+ contracts,
110− inviteWalletM,
110+ onUpdate,
111− realWalletM,
111+}) {
112− setUrbitWallet,
113− updateProgress,
114− } = args;
115−
116− const askForFunding = (address, amount, current) => {
112+ const askForFunding = (address, minBalance, balance) =>
117− updateProgress({
113+ onUpdate({
118− type: 'notify',
114+ type: 'askFunding',
119− value: `Please make sure ${address} has at least ${amount} wei, we'll continue once that's true. Current balance: ${current}. Waiting`,
115+ value: { address, minBalance, balance },
120 });
116 });
121− };
122
117
123− if (Nothing.hasInstance(web3M)) {
118+ const gotFunding = () => onUpdate({ type: 'gotFunding' });
124− throw BRIDGE_ERROR.MISSING_WEB3;
119+ const progress = state => onUpdate({ type: 'progress', state });
125− }
126− const web3 = web3M.value;
127−
128− if (Nothing.hasInstance(contractsM)) {
129− throw BRIDGE_ERROR.MISSING_CONTRACTS;
130− }
131− const contracts = contractsM.value;
132−
133− if (Nothing.hasInstance(inviteWalletM)) {
134− throw BRIDGE_ERROR.MISSING_WALLET;
135− }
136− const inviteWallet = inviteWalletM.value;
137−
138− if (Nothing.hasInstance(realWalletM)) {
139− throw BRIDGE_ERROR.MISSING_WALLET;
140− }
141− const realWallet = realWalletM.value;
142−
143− // const realWallet = await urbitWalletFromTicket(args.realTicket, point);
144−
145− if (Nothing.hasInstance(realPointM)) {
146− throw BRIDGE_ERROR.MISSING_POINT;
147− }
148− const point = realPointM.value;
149
120
150 const inviteAddress = inviteWallet.address;
121 const inviteAddress = inviteWallet.address;
151− console.log('working as', inviteAddress);
152
122
153− // transfer from invite wallet to new wallet
123+ progress(TRANSACTION_STATES.GENERATING);
154
124
125+ // transfer from invite wallet to new wallet
155− let transferTx = azimuth.ecliptic.transferPoint(
126+ const transferTx = azimuth.ecliptic.transferPoint(
156 contracts,
127 contracts,
157 point,
128 point,
158− realWallet.ownership.keys.address
129+ wallet.ownership.keys.address
159 );
130 );
160 transferTx.gas = 500000; //TODO can maybe be lower?
131 transferTx.gas = 500000; //TODO can maybe be lower?
161
132
162 // ping gas tank with txs if needed
133 // ping gas tank with txs if needed
163−
164 let inviteNonce = await web3.eth.getTransactionCount(inviteAddress);
134 let inviteNonce = await web3.eth.getTransactionCount(inviteAddress);
165 transferTx.nonce = inviteNonce++;
135 transferTx.nonce = inviteNonce++;
166 transferTx.gasPrice = 20000000000; //NOTE we pay the premium for faster ux
136 transferTx.gasPrice = 20000000000; //NOTE we pay the premium for faster ux
167 transferTx.from = inviteAddress;
137 transferTx.from = inviteAddress;
168
138
139+ progress(TRANSACTION_STATES.SIGNING);
169− //NOTE using web3.eth.accounts.signTransaction is broken (1.0.0-beta51)
140+ // NOTE: using web3.eth.accounts.signTransaction is broken (1.0.0-beta51)
170− let transferStx = new Tx(transferTx);
141+ const transferStx = new Tx(transferTx);
171 transferStx.sign(inviteWallet.privateKey);
142 transferStx.sign(inviteWallet.privateKey);
172− let rawTransferStx = '0x' + transferStx.serialize().toString('hex');
143+ const rawTransferStx = hexify(transferStx.serialize());
173−
174 const transferCost = transferTx.gas * transferTx.gasPrice;
144 const transferCost = transferTx.gas * transferTx.gasPrice;
175− updateProgress({
145+
176− type: 'progress',
177− value: TRANSACTION_STATES.FUNDING_INVITE,
146+ progress(TRANSACTION_STATES.FUNDING_INVITE);
178− });
147+
179 let usedTank = await tank.ensureFundsFor(
148 let usedTank = await tank.ensureFundsFor(
180 web3,
149 web3,
181 point,
150 point,
182 inviteAddress,
151 inviteAddress,
183 transferCost,
152 transferCost,
184 [rawTransferStx],
153 [rawTransferStx],
185− askForFunding
154+ askForFunding,
155+ gotFunding
186 );
156 );
187
157
188− updateProgress({
189− type: 'progress',
190− value: TRANSACTION_STATES.CLAIMING,
158+ progress(TRANSACTION_STATES.CLAIMING);
191− });
192
159
193 // send transaction
160 // send transaction
194 await sendAndAwaitConfirm(web3, [Just(transferStx)], usedTank);
161 await sendAndAwaitConfirm(web3, [Just(transferStx)], usedTank);
@@ -197,15 +164,13 @@ async function startTransactions(args) {
197 // we're gonna be operating as the new wallet from here on out, so change
164 // we're gonna be operating as the new wallet from here on out, so change
198 // the relevant values
165 // the relevant values
199 //
166 //
200− setUrbitWallet(Just(realWallet));
201− const newAddress = realWallet.ownership.keys.address;
167+ const newAddress = wallet.ownership.keys.address;
202
168
203 // configure management proxy
169 // configure management proxy
204−
205− let managementTx = azimuth.ecliptic.setManagementProxy(
170+ const managementTx = azimuth.ecliptic.setManagementProxy(
206 contracts,
171 contracts,
207 point,
172 point,
208− realWallet.management.keys.address
173+ wallet.management.keys.address
209 );
174 );
210 managementTx.gas = 200000;
175 managementTx.gas = 200000;
211 managementTx.nonce = 0;
176 managementTx.nonce = 0;
@@ -214,7 +179,7 @@ async function startTransactions(args) {
214 //TODO feels like more of this logic should live in a lib?
179 //TODO feels like more of this logic should live in a lib?
215 const seed = await attemptNetworkSeedDerivation(true, {
180 const seed = await attemptNetworkSeedDerivation(true, {
216 walletType: WALLET_TYPES.TICKET,
181 walletType: WALLET_TYPES.TICKET,
217− urbitWallet: Just(realWallet),
182+ urbitWallet: Just(wallet),
218 pointCursor: Just(point),
183 pointCursor: Just(point),
219 pointCache: { [point]: { keyRevisionNumber: 0 } },
184 pointCache: { [point]: { keyRevisionNumber: 0 } },
220 });
185 });
@@ -251,17 +216,15 @@ async function startTransactions(args) {
251
216
252 let txPairs = txs.map(tx => {
217 let txPairs = txs.map(tx => {
253 let stx = new Tx(tx);
218 let stx = new Tx(tx);
254− stx.sign(Buffer.from(realWallet.ownership.keys.private, 'hex'));
219+ stx.sign(Buffer.from(wallet.ownership.keys.private, 'hex'));
255 return {
220 return {
256 raw: '0x' + stx.serialize().toString('hex'),
221 raw: '0x' + stx.serialize().toString('hex'),
257 signed: stx,
222 signed: stx,
258 };
223 };
259 });
224 });
260
225
261− updateProgress({
262− type: 'progress',
263− value: TRANSACTION_STATES.FUNDING_RECIPIENT,
226+ progress(TRANSACTION_STATES.FUNDING_RECIPIENT);
264− });
227+
265 usedTank = await tank.ensureFundsFor(
228 usedTank = await tank.ensureFundsFor(
266 web3,
229 web3,
267 point,
230 point,
@@ -271,17 +234,11 @@ async function startTransactions(args) {
271 askForFunding
234 askForFunding
272 );
235 );
273
236
274− updateProgress({
275− type: 'progress',
276− value: TRANSACTION_STATES.CONFIGURING,
237+ progress(TRANSACTION_STATES.CONFIGURING);
277− });
278
238
279 await sendAndAwaitConfirm(web3, txPairs.map(p => Just(p.signed)), usedTank);
239 await sendAndAwaitConfirm(web3, txPairs.map(p => Just(p.signed)), usedTank);
280
240
281− updateProgress({
282− type: 'progress',
283− value: TRANSACTION_STATES.CLEANING,
241+ progress(TRANSACTION_STATES.CLEANING);
284− });
285
242
286 // if non-trivial eth left in invite wallet, transfer to new ownership
243 // if non-trivial eth left in invite wallet, transfer to new ownership
287 let balance = await web3.eth.getBalance(inviteAddress);
244 let balance = await web3.eth.getBalance(inviteAddress);
@@ -300,20 +257,14 @@ async function startTransactions(args) {
300 };
257 };
301 let stx = new Tx(tx);
258 let stx = new Tx(tx);
302 stx.sign(inviteWallet.privateKey);
259 stx.sign(inviteWallet.privateKey);
303− const rawTx = '0x' + stx.serialize().toString('hex');
260+ const rawTx = hexify(stx.serialize());
304 web3.eth.sendSignedTransaction(rawTx).catch(err => {
261 web3.eth.sendSignedTransaction(rawTx).catch(err => {
305 console.log('error sending value tx, who cares', err);
262 console.log('error sending value tx, who cares', err);
306 });
263 });
307 console.log('sent old balance');
264 console.log('sent old balance');
308 }
265 }
309
266
310− updateProgress({
311− type: 'progress',
312− value: TRANSACTION_STATES.DONE,
267+ progress(TRANSACTION_STATES.DONE);
313− });
314−
315− // proceed without waiting for confirm
316− setUrbitWallet(Just(realWallet));
317}
268}
318
269
319async function sendAndAwaitConfirm(web3, signedTxs, usedTank) {
270async function sendAndAwaitConfirm(web3, signedTxs, usedTank) {
@@ -329,7 +280,7 @@ async function sendAndAwaitConfirm(web3, signedTxs, usedTank) {
329export {
280export {
330 generateWallet,
281 generateWallet,
331 downloadWallet,
282 downloadWallet,
332− startTransactions,
283+ claimPointFromInvite,
333 INVITE_STAGES,
284 INVITE_STAGES,
334 WALLET_STATES,
285 WALLET_STATES,
335 TRANSACTION_STATES,
286 TRANSACTION_STATES,
src/lib/timeout.jsnew file+1
@@ -0,0 +1 @@
1+export default ms => new Promise(resolve => setTimeout(resolve, ms));
src/lib/useResetPointCursor.jsnew file+12
@@ -0,0 +1,12 @@
1+import { useEffect } from 'react';
2+import Maybe from 'folktale/maybe';
3+
4+import { usePointCursor } from 'store/pointCursor';
5+
6+export default function useResetPointCursor() {
7+ const { setPointCursor } = usePointCursor();
8+
9+ useEffect(() => {
10+ setPointCursor(Maybe.Nothing());
11+ }, [setPointCursor]);
12+}
src/views/Activate/ActivateDisclaimer.js+16−16
@@ -23,49 +23,49 @@ export default function ActivateDisclaimer() {
23 Disclaimer
23 Disclaimer
24 </Grid.Item>
24 </Grid.Item>
25 <Grid.Item full>
25 <Grid.Item full>
26− <P>
26+ <Text className="f6 block mb4">
27 Welcome to Bridge. Please read this information. Your assets could
27 Welcome to Bridge. Please read this information. Your assets could
28 be stolen if you do not pay attention to these warnings.
28 be stolen if you do not pay attention to these warnings.
29− </P>
29+ </Text>
30
30
31− <P>
31+ <Text className="f6 block mb4">
32 <B>You own and control your assets. We do not.</B> If you send your
32 <B>You own and control your assets. We do not.</B> If you send your
33 assets to another address, we can’t get them back for you.
33 assets to another address, we can’t get them back for you.
34− </P>
34+ </Text>
35
35
36− <B>Please understand that nobody can:</B>
36+ <B className="f6">Please understand that nobody can:</B>
37− <P>
37+ <Text className="f6 block mb4">
38 1. Access your assets for you <br />
38 1. Access your assets for you <br />
39 2. Recover, reset, or modify ANY of your information <br />
39 2. Recover, reset, or modify ANY of your information <br />
40 3. Reverse, cancel, or refund transactions <br />
40 3. Reverse, cancel, or refund transactions <br />
41 4. Hold, back-up, or access your keys
41 4. Hold, back-up, or access your keys
42− </P>
42+ </Text>
43
43
44− <B>
44+ <B className="f6">
45 You’re responsible for keeping your information safe. This includes:
45 You’re responsible for keeping your information safe. This includes:
46 </B>
46 </B>
47− <P>
47+ <Text className="f6 block mb4">
48 1. Private Keys/Mnemonic Phrases and passwords <br />
48 1. Private Keys/Mnemonic Phrases and passwords <br />
49 2. JSON files <br />
49 2. JSON files <br />
50 3. Hardware wallet PINs; <br />
50 3. Hardware wallet PINs; <br />
51 4. Downloading this software from a reliable site, and ensuring it
51 4. Downloading this software from a reliable site, and ensuring it
52 has not been tampered with. [add something about using the checksum
52 has not been tampered with. [add something about using the checksum
53 here]
53 here]
54− </P>
54+ </Text>
55
55
56− <B>To be clear</B>
56+ <B className="f6">To be clear</B>
57− <P>
57+ <Text className="f6 block">
58 This software is provided “as is” without warranties of any kind and
58 This software is provided “as is” without warranties of any kind and
59 our liability to you in connection with the same is limited;
59 our liability to you in connection with the same is limited;
60− </P>
60+ </Text>
61− <P>
61+ <Text className="f6 block">
62 We have no liability for any security problems or incidents that you
62 We have no liability for any security problems or incidents that you
63 may experience, including any loss or theft of your keys or any
63 may experience, including any loss or theft of your keys or any
64 problems that may arise in connection with your wallet.
64 problems that may arise in connection with your wallet.
65− </P>
65+ </Text>
66 </Grid.Item>
66 </Grid.Item>
67 <Grid.Item full as={WarningBox}>
67 <Grid.Item full as={WarningBox}>
68− Warning: We Can't Restore of Reset Your Master Ticket
68+ Warning: Nobody but you can restore or reset your Master Ticket
69 </Grid.Item>
69 </Grid.Item>
70 <Grid.Item as={CheckboxInput} {...checkboxInput} full />
70 <Grid.Item as={CheckboxInput} {...checkboxInput} full />
71 <Grid.Item
71 <Grid.Item
src/views/Activate/PassportTransfer.js+119−34
@@ -1,64 +1,149 @@
1−import React, { useState, useEffect, useCallback } from 'react';
1+import React, { useState, useCallback } from 'react';
2−import Maybe from 'folktale/maybe';
3−import { Grid, H4, P, Text } from 'indigo-react';
2+import { Grid, H4, Text, ErrorText } from 'indigo-react';
4−import PaperCollateralRenderer from 'PaperCollateralRenderer';
3+
4+import { useNetwork } from 'store/network';
5+import { useWallet } from 'store/wallet';
6+import { useHistory } from 'store/history';
7+import { usePointCursor } from 'store/pointCursor';
5
8
6import * as need from 'lib/need';
9import * as need from 'lib/need';
7−import { useLocalRouter } from 'lib/LocalRouter';
10+import useLifecycle from 'lib/useLifecycle';
11+import { claimPointFromInvite } from 'lib/invite';
12+import timeout from 'lib/timeout';
13+import { fromWei } from 'lib/txn';
8
14
9−import { DownloadButton, ForwardButton } from 'components/Buttons';
10import Steps from 'components/Steps';
15import Steps from 'components/Steps';
11−
12−import { useActivateFlow } from './ActivateFlow';
13−import useLifecycle from 'lib/useLifecycle';
14import WarningBox from 'components/WarningBox';
16import WarningBox from 'components/WarningBox';
15import LoadingBar from 'components/LoadingBar';
17import LoadingBar from 'components/LoadingBar';
18+import Highlighted from 'components/Highlighted';
16
19
17−const STATUS = {
20+import { useActivateFlow } from './ActivateFlow';
18− CLAIMING: 'CLAIMING',
19− NETWORKING: 'NETWORKING',
20− REDIRECTING: 'REDIRECTING',
21−};
22
21
23export default function PassportTransfer({ className }) {
22export default function PassportTransfer({ className }) {
23+ const { replaceWith, names } = useHistory();
24+ const { setUrbitWallet } = useWallet();
25+ const { setPointCursor } = usePointCursor();
26+ const { web3, contracts } = useNetwork();
24 const { derivedWallet, derivedPoint, inviteWallet } = useActivateFlow();
27 const { derivedWallet, derivedPoint, inviteWallet } = useActivateFlow();
25− const [status, setStatus] = useState(STATUS.CLAIMING);
28+ const [generalError, setGeneralError] = useState();
26− const isClaiming = status === STATUS.CLAIMING;
29+ const [{ label, progress }, setState] = useState({
30+ label: 'Verify Passport',
31+ progress: 0,
32+ });
33+ const [needFunds, setNeedFunds] = useState();
34+
35+ const goToLogin = useCallback(
36+ () =>
37+ replaceWith([
38+ { key: names.LANDING },
39+ { key: names.LOGIN },
40+ { key: names.POINTS },
41+ { key: names.POINT },
42+ ]),
43+ [replaceWith, names]
44+ );
45+
46+ const goToRestart = useCallback(
47+ () => replaceWith([{ key: names.LANDING }, { key: names.ACTIVATE }]),
48+ [replaceWith, names]
49+ );
27
50
28− const titleText = (() => {
51+ const handleUpdate = useCallback(
52+ ({ type, state, value }) => {
29− switch (status) {
53+ switch (type) {
30− case STATUS.CLAIMING:
54+ case 'progress':
31− return 'Claiming Point';
55+ return setState(state);
32− case STATUS.NETWORKING:
56+ case 'askFunding':
33− return 'Setting Networking Keys';
57+ return setNeedFunds(value);
34− case STATUS.REDIRECTING:
58+ case 'gotFunding':
35− return 'Transporting to Bridge';
59+ return setNeedFunds(false);
36− default:
60+ default:
37− break;
61+ console.error(`Unknown update: ${type}`);
62+ }
63+ },
64+ [setState, setNeedFunds]
65+ );
66+
67+ const claimPoint = useCallback(async () => {
68+ const _inviteWallet = need.wallet(inviteWallet);
69+ const _wallet = need.wallet(derivedWallet);
70+ const _point = need.point(derivedPoint);
71+ const _web3 = need.web3(web3);
72+ const _contracts = need.contracts(contracts);
73+
74+ try {
75+ await claimPointFromInvite({
76+ inviteWallet: _inviteWallet,
77+ wallet: _wallet,
78+ point: _point,
79+ web3: _web3,
80+ contracts: _contracts,
81+ onUpdate: handleUpdate,
82+ });
83+ // set the global wallet
84+ setUrbitWallet(derivedWallet);
85+ setPointCursor(derivedPoint);
86+ await timeout(3000);
87+ // and redirect to login
88+ goToLogin();
89+ } catch (error) {
90+ // some generic error
91+ setGeneralError(error);
38 }
92 }
93+ }, [
94+ inviteWallet,
95+ derivedWallet,
96+ derivedPoint,
97+ web3,
98+ contracts,
99+ setUrbitWallet,
100+ setPointCursor,
101+ handleUpdate,
102+ goToLogin,
39− })();
103+ ]);
40
104
41 useLifecycle(() => {
105 useLifecycle(() => {
42− // on mount, start transactions
106+ claimPoint();
43 });
107 });
44
108
45 return (
109 return (
46 <Grid gap={4} className={className}>
110 <Grid gap={4} className={className}>
47 <Grid.Item full as={Steps} num={2} total={3} />
111 <Grid.Item full as={Steps} num={2} total={3} />
48 <Grid.Item full as={H4}>
112 <Grid.Item full as={H4}>
49− {titleText}
113+ {label}
50 </Grid.Item>
114 </Grid.Item>
51− <Grid.Item full as={LoadingBar} progress={0.5} />
115+ <Grid.Item full as={Grid}>
116+ <Grid.Item full as={LoadingBar} progress={progress} />
117+ <Grid.Item full>
52− <Grid.Item full as={Text} className="green4">
118+ <Text className="f5 green4">
53− This process can take up to 5 minutes to complete. Don't leave this page
119+ This process can take up to 5 minutes to complete. Don't leave this
54− until the process is complete.
120+ page until the process is complete.
121+ </Text>
122+ </Grid.Item>
55 </Grid.Item>
123 </Grid.Item>
56
124
57− {isClaiming && (
125+ {progress < 0 && (
58 <Grid.Item full as={WarningBox}>
126 <Grid.Item full as={WarningBox}>
59 Never give your Master Ticket to anyone
127 Never give your Master Ticket to anyone
60 </Grid.Item>
128 </Grid.Item>
61 )}
129 )}
130+
131+ {needFunds && (
132+ <Grid.Item full>
133+ <Highlighted>
134+ The address {needFunds.address} needs at least{' '}
135+ {fromWei(needFunds.minBalance)} ETH and currently has{' '}
136+ {fromWei(needFunds.balance)} ETH. Waiting until the account has
137+ enough funds.
138+ </Highlighted>
139+ </Grid.Item>
140+ )}
141+
142+ {generalError && (
143+ <Grid.Item full>
144+ <ErrorText>{generalError.message.toString()}</ErrorText>
145+ </Grid.Item>
146+ )}
62 </Grid>
147 </Grid>
63 );
148 );
64}
149}
src/views/Activate/PassportVerify.js+5−7
@@ -1,5 +1,5 @@
1import React, { useCallback, useMemo } from 'react';
1import React, { useCallback, useMemo } from 'react';
2−import { Grid, H4, P, Input } from 'indigo-react';
2+import { Grid, H4, P, Input, Text } from 'indigo-react';
3
3
4import * as need from 'lib/need';
4import * as need from 'lib/need';
5import { useLocalRouter } from 'lib/LocalRouter';
5import { useLocalRouter } from 'lib/LocalRouter';
@@ -36,12 +36,10 @@ export default function PassportVerify({ className }) {
36 <Grid.Item full as={H4}>
36 <Grid.Item full as={H4}>
37 Verify Passport
37 Verify Passport
38 </Grid.Item>
38 </Grid.Item>
39− <Grid.Item full>
39+ <Grid.Item full as={Text} className="f5">
40− <P>
41− After you download your passport, verify your custody. Your passport
40+ After you download your passport, verify your custody. Your passport
42− should be a folder of image files. One of them is your Master Ticket.
41+ should be a folder of image files. One of them is your Master Ticket.
43− Open it and enter the 4 word phrase below (with hyphens).
42+ Open it and enter the 4 word phrase below (with hyphens).
44− </P>
45 </Grid.Item>
43 </Grid.Item>
46 <Grid.Item full as={Input} {...ticketInput} />
44 <Grid.Item full as={Input} {...ticketInput} />
47 <Grid.Item
45 <Grid.Item
src/views/InviteTicket.js+2−2
@@ -28,7 +28,7 @@ import {
28 WALLET_STATES,
28 WALLET_STATES,
29 TRANSACTION_STATES,
29 TRANSACTION_STATES,
30} from '../lib/invite';
30} from '../lib/invite';
31−import { generateWallet, startTransactions } from '../lib/invite';
31+import { generateWallet, claimPointFromInvite } from '../lib/invite';
32import { withNetwork } from '../store/network';
32import { withNetwork } from '../store/network';
33import { withWallet } from '../store/wallet';
33import { withWallet } from '../store/wallet';
34import { Grid } from 'indigo-react';
34import { Grid } from 'indigo-react';
@@ -303,7 +303,7 @@ class InviteTicket extends React.Component {
303 ),
303 ),
304 });
304 });
305
305
306− startTransactions({
306+ claimPointFromInvite({
307 inviteWalletM: inviteWallet,
307 inviteWalletM: inviteWallet,
308 realWalletM: realWallet,
308 realWalletM: realWallet,
309 realPointM: realPoint,
309 realPointM: realPoint,
src/views/Login/Keystore.js+2
@@ -14,8 +14,10 @@ import { useWallet } from 'store/wallet';
14import * as need from 'lib/need';
14import * as need from 'lib/need';
15import { EthereumWallet, WALLET_TYPES } from 'lib/wallet';
15import { EthereumWallet, WALLET_TYPES } from 'lib/wallet';
16import useWalletType from 'lib/useWalletType';
16import useWalletType from 'lib/useWalletType';
17+import useResetPointCursor from 'lib/useResetPointCursor';
17
18
18export default function Keystore({ loginCompleted }) {
19export default function Keystore({ loginCompleted }) {
20+ useResetPointCursor();
19 useWalletType(WALLET_TYPES.KEYSTORE);
21 useWalletType(WALLET_TYPES.KEYSTORE);
20
22
21 // globals
23 // globals
src/views/Login/Ledger.js+2
@@ -16,6 +16,7 @@ import { useWallet } from 'store/wallet';
16import { LEDGER_LIVE_PATH, LEDGER_LEGACY_PATH } from 'lib/ledger';
16import { LEDGER_LIVE_PATH, LEDGER_LEGACY_PATH } from 'lib/ledger';
17import useWalletType from 'lib/useWalletType';
17import useWalletType from 'lib/useWalletType';
18import { WALLET_TYPES } from 'lib/wallet';
18import { WALLET_TYPES } from 'lib/wallet';
19+import useResetPointCursor from 'lib/useResetPointCursor';
19
20
20const pathOptions = [
21const pathOptions = [
21 { title: 'Ledger Live', value: LEDGER_LIVE_PATH },
22 { title: 'Ledger Live', value: LEDGER_LIVE_PATH },
@@ -28,6 +29,7 @@ const chopHdPrefix = str => (str.slice(0, 2) === 'm/' ? str.slice(2) : str);
28const addHdPrefix = str => (str.slice(0, 2) === 'm/' ? str : 'm/' + str);
29const addHdPrefix = str => (str.slice(0, 2) === 'm/' ? str : 'm/' + str);
29
30
30export default function Ledger({ loginCompleted }) {
31export default function Ledger({ loginCompleted }) {
32+ useResetPointCursor();
31 useWalletType(WALLET_TYPES.LEDGER);
33 useWalletType(WALLET_TYPES.LEDGER);
32
34
33 const { wallet, setWallet, setWalletHdPath } = useWallet();
35 const { wallet, setWallet, setWalletHdPath } = useWallet();
src/views/Login/Mnemonic.js+3
@@ -14,9 +14,12 @@ import { useWallet } from 'store/wallet';
14
14
15import { walletFromMnemonic, WALLET_TYPES } from 'lib/wallet';
15import { walletFromMnemonic, WALLET_TYPES } from 'lib/wallet';
16import useWalletType from 'lib/useWalletType';
16import useWalletType from 'lib/useWalletType';
17+import useResetPointCursor from 'lib/useResetPointCursor';
17
18
18export default function Mnemonic({ advanced, loginCompleted }) {
19export default function Mnemonic({ advanced, loginCompleted }) {
20+ useResetPointCursor();
19 useWalletType(WALLET_TYPES.MNEMONIC);
21 useWalletType(WALLET_TYPES.MNEMONIC);
22+
20 const {
23 const {
21 wallet,
24 wallet,
22 setWallet,
25 setWallet,
src/views/Login/PrivateKey.js+2
@@ -10,8 +10,10 @@ import { useWallet } from 'store/wallet';
10
10
11import { EthereumWallet, WALLET_TYPES } from 'lib/wallet';
11import { EthereumWallet, WALLET_TYPES } from 'lib/wallet';
12import useWalletType from 'lib/useWalletType';
12import useWalletType from 'lib/useWalletType';
13+import useResetPointCursor from 'lib/useResetPointCursor';
13
14
14export default function PrivateKey({ loginCompleted }) {
15export default function PrivateKey({ loginCompleted }) {
16+ useResetPointCursor();
15 useWalletType(WALLET_TYPES.PRIVATE_KEY);
17 useWalletType(WALLET_TYPES.PRIVATE_KEY);
16 const { wallet, setWallet } = useWallet();
18 const { wallet, setWallet } = useWallet();
17
19
src/views/Login/Shards.js+2
@@ -15,8 +15,10 @@ import { useWallet } from 'store/wallet';
15
15
16import { urbitWalletFromTicket, WALLET_TYPES } from 'lib/wallet';
16import { urbitWalletFromTicket, WALLET_TYPES } from 'lib/wallet';
17import useWalletType from 'lib/useWalletType';
17import useWalletType from 'lib/useWalletType';
18+import useResetPointCursor from 'lib/useResetPointCursor';
18
19
19export default function Shards({ loginCompleted }) {
20export default function Shards({ loginCompleted }) {
21+ useResetPointCursor();
20 useWalletType(WALLET_TYPES.SHARDS);
22 useWalletType(WALLET_TYPES.SHARDS);
21
23
22 const { wallet, setUrbitWallet } = useWallet();
24 const { wallet, setUrbitWallet } = useWallet();
src/views/Login/Ticket.js+2
@@ -19,6 +19,7 @@ import { usePointCursor } from 'store/pointCursor';
19import * as need from 'lib/need';
19import * as need from 'lib/need';
20import { WALLET_TYPES, urbitWalletFromTicket } from 'lib/wallet';
20import { WALLET_TYPES, urbitWalletFromTicket } from 'lib/wallet';
21import useWalletType from 'lib/useWalletType';
21import useWalletType from 'lib/useWalletType';
22+import useResetPointCursor from 'lib/useResetPointCursor';
22
23
23//TODO should be part of InputWithStatus component
24//TODO should be part of InputWithStatus component
24const INPUT_STATUS = {
25const INPUT_STATUS = {
@@ -28,6 +29,7 @@ const INPUT_STATUS = {
28};
29};
29
30
30export default function Ticket({ advanced, loginCompleted }) {
31export default function Ticket({ advanced, loginCompleted }) {
32+ useResetPointCursor();
31 useWalletType(WALLET_TYPES.TICKET);
33 useWalletType(WALLET_TYPES.TICKET);
32 // globals
34 // globals
33 const { contracts } = useNetwork();
35 const { contracts } = useNetwork();
src/views/Login/Trezor.js+2
@@ -13,6 +13,7 @@ import { InnerLabelDropdown } from 'components/old/Base';
13import { TREZOR_PATH } from 'lib/trezor';
13import { TREZOR_PATH } from 'lib/trezor';
14import useWalletType from 'lib/useWalletType';
14import useWalletType from 'lib/useWalletType';
15import { WALLET_TYPES } from 'lib/wallet';
15import { WALLET_TYPES } from 'lib/wallet';
16+import useResetPointCursor from 'lib/useResetPointCursor';
16
17
17import { useWallet } from 'store/wallet';
18import { useWallet } from 'store/wallet';
18
19
@@ -22,6 +23,7 @@ const accountOptions = [
22];
23];
23
24
24export default function Trezor({ loginCompleted }) {
25export default function Trezor({ loginCompleted }) {
26+ useResetPointCursor();
25 useWalletType(WALLET_TYPES.TREZOR);
27 useWalletType(WALLET_TYPES.TREZOR);
26
28
27 const { wallet, setWallet, setWalletHdPath } = useWallet();
29 const { wallet, setWallet, setWalletHdPath } = useWallet();