on 30fffab help sign in
bridge/src/views/Activate/ActivateCode.js
163 lines 4.8 kB history raw
1import React, { useCallback, useEffect, useState } from 'react';
2import * as azimuth from 'azimuth-js';
3import Maybe from 'folktale/maybe';
4import { useTicketInput } from 'components/Inputs';
5import { Grid, Input, H4, ErrorText } from 'indigo-react';
7import View from 'components/View';
8import { ForwardButton, OfflineButton } from 'components/Buttons';
9import Passport from 'components/Passport';
11import { useHistory } from 'store/history';
13import * as need from 'lib/need';
14import { ROUTE_NAMES } from 'lib/routeNames';
15import { useSyncKnownPoints } from 'lib/useSyncPoints';
16import FooterButton from 'components/FooterButton';
17import Blinky from 'components/Blinky';
18import { DEFAULT_HD_PATH, walletFromMnemonic } from 'lib/wallet';
19import { useNetwork } from 'store/network';
20import { generateWallet } from 'lib/invite';
21import { generateTemporaryOwnershipWallet } from 'lib/walletgen';
22import { useActivateFlow } from './ActivateFlow';
23import { useLocalRouter } from 'lib/LocalRouter';
25export default function ActivateCode() {
26 const history = useHistory();
27 const { names, push } = useLocalRouter();
28 const { contracts } = useNetwork();
29 const [generalError, setGeneralError] = useState();
30 const [deriving, setDeriving] = useState(false);
31 const {
32 derivedWallet,
33 setDerivedWallet,
34 setInviteWallet,
35 derivedPoint,
36 setDerivedPoint,
37 } = useActivateFlow();
39 const ticketInput = useTicketInput({
40 name: 'ticket',
41 label: 'Code',
42 autoFocus: true,
43 });
44 const validTicket = ticketInput.pass;
46 const goToLogin = useCallback(() => history.popAndPush(ROUTE_NAMES.LOGIN), [
47 history,
48 ]);
49 const goToDisclaimer = useCallback(() => push(names.DISCLAIMER), [
50 names,
51 push,
52 ]);
54 const pass = derivedWallet.matchWith({
55 Nothing: () => false,
56 Just: () => true,
57 });
59 useEffect(() => {
60 if (validTicket) {
61 const _contracts = need.contracts(contracts);
63 setDeriving(true);
64 // when the ticket becomes valid, derive the point
65 (async () => {
66 const { seed } = await generateTemporaryOwnershipWallet(
67 ticketInput.data
68 );
70 //TODO isn't all this accessible in the ownership object?
71 const inviteWallet = walletFromMnemonic(
72 seed,
73 DEFAULT_HD_PATH
74 ).matchWith({
75 Just: w => w.value,
76 Nothing: () => {
77 setGeneralError('Derivation Error: invalid derived seed.');
78 throw new Error();
79 },
80 });
82 const incoming = await azimuth.azimuth.getTransferringFor(
83 _contracts,
84 inviteWallet.address
85 );
87 let realPoint = Maybe.Nothing();
88 let realWallet = Maybe.Nothing();
90 if (incoming.length > 0) {
91 let pointNum = parseInt(incoming[0], 10);
92 realPoint = Maybe.Just(pointNum);
94 const genWallet = await generateWallet(pointNum);
96 realWallet = Maybe.Just(genWallet);
97 if (incoming.length > 1) {
98 setGeneralError(
99 'This invite code has multiple points available.\n' +
100 "Once you've activated this point, activate the next with the same process."
101 );
102 }
103 } else {
104 setGeneralError(
105 'Invite code has no claimable point.\n' +
106 'Check your invite code and try again?'
107 );
108 }
110 setDerivedPoint(realPoint);
111 setDerivedWallet(realWallet);
112 setInviteWallet(Maybe.Just(inviteWallet));
113 setDeriving(false);
114 })();
115 } else {
116 setGeneralError(false);
117 }
118 }, [
119 validTicket,
120 contracts,
121 ticketInput.data,
122 setDerivedPoint,
123 setDerivedWallet,
124 setInviteWallet,
125 ]);
127 // when we know the derived point, ensure we have the data to display it
128 useSyncKnownPoints([derivedPoint.getOrElse(null)].filter(p => p !== null));
130 return (
131 <View>
132 <Grid>
133 <Grid.Item as={Passport} point={derivedPoint} full />
134 <Grid.Item as={H4} className="mt3 mb2" full>
135 Activate
136 </Grid.Item>
137 <Grid.Item as={Input} {...ticketInput} full />
138 {generalError && (
139 <Grid.Item full>
140 <ErrorText>{generalError}</ErrorText>{' '}
141 </Grid.Item>
142 )}
143 <Grid.Item
144 as={ForwardButton}
145 className="mt4"
146 disabled={!pass || deriving}
147 accessory={deriving ? <Blinky /> : null}
148 onClick={goToDisclaimer}
149 solid
150 full>
151 {deriving && 'Deriving...'}
152 {!deriving && 'Go'}
153 </Grid.Item>
154 <Grid.Divider className="mt3" />
155 <Grid.Item as={ForwardButton} onClick={goToLogin} full>
156 Login
157 </Grid.Item>
158 <Grid.Divider />
159 </Grid>
160 <FooterButton as={OfflineButton} />
161 </View>
162 );