on master help sign in
Implement ticket verification page
42eaa49Fang
src/bridge/lib/router.js+12
@@ -6,6 +6,8 @@ import Landing from '../views/Landing'
6
6
7import InviteLogin from '../views/InviteLogin'
7import InviteLogin from '../views/InviteLogin'
8import InviteWallet from '../views/InviteWallet'
8import InviteWallet from '../views/InviteWallet'
9+import InviteVerify from '../views/InviteVerify.js'
10+import InviteTransactions from '../views/InviteTransactions.js'
9
11
10import AcceptTransfer from '../views/AcceptTransfer'
12import AcceptTransfer from '../views/AcceptTransfer'
11import CancelTransfer from '../views/CancelTransfer'
13import CancelTransfer from '../views/CancelTransfer'
@@ -42,6 +44,8 @@ const ROUTE_NAMES = {
42 //
44 //
43 INVITE_LOGIN: Symbol('INVITE_LOGIN'),
45 INVITE_LOGIN: Symbol('INVITE_LOGIN'),
44 INVITE_WALLET: Symbol('INVITE_WALLET'),
46 INVITE_WALLET: Symbol('INVITE_WALLET'),
47+ INVITE_VERIFY: Symbol('INVITE_VERIFY'),
48+ INVITE_TRANSACTIONS: Symbol('INVITE_TRANSACTIONS'),
45 //
49 //
46 ACCEPT_TRANSFER: Symbol('ACCEPT_TRANSFER'),
50 ACCEPT_TRANSFER: Symbol('ACCEPT_TRANSFER'),
47 CANCEL_TRANSFER: Symbol('CANCEL_TRANSFER'),
51 CANCEL_TRANSFER: Symbol('CANCEL_TRANSFER'),
@@ -75,6 +79,8 @@ const createRoutes = () => {
75 //
79 //
76 routes[ROUTE_NAMES.INVITE_LOGIN] = InviteLogin
80 routes[ROUTE_NAMES.INVITE_LOGIN] = InviteLogin
77 routes[ROUTE_NAMES.INVITE_WALLET] = InviteWallet
81 routes[ROUTE_NAMES.INVITE_WALLET] = InviteWallet
82+ routes[ROUTE_NAMES.INVITE_VERIFY] = InviteVerify
83+ routes[ROUTE_NAMES.INVITE_TRANSACTIONS] = InviteTransactions
78 //
84 //
79 routes[ROUTE_NAMES.ACCEPT_TRANSFER] = AcceptTransfer
85 routes[ROUTE_NAMES.ACCEPT_TRANSFER] = AcceptTransfer
80 routes[ROUTE_NAMES.CANCEL_TRANSFER] = CancelTransfer
86 routes[ROUTE_NAMES.CANCEL_TRANSFER] = CancelTransfer
@@ -117,6 +123,12 @@ const renderRoute = (props, route) => {
117 : route === ROUTE_NAMES.INVITE_WALLET
123 : route === ROUTE_NAMES.INVITE_WALLET
118 ? 'Claim invite'
124 ? 'Claim invite'
119
125
126+ : route === ROUTE_NAMES.INVITE_VERIFY
127+ ? 'Verify new wallet'
128+
129+ : route === ROUTE_NAMES.INVITE_TRANSACTIONS
130+ ? 'Setting up new wallet'
131+
120 : route === ROUTE_NAMES.NETWORK
132 : route === ROUTE_NAMES.NETWORK
121 ? `${renderNetworkType(networkType)}`
133 ? `${renderNetworkType(networkType)}`
122
134
src/bridge/views/InviteLogin.js−14
@@ -33,25 +33,12 @@ class InviteLogin extends React.Component {
33 this.ticketPlaceholder = placeholder(12)
33 this.ticketPlaceholder = placeholder(12)
34
34
35 this.handleTicketInput = this.handleTicketInput.bind(this)
35 this.handleTicketInput = this.handleTicketInput.bind(this)
36− this.handlePointNameInput = this.handlePointNameInput.bind(this)
37 }
36 }
38
37
39 handleTicketInput(ticket) {
38 handleTicketInput(ticket) {
40 this.setState({ ticket })
39 this.setState({ ticket })
41 }
40 }
42
41
43− handlePointNameInput(pointName) {
44− if (pointName.length < 15) {
45− this.setState({ pointName })
46− }
47− }
48−
49− // buttonTriState = (wallet) => {
50− // if (wallet.isNothing()) return 'blue'
51− // if (wallet === false) return 'yellow'
52− // if (Nothing.hasInstance(wallet)) return 'green'
53− // }
54−
55 async walletFromTicket(ticket, pointName) {
42 async walletFromTicket(ticket, pointName) {
56 const { setWallet, setUrbitWallet } = this.props
43 const { setWallet, setUrbitWallet } = this.props
57
44
@@ -78,7 +65,6 @@ class InviteLogin extends React.Component {
78 const { wallet } = this.props
65 const { wallet } = this.props
79 const { ticket, pointName } = this.state
66 const { ticket, pointName } = this.state
80
67
81− const phPoint = this.pointPlaceholder
82 const phTick = this.ticketPlaceholder
68 const phTick = this.ticketPlaceholder
83
69
84 return (
70 return (
src/bridge/views/InviteTransactions.jsnew file+76
@@ -0,0 +1,76 @@
1+import { Just, Nothing } from 'folktale/maybe'
2+import React from 'react'
3+import { pour } from 'sigil-js'
4+import * as ob from 'urbit-ob'
5+import * as azimuth from 'azimuth-js'
6+
7+import { EthereumWallet } from '../lib/wallet'
8+
9+import ReactSVGComponents from '../components/ReactSVGComponents'
10+import KeysAndMetadata from './Point/KeysAndMetadata'
11+import Actions from './Point/Actions'
12+import { BRIDGE_ERROR } from '../lib/error'
13+import { Row, Col, Warning, Button, H1, H3 } from '../components/Base'
14+
15+
16+class InviteVerify extends React.Component {
17+
18+ constructor(props) {
19+ super(props)
20+
21+ this.state = {
22+ point: this.props.routeData.point,
23+ ticket: this.props.routeData.ticket
24+ }
25+ }
26+
27+ componentDidMount() {
28+ //TODO start transactions
29+ // - sign transfer transaction to new wallet with invite wallet
30+ // - ping gas tank if needed
31+ // - wait for tx confirm
32+ // - sign configuration transactions (management, networking) with new wallet
33+ // - ping gas tank if needed
34+ // - wait for tx confirms
35+ }
36+
37+ componentDidUpdate(prevProps) {
38+ //
39+ }
40+
41+ render() {
42+
43+ const { point } = this.state;
44+
45+ const name = ob.patp(point);
46+ const sigil = pour({
47+ patp: name,
48+ renderer: ReactSVGComponents,
49+ size: 256
50+ });
51+ let pointOverview = (
52+ //TODO Passport display component
53+ <>
54+ <div className={'mt-12 pt-6'}>
55+ { sigil }
56+ </div>
57+ <H3><code>{ name }</code></H3>
58+ </>
59+ );
60+
61+ console.log('tickets', this.state.ticket, this.state.realTicket, (this.state.realTicket === this.state.ticket));
62+ return (
63+ <Row>
64+ <Col>
65+
66+ { pointOverview }
67+
68+ <p>{ 'Please wait while your wallet and point are prepared for use.' }</p>
69+
70+ </Col>
71+ </Row>
72+ )
73+ }
74+}
75+
76+export default InviteVerify
src/bridge/views/InviteVerify.jsnew file+115
@@ -0,0 +1,115 @@
1+import { Just, Nothing } from 'folktale/maybe'
2+import React from 'react'
3+import { pour } from 'sigil-js'
4+import * as ob from 'urbit-ob'
5+import * as azimuth from 'azimuth-js'
6+
7+import { ROUTE_NAMES } from '../lib/router'
8+
9+import { InnerLabel, TicketInput } from '../components/Base'
10+import ReactSVGComponents from '../components/ReactSVGComponents'
11+import KeysAndMetadata from './Point/KeysAndMetadata'
12+import Actions from './Point/Actions'
13+import { BRIDGE_ERROR } from '../lib/error'
14+import { Row, Col, Warning, Button, H1, H3 } from '../components/Base'
15+
16+//TODO from Ticket.js, move to lib
17+const placeholder = (len) => {
18+ let bytes = window.crypto.getRandomValues(new Uint8Array(len))
19+ let hex = bytes.reduce((acc, byt) =>
20+ acc + byt.toString(16).padStart(2, '0'),
21+ ''
22+ )
23+ return ob.hex2patq(hex)
24+}
25+
26+class InviteVerify extends React.Component {
27+
28+ constructor(props) {
29+ super(props)
30+
31+ this.state = {
32+ point: this.props.routeData.point,
33+ realTicket: this.props.routeData.ticket
34+ }
35+
36+ this.ticketPlaceholder = placeholder(8);
37+ this.handleTicketInput = this.handleTicketInput.bind(this);
38+ this.proceed = this.proceed.bind(this);
39+ }
40+
41+ componentDidMount() {
42+ //
43+ }
44+
45+ componentDidUpdate(prevProps) {
46+ //
47+ }
48+
49+ handleTicketInput(ticket) {
50+ this.setState({ ticket })
51+ }
52+
53+ proceed() {
54+ this.props.pushRoute(ROUTE_NAMES.INVITE_TRANSACTIONS, {
55+ ticket: this.state.realTicket,
56+ point: this.state.point
57+ });
58+ }
59+
60+ render() {
61+
62+ const { point } = this.state;
63+
64+ const name = ob.patp(point);
65+ const sigil = pour({
66+ patp: name,
67+ renderer: ReactSVGComponents,
68+ size: 256
69+ });
70+ let pointOverview = (
71+ //TODO Passport display component
72+ <>
73+ <div className={'mt-12 pt-6'}>
74+ { sigil }
75+ </div>
76+ <H3><code>{ name }</code></H3>
77+ </>
78+ );
79+
80+ return (
81+ <Row>
82+ <Col>
83+
84+ { pointOverview }
85+
86+ <p>{`Please input the master ticket for ${point} that you downloaded in the previous step.`}</p>
87+
88+ <TicketInput
89+ className='mono mt-8'
90+ prop-size='lg'
91+ prop-format='innerLabel'
92+ type='password'
93+ name='ticket'
94+ placeholder={ `e.g. ${this.ticketPlaceholder}` }
95+ value={ this.state.ticket }
96+ onChange={ this.handleTicketInput }>
97+ <InnerLabel>{ 'Ticket' }</InnerLabel>
98+ </TicketInput>
99+
100+ <Button
101+ className={'mt-4'}
102+ prop-size={'xl wide'}
103+ disabled={(this.state.ticket !== this.state.realTicket)}
104+ onClick={this.proceed}
105+ >
106+ { 'Continue →' }
107+ </Button>
108+
109+ </Col>
110+ </Row>
111+ )
112+ }
113+}
114+
115+export default InviteVerify
src/bridge/views/InviteWallet.js+7−3
@@ -5,6 +5,7 @@ import * as ob from 'urbit-ob'
5import * as azimuth from 'azimuth-js'
5import * as azimuth from 'azimuth-js'
6
6
7import { addressFromSecp256k1Public, EthereumWallet } from '../lib/wallet'
7import { addressFromSecp256k1Public, EthereumWallet } from '../lib/wallet'
8+import { ROUTE_NAMES } from '../lib/router'
8
9
9import PointList from '../components/PointList'
10import PointList from '../components/PointList'
10import ReactSVGComponents from '../components/ReactSVGComponents'
11import ReactSVGComponents from '../components/ReactSVGComponents'
@@ -39,10 +40,10 @@ class InviteWallet extends React.Component {
39 wallet: Nothing(),
40 wallet: Nothing(),
40 paper: Nothing(),
41 paper: Nothing(),
41 downloaded: false
42 downloaded: false
42− //TODO remove bools in favor of Nothings/Justs
43 }
43 }
44
44
45 this.download = this.download.bind(this)
45 this.download = this.download.bind(this)
46+ this.proceed = this.proceed.bind(this)
46 }
47 }
47
48
48 componentDidMount() {
49 componentDidMount() {
@@ -162,7 +163,10 @@ class InviteWallet extends React.Component {
162 }
163 }
163
164
164 proceed() {
165 proceed() {
165− //TODO
166+ this.props.pushRoute(ROUTE_NAMES.INVITE_VERIFY, {
167+ ticket: this.state.wallet.value.ticket,
168+ point: this.state.point.value
169+ });
166 }
170 }
167
171
168 render() {
172 render() {
@@ -269,7 +273,7 @@ class InviteWallet extends React.Component {
269 { balanceWarning }
273 { balanceWarning }
270 { pointOverview }
274 { pointOverview }
271
275
272− <p>{'TODO copy. you need a wallet to receive the point into. download it below.'}</p>
276+ <p>{'TODO copy. you need a wallet to receive the point into. download it below. also explanation of wallet files/storage'}</p>
273
277
274 { downloadButton }
278 { downloadButton }
275 { nextButton }
279 { nextButton }