@depay/web3-wallets-evm 13.1.1 → 13.1.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.
@@ -1,7 +1,7 @@
1
1
  import { Blockchain } from '@depay/web3-blockchains';
2
2
  import { ethers } from 'ethers';
3
3
  import { CONSTANTS } from '@depay/web3-constants';
4
- import { getProvider, estimate } from '@depay/web3-client-evm';
4
+ import { request, getProvider, estimate } from '@depay/web3-client-evm';
5
5
  import { WalletConnectClient, QRCodeModal } from '@depay/walletconnect-v1';
6
6
  import { CoinbaseWalletSDK } from '@depay/coinbase-wallet-sdk';
7
7
 
@@ -112,12 +112,14 @@ const sendTransaction$2 = async ({ transaction, wallet })=> {
112
112
  throw({ code: 'WRONG_NETWORK' })
113
113
  }
114
114
  await transaction.prepare({ wallet });
115
+ let transactionCount = await request({ blockchain: transaction.blockchain, method: 'transactionCount', address: transaction.from });
116
+ transaction.nonce = transactionCount;
115
117
  let provider = new ethers.providers.Web3Provider(window.ethereum, 'any');
116
118
  let signer = provider.getSigner(0);
117
119
  await submit$2({ transaction, provider, signer }).then((sentTransaction)=>{
118
120
  if (sentTransaction) {
119
121
  transaction.id = sentTransaction.hash;
120
- transaction.nonce = sentTransaction.nonce;
122
+ transaction.nonce = sentTransaction.nonce || transactionCount;
121
123
  transaction.url = Blockchain.findByName(transaction.blockchain).explorerUrlFor({ transaction });
122
124
  if (transaction.sent) transaction.sent(transaction);
123
125
  sentTransaction.wait(1).then(() => {
@@ -334,6 +336,8 @@ const sendTransaction$1 = async ({ transaction, wallet })=> {
334
336
  throw({ code: 'WRONG_NETWORK' })
335
337
  }
336
338
  await transaction.prepare({ wallet });
339
+ let transactionCount = await request({ blockchain: transaction.blockchain, method: 'transactionCount', address: transaction.from });
340
+ transaction.nonce = transactionCount;
337
341
  await submit$1({ transaction, wallet }).then(async (tx)=>{
338
342
  if (tx) {
339
343
  let blockchain = Blockchain.findByName(transaction.blockchain);
@@ -341,7 +345,7 @@ const sendTransaction$1 = async ({ transaction, wallet })=> {
341
345
  transaction.url = blockchain.explorerUrlFor({ transaction });
342
346
  if (transaction.sent) transaction.sent(transaction);
343
347
  let sentTransaction = await retrieveTransaction(tx, transaction.blockchain);
344
- transaction.nonce = sentTransaction.nonce;
348
+ transaction.nonce = sentTransaction.nonce || transactionCount;
345
349
  if(!sentTransaction) {
346
350
  transaction._failed = true;
347
351
  console.log('Error retrieving transaction');
package/dist/esm/index.js CHANGED
@@ -2,11 +2,11 @@ import { Blockchain } from '@depay/web3-blockchains';
2
2
  import { ethers } from 'ethers';
3
3
  import { CONSTANTS } from '@depay/web3-constants';
4
4
  import { PublicKey, Transaction as Transaction$1, SystemProgram } from '@depay/solana-web3.js';
5
- import { getProvider, estimate } from '@depay/web3-client';
5
+ import { getProvider, request as request$1, estimate } from '@depay/web3-client';
6
6
  import { WalletConnectClient, QRCodeModal } from '@depay/walletconnect-v1';
7
7
  import { CoinbaseWalletSDK } from '@depay/coinbase-wallet-sdk';
8
8
 
9
- function _optionalChain$8(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
9
+ function _optionalChain$9(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
10
10
  class Transaction {
11
11
 
12
12
  constructor({ blockchain, from, to, value, api, method, params, instructions, sent, succeeded, failed }) {
@@ -17,7 +17,7 @@ class Transaction {
17
17
  this.to = (to && to.match('0x')) ? ethers.utils.getAddress(to) : to;
18
18
 
19
19
  // optional
20
- this.value = _optionalChain$8([Transaction, 'access', _ => _.bigNumberify, 'call', _2 => _2(value, blockchain), 'optionalAccess', _3 => _3.toString, 'call', _4 => _4()]);
20
+ this.value = _optionalChain$9([Transaction, 'access', _ => _.bigNumberify, 'call', _2 => _2(value, blockchain), 'optionalAccess', _3 => _3.toString, 'call', _4 => _4()]);
21
21
  this.api = api;
22
22
  this.method = method;
23
23
  this.params = params;
@@ -104,6 +104,387 @@ class Transaction {
104
104
  }
105
105
  }
106
106
 
107
+ let supported$3 = ['ethereum', 'bsc', 'polygon', 'velas'];
108
+ supported$3.evm = ['ethereum', 'bsc', 'polygon', 'velas'];
109
+ supported$3.solana = [];
110
+
111
+ const BATCH_INTERVAL = 10;
112
+ const CHUNK_SIZE = 99;
113
+
114
+ class StaticJsonRpcBatchProvider extends ethers.providers.JsonRpcProvider {
115
+
116
+ constructor(url, network, endpoints) {
117
+ super(url);
118
+ this._network = network;
119
+ this._endpoint = url;
120
+ this._endpoints = endpoints;
121
+ }
122
+
123
+ detectNetwork() {
124
+ return Promise.resolve(Blockchain.findByName(this._network).id)
125
+ }
126
+
127
+ requestChunk(chunk, endpoint) {
128
+
129
+ const request = chunk.map((inflight) => inflight.request);
130
+
131
+ return ethers.utils.fetchJson(endpoint, JSON.stringify(request))
132
+ .then((result) => {
133
+ // For each result, feed it to the correct Promise, depending
134
+ // on whether it was a success or error
135
+ chunk.forEach((inflightRequest, index) => {
136
+ const payload = result[index];
137
+ if (payload.error) {
138
+ const error = new Error(payload.error.message);
139
+ error.code = payload.error.code;
140
+ error.data = payload.error.data;
141
+ inflightRequest.reject(error);
142
+ }
143
+ else {
144
+ inflightRequest.resolve(payload.result);
145
+ }
146
+ });
147
+ }).catch((error) => {
148
+ if(error && error.code == 'SERVER_ERROR') {
149
+ const index = this._endpoints.indexOf(this._endpoint)+1;
150
+ this._endpoint = index >= this._endpoints.length ? this._endpoints[0] : this._endpoints[index];
151
+ this.requestChunk(chunk, this._endpoint);
152
+ } else {
153
+ chunk.forEach((inflightRequest) => {
154
+ inflightRequest.reject(error);
155
+ });
156
+ }
157
+ })
158
+ }
159
+
160
+ send(method, params) {
161
+
162
+ const request = {
163
+ method: method,
164
+ params: params,
165
+ id: (this._nextId++),
166
+ jsonrpc: "2.0"
167
+ };
168
+
169
+ if (this._pendingBatch == null) {
170
+ this._pendingBatch = [];
171
+ }
172
+
173
+ const inflightRequest = { request, resolve: null, reject: null };
174
+
175
+ const promise = new Promise((resolve, reject) => {
176
+ inflightRequest.resolve = resolve;
177
+ inflightRequest.reject = reject;
178
+ });
179
+
180
+ this._pendingBatch.push(inflightRequest);
181
+
182
+ if (!this._pendingBatchAggregator) {
183
+ // Schedule batch for next event loop + short duration
184
+ this._pendingBatchAggregator = setTimeout(() => {
185
+ // Get the current batch and clear it, so new requests
186
+ // go into the next batch
187
+ const batch = this._pendingBatch;
188
+ this._pendingBatch = null;
189
+ this._pendingBatchAggregator = null;
190
+ // Prepare Chunks of CHUNK_SIZE
191
+ const chunks = [];
192
+ for (let i = 0; i < Math.ceil(batch.length / CHUNK_SIZE); i++) {
193
+ chunks[i] = batch.slice(i*CHUNK_SIZE, (i+1)*CHUNK_SIZE);
194
+ }
195
+ chunks.forEach((chunk)=>{
196
+ // Get the request as an array of requests
197
+ chunk.map((inflight) => inflight.request);
198
+ return this.requestChunk(chunk, this._endpoint)
199
+ });
200
+ }, BATCH_INTERVAL);
201
+ }
202
+
203
+ return promise
204
+ }
205
+
206
+ }
207
+
208
+ let getWindow = () => {
209
+ if (typeof global == 'object') return global
210
+ return window
211
+ };
212
+
213
+ // MAKE SURE PROVIDER SUPPORT BATCH SIZE OF 99 BATCH REQUESTS!
214
+ const ENDPOINTS = {
215
+ ethereum: ['https://rpc.ankr.com/eth', 'https://eth-mainnet-public.unifra.io', 'https://ethereum.publicnode.com'],
216
+ bsc: ['https://bsc-dataseed.binance.org', 'https://bsc-dataseed1.ninicoin.io', 'https://bsc-dataseed3.defibit.io'],
217
+ polygon: ['https://polygon-rpc.com', 'https://poly-rpc.gateway.pokt.network', 'https://matic-mainnet.chainstacklabs.com'],
218
+ velas: ['https://mainnet.velas.com/rpc', 'https://evmexplorer.velas.com/rpc', 'https://explorer.velas.com/rpc'],
219
+ };
220
+
221
+ const getProviders = ()=> {
222
+ if(getWindow()._clientProviders == undefined) {
223
+ getWindow()._clientProviders = {};
224
+ }
225
+ return getWindow()._clientProviders
226
+ };
227
+
228
+ const setProvider$1 = (blockchain, provider)=> {
229
+ getProviders()[blockchain] = provider;
230
+ };
231
+
232
+ const setProviderEndpoints$1 = async (blockchain, endpoints)=> {
233
+
234
+ let endpoint;
235
+ let window = getWindow();
236
+
237
+ if(
238
+ window.fetch == undefined ||
239
+ (typeof process != 'undefined' && process['env'] && process['env']['NODE_ENV'] == 'test') ||
240
+ (typeof window.cy != 'undefined')
241
+ ) {
242
+ endpoint = endpoints[0];
243
+ } else {
244
+
245
+ let responseTimes = await Promise.all(endpoints.map((endpoint)=>{
246
+ return new Promise(async (resolve)=>{
247
+ let timeout = 900;
248
+ let before = new Date().getTime();
249
+ setTimeout(()=>resolve(timeout), timeout);
250
+ const response = await fetch(endpoint, {
251
+ method: 'POST',
252
+ headers: {
253
+ 'Accept': 'application/json',
254
+ 'Content-Type': 'application/json'
255
+ },
256
+ body: JSON.stringify({ method: 'net_version', id: 1, jsonrpc: '2.0' })
257
+ });
258
+ if(!response.ok) { return resolve(999) }
259
+ let after = new Date().getTime();
260
+ resolve(after-before);
261
+ })
262
+ }));
263
+
264
+ const fastestResponse = Math.min(...responseTimes);
265
+ const fastestIndex = responseTimes.indexOf(fastestResponse);
266
+ endpoint = endpoints[fastestIndex];
267
+ }
268
+
269
+ setProvider$1(
270
+ blockchain,
271
+ new StaticJsonRpcBatchProvider(endpoint, blockchain, endpoints)
272
+ );
273
+ };
274
+
275
+ const getProvider$1 = async (blockchain)=> {
276
+
277
+ let providers = getProviders();
278
+ if(providers && providers[blockchain]){ return providers[blockchain] }
279
+
280
+ let window = getWindow();
281
+ if(window._getProviderPromise && window._getProviderPromise[blockchain]) { return await window._getProviderPromise[blockchain] }
282
+
283
+ if(!window._getProviderPromise){ window._getProviderPromise = {}; }
284
+ window._getProviderPromise[blockchain] = new Promise(async(resolve)=> {
285
+ await setProviderEndpoints$1(blockchain, ENDPOINTS[blockchain]);
286
+ resolve(getWindow()._clientProviders[blockchain]);
287
+ });
288
+
289
+ return await window._getProviderPromise[blockchain]
290
+ };
291
+
292
+ var EVM = {
293
+ getProvider: getProvider$1,
294
+ setProviderEndpoints: setProviderEndpoints$1,
295
+ setProvider: setProvider$1,
296
+ };
297
+
298
+ function _optionalChain$8(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
299
+ let getCacheStore = () => {
300
+ if (getWindow()._cacheStore == undefined) {
301
+ resetCache();
302
+ }
303
+ return getWindow()._cacheStore
304
+ };
305
+
306
+ let getPromiseStore = () => {
307
+ if (getWindow()._promiseStore == undefined) {
308
+ resetCache();
309
+ }
310
+ return getWindow()._promiseStore
311
+ };
312
+
313
+ let resetCache = () => {
314
+ getWindow()._cacheStore = {};
315
+ getWindow()._promiseStore = {};
316
+ getWindow()._clientProviders = {};
317
+ };
318
+
319
+ let set = function ({ key, value, expires }) {
320
+ getCacheStore()[key] = {
321
+ expiresAt: Date.now() + expires,
322
+ value,
323
+ };
324
+ };
325
+
326
+ let get = function ({ key, expires }) {
327
+ let cachedEntry = getCacheStore()[key];
328
+ if (_optionalChain$8([cachedEntry, 'optionalAccess', _ => _.expiresAt]) > Date.now()) {
329
+ return cachedEntry.value
330
+ }
331
+ };
332
+
333
+ let getPromise = function({ key }) {
334
+ return getPromiseStore()[key]
335
+ };
336
+
337
+ let setPromise = function({ key, promise }) {
338
+ getPromiseStore()[key] = promise;
339
+ return promise
340
+ };
341
+
342
+ let deletePromise = function({ key }) {
343
+ getPromiseStore()[key] = undefined;
344
+ };
345
+
346
+ let cache = function ({ call, key, expires = 0 }) {
347
+ return new Promise((resolve, reject)=>{
348
+ let value;
349
+ key = JSON.stringify(key);
350
+
351
+ // get existing promise (of a previous pending request asking for the exact same thing)
352
+ let existingPromise = getPromise({ key });
353
+ if(existingPromise) {
354
+ return existingPromise
355
+ .then(resolve)
356
+ .catch(reject)
357
+ }
358
+
359
+ setPromise({ key, promise: new Promise((resolveQueue, rejectQueue)=>{
360
+ if (expires === 0) {
361
+ return call()
362
+ .then((value)=>{
363
+ resolve(value);
364
+ resolveQueue(value);
365
+ })
366
+ .catch((error)=>{
367
+ reject(error);
368
+ rejectQueue(error);
369
+ })
370
+ }
371
+
372
+ // get cached value
373
+ value = get({ key, expires });
374
+ if (value) {
375
+ resolve(value);
376
+ resolveQueue(value);
377
+ return value
378
+ }
379
+
380
+ // set new cache value
381
+ call()
382
+ .then((value)=>{
383
+ if (value) {
384
+ set({ key, value, expires });
385
+ }
386
+ resolve(value);
387
+ resolveQueue(value);
388
+ })
389
+ .catch((error)=>{
390
+ reject(error);
391
+ rejectQueue(error);
392
+ });
393
+ })
394
+ }).then(()=>{
395
+ deletePromise({ key });
396
+ }).catch(()=>{
397
+ deletePromise({ key });
398
+ });
399
+ })
400
+ };
401
+
402
+ var parseUrl = (url) => {
403
+ if (typeof url == 'object') {
404
+ return url
405
+ }
406
+ let deconstructed = url.match(/(?<blockchain>\w+):\/\/(?<part1>[\w\d]+)(\/(?<part2>[\w\d]+)*)?/);
407
+
408
+ if(deconstructed.groups.part2 == undefined) {
409
+ if(deconstructed.groups.part1.match(/\d/)) {
410
+ return {
411
+ blockchain: deconstructed.groups.blockchain,
412
+ address: deconstructed.groups.part1
413
+ }
414
+ } else {
415
+ return {
416
+ blockchain: deconstructed.groups.blockchain,
417
+ method: deconstructed.groups.part1
418
+ }
419
+ }
420
+ } else {
421
+ return {
422
+ blockchain: deconstructed.groups.blockchain,
423
+ address: deconstructed.groups.part1,
424
+ method: deconstructed.groups.part2
425
+ }
426
+ }
427
+ };
428
+
429
+ let paramsToContractArgs = ({ contract, method, params }) => {
430
+ let fragment = contract.interface.fragments.find((fragment) => {
431
+ return fragment.name == method
432
+ });
433
+
434
+ return fragment.inputs.map((input, index) => {
435
+ if (Array.isArray(params)) {
436
+ return params[index]
437
+ } else {
438
+ return params[input.name]
439
+ }
440
+ })
441
+ };
442
+
443
+ let contractCall = ({ address, api, method, params, provider, block }) => {
444
+ let contract = new ethers.Contract(address, api, provider);
445
+ let args = paramsToContractArgs({ contract, method, params });
446
+ return contract[method](...args, { blockTag: block })
447
+ };
448
+
449
+ let balance = ({ address, provider }) => {
450
+ return provider.getBalance(address)
451
+ };
452
+
453
+ let transactionCount = ({ address, provider }) => {
454
+ return provider.getTransactionCount(address)
455
+ };
456
+
457
+ var requestEVM = async ({ blockchain, address, api, method, params, block }) => {
458
+ const provider = await EVM.getProvider(blockchain);
459
+
460
+ if (api) {
461
+ return contractCall({ address, api, method, params, provider, block })
462
+ } else if (method === 'latestBlockNumber') {
463
+ return provider.getBlockNumber()
464
+ } else if (method === 'balance') {
465
+ return balance({ address, provider })
466
+ } else if (method === 'transactionCount') {
467
+ return transactionCount({ address, provider })
468
+ }
469
+ };
470
+
471
+ let request = async function (url, options) {
472
+ let { blockchain, address, method } = parseUrl(url);
473
+ let { api, params, cache: cache$1, block } = (typeof(url) == 'object' ? url : options) || {};
474
+
475
+ return await cache({
476
+ expires: cache$1 || 0,
477
+ key: [blockchain, address, method, params, block],
478
+ call: async()=>{
479
+ if(supported$3.evm.includes(blockchain)) {
480
+ return requestEVM({ blockchain, address, api, method, params, block })
481
+ } else {
482
+ throw 'Unknown blockchain: ' + blockchain
483
+ }
484
+ }
485
+ })
486
+ };
487
+
107
488
  const sendTransaction$3 = async ({ transaction, wallet })=> {
108
489
  transaction = new Transaction(transaction);
109
490
  if((await wallet.connectedTo(transaction.blockchain)) == false) {
@@ -113,12 +494,14 @@ const sendTransaction$3 = async ({ transaction, wallet })=> {
113
494
  throw({ code: 'WRONG_NETWORK' })
114
495
  }
115
496
  await transaction.prepare({ wallet });
497
+ let transactionCount = await request({ blockchain: transaction.blockchain, method: 'transactionCount', address: transaction.from });
498
+ transaction.nonce = transactionCount;
116
499
  let provider = new ethers.providers.Web3Provider(window.ethereum, 'any');
117
500
  let signer = provider.getSigner(0);
118
501
  await submit$3({ transaction, provider, signer }).then((sentTransaction)=>{
119
502
  if (sentTransaction) {
120
503
  transaction.id = sentTransaction.hash;
121
- transaction.nonce = sentTransaction.nonce;
504
+ transaction.nonce = sentTransaction.nonce || transactionCount;
122
505
  transaction.url = Blockchain.findByName(transaction.blockchain).explorerUrlFor({ transaction });
123
506
  if (transaction.sent) transaction.sent(transaction);
124
507
  sentTransaction.wait(1).then(() => {
@@ -525,6 +908,8 @@ const sendTransaction$1 = async ({ transaction, wallet })=> {
525
908
  throw({ code: 'WRONG_NETWORK' })
526
909
  }
527
910
  await transaction.prepare({ wallet });
911
+ let transactionCount = await request$1({ blockchain: transaction.blockchain, method: 'transactionCount', address: transaction.from });
912
+ transaction.nonce = transactionCount;
528
913
  await submit$1({ transaction, wallet }).then(async (tx)=>{
529
914
  if (tx) {
530
915
  let blockchain = Blockchain.findByName(transaction.blockchain);
@@ -532,7 +917,7 @@ const sendTransaction$1 = async ({ transaction, wallet })=> {
532
917
  transaction.url = blockchain.explorerUrlFor({ transaction });
533
918
  if (transaction.sent) transaction.sent(transaction);
534
919
  let sentTransaction = await retrieveTransaction(tx, transaction.blockchain);
535
- transaction.nonce = sentTransaction.nonce;
920
+ transaction.nonce = sentTransaction.nonce || transactionCount;
536
921
  if(!sentTransaction) {
537
922
  transaction._failed = true;
538
923
  console.log('Error retrieving transaction');
@@ -111,12 +111,14 @@
111
111
  throw({ code: 'WRONG_NETWORK' })
112
112
  }
113
113
  await transaction.prepare({ wallet });
114
+ let transactionCount = await web3ClientEvm.request({ blockchain: transaction.blockchain, method: 'transactionCount', address: transaction.from });
115
+ transaction.nonce = transactionCount;
114
116
  let provider = new ethers.ethers.providers.Web3Provider(window.ethereum, 'any');
115
117
  let signer = provider.getSigner(0);
116
118
  await submit$2({ transaction, provider, signer }).then((sentTransaction)=>{
117
119
  if (sentTransaction) {
118
120
  transaction.id = sentTransaction.hash;
119
- transaction.nonce = sentTransaction.nonce;
121
+ transaction.nonce = sentTransaction.nonce || transactionCount;
120
122
  transaction.url = web3Blockchains.Blockchain.findByName(transaction.blockchain).explorerUrlFor({ transaction });
121
123
  if (transaction.sent) transaction.sent(transaction);
122
124
  sentTransaction.wait(1).then(() => {
@@ -333,6 +335,8 @@
333
335
  throw({ code: 'WRONG_NETWORK' })
334
336
  }
335
337
  await transaction.prepare({ wallet });
338
+ let transactionCount = await web3ClientEvm.request({ blockchain: transaction.blockchain, method: 'transactionCount', address: transaction.from });
339
+ transaction.nonce = transactionCount;
336
340
  await submit$1({ transaction, wallet }).then(async (tx)=>{
337
341
  if (tx) {
338
342
  let blockchain = web3Blockchains.Blockchain.findByName(transaction.blockchain);
@@ -340,7 +344,7 @@
340
344
  transaction.url = blockchain.explorerUrlFor({ transaction });
341
345
  if (transaction.sent) transaction.sent(transaction);
342
346
  let sentTransaction = await retrieveTransaction(tx, transaction.blockchain);
343
- transaction.nonce = sentTransaction.nonce;
347
+ transaction.nonce = sentTransaction.nonce || transactionCount;
344
348
  if(!sentTransaction) {
345
349
  transaction._failed = true;
346
350
  console.log('Error retrieving transaction');
package/dist/umd/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Web3Wallets = {}, global.Web3Blockchains, global.ethers, global.Web3Constants, global.SolanaWeb3js, global.Web3Client, global.WalletConnect, global.CoinbaseWalletSdk));
5
5
  }(this, (function (exports, web3Blockchains, ethers, web3Constants, solanaWeb3_js, web3Client, walletconnectV1, coinbaseWalletSdk) { 'use strict';
6
6
 
7
- function _optionalChain$8(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
7
+ function _optionalChain$9(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
8
8
  class Transaction {
9
9
 
10
10
  constructor({ blockchain, from, to, value, api, method, params, instructions, sent, succeeded, failed }) {
@@ -15,7 +15,7 @@
15
15
  this.to = (to && to.match('0x')) ? ethers.ethers.utils.getAddress(to) : to;
16
16
 
17
17
  // optional
18
- this.value = _optionalChain$8([Transaction, 'access', _ => _.bigNumberify, 'call', _2 => _2(value, blockchain), 'optionalAccess', _3 => _3.toString, 'call', _4 => _4()]);
18
+ this.value = _optionalChain$9([Transaction, 'access', _ => _.bigNumberify, 'call', _2 => _2(value, blockchain), 'optionalAccess', _3 => _3.toString, 'call', _4 => _4()]);
19
19
  this.api = api;
20
20
  this.method = method;
21
21
  this.params = params;
@@ -102,6 +102,387 @@
102
102
  }
103
103
  }
104
104
 
105
+ let supported$3 = ['ethereum', 'bsc', 'polygon', 'velas'];
106
+ supported$3.evm = ['ethereum', 'bsc', 'polygon', 'velas'];
107
+ supported$3.solana = [];
108
+
109
+ const BATCH_INTERVAL = 10;
110
+ const CHUNK_SIZE = 99;
111
+
112
+ class StaticJsonRpcBatchProvider extends ethers.ethers.providers.JsonRpcProvider {
113
+
114
+ constructor(url, network, endpoints) {
115
+ super(url);
116
+ this._network = network;
117
+ this._endpoint = url;
118
+ this._endpoints = endpoints;
119
+ }
120
+
121
+ detectNetwork() {
122
+ return Promise.resolve(web3Blockchains.Blockchain.findByName(this._network).id)
123
+ }
124
+
125
+ requestChunk(chunk, endpoint) {
126
+
127
+ const request = chunk.map((inflight) => inflight.request);
128
+
129
+ return ethers.ethers.utils.fetchJson(endpoint, JSON.stringify(request))
130
+ .then((result) => {
131
+ // For each result, feed it to the correct Promise, depending
132
+ // on whether it was a success or error
133
+ chunk.forEach((inflightRequest, index) => {
134
+ const payload = result[index];
135
+ if (payload.error) {
136
+ const error = new Error(payload.error.message);
137
+ error.code = payload.error.code;
138
+ error.data = payload.error.data;
139
+ inflightRequest.reject(error);
140
+ }
141
+ else {
142
+ inflightRequest.resolve(payload.result);
143
+ }
144
+ });
145
+ }).catch((error) => {
146
+ if(error && error.code == 'SERVER_ERROR') {
147
+ const index = this._endpoints.indexOf(this._endpoint)+1;
148
+ this._endpoint = index >= this._endpoints.length ? this._endpoints[0] : this._endpoints[index];
149
+ this.requestChunk(chunk, this._endpoint);
150
+ } else {
151
+ chunk.forEach((inflightRequest) => {
152
+ inflightRequest.reject(error);
153
+ });
154
+ }
155
+ })
156
+ }
157
+
158
+ send(method, params) {
159
+
160
+ const request = {
161
+ method: method,
162
+ params: params,
163
+ id: (this._nextId++),
164
+ jsonrpc: "2.0"
165
+ };
166
+
167
+ if (this._pendingBatch == null) {
168
+ this._pendingBatch = [];
169
+ }
170
+
171
+ const inflightRequest = { request, resolve: null, reject: null };
172
+
173
+ const promise = new Promise((resolve, reject) => {
174
+ inflightRequest.resolve = resolve;
175
+ inflightRequest.reject = reject;
176
+ });
177
+
178
+ this._pendingBatch.push(inflightRequest);
179
+
180
+ if (!this._pendingBatchAggregator) {
181
+ // Schedule batch for next event loop + short duration
182
+ this._pendingBatchAggregator = setTimeout(() => {
183
+ // Get the current batch and clear it, so new requests
184
+ // go into the next batch
185
+ const batch = this._pendingBatch;
186
+ this._pendingBatch = null;
187
+ this._pendingBatchAggregator = null;
188
+ // Prepare Chunks of CHUNK_SIZE
189
+ const chunks = [];
190
+ for (let i = 0; i < Math.ceil(batch.length / CHUNK_SIZE); i++) {
191
+ chunks[i] = batch.slice(i*CHUNK_SIZE, (i+1)*CHUNK_SIZE);
192
+ }
193
+ chunks.forEach((chunk)=>{
194
+ // Get the request as an array of requests
195
+ chunk.map((inflight) => inflight.request);
196
+ return this.requestChunk(chunk, this._endpoint)
197
+ });
198
+ }, BATCH_INTERVAL);
199
+ }
200
+
201
+ return promise
202
+ }
203
+
204
+ }
205
+
206
+ let getWindow = () => {
207
+ if (typeof global == 'object') return global
208
+ return window
209
+ };
210
+
211
+ // MAKE SURE PROVIDER SUPPORT BATCH SIZE OF 99 BATCH REQUESTS!
212
+ const ENDPOINTS = {
213
+ ethereum: ['https://rpc.ankr.com/eth', 'https://eth-mainnet-public.unifra.io', 'https://ethereum.publicnode.com'],
214
+ bsc: ['https://bsc-dataseed.binance.org', 'https://bsc-dataseed1.ninicoin.io', 'https://bsc-dataseed3.defibit.io'],
215
+ polygon: ['https://polygon-rpc.com', 'https://poly-rpc.gateway.pokt.network', 'https://matic-mainnet.chainstacklabs.com'],
216
+ velas: ['https://mainnet.velas.com/rpc', 'https://evmexplorer.velas.com/rpc', 'https://explorer.velas.com/rpc'],
217
+ };
218
+
219
+ const getProviders = ()=> {
220
+ if(getWindow()._clientProviders == undefined) {
221
+ getWindow()._clientProviders = {};
222
+ }
223
+ return getWindow()._clientProviders
224
+ };
225
+
226
+ const setProvider$1 = (blockchain, provider)=> {
227
+ getProviders()[blockchain] = provider;
228
+ };
229
+
230
+ const setProviderEndpoints$1 = async (blockchain, endpoints)=> {
231
+
232
+ let endpoint;
233
+ let window = getWindow();
234
+
235
+ if(
236
+ window.fetch == undefined ||
237
+ (typeof process != 'undefined' && process['env'] && process['env']['NODE_ENV'] == 'test') ||
238
+ (typeof window.cy != 'undefined')
239
+ ) {
240
+ endpoint = endpoints[0];
241
+ } else {
242
+
243
+ let responseTimes = await Promise.all(endpoints.map((endpoint)=>{
244
+ return new Promise(async (resolve)=>{
245
+ let timeout = 900;
246
+ let before = new Date().getTime();
247
+ setTimeout(()=>resolve(timeout), timeout);
248
+ const response = await fetch(endpoint, {
249
+ method: 'POST',
250
+ headers: {
251
+ 'Accept': 'application/json',
252
+ 'Content-Type': 'application/json'
253
+ },
254
+ body: JSON.stringify({ method: 'net_version', id: 1, jsonrpc: '2.0' })
255
+ });
256
+ if(!response.ok) { return resolve(999) }
257
+ let after = new Date().getTime();
258
+ resolve(after-before);
259
+ })
260
+ }));
261
+
262
+ const fastestResponse = Math.min(...responseTimes);
263
+ const fastestIndex = responseTimes.indexOf(fastestResponse);
264
+ endpoint = endpoints[fastestIndex];
265
+ }
266
+
267
+ setProvider$1(
268
+ blockchain,
269
+ new StaticJsonRpcBatchProvider(endpoint, blockchain, endpoints)
270
+ );
271
+ };
272
+
273
+ const getProvider$1 = async (blockchain)=> {
274
+
275
+ let providers = getProviders();
276
+ if(providers && providers[blockchain]){ return providers[blockchain] }
277
+
278
+ let window = getWindow();
279
+ if(window._getProviderPromise && window._getProviderPromise[blockchain]) { return await window._getProviderPromise[blockchain] }
280
+
281
+ if(!window._getProviderPromise){ window._getProviderPromise = {}; }
282
+ window._getProviderPromise[blockchain] = new Promise(async(resolve)=> {
283
+ await setProviderEndpoints$1(blockchain, ENDPOINTS[blockchain]);
284
+ resolve(getWindow()._clientProviders[blockchain]);
285
+ });
286
+
287
+ return await window._getProviderPromise[blockchain]
288
+ };
289
+
290
+ var EVM = {
291
+ getProvider: getProvider$1,
292
+ setProviderEndpoints: setProviderEndpoints$1,
293
+ setProvider: setProvider$1,
294
+ };
295
+
296
+ function _optionalChain$8(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
297
+ let getCacheStore = () => {
298
+ if (getWindow()._cacheStore == undefined) {
299
+ resetCache();
300
+ }
301
+ return getWindow()._cacheStore
302
+ };
303
+
304
+ let getPromiseStore = () => {
305
+ if (getWindow()._promiseStore == undefined) {
306
+ resetCache();
307
+ }
308
+ return getWindow()._promiseStore
309
+ };
310
+
311
+ let resetCache = () => {
312
+ getWindow()._cacheStore = {};
313
+ getWindow()._promiseStore = {};
314
+ getWindow()._clientProviders = {};
315
+ };
316
+
317
+ let set = function ({ key, value, expires }) {
318
+ getCacheStore()[key] = {
319
+ expiresAt: Date.now() + expires,
320
+ value,
321
+ };
322
+ };
323
+
324
+ let get = function ({ key, expires }) {
325
+ let cachedEntry = getCacheStore()[key];
326
+ if (_optionalChain$8([cachedEntry, 'optionalAccess', _ => _.expiresAt]) > Date.now()) {
327
+ return cachedEntry.value
328
+ }
329
+ };
330
+
331
+ let getPromise = function({ key }) {
332
+ return getPromiseStore()[key]
333
+ };
334
+
335
+ let setPromise = function({ key, promise }) {
336
+ getPromiseStore()[key] = promise;
337
+ return promise
338
+ };
339
+
340
+ let deletePromise = function({ key }) {
341
+ getPromiseStore()[key] = undefined;
342
+ };
343
+
344
+ let cache = function ({ call, key, expires = 0 }) {
345
+ return new Promise((resolve, reject)=>{
346
+ let value;
347
+ key = JSON.stringify(key);
348
+
349
+ // get existing promise (of a previous pending request asking for the exact same thing)
350
+ let existingPromise = getPromise({ key });
351
+ if(existingPromise) {
352
+ return existingPromise
353
+ .then(resolve)
354
+ .catch(reject)
355
+ }
356
+
357
+ setPromise({ key, promise: new Promise((resolveQueue, rejectQueue)=>{
358
+ if (expires === 0) {
359
+ return call()
360
+ .then((value)=>{
361
+ resolve(value);
362
+ resolveQueue(value);
363
+ })
364
+ .catch((error)=>{
365
+ reject(error);
366
+ rejectQueue(error);
367
+ })
368
+ }
369
+
370
+ // get cached value
371
+ value = get({ key, expires });
372
+ if (value) {
373
+ resolve(value);
374
+ resolveQueue(value);
375
+ return value
376
+ }
377
+
378
+ // set new cache value
379
+ call()
380
+ .then((value)=>{
381
+ if (value) {
382
+ set({ key, value, expires });
383
+ }
384
+ resolve(value);
385
+ resolveQueue(value);
386
+ })
387
+ .catch((error)=>{
388
+ reject(error);
389
+ rejectQueue(error);
390
+ });
391
+ })
392
+ }).then(()=>{
393
+ deletePromise({ key });
394
+ }).catch(()=>{
395
+ deletePromise({ key });
396
+ });
397
+ })
398
+ };
399
+
400
+ var parseUrl = (url) => {
401
+ if (typeof url == 'object') {
402
+ return url
403
+ }
404
+ let deconstructed = url.match(/(?<blockchain>\w+):\/\/(?<part1>[\w\d]+)(\/(?<part2>[\w\d]+)*)?/);
405
+
406
+ if(deconstructed.groups.part2 == undefined) {
407
+ if(deconstructed.groups.part1.match(/\d/)) {
408
+ return {
409
+ blockchain: deconstructed.groups.blockchain,
410
+ address: deconstructed.groups.part1
411
+ }
412
+ } else {
413
+ return {
414
+ blockchain: deconstructed.groups.blockchain,
415
+ method: deconstructed.groups.part1
416
+ }
417
+ }
418
+ } else {
419
+ return {
420
+ blockchain: deconstructed.groups.blockchain,
421
+ address: deconstructed.groups.part1,
422
+ method: deconstructed.groups.part2
423
+ }
424
+ }
425
+ };
426
+
427
+ let paramsToContractArgs = ({ contract, method, params }) => {
428
+ let fragment = contract.interface.fragments.find((fragment) => {
429
+ return fragment.name == method
430
+ });
431
+
432
+ return fragment.inputs.map((input, index) => {
433
+ if (Array.isArray(params)) {
434
+ return params[index]
435
+ } else {
436
+ return params[input.name]
437
+ }
438
+ })
439
+ };
440
+
441
+ let contractCall = ({ address, api, method, params, provider, block }) => {
442
+ let contract = new ethers.ethers.Contract(address, api, provider);
443
+ let args = paramsToContractArgs({ contract, method, params });
444
+ return contract[method](...args, { blockTag: block })
445
+ };
446
+
447
+ let balance = ({ address, provider }) => {
448
+ return provider.getBalance(address)
449
+ };
450
+
451
+ let transactionCount = ({ address, provider }) => {
452
+ return provider.getTransactionCount(address)
453
+ };
454
+
455
+ var requestEVM = async ({ blockchain, address, api, method, params, block }) => {
456
+ const provider = await EVM.getProvider(blockchain);
457
+
458
+ if (api) {
459
+ return contractCall({ address, api, method, params, provider, block })
460
+ } else if (method === 'latestBlockNumber') {
461
+ return provider.getBlockNumber()
462
+ } else if (method === 'balance') {
463
+ return balance({ address, provider })
464
+ } else if (method === 'transactionCount') {
465
+ return transactionCount({ address, provider })
466
+ }
467
+ };
468
+
469
+ let request = async function (url, options) {
470
+ let { blockchain, address, method } = parseUrl(url);
471
+ let { api, params, cache: cache$1, block } = (typeof(url) == 'object' ? url : options) || {};
472
+
473
+ return await cache({
474
+ expires: cache$1 || 0,
475
+ key: [blockchain, address, method, params, block],
476
+ call: async()=>{
477
+ if(supported$3.evm.includes(blockchain)) {
478
+ return requestEVM({ blockchain, address, api, method, params, block })
479
+ } else {
480
+ throw 'Unknown blockchain: ' + blockchain
481
+ }
482
+ }
483
+ })
484
+ };
485
+
105
486
  const sendTransaction$3 = async ({ transaction, wallet })=> {
106
487
  transaction = new Transaction(transaction);
107
488
  if((await wallet.connectedTo(transaction.blockchain)) == false) {
@@ -111,12 +492,14 @@
111
492
  throw({ code: 'WRONG_NETWORK' })
112
493
  }
113
494
  await transaction.prepare({ wallet });
495
+ let transactionCount = await request({ blockchain: transaction.blockchain, method: 'transactionCount', address: transaction.from });
496
+ transaction.nonce = transactionCount;
114
497
  let provider = new ethers.ethers.providers.Web3Provider(window.ethereum, 'any');
115
498
  let signer = provider.getSigner(0);
116
499
  await submit$3({ transaction, provider, signer }).then((sentTransaction)=>{
117
500
  if (sentTransaction) {
118
501
  transaction.id = sentTransaction.hash;
119
- transaction.nonce = sentTransaction.nonce;
502
+ transaction.nonce = sentTransaction.nonce || transactionCount;
120
503
  transaction.url = web3Blockchains.Blockchain.findByName(transaction.blockchain).explorerUrlFor({ transaction });
121
504
  if (transaction.sent) transaction.sent(transaction);
122
505
  sentTransaction.wait(1).then(() => {
@@ -523,6 +906,8 @@
523
906
  throw({ code: 'WRONG_NETWORK' })
524
907
  }
525
908
  await transaction.prepare({ wallet });
909
+ let transactionCount = await web3Client.request({ blockchain: transaction.blockchain, method: 'transactionCount', address: transaction.from });
910
+ transaction.nonce = transactionCount;
526
911
  await submit$1({ transaction, wallet }).then(async (tx)=>{
527
912
  if (tx) {
528
913
  let blockchain = web3Blockchains.Blockchain.findByName(transaction.blockchain);
@@ -530,7 +915,7 @@
530
915
  transaction.url = blockchain.explorerUrlFor({ transaction });
531
916
  if (transaction.sent) transaction.sent(transaction);
532
917
  let sentTransaction = await retrieveTransaction(tx, transaction.blockchain);
533
- transaction.nonce = sentTransaction.nonce;
918
+ transaction.nonce = sentTransaction.nonce || transactionCount;
534
919
  if(!sentTransaction) {
535
920
  transaction._failed = true;
536
921
  console.log('Error retrieving transaction');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@depay/web3-wallets-evm",
3
3
  "moduleName": "Web3Wallets",
4
- "version": "13.1.1",
4
+ "version": "13.1.2",
5
5
  "description": "One-Stop-Shop JavaScript library to integrate various web3 crypto wallets and multiple blockchains at once with a single interface.",
6
6
  "main": "dist/umd/index.evm.js",
7
7
  "module": "dist/esm/index.evm.js",
@@ -28,7 +28,7 @@
28
28
  "@depay/coinbase-wallet-sdk": "^1.1.0",
29
29
  "@depay/walletconnect-v1": "^1.7.10",
30
30
  "@depay/web3-blockchains": "^6.3.1",
31
- "@depay/web3-client-evm": "^10.2.1",
31
+ "@depay/web3-client-evm": "^10.3.0",
32
32
  "@depay/web3-constants": "^6.3.2",
33
33
  "ethers": "^5.7.1"
34
34
  },