@toruslabs/ethereum-controllers 6.3.2 → 7.0.0-alpha.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 (79) hide show
  1. package/dist/757.ethereumControllers.cjs.js +226 -0
  2. package/dist/ethereumControllers.cjs.js +18978 -2202
  3. package/dist/ethereumControllers.esm.js +1225 -1044
  4. package/dist/ethereumControllers.umd.min.js +1 -1
  5. package/dist/lib.cjs/AccountAbstraction/AccountAbstractionController.js +218 -0
  6. package/dist/lib.cjs/AccountAbstraction/smartAccounts/BiconomySmartAccount.js +29 -0
  7. package/dist/lib.cjs/AccountAbstraction/smartAccounts/KernelSmartAccount.js +24 -0
  8. package/dist/lib.cjs/AccountAbstraction/smartAccounts/NexusSmartAccount.js +30 -0
  9. package/dist/lib.cjs/AccountAbstraction/smartAccounts/SafeSmartAccount.js +32 -0
  10. package/dist/lib.cjs/AccountAbstraction/smartAccounts/TrustSmartAccount.js +31 -0
  11. package/dist/lib.cjs/Block/PollingBlockTracker.js +1 -2
  12. package/dist/lib.cjs/Currency/CurrencyController.js +1 -2
  13. package/dist/lib.cjs/Gas/GasFeeController.js +1 -2
  14. package/dist/lib.cjs/Message/AddChainController.js +6 -9
  15. package/dist/lib.cjs/Message/MessageController.js +7 -10
  16. package/dist/lib.cjs/Message/PersonalMessageController.js +7 -10
  17. package/dist/lib.cjs/Message/SwitchChainController.js +6 -9
  18. package/dist/lib.cjs/Message/TypedMessageController.js +8 -8
  19. package/dist/lib.cjs/Nfts/NftsController.js +1 -2
  20. package/dist/lib.cjs/Preferences/PreferencesController.js +6 -3
  21. package/dist/lib.cjs/Tokens/TokenRatesController.js +1 -2
  22. package/dist/lib.cjs/Tokens/TokensController.js +1 -1
  23. package/dist/lib.cjs/index.js +15 -5
  24. package/dist/lib.cjs/utils/constants.js +10 -12
  25. package/dist/lib.cjs/utils/helpers.js +0 -25
  26. package/dist/lib.esm/AccountAbstraction/AccountAbstractionController.js +214 -0
  27. package/dist/lib.esm/AccountAbstraction/smartAccounts/BiconomySmartAccount.js +27 -0
  28. package/dist/lib.esm/AccountAbstraction/smartAccounts/KernelSmartAccount.js +22 -0
  29. package/dist/lib.esm/AccountAbstraction/smartAccounts/NexusSmartAccount.js +28 -0
  30. package/dist/lib.esm/AccountAbstraction/smartAccounts/SafeSmartAccount.js +30 -0
  31. package/dist/lib.esm/AccountAbstraction/smartAccounts/TrustSmartAccount.js +29 -0
  32. package/dist/lib.esm/Block/PollingBlockTracker.js +1 -2
  33. package/dist/lib.esm/Currency/CurrencyController.js +1 -2
  34. package/dist/lib.esm/Gas/GasFeeController.js +1 -2
  35. package/dist/lib.esm/Message/AddChainController.js +3 -6
  36. package/dist/lib.esm/Message/MessageController.js +4 -7
  37. package/dist/lib.esm/Message/PersonalMessageController.js +4 -7
  38. package/dist/lib.esm/Message/SwitchChainController.js +3 -6
  39. package/dist/lib.esm/Message/TypedMessageController.js +5 -5
  40. package/dist/lib.esm/Nfts/NftsController.js +1 -2
  41. package/dist/lib.esm/Preferences/PreferencesController.js +6 -3
  42. package/dist/lib.esm/Tokens/TokenRatesController.js +1 -2
  43. package/dist/lib.esm/Tokens/TokensController.js +2 -2
  44. package/dist/lib.esm/index.js +8 -3
  45. package/dist/lib.esm/utils/constants.js +10 -11
  46. package/dist/lib.esm/utils/helpers.js +1 -25
  47. package/dist/types/AccountAbstraction/AccountAbstractionController.d.ts +52 -0
  48. package/dist/types/AccountAbstraction/smartAccounts/BiconomySmartAccount.d.ts +15 -0
  49. package/dist/types/AccountAbstraction/smartAccounts/KernelSmartAccount.d.ts +16 -0
  50. package/dist/types/AccountAbstraction/smartAccounts/LightSmartAccount.d.ts +15 -0
  51. package/dist/types/AccountAbstraction/smartAccounts/NexusSmartAccount.d.ts +15 -0
  52. package/dist/types/AccountAbstraction/smartAccounts/SafeSmartAccount.d.ts +16 -0
  53. package/dist/types/AccountAbstraction/smartAccounts/SimpleSmartAccount.d.ts +16 -0
  54. package/dist/types/AccountAbstraction/smartAccounts/TrustSmartAccount.d.ts +16 -0
  55. package/dist/types/AccountAbstraction/smartAccounts/index.d.ts +5 -0
  56. package/dist/types/Block/PollingBlockTracker.d.ts +2 -2
  57. package/dist/types/Currency/CurrencyController.d.ts +2 -2
  58. package/dist/types/Message/AddChainController.d.ts +3 -6
  59. package/dist/types/Message/MessageController.d.ts +5 -8
  60. package/dist/types/Message/PersonalMessageController.d.ts +5 -8
  61. package/dist/types/Message/SwitchChainController.d.ts +3 -6
  62. package/dist/types/Message/TypedMessageController.d.ts +3 -3
  63. package/dist/types/Message/types.d.ts +2 -0
  64. package/dist/types/Message/utils.d.ts +2 -1
  65. package/dist/types/Network/createEthereumMiddleware.d.ts +2 -2
  66. package/dist/types/Nfts/NftsController.d.ts +2 -2
  67. package/dist/types/Preferences/PreferencesController.d.ts +1 -1
  68. package/dist/types/Tokens/ITokensController.d.ts +4 -6
  69. package/dist/types/Tokens/TokenRatesController.d.ts +6 -14
  70. package/dist/types/Tokens/TokensController.d.ts +7 -7
  71. package/dist/types/Transaction/TransactionController.d.ts +2 -2
  72. package/dist/types/index.d.ts +2 -6
  73. package/dist/types/utils/constants.d.ts +8 -10
  74. package/dist/types/utils/helpers.d.ts +0 -3
  75. package/dist/types/utils/interfaces.d.ts +27 -2
  76. package/package.json +6 -4
  77. package/dist/lib.cjs/Message/AbstractMessageController.js +0 -107
  78. package/dist/lib.esm/Message/AbstractMessageController.js +0 -105
  79. package/dist/types/Message/AbstractMessageController.d.ts +0 -35
@@ -1,19 +1,22 @@
1
1
  import _objectSpread from '@babel/runtime/helpers/objectSpread2';
2
2
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
3
- import { CHAIN_NAMESPACES, BaseController, randomId, TransactionStatus, TRANSACTION_TYPES, formatSmallNumbers, addressSlicer, ACTIVITY_ACTION_RECEIVE, ACTIVITY_ACTION_SEND, significantDigits, BaseBlockTracker, timeout, BaseCurrencyController, cloneDeep, BaseKeyringController, concatSig, PROVIDER_JRPC_METHODS, createFetchMiddleware, createInflightCacheMiddleware, createSwappableProxy, createEventEmitterProxy, BasePreferencesController, isUnauthorizedError, TX_EVENTS, BaseTransactionStateManager, omitBy, transactionMatchesNetwork as transactionMatchesNetwork$1, pickBy } from '@toruslabs/base-controllers';
3
+ import { CHAIN_NAMESPACES, BaseController, TransactionStatus, BaseBlockTracker, idleTimeTracker, timeout, BaseCurrencyController, cloneDeep, BaseKeyringController, concatSig, AbstractMessageController, MessageStatus, randomId, MESSAGE_EVENTS, PROVIDER_JRPC_METHODS, createFetchMiddleware, createInflightCacheMiddleware, createSwappableProxy, createEventEmitterProxy, TRANSACTION_TYPES, formatSmallNumbers, addressSlicer, ACTIVITY_ACTION_RECEIVE, ACTIVITY_ACTION_SEND, significantDigits, BasePreferencesController, isUnauthorizedError, TX_EVENTS, BaseTransactionStateManager, omitBy, transactionMatchesNetwork as transactionMatchesNetwork$1, pickBy } from '@toruslabs/base-controllers';
4
4
  import { Mutex } from 'async-mutex';
5
- import { BrowserProvider, toQuantity, Contract, Interface, SigningKey, hashMessage, TypedDataEncoder, isHexString as isHexString$1, JsonRpcProvider, Transaction, keccak256 } from 'ethers';
5
+ import { BrowserProvider, toQuantity, Contract, isHexString, SigningKey, hashMessage, TypedDataEncoder, JsonRpcProvider, Interface, Transaction, keccak256 } from 'ethers';
6
6
  import log from 'loglevel';
7
- import { isHexString, addHexPrefix, isValidAddress, stripHexPrefix, toChecksumAddress, bytesToHex, privateToPublic, privateToAddress, ecsign, bigIntToBytes } from '@ethereumjs/util';
8
- import BigNumber from 'bignumber.js';
9
- import { rpcErrors, providerErrors, createAsyncMiddleware, mergeMiddleware, createScaffoldMiddleware, providerFromMiddleware, JRPCEngine, providerFromEngine, SafeEventEmitter } from '@web3auth/auth';
7
+ import { JRPCEngine, providerFromEngine, createAsyncMiddleware, mergeMiddleware, createScaffoldMiddleware, providerFromMiddleware, rpcErrors, SafeEventEmitter, providerErrors } from '@web3auth/auth';
8
+ import { defineChain, createPublicClient, http, createWalletClient } from 'viem';
9
+ import { createPaymasterClient, createBundlerClient, entryPoint06Address, entryPoint07Address } from 'viem/account-abstraction';
10
10
  import { get } from '@toruslabs/http-helpers';
11
+ import { stripHexPrefix, isHexString as isHexString$1, addHexPrefix, bytesToHex, privateToPublic, toChecksumAddress, privateToAddress, ecsign, bigIntToBytes, isValidAddress } from '@ethereumjs/util';
12
+ import BigNumber from 'bignumber.js';
11
13
  import _objectDestructuringEmpty from '@babel/runtime/helpers/objectDestructuringEmpty';
12
14
  import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
13
15
  import BN, { BN as BN$1 } from 'bn.js';
14
16
  import stringify from 'fast-safe-stringify';
15
17
  import deepmerge from 'deepmerge';
16
18
  import jsonDiffer from 'fast-json-patch';
19
+ import { toBiconomySmartAccount, toEcdsaKernelSmartAccount, toNexusSmartAccount, toSafeSmartAccount, toTrustSmartAccount } from 'permissionless/accounts';
17
20
 
18
21
  const erc20Abi = [{
19
22
  constant: true,
@@ -827,16 +830,15 @@ const COINGECKO_PLATFORMS_CHAIN_CODE_MAP = {
827
830
  currency: "eth"
828
831
  }
829
832
  };
830
- const MessageStatus = {
831
- UNAPPROVED: "unapproved",
832
- SIGNED: "signed",
833
- PENDING: "pending",
834
- APPROVED: "approved",
835
- REJECTED: "rejected",
836
- FAILED: "failed"
837
- };
838
- const MESSAGE_EVENTS = {
839
- UNAPPROVED_MESSAGE: "unapprovedMessage"
833
+ const SMART_ACCOUNT = {
834
+ BICONOMY: "biconomy",
835
+ KERNEL: "kernel",
836
+ SAFE: "safe",
837
+ TRUST: "trust",
838
+ // TODO: disabled because of pimlico issues
839
+ LIGHT: "light",
840
+ SIMPLE: "simple",
841
+ NEXUS: "nexus"
840
842
  };
841
843
 
842
844
  const SINGLE_CALL_BALANCES_ADDRESSES = {
@@ -998,837 +1000,608 @@ class AccountTrackerController extends BaseController {
998
1000
  }
999
1001
  }
1000
1002
 
1001
- const erc20Interface = new Interface(erc20Abi);
1002
- const erc721Interface = new Interface(erc721Abi);
1003
- const erc1155Interface = new Interface(erc1155Abi);
1004
-
1005
- // functions that handle normalizing of that key in txParams
1006
-
1007
- const normalizers = {
1008
- from: (from, LowerCase = true) => LowerCase ? addHexPrefix(from).toLowerCase() : addHexPrefix(from),
1009
- to: (to, LowerCase = true) => LowerCase ? addHexPrefix(to).toLowerCase() : addHexPrefix(to),
1010
- nonce: nonce => addHexPrefix(nonce),
1011
- customNonceValue: nonce => addHexPrefix(nonce),
1012
- value: value => addHexPrefix(value),
1013
- data: data => addHexPrefix(data),
1014
- gas: gas => addHexPrefix(gas),
1015
- gasPrice: gasPrice => addHexPrefix(gasPrice),
1016
- type: addHexPrefix,
1017
- maxFeePerGas: addHexPrefix,
1018
- maxPriorityFeePerGas: addHexPrefix
1003
+ const eoaInterceptorMiddleware = eoaAddress => (req, res, next, end) => {
1004
+ req.isAAProviderRequest = true;
1005
+ if (req.method === "eth_accounts" || req.method === "eth_requestAccounts") {
1006
+ res.result = [eoaAddress];
1007
+ end();
1008
+ return;
1009
+ }
1010
+ next();
1019
1011
  };
1020
-
1021
- /**
1022
- * normalizes txParams
1023
- */
1024
- function normalizeTxParameters(txParameters, lowerCase = true) {
1025
- // apply only keys in the normalizers
1026
- const normalizedTxParameters = {
1027
- id: txParameters.id || randomId(),
1028
- from: txParameters.from
1012
+ function eoaProviderAsMiddleware(provider) {
1013
+ return async (req, res, _next, end) => {
1014
+ // send request to provider
1015
+ try {
1016
+ const providerRes = await provider.request(req);
1017
+ res.result = providerRes;
1018
+ return end();
1019
+ } catch (error) {
1020
+ return end(error);
1021
+ }
1029
1022
  };
1030
- for (const key in normalizers) {
1031
- const currentKey = key;
1032
- if (txParameters[currentKey])
1033
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1034
- normalizedTxParameters[currentKey] = normalizers[currentKey](txParameters[currentKey], lowerCase);
1035
- }
1036
- return normalizedTxParameters;
1037
1023
  }
1038
- function transactionMatchesNetwork(transaction, chainId) {
1039
- if (typeof transaction.chainId !== "undefined") {
1040
- return transaction.chainId === chainId;
1024
+ class AccountAbstractionController extends BaseController {
1025
+ constructor({
1026
+ config,
1027
+ state,
1028
+ getProviderConfig,
1029
+ onNetworkStateChange
1030
+ }) {
1031
+ super({
1032
+ state,
1033
+ config
1034
+ });
1035
+ _defineProperty(this, "_smartAccount", void 0);
1036
+ _defineProperty(this, "_publicClient", void 0);
1037
+ _defineProperty(this, "_walletClient", void 0);
1038
+ _defineProperty(this, "_bundlerClient", void 0);
1039
+ _defineProperty(this, "_paymasterClient", void 0);
1040
+ _defineProperty(this, "getProviderConfig", void 0);
1041
+ this.initialize();
1042
+ this.getProviderConfig = getProviderConfig;
1043
+ // TODO: handle network change in torus controller & call setupProvider
1044
+ onNetworkStateChange(networkState => {
1045
+ if (networkState.chainId !== this.config.chainId) {
1046
+ this.configure({
1047
+ chainId: networkState.chainId
1048
+ });
1049
+ }
1050
+ });
1051
+ }
1052
+ get smartAccount() {
1053
+ return this._smartAccount;
1054
+ }
1055
+ get bundlerClient() {
1056
+ return this._bundlerClient;
1057
+ }
1058
+ get walletClient() {
1059
+ return this._walletClient;
1060
+ }
1061
+ async setupProvider(eoaProvider, eoaAddress) {
1062
+ var _this$config$bundlerC;
1063
+ const providerConfig = this.getProviderConfig();
1064
+ const chain = defineChain({
1065
+ id: Number.parseInt(providerConfig.chainId, 16),
1066
+ // id in number form
1067
+ name: providerConfig.displayName,
1068
+ rpcUrls: {
1069
+ default: {
1070
+ http: [providerConfig.rpcTarget],
1071
+ webSocket: [providerConfig.wsTarget]
1072
+ }
1073
+ },
1074
+ blockExplorers: providerConfig.blockExplorerUrl ? {
1075
+ default: {
1076
+ name: "explorer",
1077
+ // TODO: correct name if chain config has it
1078
+ url: providerConfig.blockExplorerUrl
1079
+ }
1080
+ } : undefined,
1081
+ nativeCurrency: {
1082
+ name: providerConfig.tickerName,
1083
+ symbol: providerConfig.ticker,
1084
+ decimals: providerConfig.decimals || 18
1085
+ }
1086
+ });
1087
+ this._publicClient = createPublicClient({
1088
+ chain,
1089
+ transport: http(providerConfig.rpcTarget)
1090
+ });
1091
+ const aaEngine = new JRPCEngine();
1092
+ aaEngine.push(eoaInterceptorMiddleware(eoaAddress));
1093
+ aaEngine.push(eoaProviderAsMiddleware(eoaProvider));
1094
+ const provider = providerFromEngine(aaEngine);
1095
+ this._smartAccount = await this.config.smartAccountInit.getSmartAccount({
1096
+ owner: provider,
1097
+ client: this._publicClient
1098
+ });
1099
+ if (this.config.paymasterConfig) {
1100
+ var _this$config$paymaste;
1101
+ this._paymasterClient = createPaymasterClient(_objectSpread(_objectSpread({}, this.config.paymasterConfig), {}, {
1102
+ transport: (_this$config$paymaste = this.config.paymasterConfig.transport) !== null && _this$config$paymaste !== void 0 ? _this$config$paymaste : http(this.config.paymasterConfig.url)
1103
+ }));
1104
+ }
1105
+ this._bundlerClient = createBundlerClient(_objectSpread(_objectSpread({}, this.config.bundlerConfig), {}, {
1106
+ account: this.smartAccount,
1107
+ client: this._publicClient,
1108
+ transport: (_this$config$bundlerC = this.config.bundlerConfig.transport) !== null && _this$config$bundlerC !== void 0 ? _this$config$bundlerC : http(this.config.bundlerConfig.url),
1109
+ paymaster: this._paymasterClient
1110
+ }));
1111
+ this._walletClient = createWalletClient({
1112
+ account: this.smartAccount,
1113
+ chain,
1114
+ transport: http()
1115
+ });
1116
+ log.info("check: this._smartAccount", this.smartAccount.address);
1117
+ this.update({
1118
+ smartAccountAddress: this.smartAccount.address
1119
+ });
1120
+ }
1121
+ async sendTransaction(id, tx, address) {
1122
+ var _txParams$chainId;
1123
+ if (address.toLowerCase() !== this.smartAccount.address.toLowerCase()) {
1124
+ throw new Error("Invalid address");
1125
+ }
1126
+ const txParams = tx;
1127
+ const userOperationParams = {
1128
+ account: this.smartAccount,
1129
+ calls: [{
1130
+ to: txParams.to,
1131
+ // Explicit conversation required to avoid value being passed as hex
1132
+ value: BigInt(txParams.value),
1133
+ data: txParams.data
1134
+ }]
1135
+ // should not use maxFeePerGas/maxPriorityFeePerGas from transaction params since that's fee for transaction not user operation and let bundler handle it instead
1136
+ };
1137
+ const userOpMeta = {
1138
+ transactionParams: txParams,
1139
+ chainId: (_txParams$chainId = txParams.chainId) !== null && _txParams$chainId !== void 0 ? _txParams$chainId : this.getProviderConfig().chainId,
1140
+ createdAt: new Date(),
1141
+ status: TransactionStatus.approved
1142
+ };
1143
+ this.updateUserOpMeta(id, userOpMeta);
1144
+ // @ts-expect-error viem types are too deep
1145
+ const userOpHash = await this.bundlerClient.sendUserOperation(userOperationParams);
1146
+ this.updateUserOpMeta(id, {
1147
+ userOpHash,
1148
+ status: TransactionStatus.submitted
1149
+ });
1150
+ const txReceipt = await this.bundlerClient.waitForUserOperationReceipt({
1151
+ hash: userOpHash
1152
+ });
1153
+ this.updateUserOpMeta(id, {
1154
+ receipt: txReceipt,
1155
+ status: txReceipt.success ? TransactionStatus.confirmed : TransactionStatus.failed
1156
+ });
1157
+ return txReceipt.receipt.transactionHash;
1158
+ }
1159
+ async signMessage(message, address) {
1160
+ if (address.toLowerCase() !== this.smartAccount.address.toLowerCase()) {
1161
+ throw new Error("Invalid address");
1162
+ }
1163
+ return this.smartAccount.sign({
1164
+ hash: message
1165
+ });
1166
+ }
1167
+ async signPersonalMessage(message, address) {
1168
+ var _this$walletClient;
1169
+ if (address.toLowerCase() !== this.smartAccount.address.toLowerCase()) {
1170
+ throw new Error("Invalid address");
1171
+ }
1172
+ return (_this$walletClient = this.walletClient) === null || _this$walletClient === void 0 ? void 0 : _this$walletClient.signMessage({
1173
+ account: this.smartAccount,
1174
+ message: isHexString(message) ? {
1175
+ raw: message
1176
+ } : message
1177
+ });
1178
+ }
1179
+ async signTypedData(data, address) {
1180
+ var _this$walletClient2;
1181
+ if (address.toLowerCase() !== this.smartAccount.address.toLowerCase()) {
1182
+ throw new Error("Invalid address");
1183
+ }
1184
+ return (_this$walletClient2 = this.walletClient) === null || _this$walletClient2 === void 0 ? void 0 : _this$walletClient2.signTypedData({
1185
+ account: this.smartAccount,
1186
+ domain: _objectSpread(_objectSpread({}, data.domain), {}, {
1187
+ verifyingContract: data.domain.verifyingContract,
1188
+ salt: data.domain.salt,
1189
+ chainId: Number(data.domain.chainId)
1190
+ }),
1191
+ primaryType: data.primaryType,
1192
+ types: data.types,
1193
+ message: data.message
1194
+ });
1195
+ }
1196
+ updateUserOpMeta(id, data) {
1197
+ const userOp = this.state.userOperations[id];
1198
+ if (!userOp) return;
1199
+ this.update({
1200
+ userOperations: _objectSpread(_objectSpread({}, this.state.userOperations), {}, {
1201
+ [id]: _objectSpread(_objectSpread({}, userOp), data)
1202
+ })
1203
+ });
1041
1204
  }
1042
- return false;
1043
1205
  }
1044
1206
 
1045
- /**
1046
- * Determines if the maxFeePerGas and maxPriorityFeePerGas fields are supplied
1047
- * and valid inputs. This will return false for non hex string inputs.
1048
- * the transaction to check
1049
- * @returns true if transaction uses valid EIP1559 fields
1050
- */
1051
- function isEIP1559Transaction(transaction) {
1052
- var _transaction$transact, _transaction$transact2;
1053
- return isHexString(addHexPrefix(transaction === null || transaction === void 0 || (_transaction$transact = transaction.transaction) === null || _transaction$transact === void 0 ? void 0 : _transaction$transact.maxFeePerGas)) && isHexString(addHexPrefix(transaction === null || transaction === void 0 || (_transaction$transact2 = transaction.transaction) === null || _transaction$transact2 === void 0 ? void 0 : _transaction$transact2.maxPriorityFeePerGas));
1207
+ class BiconomySmartAccount {
1208
+ constructor(options) {
1209
+ _defineProperty(this, "name", SMART_ACCOUNT.BICONOMY);
1210
+ _defineProperty(this, "options", void 0);
1211
+ this.options = options;
1212
+ }
1213
+ async getSmartAccount(params) {
1214
+ var _this$options, _this$options2;
1215
+ return toBiconomySmartAccount(_objectSpread(_objectSpread(_objectSpread({}, this.options || {}), {}, {
1216
+ entryPoint: {
1217
+ address: ((_this$options = this.options) === null || _this$options === void 0 || (_this$options = _this$options.entryPoint) === null || _this$options === void 0 ? void 0 : _this$options.address) || entryPoint06Address,
1218
+ version: ((_this$options2 = this.options) === null || _this$options2 === void 0 || (_this$options2 = _this$options2.entryPoint) === null || _this$options2 === void 0 ? void 0 : _this$options2.version) || "0.6"
1219
+ }
1220
+ }, params), {}, {
1221
+ owners: [params.owner],
1222
+ client: params.client
1223
+ }));
1224
+ }
1054
1225
  }
1055
1226
 
1056
- /**
1057
- * Determine if the maxFeePerGas and maxPriorityFeePerGas fields are not
1058
- * supplied and that the gasPrice field is valid if it is provided. This will
1059
- * return false if gasPrice is a non hex string.
1060
- * transaction -
1061
- * the transaction to check
1062
- * @returns true if transaction uses valid Legacy fields OR lacks
1063
- * EIP1559 fields
1064
- */
1065
- function isLegacyTransaction(transaction) {
1066
- return typeof transaction.transaction.maxFeePerGas === "undefined" && typeof transaction.transaction.maxPriorityFeePerGas === "undefined" && (typeof transaction.transaction.gasPrice === "undefined" || isHexString(addHexPrefix(transaction.transaction.gasPrice)));
1067
- }
1227
+ // use type of function so we don't need to pass in generic to parameter type
1068
1228
 
1069
- /**
1070
- * Given two fields, ensure that the second field is not included in txParams,
1071
- * and if it is throw an invalidParams error.
1072
- */
1073
- function ensureMutuallyExclusiveFieldsNotProvided(txParams, fieldBeingValidated, mutuallyExclusiveField) {
1074
- if (typeof txParams[mutuallyExclusiveField] !== "undefined") {
1075
- throw rpcErrors.invalidParams(`Invalid transaction params: specified ${fieldBeingValidated} but also included ${mutuallyExclusiveField}, these cannot be mixed`);
1229
+ class KernelSmartAccount {
1230
+ constructor(options) {
1231
+ _defineProperty(this, "name", SMART_ACCOUNT.KERNEL);
1232
+ _defineProperty(this, "options", void 0);
1233
+ this.options = options;
1234
+ }
1235
+ async getSmartAccount(params) {
1236
+ return toEcdsaKernelSmartAccount(_objectSpread(_objectSpread(_objectSpread({}, this.options || {}), params), {}, {
1237
+ owners: [params.owner],
1238
+ client: params.client
1239
+ }));
1076
1240
  }
1077
1241
  }
1078
1242
 
1079
- /**
1080
- * Ensures that the provided value for field is a string, throws an
1081
- * invalidParams error if field is not a string.
1082
- */
1083
- function ensureFieldIsString(txParams, field) {
1084
- if (typeof txParams[field] !== "string") {
1085
- throw rpcErrors.invalidParams(`Invalid transaction params: ${field} is not a string. got: (${txParams[field]})`);
1243
+ class NexusSmartAccount {
1244
+ constructor(options) {
1245
+ _defineProperty(this, "name", SMART_ACCOUNT.NEXUS);
1246
+ _defineProperty(this, "options", void 0);
1247
+ this.options = options;
1248
+ }
1249
+ async getSmartAccount(params) {
1250
+ var _this$options, _this$options2, _this$options3;
1251
+ return toNexusSmartAccount(_objectSpread(_objectSpread(_objectSpread({}, this.options || {}), {}, {
1252
+ entryPoint: {
1253
+ address: ((_this$options = this.options) === null || _this$options === void 0 || (_this$options = _this$options.entryPoint) === null || _this$options === void 0 ? void 0 : _this$options.address) || entryPoint07Address,
1254
+ version: ((_this$options2 = this.options) === null || _this$options2 === void 0 || (_this$options2 = _this$options2.entryPoint) === null || _this$options2 === void 0 ? void 0 : _this$options2.version) || "0.7"
1255
+ },
1256
+ version: ((_this$options3 = this.options) === null || _this$options3 === void 0 ? void 0 : _this$options3.version) || "1.0.0"
1257
+ }, params), {}, {
1258
+ owners: [params.owner],
1259
+ client: params.client
1260
+ }));
1086
1261
  }
1087
1262
  }
1088
1263
 
1089
- /**
1090
- * Ensures that the provided txParams has the proper 'type' specified for the
1091
- * given field, if it is provided. If types do not match throws an
1092
- * invalidParams error.
1093
- */
1094
- function ensureProperTransactionEnvelopeTypeProvided(txParams, field) {
1095
- switch (field) {
1096
- case "maxFeePerGas":
1097
- case "maxPriorityFeePerGas":
1098
- if (txParams.type && txParams.type !== TRANSACTION_ENVELOPE_TYPES.FEE_MARKET) {
1099
- throw rpcErrors.invalidParams(`Invalid transaction envelope type: specified type "${txParams.type}" but ` + `including maxFeePerGas and maxPriorityFeePerGas requires type: "${TRANSACTION_ENVELOPE_TYPES.FEE_MARKET}"`);
1100
- }
1101
- break;
1102
- case "gasPrice":
1103
- default:
1104
- if (txParams.type && txParams.type === TRANSACTION_ENVELOPE_TYPES.FEE_MARKET) {
1105
- throw rpcErrors.invalidParams(`Invalid transaction envelope type: specified type "${txParams.type}" but ` + "included a gasPrice instead of maxFeePerGas and maxPriorityFeePerGas");
1106
- }
1264
+ // use type of function so we don't need to pass in generic to parameter type
1265
+
1266
+ class SafeSmartAccount {
1267
+ constructor(options) {
1268
+ _defineProperty(this, "name", SMART_ACCOUNT.SAFE);
1269
+ _defineProperty(this, "options", void 0);
1270
+ this.options = options;
1271
+ }
1272
+ async getSmartAccount(params) {
1273
+ var _this$options, _this$options2, _this$options3;
1274
+ return toSafeSmartAccount(_objectSpread(_objectSpread(_objectSpread({}, this.options || {}), {}, {
1275
+ entryPoint: {
1276
+ address: ((_this$options = this.options) === null || _this$options === void 0 || (_this$options = _this$options.entryPoint) === null || _this$options === void 0 ? void 0 : _this$options.address) || entryPoint07Address,
1277
+ version: ((_this$options2 = this.options) === null || _this$options2 === void 0 || (_this$options2 = _this$options2.entryPoint) === null || _this$options2 === void 0 ? void 0 : _this$options2.version) || "0.7"
1278
+ },
1279
+ version: ((_this$options3 = this.options) === null || _this$options3 === void 0 ? void 0 : _this$options3.version) || "1.4.1"
1280
+ }, params), {}, {
1281
+ owners: [params.owner],
1282
+ client: params.client
1283
+ }));
1107
1284
  }
1108
1285
  }
1109
1286
 
1110
- /**
1111
- * validates the from field in txParams
1112
- */
1113
- function validateFrom(txParams) {
1114
- if (!(typeof txParams.from === "string")) {
1115
- throw rpcErrors.invalidParams(`Invalid "from" address "${txParams.from}": not a string.`);
1116
- }
1117
- if (!isValidAddress(txParams.from)) {
1118
- throw rpcErrors.invalidParams('Invalid "from" address.');
1287
+ // use type of function so we don't need to pass in generic to parameter type
1288
+
1289
+ class TrustSmartAccount {
1290
+ constructor(options) {
1291
+ _defineProperty(this, "name", SMART_ACCOUNT.TRUST);
1292
+ _defineProperty(this, "options", void 0);
1293
+ this.options = options;
1294
+ }
1295
+ async getSmartAccount(params) {
1296
+ var _this$options, _this$options2;
1297
+ return toTrustSmartAccount(_objectSpread(_objectSpread(_objectSpread({}, this.options || {}), {}, {
1298
+ entryPoint: {
1299
+ address: ((_this$options = this.options) === null || _this$options === void 0 || (_this$options = _this$options.entryPoint) === null || _this$options === void 0 ? void 0 : _this$options.address) || entryPoint06Address,
1300
+ version: ((_this$options2 = this.options) === null || _this$options2 === void 0 || (_this$options2 = _this$options2.entryPoint) === null || _this$options2 === void 0 ? void 0 : _this$options2.version) || "0.6"
1301
+ }
1302
+ }, params), {}, {
1303
+ owner: params.owner,
1304
+ client: params.client
1305
+ }));
1119
1306
  }
1120
1307
  }
1121
1308
 
1122
- /**
1123
- * validates the to field in txParams
1124
- */
1125
- function validateRecipient(txParameters) {
1126
- if (txParameters.to === "0x" || txParameters.to === null) {
1127
- if (txParameters.data) {
1128
- delete txParameters.to;
1129
- } else {
1130
- throw rpcErrors.invalidParams('Invalid "to" address.');
1309
+ const DEFAULT_POLLING_INTERVAL = 20;
1310
+ const DEFAULT_RETRY_TIMEOUT = 2;
1311
+ const SEC = 1000;
1312
+ class PollingBlockTracker extends BaseBlockTracker {
1313
+ constructor({
1314
+ config,
1315
+ state = {}
1316
+ }) {
1317
+ if (!config.provider) {
1318
+ throw new Error("PollingBlockTracker - no provider specified.");
1131
1319
  }
1132
- } else if (txParameters.to !== undefined && !isValidAddress(txParameters.to)) {
1133
- throw rpcErrors.invalidParams('Invalid "to" address.');
1320
+ super({
1321
+ config,
1322
+ state
1323
+ });
1324
+ const pollingInterval = config.pollingInterval || DEFAULT_POLLING_INTERVAL;
1325
+ const retryTimeout = config.retryTimeout || DEFAULT_RETRY_TIMEOUT;
1326
+
1327
+ // merge default + provided config.
1328
+ this.defaultConfig = {
1329
+ provider: config.provider,
1330
+ pollingInterval: pollingInterval * SEC,
1331
+ retryTimeout: retryTimeout * SEC,
1332
+ setSkipCacheFlag: config.setSkipCacheFlag || false
1333
+ };
1334
+ this.initialize();
1335
+ }
1336
+ async checkForLatestBlock() {
1337
+ await this._updateLatestBlock();
1338
+ return this.getLatestBlock();
1134
1339
  }
1135
- return txParameters;
1136
- }
1137
1340
 
1138
- /**
1139
- * Validates the given tx parameters
1140
- * @throws if the tx params contains invalid fields
1141
- */
1142
- function validateTxParameters(txParams, eip1559Compatibility = true) {
1143
- if (!txParams || typeof txParams !== "object" || Array.isArray(txParams)) {
1144
- throw rpcErrors.invalidParams("Invalid transaction params: must be an object.");
1341
+ // overrides the BaseBlockTracker._start method.
1342
+ _start() {
1343
+ this._synchronize().catch(err => this.emit("error", err));
1145
1344
  }
1146
- if (!txParams.to && !txParams.data) {
1147
- throw rpcErrors.invalidParams('Invalid transaction params: must specify "data" for contract deployments, or "to" (and optionally "data") for all other types of transactions.');
1345
+ async _synchronize() {
1346
+ while (this.state._isRunning) {
1347
+ if (idleTimeTracker.checkIfIdle()) return;
1348
+ try {
1349
+ await this._updateLatestBlock();
1350
+ await timeout(this.config.pollingInterval);
1351
+ } catch (err) {
1352
+ const newErr = new Error(`PollingBlockTracker - encountered an error while attempting to update latest block:\n${err.stack}`);
1353
+ try {
1354
+ this.emit("error", newErr);
1355
+ } catch (emitErr) {
1356
+ log.error(newErr);
1357
+ }
1358
+ await timeout(this.config.retryTimeout);
1359
+ }
1360
+ }
1148
1361
  }
1149
- if (isEIP1559Transaction({
1150
- transaction: txParams
1151
- }) && !eip1559Compatibility) {
1152
- throw rpcErrors.invalidParams("Invalid transaction params: params specify an EIP-1559 transaction but the current network does not support EIP-1559");
1362
+ async _updateLatestBlock() {
1363
+ // fetch + set latest block
1364
+ const latestBlock = await this._fetchLatestBlock();
1365
+ this._newPotentialLatest(latestBlock);
1153
1366
  }
1154
- Object.entries(txParams).forEach(([key, value]) => {
1155
- // validate types
1156
- switch (key) {
1157
- case "from":
1158
- validateFrom(txParams);
1159
- break;
1160
- case "to":
1161
- validateRecipient(txParams);
1162
- break;
1163
- case "gasPrice":
1164
- ensureProperTransactionEnvelopeTypeProvided(txParams, "gasPrice");
1165
- ensureMutuallyExclusiveFieldsNotProvided(txParams, "gasPrice", "maxFeePerGas");
1166
- ensureMutuallyExclusiveFieldsNotProvided(txParams, "gasPrice", "maxPriorityFeePerGas");
1167
- ensureFieldIsString(txParams, "gasPrice");
1168
- break;
1169
- case "maxFeePerGas":
1170
- ensureProperTransactionEnvelopeTypeProvided(txParams, "maxFeePerGas");
1171
- ensureMutuallyExclusiveFieldsNotProvided(txParams, "maxFeePerGas", "gasPrice");
1172
- ensureFieldIsString(txParams, "maxFeePerGas");
1173
- break;
1174
- case "maxPriorityFeePerGas":
1175
- ensureProperTransactionEnvelopeTypeProvided(txParams, "maxPriorityFeePerGas");
1176
- ensureMutuallyExclusiveFieldsNotProvided(txParams, "maxPriorityFeePerGas", "gasPrice");
1177
- ensureFieldIsString(txParams, "maxPriorityFeePerGas");
1178
- break;
1179
- case "value":
1180
- ensureFieldIsString(txParams, "value");
1181
- if (value.toString().includes("-")) {
1182
- throw rpcErrors.invalidParams(`Invalid transaction value "${value}": not a positive number.`);
1183
- }
1184
- if (value.toString().includes(".")) {
1185
- throw rpcErrors.invalidParams(`Invalid transaction value of "${value}": number must be in wei.`);
1186
- }
1187
- break;
1188
- case "chainId":
1189
- if (typeof value !== "number" && typeof value !== "string") {
1190
- throw rpcErrors.invalidParams(`Invalid transaction params: ${key} is not a Number or hex string. got: (${value})`);
1191
- }
1192
- break;
1193
- default:
1194
- ensureFieldIsString(txParams, key);
1367
+ async _fetchLatestBlock() {
1368
+ try {
1369
+ const block = await this.config.provider.request({
1370
+ method: "eth_getBlockByNumber",
1371
+ params: ["latest", false]
1372
+ });
1373
+ return {
1374
+ blockHash: block.hash,
1375
+ idempotencyKey: block.number,
1376
+ timestamp: block.timestamp,
1377
+ baseFeePerGas: block.baseFeePerGas,
1378
+ gasLimit: block.gasLimit
1379
+ };
1380
+ } catch (error) {
1381
+ log.error("Polling Block Tracker: ", error);
1382
+ throw new Error(`PollingBlockTracker - encountered error fetching block:\n${error.message}`);
1195
1383
  }
1196
- });
1197
- }
1198
- function normalizeAndValidateTxParams(txParams, lowerCase = true) {
1199
- const normalizedTxParams = normalizeTxParameters(txParams, lowerCase);
1200
- validateTxParameters(normalizedTxParams);
1201
- return normalizedTxParams;
1384
+ }
1202
1385
  }
1203
1386
 
1204
- /**
1205
- * @returns an array of states that can be considered final
1206
- */
1207
- function getFinalStates() {
1208
- return [TransactionStatus.rejected,
1209
- // the user has responded no!
1210
- TransactionStatus.confirmed,
1211
- // the tx has been included in a block.
1212
- TransactionStatus.failed,
1213
- // the tx failed for some reason, included on tx data.
1214
- TransactionStatus.dropped // the tx nonce was already used
1215
- ];
1216
- }
1217
- function parseStandardTokenTransactionData(data) {
1218
- try {
1219
- const txDesc = erc20Interface.parseTransaction({
1220
- data
1387
+ class CurrencyController extends BaseCurrencyController {
1388
+ constructor({
1389
+ config,
1390
+ state,
1391
+ onNetworkChanged
1392
+ }) {
1393
+ super({
1394
+ config,
1395
+ state
1221
1396
  });
1222
- if (txDesc) return {
1223
- name: txDesc.name,
1224
- methodParams: txDesc.args.toArray(),
1225
- type: CONTRACT_TYPE_ERC20
1226
- };
1227
- } catch {
1228
- // ignore and next try to parse with erc721 ABI
1229
- }
1230
- try {
1231
- const txDesc = erc721Interface.parseTransaction({
1232
- data
1397
+ _defineProperty(this, "conversionInterval", void 0);
1398
+ this.defaultState = _objectSpread(_objectSpread({}, this.defaultState), {}, {
1399
+ commonDenomination: "USD",
1400
+ commonDenominatorPrice: 0
1401
+ });
1402
+ this.initialize();
1403
+ onNetworkChanged(networkState => {
1404
+ // to be called as (listener) => this.networkController.on('networkDidChange', listener);
1405
+ if (networkState.providerConfig.ticker.toUpperCase() !== this.state.nativeCurrency.toUpperCase()) {
1406
+ this.setNativeCurrency(networkState.providerConfig.ticker);
1407
+ this.updateConversionRate();
1408
+ }
1233
1409
  });
1234
- if (txDesc) return {
1235
- name: txDesc.name,
1236
- methodParams: txDesc.args.toArray(),
1237
- type: CONTRACT_TYPE_ERC721
1238
- };
1239
- } catch {
1240
- // ignore and next try to parse with erc1155 ABI
1241
1410
  }
1242
- try {
1243
- const txDesc = erc1155Interface.parseTransaction({
1244
- data
1411
+ setCommonDenomination(commonDenomination) {
1412
+ this.update({
1413
+ commonDenomination
1245
1414
  });
1246
- if (txDesc) return {
1247
- name: txDesc.name,
1248
- methodParams: txDesc.args.toArray(),
1249
- type: CONTRACT_TYPE_ERC1155
1250
- };
1251
- } catch {
1252
- // ignore and return undefined
1253
1415
  }
1254
- return undefined;
1255
- }
1256
- const readAddressAsContract = async (provider, address) => {
1257
- let contractCode;
1258
- try {
1259
- contractCode = await provider.request({
1260
- method: METHOD_TYPES.ETH_GET_CODE,
1261
- params: [address, "latest"]
1416
+ getCommonDenomination() {
1417
+ return this.state.commonDenomination;
1418
+ }
1419
+ setCommonDenominatorPrice(commonDenominatorPrice) {
1420
+ this.update({
1421
+ commonDenominatorPrice
1262
1422
  });
1263
- } catch (e) {
1264
- contractCode = null;
1265
1423
  }
1266
- const isContractAddress = contractCode ? contractCode !== "0x" && contractCode !== "0x0" : false;
1267
- return {
1268
- contractCode,
1269
- isContractAddress
1270
- };
1271
- };
1272
- async function determineTransactionType(txParams, provider) {
1273
- const {
1274
- data,
1275
- to
1276
- } = txParams;
1277
- let name = "";
1278
- let methodParams = [];
1279
- let type = "";
1280
- try {
1281
- ({
1282
- name,
1283
- methodParams,
1284
- type
1285
- } = data && parseStandardTokenTransactionData(data) || {});
1286
- } catch (error) {
1287
- log.debug("Failed to parse transaction data", error);
1424
+ getCommonDenominatorPrice() {
1425
+ return this.state.commonDenominatorPrice;
1288
1426
  }
1289
- let result;
1290
- let contractCode = "";
1291
- if (data && !to) {
1292
- result = TRANSACTION_TYPES.DEPLOY_CONTRACT;
1293
- } else {
1294
- const {
1295
- contractCode: resultCode,
1296
- isContractAddress
1297
- } = await readAddressAsContract(provider, to);
1298
- contractCode = resultCode;
1299
- if (isContractAddress) {
1300
- const valueExists = txParams.value && Number(txParams.value) !== 0;
1301
- const tokenMethodName = [TRANSACTION_TYPES.TOKEN_METHOD_APPROVE, TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER, TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM, TRANSACTION_TYPES.COLLECTIBLE_METHOD_SAFE_TRANSFER_FROM, TRANSACTION_TYPES.SET_APPROVAL_FOR_ALL].find(x => {
1302
- var _name;
1303
- return x.toLowerCase() === ((_name = name) === null || _name === void 0 ? void 0 : _name.toLowerCase());
1304
- });
1305
- result = data && tokenMethodName && !valueExists ? tokenMethodName : TRANSACTION_TYPES.CONTRACT_INTERACTION;
1427
+
1428
+ /**
1429
+ * Creates a new poll, using setInterval, to periodically call updateConversionRate. The id of the interval is
1430
+ * stored at the controller's conversionInterval property. If it is called and such an id already exists, the
1431
+ * previous interval is clear and a new one is created.
1432
+ */
1433
+ scheduleConversionInterval() {
1434
+ if (this.conversionInterval) {
1435
+ window.clearInterval(this.conversionInterval);
1436
+ }
1437
+ this.conversionInterval = window.setInterval(() => {
1438
+ if (!idleTimeTracker.checkIfIdle()) {
1439
+ this.updateConversionRate();
1440
+ }
1441
+ }, this.config.pollInterval);
1442
+ }
1443
+
1444
+ /**
1445
+ * Updates the conversionRate and conversionDate properties associated with the currentCurrency. Updated info is
1446
+ * fetched from an external API
1447
+ */
1448
+ async updateConversionRate() {
1449
+ const currentCurrency = this.getCurrentCurrency();
1450
+ const nativeCurrency = this.getNativeCurrency();
1451
+ const commonDenomination = this.getCommonDenomination();
1452
+ const conversionRate = await this.retrieveConversionRate(nativeCurrency, currentCurrency, commonDenomination);
1453
+ const currentCurrencyRate = Number.parseFloat(conversionRate[currentCurrency.toUpperCase()]);
1454
+ const commonDenominationRate = Number.parseFloat(conversionRate[commonDenomination.toUpperCase()]);
1455
+ // set conversion rate
1456
+ if (currentCurrencyRate || commonDenominationRate) {
1457
+ // ETC
1458
+ this.setConversionRate(currentCurrencyRate);
1459
+ this.setConversionDate(Math.floor(Date.now() / 1000).toString());
1460
+ if (currentCurrency.toUpperCase() === commonDenomination.toUpperCase()) {
1461
+ this.setCommonDenominatorPrice(currentCurrencyRate);
1462
+ } else {
1463
+ this.setCommonDenominatorPrice(commonDenominationRate);
1464
+ }
1306
1465
  } else {
1307
- result = TRANSACTION_TYPES.SENT_ETHER;
1466
+ this.setConversionRate(0);
1467
+ this.setConversionDate("N/A");
1308
1468
  }
1309
1469
  }
1310
- return {
1311
- type: type || CONTRACT_TYPE_ETH,
1312
- category: result,
1313
- methodParams,
1314
- getCodeResponse: contractCode
1315
- };
1470
+ async retrieveConversionRate(fromCurrency, toCurrency, commonDenomination) {
1471
+ try {
1472
+ let apiUrl = `${this.config.api}/currency?fsym=${fromCurrency.toUpperCase()}&tsyms=${toCurrency.toUpperCase()}`;
1473
+ if (commonDenomination && commonDenomination.toUpperCase() !== toCurrency.toUpperCase()) {
1474
+ apiUrl += `,${commonDenomination.toUpperCase()}`;
1475
+ }
1476
+ const parsedResponse = await get(apiUrl);
1477
+ return parsedResponse;
1478
+ } catch (error) {
1479
+ log.error(error, `CurrencyController - updateCommonDenominatorPrice: Failed to query rate for currency: ${fromCurrency}/ ${toCurrency}`);
1480
+ }
1481
+ return {
1482
+ [toCurrency.toUpperCase()]: "0",
1483
+ [commonDenomination.toUpperCase()]: "0"
1484
+ };
1485
+ }
1316
1486
  }
1317
1487
 
1318
- function hexToBn(hex) {
1319
- return new BigNumber(stripHexPrefix(hex), 16);
1320
- }
1321
- function BNToHex(bn) {
1322
- return addHexPrefix(bn.toString(16));
1323
- }
1324
- function getEtherScanHashLink(txHash, chainId) {
1325
- if (!SUPPORTED_NETWORKS[chainId]) return "";
1326
- return `${SUPPORTED_NETWORKS[chainId].blockExplorerUrl}/tx/${txHash}`;
1327
- }
1328
- const formatPastTx = params => {
1329
- var _transaction$to;
1330
- const {
1331
- transaction,
1332
- lowerCaseSelectedAddress,
1333
- blockExplorerUrl
1334
- } = params;
1335
- let totalAmountString = "";
1336
- if (transaction.type === CONTRACT_TYPE_ERC721 || transaction.type === CONTRACT_TYPE_ERC1155) totalAmountString = transaction.symbol;else if (transaction.type === CONTRACT_TYPE_ERC20) totalAmountString = formatSmallNumbers(Number.parseFloat(transaction.total_amount), transaction.symbol, true);else totalAmountString = formatSmallNumbers(Number.parseFloat(transaction.total_amount), transaction.type_name, true);
1337
- const currencyAmountString = transaction.type === CONTRACT_TYPE_ERC721 || transaction.type === CONTRACT_TYPE_ERC1155 || transaction.isEtherscan ? "" : formatSmallNumbers(Number.parseFloat(transaction.currency_amount), transaction.selected_currency, true);
1338
- const finalObject = {
1339
- id: transaction.created_at.toString(),
1340
- date: new Date(transaction.created_at).toString(),
1341
- from: transaction.from,
1342
- from_aa_address: transaction.from_aa_address,
1343
- slicedFrom: typeof transaction.from === "string" ? addressSlicer(transaction.from) : "",
1344
- to: transaction.to,
1345
- slicedTo: typeof transaction.to === "string" ? addressSlicer(transaction.to) : "",
1346
- action: lowerCaseSelectedAddress === ((_transaction$to = transaction.to) === null || _transaction$to === void 0 ? void 0 : _transaction$to.toLowerCase()) || "" ? ACTIVITY_ACTION_RECEIVE : ACTIVITY_ACTION_SEND,
1347
- totalAmount: transaction.total_amount,
1348
- totalAmountString,
1349
- currencyAmount: transaction.currency_amount,
1350
- currencyAmountString,
1351
- amount: `${totalAmountString} / ${currencyAmountString}`,
1352
- status: transaction.status,
1353
- etherscanLink: blockExplorerUrl ? `${blockExplorerUrl}/tx/${transaction.transaction_hash}` : "",
1354
- chainId: transaction.chain_id,
1355
- ethRate: Number.parseFloat(transaction === null || transaction === void 0 ? void 0 : transaction.total_amount) && Number.parseFloat(transaction === null || transaction === void 0 ? void 0 : transaction.currency_amount) ? `1 ${transaction.symbol} = ${significantDigits(Number.parseFloat(transaction.currency_amount) / Number.parseFloat(transaction.total_amount))}` : "",
1356
- currencyUsed: transaction.selected_currency,
1357
- type: transaction.type,
1358
- type_name: transaction.type_name,
1359
- type_image_link: transaction.type_image_link,
1360
- transaction_hash: transaction.transaction_hash,
1361
- transaction_category: transaction.transaction_category,
1362
- isEtherscan: transaction.isEtherscan,
1363
- input: transaction.input || "",
1364
- token_id: transaction.token_id || "",
1365
- contract_address: transaction.contract_address || "",
1366
- nonce: transaction.nonce || "",
1367
- is_cancel: !!transaction.is_cancel || false,
1368
- gas: transaction.gas || "",
1369
- gasPrice: transaction.gasPrice || ""
1370
- };
1371
- return finalObject;
1488
+ const _excluded$1 = ["aBase", "bBase"],
1489
+ _excluded2 = ["aBase", "bBase"],
1490
+ _excluded3 = ["multiplicandBase", "multiplierBase"];
1491
+
1492
+ // Big Number Constants
1493
+ const BIG_NUMBER_WEI_MULTIPLIER = new BigNumber("1000000000000000000");
1494
+ const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber("1000000000");
1495
+ const BIG_NUMBER_ETH_MULTIPLIER = new BigNumber("1");
1496
+ // Setter Maps
1497
+ const toBigNumber = {
1498
+ hex: n => new BigNumber(stripHexPrefix(n), 16),
1499
+ dec: n => new BigNumber(String(n), 10),
1500
+ BN: n => new BigNumber(n.toString(16), 16)
1501
+ };
1502
+ const toNormalizedDenomination = {
1503
+ WEI: bigNumber => bigNumber.div(BIG_NUMBER_WEI_MULTIPLIER),
1504
+ GWEI: bigNumber => bigNumber.div(BIG_NUMBER_GWEI_MULTIPLIER),
1505
+ ETH: bigNumber => bigNumber.div(BIG_NUMBER_ETH_MULTIPLIER)
1506
+ };
1507
+ const toSpecifiedDenomination = {
1508
+ WEI: bigNumber => bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).dp(0, BigNumber.ROUND_HALF_UP),
1509
+ GWEI: bigNumber => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).dp(9, BigNumber.ROUND_HALF_UP),
1510
+ ETH: bigNumber => bigNumber.times(BIG_NUMBER_ETH_MULTIPLIER).dp(9, BigNumber.ROUND_HALF_UP)
1511
+ };
1512
+ const baseChange = {
1513
+ hex: n => n.toString(16),
1514
+ dec: n => new BigNumber(n).toString(10),
1515
+ BN: n => new BN(n.toString(16))
1372
1516
  };
1373
1517
 
1518
+ // Utility function for checking base types
1519
+ const isValidBase = base => Number.isInteger(base) && base > 1;
1520
+
1374
1521
  /**
1375
- * Ref - https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionreceipt
1522
+ * Utility method to convert a value between denominations, formats and currencies.
1376
1523
  */
1377
- const getEthTxStatus = async (hash, provider) => {
1378
- try {
1379
- const result = await provider.request({
1380
- method: METHOD_TYPES.ETH_GET_TRANSACTION_RECEIPT,
1381
- params: [hash]
1382
- });
1383
- if (result === null) return TransactionStatus.submitted;
1384
- if (result && result.status === "0x1") return TransactionStatus.confirmed;
1385
- if (result && result.status === "0x0") return TransactionStatus.rejected;
1386
- return undefined;
1387
- } catch (err) {
1388
- log.warn("unable to fetch transaction status", err);
1389
- return undefined;
1524
+ const converter = ({
1525
+ value,
1526
+ fromNumericBase,
1527
+ fromDenomination,
1528
+ fromCurrency,
1529
+ toNumericBase,
1530
+ toDenomination,
1531
+ toCurrency,
1532
+ numberOfDecimals,
1533
+ conversionRate,
1534
+ invertConversionRate,
1535
+ roundDown
1536
+ }) => {
1537
+ let convertedValue = fromNumericBase ? toBigNumber[fromNumericBase](value) : value;
1538
+ if (fromDenomination) {
1539
+ convertedValue = toNormalizedDenomination[fromDenomination](convertedValue);
1390
1540
  }
1391
- };
1392
- function formatDate(inputDate) {
1393
- const monthList = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
1394
- const date = new Date(inputDate);
1395
- const day = date.getDate();
1396
- const month = monthList[date.getMonth()];
1397
- const year = date.getFullYear();
1398
- return `${day} ${month} ${year}`;
1399
- }
1400
- function formatTime(time) {
1401
- return new Date(time).toTimeString().slice(0, 8);
1402
- }
1403
- const idleTimeTracker = (activityThresholdTime => {
1404
- let isIdle = false;
1405
- let idleTimeout = null;
1406
- const resetTimer = () => {
1407
- if (idleTimeout) {
1408
- window.clearTimeout(idleTimeout);
1409
- }
1410
- isIdle = false;
1411
- idleTimeout = window.setTimeout(() => {
1412
- isIdle = true;
1413
- }, activityThresholdTime * 1000);
1414
- };
1415
- if (typeof window !== "undefined" && typeof document !== "undefined") {
1416
- window.addEventListener("load", resetTimer);
1417
- document.addEventListener("mousemove", resetTimer);
1418
- document.addEventListener("keydown", resetTimer);
1541
+ if (fromCurrency !== toCurrency) {
1542
+ if (conversionRate === null || conversionRate === undefined) {
1543
+ throw new Error(`Converting from ${fromCurrency} to ${toCurrency} requires a conversionRate, but one was not provided`);
1544
+ }
1545
+ let rate = toBigNumber.dec(conversionRate);
1546
+ if (invertConversionRate) {
1547
+ rate = new BigNumber(1).div(conversionRate);
1548
+ }
1549
+ convertedValue = convertedValue.times(rate);
1550
+ }
1551
+ if (toDenomination) {
1552
+ convertedValue = toSpecifiedDenomination[toDenomination](convertedValue);
1419
1553
  }
1420
- function checkIfIdle() {
1421
- return isIdle;
1554
+ if (numberOfDecimals) {
1555
+ convertedValue = convertedValue.dp(numberOfDecimals, BigNumber.ROUND_HALF_DOWN);
1422
1556
  }
1423
- return {
1424
- checkIfIdle
1425
- };
1426
- })(60 * 3);
1427
- function isAddressByChainId(address, _chainId) {
1428
- // TOOD: add rsk network checks.
1429
- return isValidAddress(address);
1430
- }
1431
- function toChecksumAddressByChainId(address, chainId) {
1432
- // TOOD: add rsk network checks.
1433
- if (!isAddressByChainId(address)) return address;
1434
- return toChecksumAddress(address);
1435
- }
1436
- const GAS_LIMITS = {
1437
- // maximum gasLimit of a simple send
1438
- SIMPLE: addHexPrefix(21000 .toString(16)),
1439
- // a base estimate for token transfers.
1440
- BASE_TOKEN_ESTIMATE: addHexPrefix(100000 .toString(16))
1557
+ if (roundDown) {
1558
+ convertedValue = convertedValue.dp(roundDown, BigNumber.ROUND_DOWN);
1559
+ }
1560
+ if (toNumericBase) {
1561
+ convertedValue = baseChange[toNumericBase](convertedValue);
1562
+ }
1563
+ return convertedValue;
1441
1564
  };
1442
- function bnLessThan(a, b) {
1443
- if (a === null || a === undefined || b === null || b === undefined) {
1444
- return null;
1565
+ const conversionUtil = (value, {
1566
+ fromCurrency = null,
1567
+ toCurrency = fromCurrency,
1568
+ fromNumericBase,
1569
+ toNumericBase,
1570
+ fromDenomination,
1571
+ toDenomination,
1572
+ numberOfDecimals,
1573
+ conversionRate,
1574
+ invertConversionRate
1575
+ }) => {
1576
+ if (fromCurrency !== toCurrency && !conversionRate) {
1577
+ return 0;
1445
1578
  }
1446
- return new BigNumber(a, 10).lt(b, 10);
1447
- }
1448
- const getIpfsEndpoint = path => `https://infura-ipfs.io/${path}`;
1449
- function sanitizeNftMetdataUrl(url) {
1450
- let finalUri = url;
1451
- if (url !== null && url !== void 0 && url.startsWith("ipfs")) {
1452
- const ipfsPath = url.split("ipfs://")[1];
1453
- finalUri = getIpfsEndpoint(ipfsPath);
1579
+ return converter({
1580
+ fromCurrency,
1581
+ toCurrency,
1582
+ fromNumericBase,
1583
+ toNumericBase,
1584
+ fromDenomination,
1585
+ toDenomination,
1586
+ numberOfDecimals,
1587
+ conversionRate,
1588
+ invertConversionRate,
1589
+ value
1590
+ });
1591
+ };
1592
+ const getBigNumber = (value, base) => {
1593
+ if (!isValidBase(base)) {
1594
+ throw new Error("Must specificy valid base");
1454
1595
  }
1455
- return finalUri;
1456
- }
1457
- function getChainType(chainId) {
1458
- if (chainId === MAINNET_CHAIN_ID) {
1459
- return "mainnet";
1460
- } else if (TEST_CHAINS.includes(chainId)) {
1461
- return "testnet";
1596
+
1597
+ // We don't include 'number' here, because BigNumber will throw if passed
1598
+ // a number primitive it considers unsafe.
1599
+ if (typeof value === "string" || value instanceof BigNumber) {
1600
+ return new BigNumber(value, base);
1462
1601
  }
1463
- return "custom";
1464
- }
1465
- const addEtherscanTransactions = async params => {
1466
- const {
1467
- txn,
1468
- lowerCaseSelectedAddress,
1469
- provider,
1470
- chainId,
1471
- blockExplorerUrl
1472
- } = params;
1473
- const transactionPromises = await Promise.all(txn.map(async tx => {
1474
- var _SUPPORTED_NETWORKS$c, _SUPPORTED_NETWORKS$c2;
1475
- const {
1476
- category,
1477
- type
1478
- } = await determineTransactionType(_objectSpread(_objectSpread({}, tx), {}, {
1479
- data: tx.input
1480
- }), provider);
1481
- tx.transaction_category = tx.transaction_category || category;
1482
- tx.type_image_link = ((_SUPPORTED_NETWORKS$c = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c === void 0 ? void 0 : _SUPPORTED_NETWORKS$c.logo) || "";
1483
- tx.type_name = (_SUPPORTED_NETWORKS$c2 = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c2 === void 0 ? void 0 : _SUPPORTED_NETWORKS$c2.ticker;
1484
- tx.type = type;
1485
- return tx;
1486
- }));
1487
- const finalTxs = transactionPromises.reduce((accumulator, x) => {
1488
- var _SUPPORTED_NETWORKS$c3, _SUPPORTED_NETWORKS$c4;
1489
- let totalAmountString = x.value ? new BigNumber(x.value).div(new BigNumber(10).pow(new BigNumber(x.tokenDecimal || 18))).toString() : "";
1490
- let type = CONTRACT_TYPE_ETH;
1491
- if (x.contractAddress !== "") {
1492
- if (x.tokenID) {
1493
- type = x.tokenValue ? CONTRACT_TYPE_ERC1155 : CONTRACT_TYPE_ERC721;
1494
- } else {
1495
- type = CONTRACT_TYPE_ERC20;
1496
- }
1497
- }
1498
- if (type === CONTRACT_TYPE_ERC1155) {
1499
- totalAmountString = x.tokenValue;
1500
- }
1501
- const etherscanTransaction = {
1502
- type,
1503
- type_image_link: x.type_image_link || "n/a",
1504
- type_name: x.tokenName || ((_SUPPORTED_NETWORKS$c3 = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c3 === void 0 ? void 0 : _SUPPORTED_NETWORKS$c3.ticker) || "n/a",
1505
- symbol: x.tokenSymbol || ((_SUPPORTED_NETWORKS$c4 = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c4 === void 0 ? void 0 : _SUPPORTED_NETWORKS$c4.ticker),
1506
- token_id: x.tokenID || "",
1507
- total_amount: totalAmountString,
1508
- created_at: new Date(Number(x.timeStamp) * 1000),
1509
- from: x.from,
1510
- to: x.to,
1511
- transaction_hash: x.hash,
1512
- status: x.txreceipt_status && x.txreceipt_status === "0" ? TransactionStatus.failed : TransactionStatus.confirmed,
1513
- isEtherscan: true,
1514
- input: x.input,
1515
- contract_address: x.contractAddress,
1516
- transaction_category: x.transaction_category,
1517
- gas: `0x${new BigNumber(x.gasUsed || 0, 10).toString(16)}`,
1518
- gasPrice: `0x${new BigNumber(x.gasPrice || 0, 10).toString(16)}`,
1519
- chain_id: chainId,
1520
- currency_amount: "",
1521
- nonce: x.nonce,
1522
- from_aa_address: "",
1523
- is_cancel: false,
1524
- selected_currency: ""
1525
- };
1526
- accumulator.push(formatPastTx({
1527
- transaction: etherscanTransaction,
1528
- lowerCaseSelectedAddress,
1529
- blockExplorerUrl
1530
- }));
1531
- return accumulator;
1532
- }, []);
1533
- return finalTxs;
1534
- };
1535
-
1536
- const DEFAULT_POLLING_INTERVAL = 20;
1537
- const DEFAULT_RETRY_TIMEOUT = 2;
1538
- const SEC = 1000;
1539
- class PollingBlockTracker extends BaseBlockTracker {
1540
- constructor({
1541
- config,
1542
- state = {}
1543
- }) {
1544
- if (!config.provider) {
1545
- throw new Error("PollingBlockTracker - no provider specified.");
1546
- }
1547
- super({
1548
- config,
1549
- state
1550
- });
1551
- const pollingInterval = config.pollingInterval || DEFAULT_POLLING_INTERVAL;
1552
- const retryTimeout = config.retryTimeout || DEFAULT_RETRY_TIMEOUT;
1553
-
1554
- // merge default + provided config.
1555
- this.defaultConfig = {
1556
- provider: config.provider,
1557
- pollingInterval: pollingInterval * SEC,
1558
- retryTimeout: retryTimeout * SEC,
1559
- setSkipCacheFlag: config.setSkipCacheFlag || false
1560
- };
1561
- this.initialize();
1562
- }
1563
- async checkForLatestBlock() {
1564
- await this._updateLatestBlock();
1565
- return this.getLatestBlock();
1566
- }
1567
-
1568
- // overrides the BaseBlockTracker._start method.
1569
- _start() {
1570
- this._synchronize().catch(err => this.emit("error", err));
1571
- }
1572
- async _synchronize() {
1573
- while (this.state._isRunning) {
1574
- if (idleTimeTracker.checkIfIdle()) return;
1575
- try {
1576
- await this._updateLatestBlock();
1577
- await timeout(this.config.pollingInterval);
1578
- } catch (err) {
1579
- const newErr = new Error(`PollingBlockTracker - encountered an error while attempting to update latest block:\n${err.stack}`);
1580
- try {
1581
- this.emit("error", newErr);
1582
- } catch (emitErr) {
1583
- log.error(newErr);
1584
- }
1585
- await timeout(this.config.retryTimeout);
1586
- }
1587
- }
1588
- }
1589
- async _updateLatestBlock() {
1590
- // fetch + set latest block
1591
- const latestBlock = await this._fetchLatestBlock();
1592
- this._newPotentialLatest(latestBlock);
1593
- }
1594
- async _fetchLatestBlock() {
1595
- try {
1596
- const block = await this.config.provider.request({
1597
- method: "eth_getBlockByNumber",
1598
- params: ["latest", false]
1599
- });
1600
- return {
1601
- blockHash: block.hash,
1602
- idempotencyKey: block.number,
1603
- timestamp: block.timestamp,
1604
- baseFeePerGas: block.baseFeePerGas,
1605
- gasLimit: block.gasLimit
1606
- };
1607
- } catch (error) {
1608
- log.error("Polling Block Tracker: ", error);
1609
- throw new Error(`PollingBlockTracker - encountered error fetching block:\n${error.message}`);
1610
- }
1611
- }
1612
- }
1613
-
1614
- class CurrencyController extends BaseCurrencyController {
1615
- constructor({
1616
- config,
1617
- state,
1618
- onNetworkChanged
1619
- }) {
1620
- super({
1621
- config,
1622
- state
1623
- });
1624
- _defineProperty(this, "conversionInterval", void 0);
1625
- this.defaultState = _objectSpread(_objectSpread({}, this.defaultState), {}, {
1626
- commonDenomination: "USD",
1627
- commonDenominatorPrice: 0
1628
- });
1629
- this.initialize();
1630
- onNetworkChanged(networkState => {
1631
- // to be called as (listener) => this.networkController.on('networkDidChange', listener);
1632
- if (networkState.providerConfig.ticker.toUpperCase() !== this.state.nativeCurrency.toUpperCase()) {
1633
- this.setNativeCurrency(networkState.providerConfig.ticker);
1634
- this.updateConversionRate();
1635
- }
1636
- });
1637
- }
1638
- setCommonDenomination(commonDenomination) {
1639
- this.update({
1640
- commonDenomination
1641
- });
1642
- }
1643
- getCommonDenomination() {
1644
- return this.state.commonDenomination;
1645
- }
1646
- setCommonDenominatorPrice(commonDenominatorPrice) {
1647
- this.update({
1648
- commonDenominatorPrice
1649
- });
1650
- }
1651
- getCommonDenominatorPrice() {
1652
- return this.state.commonDenominatorPrice;
1653
- }
1654
-
1655
- /**
1656
- * Creates a new poll, using setInterval, to periodically call updateConversionRate. The id of the interval is
1657
- * stored at the controller's conversionInterval property. If it is called and such an id already exists, the
1658
- * previous interval is clear and a new one is created.
1659
- */
1660
- scheduleConversionInterval() {
1661
- if (this.conversionInterval) {
1662
- window.clearInterval(this.conversionInterval);
1663
- }
1664
- this.conversionInterval = window.setInterval(() => {
1665
- if (!idleTimeTracker.checkIfIdle()) {
1666
- this.updateConversionRate();
1667
- }
1668
- }, this.config.pollInterval);
1669
- }
1670
-
1671
- /**
1672
- * Updates the conversionRate and conversionDate properties associated with the currentCurrency. Updated info is
1673
- * fetched from an external API
1674
- */
1675
- async updateConversionRate() {
1676
- const currentCurrency = this.getCurrentCurrency();
1677
- const nativeCurrency = this.getNativeCurrency();
1678
- const commonDenomination = this.getCommonDenomination();
1679
- const conversionRate = await this.retrieveConversionRate(nativeCurrency, currentCurrency, commonDenomination);
1680
- const currentCurrencyRate = Number.parseFloat(conversionRate[currentCurrency.toUpperCase()]);
1681
- const commonDenominationRate = Number.parseFloat(conversionRate[commonDenomination.toUpperCase()]);
1682
- // set conversion rate
1683
- if (currentCurrencyRate || commonDenominationRate) {
1684
- // ETC
1685
- this.setConversionRate(currentCurrencyRate);
1686
- this.setConversionDate(Math.floor(Date.now() / 1000).toString());
1687
- if (currentCurrency.toUpperCase() === commonDenomination.toUpperCase()) {
1688
- this.setCommonDenominatorPrice(currentCurrencyRate);
1689
- } else {
1690
- this.setCommonDenominatorPrice(commonDenominationRate);
1691
- }
1692
- } else {
1693
- this.setConversionRate(0);
1694
- this.setConversionDate("N/A");
1695
- }
1696
- }
1697
- async retrieveConversionRate(fromCurrency, toCurrency, commonDenomination) {
1698
- try {
1699
- let apiUrl = `${this.config.api}/currency?fsym=${fromCurrency.toUpperCase()}&tsyms=${toCurrency.toUpperCase()}`;
1700
- if (commonDenomination && commonDenomination.toUpperCase() !== toCurrency.toUpperCase()) {
1701
- apiUrl += `,${commonDenomination.toUpperCase()}`;
1702
- }
1703
- const parsedResponse = await get(apiUrl);
1704
- return parsedResponse;
1705
- } catch (error) {
1706
- log.error(error, `CurrencyController - updateCommonDenominatorPrice: Failed to query rate for currency: ${fromCurrency}/ ${toCurrency}`);
1707
- }
1708
- return {
1709
- [toCurrency.toUpperCase()]: "0",
1710
- [commonDenomination.toUpperCase()]: "0"
1711
- };
1712
- }
1713
- }
1714
-
1715
- const _excluded$1 = ["aBase", "bBase"],
1716
- _excluded2 = ["aBase", "bBase"],
1717
- _excluded3 = ["multiplicandBase", "multiplierBase"];
1718
-
1719
- // Big Number Constants
1720
- const BIG_NUMBER_WEI_MULTIPLIER = new BigNumber("1000000000000000000");
1721
- const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber("1000000000");
1722
- const BIG_NUMBER_ETH_MULTIPLIER = new BigNumber("1");
1723
- // Setter Maps
1724
- const toBigNumber = {
1725
- hex: n => new BigNumber(stripHexPrefix(n), 16),
1726
- dec: n => new BigNumber(String(n), 10),
1727
- BN: n => new BigNumber(n.toString(16), 16)
1728
- };
1729
- const toNormalizedDenomination = {
1730
- WEI: bigNumber => bigNumber.div(BIG_NUMBER_WEI_MULTIPLIER),
1731
- GWEI: bigNumber => bigNumber.div(BIG_NUMBER_GWEI_MULTIPLIER),
1732
- ETH: bigNumber => bigNumber.div(BIG_NUMBER_ETH_MULTIPLIER)
1733
- };
1734
- const toSpecifiedDenomination = {
1735
- WEI: bigNumber => bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).dp(0, BigNumber.ROUND_HALF_UP),
1736
- GWEI: bigNumber => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).dp(9, BigNumber.ROUND_HALF_UP),
1737
- ETH: bigNumber => bigNumber.times(BIG_NUMBER_ETH_MULTIPLIER).dp(9, BigNumber.ROUND_HALF_UP)
1738
- };
1739
- const baseChange = {
1740
- hex: n => n.toString(16),
1741
- dec: n => new BigNumber(n).toString(10),
1742
- BN: n => new BN(n.toString(16))
1743
- };
1744
-
1745
- // Utility function for checking base types
1746
- const isValidBase = base => Number.isInteger(base) && base > 1;
1747
-
1748
- /**
1749
- * Utility method to convert a value between denominations, formats and currencies.
1750
- */
1751
- const converter = ({
1752
- value,
1753
- fromNumericBase,
1754
- fromDenomination,
1755
- fromCurrency,
1756
- toNumericBase,
1757
- toDenomination,
1758
- toCurrency,
1759
- numberOfDecimals,
1760
- conversionRate,
1761
- invertConversionRate,
1762
- roundDown
1763
- }) => {
1764
- let convertedValue = fromNumericBase ? toBigNumber[fromNumericBase](value) : value;
1765
- if (fromDenomination) {
1766
- convertedValue = toNormalizedDenomination[fromDenomination](convertedValue);
1767
- }
1768
- if (fromCurrency !== toCurrency) {
1769
- if (conversionRate === null || conversionRate === undefined) {
1770
- throw new Error(`Converting from ${fromCurrency} to ${toCurrency} requires a conversionRate, but one was not provided`);
1771
- }
1772
- let rate = toBigNumber.dec(conversionRate);
1773
- if (invertConversionRate) {
1774
- rate = new BigNumber(1).div(conversionRate);
1775
- }
1776
- convertedValue = convertedValue.times(rate);
1777
- }
1778
- if (toDenomination) {
1779
- convertedValue = toSpecifiedDenomination[toDenomination](convertedValue);
1780
- }
1781
- if (numberOfDecimals) {
1782
- convertedValue = convertedValue.dp(numberOfDecimals, BigNumber.ROUND_HALF_DOWN);
1783
- }
1784
- if (roundDown) {
1785
- convertedValue = convertedValue.dp(roundDown, BigNumber.ROUND_DOWN);
1786
- }
1787
- if (toNumericBase) {
1788
- convertedValue = baseChange[toNumericBase](convertedValue);
1789
- }
1790
- return convertedValue;
1791
- };
1792
- const conversionUtil = (value, {
1793
- fromCurrency = null,
1794
- toCurrency = fromCurrency,
1795
- fromNumericBase,
1796
- toNumericBase,
1797
- fromDenomination,
1798
- toDenomination,
1799
- numberOfDecimals,
1800
- conversionRate,
1801
- invertConversionRate
1802
- }) => {
1803
- if (fromCurrency !== toCurrency && !conversionRate) {
1804
- return 0;
1805
- }
1806
- return converter({
1807
- fromCurrency,
1808
- toCurrency,
1809
- fromNumericBase,
1810
- toNumericBase,
1811
- fromDenomination,
1812
- toDenomination,
1813
- numberOfDecimals,
1814
- conversionRate,
1815
- invertConversionRate,
1816
- value
1817
- });
1818
- };
1819
- const getBigNumber = (value, base) => {
1820
- if (!isValidBase(base)) {
1821
- throw new Error("Must specificy valid base");
1822
- }
1823
-
1824
- // We don't include 'number' here, because BigNumber will throw if passed
1825
- // a number primitive it considers unsafe.
1826
- if (typeof value === "string" || value instanceof BigNumber) {
1827
- return new BigNumber(value, base);
1828
- }
1829
- return new BigNumber(String(value), base);
1830
- };
1831
- const addCurrencies = (a, b, options = {}) => {
1602
+ return new BigNumber(String(value), base);
1603
+ };
1604
+ const addCurrencies = (a, b, options = {}) => {
1832
1605
  const {
1833
1606
  aBase,
1834
1607
  bBase
@@ -2171,7 +1944,7 @@ class GasFeeController extends BaseController {
2171
1944
  const chainId = this.getNetworkIdentifier();
2172
1945
  if (chainId === "loading") return;
2173
1946
  let chainIdInt;
2174
- if (typeof chainId === "string" && isHexString(addHexPrefix(chainId))) {
1947
+ if (typeof chainId === "string" && isHexString$1(addHexPrefix(chainId))) {
2175
1948
  chainIdInt = Number.parseInt(chainId, 16);
2176
1949
  }
2177
1950
  try {
@@ -2328,7 +2101,7 @@ class KeyringController extends BaseKeyringController {
2328
2101
  // we need to check if the data is hex or not
2329
2102
  // For historical reasons, you must submit the message to sign in hex-encoded UTF-8.
2330
2103
  // https://docs.metamask.io/wallet/how-to/sign-data/#use-personal_sign
2331
- const message = isHexString(data) ? Buffer.from(stripHexPrefix(data), "hex") : Buffer.from(data);
2104
+ const message = isHexString$1(data) ? Buffer.from(stripHexPrefix(data), "hex") : Buffer.from(data);
2332
2105
  const signature = privKey.sign(hashMessage(message)).serialized;
2333
2106
  return signature;
2334
2107
  }
@@ -2349,105 +2122,6 @@ class KeyringController extends BaseKeyringController {
2349
2122
  }
2350
2123
  }
2351
2124
 
2352
- class AbstractMessageController extends BaseController {
2353
- /**
2354
- * Controller in charge of managing - storing, adding, removing, updating - Messages.
2355
- *
2356
- */
2357
- constructor({
2358
- config,
2359
- state,
2360
- getNetworkIdentifier
2361
- }) {
2362
- super({
2363
- config,
2364
- state
2365
- });
2366
- _defineProperty(this, "messages", void 0);
2367
- _defineProperty(this, "getNetworkIdentifier", void 0);
2368
- this.defaultState = {
2369
- unapprovedMessages: {},
2370
- unapprovedMessagesCount: 0
2371
- };
2372
- this.messages = [];
2373
- this.defaultConfig = {};
2374
- this.getNetworkIdentifier = getNetworkIdentifier;
2375
- super.initialize();
2376
- }
2377
- getMessage(messageId) {
2378
- return this.messages.find(message => message.id === messageId);
2379
- }
2380
- getAllMessages() {
2381
- return this.messages;
2382
- }
2383
- setMetadata(messageId, metadata) {
2384
- const message = this.getMessage(messageId);
2385
- if (!message) {
2386
- throw new Error(`${this.name}: Message not found for id: ${messageId}.`);
2387
- }
2388
- message.metadata = metadata;
2389
- this.updateMessage(message);
2390
- }
2391
- getUnapprovedMessages() {
2392
- return this.messages.filter(message => message.status === MessageStatus.UNAPPROVED).reduce((result, message) => {
2393
- result[message.id] = message;
2394
- return result;
2395
- }, {});
2396
- }
2397
- async addMessage(message) {
2398
- this.messages.push(message);
2399
- this.saveMessageList();
2400
- }
2401
- approveMessage(messageId, messageParams) {
2402
- this.setMessageStatus(messageId, MessageStatus.APPROVED);
2403
- return this.prepMessageForSigning(messageParams);
2404
- }
2405
- setMessageStatus(messageId, status) {
2406
- const message = this.getMessage(messageId);
2407
- if (!message) {
2408
- throw new Error(`${this.name}: Message not found for id: ${messageId}.`);
2409
- }
2410
- message.status = status;
2411
- this.updateMessage(message);
2412
- this.emit(`${messageId}:${status}`, message);
2413
- if (status === MessageStatus.REJECTED || status === MessageStatus.SIGNED || status === MessageStatus.FAILED) {
2414
- this.emit(`${messageId}:finished`, message);
2415
- }
2416
- }
2417
- async waitForFinishStatus(msgParams, messageName) {
2418
- return new Promise((resolve, reject) => {
2419
- const handleFinished = msg => {
2420
- if (msg.status === MessageStatus.REJECTED) {
2421
- return reject(providerErrors.userRejectedRequest(`${messageName} Signature: User denied message signature`));
2422
- }
2423
- if (msg.status === MessageStatus.FAILED) {
2424
- return reject(rpcErrors.internal(`${messageName} Signature: failed to sign message ${msg.error}`));
2425
- }
2426
- if (msg.status === MessageStatus.SIGNED) {
2427
- return resolve(msg.rawSig);
2428
- }
2429
- return reject(rpcErrors.internal(`${messageName} Signature: Unknown problem: ${JSON.stringify(msgParams)}`));
2430
- };
2431
- this.once(`${msgParams.id}:finished`, handleFinished);
2432
- });
2433
- }
2434
- updateMessage(message) {
2435
- const index = this.messages.findIndex(msg => message.id === msg.id);
2436
- if (index !== -1) {
2437
- this.messages[index] = message;
2438
- }
2439
- this.saveMessageList();
2440
- }
2441
- saveMessageList() {
2442
- const unapprovedMessages = this.getUnapprovedMessages();
2443
- const unapprovedMessagesCount = Object.keys(unapprovedMessages).length;
2444
- this.update({
2445
- unapprovedMessages,
2446
- unapprovedMessagesCount
2447
- });
2448
- }
2449
- }
2450
-
2451
2125
  const hexRe = /^[0-9A-Fa-f]+$/gu;
2452
2126
  function validateAddress(address, propertyName) {
2453
2127
  if (!address || typeof address !== "string" || !isValidAddress(address)) {
@@ -2516,7 +2190,7 @@ async function validateAddChainData(data) {
2516
2190
  if (!chainId) {
2517
2191
  throw new Error("Invalid add chain params: please pass chainId in params");
2518
2192
  }
2519
- if (!isHexString$1(chainId)) {
2193
+ if (!isHexString(chainId)) {
2520
2194
  throw new Error("Invalid add chain params: please pass a valid hex chainId in params, for: ex: 0x1");
2521
2195
  }
2522
2196
  if (!rpcUrls || rpcUrls.length === 0) throw new Error("params.rpcUrls not provided");
@@ -2544,7 +2218,7 @@ function validateSwitchChainData(data) {
2544
2218
  if (!chainId) {
2545
2219
  throw new Error("Invalid switch chain params: please pass chainId in params");
2546
2220
  }
2547
- if (!isHexString$1(chainId)) {
2221
+ if (!isHexString(chainId)) {
2548
2222
  throw new Error("Invalid switch chain params: please pass a valid hex chainId in params, for: ex: 0x1");
2549
2223
  }
2550
2224
  }
@@ -2553,13 +2227,11 @@ class AddChainController extends AbstractMessageController {
2553
2227
  constructor({
2554
2228
  config,
2555
2229
  state,
2556
- getNetworkIdentifier,
2557
2230
  addChain
2558
2231
  }) {
2559
2232
  super({
2560
2233
  config,
2561
- state,
2562
- getNetworkIdentifier
2234
+ state
2563
2235
  });
2564
2236
  _defineProperty(this, "name", "AddChainController");
2565
2237
  _defineProperty(this, "addChain", void 0);
@@ -2620,13 +2292,11 @@ class MessageController extends AbstractMessageController {
2620
2292
  constructor({
2621
2293
  config,
2622
2294
  state,
2623
- signMessage,
2624
- getNetworkIdentifier
2295
+ signMessage
2625
2296
  }) {
2626
2297
  super({
2627
2298
  config,
2628
- state,
2629
- getNetworkIdentifier
2299
+ state
2630
2300
  });
2631
2301
  _defineProperty(this, "name", "MessageController");
2632
2302
  _defineProperty(this, "signMessage", void 0);
@@ -2686,13 +2356,11 @@ class PersonalMessageController extends AbstractMessageController {
2686
2356
  constructor({
2687
2357
  config,
2688
2358
  state,
2689
- signPersonalMessage,
2690
- getNetworkIdentifier
2359
+ signPersonalMessage
2691
2360
  }) {
2692
2361
  super({
2693
2362
  config,
2694
- state,
2695
- getNetworkIdentifier
2363
+ state
2696
2364
  });
2697
2365
  _defineProperty(this, "name", "PersonalMessageController");
2698
2366
  _defineProperty(this, "signPersonalMessage", void 0);
@@ -2752,13 +2420,11 @@ class SwitchChainController extends AbstractMessageController {
2752
2420
  constructor({
2753
2421
  config,
2754
2422
  state,
2755
- getNetworkIdentifier,
2756
2423
  switchChain
2757
2424
  }) {
2758
2425
  super({
2759
2426
  config,
2760
- state,
2761
- getNetworkIdentifier
2427
+ state
2762
2428
  });
2763
2429
  _defineProperty(this, "name", "SwitchChainController");
2764
2430
  _defineProperty(this, "switchChain", void 0);
@@ -2824,12 +2490,13 @@ class TypedMessageController extends AbstractMessageController {
2824
2490
  }) {
2825
2491
  super({
2826
2492
  config,
2827
- state,
2828
- getNetworkIdentifier
2493
+ state
2829
2494
  });
2830
2495
  _defineProperty(this, "name", "TypedMessageController");
2831
2496
  _defineProperty(this, "signTypedData", void 0);
2497
+ _defineProperty(this, "getNetworkIdentifier", void 0);
2832
2498
  this.signTypedData = signTypedData;
2499
+ this.getNetworkIdentifier = getNetworkIdentifier;
2833
2500
  this.initialize();
2834
2501
  }
2835
2502
  async processSignTypedMessage(messageId) {
@@ -3364,154 +3031,665 @@ class NetworkController extends BaseController {
3364
3031
  return this.state.providerConfig.rpcTarget;
3365
3032
  }
3366
3033
 
3367
- /**
3368
- * Called by orchestrator once while initializing the class
3369
- * @param providerHandlers - JRPC handlers for provider
3370
- * @returns - provider - Returns the providerProxy
3371
- */
3372
- initializeProvider(providerHandlers) {
3373
- this.baseProviderHandlers = providerHandlers;
3374
- this.configureProvider();
3375
- this.lookupNetwork(); // Not awaiting this, because we don't want to block the initialization
3376
- return this.providerProxy;
3034
+ /**
3035
+ * Called by orchestrator once while initializing the class
3036
+ * @param providerHandlers - JRPC handlers for provider
3037
+ * @returns - provider - Returns the providerProxy
3038
+ */
3039
+ initializeProvider(providerHandlers) {
3040
+ this.baseProviderHandlers = providerHandlers;
3041
+ this.configureProvider();
3042
+ this.lookupNetwork(); // Not awaiting this, because we don't want to block the initialization
3043
+ return this.providerProxy;
3044
+ }
3045
+ getProvider() {
3046
+ return this.providerProxy;
3047
+ }
3048
+ getBlockTracker() {
3049
+ return this.blockTrackerProxy;
3050
+ }
3051
+ getProviderConfig() {
3052
+ return this.state.providerConfig;
3053
+ }
3054
+ setProviderConfig(config) {
3055
+ this.update({
3056
+ providerConfig: _objectSpread({}, config)
3057
+ });
3058
+ this.refreshNetwork();
3059
+ }
3060
+ async getEIP1559Compatibility() {
3061
+ const {
3062
+ EIPS_1559
3063
+ } = this.state.properties;
3064
+ // log.info('checking eip 1559 compatibility')
3065
+ if (EIPS_1559 !== undefined) {
3066
+ return EIPS_1559;
3067
+ }
3068
+ const latestBlock = await this.blockTracker.getLatestBlock();
3069
+ const supportsEIP1559 = latestBlock && latestBlock.baseFeePerGas !== undefined;
3070
+ this.update({
3071
+ properties: {
3072
+ EIPS_1559: supportsEIP1559
3073
+ }
3074
+ });
3075
+ return supportsEIP1559;
3076
+ }
3077
+
3078
+ /**
3079
+ * Refreshes the current network code
3080
+ */
3081
+ async lookupNetwork() {
3082
+ const {
3083
+ chainId,
3084
+ rpcTarget
3085
+ } = this.getProviderConfig();
3086
+ if (!chainId || !rpcTarget || !this.provider) {
3087
+ this.update({
3088
+ chainId: "loading",
3089
+ properties: {}
3090
+ });
3091
+ return;
3092
+ }
3093
+ const releaseLock = await this.mutex.acquire();
3094
+ try {
3095
+ // use eth_chainId
3096
+ const [networkChainId] = await Promise.all([this.provider.request({
3097
+ method: "eth_chainId"
3098
+ }), this.getEIP1559Compatibility()]);
3099
+ log.info("network fetched chain id", networkChainId);
3100
+ // update chain ID
3101
+ this.update({
3102
+ chainId: networkChainId
3103
+ });
3104
+ this.emit("networkDidChange");
3105
+ } catch {
3106
+ this.update({
3107
+ chainId: "loading"
3108
+ });
3109
+ } finally {
3110
+ releaseLock();
3111
+ }
3112
+ }
3113
+ configureProvider() {
3114
+ const _this$getProviderConf = this.getProviderConfig(),
3115
+ {
3116
+ chainId,
3117
+ rpcTarget
3118
+ } = _this$getProviderConf,
3119
+ rest = _objectWithoutProperties(_this$getProviderConf, _excluded);
3120
+ if (!chainId || !rpcTarget) {
3121
+ throw new Error("chainId and rpcTarget must be provider in providerConfig");
3122
+ }
3123
+ this.configureStandardProvider(_objectSpread({
3124
+ chainId,
3125
+ rpcTarget
3126
+ }, rest));
3127
+ }
3128
+ setNetworkClient({
3129
+ networkMiddleware,
3130
+ blockTracker
3131
+ }) {
3132
+ const ethereumMiddleware = createEthereumMiddleware(this.baseProviderHandlers);
3133
+ const engine = new JRPCEngine();
3134
+ engine.push(ethereumMiddleware);
3135
+ engine.push(networkMiddleware);
3136
+ const provider = providerFromEngine(engine);
3137
+ this.setProvider({
3138
+ provider,
3139
+ blockTracker
3140
+ });
3141
+ }
3142
+ setProvider({
3143
+ provider,
3144
+ blockTracker
3145
+ }) {
3146
+ if (this.providerProxy) {
3147
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3148
+ // @ts-ignore
3149
+ this.providerProxy.setTarget(provider);
3150
+ } else {
3151
+ this.providerProxy = createSwappableProxy(provider);
3152
+ }
3153
+ if (this.blockTrackerProxy) {
3154
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3155
+ // @ts-ignore
3156
+ this.blockTrackerProxy.setTarget(blockTracker);
3157
+ } else {
3158
+ this.blockTrackerProxy = createEventEmitterProxy(blockTracker, {
3159
+ eventFilter: "skipInternal"
3160
+ });
3161
+ }
3162
+
3163
+ // set new provider and blockTracker
3164
+ this.provider = provider;
3165
+ provider.setMaxListeners(10);
3166
+ this.blockTracker = blockTracker;
3167
+ }
3168
+ configureStandardProvider(providerConfig) {
3169
+ const networkClient = createJsonRpcClient(providerConfig, this.config);
3170
+ log.info("networkClient", networkClient);
3171
+ this.setNetworkClient(networkClient);
3172
+ }
3173
+ refreshNetwork() {
3174
+ this.update({
3175
+ chainId: "loading",
3176
+ properties: {}
3177
+ });
3178
+ this.configureProvider();
3179
+ this.lookupNetwork();
3180
+ }
3181
+ }
3182
+
3183
+ const erc20Interface = new Interface(erc20Abi);
3184
+ const erc721Interface = new Interface(erc721Abi);
3185
+ const erc1155Interface = new Interface(erc1155Abi);
3186
+
3187
+ // functions that handle normalizing of that key in txParams
3188
+
3189
+ const normalizers = {
3190
+ from: (from, LowerCase = true) => LowerCase ? addHexPrefix(from).toLowerCase() : addHexPrefix(from),
3191
+ to: (to, LowerCase = true) => LowerCase ? addHexPrefix(to).toLowerCase() : addHexPrefix(to),
3192
+ nonce: nonce => addHexPrefix(nonce),
3193
+ customNonceValue: nonce => addHexPrefix(nonce),
3194
+ value: value => addHexPrefix(value),
3195
+ data: data => addHexPrefix(data),
3196
+ gas: gas => addHexPrefix(gas),
3197
+ gasPrice: gasPrice => addHexPrefix(gasPrice),
3198
+ type: addHexPrefix,
3199
+ maxFeePerGas: addHexPrefix,
3200
+ maxPriorityFeePerGas: addHexPrefix
3201
+ };
3202
+
3203
+ /**
3204
+ * normalizes txParams
3205
+ */
3206
+ function normalizeTxParameters(txParameters, lowerCase = true) {
3207
+ // apply only keys in the normalizers
3208
+ const normalizedTxParameters = {
3209
+ id: txParameters.id || randomId(),
3210
+ from: txParameters.from
3211
+ };
3212
+ for (const key in normalizers) {
3213
+ const currentKey = key;
3214
+ if (txParameters[currentKey])
3215
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3216
+ normalizedTxParameters[currentKey] = normalizers[currentKey](txParameters[currentKey], lowerCase);
3217
+ }
3218
+ return normalizedTxParameters;
3219
+ }
3220
+ function transactionMatchesNetwork(transaction, chainId) {
3221
+ if (typeof transaction.chainId !== "undefined") {
3222
+ return transaction.chainId === chainId;
3223
+ }
3224
+ return false;
3225
+ }
3226
+
3227
+ /**
3228
+ * Determines if the maxFeePerGas and maxPriorityFeePerGas fields are supplied
3229
+ * and valid inputs. This will return false for non hex string inputs.
3230
+ * the transaction to check
3231
+ * @returns true if transaction uses valid EIP1559 fields
3232
+ */
3233
+ function isEIP1559Transaction(transaction) {
3234
+ var _transaction$transact, _transaction$transact2;
3235
+ return isHexString$1(addHexPrefix(transaction === null || transaction === void 0 || (_transaction$transact = transaction.transaction) === null || _transaction$transact === void 0 ? void 0 : _transaction$transact.maxFeePerGas)) && isHexString$1(addHexPrefix(transaction === null || transaction === void 0 || (_transaction$transact2 = transaction.transaction) === null || _transaction$transact2 === void 0 ? void 0 : _transaction$transact2.maxPriorityFeePerGas));
3236
+ }
3237
+
3238
+ /**
3239
+ * Determine if the maxFeePerGas and maxPriorityFeePerGas fields are not
3240
+ * supplied and that the gasPrice field is valid if it is provided. This will
3241
+ * return false if gasPrice is a non hex string.
3242
+ * transaction -
3243
+ * the transaction to check
3244
+ * @returns true if transaction uses valid Legacy fields OR lacks
3245
+ * EIP1559 fields
3246
+ */
3247
+ function isLegacyTransaction(transaction) {
3248
+ return typeof transaction.transaction.maxFeePerGas === "undefined" && typeof transaction.transaction.maxPriorityFeePerGas === "undefined" && (typeof transaction.transaction.gasPrice === "undefined" || isHexString$1(addHexPrefix(transaction.transaction.gasPrice)));
3249
+ }
3250
+
3251
+ /**
3252
+ * Given two fields, ensure that the second field is not included in txParams,
3253
+ * and if it is throw an invalidParams error.
3254
+ */
3255
+ function ensureMutuallyExclusiveFieldsNotProvided(txParams, fieldBeingValidated, mutuallyExclusiveField) {
3256
+ if (typeof txParams[mutuallyExclusiveField] !== "undefined") {
3257
+ throw rpcErrors.invalidParams(`Invalid transaction params: specified ${fieldBeingValidated} but also included ${mutuallyExclusiveField}, these cannot be mixed`);
3258
+ }
3259
+ }
3260
+
3261
+ /**
3262
+ * Ensures that the provided value for field is a string, throws an
3263
+ * invalidParams error if field is not a string.
3264
+ */
3265
+ function ensureFieldIsString(txParams, field) {
3266
+ if (typeof txParams[field] !== "string") {
3267
+ throw rpcErrors.invalidParams(`Invalid transaction params: ${field} is not a string. got: (${txParams[field]})`);
3268
+ }
3269
+ }
3270
+
3271
+ /**
3272
+ * Ensures that the provided txParams has the proper 'type' specified for the
3273
+ * given field, if it is provided. If types do not match throws an
3274
+ * invalidParams error.
3275
+ */
3276
+ function ensureProperTransactionEnvelopeTypeProvided(txParams, field) {
3277
+ switch (field) {
3278
+ case "maxFeePerGas":
3279
+ case "maxPriorityFeePerGas":
3280
+ if (txParams.type && txParams.type !== TRANSACTION_ENVELOPE_TYPES.FEE_MARKET) {
3281
+ throw rpcErrors.invalidParams(`Invalid transaction envelope type: specified type "${txParams.type}" but ` + `including maxFeePerGas and maxPriorityFeePerGas requires type: "${TRANSACTION_ENVELOPE_TYPES.FEE_MARKET}"`);
3282
+ }
3283
+ break;
3284
+ case "gasPrice":
3285
+ default:
3286
+ if (txParams.type && txParams.type === TRANSACTION_ENVELOPE_TYPES.FEE_MARKET) {
3287
+ throw rpcErrors.invalidParams(`Invalid transaction envelope type: specified type "${txParams.type}" but ` + "included a gasPrice instead of maxFeePerGas and maxPriorityFeePerGas");
3288
+ }
3289
+ }
3290
+ }
3291
+
3292
+ /**
3293
+ * validates the from field in txParams
3294
+ */
3295
+ function validateFrom(txParams) {
3296
+ if (!(typeof txParams.from === "string")) {
3297
+ throw rpcErrors.invalidParams(`Invalid "from" address "${txParams.from}": not a string.`);
3377
3298
  }
3378
- getProvider() {
3379
- return this.providerProxy;
3299
+ if (!isValidAddress(txParams.from)) {
3300
+ throw rpcErrors.invalidParams('Invalid "from" address.');
3380
3301
  }
3381
- getBlockTracker() {
3382
- return this.blockTrackerProxy;
3302
+ }
3303
+
3304
+ /**
3305
+ * validates the to field in txParams
3306
+ */
3307
+ function validateRecipient(txParameters) {
3308
+ if (txParameters.to === "0x" || txParameters.to === null) {
3309
+ if (txParameters.data) {
3310
+ delete txParameters.to;
3311
+ } else {
3312
+ throw rpcErrors.invalidParams('Invalid "to" address.');
3313
+ }
3314
+ } else if (txParameters.to !== undefined && !isValidAddress(txParameters.to)) {
3315
+ throw rpcErrors.invalidParams('Invalid "to" address.');
3383
3316
  }
3384
- getProviderConfig() {
3385
- return this.state.providerConfig;
3317
+ return txParameters;
3318
+ }
3319
+
3320
+ /**
3321
+ * Validates the given tx parameters
3322
+ * @throws if the tx params contains invalid fields
3323
+ */
3324
+ function validateTxParameters(txParams, eip1559Compatibility = true) {
3325
+ if (!txParams || typeof txParams !== "object" || Array.isArray(txParams)) {
3326
+ throw rpcErrors.invalidParams("Invalid transaction params: must be an object.");
3386
3327
  }
3387
- setProviderConfig(config) {
3388
- this.update({
3389
- providerConfig: _objectSpread({}, config)
3390
- });
3391
- this.refreshNetwork();
3328
+ if (!txParams.to && !txParams.data) {
3329
+ throw rpcErrors.invalidParams('Invalid transaction params: must specify "data" for contract deployments, or "to" (and optionally "data") for all other types of transactions.');
3392
3330
  }
3393
- async getEIP1559Compatibility() {
3394
- const {
3395
- EIPS_1559
3396
- } = this.state.properties;
3397
- // log.info('checking eip 1559 compatibility')
3398
- if (EIPS_1559 !== undefined) {
3399
- return EIPS_1559;
3331
+ if (isEIP1559Transaction({
3332
+ transaction: txParams
3333
+ }) && !eip1559Compatibility) {
3334
+ throw rpcErrors.invalidParams("Invalid transaction params: params specify an EIP-1559 transaction but the current network does not support EIP-1559");
3335
+ }
3336
+ Object.entries(txParams).forEach(([key, value]) => {
3337
+ // validate types
3338
+ switch (key) {
3339
+ case "from":
3340
+ validateFrom(txParams);
3341
+ break;
3342
+ case "to":
3343
+ validateRecipient(txParams);
3344
+ break;
3345
+ case "gasPrice":
3346
+ ensureProperTransactionEnvelopeTypeProvided(txParams, "gasPrice");
3347
+ ensureMutuallyExclusiveFieldsNotProvided(txParams, "gasPrice", "maxFeePerGas");
3348
+ ensureMutuallyExclusiveFieldsNotProvided(txParams, "gasPrice", "maxPriorityFeePerGas");
3349
+ ensureFieldIsString(txParams, "gasPrice");
3350
+ break;
3351
+ case "maxFeePerGas":
3352
+ ensureProperTransactionEnvelopeTypeProvided(txParams, "maxFeePerGas");
3353
+ ensureMutuallyExclusiveFieldsNotProvided(txParams, "maxFeePerGas", "gasPrice");
3354
+ ensureFieldIsString(txParams, "maxFeePerGas");
3355
+ break;
3356
+ case "maxPriorityFeePerGas":
3357
+ ensureProperTransactionEnvelopeTypeProvided(txParams, "maxPriorityFeePerGas");
3358
+ ensureMutuallyExclusiveFieldsNotProvided(txParams, "maxPriorityFeePerGas", "gasPrice");
3359
+ ensureFieldIsString(txParams, "maxPriorityFeePerGas");
3360
+ break;
3361
+ case "value":
3362
+ ensureFieldIsString(txParams, "value");
3363
+ if (value.toString().includes("-")) {
3364
+ throw rpcErrors.invalidParams(`Invalid transaction value "${value}": not a positive number.`);
3365
+ }
3366
+ if (value.toString().includes(".")) {
3367
+ throw rpcErrors.invalidParams(`Invalid transaction value of "${value}": number must be in wei.`);
3368
+ }
3369
+ break;
3370
+ case "chainId":
3371
+ if (typeof value !== "number" && typeof value !== "string") {
3372
+ throw rpcErrors.invalidParams(`Invalid transaction params: ${key} is not a Number or hex string. got: (${value})`);
3373
+ }
3374
+ break;
3375
+ default:
3376
+ ensureFieldIsString(txParams, key);
3400
3377
  }
3401
- const latestBlock = await this.blockTracker.getLatestBlock();
3402
- const supportsEIP1559 = latestBlock && latestBlock.baseFeePerGas !== undefined;
3403
- this.update({
3404
- properties: {
3405
- EIPS_1559: supportsEIP1559
3406
- }
3378
+ });
3379
+ }
3380
+ function normalizeAndValidateTxParams(txParams, lowerCase = true) {
3381
+ const normalizedTxParams = normalizeTxParameters(txParams, lowerCase);
3382
+ validateTxParameters(normalizedTxParams);
3383
+ return normalizedTxParams;
3384
+ }
3385
+
3386
+ /**
3387
+ * @returns an array of states that can be considered final
3388
+ */
3389
+ function getFinalStates() {
3390
+ return [TransactionStatus.rejected,
3391
+ // the user has responded no!
3392
+ TransactionStatus.confirmed,
3393
+ // the tx has been included in a block.
3394
+ TransactionStatus.failed,
3395
+ // the tx failed for some reason, included on tx data.
3396
+ TransactionStatus.dropped // the tx nonce was already used
3397
+ ];
3398
+ }
3399
+ function parseStandardTokenTransactionData(data) {
3400
+ try {
3401
+ const txDesc = erc20Interface.parseTransaction({
3402
+ data
3407
3403
  });
3408
- return supportsEIP1559;
3404
+ if (txDesc) return {
3405
+ name: txDesc.name,
3406
+ methodParams: txDesc.args.toArray(),
3407
+ type: CONTRACT_TYPE_ERC20
3408
+ };
3409
+ } catch {
3410
+ // ignore and next try to parse with erc721 ABI
3409
3411
  }
3410
-
3411
- /**
3412
- * Refreshes the current network code
3413
- */
3414
- async lookupNetwork() {
3415
- const {
3416
- chainId,
3417
- rpcTarget
3418
- } = this.getProviderConfig();
3419
- if (!chainId || !rpcTarget || !this.provider) {
3420
- this.update({
3421
- chainId: "loading",
3422
- properties: {}
3423
- });
3424
- return;
3425
- }
3426
- const releaseLock = await this.mutex.acquire();
3427
- try {
3428
- // use eth_chainId
3429
- const [networkChainId] = await Promise.all([this.provider.request({
3430
- method: "eth_chainId"
3431
- }), this.getEIP1559Compatibility()]);
3432
- log.info("network fetched chain id", networkChainId);
3433
- // update chain ID
3434
- this.update({
3435
- chainId: networkChainId
3436
- });
3437
- this.emit("networkDidChange");
3438
- } catch {
3439
- this.update({
3440
- chainId: "loading"
3441
- });
3442
- } finally {
3443
- releaseLock();
3444
- }
3412
+ try {
3413
+ const txDesc = erc721Interface.parseTransaction({
3414
+ data
3415
+ });
3416
+ if (txDesc) return {
3417
+ name: txDesc.name,
3418
+ methodParams: txDesc.args.toArray(),
3419
+ type: CONTRACT_TYPE_ERC721
3420
+ };
3421
+ } catch {
3422
+ // ignore and next try to parse with erc1155 ABI
3445
3423
  }
3446
- configureProvider() {
3447
- const _this$getProviderConf = this.getProviderConfig(),
3448
- {
3449
- chainId,
3450
- rpcTarget
3451
- } = _this$getProviderConf,
3452
- rest = _objectWithoutProperties(_this$getProviderConf, _excluded);
3453
- if (!chainId || !rpcTarget) {
3454
- throw new Error("chainId and rpcTarget must be provider in providerConfig");
3455
- }
3456
- this.configureStandardProvider(_objectSpread({
3457
- chainId,
3458
- rpcTarget
3459
- }, rest));
3424
+ try {
3425
+ const txDesc = erc1155Interface.parseTransaction({
3426
+ data
3427
+ });
3428
+ if (txDesc) return {
3429
+ name: txDesc.name,
3430
+ methodParams: txDesc.args.toArray(),
3431
+ type: CONTRACT_TYPE_ERC1155
3432
+ };
3433
+ } catch {
3434
+ // ignore and return undefined
3460
3435
  }
3461
- setNetworkClient({
3462
- networkMiddleware,
3463
- blockTracker
3464
- }) {
3465
- const ethereumMiddleware = createEthereumMiddleware(this.baseProviderHandlers);
3466
- const engine = new JRPCEngine();
3467
- engine.push(ethereumMiddleware);
3468
- engine.push(networkMiddleware);
3469
- const provider = providerFromEngine(engine);
3470
- this.setProvider({
3471
- provider,
3472
- blockTracker
3436
+ return undefined;
3437
+ }
3438
+ const readAddressAsContract = async (provider, address) => {
3439
+ let contractCode;
3440
+ try {
3441
+ contractCode = await provider.request({
3442
+ method: METHOD_TYPES.ETH_GET_CODE,
3443
+ params: [address, "latest"]
3473
3444
  });
3445
+ } catch (e) {
3446
+ contractCode = null;
3447
+ }
3448
+ const isContractAddress = contractCode ? contractCode !== "0x" && contractCode !== "0x0" : false;
3449
+ return {
3450
+ contractCode,
3451
+ isContractAddress
3452
+ };
3453
+ };
3454
+ async function determineTransactionType(txParams, provider) {
3455
+ const {
3456
+ data,
3457
+ to
3458
+ } = txParams;
3459
+ let name = "";
3460
+ let methodParams = [];
3461
+ let type = "";
3462
+ try {
3463
+ ({
3464
+ name,
3465
+ methodParams,
3466
+ type
3467
+ } = data && parseStandardTokenTransactionData(data) || {});
3468
+ } catch (error) {
3469
+ log.debug("Failed to parse transaction data", error);
3474
3470
  }
3475
- setProvider({
3476
- provider,
3477
- blockTracker
3478
- }) {
3479
- if (this.providerProxy) {
3480
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3481
- // @ts-ignore
3482
- this.providerProxy.setTarget(provider);
3483
- } else {
3484
- this.providerProxy = createSwappableProxy(provider);
3485
- }
3486
- if (this.blockTrackerProxy) {
3487
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3488
- // @ts-ignore
3489
- this.blockTrackerProxy.setTarget(blockTracker);
3490
- } else {
3491
- this.blockTrackerProxy = createEventEmitterProxy(blockTracker, {
3492
- eventFilter: "skipInternal"
3471
+ let result;
3472
+ let contractCode = "";
3473
+ if (data && !to) {
3474
+ result = TRANSACTION_TYPES.DEPLOY_CONTRACT;
3475
+ } else {
3476
+ const {
3477
+ contractCode: resultCode,
3478
+ isContractAddress
3479
+ } = await readAddressAsContract(provider, to);
3480
+ contractCode = resultCode;
3481
+ if (isContractAddress) {
3482
+ const valueExists = txParams.value && Number(txParams.value) !== 0;
3483
+ const tokenMethodName = [TRANSACTION_TYPES.TOKEN_METHOD_APPROVE, TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER, TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM, TRANSACTION_TYPES.COLLECTIBLE_METHOD_SAFE_TRANSFER_FROM, TRANSACTION_TYPES.SET_APPROVAL_FOR_ALL].find(x => {
3484
+ var _name;
3485
+ return x.toLowerCase() === ((_name = name) === null || _name === void 0 ? void 0 : _name.toLowerCase());
3493
3486
  });
3487
+ result = data && tokenMethodName && !valueExists ? tokenMethodName : TRANSACTION_TYPES.CONTRACT_INTERACTION;
3488
+ } else {
3489
+ result = TRANSACTION_TYPES.SENT_ETHER;
3494
3490
  }
3491
+ }
3492
+ return {
3493
+ type: type || CONTRACT_TYPE_ETH,
3494
+ category: result,
3495
+ methodParams,
3496
+ getCodeResponse: contractCode
3497
+ };
3498
+ }
3495
3499
 
3496
- // set new provider and blockTracker
3497
- this.provider = provider;
3498
- provider.setMaxListeners(10);
3499
- this.blockTracker = blockTracker;
3500
+ function hexToBn(hex) {
3501
+ return new BigNumber(stripHexPrefix(hex), 16);
3502
+ }
3503
+ function BNToHex(bn) {
3504
+ return addHexPrefix(bn.toString(16));
3505
+ }
3506
+ function getEtherScanHashLink(txHash, chainId) {
3507
+ if (!SUPPORTED_NETWORKS[chainId]) return "";
3508
+ return `${SUPPORTED_NETWORKS[chainId].blockExplorerUrl}/tx/${txHash}`;
3509
+ }
3510
+ const formatPastTx = params => {
3511
+ var _transaction$to;
3512
+ const {
3513
+ transaction,
3514
+ lowerCaseSelectedAddress,
3515
+ blockExplorerUrl
3516
+ } = params;
3517
+ let totalAmountString = "";
3518
+ if (transaction.type === CONTRACT_TYPE_ERC721 || transaction.type === CONTRACT_TYPE_ERC1155) totalAmountString = transaction.symbol;else if (transaction.type === CONTRACT_TYPE_ERC20) totalAmountString = formatSmallNumbers(Number.parseFloat(transaction.total_amount), transaction.symbol, true);else totalAmountString = formatSmallNumbers(Number.parseFloat(transaction.total_amount), transaction.type_name, true);
3519
+ const currencyAmountString = transaction.type === CONTRACT_TYPE_ERC721 || transaction.type === CONTRACT_TYPE_ERC1155 || transaction.isEtherscan ? "" : formatSmallNumbers(Number.parseFloat(transaction.currency_amount), transaction.selected_currency, true);
3520
+ const finalObject = {
3521
+ id: transaction.created_at.toString(),
3522
+ date: new Date(transaction.created_at).toString(),
3523
+ from: transaction.from,
3524
+ from_aa_address: transaction.from_aa_address,
3525
+ slicedFrom: typeof transaction.from === "string" ? addressSlicer(transaction.from) : "",
3526
+ to: transaction.to,
3527
+ slicedTo: typeof transaction.to === "string" ? addressSlicer(transaction.to) : "",
3528
+ action: lowerCaseSelectedAddress === ((_transaction$to = transaction.to) === null || _transaction$to === void 0 ? void 0 : _transaction$to.toLowerCase()) || "" ? ACTIVITY_ACTION_RECEIVE : ACTIVITY_ACTION_SEND,
3529
+ totalAmount: transaction.total_amount,
3530
+ totalAmountString,
3531
+ currencyAmount: transaction.currency_amount,
3532
+ currencyAmountString,
3533
+ amount: `${totalAmountString} / ${currencyAmountString}`,
3534
+ status: transaction.status,
3535
+ etherscanLink: blockExplorerUrl ? `${blockExplorerUrl}/tx/${transaction.transaction_hash}` : "",
3536
+ chainId: transaction.chain_id,
3537
+ ethRate: Number.parseFloat(transaction === null || transaction === void 0 ? void 0 : transaction.total_amount) && Number.parseFloat(transaction === null || transaction === void 0 ? void 0 : transaction.currency_amount) ? `1 ${transaction.symbol} = ${significantDigits(Number.parseFloat(transaction.currency_amount) / Number.parseFloat(transaction.total_amount))}` : "",
3538
+ currencyUsed: transaction.selected_currency,
3539
+ type: transaction.type,
3540
+ type_name: transaction.type_name,
3541
+ type_image_link: transaction.type_image_link,
3542
+ transaction_hash: transaction.transaction_hash,
3543
+ transaction_category: transaction.transaction_category,
3544
+ isEtherscan: transaction.isEtherscan,
3545
+ input: transaction.input || "",
3546
+ token_id: transaction.token_id || "",
3547
+ contract_address: transaction.contract_address || "",
3548
+ nonce: transaction.nonce || "",
3549
+ is_cancel: !!transaction.is_cancel || false,
3550
+ gas: transaction.gas || "",
3551
+ gasPrice: transaction.gasPrice || ""
3552
+ };
3553
+ return finalObject;
3554
+ };
3555
+
3556
+ /**
3557
+ * Ref - https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionreceipt
3558
+ */
3559
+ const getEthTxStatus = async (hash, provider) => {
3560
+ try {
3561
+ const result = await provider.request({
3562
+ method: METHOD_TYPES.ETH_GET_TRANSACTION_RECEIPT,
3563
+ params: [hash]
3564
+ });
3565
+ if (result === null) return TransactionStatus.submitted;
3566
+ if (result && result.status === "0x1") return TransactionStatus.confirmed;
3567
+ if (result && result.status === "0x0") return TransactionStatus.rejected;
3568
+ return undefined;
3569
+ } catch (err) {
3570
+ log.warn("unable to fetch transaction status", err);
3571
+ return undefined;
3500
3572
  }
3501
- configureStandardProvider(providerConfig) {
3502
- const networkClient = createJsonRpcClient(providerConfig, this.config);
3503
- log.info("networkClient", networkClient);
3504
- this.setNetworkClient(networkClient);
3573
+ };
3574
+ function formatDate(inputDate) {
3575
+ const monthList = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
3576
+ const date = new Date(inputDate);
3577
+ const day = date.getDate();
3578
+ const month = monthList[date.getMonth()];
3579
+ const year = date.getFullYear();
3580
+ return `${day} ${month} ${year}`;
3581
+ }
3582
+ function formatTime(time) {
3583
+ return new Date(time).toTimeString().slice(0, 8);
3584
+ }
3585
+ function isAddressByChainId(address, _chainId) {
3586
+ // TOOD: add rsk network checks.
3587
+ return isValidAddress(address);
3588
+ }
3589
+ function toChecksumAddressByChainId(address, chainId) {
3590
+ // TOOD: add rsk network checks.
3591
+ if (!isAddressByChainId(address)) return address;
3592
+ return toChecksumAddress(address);
3593
+ }
3594
+ const GAS_LIMITS = {
3595
+ // maximum gasLimit of a simple send
3596
+ SIMPLE: addHexPrefix(21000 .toString(16)),
3597
+ // a base estimate for token transfers.
3598
+ BASE_TOKEN_ESTIMATE: addHexPrefix(100000 .toString(16))
3599
+ };
3600
+ function bnLessThan(a, b) {
3601
+ if (a === null || a === undefined || b === null || b === undefined) {
3602
+ return null;
3505
3603
  }
3506
- refreshNetwork() {
3507
- this.update({
3508
- chainId: "loading",
3509
- properties: {}
3510
- });
3511
- this.configureProvider();
3512
- this.lookupNetwork();
3604
+ return new BigNumber(a, 10).lt(b, 10);
3605
+ }
3606
+ const getIpfsEndpoint = path => `https://infura-ipfs.io/${path}`;
3607
+ function sanitizeNftMetdataUrl(url) {
3608
+ let finalUri = url;
3609
+ if (url !== null && url !== void 0 && url.startsWith("ipfs")) {
3610
+ const ipfsPath = url.split("ipfs://")[1];
3611
+ finalUri = getIpfsEndpoint(ipfsPath);
3612
+ }
3613
+ return finalUri;
3614
+ }
3615
+ function getChainType(chainId) {
3616
+ if (chainId === MAINNET_CHAIN_ID) {
3617
+ return "mainnet";
3618
+ } else if (TEST_CHAINS.includes(chainId)) {
3619
+ return "testnet";
3513
3620
  }
3621
+ return "custom";
3514
3622
  }
3623
+ const addEtherscanTransactions = async params => {
3624
+ const {
3625
+ txn,
3626
+ lowerCaseSelectedAddress,
3627
+ provider,
3628
+ chainId,
3629
+ blockExplorerUrl
3630
+ } = params;
3631
+ const transactionPromises = await Promise.all(txn.map(async tx => {
3632
+ var _SUPPORTED_NETWORKS$c, _SUPPORTED_NETWORKS$c2;
3633
+ const {
3634
+ category,
3635
+ type
3636
+ } = await determineTransactionType(_objectSpread(_objectSpread({}, tx), {}, {
3637
+ data: tx.input
3638
+ }), provider);
3639
+ tx.transaction_category = tx.transaction_category || category;
3640
+ tx.type_image_link = ((_SUPPORTED_NETWORKS$c = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c === void 0 ? void 0 : _SUPPORTED_NETWORKS$c.logo) || "";
3641
+ tx.type_name = (_SUPPORTED_NETWORKS$c2 = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c2 === void 0 ? void 0 : _SUPPORTED_NETWORKS$c2.ticker;
3642
+ tx.type = type;
3643
+ return tx;
3644
+ }));
3645
+ const finalTxs = transactionPromises.reduce((accumulator, x) => {
3646
+ var _SUPPORTED_NETWORKS$c3, _SUPPORTED_NETWORKS$c4;
3647
+ let totalAmountString = x.value ? new BigNumber(x.value).div(new BigNumber(10).pow(new BigNumber(x.tokenDecimal || 18))).toString() : "";
3648
+ let type = CONTRACT_TYPE_ETH;
3649
+ if (x.contractAddress !== "") {
3650
+ if (x.tokenID) {
3651
+ type = x.tokenValue ? CONTRACT_TYPE_ERC1155 : CONTRACT_TYPE_ERC721;
3652
+ } else {
3653
+ type = CONTRACT_TYPE_ERC20;
3654
+ }
3655
+ }
3656
+ if (type === CONTRACT_TYPE_ERC1155) {
3657
+ totalAmountString = x.tokenValue;
3658
+ }
3659
+ const etherscanTransaction = {
3660
+ type,
3661
+ type_image_link: x.type_image_link || "n/a",
3662
+ type_name: x.tokenName || ((_SUPPORTED_NETWORKS$c3 = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c3 === void 0 ? void 0 : _SUPPORTED_NETWORKS$c3.ticker) || "n/a",
3663
+ symbol: x.tokenSymbol || ((_SUPPORTED_NETWORKS$c4 = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c4 === void 0 ? void 0 : _SUPPORTED_NETWORKS$c4.ticker),
3664
+ token_id: x.tokenID || "",
3665
+ total_amount: totalAmountString,
3666
+ created_at: new Date(Number(x.timeStamp) * 1000),
3667
+ from: x.from,
3668
+ to: x.to,
3669
+ transaction_hash: x.hash,
3670
+ status: x.txreceipt_status && x.txreceipt_status === "0" ? TransactionStatus.failed : TransactionStatus.confirmed,
3671
+ isEtherscan: true,
3672
+ input: x.input,
3673
+ contract_address: x.contractAddress,
3674
+ transaction_category: x.transaction_category,
3675
+ gas: `0x${new BigNumber(x.gasUsed || 0, 10).toString(16)}`,
3676
+ gasPrice: `0x${new BigNumber(x.gasPrice || 0, 10).toString(16)}`,
3677
+ chain_id: chainId,
3678
+ currency_amount: "",
3679
+ nonce: x.nonce,
3680
+ from_aa_address: "",
3681
+ is_cancel: false,
3682
+ selected_currency: ""
3683
+ };
3684
+ accumulator.push(formatPastTx({
3685
+ transaction: etherscanTransaction,
3686
+ lowerCaseSelectedAddress,
3687
+ blockExplorerUrl
3688
+ }));
3689
+ return accumulator;
3690
+ }, []);
3691
+ return finalTxs;
3692
+ };
3515
3693
 
3516
3694
  class NftHandler {
3517
3695
  constructor({
@@ -3933,6 +4111,7 @@ class PreferencesController extends BasePreferencesController {
3933
4111
  async initPreferences(params) {
3934
4112
  const {
3935
4113
  address,
4114
+ eoaAddress,
3936
4115
  jwtToken,
3937
4116
  calledFromEmbed,
3938
4117
  userInfo,
@@ -3947,6 +4126,7 @@ class PreferencesController extends BasePreferencesController {
3947
4126
  } = params;
3948
4127
  await super.init({
3949
4128
  address,
4129
+ eoaAddress,
3950
4130
  userInfo,
3951
4131
  idToken: jwtToken,
3952
4132
  type,
@@ -3961,7 +4141,7 @@ class PreferencesController extends BasePreferencesController {
3961
4141
  verifier,
3962
4142
  verifierId
3963
4143
  } = userInfo || {};
3964
- const userExists = await this.sync(address);
4144
+ const userExists = await this.sync(address, eoaAddress);
3965
4145
  if (!userExists) {
3966
4146
  const accountState = this.getAddressState(address);
3967
4147
  await this.createUser({
@@ -3971,6 +4151,7 @@ class PreferencesController extends BasePreferencesController {
3971
4151
  verifierId,
3972
4152
  locale,
3973
4153
  address,
4154
+ eoaAddress,
3974
4155
  type,
3975
4156
  web3AuthNetwork
3976
4157
  });
@@ -3992,9 +4173,9 @@ class PreferencesController extends BasePreferencesController {
3992
4173
  getSelectedAddress() {
3993
4174
  return this.state.selectedAddress;
3994
4175
  }
3995
- async sync(address) {
4176
+ async sync(address, eoaAddress) {
3996
4177
  try {
3997
- const user = await this.getUser(address);
4178
+ const user = await this.getUser(address, eoaAddress);
3998
4179
  if (user) {
3999
4180
  const {
4000
4181
  default_currency: defaultCurrency,
@@ -5989,4 +6170,4 @@ class TransactionController extends TransactionStateManager {
5989
6170
  }
5990
6171
  }
5991
6172
 
5992
- export { ARBITRUM_MAINNET_CHAIN_ID, ARBITRUM_TESTNET_CHAIN_ID, AVALANCHE_MAINNET_CHAIN_ID, AVALANCHE_TESTNET_CHAIN_ID, AbstractMessageController, AccountTrackerController, AddChainController, BASE_CHAIN_ID, BASE_TESTNET_CHAIN_ID, BNToHex, BSC_MAINNET_CHAIN_ID, BSC_TESTNET_CHAIN_ID, CELO_MAINNET_CHAIN_ID, CHAIN_ID_TO_GAS_LIMIT_BUFFER_MAP, COINGECKO_PLATFORMS_CHAIN_CODE_MAP, COINGECKO_SUPPORTED_CURRENCIES, CONTRACT_TYPE_ERC1155, CONTRACT_TYPE_ERC20, CONTRACT_TYPE_ERC721, CONTRACT_TYPE_ETH, CurrencyController, DEFAULT_CURRENCY, ERC1155_INTERFACE_ID, ERC721_ENUMERABLE_INTERFACE_ID, ERC721_INTERFACE_ID, ERC721_METADATA_INTERFACE_ID, ETHERSCAN_SUPPORTED_CHAINS, GAS_ESTIMATE_TYPES, GAS_LIMITS, GasFeeController, KeyringController, LOCALHOST, MAINNET_CHAIN_ID, MESSAGE_EVENTS, METHOD_TYPES, MessageController, MessageStatus, NetworkController, NftHandler, NftsController, NonceTracker, OLD_ERC721_LIST, OPTIMISM_MAINNET_CHAIN_ID, OPTIMISM_TESTNET_CHAIN_ID, POLYGON_AMOY_CHAIN_ID, POLYGON_CHAIN_ID, PendingTransactionTracker, PersonalMessageController, PollingBlockTracker, PreferencesController, SEPOLIA_CHAIN_ID, SIMPLEHASH_SUPPORTED_CHAINS, SUPPORTED_NETWORKS, SwitchChainController, TEST_CHAINS, TRANSACTION_ENVELOPE_TYPES, TokenHandler, TokenRatesController, TokensController, TransactionController, TransactionGasUtil, TransactionStateManager, TypedMessageController, XDAI_CHAIN_ID, addCurrencies, addEtherscanTransactions, bnLessThan, conversionGTE, conversionGreaterThan, conversionLTE, conversionLessThan, conversionMax, conversionUtil, createChainIdMiddleware, createEthereumMiddleware, createGetAccountsMiddleware, createJsonRpcClient, createPendingNonceMiddleware, createPendingTxMiddleware, createProcessAddEthereumChain, createProcessEthSignMessage, createProcessPersonalMessage, createProcessSwitchEthereumChain, createProcessTransactionMiddleware, createProcessTypedMessageV4, createProviderConfigMiddleware, createRequestAccountsMiddleware, decGWEIToHexWEI, determineTransactionType, ensureFieldIsString, ensureMutuallyExclusiveFieldsNotProvided, erc1155Abi, erc20Abi, erc721Abi, formatDate, formatPastTx, formatTime, formatTxMetaForRpcResult, generateHistoryEntry, getBigNumber, getChainType, getEthTxStatus, getEtherScanHashLink, getFinalStates, getIpfsEndpoint, hexToBn, hexWEIToDecGWEI, idleTimeTracker, isAddressByChainId, isEIP1559Transaction, isLegacyTransaction, multiplyCurrencies, normalizeAndValidateTxParams, normalizeMessageData, normalizeTxParameters, parseStandardTokenTransactionData, readAddressAsContract, replayHistory, sanitizeNftMetdataUrl, singleBalanceCheckerAbi, snapshotFromTxMeta, subtractCurrencies, toChecksumAddressByChainId, toNegative, transactionMatchesNetwork, validateAddChainData, validateAddress, validateFrom, validateRecipient, validateSignMessageData, validateSwitchChainData, validateTxParameters, validateTypedSignMessageDataV4 };
6173
+ export { ARBITRUM_MAINNET_CHAIN_ID, ARBITRUM_TESTNET_CHAIN_ID, AVALANCHE_MAINNET_CHAIN_ID, AVALANCHE_TESTNET_CHAIN_ID, AccountAbstractionController, AccountTrackerController, AddChainController, BASE_CHAIN_ID, BASE_TESTNET_CHAIN_ID, BNToHex, BSC_MAINNET_CHAIN_ID, BSC_TESTNET_CHAIN_ID, BiconomySmartAccount, CELO_MAINNET_CHAIN_ID, CHAIN_ID_TO_GAS_LIMIT_BUFFER_MAP, COINGECKO_PLATFORMS_CHAIN_CODE_MAP, COINGECKO_SUPPORTED_CURRENCIES, CONTRACT_TYPE_ERC1155, CONTRACT_TYPE_ERC20, CONTRACT_TYPE_ERC721, CONTRACT_TYPE_ETH, CurrencyController, DEFAULT_CURRENCY, ERC1155_INTERFACE_ID, ERC721_ENUMERABLE_INTERFACE_ID, ERC721_INTERFACE_ID, ERC721_METADATA_INTERFACE_ID, ETHERSCAN_SUPPORTED_CHAINS, GAS_ESTIMATE_TYPES, GAS_LIMITS, GasFeeController, KernelSmartAccount, KeyringController, LOCALHOST, MAINNET_CHAIN_ID, METHOD_TYPES, MessageController, NetworkController, NexusSmartAccount, NftHandler, NftsController, NonceTracker, OLD_ERC721_LIST, OPTIMISM_MAINNET_CHAIN_ID, OPTIMISM_TESTNET_CHAIN_ID, POLYGON_AMOY_CHAIN_ID, POLYGON_CHAIN_ID, PendingTransactionTracker, PersonalMessageController, PollingBlockTracker, PreferencesController, SEPOLIA_CHAIN_ID, SIMPLEHASH_SUPPORTED_CHAINS, SMART_ACCOUNT, SUPPORTED_NETWORKS, SafeSmartAccount, SwitchChainController, TEST_CHAINS, TRANSACTION_ENVELOPE_TYPES, TokenHandler, TokenRatesController, TokensController, TransactionController, TransactionGasUtil, TransactionStateManager, TrustSmartAccount, TypedMessageController, XDAI_CHAIN_ID, addCurrencies, addEtherscanTransactions, bnLessThan, conversionGTE, conversionGreaterThan, conversionLTE, conversionLessThan, conversionMax, conversionUtil, createChainIdMiddleware, createEthereumMiddleware, createGetAccountsMiddleware, createJsonRpcClient, createPendingNonceMiddleware, createPendingTxMiddleware, createProcessAddEthereumChain, createProcessEthSignMessage, createProcessPersonalMessage, createProcessSwitchEthereumChain, createProcessTransactionMiddleware, createProcessTypedMessageV4, createProviderConfigMiddleware, createRequestAccountsMiddleware, decGWEIToHexWEI, determineTransactionType, ensureFieldIsString, ensureMutuallyExclusiveFieldsNotProvided, eoaInterceptorMiddleware, eoaProviderAsMiddleware, erc1155Abi, erc20Abi, erc721Abi, formatDate, formatPastTx, formatTime, formatTxMetaForRpcResult, generateHistoryEntry, getBigNumber, getChainType, getEthTxStatus, getEtherScanHashLink, getFinalStates, getIpfsEndpoint, hexToBn, hexWEIToDecGWEI, isAddressByChainId, isEIP1559Transaction, isLegacyTransaction, multiplyCurrencies, normalizeAndValidateTxParams, normalizeMessageData, normalizeTxParameters, parseStandardTokenTransactionData, readAddressAsContract, replayHistory, sanitizeNftMetdataUrl, singleBalanceCheckerAbi, snapshotFromTxMeta, subtractCurrencies, toChecksumAddressByChainId, toNegative, transactionMatchesNetwork, validateAddChainData, validateAddress, validateFrom, validateRecipient, validateSignMessageData, validateSwitchChainData, validateTxParameters, validateTypedSignMessageDataV4 };