on c59dd78 help sign in
bridge/src/Bridge.js
319 lines 9.3 kB history raw
1import Maybe from 'folktale/maybe'
2import * as lodash from 'lodash'
3import * as azimuth from 'azimuth-js'
4import { Stack } from 'immutable'
5import { CONTRACT_ADDRESSES } from './lib/contracts'
6import React from 'react'
8import Web3 from 'web3'
9import Footer from './components/Footer'
10import Header from './components/Header'
11import { Container, Row, Col } from './components/Base'
13import { ROUTE_NAMES, router } from './lib/router'
14import { NETWORK_NAMES } from './lib/network'
15import { WALLET_NAMES, DEFAULT_HD_PATH } from './lib/wallet'
16import { BRIDGE_ERROR } from './lib/error'
18import './style/index.css'
20const initWeb3 = (networkType) => {
21 if (networkType === NETWORK_NAMES.MAINNET) {
22 const endpoint =
23 `https://mainnet.infura.io/v3/${process.env.REACT_APP_INFURA_KEY}`
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 }
38class Bridge extends React.Component {
40 constructor(props) {
41 super(props)
43 const networkType =
44 process.env.NODE_ENV === 'development'
45 ? NETWORK_NAMES.LOCAL
46 : NETWORK_NAMES.MAINNET
48 // Sidestepping full network selection to allow for point viewing,
49 // but still respecting the networkType
50 const { web3, contracts } = initWeb3(networkType)
52 // NB (jtobin):
53 //
54 // Note that the 'wallet' prop has type depending on the 'walletType' prop.
55 // These could be bound together in a single structure (so that
56 // 'walletType' acted more explicitly as a data constructor of sorts) but
57 // it doesn't necessarily help us much, since we branch on 'walletType'
58 // before setting 'wallet'.
59 //
60 // Wallets are always wrapped in Maybe. For most authentication
61 // mechanisms, Maybe wraps a BIP32 HD wallet; for Ethereum private keys,
62 // JSON keystore files, and Metamask authentication, it wraps an
63 // 'EthereumWallet'.
65 this.state = {
66 // routes
67 routeCrumbs: Stack([ ROUTE_NAMES.LANDING ]),
68 routeData: {},
69 // network
70 networkType: networkType,
71 web3: Maybe.Just(web3),
72 contracts: Maybe.Just(contracts),
73 // wallet
74 walletType: WALLET_NAMES.MNEMONIC,
75 wallet: Maybe.Nothing(),
76 walletHdPath: DEFAULT_HD_PATH,
77 // urbit wallet-related
78 urbitWallet: Maybe.Nothing(),
79 authMnemonic: Maybe.Nothing(),
80 networkSeedCache: null,
81 // point
82 pointCursor: Maybe.Nothing(),
83 pointCache: {},
84 // txn
85 txnHashCursor: Maybe.Nothing()
86 }
88 this.pushRoute = this.pushRoute.bind(this)
89 this.popRoute = this.popRoute.bind(this)
90 this.skipRoute = this.skipRoute.bind(this)
91 this.setNetworkType = this.setNetworkType.bind(this)
92 this.setNetwork = this.setNetwork.bind(this)
93 this.setWalletType = this.setWalletType.bind(this)
94 this.setWallet = this.setWallet.bind(this)
95 this.setWalletHdPath = this.setWalletHdPath.bind(this)
96 this.setUrbitWallet = this.setUrbitWallet.bind(this)
97 this.setAuthMnemonic = this.setAuthMnemonic.bind(this)
98 this.setPointCursor = this.setPointCursor.bind(this)
99 this.setTxnHashCursor = this.setTxnHashCursor.bind(this)
100 this.setNetworkSeedCache = this.setNetworkSeedCache.bind(this)
101 this.addToPointCache = this.addToPointCache.bind(this)
102 }
104 componentDidMount() {
105 window.history.pushState(null, null, null);
107 window.onpopstate = (e) => {
108 window.history.pushState(null, null, null);
109 this.popRoute();
110 }
112 // NB (jtobin):
113 //
114 // If running in development, the following can be tweaked to get you set
115 // up with a desirable initial state.
117 // if (process.env.NODE_ENV === 'development') {
118 //
119 // const socket = 'ws://localhost:8545'
120 // const provider = new Web3.providers.WebsocketProvider(socket)
121 // const web3 = new Web3(provider)
122 // const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.DEV)
123 //
124 // const mnemonic = process.env.REACT_APP_DEV_MNEMONIC
125 // const hdpath = process.env.REACT_APP_HD_PATH
126 //
127 // this.setState({
128 // routeCrumbs: Stack([
129 // // ROUTE_NAMES.CREATE_GALAXY,
130 // // ROUTE_NAMES.SHIP,
131 // ROUTE_NAMES.SHIPS,
132 // // ROUTE_NAMES.MNEMONIC,
133 // ROUTE_NAMES.WALLET,
134 // ROUTE_NAMES.NETWORK,
135 // ROUTE_NAMES.LANDING
136 // ]),
137 // networkType: NETWORK_NAMES.LOCAL,
138 // pointCursor: Maybe.Just(0),
139 // web3: Maybe.Just(web3),
140 // contracts: Maybe.Just(contracts),
141 // walletType: WALLET_NAMES.MNEMONIC,
142 // wallet: walletFromMnemonic(mnemonic, hdpath),
143 // urbitWallet: Maybe.Nothing(),
144 // authMnemonic: Maybe.Just('benefit crew supreme gesture quantum web media hazard theory mercy wing kitten')
145 // })
146 // }
149 pushRoute(symbol, routeData) {
150 if (lodash.includes(ROUTE_NAMES, symbol)) {
151 this.setState((state, _) => ({
152 routeCrumbs: state.routeCrumbs.push(symbol),
153 routeData: routeData
154 }));
156 // Scroll to top of page with each route transition.
157 window.scrollTo(0, 0);
159 } else {
160 throw BRIDGE_ERROR.INVALID_ROUTE
161 }
162 }
164 skipRoute(len) {
165 this.setState((state, _) => ({
166 routeCrumbs: state.routeCrumbs.skip(len)
167 }))
168 }
170 popRoute() {
171 this.setState((state, _) => ({
172 routeCrumbs: state.routeCrumbs.shift()
173 }))
174 }
176 setNetworkType(symbol) {
177 if (lodash.includes(NETWORK_NAMES, symbol)) {
178 this.setState({
179 networkType: symbol
180 })
181 } else {
182 throw BRIDGE_ERROR.INVALID_NETWORK_TYPE
183 }
184 }
186 setNetworkSeedCache(networkSeed) {
187 this.setState({
188 networkSeedCache: networkSeed
189 })
190 }
192 setNetwork(web3, contracts) {
193 this.setState({
194 web3: web3,
195 contracts: contracts
196 })
197 }
199 setWalletType(symbol) {
200 if (lodash.includes(WALLET_NAMES, symbol)) {
201 this.setState({
202 walletType: symbol
203 })
204 } else {
205 throw BRIDGE_ERROR.INVALID_WALLET_TYPE
206 }
207 }
209 setWallet(wallet) {
210 this.setState({ wallet })
211 }
213 setWalletHdPath(walletHdPath) {
214 this.setState({ walletHdPath })
215 }
217 setUrbitWallet(urbitWallet) {
218 this.setState({ urbitWallet })
219 }
221 setAuthMnemonic(authMnemonic) {
222 this.setState({ authMnemonic })
223 }
225 setPointCursor(pointCursor) {
226 this.setState({ pointCursor })
227 }
229 addToPointCache(entry) {
230 this.setState((state, _) => ({
231 pointCache: Object.assign(state.pointCache, entry)
232 }))
233 }
235 setTxnHashCursor(txnHashCursor) {
236 this.setState({ txnHashCursor })
237 }
239 render() {
240 const {
241 routeCrumbs,
242 routeData,
243 networkType,
244 walletType,
245 walletHdPath,
246 wallet,
247 urbitWallet,
248 authMnemonic,
249 networkSeedCache,
250 pointCursor,
251 pointCache,
252 txnHashCursor,
253 web3,
254 contracts
255 } = this.state
257 const View = router(routeCrumbs.peek())
259 return (
260 <Container>
261 <Row>
262 <Col className='col-md-1' />
263 <Col className='col-md-10' style={{maxWidth: '620px'}}>
264 <Header
265 routeCrumbs={ routeCrumbs }
266 skipRoute={ this.skipRoute }
267 networkType={ networkType }
268 wallet={ wallet }
269 pointCursor={ pointCursor } />
271 <Row className={ 'row wrapper' }>
273 <View
274 // router
275 pushRoute={ this.pushRoute }
276 popRoute={ this.popRoute }
277 routeData={ routeData }
278 // network
279 setNetworkType={ this.setNetworkType }
280 setNetwork={ this.setNetwork }
281 networkType={ networkType }
282 web3={ web3 }
283 contracts={ contracts }
284 // wallet
285 setWalletType={ this.setWalletType }
286 setWalletHdPath={ this.setWalletHdPath }
287 setWallet={ this.setWallet }
288 walletType={ walletType }
289 walletHdPath={ walletHdPath }
290 wallet={ wallet }
291 // urbit wallet
292 urbitWallet={ urbitWallet }
293 setUrbitWallet={ this.setUrbitWallet }
294 authMnemonic={ authMnemonic }
295 setAuthMnemonic={ this.setAuthMnemonic }
296 // point
297 setPointCursor={ this.setPointCursor }
298 addToPointCache={ this.addToPointCache }
299 pointCursor={ pointCursor }
300 pointCache={ pointCache }
301 networkSeedCache= { networkSeedCache }
302 setNetworkSeedCache= { this.setNetworkSeedCache }
303 // txn
304 setTxnHashCursor={ this.setTxnHashCursor }
305 txnHashCursor={ txnHashCursor } />
307 <div className={'push'} />
309 </Row>
311 <Footer />
312 </Col>
313 </Row>
314 </Container>
315 )
316 }
319export default Bridge