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