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