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