@@ -1,16 +1,16 @@
1−import { Just, Nothing } from 'folktale/maybe';
2−import * as lodash from 'lodash';
3−import * as azimuth from 'azimuth-js';
4−import { Stack } from 'immutable';
5−import { CONTRACT_ADDRESSES } from './lib/contracts';
6import React from 'react';
1import React from 'react';
2+import { Just, Nothing } from 'folktale/maybe';
3+import { includes } from 'lodash';
8−import Web3 from 'web3';
9import Footer from './components/Footer';
5import Footer from './components/Footer';
10import Header from './components/Header';
6import Header from './components/Header';
11import { Container, Row, Col } from './components/Base';
7import { Container, Row, Col } from './components/Base';
13−import { ROUTE_NAMES, router } from './lib/router';
9+import { router } from './lib/router';
10+import { initWeb3 } from './lib/web3';
11+import { ROUTE_NAMES } from './lib/routeNames';
12+import { HistoryProvider, withHistory, useHistory } from './store/history';
13+import { TxnConfirmationsProvider } from './store/txnConfirmations';
14import { NETWORK_NAMES } from './lib/network';
14import { NETWORK_NAMES } from './lib/network';
16 WALLET_NAMES,
16 WALLET_NAMES,
@@ -19,35 +19,54 @@ import {
19 addressFromSecp256k1Public,
19 addressFromSecp256k1Public,
20} from './lib/wallet';
20} from './lib/wallet';
21import { BRIDGE_ERROR } from './lib/error';
21import { BRIDGE_ERROR } from './lib/error';
22−
22+import { isLocal } from './lib/flags';
23−const initWeb3 = networkType => {
23+
24− if (networkType === NETWORK_NAMES.MAINNET) {
24+// NB(shrugs): toggle this variable to use the default local state.
25− const endpoint = `https://mainnet.infura.io/v3/${
25+// don't commit changes to this line, but there shouldn't be a problem
26− process.env.REACT_APP_INFURA_ENDPOINT
26+// if you do because we'll never stub on a production build.
27− }`;
27+const shouldStubLocal = false;
28−
28+const isStubbed = isLocal && shouldStubLocal;
29− const provider = new Web3.providers.HttpProvider(endpoint);
29+const kInitialRoutes = isStubbed
30− const web3 = new Web3(provider);
30+ ? [
31− const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.MAINNET);
31+ { name: ROUTE_NAMES.SHIPS },
32− return { web3: web3, contracts: contracts };
32+ { name: ROUTE_NAMES.WALLET },
33− } else if (networkType === NETWORK_NAMES.LOCAL) {
33+ { name: ROUTE_NAMES.NETWORK },
34− const protocol = process.env.NODE_ENV === 'development' ? 'ws' : 'wss';
34+ { name: ROUTE_NAMES.LANDING },
35− const endpoint = `${protocol}://localhost:8545`;
35+ ]
36− const provider = new Web3.providers.WebsocketProvider(endpoint);
36+ : [{ name: ROUTE_NAMES.LANDING }];
37− const web3 = new Web3(provider);
37+
38− const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.DEV);
38+// the router itself is a component that renders a specific view
39− return { web3: web3, contracts: contracts };
39+// based on the latest history state
40− }
40+const Router = function(props) {
41+ const history = useHistory();
42+ const Route = router(history.peek());
44+ return <Route {...props} />;
47+// NB(shrugs): separate component because it needs withHistory
48+// this will be must better structured as part of the UI overhaul
49+const VariableWidthColumn = withHistory(({ history, children }) => (
50+ // For the invite acceptance flow, widen the screen to use the full
51+ // container, and hide the breadcrumbs
54+ history.includes(ROUTE_NAMES.INVITE_TICKET)
56+ : 'col-md-offset-1 col-md-10'
59+ history.includes(ROUTE_NAMES.INVITE_TICKET) ? {} : { maxWidth: '620px' }
43class Bridge extends React.Component {
65class Bridge extends React.Component {
44 constructor(props) {
66 constructor(props) {
45 super(props);
67 super(props);
48− process.env.NODE_ENV === 'development'
49− ? NETWORK_NAMES.LOCAL
50− : NETWORK_NAMES.MAINNET;
69+ const networkType = isLocal ? NETWORK_NAMES.LOCAL : NETWORK_NAMES.MAINNET;
52 // Sidestepping full network selection to allow for point viewing,
71 // Sidestepping full network selection to allow for point viewing,
53 // but still respecting the networkType
72 // but still respecting the networkType
@@ -67,9 +86,6 @@ class Bridge extends React.Component {
67 // 'EthereumWallet'.
86 // 'EthereumWallet'.
69 this.state = {
88 this.state = {
71− routeCrumbs: Stack([ROUTE_NAMES.LANDING]),
73 // network
89 // network
74 networkType: networkType,
90 networkType: networkType,
75 web3: Just(web3),
91 web3: Just(web3),
@@ -90,9 +106,6 @@ class Bridge extends React.Component {
90 txnConfirmations: {},
106 txnConfirmations: {},
93− this.pushRoute = this.pushRoute.bind(this);
94− this.popRoute = this.popRoute.bind(this);
95− this.skipRoute = this.skipRoute.bind(this);
96 this.setNetworkType = this.setNetworkType.bind(this);
109 this.setNetworkType = this.setNetworkType.bind(this);
97 this.setNetwork = this.setNetwork.bind(this);
110 this.setNetwork = this.setNetwork.bind(this);
98 this.setWalletType = this.setWalletType.bind(this);
111 this.setWalletType = this.setWalletType.bind(this);
@@ -102,84 +115,31 @@ class Bridge extends React.Component {
102 this.setAuthMnemonic = this.setAuthMnemonic.bind(this);
115 this.setAuthMnemonic = this.setAuthMnemonic.bind(this);
103 this.setPointCursor = this.setPointCursor.bind(this);
116 this.setPointCursor = this.setPointCursor.bind(this);
104 this.setTxnHashCursor = this.setTxnHashCursor.bind(this);
117 this.setTxnHashCursor = this.setTxnHashCursor.bind(this);
105− this.setTxnConfirmations = this.setTxnConfirmations.bind(this);
106 this.setNetworkSeedCache = this.setNetworkSeedCache.bind(this);
118 this.setNetworkSeedCache = this.setNetworkSeedCache.bind(this);
107 this.addToPointCache = this.addToPointCache.bind(this);
119 this.addToPointCache = this.addToPointCache.bind(this);
110 componentDidMount() {
122 componentDidMount() {
111− window.history.pushState(null, null, null);
113− window.onpopstate = e => {
114− window.history.pushState(null, null, null);
118− // NB (jtobin):
123+ // NB (jtobin, shrugs):
120 // If running in development, the following can be tweaked to get you set
125 // If running in development, the following can be tweaked to get you set
121 // up with a desirable initial state.
126 // up with a desirable initial state.
128+ const mnemonic = process.env.REACT_APP_DEV_MNEMONIC;
129+ const hdpath = process.env.REACT_APP_HD_PATH;
123− // if (process.env.NODE_ENV === 'development') {
125− // const socket = 'ws://localhost:8545'
126− // const provider = new Web3.providers.WebsocketProvider(socket)
127− // const web3 = new Web3(provider)
128− // const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.DEV)
130− // const mnemonic = process.env.REACT_APP_DEV_MNEMONIC
131− // const hdpath = process.env.REACT_APP_HD_PATH
133− // this.setState({
131+ this.setState({
134− // routeCrumbs: Stack([
135− // // ROUTE_NAMES.CREATE_GALAXY,
136− // // ROUTE_NAMES.SHIP,
137− // ROUTE_NAMES.SHIPS,
138− // // ROUTE_NAMES.MNEMONIC,
139− // ROUTE_NAMES.WALLET,
140− // ROUTE_NAMES.NETWORK,
141− // ROUTE_NAMES.LANDING
143− // networkType: NETWORK_NAMES.LOCAL,
144− // pointCursor: Just(0),
132+ pointCursor: Just(0),
145− // web3: Just(web3),
146− // contracts: Just(contracts),
147− // walletType: WALLET_NAMES.MNEMONIC,
133+ walletType: WALLET_NAMES.MNEMONIC,
148− // wallet: walletFromMnemonic(mnemonic, hdpath),
134+ wallet: walletFromMnemonic(mnemonic, hdpath),
149− // urbitWallet: Nothing(),
135+ urbitWallet: Nothing(),
150− // authMnemonic: Just('benefit crew supreme gesture quantum web media hazard theory mercy wing kitten')
136+ authMnemonic: Just(mnemonic),
155− pushRoute(symbol, routeData) {
156− if (lodash.includes(ROUTE_NAMES, symbol)) {
157− this.setState((state, _) => ({
158− routeCrumbs: state.routeCrumbs.push(symbol),
159− routeData: routeData,
162− // Scroll to top of page with each route transition.
163− window.scrollTo(0, 0);
165− throw BRIDGE_ERROR.INVALID_ROUTE;
170− this.setState((state, _) => ({
171− routeCrumbs: state.routeCrumbs.skip(len),
176− this.setState((state, _) => ({
177− routeCrumbs: state.routeCrumbs.shift(),
181 setNetworkType(symbol) {
141 setNetworkType(symbol) {
182− if (lodash.includes(NETWORK_NAMES, symbol)) {
142+ if (includes(NETWORK_NAMES, symbol)) {
183 this.setState({
143 this.setState({
184 networkType: symbol,
144 networkType: symbol,
@@ -203,7 +163,7 @@ class Bridge extends React.Component {
205 setWalletType(symbol) {
165 setWalletType(symbol) {
206− if (lodash.includes(WALLET_NAMES, symbol)) {
166+ if (includes(WALLET_NAMES, symbol)) {
207 this.setState({
167 this.setState({
208 walletType: symbol,
168 walletType: symbol,
@@ -260,23 +220,8 @@ class Bridge extends React.Component {
260 this.setState({ txnHashCursor });
220 this.setState({ txnHashCursor });
263− setTxnConfirmations(txnHash, txnConfirmations) {
264− this.setState((prevState, _) => {
265− return prevState.routeCrumbs.peek() === ROUTE_NAMES.SENT_TRANSACTION
268− ...prevState.txnConfirmations,
269− [txnHash]: txnConfirmations,
276 render() {
223 render() {
280 networkType,
225 networkType,
281 walletType,
226 walletType,
282 walletHdPath,
227 walletHdPath,
@@ -288,87 +233,66 @@ class Bridge extends React.Component {
288 pointCursor,
233 pointCursor,
289 pointCache,
234 pointCache,
290 txnHashCursor,
235 txnHashCursor,
293 contracts,
237 contracts,
294 } = this.state;
238 } = this.state;
296− const View = router(routeCrumbs.peek());
298− // For the invite acceptance flow, widen the screen to use the full
299− // container, and hide the breadcrumbs
300− const colClass = routeCrumbs.contains(ROUTE_NAMES.INVITE_TICKET)
302− : 'col-md-offset-1 col-md-10';
304− const colStyle = routeCrumbs.contains(ROUTE_NAMES.INVITE_TICKET)
306− : { maxWidth: '620px' };
308− const showCrumbs = routeCrumbs.contains(ROUTE_NAMES.INVITE_TICKET)
313− <Container>
241+ <HistoryProvider initialRoutes={kInitialRoutes}>
314− <Row>
242+ <TxnConfirmationsProvider>
315− <Col className={colClass} style={colStyle}>
243+ <Container>
245+ <VariableWidthColumn>
317− routeCrumbs={routeCrumbs}
318− skipRoute={this.skipRoute}
247+ skipRoute={this.skipRoute}
319− networkType={networkType}
248+ networkType={networkType}
320− wallet={wallet}
249+ wallet={wallet}
321− showCrumbs={showCrumbs}
322− pointCursor={pointCursor}
250+ pointCursor={pointCursor}
325− <Row className={'row wrapper'}>
253+ <Row className={'row wrapper'}>
328− pushRoute={this.pushRoute}
329− popRoute={this.popRoute}
330− routeData={routeData}
331− // network
255+ // network
332− setNetworkType={this.setNetworkType}
256+ setNetworkType={this.setNetworkType}
333− setNetwork={this.setNetwork}
257+ setNetwork={this.setNetwork}
334− networkType={networkType}
258+ networkType={networkType}
335− web3={web3}
259+ web3={web3}
336− contracts={contracts}
260+ contracts={contracts}
337− // wallet
261+ // wallet
338− setWalletType={this.setWalletType}
262+ setWalletType={this.setWalletType}
339− setWalletHdPath={this.setWalletHdPath}
263+ setWalletHdPath={this.setWalletHdPath}
340− setWallet={this.setWallet}
264+ setWallet={this.setWallet}
341− walletType={walletType}
265+ walletType={walletType}
342− walletHdPath={walletHdPath}
266+ walletHdPath={walletHdPath}
343− wallet={wallet}
267+ wallet={wallet}
344− // urbit wallet
268+ // urbit wallet
345− urbitWallet={urbitWallet}
269+ urbitWallet={urbitWallet}
346− setUrbitWallet={this.setUrbitWallet}
270+ setUrbitWallet={this.setUrbitWallet}
347− authMnemonic={authMnemonic}
271+ authMnemonic={authMnemonic}
348− setAuthMnemonic={this.setAuthMnemonic}
272+ setAuthMnemonic={this.setAuthMnemonic}
349− // point
273+ // point
350− setPointCursor={this.setPointCursor}
274+ setPointCursor={this.setPointCursor}
351− addToPointCache={this.addToPointCache}
275+ addToPointCache={this.addToPointCache}
352− pointCursor={pointCursor}
276+ pointCursor={pointCursor}
353− pointCache={pointCache}
277+ pointCache={pointCache}
354− networkSeedCache={networkSeedCache}
278+ networkSeedCache={networkSeedCache}
355− networkRevisionCache={networkRevisionCache}
279+ networkRevisionCache={networkRevisionCache}
356− setNetworkSeedCache={this.setNetworkSeedCache}
280+ setNetworkSeedCache={this.setNetworkSeedCache}
358− onSent={this.setTxnHashCursor}
282+ onSent={this.setTxnHashCursor}
359− setTxnHashCursor={this.setTxnHashCursor}
283+ setTxnHashCursor={this.setTxnHashCursor}
360− txnHashCursor={txnHashCursor}
284+ txnHashCursor={txnHashCursor}
361− setTxnConfirmations={this.setTxnConfirmations}
362− txnConfirmations={txnConfirmations}
365− <div className={'push'} />
287+ <div className={'push'} />
291+ </VariableWidthColumn>
368− <Footer />
294+ </TxnConfirmationsProvider>
369− </Col>
295+ </HistoryProvider>