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