on master help sign in
Merge pull request #154 from urbit/feat/network-state
51fd14cMatt Condon
src/bridge/Bridge.js+58−88
@@ -7,11 +7,10 @@ import Header from './components/Header';
7import { Container, Row, Col } from './components/Base';
7import { Container, Row, Col } from './components/Base';
8
8
9import { router } from './lib/router';
9import { router } from './lib/router';
10−import { initWeb3 } from './lib/web3';
11import { ROUTE_NAMES } from './lib/routeNames';
10import { ROUTE_NAMES } from './lib/routeNames';
12import { HistoryProvider, withHistory, useHistory } from './store/history';
11import { HistoryProvider, withHistory, useHistory } from './store/history';
13import { TxnConfirmationsProvider } from './store/txnConfirmations';
12import { TxnConfirmationsProvider } from './store/txnConfirmations';
14−import { NETWORK_NAMES } from './lib/network';
13+import { NETWORK_TYPES } from './lib/network';
15import {
14import {
16 WALLET_NAMES,
15 WALLET_NAMES,
17 DEFAULT_HD_PATH,
16 DEFAULT_HD_PATH,
@@ -19,13 +18,16 @@ import {
19 addressFromSecp256k1Public,
18 addressFromSecp256k1Public,
20} from './lib/wallet';
19} from './lib/wallet';
21import { BRIDGE_ERROR } from './lib/error';
20import { BRIDGE_ERROR } from './lib/error';
22−import { isLocal } from './lib/flags';
21+import { isDevelopment } from './lib/flags';
22+import nest from './lib/nest';
23+import { OnlineProvider } from './store/online';
24+import { NetworkProvider } from './store/network';
23
25
24// NB(shrugs): toggle this variable to use the default local state.
26// 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
27// 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.
28// if you do because we'll never stub on a production build.
27const shouldStubLocal = false;
29const shouldStubLocal = false;
28−const isStubbed = isLocal && shouldStubLocal;
30+const isStubbed = isDevelopment && shouldStubLocal;
29const kInitialRoutes = isStubbed
31const kInitialRoutes = isStubbed
30 ? [
32 ? [
31 { name: ROUTE_NAMES.SHIPS },
33 { name: ROUTE_NAMES.SHIPS },
@@ -34,9 +36,12 @@ const kInitialRoutes = isStubbed
34 { name: ROUTE_NAMES.LANDING },
36 { name: ROUTE_NAMES.LANDING },
35 ]
37 ]
36 : [{ name: ROUTE_NAMES.LANDING }];
38 : [{ name: ROUTE_NAMES.LANDING }];
39+const kInitialNetworkType = isDevelopment
40+ ? NETWORK_TYPES.LOCAL
41+ : NETWORK_TYPES.MAINNET;
37
42
38−// the router itself is a component that renders a specific view
43+// the router itself is just a component that renders a specific view
39−// based on the latest history state
44+// depending on the history
40const Router = function(props) {
45const Router = function(props) {
41 const history = useHistory();
46 const history = useHistory();
42 const Route = router(history.peek());
47 const Route = router(history.peek());
@@ -62,16 +67,18 @@ const VariableWidthColumn = withHistory(({ history, children }) => (
62 </Col>
67 </Col>
63));
68));
64
69
70+// nest all of the providers within each other to avoid hella depth
71+const AllProviders = nest([
72+ HistoryProvider,
73+ TxnConfirmationsProvider,
74+ OnlineProvider,
75+ NetworkProvider,
76+]);
77+
65class Bridge extends React.Component {
78class Bridge extends React.Component {
66 constructor(props) {
79 constructor(props) {
67 super(props);
80 super(props);
68
81
69− const networkType = isLocal ? NETWORK_NAMES.LOCAL : NETWORK_NAMES.MAINNET;
70−
71− // Sidestepping full network selection to allow for point viewing,
72− // but still respecting the networkType
73− const { web3, contracts } = initWeb3(networkType);
74−
75 // NB (jtobin):
82 // NB (jtobin):
76 //
83 //
77 // Note that the 'wallet' prop has type depending on the 'walletType' prop.
84 // Note that the 'wallet' prop has type depending on the 'walletType' prop.
@@ -86,10 +93,6 @@ class Bridge extends React.Component {
86 // 'EthereumWallet'.
93 // 'EthereumWallet'.
87
94
88 this.state = {
95 this.state = {
89− // network
90− networkType: networkType,
91− web3: Just(web3),
92− contracts: Just(contracts),
93 // wallet
96 // wallet
94 walletType: WALLET_NAMES.MNEMONIC,
97 walletType: WALLET_NAMES.MNEMONIC,
95 wallet: Nothing(),
98 wallet: Nothing(),
@@ -106,8 +109,6 @@ class Bridge extends React.Component {
106 txnConfirmations: {},
109 txnConfirmations: {},
107 };
110 };
108
111
109− this.setNetworkType = this.setNetworkType.bind(this);
110− this.setNetwork = this.setNetwork.bind(this);
111 this.setWalletType = this.setWalletType.bind(this);
112 this.setWalletType = this.setWalletType.bind(this);
112 this.setWallet = this.setWallet.bind(this);
113 this.setWallet = this.setWallet.bind(this);
113 this.setWalletHdPath = this.setWalletHdPath.bind(this);
114 this.setWalletHdPath = this.setWalletHdPath.bind(this);
@@ -138,16 +139,6 @@ class Bridge extends React.Component {
138 }
139 }
139 }
140 }
140
141
141− setNetworkType(symbol) {
142− if (includes(NETWORK_NAMES, symbol)) {
143− this.setState({
144− networkType: symbol,
145− });
146− } else {
147− throw BRIDGE_ERROR.INVALID_NETWORK_TYPE;
148− }
149− }
150−
151 setNetworkSeedCache(networkSeed, revision) {
142 setNetworkSeedCache(networkSeed, revision) {
152 this.setState({
143 this.setState({
153 networkSeedCache: networkSeed,
144 networkSeedCache: networkSeed,
@@ -155,13 +146,6 @@ class Bridge extends React.Component {
155 });
146 });
156 }
147 }
157
148
158− setNetwork(web3, contracts) {
159− this.setState({
160− web3: web3,
161− contracts: contracts,
162− });
163− }
164−
165 setWalletType(symbol) {
149 setWalletType(symbol) {
166 if (includes(WALLET_NAMES, symbol)) {
150 if (includes(WALLET_NAMES, symbol)) {
167 this.setState({
151 this.setState({
@@ -222,7 +206,6 @@ class Bridge extends React.Component {
222
206
223 render() {
207 render() {
224 const {
208 const {
225− networkType,
226 walletType,
209 walletType,
227 walletHdPath,
210 walletHdPath,
228 wallet,
211 wallet,
@@ -233,66 +216,53 @@ class Bridge extends React.Component {
233 pointCursor,
216 pointCursor,
234 pointCache,
217 pointCache,
235 txnHashCursor,
218 txnHashCursor,
236− web3,
237− contracts,
238 } = this.state;
219 } = this.state;
239
220
240 return (
221 return (
222+ <AllProviders
241− <HistoryProvider initialRoutes={kInitialRoutes}>
223+ initialRoutes={kInitialRoutes}
242− <TxnConfirmationsProvider>
224+ initialNetworkType={kInitialNetworkType}>
243− <Container>
225+ <Container>
244− <Row>
226+ <Row>
245− <VariableWidthColumn>
227+ <VariableWidthColumn>
246− <Header
228+ <Header
247− skipRoute={this.skipRoute}
229+ skipRoute={this.skipRoute}
248− networkType={networkType}
230+ wallet={wallet}
231+ pointCursor={pointCursor}
232+ />
233+
234+ <Row className={'row wrapper'}>
235+ <Router
236+ setWalletType={this.setWalletType}
237+ setWalletHdPath={this.setWalletHdPath}
238+ setWallet={this.setWallet}
239+ walletType={walletType}
240+ walletHdPath={walletHdPath}
249 wallet={wallet}
241 wallet={wallet}
242+ urbitWallet={urbitWallet}
243+ setUrbitWallet={this.setUrbitWallet}
244+ authMnemonic={authMnemonic}
245+ setAuthMnemonic={this.setAuthMnemonic}
246+ setPointCursor={this.setPointCursor}
247+ addToPointCache={this.addToPointCache}
250 pointCursor={pointCursor}
248 pointCursor={pointCursor}
249+ pointCache={pointCache}
250+ networkSeedCache={networkSeedCache}
251+ networkRevisionCache={networkRevisionCache}
252+ setNetworkSeedCache={this.setNetworkSeedCache}
253+ onSent={this.setTxnHashCursor}
254+ setTxnHashCursor={this.setTxnHashCursor}
255+ txnHashCursor={txnHashCursor}
251 />
256 />
252
257
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'} />
258+ <div className={'push'} />
288− </Row>
259+ </Row>
289
260
290− <Footer />
261+ <Footer />
291− </VariableWidthColumn>
262+ </VariableWidthColumn>
292− </Row>
263+ </Row>
293− </Container>
264+ </Container>
294− </TxnConfirmationsProvider>
265+ </AllProviders>
295− </HistoryProvider>
296 );
266 );
297 }
267 }
298}
268}
src/bridge/components/Header.js+9−7
@@ -5,9 +5,16 @@ import { getRouteBreadcrumb } from '../lib/router';
5import { ROUTE_NAMES } from '../lib/routeNames';
5import { ROUTE_NAMES } from '../lib/routeNames';
6import { useHistory } from '../store/history';
6import { useHistory } from '../store/history';
7import { isLast } from '../lib/lib';
7import { isLast } from '../lib/lib';
8+import { useNetwork } from '../store/network';
9+
10+function useRouteBreadcrumbBuilder(props) {
11+ const { networkType } = useNetwork();
12+ return getRouteBreadcrumb({ ...props, networkType });
13+}
8
14
9function Crumbs(props) {
15function Crumbs(props) {
10 const history = useHistory();
16 const history = useHistory();
17+ const breadcrumbBuilder = useRouteBreadcrumbBuilder(props);
11
18
12 return (
19 return (
13 <>
20 <>
@@ -17,9 +24,8 @@ function Crumbs(props) {
17 <Button
24 <Button
18 prop-type={'link'}
25 prop-type={'link'}
19 prop-size={'sm'}
26 prop-size={'sm'}
20− key={`history-button-${idx}`}
21 onClick={() => history.pop(history.size - idx - 1)}>
27 onClick={() => history.pop(history.size - idx - 1)}>
22− {getRouteBreadcrumb(props, route)}
28+ {breadcrumbBuilder(route)}
23 </Button>
29 </Button>
24
30
25 {isLast(history.size, idx) ? (
31 {isLast(history.size, idx) ? (
@@ -42,11 +48,7 @@ function Header(props) {
42 if (showCrumbs) {
48 if (showCrumbs) {
43 return (
49 return (
44 <div className={'flex items-center h-10'}>
50 <div className={'flex items-center h-10'}>
45− <Crumbs
46− networkType={props.networkType}
47− wallet={props.wallet}
48− pointCursor={props.pointCursor}
51+ <Crumbs wallet={props.wallet} pointCursor={props.pointCursor} />
49− />
50 </div>
52 </div>
51 );
53 );
52 }
54 }
src/bridge/components/StatelessTransaction.js+9−3
@@ -10,9 +10,8 @@ import { Warning } from '../components/Base';
10
10
11import { BRIDGE_ERROR } from '../lib/error';
11import { BRIDGE_ERROR } from '../lib/error';
12import { ROUTE_NAMES } from '../lib/routeNames';
12import { ROUTE_NAMES } from '../lib/routeNames';
13−import { withHistory } from '../store/history';
13+import { compose } from '../lib/lib';
14import * as tank from '../lib/tank';
14import * as tank from '../lib/tank';
15−
16import {
15import {
17 sendSignedTransaction,
16 sendSignedTransaction,
18 fromWei,
17 fromWei,
@@ -21,7 +20,10 @@ import {
21 renderSignedTx,
20 renderSignedTx,
22 signTransaction,
21 signTransaction,
23} from '../lib/txn';
22} from '../lib/txn';
23+
24import { withTxnConfirmations } from '../store/txnConfirmations';
24import { withTxnConfirmations } from '../store/txnConfirmations';
25+import { withNetwork } from '../store/network';
26+import { withHistory } from '../store/history';
25
27
26const SUBMISSION_STATES = {
28const SUBMISSION_STATES = {
27 PROMPT: 'Send transaction',
29 PROMPT: 'Send transaction',
@@ -579,4 +581,8 @@ class StatelessTransaction extends React.Component {
579 }
581 }
580}
582}
581
583
584+export default compose(
585+ withNetwork,
582−export default withTxnConfirmations(withHistory(StatelessTransaction));
586+ withTxnConfirmations,
587+ withHistory
588+)(StatelessTransaction);
src/bridge/lib/flags.js+2−1
@@ -1 +1,2 @@
1+// are we running bridge in a development build
1−export const isLocal = process.env.NODE_ENV === 'development';
2+export const isDevelopment = process.env.NODE_ENV === 'development';
src/bridge/lib/invite.js+2−2
@@ -105,8 +105,8 @@ async function downloadWallet(paper) {
105async function startTransactions(args) {
105async function startTransactions(args) {
106 let {
106 let {
107 realPointM,
107 realPointM,
108− web3M,
108+ web3: web3M,
109− contractsM,
109+ contracts: contractsM,
110 inviteWalletM,
110 inviteWalletM,
111 realWalletM,
111 realWalletM,
112 setUrbitWallet,
112 setUrbitWallet,
src/bridge/lib/nest.jsnew file+7
@@ -0,0 +1,7 @@
1+import { createFactory } from 'react';
2+
3+// inspired by recompose/nest
4+export default (components = []) => ({ children, ...props }) =>
5+ components
6+ .map(createFactory)
7+ .reduceRight((child, factory) => factory(props, child), children);
src/bridge/lib/network.js+6−6
@@ -1,4 +1,4 @@
1−const NETWORK_NAMES = {
1+const NETWORK_TYPES = {
2 OFFLINE: Symbol('OFFLINE'),
2 OFFLINE: Symbol('OFFLINE'),
3 LOCAL: Symbol('LOCAL'),
3 LOCAL: Symbol('LOCAL'),
4 ROPSTEN: Symbol('ROPSTEN'),
4 ROPSTEN: Symbol('ROPSTEN'),
@@ -6,14 +6,14 @@ const NETWORK_NAMES = {
6};
6};
7
7
8const renderNetworkType = network =>
8const renderNetworkType = network =>
9− network === NETWORK_NAMES.OFFLINE
9+ network === NETWORK_TYPES.OFFLINE
10 ? 'Offline'
10 ? 'Offline'
11− : network === NETWORK_NAMES.ROPSTEN
11+ : network === NETWORK_TYPES.ROPSTEN
12 ? 'Ropsten'
12 ? 'Ropsten'
13− : network === NETWORK_NAMES.MAINNET
13+ : network === NETWORK_TYPES.MAINNET
14 ? 'Main Network'
14 ? 'Main Network'
15− : network === NETWORK_NAMES.LOCAL
15+ : network === NETWORK_TYPES.LOCAL
16 ? 'Local Node'
16 ? 'Local Node'
17 : 'Offline';
17 : 'Offline';
18
18
19−export { NETWORK_NAMES, renderNetworkType };
19+export { NETWORK_TYPES, renderNetworkType };
src/bridge/lib/router.js+7−5
@@ -67,9 +67,11 @@ const ROUTES = {
67 [ROUTE_NAMES.GEN_KEYFILE]: GenKeyfile,
67 [ROUTE_NAMES.GEN_KEYFILE]: GenKeyfile,
68};
68};
69
69
70−export const getRouteBreadcrumb = (props, route) => {
70+export const getRouteBreadcrumb = ({
71− const { wallet, networkType } = props;
71+ networkType,
72−
72+ wallet,
73+ pointCursor,
74+}) => route => {
73 switch (route.name) {
75 switch (route.name) {
74 case ROUTE_NAMES.INVITE_TICKET:
76 case ROUTE_NAMES.INVITE_TICKET:
75 return 'Invite code';
77 return 'Invite code';
@@ -80,7 +82,7 @@ export const getRouteBreadcrumb = (props, route) => {
80 case ROUTE_NAMES.INVITES_MANAGE:
82 case ROUTE_NAMES.INVITES_MANAGE:
81 return 'Manage invites';
83 return 'Manage invites';
82 case ROUTE_NAMES.NETWORK:
84 case ROUTE_NAMES.NETWORK:
83− return `${renderNetworkType(networkType)}`;
85+ return renderNetworkType(networkType);
84 case ROUTE_NAMES.WALLET:
86 case ROUTE_NAMES.WALLET:
85 return wallet.matchWith({
87 return wallet.matchWith({
86 Nothing: () => 'Wallet',
88 Nothing: () => 'Wallet',
@@ -110,7 +112,7 @@ export const getRouteBreadcrumb = (props, route) => {
110 case ROUTE_NAMES.VIEW_SHIP:
112 case ROUTE_NAMES.VIEW_SHIP:
111 return 'View';
113 return 'View';
112 case ROUTE_NAMES.SHIP:
114 case ROUTE_NAMES.SHIP:
113− return ob.patp(need.pointCursor(props));
115+ return ob.patp(need.pointCursor({ pointCursor }));
114 case ROUTE_NAMES.SET_TRANSFER_PROXY:
116 case ROUTE_NAMES.SET_TRANSFER_PROXY:
115 case ROUTE_NAMES.SET_MANAGEMENT_PROXY:
117 case ROUTE_NAMES.SET_MANAGEMENT_PROXY:
116 case ROUTE_NAMES.SET_SPAWN_PROXY:
118 case ROUTE_NAMES.SET_SPAWN_PROXY:
src/bridge/lib/txn.js+4−4
@@ -4,7 +4,7 @@ import Tx from 'ethereumjs-tx';
4import { toWei, fromWei, toHex } from 'web3-utils';
4import { toWei, fromWei, toHex } from 'web3-utils';
5
5
6import { BRIDGE_ERROR } from '../lib/error';
6import { BRIDGE_ERROR } from '../lib/error';
7−import { NETWORK_NAMES } from '../lib/network';
7+import { NETWORK_TYPES } from '../lib/network';
8import { ledgerSignTransaction } from '../lib/ledger';
8import { ledgerSignTransaction } from '../lib/ledger';
9import { trezorSignTransaction } from '../lib/trezor';
9import { trezorSignTransaction } from '../lib/trezor';
10import { WALLET_NAMES, addHexPrefix } from '../lib/wallet';
10import { WALLET_NAMES, addHexPrefix } from '../lib/wallet';
@@ -90,9 +90,9 @@ const signTransaction = async config => {
90 };
90 };
91
91
92 const defaultEip155Networks = [
92 const defaultEip155Networks = [
93− NETWORK_NAMES.MAINNET,
93+ NETWORK_TYPES.MAINNET,
94− NETWORK_NAMES.ROPSTEN,
94+ NETWORK_TYPES.ROPSTEN,
95− NETWORK_NAMES.OFFLINE,
95+ NETWORK_TYPES.OFFLINE,
96 ];
96 ];
97
97
98 const needEip155Params =
98 const needEip155Params =
src/bridge/lib/web3.jsdeleted−23
@@ -1,23 +0,0 @@
1−import * as azimuth from 'azimuth-js';
2−import Web3 from 'web3';
3−
4−import { CONTRACT_ADDRESSES } from './contracts';
5−import { NETWORK_NAMES } from './network';
6−
7−export const initWeb3 = networkType => {
8− if (networkType === NETWORK_NAMES.MAINNET) {
9− const endpoint = `https://mainnet.infura.io/v3/${process.env.REACT_APP_INFURA_ENDPOINT}`;
10−
11− const provider = new Web3.providers.HttpProvider(endpoint);
12− const web3 = new Web3(provider);
13− const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.MAINNET);
14− return { web3: web3, contracts: contracts };
15− } else if (networkType === NETWORK_NAMES.LOCAL) {
16− const protocol = process.env.NODE_ENV === 'development' ? 'ws' : 'wss';
17− const endpoint = `${protocol}://localhost:8545`;
18− const provider = new Web3.providers.WebsocketProvider(endpoint);
19− const web3 = new Web3(provider);
20− const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.DEV);
21− return { web3: web3, contracts: contracts };
22− }
23−};
src/bridge/store/history.js+8−2
@@ -1,10 +1,16 @@
1−import React, { forwardRef, useContext, useState, useEffect } from 'react';
1+import React, {
2+ createContext,
3+ forwardRef,
4+ useContext,
5+ useState,
6+ useEffect,
7+} from 'react';
2import { last, includes } from 'lodash';
8import { last, includes } from 'lodash';
3
9
4import { BRIDGE_ERROR } from '../lib/error';
10import { BRIDGE_ERROR } from '../lib/error';
5import { ROUTE_NAMES } from '../lib/routeNames';
11import { ROUTE_NAMES } from '../lib/routeNames';
6
12
7−export const HistoryContext = React.createContext(null);
13+export const HistoryContext = createContext(null);
8
14
9function _useHistory(initialRoutes = []) {
15function _useHistory(initialRoutes = []) {
10 const [history, setHistory] = useState(initialRoutes);
16 const [history, setHistory] = useState(initialRoutes);
src/bridge/store/network.jsnew file+119
@@ -0,0 +1,119 @@
1+import React, {
2+ createContext,
3+ forwardRef,
4+ useContext,
5+ useMemo,
6+ useState,
7+} from 'react';
8+import * as azimuth from 'azimuth-js';
9+import Web3 from 'web3';
10+import Maybe from 'folktale/maybe';
11+import { includes } from 'lodash';
12+
13+import { CONTRACT_ADDRESSES } from '../lib/contracts';
14+import { NETWORK_TYPES } from '../lib/network';
15+import { isDevelopment } from '../lib/flags';
16+import { BRIDGE_ERROR } from '../lib/error';
17+
18+function _useNetwork(initialNetworkType = null) {
19+ const [networkType, _setNetworkType] = useState(initialNetworkType);
20+
21+ const setNetworkType = networkType => {
22+ if (!includes(NETWORK_TYPES, networkType)) {
23+ throw BRIDGE_ERROR.INVALID_NETWORK_TYPE;
24+ }
25+ _setNetworkType(networkType);
26+ };
27+
28+ const { web3, contracts } = useMemo(() => {
29+ // given a web3 provider and contract addresses,
30+ // build the web3 and contracts objects
31+ const initWeb3 = (provider, contractAddresses) => {
32+ const web3 = new Web3(provider);
33+ const contracts = azimuth.initContracts(web3, contractAddresses);
34+
35+ return {
36+ web3: Maybe.Just(web3),
37+ contracts: Maybe.Just(contracts),
38+ };
39+ };
40+
41+ switch (networkType) {
42+ case NETWORK_TYPES.LOCAL: {
43+ const protocol = isDevelopment ? 'ws' : 'wss';
44+ const endpoint = `${protocol}://localhost:8545`;
45+
46+ return initWeb3(
47+ new Web3.providers.WebsocketProvider(endpoint),
48+ CONTRACT_ADDRESSES.DEV
49+ );
50+ }
51+ case NETWORK_TYPES.ROPSTEN: {
52+ const endpoint = `https://ropsten.infura.io/v3/${process.env.REACT_APP_INFURA_ENDPOINT}`;
53+
54+ return initWeb3(
55+ new Web3.providers.HttpProvider(endpoint),
56+ CONTRACT_ADDRESSES.ROPSTEN
57+ );
58+ }
59+ case NETWORK_TYPES.MAINNET: {
60+ const endpoint = `https://mainnet.infura.io/v3/${process.env.REACT_APP_INFURA_ENDPOINT}`;
61+
62+ return initWeb3(
63+ new Web3.providers.HttpProvider(endpoint),
64+ CONTRACT_ADDRESSES.MAINNET
65+ );
66+ }
67+ case NETWORK_TYPES.OFFLINE:
68+ default: {
69+ // NB (jtobin):
70+ //
71+ // The 'offline' network type targets the mainnet contracts, but does not
72+ // actually use a provider to connect. We use a web3 instance to
73+ // initalise the contracts, but the network itself is set to Nothing.
74+ //
75+ // We may want to offer the ability to select a target network for
76+ // transactions when offline.
77+
78+ // Note: example.com:3456 doesn't actually point to anything, we just need
79+ // a provider to initialize the Web3 object
80+ return {
81+ ...initWeb3(
82+ new Web3.providers.HttpProvider('http://example.com:3456'),
83+ isDevelopment ? CONTRACT_ADDRESSES.DEV : CONTRACT_ADDRESSES.MAINNET
84+ ),
85+ web3: Maybe.Nothing(),
86+ // ^ overwrite the web3 object from initWeb3 with a Maybe.Nothing
87+ // to indicate that there is no valid web3 connection
88+ };
89+ }
90+ }
91+ }, [networkType]);
92+
93+ return { networkType, setNetworkType, web3, contracts };
94+}
95+
96+const NetworkContext = createContext(null);
97+
98+// provider
99+export function NetworkProvider({ initialNetworkType, children }) {
100+ const value = _useNetwork(initialNetworkType);
101+ return (
102+ <NetworkContext.Provider value={value}>{children}</NetworkContext.Provider>
103+ );
104+}
105+
106+// hook consumer
107+export function useNetwork() {
108+ return useContext(NetworkContext);
109+}
110+
111+// hoc consumer
112+export const withNetwork = Component =>
113+ forwardRef((props, ref) => {
114+ return (
115+ <NetworkContext.Consumer>
116+ {value => <Component ref={ref} {...value} {...props} />}
117+ </NetworkContext.Consumer>
118+ );
119+ });
src/bridge/store/online.jsnew file+66
@@ -0,0 +1,66 @@
1+import React, {
2+ createContext,
3+ forwardRef,
4+ useContext,
5+ useEffect,
6+ useState,
7+} from 'react';
8+
9+export const ONLINE_STATUS = {
10+ ONLINE: Symbol('ONLINE'),
11+ OFFLINE: Symbol('OFFLINE'),
12+ UNKNOWN: Symbol('UNKNOWN'),
13+};
14+
15+const getNetworkState = () => {
16+ if ('onLine' in navigator) {
17+ return navigator.onLine ? ONLINE_STATUS.ONLINE : ONLINE_STATUS.OFFLINE;
18+ }
19+
20+ return ONLINE_STATUS.UNKNOWN;
21+};
22+
23+function _useOnline() {
24+ const [online, setOnline] = useState(getNetworkState());
25+
26+ useEffect(() => {
27+ function handleOnlineStatus(event) {
28+ setOnline(getNetworkState());
29+ }
30+
31+ window.addEventListener('online', handleOnlineStatus);
32+ window.addEventListener('offline', handleOnlineStatus);
33+
34+ return () => {
35+ window.removeEventListener('online', handleOnlineStatus);
36+ window.removeEventListener('offline', handleOnlineStatus);
37+ };
38+ }, []);
39+
40+ return online;
41+}
42+
43+const OnlineContext = createContext(null);
44+
45+// provider
46+export function OnlineProvider({ children }) {
47+ const online = _useOnline();
48+ return (
49+ <OnlineContext.Provider value={online}>{children}</OnlineContext.Provider>
50+ );
51+}
52+
53+// hook consumer
54+export function useOnline() {
55+ return useContext(OnlineContext);
56+}
57+
58+// hoc consumer
59+export const withOnline = Component =>
60+ forwardRef((props, ref) => {
61+ return (
62+ <OnlineContext.Consumer>
63+ {online => <Component ref={ref} online={online} {...props} />}
64+ </OnlineContext.Consumer>
65+ );
66+ });
src/bridge/store/txnConfirmations.js+13−8
@@ -1,8 +1,8 @@
1−import React, { forwardRef, useContext, useState } from 'react';
1+import React, { createContext, forwardRef, useContext, useState } from 'react';
2
2
3−export const TxnConfirmationsContext = React.createContext(null);
3+export const TxnConfirmationsContext = createContext(null);
4
4
5−export function TxnConfirmationsProvider({ children }) {
5+function _useTxnConfirmations() {
6 const [confirmations, setConfirmations] = useState({});
6 const [confirmations, setConfirmations] = useState({});
7
7
8 const setTxnConfirmations = (txnHash, txnConfirmations) => {
8 const setTxnConfirmations = (txnHash, txnConfirmations) => {
@@ -12,12 +12,17 @@ export function TxnConfirmationsProvider({ children }) {
12 });
12 });
13 };
13 };
14
14
15+ return {
16+ txnConfirmations: confirmations,
17+ setTxnConfirmations,
18+ };
19+}
20+
21+export function TxnConfirmationsProvider({ children }) {
22+ const value = _useTxnConfirmations();
23+
15 return (
24 return (
16− <TxnConfirmationsContext.Provider
25+ <TxnConfirmationsContext.Provider value={value}>
17− value={{
18− txnConfirmations: confirmations,
19− setTxnConfirmations,
20− }}>
21 {children}
26 {children}
22 </TxnConfirmationsContext.Provider>
27 </TxnConfirmationsContext.Provider>
23 );
28 );
src/bridge/views/AcceptTransfer.js+7−5
@@ -12,8 +12,10 @@ import * as ob from 'urbit-ob';
12import * as need from '../lib/need';
12import * as need from '../lib/need';
13
13
14import StatelessTransaction from '../components/StatelessTransaction';
14import StatelessTransaction from '../components/StatelessTransaction';
15−import { NETWORK_NAMES } from '../lib/network';
15+import { NETWORK_TYPES } from '../lib/network';
16import { isValidAddress } from '../lib/wallet';
16import { isValidAddress } from '../lib/wallet';
17+import { withNetwork } from '../store/network';
18+import { compose } from '../lib/lib';
17
19
18class AcceptTransfer extends React.Component {
20class AcceptTransfer extends React.Component {
19 constructor(props) {
21 constructor(props) {
@@ -61,11 +63,11 @@ class AcceptTransfer extends React.Component {
61 const canGenerate = validAddress === true;
63 const canGenerate = validAddress === true;
62
64
63 const esvisible =
65 const esvisible =
64− props.networkType === NETWORK_NAMES.ROPSTEN ||
66+ props.networkType === NETWORK_TYPES.ROPSTEN ||
65− props.networkType === NETWORK_NAMES.MAINNET;
67+ props.networkType === NETWORK_TYPES.MAINNET;
66
68
67 const esdomain =
69 const esdomain =
68− props.networkType === NETWORK_NAMES.ROPSTEN
70+ props.networkType === NETWORK_TYPES.ROPSTEN
69 ? 'ropsten.etherscan.io'
71 ? 'ropsten.etherscan.io'
70 : 'etherscan.io';
72 : 'etherscan.io';
71
73
@@ -117,4 +119,4 @@ class AcceptTransfer extends React.Component {
117 }
119 }
118}
120}
119
121
120−export default AcceptTransfer;
122+export default compose(withNetwork)(AcceptTransfer);
src/bridge/views/CancelTransfer.js+3−1
@@ -7,6 +7,8 @@ import * as need from '../lib/need';
7
7
8import StatelessTransaction from '../components/StatelessTransaction';
8import StatelessTransaction from '../components/StatelessTransaction';
9import { ETH_ZERO_ADDR } from '../lib/wallet';
9import { ETH_ZERO_ADDR } from '../lib/wallet';
10+import { withNetwork } from '../store/network';
11+import { compose } from '../lib/lib';
10
12
11class CancelTransfer extends React.Component {
13class CancelTransfer extends React.Component {
12 constructor(props) {
14 constructor(props) {
@@ -73,4 +75,4 @@ class CancelTransfer extends React.Component {
73 }
75 }
74}
76}
75
77
76−export default CancelTransfer;
78+export default compose(withNetwork)(CancelTransfer);
src/bridge/views/CreateGalaxy.js+7−6
@@ -15,12 +15,13 @@ import {
15} from '../components/Base';
15} from '../components/Base';
16import StatelessTransaction from '../components/StatelessTransaction';
16import StatelessTransaction from '../components/StatelessTransaction';
17
17
18−import { NETWORK_NAMES } from '../lib/network';
18+import { NETWORK_TYPES } from '../lib/network';
19import { canDecodePatp } from '../lib/txn';
19import { canDecodePatp } from '../lib/txn';
20
20
21import { ETH_ZERO_ADDR, isValidAddress, eqAddr } from '../lib/wallet';
21import { ETH_ZERO_ADDR, isValidAddress, eqAddr } from '../lib/wallet';
22
22
23−import { isValidGalaxy } from '../lib/lib';
23+import { isValidGalaxy, compose } from '../lib/lib';
24+import { withNetwork } from '../store/network';
24
25
25const buttonTriState = status => {
26const buttonTriState = status => {
26 if (status === null) return 'blue';
27 if (status === null) return 'blue';
@@ -117,11 +118,11 @@ class CreateGalaxy extends React.Component {
117 state.isAvailable === true;
118 state.isAvailable === true;
118
119
119 const esvisible =
120 const esvisible =
120− props.networkType === NETWORK_NAMES.ROPSTEN ||
121+ props.networkType === NETWORK_TYPES.ROPSTEN ||
121− props.networkType === NETWORK_NAMES.MAINNET;
122+ props.networkType === NETWORK_TYPES.MAINNET;
122
123
123 const esdomain =
124 const esdomain =
124− props.networkType === NETWORK_NAMES.ROPSTEN
125+ props.networkType === NETWORK_TYPES.ROPSTEN
125 ? 'ropsten.etherscan.io'
126 ? 'ropsten.etherscan.io'
126 : 'etherscan.io';
127 : 'etherscan.io';
127
128
@@ -194,4 +195,4 @@ class CreateGalaxy extends React.Component {
194 }
195 }
195}
196}
196
197
197−export default CreateGalaxy;
198+export default compose(withNetwork)(CreateGalaxy);
src/bridge/views/InviteTicket.js+8−4
@@ -13,7 +13,7 @@ import {
13import * as azimuth from 'azimuth-js';
13import * as azimuth from 'azimuth-js';
14import * as need from '../lib/need';
14import * as need from '../lib/need';
15
15
16−import { randomPatq } from '../lib/lib';
16+import { randomPatq, compose } from '../lib/lib';
17import { ROUTE_NAMES } from '../lib/routeNames';
17import { ROUTE_NAMES } from '../lib/routeNames';
18import { withHistory } from '../store/history';
18import { withHistory } from '../store/history';
19import {
19import {
@@ -28,6 +28,7 @@ import {
28 TRANSACTION_STATES,
28 TRANSACTION_STATES,
29} from '../lib/invite';
29} from '../lib/invite';
30import { generateWallet, startTransactions } from '../lib/invite';
30import { generateWallet, startTransactions } from '../lib/invite';
31+import { withNetwork } from '../store/network';
31
32
32class InviteTicket extends React.Component {
33class InviteTicket extends React.Component {
33 constructor(props) {
34 constructor(props) {
@@ -305,8 +306,8 @@ class InviteTicket extends React.Component {
305 realWalletM: realWallet,
306 realWalletM: realWallet,
306 realPointM: realPoint,
307 realPointM: realPoint,
307 realTicket: verifyTicket,
308 realTicket: verifyTicket,
308− web3M: web3,
309+ web3,
309− contractsM: contracts,
310+ contracts,
310 setUrbitWallet,
311 setUrbitWallet,
311 updateProgress: this.updateProgress,
312 updateProgress: this.updateProgress,
312 }).then(() => {
313 }).then(() => {
@@ -422,4 +423,7 @@ class InviteTicket extends React.Component {
422 }
423 }
423}
424}
424
425
426+export default compose(
427+ withNetwork,
428+ withHistory
425−export default withHistory(InviteTicket);
429+)(InviteTicket);
src/bridge/views/InvitesManage.js+3−1
@@ -14,6 +14,8 @@ import {
14 ValidatedSigil,
14 ValidatedSigil,
15} from '../components/Base';
15} from '../components/Base';
16import StatelessTransaction from '../components/StatelessTransaction';
16import StatelessTransaction from '../components/StatelessTransaction';
17+import { withNetwork } from '../store/network';
18+import { compose } from '../lib/lib';
17
19
18class InvitesManage extends React.Component {
20class InvitesManage extends React.Component {
19 constructor(props) {
21 constructor(props) {
@@ -182,4 +184,4 @@ class InvitesManage extends React.Component {
182 }
184 }
183}
185}
184
186
185−export default InvitesManage;
187+export default compose(withNetwork)(InvitesManage);
src/bridge/views/InvitesSend.js+3−1
@@ -19,6 +19,8 @@ import {
19 toWei,
19 toWei,
20} from '../lib/txn';
20} from '../lib/txn';
21import * as tank from '../lib/tank';
21import * as tank from '../lib/tank';
22+import { withNetwork } from '../store/network';
23+import { compose } from '../lib/lib';
22
24
23const GAS_PRICE_GWEI = 20; // we pay the premium for faster ux
25const GAS_PRICE_GWEI = 20; // we pay the premium for faster ux
24const GAS_LIMIT = 350000;
26const GAS_LIMIT = 350000;
@@ -491,4 +493,4 @@ class InvitesSend extends React.Component {
491 }
493 }
492}
494}
493
495
494−export default InvitesSend;
496+export default compose(withNetwork)(InvitesSend);
src/bridge/views/IssueChild.js+7−5
@@ -19,11 +19,13 @@ import {
19
19
20import StatelessTransaction from '../components/StatelessTransaction';
20import StatelessTransaction from '../components/StatelessTransaction';
21
21
22−import { NETWORK_NAMES } from '../lib/network';
22+import { NETWORK_TYPES } from '../lib/network';
23import { getSpawnCandidate } from '../lib/child';
23import { getSpawnCandidate } from '../lib/child';
24import { canDecodePatp } from '../lib/txn';
24import { canDecodePatp } from '../lib/txn';
25
25
26import { isValidAddress } from '../lib/wallet';
26import { isValidAddress } from '../lib/wallet';
27+import { withNetwork } from '../store/network';
28+import { compose } from '../lib/lib';
27
29
28const setFind = (set, pred) => {
30const setFind = (set, pred) => {
29 for (const e of set) {
31 for (const e of set) {
@@ -151,11 +153,11 @@ class IssueChild extends React.Component {
151 });
153 });
152
154
153 const esvisible =
155 const esvisible =
154− props.networkType === NETWORK_NAMES.ROPSTEN ||
156+ props.networkType === NETWORK_TYPES.ROPSTEN ||
155− props.networkType === NETWORK_NAMES.MAINNET;
157+ props.networkType === NETWORK_TYPES.MAINNET;
156
158
157 const esdomain =
159 const esdomain =
158− props.networkType === NETWORK_NAMES.ROPSTEN
160+ props.networkType === NETWORK_TYPES.ROPSTEN
159 ? 'ropsten.etherscan.io'
161 ? 'ropsten.etherscan.io'
160 : 'etherscan.io';
162 : 'etherscan.io';
161
163
@@ -253,4 +255,4 @@ class IssueChild extends React.Component {
253 }
255 }
254}
256}
255
257
256−export default IssueChild;
258+export default compose(withNetwork)(IssueChild);
src/bridge/views/Keystore.js+2−1
@@ -10,6 +10,7 @@ import { BRIDGE_ERROR } from '../lib/error';
10import { ROUTE_NAMES } from '../lib/routeNames';
10import { ROUTE_NAMES } from '../lib/routeNames';
11import { withHistory } from '../store/history';
11import { withHistory } from '../store/history';
12import { EthereumWallet } from '../lib/wallet';
12import { EthereumWallet } from '../lib/wallet';
13+import { compose } from '../lib/lib';
13
14
14class Keystore extends React.Component {
15class Keystore extends React.Component {
15 constructor(props) {
16 constructor(props) {
@@ -159,4 +160,4 @@ class Keystore extends React.Component {
159 }
160 }
160}
161}
161
162
162−export default withHistory(Keystore);
163+export default compose(withHistory)(Keystore);
src/bridge/views/Ledger.js+2−1
@@ -11,6 +11,7 @@ import * as secp256k1 from 'secp256k1';
11import { LEDGER_LIVE_PATH, LEDGER_LEGACY_PATH } from '../lib/ledger';
11import { LEDGER_LIVE_PATH, LEDGER_LEGACY_PATH } from '../lib/ledger';
12import { ROUTE_NAMES } from '../lib/routeNames';
12import { ROUTE_NAMES } from '../lib/routeNames';
13import { withHistory } from '../store/history';
13import { withHistory } from '../store/history';
14+import { compose } from '../lib/lib';
14
15
15const chopHdPrefix = str => (str.slice(0, 2) === 'm/' ? str.slice(2) : str);
16const chopHdPrefix = str => (str.slice(0, 2) === 'm/' ? str.slice(2) : str);
16
17
@@ -217,4 +218,4 @@ class Ledger extends React.Component {
217 }
218 }
218}
219}
219
220
220−export default withHistory(Ledger);
221+export default compose(withHistory)(Ledger);
src/bridge/views/Mnemonic.js+2−1
@@ -13,6 +13,7 @@ import { Row, Col, H1 } from '../components/Base';
13import { ROUTE_NAMES } from '../lib/routeNames';
13import { ROUTE_NAMES } from '../lib/routeNames';
14import { withHistory } from '../store/history';
14import { withHistory } from '../store/history';
15import { DEFAULT_HD_PATH, walletFromMnemonic } from '../lib/wallet';
15import { DEFAULT_HD_PATH, walletFromMnemonic } from '../lib/wallet';
16+import { compose } from '../lib/lib';
16
17
17class Mnemonic extends React.Component {
18class Mnemonic extends React.Component {
18 constructor(props) {
19 constructor(props) {
@@ -160,4 +161,4 @@ class Mnemonic extends React.Component {
160 }
161 }
161}
162}
162
163
163−export default withHistory(Mnemonic);
164+export default compose(withHistory)(Mnemonic);
src/bridge/views/Network.js+59−138
@@ -1,145 +1,66 @@
1−import Maybe from 'folktale/maybe';
2import React from 'react';
1import React from 'react';
2+
3import { Button } from '../components/Base';
3import { Button } from '../components/Base';
4import { InnerLabelDropdown } from '../components/Base';
4import { InnerLabelDropdown } from '../components/Base';
5import { Row, Col, H1, P } from '../components/Base';
5import { Row, Col, H1, P } from '../components/Base';
6−import * as azimuth from 'azimuth-js';
7−import Web3 from 'web3';
8−
9−import { CONTRACT_ADDRESSES } from '../lib/contracts';
10−import { NETWORK_NAMES, renderNetworkType } from '../lib/network';
6+import { NETWORK_TYPES, renderNetworkType } from '../lib/network';
11import { ROUTE_NAMES } from '../lib/routeNames';
7import { ROUTE_NAMES } from '../lib/routeNames';
12−import { withHistory } from '../store/history';
8+import { useHistory } from '../store/history';
13−
9+import { useNetwork } from '../store/network';
14−class Network extends React.Component {
10+
15− constructor(props) {
11+const kNetworkOptions = [
16− super(props);
17−
18− this.handleNetworkChange = this.handleNetworkChange.bind(this);
19− }
20−
21− handleNetworkChange(network) {
22− const { setNetworkType, setNetwork } = this.props;
23−
24− if (network === NETWORK_NAMES.LOCAL) {
25− setNetworkType(network);
26−
27− const endpoint = 'ws://localhost:8545';
28− const provider = new Web3.providers.WebsocketProvider(endpoint);
29− const web3 = new Web3(provider);
30− const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.DEV);
31−
32− setNetwork(Maybe.Just(web3), Maybe.Just(contracts));
33− }
34−
35− if (network === NETWORK_NAMES.ROPSTEN) {
36− setNetworkType(network);
37−
38− const endpoint = `https://ropsten.infura.io/v3/${process.env.REACT_APP_INFURA_ENDPOINT}`;
39−
40− const provider = new Web3.providers.HttpProvider(endpoint);
41− const web3 = new Web3(provider);
42− const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.ROPSTEN);
43−
44− setNetwork(Maybe.Just(web3), Maybe.Just(contracts));
45− }
46−
47− if (network === NETWORK_NAMES.MAINNET) {
48− setNetworkType(network);
49−
50− const endpoint = `https://mainnet.infura.io/v3/${process.env.REACT_APP_INFURA_ENDPOINT}`;
51−
52− const provider = new Web3.providers.HttpProvider(endpoint);
53− const web3 = new Web3(provider);
54− const contracts = azimuth.initContracts(web3, CONTRACT_ADDRESSES.MAINNET);
55−
56− setNetwork(Maybe.Just(web3), Maybe.Just(contracts));
57− }
58−
59− if (network === NETWORK_NAMES.OFFLINE) {
60− setNetworkType(network);
61−
62− // NB (jtobin):
63− //
64− // The 'offline' network type targets the mainnet contracts, but does not
65− // actually use a provider to connect. We use a web3 instance to
66− // initalise the contracts, but the network itself is set to Nothing.
67− //
68− // We may want to offer the ability to select a target network for
69− // transactions when offline.
70−
71− // Note: localhost:3456 doesn't actually point to anything, we just need
72− // a provider to initialize the Web3 object
73− const provider = new Web3.providers.HttpProvider('http://localhost:3456');
74− const web3 = new Web3(provider);
75−
76− const target =
77− process.env.NODE_ENV === 'development'
78− ? CONTRACT_ADDRESSES.DEV
79− : CONTRACT_ADDRESSES.MAINNET;
80−
81− const contracts = azimuth.initContracts(web3, target);
82−
83− setNetwork(Maybe.Nothing(), Maybe.Just(contracts));
84− }
85− }
86−
87− getNetworkOptions() {
88− return [
89− {
12+ {
90− title: 'Main Network (default)',
13+ title: 'Main Network (default)',
91− value: NETWORK_NAMES.MAINNET,
14+ value: NETWORK_TYPES.MAINNET,
92− },
15+ },
93− {
16+ {
17+ title: 'Ropsten',
18+ value: NETWORK_TYPES.ROPSTEN,
19+ },
20+ {
94− title: 'Local Node',
21+ title: 'Local Node',
95− value: NETWORK_NAMES.LOCAL,
22+ value: NETWORK_TYPES.LOCAL,
96− },
97− {
98− title: 'Ropsten',
99− value: NETWORK_NAMES.ROPSTEN,
100− },
23+ },
101− {
24+ {
102− type: 'divider',
25+ type: 'divider',
103− },
26+ },
104− {
27+ {
105− title: 'Offline',
28+ title: 'Offline',
106− value: NETWORK_NAMES.OFFLINE,
29+ value: NETWORK_TYPES.OFFLINE,
107− },
30+ },
108− ];
31+];
109− }
32+
110−
33+function Network() {
111− render() {
112− const { networkType, history } = this.props;
34+ const { networkType, setNetworkType } = useNetwork();
113− const networkOptions = this.getNetworkOptions();
35+ const history = useHistory();
114−
36+
115− return (
37+ return (
116− <Row>
38+ <Row>
117− <Col>
39+ <Col>
118− <H1>{'Select Network'}</H1>
40+ <H1>{'Select Network'}</H1>
119−
41+
120− <P>
42+ <P>
121− {"Please select the Ethereum node you'd like to send " +
43+ {"Please select the Ethereum node you'd like to send " +
122− 'transactions to. For highly valuable keys, please select ' +
44+ 'transactions to. For highly valuable keys, please select ' +
123− 'offline mode.'}
45+ 'offline mode.'}
124− </P>
46+ </P>
125−
47+
126− <InnerLabelDropdown
48+ <InnerLabelDropdown
127− className={'mt-6'}
49+ className={'mt-6'}
128− title={'Node:'}
50+ title={'Node:'}
129− handleUpdate={this.handleNetworkChange}
51+ handleUpdate={setNetworkType}
130− options={networkOptions}
52+ options={kNetworkOptions}
131− currentSelectionTitle={renderNetworkType(networkType)}
53+ currentSelectionTitle={renderNetworkType(networkType)}
132− />
54+ />
133−
55+
134− <Button
56+ <Button
135− className={'mt-10'}
57+ className={'mt-10'}
136− onClick={() => history.push(ROUTE_NAMES.WALLET)}>
58+ onClick={() => history.push(ROUTE_NAMES.WALLET)}>
137− {'Continue →'}
59+ {'Continue →'}
138− </Button>
60+ </Button>
139− </Col>
61+ </Col>
140− </Row>
62+ </Row>
141− );
63+ );
142− }
143}
64}
144
65
145−export default withHistory(Network);
66+export default Network;
src/bridge/views/Point.js+6−1
@@ -11,6 +11,8 @@ import KeysAndMetadata from './Point/KeysAndMetadata';
11import Actions from './Point/Actions';
11import Actions from './Point/Actions';
12import { Row, Col, H1, H3 } from '../components/Base';
12import { Row, Col, H1, H3 } from '../components/Base';
13import { withHistory } from '../store/history';
13import { withHistory } from '../store/history';
14+import { withNetwork } from '../store/network';
15+import { compose } from '../lib/lib';
14
16
15class Point extends React.Component {
17class Point extends React.Component {
16 constructor(props) {
18 constructor(props) {
@@ -135,4 +137,7 @@ class Point extends React.Component {
135 }
137 }
136}
138}
137
139
140+export default compose(
141+ withNetwork,
138−export default withHistory(Point);
142+ withHistory
143+)(Point);
src/bridge/views/Points.js+8−3
@@ -4,10 +4,12 @@ import { Button } from '../components/Base';
4import * as azimuth from 'azimuth-js';
4import * as azimuth from 'azimuth-js';
5
5
6import PointList from '../components/PointList';
6import PointList from '../components/PointList';
7−import { NETWORK_NAMES } from '../lib/network';
7+import { NETWORK_TYPES } from '../lib/network';
8import { ROUTE_NAMES } from '../lib/routeNames';
8import { ROUTE_NAMES } from '../lib/routeNames';
9import { withHistory } from '../store/history';
9import { withHistory } from '../store/history';
10import { ETH_ZERO_ADDR, eqAddr } from '../lib/wallet';
10import { ETH_ZERO_ADDR, eqAddr } from '../lib/wallet';
11+import { withNetwork } from '../store/network';
12+import { compose } from '../lib/lib';
11
13
12const hasTransferProxy = (cache, point) =>
14const hasTransferProxy = (cache, point) =>
13 point in cache ? !eqAddr(cache[point].transferProxy, ETH_ZERO_ADDR) : false;
15 point in cache ? !eqAddr(cache[point].transferProxy, ETH_ZERO_ADDR) : false;
@@ -17,7 +19,7 @@ class Points extends React.Component {
17 super(props);
19 super(props);
18
20
19 const { networkType } = props;
21 const { networkType } = props;
20− const loading = networkType !== NETWORK_NAMES.OFFLINE;
22+ const loading = networkType !== NETWORK_TYPES.OFFLINE;
21
23
22 this.state = {
24 this.state = {
23 points: [],
25 points: [],
@@ -255,4 +257,7 @@ class Points extends React.Component {
255 }
257 }
256}
258}
257
259
260+export default compose(
261+ withNetwork,
258−export default withHistory(Points);
262+ withHistory
263+)(Points);
src/bridge/views/PrivateKey.js+2−1
@@ -7,6 +7,7 @@ import { Row, Col, H1 } from '../components/Base';
7import { ROUTE_NAMES } from '../lib/routeNames';
7import { ROUTE_NAMES } from '../lib/routeNames';
8import { withHistory } from '../store/history';
8import { withHistory } from '../store/history';
9import { EthereumWallet } from '../lib/wallet';
9import { EthereumWallet } from '../lib/wallet';
10+import { compose } from '../lib/lib';
10
11
11class PrivateKey extends React.Component {
12class PrivateKey extends React.Component {
12 constructor(props) {
13 constructor(props) {
@@ -73,4 +74,4 @@ class PrivateKey extends React.Component {
73 }
74 }
74}
75}
75
76
76−export default withHistory(PrivateKey);
77+export default compose(withHistory)(PrivateKey);
src/bridge/views/SentTransaction.js+15−10
@@ -7,8 +7,9 @@ import { Button } from '../components/Base';
7import { ROUTE_NAMES } from '../lib/routeNames';
7import { ROUTE_NAMES } from '../lib/routeNames';
8import { useHistory } from '../store/history';
8import { useHistory } from '../store/history';
9import { BRIDGE_ERROR, renderTxnError } from '../lib/error';
9import { BRIDGE_ERROR, renderTxnError } from '../lib/error';
10−import { NETWORK_NAMES } from '../lib/network';
10+import { NETWORK_TYPES } from '../lib/network';
11−import { withTxnConfirmations } from '../store/txnConfirmations';
11+import { useTxnConfirmations } from '../store/txnConfirmations';
12+import { useNetwork } from '../store/network';
12
13
13class Success extends React.Component {
14class Success extends React.Component {
14 constructor(props) {
15 constructor(props) {
@@ -39,11 +40,11 @@ class Success extends React.Component {
39 const { pending } = state;
40 const { pending } = state;
40
41
41 const esvisible =
42 const esvisible =
42− networkType === NETWORK_NAMES.ROPSTEN ||
43+ networkType === NETWORK_TYPES.ROPSTEN ||
43− networkType === NETWORK_NAMES.MAINNET;
44+ networkType === NETWORK_TYPES.MAINNET;
44
45
45 const esdomain =
46 const esdomain =
46− networkType === NETWORK_NAMES.ROPSTEN
47+ networkType === NETWORK_TYPES.ROPSTEN
47 ? 'ropsten.etherscan.io'
48 ? 'ropsten.etherscan.io'
48 : 'etherscan.io';
49 : 'etherscan.io';
49
50
@@ -109,14 +110,18 @@ const Failure = props => (
109 </Row>
110 </Row>
110);
111);
111
112
112−const SentTransaction = props => {
113+function SentTransaction(props) {
113 const history = useHistory();
114 const history = useHistory();
115+ const { txnConfirmations } = useTxnConfirmations();
116+ const { web3 } = useNetwork();
117+
114− const { txnHashCursor, networkType, txnConfirmations } = props;
118+ const { txnHashCursor, networkType } = props;
115 const { setPointCursor, pointCursor } = props;
119 const { setPointCursor, pointCursor } = props;
116
120
117 const promptKeyfile = history.data && history.data.promptKeyfile;
121 const promptKeyfile = history.data && history.data.promptKeyfile;
118
122
123+ // TODO: remove need's assumption about accepting the props object
119− const w3 = need.web3(props);
124+ const w3 = need.web3({ web3 });
120
125
121 const result = txnHashCursor.matchWith({
126 const result = txnHashCursor.matchWith({
122 Nothing: _ => {
127 Nothing: _ => {
@@ -174,6 +179,6 @@ const SentTransaction = props => {
174 {keyfile}
179 {keyfile}
175 </div>
180 </div>
176 );
181 );
177−};
182+}
178
183
179−export default withTxnConfirmations(SentTransaction);
184+export default SentTransaction;
src/bridge/views/SetKeys.js+3−1
@@ -11,6 +11,8 @@ import { attemptSeedDerivation } from '../lib/keys';
11import * as kg from 'urbit-key-generation/dist/index';
11import * as kg from 'urbit-key-generation/dist/index';
12
12
13import { addHexPrefix } from '../lib/wallet';
13import { addHexPrefix } from '../lib/wallet';
14+import { withNetwork } from '../store/network';
15+import { compose } from '../lib/lib';
14
16
15class SetKeys extends React.Component {
17class SetKeys extends React.Component {
16 constructor(props) {
18 constructor(props) {
@@ -196,4 +198,4 @@ class SetKeys extends React.Component {
196 }
198 }
197}
199}
198
200
199−export default SetKeys;
201+export default compose(withNetwork)(SetKeys);
src/bridge/views/SetProxy.js+20−18
@@ -17,25 +17,15 @@ import * as ob from 'urbit-ob';
17
17
18import { PROXY_TYPE, renderProxyType } from '../lib/proxy';
18import { PROXY_TYPE, renderProxyType } from '../lib/proxy';
19
19
20−import { NETWORK_NAMES } from '../lib/network';
20+import { NETWORK_TYPES } from '../lib/network';
21
21
22import StatelessTransaction from '../components/StatelessTransaction';
22import StatelessTransaction from '../components/StatelessTransaction';
23
23
24import { isValidAddress } from '../lib/wallet';
24import { isValidAddress } from '../lib/wallet';
25+import { withNetwork } from '../store/network';
26+import { compose } from '../lib/lib';
25
27
26−const SetManagementProxy = props => (
27− <SetProxy {...props} proxyType={PROXY_TYPE.MANAGEMENT_PROXY} />
28−);
29−
30−const SetSpawnProxy = props => (
31− <SetProxy {...props} proxyType={PROXY_TYPE.SPAWN_PROXY} />
32−);
33−
34−const SetTransferProxy = props => (
35− <SetProxy {...props} proxyType={PROXY_TYPE.TRANSFER_PROXY} />
36−);
37−
38−class SetProxy extends React.Component {
28+class _SetProxy extends React.Component {
39 constructor(props) {
29 constructor(props) {
40 super(props);
30 super(props);
41
31
@@ -99,11 +89,11 @@ class SetProxy extends React.Component {
99 const canGenerate = validAddress === true;
89 const canGenerate = validAddress === true;
100
90
101 const esvisible =
91 const esvisible =
102− props.networkType === NETWORK_NAMES.ROPSTEN ||
92+ props.networkType === NETWORK_TYPES.ROPSTEN ||
103− props.networkType === NETWORK_NAMES.MAINNET;
93+ props.networkType === NETWORK_TYPES.MAINNET;
104
94
105 const esdomain =
95 const esdomain =
106− props.networkType === NETWORK_NAMES.ROPSTEN
96+ props.networkType === NETWORK_TYPES.ROPSTEN
107 ? 'ropsten.etherscan.io'
97 ? 'ropsten.etherscan.io'
108 : 'etherscan.io';
98 : 'etherscan.io';
109
99
@@ -179,4 +169,16 @@ class SetProxy extends React.Component {
179 }
169 }
180}
170}
181
171
172+const SetProxy = compose(withNetwork)(_SetProxy);
173+
182−export { SetManagementProxy, SetSpawnProxy, SetTransferProxy };
174+export const SetManagementProxy = props => (
175+ <SetProxy {...props} proxyType={PROXY_TYPE.MANAGEMENT_PROXY} />
176+);
177+
178+export const SetSpawnProxy = props => (
179+ <SetProxy {...props} proxyType={PROXY_TYPE.SPAWN_PROXY} />
180+);
181+
182+export const SetTransferProxy = props => (
183+ <SetProxy {...props} proxyType={PROXY_TYPE.TRANSFER_PROXY} />
184+);
src/bridge/views/Shards.js+2−1
@@ -16,6 +16,7 @@ import * as ob from 'urbit-ob';
16import { ROUTE_NAMES } from '../lib/routeNames';
16import { ROUTE_NAMES } from '../lib/routeNames';
17import { withHistory } from '../store/history';
17import { withHistory } from '../store/history';
18import { urbitWalletFromTicket } from '../lib/wallet';
18import { urbitWalletFromTicket } from '../lib/wallet';
19+import { compose } from '../lib/lib';
19
20
20const placeholder = len => {
21const placeholder = len => {
21 let bytes = window.crypto.getRandomValues(new Uint8Array(len));
22 let bytes = window.crypto.getRandomValues(new Uint8Array(len));
@@ -211,4 +212,4 @@ class Shards extends React.Component {
211 }
212 }
212}
213}
213
214
214−export default withHistory(Shards);
215+export default compose(withHistory)(Shards);
src/bridge/views/Ticket.js+2−2
@@ -11,7 +11,7 @@ import {
11} from '../components/Base';
11} from '../components/Base';
12import { Row, Col, H1, P } from '../components/Base';
12import { Row, Col, H1, P } from '../components/Base';
13
13
14−import { randomPatq } from '../lib/lib';
14+import { randomPatq, compose } from '../lib/lib';
15import { ROUTE_NAMES } from '../lib/routeNames';
15import { ROUTE_NAMES } from '../lib/routeNames';
16import { withHistory } from '../store/history';
16import { withHistory } from '../store/history';
17import { urbitWalletFromTicket } from '../lib/wallet';
17import { urbitWalletFromTicket } from '../lib/wallet';
@@ -150,4 +150,4 @@ class Ticket extends React.Component {
150 }
150 }
151}
151}
152
152
153−export default withHistory(Ticket);
153+export default compose(withHistory)(Ticket);
src/bridge/views/Transfer.js+7−5
@@ -16,9 +16,11 @@ import {
16import { AddressInput } from '../components/Base';
16import { AddressInput } from '../components/Base';
17import StatelessTransaction from '../components/StatelessTransaction';
17import StatelessTransaction from '../components/StatelessTransaction';
18
18
19−import { NETWORK_NAMES } from '../lib/network';
19+import { NETWORK_TYPES } from '../lib/network';
20
20
21import { isValidAddress } from '../lib/wallet';
21import { isValidAddress } from '../lib/wallet';
22+import { withNetwork } from '../store/network';
23+import { compose } from '../lib/lib';
22
24
23class Transfer extends React.Component {
25class Transfer extends React.Component {
24 constructor(props) {
26 constructor(props) {
@@ -70,11 +72,11 @@ class Transfer extends React.Component {
70 const canGenerate = validAddress === true;
72 const canGenerate = validAddress === true;
71
73
72 const esvisible =
74 const esvisible =
73− props.networkType === NETWORK_NAMES.ROPSTEN ||
75+ props.networkType === NETWORK_TYPES.ROPSTEN ||
74− props.networkType === NETWORK_NAMES.MAINNET;
76+ props.networkType === NETWORK_TYPES.MAINNET;
75
77
76 const esdomain =
78 const esdomain =
77− props.networkType === NETWORK_NAMES.ROPSTEN
79+ props.networkType === NETWORK_TYPES.ROPSTEN
78 ? 'ropsten.etherscan.io'
80 ? 'ropsten.etherscan.io'
79 : 'etherscan.io';
81 : 'etherscan.io';
80
82
@@ -130,4 +132,4 @@ class Transfer extends React.Component {
130 }
132 }
131}
133}
132
134
133−export default Transfer;
135+export default compose(withNetwork)(Transfer);
src/bridge/views/Trezor.js+2−1
@@ -10,6 +10,7 @@ import * as secp256k1 from 'secp256k1';
10import { TREZOR_PATH } from '../lib/trezor';
10import { TREZOR_PATH } from '../lib/trezor';
11import { ROUTE_NAMES } from '../lib/routeNames';
11import { ROUTE_NAMES } from '../lib/routeNames';
12import { withHistory } from '../store/history';
12import { withHistory } from '../store/history';
13+import { compose } from '../lib/lib';
13
14
14class Trezor extends React.Component {
15class Trezor extends React.Component {
15 constructor(props) {
16 constructor(props) {
@@ -139,4 +140,4 @@ class Trezor extends React.Component {
139 }
140 }
140}
141}
141
142
142−export default withHistory(Trezor);
143+export default compose(withHistory)(Trezor);
src/bridge/views/ViewPoint.js+2−1
@@ -8,6 +8,7 @@ import { InnerLabel, PointInput, ValidatedSigil } from '../components/Base';
8
8
9import { ROUTE_NAMES } from '../lib/routeNames';
9import { ROUTE_NAMES } from '../lib/routeNames';
10import { withHistory } from '../store/history';
10import { withHistory } from '../store/history';
11+import { compose } from '../lib/lib';
11
12
12class ViewPoint extends React.Component {
13class ViewPoint extends React.Component {
13 constructor(props) {
14 constructor(props) {
@@ -80,4 +81,4 @@ class ViewPoint extends React.Component {
80 }
81 }
81}
82}
82
83
83−export default withHistory(ViewPoint);
84+export default compose(withHistory)(ViewPoint);
src/bridge/views/Wallet.js+2−1
@@ -7,6 +7,7 @@ import { Row, Col } from '../components/Base';
7import { ROUTE_NAMES } from '../lib/routeNames';
7import { ROUTE_NAMES } from '../lib/routeNames';
8import { withHistory } from '../store/history';
8import { withHistory } from '../store/history';
9import { WALLET_NAMES, renderWalletType } from '../lib/wallet';
9import { WALLET_NAMES, renderWalletType } from '../lib/wallet';
10+import { compose } from '../lib/lib';
10
11
11class Wallet extends React.Component {
12class Wallet extends React.Component {
12 componentDidMount() {
13 componentDidMount() {
@@ -104,4 +105,4 @@ class Wallet extends React.Component {
104 }
105 }
105}
106}
106
107
107−export default withHistory(Wallet);
108+export default compose(withHistory)(Wallet);
src/walletgen/Walletgen.js+21−41
@@ -4,7 +4,7 @@ import * as lodash from 'lodash';
4import Header from './components/Header';
4import Header from './components/Header';
5import Footer from './components/Footer';
5import Footer from './components/Footer';
6
6
7−import { NETWORK_STATES, PROFILE_STATES, GEN_STATES } from './lib/constants';
7+import { PROFILE_STATES, GEN_STATES } from './lib/constants';
8
8
9import PrivacyPolicy from './views/PrivacyPolicy';
9import PrivacyPolicy from './views/PrivacyPolicy';
10import Welcome from './views/Welcome';
10import Welcome from './views/Welcome';
@@ -19,8 +19,7 @@ import Done from './views/Done';
19
19
20import './style/index.css';
20import './style/index.css';
21
21
22−const checkNetwork = () =>
22+import { OnlineProvider } from '../bridge/store/online';
23− navigator.onLine ? NETWORK_STATES.ONLINE : NETWORK_STATES.OFFLINE;
24
23
25const ROUTES = [
24const ROUTES = [
26 { path: '/Welcome', Component: Welcome },
25 { path: '/Welcome', Component: Welcome },
@@ -41,7 +40,6 @@ class Walletgen extends React.Component {
41 constructor(props) {
40 constructor(props) {
42 super(props);
41 super(props);
43 this.state = {
42 this.state = {
44− network: checkNetwork(),
45 'profile.state': PROFILE_STATES.NOSTART,
43 'profile.state': PROFILE_STATES.NOSTART,
46 'profile.value': null,
44 'profile.value': null,
47 'profile.shipCount': 0,
45 'profile.shipCount': 0,
@@ -65,18 +63,9 @@ class Walletgen extends React.Component {
65 };
63 };
66 }
64 }
67
65
68− componentDidMount = () => {
69− window.addEventListener('online', () =>
70− this.setState({ network: NETWORK_STATES.ONLINE })
71− );
72− window.addEventListener('offline', () =>
73− this.setState({ network: NETWORK_STATES.OFFLINE })
74− );
75− };
76−
77 setGlobalState = state => this.setState(state);
66 setGlobalState = state => this.setState(state);
78
67
79− router = (network, path) => {
68+ router = path => {
80 const route = key => {
69 const route = key => {
81 const { Component } = lodash.find(ROUTES, { path: key });
70 const { Component } = lodash.find(ROUTES, { path: key });
82 const globals = {
71 const globals = {
@@ -87,39 +76,30 @@ class Walletgen extends React.Component {
87 };
76 };
88
77
89 return route(path);
78 return route(path);
90−
91− // return network === NETWORK_STATES.ONLINE
92− // ? <NetworkWarning />
93− // : !(network === NETWORK_STATES.OFFLINE)
94− // ? <h1>Detecting your network state.</h1>
95− // : route(path)
96 };
79 };
97
80
98 render() {
81 render() {
99− const { network, route, currentStep, lastRoute } = this.state;
82+ const { route, currentStep, lastRoute } = this.state;
100
83
101− const routed = this.router(network, route); // hacky prod
84+ const routed = this.router(route);
102− // const routed = this.router(NETWORK_STATES.OFFLINE, true, route) // hacky dev
103
85
104 return (
86 return (
87+ <OnlineProvider>
105− <main className={'container'}>
88+ <main className={'container'}>
106− <Header
107− network={network}
108− currentStep={currentStep}
89+ <Header currentStep={currentStep} totalSteps={TOTAL_STEPS} />
109− totalSteps={TOTAL_STEPS}
90+
110− />
111−
112− <div className={'row wrapper'}>
91+ <div className={'row wrapper'}>
113− <div className={'col-'}>{routed}</div>
92+ <div className={'col-'}>{routed}</div>
114− <div className={'push'} />
93+ <div className={'push'} />
115− </div>
94+ </div>
116−
95+
117− <Footer
96+ <Footer
118− route={route}
97+ route={route}
119− lastRoute={lastRoute}
98+ lastRoute={lastRoute}
120− setGlobalState={this.setGlobalState}
99+ setGlobalState={this.setGlobalState}
121− />
100+ />
122− </main>
101+ </main>
102+ </OnlineProvider>
123 );
103 );
124 }
104 }
125}
105}
src/walletgen/components/Header.js+35−24
@@ -1,7 +1,7 @@
1import React from 'react';
1import React from 'react';
2−import { seq } from '../lib/lib';
3
2
4−import { NETWORK_STATES } from '../lib/constants';
3+import { useOnline, ONLINE_STATUS } from '../../bridge/store/online';
4+import { seq } from '../../bridge/lib/lib';
5
5
6const StatusIndicator = props => (
6const StatusIndicator = props => (
7 <div className={`flex h-9 align-center ${props.c2} flex-shrink-0`}>
7 <div className={`flex h-9 align-center ${props.c2} flex-shrink-0`}>
@@ -12,27 +12,38 @@ const StatusIndicator = props => (
12 </div>
12 </div>
13);
13);
14
14
15−const ChooseIndicator = props =>
15+function ChooseIndicator(props) {
16− props.network === NETWORK_STATES.ONLINE ? (
16+ const online = useOnline();
17+
18+ switch (online) {
19+ case ONLINE_STATUS.ONLINE:
20+ return (
17− <StatusIndicator
21+ <StatusIndicator
18− message={'You are online.'}
22+ message={'You are online.'}
19− c1={'bg-red'}
23+ c1={'bg-red'}
20− c2={'bg-red'}
24+ c2={'bg-red'}
21− error
25+ error
22− />
26+ />
23− ) : props.network === NETWORK_STATES.OFFLINE ? (
27+ );
28+ case ONLINE_STATUS.OFFLINE:
29+ return (
24− <StatusIndicator
30+ <StatusIndicator
25− message={'You are offline.'}
31+ message={'You are offline.'}
26− c1={'bg-green'}
32+ c1={'bg-green'}
27− c2={'bg-green'}
33+ c2={'bg-green'}
28− />
34+ />
29− ) : (
35+ );
36+ case ONLINE_STATUS.UNKNOWN:
37+ default:
38+ return (
30− <StatusIndicator
39+ <StatusIndicator
31− message={'Checking network connection..'}
40+ message={'Checking network connection..'}
32− c1={'bg-orange'}
41+ c1={'bg-orange'}
33− c2={'bg-orange'}
42+ c2={'bg-orange'}
34− />
43+ />
35− );
44+ );
45+ }
46+}
36
47
37const ProgressIndicator = ({ currentStep, totalSteps }) => (
48const ProgressIndicator = ({ currentStep, totalSteps }) => (
38 <div className={'relative h-9 col- mb-0'}>
49 <div className={'relative h-9 col- mb-0'}>
@@ -61,7 +72,7 @@ const Header = props => (
61 totalSteps={props.totalSteps}
72 totalSteps={props.totalSteps}
62 currentStep={props.currentStep}
73 currentStep={props.currentStep}
63 />
74 />
64− <ChooseIndicator network={props.network} />
75+ <ChooseIndicator />
65 </div>
76 </div>
66 <div className={'col-md-8 h-15 flex align-center'}>
77 <div className={'col-md-8 h-15 flex align-center'}>
67 <h1 className={'m-0 p-0'}>{'Wallet Generator'}</h1>
78 <h1 className={'m-0 p-0'}>{'Wallet Generator'}</h1>
src/walletgen/lib/constants.js−7
@@ -11,12 +11,6 @@ const GALAXY_ENTROPY_BITS = 384;
11
11
12const SEED_ENTROPY_BITS = 128;
12const SEED_ENTROPY_BITS = 128;
13
13
14−const NETWORK_STATES = {
15− ONLINE: Symbol('ONLINE'),
16− OFFLINE: Symbol('OFFLINE'),
17− UNKNOWN: Symbol('UNKNOWN'),
18−};
19−
20const GEN_STATES = {
14const GEN_STATES = {
21 ENY_NOSTART: Symbol('ENY_NOSTART'),
15 ENY_NOSTART: Symbol('ENY_NOSTART'),
22 ENY_PENDING: Symbol('ENY_PENDING'),
16 ENY_PENDING: Symbol('ENY_PENDING'),
@@ -48,7 +42,6 @@ const PROFILE_STATES = {
48};
42};
49
43
50export {
44export {
51− NETWORK_STATES,
52 GEN_STATES,
45 GEN_STATES,
53 BUTTON_STATES,
46 BUTTON_STATES,
54 PROFILE_STATES,
47 PROFILE_STATES,
src/walletgen/lib/lib.js+1−6
@@ -66,9 +66,4 @@ const generateWallet = async (point, ticket, boot) => {
66const generateOwnershipWallet = (ship, ticket) =>
66const generateOwnershipWallet = (ship, ticket) =>
67 kg.generateOwnershipWallet({ ship, ticket });
67 kg.generateOwnershipWallet({ ship, ticket });
68
68
69−const seq = num => Array.from(Array(num), (_, i) => i);
70−
71−const compose = (...fs) =>
72− fs.reduceRight((pF, nF) => (...args) => nF(pF(...args)), v => v);
73−
74−export { makeTicket, generateWallet, generateOwnershipWallet, compose, seq };
69+export { makeTicket, generateWallet, generateOwnershipWallet };
src/walletgen/views/Upload.js+1−1
@@ -3,7 +3,7 @@ import React, { Component } from 'react';
3import Button from '../components/Button';
3import Button from '../components/Button';
4import UploadButton from '../components/UploadButton';
4import UploadButton from '../components/UploadButton';
5
5
6−import { compose } from '../lib/lib';
6+import { compose } from '../../bridge/lib/lib';
7
7
8import { PROFILE_STATES } from '../lib/constants';
8import { PROFILE_STATES } from '../lib/constants';
9
9