on bfbafde help sign in
bridge/src/store/network.js
131 lines 4.0 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';
19function _useNetwork(initialNetworkType = null) {
20 const [networkType, setNetworkType] = useState(initialNetworkType);
22 const [metamask, setMetamask] = useState(false);
24 useEffect(() => {
25 (async () => {
26 if (window.ethereum) {
27 try {
28 await window.ethereum.enable();
29 setMetamask(true);
30 setNetworkType(chainIdToNetworkType(window.ethereum.chainId));
31 } catch (e) {
32 console.log('Metamask denied');
33 }
34 }
35 })();
36 }, []);
38 const { web3, contracts } = useMemo(() => {
39 // given a web3 provider and contract addresses,
40 // build the web3 and contracts objects
41 const initWeb3 = (provider, contractAddresses) => {
42 // use an in-window eth provider if possible
43 const _provider = metamask ? window.ethereum : provider;
44 const web3 = new Web3(_provider);
45 const contracts = azimuth.initContracts(web3, contractAddresses);
47 return {
48 web3: Just(web3),
49 contracts: Just(contracts),
50 };
51 };
53 switch (networkType) {
54 case NETWORK_TYPES.LOCAL: {
55 const protocol = isDevelopment ? 'ws' : 'wss';
56 const endpoint = `${protocol}://${document.location.hostname}:8545`;
58 return initWeb3(
59 new Web3.providers.WebsocketProvider(endpoint),
60 CONTRACT_ADDRESSES.DEV
61 );
62 }
63 case NETWORK_TYPES.ROPSTEN: {
64 const endpoint = `https://ropsten.infura.io/v3/${process.env.REACT_APP_INFURA_ENDPOINT}`;
66 return initWeb3(
67 new Web3.providers.HttpProvider(endpoint),
68 CONTRACT_ADDRESSES.ROPSTEN
69 );
70 }
71 case NETWORK_TYPES.MAINNET: {
72 const endpoint = `https://mainnet.infura.io/v3/${process.env.REACT_APP_INFURA_ENDPOINT}`;
74 return initWeb3(
75 new Web3.providers.HttpProvider(endpoint),
76 CONTRACT_ADDRESSES.MAINNET
77 );
78 }
79 case NETWORK_TYPES.OFFLINE:
80 default: {
81 // NB (jtobin):
82 //
83 // The 'offline' network type targets the mainnet contracts, but does not
84 // actually use a provider to connect. We use a web3 instance to
85 // initalise the contracts, but the network itself is set to Nothing.
86 //
87 // We may want to offer the ability to select a target network for
88 // transactions when offline.
90 // Note: example.com:3456 doesn't actually point to anything, we just need
91 // a provider to initialize the Web3 object
92 return {
93 ...initWeb3(
94 new Web3.providers.HttpProvider('http://example.com:3456'),
95 isDevelopment ? CONTRACT_ADDRESSES.DEV : CONTRACT_ADDRESSES.MAINNET
96 ),
97 web3: Nothing(),
98 // ^ overwrite the web3 object from initWeb3 with a Nothing
99 // to indicate that there is no valid web3 connection
100 };
101 }
102 }
103 }, [networkType, metamask]);
105 return { networkType, setNetworkType, web3, contracts };
108const NetworkContext = createContext(null);
110// provider
111export function NetworkProvider({ initialNetworkType, children }) {
112 const value = _useNetwork(initialNetworkType);
113 return (
114 <NetworkContext.Provider value={value}>{children}</NetworkContext.Provider>
115 );
118// hook consumer
119export function useNetwork() {
120 return useContext(NetworkContext);
123// hoc consumer
124export const withNetwork = Component =>
125 forwardRef((props, ref) => {
126 return (
127 <NetworkContext.Consumer>
128 {value => <Component ref={ref} {...value} {...props} />}
129 </NetworkContext.Consumer>
130 );
131 });