@@ -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';
61import React from 'react';
2+import { Just, Nothing } from 'folktale/maybe';
3+import { includes } from 'lodash';
74
8−import Web3 from 'web3';
95import Footer from './components/Footer';
106import Header from './components/Header';
117import { Container, Row, Col } from './components/Base';
128
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';
1414import { NETWORK_NAMES } from './lib/network';
1515import {
1616 WALLET_NAMES,
@@ -19,35 +19,54 @@ import {
1919 addressFromSecp256k1Public,
2020} from './lib/wallet';
2121import { BRIDGE_ERROR } from './lib/error';
22−
23−const initWeb3 = networkType => {
24− if (networkType === NETWORK_NAMES.MAINNET) {
25− const endpoint = `https://mainnet.infura.io/v3/${
26− process.env.REACT_APP_INFURA_ENDPOINT
27− }`;
28−
29− const provider = new Web3.providers.HttpProvider(endpoint);
30− const web3 = new Web3(provider);
31− const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.MAINNET);
32− return { web3: web3, contracts: contracts };
33− } else if (networkType === NETWORK_NAMES.LOCAL) {
34− const protocol = process.env.NODE_ENV === 'development' ? 'ws' : 'wss';
35− const endpoint = `${protocol}://localhost:8545`;
36− const provider = new Web3.providers.WebsocketProvider(endpoint);
37− const web3 = new Web3(provider);
38− const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.DEV);
39− return { web3: web3, contracts: contracts };
40− }
22+import { isLocal } from './lib/flags';
23+
24+// NB(shrugs): toggle this variable to use the default local state.
25+// don't commit changes to this line, but there shouldn't be a problem
26+// if you do because we'll never stub on a production build.
27+const shouldStubLocal = false;
28+const isStubbed = isLocal && shouldStubLocal;
29+const kInitialRoutes = isStubbed
30+ ? [
31+ { name: ROUTE_NAMES.SHIPS },
32+ { name: ROUTE_NAMES.WALLET },
33+ { name: ROUTE_NAMES.NETWORK },
34+ { name: ROUTE_NAMES.LANDING },
35+ ]
36+ : [{ name: ROUTE_NAMES.LANDING }];
37+
38+// the router itself is a component that renders a specific view
39+// based on the latest history state
40+const Router = function(props) {
41+ const history = useHistory();
42+ const Route = router(history.peek());
43+
44+ return <Route {...props} />;
4145};
4246
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
52+ <Col
53+ className={
54+ history.includes(ROUTE_NAMES.INVITE_TICKET)
55+ ? 'col-md-12'
56+ : 'col-md-offset-1 col-md-10'
57+ }
58+ style={
59+ history.includes(ROUTE_NAMES.INVITE_TICKET) ? {} : { maxWidth: '620px' }
60+ }>
61+ {children}
62+ </Col>
63+));
64+
4365class Bridge extends React.Component {
4466 constructor(props) {
4567 super(props);
4668
47− const networkType =
48− process.env.NODE_ENV === 'development'
49− ? NETWORK_NAMES.LOCAL
50− : NETWORK_NAMES.MAINNET;
69+ const networkType = isLocal ? NETWORK_NAMES.LOCAL : NETWORK_NAMES.MAINNET;
5170
5271 // Sidestepping full network selection to allow for point viewing,
5372 // but still respecting the networkType
@@ -67,9 +86,6 @@ class Bridge extends React.Component {
6786 // 'EthereumWallet'.
6887
6988 this.state = {
70− // routes
71− routeCrumbs: Stack([ROUTE_NAMES.LANDING]),
72− routeData: {},
7389 // network
7490 networkType: networkType,
7591 web3: Just(web3),
@@ -90,9 +106,6 @@ class Bridge extends React.Component {
90106 txnConfirmations: {},
91107 };
92108
93− this.pushRoute = this.pushRoute.bind(this);
94− this.popRoute = this.popRoute.bind(this);
95− this.skipRoute = this.skipRoute.bind(this);
96109 this.setNetworkType = this.setNetworkType.bind(this);
97110 this.setNetwork = this.setNetwork.bind(this);
98111 this.setWalletType = this.setWalletType.bind(this);
@@ -102,84 +115,31 @@ class Bridge extends React.Component {
102115 this.setAuthMnemonic = this.setAuthMnemonic.bind(this);
103116 this.setPointCursor = this.setPointCursor.bind(this);
104117 this.setTxnHashCursor = this.setTxnHashCursor.bind(this);
105− this.setTxnConfirmations = this.setTxnConfirmations.bind(this);
106118 this.setNetworkSeedCache = this.setNetworkSeedCache.bind(this);
107119 this.addToPointCache = this.addToPointCache.bind(this);
108120 }
109121
110122 componentDidMount() {
111− window.history.pushState(null, null, null);
112−
113− window.onpopstate = e => {
114− window.history.pushState(null, null, null);
115− this.popRoute();
116− };
117−
118− // NB (jtobin):
123+ // NB (jtobin, shrugs):
119124 //
120125 // If running in development, the following can be tweaked to get you set
121126 // up with a desirable initial state.
127+ if (isStubbed) {
128+ const mnemonic = process.env.REACT_APP_DEV_MNEMONIC;
129+ const hdpath = process.env.REACT_APP_HD_PATH;
122130
123− // if (process.env.NODE_ENV === 'development') {
124− //
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)
129− //
130− // const mnemonic = process.env.REACT_APP_DEV_MNEMONIC
131− // const hdpath = process.env.REACT_APP_HD_PATH
132− //
133− // 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
142− // ]),
143− // networkType: NETWORK_NAMES.LOCAL,
144− // pointCursor: Just(0),
145− // web3: Just(web3),
146− // contracts: Just(contracts),
147− // walletType: WALLET_NAMES.MNEMONIC,
148− // wallet: walletFromMnemonic(mnemonic, hdpath),
149− // urbitWallet: Nothing(),
150− // authMnemonic: Just('benefit crew supreme gesture quantum web media hazard theory mercy wing kitten')
151− // })
152− // }
153− }
154−
155− pushRoute(symbol, routeData) {
156− if (lodash.includes(ROUTE_NAMES, symbol)) {
157− this.setState((state, _) => ({
158− routeCrumbs: state.routeCrumbs.push(symbol),
159− routeData: routeData,
160− }));
161−
162− // Scroll to top of page with each route transition.
163− window.scrollTo(0, 0);
164− } else {
165− throw BRIDGE_ERROR.INVALID_ROUTE;
131+ this.setState({
132+ pointCursor: Just(0),
133+ walletType: WALLET_NAMES.MNEMONIC,
134+ wallet: walletFromMnemonic(mnemonic, hdpath),
135+ urbitWallet: Nothing(),
136+ authMnemonic: Just(mnemonic),
137+ });
166138 }
167139 }
168140
169− skipRoute(len) {
170− this.setState((state, _) => ({
171− routeCrumbs: state.routeCrumbs.skip(len),
172− }));
173− }
174−
175− popRoute() {
176− this.setState((state, _) => ({
177− routeCrumbs: state.routeCrumbs.shift(),
178− }));
179− }
180−
181141 setNetworkType(symbol) {
182− if (lodash.includes(NETWORK_NAMES, symbol)) {
142+ if (includes(NETWORK_NAMES, symbol)) {
183143 this.setState({
184144 networkType: symbol,
185145 });
@@ -203,7 +163,7 @@ class Bridge extends React.Component {
203163 }
204164
205165 setWalletType(symbol) {
206− if (lodash.includes(WALLET_NAMES, symbol)) {
166+ if (includes(WALLET_NAMES, symbol)) {
207167 this.setState({
208168 walletType: symbol,
209169 });
@@ -260,23 +220,8 @@ class Bridge extends React.Component {
260220 this.setState({ txnHashCursor });
261221 }
262222
263− setTxnConfirmations(txnHash, txnConfirmations) {
264− this.setState((prevState, _) => {
265− return prevState.routeCrumbs.peek() === ROUTE_NAMES.SENT_TRANSACTION
266− ? {
267− txnConfirmations: {
268− ...prevState.txnConfirmations,
269− [txnHash]: txnConfirmations,
270− },
271− }
272− : null;
273− });
274− }
275−
276223 render() {
277224 const {
278− routeCrumbs,
279− routeData,
280225 networkType,
281226 walletType,
282227 walletHdPath,
@@ -288,87 +233,66 @@ class Bridge extends React.Component {
288233 pointCursor,
289234 pointCache,
290235 txnHashCursor,
291− txnConfirmations,
292236 web3,
293237 contracts,
294238 } = this.state;
295239
296− const View = router(routeCrumbs.peek());
297−
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)
301− ? 'col-md-12'
302− : 'col-md-offset-1 col-md-10';
303−
304− const colStyle = routeCrumbs.contains(ROUTE_NAMES.INVITE_TICKET)
305− ? {}
306− : { maxWidth: '620px' };
307−
308− const showCrumbs = routeCrumbs.contains(ROUTE_NAMES.INVITE_TICKET)
309− ? false
310− : true;
311−
312240 return (
313− <Container>
314− <Row>
315− <Col className={colClass} style={colStyle}>
316− <Header
317− routeCrumbs={routeCrumbs}
318− skipRoute={this.skipRoute}
319− networkType={networkType}
320− wallet={wallet}
321− showCrumbs={showCrumbs}
322− pointCursor={pointCursor}
323− />
324−
325− <Row className={'row wrapper'}>
326− <View
327− // router
328− pushRoute={this.pushRoute}
329− popRoute={this.popRoute}
330− routeData={routeData}
331− // network
332− setNetworkType={this.setNetworkType}
333− setNetwork={this.setNetwork}
334− networkType={networkType}
335− web3={web3}
336− contracts={contracts}
337− // wallet
338− setWalletType={this.setWalletType}
339− setWalletHdPath={this.setWalletHdPath}
340− setWallet={this.setWallet}
341− walletType={walletType}
342− walletHdPath={walletHdPath}
343− wallet={wallet}
344− // urbit wallet
345− urbitWallet={urbitWallet}
346− setUrbitWallet={this.setUrbitWallet}
347− authMnemonic={authMnemonic}
348− setAuthMnemonic={this.setAuthMnemonic}
349− // point
350− setPointCursor={this.setPointCursor}
351− addToPointCache={this.addToPointCache}
352− pointCursor={pointCursor}
353− pointCache={pointCache}
354− networkSeedCache={networkSeedCache}
355− networkRevisionCache={networkRevisionCache}
356− setNetworkSeedCache={this.setNetworkSeedCache}
357− // txn
358− onSent={this.setTxnHashCursor}
359− setTxnHashCursor={this.setTxnHashCursor}
360− txnHashCursor={txnHashCursor}
361− setTxnConfirmations={this.setTxnConfirmations}
362− txnConfirmations={txnConfirmations}
363− />
364−
365− <div className={'push'} />
241+ <HistoryProvider initialRoutes={kInitialRoutes}>
242+ <TxnConfirmationsProvider>
243+ <Container>
244+ <Row>
245+ <VariableWidthColumn>
246+ <Header
247+ skipRoute={this.skipRoute}
248+ networkType={networkType}
249+ wallet={wallet}
250+ pointCursor={pointCursor}
251+ />
252+
253+ <Row className={'row wrapper'}>
254+ <Router
255+ // network
256+ setNetworkType={this.setNetworkType}
257+ setNetwork={this.setNetwork}
258+ networkType={networkType}
259+ web3={web3}
260+ contracts={contracts}
261+ // wallet
262+ setWalletType={this.setWalletType}
263+ setWalletHdPath={this.setWalletHdPath}
264+ setWallet={this.setWallet}
265+ walletType={walletType}
266+ walletHdPath={walletHdPath}
267+ wallet={wallet}
268+ // urbit wallet
269+ urbitWallet={urbitWallet}
270+ setUrbitWallet={this.setUrbitWallet}
271+ authMnemonic={authMnemonic}
272+ setAuthMnemonic={this.setAuthMnemonic}
273+ // point
274+ setPointCursor={this.setPointCursor}
275+ addToPointCache={this.addToPointCache}
276+ pointCursor={pointCursor}
277+ pointCache={pointCache}
278+ networkSeedCache={networkSeedCache}
279+ networkRevisionCache={networkRevisionCache}
280+ setNetworkSeedCache={this.setNetworkSeedCache}
281+ // txn
282+ onSent={this.setTxnHashCursor}
283+ setTxnHashCursor={this.setTxnHashCursor}
284+ txnHashCursor={txnHashCursor}
285+ />
286+
287+ <div className={'push'} />
288+ </Row>
289+
290+ <Footer />
291+ </VariableWidthColumn>
366292 </Row>
367−
368− <Footer />
369− </Col>
370− </Row>
371− </Container>
293+ </Container>
294+ </TxnConfirmationsProvider>
295+ </HistoryProvider>
372296 );
373297 }
374298}