quantumcoin 6.14.1 → 6.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/quantumcoin.js +2697 -7812
- package/dist/quantumcoin.js.map +1 -1
- package/dist/quantumcoin.min.js +1 -1
- package/dist/quantumcoin.min.js'.gz' +0 -0
- package/dist/quantumcoin.umd.js +2698 -7835
- package/dist/quantumcoin.umd.js.map +1 -1
- package/dist/quantumcoin.umd.min.js +1 -1
- package/dist/quantumcoin.umd.min.js'.gz' +0 -0
- package/dist/wordlists-extra.min.js'.gz' +0 -0
- package/lib.commonjs/address/address.d.ts +1 -21
- package/lib.commonjs/address/address.d.ts.map +1 -1
- package/lib.commonjs/address/address.js +2 -30
- package/lib.commonjs/address/address.js.map +1 -1
- package/lib.commonjs/address/index.d.ts +1 -1
- package/lib.commonjs/address/index.d.ts.map +1 -1
- package/lib.commonjs/address/index.js +1 -2
- package/lib.commonjs/address/index.js.map +1 -1
- package/lib.commonjs/crypto/signature.d.ts +4 -17
- package/lib.commonjs/crypto/signature.d.ts.map +1 -1
- package/lib.commonjs/crypto/signature.js +57 -60
- package/lib.commonjs/crypto/signature.js.map +1 -1
- package/lib.commonjs/crypto/signing-key.d.ts +5 -64
- package/lib.commonjs/crypto/signing-key.d.ts.map +1 -1
- package/lib.commonjs/crypto/signing-key.js +27 -101
- package/lib.commonjs/crypto/signing-key.js.map +1 -1
- package/lib.commonjs/providers/default-provider.d.ts +0 -8
- package/lib.commonjs/providers/default-provider.d.ts.map +1 -1
- package/lib.commonjs/providers/default-provider.js +0 -108
- package/lib.commonjs/providers/default-provider.js.map +1 -1
- package/lib.commonjs/providers/index.d.ts +0 -9
- package/lib.commonjs/providers/index.d.ts.map +1 -1
- package/lib.commonjs/providers/index.js +1 -21
- package/lib.commonjs/providers/index.js.map +1 -1
- package/lib.commonjs/providers/network.js +1 -99
- package/lib.commonjs/providers/network.js.map +1 -1
- package/lib.commonjs/quantumcoin.d.ts +4 -4
- package/lib.commonjs/quantumcoin.d.ts.map +1 -1
- package/lib.commonjs/quantumcoin.js +4 -26
- package/lib.commonjs/quantumcoin.js.map +1 -1
- package/lib.commonjs/transaction/address.d.ts +1 -1
- package/lib.commonjs/transaction/address.d.ts.map +1 -1
- package/lib.commonjs/transaction/address.js +9 -5
- package/lib.commonjs/transaction/address.js.map +1 -1
- package/lib.commonjs/wallet/hdwallet.d.ts.map +1 -1
- package/lib.commonjs/wallet/hdwallet.js +4 -5
- package/lib.commonjs/wallet/hdwallet.js.map +1 -1
- package/lib.commonjs/wallet/index.d.ts +2 -6
- package/lib.commonjs/wallet/index.d.ts.map +1 -1
- package/lib.commonjs/wallet/index.js +1 -14
- package/lib.commonjs/wallet/index.js.map +1 -1
- package/lib.commonjs/wallet/json-keystore.d.ts +3 -52
- package/lib.commonjs/wallet/json-keystore.d.ts.map +1 -1
- package/lib.commonjs/wallet/json-keystore.js +41 -246
- package/lib.commonjs/wallet/json-keystore.js.map +1 -1
- package/lib.commonjs/wallet/seedwallet.d.ts +4 -0
- package/lib.commonjs/wallet/seedwallet.d.ts.map +1 -0
- package/lib.commonjs/wallet/seedwallet.js +8 -0
- package/lib.commonjs/wallet/seedwallet.js.map +1 -0
- package/lib.commonjs/wallet/wallet.d.ts +5 -14
- package/lib.commonjs/wallet/wallet.d.ts.map +1 -1
- package/lib.commonjs/wallet/wallet.js +12 -51
- package/lib.commonjs/wallet/wallet.js.map +1 -1
- package/lib.esm/address/address.d.ts +1 -21
- package/lib.esm/address/address.d.ts.map +1 -1
- package/lib.esm/address/address.js +1 -28
- package/lib.esm/address/address.js.map +1 -1
- package/lib.esm/address/index.d.ts +1 -1
- package/lib.esm/address/index.d.ts.map +1 -1
- package/lib.esm/address/index.js +1 -1
- package/lib.esm/address/index.js.map +1 -1
- package/lib.esm/crypto/signature.d.ts +4 -17
- package/lib.esm/crypto/signature.d.ts.map +1 -1
- package/lib.esm/crypto/signature.js +45 -46
- package/lib.esm/crypto/signature.js.map +1 -1
- package/lib.esm/crypto/signing-key.d.ts +5 -64
- package/lib.esm/crypto/signing-key.d.ts.map +1 -1
- package/lib.esm/crypto/signing-key.js +26 -102
- package/lib.esm/crypto/signing-key.js.map +1 -1
- package/lib.esm/providers/default-provider.d.ts +0 -8
- package/lib.esm/providers/default-provider.d.ts.map +1 -1
- package/lib.esm/providers/default-provider.js +0 -108
- package/lib.esm/providers/default-provider.js.map +1 -1
- package/lib.esm/providers/index.d.ts +0 -9
- package/lib.esm/providers/index.d.ts.map +1 -1
- package/lib.esm/providers/index.js +0 -9
- package/lib.esm/providers/index.js.map +1 -1
- package/lib.esm/providers/network.js +3 -101
- package/lib.esm/providers/network.js.map +1 -1
- package/lib.esm/quantumcoin.d.ts +4 -4
- package/lib.esm/quantumcoin.d.ts.map +1 -1
- package/lib.esm/quantumcoin.js +3 -3
- package/lib.esm/quantumcoin.js.map +1 -1
- package/lib.esm/transaction/address.d.ts +1 -1
- package/lib.esm/transaction/address.d.ts.map +1 -1
- package/lib.esm/transaction/address.js +7 -4
- package/lib.esm/transaction/address.js.map +1 -1
- package/lib.esm/wallet/hdwallet.d.ts.map +1 -1
- package/lib.esm/wallet/hdwallet.js +4 -5
- package/lib.esm/wallet/hdwallet.js.map +1 -1
- package/lib.esm/wallet/index.d.ts +2 -6
- package/lib.esm/wallet/index.d.ts.map +1 -1
- package/lib.esm/wallet/index.js +1 -4
- package/lib.esm/wallet/index.js.map +1 -1
- package/lib.esm/wallet/json-keystore.d.ts +3 -52
- package/lib.esm/wallet/json-keystore.d.ts.map +1 -1
- package/lib.esm/wallet/json-keystore.js +32 -241
- package/lib.esm/wallet/json-keystore.js.map +1 -1
- package/lib.esm/wallet/seedwallet.d.ts +4 -0
- package/lib.esm/wallet/seedwallet.d.ts.map +1 -0
- package/lib.esm/wallet/seedwallet.js +4 -0
- package/lib.esm/wallet/seedwallet.js.map +1 -0
- package/lib.esm/wallet/wallet.d.ts +5 -14
- package/lib.esm/wallet/wallet.d.ts.map +1 -1
- package/lib.esm/wallet/wallet.js +12 -53
- package/lib.esm/wallet/wallet.js.map +1 -1
- package/package.json +5 -2
- package/src.ts/address/address.ts +2 -27
- package/src.ts/address/index.ts +1 -1
- package/src.ts/crypto/signature.ts +31 -45
- package/src.ts/crypto/signing-key.ts +31 -109
- package/src.ts/providers/default-provider.ts +0 -106
- package/src.ts/providers/index.ts +0 -10
- package/src.ts/providers/network.ts +3 -111
- package/src.ts/quantumcoin.ts +7 -17
- package/src.ts/transaction/address.ts +8 -5
- package/src.ts/wallet/index.ts +2 -17
- package/src.ts/wallet/json-keystore.ts +42 -325
- package/src.ts/wallet/wallet.ts +23 -47
- package/src.ts/providers/provider-alchemy.ts +0 -166
- package/src.ts/providers/provider-ankr.ts +0 -153
- package/src.ts/providers/provider-blockscout.ts +0 -167
- package/src.ts/providers/provider-chainstack.ts +0 -113
- package/src.ts/providers/provider-cloudflare.ts +0 -24
- package/src.ts/providers/provider-etherscan.ts +0 -671
- package/src.ts/providers/provider-infura.ts +0 -220
- package/src.ts/providers/provider-pocket.ts +0 -121
- package/src.ts/providers/provider-quicknode.ts +0 -177
- package/src.ts/wallet/hdwallet.ts +0 -586
- package/src.ts/wallet/json-crowdsale.ts +0 -74
- package/src.ts/wallet/mnemonic.ts +0 -203
|
@@ -1,671 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* [[link-etherscan]] provides a third-party service for connecting to
|
|
3
|
-
* various blockchains over a combination of JSON-RPC and custom API
|
|
4
|
-
* endpoints.
|
|
5
|
-
*
|
|
6
|
-
* **Supported Networks**
|
|
7
|
-
*
|
|
8
|
-
* - Ethereum Mainnet (``mainnet``)
|
|
9
|
-
* - Goerli Testnet (``goerli``)
|
|
10
|
-
* - Sepolia Testnet (``sepolia``)
|
|
11
|
-
* - Holesky Testnet (``holesky``)
|
|
12
|
-
* - Arbitrum (``arbitrum``)
|
|
13
|
-
* - Arbitrum Goerli Testnet (``arbitrum-goerli``)
|
|
14
|
-
* - Base (``base``)
|
|
15
|
-
* - Base Sepolia Testnet (``base-sepolia``)
|
|
16
|
-
* - BNB Smart Chain Mainnet (``bnb``)
|
|
17
|
-
* - BNB Smart Chain Testnet (``bnbt``)
|
|
18
|
-
* - Optimism (``optimism``)
|
|
19
|
-
* - Optimism Goerli Testnet (``optimism-goerli``)
|
|
20
|
-
* - Polygon (``matic``)
|
|
21
|
-
* - Polygon Mumbai Testnet (``matic-mumbai``)
|
|
22
|
-
* - Polygon Amoy Testnet (``matic-amoy``)
|
|
23
|
-
*
|
|
24
|
-
* @_subsection api/providers/thirdparty:Etherscan [providers-etherscan]
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
import { AbiCoder } from "../abi/index.js";
|
|
28
|
-
import { Contract } from "../contract/index.js";
|
|
29
|
-
import { accessListify, Transaction } from "../transaction/index.js";
|
|
30
|
-
import {
|
|
31
|
-
defineProperties,
|
|
32
|
-
hexlify, toQuantity,
|
|
33
|
-
FetchRequest,
|
|
34
|
-
assert, assertArgument, isError,
|
|
35
|
-
// parseUnits,
|
|
36
|
-
toUtf8String
|
|
37
|
-
} from "../utils/index.js";
|
|
38
|
-
|
|
39
|
-
import { AbstractProvider } from "./abstract-provider.js";
|
|
40
|
-
import { Network } from "./network.js";
|
|
41
|
-
import { NetworkPlugin } from "./plugins-network.js";
|
|
42
|
-
import { showThrottleMessage } from "./community.js";
|
|
43
|
-
|
|
44
|
-
import { PerformActionRequest } from "./abstract-provider.js";
|
|
45
|
-
import type { Networkish } from "./network.js";
|
|
46
|
-
//import type { } from "./pagination";
|
|
47
|
-
import type { TransactionRequest } from "./provider.js";
|
|
48
|
-
|
|
49
|
-
const THROTTLE = 2000;
|
|
50
|
-
|
|
51
|
-
function isPromise<T = any>(value: any): value is Promise<T> {
|
|
52
|
-
return (value && typeof(value.then) === "function");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* When subscribing to the ``"debug"`` event on an Etherscan-based
|
|
58
|
-
* provider, the events receive a **DebugEventEtherscanProvider**
|
|
59
|
-
* payload.
|
|
60
|
-
*
|
|
61
|
-
* @_docloc: api/providers/thirdparty:Etherscan
|
|
62
|
-
*/
|
|
63
|
-
export type DebugEventEtherscanProvider = {
|
|
64
|
-
action: "sendRequest",
|
|
65
|
-
id: number,
|
|
66
|
-
url: string,
|
|
67
|
-
payload: Record<string, any>
|
|
68
|
-
} | {
|
|
69
|
-
action: "receiveRequest",
|
|
70
|
-
id: number,
|
|
71
|
-
result: any
|
|
72
|
-
} | {
|
|
73
|
-
action: "receiveError",
|
|
74
|
-
id: number,
|
|
75
|
-
error: any
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const EtherscanPluginId = "org.ethers.plugins.provider.Etherscan";
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* A Network can include an **EtherscanPlugin** to provide
|
|
82
|
-
* a custom base URL.
|
|
83
|
-
*
|
|
84
|
-
* @_docloc: api/providers/thirdparty:Etherscan
|
|
85
|
-
*/
|
|
86
|
-
export class EtherscanPlugin extends NetworkPlugin {
|
|
87
|
-
/**
|
|
88
|
-
* The Etherscan API base URL.
|
|
89
|
-
*/
|
|
90
|
-
readonly baseUrl!: string;
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Creates a new **EtherscanProvider** which will use
|
|
94
|
-
* %%baseUrl%%.
|
|
95
|
-
*/
|
|
96
|
-
constructor(baseUrl: string) {
|
|
97
|
-
super(EtherscanPluginId);
|
|
98
|
-
defineProperties<EtherscanPlugin>(this, { baseUrl });
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
clone(): EtherscanPlugin {
|
|
102
|
-
return new EtherscanPlugin(this.baseUrl);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const skipKeys = [ "enableCcipRead" ];
|
|
107
|
-
|
|
108
|
-
let nextId = 1;
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* The **EtherscanBaseProvider** is the super-class of
|
|
112
|
-
* [[EtherscanProvider]], which should generally be used instead.
|
|
113
|
-
*
|
|
114
|
-
* Since the **EtherscanProvider** includes additional code for
|
|
115
|
-
* [[Contract]] access, in //rare cases// that contracts are not
|
|
116
|
-
* used, this class can reduce code size.
|
|
117
|
-
*
|
|
118
|
-
* @_docloc: api/providers/thirdparty:Etherscan
|
|
119
|
-
*/
|
|
120
|
-
export class EtherscanProvider extends AbstractProvider {
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* The connected network.
|
|
124
|
-
*/
|
|
125
|
-
readonly network!: Network;
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* The API key or null if using the community provided bandwidth.
|
|
129
|
-
*/
|
|
130
|
-
readonly apiKey!: null | string;
|
|
131
|
-
|
|
132
|
-
readonly #plugin: null | EtherscanPlugin;
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Creates a new **EtherscanBaseProvider**.
|
|
136
|
-
*/
|
|
137
|
-
constructor(_network?: Networkish, _apiKey?: string) {
|
|
138
|
-
const apiKey = (_apiKey != null) ? _apiKey: null;
|
|
139
|
-
|
|
140
|
-
super();
|
|
141
|
-
|
|
142
|
-
const network = Network.from(_network);
|
|
143
|
-
|
|
144
|
-
this.#plugin = network.getPlugin<EtherscanPlugin>(EtherscanPluginId);
|
|
145
|
-
|
|
146
|
-
defineProperties<EtherscanProvider>(this, { apiKey, network });
|
|
147
|
-
|
|
148
|
-
// Test that the network is supported by Etherscan
|
|
149
|
-
this.getBaseUrl();
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Returns the base URL.
|
|
154
|
-
*
|
|
155
|
-
* If an [[EtherscanPlugin]] is configured on the
|
|
156
|
-
* [[EtherscanBaseProvider_network]], returns the plugin's
|
|
157
|
-
* baseUrl.
|
|
158
|
-
*/
|
|
159
|
-
getBaseUrl(): string {
|
|
160
|
-
if (this.#plugin) { return this.#plugin.baseUrl; }
|
|
161
|
-
|
|
162
|
-
switch(this.network.name) {
|
|
163
|
-
case "mainnet":
|
|
164
|
-
return "https:/\/api.etherscan.io";
|
|
165
|
-
case "goerli":
|
|
166
|
-
return "https:/\/api-goerli.etherscan.io";
|
|
167
|
-
case "sepolia":
|
|
168
|
-
return "https:/\/api-sepolia.etherscan.io";
|
|
169
|
-
case "holesky":
|
|
170
|
-
return "https:/\/api-holesky.etherscan.io";
|
|
171
|
-
|
|
172
|
-
case "arbitrum":
|
|
173
|
-
return "https:/\/api.arbiscan.io";
|
|
174
|
-
case "arbitrum-goerli":
|
|
175
|
-
return "https:/\/api-goerli.arbiscan.io";
|
|
176
|
-
case "base":
|
|
177
|
-
return "https:/\/api.basescan.org";
|
|
178
|
-
case "base-sepolia":
|
|
179
|
-
return "https:/\/api-sepolia.basescan.org";
|
|
180
|
-
case "bnb":
|
|
181
|
-
return "https:/\/api.bscscan.com";
|
|
182
|
-
case "bnbt":
|
|
183
|
-
return "https:/\/api-testnet.bscscan.com";
|
|
184
|
-
case "matic":
|
|
185
|
-
return "https:/\/api.polygonscan.com";
|
|
186
|
-
case "matic-amoy":
|
|
187
|
-
return "https:/\/api-amoy.polygonscan.com";
|
|
188
|
-
case "matic-mumbai":
|
|
189
|
-
return "https:/\/api-testnet.polygonscan.com";
|
|
190
|
-
case "optimism":
|
|
191
|
-
return "https:/\/api-optimistic.etherscan.io";
|
|
192
|
-
case "optimism-goerli":
|
|
193
|
-
return "https:/\/api-goerli-optimistic.etherscan.io";
|
|
194
|
-
|
|
195
|
-
default:
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
assertArgument(false, "unsupported network", "network", this.network);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Returns the URL for the %%module%% and %%params%%.
|
|
203
|
-
*/
|
|
204
|
-
getUrl(module: string, params: Record<string, string>): string {
|
|
205
|
-
const query = Object.keys(params).reduce((accum, key) => {
|
|
206
|
-
const value = params[key];
|
|
207
|
-
if (value != null) {
|
|
208
|
-
accum += `&${ key }=${ value }`
|
|
209
|
-
}
|
|
210
|
-
return accum
|
|
211
|
-
}, "");
|
|
212
|
-
const apiKey = ((this.apiKey) ? `&apikey=${ this.apiKey }`: "");
|
|
213
|
-
return `${ this.getBaseUrl() }/api?module=${ module }${ query }${ apiKey }`;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Returns the URL for using POST requests.
|
|
218
|
-
*/
|
|
219
|
-
getPostUrl(): string {
|
|
220
|
-
return `${ this.getBaseUrl() }/api`;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Returns the parameters for using POST requests.
|
|
225
|
-
*/
|
|
226
|
-
getPostData(module: string, params: Record<string, any>): Record<string, any> {
|
|
227
|
-
params.module = module;
|
|
228
|
-
params.apikey = this.apiKey;
|
|
229
|
-
return params;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
async detectNetwork(): Promise<Network> {
|
|
233
|
-
return this.network;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Resolves to the result of calling %%module%% with %%params%%.
|
|
238
|
-
*
|
|
239
|
-
* If %%post%%, the request is made as a POST request.
|
|
240
|
-
*/
|
|
241
|
-
async fetch(module: string, params: Record<string, any>, post?: boolean): Promise<any> {
|
|
242
|
-
const id = nextId++;
|
|
243
|
-
|
|
244
|
-
const url = (post ? this.getPostUrl(): this.getUrl(module, params));
|
|
245
|
-
const payload = (post ? this.getPostData(module, params): null);
|
|
246
|
-
|
|
247
|
-
this.emit("debug", { action: "sendRequest", id, url, payload: payload });
|
|
248
|
-
|
|
249
|
-
const request = new FetchRequest(url);
|
|
250
|
-
request.setThrottleParams({ slotInterval: 1000 });
|
|
251
|
-
request.retryFunc = (req, resp, attempt: number) => {
|
|
252
|
-
if (this.isCommunityResource()) {
|
|
253
|
-
showThrottleMessage("Etherscan");
|
|
254
|
-
}
|
|
255
|
-
return Promise.resolve(true);
|
|
256
|
-
};
|
|
257
|
-
request.processFunc = async (request, response) => {
|
|
258
|
-
const result = response.hasBody() ? JSON.parse(toUtf8String(response.body)): { };
|
|
259
|
-
const throttle = ((typeof(result.result) === "string") ? result.result: "").toLowerCase().indexOf("rate limit") >= 0;
|
|
260
|
-
if (module === "proxy") {
|
|
261
|
-
// This JSON response indicates we are being throttled
|
|
262
|
-
if (result && result.status == 0 && result.message == "NOTOK" && throttle) {
|
|
263
|
-
this.emit("debug", { action: "receiveError", id, reason: "proxy-NOTOK", error: result });
|
|
264
|
-
response.throwThrottleError(result.result, THROTTLE);
|
|
265
|
-
}
|
|
266
|
-
} else {
|
|
267
|
-
if (throttle) {
|
|
268
|
-
this.emit("debug", { action: "receiveError", id, reason: "null result", error: result.result });
|
|
269
|
-
response.throwThrottleError(result.result, THROTTLE);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return response;
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
if (payload) {
|
|
276
|
-
request.setHeader("content-type", "application/x-www-form-urlencoded; charset=UTF-8");
|
|
277
|
-
request.body = Object.keys(payload).map((k) => `${ k }=${ payload[k] }`).join("&");
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const response = await request.send();
|
|
281
|
-
try {
|
|
282
|
-
response.assertOk();
|
|
283
|
-
} catch (error) {
|
|
284
|
-
this.emit("debug", { action: "receiveError", id, error, reason: "assertOk" });
|
|
285
|
-
assert(false, "response error", "SERVER_ERROR", { request, response });
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (!response.hasBody()) {
|
|
289
|
-
this.emit("debug", { action: "receiveError", id, error: "missing body", reason: "null body" });
|
|
290
|
-
assert(false, "missing response", "SERVER_ERROR", { request, response });
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const result = JSON.parse(toUtf8String(response.body));
|
|
294
|
-
if (module === "proxy") {
|
|
295
|
-
if (result.jsonrpc != "2.0") {
|
|
296
|
-
this.emit("debug", { action: "receiveError", id, result, reason: "invalid JSON-RPC" });
|
|
297
|
-
assert(false, "invalid JSON-RPC response (missing jsonrpc='2.0')", "SERVER_ERROR", { request, response, info: { result } });
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (result.error) {
|
|
301
|
-
this.emit("debug", { action: "receiveError", id, result, reason: "JSON-RPC error" });
|
|
302
|
-
assert(false, "error response", "SERVER_ERROR", { request, response, info: { result } });
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
this.emit("debug", { action: "receiveRequest", id, result });
|
|
306
|
-
|
|
307
|
-
return result.result;
|
|
308
|
-
|
|
309
|
-
} else {
|
|
310
|
-
// getLogs, getHistory have weird success responses
|
|
311
|
-
if (result.status == 0 && (result.message === "No records found" || result.message === "No transactions found")) {
|
|
312
|
-
this.emit("debug", { action: "receiveRequest", id, result });
|
|
313
|
-
return result.result;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (result.status != 1 || (typeof(result.message) === "string" && !result.message.match(/^OK/))) {
|
|
317
|
-
this.emit("debug", { action: "receiveError", id, result });
|
|
318
|
-
assert(false, "error response", "SERVER_ERROR", { request, response, info: { result } });
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
this.emit("debug", { action: "receiveRequest", id, result });
|
|
322
|
-
|
|
323
|
-
return result.result;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Returns %%transaction%% normalized for the Etherscan API.
|
|
329
|
-
*/
|
|
330
|
-
_getTransactionPostData(transaction: TransactionRequest): Record<string, string> {
|
|
331
|
-
const result: Record<string, string> = { };
|
|
332
|
-
for (let key in transaction) {
|
|
333
|
-
if (skipKeys.indexOf(key) >= 0) { continue; }
|
|
334
|
-
|
|
335
|
-
if ((<any>transaction)[key] == null) { continue; }
|
|
336
|
-
let value = (<any>transaction)[key];
|
|
337
|
-
if (key === "type" && value === 0) { continue; }
|
|
338
|
-
if (key === "blockTag" && value === "latest") { continue; }
|
|
339
|
-
|
|
340
|
-
// Quantity-types require no leading zero, unless 0
|
|
341
|
-
if ((<any>{ type: true, gasLimit: true, gasPrice: true, maxFeePerGs: true, maxPriorityFeePerGas: true, nonce: true, value: true })[key]) {
|
|
342
|
-
value = toQuantity(value);
|
|
343
|
-
|
|
344
|
-
} else if (key === "accessList") {
|
|
345
|
-
value = "[" + accessListify(value).map((set) => {
|
|
346
|
-
return `{address:"${ set.address }",storageKeys:["${ set.storageKeys.join('","') }"]}`;
|
|
347
|
-
}).join(",") + "]";
|
|
348
|
-
|
|
349
|
-
} else if (key === "blobVersionedHashes") {
|
|
350
|
-
if (value.length === 0) { continue; }
|
|
351
|
-
|
|
352
|
-
// @TODO: update this once the API supports blobs
|
|
353
|
-
assert(false, "Etherscan API does not support blobVersionedHashes", "UNSUPPORTED_OPERATION", {
|
|
354
|
-
operation: "_getTransactionPostData",
|
|
355
|
-
info: { transaction }
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
} else {
|
|
359
|
-
value = hexlify(value);
|
|
360
|
-
}
|
|
361
|
-
result[key] = value;
|
|
362
|
-
}
|
|
363
|
-
return result;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* Throws the normalized Etherscan error.
|
|
368
|
-
*/
|
|
369
|
-
_checkError(req: PerformActionRequest, error: Error, transaction: any): never {
|
|
370
|
-
|
|
371
|
-
// Pull any message out if, possible
|
|
372
|
-
let message = "";
|
|
373
|
-
if (isError(error, "SERVER_ERROR")) {
|
|
374
|
-
// Check for an error emitted by a proxy call
|
|
375
|
-
try {
|
|
376
|
-
message = (<any>error).info.result.error.message;
|
|
377
|
-
} catch (e) { }
|
|
378
|
-
|
|
379
|
-
if (!message) {
|
|
380
|
-
try {
|
|
381
|
-
message = (<any>error).info.message;
|
|
382
|
-
} catch (e) { }
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
if (req.method === "estimateGas") {
|
|
387
|
-
if (!message.match(/revert/i) && message.match(/insufficient funds/i)) {
|
|
388
|
-
assert(false, "insufficient funds", "INSUFFICIENT_FUNDS", {
|
|
389
|
-
transaction: req.transaction
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
if (req.method === "call" || req.method === "estimateGas") {
|
|
395
|
-
if (message.match(/execution reverted/i)) {
|
|
396
|
-
let data = "";
|
|
397
|
-
try {
|
|
398
|
-
data = (<any>error).info.result.error.data;
|
|
399
|
-
} catch (error) { }
|
|
400
|
-
|
|
401
|
-
const e = AbiCoder.getBuiltinCallException(req.method, <any>req.transaction, data);
|
|
402
|
-
e.info = { request: req, error }
|
|
403
|
-
throw e;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
if (message) {
|
|
408
|
-
if (req.method === "broadcastTransaction") {
|
|
409
|
-
const transaction = Transaction.from(req.signedTransaction);
|
|
410
|
-
if (message.match(/replacement/i) && message.match(/underpriced/i)) {
|
|
411
|
-
assert(false, "replacement fee too low", "REPLACEMENT_UNDERPRICED", {
|
|
412
|
-
transaction
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (message.match(/insufficient funds/)) {
|
|
417
|
-
assert(false, "insufficient funds for intrinsic transaction cost", "INSUFFICIENT_FUNDS", {
|
|
418
|
-
transaction
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
if (message.match(/same hash was already imported|transaction nonce is too low|nonce too low/)) {
|
|
423
|
-
assert(false, "nonce has already been used", "NONCE_EXPIRED", {
|
|
424
|
-
transaction
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// Something we could not process
|
|
431
|
-
throw error;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
async _detectNetwork(): Promise<Network> {
|
|
435
|
-
return this.network;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
async _perform(req: PerformActionRequest): Promise<any> {
|
|
439
|
-
switch (req.method) {
|
|
440
|
-
case "chainId":
|
|
441
|
-
return this.network.chainId;
|
|
442
|
-
|
|
443
|
-
case "getBlockNumber":
|
|
444
|
-
return this.fetch("proxy", { action: "eth_blockNumber" });
|
|
445
|
-
|
|
446
|
-
case "getGasPrice":
|
|
447
|
-
return this.fetch("proxy", { action: "eth_gasPrice" });
|
|
448
|
-
|
|
449
|
-
case "getPriorityFee":
|
|
450
|
-
// This is temporary until Etherscan completes support
|
|
451
|
-
if (this.network.name === "mainnet") {
|
|
452
|
-
return "1000000000";
|
|
453
|
-
} else if (this.network.name === "optimism") {
|
|
454
|
-
return "1000000";
|
|
455
|
-
} else {
|
|
456
|
-
throw new Error("fallback onto the AbstractProvider default");
|
|
457
|
-
}
|
|
458
|
-
/* Working with Etherscan to get this added:
|
|
459
|
-
try {
|
|
460
|
-
const test = await this.fetch("proxy", {
|
|
461
|
-
action: "eth_maxPriorityFeePerGas"
|
|
462
|
-
});
|
|
463
|
-
console.log(test);
|
|
464
|
-
return test;
|
|
465
|
-
} catch (e) {
|
|
466
|
-
console.log("DEBUG", e);
|
|
467
|
-
throw e;
|
|
468
|
-
}
|
|
469
|
-
*/
|
|
470
|
-
/* This might be safe; but due to rounding neither myself
|
|
471
|
-
or Etherscan are necessarily comfortable with this. :)
|
|
472
|
-
try {
|
|
473
|
-
const result = await this.fetch("gastracker", { action: "gasoracle" });
|
|
474
|
-
console.log(result);
|
|
475
|
-
const gasPrice = parseUnits(result.SafeGasPrice, "gwei");
|
|
476
|
-
const baseFee = parseUnits(result.suggestBaseFee, "gwei");
|
|
477
|
-
const priorityFee = gasPrice - baseFee;
|
|
478
|
-
if (priorityFee < 0) { throw new Error("negative priority fee; defer to abstract provider default"); }
|
|
479
|
-
return priorityFee;
|
|
480
|
-
} catch (error) {
|
|
481
|
-
console.log("DEBUG", error);
|
|
482
|
-
throw error;
|
|
483
|
-
}
|
|
484
|
-
*/
|
|
485
|
-
|
|
486
|
-
case "getBalance":
|
|
487
|
-
// Returns base-10 result
|
|
488
|
-
return this.fetch("account", {
|
|
489
|
-
action: "balance",
|
|
490
|
-
address: req.address,
|
|
491
|
-
tag: req.blockTag
|
|
492
|
-
});
|
|
493
|
-
|
|
494
|
-
case "getTransactionCount":
|
|
495
|
-
return this.fetch("proxy", {
|
|
496
|
-
action: "eth_getTransactionCount",
|
|
497
|
-
address: req.address,
|
|
498
|
-
tag: req.blockTag
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
case "getCode":
|
|
502
|
-
return this.fetch("proxy", {
|
|
503
|
-
action: "eth_getCode",
|
|
504
|
-
address: req.address,
|
|
505
|
-
tag: req.blockTag
|
|
506
|
-
});
|
|
507
|
-
|
|
508
|
-
case "getStorage":
|
|
509
|
-
return this.fetch("proxy", {
|
|
510
|
-
action: "eth_getStorageAt",
|
|
511
|
-
address: req.address,
|
|
512
|
-
position: req.position,
|
|
513
|
-
tag: req.blockTag
|
|
514
|
-
});
|
|
515
|
-
|
|
516
|
-
case "broadcastTransaction":
|
|
517
|
-
return this.fetch("proxy", {
|
|
518
|
-
action: "eth_sendRawTransaction",
|
|
519
|
-
hex: req.signedTransaction
|
|
520
|
-
}, true).catch((error) => {
|
|
521
|
-
return this._checkError(req, <Error>error, req.signedTransaction);
|
|
522
|
-
});
|
|
523
|
-
|
|
524
|
-
case "getBlock":
|
|
525
|
-
if ("blockTag" in req) {
|
|
526
|
-
return this.fetch("proxy", {
|
|
527
|
-
action: "eth_getBlockByNumber",
|
|
528
|
-
tag: req.blockTag,
|
|
529
|
-
boolean: (req.includeTransactions ? "true": "false")
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
assert(false, "getBlock by blockHash not supported by Etherscan", "UNSUPPORTED_OPERATION", {
|
|
534
|
-
operation: "getBlock(blockHash)"
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
case "getTransaction":
|
|
538
|
-
return this.fetch("proxy", {
|
|
539
|
-
action: "eth_getTransactionByHash",
|
|
540
|
-
txhash: req.hash
|
|
541
|
-
});
|
|
542
|
-
|
|
543
|
-
case "getTransactionReceipt":
|
|
544
|
-
return this.fetch("proxy", {
|
|
545
|
-
action: "eth_getTransactionReceipt",
|
|
546
|
-
txhash: req.hash
|
|
547
|
-
});
|
|
548
|
-
|
|
549
|
-
case "call": {
|
|
550
|
-
if (req.blockTag !== "latest") {
|
|
551
|
-
throw new Error("EtherscanProvider does not support blockTag for call");
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
const postData = this._getTransactionPostData(req.transaction);
|
|
555
|
-
postData.module = "proxy";
|
|
556
|
-
postData.action = "eth_call";
|
|
557
|
-
|
|
558
|
-
try {
|
|
559
|
-
return await this.fetch("proxy", postData, true);
|
|
560
|
-
} catch (error) {
|
|
561
|
-
return this._checkError(req, <Error>error, req.transaction);
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
case "estimateGas": {
|
|
566
|
-
const postData = this._getTransactionPostData(req.transaction);
|
|
567
|
-
postData.module = "proxy";
|
|
568
|
-
postData.action = "eth_estimateGas";
|
|
569
|
-
|
|
570
|
-
try {
|
|
571
|
-
return await this.fetch("proxy", postData, true);
|
|
572
|
-
} catch (error) {
|
|
573
|
-
return this._checkError(req, <Error>error, req.transaction);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
/*
|
|
577
|
-
case "getLogs": {
|
|
578
|
-
// Needs to complain if more than one address is passed in
|
|
579
|
-
const args: Record<string, any> = { action: "getLogs" }
|
|
580
|
-
|
|
581
|
-
if (params.filter.fromBlock) {
|
|
582
|
-
args.fromBlock = checkLogTag(params.filter.fromBlock);
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
if (params.filter.toBlock) {
|
|
586
|
-
args.toBlock = checkLogTag(params.filter.toBlock);
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
if (params.filter.address) {
|
|
590
|
-
args.address = params.filter.address;
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
// @TODO: We can handle slightly more complicated logs using the logs API
|
|
594
|
-
if (params.filter.topics && params.filter.topics.length > 0) {
|
|
595
|
-
if (params.filter.topics.length > 1) {
|
|
596
|
-
logger.throwError("unsupported topic count", Logger.Errors.UNSUPPORTED_OPERATION, { topics: params.filter.topics });
|
|
597
|
-
}
|
|
598
|
-
if (params.filter.topics.length === 1) {
|
|
599
|
-
const topic0 = params.filter.topics[0];
|
|
600
|
-
if (typeof(topic0) !== "string" || topic0.length !== 66) {
|
|
601
|
-
logger.throwError("unsupported topic format", Logger.Errors.UNSUPPORTED_OPERATION, { topic0: topic0 });
|
|
602
|
-
}
|
|
603
|
-
args.topic0 = topic0;
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
const logs: Array<any> = await this.fetch("logs", args);
|
|
608
|
-
|
|
609
|
-
// Cache txHash => blockHash
|
|
610
|
-
let blocks: { [tag: string]: string } = {};
|
|
611
|
-
|
|
612
|
-
// Add any missing blockHash to the logs
|
|
613
|
-
for (let i = 0; i < logs.length; i++) {
|
|
614
|
-
const log = logs[i];
|
|
615
|
-
if (log.blockHash != null) { continue; }
|
|
616
|
-
if (blocks[log.blockNumber] == null) {
|
|
617
|
-
const block = await this.getBlock(log.blockNumber);
|
|
618
|
-
if (block) {
|
|
619
|
-
blocks[log.blockNumber] = block.hash;
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
log.blockHash = blocks[log.blockNumber];
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
return logs;
|
|
627
|
-
}
|
|
628
|
-
*/
|
|
629
|
-
default:
|
|
630
|
-
break;
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
return super._perform(req);
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
async getNetwork(): Promise<Network> {
|
|
637
|
-
return this.network;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
/**
|
|
641
|
-
* Resolves to the current price of ether.
|
|
642
|
-
*
|
|
643
|
-
* This returns ``0`` on any network other than ``mainnet``.
|
|
644
|
-
*/
|
|
645
|
-
async getEtherPrice(): Promise<number> {
|
|
646
|
-
if (this.network.name !== "mainnet") { return 0.0; }
|
|
647
|
-
return parseFloat((await this.fetch("stats", { action: "ethprice" })).ethusd);
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
/**
|
|
651
|
-
* Resolves to a [Contract]] for %%address%%, using the
|
|
652
|
-
* Etherscan API to retreive the Contract ABI.
|
|
653
|
-
*/
|
|
654
|
-
async getContract(_address: string): Promise<null | Contract> {
|
|
655
|
-
let address = this._getAddress(_address);
|
|
656
|
-
if (isPromise(address)) { address = await address; }
|
|
657
|
-
|
|
658
|
-
try {
|
|
659
|
-
const resp = await this.fetch("contract", {
|
|
660
|
-
action: "getabi", address });
|
|
661
|
-
const abi = JSON.parse(resp);
|
|
662
|
-
return new Contract(address, abi, this);
|
|
663
|
-
} catch (error) {
|
|
664
|
-
return null;
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
isCommunityResource(): boolean {
|
|
669
|
-
return (this.apiKey == null);
|
|
670
|
-
}
|
|
671
|
-
}
|