@0xsequence/provider 1.10.15 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/0xsequence-provider.cjs.dev.js +656 -648
  2. package/dist/0xsequence-provider.cjs.prod.js +656 -648
  3. package/dist/0xsequence-provider.esm.js +660 -652
  4. package/dist/declarations/src/client.d.ts +7 -3
  5. package/dist/declarations/src/provider.d.ts +31 -22
  6. package/dist/declarations/src/signer.d.ts +15 -14
  7. package/dist/declarations/src/transports/base-provider-transport.d.ts +6 -2
  8. package/dist/declarations/src/transports/base-wallet-transport.d.ts +6 -2
  9. package/dist/declarations/src/transports/mux-transport/mux-message-provider.d.ts +5 -2
  10. package/dist/declarations/src/transports/wallet-request-handler.d.ts +7 -6
  11. package/dist/declarations/src/types.d.ts +6 -11
  12. package/dist/declarations/src/utils/index.d.ts +3 -3
  13. package/dist/declarations/src/utils.d.ts +7 -7
  14. package/package.json +12 -12
  15. package/src/client.ts +29 -51
  16. package/src/eip191exceptions.ts +2 -2
  17. package/src/extended.ts +5 -5
  18. package/src/init.ts +9 -10
  19. package/src/provider.ts +112 -66
  20. package/src/signer.ts +38 -43
  21. package/src/transactions.ts +4 -4
  22. package/src/transports/base-provider-transport.ts +19 -23
  23. package/src/transports/base-wallet-transport.ts +22 -13
  24. package/src/transports/mux-transport/mux-message-provider.ts +5 -6
  25. package/src/transports/proxy-transport/proxy-message-provider.ts +5 -2
  26. package/src/transports/wallet-request-handler.ts +91 -130
  27. package/src/transports/window-transport/window-message-handler.ts +15 -3
  28. package/src/transports/window-transport/window-message-provider.ts +1 -1
  29. package/src/types.ts +8 -11
  30. package/src/utils/index.ts +4 -4
  31. package/src/utils.ts +16 -18
@@ -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
  }
@@ -1880,7 +1886,13 @@ 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, (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
+ });
1884
1896
  } catch (err) {
1885
1897
  // event is not a ProviderMessage JSON object, skip
1886
1898
  return;
@@ -1919,7 +1931,6 @@ class WindowMessageHandler extends BaseWalletTransport {
1919
1931
 
1920
1932
  // record open details (sessionId + default network) from the window url
1921
1933
  const {
1922
- pathname,
1923
1934
  search: rawParams
1924
1935
  } = new URL(windowHref || window.location.href);
1925
1936
  let session = this.getWindowTransportSession(rawParams);
@@ -2003,6 +2014,9 @@ class WindowMessageHandler extends BaseWalletTransport {
2003
2014
  }
2004
2015
  }
2005
2016
  }
2017
+ const isBigNumberSerialized = value => {
2018
+ return typeof value === 'object' && value.type === 'BigNumber' && ethers.ethers.isHexString(value.hex);
2019
+ };
2006
2020
 
2007
2021
  function isMuxTransportTemplate(obj) {
2008
2022
  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') && (
@@ -2053,13 +2067,6 @@ class MuxMessageProvider {
2053
2067
  }
2054
2068
  this.messageProviders.forEach(m => m.openWallet(path, intent, networkId));
2055
2069
  };
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
2070
  this.sendMessageRequest = async function (message) {
2064
2071
  if (_this.provider) {
2065
2072
  return _this.provider.sendMessageRequest(message);
@@ -2156,6 +2163,12 @@ class MuxMessageProvider {
2156
2163
  }
2157
2164
  return true;
2158
2165
  }
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
+ }
2159
2172
  sendMessage(message) {
2160
2173
  if (!message.idx || message.idx <= 0) {
2161
2174
  throw new Error('message idx is empty');
@@ -2190,7 +2203,7 @@ function fromExtended(transaction) {
2190
2203
 
2191
2204
  const SIGNER_READY_TIMEOUT = 10000;
2192
2205
  class WalletRequestHandler {
2193
- constructor(_account, prompter, networks) {
2206
+ constructor(account, prompter, networks) {
2194
2207
  var _this = this;
2195
2208
  // signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
2196
2209
  // value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
@@ -2223,417 +2236,6 @@ class WalletRequestHandler {
2223
2236
  }
2224
2237
  return promptConnectDetails;
2225
2238
  };
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
2239
  this.isSignedIn = async function () {
2638
2240
  await _this.signerReady();
2639
2241
  return !!_this.account;
@@ -2645,7 +2247,7 @@ class WalletRequestHandler {
2645
2247
  }
2646
2248
  return _this.account;
2647
2249
  };
2648
- this.account = _account;
2250
+ this.account = account;
2649
2251
  this.prompter = prompter;
2650
2252
  this.networks = networks;
2651
2253
  }
@@ -2729,7 +2331,7 @@ class WalletRequestHandler {
2729
2331
  const chainId = network.findSupportedNetwork(networkId).chainId;
2730
2332
  const connectDetails = {
2731
2333
  connected: true,
2732
- chainId: ethers.ethers.utils.hexValue(chainId)
2334
+ chainId: ethers.ethers.toQuantity(chainId)
2733
2335
  };
2734
2336
  if (options && options.authorize) {
2735
2337
  // Perform ethauth eip712 request and construct the ConnectDetails response
@@ -2764,20 +2366,415 @@ class WalletRequestHandler {
2764
2366
  // sendMessageRequest will unwrap the ProviderMessageRequest and send it to the JsonRpcHandler
2765
2367
  // (aka, the signer in this instance) and then responds with a wrapped response of
2766
2368
  // 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?
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
+ }
2771
2408
 
2772
- const responseMessage = _extends({}, message, {
2773
- data: response
2774
- });
2409
+ // wallet account
2410
+ const account = this.account;
2411
+ if (!account) {
2412
+ throw new Error('WalletRequestHandler: wallet account is not configured');
2413
+ }
2775
2414
 
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
- });
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(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 === null ? null : 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
+ }
2750
+
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
+ }
2766
+
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
+ utils.logger.error(err);
2773
+ throw {
2774
+ message: err == null ? void 0 : err.message,
2775
+ code: 4001
2776
+ };
2777
+ }
2781
2778
  }
2782
2779
  on(event, fn) {
2783
2780
  this.events.on(event, fn);
@@ -2865,7 +2862,7 @@ class WalletRequestHandler {
2865
2862
  this.events.emit('disconnect', undefined, origin);
2866
2863
  }
2867
2864
  notifyChainChanged(chainId, origin) {
2868
- this.events.emit('chainChanged', ethers.ethers.utils.hexValue(chainId), origin);
2865
+ this.events.emit('chainChanged', ethers.ethers.toQuantity(chainId), origin);
2869
2866
  }
2870
2867
  async notifyNetworks(networks) {
2871
2868
  const n = networks || (await this.getNetworks(true));
@@ -2873,7 +2870,7 @@ class WalletRequestHandler {
2873
2870
  if (n.length > 0) {
2874
2871
  const defaultNetwork = n.find(network => network.chainId === this.defaultChainId());
2875
2872
  if (defaultNetwork) {
2876
- this.events.emit('chainChanged', ethers.ethers.utils.hexValue(defaultNetwork.chainId));
2873
+ this.events.emit('chainChanged', ethers.ethers.toQuantity(defaultNetwork.chainId));
2877
2874
  }
2878
2875
  } else {
2879
2876
  this.events.emit('chainChanged', '0x0');
@@ -2942,6 +2939,19 @@ function getLegacyWalletState(chainId, status) {
2942
2939
  }
2943
2940
  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
2941
 
2942
+ function _objectWithoutPropertiesLoose(source, excluded) {
2943
+ if (source == null) return {};
2944
+ var target = {};
2945
+ var sourceKeys = Object.keys(source);
2946
+ var key, i;
2947
+ for (i = 0; i < sourceKeys.length; i++) {
2948
+ key = sourceKeys[i];
2949
+ if (excluded.indexOf(key) >= 0) continue;
2950
+ target[key] = source[key];
2951
+ }
2952
+ return target;
2953
+ }
2954
+
2945
2955
  class SequenceSigner {
2946
2956
  get utils() {
2947
2957
  return this.provider.utils;
@@ -2950,7 +2960,6 @@ class SequenceSigner {
2950
2960
  this.client = client;
2951
2961
  this.provider = provider;
2952
2962
  this.singleNetworkSigners = {};
2953
- this._isSigner = true;
2954
2963
  this._isSequenceSigner = true;
2955
2964
  }
2956
2965
  async getAddress() {
@@ -3020,12 +3029,17 @@ class SequenceSigner {
3020
3029
  });
3021
3030
  const provider = this.getProvider(chainId);
3022
3031
  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
3032
+ const result = await new Promise(resolve => {
3033
+ const check = async function check() {
3034
+ const tx = await provider.getTransaction(txHash);
3035
+ if (tx !== null) {
3036
+ return resolve(tx);
3037
+ }
3038
+ await provider.once('block', check);
3039
+ };
3040
+ check();
3028
3041
  });
3042
+ return result;
3029
3043
  } catch (err) {
3030
3044
  err.transactionHash = txHash;
3031
3045
  throw err;
@@ -3047,15 +3061,12 @@ class SequenceSigner {
3047
3061
  async estimateGas(transaction, optionals) {
3048
3062
  return this.getProvider(optionals == null ? void 0 : optionals.chainId).estimateGas(transaction);
3049
3063
  }
3050
- async call(transaction, blockTag, optionals) {
3051
- return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction, blockTag);
3064
+ async call(transaction, optionals) {
3065
+ return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction);
3052
3066
  }
3053
3067
  getChainId() {
3054
3068
  return Promise.resolve(this.client.getChainId());
3055
3069
  }
3056
- async getGasPrice(optionals) {
3057
- return this.getProvider(optionals == null ? void 0 : optionals.chainId).getGasPrice();
3058
- }
3059
3070
  async getFeeData(optionals) {
3060
3071
  return this.getProvider(optionals == null ? void 0 : optionals.chainId).getFeeData();
3061
3072
  }
@@ -3063,7 +3074,7 @@ class SequenceSigner {
3063
3074
  const res = await this.provider.resolveName(name);
3064
3075
 
3065
3076
  // For some reason ethers.Signer expects this to return `string`
3066
- // but ethers.providers.Provider expects this to return `string | null`.
3077
+ // but ethers.Provider expects this to return `string | null`.
3067
3078
  // The signer doesn't have any other source of information, so we'll
3068
3079
  // fail if the provider doesn't return a result.
3069
3080
  if (res === null) {
@@ -3074,6 +3085,12 @@ class SequenceSigner {
3074
3085
  _checkProvider(_operation) {
3075
3086
  // We always have a provider, so this is a noop
3076
3087
  }
3088
+ getNonce(_blockTag) {
3089
+ throw new Error('SequenceSigner does not support getNonce');
3090
+ }
3091
+ populateCall(_transaction) {
3092
+ throw new Error('SequenceSigner does not support populateCall');
3093
+ }
3077
3094
  populateTransaction(_transaction) {
3078
3095
  throw new Error('SequenceSigner does not support populateTransaction');
3079
3096
  }
@@ -3211,31 +3228,43 @@ class WalletUtils {
3211
3228
  // recoverAddress()
3212
3229
  }
3213
3230
 
3214
- class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3215
- constructor(client, providerFor, networks = network.allNetworks) {
3231
+ const _excluded = ["method"];
3232
+ const EIP1193EventTypes = ['connect', 'disconnect', 'chainChanged', 'accountsChanged'];
3233
+ class SequenceProvider extends ethers.ethers.AbstractProvider {
3234
+ constructor(client, providerFor, networks = network.allNetworks, options) {
3216
3235
  // We support a lot of networks
3217
3236
  // but we start with the default one
3218
- super(client.getChainId());
3237
+ super(client.getChainId(), options);
3219
3238
 
3220
3239
  // Emit events as defined by EIP-1193
3221
3240
  this.client = client;
3222
3241
  this.providerFor = providerFor;
3223
3242
  this.networks = networks;
3243
+ this.options = options;
3224
3244
  this.singleNetworkProviders = {};
3225
3245
  this._isSequenceProvider = true;
3226
3246
  this.utils = void 0;
3227
3247
  this.signer = void 0;
3248
+ this.eip1193EventListeners = new Map();
3228
3249
  client.onConnect(details => {
3229
- this.emit('connect', details);
3250
+ var _this$eip1193EventLis;
3251
+ //this.emit('connect', details)
3252
+ (_this$eip1193EventLis = this.eip1193EventListeners.get('connect')) == null || _this$eip1193EventLis.forEach(listener => listener(details));
3230
3253
  });
3231
3254
  client.onDisconnect(error => {
3232
- this.emit('disconnect', error);
3255
+ var _this$eip1193EventLis2;
3256
+ //this.emit('disconnect', error)
3257
+ (_this$eip1193EventLis2 = this.eip1193EventListeners.get('disconnect')) == null || _this$eip1193EventLis2.forEach(listener => listener(error));
3233
3258
  });
3234
3259
  client.onDefaultChainIdChanged(chainId => {
3235
- this.emit('chainChanged', chainId);
3260
+ var _this$eip1193EventLis3;
3261
+ //this.emit('chainChanged', chainId)
3262
+ (_this$eip1193EventLis3 = this.eip1193EventListeners.get('chainChanged')) == null || _this$eip1193EventLis3.forEach(listener => listener(chainId));
3236
3263
  });
3237
3264
  client.onAccountsChanged(accounts => {
3238
- this.emit('accountsChanged', accounts);
3265
+ var _this$eip1193EventLis4;
3266
+ //this.emit('accountsChanged', accounts)
3267
+ (_this$eip1193EventLis4 = this.eip1193EventListeners.get('accountsChanged')) == null || _this$eip1193EventLis4.forEach(listener => listener(accounts));
3239
3268
  });
3240
3269
 
3241
3270
  // NOTICE: We don't emit 'open' and 'close' events
@@ -3252,6 +3281,29 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3252
3281
  // Create a utils instance
3253
3282
  this.utils = new WalletUtils(this.signer);
3254
3283
  }
3284
+ async on(event, listener) {
3285
+ if (EIP1193EventTypes.includes(event)) {
3286
+ const listeners = this.eip1193EventListeners.get(event) || new Set();
3287
+ listeners.add(listener);
3288
+ this.eip1193EventListeners.set(event, listeners);
3289
+ return this;
3290
+ }
3291
+ return super.on(event, listener);
3292
+ }
3293
+ async off(event, listener) {
3294
+ if (EIP1193EventTypes.includes(event)) {
3295
+ const listeners = this.eip1193EventListeners.get(event);
3296
+ if (listeners) {
3297
+ if (listener) {
3298
+ listeners.delete(listener);
3299
+ } else {
3300
+ listeners.clear();
3301
+ }
3302
+ }
3303
+ return this;
3304
+ }
3305
+ return super.off(event, listener);
3306
+ }
3255
3307
  getSigner(chainId) {
3256
3308
  return this.signer.getSigner(chainId);
3257
3309
  }
@@ -3344,7 +3396,7 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3344
3396
  }
3345
3397
  const useChainId = this.toChainId(chainId);
3346
3398
  if (!this.singleNetworkProviders[useChainId]) {
3347
- this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId);
3399
+ this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId, this.options);
3348
3400
  }
3349
3401
  return this.singleNetworkProviders[useChainId];
3350
3402
  }
@@ -3364,11 +3416,26 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3364
3416
  }
3365
3417
  return provider;
3366
3418
  }
3419
+ async _perform(req) {
3420
+ var _provider$getRpcReque;
3421
+ const {
3422
+ method
3423
+ } = req,
3424
+ args = _objectWithoutPropertiesLoose(req, _excluded);
3425
+ const provider = await this._getSubprovider();
3426
+ const prepared = (_provider$getRpcReque = provider.getRpcRequest(req)) != null ? _provider$getRpcReque : {
3427
+ method,
3428
+ args: Object.values(args)
3429
+ };
3430
+ if (!prepared) {
3431
+ throw new Error(`Unsupported method ${req.method}`);
3432
+ }
3433
+ return provider.send(prepared.method, prepared.args);
3434
+ }
3367
3435
  async perform(method, params) {
3368
- var _provider$prepareRequ;
3369
3436
  // First we check if the method should be handled by the client
3370
3437
  if (method === 'eth_chainId') {
3371
- return ethers.ethers.utils.hexValue(await this.useChainId());
3438
+ return ethers.ethers.toQuantity(await this.useChainId());
3372
3439
  }
3373
3440
  if (method === 'eth_accounts') {
3374
3441
  return [this.client.getAddress()];
@@ -3388,17 +3455,15 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3388
3455
  method === 'sequence_sign' || method === 'sequence_signTypedData_v4') {
3389
3456
  // We pass the chainId to the client, if we don't pass one
3390
3457
  // the client will use its own default chainId
3391
- return this.client.send({
3458
+ return this.client.request({
3392
3459
  method,
3393
- params
3394
- }, this.getChainId());
3460
+ params,
3461
+ chainId: this.getChainId()
3462
+ });
3395
3463
  }
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]);
3464
+ return this._perform(_extends({
3465
+ method
3466
+ }, params));
3402
3467
  }
3403
3468
  send(method, params) {
3404
3469
  return this.perform(method, params);
@@ -3406,14 +3471,18 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3406
3471
  request(request) {
3407
3472
  return this.perform(request.method, request.params);
3408
3473
  }
3409
- async detectNetwork() {
3474
+ async _detectNetwork() {
3410
3475
  const chainId = this.client.getChainId();
3411
- const network$1 = network.findNetworkConfig(this.networks, chainId);
3412
- if (!network$1) {
3476
+ const found = network.findNetworkConfig(this.networks, chainId);
3477
+ if (!found) {
3413
3478
  throw new Error(`Unknown network ${chainId}`);
3414
3479
  }
3480
+ const network$1 = new ethers.ethers.Network(found.name, found.chainId);
3415
3481
  return network$1;
3416
3482
  }
3483
+ async detectNetwork() {
3484
+ return this._detectNetwork();
3485
+ }
3417
3486
 
3418
3487
  // Override most of the methods, so we add support for an optional chainId
3419
3488
  // argument, which is used to select the provider to use.
@@ -3430,9 +3499,9 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3430
3499
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3431
3500
  return provider.getBlockNumber();
3432
3501
  }
3433
- async getGasPrice(optionals) {
3502
+ async getFeeData(optionals) {
3434
3503
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3435
- return provider.getGasPrice();
3504
+ return provider.getFeeData();
3436
3505
  }
3437
3506
  async getBalance(addressOrName, blockTag, optionals) {
3438
3507
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
@@ -3446,21 +3515,21 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3446
3515
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3447
3516
  return provider.getCode(addressOrName, blockTag);
3448
3517
  }
3449
- async getStorageAt(addressOrName, position, blockTag, optionals) {
3518
+ async getStorage(addressOrName, position, blockTag, optionals) {
3450
3519
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3451
- return provider.getStorageAt(addressOrName, position, blockTag);
3520
+ return provider.getStorage(addressOrName, position, blockTag);
3452
3521
  }
3453
- async call(transaction, blockTag, optionals) {
3522
+ async call(transaction, optionals) {
3454
3523
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3455
- return provider.call(transaction, blockTag);
3524
+ return provider.call(transaction);
3456
3525
  }
3457
3526
  async estimateGas(transaction, optionals) {
3458
3527
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3459
3528
  return provider.estimateGas(transaction);
3460
3529
  }
3461
- async getBlock(blockHashOrBlockTag, optionals) {
3530
+ async getBlock(blockHashOrBlockTag, prefetchTxs, optionals) {
3462
3531
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
3463
- return provider.getBlock(blockHashOrBlockTag);
3532
+ return provider.getBlock(blockHashOrBlockTag, prefetchTxs);
3464
3533
  }
3465
3534
  async getTransaction(transactionHash, optionals) {
3466
3535
  const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
@@ -3487,7 +3556,7 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
3487
3556
  return provider.getResolver(name);
3488
3557
  }
3489
3558
  async resolveName(name) {
3490
- if (ethers.ethers.utils.isAddress(await name)) {
3559
+ if (ethers.ethers.isAddress(name)) {
3491
3560
  return name;
3492
3561
  }
3493
3562
  if (!(await this.supportsENS())) {
@@ -3520,7 +3589,7 @@ SequenceProvider.is = provider => {
3520
3589
  };
3521
3590
  function normalizeChainId(chainId) {
3522
3591
  if (typeof chainId === 'object') return normalizeChainId(chainId.chainId);
3523
- return ethers.ethers.BigNumber.from(chainId).toNumber();
3592
+ return Number(chainId);
3524
3593
  }
3525
3594
 
3526
3595
  /**
@@ -3533,8 +3602,8 @@ function normalizeChainId(chainId) {
3533
3602
  * NOTICE: These networks won't support ENS unless they are the mainnet.
3534
3603
  */
3535
3604
  class SingleNetworkSequenceProvider extends SequenceProvider {
3536
- constructor(client, providerFor, chainId) {
3537
- super(client, providerFor);
3605
+ constructor(client, providerFor, chainId, options) {
3606
+ super(client, providerFor, undefined, options);
3538
3607
  this.chainId = chainId;
3539
3608
  this._isSingleNetworkSequenceProvider = true;
3540
3609
  }
@@ -3553,11 +3622,11 @@ class SingleNetworkSequenceProvider extends SequenceProvider {
3553
3622
  }
3554
3623
  async getNetwork() {
3555
3624
  const networks = await this.client.getNetworks();
3556
- const res = network.findNetworkConfig(networks, this.chainId);
3557
- if (!res) {
3625
+ const found = network.findNetworkConfig(networks, this.chainId);
3626
+ if (!found) {
3558
3627
  throw new Error(`Unsupported network ${this.chainId}`);
3559
3628
  }
3560
- return res;
3629
+ return new ethers.ethers.Network(found.name, found.chainId);
3561
3630
  }
3562
3631
 
3563
3632
  /**
@@ -3620,55 +3689,6 @@ const setupAnalytics = (projectAccessKey, server) => {
3620
3689
  });
3621
3690
  };
3622
3691
 
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
3692
  /**
3673
3693
  * This session class is meant to persist the state of the wallet connection
3674
3694
  * whitin the dapp. This enables the client to retain the wallet address (and some more)
@@ -3784,7 +3804,7 @@ class SequenceClient {
3784
3804
  });
3785
3805
  this.transport.on('connect', response => {
3786
3806
  var _this$callbacks$conne;
3787
- const chainIdHex = ethers.ethers.utils.hexValue(this.getChainId());
3807
+ const chainIdHex = ethers.ethers.toQuantity(this.getChainId());
3788
3808
  (_this$callbacks$conne = this.callbacks.connect) == null || _this$callbacks$conne.forEach(cb => cb(_extends({}, response, {
3789
3809
  // Ignore the full connect response
3790
3810
  // use the chainId defined locally
@@ -3820,7 +3840,7 @@ class SequenceClient {
3820
3840
  // instead we handle it locally, so we listen for changes in the store
3821
3841
  this.defaultChainId.onDefaultChainIdChanged(chainId => {
3822
3842
  var _this$callbacks$chain2;
3823
- const chainIdHex = ethers.ethers.utils.hexValue(chainId);
3843
+ const chainIdHex = ethers.ethers.toQuantity(chainId);
3824
3844
  (_this$callbacks$chain2 = this.callbacks.chainChanged) == null || _this$callbacks$chain2.forEach(cb => cb(chainIdHex));
3825
3845
  });
3826
3846
  if (options != null && options.projectAccessKey) {
@@ -3933,7 +3953,7 @@ class SequenceClient {
3933
3953
  type: 'connect',
3934
3954
  options: _extends({}, options, {
3935
3955
  networkId: this.getChainId(),
3936
- clientVersion: packageJson.version
3956
+ clientVersion: core.VERSION
3937
3957
  })
3938
3958
  });
3939
3959
  const connectDetails = await this.transport.waitUntilConnected().catch(error => {
@@ -3953,7 +3973,7 @@ class SequenceClient {
3953
3973
  // Normalize chainId into a decimal string
3954
3974
  // TODO: Remove this once wallet-webapp returns chainId as a string
3955
3975
  if (connectDetails.chainId) {
3956
- connectDetails.chainId = ethers.ethers.BigNumber.from(connectDetails.chainId).toString();
3976
+ connectDetails.chainId = BigInt(connectDetails.chainId).toString();
3957
3977
  }
3958
3978
  if (connectDetails.connected) {
3959
3979
  var _connectDetails$sessi;
@@ -3979,33 +3999,17 @@ class SequenceClient {
3979
3999
 
3980
4000
  // Higher level API
3981
4001
 
3982
- // Working with sendAsync is less idiomatic
3983
- // but transport uses it instead of send, so we wrap it
3984
- send(request, chainId) {
4002
+ async request(request) {
3985
4003
  // Internally when sending requests we use `legacy_sign`
3986
4004
  // to avoid the default EIP6492 behavior overriding an explicit
3987
4005
  // "legacy sign" request, so we map the method here.
3988
4006
  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
- });
4007
+ return this.transport.request(request);
4004
4008
  }
4005
4009
  async getNetworks(pull) {
4006
4010
  const connectedSession = this.session.connectedSession();
4007
4011
  if (pull) {
4008
- connectedSession.networks = await this.send({
4012
+ connectedSession.networks = await this.request({
4009
4013
  method: 'sequence_getNetworks'
4010
4014
  });
4011
4015
  this.session.setSession(connectedSession);
@@ -4061,15 +4065,14 @@ class SequenceClient {
4061
4065
  chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
4062
4066
  }
4063
4067
  });
4064
-
4065
- // Serialize a BytesLike or string message into a hex string before sending
4066
- message = ethers.ethers.utils.hexlify(messageToBytes(message));
4068
+ message = ethers.ethers.hexlify(messageToBytes(message));
4067
4069
 
4068
4070
  // Address is ignored by the wallet webapp
4069
- return this.send({
4071
+ return this.request({
4070
4072
  method,
4071
- params: [message, this.getAddress()]
4072
- }, options == null ? void 0 : options.chainId);
4073
+ params: [message, this.getAddress()],
4074
+ chainId: options == null ? void 0 : options.chainId
4075
+ });
4073
4076
  }
4074
4077
  async signTypedData(typedData, options) {
4075
4078
  var _this$analytics5;
@@ -4077,7 +4080,7 @@ class SequenceClient {
4077
4080
 
4078
4081
  // TODO: Stop using ethers for this, this is the only place where we use it
4079
4082
  // and it makes the client depend on ethers.
4080
- const encoded = ethers.ethers.utils._TypedDataEncoder.getPayload(typedData.domain, typedData.types, typedData.message);
4083
+ const encoded = ethers.ethers.TypedDataEncoder.getPayload(typedData.domain, typedData.types, typedData.message);
4081
4084
 
4082
4085
  // The sign typed data will use one of the following chainIds, in order:
4083
4086
  // - The one provided in the options
@@ -4090,10 +4093,11 @@ class SequenceClient {
4090
4093
  chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
4091
4094
  }
4092
4095
  });
4093
- return this.send({
4096
+ return this.request({
4094
4097
  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());
4098
+ params: [this.getAddress(), encoded],
4099
+ chainId: (options == null ? void 0 : options.chainId) || typedData.domain.chainId && Number(typedData.domain.chainId) || this.getChainId()
4100
+ });
4097
4101
  }
4098
4102
  async sendTransaction(tx, options) {
4099
4103
  var _this$analytics6;
@@ -4105,22 +4109,24 @@ class SequenceClient {
4105
4109
  chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
4106
4110
  }
4107
4111
  });
4108
- return this.send({
4112
+ return this.request({
4109
4113
  method: 'eth_sendTransaction',
4110
- params: [extendedTxs]
4111
- }, options == null ? void 0 : options.chainId);
4114
+ params: [extendedTxs],
4115
+ chainId: options == null ? void 0 : options.chainId
4116
+ });
4112
4117
  }
4113
4118
  async getWalletContext() {
4114
- return this.send({
4119
+ return this.request({
4115
4120
  method: 'sequence_getWalletContext'
4116
4121
  });
4117
4122
  }
4118
4123
  async getOnchainWalletConfig(options) {
4119
4124
  // NOTICE: sequence_getWalletConfig sends the chainId as a param
4120
- const res = await this.send({
4125
+ const res = await this.request({
4121
4126
  method: 'sequence_getWalletConfig',
4122
- params: [(options == null ? void 0 : options.chainId) || this.getChainId()]
4123
- }, options == null ? void 0 : options.chainId);
4127
+ params: [(options == null ? void 0 : options.chainId) || this.getChainId()],
4128
+ chainId: options == null ? void 0 : options.chainId
4129
+ });
4124
4130
  return Array.isArray(res) ? res[0] : res;
4125
4131
  }
4126
4132
 
@@ -4199,9 +4205,11 @@ const initWallet = (projectAccessKey, partialConfig) => {
4199
4205
  if (!rpcUrl) {
4200
4206
  throw new Error(`no rpcUrl found for chainId: ${chainId}`);
4201
4207
  }
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);
4208
+ rpcProviders[chainId] = new network.JsonRpcProvider(rpcUrl, {
4209
+ middlewares: [network.loggingProviderMiddleware, network.exceptionProviderMiddleware, new network.CachedProvider()]
4210
+ }, {
4211
+ cacheTimeout: -1
4212
+ });
4205
4213
  }
4206
4214
  return rpcProviders[chainId];
4207
4215
  };