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