on b30edac help sign in
bridge/src/Bridge.js
297 lines 8.6 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 // network
69 networkType: networkType,
70 web3: Maybe.Just(web3),
71 contracts: Maybe.Just(contracts),
72 // wallet
73 walletType: WALLET_NAMES.MNEMONIC,
74 wallet: Maybe.Nothing(),
75 walletHdPath: DEFAULT_HD_PATH,
76 // urbit wallet-related
77 urbitWallet: Maybe.Nothing(),
78 authMnemonic: Maybe.Nothing(),
79 // point
80 pointCursor: Maybe.Nothing(),
81 pointCache: {},
82 // txn
83 txnHashCursor: Maybe.Nothing()
84 }
86 this.pushRoute = this.pushRoute.bind(this)
87 this.popRoute = this.popRoute.bind(this)
88 this.skipRoute = this.skipRoute.bind(this)
89 this.setNetworkType = this.setNetworkType.bind(this)
90 this.setNetwork = this.setNetwork.bind(this)
91 this.setWalletType = this.setWalletType.bind(this)
92 this.setWallet = this.setWallet.bind(this)
93 this.setWalletHdPath = this.setWalletHdPath.bind(this)
94 this.setUrbitWallet = this.setUrbitWallet.bind(this)
95 this.setAuthMnemonic = this.setAuthMnemonic.bind(this)
96 this.setPointCursor = this.setPointCursor.bind(this)
97 this.setTxnHashCursor = this.setTxnHashCursor.bind(this)
98 this.addToPointCache = this.addToPointCache.bind(this)
99 }
101 componentDidMount() {
103 // NB (jtobin):
104 //
105 // If running in development, the following can be tweaked to get you set
106 // up with a desirable initial state.
108 // if (process.env.NODE_ENV === 'development') {
109 //
110 // const socket = 'wss://localhost:8545'
111 // const provider = new Web3.providers.WebsocketProvider(socket)
112 // const web3 = new Web3(provider)
113 // const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.DEV)
114 //
115 // const mnemonic = process.env.REACT_APP_DEV_MNEMONIC
116 // const hdpath = process.env.REACT_APP_HD_PATH
117 //
118 // this.setState({
119 // routeCrumbs: Stack([
120 // ROUTE_NAMES.CREATE_GALAXY,
121 // ROUTE_NAMES.SHIPS,
122 // // ROUTE_NAMES.MNEMONIC,
123 // ROUTE_NAMES.WALLET,
124 // ROUTE_NAMES.NETWORK,
125 // ROUTE_NAMES.LANDING
126 // ]),
127 // networkType: NETWORK_NAMES.LOCAL,
128 // web3: Maybe.Just(web3),
129 // contracts: Maybe.Just(contracts),
130 // walletType: WALLET_NAMES.MNEMONIC,
131 // wallet: walletFromMnemonic(mnemonic, hdpath),
132 // urbitWallet: Maybe.Nothing(),
133 // authMnemonic: Maybe.Nothing()
134 // })
135 // }
138 pushRoute(symbol) {
139 if (lodash.includes(ROUTE_NAMES, symbol)) {
140 this.setState((state, _) => ({
141 routeCrumbs: state.routeCrumbs.push(symbol),
142 }));
144 // Scroll to top of page with each route transition.
145 window.scrollTo(0, 0);
147 } else {
148 throw BRIDGE_ERROR.INVALID_ROUTE
149 }
150 }
152 skipRoute(len) {
153 this.setState((state, _) => ({
154 routeCrumbs: state.routeCrumbs.skip(len)
155 }))
156 }
158 popRoute() {
159 this.setState((state, _) => ({
160 routeCrumbs: state.routeCrumbs.shift()
161 }))
162 }
164 setNetworkType(symbol) {
165 if (lodash.includes(NETWORK_NAMES, symbol)) {
166 this.setState({
167 networkType: symbol
168 })
169 } else {
170 throw BRIDGE_ERROR.INVALID_NETWORK_TYPE
171 }
172 }
174 setNetwork(web3, contracts) {
175 this.setState({
176 web3: web3,
177 contracts: contracts
178 })
179 }
181 setWalletType(symbol) {
182 if (lodash.includes(WALLET_NAMES, symbol)) {
183 this.setState({
184 walletType: symbol
185 })
186 } else {
187 throw BRIDGE_ERROR.INVALID_WALLET_TYPE
188 }
189 }
191 setWallet(wallet) {
192 this.setState({ wallet })
193 }
195 setWalletHdPath(walletHdPath) {
196 this.setState({ walletHdPath })
197 }
199 setUrbitWallet(urbitWallet) {
200 this.setState({ urbitWallet })
201 }
203 setAuthMnemonic(authMnemonic) {
204 this.setState({ authMnemonic })
205 }
207 setPointCursor(pointCursor) {
208 this.setState({ pointCursor })
209 }
211 addToPointCache(entry) {
212 this.setState((state, _) => ({
213 pointCache: Object.assign(state.pointCache, entry)
214 }))
215 }
217 setTxnHashCursor(txnHashCursor) {
218 this.setState({ txnHashCursor })
219 }
221 render() {
222 const {
223 routeCrumbs,
224 networkType,
225 walletType,
226 walletHdPath,
227 wallet,
228 urbitWallet,
229 authMnemonic,
230 pointCursor,
231 pointCache,
232 txnHashCursor,
233 web3,
234 contracts
235 } = this.state
237 const View = router(routeCrumbs.peek())
239 return (
240 <Container>
241 <Row>
242 <Col className='col-md-1' />
243 <Col className='col-md-10' style={{maxWidth: '620px'}}>
244 <Header
245 routeCrumbs={ routeCrumbs }
246 skipRoute={ this.skipRoute }
247 networkType={ networkType }
248 wallet={ wallet }
249 pointCursor={ pointCursor } />
251 <Row className={ 'row wrapper' }>
253 <View
254 // router
255 pushRoute={ this.pushRoute }
256 popRoute={ this.popRoute }
257 // network
258 setNetworkType={ this.setNetworkType }
259 setNetwork={ this.setNetwork }
260 networkType={ networkType }
261 web3={ web3 }
262 contracts={ contracts }
263 // wallet
264 setWalletType={ this.setWalletType }
265 setWalletHdPath={ this.setWalletHdPath }
266 setWallet={ this.setWallet }
267 walletType={ walletType }
268 walletHdPath={ walletHdPath }
269 wallet={ wallet }
270 // urbit wallet
271 urbitWallet={ urbitWallet }
272 setUrbitWallet={ this.setUrbitWallet }
273 authMnemonic={ authMnemonic }
274 setAuthMnemonic={ this.setAuthMnemonic }
275 // point
276 setPointCursor={ this.setPointCursor }
277 addToPointCache={ this.addToPointCache }
278 pointCursor={ pointCursor }
279 pointCache={ pointCache }
280 // txn
281 setTxnHashCursor={ this.setTxnHashCursor }
282 txnHashCursor={ txnHashCursor } />
284 <div className={'push'} />
286 </Row>
288 <Footer />
289 </Col>
290 <Col className='col-md-1' />
291 </Row>
292 </Container>
293 )
294 }
297export default Bridge