@@ -1,434 +0,0 @@
1−import { Just, Nothing } from 'folktale/maybe';
2−import React from 'react';
3−import * as azimuth from 'azimuth-js';
4−import * as need from 'lib/need';
5−
6−import View from 'components/View';
7−
8−import {
9− InnerLabel,
10− Warning,
11− TicketInput,
12− VerifyTicketInput,
13− Button,
14− Passport,
15−} from '../components/old/Base';
16−
17−import { randomPatq, compose } from '../lib/lib';
18−import { ROUTE_NAMES } from '../lib/routeNames';
19−import { withHistory } from '../store/history';
20−import {
21− DEFAULT_HD_PATH,
22− ownershipWalletFromTicket,
23− walletFromMnemonic,
24−} from '../lib/wallet';
25−import { BRIDGE_ERROR } from '../lib/error';
26−import {
27− INVITE_STAGES,
28− WALLET_STATES,
29− TRANSACTION_STATES,
30−} from '../lib/invite';
31−import { generateWallet, startTransactions } from '../lib/invite';
32−import { withNetwork } from '../store/network';
33−import { withWallet } from '../store/wallet';
34−import { Grid } from 'indigo-react';
35−
36−class InviteTicket extends React.Component {
37− constructor(props) {
38− super(props);
39−
40− this.state = {
41− inviteTicket: '',
42− inviteWallet: Nothing(),
43− verifyTicket: '',
44− realTicket: '',
45− realPoint: Nothing(),
46− realWallet: Nothing(),
47− walletReady: false,
48− walletStates: [],
49− errors: [],
50− stage: INVITE_STAGES.INVITE_LOGIN,
51− transactionProgress: TRANSACTION_STATES.GENERATING,
52− };
53−
54− this.pointPlaceholder = randomPatq(4);
55− this.ticketPlaceholder = randomPatq(12);
56−
57− this.handleInviteTicketInput = this.handleInviteTicketInput.bind(this);
58− this.handleVerifyTicketInput = this.handleVerifyTicketInput.bind(this);
59− this.updateProgress = this.updateProgress.bind(this);
60− this.pushWalletState = this.pushWalletState.bind(this);
61− this.navigateLogin = this.navigateLogin.bind(this);
62− }
63−
64− pushWalletState(walletState) {
65− this.setState({
66− walletStates: this.state.walletStates.concat(walletState),
67− });
68− }
69−
70− navigateLogin() {
71− this.props.history.popAndPush(ROUTE_NAMES.LOGIN);
72− }
73−
74− handleInviteTicketInput(inviteTicket) {
75− this.setState({ inviteTicket });
76− }
77−
78− handleVerifyTicketInput(verifyTicket) {
79− this.setState({ verifyTicket });
80− }
81−
82− updateTransactionProgress(transactionProgress) {
83− this.setState({ transactionProgress });
84− }
85−
86− async unlockInviteWallet(inviteTicket) {
87− this.setState({
88− walletStates: this.state.walletStates.concat(WALLET_STATES.UNLOCKING),
89− stage: INVITE_STAGES.INVITE_WALLET,
90− });
91−
92− //NOTE ~zod because tmp wallet
93− const ownership = await ownershipWalletFromTicket(inviteTicket, 0);
94− const mnemonic = ownership.seed;
95− //TODO isn't all this accessible in the ownership object?
96− const inviteWallet = walletFromMnemonic(
97− mnemonic,
98− DEFAULT_HD_PATH
99− ).matchWith({
100− Just: w => w.value,
101− Nothing: () => {
102− throw BRIDGE_ERROR.MISSING_WALLET;
103− },
104− });
105−
106− const addr = inviteWallet.address;
107−
108− const contracts = need.contracts(this.props.contracts);
109−
110− const incoming = await azimuth.azimuth.getTransferringFor(contracts, addr);
111−
112− this.setState({
113− walletStates: this.state.walletStates.concat(WALLET_STATES.GENERATING),
114− });
115−
116− let realPoint = Nothing();
117− let realWallet = Nothing();
118− let errors = [];
119−
120− if (incoming.length > 0) {
121− let pointNum = parseInt(incoming[0], 10);
122− realPoint = Just(pointNum);
123−
124− this.setState({
125− realPoint,
126− });
127−
128− let genWallet = await generateWallet(pointNum);
129−
130− realWallet = Just(genWallet);
131− if (incoming.length > 1) {
132− //TODO notify user "...and others / ticket reusable"
133− }
134− } else {
135− errors = [
136− 'Invite code has no claimable ship. Check your invite code and try again.',
137− ];
138− }
139−
140− this.setState({
141− realWallet,
142− inviteWallet: Just(inviteWallet),
143− // dev mode: uncomment this out to autofill verified ticket
144− verifyTicket: !Nothing.hasInstance(realWallet)
145− ? realWallet.value.ticket
146− : '',
147− walletStates: this.state.walletStates.concat(WALLET_STATES.RENDERING),
148− errors,
149− });
150− }
151−
152− getTicketElement() {
153− const phTick = this.ticketPlaceholder;
154−
155− let isLogin = this.state.stage === INVITE_STAGES.INVITE_LOGIN;
156− let isVerify = this.state.stage === INVITE_STAGES.INVITE_VERIFY;
157−
158− if (isLogin || isVerify) {
159− let value = isLogin ? this.state.inviteTicket : this.state.verifyTicket;
160− let handler = isLogin
161− ? this.handleInviteTicketInput
162− : this.handleVerifyTicketInput;
163− let label = isLogin ? 'Activation code' : 'ticket';
164−
165− // if realWallet is Just, then VerifyTicketInput appropriate contents; if Nothing, remain Nothing
166− const Verified = this.state.realWallet.map(realWallet =>
167− VerifyTicketInput(realWallet.ticket)
168− );
169−
170− // Verified.getOrElse(TicketInput) falls back to TicketInput if Verified is Nothing
171− const TicketElem = isVerify
172− ? Verified.getOrElse(TicketInput)
173− : TicketInput;
174−
175− return (
176− <TicketElem
177− className="mono mt-8"
178− prop-size="md"
179− prop-format="innerLabel"
180− type="text"
181− autoFocus
182− name="invite"
183− placeholder={`e.g. ${phTick}`}
184− value={value}
185− onChange={handler}>
186− <InnerLabel>{label}</InnerLabel>
187− </TicketElem>
188− );
189− } else {
190− return null;
191− }
192− }
193−
194− getStageText() {
195− const { stage } = this.state;
196−
197− let progressWidth = this.state.transactionProgress.pct;
198−
199− const stageText =
200− stage === INVITE_STAGES.INVITE_LOGIN ? (
201− <h1 className="text-700 mt-15">Welcome</h1>
202− ) : stage === INVITE_STAGES.INVITE_WALLET ? (
203− <div>
204− <h1 className="fs-6 lh-8 mb-3">Passport</h1>
205− <p>
206− A passport is your digital identity. You will use your passport to
207− access your true computer, send payments, and administer your
208− identity. So naturally, you must keep this secure.
209− </p>
210− <p>
211− After you’ve downloaded your passport, back up the ticket manually
212− or store on a trusted device.
213− </p>
214− </div>
215− ) : stage === INVITE_STAGES.INVITE_VERIFY ? (
216− <div>
217− <h1 className="fs-6 lh-8 mb-3">Verify Passport</h1>
218− <p>
219− Afer you download your passport, verify your custody. Your passport
220− should be a folder of image files. One of them is your Master
221− Ticket. Open it and enter the 4 word phrase below (with hyphens).
222− </p>
223− </div>
224− ) : INVITE_STAGES.INVITE_TRANSACTIONS ? (
225− this.state.transactionProgress.label ===
226− TRANSACTION_STATES.DONE.label ? (
227− <div>
228− <h1 className="fs-6 lh-8 mb-3">
229− <span>Success</span>
230− <span className="ml-4 green">✓</span>
231− </h1>
232− <p>Transferring to Bridge...</p>
233− </div>
234− ) : (
235− <div>
236− <h1 className="fs-6 lh-8 mb-3">Submitting</h1>
237− <p className="mt-4 mb-4">
238− This step can take up to five minutes. Please do not leave this
239− page until the transactions are complete.
240− </p>
241− <div className="passport-progress mb-2">
242− <div
243− className="passport-progress-filled"
244− style={{ width: progressWidth }}
245− />
246− </div>
247− <div className="flex justify-between">
248− <div className="text-mono text-sm lh-6 green-dark">
249− {this.state.transactionProgress.label}
250− </div>
251− </div>
252− </div>
253− )
254− ) : null;
255−
256− return stageText;
257− }
258−
259− updateProgress(notification) {
260− let newState =
261− notification.type === 'progress'
262− ? { transactionProgress: notification.value }
263− : notification.type === 'notify'
264− ? { errors: [notification.value] }
265− : {};
266−
267− this.setState(newState);
268− }
269−
270− getContinueButton() {
271− const {
272− realPoint,
273− realWallet,
274− inviteWallet,
275− stage,
276− walletStates,
277− verifyTicket,
278− inviteTicket,
279− } = this.state;
280− const { web3, contracts, setUrbitWallet } = this.props;
281−
282− const btnColor = this.state.walletStates.includes(WALLET_STATES.PAPER_READY)
283− ? 'green'
284− : 'black';
285−
286− const clickHandler =
287− stage === INVITE_STAGES.INVITE_LOGIN
288− ? () => {
289− this.unlockInviteWallet(inviteTicket);
290− }
291− : stage === INVITE_STAGES.INVITE_WALLET
292− ? () => {
293− this.setState({
294− stage: INVITE_STAGES.INVITE_VERIFY,
295− });
296− }
297− : stage === INVITE_STAGES.INVITE_VERIFY
298− ? () => {
299− this.setState({
300− stage: INVITE_STAGES.INVITE_TRANSACTIONS,
301− walletStates: this.state.walletStates.concat(
302− WALLET_STATES.TRANSACTIONS
303− ),
304− });
305−
306− startTransactions({
307− inviteWalletM: inviteWallet,
308− realWalletM: realWallet,
309− realPointM: realPoint,
310− realTicket: verifyTicket,
311− web3,
312− contracts,
313− setUrbitWallet,
314− updateProgress: this.updateProgress,
315− }).then(() => {
316− setTimeout(() => {
317− this.props.history.pop();
318− }, 5000);
319− });
320− }
321− : null;
322−
323− const ticketMatches = this.state.realWallet.matchWith({
324− Just: wal => wal.value.ticket === this.state.verifyTicket,
325− Nothing: () => false,
326− });
327−
328− const continueReady =
329− stage === INVITE_STAGES.INVITE_WALLET
330− ? walletStates.includes(WALLET_STATES.DOWNLOADED)
331− : stage === INVITE_STAGES.INVITE_VERIFY
332− ? ticketMatches
333− : true;
334−
335− const buttonElem =
336− stage === INVITE_STAGES.INVITE_TRANSACTIONS ? null : (
337− <Button
338− className={'mt-4'}
339− prop-size={'lg'}
340− prop-color={btnColor}
341− disabled={!continueReady}
342− onClick={clickHandler}>
343− {'Continue →'}
344− </Button>
345− );
346−
347− return buttonElem;
348− }
349−
350− getStageDisplay() {
351− const { stage } = this.state;
352−
353− if (stage === INVITE_STAGES.INVITE_LOGIN) return null;
354−
355− return (
356− <div className="mt-6 mb-8">
357− <span
358− className={`fs-35 mr-3 ${stage !== INVITE_STAGES.INVITE_WALLET &&
359− 'gray-20'}`}>
360− 1 Passport
361− </span>
362− <span
363− className={`fs-35 mr-3 ${stage !== INVITE_STAGES.INVITE_VERIFY &&
364− 'gray-20'}`}>
365− 2 Verify
366− </span>
367− <span
368− className={`fs-35 mr-3 ${stage !==
369− INVITE_STAGES.INVITE_TRANSACTIONS && 'gray-20'}`}>
370− 3 Invite
371− </span>
372− </div>
373− );
374− }
375−
376− getErrors() {
377− if (this.state.errors.length === 0) return null;
378−
379− let errorElems = this.state.errors.map(e => <span>{e}</span>);
380−
381− return (
382− <Warning>
383− <h3 className={'mb-2'}>{'Warning'}</h3>
384− {errorElems}
385− </Warning>
386− );
387− }
388−
389− render() {
390− let stageDisplay = this.getStageDisplay();
391− let stageText = this.getStageText();
392− let ticketElem = this.getTicketElement();
393− let continueButton = this.getContinueButton();
394− let errorDisplay = this.getErrors();
395−
396− return (
397− <View.Full>
398− <Grid>
399− <Grid.Item half={1}>
400− {stageDisplay}
401− {errorDisplay}
402− {stageText}
403− {ticketElem}
404− {continueButton}
405−
406− {this.state.stage === INVITE_STAGES.INVITE_LOGIN && (
407− <Button
408− prop-type={`link`}
409− prop-size={`sm`}
410− className={`block mt-4`}
411− onClick={this.navigateLogin}>
412− {`Log in`}
413− </Button>
414− )}
415− </Grid.Item>
416− <Grid.Item half={2}>
417− <Passport
418− point={this.state.realPoint}
419− wallet={this.state.realWallet}
420− walletStates={this.state.walletStates}
421− pushWalletState={this.pushWalletState}
422− />
423− </Grid.Item>
424− </Grid>
425− </View.Full>
426− );
427− }
428−}
429−
430−export default compose(
431− withNetwork,
432− withHistory,
433− withWallet
434−)(InviteTicket);