on 5eceb4e help sign in
bridge/src/store/network.js
174 lines 5.2 kB history raw
1import React, {
2 createContext,
3 forwardRef,
4 useContext,
5 useMemo,
6 useState,
7 useEffect,
8} from 'react';
9import { Just, Nothing } from 'folktale/maybe';
10import * as azimuth from 'azimuth-js';
11import Web3 from 'web3';
12import { includes } from 'lodash';
14import { CONTRACT_ADDRESSES } from '../lib/contracts';
15import { NETWORK_TYPES, chainIdToNetworkType } from '../lib/network';
16import { isDevelopment } from '../lib/flags';
17import { BRIDGE_ERROR } from '../lib/error';
19import { Grid } from 'indigo-react';
20import View from 'components/View';
21import Blinky from 'components/Blinky';
23function _useNetwork(initialNetworkType = null) {
24 const [networkType, setNetworkType] = useState(initialNetworkType);
26 const [metamask, setMetamask] = useState(false);
27 const [web3, setWeb3] = useState(Nothing());
28 const [contracts, setContracts] = useState(Nothing());
30 useEffect(() => {
31 (async () => {
32 if (window.ethereum) {
33 try {
34 await window.ethereum.enable();
35 setMetamask(true);
36 setNetworkType(chainIdToNetworkType(window.ethereum.chainId));
37 } catch (e) {
38 console.log('Metamask denied');
39 }
40 }
41 })();
42 }, []);
44 useEffect(() => {
45 (async () => {
46 // given a web3 provider and contract addresses,
47 // build the web3 and contracts objects
48 const initWeb3 = async (provider, contractAddresses) => {
49 // use an in-window eth provider if possible
50 const _provider = metamask ? window.ethereum : provider;
51 const web3 = new Web3(_provider);
53 let contracts = await azimuth.initContractsPartial(
54 web3,
55 contractAddresses.azimuth
56 );
57 contracts = azimuth.contracts.newLinearStarRelease(
58 contracts,
59 web3,
60 contractAddresses.linearSR
61 );
62 contracts = azimuth.contracts.newConditionalStarRelease(
63 contracts,
64 web3,
65 contractAddresses.conditionalSR
66 );
67 contracts = azimuth.contracts.newDelegatedSending(
68 contracts,
69 web3,
70 contractAddresses.delegatedSending
71 );
73 setWeb3(Just(web3));
74 setContracts(Just(contracts));
75 return;
76 };
78 switch (networkType) {
79 case NETWORK_TYPES.LOCAL: {
80 const protocol = isDevelopment ? 'ws' : 'wss';
81 const endpoint = `${protocol}://${document.location.hostname}:8545`;
83 initWeb3(
84 new Web3.providers.WebsocketProvider(endpoint),
85 CONTRACT_ADDRESSES.DEV
86 );
87 return;
88 }
89 case NETWORK_TYPES.ROPSTEN: {
90 const endpoint = `https://ropsten.infura.io/v3/${process.env.REACT_APP_INFURA_ENDPOINT}`;
92 initWeb3(
93 new Web3.providers.HttpProvider(endpoint),
94 CONTRACT_ADDRESSES.ROPSTEN
95 );
96 return;
97 }
98 case NETWORK_TYPES.MAINNET: {
99 const endpoint = `https://mainnet.infura.io/v3/${process.env.REACT_APP_INFURA_ENDPOINT}`;
101 initWeb3(
102 new Web3.providers.HttpProvider(endpoint),
103 CONTRACT_ADDRESSES.MAINNET
104 );
105 return;
106 }
107 case NETWORK_TYPES.OFFLINE:
108 default: {
109 // NB (jtobin):
110 //
111 // The 'offline' network type targets the mainnet contracts, but does
112 // not actually use a provider to connect. We use a web3 instance to
113 // initalise the contracts, but the network itself is set to Nothing.
114 //
115 // We may want to offer the ability to select a target network for
116 // transactions when offline.
118 // Note: example.com:3456 doesn't actually point to anything, we just
119 // need a provider to initialize the Web3 object
120 initWeb3(
121 new Web3.providers.HttpProvider('http://example.com:3456'),
122 isDevelopment ? CONTRACT_ADDRESSES.DEV : CONTRACT_ADDRESSES.MAINNET
123 );
124 setWeb3(Nothing());
125 // ^ overwrite the web3 object from initWeb3 with a Nothing
126 // to indicate that there is no valid web3 connection
127 return;
128 }
129 }
130 })();
131 }, [networkType, metamask]);
133 return { networkType, setNetworkType, web3, contracts };
136const NetworkContext = createContext(null);
138// provider
139export function NetworkProvider({ initialNetworkType, children }) {
140 const value = _useNetwork(initialNetworkType);
142 if (Just.hasInstance(value.contracts)) {
143 return (
144 <NetworkContext.Provider value={value}>
145 {children}
146 </NetworkContext.Provider>
147 );
148 } else {
149 return (
150 <View inset>
151 <Grid>
152 <Grid.Item full className="mt8 t-center">
153 <Blinky /> Connecting...
154 </Grid.Item>
155 </Grid>
156 </View>
157 );
158 }
161// hook consumer
162export function useNetwork() {
163 return useContext(NetworkContext);
166// hoc consumer
167export const withNetwork = Component =>
168 forwardRef((props, ref) => {
169 return (
170 <NetworkContext.Consumer>
171 {value => <Component ref={ref} {...value} {...props} />}
172 </NetworkContext.Consumer>
173 );
174 });