@0xsequence/provider 1.10.15 → 2.0.0

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.
Files changed (31) hide show
  1. package/dist/0xsequence-provider.cjs.dev.js +656 -648
  2. package/dist/0xsequence-provider.cjs.prod.js +656 -648
  3. package/dist/0xsequence-provider.esm.js +660 -652
  4. package/dist/declarations/src/client.d.ts +7 -3
  5. package/dist/declarations/src/provider.d.ts +31 -22
  6. package/dist/declarations/src/signer.d.ts +15 -14
  7. package/dist/declarations/src/transports/base-provider-transport.d.ts +6 -2
  8. package/dist/declarations/src/transports/base-wallet-transport.d.ts +6 -2
  9. package/dist/declarations/src/transports/mux-transport/mux-message-provider.d.ts +5 -2
  10. package/dist/declarations/src/transports/wallet-request-handler.d.ts +7 -6
  11. package/dist/declarations/src/types.d.ts +6 -11
  12. package/dist/declarations/src/utils/index.d.ts +3 -3
  13. package/dist/declarations/src/utils.d.ts +7 -7
  14. package/package.json +12 -12
  15. package/src/client.ts +29 -51
  16. package/src/eip191exceptions.ts +2 -2
  17. package/src/extended.ts +5 -5
  18. package/src/init.ts +9 -10
  19. package/src/provider.ts +112 -66
  20. package/src/signer.ts +38 -43
  21. package/src/transactions.ts +4 -4
  22. package/src/transports/base-provider-transport.ts +19 -23
  23. package/src/transports/base-wallet-transport.ts +22 -13
  24. package/src/transports/mux-transport/mux-message-provider.ts +5 -6
  25. package/src/transports/proxy-transport/proxy-message-provider.ts +5 -2
  26. package/src/transports/wallet-request-handler.ts +91 -130
  27. package/src/transports/window-transport/window-message-handler.ts +15 -3
  28. package/src/transports/window-transport/window-message-provider.ts +1 -1
  29. package/src/types.ts +8 -11
  30. package/src/utils/index.ts +4 -4
  31. package/src/utils.ts +16 -18
@@ -1,13 +1,13 @@
1
1
  import { walletContracts } from '@0xsequence/abi';
2
- import { commons } from '@0xsequence/core';
3
- import { ethers, BigNumber } from 'ethers';
2
+ import { commons, VERSION } from '@0xsequence/core';
3
+ import { ethers } from 'ethers';
4
4
  import { EventEmitter2 } from 'eventemitter2';
5
- import { logger, encodeMessageDigest, encodeTypedDataDigest, sanitizeNumberString, sanitizeHost, sanitizeAlphanumeric, base64EncodeObject, base64DecodeObject } from '@0xsequence/utils';
6
- import { findSupportedNetwork, ChainId, findNetworkConfig, allNetworks, JsonRpcRouter, loggingProviderMiddleware, exceptionProviderMiddleware, CachedProvider, JsonRpcSender } from '@0xsequence/network';
5
+ import { logger, encodeMessageDigest, encodeTypedDataDigest, sanitizeNumberString, sanitizeHost, sanitizeAlphanumeric, base64EncodeObject, base64DecodeObject, toHexString } from '@0xsequence/utils';
6
+ import { findSupportedNetwork, ChainId, findNetworkConfig, allNetworks, JsonRpcProvider, loggingProviderMiddleware, exceptionProviderMiddleware, CachedProvider } from '@0xsequence/network';
7
7
  import { signAuthorization } from '@0xsequence/auth';
8
8
  import { isBrowser, Databeat } from '@databeat/tracker';
9
9
 
10
- const PROHIBITED_FUNCTIONS = new Map(['addHook(bytes4,address)', 'clearExtraImageHashes(bytes32[])', 'removeHook(bytes4)', 'setExtraImageHash(bytes32,uint256)', 'updateIPFSRoot(bytes32)', 'updateImageHash(bytes32)', 'updateImageHashAndIPFS(bytes32,bytes32)', 'updateImplementation(address)'].map(signature => [ethers.utils.keccak256(ethers.utils.toUtf8Bytes(signature)).slice(0, 10), signature]));
10
+ const PROHIBITED_FUNCTIONS = new Map(['addHook(bytes4,address)', 'clearExtraImageHashes(bytes32[])', 'removeHook(bytes4)', 'setExtraImageHash(bytes32,uint256)', 'updateIPFSRoot(bytes32)', 'updateImageHash(bytes32)', 'updateImageHashAndIPFS(bytes32,bytes32)', 'updateImplementation(address)'].map(signature => [ethers.id(signature).slice(0, 10), signature]));
11
11
  function validateTransactionRequest(wallet, transaction) {
12
12
  const transactions = commons.transaction.fromTransactionish(wallet, transaction);
13
13
  const unwound = commons.transaction.unwind(wallet, transactions);
@@ -16,7 +16,7 @@ function validateTransactionRequest(wallet, transaction) {
16
16
  function validateTransaction(wallet, transaction) {
17
17
  if (transaction.to.toLowerCase() === wallet.toLowerCase()) {
18
18
  if (transaction.data) {
19
- const data = ethers.utils.arrayify(transaction.data);
19
+ const data = ethers.getBytes(transaction.data);
20
20
  if (data.length >= 4 && !isCreateContractCall(data)) {
21
21
  throw new Error('self calls are forbidden');
22
22
  }
@@ -26,7 +26,7 @@ function validateTransaction(wallet, transaction) {
26
26
  throw new Error('delegate calls are forbidden');
27
27
  }
28
28
  if (transaction.data) {
29
- const data = ethers.utils.hexlify(transaction.data);
29
+ const data = ethers.hexlify(transaction.data);
30
30
  const selector = data.slice(0, 10);
31
31
  const signature = PROHIBITED_FUNCTIONS.get(selector);
32
32
  if (signature) {
@@ -36,7 +36,7 @@ function validateTransaction(wallet, transaction) {
36
36
  }
37
37
  }
38
38
  function isCreateContractCall(data) {
39
- const walletInterface = new ethers.utils.Interface(walletContracts.mainModule.abi);
39
+ const walletInterface = new ethers.Interface(walletContracts.mainModule.abi);
40
40
  try {
41
41
  walletInterface.decodeFunctionData('createContract', data);
42
42
  return true;
@@ -64,6 +64,8 @@ function isProviderTransport(transport) {
64
64
  return transport && typeof transport === 'object' && typeof transport.register === 'function' && typeof transport.unregister === 'function' && typeof transport.openWallet === 'function' && typeof transport.closeWallet === 'function' && typeof transport.isOpened === 'function' && typeof transport.isConnected === 'function' && typeof transport.on === 'function';
65
65
  }
66
66
 
67
+ // Older versions of sequence.js will require a JsonRpcResponse result type, but newer versions use raw EIP1193 results
68
+
67
69
  // ProviderMessageCallback is used to respond to ProviderMessage requests. The error
68
70
  // argument is for exceptions during the execution, and response is the response payload
69
71
  // which may contain the result or an error payload from the wallet.
@@ -121,8 +123,6 @@ const ErrSignedInRequired = new ProviderError('Wallet is not signed in. Connect
121
123
 
122
124
  // TODO: lets build some nice error handling tools, prob in /utils ...
123
125
 
124
- // This is required by viem, it expects a provider to have an EIP-1193 compliant `request` attribute.
125
-
126
126
  const PROVIDER_OPEN_TIMEOUT = 30000; // in ms
127
127
 
128
128
  let _messageIdx = 0;
@@ -143,42 +143,6 @@ class BaseProviderTransport {
143
143
  this._sessionId = void 0;
144
144
  this._init = void 0;
145
145
  this._registered = void 0;
146
- this.sendAsync = async function (request, callback, chainId) {
147
- // here, we receive the message from the dapp provider call
148
-
149
- if (_this.state === OpenState.CLOSED) {
150
- // flag the wallet to auto-close once user submits input. ie.
151
- // prompting to sign a message or transaction
152
- _this.confirmationOnly = true;
153
- }
154
-
155
- // open/focus the wallet.
156
- // automatically open the wallet when a provider request makes it here.
157
- //
158
- // NOTE: if we're not signed in, then the provider will fail, users must first connect+sign in.
159
- //
160
- // TODO: how does this behave with a session has expired?
161
- _this.openWallet(undefined, {
162
- type: 'jsonRpcRequest',
163
- method: request.method
164
- }, chainId);
165
-
166
- // send message request, await, and then execute callback after receiving the response
167
- try {
168
- if (!_this.isOpened()) {
169
- await _this.waitUntilOpened(); // will throw on timeout
170
- }
171
- const response = await _this.sendMessageRequest({
172
- idx: nextMessageIdx(),
173
- type: EventType.MESSAGE,
174
- data: request,
175
- chainId: chainId
176
- });
177
- callback(undefined, response.data);
178
- } catch (err) {
179
- callback(err);
180
- }
181
- };
182
146
  // sendMessageRequest sends a ProviderMessageRequest over the wire to the wallet
183
147
  this.sendMessageRequest = async function (message) {
184
148
  return new Promise((resolve, reject) => {
@@ -288,6 +252,36 @@ class BaseProviderTransport {
288
252
  const session = (_this$openPayload2 = this.openPayload) == null ? void 0 : _this$openPayload2.session;
289
253
  return this.registered && session !== undefined && !!session.accountAddress && session.accountAddress.length === 42 && !!session.networks && session.networks.length > 0;
290
254
  }
255
+ async request(request) {
256
+ if (this.state === OpenState.CLOSED) {
257
+ // flag the wallet to auto-close once user submits input. ie.
258
+ // prompting to sign a message or transaction
259
+ this.confirmationOnly = true;
260
+ }
261
+
262
+ // open/focus the wallet.
263
+ // automatically open the wallet when a provider request makes it here.
264
+ //
265
+ // NOTE: if we're not signed in, then the provider will fail, users must first connect+sign in.
266
+ //
267
+ // TODO: how does this behave with a session has expired?
268
+ this.openWallet(undefined, {
269
+ type: 'jsonRpcRequest',
270
+ method: request.method
271
+ }, request.chainId);
272
+ if (!this.isOpened()) {
273
+ await this.waitUntilOpened(); // will throw on timeout
274
+ }
275
+ const response = await this.sendMessageRequest({
276
+ idx: nextMessageIdx(),
277
+ type: EventType.MESSAGE,
278
+ data: request,
279
+ chainId: request.chainId,
280
+ clientVersion: VERSION
281
+ });
282
+ return response.data;
283
+ }
284
+
291
285
  // handleMessage will handle message received from the remote wallet
292
286
  handleMessage(message) {
293
287
  var _this2 = this;
@@ -309,7 +303,8 @@ class BaseProviderTransport {
309
303
  data: {
310
304
  sessionId: this._sessionId,
311
305
  nonce: nonce
312
- }
306
+ },
307
+ clientVersion: VERSION
313
308
  });
314
309
  }
315
310
  if (this._init !== InitState.OK) {
@@ -394,7 +389,7 @@ class BaseProviderTransport {
394
389
  };
395
390
  if (message.data && message.data.length > 0) {
396
391
  this.accountsChangedPayload = {
397
- accounts: [ethers.utils.getAddress(message.data[0])],
392
+ accounts: [ethers.getAddress(message.data[0])],
398
393
  origin: message.origin
399
394
  };
400
395
  this.events.emit('accountsChanged', this.accountsChangedPayload.accounts, this.accountsChangedPayload.origin);
@@ -499,7 +494,7 @@ const EIP_191_PREFIX_EXCEPTIONS = [
499
494
  const DCL_REGEX = /^Decentraland Login\nEphemeral address: 0x[a-fA-F0-9]{40}\nExpiration: (\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)((-(\d{2}):(\d{2})|Z)?)$/;
500
495
  function isDecentralandLoginMessage(bytes) {
501
496
  try {
502
- const stringified = ethers.utils.toUtf8String(bytes);
497
+ const stringified = ethers.toUtf8String(bytes);
503
498
  return DCL_REGEX.test(stringified);
504
499
  } catch (_unused) {
505
500
  return false;
@@ -509,7 +504,7 @@ function isDecentralandLoginMessage(bytes) {
509
504
  // try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
510
505
  // see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
511
506
  function isZeroExV3Order(bytes) {
512
- const abi = new ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi);
507
+ const abi = new ethers.Interface(ZeroXV3EIP1271OrderWithHashAbi);
513
508
  try {
514
509
  abi.decodeFunctionData('OrderWithHash', bytes);
515
510
  return true;
@@ -591,19 +586,19 @@ const ZeroXV3EIP1271OrderWithHashAbi = [{
591
586
  type: 'function'
592
587
  }];
593
588
 
594
- const eip191prefix = ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n');
589
+ const eip191prefix = ethers.toUtf8Bytes('\x19Ethereum Signed Message:\n');
595
590
  const messageToBytes = message => {
596
- if (ethers.utils.isBytesLike(message)) {
597
- return ethers.utils.arrayify(message);
591
+ if (ethers.isBytesLike(message)) {
592
+ return ethers.getBytes(message);
598
593
  }
599
- return ethers.utils.toUtf8Bytes(message);
594
+ return ethers.toUtf8Bytes(message);
600
595
  };
601
596
  const prefixEIP191Message = message => {
602
597
  const messageBytes = messageToBytes(message);
603
598
  if (messageIsExemptFromEIP191Prefix(messageBytes)) {
604
599
  return messageBytes;
605
600
  } else {
606
- return ethers.utils.concat([eip191prefix, ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
601
+ return ethers.getBytes(ethers.concat([eip191prefix, ethers.toUtf8Bytes(String(messageBytes.length)), messageBytes]));
607
602
  }
608
603
  };
609
604
  const trimEIP191Prefix = prefixedMessage => {
@@ -628,9 +623,9 @@ const trimEIP191Prefix = prefixedMessage => {
628
623
  let prefixCharLenght;
629
624
  let prefixAsNumber;
630
625
  try {
631
- prefixAsNumber = Number(ethers.utils.toUtf8String(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
626
+ prefixAsNumber = Number(ethers.toUtf8String(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
632
627
  } catch (_unused) {
633
- prefixAsNumber = Number(ethers.utils.hexlify(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
628
+ prefixAsNumber = Number(ethers.hexlify(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
634
629
  }
635
630
  if (prefixAsNumber > ethereumSignedMessagePartSlicedArray.length || !Number.isInteger(prefixAsNumber)) {
636
631
  prefixCharLenght = maxPrefixCharLength - 1;
@@ -745,9 +740,9 @@ function useBestStore() {
745
740
  async function resolveArrayProperties(object) {
746
741
  if (Array.isArray(object)) {
747
742
  // T must include array type
748
- return Promise.all(object.map(o => ethers.utils.resolveProperties(o)));
743
+ return Promise.all(object.map(o => ethers.resolveProperties(o)));
749
744
  }
750
- return ethers.utils.resolveProperties(object);
745
+ return ethers.resolveProperties(object);
751
746
  }
752
747
 
753
748
  const TRANSPORT_SESSION_LS_KEY = '@sequence.transportSession';
@@ -764,9 +759,6 @@ class BaseWalletTransport {
764
759
  // will auto-detect and set this value if it can. This is determined
765
760
  // as the parent app/window which opened the wallet.
766
761
  this.appOrigin = void 0;
767
- this.sendAsync = async function (request, callback, chainId) {
768
- throw new Error('abstract method');
769
- };
770
762
  this.handleMessage = async function (message) {
771
763
  const request = message;
772
764
 
@@ -1002,7 +994,7 @@ class BaseWalletTransport {
1002
994
  if (!networks || networks.length === 0) {
1003
995
  this.notifyChainChanged('0x0');
1004
996
  } else {
1005
- this.notifyChainChanged(ethers.utils.hexValue(networks.find(network => network.isDefaultChain).chainId));
997
+ this.notifyChainChanged(ethers.toQuantity(networks.find(network => network.isDefaultChain).chainId));
1006
998
  }
1007
999
  });
1008
1000
  this.walletRequestHandler.on('chainChanged', (chainIdHex, origin) => {
@@ -1026,6 +1018,9 @@ class BaseWalletTransport {
1026
1018
  unregister() {
1027
1019
  throw new Error('abstract method');
1028
1020
  }
1021
+ request(request) {
1022
+ throw new Error('abstract method');
1023
+ }
1029
1024
  sendMessage(message) {
1030
1025
  throw new Error('abstract method');
1031
1026
  }
@@ -1044,7 +1039,8 @@ class BaseWalletTransport {
1044
1039
  sessionId,
1045
1040
  session,
1046
1041
  error
1047
- }
1042
+ },
1043
+ clientVersion: VERSION
1048
1044
  });
1049
1045
  }
1050
1046
  notifyClose(error) {
@@ -1053,14 +1049,16 @@ class BaseWalletTransport {
1053
1049
  type: EventType.CLOSE,
1054
1050
  data: error ? {
1055
1051
  error
1056
- } : null
1052
+ } : null,
1053
+ clientVersion: VERSION
1057
1054
  });
1058
1055
  }
1059
1056
  notifyConnect(connectDetails) {
1060
1057
  this.sendMessage({
1061
1058
  idx: -1,
1062
1059
  type: EventType.CONNECT,
1063
- data: connectDetails
1060
+ data: connectDetails,
1061
+ clientVersion: VERSION
1064
1062
  });
1065
1063
  }
1066
1064
  notifyDisconnect(error, origin) {
@@ -1070,7 +1068,8 @@ class BaseWalletTransport {
1070
1068
  data: error ? {
1071
1069
  error
1072
1070
  } : null,
1073
- origin
1071
+ origin,
1072
+ clientVersion: VERSION
1074
1073
  });
1075
1074
  }
1076
1075
  notifyAccountsChanged(accounts, origin) {
@@ -1078,7 +1077,8 @@ class BaseWalletTransport {
1078
1077
  idx: -1,
1079
1078
  type: EventType.ACCOUNTS_CHANGED,
1080
1079
  data: accounts,
1081
- origin
1080
+ origin,
1081
+ clientVersion: VERSION
1082
1082
  });
1083
1083
  }
1084
1084
  notifyChainChanged(chainIdHex, origin) {
@@ -1086,21 +1086,24 @@ class BaseWalletTransport {
1086
1086
  idx: -1,
1087
1087
  type: EventType.CHAIN_CHANGED,
1088
1088
  data: chainIdHex,
1089
- origin
1089
+ origin,
1090
+ clientVersion: VERSION
1090
1091
  });
1091
1092
  }
1092
1093
  notifyNetworks(networks) {
1093
1094
  this.sendMessage({
1094
1095
  idx: -1,
1095
1096
  type: EventType.NETWORKS,
1096
- data: networks
1097
+ data: networks,
1098
+ clientVersion: VERSION
1097
1099
  });
1098
1100
  }
1099
1101
  notifyWalletContext(walletContext) {
1100
1102
  this.sendMessage({
1101
1103
  idx: -1,
1102
1104
  type: EventType.WALLET_CONTEXT,
1103
- data: walletContext
1105
+ data: walletContext,
1106
+ clientVersion: VERSION
1104
1107
  });
1105
1108
  }
1106
1109
  isValidInitAck(message) {
@@ -1171,7 +1174,8 @@ class BaseWalletTransport {
1171
1174
  type: EventType.INIT,
1172
1175
  data: {
1173
1176
  nonce: this._initNonce
1174
- }
1177
+ },
1178
+ clientVersion: VERSION
1175
1179
  });
1176
1180
  this._init = InitState.SENT_NONCE;
1177
1181
 
@@ -1270,7 +1274,8 @@ class ProxyMessageProvider extends BaseProviderTransport {
1270
1274
  intent,
1271
1275
  networkId,
1272
1276
  sessionId
1273
- }
1277
+ },
1278
+ clientVersion: VERSION
1274
1279
  });
1275
1280
  }
1276
1281
  };
@@ -1288,7 +1293,8 @@ class ProxyMessageProvider extends BaseProviderTransport {
1288
1293
  this.sendMessage({
1289
1294
  idx: -1,
1290
1295
  type: EventType.CLOSE,
1291
- data: null
1296
+ data: null,
1297
+ clientVersion: VERSION
1292
1298
  });
1293
1299
  this.close();
1294
1300
  }
@@ -1876,7 +1882,13 @@ class WindowMessageHandler extends BaseWalletTransport {
1876
1882
  // Wallet always expects json-rpc request messages from a dapp
1877
1883
  let request;
1878
1884
  try {
1879
- request = JSON.parse(event.data);
1885
+ request = JSON.parse(event.data, (key, value) => {
1886
+ // BigNumber compatibility with older versions of sequence.js
1887
+ if (isBigNumberSerialized(value)) {
1888
+ return BigInt(value.hex);
1889
+ }
1890
+ return value;
1891
+ });
1880
1892
  } catch (err) {
1881
1893
  // event is not a ProviderMessage JSON object, skip
1882
1894
  return;
@@ -1915,7 +1927,6 @@ class WindowMessageHandler extends BaseWalletTransport {
1915
1927
 
1916
1928
  // record open details (sessionId + default network) from the window url
1917
1929
  const {
1918
- pathname,
1919
1930
  search: rawParams
1920
1931
  } = new URL(windowHref || window.location.href);
1921
1932
  let session = this.getWindowTransportSession(rawParams);
@@ -1999,6 +2010,9 @@ class WindowMessageHandler extends BaseWalletTransport {
1999
2010
  }
2000
2011
  }
2001
2012
  }
2013
+ const isBigNumberSerialized = value => {
2014
+ return typeof value === 'object' && value.type === 'BigNumber' && ethers.isHexString(value.hex);
2015
+ };
2002
2016
 
2003
2017
  function isMuxTransportTemplate(obj) {
2004
2018
  return obj && typeof obj === 'object' && (obj.windowTransport && typeof obj.windowTransport === 'object' || obj.proxyTransport && typeof obj.proxyTransport === 'object' || obj.extensionTransport && typeof obj.extensionTransport === 'object' || obj.unrealTransport && typeof obj.unrealTransport === 'object') && (
@@ -2049,13 +2063,6 @@ class MuxMessageProvider {
2049
2063
  }
2050
2064
  this.messageProviders.forEach(m => m.openWallet(path, intent, networkId));
2051
2065
  };
2052
- this.sendAsync = async function (request, callback, chainId) {
2053
- if (_this.provider) {
2054
- _this.provider.sendAsync(request, callback, chainId);
2055
- return;
2056
- }
2057
- throw new Error('impossible state, wallet must be opened first');
2058
- };
2059
2066
  this.sendMessageRequest = async function (message) {
2060
2067
  if (_this.provider) {
2061
2068
  return _this.provider.sendMessageRequest(message);
@@ -2152,6 +2159,12 @@ class MuxMessageProvider {
2152
2159
  }
2153
2160
  return true;
2154
2161
  }
2162
+ request(request) {
2163
+ if (!this.provider) {
2164
+ throw new Error('impossible state, wallet must be opened first');
2165
+ }
2166
+ return this.provider.request(request);
2167
+ }
2155
2168
  sendMessage(message) {
2156
2169
  if (!message.idx || message.idx <= 0) {
2157
2170
  throw new Error('message idx is empty');
@@ -2186,7 +2199,7 @@ function fromExtended(transaction) {
2186
2199
 
2187
2200
  const SIGNER_READY_TIMEOUT = 10000;
2188
2201
  class WalletRequestHandler {
2189
- constructor(_account, prompter, networks) {
2202
+ constructor(account, prompter, networks) {
2190
2203
  var _this = this;
2191
2204
  // signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
2192
2205
  // value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
@@ -2219,417 +2232,6 @@ class WalletRequestHandler {
2219
2232
  }
2220
2233
  return promptConnectDetails;
2221
2234
  };
2222
- // sendAsync implements the JsonRpcHandler interface for sending JsonRpcRequests to the wallet
2223
- this.sendAsync = async function (request, callback, chainId) {
2224
- const response = {
2225
- jsonrpc: '2.0',
2226
- id: request.id,
2227
- result: null
2228
- };
2229
- await _this.getAccount();
2230
- try {
2231
- var _this$account;
2232
- // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
2233
- if ((!_this.account || _this.account === null) && !permittedJsonRpcMethods.includes(request.method)) {
2234
- // throw new Error(`not logged in. ${request.method} is unavailable`)
2235
- throw ErrSignedInRequired;
2236
- }
2237
-
2238
- // wallet account
2239
- const account = _this.account;
2240
- if (!account) throw new Error('WalletRequestHandler: wallet account is not configured');
2241
-
2242
- // fetch the provider for the specific chain, or undefined will select defaultChain
2243
- const provider = (_this$account = _this.account) == null ? void 0 : _this$account.providerFor(chainId != null ? chainId : _this.defaultChainId());
2244
- if (!provider) throw new Error(`WalletRequestHandler: wallet provider is not configured for chainId ${chainId}`);
2245
- const jsonRpcProvider = provider instanceof ethers.providers.JsonRpcProvider ? provider : undefined;
2246
- switch (request.method) {
2247
- case 'net_version':
2248
- {
2249
- if (!jsonRpcProvider) {
2250
- throw new Error(`Account provider doesn't support send method`);
2251
- }
2252
- const result = await jsonRpcProvider.send('net_version', []);
2253
- response.result = result;
2254
- break;
2255
- }
2256
- case 'eth_chainId':
2257
- {
2258
- if (!jsonRpcProvider) {
2259
- throw new Error(`Account provider doesn't support send method`);
2260
- }
2261
- const result = await jsonRpcProvider.send('eth_chainId', []);
2262
- response.result = result;
2263
- break;
2264
- }
2265
- case 'eth_accounts':
2266
- {
2267
- const walletAddress = account.address;
2268
- response.result = [walletAddress];
2269
- break;
2270
- }
2271
- case 'eth_getBalance':
2272
- {
2273
- const [accountAddress, blockTag] = request.params;
2274
- const walletBalance = await provider.getBalance(accountAddress, blockTag);
2275
- response.result = walletBalance.toHexString();
2276
- break;
2277
- }
2278
- case 'sequence_sign':
2279
- case 'personal_sign':
2280
- case 'eth_sign':
2281
- {
2282
- // note: message from json-rpc input is in hex format
2283
- let message;
2284
-
2285
- // there is a difference in the order of the params:
2286
- // sequence_sign, personal_sign: [data, address]
2287
- // eth_sign: [address, data]
2288
- switch (request.method) {
2289
- case 'sequence_sign':
2290
- case 'personal_sign':
2291
- {
2292
- const [data, _address] = request.params;
2293
- message = data;
2294
- break;
2295
- }
2296
- case 'eth_sign':
2297
- {
2298
- const [_address, data] = request.params;
2299
- message = data;
2300
- break;
2301
- }
2302
- }
2303
- let sig = '';
2304
-
2305
- // Message must be prefixed with "\x19Ethereum Signed Message:\n"
2306
- // as defined by EIP-191
2307
- const prefixedMessage = prefixEIP191Message(message);
2308
-
2309
- // TODO:
2310
- // if (process.env.TEST_MODE === 'true' && this.prompter === null) {
2311
- const sequenceVerified = request.method === 'sequence_sign';
2312
- if (_this.prompter === null) {
2313
- // prompter is null, so we'll sign from here
2314
- sig = await account.signMessage(prefixedMessage, chainId != null ? chainId : _this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
2315
- } else {
2316
- sig = await _this.prompter.promptSignMessage({
2317
- chainId: chainId,
2318
- message: prefixedMessage,
2319
- eip6492: sequenceVerified
2320
- }, _this.connectOptions);
2321
- }
2322
- if (sig && sig.length > 0) {
2323
- response.result = sig;
2324
- } else {
2325
- // The user has declined the request when value is null
2326
- throw new Error('declined by user');
2327
- }
2328
- break;
2329
- }
2330
- case 'sequence_signTypedData_v4':
2331
- case 'eth_signTypedData':
2332
- case 'eth_signTypedData_v4':
2333
- {
2334
- // note: signingAddress from json-rpc input is in hex format, and typedDataObject
2335
- // should be an object, but in some instances may be double string encoded
2336
- const [signingAddress, typedDataObject] = request.params;
2337
- let typedData = undefined;
2338
- if (typeof typedDataObject === 'string') {
2339
- try {
2340
- typedData = JSON.parse(typedDataObject);
2341
- } catch (e) {
2342
- console.warn('walletRequestHandler: error parsing typedData', e);
2343
- }
2344
- } else {
2345
- typedData = typedDataObject;
2346
- }
2347
- if (!typedData || !typedData.domain || !typedData.types || !typedData.message) {
2348
- throw new Error('invalid typedData object');
2349
- }
2350
- let sig = '';
2351
- const sequenceVerified = request.method === 'sequence_signTypedData_v4';
2352
- if (_this.prompter === null) {
2353
- // prompter is null, so we'll sign from here
2354
- sig = await account.signTypedData(typedData.domain, typedData.types, typedData.message, chainId != null ? chainId : _this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
2355
- } else {
2356
- sig = await _this.prompter.promptSignMessage({
2357
- chainId: chainId,
2358
- typedData: typedData,
2359
- eip6492: sequenceVerified
2360
- }, _this.connectOptions);
2361
- }
2362
- if (sig && sig.length > 0) {
2363
- response.result = sig;
2364
- } else {
2365
- // The user has declined the request when value is null
2366
- throw new Error('declined by user');
2367
- }
2368
- break;
2369
- }
2370
- case 'eth_sendTransaction':
2371
- {
2372
- // https://eth.wiki/json-rpc/API#eth_sendtransaction
2373
- const transactionParams = fromExtended(request.params[0]).map(tx => {
2374
- // eth_sendTransaction uses 'gas'
2375
- // ethers and sequence use 'gasLimit'
2376
- if ('gas' in tx && tx.gasLimit === undefined) {
2377
- tx.gasLimit = tx.gas;
2378
- delete tx.gas;
2379
- }
2380
- return tx;
2381
- });
2382
- validateTransactionRequest(account.address, transactionParams);
2383
- let txnHash = '';
2384
- if (_this.prompter === null) {
2385
- var _txnResponse$hash;
2386
- // prompter is null, so we'll send from here
2387
- const txnResponse = await account.sendTransaction(transactionParams, chainId != null ? chainId : _this.defaultChainId());
2388
- txnHash = (_txnResponse$hash = txnResponse == null ? void 0 : txnResponse.hash) != null ? _txnResponse$hash : '';
2389
- } else {
2390
- // prompt user to provide the response
2391
- txnHash = await _this.prompter.promptSendTransaction(transactionParams, chainId, _this.connectOptions);
2392
- }
2393
- if (txnHash) {
2394
- response.result = txnHash;
2395
- } else {
2396
- // The user has declined the request when value is null
2397
- throw new Error('declined by user');
2398
- }
2399
- break;
2400
- }
2401
- case 'eth_signTransaction':
2402
- {
2403
- // https://eth.wiki/json-rpc/API#eth_signTransaction
2404
- const [transaction] = request.params;
2405
- const sender = ethers.utils.getAddress(transaction.from);
2406
- if (sender !== account.address) {
2407
- throw new Error('sender address does not match wallet');
2408
- }
2409
- validateTransactionRequest(account.address, transaction);
2410
- if (_this.prompter === null) {
2411
- // The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
2412
- // this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
2413
- //
2414
- // TODO: verify serializing / transporting the SignedTransaction object works as expected, most likely however
2415
- // we will want to resolveProperties the big number values to hex strings
2416
- response.result = await account.signTransactions(transaction, chainId != null ? chainId : _this.defaultChainId());
2417
- } else {
2418
- response.result = await _this.prompter.promptSignTransaction(transaction, chainId, _this.connectOptions);
2419
- }
2420
- break;
2421
- }
2422
- case 'eth_sendRawTransaction':
2423
- {
2424
- // NOTE: we're not using a prompter here as the transaction is already signed
2425
- // and would have prompted the user upon signing.
2426
-
2427
- // https://eth.wiki/json-rpc/API#eth_sendRawTransaction
2428
- if (commons.transaction.isSignedTransactionBundle(request.params[0])) {
2429
- const txChainId = BigNumber.from(request.params[0].chainId).toNumber();
2430
- const tx = await account.relayer(txChainId).relay(request.params[0]);
2431
- response.result = tx.hash;
2432
- } else {
2433
- const tx = await provider.sendTransaction(request.params[0]);
2434
- response.result = tx.hash;
2435
- }
2436
- break;
2437
- }
2438
- case 'eth_getTransactionCount':
2439
- {
2440
- const address = ethers.utils.getAddress(request.params[0]);
2441
- const tag = request.params[1];
2442
-
2443
- // TODO: Maybe we should fetch this data from the relayer or from the reader
2444
- // but for now we keep it simple and just use the provider
2445
-
2446
- const count = await provider.getTransactionCount(address, tag);
2447
- response.result = ethers.BigNumber.from(count).toHexString();
2448
- break;
2449
- }
2450
- case 'eth_blockNumber':
2451
- {
2452
- response.result = await provider.getBlockNumber();
2453
- break;
2454
- }
2455
- case 'eth_getBlockByNumber':
2456
- {
2457
- response.result = await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
2458
- break;
2459
- }
2460
- case 'eth_getBlockByHash':
2461
- {
2462
- response.result = await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
2463
- break;
2464
- }
2465
- case 'eth_getTransactionByHash':
2466
- {
2467
- response.result = await provider.getTransaction(request.params[0]);
2468
- break;
2469
- }
2470
- case 'eth_call':
2471
- {
2472
- const [transactionObject, blockTag] = request.params;
2473
- response.result = await provider.call(transactionObject, blockTag);
2474
- break;
2475
- }
2476
- case 'eth_getCode':
2477
- {
2478
- const [contractAddress, blockTag] = request.params;
2479
- response.result = await provider.getCode(contractAddress, blockTag);
2480
- break;
2481
- }
2482
- case 'eth_estimateGas':
2483
- {
2484
- const [transactionObject] = request.params;
2485
- response.result = await provider.estimateGas(transactionObject);
2486
- break;
2487
- }
2488
- case 'eth_gasPrice':
2489
- {
2490
- const gasPrice = await provider.getGasPrice();
2491
- response.result = gasPrice.toHexString();
2492
- break;
2493
- }
2494
- case 'wallet_switchEthereumChain':
2495
- {
2496
- const [switchParams] = request.params;
2497
- if (!switchParams.chainId || switchParams.chainId.length === 0) {
2498
- throw new Error('invalid chainId');
2499
- }
2500
- const _chainId = ethers.BigNumber.from(switchParams.chainId);
2501
- _this.setDefaultChainId(_chainId.toNumber());
2502
- response.result = null; // success
2503
- break;
2504
- }
2505
-
2506
- // smart wallet method
2507
- case 'sequence_getWalletContext':
2508
- {
2509
- response.result = account.contexts;
2510
- break;
2511
- }
2512
-
2513
- // smart wallet method
2514
- case 'sequence_getWalletConfig':
2515
- {
2516
- const [_chainId2] = request.params;
2517
- if (_chainId2) {
2518
- response.result = [(await account.status(_chainId2)).onChain.config];
2519
- } else {
2520
- response.result = await Promise.all(account.networks.map(async function (network) {
2521
- const status = await account.status(network.chainId);
2522
- return status.onChain.config;
2523
- }));
2524
- }
2525
- break;
2526
- }
2527
-
2528
- // smart wallet method
2529
- case 'sequence_getWalletState':
2530
- {
2531
- const [_chainId3] = request.params;
2532
- // TODO: Add getWalletState to the Signer interface
2533
- if (_chainId3) {
2534
- response.result = [getLegacyWalletState(_chainId3, await account.status(_chainId3))];
2535
- } else {
2536
- response.result = await Promise.all(account.networks.map(async function (network) {
2537
- const status = await account.status(network.chainId);
2538
- return getLegacyWalletState(network.chainId, status);
2539
- }));
2540
- }
2541
- break;
2542
- }
2543
-
2544
- // smart wallet method
2545
- case 'sequence_getNetworks':
2546
- {
2547
- // NOTE: must ensure that the response result below returns clean serialized data, which is to omit
2548
- // the provider and relayer objects and only return the urls so can be reinstantiated on dapp side.
2549
- // This is handled by this.getNetworks() but noted here for future readers.
2550
- response.result = await _this.getNetworks(true);
2551
- break;
2552
- }
2553
- case 'sequence_isSequence':
2554
- {
2555
- response.result = true;
2556
- break;
2557
- }
2558
-
2559
- // smart wallet method
2560
- case 'sequence_updateConfig':
2561
- {
2562
- throw new Error('sequence_updateConfig method is not allowed from a dapp');
2563
- // NOTE: method is disabled as we don't need a dapp to request to update a config.
2564
- // However, if we ever want this, we can enable it but must also use the prompter
2565
- // for confirmation.
2566
- //
2567
- // const [newConfig] = request.params
2568
- // response.result = await signer.updateConfig(newConfig)
2569
- break;
2570
- }
2571
-
2572
- // smart wallet method
2573
- case 'sequence_publishConfig':
2574
- {
2575
- throw new Error('sequence_publishConfig method is not allowed from a dapp');
2576
- break;
2577
- }
2578
-
2579
- // relayer method
2580
- case 'sequence_gasRefundOptions':
2581
- {
2582
- // TODO
2583
- break;
2584
- }
2585
-
2586
- // relayer method
2587
- case 'sequence_getNonce':
2588
- {
2589
- // TODO
2590
- break;
2591
- }
2592
-
2593
- // relayer method
2594
- case 'sequence_relay':
2595
- {
2596
- // TODO
2597
- break;
2598
- }
2599
-
2600
- // set default network of wallet
2601
- case 'sequence_setDefaultNetwork':
2602
- {
2603
- const [defaultChainId] = request.params;
2604
- if (!defaultChainId) {
2605
- throw new Error('invalid request, method argument defaultChainId cannot be empty');
2606
- }
2607
- _this.setDefaultChainId(defaultChainId);
2608
- response.result = await _this.getNetworks(true);
2609
- break;
2610
- }
2611
- default:
2612
- {
2613
- if (!jsonRpcProvider) {
2614
- throw new Error(`Account provider doesn't support send method`);
2615
- }
2616
-
2617
- // NOTE: provider here will be chain-bound if chainId is provided
2618
- const providerResponse = await jsonRpcProvider.send(request.method, request.params);
2619
- response.result = providerResponse;
2620
- }
2621
- }
2622
- } catch (err) {
2623
- logger.error(err);
2624
-
2625
- // See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md#rpc-errors
2626
- response.result = null;
2627
- response.error = _extends({}, new Error(err), {
2628
- code: 4001
2629
- });
2630
- }
2631
- callback(undefined, response);
2632
- };
2633
2235
  this.isSignedIn = async function () {
2634
2236
  await _this.signerReady();
2635
2237
  return !!_this.account;
@@ -2641,7 +2243,7 @@ class WalletRequestHandler {
2641
2243
  }
2642
2244
  return _this.account;
2643
2245
  };
2644
- this.account = _account;
2246
+ this.account = account;
2645
2247
  this.prompter = prompter;
2646
2248
  this.networks = networks;
2647
2249
  }
@@ -2725,7 +2327,7 @@ class WalletRequestHandler {
2725
2327
  const chainId = findSupportedNetwork(networkId).chainId;
2726
2328
  const connectDetails = {
2727
2329
  connected: true,
2728
- chainId: ethers.utils.hexValue(chainId)
2330
+ chainId: ethers.toQuantity(chainId)
2729
2331
  };
2730
2332
  if (options && options.authorize) {
2731
2333
  // Perform ethauth eip712 request and construct the ConnectDetails response
@@ -2760,20 +2362,415 @@ class WalletRequestHandler {
2760
2362
  // sendMessageRequest will unwrap the ProviderMessageRequest and send it to the JsonRpcHandler
2761
2363
  // (aka, the signer in this instance) and then responds with a wrapped response of
2762
2364
  // ProviderMessageResponse to be sent over the transport
2763
- sendMessageRequest(message) {
2764
- return new Promise(resolve => {
2765
- this.sendAsync(message.data, (error, response) => {
2766
- // TODO: if response includes data.error, why do we need a separate error argument here?
2365
+ async sendMessageRequest(message) {
2366
+ var _message$clientVersio;
2367
+ // Older versions of the client require the response to be jsonrpc wrapped
2368
+ const majorVersion = Number(((_message$clientVersio = message.clientVersion) == null ? void 0 : _message$clientVersio.split('.')[0]) || '0');
2369
+ const isJsonRpcResponse = majorVersion < 2;
2370
+ const jsonRpcResponse = {
2371
+ id: message.data.id,
2372
+ jsonrpc: '2.0',
2373
+ result: null,
2374
+ error: undefined
2375
+ };
2376
+ try {
2377
+ const result = await this.request({
2378
+ method: message.data.method,
2379
+ params: message.data.params,
2380
+ chainId: message.chainId
2381
+ });
2382
+ return _extends({}, message, {
2383
+ data: isJsonRpcResponse ? _extends({}, jsonRpcResponse, {
2384
+ result
2385
+ }) : result
2386
+ });
2387
+ } catch (error) {
2388
+ return _extends({}, message, {
2389
+ data: isJsonRpcResponse ? _extends({}, jsonRpcResponse, {
2390
+ error
2391
+ }) : error
2392
+ });
2393
+ }
2394
+ }
2395
+ async request(request) {
2396
+ await this.getAccount();
2397
+ try {
2398
+ var _this$account, _request$chainId;
2399
+ // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
2400
+ if ((!this.account || this.account === null) && !permittedJsonRpcMethods.includes(request.method)) {
2401
+ // throw new Error(`not logged in. ${request.method} is unavailable`)
2402
+ throw ErrSignedInRequired;
2403
+ }
2767
2404
 
2768
- const responseMessage = _extends({}, message, {
2769
- data: response
2770
- });
2405
+ // wallet account
2406
+ const account = this.account;
2407
+ if (!account) {
2408
+ throw new Error('WalletRequestHandler: wallet account is not configured');
2409
+ }
2771
2410
 
2772
- // NOTE: we always resolve here, are the sendAsync call will wrap any exceptions
2773
- // in the error field of the response to ensure we send back to the user
2774
- resolve(responseMessage);
2775
- }, message.chainId);
2776
- });
2411
+ // fetch the provider for the specific chain, or undefined will select defaultChain
2412
+ const provider = (_this$account = this.account) == null ? void 0 : _this$account.providerFor((_request$chainId = request.chainId) != null ? _request$chainId : this.defaultChainId());
2413
+ if (!provider) {
2414
+ throw new Error(`WalletRequestHandler: wallet provider is not configured for chainId ${request.chainId}`);
2415
+ }
2416
+ const jsonRpcProvider = provider instanceof ethers.JsonRpcProvider ? provider : undefined;
2417
+ switch (request.method) {
2418
+ case 'net_version':
2419
+ {
2420
+ if (!jsonRpcProvider) {
2421
+ throw new Error(`Account provider doesn't support send method`);
2422
+ }
2423
+ return await jsonRpcProvider.send('net_version', []);
2424
+ }
2425
+ case 'eth_chainId':
2426
+ {
2427
+ if (!jsonRpcProvider) {
2428
+ throw new Error(`Account provider doesn't support send method`);
2429
+ }
2430
+ return await jsonRpcProvider.send('eth_chainId', []);
2431
+ }
2432
+ case 'eth_accounts':
2433
+ {
2434
+ return [account.address];
2435
+ }
2436
+ case 'eth_getBalance':
2437
+ {
2438
+ const [accountAddress, blockTag] = request.params;
2439
+ const walletBalance = await provider.getBalance(accountAddress, blockTag);
2440
+ return toHexString(walletBalance);
2441
+ }
2442
+ case 'sequence_sign':
2443
+ case 'personal_sign':
2444
+ case 'eth_sign':
2445
+ {
2446
+ // note: message from json-rpc input is in hex format
2447
+ let message;
2448
+
2449
+ // there is a difference in the order of the params:
2450
+ // sequence_sign, personal_sign: [data, address]
2451
+ // eth_sign: [address, data]
2452
+ switch (request.method) {
2453
+ case 'sequence_sign':
2454
+ case 'personal_sign':
2455
+ {
2456
+ const [data, _address] = request.params;
2457
+ message = data;
2458
+ break;
2459
+ }
2460
+ case 'eth_sign':
2461
+ {
2462
+ const [_address, data] = request.params;
2463
+ message = data;
2464
+ break;
2465
+ }
2466
+ }
2467
+ let sig = '';
2468
+
2469
+ // Message must be prefixed with "\x19Ethereum Signed Message:\n"
2470
+ // as defined by EIP-191
2471
+ const prefixedMessage = prefixEIP191Message(message);
2472
+
2473
+ // TODO:
2474
+ // if (process.env.TEST_MODE === 'true' && this.prompter === null) {
2475
+ const sequenceVerified = request.method === 'sequence_sign';
2476
+ if (this.prompter === null) {
2477
+ var _request$chainId2;
2478
+ // prompter is null, so we'll sign from here
2479
+ sig = await account.signMessage(prefixedMessage, (_request$chainId2 = request.chainId) != null ? _request$chainId2 : this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
2480
+ } else {
2481
+ sig = await this.prompter.promptSignMessage({
2482
+ chainId: request.chainId,
2483
+ message: ethers.getBytes(prefixedMessage),
2484
+ eip6492: sequenceVerified
2485
+ }, this.connectOptions);
2486
+ }
2487
+ if (sig && sig.length > 0) {
2488
+ return sig;
2489
+ } else {
2490
+ // The user has declined the request when value is null
2491
+ throw new Error('declined by user');
2492
+ }
2493
+ }
2494
+ case 'sequence_signTypedData_v4':
2495
+ case 'eth_signTypedData':
2496
+ case 'eth_signTypedData_v4':
2497
+ {
2498
+ // note: signingAddress from json-rpc input is in hex format, and typedDataObject
2499
+ // should be an object, but in some instances may be double string encoded
2500
+ const [signingAddress, typedDataObject] = request.params;
2501
+ let typedData = undefined;
2502
+ if (typeof typedDataObject === 'string') {
2503
+ try {
2504
+ typedData = JSON.parse(typedDataObject);
2505
+ } catch (e) {
2506
+ console.warn('walletRequestHandler: error parsing typedData', e);
2507
+ }
2508
+ } else {
2509
+ typedData = typedDataObject;
2510
+ }
2511
+ if (!typedData || !typedData.domain || !typedData.types || !typedData.message) {
2512
+ throw new Error('invalid typedData object');
2513
+ }
2514
+ let sig = '';
2515
+ const sequenceVerified = request.method === 'sequence_signTypedData_v4';
2516
+ if (this.prompter === null) {
2517
+ var _request$chainId3;
2518
+ // prompter is null, so we'll sign from here
2519
+ sig = await account.signTypedData(typedData.domain, typedData.types, typedData.message, (_request$chainId3 = request.chainId) != null ? _request$chainId3 : this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
2520
+ } else {
2521
+ sig = await this.prompter.promptSignMessage({
2522
+ chainId: request.chainId,
2523
+ typedData: typedData,
2524
+ eip6492: sequenceVerified
2525
+ }, this.connectOptions);
2526
+ }
2527
+ if (sig && sig.length > 0) {
2528
+ return sig;
2529
+ } else {
2530
+ // The user has declined the request when value is null
2531
+ throw new Error('declined by user');
2532
+ }
2533
+ }
2534
+ case 'eth_sendTransaction':
2535
+ {
2536
+ // https://eth.wiki/json-rpc/API#eth_sendtransaction
2537
+ const transactionParams = fromExtended(request.params[0]).map(tx => {
2538
+ // eth_sendTransaction uses 'gas'
2539
+ // ethers and sequence use 'gasLimit'
2540
+ if ('gas' in tx && tx.gasLimit === undefined) {
2541
+ tx.gasLimit = tx.gas;
2542
+ delete tx.gas;
2543
+ }
2544
+ return tx;
2545
+ });
2546
+ validateTransactionRequest(account.address, transactionParams);
2547
+ let txnHash = '';
2548
+ if (this.prompter === null) {
2549
+ var _request$chainId4, _txnResponse$hash;
2550
+ // prompter is null, so we'll send from here
2551
+ const txnResponse = await account.sendTransaction(transactionParams, (_request$chainId4 = request.chainId) != null ? _request$chainId4 : this.defaultChainId());
2552
+ txnHash = (_txnResponse$hash = txnResponse == null ? void 0 : txnResponse.hash) != null ? _txnResponse$hash : '';
2553
+ } else {
2554
+ // prompt user to provide the response
2555
+ txnHash = await this.prompter.promptSendTransaction(transactionParams, request.chainId, this.connectOptions);
2556
+ }
2557
+ if (txnHash) {
2558
+ return txnHash;
2559
+ } else {
2560
+ // The user has declined the request when value is null
2561
+ throw new Error('declined by user');
2562
+ }
2563
+ }
2564
+ case 'eth_signTransaction':
2565
+ {
2566
+ // https://eth.wiki/json-rpc/API#eth_signTransaction
2567
+ const [transaction] = request.params;
2568
+ const sender = ethers.getAddress(transaction.from);
2569
+ if (sender !== account.address) {
2570
+ throw new Error('sender address does not match wallet');
2571
+ }
2572
+ validateTransactionRequest(account.address, transaction);
2573
+ if (this.prompter === null) {
2574
+ var _request$chainId5;
2575
+ // The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
2576
+ // this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
2577
+ //
2578
+ // TODO: verify serializing / transporting the SignedTransaction object works as expected, most likely however
2579
+ // we will want to resolveProperties the big number values to hex strings
2580
+ return await account.signTransactions(transaction, (_request$chainId5 = request.chainId) != null ? _request$chainId5 : this.defaultChainId());
2581
+ } else {
2582
+ return await this.prompter.promptSignTransaction(transaction, request.chainId, this.connectOptions);
2583
+ }
2584
+ }
2585
+ case 'eth_sendRawTransaction':
2586
+ {
2587
+ // NOTE: we're not using a prompter here as the transaction is already signed
2588
+ // and would have prompted the user upon signing.
2589
+
2590
+ // https://eth.wiki/json-rpc/API#eth_sendRawTransaction
2591
+ if (commons.transaction.isSignedTransactionBundle(request.params[0])) {
2592
+ const txChainId = Number(request.params[0].chainId);
2593
+ const tx = await account.relayer(txChainId).relay(request.params[0]);
2594
+ return tx.hash;
2595
+ } else {
2596
+ const tx = await provider.broadcastTransaction(request.params[0]);
2597
+ return tx.hash;
2598
+ }
2599
+ }
2600
+ case 'eth_getTransactionCount':
2601
+ {
2602
+ const address = ethers.getAddress(request.params[0]);
2603
+ const tag = request.params[1];
2604
+
2605
+ // TODO: Maybe we should fetch this data from the relayer or from the reader
2606
+ // but for now we keep it simple and just use the provider
2607
+
2608
+ const count = await provider.getTransactionCount(address, tag);
2609
+ return toHexString(BigInt(count));
2610
+ }
2611
+ case 'eth_blockNumber':
2612
+ {
2613
+ return await provider.getBlockNumber();
2614
+ }
2615
+ case 'eth_getBlockByNumber':
2616
+ {
2617
+ return await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
2618
+ }
2619
+ case 'eth_getBlockByHash':
2620
+ {
2621
+ return await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
2622
+ }
2623
+ case 'eth_getTransactionByHash':
2624
+ {
2625
+ return await provider.getTransaction(request.params[0]);
2626
+ }
2627
+ case 'eth_call':
2628
+ {
2629
+ const [transactionObject, blockTag] = request.params;
2630
+ return await provider.call(_extends({}, transactionObject, {
2631
+ blockTag
2632
+ }));
2633
+ }
2634
+ case 'eth_getCode':
2635
+ {
2636
+ const [contractAddress, blockTag] = request.params;
2637
+ return await provider.getCode(contractAddress, blockTag);
2638
+ }
2639
+ case 'eth_estimateGas':
2640
+ {
2641
+ const [transactionObject] = request.params;
2642
+ return await provider.estimateGas(transactionObject);
2643
+ }
2644
+ case 'eth_gasPrice':
2645
+ {
2646
+ const feeData = await provider.getFeeData();
2647
+ return feeData.gasPrice === null ? null : toHexString(feeData.gasPrice);
2648
+ }
2649
+ case 'wallet_switchEthereumChain':
2650
+ {
2651
+ const [switchParams] = request.params;
2652
+ if (!switchParams.chainId || switchParams.chainId.length === 0) {
2653
+ throw new Error('invalid chainId');
2654
+ }
2655
+ const chainId = BigInt(switchParams.chainId);
2656
+ this.setDefaultChainId(Number(chainId));
2657
+ return null; // success
2658
+ }
2659
+
2660
+ // smart wallet method
2661
+ case 'sequence_getWalletContext':
2662
+ {
2663
+ return account.contexts;
2664
+ }
2665
+
2666
+ // smart wallet method
2667
+ case 'sequence_getWalletConfig':
2668
+ {
2669
+ const [chainId] = request.params;
2670
+ if (chainId) {
2671
+ return [(await account.status(chainId)).onChain.config];
2672
+ } else {
2673
+ return await Promise.all(account.networks.map(async function (network) {
2674
+ const status = await account.status(network.chainId);
2675
+ return status.onChain.config;
2676
+ }));
2677
+ }
2678
+ }
2679
+
2680
+ // smart wallet method
2681
+ case 'sequence_getWalletState':
2682
+ {
2683
+ const [chainId] = request.params;
2684
+ // TODO: Add getWalletState to the Signer interface
2685
+ if (chainId) {
2686
+ return [getLegacyWalletState(chainId, await account.status(chainId))];
2687
+ } else {
2688
+ return await Promise.all(account.networks.map(async function (network) {
2689
+ const status = await account.status(network.chainId);
2690
+ return getLegacyWalletState(network.chainId, status);
2691
+ }));
2692
+ }
2693
+ }
2694
+
2695
+ // smart wallet method
2696
+ case 'sequence_getNetworks':
2697
+ {
2698
+ // NOTE: must ensure that the response result below returns clean serialized data, which is to omit
2699
+ // the provider and relayer objects and only return the urls so can be reinstantiated on dapp side.
2700
+ // This is handled by this.getNetworks() but noted here for future readers.
2701
+ return await this.getNetworks(true);
2702
+ }
2703
+ case 'sequence_isSequence':
2704
+ {
2705
+ return true;
2706
+ }
2707
+
2708
+ // smart wallet method
2709
+ case 'sequence_updateConfig':
2710
+ {
2711
+ throw new Error('sequence_updateConfig method is not allowed from a dapp');
2712
+ // NOTE: method is disabled as we don't need a dapp to request to update a config.
2713
+ // However, if we ever want this, we can enable it but must also use the prompter
2714
+ // for confirmation.
2715
+ //
2716
+ // const [newConfig] = request.params
2717
+ // return await signer.updateConfig(newConfig)
2718
+ }
2719
+
2720
+ // smart wallet method
2721
+ case 'sequence_publishConfig':
2722
+ {
2723
+ throw new Error('sequence_publishConfig method is not allowed from a dapp');
2724
+ }
2725
+
2726
+ // relayer method
2727
+ case 'sequence_gasRefundOptions':
2728
+ {
2729
+ // TODO
2730
+ break;
2731
+ }
2732
+
2733
+ // relayer method
2734
+ case 'sequence_getNonce':
2735
+ {
2736
+ // TODO
2737
+ break;
2738
+ }
2739
+
2740
+ // relayer method
2741
+ case 'sequence_relay':
2742
+ {
2743
+ // TODO
2744
+ break;
2745
+ }
2746
+
2747
+ // set default network of wallet
2748
+ case 'sequence_setDefaultNetwork':
2749
+ {
2750
+ const [defaultChainId] = request.params;
2751
+ if (!defaultChainId) {
2752
+ throw new Error('invalid request, method argument defaultChainId cannot be empty');
2753
+ }
2754
+ this.setDefaultChainId(defaultChainId);
2755
+ return await this.getNetworks(true);
2756
+ }
2757
+ default:
2758
+ {
2759
+ if (!jsonRpcProvider) {
2760
+ throw new Error(`Account provider doesn't support send method`);
2761
+ }
2762
+
2763
+ // NOTE: provider here will be chain-bound if chainId is provided
2764
+ return await jsonRpcProvider.send(request.method, request.params);
2765
+ }
2766
+ }
2767
+ } catch (err) {
2768
+ logger.error(err);
2769
+ throw {
2770
+ message: err == null ? void 0 : err.message,
2771
+ code: 4001
2772
+ };
2773
+ }
2777
2774
  }
2778
2775
  on(event, fn) {
2779
2776
  this.events.on(event, fn);
@@ -2861,7 +2858,7 @@ class WalletRequestHandler {
2861
2858
  this.events.emit('disconnect', undefined, origin);
2862
2859
  }
2863
2860
  notifyChainChanged(chainId, origin) {
2864
- this.events.emit('chainChanged', ethers.utils.hexValue(chainId), origin);
2861
+ this.events.emit('chainChanged', ethers.toQuantity(chainId), origin);
2865
2862
  }
2866
2863
  async notifyNetworks(networks) {
2867
2864
  const n = networks || (await this.getNetworks(true));
@@ -2869,7 +2866,7 @@ class WalletRequestHandler {
2869
2866
  if (n.length > 0) {
2870
2867
  const defaultNetwork = n.find(network => network.chainId === this.defaultChainId());
2871
2868
  if (defaultNetwork) {
2872
- this.events.emit('chainChanged', ethers.utils.hexValue(defaultNetwork.chainId));
2869
+ this.events.emit('chainChanged', ethers.toQuantity(defaultNetwork.chainId));
2873
2870
  }
2874
2871
  } else {
2875
2872
  this.events.emit('chainChanged', '0x0');
@@ -2938,6 +2935,19 @@ function getLegacyWalletState(chainId, status) {
2938
2935
  }
2939
2936
  const permittedJsonRpcMethods = ['net_version', 'eth_chainId', 'eth_getBalance', 'eth_getTransactionCount', 'eth_blockNumber', 'eth_getBlockByNumber', 'eth_getBlockByHash', 'eth_getTransactionByHash', 'eth_getCode', 'eth_estimateGas', 'eth_gasPrice', 'sequence_getWalletContext', 'sequence_getNetworks', 'sequence_setDefaultNetwork'];
2940
2937
 
2938
+ function _objectWithoutPropertiesLoose(source, excluded) {
2939
+ if (source == null) return {};
2940
+ var target = {};
2941
+ var sourceKeys = Object.keys(source);
2942
+ var key, i;
2943
+ for (i = 0; i < sourceKeys.length; i++) {
2944
+ key = sourceKeys[i];
2945
+ if (excluded.indexOf(key) >= 0) continue;
2946
+ target[key] = source[key];
2947
+ }
2948
+ return target;
2949
+ }
2950
+
2941
2951
  class SequenceSigner {
2942
2952
  get utils() {
2943
2953
  return this.provider.utils;
@@ -2946,7 +2956,6 @@ class SequenceSigner {
2946
2956
  this.client = client;
2947
2957
  this.provider = provider;
2948
2958
  this.singleNetworkSigners = {};
2949
- this._isSigner = true;
2950
2959
  this._isSequenceSigner = true;
2951
2960
  }
2952
2961
  async getAddress() {
@@ -3016,12 +3025,17 @@ class SequenceSigner {
3016
3025
  });
3017
3026
  const provider = this.getProvider(chainId);
3018
3027
  try {
3019
- return await ethers.utils.poll(async function () {
3020
- const tx = await provider.getTransaction(txHash);
3021
- return tx ? provider._wrapTransaction(tx, txHash) : undefined;
3022
- }, {
3023
- onceBlock: provider
3028
+ const result = await new Promise(resolve => {
3029
+ const check = async function check() {
3030
+ const tx = await provider.getTransaction(txHash);
3031
+ if (tx !== null) {
3032
+ return resolve(tx);
3033
+ }
3034
+ await provider.once('block', check);
3035
+ };
3036
+ check();
3024
3037
  });
3038
+ return result;
3025
3039
  } catch (err) {
3026
3040
  err.transactionHash = txHash;
3027
3041
  throw err;
@@ -3043,15 +3057,12 @@ class SequenceSigner {
3043
3057
  async estimateGas(transaction, optionals) {
3044
3058
  return this.getProvider(optionals == null ? void 0 : optionals.chainId).estimateGas(transaction);
3045
3059
  }
3046
- async call(transaction, blockTag, optionals) {
3047
- return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction, blockTag);
3060
+ async call(transaction, optionals) {
3061
+ return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction);
3048
3062
  }
3049
3063
  getChainId() {
3050
3064
  return Promise.resolve(this.client.getChainId());
3051
3065
  }
3052
- async getGasPrice(optionals) {
3053
- return this.getProvider(optionals == null ? void 0 : optionals.chainId).getGasPrice();
3054
- }
3055
3066
  async getFeeData(optionals) {
3056
3067
  return this.getProvider(optionals == null ? void 0 : optionals.chainId).getFeeData();
3057
3068
  }
@@ -3059,7 +3070,7 @@ class SequenceSigner {
3059
3070
  const res = await this.provider.resolveName(name);
3060
3071
 
3061
3072
  // For some reason ethers.Signer expects this to return `string`
3062
- // but ethers.providers.Provider expects this to return `string | null`.
3073
+ // but ethers.Provider expects this to return `string | null`.
3063
3074
  // The signer doesn't have any other source of information, so we'll
3064
3075
  // fail if the provider doesn't return a result.
3065
3076
  if (res === null) {
@@ -3070,6 +3081,12 @@ class SequenceSigner {
3070
3081
  _checkProvider(_operation) {
3071
3082
  // We always have a provider, so this is a noop
3072
3083
  }
3084
+ getNonce(_blockTag) {
3085
+ throw new Error('SequenceSigner does not support getNonce');
3086
+ }
3087
+ populateCall(_transaction) {
3088
+ throw new Error('SequenceSigner does not support populateCall');
3089
+ }
3073
3090
  populateTransaction(_transaction) {
3074
3091
  throw new Error('SequenceSigner does not support populateTransaction');
3075
3092
  }
@@ -3207,31 +3224,43 @@ class WalletUtils {
3207
3224
  // recoverAddress()
3208
3225
  }
3209
3226
 
3210
- class SequenceProvider extends ethers.providers.BaseProvider {
3211
- constructor(client, providerFor, networks = allNetworks) {
3227
+ const _excluded = ["method"];
3228
+ const EIP1193EventTypes = ['connect', 'disconnect', 'chainChanged', 'accountsChanged'];
3229
+ class SequenceProvider extends ethers.AbstractProvider {
3230
+ constructor(client, providerFor, networks = allNetworks, options) {
3212
3231
  // We support a lot of networks
3213
3232
  // but we start with the default one
3214
- super(client.getChainId());
3233
+ super(client.getChainId(), options);
3215
3234
 
3216
3235
  // Emit events as defined by EIP-1193
3217
3236
  this.client = client;
3218
3237
  this.providerFor = providerFor;
3219
3238
  this.networks = networks;
3239
+ this.options = options;
3220
3240
  this.singleNetworkProviders = {};
3221
3241
  this._isSequenceProvider = true;
3222
3242
  this.utils = void 0;
3223
3243
  this.signer = void 0;
3244
+ this.eip1193EventListeners = new Map();
3224
3245
  client.onConnect(details => {
3225
- this.emit('connect', details);
3246
+ var _this$eip1193EventLis;
3247
+ //this.emit('connect', details)
3248
+ (_this$eip1193EventLis = this.eip1193EventListeners.get('connect')) == null || _this$eip1193EventLis.forEach(listener => listener(details));
3226
3249
  });
3227
3250
  client.onDisconnect(error => {
3228
- this.emit('disconnect', error);
3251
+ var _this$eip1193EventLis2;
3252
+ //this.emit('disconnect', error)
3253
+ (_this$eip1193EventLis2 = this.eip1193EventListeners.get('disconnect')) == null || _this$eip1193EventLis2.forEach(listener => listener(error));
3229
3254
  });
3230
3255
  client.onDefaultChainIdChanged(chainId => {
3231
- this.emit('chainChanged', chainId);
3256
+ var _this$eip1193EventLis3;
3257
+ //this.emit('chainChanged', chainId)
3258
+ (_this$eip1193EventLis3 = this.eip1193EventListeners.get('chainChanged')) == null || _this$eip1193EventLis3.forEach(listener => listener(chainId));
3232
3259
  });
3233
3260
  client.onAccountsChanged(accounts => {
3234
- this.emit('accountsChanged', accounts);
3261
+ var _this$eip1193EventLis4;
3262
+ //this.emit('accountsChanged', accounts)
3263
+ (_this$eip1193EventLis4 = this.eip1193EventListeners.get('accountsChanged')) == null || _this$eip1193EventLis4.forEach(listener => listener(accounts));
3235
3264
  });
3236
3265
 
3237
3266
  // NOTICE: We don't emit 'open' and 'close' events
@@ -3248,6 +3277,29 @@ class SequenceProvider extends ethers.providers.BaseProvider {
3248
3277
  // Create a utils instance
3249
3278
  this.utils = new WalletUtils(this.signer);
3250
3279
  }
3280
+ async on(event, listener) {
3281
+ if (EIP1193EventTypes.includes(event)) {
3282
+ const listeners = this.eip1193EventListeners.get(event) || new Set();
3283
+ listeners.add(listener);
3284
+ this.eip1193EventListeners.set(event, listeners);
3285
+ return this;
3286
+ }
3287
+ return super.on(event, listener);
3288
+ }
3289
+ async off(event, listener) {
3290
+ if (EIP1193EventTypes.includes(event)) {
3291
+ const listeners = this.eip1193EventListeners.get(event);
3292
+ if (listeners) {
3293
+ if (listener) {
3294
+ listeners.delete(listener);
3295
+ } else {
3296
+ listeners.clear();
3297
+ }
3298
+ }
3299
+ return this;
3300
+ }
3301
+ return super.off(event, listener);
3302
+ }
3251
3303
  getSigner(chainId) {
3252
3304
  return this.signer.getSigner(chainId);
3253
3305
  }
@@ -3340,7 +3392,7 @@ class SequenceProvider extends ethers.providers.BaseProvider {
3340
3392
  }
3341
3393
  const useChainId = this.toChainId(chainId);
3342
3394
  if (!this.singleNetworkProviders[useChainId]) {
3343
- this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId);
3395
+ this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId, this.options);
3344
3396
  }
3345
3397
  return this.singleNetworkProviders[useChainId];
3346
3398
  }
@@ -3360,11 +3412,26 @@ class SequenceProvider extends ethers.providers.BaseProvider {
3360
3412
  }
3361
3413
  return provider;
3362
3414
  }
3415
+ async _perform(req) {
3416
+ var _provider$getRpcReque;
3417
+ const {
3418
+ method
3419
+ } = req,
3420
+ args = _objectWithoutPropertiesLoose(req, _excluded);
3421
+ const provider = await this._getSubprovider();
3422
+ const prepared = (_provider$getRpcReque = provider.getRpcRequest(req)) != null ? _provider$getRpcReque : {
3423
+ method,
3424
+ args: Object.values(args)
3425
+ };
3426
+ if (!prepared) {
3427
+ throw new Error(`Unsupported method ${req.method}`);
3428
+ }
3429
+ return provider.send(prepared.method, prepared.args);
3430
+ }
3363
3431
  async perform(method, params) {
3364
- var _provider$prepareRequ;
3365
3432
  // First we check if the method should be handled by the client
3366
3433
  if (method === 'eth_chainId') {
3367
- return ethers.utils.hexValue(await this.useChainId());
3434
+ return ethers.toQuantity(await this.useChainId());
3368
3435
  }
3369
3436
  if (method === 'eth_accounts') {
3370
3437
  return [this.client.getAddress()];
@@ -3384,17 +3451,15 @@ class SequenceProvider extends ethers.providers.BaseProvider {
3384
3451
  method === 'sequence_sign' || method === 'sequence_signTypedData_v4') {
3385
3452
  // We pass the chainId to the client, if we don't pass one
3386
3453
  // the client will use its own default chainId
3387
- return this.client.send({
3454
+ return this.client.request({
3388
3455
  method,
3389
- params
3390
- }, this.getChainId());
3456
+ params,
3457
+ chainId: this.getChainId()
3458
+ });
3391
3459
  }
3392
-
3393
- // Forward call to the corresponding provider
3394
- // we use the provided chainId, or the default one provided by the client
3395
- const provider = await this._getSubprovider();
3396
- const prepared = (_provider$prepareRequ = provider.prepareRequest(method, params)) != null ? _provider$prepareRequ : [method, params];
3397
- return provider.send(prepared[0], prepared[1]);
3460
+ return this._perform(_extends({
3461
+ method
3462
+ }, params));
3398
3463
  }
3399
3464
  send(method, params) {
3400
3465
  return this.perform(method, params);
@@ -3402,14 +3467,18 @@ class SequenceProvider extends ethers.providers.BaseProvider {
3402
3467
  request(request) {
3403
3468
  return this.perform(request.method, request.params);
3404
3469
  }
3405
- async detectNetwork() {
3470
+ async _detectNetwork() {
3406
3471
  const chainId = this.client.getChainId();
3407
- const network = findNetworkConfig(this.networks, chainId);
3408
- if (!network) {
3472
+ const found = findNetworkConfig(this.networks, chainId);
3473
+ if (!found) {
3409
3474
  throw new Error(`Unknown network ${chainId}`);
3410
3475
  }
3476
+ const network = new ethers.Network(found.name, found.chainId);
3411
3477
  return network;
3412
3478
  }
3479
+ async detectNetwork() {
3480
+ return this._detectNetwork();
3481
+ }
3413
3482
 
3414
3483
  // Override most of the methods, so we add support for an optional chainId
3415
3484
  // argument, which is used to select the provider to use.
@@ -3426,9 +3495,9 @@ class SequenceProvider extends ethers.providers.BaseProvider {
3426
3495
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3427
3496
  return provider.getBlockNumber();
3428
3497
  }
3429
- async getGasPrice(optionals) {
3498
+ async getFeeData(optionals) {
3430
3499
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3431
- return provider.getGasPrice();
3500
+ return provider.getFeeData();
3432
3501
  }
3433
3502
  async getBalance(addressOrName, blockTag, optionals) {
3434
3503
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
@@ -3442,21 +3511,21 @@ class SequenceProvider extends ethers.providers.BaseProvider {
3442
3511
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3443
3512
  return provider.getCode(addressOrName, blockTag);
3444
3513
  }
3445
- async getStorageAt(addressOrName, position, blockTag, optionals) {
3514
+ async getStorage(addressOrName, position, blockTag, optionals) {
3446
3515
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3447
- return provider.getStorageAt(addressOrName, position, blockTag);
3516
+ return provider.getStorage(addressOrName, position, blockTag);
3448
3517
  }
3449
- async call(transaction, blockTag, optionals) {
3518
+ async call(transaction, optionals) {
3450
3519
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3451
- return provider.call(transaction, blockTag);
3520
+ return provider.call(transaction);
3452
3521
  }
3453
3522
  async estimateGas(transaction, optionals) {
3454
3523
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3455
3524
  return provider.estimateGas(transaction);
3456
3525
  }
3457
- async getBlock(blockHashOrBlockTag, optionals) {
3526
+ async getBlock(blockHashOrBlockTag, prefetchTxs, optionals) {
3458
3527
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3459
- return provider.getBlock(blockHashOrBlockTag);
3528
+ return provider.getBlock(blockHashOrBlockTag, prefetchTxs);
3460
3529
  }
3461
3530
  async getTransaction(transactionHash, optionals) {
3462
3531
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
@@ -3483,7 +3552,7 @@ class SequenceProvider extends ethers.providers.BaseProvider {
3483
3552
  return provider.getResolver(name);
3484
3553
  }
3485
3554
  async resolveName(name) {
3486
- if (ethers.utils.isAddress(await name)) {
3555
+ if (ethers.isAddress(name)) {
3487
3556
  return name;
3488
3557
  }
3489
3558
  if (!(await this.supportsENS())) {
@@ -3516,7 +3585,7 @@ SequenceProvider.is = provider => {
3516
3585
  };
3517
3586
  function normalizeChainId(chainId) {
3518
3587
  if (typeof chainId === 'object') return normalizeChainId(chainId.chainId);
3519
- return ethers.BigNumber.from(chainId).toNumber();
3588
+ return Number(chainId);
3520
3589
  }
3521
3590
 
3522
3591
  /**
@@ -3529,8 +3598,8 @@ function normalizeChainId(chainId) {
3529
3598
  * NOTICE: These networks won't support ENS unless they are the mainnet.
3530
3599
  */
3531
3600
  class SingleNetworkSequenceProvider extends SequenceProvider {
3532
- constructor(client, providerFor, chainId) {
3533
- super(client, providerFor);
3601
+ constructor(client, providerFor, chainId, options) {
3602
+ super(client, providerFor, undefined, options);
3534
3603
  this.chainId = chainId;
3535
3604
  this._isSingleNetworkSequenceProvider = true;
3536
3605
  }
@@ -3549,11 +3618,11 @@ class SingleNetworkSequenceProvider extends SequenceProvider {
3549
3618
  }
3550
3619
  async getNetwork() {
3551
3620
  const networks = await this.client.getNetworks();
3552
- const res = findNetworkConfig(networks, this.chainId);
3553
- if (!res) {
3621
+ const found = findNetworkConfig(networks, this.chainId);
3622
+ if (!found) {
3554
3623
  throw new Error(`Unsupported network ${this.chainId}`);
3555
3624
  }
3556
- return res;
3625
+ return new ethers.Network(found.name, found.chainId);
3557
3626
  }
3558
3627
 
3559
3628
  /**
@@ -3616,55 +3685,6 @@ const setupAnalytics = (projectAccessKey, server) => {
3616
3685
  });
3617
3686
  };
3618
3687
 
3619
- var packageJson = {
3620
- name: "@0xsequence/provider",
3621
- version: "1.10.15",
3622
- description: "provider sub-package for Sequence",
3623
- repository: "https://github.com/0xsequence/sequence.js/tree/master/packages/provider",
3624
- source: "src/index.ts",
3625
- main: "dist/0xsequence-provider.cjs.js",
3626
- module: "dist/0xsequence-provider.esm.js",
3627
- author: "Horizon Blockchain Games",
3628
- license: "Apache-2.0",
3629
- scripts: {
3630
- test: "pnpm test:concurrently 'pnpm test:run'",
3631
- "test:run": "pnpm test:file tests/**/*.spec.ts",
3632
- "test:file": "NODE_OPTIONS='--import tsx' mocha --timeout 30000",
3633
- typecheck: "tsc --noEmit",
3634
- "test:concurrently": "concurrently -k --success first 'pnpm start:hardhat1' 'pnpm start:hardhat2'",
3635
- "start:hardhat1": "pnpm start:hardhat1:verbose > /dev/null 2>&1",
3636
- "start:hardhat2": "pnpm start:hardhat2:verbose > /dev/null 2>&1",
3637
- "start:hardhat1:verbose": "hardhat node --config hardhat1.config.js --hostname 0.0.0.0 --port 9595",
3638
- "start:hardhat2:verbose": "hardhat node --config hardhat2.config.js --hostname 0.0.0.0 --port 8595"
3639
- },
3640
- dependencies: {
3641
- "@0xsequence/abi": "workspace:*",
3642
- "@0xsequence/account": "workspace:*",
3643
- "@0xsequence/auth": "workspace:*",
3644
- "@0xsequence/core": "workspace:*",
3645
- "@0xsequence/migration": "workspace:*",
3646
- "@0xsequence/network": "workspace:*",
3647
- "@0xsequence/relayer": "workspace:*",
3648
- "@0xsequence/utils": "workspace:*",
3649
- "@0xsequence/wallet": "workspace:*",
3650
- "@databeat/tracker": "^0.9.1",
3651
- eventemitter2: "^6.4.5",
3652
- "webextension-polyfill": "^0.10.0"
3653
- },
3654
- peerDependencies: {
3655
- ethers: ">=5.5 < 6"
3656
- },
3657
- devDependencies: {
3658
- "@types/webextension-polyfill": "^0.10.0",
3659
- ethers: "^5.7.2",
3660
- hardhat: "^2.20.1"
3661
- },
3662
- files: [
3663
- "src",
3664
- "dist"
3665
- ]
3666
- };
3667
-
3668
3688
  /**
3669
3689
  * This session class is meant to persist the state of the wallet connection
3670
3690
  * whitin the dapp. This enables the client to retain the wallet address (and some more)
@@ -3780,7 +3800,7 @@ class SequenceClient {
3780
3800
  });
3781
3801
  this.transport.on('connect', response => {
3782
3802
  var _this$callbacks$conne;
3783
- const chainIdHex = ethers.utils.hexValue(this.getChainId());
3803
+ const chainIdHex = ethers.toQuantity(this.getChainId());
3784
3804
  (_this$callbacks$conne = this.callbacks.connect) == null || _this$callbacks$conne.forEach(cb => cb(_extends({}, response, {
3785
3805
  // Ignore the full connect response
3786
3806
  // use the chainId defined locally
@@ -3816,7 +3836,7 @@ class SequenceClient {
3816
3836
  // instead we handle it locally, so we listen for changes in the store
3817
3837
  this.defaultChainId.onDefaultChainIdChanged(chainId => {
3818
3838
  var _this$callbacks$chain2;
3819
- const chainIdHex = ethers.utils.hexValue(chainId);
3839
+ const chainIdHex = ethers.toQuantity(chainId);
3820
3840
  (_this$callbacks$chain2 = this.callbacks.chainChanged) == null || _this$callbacks$chain2.forEach(cb => cb(chainIdHex));
3821
3841
  });
3822
3842
  if (options != null && options.projectAccessKey) {
@@ -3929,7 +3949,7 @@ class SequenceClient {
3929
3949
  type: 'connect',
3930
3950
  options: _extends({}, options, {
3931
3951
  networkId: this.getChainId(),
3932
- clientVersion: packageJson.version
3952
+ clientVersion: VERSION
3933
3953
  })
3934
3954
  });
3935
3955
  const connectDetails = await this.transport.waitUntilConnected().catch(error => {
@@ -3949,7 +3969,7 @@ class SequenceClient {
3949
3969
  // Normalize chainId into a decimal string
3950
3970
  // TODO: Remove this once wallet-webapp returns chainId as a string
3951
3971
  if (connectDetails.chainId) {
3952
- connectDetails.chainId = ethers.BigNumber.from(connectDetails.chainId).toString();
3972
+ connectDetails.chainId = BigInt(connectDetails.chainId).toString();
3953
3973
  }
3954
3974
  if (connectDetails.connected) {
3955
3975
  var _connectDetails$sessi;
@@ -3975,33 +3995,17 @@ class SequenceClient {
3975
3995
 
3976
3996
  // Higher level API
3977
3997
 
3978
- // Working with sendAsync is less idiomatic
3979
- // but transport uses it instead of send, so we wrap it
3980
- send(request, chainId) {
3998
+ async request(request) {
3981
3999
  // Internally when sending requests we use `legacy_sign`
3982
4000
  // to avoid the default EIP6492 behavior overriding an explicit
3983
4001
  // "legacy sign" request, so we map the method here.
3984
4002
  request.method = this.mapSignMethod(request.method);
3985
- return new Promise((resolve, reject) => {
3986
- this.transport.sendAsync(request, (error, response) => {
3987
- if (error) {
3988
- reject(error);
3989
- } else if (response === undefined) {
3990
- reject(new Error(`Got undefined response for request: ${request}`));
3991
- } else if (typeof response === 'object' && response.error) {
3992
- reject(response.error);
3993
- } else if (typeof response === 'object' && response.result) {
3994
- resolve(response.result);
3995
- } else {
3996
- reject(new Error(`Got invalid response for request: ${request}`));
3997
- }
3998
- }, chainId || this.getChainId());
3999
- });
4003
+ return this.transport.request(request);
4000
4004
  }
4001
4005
  async getNetworks(pull) {
4002
4006
  const connectedSession = this.session.connectedSession();
4003
4007
  if (pull) {
4004
- connectedSession.networks = await this.send({
4008
+ connectedSession.networks = await this.request({
4005
4009
  method: 'sequence_getNetworks'
4006
4010
  });
4007
4011
  this.session.setSession(connectedSession);
@@ -4057,15 +4061,14 @@ class SequenceClient {
4057
4061
  chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
4058
4062
  }
4059
4063
  });
4060
-
4061
- // Serialize a BytesLike or string message into a hex string before sending
4062
- message = ethers.utils.hexlify(messageToBytes(message));
4064
+ message = ethers.hexlify(messageToBytes(message));
4063
4065
 
4064
4066
  // Address is ignored by the wallet webapp
4065
- return this.send({
4067
+ return this.request({
4066
4068
  method,
4067
- params: [message, this.getAddress()]
4068
- }, options == null ? void 0 : options.chainId);
4069
+ params: [message, this.getAddress()],
4070
+ chainId: options == null ? void 0 : options.chainId
4071
+ });
4069
4072
  }
4070
4073
  async signTypedData(typedData, options) {
4071
4074
  var _this$analytics5;
@@ -4073,7 +4076,7 @@ class SequenceClient {
4073
4076
 
4074
4077
  // TODO: Stop using ethers for this, this is the only place where we use it
4075
4078
  // and it makes the client depend on ethers.
4076
- const encoded = ethers.utils._TypedDataEncoder.getPayload(typedData.domain, typedData.types, typedData.message);
4079
+ const encoded = ethers.TypedDataEncoder.getPayload(typedData.domain, typedData.types, typedData.message);
4077
4080
 
4078
4081
  // The sign typed data will use one of the following chainIds, in order:
4079
4082
  // - The one provided in the options
@@ -4086,10 +4089,11 @@ class SequenceClient {
4086
4089
  chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
4087
4090
  }
4088
4091
  });
4089
- return this.send({
4092
+ return this.request({
4090
4093
  method,
4091
- params: [this.getAddress(), encoded]
4092
- }, (options == null ? void 0 : options.chainId) || typedData.domain.chainId && ethers.BigNumber.from(typedData.domain.chainId).toNumber() || this.getChainId());
4094
+ params: [this.getAddress(), encoded],
4095
+ chainId: (options == null ? void 0 : options.chainId) || typedData.domain.chainId && Number(typedData.domain.chainId) || this.getChainId()
4096
+ });
4093
4097
  }
4094
4098
  async sendTransaction(tx, options) {
4095
4099
  var _this$analytics6;
@@ -4101,22 +4105,24 @@ class SequenceClient {
4101
4105
  chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
4102
4106
  }
4103
4107
  });
4104
- return this.send({
4108
+ return this.request({
4105
4109
  method: 'eth_sendTransaction',
4106
- params: [extendedTxs]
4107
- }, options == null ? void 0 : options.chainId);
4110
+ params: [extendedTxs],
4111
+ chainId: options == null ? void 0 : options.chainId
4112
+ });
4108
4113
  }
4109
4114
  async getWalletContext() {
4110
- return this.send({
4115
+ return this.request({
4111
4116
  method: 'sequence_getWalletContext'
4112
4117
  });
4113
4118
  }
4114
4119
  async getOnchainWalletConfig(options) {
4115
4120
  // NOTICE: sequence_getWalletConfig sends the chainId as a param
4116
- const res = await this.send({
4121
+ const res = await this.request({
4117
4122
  method: 'sequence_getWalletConfig',
4118
- params: [(options == null ? void 0 : options.chainId) || this.getChainId()]
4119
- }, options == null ? void 0 : options.chainId);
4123
+ params: [(options == null ? void 0 : options.chainId) || this.getChainId()],
4124
+ chainId: options == null ? void 0 : options.chainId
4125
+ });
4120
4126
  return Array.isArray(res) ? res[0] : res;
4121
4127
  }
4122
4128
 
@@ -4195,9 +4201,11 @@ const initWallet = (projectAccessKey, partialConfig) => {
4195
4201
  if (!rpcUrl) {
4196
4202
  throw new Error(`no rpcUrl found for chainId: ${chainId}`);
4197
4203
  }
4198
- const baseProvider = new ethers.providers.JsonRpcProvider(rpcUrl);
4199
- const router = new JsonRpcRouter([loggingProviderMiddleware, exceptionProviderMiddleware, new CachedProvider()], new JsonRpcSender(baseProvider));
4200
- rpcProviders[chainId] = new ethers.providers.Web3Provider(router, chainId);
4204
+ rpcProviders[chainId] = new JsonRpcProvider(rpcUrl, {
4205
+ middlewares: [loggingProviderMiddleware, exceptionProviderMiddleware, new CachedProvider()]
4206
+ }, {
4207
+ cacheTimeout: -1
4208
+ });
4201
4209
  }
4202
4210
  return rpcProviders[chainId];
4203
4211
  };