on 404abcb help sign in
bridge/src/views/Activate/ActivateCode.js
157 lines 4.8 kB history raw
1import React, { useCallback, useEffect, useState } from 'react';
2import { Just, Nothing } from 'folktale/maybe';
3import * as azimuth from 'azimuth-js';
4import { Grid, Input, H4, ErrorText } from 'indigo-react';
6import View from 'components/View';
7import { ForwardButton } from 'components/Buttons';
8import Passport from 'components/Passport';
10import { useHistory } from 'store/history';
12import { useTicketInput } from 'lib/useInputs';
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';
24import useImpliedTicket from 'lib/useImpliedTicket';
26export default function ActivateCode() {
27 const history = useHistory();
28 const { names, push } = useLocalRouter();
29 const { contracts } = useNetwork();
30 const impliedTicket = useImpliedTicket();
31 const [generalError, setGeneralError] = useState();
32 const [deriving, setDeriving] = useState(false);
33 const {
34 derivedWallet,
35 setDerivedWallet,
36 setInviteWallet,
37 derivedPoint,
38 setDerivedPoint,
39 } = useActivateFlow();
41 const [ticketInput, { pass: validTicket }] = useTicketInput({
42 name: 'ticket',
43 label: 'Code',
44 initialValue: impliedTicket || '',
45 autoFocus: true,
46 });
48 const goToLogin = useCallback(() => history.popAndPush(ROUTE_NAMES.LOGIN), [
49 history,
50 ]);
51 const goToDisclaimer = useCallback(() => push(names.DISCLAIMER), [
52 names,
53 push,
54 ]);
56 const pass = derivedWallet.matchWith({
57 Nothing: () => false,
58 Just: () => true,
59 });
61 useEffect(() => {
62 if (validTicket) {
63 const _contracts = need.contracts(contracts);
65 setDeriving(true);
66 // when the ticket becomes valid, derive the point
67 (async () => {
68 const { seed } = await generateTemporaryOwnershipWallet(
69 ticketInput.data
70 );
72 //TODO isn't all this accessible in the ownership object?
73 const inviteWallet = walletFromMnemonic(seed, DEFAULT_HD_PATH);
74 const _inviteWallet = need.wallet(inviteWallet);
76 const owned = await azimuth.azimuth.getOwnedPoints(
77 _contracts,
78 _inviteWallet.address
79 );
80 const transferring = await azimuth.azimuth.getTransferringFor(
81 _contracts,
82 _inviteWallet.address
83 );
84 const incoming = [...owned, ...transferring];
86 let realPoint = Nothing();
87 let wallet = Nothing();
89 if (incoming.length > 0) {
90 const pointNum = parseInt(incoming[0], 10);
91 realPoint = Just(pointNum);
92 wallet = Just(await generateWallet(pointNum));
94 if (incoming.length > 1) {
95 setGeneralError(
96 'This invite code has multiple points available.\n' +
97 "Once you've activated this point, activate the next with the same process."
98 );
99 }
100 } else {
101 setGeneralError(
102 'Invite code has no claimable point.\n' +
103 'Check your invite code and try again?'
104 );
105 }
107 setDerivedPoint(realPoint);
108 setDerivedWallet(wallet);
109 setInviteWallet(inviteWallet);
110 setDeriving(false);
111 })();
112 } else {
113 setGeneralError(false);
114 }
115 }, [
116 validTicket,
117 contracts,
118 ticketInput.data,
119 setDerivedPoint,
120 setDerivedWallet,
121 setInviteWallet,
122 ]);
124 // when we know the derived point, ensure we have the data to display it
125 useSyncKnownPoints([derivedPoint.getOrElse(null)].filter(p => p !== null));
127 return (
128 <View>
129 <Grid>
130 <Grid.Item as={Passport} point={derivedPoint} full />
131 <Grid.Item as={H4} className="mt3 mb2" full>
132 Activate
133 </Grid.Item>
134 <Grid.Item as={Input} {...ticketInput} full />
135 {generalError && (
136 <Grid.Item full>
137 <ErrorText>{generalError}</ErrorText>{' '}
138 </Grid.Item>
139 )}
140 <Grid.Item
141 as={ForwardButton}
142 className="mt4"
143 disabled={!pass || deriving}
144 accessory={deriving ? <Blinky /> : undefined}
145 onClick={goToDisclaimer}
146 solid
147 full>
148 {deriving && 'Deriving...'}
149 {!deriving && 'Go'}
150 </Grid.Item>
151 </Grid>
152 <FooterButton as={ForwardButton} onClick={goToLogin}>
153 Login
154 </FooterButton>
155 </View>
156 );