on master help sign in
Add view a point button to landing page
commit7468eca560ecbe602d0260d880f4a50573570e38 authorpkova <pyry.kovanen@gmail.com> dateTue 19 Mar 2019, 20:11 (8 years ago) parent1efb09a
5 files changed+281−229
src/Bridge.js+27−2 src/views/Landing.js+14 src/views/Network.js−5 src/views/Point.js+10−222 src/views/Point/Actions.js+230
src/Bridge.js+27−2
@@ -1,8 +1,11 @@
11import Maybe from 'folktale/maybe'
22import * as lodash from 'lodash'
3+import * as azimuth from 'azimuth-js'
34import { Stack } from 'immutable'
5+import { CONTRACT_ADDRESSES } from './lib/contracts'
46import React from 'react'
57
8+import Web3 from 'web3'
69import Footer from './components/Footer'
710import Header from './components/Header'
811import { Container, Row, Col } from './components/Base'
@@ -14,6 +17,24 @@ import { BRIDGE_ERROR } from './lib/error'
1417
1518import './style/index.css'
1619
20+const initWeb3 = (networkType) => {
21+ if (networkType === NETWORK_NAMES.MAINNET) {
22+ const endpoint =
23+ `https://mainnet.infura.io/v3/${process.env.REACT_APP_INFURA_KEY}`
24+
25+ const provider = new Web3.providers.HttpProvider(endpoint)
26+ const web3 = new Web3(provider)
27+ const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.MAINNET)
28+ return {web3: web3, contracts: contracts}
29+ } else if (networkType === NETWORK_NAMES.LOCAL) {
30+ const endpoint = 'wss://localhost:8545'
31+ const provider = new Web3.providers.WebsocketProvider(endpoint)
32+ const web3 = new Web3(provider)
33+ const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.DEV)
34+ return {web3: web3, contracts: contracts}
35+ }
36+}
37+
1738class Bridge extends React.Component {
1839
1940 constructor(props) {
@@ -24,6 +45,10 @@ class Bridge extends React.Component {
2445 ? NETWORK_NAMES.LOCAL
2546 : NETWORK_NAMES.MAINNET
2647
48+ // Sidestepping full network selection to allow for point viewing,
49+ // but still respecting the networkType
50+ const { web3, contracts } = initWeb3(networkType)
51+
2752 // NB (jtobin):
2853 //
2954 // Note that the 'wallet' prop has type depending on the 'walletType' prop.
@@ -42,8 +67,8 @@ class Bridge extends React.Component {
4267 routeCrumbs: Stack([ ROUTE_NAMES.LANDING ]),
4368 // network
4469 networkType: networkType,
45− web3: Maybe.Nothing(),
46− contracts: Maybe.Nothing(),
70+ web3: Maybe.Just(web3),
71+ contracts: Maybe.Just(contracts),
4772 // wallet
4873 walletType: WALLET_NAMES.MNEMONIC,
4974 wallet: Maybe.Nothing(),
src/views/Landing.js+14
@@ -34,6 +34,20 @@ const Landing = (props) =>
3434 </P>
3535
3636 {
37+ <Row>
38+ <Col>
39+ <Button
40+ prop-type={'link'}
41+ prop-size={'md'}
42+ onClick={ () => props.pushRoute(ROUTE_NAMES.VIEW_SHIP) }
43+ >
44+ { 'View a point →' }
45+ </Button>
46+ <P>
47+ { "View a point on Azimuth." }
48+ </P>
49+ </Col>
50+ </Row>
3751 // FIXME add address view
3852 // <LinkButton
3953 // size={'l'}
src/views/Network.js−5
@@ -34,11 +34,6 @@ class Network extends React.Component {
3434 }))
3535 }
3636
37− componentDidMount() {
38− const { networkType } = this.props
39− this.handleNetworkChange(networkType)
40− }
41−
4237 handleNetworkChange(network) {
4338 const { setNetworkType, setNetwork } = this.props
4439
src/views/Point.js+10−222
@@ -7,19 +7,10 @@ import * as azimuth from 'azimuth-js'
77import PointList from '../components/PointList'
88import ReactSVGComponents from '../components/ReactSVGComponents'
99import KeysAndMetadata from './Point/KeysAndMetadata'
10+import Actions from './Point/Actions'
1011import { BRIDGE_ERROR } from '../lib/error'
11−import { ROUTE_NAMES } from '../lib/router'
12−import { Row, Col, H1, H2, H3, P } from '../components/Base'
13−import { Button } from '../components/Base'
14−import {
15− ETH_ZERO_ADDR,
16− CURVE_ZERO_ADDR,
17− addressFromSecp256k1Public,
18− eqAddr
19− } from '../lib/wallet'
12+import { Row, Col, H1, H3 } from '../components/Base'
2013
21−const isPlanet = point =>
22− parseInt(point, 10) > 65535
2314
2415class Point extends React.Component {
2516
@@ -84,12 +75,6 @@ class Point extends React.Component {
8475
8576 const { spawned } = this.state
8677
87− const addr = wallet.matchWith({
88− Just: (wal) => addressFromSecp256k1Public(wal.value.publicKey),
89− Nothing: () => {
90− throw BRIDGE_ERROR.MISSING_WALLET
91− }
92− })
9378
9479 const point = pointCursor.matchWith({
9580 Just: (cursor) => cursor.value,
@@ -113,93 +98,11 @@ class Point extends React.Component {
11398
11499 const online = Maybe.Just.hasInstance(web3)
115100
116− const canSetTransferProxy = pointDetails.matchWith({
117− // also should check is addr is operator
118− Nothing: _ => false,
119− Just: details => eqAddr(details.value.owner, addr)
101+ const authenticated = wallet.matchWith({
102+ Just: _ => true,
103+ Nothing: _ => false
120104 })
121105
122− const canSetSpawnProxy = pointDetails.matchWith({
123− Nothing: _ => false,
124− Just: details =>
125− eqAddr(details.value.owner, addr) && details.value.active
126− })
127−
128−
129− const canSetManagementProxy = pointDetails.matchWith({
130− Nothing: _ => false,
131− Just: details =>
132− eqAddr(details.value.owner, addr) && details.value.active
133− })
134−
135− const canConfigureKeys = pointDetails.matchWith({
136− Nothing: _ => false,
137− Just: details => {
138− const canManage =
139− eqAddr(details.value.owner, addr)
140− || eqAddr(details.value.managementProxy, addr)
141−
142− return canManage && details.value.active
143− }
144− })
145−
146− const canIssueChild =
147− pointDetails.matchWith({
148− Nothing: () => false,
149− Just: (details) => {
150− const hasPermission =
151− eqAddr(details.value.owner, addr)
152− || eqAddr(details.value.spawnProxy, addr)
153−
154− const isBooted =
155− details.value.keyRevisionNumber > 0
156−
157− const isNotPlanet = !isPlanet(point)
158−
159− return hasPermission && isBooted && isNotPlanet
160− }
161− })
162−
163− const planet = isPlanet(point)
164−
165− const canTransfer =
166− pointDetails.matchWith({
167− Nothing: () => false,
168− Just: (deets) =>
169− eqAddr(deets.value.transferProxy, addr) ||
170− eqAddr(deets.value.owner, addr)
171− })
172−
173− const canGenKeyfile =
174− pointDetails.matchWith({
175− Nothing: () => false,
176− Just: (deets) => {
177− const hasPermission =
178− eqAddr(deets.value.owner, addr)
179− || eqAddr(deets.value.managementProxy, addr)
180−
181− const isBooted =
182− deets.value.keyRevisionNumber > 0
183−
184− return hasPermission && isBooted
185− }
186− })
187−
188− const canAcceptTransfer =
189− pointDetails.matchWith({
190− Nothing: () => false,
191− Just: (deets) =>
192− eqAddr(deets.value.transferProxy, addr)
193− })
194−
195− const canCancelTransfer =
196− pointDetails.matchWith({
197− Nothing: () => false,
198− Just: (deets) =>
199− eqAddr(deets.value.owner, addr) &&
200− !eqAddr(deets.value.transferProxy, ETH_ZERO_ADDR)
201− })
202−
203106 const routeHandler = route => {
204107 popRoute()
205108 pushRoute(route)
@@ -219,141 +122,26 @@ class Point extends React.Component {
219122 </div>
220123
221124
222− const displayReminder = pointDetails.matchWith({
223− Nothing: () => false,
224− Just: (deets) => {
225− return deets.value.encryptionKey === CURVE_ZERO_ADDR
226− && deets.value.authenticationKey === CURVE_ZERO_ADDR
227− }
228− })
229125
230126 return (
231127 <Row>
232128 <Col>
233−
234129 <div className={'mt-12 pt-6'}>
235130 { sigil }
236131 </div>
237−
238132 <H1><code>{ name }</code></H1>
239−
240− <H2>{ 'Actions' }</H2>
241−
242133 {
243− displayReminder
244− ? <P>{`Before you can issue child points or generate your Arvo
245− keyfile, you need to set your public keys.`}</P>
246− : ''
134+ authenticated
135+ ? <Actions pushRoute={ pushRoute } online={ online } point={ point } pointDetails={ pointDetails } wallet={ wallet }/>
136+ : null
247137 }
248138
249− <Row>
250− <Col className={'flex flex-column items-start col-md-4'}>
251− <Button
252− prop-size={'sm'}
253− prop-type={'link'}
254− disabled={ (online || planet) && !canIssueChild }
255− onClick={ () => {
256− pushRoute(ROUTE_NAMES.ISSUE_CHILD)
257− }}
258− >
259− { 'Issue child' }
260− </Button>
261−
262− <Button
263− prop-size={'sm'}
264− prop-type={'link'}
265− disabled={ !canAcceptTransfer }
266− onClick={ () => {
267− pushRoute(ROUTE_NAMES.ACCEPT_TRANSFER)
268− }}
269− >
270− { 'Accept incoming transfer' }
271− </Button>
272−
273− <Button
274− prop-size={'sm'}
275− prop-type={'link'}
276− disabled={ online && !canCancelTransfer }
277− onClick={ () => {
278− pushRoute(ROUTE_NAMES.CANCEL_TRANSFER)
279− }}
280− >
281− { 'Cancel outgoing transfer' }
282− </Button>
283−
284− <Button
285− prop-size={'sm'}
286− prop-type={'link'}
287− disabled={ !canGenKeyfile }
288− onClick={ () => {
289− pushRoute(ROUTE_NAMES.GEN_KEYFILE)
290− }}
291− >
292− { 'Generate Arvo keyfile' }
293− </Button>
294−
295− </Col>
296− <Col className={'flex flex-column items-start col-md-4'}>
297−
298− <Button
299− disabled={ online && !canSetSpawnProxy }
300− prop-size={'sm'}
301− prop-type={'link'}
302− onClick={ () => {
303− pushRoute(ROUTE_NAMES.SET_SPAWN_PROXY)
304− }}
305− >
306− { 'Set spawn proxy' }
307− </Button>
308−
309− <Button
310− disabled={ online && !canSetManagementProxy }
311− prop-size={'sm'}
312− prop-type={'link'}
313− onClick={ () => {
314− pushRoute(ROUTE_NAMES.SET_MANAGEMENT_PROXY)
315− }}
316− >
317− { 'Set management proxy' }
318− </Button>
319−
320− <Button
321− disabled={ online && !canConfigureKeys }
322− prop-size={'sm'}
323− prop-type={'link'}
324− onClick={ () => {
325− pushRoute(ROUTE_NAMES.SET_KEYS)
326− }}
327− >
328− { 'Set public keys' }
329− </Button>
330−
331− <Button
332− disabled={ online && !canTransfer }
333− prop-size={'sm'}
334− prop-type={'link'}
335− onClick={ () => {
336− pushRoute(ROUTE_NAMES.TRANSFER)
337− }}
338− >
339− { 'Transfer' }
340− </Button>
341−
342− </Col>
343− </Row>
344−
345−
346−
347− {
139+ {
348140 online
349141 ? <KeysAndMetadata pointDetails={ pointDetails } />
350142 : <div />
351− }
352−
353−
354−
143+ }
355144 { issuedPointList }
356−
357145 </Col>
358146 </Row>
359147 )
src/views/Point/Actions.jsnew file+230
@@ -0,0 +1,230 @@
1+import React from 'react'
2+import {
3+ ETH_ZERO_ADDR,
4+ CURVE_ZERO_ADDR,
5+ addressFromSecp256k1Public,
6+ eqAddr
7+} from '../../lib/wallet'
8+import { BRIDGE_ERROR } from '../../lib/error'
9+import { Row, Col, H2, P } from '../../components/Base'
10+import { Button } from '../../components/Base'
11+import { ROUTE_NAMES } from '../../lib/router'
12+
13+
14+const isPlanet = point =>
15+ parseInt(point, 10) > 65535
16+
17+const Actions = (props) => {
18+ const { pushRoute, online, point, pointDetails, wallet } = props
19+
20+ const addr = wallet.matchWith({
21+ Just: (wal) => addressFromSecp256k1Public(wal.value.publicKey),
22+ Nothing: () => {
23+ throw BRIDGE_ERROR.MISSING_WALLET
24+ }
25+ })
26+
27+ const canSetTransferProxy = pointDetails.matchWith({
28+ // also should check is addr is operator
29+ Nothing: _ => false,
30+ Just: details => eqAddr(details.value.owner, addr)
31+ })
32+
33+ const canSetSpawnProxy = pointDetails.matchWith({
34+ Nothing: _ => false,
35+ Just: details =>
36+ eqAddr(details.value.owner, addr) && details.value.active
37+ })
38+
39+
40+ const canSetManagementProxy = pointDetails.matchWith({
41+ Nothing: _ => false,
42+ Just: details =>
43+ eqAddr(details.value.owner, addr) && details.value.active
44+ })
45+
46+ const canConfigureKeys = pointDetails.matchWith({
47+ Nothing: _ => false,
48+ Just: details => {
49+ const canManage =
50+ eqAddr(details.value.owner, addr)
51+ || eqAddr(details.value.managementProxy, addr)
52+
53+ return canManage && details.value.active
54+ }
55+ })
56+
57+ const canIssueChild =
58+ pointDetails.matchWith({
59+ Nothing: () => false,
60+ Just: (details) => {
61+ const hasPermission =
62+ eqAddr(details.value.owner, addr)
63+ || eqAddr(details.value.spawnProxy, addr)
64+
65+ const isBooted =
66+ details.value.keyRevisionNumber > 0
67+
68+ const isNotPlanet = !isPlanet(point)
69+
70+ return hasPermission && isBooted && isNotPlanet
71+ }
72+ })
73+
74+ const planet = isPlanet(point)
75+
76+ const canTransfer =
77+ pointDetails.matchWith({
78+ Nothing: () => false,
79+ Just: (deets) =>
80+ eqAddr(deets.value.transferProxy, addr) ||
81+ eqAddr(deets.value.owner, addr)
82+ })
83+
84+ const canGenKeyfile =
85+ pointDetails.matchWith({
86+ Nothing: () => false,
87+ Just: (deets) => {
88+ const hasPermission =
89+ eqAddr(deets.value.owner, addr)
90+ || eqAddr(deets.value.managementProxy, addr)
91+
92+ const isBooted =
93+ deets.value.keyRevisionNumber > 0
94+
95+ return hasPermission && isBooted
96+ }
97+ })
98+
99+ const canAcceptTransfer =
100+ pointDetails.matchWith({
101+ Nothing: () => false,
102+ Just: (deets) =>
103+ eqAddr(deets.value.transferProxy, addr)
104+ })
105+
106+ const canCancelTransfer =
107+ pointDetails.matchWith({
108+ Nothing: () => false,
109+ Just: (deets) =>
110+ eqAddr(deets.value.owner, addr) &&
111+ !eqAddr(deets.value.transferProxy, ETH_ZERO_ADDR)
112+ })
113+
114+ const displayReminder = pointDetails.matchWith({
115+ Nothing: () => false,
116+ Just: (deets) => {
117+ return deets.value.encryptionKey === CURVE_ZERO_ADDR
118+ && deets.value.authenticationKey === CURVE_ZERO_ADDR
119+ }
120+ })
121+
122+ return (
123+ <div>
124+ <H2>{ 'Actions' }</H2>
125+ {
126+ displayReminder
127+ ? <P>{`Before you can issue child points or generate your Arvo
128+ keyfile, you need to set your public keys.`}</P>
129+ : ''
130+ }
131+ <Row>
132+ <Col className={'flex flex-column items-start col-md-4'}>
133+ <Button
134+ prop-size={'sm'}
135+ prop-type={'link'}
136+ disabled={ (online || planet) && !canIssueChild }
137+ onClick={ () => {
138+ pushRoute(ROUTE_NAMES.ISSUE_CHILD)
139+ }}
140+ >
141+ { 'Issue child' }
142+ </Button>
143+
144+ <Button
145+ prop-size={'sm'}
146+ prop-type={'link'}
147+ disabled={ !canAcceptTransfer }
148+ onClick={ () => {
149+ pushRoute(ROUTE_NAMES.ACCEPT_TRANSFER)
150+ }}
151+ >
152+ { 'Accept incoming transfer' }
153+ </Button>
154+
155+ <Button
156+ prop-size={'sm'}
157+ prop-type={'link'}
158+ disabled={ online && !canCancelTransfer }
159+ onClick={ () => {
160+ pushRoute(ROUTE_NAMES.CANCEL_TRANSFER)
161+ }}
162+ >
163+ { 'Cancel outgoing transfer' }
164+ </Button>
165+
166+ <Button
167+ prop-size={'sm'}
168+ prop-type={'link'}
169+ disabled={ !canGenKeyfile }
170+ onClick={ () => {
171+ pushRoute(ROUTE_NAMES.GEN_KEYFILE)
172+ }}
173+ >
174+ { 'Generate Arvo keyfile' }
175+ </Button>
176+
177+ </Col>
178+ <Col className={'flex flex-column items-start col-md-4'}>
179+
180+ <Button
181+ disabled={ online && !canSetSpawnProxy }
182+ prop-size={'sm'}
183+ prop-type={'link'}
184+ onClick={ () => {
185+ pushRoute(ROUTE_NAMES.SET_SPAWN_PROXY)
186+ }}
187+ >
188+ { 'Set spawn proxy' }
189+ </Button>
190+
191+ <Button
192+ disabled={ online && !canSetManagementProxy }
193+ prop-size={'sm'}
194+ prop-type={'link'}
195+ onClick={ () => {
196+ pushRoute(ROUTE_NAMES.SET_MANAGEMENT_PROXY)
197+ }}
198+ >
199+ { 'Set management proxy' }
200+ </Button>
201+
202+ <Button
203+ disabled={ online && !canConfigureKeys }
204+ prop-size={'sm'}
205+ prop-type={'link'}
206+ onClick={ () => {
207+ pushRoute(ROUTE_NAMES.SET_KEYS)
208+ }}
209+ >
210+ { 'Set public keys' }
211+ </Button>
212+
213+ <Button
214+ disabled={ online && !canTransfer }
215+ prop-size={'sm'}
216+ prop-type={'link'}
217+ onClick={ () => {
218+ pushRoute(ROUTE_NAMES.TRANSFER)
219+ }}
220+ >
221+ { 'Transfer' }
222+ </Button>
223+
224+ </Col>
225+ </Row>
226+ </div>
227+ )
228+}
229+
230+export default Actions