@0xsequence/provider 1.10.15 → 2.0.1

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 (33) hide show
  1. package/dist/0xsequence-provider.cjs.dev.js +663 -653
  2. package/dist/0xsequence-provider.cjs.prod.js +663 -653
  3. package/dist/0xsequence-provider.esm.js +667 -657
  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 +41 -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/unreal-transport/unreal-message-handler.ts +2 -2
  27. package/src/transports/unreal-transport/unreal-message-provider.ts +2 -2
  28. package/src/transports/wallet-request-handler.ts +91 -130
  29. package/src/transports/window-transport/window-message-handler.ts +5 -4
  30. package/src/transports/window-transport/window-message-provider.ts +4 -4
  31. package/src/types.ts +8 -11
  32. package/src/utils/index.ts +4 -4
  33. package/src/utils.ts +16 -18
@@ -11,7 +11,7 @@ var network = require('@0xsequence/network');
11
11
  var auth = require('@0xsequence/auth');
12
12
  var tracker = require('@databeat/tracker');
13
13
 
14
- 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.ethers.utils.keccak256(ethers.ethers.utils.toUtf8Bytes(signature)).slice(0, 10), signature]));
14
+ 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.ethers.id(signature).slice(0, 10), signature]));
15
15
  function validateTransactionRequest(wallet, transaction) {
16
16
  const transactions = core.commons.transaction.fromTransactionish(wallet, transaction);
17
17
  const unwound = core.commons.transaction.unwind(wallet, transactions);
@@ -20,7 +20,7 @@ function validateTransactionRequest(wallet, transaction) {
20
20
  function validateTransaction(wallet, transaction) {
21
21
  if (transaction.to.toLowerCase() === wallet.toLowerCase()) {
22
22
  if (transaction.data) {
23
- const data = ethers.ethers.utils.arrayify(transaction.data);
23
+ const data = ethers.ethers.getBytes(transaction.data);
24
24
  if (data.length >= 4 && !isCreateContractCall(data)) {
25
25
  throw new Error('self calls are forbidden');
26
26
  }
@@ -30,7 +30,7 @@ function validateTransaction(wallet, transaction) {
30
30
  throw new Error('delegate calls are forbidden');
31
31
  }
32
32
  if (transaction.data) {
33
- const data = ethers.ethers.utils.hexlify(transaction.data);
33
+ const data = ethers.ethers.hexlify(transaction.data);
34
34
  const selector = data.slice(0, 10);
35
35
  const signature = PROHIBITED_FUNCTIONS.get(selector);
36
36
  if (signature) {
@@ -40,7 +40,7 @@ function validateTransaction(wallet, transaction) {
40
40
  }
41
41
  }
42
42
  function isCreateContractCall(data) {
43
- const walletInterface = new ethers.ethers.utils.Interface(abi.walletContracts.mainModule.abi);
43
+ const walletInterface = new ethers.ethers.Interface(abi.walletContracts.mainModule.abi);
44
44
  try {
45
45
  walletInterface.decodeFunctionData('createContract', data);
46
46
  return true;
@@ -68,6 +68,8 @@ function isProviderTransport(transport) {
68
68
  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';
69
69
  }
70
70
 
71
+ // Older versions of sequence.js will require a JsonRpcResponse result type, but newer versions use raw EIP1193 results
72
+
71
73
  // ProviderMessageCallback is used to respond to ProviderMessage requests. The error
72
74
  // argument is for exceptions during the execution, and response is the response payload
73
75
  // which may contain the result or an error payload from the wallet.
@@ -125,8 +127,6 @@ const ErrSignedInRequired = new ProviderError('Wallet is not signed in. Connect
125
127
 
126
128
  // TODO: lets build some nice error handling tools, prob in /utils ...
127
129
 
128
- // This is required by viem, it expects a provider to have an EIP-1193 compliant `request` attribute.
129
-
130
130
  const PROVIDER_OPEN_TIMEOUT = 30000; // in ms
131
131
 
132
132
  let _messageIdx = 0;
@@ -147,42 +147,6 @@ class BaseProviderTransport {
147
147
  this._sessionId = void 0;
148
148
  this._init = void 0;
149
149
  this._registered = void 0;
150
- this.sendAsync = async function (request, callback, chainId) {
151
- // here, we receive the message from the dapp provider call
152
-
153
- if (_this.state === OpenState.CLOSED) {
154
- // flag the wallet to auto-close once user submits input. ie.
155
- // prompting to sign a message or transaction
156
- _this.confirmationOnly = true;
157
- }
158
-
159
- // open/focus the wallet.
160
- // automatically open the wallet when a provider request makes it here.
161
- //
162
- // NOTE: if we're not signed in, then the provider will fail, users must first connect+sign in.
163
- //
164
- // TODO: how does this behave with a session has expired?
165
- _this.openWallet(undefined, {
166
- type: 'jsonRpcRequest',
167
- method: request.method
168
- }, chainId);
169
-
170
- // send message request, await, and then execute callback after receiving the response
171
- try {
172
- if (!_this.isOpened()) {
173
- await _this.waitUntilOpened(); // will throw on timeout
174
- }
175
- const response = await _this.sendMessageRequest({
176
- idx: nextMessageIdx(),
177
- type: EventType.MESSAGE,
178
- data: request,
179
- chainId: chainId
180
- });
181
- callback(undefined, response.data);
182
- } catch (err) {
183
- callback(err);
184
- }
185
- };
186
150
  // sendMessageRequest sends a ProviderMessageRequest over the wire to the wallet
187
151
  this.sendMessageRequest = async function (message) {
188
152
  return new Promise((resolve, reject) => {
@@ -292,6 +256,36 @@ class BaseProviderTransport {
292
256
  const session = (_this$openPayload2 = this.openPayload) == null ? void 0 : _this$openPayload2.session;
293
257
  return this.registered && session !== undefined && !!session.accountAddress && session.accountAddress.length === 42 && !!session.networks && session.networks.length > 0;
294
258
  }
259
+ async request(request) {
260
+ if (this.state === OpenState.CLOSED) {
261
+ // flag the wallet to auto-close once user submits input. ie.
262
+ // prompting to sign a message or transaction
263
+ this.confirmationOnly = true;
264
+ }
265
+
266
+ // open/focus the wallet.
267
+ // automatically open the wallet when a provider request makes it here.
268
+ //
269
+ // NOTE: if we're not signed in, then the provider will fail, users must first connect+sign in.
270
+ //
271
+ // TODO: how does this behave with a session has expired?
272
+ this.openWallet(undefined, {
273
+ type: 'jsonRpcRequest',
274
+ method: request.method
275
+ }, request.chainId);
276
+ if (!this.isOpened()) {
277
+ await this.waitUntilOpened(); // will throw on timeout
278
+ }
279
+ const response = await this.sendMessageRequest({
280
+ idx: nextMessageIdx(),
281
+ type: EventType.MESSAGE,
282
+ data: request,
283
+ chainId: request.chainId,
284
+ clientVersion: core.VERSION
285
+ });
286
+ return response.data;
287
+ }
288
+
295
289
  // handleMessage will handle message received from the remote wallet
296
290
  handleMessage(message) {
297
291
  var _this2 = this;
@@ -313,7 +307,8 @@ class BaseProviderTransport {
313
307
  data: {
314
308
  sessionId: this._sessionId,
315
309
  nonce: nonce
316
- }
310
+ },
311
+ clientVersion: core.VERSION
317
312
  });
318
313
  }
319
314
  if (this._init !== InitState.OK) {
@@ -398,7 +393,7 @@ class BaseProviderTransport {
398
393
  };
399
394
  if (message.data && message.data.length > 0) {
400
395
  this.accountsChangedPayload = {
401
- accounts: [ethers.ethers.utils.getAddress(message.data[0])],
396
+ accounts: [ethers.ethers.getAddress(message.data[0])],
402
397
  origin: message.origin
403
398
  };
404
399
  this.events.emit('accountsChanged', this.accountsChangedPayload.accounts, this.accountsChangedPayload.origin);
@@ -503,7 +498,7 @@ const EIP_191_PREFIX_EXCEPTIONS = [
503
498
  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)?)$/;
504
499
  function isDecentralandLoginMessage(bytes) {
505
500
  try {
506
- const stringified = ethers.ethers.utils.toUtf8String(bytes);
501
+ const stringified = ethers.ethers.toUtf8String(bytes);
507
502
  return DCL_REGEX.test(stringified);
508
503
  } catch (_unused) {
509
504
  return false;
@@ -513,7 +508,7 @@ function isDecentralandLoginMessage(bytes) {
513
508
  // try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
514
509
  // see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
515
510
  function isZeroExV3Order(bytes) {
516
- const abi = new ethers.ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi);
511
+ const abi = new ethers.ethers.Interface(ZeroXV3EIP1271OrderWithHashAbi);
517
512
  try {
518
513
  abi.decodeFunctionData('OrderWithHash', bytes);
519
514
  return true;
@@ -595,19 +590,19 @@ const ZeroXV3EIP1271OrderWithHashAbi = [{
595
590
  type: 'function'
596
591
  }];
597
592
 
598
- const eip191prefix = ethers.ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n');
593
+ const eip191prefix = ethers.ethers.toUtf8Bytes('\x19Ethereum Signed Message:\n');
599
594
  const messageToBytes = message => {
600
- if (ethers.ethers.utils.isBytesLike(message)) {
601
- return ethers.ethers.utils.arrayify(message);
595
+ if (ethers.ethers.isBytesLike(message)) {
596
+ return ethers.ethers.getBytes(message);
602
597
  }
603
- return ethers.ethers.utils.toUtf8Bytes(message);
598
+ return ethers.ethers.toUtf8Bytes(message);
604
599
  };
605
600
  const prefixEIP191Message = message => {
606
601
  const messageBytes = messageToBytes(message);
607
602
  if (messageIsExemptFromEIP191Prefix(messageBytes)) {
608
603
  return messageBytes;
609
604
  } else {
610
- return ethers.ethers.utils.concat([eip191prefix, ethers.ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
605
+ return ethers.ethers.getBytes(ethers.ethers.concat([eip191prefix, ethers.ethers.toUtf8Bytes(String(messageBytes.length)), messageBytes]));
611
606
  }
612
607
  };
613
608
  const trimEIP191Prefix = prefixedMessage => {
@@ -632,9 +627,9 @@ const trimEIP191Prefix = prefixedMessage => {
632
627
  let prefixCharLenght;
633
628
  let prefixAsNumber;
634
629
  try {
635
- prefixAsNumber = Number(ethers.ethers.utils.toUtf8String(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
630
+ prefixAsNumber = Number(ethers.ethers.toUtf8String(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
636
631
  } catch (_unused) {
637
- prefixAsNumber = Number(ethers.ethers.utils.hexlify(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
632
+ prefixAsNumber = Number(ethers.ethers.hexlify(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
638
633
  }
639
634
  if (prefixAsNumber > ethereumSignedMessagePartSlicedArray.length || !Number.isInteger(prefixAsNumber)) {
640
635
  prefixCharLenght = maxPrefixCharLength - 1;
@@ -749,9 +744,9 @@ function useBestStore() {
749
744
  async function resolveArrayProperties(object) {
750
745
  if (Array.isArray(object)) {
751
746
  // T must include array type
752
- return Promise.all(object.map(o => ethers.ethers.utils.resolveProperties(o)));
747
+ return Promise.all(object.map(o => ethers.ethers.resolveProperties(o)));
753
748
  }
754
- return ethers.ethers.utils.resolveProperties(object);
749
+ return ethers.ethers.resolveProperties(object);
755
750
  }
756
751
 
757
752
  const TRANSPORT_SESSION_LS_KEY = '@sequence.transportSession';
@@ -768,9 +763,6 @@ class BaseWalletTransport {
768
763
  // will auto-detect and set this value if it can. This is determined
769
764
  // as the parent app/window which opened the wallet.
770
765
  this.appOrigin = void 0;
771
- this.sendAsync = async function (request, callback, chainId) {
772
- throw new Error('abstract method');
773
- };
774
766
  this.handleMessage = async function (message) {
775
767
  const request = message;
776
768
 
@@ -1006,7 +998,7 @@ class BaseWalletTransport {
1006
998
  if (!networks || networks.length === 0) {
1007
999
  this.notifyChainChanged('0x0');
1008
1000
  } else {
1009
- this.notifyChainChanged(ethers.ethers.utils.hexValue(networks.find(network => network.isDefaultChain).chainId));
1001
+ this.notifyChainChanged(ethers.ethers.toQuantity(networks.find(network => network.isDefaultChain).chainId));
1010
1002
  }
1011
1003
  });
1012
1004
  this.walletRequestHandler.on('chainChanged', (chainIdHex, origin) => {
@@ -1030,6 +1022,9 @@ class BaseWalletTransport {
1030
1022
  unregister() {
1031
1023
  throw new Error('abstract method');
1032
1024
  }
1025
+ request(request) {
1026
+ throw new Error('abstract method');
1027
+ }
1033
1028
  sendMessage(message) {
1034
1029
  throw new Error('abstract method');
1035
1030
  }
@@ -1048,7 +1043,8 @@ class BaseWalletTransport {
1048
1043
  sessionId,
1049
1044
  session,
1050
1045
  error
1051
- }
1046
+ },
1047
+ clientVersion: core.VERSION
1052
1048
  });
1053
1049
  }
1054
1050
  notifyClose(error) {
@@ -1057,14 +1053,16 @@ class BaseWalletTransport {
1057
1053
  type: EventType.CLOSE,
1058
1054
  data: error ? {
1059
1055
  error
1060
- } : null
1056
+ } : null,
1057
+ clientVersion: core.VERSION
1061
1058
  });
1062
1059
  }
1063
1060
  notifyConnect(connectDetails) {
1064
1061
  this.sendMessage({
1065
1062
  idx: -1,
1066
1063
  type: EventType.CONNECT,
1067
- data: connectDetails
1064
+ data: connectDetails,
1065
+ clientVersion: core.VERSION
1068
1066
  });
1069
1067
  }
1070
1068
  notifyDisconnect(error, origin) {
@@ -1074,7 +1072,8 @@ class BaseWalletTransport {
1074
1072
  data: error ? {
1075
1073
  error
1076
1074
  } : null,
1077
- origin
1075
+ origin,
1076
+ clientVersion: core.VERSION
1078
1077
  });
1079
1078
  }
1080
1079
  notifyAccountsChanged(accounts, origin) {
@@ -1082,7 +1081,8 @@ class BaseWalletTransport {
1082
1081
  idx: -1,
1083
1082
  type: EventType.ACCOUNTS_CHANGED,
1084
1083
  data: accounts,
1085
- origin
1084
+ origin,
1085
+ clientVersion: core.VERSION
1086
1086
  });
1087
1087
  }
1088
1088
  notifyChainChanged(chainIdHex, origin) {
@@ -1090,21 +1090,24 @@ class BaseWalletTransport {
1090
1090
  idx: -1,
1091
1091
  type: EventType.CHAIN_CHANGED,
1092
1092
  data: chainIdHex,
1093
- origin
1093
+ origin,
1094
+ clientVersion: core.VERSION
1094
1095
  });
1095
1096
  }
1096
1097
  notifyNetworks(networks) {
1097
1098
  this.sendMessage({
1098
1099
  idx: -1,
1099
1100
  type: EventType.NETWORKS,
1100
- data: networks
1101
+ data: networks,
1102
+ clientVersion: core.VERSION
1101
1103
  });
1102
1104
  }
1103
1105
  notifyWalletContext(walletContext) {
1104
1106
  this.sendMessage({
1105
1107
  idx: -1,
1106
1108
  type: EventType.WALLET_CONTEXT,
1107
- data: walletContext
1109
+ data: walletContext,
1110
+ clientVersion: core.VERSION
1108
1111
  });
1109
1112
  }
1110
1113
  isValidInitAck(message) {
@@ -1175,7 +1178,8 @@ class BaseWalletTransport {
1175
1178
  type: EventType.INIT,
1176
1179
  data: {
1177
1180
  nonce: this._initNonce
1178
- }
1181
+ },
1182
+ clientVersion: core.VERSION
1179
1183
  });
1180
1184
  this._init = InitState.SENT_NONCE;
1181
1185
 
@@ -1274,7 +1278,8 @@ class ProxyMessageProvider extends BaseProviderTransport {
1274
1278
  intent,
1275
1279
  networkId,
1276
1280
  sessionId
1277
- }
1281
+ },
1282
+ clientVersion: core.VERSION
1278
1283
  });
1279
1284
  }
1280
1285
  };
@@ -1292,7 +1297,8 @@ class ProxyMessageProvider extends BaseProviderTransport {
1292
1297
  this.sendMessage({
1293
1298
  idx: -1,
1294
1299
  type: EventType.CLOSE,
1295
- data: null
1300
+ data: null,
1301
+ clientVersion: core.VERSION
1296
1302
  });
1297
1303
  this.close();
1298
1304
  }
@@ -1455,7 +1461,7 @@ class UnrealMessageProvider extends BaseProviderTransport {
1455
1461
  // all lowercase is an annoying limitation of Unreal CEF BindUObject
1456
1462
  sendMessage(message) {
1457
1463
  var _window$ue3;
1458
- const postedMessage = typeof message !== 'string' ? JSON.stringify(message) : message;
1464
+ const postedMessage = typeof message !== 'string' ? JSON.stringify(message, utils.bigintReplacer) : message;
1459
1465
  console.log('Sending message to wallet:', postedMessage);
1460
1466
  (_window$ue3 = window.ue) == null || (_window$ue3 = _window$ue3.sequencewallettransport) == null || _window$ue3.sendmessagetowallet(postedMessage);
1461
1467
  }
@@ -1554,7 +1560,7 @@ class UnrealMessageHandler extends BaseWalletTransport {
1554
1560
  return;
1555
1561
  }
1556
1562
  // prepare payload
1557
- const payload = JSON.stringify(message);
1563
+ const payload = JSON.stringify(message, utils.bigintReplacer);
1558
1564
 
1559
1565
  // post-message to app.
1560
1566
  (_window$ue3 = window.ue) == null || (_window$ue3 = _window$ue3.sequencewallettransport) == null || _window$ue3.sendmessagetosequencejs(payload);
@@ -1829,7 +1835,7 @@ class WindowMessageProvider extends BaseProviderTransport {
1829
1835
  }
1830
1836
  let message;
1831
1837
  try {
1832
- message = JSON.parse(event.data);
1838
+ message = JSON.parse(event.data, utils.bigintReviver);
1833
1839
  } catch (err) {
1834
1840
  // event is not a ProviderMessage JSON object, skip
1835
1841
  return;
@@ -1853,7 +1859,7 @@ class WindowMessageProvider extends BaseProviderTransport {
1853
1859
  utils.logger.warn('WindowMessageProvider: sendMessage failed as walletWindow is unavailable');
1854
1860
  return;
1855
1861
  }
1856
- const postedMessage = typeof message !== 'string' ? JSON.stringify(message) : message;
1862
+ const postedMessage = typeof message !== 'string' ? JSON.stringify(message, utils.bigintReplacer) : message;
1857
1863
  this.walletWindow.postMessage(postedMessage, this.walletURL.origin);
1858
1864
  }
1859
1865
  }
@@ -1880,7 +1886,7 @@ class WindowMessageHandler extends BaseWalletTransport {
1880
1886
  // Wallet always expects json-rpc request messages from a dapp
1881
1887
  let request;
1882
1888
  try {
1883
- request = JSON.parse(event.data);
1889
+ request = JSON.parse(event.data, utils.bigintReviver);
1884
1890
  } catch (err) {
1885
1891
  // event is not a ProviderMessage JSON object, skip
1886
1892
  return;
@@ -1919,7 +1925,6 @@ class WindowMessageHandler extends BaseWalletTransport {
1919
1925
 
1920
1926
  // record open details (sessionId + default network) from the window url
1921
1927
  const {
1922
- pathname,
1923
1928
  search: rawParams
1924
1929
  } = new URL(windowHref || window.location.href);
1925
1930
  let session = this.getWindowTransportSession(rawParams);
@@ -1971,7 +1976,7 @@ class WindowMessageHandler extends BaseWalletTransport {
1971
1976
  // postMessage sends message to the dapp window
1972
1977
  sendMessage(message) {
1973
1978
  // prepare payload
1974
- const payload = JSON.stringify(message);
1979
+ const payload = JSON.stringify(message, utils.bigintReplacer);
1975
1980
 
1976
1981
  // post-message to app.
1977
1982
  // only for init requests, we send to '*' origin
@@ -2053,13 +2058,6 @@ class MuxMessageProvider {
2053
2058
  }
2054
2059
  this.messageProviders.forEach(m => m.openWallet(path, intent, networkId));
2055
2060
  };
2056
- this.sendAsync = async function (request, callback, chainId) {
2057
- if (_this.provider) {
2058
- _this.provider.sendAsync(request, callback, chainId);
2059
- return;
2060
- }
2061
- throw new Error('impossible state, wallet must be opened first');
2062
- };
2063
2061
  this.sendMessageRequest = async function (message) {
2064
2062
  if (_this.provider) {
2065
2063
  return _this.provider.sendMessageRequest(message);
@@ -2156,6 +2154,12 @@ class MuxMessageProvider {
2156
2154
  }
2157
2155
  return true;
2158
2156
  }
2157
+ request(request) {
2158
+ if (!this.provider) {
2159
+ throw new Error('impossible state, wallet must be opened first');
2160
+ }
2161
+ return this.provider.request(request);
2162
+ }
2159
2163
  sendMessage(message) {
2160
2164
  if (!message.idx || message.idx <= 0) {
2161
2165
  throw new Error('message idx is empty');
@@ -2190,7 +2194,7 @@ function fromExtended(transaction) {
2190
2194
 
2191
2195
  const SIGNER_READY_TIMEOUT = 10000;
2192
2196
  class WalletRequestHandler {
2193
- constructor(_account, prompter, networks) {
2197
+ constructor(account, prompter, networks) {
2194
2198
  var _this = this;
2195
2199
  // signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
2196
2200
  // value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
@@ -2223,417 +2227,6 @@ class WalletRequestHandler {
2223
2227
  }
2224
2228
  return promptConnectDetails;
2225
2229
  };
2226
- // sendAsync implements the JsonRpcHandler interface for sending JsonRpcRequests to the wallet
2227
- this.sendAsync = async function (request, callback, chainId) {
2228
- const response = {
2229
- jsonrpc: '2.0',
2230
- id: request.id,
2231
- result: null
2232
- };
2233
- await _this.getAccount();
2234
- try {
2235
- var _this$account;
2236
- // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
2237
- if ((!_this.account || _this.account === null) && !permittedJsonRpcMethods.includes(request.method)) {
2238
- // throw new Error(`not logged in. ${request.method} is unavailable`)
2239
- throw ErrSignedInRequired;
2240
- }
2241
-
2242
- // wallet account
2243
- const account = _this.account;
2244
- if (!account) throw new Error('WalletRequestHandler: wallet account is not configured');
2245
-
2246
- // fetch the provider for the specific chain, or undefined will select defaultChain
2247
- const provider = (_this$account = _this.account) == null ? void 0 : _this$account.providerFor(chainId != null ? chainId : _this.defaultChainId());
2248
- if (!provider) throw new Error(`WalletRequestHandler: wallet provider is not configured for chainId ${chainId}`);
2249
- const jsonRpcProvider = provider instanceof ethers.ethers.providers.JsonRpcProvider ? provider : undefined;
2250
- switch (request.method) {
2251
- case 'net_version':
2252
- {
2253
- if (!jsonRpcProvider) {
2254
- throw new Error(`Account provider doesn't support send method`);
2255
- }
2256
- const result = await jsonRpcProvider.send('net_version', []);
2257
- response.result = result;
2258
- break;
2259
- }
2260
- case 'eth_chainId':
2261
- {
2262
- if (!jsonRpcProvider) {
2263
- throw new Error(`Account provider doesn't support send method`);
2264
- }
2265
- const result = await jsonRpcProvider.send('eth_chainId', []);
2266
- response.result = result;
2267
- break;
2268
- }
2269
- case 'eth_accounts':
2270
- {
2271
- const walletAddress = account.address;
2272
- response.result = [walletAddress];
2273
- break;
2274
- }
2275
- case 'eth_getBalance':
2276
- {
2277
- const [accountAddress, blockTag] = request.params;
2278
- const walletBalance = await provider.getBalance(accountAddress, blockTag);
2279
- response.result = walletBalance.toHexString();
2280
- break;
2281
- }
2282
- case 'sequence_sign':
2283
- case 'personal_sign':
2284
- case 'eth_sign':
2285
- {
2286
- // note: message from json-rpc input is in hex format
2287
- let message;
2288
-
2289
- // there is a difference in the order of the params:
2290
- // sequence_sign, personal_sign: [data, address]
2291
- // eth_sign: [address, data]
2292
- switch (request.method) {
2293
- case 'sequence_sign':
2294
- case 'personal_sign':
2295
- {
2296
- const [data, _address] = request.params;
2297
- message = data;
2298
- break;
2299
- }
2300
- case 'eth_sign':
2301
- {
2302
- const [_address, data] = request.params;
2303
- message = data;
2304
- break;
2305
- }
2306
- }
2307
- let sig = '';
2308
-
2309
- // Message must be prefixed with "\x19Ethereum Signed Message:\n"
2310
- // as defined by EIP-191
2311
- const prefixedMessage = prefixEIP191Message(message);
2312
-
2313
- // TODO:
2314
- // if (process.env.TEST_MODE === 'true' && this.prompter === null) {
2315
- const sequenceVerified = request.method === 'sequence_sign';
2316
- if (_this.prompter === null) {
2317
- // prompter is null, so we'll sign from here
2318
- sig = await account.signMessage(prefixedMessage, chainId != null ? chainId : _this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
2319
- } else {
2320
- sig = await _this.prompter.promptSignMessage({
2321
- chainId: chainId,
2322
- message: prefixedMessage,
2323
- eip6492: sequenceVerified
2324
- }, _this.connectOptions);
2325
- }
2326
- if (sig && sig.length > 0) {
2327
- response.result = sig;
2328
- } else {
2329
- // The user has declined the request when value is null
2330
- throw new Error('declined by user');
2331
- }
2332
- break;
2333
- }
2334
- case 'sequence_signTypedData_v4':
2335
- case 'eth_signTypedData':
2336
- case 'eth_signTypedData_v4':
2337
- {
2338
- // note: signingAddress from json-rpc input is in hex format, and typedDataObject
2339
- // should be an object, but in some instances may be double string encoded
2340
- const [signingAddress, typedDataObject] = request.params;
2341
- let typedData = undefined;
2342
- if (typeof typedDataObject === 'string') {
2343
- try {
2344
- typedData = JSON.parse(typedDataObject);
2345
- } catch (e) {
2346
- console.warn('walletRequestHandler: error parsing typedData', e);
2347
- }
2348
- } else {
2349
- typedData = typedDataObject;
2350
- }
2351
- if (!typedData || !typedData.domain || !typedData.types || !typedData.message) {
2352
- throw new Error('invalid typedData object');
2353
- }
2354
- let sig = '';
2355
- const sequenceVerified = request.method === 'sequence_signTypedData_v4';
2356
- if (_this.prompter === null) {
2357
- // prompter is null, so we'll sign from here
2358
- sig = await account.signTypedData(typedData.domain, typedData.types, typedData.message, chainId != null ? chainId : _this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
2359
- } else {
2360
- sig = await _this.prompter.promptSignMessage({
2361
- chainId: chainId,
2362
- typedData: typedData,
2363
- eip6492: sequenceVerified
2364
- }, _this.connectOptions);
2365
- }
2366
- if (sig && sig.length > 0) {
2367
- response.result = sig;
2368
- } else {
2369
- // The user has declined the request when value is null
2370
- throw new Error('declined by user');
2371
- }
2372
- break;
2373
- }
2374
- case 'eth_sendTransaction':
2375
- {
2376
- // https://eth.wiki/json-rpc/API#eth_sendtransaction
2377
- const transactionParams = fromExtended(request.params[0]).map(tx => {
2378
- // eth_sendTransaction uses 'gas'
2379
- // ethers and sequence use 'gasLimit'
2380
- if ('gas' in tx && tx.gasLimit === undefined) {
2381
- tx.gasLimit = tx.gas;
2382
- delete tx.gas;
2383
- }
2384
- return tx;
2385
- });
2386
- validateTransactionRequest(account.address, transactionParams);
2387
- let txnHash = '';
2388
- if (_this.prompter === null) {
2389
- var _txnResponse$hash;
2390
- // prompter is null, so we'll send from here
2391
- const txnResponse = await account.sendTransaction(transactionParams, chainId != null ? chainId : _this.defaultChainId());
2392
- txnHash = (_txnResponse$hash = txnResponse == null ? void 0 : txnResponse.hash) != null ? _txnResponse$hash : '';
2393
- } else {
2394
- // prompt user to provide the response
2395
- txnHash = await _this.prompter.promptSendTransaction(transactionParams, chainId, _this.connectOptions);
2396
- }
2397
- if (txnHash) {
2398
- response.result = txnHash;
2399
- } else {
2400
- // The user has declined the request when value is null
2401
- throw new Error('declined by user');
2402
- }
2403
- break;
2404
- }
2405
- case 'eth_signTransaction':
2406
- {
2407
- // https://eth.wiki/json-rpc/API#eth_signTransaction
2408
- const [transaction] = request.params;
2409
- const sender = ethers.ethers.utils.getAddress(transaction.from);
2410
- if (sender !== account.address) {
2411
- throw new Error('sender address does not match wallet');
2412
- }
2413
- validateTransactionRequest(account.address, transaction);
2414
- if (_this.prompter === null) {
2415
- // The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
2416
- // this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
2417
- //
2418
- // TODO: verify serializing / transporting the SignedTransaction object works as expected, most likely however
2419
- // we will want to resolveProperties the big number values to hex strings
2420
- response.result = await account.signTransactions(transaction, chainId != null ? chainId : _this.defaultChainId());
2421
- } else {
2422
- response.result = await _this.prompter.promptSignTransaction(transaction, chainId, _this.connectOptions);
2423
- }
2424
- break;
2425
- }
2426
- case 'eth_sendRawTransaction':
2427
- {
2428
- // NOTE: we're not using a prompter here as the transaction is already signed
2429
- // and would have prompted the user upon signing.
2430
-
2431
- // https://eth.wiki/json-rpc/API#eth_sendRawTransaction
2432
- if (core.commons.transaction.isSignedTransactionBundle(request.params[0])) {
2433
- const txChainId = ethers.BigNumber.from(request.params[0].chainId).toNumber();
2434
- const tx = await account.relayer(txChainId).relay(request.params[0]);
2435
- response.result = tx.hash;
2436
- } else {
2437
- const tx = await provider.sendTransaction(request.params[0]);
2438
- response.result = tx.hash;
2439
- }
2440
- break;
2441
- }
2442
- case 'eth_getTransactionCount':
2443
- {
2444
- const address = ethers.ethers.utils.getAddress(request.params[0]);
2445
- const tag = request.params[1];
2446
-
2447
- // TODO: Maybe we should fetch this data from the relayer or from the reader
2448
- // but for now we keep it simple and just use the provider
2449
-
2450
- const count = await provider.getTransactionCount(address, tag);
2451
- response.result = ethers.ethers.BigNumber.from(count).toHexString();
2452
- break;
2453
- }
2454
- case 'eth_blockNumber':
2455
- {
2456
- response.result = await provider.getBlockNumber();
2457
- break;
2458
- }
2459
- case 'eth_getBlockByNumber':
2460
- {
2461
- response.result = await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
2462
- break;
2463
- }
2464
- case 'eth_getBlockByHash':
2465
- {
2466
- response.result = await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
2467
- break;
2468
- }
2469
- case 'eth_getTransactionByHash':
2470
- {
2471
- response.result = await provider.getTransaction(request.params[0]);
2472
- break;
2473
- }
2474
- case 'eth_call':
2475
- {
2476
- const [transactionObject, blockTag] = request.params;
2477
- response.result = await provider.call(transactionObject, blockTag);
2478
- break;
2479
- }
2480
- case 'eth_getCode':
2481
- {
2482
- const [contractAddress, blockTag] = request.params;
2483
- response.result = await provider.getCode(contractAddress, blockTag);
2484
- break;
2485
- }
2486
- case 'eth_estimateGas':
2487
- {
2488
- const [transactionObject] = request.params;
2489
- response.result = await provider.estimateGas(transactionObject);
2490
- break;
2491
- }
2492
- case 'eth_gasPrice':
2493
- {
2494
- const gasPrice = await provider.getGasPrice();
2495
- response.result = gasPrice.toHexString();
2496
- break;
2497
- }
2498
- case 'wallet_switchEthereumChain':
2499
- {
2500
- const [switchParams] = request.params;
2501
- if (!switchParams.chainId || switchParams.chainId.length === 0) {
2502
- throw new Error('invalid chainId');
2503
- }
2504
- const _chainId = ethers.ethers.BigNumber.from(switchParams.chainId);
2505
- _this.setDefaultChainId(_chainId.toNumber());
2506
- response.result = null; // success
2507
- break;
2508
- }
2509
-
2510
- // smart wallet method
2511
- case 'sequence_getWalletContext':
2512
- {
2513
- response.result = account.contexts;
2514
- break;
2515
- }
2516
-
2517
- // smart wallet method
2518
- case 'sequence_getWalletConfig':
2519
- {
2520
- const [_chainId2] = request.params;
2521
- if (_chainId2) {
2522
- response.result = [(await account.status(_chainId2)).onChain.config];
2523
- } else {
2524
- response.result = await Promise.all(account.networks.map(async function (network) {
2525
- const status = await account.status(network.chainId);
2526
- return status.onChain.config;
2527
- }));
2528
- }
2529
- break;
2530
- }
2531
-
2532
- // smart wallet method
2533
- case 'sequence_getWalletState':
2534
- {
2535
- const [_chainId3] = request.params;
2536
- // TODO: Add getWalletState to the Signer interface
2537
- if (_chainId3) {
2538
- response.result = [getLegacyWalletState(_chainId3, await account.status(_chainId3))];
2539
- } else {
2540
- response.result = await Promise.all(account.networks.map(async function (network) {
2541
- const status = await account.status(network.chainId);
2542
- return getLegacyWalletState(network.chainId, status);
2543
- }));
2544
- }
2545
- break;
2546
- }
2547
-
2548
- // smart wallet method
2549
- case 'sequence_getNetworks':
2550
- {
2551
- // NOTE: must ensure that the response result below returns clean serialized data, which is to omit
2552
- // the provider and relayer objects and only return the urls so can be reinstantiated on dapp side.
2553
- // This is handled by this.getNetworks() but noted here for future readers.
2554
- response.result = await _this.getNetworks(true);
2555
- break;
2556
- }
2557
- case 'sequence_isSequence':
2558
- {
2559
- response.result = true;
2560
- break;
2561
- }
2562
-
2563
- // smart wallet method
2564
- case 'sequence_updateConfig':
2565
- {
2566
- throw new Error('sequence_updateConfig method is not allowed from a dapp');
2567
- // NOTE: method is disabled as we don't need a dapp to request to update a config.
2568
- // However, if we ever want this, we can enable it but must also use the prompter
2569
- // for confirmation.
2570
- //
2571
- // const [newConfig] = request.params
2572
- // response.result = await signer.updateConfig(newConfig)
2573
- break;
2574
- }
2575
-
2576
- // smart wallet method
2577
- case 'sequence_publishConfig':
2578
- {
2579
- throw new Error('sequence_publishConfig method is not allowed from a dapp');
2580
- break;
2581
- }
2582
-
2583
- // relayer method
2584
- case 'sequence_gasRefundOptions':
2585
- {
2586
- // TODO
2587
- break;
2588
- }
2589
-
2590
- // relayer method
2591
- case 'sequence_getNonce':
2592
- {
2593
- // TODO
2594
- break;
2595
- }
2596
-
2597
- // relayer method
2598
- case 'sequence_relay':
2599
- {
2600
- // TODO
2601
- break;
2602
- }
2603
-
2604
- // set default network of wallet
2605
- case 'sequence_setDefaultNetwork':
2606
- {
2607
- const [defaultChainId] = request.params;
2608
- if (!defaultChainId) {
2609
- throw new Error('invalid request, method argument defaultChainId cannot be empty');
2610
- }
2611
- _this.setDefaultChainId(defaultChainId);
2612
- response.result = await _this.getNetworks(true);
2613
- break;
2614
- }
2615
- default:
2616
- {
2617
- if (!jsonRpcProvider) {
2618
- throw new Error(`Account provider doesn't support send method`);
2619
- }
2620
-
2621
- // NOTE: provider here will be chain-bound if chainId is provided
2622
- const providerResponse = await jsonRpcProvider.send(request.method, request.params);
2623
- response.result = providerResponse;
2624
- }
2625
- }
2626
- } catch (err) {
2627
- utils.logger.error(err);
2628
-
2629
- // See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md#rpc-errors
2630
- response.result = null;
2631
- response.error = _extends({}, new Error(err), {
2632
- code: 4001
2633
- });
2634
- }
2635
- callback(undefined, response);
2636
- };
2637
2230
  this.isSignedIn = async function () {
2638
2231
  await _this.signerReady();
2639
2232
  return !!_this.account;
@@ -2645,7 +2238,7 @@ class WalletRequestHandler {
2645
2238
  }
2646
2239
  return _this.account;
2647
2240
  };
2648
- this.account = _account;
2241
+ this.account = account;
2649
2242
  this.prompter = prompter;
2650
2243
  this.networks = networks;
2651
2244
  }
@@ -2729,7 +2322,7 @@ class WalletRequestHandler {
2729
2322
  const chainId = network.findSupportedNetwork(networkId).chainId;
2730
2323
  const connectDetails = {
2731
2324
  connected: true,
2732
- chainId: ethers.ethers.utils.hexValue(chainId)
2325
+ chainId: ethers.ethers.toQuantity(chainId)
2733
2326
  };
2734
2327
  if (options && options.authorize) {
2735
2328
  // Perform ethauth eip712 request and construct the ConnectDetails response
@@ -2764,20 +2357,415 @@ class WalletRequestHandler {
2764
2357
  // sendMessageRequest will unwrap the ProviderMessageRequest and send it to the JsonRpcHandler
2765
2358
  // (aka, the signer in this instance) and then responds with a wrapped response of
2766
2359
  // ProviderMessageResponse to be sent over the transport
2767
- sendMessageRequest(message) {
2768
- return new Promise(resolve => {
2769
- this.sendAsync(message.data, (error, response) => {
2770
- // TODO: if response includes data.error, why do we need a separate error argument here?
2360
+ async sendMessageRequest(message) {
2361
+ var _message$clientVersio;
2362
+ // Older versions of the client require the response to be jsonrpc wrapped
2363
+ const majorVersion = Number(((_message$clientVersio = message.clientVersion) == null ? void 0 : _message$clientVersio.split('.')[0]) || '0');
2364
+ const isJsonRpcResponse = majorVersion < 2;
2365
+ const jsonRpcResponse = {
2366
+ id: message.data.id,
2367
+ jsonrpc: '2.0',
2368
+ result: null,
2369
+ error: undefined
2370
+ };
2371
+ try {
2372
+ const result = await this.request({
2373
+ method: message.data.method,
2374
+ params: message.data.params,
2375
+ chainId: message.chainId
2376
+ });
2377
+ return _extends({}, message, {
2378
+ data: isJsonRpcResponse ? _extends({}, jsonRpcResponse, {
2379
+ result
2380
+ }) : result
2381
+ });
2382
+ } catch (error) {
2383
+ return _extends({}, message, {
2384
+ data: isJsonRpcResponse ? _extends({}, jsonRpcResponse, {
2385
+ error
2386
+ }) : error
2387
+ });
2388
+ }
2389
+ }
2390
+ async request(request) {
2391
+ await this.getAccount();
2392
+ try {
2393
+ var _this$account, _request$chainId;
2394
+ // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
2395
+ if ((!this.account || this.account === null) && !permittedJsonRpcMethods.includes(request.method)) {
2396
+ // throw new Error(`not logged in. ${request.method} is unavailable`)
2397
+ throw ErrSignedInRequired;
2398
+ }
2771
2399
 
2772
- const responseMessage = _extends({}, message, {
2773
- data: response
2774
- });
2400
+ // wallet account
2401
+ const account = this.account;
2402
+ if (!account) {
2403
+ throw new Error('WalletRequestHandler: wallet account is not configured');
2404
+ }
2775
2405
 
2776
- // NOTE: we always resolve here, are the sendAsync call will wrap any exceptions
2777
- // in the error field of the response to ensure we send back to the user
2778
- resolve(responseMessage);
2779
- }, message.chainId);
2780
- });
2406
+ // fetch the provider for the specific chain, or undefined will select defaultChain
2407
+ const provider = (_this$account = this.account) == null ? void 0 : _this$account.providerFor((_request$chainId = request.chainId) != null ? _request$chainId : this.defaultChainId());
2408
+ if (!provider) {
2409
+ throw new Error(`WalletRequestHandler: wallet provider is not configured for chainId ${request.chainId}`);
2410
+ }
2411
+ const jsonRpcProvider = provider instanceof ethers.ethers.JsonRpcProvider ? provider : undefined;
2412
+ switch (request.method) {
2413
+ case 'net_version':
2414
+ {
2415
+ if (!jsonRpcProvider) {
2416
+ throw new Error(`Account provider doesn't support send method`);
2417
+ }
2418
+ return await jsonRpcProvider.send('net_version', []);
2419
+ }
2420
+ case 'eth_chainId':
2421
+ {
2422
+ if (!jsonRpcProvider) {
2423
+ throw new Error(`Account provider doesn't support send method`);
2424
+ }
2425
+ return await jsonRpcProvider.send('eth_chainId', []);
2426
+ }
2427
+ case 'eth_accounts':
2428
+ {
2429
+ return [account.address];
2430
+ }
2431
+ case 'eth_getBalance':
2432
+ {
2433
+ const [accountAddress, blockTag] = request.params;
2434
+ const walletBalance = await provider.getBalance(accountAddress, blockTag);
2435
+ return utils.toHexString(walletBalance);
2436
+ }
2437
+ case 'sequence_sign':
2438
+ case 'personal_sign':
2439
+ case 'eth_sign':
2440
+ {
2441
+ // note: message from json-rpc input is in hex format
2442
+ let message;
2443
+
2444
+ // there is a difference in the order of the params:
2445
+ // sequence_sign, personal_sign: [data, address]
2446
+ // eth_sign: [address, data]
2447
+ switch (request.method) {
2448
+ case 'sequence_sign':
2449
+ case 'personal_sign':
2450
+ {
2451
+ const [data, _address] = request.params;
2452
+ message = data;
2453
+ break;
2454
+ }
2455
+ case 'eth_sign':
2456
+ {
2457
+ const [_address, data] = request.params;
2458
+ message = data;
2459
+ break;
2460
+ }
2461
+ }
2462
+ let sig = '';
2463
+
2464
+ // Message must be prefixed with "\x19Ethereum Signed Message:\n"
2465
+ // as defined by EIP-191
2466
+ const prefixedMessage = prefixEIP191Message(message);
2467
+
2468
+ // TODO:
2469
+ // if (process.env.TEST_MODE === 'true' && this.prompter === null) {
2470
+ const sequenceVerified = request.method === 'sequence_sign';
2471
+ if (this.prompter === null) {
2472
+ var _request$chainId2;
2473
+ // prompter is null, so we'll sign from here
2474
+ sig = await account.signMessage(prefixedMessage, (_request$chainId2 = request.chainId) != null ? _request$chainId2 : this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
2475
+ } else {
2476
+ sig = await this.prompter.promptSignMessage({
2477
+ chainId: request.chainId,
2478
+ message: ethers.ethers.getBytes(prefixedMessage),
2479
+ eip6492: sequenceVerified
2480
+ }, this.connectOptions);
2481
+ }
2482
+ if (sig && sig.length > 0) {
2483
+ return sig;
2484
+ } else {
2485
+ // The user has declined the request when value is null
2486
+ throw new Error('declined by user');
2487
+ }
2488
+ }
2489
+ case 'sequence_signTypedData_v4':
2490
+ case 'eth_signTypedData':
2491
+ case 'eth_signTypedData_v4':
2492
+ {
2493
+ // note: signingAddress from json-rpc input is in hex format, and typedDataObject
2494
+ // should be an object, but in some instances may be double string encoded
2495
+ const [signingAddress, typedDataObject] = request.params;
2496
+ let typedData = undefined;
2497
+ if (typeof typedDataObject === 'string') {
2498
+ try {
2499
+ typedData = JSON.parse(typedDataObject);
2500
+ } catch (e) {
2501
+ console.warn('walletRequestHandler: error parsing typedData', e);
2502
+ }
2503
+ } else {
2504
+ typedData = typedDataObject;
2505
+ }
2506
+ if (!typedData || !typedData.domain || !typedData.types || !typedData.message) {
2507
+ throw new Error('invalid typedData object');
2508
+ }
2509
+ let sig = '';
2510
+ const sequenceVerified = request.method === 'sequence_signTypedData_v4';
2511
+ if (this.prompter === null) {
2512
+ var _request$chainId3;
2513
+ // prompter is null, so we'll sign from here
2514
+ sig = await account.signTypedData(typedData.domain, typedData.types, typedData.message, (_request$chainId3 = request.chainId) != null ? _request$chainId3 : this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
2515
+ } else {
2516
+ sig = await this.prompter.promptSignMessage({
2517
+ chainId: request.chainId,
2518
+ typedData: typedData,
2519
+ eip6492: sequenceVerified
2520
+ }, this.connectOptions);
2521
+ }
2522
+ if (sig && sig.length > 0) {
2523
+ return sig;
2524
+ } else {
2525
+ // The user has declined the request when value is null
2526
+ throw new Error('declined by user');
2527
+ }
2528
+ }
2529
+ case 'eth_sendTransaction':
2530
+ {
2531
+ // https://eth.wiki/json-rpc/API#eth_sendtransaction
2532
+ const transactionParams = fromExtended(request.params[0]).map(tx => {
2533
+ // eth_sendTransaction uses 'gas'
2534
+ // ethers and sequence use 'gasLimit'
2535
+ if ('gas' in tx && tx.gasLimit === undefined) {
2536
+ tx.gasLimit = tx.gas;
2537
+ delete tx.gas;
2538
+ }
2539
+ return tx;
2540
+ });
2541
+ validateTransactionRequest(account.address, transactionParams);
2542
+ let txnHash = '';
2543
+ if (this.prompter === null) {
2544
+ var _request$chainId4, _txnResponse$hash;
2545
+ // prompter is null, so we'll send from here
2546
+ const txnResponse = await account.sendTransaction(transactionParams, (_request$chainId4 = request.chainId) != null ? _request$chainId4 : this.defaultChainId());
2547
+ txnHash = (_txnResponse$hash = txnResponse == null ? void 0 : txnResponse.hash) != null ? _txnResponse$hash : '';
2548
+ } else {
2549
+ // prompt user to provide the response
2550
+ txnHash = await this.prompter.promptSendTransaction(transactionParams, request.chainId, this.connectOptions);
2551
+ }
2552
+ if (txnHash) {
2553
+ return txnHash;
2554
+ } else {
2555
+ // The user has declined the request when value is null
2556
+ throw new Error('declined by user');
2557
+ }
2558
+ }
2559
+ case 'eth_signTransaction':
2560
+ {
2561
+ // https://eth.wiki/json-rpc/API#eth_signTransaction
2562
+ const [transaction] = request.params;
2563
+ const sender = ethers.ethers.getAddress(transaction.from);
2564
+ if (sender !== account.address) {
2565
+ throw new Error('sender address does not match wallet');
2566
+ }
2567
+ validateTransactionRequest(account.address, transaction);
2568
+ if (this.prompter === null) {
2569
+ var _request$chainId5;
2570
+ // The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
2571
+ // this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
2572
+ //
2573
+ // TODO: verify serializing / transporting the SignedTransaction object works as expected, most likely however
2574
+ // we will want to resolveProperties the big number values to hex strings
2575
+ return await account.signTransactions(transaction, (_request$chainId5 = request.chainId) != null ? _request$chainId5 : this.defaultChainId());
2576
+ } else {
2577
+ return await this.prompter.promptSignTransaction(transaction, request.chainId, this.connectOptions);
2578
+ }
2579
+ }
2580
+ case 'eth_sendRawTransaction':
2581
+ {
2582
+ // NOTE: we're not using a prompter here as the transaction is already signed
2583
+ // and would have prompted the user upon signing.
2584
+
2585
+ // https://eth.wiki/json-rpc/API#eth_sendRawTransaction
2586
+ if (core.commons.transaction.isSignedTransactionBundle(request.params[0])) {
2587
+ const txChainId = Number(request.params[0].chainId);
2588
+ const tx = await account.relayer(txChainId).relay(request.params[0]);
2589
+ return tx.hash;
2590
+ } else {
2591
+ const tx = await provider.broadcastTransaction(request.params[0]);
2592
+ return tx.hash;
2593
+ }
2594
+ }
2595
+ case 'eth_getTransactionCount':
2596
+ {
2597
+ const address = ethers.ethers.getAddress(request.params[0]);
2598
+ const tag = request.params[1];
2599
+
2600
+ // TODO: Maybe we should fetch this data from the relayer or from the reader
2601
+ // but for now we keep it simple and just use the provider
2602
+
2603
+ const count = await provider.getTransactionCount(address, tag);
2604
+ return utils.toHexString(BigInt(count));
2605
+ }
2606
+ case 'eth_blockNumber':
2607
+ {
2608
+ return await provider.getBlockNumber();
2609
+ }
2610
+ case 'eth_getBlockByNumber':
2611
+ {
2612
+ return await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
2613
+ }
2614
+ case 'eth_getBlockByHash':
2615
+ {
2616
+ return await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
2617
+ }
2618
+ case 'eth_getTransactionByHash':
2619
+ {
2620
+ return await provider.getTransaction(request.params[0]);
2621
+ }
2622
+ case 'eth_call':
2623
+ {
2624
+ const [transactionObject, blockTag] = request.params;
2625
+ return await provider.call(_extends({}, transactionObject, {
2626
+ blockTag
2627
+ }));
2628
+ }
2629
+ case 'eth_getCode':
2630
+ {
2631
+ const [contractAddress, blockTag] = request.params;
2632
+ return await provider.getCode(contractAddress, blockTag);
2633
+ }
2634
+ case 'eth_estimateGas':
2635
+ {
2636
+ const [transactionObject] = request.params;
2637
+ return await provider.estimateGas(transactionObject);
2638
+ }
2639
+ case 'eth_gasPrice':
2640
+ {
2641
+ const feeData = await provider.getFeeData();
2642
+ return feeData.gasPrice === null ? null : utils.toHexString(feeData.gasPrice);
2643
+ }
2644
+ case 'wallet_switchEthereumChain':
2645
+ {
2646
+ const [switchParams] = request.params;
2647
+ if (!switchParams.chainId || switchParams.chainId.length === 0) {
2648
+ throw new Error('invalid chainId');
2649
+ }
2650
+ const chainId = BigInt(switchParams.chainId);
2651
+ this.setDefaultChainId(Number(chainId));
2652
+ return null; // success
2653
+ }
2654
+
2655
+ // smart wallet method
2656
+ case 'sequence_getWalletContext':
2657
+ {
2658
+ return account.contexts;
2659
+ }
2660
+
2661
+ // smart wallet method
2662
+ case 'sequence_getWalletConfig':
2663
+ {
2664
+ const [chainId] = request.params;
2665
+ if (chainId) {
2666
+ return [(await account.status(chainId)).onChain.config];
2667
+ } else {
2668
+ return await Promise.all(account.networks.map(async function (network) {
2669
+ const status = await account.status(network.chainId);
2670
+ return status.onChain.config;
2671
+ }));
2672
+ }
2673
+ }
2674
+
2675
+ // smart wallet method
2676
+ case 'sequence_getWalletState':
2677
+ {
2678
+ const [chainId] = request.params;
2679
+ // TODO: Add getWalletState to the Signer interface
2680
+ if (chainId) {
2681
+ return [getLegacyWalletState(chainId, await account.status(chainId))];
2682
+ } else {
2683
+ return await Promise.all(account.networks.map(async function (network) {
2684
+ const status = await account.status(network.chainId);
2685
+ return getLegacyWalletState(network.chainId, status);
2686
+ }));
2687
+ }
2688
+ }
2689
+
2690
+ // smart wallet method
2691
+ case 'sequence_getNetworks':
2692
+ {
2693
+ // NOTE: must ensure that the response result below returns clean serialized data, which is to omit
2694
+ // the provider and relayer objects and only return the urls so can be reinstantiated on dapp side.
2695
+ // This is handled by this.getNetworks() but noted here for future readers.
2696
+ return await this.getNetworks(true);
2697
+ }
2698
+ case 'sequence_isSequence':
2699
+ {
2700
+ return true;
2701
+ }
2702
+
2703
+ // smart wallet method
2704
+ case 'sequence_updateConfig':
2705
+ {
2706
+ throw new Error('sequence_updateConfig method is not allowed from a dapp');
2707
+ // NOTE: method is disabled as we don't need a dapp to request to update a config.
2708
+ // However, if we ever want this, we can enable it but must also use the prompter
2709
+ // for confirmation.
2710
+ //
2711
+ // const [newConfig] = request.params
2712
+ // return await signer.updateConfig(newConfig)
2713
+ }
2714
+
2715
+ // smart wallet method
2716
+ case 'sequence_publishConfig':
2717
+ {
2718
+ throw new Error('sequence_publishConfig method is not allowed from a dapp');
2719
+ }
2720
+
2721
+ // relayer method
2722
+ case 'sequence_gasRefundOptions':
2723
+ {
2724
+ // TODO
2725
+ break;
2726
+ }
2727
+
2728
+ // relayer method
2729
+ case 'sequence_getNonce':
2730
+ {
2731
+ // TODO
2732
+ break;
2733
+ }
2734
+
2735
+ // relayer method
2736
+ case 'sequence_relay':
2737
+ {
2738
+ // TODO
2739
+ break;
2740
+ }
2741
+
2742
+ // set default network of wallet
2743
+ case 'sequence_setDefaultNetwork':
2744
+ {
2745
+ const [defaultChainId] = request.params;
2746
+ if (!defaultChainId) {
2747
+ throw new Error('invalid request, method argument defaultChainId cannot be empty');
2748
+ }
2749
+ this.setDefaultChainId(defaultChainId);
2750
+ return await this.getNetworks(true);
2751
+ }
2752
+ default:
2753
+ {
2754
+ if (!jsonRpcProvider) {
2755
+ throw new Error(`Account provider doesn't support send method`);
2756
+ }
2757
+
2758
+ // NOTE: provider here will be chain-bound if chainId is provided
2759
+ return await jsonRpcProvider.send(request.method, request.params);
2760
+ }
2761
+ }
2762
+ } catch (err) {
2763
+ utils.logger.error(err);
2764
+ throw {
2765
+ message: err == null ? void 0 : err.message,
2766
+ code: 4001
2767
+ };
2768
+ }
2781
2769
  }
2782
2770
  on(event, fn) {
2783
2771
  this.events.on(event, fn);
@@ -2865,7 +2853,7 @@ class WalletRequestHandler {
2865
2853
  this.events.emit('disconnect', undefined, origin);
2866
2854
  }
2867
2855
  notifyChainChanged(chainId, origin) {
2868
- this.events.emit('chainChanged', ethers.ethers.utils.hexValue(chainId), origin);
2856
+ this.events.emit('chainChanged', ethers.ethers.toQuantity(chainId), origin);
2869
2857
  }
2870
2858
  async notifyNetworks(networks) {
2871
2859
  const n = networks || (await this.getNetworks(true));
@@ -2873,7 +2861,7 @@ class WalletRequestHandler {
2873
2861
  if (n.length > 0) {
2874
2862
  const defaultNetwork = n.find(network => network.chainId === this.defaultChainId());
2875
2863
  if (defaultNetwork) {
2876
- this.events.emit('chainChanged', ethers.ethers.utils.hexValue(defaultNetwork.chainId));
2864
+ this.events.emit('chainChanged', ethers.ethers.toQuantity(defaultNetwork.chainId));
2877
2865
  }
2878
2866
  } else {
2879
2867
  this.events.emit('chainChanged', '0x0');
@@ -2942,6 +2930,19 @@ function getLegacyWalletState(chainId, status) {
2942
2930
  }
2943
2931
  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'];
2944
2932
 
2933
+ function _objectWithoutPropertiesLoose(source, excluded) {
2934
+ if (source == null) return {};
2935
+ var target = {};
2936
+ var sourceKeys = Object.keys(source);
2937
+ var key, i;
2938
+ for (i = 0; i < sourceKeys.length; i++) {
2939
+ key = sourceKeys[i];
2940
+ if (excluded.indexOf(key) >= 0) continue;
2941
+ target[key] = source[key];
2942
+ }
2943
+ return target;
2944
+ }
2945
+
2945
2946
  class SequenceSigner {
2946
2947
  get utils() {
2947
2948
  return this.provider.utils;
@@ -2950,7 +2951,6 @@ class SequenceSigner {
2950
2951
  this.client = client;
2951
2952
  this.provider = provider;
2952
2953
  this.singleNetworkSigners = {};
2953
- this._isSigner = true;
2954
2954
  this._isSequenceSigner = true;
2955
2955
  }
2956
2956
  async getAddress() {
@@ -3020,12 +3020,17 @@ class SequenceSigner {
3020
3020
  });
3021
3021
  const provider = this.getProvider(chainId);
3022
3022
  try {
3023
- return await ethers.ethers.utils.poll(async function () {
3024
- const tx = await provider.getTransaction(txHash);
3025
- return tx ? provider._wrapTransaction(tx, txHash) : undefined;
3026
- }, {
3027
- onceBlock: provider
3023
+ const result = await new Promise(resolve => {
3024
+ const check = async function check() {
3025
+ const tx = await provider.getTransaction(txHash);
3026
+ if (tx !== null) {
3027
+ return resolve(tx);
3028
+ }
3029
+ await provider.once('block', check);
3030
+ };
3031
+ check();
3028
3032
  });
3033
+ return result;
3029
3034
  } catch (err) {
3030
3035
  err.transactionHash = txHash;
3031
3036
  throw err;
@@ -3047,15 +3052,12 @@ class SequenceSigner {
3047
3052
  async estimateGas(transaction, optionals) {
3048
3053
  return this.getProvider(optionals == null ? void 0 : optionals.chainId).estimateGas(transaction);
3049
3054
  }
3050
- async call(transaction, blockTag, optionals) {
3051
- return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction, blockTag);
3055
+ async call(transaction, optionals) {
3056
+ return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction);
3052
3057
  }
3053
3058
  getChainId() {
3054
3059
  return Promise.resolve(this.client.getChainId());
3055
3060
  }
3056
- async getGasPrice(optionals) {
3057
- return this.getProvider(optionals == null ? void 0 : optionals.chainId).getGasPrice();
3058
- }
3059
3061
  async getFeeData(optionals) {
3060
3062
  return this.getProvider(optionals == null ? void 0 : optionals.chainId).getFeeData();
3061
3063
  }
@@ -3063,7 +3065,7 @@ class SequenceSigner {
3063
3065
  const res = await this.provider.resolveName(name);
3064
3066
 
3065
3067
  // For some reason ethers.Signer expects this to return `string`
3066
- // but ethers.providers.Provider expects this to return `string | null`.
3068
+ // but ethers.Provider expects this to return `string | null`.
3067
3069
  // The signer doesn't have any other source of information, so we'll
3068
3070
  // fail if the provider doesn't return a result.
3069
3071
  if (res === null) {
@@ -3074,6 +3076,12 @@ class SequenceSigner {
3074
3076
  _checkProvider(_operation) {
3075
3077
  // We always have a provider, so this is a noop
3076
3078
  }
3079
+ getNonce(_blockTag) {
3080
+ throw new Error('SequenceSigner does not support getNonce');
3081
+ }
3082
+ populateCall(_transaction) {
3083
+ throw new Error('SequenceSigner does not support populateCall');
3084
+ }
3077
3085
  populateTransaction(_transaction) {
3078
3086
  throw new Error('SequenceSigner does not support populateTransaction');
3079
3087
  }
@@ -3211,31 +3219,43 @@ class WalletUtils {
3211
3219
  // recoverAddress()
3212
3220
  }
3213
3221
 
3214
- class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3215
- constructor(client, providerFor, networks = network.allNetworks) {
3222
+ const _excluded = ["method"];
3223
+ const EIP1193EventTypes = ['connect', 'disconnect', 'chainChanged', 'accountsChanged'];
3224
+ class SequenceProvider extends ethers.ethers.AbstractProvider {
3225
+ constructor(client, providerFor, networks = network.allNetworks, options) {
3216
3226
  // We support a lot of networks
3217
3227
  // but we start with the default one
3218
- super(client.getChainId());
3228
+ super(client.getChainId(), options);
3219
3229
 
3220
3230
  // Emit events as defined by EIP-1193
3221
3231
  this.client = client;
3222
3232
  this.providerFor = providerFor;
3223
3233
  this.networks = networks;
3234
+ this.options = options;
3224
3235
  this.singleNetworkProviders = {};
3225
3236
  this._isSequenceProvider = true;
3226
3237
  this.utils = void 0;
3227
3238
  this.signer = void 0;
3239
+ this.eip1193EventListeners = new Map();
3228
3240
  client.onConnect(details => {
3229
- this.emit('connect', details);
3241
+ var _this$eip1193EventLis;
3242
+ //this.emit('connect', details)
3243
+ (_this$eip1193EventLis = this.eip1193EventListeners.get('connect')) == null || _this$eip1193EventLis.forEach(listener => listener(details));
3230
3244
  });
3231
3245
  client.onDisconnect(error => {
3232
- this.emit('disconnect', error);
3246
+ var _this$eip1193EventLis2;
3247
+ //this.emit('disconnect', error)
3248
+ (_this$eip1193EventLis2 = this.eip1193EventListeners.get('disconnect')) == null || _this$eip1193EventLis2.forEach(listener => listener(error));
3233
3249
  });
3234
3250
  client.onDefaultChainIdChanged(chainId => {
3235
- this.emit('chainChanged', chainId);
3251
+ var _this$eip1193EventLis3;
3252
+ //this.emit('chainChanged', chainId)
3253
+ (_this$eip1193EventLis3 = this.eip1193EventListeners.get('chainChanged')) == null || _this$eip1193EventLis3.forEach(listener => listener(chainId));
3236
3254
  });
3237
3255
  client.onAccountsChanged(accounts => {
3238
- this.emit('accountsChanged', accounts);
3256
+ var _this$eip1193EventLis4;
3257
+ //this.emit('accountsChanged', accounts)
3258
+ (_this$eip1193EventLis4 = this.eip1193EventListeners.get('accountsChanged')) == null || _this$eip1193EventLis4.forEach(listener => listener(accounts));
3239
3259
  });
3240
3260
 
3241
3261
  // NOTICE: We don't emit 'open' and 'close' events
@@ -3252,6 +3272,29 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3252
3272
  // Create a utils instance
3253
3273
  this.utils = new WalletUtils(this.signer);
3254
3274
  }
3275
+ async on(event, listener) {
3276
+ if (EIP1193EventTypes.includes(event)) {
3277
+ const listeners = this.eip1193EventListeners.get(event) || new Set();
3278
+ listeners.add(listener);
3279
+ this.eip1193EventListeners.set(event, listeners);
3280
+ return this;
3281
+ }
3282
+ return super.on(event, listener);
3283
+ }
3284
+ async off(event, listener) {
3285
+ if (EIP1193EventTypes.includes(event)) {
3286
+ const listeners = this.eip1193EventListeners.get(event);
3287
+ if (listeners) {
3288
+ if (listener) {
3289
+ listeners.delete(listener);
3290
+ } else {
3291
+ listeners.clear();
3292
+ }
3293
+ }
3294
+ return this;
3295
+ }
3296
+ return super.off(event, listener);
3297
+ }
3255
3298
  getSigner(chainId) {
3256
3299
  return this.signer.getSigner(chainId);
3257
3300
  }
@@ -3344,7 +3387,7 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3344
3387
  }
3345
3388
  const useChainId = this.toChainId(chainId);
3346
3389
  if (!this.singleNetworkProviders[useChainId]) {
3347
- this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId);
3390
+ this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId, this.options);
3348
3391
  }
3349
3392
  return this.singleNetworkProviders[useChainId];
3350
3393
  }
@@ -3364,11 +3407,26 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3364
3407
  }
3365
3408
  return provider;
3366
3409
  }
3410
+ async _perform(req) {
3411
+ var _provider$getRpcReque;
3412
+ const {
3413
+ method
3414
+ } = req,
3415
+ args = _objectWithoutPropertiesLoose(req, _excluded);
3416
+ const provider = await this._getSubprovider();
3417
+ const prepared = (_provider$getRpcReque = provider.getRpcRequest(req)) != null ? _provider$getRpcReque : {
3418
+ method,
3419
+ args: Object.values(args)
3420
+ };
3421
+ if (!prepared) {
3422
+ throw new Error(`Unsupported method ${req.method}`);
3423
+ }
3424
+ return provider.send(prepared.method, prepared.args);
3425
+ }
3367
3426
  async perform(method, params) {
3368
- var _provider$prepareRequ;
3369
3427
  // First we check if the method should be handled by the client
3370
3428
  if (method === 'eth_chainId') {
3371
- return ethers.ethers.utils.hexValue(await this.useChainId());
3429
+ return ethers.ethers.toQuantity(await this.useChainId());
3372
3430
  }
3373
3431
  if (method === 'eth_accounts') {
3374
3432
  return [this.client.getAddress()];
@@ -3388,17 +3446,15 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3388
3446
  method === 'sequence_sign' || method === 'sequence_signTypedData_v4') {
3389
3447
  // We pass the chainId to the client, if we don't pass one
3390
3448
  // the client will use its own default chainId
3391
- return this.client.send({
3449
+ return this.client.request({
3392
3450
  method,
3393
- params
3394
- }, this.getChainId());
3451
+ params,
3452
+ chainId: this.getChainId()
3453
+ });
3395
3454
  }
3396
-
3397
- // Forward call to the corresponding provider
3398
- // we use the provided chainId, or the default one provided by the client
3399
- const provider = await this._getSubprovider();
3400
- const prepared = (_provider$prepareRequ = provider.prepareRequest(method, params)) != null ? _provider$prepareRequ : [method, params];
3401
- return provider.send(prepared[0], prepared[1]);
3455
+ return this._perform(_extends({
3456
+ method
3457
+ }, params));
3402
3458
  }
3403
3459
  send(method, params) {
3404
3460
  return this.perform(method, params);
@@ -3406,14 +3462,18 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3406
3462
  request(request) {
3407
3463
  return this.perform(request.method, request.params);
3408
3464
  }
3409
- async detectNetwork() {
3465
+ async _detectNetwork() {
3410
3466
  const chainId = this.client.getChainId();
3411
- const network$1 = network.findNetworkConfig(this.networks, chainId);
3412
- if (!network$1) {
3467
+ const found = network.findNetworkConfig(this.networks, chainId);
3468
+ if (!found) {
3413
3469
  throw new Error(`Unknown network ${chainId}`);
3414
3470
  }
3471
+ const network$1 = new ethers.ethers.Network(found.name, found.chainId);
3415
3472
  return network$1;
3416
3473
  }
3474
+ async detectNetwork() {
3475
+ return this._detectNetwork();
3476
+ }
3417
3477
 
3418
3478
  // Override most of the methods, so we add support for an optional chainId
3419
3479
  // argument, which is used to select the provider to use.
@@ -3430,9 +3490,9 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3430
3490
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3431
3491
  return provider.getBlockNumber();
3432
3492
  }
3433
- async getGasPrice(optionals) {
3493
+ async getFeeData(optionals) {
3434
3494
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3435
- return provider.getGasPrice();
3495
+ return provider.getFeeData();
3436
3496
  }
3437
3497
  async getBalance(addressOrName, blockTag, optionals) {
3438
3498
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
@@ -3446,21 +3506,21 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3446
3506
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3447
3507
  return provider.getCode(addressOrName, blockTag);
3448
3508
  }
3449
- async getStorageAt(addressOrName, position, blockTag, optionals) {
3509
+ async getStorage(addressOrName, position, blockTag, optionals) {
3450
3510
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3451
- return provider.getStorageAt(addressOrName, position, blockTag);
3511
+ return provider.getStorage(addressOrName, position, blockTag);
3452
3512
  }
3453
- async call(transaction, blockTag, optionals) {
3513
+ async call(transaction, optionals) {
3454
3514
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3455
- return provider.call(transaction, blockTag);
3515
+ return provider.call(transaction);
3456
3516
  }
3457
3517
  async estimateGas(transaction, optionals) {
3458
3518
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3459
3519
  return provider.estimateGas(transaction);
3460
3520
  }
3461
- async getBlock(blockHashOrBlockTag, optionals) {
3521
+ async getBlock(blockHashOrBlockTag, prefetchTxs, optionals) {
3462
3522
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3463
- return provider.getBlock(blockHashOrBlockTag);
3523
+ return provider.getBlock(blockHashOrBlockTag, prefetchTxs);
3464
3524
  }
3465
3525
  async getTransaction(transactionHash, optionals) {
3466
3526
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
@@ -3487,7 +3547,7 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3487
3547
  return provider.getResolver(name);
3488
3548
  }
3489
3549
  async resolveName(name) {
3490
- if (ethers.ethers.utils.isAddress(await name)) {
3550
+ if (ethers.ethers.isAddress(name)) {
3491
3551
  return name;
3492
3552
  }
3493
3553
  if (!(await this.supportsENS())) {
@@ -3520,7 +3580,7 @@ SequenceProvider.is = provider => {
3520
3580
  };
3521
3581
  function normalizeChainId(chainId) {
3522
3582
  if (typeof chainId === 'object') return normalizeChainId(chainId.chainId);
3523
- return ethers.ethers.BigNumber.from(chainId).toNumber();
3583
+ return Number(chainId);
3524
3584
  }
3525
3585
 
3526
3586
  /**
@@ -3533,8 +3593,8 @@ function normalizeChainId(chainId) {
3533
3593
  * NOTICE: These networks won't support ENS unless they are the mainnet.
3534
3594
  */
3535
3595
  class SingleNetworkSequenceProvider extends SequenceProvider {
3536
- constructor(client, providerFor, chainId) {
3537
- super(client, providerFor);
3596
+ constructor(client, providerFor, chainId, options) {
3597
+ super(client, providerFor, undefined, options);
3538
3598
  this.chainId = chainId;
3539
3599
  this._isSingleNetworkSequenceProvider = true;
3540
3600
  }
@@ -3553,11 +3613,11 @@ class SingleNetworkSequenceProvider extends SequenceProvider {
3553
3613
  }
3554
3614
  async getNetwork() {
3555
3615
  const networks = await this.client.getNetworks();
3556
- const res = network.findNetworkConfig(networks, this.chainId);
3557
- if (!res) {
3616
+ const found = network.findNetworkConfig(networks, this.chainId);
3617
+ if (!found) {
3558
3618
  throw new Error(`Unsupported network ${this.chainId}`);
3559
3619
  }
3560
- return res;
3620
+ return new ethers.ethers.Network(found.name, found.chainId);
3561
3621
  }
3562
3622
 
3563
3623
  /**
@@ -3620,55 +3680,6 @@ const setupAnalytics = (projectAccessKey, server) => {
3620
3680
  });
3621
3681
  };
3622
3682
 
3623
- var packageJson = {
3624
- name: "@0xsequence/provider",
3625
- version: "1.10.15",
3626
- description: "provider sub-package for Sequence",
3627
- repository: "https://github.com/0xsequence/sequence.js/tree/master/packages/provider",
3628
- source: "src/index.ts",
3629
- main: "dist/0xsequence-provider.cjs.js",
3630
- module: "dist/0xsequence-provider.esm.js",
3631
- author: "Horizon Blockchain Games",
3632
- license: "Apache-2.0",
3633
- scripts: {
3634
- test: "pnpm test:concurrently 'pnpm test:run'",
3635
- "test:run": "pnpm test:file tests/**/*.spec.ts",
3636
- "test:file": "NODE_OPTIONS='--import tsx' mocha --timeout 30000",
3637
- typecheck: "tsc --noEmit",
3638
- "test:concurrently": "concurrently -k --success first 'pnpm start:hardhat1' 'pnpm start:hardhat2'",
3639
- "start:hardhat1": "pnpm start:hardhat1:verbose > /dev/null 2>&1",
3640
- "start:hardhat2": "pnpm start:hardhat2:verbose > /dev/null 2>&1",
3641
- "start:hardhat1:verbose": "hardhat node --config hardhat1.config.js --hostname 0.0.0.0 --port 9595",
3642
- "start:hardhat2:verbose": "hardhat node --config hardhat2.config.js --hostname 0.0.0.0 --port 8595"
3643
- },
3644
- dependencies: {
3645
- "@0xsequence/abi": "workspace:*",
3646
- "@0xsequence/account": "workspace:*",
3647
- "@0xsequence/auth": "workspace:*",
3648
- "@0xsequence/core": "workspace:*",
3649
- "@0xsequence/migration": "workspace:*",
3650
- "@0xsequence/network": "workspace:*",
3651
- "@0xsequence/relayer": "workspace:*",
3652
- "@0xsequence/utils": "workspace:*",
3653
- "@0xsequence/wallet": "workspace:*",
3654
- "@databeat/tracker": "^0.9.1",
3655
- eventemitter2: "^6.4.5",
3656
- "webextension-polyfill": "^0.10.0"
3657
- },
3658
- peerDependencies: {
3659
- ethers: ">=5.5 < 6"
3660
- },
3661
- devDependencies: {
3662
- "@types/webextension-polyfill": "^0.10.0",
3663
- ethers: "^5.7.2",
3664
- hardhat: "^2.20.1"
3665
- },
3666
- files: [
3667
- "src",
3668
- "dist"
3669
- ]
3670
- };
3671
-
3672
3683
  /**
3673
3684
  * This session class is meant to persist the state of the wallet connection
3674
3685
  * whitin the dapp. This enables the client to retain the wallet address (and some more)
@@ -3784,7 +3795,7 @@ class SequenceClient {
3784
3795
  });
3785
3796
  this.transport.on('connect', response => {
3786
3797
  var _this$callbacks$conne;
3787
- const chainIdHex = ethers.ethers.utils.hexValue(this.getChainId());
3798
+ const chainIdHex = ethers.ethers.toQuantity(this.getChainId());
3788
3799
  (_this$callbacks$conne = this.callbacks.connect) == null || _this$callbacks$conne.forEach(cb => cb(_extends({}, response, {
3789
3800
  // Ignore the full connect response
3790
3801
  // use the chainId defined locally
@@ -3820,7 +3831,7 @@ class SequenceClient {
3820
3831
  // instead we handle it locally, so we listen for changes in the store
3821
3832
  this.defaultChainId.onDefaultChainIdChanged(chainId => {
3822
3833
  var _this$callbacks$chain2;
3823
- const chainIdHex = ethers.ethers.utils.hexValue(chainId);
3834
+ const chainIdHex = ethers.ethers.toQuantity(chainId);
3824
3835
  (_this$callbacks$chain2 = this.callbacks.chainChanged) == null || _this$callbacks$chain2.forEach(cb => cb(chainIdHex));
3825
3836
  });
3826
3837
  if (options != null && options.projectAccessKey) {
@@ -3933,7 +3944,7 @@ class SequenceClient {
3933
3944
  type: 'connect',
3934
3945
  options: _extends({}, options, {
3935
3946
  networkId: this.getChainId(),
3936
- clientVersion: packageJson.version
3947
+ clientVersion: core.VERSION
3937
3948
  })
3938
3949
  });
3939
3950
  const connectDetails = await this.transport.waitUntilConnected().catch(error => {
@@ -3953,7 +3964,7 @@ class SequenceClient {
3953
3964
  // Normalize chainId into a decimal string
3954
3965
  // TODO: Remove this once wallet-webapp returns chainId as a string
3955
3966
  if (connectDetails.chainId) {
3956
- connectDetails.chainId = ethers.ethers.BigNumber.from(connectDetails.chainId).toString();
3967
+ connectDetails.chainId = BigInt(connectDetails.chainId).toString();
3957
3968
  }
3958
3969
  if (connectDetails.connected) {
3959
3970
  var _connectDetails$sessi;
@@ -3979,33 +3990,20 @@ class SequenceClient {
3979
3990
 
3980
3991
  // Higher level API
3981
3992
 
3982
- // Working with sendAsync is less idiomatic
3983
- // but transport uses it instead of send, so we wrap it
3984
- send(request, chainId) {
3993
+ async request(request) {
3985
3994
  // Internally when sending requests we use `legacy_sign`
3986
3995
  // to avoid the default EIP6492 behavior overriding an explicit
3987
3996
  // "legacy sign" request, so we map the method here.
3988
3997
  request.method = this.mapSignMethod(request.method);
3989
- return new Promise((resolve, reject) => {
3990
- this.transport.sendAsync(request, (error, response) => {
3991
- if (error) {
3992
- reject(error);
3993
- } else if (response === undefined) {
3994
- reject(new Error(`Got undefined response for request: ${request}`));
3995
- } else if (typeof response === 'object' && response.error) {
3996
- reject(response.error);
3997
- } else if (typeof response === 'object' && response.result) {
3998
- resolve(response.result);
3999
- } else {
4000
- reject(new Error(`Got invalid response for request: ${request}`));
4001
- }
4002
- }, chainId || this.getChainId());
4003
- });
3998
+ const result = await this.transport.request(request);
3999
+
4000
+ // We may need to unwrap the response if it's a JSON-RPC response. ie. older universal wallet versions
4001
+ return unwrapJsonRpcResponse(result);
4004
4002
  }
4005
4003
  async getNetworks(pull) {
4006
4004
  const connectedSession = this.session.connectedSession();
4007
4005
  if (pull) {
4008
- connectedSession.networks = await this.send({
4006
+ connectedSession.networks = await this.request({
4009
4007
  method: 'sequence_getNetworks'
4010
4008
  });
4011
4009
  this.session.setSession(connectedSession);
@@ -4061,15 +4059,14 @@ class SequenceClient {
4061
4059
  chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
4062
4060
  }
4063
4061
  });
4064
-
4065
- // Serialize a BytesLike or string message into a hex string before sending
4066
- message = ethers.ethers.utils.hexlify(messageToBytes(message));
4062
+ message = ethers.ethers.hexlify(messageToBytes(message));
4067
4063
 
4068
4064
  // Address is ignored by the wallet webapp
4069
- return this.send({
4065
+ return this.request({
4070
4066
  method,
4071
- params: [message, this.getAddress()]
4072
- }, options == null ? void 0 : options.chainId);
4067
+ params: [message, this.getAddress()],
4068
+ chainId: options == null ? void 0 : options.chainId
4069
+ });
4073
4070
  }
4074
4071
  async signTypedData(typedData, options) {
4075
4072
  var _this$analytics5;
@@ -4077,7 +4074,7 @@ class SequenceClient {
4077
4074
 
4078
4075
  // TODO: Stop using ethers for this, this is the only place where we use it
4079
4076
  // and it makes the client depend on ethers.
4080
- const encoded = ethers.ethers.utils._TypedDataEncoder.getPayload(typedData.domain, typedData.types, typedData.message);
4077
+ const encoded = ethers.ethers.TypedDataEncoder.getPayload(typedData.domain, typedData.types, typedData.message);
4081
4078
 
4082
4079
  // The sign typed data will use one of the following chainIds, in order:
4083
4080
  // - The one provided in the options
@@ -4090,10 +4087,11 @@ class SequenceClient {
4090
4087
  chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
4091
4088
  }
4092
4089
  });
4093
- return this.send({
4090
+ return this.request({
4094
4091
  method,
4095
- params: [this.getAddress(), encoded]
4096
- }, (options == null ? void 0 : options.chainId) || typedData.domain.chainId && ethers.ethers.BigNumber.from(typedData.domain.chainId).toNumber() || this.getChainId());
4092
+ params: [this.getAddress(), encoded],
4093
+ chainId: (options == null ? void 0 : options.chainId) || typedData.domain.chainId && Number(typedData.domain.chainId) || this.getChainId()
4094
+ });
4097
4095
  }
4098
4096
  async sendTransaction(tx, options) {
4099
4097
  var _this$analytics6;
@@ -4105,22 +4103,24 @@ class SequenceClient {
4105
4103
  chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
4106
4104
  }
4107
4105
  });
4108
- return this.send({
4106
+ return this.request({
4109
4107
  method: 'eth_sendTransaction',
4110
- params: [extendedTxs]
4111
- }, options == null ? void 0 : options.chainId);
4108
+ params: [extendedTxs],
4109
+ chainId: options == null ? void 0 : options.chainId
4110
+ });
4112
4111
  }
4113
4112
  async getWalletContext() {
4114
- return this.send({
4113
+ return this.request({
4115
4114
  method: 'sequence_getWalletContext'
4116
4115
  });
4117
4116
  }
4118
4117
  async getOnchainWalletConfig(options) {
4119
4118
  // NOTICE: sequence_getWalletConfig sends the chainId as a param
4120
- const res = await this.send({
4119
+ const res = await this.request({
4121
4120
  method: 'sequence_getWalletConfig',
4122
- params: [(options == null ? void 0 : options.chainId) || this.getChainId()]
4123
- }, options == null ? void 0 : options.chainId);
4121
+ params: [(options == null ? void 0 : options.chainId) || this.getChainId()],
4122
+ chainId: options == null ? void 0 : options.chainId
4123
+ });
4124
4124
  return Array.isArray(res) ? res[0] : res;
4125
4125
  }
4126
4126
 
@@ -4130,6 +4130,14 @@ class SequenceClient {
4130
4130
  // exclusively used for Sequence specific methods
4131
4131
  }
4132
4132
 
4133
+ // Unwrap a JsonRpcResponse result
4134
+ const unwrapJsonRpcResponse = response => {
4135
+ if (response && typeof response === 'object' && 'jsonrpc' in response && 'result' in response) {
4136
+ return response.result;
4137
+ }
4138
+ return response;
4139
+ };
4140
+
4133
4141
  const DefaultProviderConfig = {
4134
4142
  transports: {
4135
4143
  walletAppURL: 'https://sequence.app',
@@ -4199,9 +4207,11 @@ const initWallet = (projectAccessKey, partialConfig) => {
4199
4207
  if (!rpcUrl) {
4200
4208
  throw new Error(`no rpcUrl found for chainId: ${chainId}`);
4201
4209
  }
4202
- const baseProvider = new ethers.ethers.providers.JsonRpcProvider(rpcUrl);
4203
- const router = new network.JsonRpcRouter([network.loggingProviderMiddleware, network.exceptionProviderMiddleware, new network.CachedProvider()], new network.JsonRpcSender(baseProvider));
4204
- rpcProviders[chainId] = new ethers.ethers.providers.Web3Provider(router, chainId);
4210
+ rpcProviders[chainId] = new network.JsonRpcProvider(rpcUrl, {
4211
+ middlewares: [network.loggingProviderMiddleware, network.exceptionProviderMiddleware, new network.CachedProvider()]
4212
+ }, {
4213
+ cacheTimeout: -1
4214
+ });
4205
4215
  }
4206
4216
  return rpcProviders[chainId];
4207
4217
  };