@exodus/web3-ethereum 12.2.1 → 12.4.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.
@@ -9,7 +9,7 @@ export interface EthereumProviderEvents {
9
9
  }
10
10
  export declare class EthereumProvider extends BaseProvider<EthereumProviderEvents> {
11
11
  #private;
12
- constructor({ accountsObservable, storage, storageKeyPrefix, supportedChainIds, transport, getDefaultChainId, }: Deps);
12
+ constructor({ accountsObservable, transport, storage, storageKeyPrefix, supportedChainIds, getDefaultChainId, }: Deps);
13
13
  protected _callRpcMethod<Params, Response>(method: string, params: Params): Promise<Response>;
14
14
  isConnected(): boolean;
15
15
  request: (args: RequestArguments) => Promise<unknown>;
@@ -1,9 +1,10 @@
1
1
  import { BaseProvider } from '@exodus/web3-provider';
2
2
  import { ethErrors } from 'eth-rpc-errors';
3
3
  import { createStorageWrapper } from './storage.js';
4
+ const DEFAULT_CHAIN_ID = '0x1'; // Ethereum Mainnet.
4
5
  export class EthereumProvider extends BaseProvider {
5
6
  #storage;
6
- #supportedChainIds = [];
7
+ #supportedChainIds;
7
8
  #getDefaultChainId;
8
9
  #initializePromise = null;
9
10
  #initialized = false;
@@ -11,18 +12,16 @@ export class EthereumProvider extends BaseProvider {
11
12
  #chainId = null;
12
13
  #accounts = [];
13
14
  #selectedAddress = null;
14
- constructor({ accountsObservable, storage, storageKeyPrefix, supportedChainIds, transport, getDefaultChainId, }) {
15
- if (!supportedChainIds?.length) {
16
- throw new Error('At least one supported chain must be provided');
17
- }
15
+ constructor({ accountsObservable, transport, storage, storageKeyPrefix, supportedChainIds = [DEFAULT_CHAIN_ID], getDefaultChainId = () => Promise.resolve(null), }) {
16
+ super({ transport });
18
17
  if (!storageKeyPrefix) {
19
- throw new Error('"storageKeyPrefix" must be provided');
18
+ throw new Error('"storageKeyPrefix" must be provided.');
20
19
  }
21
- super({ transport });
22
20
  this.#storage = createStorageWrapper(storage, storageKeyPrefix);
23
21
  this.#supportedChainIds = supportedChainIds
24
- .map((chainId) => chainId.toLowerCase())
22
+ .map(this.#sanitizeChainId)
25
23
  .sort();
24
+ this.#getDefaultChainId = async () => getDefaultChainId().then((chainId) => chainId ? this.#sanitizeChainId(chainId) : null);
26
25
  // Observe account changes.
27
26
  this.on('connect', () => {
28
27
  const unobserve = accountsObservable.observe((accounts) => {
@@ -34,9 +33,6 @@ export class EthereumProvider extends BaseProvider {
34
33
  this.#isConnected = true;
35
34
  });
36
35
  this.#initializePromise = this.#initialize();
37
- this.#getDefaultChainId = getDefaultChainId
38
- ? getDefaultChainId
39
- : async () => null;
40
36
  }
41
37
  _callRpcMethod(method, params) {
42
38
  const prefix = this.#chainId;
@@ -59,8 +55,15 @@ export class EthereumProvider extends BaseProvider {
59
55
  };
60
56
  #getChainId = async () => {
61
57
  const storedChainId = await this.#storage.getChainId();
62
- const defaultChainId = this.#supportedChainIds[0];
63
- return storedChainId ?? defaultChainId;
58
+ if (storedChainId) {
59
+ return storedChainId;
60
+ }
61
+ // TODO: Do we still need remote-config default chain IDs?
62
+ const defaultChainId = await this.#getDefaultChainId();
63
+ if (defaultChainId) {
64
+ return defaultChainId;
65
+ }
66
+ return this.#supportedChainIds[0];
64
67
  };
65
68
  #getAccounts = async () => {
66
69
  return this._callRpcMethod('eth_accounts', []);
@@ -68,7 +71,7 @@ export class EthereumProvider extends BaseProvider {
68
71
  #initialize = async () => {
69
72
  const chainId = await this.#getChainId();
70
73
  this.#handleConnect(chainId);
71
- this.#handleChainChanged(chainId.toLowerCase());
74
+ this.#handleChainChanged(chainId);
72
75
  const accounts = await this.#getAccounts();
73
76
  this.#initialized = true;
74
77
  this.#initializePromise = null;
@@ -79,6 +82,9 @@ export class EthereumProvider extends BaseProvider {
79
82
  await this.#initializePromise;
80
83
  }
81
84
  };
85
+ #sanitizeChainId = (chainId) => {
86
+ return chainId.toLowerCase();
87
+ };
82
88
  #handleConnect = (chainId) => {
83
89
  if (!this.#isConnected) {
84
90
  this.#isConnected = true;
@@ -111,13 +117,6 @@ export class EthereumProvider extends BaseProvider {
111
117
  await this._callRpcMethod('wallet_requestPermissions', [permissions]);
112
118
  const accounts = await this._callRpcMethod('eth_accounts', []);
113
119
  this.#handleAccountsChanged(accounts);
114
- if (!(await this.#storage.getChainId())) {
115
- // Get default chain Id from remote config
116
- const defaultChainId = await this.#getDefaultChainId();
117
- if (defaultChainId) {
118
- this.#handleChainChanged(defaultChainId.toLowerCase());
119
- }
120
- }
121
120
  return accounts;
122
121
  };
123
122
  #addChain = async (chainId) => {
@@ -128,10 +127,21 @@ export class EthereumProvider extends BaseProvider {
128
127
  return this.#switchChain(chainId);
129
128
  };
130
129
  #switchChain = async (chainId) => {
131
- const lowerCaseChainId = chainId.toLowerCase();
132
- this.#assertChainSupported(lowerCaseChainId);
133
- this.#handleChainChanged(lowerCaseChainId);
134
- await this.#storage.setChainId(lowerCaseChainId);
130
+ if (chainId !== this.#chainId) {
131
+ try {
132
+ // Try to switch to one of the provider known chains.
133
+ this.#assertChainSupported(chainId);
134
+ }
135
+ catch (err) {
136
+ // Attempt to switch to a dynamically supported chain.
137
+ const didSwitch = await this._callRpcMethod('wallet_switchEthereumChain', [{ chainId }]);
138
+ if (!didSwitch) {
139
+ throw err;
140
+ }
141
+ }
142
+ this.#handleChainChanged(chainId);
143
+ await this.#storage.setChainId(chainId);
144
+ }
135
145
  return null;
136
146
  };
137
147
  isConnected() {
@@ -171,13 +181,13 @@ export class EthereumProvider extends BaseProvider {
171
181
  // See: https://eips.ethereum.org/EIPS/eip-3085.
172
182
  if (method === 'wallet_addEthereumChain') {
173
183
  const { chainId } = params[0];
174
- return this.#addChain(chainId);
184
+ return this.#addChain(this.#sanitizeChainId(chainId));
175
185
  }
176
186
  // EIP-3326.
177
187
  // See: https://eips.ethereum.org/EIPS/eip-3326.
178
188
  if (method === 'wallet_switchEthereumChain') {
179
189
  const { chainId } = params[0];
180
- return this.#switchChain(chainId);
190
+ return this.#switchChain(this.#sanitizeChainId(chainId));
181
191
  }
182
192
  /**
183
193
  * Request.
@@ -34,8 +34,8 @@ export declare type Deps = BaseProviderDeps & {
34
34
  accountsObservable: Observable;
35
35
  storage: Storage;
36
36
  storageKeyPrefix?: string;
37
- supportedChainIds: string[];
38
- getDefaultChainId?: () => Promise<string | null>;
37
+ supportedChainIds?: ChainId[];
38
+ getDefaultChainId?: () => Promise<ChainId | null>;
39
39
  };
40
40
  export interface ProviderStorage {
41
41
  getChainId: () => Promise<ChainId | null>;
@@ -9,7 +9,7 @@ async function getDefaultPurposeForLedger(asset) {
9
9
  return purposes[0];
10
10
  }
11
11
  const createEVMDepsFactory = ({ analytics, blockchainMetadata, }) => {
12
- return ({ assetName, origin, getAsset, getAddress: _getAddress, getPrivateKey, getFeeData: getFeeConfig, getCustomFeeRate, getActiveWalletAccount, simulateEthereumTransactions, getActiveWalletAccountData, transactionSigner, getLedgerDevice, }) => {
12
+ return ({ assetName, origin, getAsset, getAddress: _getAddress, getSupportedChainIds, getPrivateKey, getFeeData: getFeeConfig, getCustomFeeRate, getActiveWalletAccount, simulateEthereumTransactions, getActiveWalletAccountData, transactionSigner, getLedgerDevice, }) => {
13
13
  const asset = getAsset(assetName);
14
14
  const server = getServer(asset);
15
15
  const forwardRequest = async ({ method, params }) => {
@@ -155,6 +155,7 @@ const createEVMDepsFactory = ({ analytics, blockchainMetadata, }) => {
155
155
  getFeeData,
156
156
  getEstimatedGas,
157
157
  getCustomFeeData,
158
+ getSupportedChainIds,
158
159
  onEthWalletWatchAssetRequest: trackWalletWatchAssetUse,
159
160
  simulateEthereumTransactions,
160
161
  transactionSigner,
@@ -62,7 +62,7 @@ const isValidGasLimitValue = (value) => {
62
62
  return proposedGasLimit.lte(maximumBlockGasLimit);
63
63
  };
64
64
  export function exposeHandlers(rpc, deps) {
65
- const { chainId, isTrusted, isAutoApproved, ensureTrusted, approveConnection, approveMessage, approveTransactions, forwardRequest, getAddress, getEstimatedGas, getCustomFeeData, getFeeData, getNonce, sendRawTransaction, simulateEthereumTransactions, scanDomains, onTransactionsSigned = () => { }, onEthWalletWatchAssetRequest = () => { }, isUnlocked = () => true, ensureUnlocked = async () => true, getAsset, getOrigin, getActiveWalletAccountData, transactionSigner, messageSigner, } = deps;
65
+ const { chainId, isTrusted, isAutoApproved, ensureTrusted, approveConnection, approveMessage, approveTransactions, forwardRequest, getSupportedChainIds = async () => [], getAddress, getEstimatedGas, getCustomFeeData, getFeeData, getNonce, sendRawTransaction, simulateEthereumTransactions, scanDomains, onTransactionsSigned = () => { }, onEthWalletWatchAssetRequest = () => { }, isUnlocked = () => true, ensureUnlocked = async () => true, getAsset, getOrigin, getPathname, getActiveWalletAccountData, transactionSigner, messageSigner, } = deps;
66
66
  const network = `evm:${chainId}`;
67
67
  async function assertTrusted() {
68
68
  const trusted = await isTrusted();
@@ -135,10 +135,11 @@ export function exposeHandlers(rpc, deps) {
135
135
  const preparedTransaction = await prepareTransaction(transaction);
136
136
  validateTransaction(preparedTransaction);
137
137
  const origin = getOrigin();
138
+ const pathname = getPathname ? getPathname() : '';
138
139
  const simulatedChanges = await simulateEthereumTransactions({
139
140
  asset,
140
141
  transactions: [preparedTransaction],
141
- origin,
142
+ origin: origin + pathname,
142
143
  });
143
144
  await approve(approveTransactions, network, simulatedChanges);
144
145
  const modifiedTransaction = await applyCustomFeeRate(preparedTransaction);
@@ -264,15 +265,22 @@ export function exposeHandlers(rpc, deps) {
264
265
  isTrusted,
265
266
  ensureUnlocked,
266
267
  getOrigin,
268
+ getPathname,
267
269
  scanDomains,
268
270
  }, network);
269
271
  return [{ parentCapability: ETH_ACCOUNTS_PERMISSION }];
270
272
  });
271
- exposeEvmFunction('wallet_watchAsset', async (assetDetails) => {
273
+ exposeEvmFunction('wallet_switchEthereumChain', async (param) => {
272
274
  await assertTrusted();
273
- const assetAdded = await onEthWalletWatchAssetRequest(assetDetails);
275
+ const chainId = param.chainId;
276
+ const supportedChainIds = await getSupportedChainIds();
277
+ return supportedChainIds.includes(chainId);
278
+ });
279
+ exposeEvmFunction('wallet_watchAsset', async (param) => {
280
+ await assertTrusted();
281
+ const assetAdded = await onEthWalletWatchAssetRequest(param);
274
282
  if (!assetAdded) {
275
- throw new AssetNotSupportedError(assetDetails.type);
283
+ throw new AssetNotSupportedError(param.type);
276
284
  }
277
285
  return true;
278
286
  });
@@ -18,7 +18,7 @@ const validateEVMDeps = (evm) => {
18
18
  'transactionSigner',
19
19
  'messageSigner',
20
20
  ];
21
- const optionalKeys = ['onEthWalletWatchAssetRequest'];
21
+ const optionalKeys = ['getSupportedChainIds', 'onEthWalletWatchAssetRequest'];
22
22
  validateDeps(evm, requiredKeys, optionalKeys);
23
23
  };
24
24
  function validateEVMsDeps(evms) {
@@ -937,13 +937,81 @@ export function validateRequest(value) {
937
937
  }
938
938
  return true
939
939
  }
940
+ const ref14 = function validate(data) {
941
+ validate.errors = null
942
+ if (!Array.isArray(data)) {
943
+ validate.errors = [{ keywordLocation: '#/type', instanceLocation: '#' }]
944
+ return false
945
+ }
946
+ if (data.length < 1) {
947
+ validate.errors = [
948
+ { keywordLocation: '#/minItems', instanceLocation: '#' },
949
+ ]
950
+ return false
951
+ }
952
+ if (0 in data && hasOwn(data, 0)) {
953
+ if (
954
+ !(typeof data[0] === 'object' && data[0] && !Array.isArray(data[0]))
955
+ ) {
956
+ validate.errors = [
957
+ { keywordLocation: '#/0/type', instanceLocation: '#/0' },
958
+ ]
959
+ return false
960
+ }
961
+ if (!('chainId' in data[0] && hasOwn(data[0], 'chainId'))) {
962
+ validate.errors = [
963
+ {
964
+ keywordLocation: '#/0/required',
965
+ instanceLocation: '#/0/chainId',
966
+ },
967
+ ]
968
+ return false
969
+ }
970
+ if (!(typeof data[0].chainId === 'string')) {
971
+ validate.errors = [
972
+ {
973
+ keywordLocation: '#/0/properties/chainId/type',
974
+ instanceLocation: '#/0/chainId',
975
+ },
976
+ ]
977
+ return false
978
+ }
979
+ if (!format4.test(data[0].chainId)) {
980
+ validate.errors = [
981
+ {
982
+ keywordLocation: '#/0/properties/chainId/format',
983
+ instanceLocation: '#/0/chainId',
984
+ },
985
+ ]
986
+ return false
987
+ }
988
+ for (const key6 of Object.keys(data[0])) {
989
+ if (key6 !== 'chainId') {
990
+ validate.errors = [
991
+ {
992
+ keywordLocation: '#/0/additionalProperties',
993
+ instanceLocation: '#/' + pointerPart(key6),
994
+ },
995
+ ]
996
+ return false
997
+ }
998
+ }
999
+ }
1000
+ if (data.length > 1) {
1001
+ validate.errors = [
1002
+ { keywordLocation: '#/items', instanceLocation: '#' },
1003
+ ]
1004
+ return false
1005
+ }
1006
+ return true
1007
+ }
940
1008
  const format6 = new RegExp(
941
1009
  "^[a-z][a-z0-9+\\-.]*:(?:\\/?\\/(?:(?:[a-z0-9\\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d\\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|v[0-9a-f]+\\.[a-z0-9\\-._~!$&'()*+,;=:]+)\\]|(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d\\d?)|(?:[a-z0-9\\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\\d*)?(?:\\/(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\\/?(?:(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\\/(?:[a-z0-9\\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?)(?:\\?(?:[a-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$",
942
1010
  'i',
943
1011
  )
944
1012
  const format7 = (input) =>
945
1013
  input.length % 4 === 0 && /^[a-z0-9+/]*={0,3}$/i.test(input)
946
- const ref16 = function validate(data) {
1014
+ const ref17 = function validate(data) {
947
1015
  validate.errors = null
948
1016
  if (!(typeof data === 'string')) {
949
1017
  validate.errors = [{ keywordLocation: '#/type', instanceLocation: '#' }]
@@ -963,7 +1031,7 @@ export function validateRequest(value) {
963
1031
  }
964
1032
  return true
965
1033
  }
966
- const ref15 = function validate(data) {
1034
+ const ref16 = function validate(data) {
967
1035
  validate.errors = null
968
1036
  if (!(typeof data === 'object' && data && !Array.isArray(data))) {
969
1037
  validate.errors = [{ keywordLocation: '#/type', instanceLocation: '#' }]
@@ -1042,11 +1110,11 @@ export function validateRequest(value) {
1042
1110
  })()
1043
1111
  if (sub23) passes5++
1044
1112
  const sub24 = (() => {
1045
- const err38 = validate.errors
1046
- const res38 = ref16(data.image)
1047
- const suberr38 = ref16.errors
1048
- validate.errors = err38
1049
- if (!res38) return false
1113
+ const err39 = validate.errors
1114
+ const res39 = ref17(data.image)
1115
+ const suberr39 = ref17.errors
1116
+ validate.errors = err39
1117
+ if (!res39) return false
1050
1118
  return true
1051
1119
  })()
1052
1120
  if (sub24) passes5++
@@ -1071,18 +1139,18 @@ export function validateRequest(value) {
1071
1139
  return false
1072
1140
  }
1073
1141
  }
1074
- for (const key6 of Object.keys(data)) {
1142
+ for (const key7 of Object.keys(data)) {
1075
1143
  if (
1076
- key6 !== 'address' &&
1077
- key6 !== 'symbol' &&
1078
- key6 !== 'decimals' &&
1079
- key6 !== 'image' &&
1080
- key6 !== 'chainId'
1144
+ key7 !== 'address' &&
1145
+ key7 !== 'symbol' &&
1146
+ key7 !== 'decimals' &&
1147
+ key7 !== 'image' &&
1148
+ key7 !== 'chainId'
1081
1149
  ) {
1082
1150
  validate.errors = [
1083
1151
  {
1084
1152
  keywordLocation: '#/additionalProperties',
1085
- instanceLocation: '#/' + pointerPart(key6),
1153
+ instanceLocation: '#/' + pointerPart(key7),
1086
1154
  },
1087
1155
  ]
1088
1156
  return false
@@ -1090,7 +1158,7 @@ export function validateRequest(value) {
1090
1158
  }
1091
1159
  return true
1092
1160
  }
1093
- const ref14 = function validate(data) {
1161
+ const ref15 = function validate(data) {
1094
1162
  validate.errors = null
1095
1163
  if (!(typeof data === 'object' && data && !Array.isArray(data))) {
1096
1164
  validate.errors = [{ keywordLocation: '#/type', instanceLocation: '#' }]
@@ -1135,22 +1203,22 @@ export function validateRequest(value) {
1135
1203
  ]
1136
1204
  return false
1137
1205
  }
1138
- const err39 = validate.errors
1139
- const res39 = ref15(data.options)
1140
- const suberr39 = ref15.errors
1141
- validate.errors = err39
1142
- if (!res39) {
1206
+ const err40 = validate.errors
1207
+ const res40 = ref16(data.options)
1208
+ const suberr40 = ref16.errors
1209
+ validate.errors = err40
1210
+ if (!res40) {
1143
1211
  validate.errors = [
1144
- errorMerge(suberr39[0], '#/properties/options/$ref', '#/options'),
1212
+ errorMerge(suberr40[0], '#/properties/options/$ref', '#/options'),
1145
1213
  ]
1146
1214
  return false
1147
1215
  }
1148
- for (const key7 of Object.keys(data)) {
1149
- if (key7 !== 'type' && key7 !== 'options') {
1216
+ for (const key8 of Object.keys(data)) {
1217
+ if (key8 !== 'type' && key8 !== 'options') {
1150
1218
  validate.errors = [
1151
1219
  {
1152
1220
  keywordLocation: '#/additionalProperties',
1153
- instanceLocation: '#/' + pointerPart(key7),
1221
+ instanceLocation: '#/' + pointerPart(key8),
1154
1222
  },
1155
1223
  ]
1156
1224
  return false
@@ -2271,7 +2339,7 @@ export function validateRequest(value) {
2271
2339
  return false
2272
2340
  }
2273
2341
  break
2274
- case 'wallet_watchAsset':
2342
+ case 'wallet_switchEthereumChain':
2275
2343
  if (!('params' in data && hasOwn(data, 'params'))) {
2276
2344
  validate.errors = [
2277
2345
  {
@@ -2281,14 +2349,14 @@ export function validateRequest(value) {
2281
2349
  ]
2282
2350
  return false
2283
2351
  }
2284
- const err40 = validate.errors
2285
- const res40 = ref14(data.params)
2286
- const suberr40 = ref14.errors
2287
- validate.errors = err40
2288
- if (!res40) {
2352
+ const err38 = validate.errors
2353
+ const res38 = ref14(data.params)
2354
+ const suberr38 = ref14.errors
2355
+ validate.errors = err38
2356
+ if (!res38) {
2289
2357
  validate.errors = [
2290
2358
  errorMerge(
2291
- suberr40[0],
2359
+ suberr38[0],
2292
2360
  '#/oneOf/44/properties/params/$ref',
2293
2361
  '#/params',
2294
2362
  ),
@@ -2296,7 +2364,7 @@ export function validateRequest(value) {
2296
2364
  return false
2297
2365
  }
2298
2366
  break
2299
- case 'web3_clientVersion':
2367
+ case 'wallet_watchAsset':
2300
2368
  if (!('params' in data && hasOwn(data, 'params'))) {
2301
2369
  validate.errors = [
2302
2370
  {
@@ -2306,10 +2374,35 @@ export function validateRequest(value) {
2306
2374
  ]
2307
2375
  return false
2308
2376
  }
2377
+ const err41 = validate.errors
2378
+ const res41 = ref15(data.params)
2379
+ const suberr41 = ref15.errors
2380
+ validate.errors = err41
2381
+ if (!res41) {
2382
+ validate.errors = [
2383
+ errorMerge(
2384
+ suberr41[0],
2385
+ '#/oneOf/45/properties/params/$ref',
2386
+ '#/params',
2387
+ ),
2388
+ ]
2389
+ return false
2390
+ }
2391
+ break
2392
+ case 'web3_clientVersion':
2393
+ if (!('params' in data && hasOwn(data, 'params'))) {
2394
+ validate.errors = [
2395
+ {
2396
+ keywordLocation: '#/oneOf/46/required',
2397
+ instanceLocation: '#/params',
2398
+ },
2399
+ ]
2400
+ return false
2401
+ }
2309
2402
  if (!(Array.isArray(data.params) && data.params.length === 0)) {
2310
2403
  validate.errors = [
2311
2404
  {
2312
- keywordLocation: '#/oneOf/45/properties/params/const',
2405
+ keywordLocation: '#/oneOf/46/properties/params/const',
2313
2406
  instanceLocation: '#/params',
2314
2407
  },
2315
2408
  ]
@@ -2320,7 +2413,7 @@ export function validateRequest(value) {
2320
2413
  if (!('params' in data && hasOwn(data, 'params'))) {
2321
2414
  validate.errors = [
2322
2415
  {
2323
- keywordLocation: '#/oneOf/46/required',
2416
+ keywordLocation: '#/oneOf/47/required',
2324
2417
  instanceLocation: '#/params',
2325
2418
  },
2326
2419
  ]
@@ -2329,7 +2422,7 @@ export function validateRequest(value) {
2329
2422
  if (!(Array.isArray(data.params) && data.params.length === 0)) {
2330
2423
  validate.errors = [
2331
2424
  {
2332
- keywordLocation: '#/oneOf/46/properties/params/const',
2425
+ keywordLocation: '#/oneOf/47/properties/params/const',
2333
2426
  instanceLocation: '#/params',
2334
2427
  },
2335
2428
  ]
@@ -2342,17 +2435,17 @@ export function validateRequest(value) {
2342
2435
  ]
2343
2436
  return false
2344
2437
  }
2345
- for (const key8 of Object.keys(data)) {
2438
+ for (const key9 of Object.keys(data)) {
2346
2439
  if (
2347
- key8 !== 'id' &&
2348
- key8 !== 'jsonrpc' &&
2349
- key8 !== 'method' &&
2350
- key8 !== 'params'
2440
+ key9 !== 'id' &&
2441
+ key9 !== 'jsonrpc' &&
2442
+ key9 !== 'method' &&
2443
+ key9 !== 'params'
2351
2444
  ) {
2352
2445
  validate.errors = [
2353
2446
  {
2354
2447
  keywordLocation: '#/unevaluatedProperties',
2355
- instanceLocation: '#/' + pointerPart(key8),
2448
+ instanceLocation: '#/' + pointerPart(key9),
2356
2449
  },
2357
2450
  ]
2358
2451
  return false
package/lib/types.d.ts CHANGED
@@ -33,6 +33,7 @@ export interface CreateEvmDepsParams {
33
33
  getAsset: (assetName: string) => Asset;
34
34
  getFeeData: ({ assetName }: GetFeeDataParams) => Promise<EthereumFeeData>;
35
35
  getCustomFeeRate?: () => Promise<NumberUnit>;
36
+ getSupportedChainIds?: () => Promise<string[]>;
36
37
  getPrivateKey?: (assetName: string) => Promise<{
37
38
  privateKey: Buffer;
38
39
  }>;
@@ -45,6 +46,7 @@ export declare type EVMFactory = (params: CreateEvmDepsParams) => EVMDeps;
45
46
  export declare type EVMTransactionSignerModule = ITransactionSignerModule<EVMUnsignedTransaction>;
46
47
  export declare type EVMDeps = {
47
48
  chainId: string;
49
+ getSupportedChainIds?: () => Promise<string[]>;
48
50
  getAddress: () => Promise<string>;
49
51
  sendRawTransaction: (rawTransaction: string) => Promise<EthTransactionHash>;
50
52
  simulateEthereumTransactions: SimulateTransactionsFn;
@@ -55,7 +57,7 @@ export declare type EVMDeps = {
55
57
  forwardRequest: (args: EthRequestArguments) => Promise<unknown>;
56
58
  transactionSigner: EVMTransactionSignerModule;
57
59
  messageSigner: EVMMessageSigner;
58
- onEthWalletWatchAssetRequest?: (assetDetails: EthWalletWatchAsset) => Promise<boolean>;
60
+ onEthWalletWatchAssetRequest?: (param: EthWalletWatchAsset) => Promise<boolean>;
59
61
  getActiveWalletAccountData: GetActiveWalletAccountData;
60
62
  };
61
63
  export declare type Dependencies = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@exodus/web3-ethereum",
3
3
  "description": "Apps connectivity library for EVM-compatible chains.",
4
- "version": "12.2.1",
4
+ "version": "12.4.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "module": "lib/index.js",
@@ -35,9 +35,9 @@
35
35
  "@exodus/currency": "^2.1.2",
36
36
  "@exodus/ethereum-api": "^6.3.33",
37
37
  "@exodus/web3-constants": "^1.30.0",
38
- "@exodus/web3-ethereum-utils": "^3.27.1",
38
+ "@exodus/web3-ethereum-utils": "^3.28.0",
39
39
  "@exodus/web3-provider": "^3.14.0",
40
- "@exodus/web3-rpc-handlers": "^2.20.0",
40
+ "@exodus/web3-rpc-handlers": "^2.21.0",
41
41
  "@exodus/web3-utils": "^1.44.0",
42
42
  "bn.js": "^5.2.0",
43
43
  "eth-rpc-errors": "^4.0.3"
@@ -46,10 +46,10 @@
46
46
  "@exodus/assets": "^8.0.95",
47
47
  "@exodus/json-rpc": "^1.11.0",
48
48
  "@exodus/schemasafe": "^1.0.0",
49
- "@exodus/web3-management": "0.29.0",
49
+ "@exodus/web3-management": "0.30.0",
50
50
  "@exodus/web3-types": "0.0.0",
51
51
  "@exodus/web3-validation": "^1.38.0",
52
52
  "@wallet-standard/base": "^1.0.1"
53
53
  },
54
- "gitHead": "d17aa615504e5a8736e368f66c704b5c6333a29a"
54
+ "gitHead": "ef0ce5b2df8bcb8602fd6e752272b96017f2a9e6"
55
55
  }