This repository has been archived by the owner on Feb 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 147
/
example.js
222 lines (175 loc) · 6.35 KB
/
example.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
"use strict";
/**
* Example JavaScript code that interacts with the page and Web3 wallets
*/
// Unpkg imports
const Web3Modal = window.Web3Modal.default;
const WalletConnectProvider = window.WalletConnectProvider.default;
const Fortmatic = window.Fortmatic;
const evmChains = window.evmChains;
// Web3modal instance
let web3Modal
// Chosen wallet provider given by the dialog window
let provider;
// Address of the selected account
let selectedAccount;
/**
* Setup the orchestra
*/
function init() {
console.log("Initializing example");
console.log("WalletConnectProvider is", WalletConnectProvider);
console.log("Fortmatic is", Fortmatic);
console.log("window.web3 is", window.web3, "window.ethereum is", window.ethereum);
// Check that the web page is run in a secure context,
// as otherwise MetaMask won't be available
if(location.protocol !== 'https:') {
// https://ethereum.stackexchange.com/a/62217/620
const alert = document.querySelector("#alert-error-https");
alert.style.display = "block";
document.querySelector("#btn-connect").setAttribute("disabled", "disabled")
return;
}
// Tell Web3modal what providers we have available.
// Built-in web browser provider (only one can exist as a time)
// like MetaMask, Brave or Opera is added automatically by Web3modal
const providerOptions = {
walletconnect: {
package: WalletConnectProvider,
options: {
// Mikko's test key - don't copy as your mileage may vary
infuraId: "8043bb2cf99347b1bfadfb233c5325c0",
}
},
fortmatic: {
package: Fortmatic,
options: {
// Mikko's TESTNET api key
key: "pk_test_391E26A3B43A3350"
}
}
};
web3Modal = new Web3Modal({
cacheProvider: false, // optional
providerOptions, // required
disableInjectedProvider: false, // optional. For MetaMask / Brave / Opera.
});
console.log("Web3Modal instance is", web3Modal);
}
/**
* Kick in the UI action after Web3modal dialog has chosen a provider
*/
async function fetchAccountData() {
// Get a Web3 instance for the wallet
const web3 = new Web3(provider);
console.log("Web3 instance is", web3);
// Get connected chain id from Ethereum node
const chainId = await web3.eth.getChainId();
// Load chain information over an HTTP API
const chainData = evmChains.getChain(chainId);
document.querySelector("#network-name").textContent = chainData.name;
// Get list of accounts of the connected wallet
const accounts = await web3.eth.getAccounts();
// MetaMask does not give you all accounts, only the selected account
console.log("Got accounts", accounts);
selectedAccount = accounts[0];
document.querySelector("#selected-account").textContent = selectedAccount;
// Get a handl
const template = document.querySelector("#template-balance");
const accountContainer = document.querySelector("#accounts");
// Purge UI elements any previously loaded accounts
accountContainer.innerHTML = '';
// Go through all accounts and get their ETH balance
const rowResolvers = accounts.map(async (address) => {
const balance = await web3.eth.getBalance(address);
// ethBalance is a BigNumber instance
// https://github.com/indutny/bn.js/
const ethBalance = web3.utils.fromWei(balance, "ether");
const humanFriendlyBalance = parseFloat(ethBalance).toFixed(4);
// Fill in the templated row and put in the document
const clone = template.content.cloneNode(true);
clone.querySelector(".address").textContent = address;
clone.querySelector(".balance").textContent = humanFriendlyBalance;
accountContainer.appendChild(clone);
});
// Because rendering account does its own RPC commucation
// with Ethereum node, we do not want to display any results
// until data for all accounts is loaded
await Promise.all(rowResolvers);
// Display fully loaded UI for wallet data
document.querySelector("#prepare").style.display = "none";
document.querySelector("#connected").style.display = "block";
}
/**
* Fetch account data for UI when
* - User switches accounts in wallet
* - User switches networks in wallet
* - User connects wallet initially
*/
async function refreshAccountData() {
// If any current data is displayed when
// the user is switching acounts in the wallet
// immediate hide this data
document.querySelector("#connected").style.display = "none";
document.querySelector("#prepare").style.display = "block";
// Disable button while UI is loading.
// fetchAccountData() will take a while as it communicates
// with Ethereum node via JSON-RPC and loads chain data
// over an API call.
document.querySelector("#btn-connect").setAttribute("disabled", "disabled")
await fetchAccountData(provider);
document.querySelector("#btn-connect").removeAttribute("disabled")
}
/**
* Connect wallet button pressed.
*/
async function onConnect() {
console.log("Opening a dialog", web3Modal);
try {
provider = await web3Modal.connect();
} catch(e) {
console.log("Could not get a wallet connection", e);
return;
}
// Subscribe to accounts change
provider.on("accountsChanged", (accounts) => {
fetchAccountData();
});
// Subscribe to chainId change
provider.on("chainChanged", (chainId) => {
fetchAccountData();
});
// Subscribe to networkId change
provider.on("networkChanged", (networkId) => {
fetchAccountData();
});
await refreshAccountData();
}
/**
* Disconnect wallet button pressed.
*/
async function onDisconnect() {
console.log("Killing the wallet connection", provider);
// TODO: Which providers have close method?
if(provider.close) {
await provider.close();
// If the cached provider is not cleared,
// WalletConnect will default to the existing session
// and does not allow to re-scan the QR code with a new wallet.
// Depending on your use case you may want or want not his behavir.
await web3Modal.clearCachedProvider();
provider = null;
}
selectedAccount = null;
// Set the UI back to the initial state
document.querySelector("#prepare").style.display = "block";
document.querySelector("#connected").style.display = "none";
}
/**
* Main entry point.
*/
window.addEventListener('load', async () => {
init();
document.querySelector("#btn-connect").addEventListener("click", onConnect);
document.querySelector("#btn-disconnect").addEventListener("click", onDisconnect);
});