@0xsequence/provider 0.0.0-20240703210534 → 0.0.0-20240704152116

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 +647 -665
  2. package/dist/0xsequence-provider.cjs.prod.js +647 -665
  3. package/dist/0xsequence-provider.esm.js +651 -669
  4. package/dist/declarations/src/client.d.ts +3 -7
  5. package/dist/declarations/src/provider.d.ts +22 -31
  6. package/dist/declarations/src/signer.d.ts +14 -15
  7. package/dist/declarations/src/transports/base-provider-transport.d.ts +2 -6
  8. package/dist/declarations/src/transports/base-wallet-transport.d.ts +2 -6
  9. package/dist/declarations/src/transports/mux-transport/mux-message-provider.d.ts +2 -5
  10. package/dist/declarations/src/transports/wallet-request-handler.d.ts +6 -7
  11. package/dist/declarations/src/types.d.ts +11 -6
  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 +51 -31
  16. package/src/eip191exceptions.ts +2 -2
  17. package/src/extended.ts +5 -5
  18. package/src/init.ts +10 -9
  19. package/src/provider.ts +66 -114
  20. package/src/signer.ts +43 -46
  21. package/src/transactions.ts +4 -4
  22. package/src/transports/base-provider-transport.ts +23 -19
  23. package/src/transports/base-wallet-transport.ts +13 -22
  24. package/src/transports/mux-transport/mux-message-provider.ts +6 -5
  25. package/src/transports/proxy-transport/proxy-message-provider.ts +2 -5
  26. package/src/transports/wallet-request-handler.ts +131 -91
  27. package/src/transports/window-transport/window-message-handler.ts +3 -17
  28. package/src/transports/window-transport/window-message-provider.ts +1 -1
  29. package/src/types.ts +11 -8
  30. package/src/utils/index.ts +4 -4
  31. package/src/utils.ts +18 -16
@@ -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.keccak256(ethers.ethers.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.utils.keccak256(ethers.ethers.utils.toUtf8Bytes(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.getBytes(transaction.data);
23
+ const data = ethers.ethers.utils.arrayify(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.hexlify(transaction.data);
33
+ const data = ethers.ethers.utils.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.Interface(abi.walletContracts.mainModule.abi);
43
+ const walletInterface = new ethers.ethers.utils.Interface(abi.walletContracts.mainModule.abi);
44
44
  try {
45
45
  walletInterface.decodeFunctionData('createContract', data);
46
46
  return true;
@@ -68,8 +68,6 @@ 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
-
73
71
  // ProviderMessageCallback is used to respond to ProviderMessage requests. The error
74
72
  // argument is for exceptions during the execution, and response is the response payload
75
73
  // which may contain the result or an error payload from the wallet.
@@ -127,6 +125,8 @@ const ErrSignedInRequired = new ProviderError('Wallet is not signed in. Connect
127
125
 
128
126
  // TODO: lets build some nice error handling tools, prob in /utils ...
129
127
 
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,6 +147,42 @@ 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
+ };
150
186
  // sendMessageRequest sends a ProviderMessageRequest over the wire to the wallet
151
187
  this.sendMessageRequest = async function (message) {
152
188
  return new Promise((resolve, reject) => {
@@ -256,36 +292,6 @@ class BaseProviderTransport {
256
292
  const session = (_this$openPayload2 = this.openPayload) == null ? void 0 : _this$openPayload2.session;
257
293
  return this.registered && session !== undefined && !!session.accountAddress && session.accountAddress.length === 42 && !!session.networks && session.networks.length > 0;
258
294
  }
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
-
289
295
  // handleMessage will handle message received from the remote wallet
290
296
  handleMessage(message) {
291
297
  var _this2 = this;
@@ -307,8 +313,7 @@ class BaseProviderTransport {
307
313
  data: {
308
314
  sessionId: this._sessionId,
309
315
  nonce: nonce
310
- },
311
- clientVersion: core.VERSION
316
+ }
312
317
  });
313
318
  }
314
319
  if (this._init !== InitState.OK) {
@@ -393,7 +398,7 @@ class BaseProviderTransport {
393
398
  };
394
399
  if (message.data && message.data.length > 0) {
395
400
  this.accountsChangedPayload = {
396
- accounts: [ethers.ethers.getAddress(message.data[0])],
401
+ accounts: [ethers.ethers.utils.getAddress(message.data[0])],
397
402
  origin: message.origin
398
403
  };
399
404
  this.events.emit('accountsChanged', this.accountsChangedPayload.accounts, this.accountsChangedPayload.origin);
@@ -498,7 +503,7 @@ const EIP_191_PREFIX_EXCEPTIONS = [
498
503
  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)?)$/;
499
504
  function isDecentralandLoginMessage(bytes) {
500
505
  try {
501
- const stringified = ethers.ethers.toUtf8String(bytes);
506
+ const stringified = ethers.ethers.utils.toUtf8String(bytes);
502
507
  return DCL_REGEX.test(stringified);
503
508
  } catch (_unused) {
504
509
  return false;
@@ -508,7 +513,7 @@ function isDecentralandLoginMessage(bytes) {
508
513
  // try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
509
514
  // see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
510
515
  function isZeroExV3Order(bytes) {
511
- const abi = new ethers.ethers.Interface(ZeroXV3EIP1271OrderWithHashAbi);
516
+ const abi = new ethers.ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi);
512
517
  try {
513
518
  abi.decodeFunctionData('OrderWithHash', bytes);
514
519
  return true;
@@ -590,19 +595,19 @@ const ZeroXV3EIP1271OrderWithHashAbi = [{
590
595
  type: 'function'
591
596
  }];
592
597
 
593
- const eip191prefix = ethers.ethers.toUtf8Bytes('\x19Ethereum Signed Message:\n');
598
+ const eip191prefix = ethers.ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n');
594
599
  const messageToBytes = message => {
595
- if (ethers.ethers.isBytesLike(message)) {
596
- return ethers.ethers.getBytes(message);
600
+ if (ethers.ethers.utils.isBytesLike(message)) {
601
+ return ethers.ethers.utils.arrayify(message);
597
602
  }
598
- return ethers.ethers.toUtf8Bytes(message);
603
+ return ethers.ethers.utils.toUtf8Bytes(message);
599
604
  };
600
605
  const prefixEIP191Message = message => {
601
606
  const messageBytes = messageToBytes(message);
602
607
  if (messageIsExemptFromEIP191Prefix(messageBytes)) {
603
608
  return messageBytes;
604
609
  } else {
605
- return ethers.ethers.getBytes(ethers.ethers.concat([eip191prefix, ethers.ethers.toUtf8Bytes(String(messageBytes.length)), messageBytes]));
610
+ return ethers.ethers.utils.concat([eip191prefix, ethers.ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
606
611
  }
607
612
  };
608
613
  const trimEIP191Prefix = prefixedMessage => {
@@ -627,9 +632,9 @@ const trimEIP191Prefix = prefixedMessage => {
627
632
  let prefixCharLenght;
628
633
  let prefixAsNumber;
629
634
  try {
630
- prefixAsNumber = Number(ethers.ethers.toUtf8String(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
635
+ prefixAsNumber = Number(ethers.ethers.utils.toUtf8String(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
631
636
  } catch (_unused) {
632
- prefixAsNumber = Number(ethers.ethers.hexlify(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
637
+ prefixAsNumber = Number(ethers.ethers.utils.hexlify(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
633
638
  }
634
639
  if (prefixAsNumber > ethereumSignedMessagePartSlicedArray.length || !Number.isInteger(prefixAsNumber)) {
635
640
  prefixCharLenght = maxPrefixCharLength - 1;
@@ -744,9 +749,9 @@ function useBestStore() {
744
749
  async function resolveArrayProperties(object) {
745
750
  if (Array.isArray(object)) {
746
751
  // T must include array type
747
- return Promise.all(object.map(o => ethers.ethers.resolveProperties(o)));
752
+ return Promise.all(object.map(o => ethers.ethers.utils.resolveProperties(o)));
748
753
  }
749
- return ethers.ethers.resolveProperties(object);
754
+ return ethers.ethers.utils.resolveProperties(object);
750
755
  }
751
756
 
752
757
  const TRANSPORT_SESSION_LS_KEY = '@sequence.transportSession';
@@ -763,6 +768,9 @@ class BaseWalletTransport {
763
768
  // will auto-detect and set this value if it can. This is determined
764
769
  // as the parent app/window which opened the wallet.
765
770
  this.appOrigin = void 0;
771
+ this.sendAsync = async function (request, callback, chainId) {
772
+ throw new Error('abstract method');
773
+ };
766
774
  this.handleMessage = async function (message) {
767
775
  const request = message;
768
776
 
@@ -998,7 +1006,7 @@ class BaseWalletTransport {
998
1006
  if (!networks || networks.length === 0) {
999
1007
  this.notifyChainChanged('0x0');
1000
1008
  } else {
1001
- this.notifyChainChanged(ethers.ethers.toQuantity(networks.find(network => network.isDefaultChain).chainId));
1009
+ this.notifyChainChanged(ethers.ethers.utils.hexValue(networks.find(network => network.isDefaultChain).chainId));
1002
1010
  }
1003
1011
  });
1004
1012
  this.walletRequestHandler.on('chainChanged', (chainIdHex, origin) => {
@@ -1022,9 +1030,6 @@ class BaseWalletTransport {
1022
1030
  unregister() {
1023
1031
  throw new Error('abstract method');
1024
1032
  }
1025
- request(request) {
1026
- throw new Error('abstract method');
1027
- }
1028
1033
  sendMessage(message) {
1029
1034
  throw new Error('abstract method');
1030
1035
  }
@@ -1043,8 +1048,7 @@ class BaseWalletTransport {
1043
1048
  sessionId,
1044
1049
  session,
1045
1050
  error
1046
- },
1047
- clientVersion: core.VERSION
1051
+ }
1048
1052
  });
1049
1053
  }
1050
1054
  notifyClose(error) {
@@ -1053,16 +1057,14 @@ class BaseWalletTransport {
1053
1057
  type: EventType.CLOSE,
1054
1058
  data: error ? {
1055
1059
  error
1056
- } : null,
1057
- clientVersion: core.VERSION
1060
+ } : null
1058
1061
  });
1059
1062
  }
1060
1063
  notifyConnect(connectDetails) {
1061
1064
  this.sendMessage({
1062
1065
  idx: -1,
1063
1066
  type: EventType.CONNECT,
1064
- data: connectDetails,
1065
- clientVersion: core.VERSION
1067
+ data: connectDetails
1066
1068
  });
1067
1069
  }
1068
1070
  notifyDisconnect(error, origin) {
@@ -1072,8 +1074,7 @@ class BaseWalletTransport {
1072
1074
  data: error ? {
1073
1075
  error
1074
1076
  } : null,
1075
- origin,
1076
- clientVersion: core.VERSION
1077
+ origin
1077
1078
  });
1078
1079
  }
1079
1080
  notifyAccountsChanged(accounts, origin) {
@@ -1081,8 +1082,7 @@ class BaseWalletTransport {
1081
1082
  idx: -1,
1082
1083
  type: EventType.ACCOUNTS_CHANGED,
1083
1084
  data: accounts,
1084
- origin,
1085
- clientVersion: core.VERSION
1085
+ origin
1086
1086
  });
1087
1087
  }
1088
1088
  notifyChainChanged(chainIdHex, origin) {
@@ -1090,24 +1090,21 @@ class BaseWalletTransport {
1090
1090
  idx: -1,
1091
1091
  type: EventType.CHAIN_CHANGED,
1092
1092
  data: chainIdHex,
1093
- origin,
1094
- clientVersion: core.VERSION
1093
+ origin
1095
1094
  });
1096
1095
  }
1097
1096
  notifyNetworks(networks) {
1098
1097
  this.sendMessage({
1099
1098
  idx: -1,
1100
1099
  type: EventType.NETWORKS,
1101
- data: networks,
1102
- clientVersion: core.VERSION
1100
+ data: networks
1103
1101
  });
1104
1102
  }
1105
1103
  notifyWalletContext(walletContext) {
1106
1104
  this.sendMessage({
1107
1105
  idx: -1,
1108
1106
  type: EventType.WALLET_CONTEXT,
1109
- data: walletContext,
1110
- clientVersion: core.VERSION
1107
+ data: walletContext
1111
1108
  });
1112
1109
  }
1113
1110
  isValidInitAck(message) {
@@ -1178,8 +1175,7 @@ class BaseWalletTransport {
1178
1175
  type: EventType.INIT,
1179
1176
  data: {
1180
1177
  nonce: this._initNonce
1181
- },
1182
- clientVersion: core.VERSION
1178
+ }
1183
1179
  });
1184
1180
  this._init = InitState.SENT_NONCE;
1185
1181
 
@@ -1278,8 +1274,7 @@ class ProxyMessageProvider extends BaseProviderTransport {
1278
1274
  intent,
1279
1275
  networkId,
1280
1276
  sessionId
1281
- },
1282
- clientVersion: core.VERSION
1277
+ }
1283
1278
  });
1284
1279
  }
1285
1280
  };
@@ -1297,8 +1292,7 @@ class ProxyMessageProvider extends BaseProviderTransport {
1297
1292
  this.sendMessage({
1298
1293
  idx: -1,
1299
1294
  type: EventType.CLOSE,
1300
- data: null,
1301
- clientVersion: core.VERSION
1295
+ data: null
1302
1296
  });
1303
1297
  this.close();
1304
1298
  }
@@ -1886,13 +1880,7 @@ class WindowMessageHandler extends BaseWalletTransport {
1886
1880
  // Wallet always expects json-rpc request messages from a dapp
1887
1881
  let request;
1888
1882
  try {
1889
- request = JSON.parse(event.data, (key, value) => {
1890
- // BigNumber compatibility with older versions of sequence.js
1891
- if (isBigNumberSerialized(value)) {
1892
- return BigInt(value.hex);
1893
- }
1894
- return value;
1895
- });
1883
+ request = JSON.parse(event.data);
1896
1884
  } catch (err) {
1897
1885
  // event is not a ProviderMessage JSON object, skip
1898
1886
  return;
@@ -1931,6 +1919,7 @@ class WindowMessageHandler extends BaseWalletTransport {
1931
1919
 
1932
1920
  // record open details (sessionId + default network) from the window url
1933
1921
  const {
1922
+ pathname,
1934
1923
  search: rawParams
1935
1924
  } = new URL(windowHref || window.location.href);
1936
1925
  let session = this.getWindowTransportSession(rawParams);
@@ -2014,9 +2003,6 @@ class WindowMessageHandler extends BaseWalletTransport {
2014
2003
  }
2015
2004
  }
2016
2005
  }
2017
- const isBigNumberSerialized = value => {
2018
- return typeof value === 'object' && 'type' in value && value.type === 'BigNumber' && 'hex' in value && ethers.ethers.isHexString(value.hex);
2019
- };
2020
2006
 
2021
2007
  function isMuxTransportTemplate(obj) {
2022
2008
  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') && (
@@ -2067,6 +2053,13 @@ class MuxMessageProvider {
2067
2053
  }
2068
2054
  this.messageProviders.forEach(m => m.openWallet(path, intent, networkId));
2069
2055
  };
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
+ };
2070
2063
  this.sendMessageRequest = async function (message) {
2071
2064
  if (_this.provider) {
2072
2065
  return _this.provider.sendMessageRequest(message);
@@ -2163,12 +2156,6 @@ class MuxMessageProvider {
2163
2156
  }
2164
2157
  return true;
2165
2158
  }
2166
- request(request) {
2167
- if (!this.provider) {
2168
- throw new Error('impossible state, wallet must be opened first');
2169
- }
2170
- return this.provider.request(request);
2171
- }
2172
2159
  sendMessage(message) {
2173
2160
  if (!message.idx || message.idx <= 0) {
2174
2161
  throw new Error('message idx is empty');
@@ -2203,7 +2190,7 @@ function fromExtended(transaction) {
2203
2190
 
2204
2191
  const SIGNER_READY_TIMEOUT = 10000;
2205
2192
  class WalletRequestHandler {
2206
- constructor(account, prompter, networks) {
2193
+ constructor(_account, prompter, networks) {
2207
2194
  var _this = this;
2208
2195
  // signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
2209
2196
  // value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
@@ -2236,6 +2223,417 @@ class WalletRequestHandler {
2236
2223
  }
2237
2224
  return promptConnectDetails;
2238
2225
  };
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
+ };
2239
2637
  this.isSignedIn = async function () {
2240
2638
  await _this.signerReady();
2241
2639
  return !!_this.account;
@@ -2247,7 +2645,7 @@ class WalletRequestHandler {
2247
2645
  }
2248
2646
  return _this.account;
2249
2647
  };
2250
- this.account = account;
2648
+ this.account = _account;
2251
2649
  this.prompter = prompter;
2252
2650
  this.networks = networks;
2253
2651
  }
@@ -2331,7 +2729,7 @@ class WalletRequestHandler {
2331
2729
  const chainId = network.findSupportedNetwork(networkId).chainId;
2332
2730
  const connectDetails = {
2333
2731
  connected: true,
2334
- chainId: ethers.ethers.toQuantity(chainId)
2732
+ chainId: ethers.ethers.utils.hexValue(chainId)
2335
2733
  };
2336
2734
  if (options && options.authorize) {
2337
2735
  // Perform ethauth eip712 request and construct the ConnectDetails response
@@ -2366,414 +2764,20 @@ class WalletRequestHandler {
2366
2764
  // sendMessageRequest will unwrap the ProviderMessageRequest and send it to the JsonRpcHandler
2367
2765
  // (aka, the signer in this instance) and then responds with a wrapped response of
2368
2766
  // ProviderMessageResponse to be sent over the transport
2369
- async sendMessageRequest(message) {
2370
- var _message$clientVersio;
2371
- // Older versions of the client require the response to be jsonrpc wrapped
2372
- const majorVersion = Number(((_message$clientVersio = message.clientVersion) == null ? void 0 : _message$clientVersio.split('.')[0]) || '0');
2373
- const isJsonRpcResponse = majorVersion < 2;
2374
- const jsonRpcResponse = {
2375
- id: message.data.id,
2376
- jsonrpc: '2.0',
2377
- result: null,
2378
- error: undefined
2379
- };
2380
- try {
2381
- const result = await this.request({
2382
- method: message.data.method,
2383
- params: message.data.params,
2384
- chainId: message.chainId
2385
- });
2386
- return _extends({}, message, {
2387
- data: isJsonRpcResponse ? _extends({}, jsonRpcResponse, {
2388
- result
2389
- }) : result
2390
- });
2391
- } catch (error) {
2392
- return _extends({}, message, {
2393
- data: isJsonRpcResponse ? _extends({}, jsonRpcResponse, {
2394
- error
2395
- }) : error
2396
- });
2397
- }
2398
- }
2399
- async request(request) {
2400
- await this.getAccount();
2401
- try {
2402
- var _this$account, _request$chainId;
2403
- // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
2404
- if ((!this.account || this.account === null) && !permittedJsonRpcMethods.includes(request.method)) {
2405
- // throw new Error(`not logged in. ${request.method} is unavailable`)
2406
- throw ErrSignedInRequired;
2407
- }
2408
-
2409
- // wallet account
2410
- const account = this.account;
2411
- if (!account) {
2412
- throw new Error('WalletRequestHandler: wallet account is not configured');
2413
- }
2414
-
2415
- // fetch the provider for the specific chain, or undefined will select defaultChain
2416
- const provider = (_this$account = this.account) == null ? void 0 : _this$account.providerFor((_request$chainId = request.chainId) != null ? _request$chainId : this.defaultChainId());
2417
- if (!provider) {
2418
- throw new Error(`WalletRequestHandler: wallet provider is not configured for chainId ${request.chainId}`);
2419
- }
2420
- const jsonRpcProvider = provider instanceof ethers.ethers.JsonRpcProvider ? provider : undefined;
2421
- switch (request.method) {
2422
- case 'net_version':
2423
- {
2424
- if (!jsonRpcProvider) {
2425
- throw new Error(`Account provider doesn't support send method`);
2426
- }
2427
- return await jsonRpcProvider.send('net_version', []);
2428
- }
2429
- case 'eth_chainId':
2430
- {
2431
- if (!jsonRpcProvider) {
2432
- throw new Error(`Account provider doesn't support send method`);
2433
- }
2434
- return await jsonRpcProvider.send('eth_chainId', []);
2435
- }
2436
- case 'eth_accounts':
2437
- {
2438
- return [account.address];
2439
- }
2440
- case 'eth_getBalance':
2441
- {
2442
- const [accountAddress, blockTag] = request.params;
2443
- const walletBalance = await provider.getBalance(accountAddress, blockTag);
2444
- return utils.toHexString(walletBalance);
2445
- }
2446
- case 'sequence_sign':
2447
- case 'personal_sign':
2448
- case 'eth_sign':
2449
- {
2450
- // note: message from json-rpc input is in hex format
2451
- let message;
2452
-
2453
- // there is a difference in the order of the params:
2454
- // sequence_sign, personal_sign: [data, address]
2455
- // eth_sign: [address, data]
2456
- switch (request.method) {
2457
- case 'sequence_sign':
2458
- case 'personal_sign':
2459
- {
2460
- const [data, _address] = request.params;
2461
- message = data;
2462
- break;
2463
- }
2464
- case 'eth_sign':
2465
- {
2466
- const [_address, data] = request.params;
2467
- message = data;
2468
- break;
2469
- }
2470
- }
2471
- let sig = '';
2472
-
2473
- // Message must be prefixed with "\x19Ethereum Signed Message:\n"
2474
- // as defined by EIP-191
2475
- const prefixedMessage = prefixEIP191Message(message);
2476
-
2477
- // TODO:
2478
- // if (process.env.TEST_MODE === 'true' && this.prompter === null) {
2479
- const sequenceVerified = request.method === 'sequence_sign';
2480
- if (this.prompter === null) {
2481
- var _request$chainId2;
2482
- // prompter is null, so we'll sign from here
2483
- sig = await account.signMessage(prefixedMessage, (_request$chainId2 = request.chainId) != null ? _request$chainId2 : this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
2484
- } else {
2485
- sig = await this.prompter.promptSignMessage({
2486
- chainId: request.chainId,
2487
- message: ethers.ethers.getBytes(prefixedMessage),
2488
- eip6492: sequenceVerified
2489
- }, this.connectOptions);
2490
- }
2491
- if (sig && sig.length > 0) {
2492
- return sig;
2493
- } else {
2494
- // The user has declined the request when value is null
2495
- throw new Error('declined by user');
2496
- }
2497
- }
2498
- case 'sequence_signTypedData_v4':
2499
- case 'eth_signTypedData':
2500
- case 'eth_signTypedData_v4':
2501
- {
2502
- // note: signingAddress from json-rpc input is in hex format, and typedDataObject
2503
- // should be an object, but in some instances may be double string encoded
2504
- const [signingAddress, typedDataObject] = request.params;
2505
- let typedData = undefined;
2506
- if (typeof typedDataObject === 'string') {
2507
- try {
2508
- typedData = JSON.parse(typedDataObject);
2509
- } catch (e) {
2510
- console.warn('walletRequestHandler: error parsing typedData', e);
2511
- }
2512
- } else {
2513
- typedData = typedDataObject;
2514
- }
2515
- if (!typedData || !typedData.domain || !typedData.types || !typedData.message) {
2516
- throw new Error('invalid typedData object');
2517
- }
2518
- let sig = '';
2519
- const sequenceVerified = request.method === 'sequence_signTypedData_v4';
2520
- if (this.prompter === null) {
2521
- var _request$chainId3;
2522
- // prompter is null, so we'll sign from here
2523
- sig = await account.signTypedData(typedData.domain, typedData.types, typedData.message, (_request$chainId3 = request.chainId) != null ? _request$chainId3 : this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
2524
- } else {
2525
- sig = await this.prompter.promptSignMessage({
2526
- chainId: request.chainId,
2527
- typedData: typedData,
2528
- eip6492: sequenceVerified
2529
- }, this.connectOptions);
2530
- }
2531
- if (sig && sig.length > 0) {
2532
- return sig;
2533
- } else {
2534
- // The user has declined the request when value is null
2535
- throw new Error('declined by user');
2536
- }
2537
- }
2538
- case 'eth_sendTransaction':
2539
- {
2540
- // https://eth.wiki/json-rpc/API#eth_sendtransaction
2541
- const transactionParams = fromExtended(request.params[0]).map(tx => {
2542
- // eth_sendTransaction uses 'gas'
2543
- // ethers and sequence use 'gasLimit'
2544
- if ('gas' in tx && tx.gasLimit === undefined) {
2545
- tx.gasLimit = tx.gas;
2546
- delete tx.gas;
2547
- }
2548
- return tx;
2549
- });
2550
- validateTransactionRequest(account.address, transactionParams);
2551
- let txnHash = '';
2552
- if (this.prompter === null) {
2553
- var _request$chainId4, _txnResponse$hash;
2554
- // prompter is null, so we'll send from here
2555
- const txnResponse = await account.sendTransaction(transactionParams, (_request$chainId4 = request.chainId) != null ? _request$chainId4 : this.defaultChainId());
2556
- txnHash = (_txnResponse$hash = txnResponse == null ? void 0 : txnResponse.hash) != null ? _txnResponse$hash : '';
2557
- } else {
2558
- // prompt user to provide the response
2559
- txnHash = await this.prompter.promptSendTransaction(transactionParams, request.chainId, this.connectOptions);
2560
- }
2561
- if (txnHash) {
2562
- return txnHash;
2563
- } else {
2564
- // The user has declined the request when value is null
2565
- throw new Error('declined by user');
2566
- }
2567
- }
2568
- case 'eth_signTransaction':
2569
- {
2570
- // https://eth.wiki/json-rpc/API#eth_signTransaction
2571
- const [transaction] = request.params;
2572
- const sender = ethers.ethers.getAddress(transaction.from);
2573
- if (sender !== account.address) {
2574
- throw new Error('sender address does not match wallet');
2575
- }
2576
- validateTransactionRequest(account.address, transaction);
2577
- if (this.prompter === null) {
2578
- var _request$chainId5;
2579
- // The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
2580
- // this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
2581
- //
2582
- // TODO: verify serializing / transporting the SignedTransaction object works as expected, most likely however
2583
- // we will want to resolveProperties the big number values to hex strings
2584
- return await account.signTransactions(transaction, (_request$chainId5 = request.chainId) != null ? _request$chainId5 : this.defaultChainId());
2585
- } else {
2586
- return await this.prompter.promptSignTransaction(transaction, request.chainId, this.connectOptions);
2587
- }
2588
- }
2589
- case 'eth_sendRawTransaction':
2590
- {
2591
- // NOTE: we're not using a prompter here as the transaction is already signed
2592
- // and would have prompted the user upon signing.
2593
-
2594
- // https://eth.wiki/json-rpc/API#eth_sendRawTransaction
2595
- if (core.commons.transaction.isSignedTransactionBundle(request.params[0])) {
2596
- const txChainId = Number(BigInt(request.params[0].chainId));
2597
- const tx = await account.relayer(txChainId).relay(request.params[0]);
2598
- return tx.hash;
2599
- } else {
2600
- const tx = await provider.broadcastTransaction(request.params[0]);
2601
- return tx.hash;
2602
- }
2603
- }
2604
- case 'eth_getTransactionCount':
2605
- {
2606
- const address = ethers.ethers.getAddress(request.params[0]);
2607
- const tag = request.params[1];
2608
-
2609
- // TODO: Maybe we should fetch this data from the relayer or from the reader
2610
- // but for now we keep it simple and just use the provider
2611
-
2612
- const count = await provider.getTransactionCount(address, tag);
2613
- return utils.toHexString(BigInt(count));
2614
- }
2615
- case 'eth_blockNumber':
2616
- {
2617
- return await provider.getBlockNumber();
2618
- }
2619
- case 'eth_getBlockByNumber':
2620
- {
2621
- return await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
2622
- }
2623
- case 'eth_getBlockByHash':
2624
- {
2625
- return await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
2626
- }
2627
- case 'eth_getTransactionByHash':
2628
- {
2629
- return await provider.getTransaction(request.params[0]);
2630
- }
2631
- case 'eth_call':
2632
- {
2633
- const [transactionObject, blockTag] = request.params;
2634
- return await provider.call(_extends({}, transactionObject, {
2635
- blockTag
2636
- }));
2637
- }
2638
- case 'eth_getCode':
2639
- {
2640
- const [contractAddress, blockTag] = request.params;
2641
- return await provider.getCode(contractAddress, blockTag);
2642
- }
2643
- case 'eth_estimateGas':
2644
- {
2645
- const [transactionObject] = request.params;
2646
- return await provider.estimateGas(transactionObject);
2647
- }
2648
- case 'eth_gasPrice':
2649
- {
2650
- const feeData = await provider.getFeeData();
2651
- return feeData.gasPrice && utils.toHexString(feeData.gasPrice);
2652
- }
2653
- case 'wallet_switchEthereumChain':
2654
- {
2655
- const [switchParams] = request.params;
2656
- if (!switchParams.chainId || switchParams.chainId.length === 0) {
2657
- throw new Error('invalid chainId');
2658
- }
2659
- const chainId = BigInt(switchParams.chainId);
2660
- this.setDefaultChainId(Number(chainId));
2661
- return null; // success
2662
- }
2663
-
2664
- // smart wallet method
2665
- case 'sequence_getWalletContext':
2666
- {
2667
- return account.contexts;
2668
- }
2669
-
2670
- // smart wallet method
2671
- case 'sequence_getWalletConfig':
2672
- {
2673
- const [chainId] = request.params;
2674
- if (chainId) {
2675
- return [(await account.status(chainId)).onChain.config];
2676
- } else {
2677
- return await Promise.all(account.networks.map(async function (network) {
2678
- const status = await account.status(network.chainId);
2679
- return status.onChain.config;
2680
- }));
2681
- }
2682
- }
2683
-
2684
- // smart wallet method
2685
- case 'sequence_getWalletState':
2686
- {
2687
- const [chainId] = request.params;
2688
- // TODO: Add getWalletState to the Signer interface
2689
- if (chainId) {
2690
- return [getLegacyWalletState(chainId, await account.status(chainId))];
2691
- } else {
2692
- return await Promise.all(account.networks.map(async function (network) {
2693
- const status = await account.status(network.chainId);
2694
- return getLegacyWalletState(network.chainId, status);
2695
- }));
2696
- }
2697
- }
2698
-
2699
- // smart wallet method
2700
- case 'sequence_getNetworks':
2701
- {
2702
- // NOTE: must ensure that the response result below returns clean serialized data, which is to omit
2703
- // the provider and relayer objects and only return the urls so can be reinstantiated on dapp side.
2704
- // This is handled by this.getNetworks() but noted here for future readers.
2705
- return await this.getNetworks(true);
2706
- }
2707
- case 'sequence_isSequence':
2708
- {
2709
- return true;
2710
- }
2711
-
2712
- // smart wallet method
2713
- case 'sequence_updateConfig':
2714
- {
2715
- throw new Error('sequence_updateConfig method is not allowed from a dapp');
2716
- // NOTE: method is disabled as we don't need a dapp to request to update a config.
2717
- // However, if we ever want this, we can enable it but must also use the prompter
2718
- // for confirmation.
2719
- //
2720
- // const [newConfig] = request.params
2721
- // return await signer.updateConfig(newConfig)
2722
- }
2723
-
2724
- // smart wallet method
2725
- case 'sequence_publishConfig':
2726
- {
2727
- throw new Error('sequence_publishConfig method is not allowed from a dapp');
2728
- }
2729
-
2730
- // relayer method
2731
- case 'sequence_gasRefundOptions':
2732
- {
2733
- // TODO
2734
- break;
2735
- }
2736
-
2737
- // relayer method
2738
- case 'sequence_getNonce':
2739
- {
2740
- // TODO
2741
- break;
2742
- }
2743
-
2744
- // relayer method
2745
- case 'sequence_relay':
2746
- {
2747
- // TODO
2748
- break;
2749
- }
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?
2750
2771
 
2751
- // set default network of wallet
2752
- case 'sequence_setDefaultNetwork':
2753
- {
2754
- const [defaultChainId] = request.params;
2755
- if (!defaultChainId) {
2756
- throw new Error('invalid request, method argument defaultChainId cannot be empty');
2757
- }
2758
- this.setDefaultChainId(defaultChainId);
2759
- return await this.getNetworks(true);
2760
- }
2761
- default:
2762
- {
2763
- if (!jsonRpcProvider) {
2764
- throw new Error(`Account provider doesn't support send method`);
2765
- }
2772
+ const responseMessage = _extends({}, message, {
2773
+ data: response
2774
+ });
2766
2775
 
2767
- // NOTE: provider here will be chain-bound if chainId is provided
2768
- return await jsonRpcProvider.send(request.method, request.params);
2769
- }
2770
- }
2771
- } catch (err) {
2772
- throw {
2773
- message: err == null ? void 0 : err.message,
2774
- code: 4001
2775
- };
2776
- }
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
+ });
2777
2781
  }
2778
2782
  on(event, fn) {
2779
2783
  this.events.on(event, fn);
@@ -2861,7 +2865,7 @@ class WalletRequestHandler {
2861
2865
  this.events.emit('disconnect', undefined, origin);
2862
2866
  }
2863
2867
  notifyChainChanged(chainId, origin) {
2864
- this.events.emit('chainChanged', ethers.ethers.toQuantity(chainId), origin);
2868
+ this.events.emit('chainChanged', ethers.ethers.utils.hexValue(chainId), origin);
2865
2869
  }
2866
2870
  async notifyNetworks(networks) {
2867
2871
  const n = networks || (await this.getNetworks(true));
@@ -2869,7 +2873,7 @@ class WalletRequestHandler {
2869
2873
  if (n.length > 0) {
2870
2874
  const defaultNetwork = n.find(network => network.chainId === this.defaultChainId());
2871
2875
  if (defaultNetwork) {
2872
- this.events.emit('chainChanged', ethers.ethers.toQuantity(defaultNetwork.chainId));
2876
+ this.events.emit('chainChanged', ethers.ethers.utils.hexValue(defaultNetwork.chainId));
2873
2877
  }
2874
2878
  } else {
2875
2879
  this.events.emit('chainChanged', '0x0');
@@ -2938,19 +2942,6 @@ function getLegacyWalletState(chainId, status) {
2938
2942
  }
2939
2943
  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
2944
 
2941
- function _objectWithoutPropertiesLoose(source, excluded) {
2942
- if (source == null) return {};
2943
- var target = {};
2944
- var sourceKeys = Object.keys(source);
2945
- var key, i;
2946
- for (i = 0; i < sourceKeys.length; i++) {
2947
- key = sourceKeys[i];
2948
- if (excluded.indexOf(key) >= 0) continue;
2949
- target[key] = source[key];
2950
- }
2951
- return target;
2952
- }
2953
-
2954
2945
  class SequenceSigner {
2955
2946
  get utils() {
2956
2947
  return this.provider.utils;
@@ -2959,6 +2950,7 @@ class SequenceSigner {
2959
2950
  this.client = client;
2960
2951
  this.provider = provider;
2961
2952
  this.singleNetworkSigners = {};
2953
+ this._isSigner = true;
2962
2954
  this._isSequenceSigner = true;
2963
2955
  }
2964
2956
  async getAddress() {
@@ -3028,19 +3020,12 @@ class SequenceSigner {
3028
3020
  });
3029
3021
  const provider = this.getProvider(chainId);
3030
3022
  try {
3031
- const result = await new Promise(resolve => {
3032
- let attempts = 0;
3033
- const check = async function check() {
3034
- attempts++;
3035
- const tx = await provider.getTransaction(txHash);
3036
- if (tx !== null) {
3037
- return resolve(tx);
3038
- }
3039
- await provider.once('block', check);
3040
- };
3041
- check();
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
3042
3028
  });
3043
- return result;
3044
3029
  } catch (err) {
3045
3030
  err.transactionHash = txHash;
3046
3031
  throw err;
@@ -3062,12 +3047,15 @@ class SequenceSigner {
3062
3047
  async estimateGas(transaction, optionals) {
3063
3048
  return this.getProvider(optionals == null ? void 0 : optionals.chainId).estimateGas(transaction);
3064
3049
  }
3065
- async call(transaction, optionals) {
3066
- return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction);
3050
+ async call(transaction, blockTag, optionals) {
3051
+ return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction, blockTag);
3067
3052
  }
3068
3053
  getChainId() {
3069
3054
  return Promise.resolve(this.client.getChainId());
3070
3055
  }
3056
+ async getGasPrice(optionals) {
3057
+ return this.getProvider(optionals == null ? void 0 : optionals.chainId).getGasPrice();
3058
+ }
3071
3059
  async getFeeData(optionals) {
3072
3060
  return this.getProvider(optionals == null ? void 0 : optionals.chainId).getFeeData();
3073
3061
  }
@@ -3075,7 +3063,7 @@ class SequenceSigner {
3075
3063
  const res = await this.provider.resolveName(name);
3076
3064
 
3077
3065
  // For some reason ethers.Signer expects this to return `string`
3078
- // but ethers.Provider expects this to return `string | null`.
3066
+ // but ethers.providers.Provider expects this to return `string | null`.
3079
3067
  // The signer doesn't have any other source of information, so we'll
3080
3068
  // fail if the provider doesn't return a result.
3081
3069
  if (res === null) {
@@ -3086,17 +3074,6 @@ class SequenceSigner {
3086
3074
  _checkProvider(_operation) {
3087
3075
  // We always have a provider, so this is a noop
3088
3076
  }
3089
-
3090
- // populateCall(transaction: ethers.PopulatedTransaction): Promise<ethers.PopulatedTransaction> {
3091
- // return this.provider.populateCall(transaction)
3092
- // }
3093
-
3094
- getNonce(_blockTag) {
3095
- throw new Error('SequenceSigner does not support getNonce');
3096
- }
3097
- populateCall(_transaction) {
3098
- throw new Error('SequenceSigner does not support populateCall');
3099
- }
3100
3077
  populateTransaction(_transaction) {
3101
3078
  throw new Error('SequenceSigner does not support populateTransaction');
3102
3079
  }
@@ -3234,43 +3211,31 @@ class WalletUtils {
3234
3211
  // recoverAddress()
3235
3212
  }
3236
3213
 
3237
- const _excluded = ["method"];
3238
- const EIP1193EventTypes = ['connect', 'disconnect', 'chainChanged', 'accountsChanged'];
3239
- class SequenceProvider extends ethers.ethers.AbstractProvider {
3240
- constructor(client, providerFor, networks = network.allNetworks, options) {
3214
+ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3215
+ constructor(client, providerFor, networks = network.allNetworks) {
3241
3216
  // We support a lot of networks
3242
3217
  // but we start with the default one
3243
- super(client.getChainId(), options);
3218
+ super(client.getChainId());
3244
3219
 
3245
3220
  // Emit events as defined by EIP-1193
3246
3221
  this.client = client;
3247
3222
  this.providerFor = providerFor;
3248
3223
  this.networks = networks;
3249
- this.options = options;
3250
3224
  this.singleNetworkProviders = {};
3251
3225
  this._isSequenceProvider = true;
3252
3226
  this.utils = void 0;
3253
3227
  this.signer = void 0;
3254
- this.eip1193EventListeners = new Map();
3255
3228
  client.onConnect(details => {
3256
- var _this$eip1193EventLis;
3257
- //this.emit('connect', details)
3258
- (_this$eip1193EventLis = this.eip1193EventListeners.get('connect')) == null || _this$eip1193EventLis.forEach(listener => listener(details));
3229
+ this.emit('connect', details);
3259
3230
  });
3260
3231
  client.onDisconnect(error => {
3261
- var _this$eip1193EventLis2;
3262
- //this.emit('disconnect', error)
3263
- (_this$eip1193EventLis2 = this.eip1193EventListeners.get('disconnect')) == null || _this$eip1193EventLis2.forEach(listener => listener(error));
3232
+ this.emit('disconnect', error);
3264
3233
  });
3265
3234
  client.onDefaultChainIdChanged(chainId => {
3266
- var _this$eip1193EventLis3;
3267
- //this.emit('chainChanged', chainId)
3268
- (_this$eip1193EventLis3 = this.eip1193EventListeners.get('chainChanged')) == null || _this$eip1193EventLis3.forEach(listener => listener(chainId));
3235
+ this.emit('chainChanged', chainId);
3269
3236
  });
3270
3237
  client.onAccountsChanged(accounts => {
3271
- var _this$eip1193EventLis4;
3272
- //this.emit('accountsChanged', accounts)
3273
- (_this$eip1193EventLis4 = this.eip1193EventListeners.get('accountsChanged')) == null || _this$eip1193EventLis4.forEach(listener => listener(accounts));
3238
+ this.emit('accountsChanged', accounts);
3274
3239
  });
3275
3240
 
3276
3241
  // NOTICE: We don't emit 'open' and 'close' events
@@ -3287,29 +3252,6 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
3287
3252
  // Create a utils instance
3288
3253
  this.utils = new WalletUtils(this.signer);
3289
3254
  }
3290
- async on(event, listener) {
3291
- if (EIP1193EventTypes.includes(event)) {
3292
- const listeners = this.eip1193EventListeners.get(event) || new Set();
3293
- listeners.add(listener);
3294
- this.eip1193EventListeners.set(event, listeners);
3295
- return this;
3296
- }
3297
- return super.on(event, listener);
3298
- }
3299
- async off(event, listener) {
3300
- if (EIP1193EventTypes.includes(event)) {
3301
- const listeners = this.eip1193EventListeners.get(event);
3302
- if (listeners) {
3303
- if (listener) {
3304
- listeners.delete(listener);
3305
- } else {
3306
- listeners.clear();
3307
- }
3308
- }
3309
- return this;
3310
- }
3311
- return super.off(event, listener);
3312
- }
3313
3255
  getSigner(chainId) {
3314
3256
  return this.signer.getSigner(chainId);
3315
3257
  }
@@ -3402,7 +3344,7 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
3402
3344
  }
3403
3345
  const useChainId = this.toChainId(chainId);
3404
3346
  if (!this.singleNetworkProviders[useChainId]) {
3405
- this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId, this.options);
3347
+ this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId);
3406
3348
  }
3407
3349
  return this.singleNetworkProviders[useChainId];
3408
3350
  }
@@ -3422,26 +3364,11 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
3422
3364
  }
3423
3365
  return provider;
3424
3366
  }
3425
- async _perform(req) {
3426
- var _provider$getRpcReque;
3427
- const {
3428
- method
3429
- } = req,
3430
- args = _objectWithoutPropertiesLoose(req, _excluded);
3431
- const provider = await this._getSubprovider();
3432
- const prepared = (_provider$getRpcReque = provider.getRpcRequest(req)) != null ? _provider$getRpcReque : {
3433
- method,
3434
- args: Object.values(args)
3435
- };
3436
- if (!prepared) {
3437
- throw new Error(`Unsupported method ${req.method}`);
3438
- }
3439
- return provider.send(prepared.method, prepared.args);
3440
- }
3441
3367
  async perform(method, params) {
3368
+ var _provider$prepareRequ;
3442
3369
  // First we check if the method should be handled by the client
3443
3370
  if (method === 'eth_chainId') {
3444
- return ethers.ethers.toQuantity(await this.useChainId());
3371
+ return ethers.ethers.utils.hexValue(await this.useChainId());
3445
3372
  }
3446
3373
  if (method === 'eth_accounts') {
3447
3374
  return [this.client.getAddress()];
@@ -3461,15 +3388,17 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
3461
3388
  method === 'sequence_sign' || method === 'sequence_signTypedData_v4') {
3462
3389
  // We pass the chainId to the client, if we don't pass one
3463
3390
  // the client will use its own default chainId
3464
- return this.client.request({
3391
+ return this.client.send({
3465
3392
  method,
3466
- params,
3467
- chainId: this.getChainId()
3468
- });
3393
+ params
3394
+ }, this.getChainId());
3469
3395
  }
3470
- return this._perform(_extends({
3471
- method
3472
- }, params));
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]);
3473
3402
  }
3474
3403
  send(method, params) {
3475
3404
  return this.perform(method, params);
@@ -3477,18 +3406,14 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
3477
3406
  request(request) {
3478
3407
  return this.perform(request.method, request.params);
3479
3408
  }
3480
- async _detectNetwork() {
3409
+ async detectNetwork() {
3481
3410
  const chainId = this.client.getChainId();
3482
- const found = network.findNetworkConfig(this.networks, chainId);
3483
- if (!found) {
3411
+ const network$1 = network.findNetworkConfig(this.networks, chainId);
3412
+ if (!network$1) {
3484
3413
  throw new Error(`Unknown network ${chainId}`);
3485
3414
  }
3486
- const network$1 = new ethers.ethers.Network(found.name, found.chainId);
3487
3415
  return network$1;
3488
3416
  }
3489
- async detectNetwork() {
3490
- return this._detectNetwork();
3491
- }
3492
3417
 
3493
3418
  // Override most of the methods, so we add support for an optional chainId
3494
3419
  // argument, which is used to select the provider to use.
@@ -3505,9 +3430,9 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
3505
3430
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3506
3431
  return provider.getBlockNumber();
3507
3432
  }
3508
- async getFeeData(optionals) {
3433
+ async getGasPrice(optionals) {
3509
3434
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3510
- return await provider.getFeeData();
3435
+ return provider.getGasPrice();
3511
3436
  }
3512
3437
  async getBalance(addressOrName, blockTag, optionals) {
3513
3438
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
@@ -3521,21 +3446,21 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
3521
3446
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3522
3447
  return provider.getCode(addressOrName, blockTag);
3523
3448
  }
3524
- async getStorage(addressOrName, position, blockTag, optionals) {
3449
+ async getStorageAt(addressOrName, position, blockTag, optionals) {
3525
3450
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3526
- return provider.getStorage(addressOrName, position, blockTag);
3451
+ return provider.getStorageAt(addressOrName, position, blockTag);
3527
3452
  }
3528
- async call(transaction, optionals) {
3453
+ async call(transaction, blockTag, optionals) {
3529
3454
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3530
- return provider.call(transaction);
3455
+ return provider.call(transaction, blockTag);
3531
3456
  }
3532
3457
  async estimateGas(transaction, optionals) {
3533
3458
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3534
3459
  return provider.estimateGas(transaction);
3535
3460
  }
3536
- async getBlock(blockHashOrBlockTag, prefetchTxs, optionals) {
3461
+ async getBlock(blockHashOrBlockTag, optionals) {
3537
3462
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3538
- return provider.getBlock(blockHashOrBlockTag, prefetchTxs);
3463
+ return provider.getBlock(blockHashOrBlockTag);
3539
3464
  }
3540
3465
  async getTransaction(transactionHash, optionals) {
3541
3466
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
@@ -3562,7 +3487,7 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
3562
3487
  return provider.getResolver(name);
3563
3488
  }
3564
3489
  async resolveName(name) {
3565
- if (ethers.ethers.isAddress(await name)) {
3490
+ if (ethers.ethers.utils.isAddress(await name)) {
3566
3491
  return name;
3567
3492
  }
3568
3493
  if (!(await this.supportsENS())) {
@@ -3595,7 +3520,7 @@ SequenceProvider.is = provider => {
3595
3520
  };
3596
3521
  function normalizeChainId(chainId) {
3597
3522
  if (typeof chainId === 'object') return normalizeChainId(chainId.chainId);
3598
- return Number(BigInt(chainId));
3523
+ return ethers.ethers.BigNumber.from(chainId).toNumber();
3599
3524
  }
3600
3525
 
3601
3526
  /**
@@ -3608,8 +3533,8 @@ function normalizeChainId(chainId) {
3608
3533
  * NOTICE: These networks won't support ENS unless they are the mainnet.
3609
3534
  */
3610
3535
  class SingleNetworkSequenceProvider extends SequenceProvider {
3611
- constructor(client, providerFor, chainId, options) {
3612
- super(client, providerFor, undefined, options);
3536
+ constructor(client, providerFor, chainId) {
3537
+ super(client, providerFor);
3613
3538
  this.chainId = chainId;
3614
3539
  this._isSingleNetworkSequenceProvider = true;
3615
3540
  }
@@ -3628,12 +3553,11 @@ class SingleNetworkSequenceProvider extends SequenceProvider {
3628
3553
  }
3629
3554
  async getNetwork() {
3630
3555
  const networks = await this.client.getNetworks();
3631
- const found = network.findNetworkConfig(networks, this.chainId);
3632
- if (!found) {
3556
+ const res = network.findNetworkConfig(networks, this.chainId);
3557
+ if (!res) {
3633
3558
  throw new Error(`Unsupported network ${this.chainId}`);
3634
3559
  }
3635
- const network$1 = new ethers.ethers.Network(found.name, found.chainId);
3636
- return network$1;
3560
+ return res;
3637
3561
  }
3638
3562
 
3639
3563
  /**
@@ -3696,6 +3620,55 @@ const setupAnalytics = (projectAccessKey, server) => {
3696
3620
  });
3697
3621
  };
3698
3622
 
3623
+ var packageJson = {
3624
+ name: "@0xsequence/provider",
3625
+ version: "0.0.0-20240704152116",
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
+
3699
3672
  /**
3700
3673
  * This session class is meant to persist the state of the wallet connection
3701
3674
  * whitin the dapp. This enables the client to retain the wallet address (and some more)
@@ -3811,7 +3784,7 @@ class SequenceClient {
3811
3784
  });
3812
3785
  this.transport.on('connect', response => {
3813
3786
  var _this$callbacks$conne;
3814
- const chainIdHex = ethers.ethers.toQuantity(this.getChainId());
3787
+ const chainIdHex = ethers.ethers.utils.hexValue(this.getChainId());
3815
3788
  (_this$callbacks$conne = this.callbacks.connect) == null || _this$callbacks$conne.forEach(cb => cb(_extends({}, response, {
3816
3789
  // Ignore the full connect response
3817
3790
  // use the chainId defined locally
@@ -3847,7 +3820,7 @@ class SequenceClient {
3847
3820
  // instead we handle it locally, so we listen for changes in the store
3848
3821
  this.defaultChainId.onDefaultChainIdChanged(chainId => {
3849
3822
  var _this$callbacks$chain2;
3850
- const chainIdHex = ethers.ethers.toQuantity(chainId);
3823
+ const chainIdHex = ethers.ethers.utils.hexValue(chainId);
3851
3824
  (_this$callbacks$chain2 = this.callbacks.chainChanged) == null || _this$callbacks$chain2.forEach(cb => cb(chainIdHex));
3852
3825
  });
3853
3826
  if (options != null && options.projectAccessKey) {
@@ -3960,7 +3933,7 @@ class SequenceClient {
3960
3933
  type: 'connect',
3961
3934
  options: _extends({}, options, {
3962
3935
  networkId: this.getChainId(),
3963
- clientVersion: core.VERSION
3936
+ clientVersion: packageJson.version
3964
3937
  })
3965
3938
  });
3966
3939
  const connectDetails = await this.transport.waitUntilConnected().catch(error => {
@@ -3980,7 +3953,7 @@ class SequenceClient {
3980
3953
  // Normalize chainId into a decimal string
3981
3954
  // TODO: Remove this once wallet-webapp returns chainId as a string
3982
3955
  if (connectDetails.chainId) {
3983
- connectDetails.chainId = BigInt(connectDetails.chainId).toString();
3956
+ connectDetails.chainId = ethers.ethers.BigNumber.from(connectDetails.chainId).toString();
3984
3957
  }
3985
3958
  if (connectDetails.connected) {
3986
3959
  var _connectDetails$sessi;
@@ -4006,17 +3979,33 @@ class SequenceClient {
4006
3979
 
4007
3980
  // Higher level API
4008
3981
 
4009
- async request(request) {
3982
+ // Working with sendAsync is less idiomatic
3983
+ // but transport uses it instead of send, so we wrap it
3984
+ send(request, chainId) {
4010
3985
  // Internally when sending requests we use `legacy_sign`
4011
3986
  // to avoid the default EIP6492 behavior overriding an explicit
4012
3987
  // "legacy sign" request, so we map the method here.
4013
3988
  request.method = this.mapSignMethod(request.method);
4014
- return this.transport.request(request);
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
+ });
4015
4004
  }
4016
4005
  async getNetworks(pull) {
4017
4006
  const connectedSession = this.session.connectedSession();
4018
4007
  if (pull) {
4019
- connectedSession.networks = await this.request({
4008
+ connectedSession.networks = await this.send({
4020
4009
  method: 'sequence_getNetworks'
4021
4010
  });
4022
4011
  this.session.setSession(connectedSession);
@@ -4073,16 +4062,14 @@ class SequenceClient {
4073
4062
  }
4074
4063
  });
4075
4064
 
4076
- // If the message is a string, even if it looks like a BytesLike string we need to represent it as utf8 bytes.
4077
- // ie. '0x1234' is a string, '0x1234' is a bytesLike string which is 2 bytes but we must sign the full '0x1234' as 6 utf8 bytes
4078
- message = ethers.ethers.hexlify(typeof message === 'string' ? ethers.ethers.toUtf8Bytes(message) : message);
4065
+ // Serialize a BytesLike or string message into a hex string before sending
4066
+ message = ethers.ethers.utils.hexlify(messageToBytes(message));
4079
4067
 
4080
4068
  // Address is ignored by the wallet webapp
4081
- return this.request({
4069
+ return this.send({
4082
4070
  method,
4083
- params: [message, this.getAddress()],
4084
- chainId: options == null ? void 0 : options.chainId
4085
- });
4071
+ params: [message, this.getAddress()]
4072
+ }, options == null ? void 0 : options.chainId);
4086
4073
  }
4087
4074
  async signTypedData(typedData, options) {
4088
4075
  var _this$analytics5;
@@ -4090,7 +4077,7 @@ class SequenceClient {
4090
4077
 
4091
4078
  // TODO: Stop using ethers for this, this is the only place where we use it
4092
4079
  // and it makes the client depend on ethers.
4093
- const encoded = ethers.ethers.TypedDataEncoder.getPayload(typedData.domain, typedData.types, typedData.message);
4080
+ const encoded = ethers.ethers.utils._TypedDataEncoder.getPayload(typedData.domain, typedData.types, typedData.message);
4094
4081
 
4095
4082
  // The sign typed data will use one of the following chainIds, in order:
4096
4083
  // - The one provided in the options
@@ -4103,11 +4090,10 @@ class SequenceClient {
4103
4090
  chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
4104
4091
  }
4105
4092
  });
4106
- return this.request({
4093
+ return this.send({
4107
4094
  method,
4108
- params: [this.getAddress(), encoded],
4109
- chainId: (options == null ? void 0 : options.chainId) || typedData.domain.chainId && Number(BigInt(typedData.domain.chainId)) || this.getChainId()
4110
- });
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());
4111
4097
  }
4112
4098
  async sendTransaction(tx, options) {
4113
4099
  var _this$analytics6;
@@ -4119,24 +4105,22 @@ class SequenceClient {
4119
4105
  chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
4120
4106
  }
4121
4107
  });
4122
- return this.request({
4108
+ return this.send({
4123
4109
  method: 'eth_sendTransaction',
4124
- params: [extendedTxs],
4125
- chainId: options == null ? void 0 : options.chainId
4126
- });
4110
+ params: [extendedTxs]
4111
+ }, options == null ? void 0 : options.chainId);
4127
4112
  }
4128
4113
  async getWalletContext() {
4129
- return this.request({
4114
+ return this.send({
4130
4115
  method: 'sequence_getWalletContext'
4131
4116
  });
4132
4117
  }
4133
4118
  async getOnchainWalletConfig(options) {
4134
4119
  // NOTICE: sequence_getWalletConfig sends the chainId as a param
4135
- const res = await this.request({
4120
+ const res = await this.send({
4136
4121
  method: 'sequence_getWalletConfig',
4137
- params: [(options == null ? void 0 : options.chainId) || this.getChainId()],
4138
- chainId: options == null ? void 0 : options.chainId
4139
- });
4122
+ params: [(options == null ? void 0 : options.chainId) || this.getChainId()]
4123
+ }, options == null ? void 0 : options.chainId);
4140
4124
  return Array.isArray(res) ? res[0] : res;
4141
4125
  }
4142
4126
 
@@ -4215,11 +4199,9 @@ const initWallet = (projectAccessKey, partialConfig) => {
4215
4199
  if (!rpcUrl) {
4216
4200
  throw new Error(`no rpcUrl found for chainId: ${chainId}`);
4217
4201
  }
4218
- rpcProviders[chainId] = new network.JsonRpcProvider(rpcUrl, {
4219
- middlewares: [network.loggingProviderMiddleware, network.exceptionProviderMiddleware, new network.CachedProvider()]
4220
- }, {
4221
- cacheTimeout: -1
4222
- });
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);
4223
4205
  }
4224
4206
  return rpcProviders[chainId];
4225
4207
  };