@toruslabs/ethereum-controllers 6.3.2 → 7.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/757.ethereumControllers.cjs.js +226 -0
  2. package/dist/ethereumControllers.cjs.js +19077 -2288
  3. package/dist/ethereumControllers.esm.js +1808 -1614
  4. package/dist/ethereumControllers.umd.min.js +1 -1
  5. package/dist/lib.cjs/AccountAbstraction/AccountAbstractionController.js +217 -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 +19 -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/Transaction/PendingTransactionTracker.js +2 -1
  24. package/dist/lib.cjs/index.js +15 -5
  25. package/dist/lib.cjs/utils/constants.js +10 -12
  26. package/dist/lib.cjs/utils/helpers.js +0 -25
  27. package/dist/lib.esm/AccountAbstraction/AccountAbstractionController.js +213 -0
  28. package/dist/lib.esm/AccountAbstraction/smartAccounts/BiconomySmartAccount.js +27 -0
  29. package/dist/lib.esm/AccountAbstraction/smartAccounts/KernelSmartAccount.js +22 -0
  30. package/dist/lib.esm/AccountAbstraction/smartAccounts/NexusSmartAccount.js +28 -0
  31. package/dist/lib.esm/AccountAbstraction/smartAccounts/SafeSmartAccount.js +30 -0
  32. package/dist/lib.esm/AccountAbstraction/smartAccounts/TrustSmartAccount.js +29 -0
  33. package/dist/lib.esm/Block/PollingBlockTracker.js +1 -2
  34. package/dist/lib.esm/Currency/CurrencyController.js +1 -2
  35. package/dist/lib.esm/Gas/GasFeeController.js +1 -2
  36. package/dist/lib.esm/Message/AddChainController.js +3 -6
  37. package/dist/lib.esm/Message/MessageController.js +4 -7
  38. package/dist/lib.esm/Message/PersonalMessageController.js +4 -7
  39. package/dist/lib.esm/Message/SwitchChainController.js +3 -6
  40. package/dist/lib.esm/Message/TypedMessageController.js +5 -5
  41. package/dist/lib.esm/Nfts/NftsController.js +1 -2
  42. package/dist/lib.esm/Preferences/PreferencesController.js +19 -3
  43. package/dist/lib.esm/Tokens/TokenRatesController.js +1 -2
  44. package/dist/lib.esm/Tokens/TokensController.js +2 -2
  45. package/dist/lib.esm/Transaction/PendingTransactionTracker.js +2 -1
  46. package/dist/lib.esm/index.js +8 -3
  47. package/dist/lib.esm/utils/constants.js +10 -11
  48. package/dist/lib.esm/utils/helpers.js +1 -25
  49. package/dist/types/AccountAbstraction/AccountAbstractionController.d.ts +52 -0
  50. package/dist/types/AccountAbstraction/smartAccounts/BiconomySmartAccount.d.ts +15 -0
  51. package/dist/types/AccountAbstraction/smartAccounts/KernelSmartAccount.d.ts +16 -0
  52. package/dist/types/AccountAbstraction/smartAccounts/LightSmartAccount.d.ts +15 -0
  53. package/dist/types/AccountAbstraction/smartAccounts/NexusSmartAccount.d.ts +15 -0
  54. package/dist/types/AccountAbstraction/smartAccounts/SafeSmartAccount.d.ts +16 -0
  55. package/dist/types/AccountAbstraction/smartAccounts/SimpleSmartAccount.d.ts +16 -0
  56. package/dist/types/AccountAbstraction/smartAccounts/TrustSmartAccount.d.ts +16 -0
  57. package/dist/types/AccountAbstraction/smartAccounts/index.d.ts +5 -0
  58. package/dist/types/Block/PollingBlockTracker.d.ts +2 -2
  59. package/dist/types/Currency/CurrencyController.d.ts +2 -2
  60. package/dist/types/Message/AddChainController.d.ts +3 -6
  61. package/dist/types/Message/MessageController.d.ts +5 -8
  62. package/dist/types/Message/PersonalMessageController.d.ts +5 -8
  63. package/dist/types/Message/SwitchChainController.d.ts +3 -6
  64. package/dist/types/Message/TypedMessageController.d.ts +3 -3
  65. package/dist/types/Message/types.d.ts +2 -0
  66. package/dist/types/Message/utils.d.ts +2 -1
  67. package/dist/types/Network/createEthereumMiddleware.d.ts +2 -2
  68. package/dist/types/Nfts/NftsController.d.ts +2 -2
  69. package/dist/types/Preferences/PreferencesController.d.ts +4 -1
  70. package/dist/types/Tokens/ITokensController.d.ts +4 -6
  71. package/dist/types/Tokens/TokenRatesController.d.ts +6 -14
  72. package/dist/types/Tokens/TokensController.d.ts +7 -7
  73. package/dist/types/Transaction/TransactionController.d.ts +2 -2
  74. package/dist/types/index.d.ts +2 -6
  75. package/dist/types/utils/constants.d.ts +8 -10
  76. package/dist/types/utils/helpers.d.ts +0 -3
  77. package/dist/types/utils/interfaces.d.ts +31 -2
  78. package/package.json +6 -4
  79. package/dist/lib.cjs/Message/AbstractMessageController.js +0 -107
  80. package/dist/lib.esm/Message/AbstractMessageController.js +0 -105
  81. 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,607 @@ 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
+ this.update({
1199
+ userOperations: _objectSpread(_objectSpread({}, this.state.userOperations), {}, {
1200
+ [id]: _objectSpread(_objectSpread({}, userOp), data)
1201
+ })
1202
+ });
1041
1203
  }
1042
- return false;
1043
1204
  }
1044
1205
 
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));
1206
+ class BiconomySmartAccount {
1207
+ constructor(options) {
1208
+ _defineProperty(this, "name", SMART_ACCOUNT.BICONOMY);
1209
+ _defineProperty(this, "options", void 0);
1210
+ this.options = options;
1211
+ }
1212
+ async getSmartAccount(params) {
1213
+ var _this$options, _this$options2;
1214
+ return toBiconomySmartAccount(_objectSpread(_objectSpread(_objectSpread({}, this.options || {}), {}, {
1215
+ entryPoint: {
1216
+ 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,
1217
+ 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"
1218
+ }
1219
+ }, params), {}, {
1220
+ owners: [params.owner],
1221
+ client: params.client
1222
+ }));
1223
+ }
1054
1224
  }
1055
1225
 
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
- }
1226
+ // use type of function so we don't need to pass in generic to parameter type
1068
1227
 
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`);
1228
+ class KernelSmartAccount {
1229
+ constructor(options) {
1230
+ _defineProperty(this, "name", SMART_ACCOUNT.KERNEL);
1231
+ _defineProperty(this, "options", void 0);
1232
+ this.options = options;
1233
+ }
1234
+ async getSmartAccount(params) {
1235
+ return toEcdsaKernelSmartAccount(_objectSpread(_objectSpread(_objectSpread({}, this.options || {}), params), {}, {
1236
+ owners: [params.owner],
1237
+ client: params.client
1238
+ }));
1076
1239
  }
1077
1240
  }
1078
1241
 
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]})`);
1242
+ class NexusSmartAccount {
1243
+ constructor(options) {
1244
+ _defineProperty(this, "name", SMART_ACCOUNT.NEXUS);
1245
+ _defineProperty(this, "options", void 0);
1246
+ this.options = options;
1247
+ }
1248
+ async getSmartAccount(params) {
1249
+ var _this$options, _this$options2, _this$options3;
1250
+ return toNexusSmartAccount(_objectSpread(_objectSpread(_objectSpread({}, this.options || {}), {}, {
1251
+ entryPoint: {
1252
+ 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,
1253
+ 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"
1254
+ },
1255
+ version: ((_this$options3 = this.options) === null || _this$options3 === void 0 ? void 0 : _this$options3.version) || "1.0.0"
1256
+ }, params), {}, {
1257
+ owners: [params.owner],
1258
+ client: params.client
1259
+ }));
1086
1260
  }
1087
1261
  }
1088
1262
 
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
- }
1263
+ // use type of function so we don't need to pass in generic to parameter type
1264
+
1265
+ class SafeSmartAccount {
1266
+ constructor(options) {
1267
+ _defineProperty(this, "name", SMART_ACCOUNT.SAFE);
1268
+ _defineProperty(this, "options", void 0);
1269
+ this.options = options;
1270
+ }
1271
+ async getSmartAccount(params) {
1272
+ var _this$options, _this$options2, _this$options3;
1273
+ return toSafeSmartAccount(_objectSpread(_objectSpread(_objectSpread({}, this.options || {}), {}, {
1274
+ entryPoint: {
1275
+ 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,
1276
+ 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"
1277
+ },
1278
+ version: ((_this$options3 = this.options) === null || _this$options3 === void 0 ? void 0 : _this$options3.version) || "1.4.1"
1279
+ }, params), {}, {
1280
+ owners: [params.owner],
1281
+ client: params.client
1282
+ }));
1107
1283
  }
1108
1284
  }
1109
1285
 
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.');
1286
+ // use type of function so we don't need to pass in generic to parameter type
1287
+
1288
+ class TrustSmartAccount {
1289
+ constructor(options) {
1290
+ _defineProperty(this, "name", SMART_ACCOUNT.TRUST);
1291
+ _defineProperty(this, "options", void 0);
1292
+ this.options = options;
1293
+ }
1294
+ async getSmartAccount(params) {
1295
+ var _this$options, _this$options2;
1296
+ return toTrustSmartAccount(_objectSpread(_objectSpread(_objectSpread({}, this.options || {}), {}, {
1297
+ entryPoint: {
1298
+ 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,
1299
+ 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"
1300
+ }
1301
+ }, params), {}, {
1302
+ owner: params.owner,
1303
+ client: params.client
1304
+ }));
1119
1305
  }
1120
1306
  }
1121
1307
 
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.');
1308
+ const DEFAULT_POLLING_INTERVAL = 20;
1309
+ const DEFAULT_RETRY_TIMEOUT = 2;
1310
+ const SEC = 1000;
1311
+ class PollingBlockTracker extends BaseBlockTracker {
1312
+ constructor({
1313
+ config,
1314
+ state = {}
1315
+ }) {
1316
+ if (!config.provider) {
1317
+ throw new Error("PollingBlockTracker - no provider specified.");
1131
1318
  }
1132
- } else if (txParameters.to !== undefined && !isValidAddress(txParameters.to)) {
1133
- throw rpcErrors.invalidParams('Invalid "to" address.');
1319
+ super({
1320
+ config,
1321
+ state
1322
+ });
1323
+ const pollingInterval = config.pollingInterval || DEFAULT_POLLING_INTERVAL;
1324
+ const retryTimeout = config.retryTimeout || DEFAULT_RETRY_TIMEOUT;
1325
+
1326
+ // merge default + provided config.
1327
+ this.defaultConfig = {
1328
+ provider: config.provider,
1329
+ pollingInterval: pollingInterval * SEC,
1330
+ retryTimeout: retryTimeout * SEC,
1331
+ setSkipCacheFlag: config.setSkipCacheFlag || false
1332
+ };
1333
+ this.initialize();
1334
+ }
1335
+ async checkForLatestBlock() {
1336
+ await this._updateLatestBlock();
1337
+ return this.getLatestBlock();
1134
1338
  }
1135
- return txParameters;
1136
- }
1137
1339
 
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.");
1340
+ // overrides the BaseBlockTracker._start method.
1341
+ _start() {
1342
+ this._synchronize().catch(err => this.emit("error", err));
1145
1343
  }
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.');
1344
+ async _synchronize() {
1345
+ while (this.state._isRunning) {
1346
+ if (idleTimeTracker.checkIfIdle()) return;
1347
+ try {
1348
+ await this._updateLatestBlock();
1349
+ await timeout(this.config.pollingInterval);
1350
+ } catch (err) {
1351
+ const newErr = new Error(`PollingBlockTracker - encountered an error while attempting to update latest block:\n${err.stack}`);
1352
+ try {
1353
+ this.emit("error", newErr);
1354
+ } catch (emitErr) {
1355
+ log.error(newErr);
1356
+ }
1357
+ await timeout(this.config.retryTimeout);
1358
+ }
1359
+ }
1148
1360
  }
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");
1361
+ async _updateLatestBlock() {
1362
+ // fetch + set latest block
1363
+ const latestBlock = await this._fetchLatestBlock();
1364
+ this._newPotentialLatest(latestBlock);
1153
1365
  }
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);
1366
+ async _fetchLatestBlock() {
1367
+ try {
1368
+ const block = await this.config.provider.request({
1369
+ method: "eth_getBlockByNumber",
1370
+ params: ["latest", false]
1371
+ });
1372
+ return {
1373
+ blockHash: block.hash,
1374
+ idempotencyKey: block.number,
1375
+ timestamp: block.timestamp,
1376
+ baseFeePerGas: block.baseFeePerGas,
1377
+ gasLimit: block.gasLimit
1378
+ };
1379
+ } catch (error) {
1380
+ log.error("Polling Block Tracker: ", error);
1381
+ throw new Error(`PollingBlockTracker - encountered error fetching block:\n${error.message}`);
1195
1382
  }
1196
- });
1197
- }
1198
- function normalizeAndValidateTxParams(txParams, lowerCase = true) {
1199
- const normalizedTxParams = normalizeTxParameters(txParams, lowerCase);
1200
- validateTxParameters(normalizedTxParams);
1201
- return normalizedTxParams;
1383
+ }
1202
1384
  }
1203
1385
 
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
1386
+ class CurrencyController extends BaseCurrencyController {
1387
+ constructor({
1388
+ config,
1389
+ state,
1390
+ onNetworkChanged
1391
+ }) {
1392
+ super({
1393
+ config,
1394
+ state
1221
1395
  });
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
1396
+ _defineProperty(this, "conversionInterval", void 0);
1397
+ this.defaultState = _objectSpread(_objectSpread({}, this.defaultState), {}, {
1398
+ commonDenomination: "USD",
1399
+ commonDenominatorPrice: 0
1400
+ });
1401
+ this.initialize();
1402
+ onNetworkChanged(networkState => {
1403
+ // to be called as (listener) => this.networkController.on('networkDidChange', listener);
1404
+ if (networkState.providerConfig.ticker.toUpperCase() !== this.state.nativeCurrency.toUpperCase()) {
1405
+ this.setNativeCurrency(networkState.providerConfig.ticker);
1406
+ this.updateConversionRate();
1407
+ }
1233
1408
  });
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
1409
  }
1242
- try {
1243
- const txDesc = erc1155Interface.parseTransaction({
1244
- data
1410
+ setCommonDenomination(commonDenomination) {
1411
+ this.update({
1412
+ commonDenomination
1245
1413
  });
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
1414
  }
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"]
1415
+ getCommonDenomination() {
1416
+ return this.state.commonDenomination;
1417
+ }
1418
+ setCommonDenominatorPrice(commonDenominatorPrice) {
1419
+ this.update({
1420
+ commonDenominatorPrice
1262
1421
  });
1263
- } catch (e) {
1264
- contractCode = null;
1265
1422
  }
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);
1423
+ getCommonDenominatorPrice() {
1424
+ return this.state.commonDenominatorPrice;
1288
1425
  }
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;
1426
+
1427
+ /**
1428
+ * Creates a new poll, using setInterval, to periodically call updateConversionRate. The id of the interval is
1429
+ * stored at the controller's conversionInterval property. If it is called and such an id already exists, the
1430
+ * previous interval is clear and a new one is created.
1431
+ */
1432
+ scheduleConversionInterval() {
1433
+ if (this.conversionInterval) {
1434
+ window.clearInterval(this.conversionInterval);
1435
+ }
1436
+ this.conversionInterval = window.setInterval(() => {
1437
+ if (!idleTimeTracker.checkIfIdle()) {
1438
+ this.updateConversionRate();
1439
+ }
1440
+ }, this.config.pollInterval);
1441
+ }
1442
+
1443
+ /**
1444
+ * Updates the conversionRate and conversionDate properties associated with the currentCurrency. Updated info is
1445
+ * fetched from an external API
1446
+ */
1447
+ async updateConversionRate() {
1448
+ const currentCurrency = this.getCurrentCurrency();
1449
+ const nativeCurrency = this.getNativeCurrency();
1450
+ const commonDenomination = this.getCommonDenomination();
1451
+ const conversionRate = await this.retrieveConversionRate(nativeCurrency, currentCurrency, commonDenomination);
1452
+ const currentCurrencyRate = Number.parseFloat(conversionRate[currentCurrency.toUpperCase()]);
1453
+ const commonDenominationRate = Number.parseFloat(conversionRate[commonDenomination.toUpperCase()]);
1454
+ // set conversion rate
1455
+ if (currentCurrencyRate || commonDenominationRate) {
1456
+ // ETC
1457
+ this.setConversionRate(currentCurrencyRate);
1458
+ this.setConversionDate(Math.floor(Date.now() / 1000).toString());
1459
+ if (currentCurrency.toUpperCase() === commonDenomination.toUpperCase()) {
1460
+ this.setCommonDenominatorPrice(currentCurrencyRate);
1461
+ } else {
1462
+ this.setCommonDenominatorPrice(commonDenominationRate);
1463
+ }
1306
1464
  } else {
1307
- result = TRANSACTION_TYPES.SENT_ETHER;
1465
+ this.setConversionRate(0);
1466
+ this.setConversionDate("N/A");
1308
1467
  }
1309
1468
  }
1310
- return {
1311
- type: type || CONTRACT_TYPE_ETH,
1312
- category: result,
1313
- methodParams,
1314
- getCodeResponse: contractCode
1315
- };
1469
+ async retrieveConversionRate(fromCurrency, toCurrency, commonDenomination) {
1470
+ try {
1471
+ let apiUrl = `${this.config.api}/currency?fsym=${fromCurrency.toUpperCase()}&tsyms=${toCurrency.toUpperCase()}`;
1472
+ if (commonDenomination && commonDenomination.toUpperCase() !== toCurrency.toUpperCase()) {
1473
+ apiUrl += `,${commonDenomination.toUpperCase()}`;
1474
+ }
1475
+ const parsedResponse = await get(apiUrl);
1476
+ return parsedResponse;
1477
+ } catch (error) {
1478
+ log.error(error, `CurrencyController - updateCommonDenominatorPrice: Failed to query rate for currency: ${fromCurrency}/ ${toCurrency}`);
1479
+ }
1480
+ return {
1481
+ [toCurrency.toUpperCase()]: "0",
1482
+ [commonDenomination.toUpperCase()]: "0"
1483
+ };
1484
+ }
1316
1485
  }
1317
1486
 
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;
1487
+ const _excluded$1 = ["aBase", "bBase"],
1488
+ _excluded2 = ["aBase", "bBase"],
1489
+ _excluded3 = ["multiplicandBase", "multiplierBase"];
1490
+
1491
+ // Big Number Constants
1492
+ const BIG_NUMBER_WEI_MULTIPLIER = new BigNumber("1000000000000000000");
1493
+ const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber("1000000000");
1494
+ const BIG_NUMBER_ETH_MULTIPLIER = new BigNumber("1");
1495
+ // Setter Maps
1496
+ const toBigNumber = {
1497
+ hex: n => new BigNumber(stripHexPrefix(n), 16),
1498
+ dec: n => new BigNumber(String(n), 10),
1499
+ BN: n => new BigNumber(n.toString(16), 16)
1500
+ };
1501
+ const toNormalizedDenomination = {
1502
+ WEI: bigNumber => bigNumber.div(BIG_NUMBER_WEI_MULTIPLIER),
1503
+ GWEI: bigNumber => bigNumber.div(BIG_NUMBER_GWEI_MULTIPLIER),
1504
+ ETH: bigNumber => bigNumber.div(BIG_NUMBER_ETH_MULTIPLIER)
1505
+ };
1506
+ const toSpecifiedDenomination = {
1507
+ WEI: bigNumber => bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).dp(0, BigNumber.ROUND_HALF_UP),
1508
+ GWEI: bigNumber => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).dp(9, BigNumber.ROUND_HALF_UP),
1509
+ ETH: bigNumber => bigNumber.times(BIG_NUMBER_ETH_MULTIPLIER).dp(9, BigNumber.ROUND_HALF_UP)
1510
+ };
1511
+ const baseChange = {
1512
+ hex: n => n.toString(16),
1513
+ dec: n => new BigNumber(n).toString(10),
1514
+ BN: n => new BN(n.toString(16))
1372
1515
  };
1373
1516
 
1517
+ // Utility function for checking base types
1518
+ const isValidBase = base => Number.isInteger(base) && base > 1;
1519
+
1374
1520
  /**
1375
- * Ref - https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionreceipt
1521
+ * Utility method to convert a value between denominations, formats and currencies.
1376
1522
  */
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;
1523
+ const converter = ({
1524
+ value,
1525
+ fromNumericBase,
1526
+ fromDenomination,
1527
+ fromCurrency,
1528
+ toNumericBase,
1529
+ toDenomination,
1530
+ toCurrency,
1531
+ numberOfDecimals,
1532
+ conversionRate,
1533
+ invertConversionRate,
1534
+ roundDown
1535
+ }) => {
1536
+ let convertedValue = fromNumericBase ? toBigNumber[fromNumericBase](value) : value;
1537
+ if (fromDenomination) {
1538
+ convertedValue = toNormalizedDenomination[fromDenomination](convertedValue);
1390
1539
  }
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);
1540
+ if (fromCurrency !== toCurrency) {
1541
+ if (conversionRate === null || conversionRate === undefined) {
1542
+ throw new Error(`Converting from ${fromCurrency} to ${toCurrency} requires a conversionRate, but one was not provided`);
1543
+ }
1544
+ let rate = toBigNumber.dec(conversionRate);
1545
+ if (invertConversionRate) {
1546
+ rate = new BigNumber(1).div(conversionRate);
1547
+ }
1548
+ convertedValue = convertedValue.times(rate);
1549
+ }
1550
+ if (toDenomination) {
1551
+ convertedValue = toSpecifiedDenomination[toDenomination](convertedValue);
1419
1552
  }
1420
- function checkIfIdle() {
1421
- return isIdle;
1553
+ if (numberOfDecimals) {
1554
+ convertedValue = convertedValue.dp(numberOfDecimals, BigNumber.ROUND_HALF_DOWN);
1422
1555
  }
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))
1556
+ if (roundDown) {
1557
+ convertedValue = convertedValue.dp(roundDown, BigNumber.ROUND_DOWN);
1558
+ }
1559
+ if (toNumericBase) {
1560
+ convertedValue = baseChange[toNumericBase](convertedValue);
1561
+ }
1562
+ return convertedValue;
1441
1563
  };
1442
- function bnLessThan(a, b) {
1443
- if (a === null || a === undefined || b === null || b === undefined) {
1444
- return null;
1564
+ const conversionUtil = (value, {
1565
+ fromCurrency = null,
1566
+ toCurrency = fromCurrency,
1567
+ fromNumericBase,
1568
+ toNumericBase,
1569
+ fromDenomination,
1570
+ toDenomination,
1571
+ numberOfDecimals,
1572
+ conversionRate,
1573
+ invertConversionRate
1574
+ }) => {
1575
+ if (fromCurrency !== toCurrency && !conversionRate) {
1576
+ return 0;
1445
1577
  }
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);
1578
+ return converter({
1579
+ fromCurrency,
1580
+ toCurrency,
1581
+ fromNumericBase,
1582
+ toNumericBase,
1583
+ fromDenomination,
1584
+ toDenomination,
1585
+ numberOfDecimals,
1586
+ conversionRate,
1587
+ invertConversionRate,
1588
+ value
1589
+ });
1590
+ };
1591
+ const getBigNumber = (value, base) => {
1592
+ if (!isValidBase(base)) {
1593
+ throw new Error("Must specificy valid base");
1454
1594
  }
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";
1595
+
1596
+ // We don't include 'number' here, because BigNumber will throw if passed
1597
+ // a number primitive it considers unsafe.
1598
+ if (typeof value === "string" || value instanceof BigNumber) {
1599
+ return new BigNumber(value, base);
1462
1600
  }
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 = {}) => {
1601
+ return new BigNumber(String(value), base);
1602
+ };
1603
+ const addCurrencies = (a, b, options = {}) => {
1832
1604
  const {
1833
1605
  aBase,
1834
1606
  bBase
@@ -2171,7 +1943,7 @@ class GasFeeController extends BaseController {
2171
1943
  const chainId = this.getNetworkIdentifier();
2172
1944
  if (chainId === "loading") return;
2173
1945
  let chainIdInt;
2174
- if (typeof chainId === "string" && isHexString(addHexPrefix(chainId))) {
1946
+ if (typeof chainId === "string" && isHexString$1(addHexPrefix(chainId))) {
2175
1947
  chainIdInt = Number.parseInt(chainId, 16);
2176
1948
  }
2177
1949
  try {
@@ -2328,7 +2100,7 @@ class KeyringController extends BaseKeyringController {
2328
2100
  // we need to check if the data is hex or not
2329
2101
  // For historical reasons, you must submit the message to sign in hex-encoded UTF-8.
2330
2102
  // 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);
2103
+ const message = isHexString$1(data) ? Buffer.from(stripHexPrefix(data), "hex") : Buffer.from(data);
2332
2104
  const signature = privKey.sign(hashMessage(message)).serialized;
2333
2105
  return signature;
2334
2106
  }
@@ -2349,105 +2121,6 @@ class KeyringController extends BaseKeyringController {
2349
2121
  }
2350
2122
  }
2351
2123
 
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
2124
  const hexRe = /^[0-9A-Fa-f]+$/gu;
2452
2125
  function validateAddress(address, propertyName) {
2453
2126
  if (!address || typeof address !== "string" || !isValidAddress(address)) {
@@ -2516,7 +2189,7 @@ async function validateAddChainData(data) {
2516
2189
  if (!chainId) {
2517
2190
  throw new Error("Invalid add chain params: please pass chainId in params");
2518
2191
  }
2519
- if (!isHexString$1(chainId)) {
2192
+ if (!isHexString(chainId)) {
2520
2193
  throw new Error("Invalid add chain params: please pass a valid hex chainId in params, for: ex: 0x1");
2521
2194
  }
2522
2195
  if (!rpcUrls || rpcUrls.length === 0) throw new Error("params.rpcUrls not provided");
@@ -2544,7 +2217,7 @@ function validateSwitchChainData(data) {
2544
2217
  if (!chainId) {
2545
2218
  throw new Error("Invalid switch chain params: please pass chainId in params");
2546
2219
  }
2547
- if (!isHexString$1(chainId)) {
2220
+ if (!isHexString(chainId)) {
2548
2221
  throw new Error("Invalid switch chain params: please pass a valid hex chainId in params, for: ex: 0x1");
2549
2222
  }
2550
2223
  }
@@ -2553,13 +2226,11 @@ class AddChainController extends AbstractMessageController {
2553
2226
  constructor({
2554
2227
  config,
2555
2228
  state,
2556
- getNetworkIdentifier,
2557
2229
  addChain
2558
2230
  }) {
2559
2231
  super({
2560
2232
  config,
2561
- state,
2562
- getNetworkIdentifier
2233
+ state
2563
2234
  });
2564
2235
  _defineProperty(this, "name", "AddChainController");
2565
2236
  _defineProperty(this, "addChain", void 0);
@@ -2620,13 +2291,11 @@ class MessageController extends AbstractMessageController {
2620
2291
  constructor({
2621
2292
  config,
2622
2293
  state,
2623
- signMessage,
2624
- getNetworkIdentifier
2294
+ signMessage
2625
2295
  }) {
2626
2296
  super({
2627
2297
  config,
2628
- state,
2629
- getNetworkIdentifier
2298
+ state
2630
2299
  });
2631
2300
  _defineProperty(this, "name", "MessageController");
2632
2301
  _defineProperty(this, "signMessage", void 0);
@@ -2686,27 +2355,158 @@ class PersonalMessageController extends AbstractMessageController {
2686
2355
  constructor({
2687
2356
  config,
2688
2357
  state,
2689
- signPersonalMessage,
2690
- getNetworkIdentifier
2358
+ signPersonalMessage
2691
2359
  }) {
2692
2360
  super({
2693
2361
  config,
2694
- state,
2695
- getNetworkIdentifier
2362
+ state
2696
2363
  });
2697
2364
  _defineProperty(this, "name", "PersonalMessageController");
2698
2365
  _defineProperty(this, "signPersonalMessage", void 0);
2699
2366
  this.signPersonalMessage = signPersonalMessage;
2700
2367
  this.initialize();
2701
2368
  }
2702
- async processSignPersonalMessage(messageId) {
2369
+ async processSignPersonalMessage(messageId) {
2370
+ const msgObject = this.getMessage(messageId);
2371
+ if (!msgObject) {
2372
+ throw new Error(`Message not found`);
2373
+ }
2374
+ try {
2375
+ const cleanMsgParams = await this.approveMessage(messageId, msgObject.messageParams);
2376
+ const rawSig = await this.signPersonalMessage(cleanMsgParams.data, cleanMsgParams.from);
2377
+ this.updateMessage(_objectSpread(_objectSpread({}, msgObject), {}, {
2378
+ rawSig
2379
+ }));
2380
+ this.setMessageStatus(messageId, MessageStatus.SIGNED);
2381
+ return rawSig;
2382
+ } catch (error) {
2383
+ log.error(error);
2384
+ msgObject.error = (error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.toString());
2385
+ this.setMessageStatus(messageId, MessageStatus.FAILED);
2386
+ }
2387
+ }
2388
+ async addNewUnapprovedMessage(messageParams, req) {
2389
+ await this.addUnapprovedMessage(messageParams, req);
2390
+ return this.waitForFinishStatus(messageParams, this.name);
2391
+ }
2392
+ async addUnapprovedMessage(messageParams, req) {
2393
+ validateSignMessageData(messageParams);
2394
+ if (req) {
2395
+ messageParams.origin = req.origin;
2396
+ }
2397
+ messageParams.data = normalizeMessageData(messageParams.data);
2398
+ const messageId = messageParams.id || randomId();
2399
+ const messageData = {
2400
+ id: messageId,
2401
+ messageParams,
2402
+ status: MessageStatus.UNAPPROVED,
2403
+ time: Date.now(),
2404
+ type: METHOD_TYPES.PERSONAL_SIGN
2405
+ };
2406
+ await this.addMessage(messageData);
2407
+ this.emit(MESSAGE_EVENTS.UNAPPROVED_MESSAGE, {
2408
+ messageData,
2409
+ req
2410
+ });
2411
+ return messageId;
2412
+ }
2413
+ prepMessageForSigning(messageParams) {
2414
+ return Promise.resolve(messageParams);
2415
+ }
2416
+ }
2417
+
2418
+ class SwitchChainController extends AbstractMessageController {
2419
+ constructor({
2420
+ config,
2421
+ state,
2422
+ switchChain
2423
+ }) {
2424
+ super({
2425
+ config,
2426
+ state
2427
+ });
2428
+ _defineProperty(this, "name", "SwitchChainController");
2429
+ _defineProperty(this, "switchChain", void 0);
2430
+ this.switchChain = switchChain;
2431
+ this.initialize();
2432
+ }
2433
+ async processSwitchChain(messageId) {
2434
+ const msgObject = this.getMessage(messageId);
2435
+ if (!msgObject) {
2436
+ throw new Error(`Message not found`);
2437
+ }
2438
+ try {
2439
+ await this.approveMessage(messageId, msgObject.messageParams);
2440
+ this.switchChain({
2441
+ chainId: msgObject.messageParams.chainId
2442
+ });
2443
+ this.updateMessage(_objectSpread(_objectSpread({}, msgObject), {}, {
2444
+ rawSig: JSON.stringify(msgObject.messageParams)
2445
+ }));
2446
+ this.setMessageStatus(messageId, MessageStatus.SIGNED);
2447
+ return null;
2448
+ } catch (error) {
2449
+ log.error(error);
2450
+ msgObject.error = (error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.toString());
2451
+ this.setMessageStatus(messageId, MessageStatus.FAILED);
2452
+ }
2453
+ }
2454
+ async addNewUnapprovedMessage(messageParams, req) {
2455
+ await this.addUnapprovedMessage(messageParams, req);
2456
+ return this.waitForFinishStatus(messageParams, this.name);
2457
+ }
2458
+ async addUnapprovedMessage(messageParams, req) {
2459
+ validateSwitchChainData(messageParams);
2460
+ if (req) {
2461
+ messageParams.origin = req.origin;
2462
+ }
2463
+ const messageId = messageParams.id || randomId();
2464
+ const messageData = {
2465
+ id: messageId,
2466
+ messageParams,
2467
+ status: MessageStatus.UNAPPROVED,
2468
+ time: Date.now(),
2469
+ type: METHOD_TYPES.SWITCH_CHAIN
2470
+ };
2471
+ await this.addMessage(messageData);
2472
+ this.emit(MESSAGE_EVENTS.UNAPPROVED_MESSAGE, {
2473
+ messageData,
2474
+ req
2475
+ });
2476
+ return messageId;
2477
+ }
2478
+ prepMessageForSigning(messageParams) {
2479
+ return Promise.resolve(messageParams);
2480
+ }
2481
+ }
2482
+
2483
+ class TypedMessageController extends AbstractMessageController {
2484
+ constructor({
2485
+ config,
2486
+ state,
2487
+ signTypedData,
2488
+ getNetworkIdentifier
2489
+ }) {
2490
+ super({
2491
+ config,
2492
+ state
2493
+ });
2494
+ _defineProperty(this, "name", "TypedMessageController");
2495
+ _defineProperty(this, "signTypedData", void 0);
2496
+ _defineProperty(this, "getNetworkIdentifier", void 0);
2497
+ this.signTypedData = signTypedData;
2498
+ this.getNetworkIdentifier = getNetworkIdentifier;
2499
+ this.initialize();
2500
+ }
2501
+ async processSignTypedMessage(messageId) {
2703
2502
  const msgObject = this.getMessage(messageId);
2704
2503
  if (!msgObject) {
2705
2504
  throw new Error(`Message not found`);
2706
2505
  }
2707
2506
  try {
2708
2507
  const cleanMsgParams = await this.approveMessage(messageId, msgObject.messageParams);
2709
- const rawSig = await this.signPersonalMessage(cleanMsgParams.data, cleanMsgParams.from);
2508
+ const msgData = JSON.parse(cleanMsgParams.data);
2509
+ const rawSig = await this.signTypedData(msgData, cleanMsgParams.from);
2710
2510
  this.updateMessage(_objectSpread(_objectSpread({}, msgObject), {}, {
2711
2511
  rawSig
2712
2512
  }));
@@ -2723,18 +2523,21 @@ class PersonalMessageController extends AbstractMessageController {
2723
2523
  return this.waitForFinishStatus(messageParams, this.name);
2724
2524
  }
2725
2525
  async addUnapprovedMessage(messageParams, req) {
2726
- validateSignMessageData(messageParams);
2526
+ const currentChainId = this.getNetworkIdentifier();
2527
+ await validateTypedSignMessageDataV4(messageParams, currentChainId);
2528
+ if (typeof messageParams.data !== "string") {
2529
+ messageParams.data = JSON.stringify(messageParams.data);
2530
+ }
2727
2531
  if (req) {
2728
2532
  messageParams.origin = req.origin;
2729
2533
  }
2730
- messageParams.data = normalizeMessageData(messageParams.data);
2731
2534
  const messageId = messageParams.id || randomId();
2732
2535
  const messageData = {
2733
2536
  id: messageId,
2734
2537
  messageParams,
2735
2538
  status: MessageStatus.UNAPPROVED,
2736
2539
  time: Date.now(),
2737
- type: METHOD_TYPES.PERSONAL_SIGN
2540
+ type: METHOD_TYPES.ETH_SIGN_TYPED_DATA_V4
2738
2541
  };
2739
2542
  await this.addMessage(messageData);
2740
2543
  this.emit(MESSAGE_EVENTS.UNAPPROVED_MESSAGE, {
@@ -2748,770 +2551,1144 @@ class PersonalMessageController extends AbstractMessageController {
2748
2551
  }
2749
2552
  }
2750
2553
 
2751
- class SwitchChainController extends AbstractMessageController {
2752
- constructor({
2753
- config,
2754
- state,
2755
- getNetworkIdentifier,
2756
- switchChain
2757
- }) {
2758
- super({
2759
- config,
2760
- state,
2761
- getNetworkIdentifier
2762
- });
2763
- _defineProperty(this, "name", "SwitchChainController");
2764
- _defineProperty(this, "switchChain", void 0);
2765
- this.switchChain = switchChain;
2766
- this.initialize();
2554
+ function createGetAccountsMiddleware({
2555
+ getAccounts
2556
+ }) {
2557
+ return createAsyncMiddleware(async (request, response, next) => {
2558
+ const {
2559
+ method
2560
+ } = request;
2561
+ if (method !== METHOD_TYPES.GET_ACCOUNTS) return next();
2562
+ if (!getAccounts) throw new Error("WalletMiddleware - opts.getAccounts not provided");
2563
+ const accounts = await getAccounts(request);
2564
+ response.result = accounts;
2565
+ });
2566
+ }
2567
+ function createProcessTransactionMiddleware({
2568
+ processTransaction
2569
+ }) {
2570
+ return createAsyncMiddleware(async (request, response, next) => {
2571
+ const {
2572
+ method
2573
+ } = request;
2574
+ if (method !== METHOD_TYPES.ETH_TRANSACTION) return next();
2575
+ if (!processTransaction) throw new Error("WalletMiddleware - opts.processTransaction not provided");
2576
+ response.result = await processTransaction(request.params, request);
2577
+ });
2578
+ }
2579
+ function createProcessEthSignMessage({
2580
+ processEthSignMessage
2581
+ }) {
2582
+ return createAsyncMiddleware(async (request, response, next) => {
2583
+ const {
2584
+ method
2585
+ } = request;
2586
+ if (method !== METHOD_TYPES.ETH_SIGN) return next();
2587
+ if (!processEthSignMessage) throw new Error("WalletMiddleware - opts.processEthSignMessage not provided");
2588
+ if (!(request !== null && request !== void 0 && request.params)) throw new Error("WalletMiddleware - missing params");
2589
+ let msgParams = request.params;
2590
+ if (Array.isArray(request.params)) {
2591
+ if (!(request.params.length === 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [address, message]`);
2592
+ const params = request.params;
2593
+ const address = params[0];
2594
+ const message = params[1];
2595
+ msgParams = {
2596
+ from: address,
2597
+ data: message
2598
+ };
2599
+ }
2600
+ response.result = await processEthSignMessage(msgParams, request);
2601
+ });
2602
+ }
2603
+ function createProcessTypedMessageV4({
2604
+ processTypedMessageV4
2605
+ }) {
2606
+ return createAsyncMiddleware(async (request, response, next) => {
2607
+ const {
2608
+ method
2609
+ } = request;
2610
+ if (method !== METHOD_TYPES.ETH_SIGN_TYPED_DATA_V4) return next();
2611
+ if (!processTypedMessageV4) throw new Error("WalletMiddleware - opts.processTypedMessageV4 is not provided");
2612
+ if (!(request !== null && request !== void 0 && request.params)) throw new Error("WalletMiddleware - missing params");
2613
+ let msgParams = request.params;
2614
+ if (Array.isArray(request.params)) {
2615
+ if (!(request.params.length === 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [address, typedData]`);
2616
+ const params = request.params;
2617
+ const address = params[0];
2618
+ const message = params[1];
2619
+ msgParams = {
2620
+ from: address,
2621
+ data: message
2622
+ };
2623
+ }
2624
+ response.result = await processTypedMessageV4(msgParams, request);
2625
+ });
2626
+ }
2627
+ function createProcessPersonalMessage({
2628
+ processPersonalMessage
2629
+ }) {
2630
+ return createAsyncMiddleware(async (request, response, next) => {
2631
+ const {
2632
+ method
2633
+ } = request;
2634
+ if (method !== METHOD_TYPES.PERSONAL_SIGN) return next();
2635
+ if (!processPersonalMessage) throw new Error("WalletMiddleware - opts.processPersonalMessage is not provided");
2636
+ if (!(request !== null && request !== void 0 && request.params)) throw new Error("WalletMiddleware - missing params");
2637
+ let msgParams = request.params;
2638
+ if (Array.isArray(request.params)) {
2639
+ if (!(request.params.length >= 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [message, address]`);
2640
+ const params = request.params;
2641
+ if (typeof params[0] === "object") {
2642
+ const {
2643
+ challenge,
2644
+ address
2645
+ } = params[0];
2646
+ msgParams = {
2647
+ from: address,
2648
+ data: challenge
2649
+ };
2650
+ } else {
2651
+ const message = params[0];
2652
+ const address = params[1];
2653
+ msgParams = {
2654
+ from: address,
2655
+ data: message
2656
+ };
2657
+ }
2658
+ }
2659
+ response.result = await processPersonalMessage(msgParams, request);
2660
+ });
2661
+ }
2662
+ function createPendingNonceMiddleware({
2663
+ getPendingNonce
2664
+ }) {
2665
+ return createAsyncMiddleware(async (request, response, next) => {
2666
+ const {
2667
+ params,
2668
+ method
2669
+ } = request;
2670
+ if (method !== METHOD_TYPES.ETH_GET_TRANSACTION_COUNT) return next();
2671
+ const {
2672
+ blockReference
2673
+ } = params;
2674
+ if (blockReference !== "pending") return next();
2675
+ response.result = await getPendingNonce(params, request);
2676
+ });
2677
+ }
2678
+ function formatTxMetaForRpcResult(txMeta) {
2679
+ const {
2680
+ r,
2681
+ s,
2682
+ v,
2683
+ txReceipt,
2684
+ transaction,
2685
+ transactionHash,
2686
+ accessList
2687
+ } = txMeta;
2688
+ const {
2689
+ to,
2690
+ data,
2691
+ nonce,
2692
+ gas,
2693
+ from,
2694
+ value,
2695
+ gasPrice,
2696
+ maxFeePerGas,
2697
+ maxPriorityFeePerGas
2698
+ } = transaction;
2699
+ const formattedTxMeta = {
2700
+ v,
2701
+ r,
2702
+ s,
2703
+ to,
2704
+ gas,
2705
+ from,
2706
+ hash: transactionHash,
2707
+ nonce,
2708
+ input: data || "0x",
2709
+ value: value || "0x0",
2710
+ accessList: accessList || null,
2711
+ blockHash: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.blockHash) || null,
2712
+ blockNumber: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.blockNumber) || null,
2713
+ transactionIndex: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.transactionIndex) || null,
2714
+ type: null
2715
+ };
2716
+ if (maxFeePerGas && maxPriorityFeePerGas) {
2717
+ formattedTxMeta.maxFeePerGas = maxFeePerGas;
2718
+ formattedTxMeta.maxPriorityFeePerGas = maxPriorityFeePerGas;
2719
+ formattedTxMeta.type = TRANSACTION_ENVELOPE_TYPES.FEE_MARKET;
2720
+ } else {
2721
+ formattedTxMeta.gasPrice = gasPrice;
2722
+ formattedTxMeta.type = TRANSACTION_ENVELOPE_TYPES.LEGACY;
2767
2723
  }
2768
- async processSwitchChain(messageId) {
2769
- const msgObject = this.getMessage(messageId);
2770
- if (!msgObject) {
2771
- throw new Error(`Message not found`);
2724
+ return formattedTxMeta;
2725
+ }
2726
+ function createPendingTxMiddleware({
2727
+ getPendingTransactionByHash
2728
+ }) {
2729
+ return createAsyncMiddleware(async (request, response, next) => {
2730
+ const {
2731
+ params,
2732
+ method
2733
+ } = request;
2734
+ if (method !== METHOD_TYPES.ETH_GET_TRANSACTION_BY_HASH) return next();
2735
+ if (!getPendingTransactionByHash) throw new Error("WalletMiddleware - opts.getPendingTransactionByHash not provided");
2736
+ const txMeta = await getPendingTransactionByHash(params, request);
2737
+ if (!txMeta) {
2738
+ return next();
2772
2739
  }
2773
- try {
2774
- await this.approveMessage(messageId, msgObject.messageParams);
2775
- this.switchChain({
2776
- chainId: msgObject.messageParams.chainId
2777
- });
2778
- this.updateMessage(_objectSpread(_objectSpread({}, msgObject), {}, {
2779
- rawSig: JSON.stringify(msgObject.messageParams)
2780
- }));
2781
- this.setMessageStatus(messageId, MessageStatus.SIGNED);
2782
- return null;
2783
- } catch (error) {
2784
- log.error(error);
2785
- msgObject.error = (error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.toString());
2786
- this.setMessageStatus(messageId, MessageStatus.FAILED);
2740
+ response.result = formatTxMetaForRpcResult(txMeta);
2741
+ return undefined;
2742
+ });
2743
+ }
2744
+ function createProcessSwitchEthereumChain({
2745
+ processSwitchEthereumChain
2746
+ }) {
2747
+ return createAsyncMiddleware(async (request, response, next) => {
2748
+ const {
2749
+ method
2750
+ } = request;
2751
+ if (method !== METHOD_TYPES.SWITCH_CHAIN) return next();
2752
+ if (!processSwitchEthereumChain) throw new Error("WalletMiddleware - opts.processSwitchEthereumChain not provided");
2753
+ if (!(request !== null && request !== void 0 && request.params)) throw new Error("WalletMiddleware - missing params");
2754
+ let msgParams = request.params;
2755
+ if (Array.isArray(request.params)) {
2756
+ if (!(request.params.length === 1)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [data]`);
2757
+ const [message] = request.params;
2758
+ msgParams = message;
2787
2759
  }
2788
- }
2789
- async addNewUnapprovedMessage(messageParams, req) {
2790
- await this.addUnapprovedMessage(messageParams, req);
2791
- return this.waitForFinishStatus(messageParams, this.name);
2792
- }
2793
- async addUnapprovedMessage(messageParams, req) {
2794
- validateSwitchChainData(messageParams);
2795
- if (req) {
2796
- messageParams.origin = req.origin;
2760
+ response.result = await processSwitchEthereumChain(msgParams, request);
2761
+ });
2762
+ }
2763
+ function createProcessAddEthereumChain({
2764
+ processAddEthereumChain
2765
+ }) {
2766
+ return createAsyncMiddleware(async (request, response, next) => {
2767
+ const {
2768
+ method
2769
+ } = request;
2770
+ if (method !== METHOD_TYPES.ADD_CHAIN) return next();
2771
+ if (!processAddEthereumChain) throw new Error("WalletMiddleware - opts.processAddEthereumChain not provided");
2772
+ if (!(request !== null && request !== void 0 && request.params)) throw new Error("WalletMiddleware - missing params");
2773
+ let msgParams = request.params;
2774
+ if (Array.isArray(request.params)) {
2775
+ if (!(request.params.length === 1)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [data]`);
2776
+ const [message] = request.params;
2777
+ msgParams = message;
2797
2778
  }
2798
- const messageId = messageParams.id || randomId();
2799
- const messageData = {
2800
- id: messageId,
2801
- messageParams,
2802
- status: MessageStatus.UNAPPROVED,
2803
- time: Date.now(),
2804
- type: METHOD_TYPES.SWITCH_CHAIN
2805
- };
2806
- await this.addMessage(messageData);
2807
- this.emit(MESSAGE_EVENTS.UNAPPROVED_MESSAGE, {
2808
- messageData,
2809
- req
2810
- });
2811
- return messageId;
2812
- }
2813
- prepMessageForSigning(messageParams) {
2814
- return Promise.resolve(messageParams);
2779
+ response.result = await processAddEthereumChain(msgParams, request);
2780
+ });
2781
+ }
2782
+ function createRequestAccountsMiddleware({
2783
+ requestAccounts
2784
+ }) {
2785
+ return createAsyncMiddleware(async (request, response, next) => {
2786
+ const {
2787
+ method
2788
+ } = request;
2789
+ if (method !== "eth_requestAccounts") return next();
2790
+ if (!requestAccounts) throw new Error("WalletMiddleware - opts.requestAccounts not provided");
2791
+ // This calls the UI login function
2792
+ const accounts = await requestAccounts(request);
2793
+ response.result = accounts;
2794
+ return undefined;
2795
+ });
2796
+ }
2797
+ function createEthereumMiddleware(providerHandlers) {
2798
+ const {
2799
+ requestAccounts,
2800
+ getAccounts,
2801
+ processTransaction,
2802
+ processEthSignMessage,
2803
+ processTypedMessageV4,
2804
+ processPersonalMessage,
2805
+ getPendingNonce,
2806
+ getPendingTransactionByHash,
2807
+ processSwitchEthereumChain,
2808
+ processAddEthereumChain,
2809
+ getProviderState,
2810
+ version
2811
+ } = providerHandlers;
2812
+ return mergeMiddleware([createScaffoldMiddleware({
2813
+ version,
2814
+ [PROVIDER_JRPC_METHODS.GET_PROVIDER_STATE]: getProviderState
2815
+ }), createRequestAccountsMiddleware({
2816
+ requestAccounts
2817
+ }), createGetAccountsMiddleware({
2818
+ getAccounts
2819
+ }), createProcessTransactionMiddleware({
2820
+ processTransaction
2821
+ }), createProcessEthSignMessage({
2822
+ processEthSignMessage
2823
+ }), createProcessTypedMessageV4({
2824
+ processTypedMessageV4
2825
+ }), createProcessPersonalMessage({
2826
+ processPersonalMessage
2827
+ }), createPendingNonceMiddleware({
2828
+ getPendingNonce
2829
+ }), createPendingTxMiddleware({
2830
+ getPendingTransactionByHash
2831
+ }), createProcessSwitchEthereumChain({
2832
+ processSwitchEthereumChain
2833
+ }), createProcessAddEthereumChain({
2834
+ processAddEthereumChain
2835
+ })]);
2836
+ }
2837
+
2838
+ let CacheStrategy = /*#__PURE__*/function (CacheStrategy) {
2839
+ CacheStrategy["Block"] = "block";
2840
+ CacheStrategy["Fork"] = "fork";
2841
+ CacheStrategy["Never"] = "never";
2842
+ CacheStrategy["Permanent"] = "perma";
2843
+ return CacheStrategy;
2844
+ }({});
2845
+ function blockTagParamIndex(method) {
2846
+ switch (method) {
2847
+ // blockTag is at index 2
2848
+ case "eth_getStorageAt":
2849
+ return 2;
2850
+ // blockTag is at index 1
2851
+ case "eth_getBalance":
2852
+ case "eth_getCode":
2853
+ case "eth_getTransactionCount":
2854
+ case "eth_call":
2855
+ return 1;
2856
+ // blockTag is at index 0
2857
+ case "eth_getBlockByNumber":
2858
+ return 0;
2859
+ // there is no blockTag
2860
+ default:
2861
+ return undefined;
2815
2862
  }
2816
2863
  }
2864
+ function cacheTypeForMethod(method) {
2865
+ switch (method) {
2866
+ // cache permanently
2867
+ case "web3_clientVersion":
2868
+ case "web3_sha3":
2869
+ case "eth_protocolVersion":
2870
+ case "eth_getBlockTransactionCountByHash":
2871
+ case "eth_getUncleCountByBlockHash":
2872
+ case "eth_getCode":
2873
+ case "eth_getBlockByHash":
2874
+ case "eth_getTransactionByHash":
2875
+ case "eth_getTransactionByBlockHashAndIndex":
2876
+ case "eth_getTransactionReceipt":
2877
+ case "eth_getUncleByBlockHashAndIndex":
2878
+ case "eth_getCompilers":
2879
+ case "eth_compileLLL":
2880
+ case "eth_compileSolidity":
2881
+ case "eth_compileSerpent":
2882
+ case "shh_version":
2883
+ case "test_permaCache":
2884
+ return CacheStrategy.Permanent;
2817
2885
 
2818
- class TypedMessageController extends AbstractMessageController {
2819
- constructor({
2820
- config,
2821
- state,
2822
- signTypedData,
2823
- getNetworkIdentifier
2824
- }) {
2825
- super({
2826
- config,
2827
- state,
2828
- getNetworkIdentifier
2829
- });
2830
- _defineProperty(this, "name", "TypedMessageController");
2831
- _defineProperty(this, "signTypedData", void 0);
2832
- this.signTypedData = signTypedData;
2833
- this.initialize();
2886
+ // cache until fork
2887
+ case "eth_getBlockByNumber":
2888
+ case "eth_getBlockTransactionCountByNumber":
2889
+ case "eth_getUncleCountByBlockNumber":
2890
+ case "eth_getTransactionByBlockNumberAndIndex":
2891
+ case "eth_getUncleByBlockNumberAndIndex":
2892
+ case "test_forkCache":
2893
+ return CacheStrategy.Fork;
2894
+
2895
+ // cache for block
2896
+ case "eth_gasPrice":
2897
+ case "eth_blockNumber":
2898
+ case "eth_getBalance":
2899
+ case "eth_getStorageAt":
2900
+ case "eth_getTransactionCount":
2901
+ case "eth_call":
2902
+ case "eth_estimateGas":
2903
+ case "eth_getFilterLogs":
2904
+ case "eth_getLogs":
2905
+ case "test_blockCache":
2906
+ return CacheStrategy.Block;
2907
+
2908
+ // never cache
2909
+ default:
2910
+ return CacheStrategy.Never;
2834
2911
  }
2835
- async processSignTypedMessage(messageId) {
2836
- const msgObject = this.getMessage(messageId);
2837
- if (!msgObject) {
2838
- throw new Error(`Message not found`);
2839
- }
2840
- try {
2841
- const cleanMsgParams = await this.approveMessage(messageId, msgObject.messageParams);
2842
- const msgData = JSON.parse(cleanMsgParams.data);
2843
- const rawSig = await this.signTypedData(msgData, cleanMsgParams.from);
2844
- this.updateMessage(_objectSpread(_objectSpread({}, msgObject), {}, {
2845
- rawSig
2846
- }));
2847
- this.setMessageStatus(messageId, MessageStatus.SIGNED);
2848
- return rawSig;
2849
- } catch (error) {
2850
- log.error(error);
2851
- msgObject.error = (error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.toString());
2852
- this.setMessageStatus(messageId, MessageStatus.FAILED);
2853
- }
2912
+ }
2913
+ function canCache(method) {
2914
+ return cacheTypeForMethod(method) !== CacheStrategy.Never;
2915
+ }
2916
+ function paramsWithoutBlockTag(request) {
2917
+ if (!request.params) {
2918
+ return [];
2854
2919
  }
2855
- async addNewUnapprovedMessage(messageParams, req) {
2856
- await this.addUnapprovedMessage(messageParams, req);
2857
- return this.waitForFinishStatus(messageParams, this.name);
2920
+ const index = blockTagParamIndex(request.method);
2921
+
2922
+ // Block tag param not passed.
2923
+ if (index === undefined || !Array.isArray(request.params) || index >= request.params.length) {
2924
+ return request.params;
2858
2925
  }
2859
- async addUnapprovedMessage(messageParams, req) {
2860
- const currentChainId = this.getNetworkIdentifier();
2861
- await validateTypedSignMessageDataV4(messageParams, currentChainId);
2862
- if (typeof messageParams.data !== "string") {
2863
- messageParams.data = JSON.stringify(messageParams.data);
2864
- }
2865
- if (req) {
2866
- messageParams.origin = req.origin;
2867
- }
2868
- const messageId = messageParams.id || randomId();
2869
- const messageData = {
2870
- id: messageId,
2871
- messageParams,
2872
- status: MessageStatus.UNAPPROVED,
2873
- time: Date.now(),
2874
- type: METHOD_TYPES.ETH_SIGN_TYPED_DATA_V4
2875
- };
2876
- await this.addMessage(messageData);
2877
- this.emit(MESSAGE_EVENTS.UNAPPROVED_MESSAGE, {
2878
- messageData,
2879
- req
2880
- });
2881
- return messageId;
2926
+
2927
+ // eth_getBlockByNumber has the block tag first, then the optional includeTx? param
2928
+ if (request.method === "eth_getBlockByNumber") {
2929
+ return request.params.slice(1);
2882
2930
  }
2883
- prepMessageForSigning(messageParams) {
2884
- return Promise.resolve(messageParams);
2931
+ return request.params.slice(0, index);
2932
+ }
2933
+ function cacheIdentifierForRequest(request, skipBlockRef) {
2934
+ var _request$params;
2935
+ const simpleParams = skipBlockRef ? paramsWithoutBlockTag(request) : (_request$params = request.params) !== null && _request$params !== void 0 ? _request$params : [];
2936
+ if (canCache(request.method)) {
2937
+ return `${request.method}:${stringify(simpleParams)}`;
2885
2938
  }
2939
+ return null;
2886
2940
  }
2887
2941
 
2888
- function createGetAccountsMiddleware({
2889
- getAccounts
2890
- }) {
2891
- return createAsyncMiddleware(async (request, response, next) => {
2892
- const {
2893
- method
2894
- } = request;
2895
- if (method !== METHOD_TYPES.GET_ACCOUNTS) return next();
2896
- if (!getAccounts) throw new Error("WalletMiddleware - opts.getAccounts not provided");
2897
- const accounts = await getAccounts(request);
2898
- response.result = accounts;
2899
- });
2900
- }
2901
- function createProcessTransactionMiddleware({
2902
- processTransaction
2903
- }) {
2904
- return createAsyncMiddleware(async (request, response, next) => {
2905
- const {
2906
- method
2907
- } = request;
2908
- if (method !== METHOD_TYPES.ETH_TRANSACTION) return next();
2909
- if (!processTransaction) throw new Error("WalletMiddleware - opts.processTransaction not provided");
2910
- response.result = await processTransaction(request.params, request);
2911
- });
2912
- }
2913
- function createProcessEthSignMessage({
2914
- processEthSignMessage
2915
- }) {
2916
- return createAsyncMiddleware(async (request, response, next) => {
2917
- const {
2918
- method
2919
- } = request;
2920
- if (method !== METHOD_TYPES.ETH_SIGN) return next();
2921
- if (!processEthSignMessage) throw new Error("WalletMiddleware - opts.processEthSignMessage not provided");
2922
- if (!(request !== null && request !== void 0 && request.params)) throw new Error("WalletMiddleware - missing params");
2923
- let msgParams = request.params;
2924
- if (Array.isArray(request.params)) {
2925
- if (!(request.params.length === 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [address, message]`);
2926
- const params = request.params;
2927
- const address = params[0];
2928
- const message = params[1];
2929
- msgParams = {
2930
- from: address,
2931
- data: message
2932
- };
2942
+ function createChainIdMiddleware(chainId) {
2943
+ return (req, res, next, end) => {
2944
+ if (req.method === "eth_chainId") {
2945
+ res.result = chainId;
2946
+ return end();
2933
2947
  }
2934
- response.result = await processEthSignMessage(msgParams, request);
2935
- });
2936
- }
2937
- function createProcessTypedMessageV4({
2938
- processTypedMessageV4
2939
- }) {
2940
- return createAsyncMiddleware(async (request, response, next) => {
2941
- const {
2942
- method
2943
- } = request;
2944
- if (method !== METHOD_TYPES.ETH_SIGN_TYPED_DATA_V4) return next();
2945
- if (!processTypedMessageV4) throw new Error("WalletMiddleware - opts.processTypedMessageV4 is not provided");
2946
- if (!(request !== null && request !== void 0 && request.params)) throw new Error("WalletMiddleware - missing params");
2947
- let msgParams = request.params;
2948
- if (Array.isArray(request.params)) {
2949
- if (!(request.params.length === 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [address, typedData]`);
2950
- const params = request.params;
2951
- const address = params[0];
2952
- const message = params[1];
2953
- msgParams = {
2954
- from: address,
2955
- data: message
2956
- };
2948
+ if (req.method === "net_version") {
2949
+ // convert to decimal
2950
+ res.result = Number.parseInt(chainId, 16).toString(10);
2951
+ return end();
2957
2952
  }
2958
- response.result = await processTypedMessageV4(msgParams, request);
2959
- });
2953
+ return next();
2954
+ };
2960
2955
  }
2961
- function createProcessPersonalMessage({
2962
- processPersonalMessage
2963
- }) {
2964
- return createAsyncMiddleware(async (request, response, next) => {
2965
- const {
2966
- method
2967
- } = request;
2968
- if (method !== METHOD_TYPES.PERSONAL_SIGN) return next();
2969
- if (!processPersonalMessage) throw new Error("WalletMiddleware - opts.processPersonalMessage is not provided");
2970
- if (!(request !== null && request !== void 0 && request.params)) throw new Error("WalletMiddleware - missing params");
2971
- let msgParams = request.params;
2972
- if (Array.isArray(request.params)) {
2973
- if (!(request.params.length >= 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [message, address]`);
2974
- const params = request.params;
2975
- if (typeof params[0] === "object") {
2976
- const {
2977
- challenge,
2978
- address
2979
- } = params[0];
2980
- msgParams = {
2981
- from: address,
2982
- data: challenge
2983
- };
2984
- } else {
2985
- const message = params[0];
2986
- const address = params[1];
2987
- msgParams = {
2988
- from: address,
2989
- data: message
2990
- };
2991
- }
2956
+ function createProviderConfigMiddleware(providerConfig) {
2957
+ return (req, res, next, end) => {
2958
+ if (req.method === "eth_provider_config") {
2959
+ res.result = providerConfig;
2960
+ return end();
2992
2961
  }
2993
- response.result = await processPersonalMessage(msgParams, request);
2994
- });
2995
- }
2996
- function createPendingNonceMiddleware({
2997
- getPendingNonce
2998
- }) {
2999
- return createAsyncMiddleware(async (request, response, next) => {
3000
- const {
3001
- params,
3002
- method
3003
- } = request;
3004
- if (method !== METHOD_TYPES.ETH_GET_TRANSACTION_COUNT) return next();
3005
- const {
3006
- blockReference
3007
- } = params;
3008
- if (blockReference !== "pending") return next();
3009
- response.result = await getPendingNonce(params, request);
3010
- });
2962
+ return next();
2963
+ };
3011
2964
  }
3012
- function formatTxMetaForRpcResult(txMeta) {
3013
- const {
3014
- r,
3015
- s,
3016
- v,
3017
- txReceipt,
3018
- transaction,
3019
- transactionHash,
3020
- accessList
3021
- } = txMeta;
2965
+ function createJsonRpcClient(providerConfig, networkConfig) {
3022
2966
  const {
3023
- to,
3024
- data,
3025
- nonce,
3026
- gas,
3027
- from,
3028
- value,
3029
- gasPrice,
3030
- maxFeePerGas,
3031
- maxPriorityFeePerGas
3032
- } = transaction;
3033
- const formattedTxMeta = {
3034
- v,
3035
- r,
3036
- s,
3037
- to,
3038
- gas,
3039
- from,
3040
- hash: transactionHash,
3041
- nonce,
3042
- input: data || "0x",
3043
- value: value || "0x0",
3044
- accessList: accessList || null,
3045
- blockHash: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.blockHash) || null,
3046
- blockNumber: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.blockNumber) || null,
3047
- transactionIndex: (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.transactionIndex) || null,
3048
- type: null
2967
+ chainId,
2968
+ rpcTarget
2969
+ } = providerConfig;
2970
+ const fetchMiddleware = createFetchMiddleware({
2971
+ rpcTarget
2972
+ });
2973
+ const blockProvider = providerFromMiddleware(fetchMiddleware);
2974
+ const blockTracker = new PollingBlockTracker({
2975
+ config: _objectSpread(_objectSpread({}, networkConfig), {}, {
2976
+ provider: blockProvider
2977
+ }),
2978
+ state: {}
2979
+ });
2980
+ const networkMiddleware = mergeMiddleware([createChainIdMiddleware(chainId), createProviderConfigMiddleware(providerConfig),
2981
+ // No need for the following middlewares for web because all browser sessions are quite short lived and each session is limited to scope of a window/tab
2982
+ // createBlockRefRewriteMiddleware({ blockTracker }),
2983
+ // createBlockCacheMiddleware({ blockTracker }),
2984
+ createInflightCacheMiddleware({
2985
+ cacheIdentifierForRequest
2986
+ }),
2987
+ // createBlockTrackerInspectorMiddleware({ blockTracker }),
2988
+ fetchMiddleware]);
2989
+ return {
2990
+ networkMiddleware,
2991
+ blockTracker
3049
2992
  };
3050
- if (maxFeePerGas && maxPriorityFeePerGas) {
3051
- formattedTxMeta.maxFeePerGas = maxFeePerGas;
3052
- formattedTxMeta.maxPriorityFeePerGas = maxPriorityFeePerGas;
3053
- formattedTxMeta.type = TRANSACTION_ENVELOPE_TYPES.FEE_MARKET;
3054
- } else {
3055
- formattedTxMeta.gasPrice = gasPrice;
3056
- formattedTxMeta.type = TRANSACTION_ENVELOPE_TYPES.LEGACY;
2993
+ }
2994
+
2995
+ const _excluded = ["chainId", "rpcTarget"];
2996
+ class NetworkController extends BaseController {
2997
+ constructor({
2998
+ config,
2999
+ state
3000
+ }) {
3001
+ super({
3002
+ config,
3003
+ state
3004
+ });
3005
+ _defineProperty(this, "name", "NetworkController");
3006
+ _defineProperty(this, "providerProxy", void 0);
3007
+ _defineProperty(this, "blockTrackerProxy", void 0);
3008
+ _defineProperty(this, "mutex", new Mutex());
3009
+ _defineProperty(this, "provider", null);
3010
+ _defineProperty(this, "blockTracker", null);
3011
+ _defineProperty(this, "baseProviderHandlers", void 0);
3012
+ this.defaultState = {
3013
+ chainId: "loading",
3014
+ properties: {
3015
+ EIPS_1559: undefined
3016
+ },
3017
+ providerConfig: SUPPORTED_NETWORKS[MAINNET_CHAIN_ID]
3018
+ };
3019
+
3020
+ // when a new network is set,
3021
+ // we set to loading first and
3022
+ // then when connection succeeds,
3023
+ // we update the network
3024
+ this.initialize();
3025
+ }
3026
+ getNetworkIdentifier() {
3027
+ return this.state.chainId;
3028
+ }
3029
+ getNetworkRPCUrl() {
3030
+ return this.state.providerConfig.rpcTarget;
3031
+ }
3032
+
3033
+ /**
3034
+ * Called by orchestrator once while initializing the class
3035
+ * @param providerHandlers - JRPC handlers for provider
3036
+ * @returns - provider - Returns the providerProxy
3037
+ */
3038
+ initializeProvider(providerHandlers) {
3039
+ this.baseProviderHandlers = providerHandlers;
3040
+ this.configureProvider();
3041
+ this.lookupNetwork(); // Not awaiting this, because we don't want to block the initialization
3042
+ return this.providerProxy;
3057
3043
  }
3058
- return formattedTxMeta;
3059
- }
3060
- function createPendingTxMiddleware({
3061
- getPendingTransactionByHash
3062
- }) {
3063
- return createAsyncMiddleware(async (request, response, next) => {
3044
+ getProvider() {
3045
+ return this.providerProxy;
3046
+ }
3047
+ getBlockTracker() {
3048
+ return this.blockTrackerProxy;
3049
+ }
3050
+ getProviderConfig() {
3051
+ return this.state.providerConfig;
3052
+ }
3053
+ setProviderConfig(config) {
3054
+ this.update({
3055
+ providerConfig: _objectSpread({}, config)
3056
+ });
3057
+ this.refreshNetwork();
3058
+ }
3059
+ async getEIP1559Compatibility() {
3064
3060
  const {
3065
- params,
3066
- method
3067
- } = request;
3068
- if (method !== METHOD_TYPES.ETH_GET_TRANSACTION_BY_HASH) return next();
3069
- if (!getPendingTransactionByHash) throw new Error("WalletMiddleware - opts.getPendingTransactionByHash not provided");
3070
- const txMeta = await getPendingTransactionByHash(params, request);
3071
- if (!txMeta) {
3072
- return next();
3061
+ EIPS_1559
3062
+ } = this.state.properties;
3063
+ // log.info('checking eip 1559 compatibility')
3064
+ if (EIPS_1559 !== undefined) {
3065
+ return EIPS_1559;
3073
3066
  }
3074
- response.result = formatTxMetaForRpcResult(txMeta);
3075
- return undefined;
3076
- });
3077
- }
3078
- function createProcessSwitchEthereumChain({
3079
- processSwitchEthereumChain
3080
- }) {
3081
- return createAsyncMiddleware(async (request, response, next) => {
3067
+ const latestBlock = await this.blockTracker.getLatestBlock();
3068
+ const supportsEIP1559 = latestBlock && latestBlock.baseFeePerGas !== undefined;
3069
+ this.update({
3070
+ properties: {
3071
+ EIPS_1559: supportsEIP1559
3072
+ }
3073
+ });
3074
+ return supportsEIP1559;
3075
+ }
3076
+
3077
+ /**
3078
+ * Refreshes the current network code
3079
+ */
3080
+ async lookupNetwork() {
3082
3081
  const {
3083
- method
3084
- } = request;
3085
- if (method !== METHOD_TYPES.SWITCH_CHAIN) return next();
3086
- if (!processSwitchEthereumChain) throw new Error("WalletMiddleware - opts.processSwitchEthereumChain not provided");
3087
- if (!(request !== null && request !== void 0 && request.params)) throw new Error("WalletMiddleware - missing params");
3088
- let msgParams = request.params;
3089
- if (Array.isArray(request.params)) {
3090
- if (!(request.params.length === 1)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [data]`);
3091
- const [message] = request.params;
3092
- msgParams = message;
3082
+ chainId,
3083
+ rpcTarget
3084
+ } = this.getProviderConfig();
3085
+ if (!chainId || !rpcTarget || !this.provider) {
3086
+ this.update({
3087
+ chainId: "loading",
3088
+ properties: {}
3089
+ });
3090
+ return;
3093
3091
  }
3094
- response.result = await processSwitchEthereumChain(msgParams, request);
3095
- });
3096
- }
3097
- function createProcessAddEthereumChain({
3098
- processAddEthereumChain
3099
- }) {
3100
- return createAsyncMiddleware(async (request, response, next) => {
3101
- const {
3102
- method
3103
- } = request;
3104
- if (method !== METHOD_TYPES.ADD_CHAIN) return next();
3105
- if (!processAddEthereumChain) throw new Error("WalletMiddleware - opts.processAddEthereumChain not provided");
3106
- if (!(request !== null && request !== void 0 && request.params)) throw new Error("WalletMiddleware - missing params");
3107
- let msgParams = request.params;
3108
- if (Array.isArray(request.params)) {
3109
- if (!(request.params.length === 1)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [data]`);
3110
- const [message] = request.params;
3111
- msgParams = message;
3092
+ const releaseLock = await this.mutex.acquire();
3093
+ try {
3094
+ // use eth_chainId
3095
+ const [networkChainId] = await Promise.all([this.provider.request({
3096
+ method: "eth_chainId"
3097
+ }), this.getEIP1559Compatibility()]);
3098
+ log.info("network fetched chain id", networkChainId);
3099
+ // update chain ID
3100
+ this.update({
3101
+ chainId: networkChainId
3102
+ });
3103
+ this.emit("networkDidChange");
3104
+ } catch {
3105
+ this.update({
3106
+ chainId: "loading"
3107
+ });
3108
+ } finally {
3109
+ releaseLock();
3110
+ }
3111
+ }
3112
+ configureProvider() {
3113
+ const _this$getProviderConf = this.getProviderConfig(),
3114
+ {
3115
+ chainId,
3116
+ rpcTarget
3117
+ } = _this$getProviderConf,
3118
+ rest = _objectWithoutProperties(_this$getProviderConf, _excluded);
3119
+ if (!chainId || !rpcTarget) {
3120
+ throw new Error("chainId and rpcTarget must be provider in providerConfig");
3121
+ }
3122
+ this.configureStandardProvider(_objectSpread({
3123
+ chainId,
3124
+ rpcTarget
3125
+ }, rest));
3126
+ }
3127
+ setNetworkClient({
3128
+ networkMiddleware,
3129
+ blockTracker
3130
+ }) {
3131
+ const ethereumMiddleware = createEthereumMiddleware(this.baseProviderHandlers);
3132
+ const engine = new JRPCEngine();
3133
+ engine.push(ethereumMiddleware);
3134
+ engine.push(networkMiddleware);
3135
+ const provider = providerFromEngine(engine);
3136
+ this.setProvider({
3137
+ provider,
3138
+ blockTracker
3139
+ });
3140
+ }
3141
+ setProvider({
3142
+ provider,
3143
+ blockTracker
3144
+ }) {
3145
+ if (this.providerProxy) {
3146
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3147
+ // @ts-ignore
3148
+ this.providerProxy.setTarget(provider);
3149
+ } else {
3150
+ this.providerProxy = createSwappableProxy(provider);
3151
+ }
3152
+ if (this.blockTrackerProxy) {
3153
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3154
+ // @ts-ignore
3155
+ this.blockTrackerProxy.setTarget(blockTracker);
3156
+ } else {
3157
+ this.blockTrackerProxy = createEventEmitterProxy(blockTracker, {
3158
+ eventFilter: "skipInternal"
3159
+ });
3112
3160
  }
3113
- response.result = await processAddEthereumChain(msgParams, request);
3114
- });
3115
- }
3116
- function createRequestAccountsMiddleware({
3117
- requestAccounts
3118
- }) {
3119
- return createAsyncMiddleware(async (request, response, next) => {
3120
- const {
3121
- method
3122
- } = request;
3123
- if (method !== "eth_requestAccounts") return next();
3124
- if (!requestAccounts) throw new Error("WalletMiddleware - opts.requestAccounts not provided");
3125
- // This calls the UI login function
3126
- const accounts = await requestAccounts(request);
3127
- response.result = accounts;
3128
- return undefined;
3129
- });
3130
- }
3131
- function createEthereumMiddleware(providerHandlers) {
3132
- const {
3133
- requestAccounts,
3134
- getAccounts,
3135
- processTransaction,
3136
- processEthSignMessage,
3137
- processTypedMessageV4,
3138
- processPersonalMessage,
3139
- getPendingNonce,
3140
- getPendingTransactionByHash,
3141
- processSwitchEthereumChain,
3142
- processAddEthereumChain,
3143
- getProviderState,
3144
- version
3145
- } = providerHandlers;
3146
- return mergeMiddleware([createScaffoldMiddleware({
3147
- version,
3148
- [PROVIDER_JRPC_METHODS.GET_PROVIDER_STATE]: getProviderState
3149
- }), createRequestAccountsMiddleware({
3150
- requestAccounts
3151
- }), createGetAccountsMiddleware({
3152
- getAccounts
3153
- }), createProcessTransactionMiddleware({
3154
- processTransaction
3155
- }), createProcessEthSignMessage({
3156
- processEthSignMessage
3157
- }), createProcessTypedMessageV4({
3158
- processTypedMessageV4
3159
- }), createProcessPersonalMessage({
3160
- processPersonalMessage
3161
- }), createPendingNonceMiddleware({
3162
- getPendingNonce
3163
- }), createPendingTxMiddleware({
3164
- getPendingTransactionByHash
3165
- }), createProcessSwitchEthereumChain({
3166
- processSwitchEthereumChain
3167
- }), createProcessAddEthereumChain({
3168
- processAddEthereumChain
3169
- })]);
3170
- }
3171
3161
 
3172
- let CacheStrategy = /*#__PURE__*/function (CacheStrategy) {
3173
- CacheStrategy["Block"] = "block";
3174
- CacheStrategy["Fork"] = "fork";
3175
- CacheStrategy["Never"] = "never";
3176
- CacheStrategy["Permanent"] = "perma";
3177
- return CacheStrategy;
3178
- }({});
3179
- function blockTagParamIndex(method) {
3180
- switch (method) {
3181
- // blockTag is at index 2
3182
- case "eth_getStorageAt":
3183
- return 2;
3184
- // blockTag is at index 1
3185
- case "eth_getBalance":
3186
- case "eth_getCode":
3187
- case "eth_getTransactionCount":
3188
- case "eth_call":
3189
- return 1;
3190
- // blockTag is at index 0
3191
- case "eth_getBlockByNumber":
3192
- return 0;
3193
- // there is no blockTag
3194
- default:
3195
- return undefined;
3162
+ // set new provider and blockTracker
3163
+ this.provider = provider;
3164
+ provider.setMaxListeners(10);
3165
+ this.blockTracker = blockTracker;
3166
+ }
3167
+ configureStandardProvider(providerConfig) {
3168
+ const networkClient = createJsonRpcClient(providerConfig, this.config);
3169
+ log.info("networkClient", networkClient);
3170
+ this.setNetworkClient(networkClient);
3171
+ }
3172
+ refreshNetwork() {
3173
+ this.update({
3174
+ chainId: "loading",
3175
+ properties: {}
3176
+ });
3177
+ this.configureProvider();
3178
+ this.lookupNetwork();
3196
3179
  }
3197
3180
  }
3198
- function cacheTypeForMethod(method) {
3199
- switch (method) {
3200
- // cache permanently
3201
- case "web3_clientVersion":
3202
- case "web3_sha3":
3203
- case "eth_protocolVersion":
3204
- case "eth_getBlockTransactionCountByHash":
3205
- case "eth_getUncleCountByBlockHash":
3206
- case "eth_getCode":
3207
- case "eth_getBlockByHash":
3208
- case "eth_getTransactionByHash":
3209
- case "eth_getTransactionByBlockHashAndIndex":
3210
- case "eth_getTransactionReceipt":
3211
- case "eth_getUncleByBlockHashAndIndex":
3212
- case "eth_getCompilers":
3213
- case "eth_compileLLL":
3214
- case "eth_compileSolidity":
3215
- case "eth_compileSerpent":
3216
- case "shh_version":
3217
- case "test_permaCache":
3218
- return CacheStrategy.Permanent;
3219
-
3220
- // cache until fork
3221
- case "eth_getBlockByNumber":
3222
- case "eth_getBlockTransactionCountByNumber":
3223
- case "eth_getUncleCountByBlockNumber":
3224
- case "eth_getTransactionByBlockNumberAndIndex":
3225
- case "eth_getUncleByBlockNumberAndIndex":
3226
- case "test_forkCache":
3227
- return CacheStrategy.Fork;
3228
3181
 
3229
- // cache for block
3230
- case "eth_gasPrice":
3231
- case "eth_blockNumber":
3232
- case "eth_getBalance":
3233
- case "eth_getStorageAt":
3234
- case "eth_getTransactionCount":
3235
- case "eth_call":
3236
- case "eth_estimateGas":
3237
- case "eth_getFilterLogs":
3238
- case "eth_getLogs":
3239
- case "test_blockCache":
3240
- return CacheStrategy.Block;
3182
+ const erc20Interface = new Interface(erc20Abi);
3183
+ const erc721Interface = new Interface(erc721Abi);
3184
+ const erc1155Interface = new Interface(erc1155Abi);
3241
3185
 
3242
- // never cache
3243
- default:
3244
- return CacheStrategy.Never;
3245
- }
3246
- }
3247
- function canCache(method) {
3248
- return cacheTypeForMethod(method) !== CacheStrategy.Never;
3249
- }
3250
- function paramsWithoutBlockTag(request) {
3251
- if (!request.params) {
3252
- return [];
3253
- }
3254
- const index = blockTagParamIndex(request.method);
3186
+ // functions that handle normalizing of that key in txParams
3255
3187
 
3256
- // Block tag param not passed.
3257
- if (index === undefined || !Array.isArray(request.params) || index >= request.params.length) {
3258
- return request.params;
3259
- }
3188
+ const normalizers = {
3189
+ from: (from, LowerCase = true) => LowerCase ? addHexPrefix(from).toLowerCase() : addHexPrefix(from),
3190
+ to: (to, LowerCase = true) => LowerCase ? addHexPrefix(to).toLowerCase() : addHexPrefix(to),
3191
+ nonce: nonce => addHexPrefix(nonce),
3192
+ customNonceValue: nonce => addHexPrefix(nonce),
3193
+ value: value => addHexPrefix(value),
3194
+ data: data => addHexPrefix(data),
3195
+ gas: gas => addHexPrefix(gas),
3196
+ gasPrice: gasPrice => addHexPrefix(gasPrice),
3197
+ type: addHexPrefix,
3198
+ maxFeePerGas: addHexPrefix,
3199
+ maxPriorityFeePerGas: addHexPrefix
3200
+ };
3260
3201
 
3261
- // eth_getBlockByNumber has the block tag first, then the optional includeTx? param
3262
- if (request.method === "eth_getBlockByNumber") {
3263
- return request.params.slice(1);
3202
+ /**
3203
+ * normalizes txParams
3204
+ */
3205
+ function normalizeTxParameters(txParameters, lowerCase = true) {
3206
+ // apply only keys in the normalizers
3207
+ const normalizedTxParameters = {
3208
+ id: txParameters.id || randomId(),
3209
+ from: txParameters.from
3210
+ };
3211
+ for (const key in normalizers) {
3212
+ const currentKey = key;
3213
+ if (txParameters[currentKey])
3214
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3215
+ normalizedTxParameters[currentKey] = normalizers[currentKey](txParameters[currentKey], lowerCase);
3264
3216
  }
3265
- return request.params.slice(0, index);
3217
+ return normalizedTxParameters;
3266
3218
  }
3267
- function cacheIdentifierForRequest(request, skipBlockRef) {
3268
- var _request$params;
3269
- const simpleParams = skipBlockRef ? paramsWithoutBlockTag(request) : (_request$params = request.params) !== null && _request$params !== void 0 ? _request$params : [];
3270
- if (canCache(request.method)) {
3271
- return `${request.method}:${stringify(simpleParams)}`;
3219
+ function transactionMatchesNetwork(transaction, chainId) {
3220
+ if (typeof transaction.chainId !== "undefined") {
3221
+ return transaction.chainId === chainId;
3272
3222
  }
3273
- return null;
3223
+ return false;
3274
3224
  }
3275
3225
 
3276
- function createChainIdMiddleware(chainId) {
3277
- return (req, res, next, end) => {
3278
- if (req.method === "eth_chainId") {
3279
- res.result = chainId;
3280
- return end();
3281
- }
3282
- if (req.method === "net_version") {
3283
- // convert to decimal
3284
- res.result = Number.parseInt(chainId, 16).toString(10);
3285
- return end();
3286
- }
3287
- return next();
3288
- };
3226
+ /**
3227
+ * Determines if the maxFeePerGas and maxPriorityFeePerGas fields are supplied
3228
+ * and valid inputs. This will return false for non hex string inputs.
3229
+ * the transaction to check
3230
+ * @returns true if transaction uses valid EIP1559 fields
3231
+ */
3232
+ function isEIP1559Transaction(transaction) {
3233
+ var _transaction$transact, _transaction$transact2;
3234
+ 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));
3289
3235
  }
3290
- function createProviderConfigMiddleware(providerConfig) {
3291
- return (req, res, next, end) => {
3292
- if (req.method === "eth_provider_config") {
3293
- res.result = providerConfig;
3294
- return end();
3295
- }
3296
- return next();
3297
- };
3236
+
3237
+ /**
3238
+ * Determine if the maxFeePerGas and maxPriorityFeePerGas fields are not
3239
+ * supplied and that the gasPrice field is valid if it is provided. This will
3240
+ * return false if gasPrice is a non hex string.
3241
+ * transaction -
3242
+ * the transaction to check
3243
+ * @returns true if transaction uses valid Legacy fields OR lacks
3244
+ * EIP1559 fields
3245
+ */
3246
+ function isLegacyTransaction(transaction) {
3247
+ return typeof transaction.transaction.maxFeePerGas === "undefined" && typeof transaction.transaction.maxPriorityFeePerGas === "undefined" && (typeof transaction.transaction.gasPrice === "undefined" || isHexString$1(addHexPrefix(transaction.transaction.gasPrice)));
3298
3248
  }
3299
- function createJsonRpcClient(providerConfig, networkConfig) {
3300
- const {
3301
- chainId,
3302
- rpcTarget
3303
- } = providerConfig;
3304
- const fetchMiddleware = createFetchMiddleware({
3305
- rpcTarget
3306
- });
3307
- const blockProvider = providerFromMiddleware(fetchMiddleware);
3308
- const blockTracker = new PollingBlockTracker({
3309
- config: _objectSpread(_objectSpread({}, networkConfig), {}, {
3310
- provider: blockProvider
3311
- }),
3312
- state: {}
3313
- });
3314
- const networkMiddleware = mergeMiddleware([createChainIdMiddleware(chainId), createProviderConfigMiddleware(providerConfig),
3315
- // No need for the following middlewares for web because all browser sessions are quite short lived and each session is limited to scope of a window/tab
3316
- // createBlockRefRewriteMiddleware({ blockTracker }),
3317
- // createBlockCacheMiddleware({ blockTracker }),
3318
- createInflightCacheMiddleware({
3319
- cacheIdentifierForRequest
3320
- }),
3321
- // createBlockTrackerInspectorMiddleware({ blockTracker }),
3322
- fetchMiddleware]);
3323
- return {
3324
- networkMiddleware,
3325
- blockTracker
3326
- };
3249
+
3250
+ /**
3251
+ * Given two fields, ensure that the second field is not included in txParams,
3252
+ * and if it is throw an invalidParams error.
3253
+ */
3254
+ function ensureMutuallyExclusiveFieldsNotProvided(txParams, fieldBeingValidated, mutuallyExclusiveField) {
3255
+ if (typeof txParams[mutuallyExclusiveField] !== "undefined") {
3256
+ throw rpcErrors.invalidParams(`Invalid transaction params: specified ${fieldBeingValidated} but also included ${mutuallyExclusiveField}, these cannot be mixed`);
3257
+ }
3327
3258
  }
3328
3259
 
3329
- const _excluded = ["chainId", "rpcTarget"];
3330
- class NetworkController extends BaseController {
3331
- constructor({
3332
- config,
3333
- state
3334
- }) {
3335
- super({
3336
- config,
3337
- state
3338
- });
3339
- _defineProperty(this, "name", "NetworkController");
3340
- _defineProperty(this, "providerProxy", void 0);
3341
- _defineProperty(this, "blockTrackerProxy", void 0);
3342
- _defineProperty(this, "mutex", new Mutex());
3343
- _defineProperty(this, "provider", null);
3344
- _defineProperty(this, "blockTracker", null);
3345
- _defineProperty(this, "baseProviderHandlers", void 0);
3346
- this.defaultState = {
3347
- chainId: "loading",
3348
- properties: {
3349
- EIPS_1559: undefined
3350
- },
3351
- providerConfig: SUPPORTED_NETWORKS[MAINNET_CHAIN_ID]
3352
- };
3260
+ /**
3261
+ * Ensures that the provided value for field is a string, throws an
3262
+ * invalidParams error if field is not a string.
3263
+ */
3264
+ function ensureFieldIsString(txParams, field) {
3265
+ if (typeof txParams[field] !== "string") {
3266
+ throw rpcErrors.invalidParams(`Invalid transaction params: ${field} is not a string. got: (${txParams[field]})`);
3267
+ }
3268
+ }
3353
3269
 
3354
- // when a new network is set,
3355
- // we set to loading first and
3356
- // then when connection succeeds,
3357
- // we update the network
3358
- this.initialize();
3270
+ /**
3271
+ * Ensures that the provided txParams has the proper 'type' specified for the
3272
+ * given field, if it is provided. If types do not match throws an
3273
+ * invalidParams error.
3274
+ */
3275
+ function ensureProperTransactionEnvelopeTypeProvided(txParams, field) {
3276
+ switch (field) {
3277
+ case "maxFeePerGas":
3278
+ case "maxPriorityFeePerGas":
3279
+ if (txParams.type && txParams.type !== TRANSACTION_ENVELOPE_TYPES.FEE_MARKET) {
3280
+ throw rpcErrors.invalidParams(`Invalid transaction envelope type: specified type "${txParams.type}" but ` + `including maxFeePerGas and maxPriorityFeePerGas requires type: "${TRANSACTION_ENVELOPE_TYPES.FEE_MARKET}"`);
3281
+ }
3282
+ break;
3283
+ case "gasPrice":
3284
+ default:
3285
+ if (txParams.type && txParams.type === TRANSACTION_ENVELOPE_TYPES.FEE_MARKET) {
3286
+ throw rpcErrors.invalidParams(`Invalid transaction envelope type: specified type "${txParams.type}" but ` + "included a gasPrice instead of maxFeePerGas and maxPriorityFeePerGas");
3287
+ }
3359
3288
  }
3360
- getNetworkIdentifier() {
3361
- return this.state.chainId;
3289
+ }
3290
+
3291
+ /**
3292
+ * validates the from field in txParams
3293
+ */
3294
+ function validateFrom(txParams) {
3295
+ if (!(typeof txParams.from === "string")) {
3296
+ throw rpcErrors.invalidParams(`Invalid "from" address "${txParams.from}": not a string.`);
3362
3297
  }
3363
- getNetworkRPCUrl() {
3364
- return this.state.providerConfig.rpcTarget;
3298
+ if (!isValidAddress(txParams.from)) {
3299
+ throw rpcErrors.invalidParams('Invalid "from" address.');
3365
3300
  }
3301
+ }
3366
3302
 
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;
3377
- }
3378
- getProvider() {
3379
- return this.providerProxy;
3303
+ /**
3304
+ * validates the to field in txParams
3305
+ */
3306
+ function validateRecipient(txParameters) {
3307
+ if (txParameters.to === "0x" || txParameters.to === null) {
3308
+ if (txParameters.data) {
3309
+ delete txParameters.to;
3310
+ } else {
3311
+ throw rpcErrors.invalidParams('Invalid "to" address.');
3312
+ }
3313
+ } else if (txParameters.to !== undefined && !isValidAddress(txParameters.to)) {
3314
+ throw rpcErrors.invalidParams('Invalid "to" address.');
3380
3315
  }
3381
- getBlockTracker() {
3382
- return this.blockTrackerProxy;
3316
+ return txParameters;
3317
+ }
3318
+
3319
+ /**
3320
+ * Validates the given tx parameters
3321
+ * @throws if the tx params contains invalid fields
3322
+ */
3323
+ function validateTxParameters(txParams, eip1559Compatibility = true) {
3324
+ if (!txParams || typeof txParams !== "object" || Array.isArray(txParams)) {
3325
+ throw rpcErrors.invalidParams("Invalid transaction params: must be an object.");
3383
3326
  }
3384
- getProviderConfig() {
3385
- return this.state.providerConfig;
3327
+ if (!txParams.to && !txParams.data) {
3328
+ throw rpcErrors.invalidParams('Invalid transaction params: must specify "data" for contract deployments, or "to" (and optionally "data") for all other types of transactions.');
3386
3329
  }
3387
- setProviderConfig(config) {
3388
- this.update({
3389
- providerConfig: _objectSpread({}, config)
3390
- });
3391
- this.refreshNetwork();
3330
+ if (isEIP1559Transaction({
3331
+ transaction: txParams
3332
+ }) && !eip1559Compatibility) {
3333
+ throw rpcErrors.invalidParams("Invalid transaction params: params specify an EIP-1559 transaction but the current network does not support EIP-1559");
3392
3334
  }
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;
3335
+ Object.entries(txParams).forEach(([key, value]) => {
3336
+ // validate types
3337
+ switch (key) {
3338
+ case "from":
3339
+ validateFrom(txParams);
3340
+ break;
3341
+ case "to":
3342
+ validateRecipient(txParams);
3343
+ break;
3344
+ case "gasPrice":
3345
+ ensureProperTransactionEnvelopeTypeProvided(txParams, "gasPrice");
3346
+ ensureMutuallyExclusiveFieldsNotProvided(txParams, "gasPrice", "maxFeePerGas");
3347
+ ensureMutuallyExclusiveFieldsNotProvided(txParams, "gasPrice", "maxPriorityFeePerGas");
3348
+ ensureFieldIsString(txParams, "gasPrice");
3349
+ break;
3350
+ case "maxFeePerGas":
3351
+ ensureProperTransactionEnvelopeTypeProvided(txParams, "maxFeePerGas");
3352
+ ensureMutuallyExclusiveFieldsNotProvided(txParams, "maxFeePerGas", "gasPrice");
3353
+ ensureFieldIsString(txParams, "maxFeePerGas");
3354
+ break;
3355
+ case "maxPriorityFeePerGas":
3356
+ ensureProperTransactionEnvelopeTypeProvided(txParams, "maxPriorityFeePerGas");
3357
+ ensureMutuallyExclusiveFieldsNotProvided(txParams, "maxPriorityFeePerGas", "gasPrice");
3358
+ ensureFieldIsString(txParams, "maxPriorityFeePerGas");
3359
+ break;
3360
+ case "value":
3361
+ ensureFieldIsString(txParams, "value");
3362
+ if (value.toString().includes("-")) {
3363
+ throw rpcErrors.invalidParams(`Invalid transaction value "${value}": not a positive number.`);
3364
+ }
3365
+ if (value.toString().includes(".")) {
3366
+ throw rpcErrors.invalidParams(`Invalid transaction value of "${value}": number must be in wei.`);
3367
+ }
3368
+ break;
3369
+ case "chainId":
3370
+ if (typeof value !== "number" && typeof value !== "string") {
3371
+ throw rpcErrors.invalidParams(`Invalid transaction params: ${key} is not a Number or hex string. got: (${value})`);
3372
+ }
3373
+ break;
3374
+ default:
3375
+ ensureFieldIsString(txParams, key);
3400
3376
  }
3401
- const latestBlock = await this.blockTracker.getLatestBlock();
3402
- const supportsEIP1559 = latestBlock && latestBlock.baseFeePerGas !== undefined;
3403
- this.update({
3404
- properties: {
3405
- EIPS_1559: supportsEIP1559
3406
- }
3377
+ });
3378
+ }
3379
+ function normalizeAndValidateTxParams(txParams, lowerCase = true) {
3380
+ const normalizedTxParams = normalizeTxParameters(txParams, lowerCase);
3381
+ validateTxParameters(normalizedTxParams);
3382
+ return normalizedTxParams;
3383
+ }
3384
+
3385
+ /**
3386
+ * @returns an array of states that can be considered final
3387
+ */
3388
+ function getFinalStates() {
3389
+ return [TransactionStatus.rejected,
3390
+ // the user has responded no!
3391
+ TransactionStatus.confirmed,
3392
+ // the tx has been included in a block.
3393
+ TransactionStatus.failed,
3394
+ // the tx failed for some reason, included on tx data.
3395
+ TransactionStatus.dropped // the tx nonce was already used
3396
+ ];
3397
+ }
3398
+ function parseStandardTokenTransactionData(data) {
3399
+ try {
3400
+ const txDesc = erc20Interface.parseTransaction({
3401
+ data
3407
3402
  });
3408
- return supportsEIP1559;
3403
+ if (txDesc) return {
3404
+ name: txDesc.name,
3405
+ methodParams: txDesc.args.toArray(),
3406
+ type: CONTRACT_TYPE_ERC20
3407
+ };
3408
+ } catch {
3409
+ // ignore and next try to parse with erc721 ABI
3409
3410
  }
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
- }
3411
+ try {
3412
+ const txDesc = erc721Interface.parseTransaction({
3413
+ data
3414
+ });
3415
+ if (txDesc) return {
3416
+ name: txDesc.name,
3417
+ methodParams: txDesc.args.toArray(),
3418
+ type: CONTRACT_TYPE_ERC721
3419
+ };
3420
+ } catch {
3421
+ // ignore and next try to parse with erc1155 ABI
3445
3422
  }
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));
3423
+ try {
3424
+ const txDesc = erc1155Interface.parseTransaction({
3425
+ data
3426
+ });
3427
+ if (txDesc) return {
3428
+ name: txDesc.name,
3429
+ methodParams: txDesc.args.toArray(),
3430
+ type: CONTRACT_TYPE_ERC1155
3431
+ };
3432
+ } catch {
3433
+ // ignore and return undefined
3460
3434
  }
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
3435
+ return undefined;
3436
+ }
3437
+ const readAddressAsContract = async (provider, address) => {
3438
+ let contractCode;
3439
+ try {
3440
+ contractCode = await provider.request({
3441
+ method: METHOD_TYPES.ETH_GET_CODE,
3442
+ params: [address, "latest"]
3473
3443
  });
3444
+ } catch (e) {
3445
+ contractCode = null;
3446
+ }
3447
+ const isContractAddress = contractCode ? contractCode !== "0x" && contractCode !== "0x0" : false;
3448
+ return {
3449
+ contractCode,
3450
+ isContractAddress
3451
+ };
3452
+ };
3453
+ async function determineTransactionType(txParams, provider) {
3454
+ const {
3455
+ data,
3456
+ to
3457
+ } = txParams;
3458
+ let name = "";
3459
+ let methodParams = [];
3460
+ let type = "";
3461
+ try {
3462
+ ({
3463
+ name,
3464
+ methodParams,
3465
+ type
3466
+ } = data && parseStandardTokenTransactionData(data) || {});
3467
+ } catch (error) {
3468
+ log.debug("Failed to parse transaction data", error);
3474
3469
  }
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"
3470
+ let result;
3471
+ let contractCode = "";
3472
+ if (data && !to) {
3473
+ result = TRANSACTION_TYPES.DEPLOY_CONTRACT;
3474
+ } else {
3475
+ const {
3476
+ contractCode: resultCode,
3477
+ isContractAddress
3478
+ } = await readAddressAsContract(provider, to);
3479
+ contractCode = resultCode;
3480
+ if (isContractAddress) {
3481
+ const valueExists = txParams.value && Number(txParams.value) !== 0;
3482
+ 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 => {
3483
+ var _name;
3484
+ return x.toLowerCase() === ((_name = name) === null || _name === void 0 ? void 0 : _name.toLowerCase());
3493
3485
  });
3486
+ result = data && tokenMethodName && !valueExists ? tokenMethodName : TRANSACTION_TYPES.CONTRACT_INTERACTION;
3487
+ } else {
3488
+ result = TRANSACTION_TYPES.SENT_ETHER;
3494
3489
  }
3490
+ }
3491
+ return {
3492
+ type: type || CONTRACT_TYPE_ETH,
3493
+ category: result,
3494
+ methodParams,
3495
+ getCodeResponse: contractCode
3496
+ };
3497
+ }
3495
3498
 
3496
- // set new provider and blockTracker
3497
- this.provider = provider;
3498
- provider.setMaxListeners(10);
3499
- this.blockTracker = blockTracker;
3499
+ function hexToBn(hex) {
3500
+ return new BigNumber(stripHexPrefix(hex), 16);
3501
+ }
3502
+ function BNToHex(bn) {
3503
+ return addHexPrefix(bn.toString(16));
3504
+ }
3505
+ function getEtherScanHashLink(txHash, chainId) {
3506
+ if (!SUPPORTED_NETWORKS[chainId]) return "";
3507
+ return `${SUPPORTED_NETWORKS[chainId].blockExplorerUrl}/tx/${txHash}`;
3508
+ }
3509
+ const formatPastTx = params => {
3510
+ var _transaction$to;
3511
+ const {
3512
+ transaction,
3513
+ lowerCaseSelectedAddress,
3514
+ blockExplorerUrl
3515
+ } = params;
3516
+ let totalAmountString = "";
3517
+ 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);
3518
+ const currencyAmountString = transaction.type === CONTRACT_TYPE_ERC721 || transaction.type === CONTRACT_TYPE_ERC1155 || transaction.isEtherscan ? "" : formatSmallNumbers(Number.parseFloat(transaction.currency_amount), transaction.selected_currency, true);
3519
+ const finalObject = {
3520
+ id: transaction.created_at.toString(),
3521
+ date: new Date(transaction.created_at).toString(),
3522
+ from: transaction.from,
3523
+ from_aa_address: transaction.from_aa_address,
3524
+ slicedFrom: typeof transaction.from === "string" ? addressSlicer(transaction.from) : "",
3525
+ to: transaction.to,
3526
+ slicedTo: typeof transaction.to === "string" ? addressSlicer(transaction.to) : "",
3527
+ action: lowerCaseSelectedAddress === ((_transaction$to = transaction.to) === null || _transaction$to === void 0 ? void 0 : _transaction$to.toLowerCase()) || "" ? ACTIVITY_ACTION_RECEIVE : ACTIVITY_ACTION_SEND,
3528
+ totalAmount: transaction.total_amount,
3529
+ totalAmountString,
3530
+ currencyAmount: transaction.currency_amount,
3531
+ currencyAmountString,
3532
+ amount: `${totalAmountString} / ${currencyAmountString}`,
3533
+ status: transaction.status,
3534
+ etherscanLink: blockExplorerUrl ? `${blockExplorerUrl}/tx/${transaction.transaction_hash}` : "",
3535
+ chainId: transaction.chain_id,
3536
+ 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))}` : "",
3537
+ currencyUsed: transaction.selected_currency,
3538
+ type: transaction.type,
3539
+ type_name: transaction.type_name,
3540
+ type_image_link: transaction.type_image_link,
3541
+ transaction_hash: transaction.transaction_hash,
3542
+ transaction_category: transaction.transaction_category,
3543
+ isEtherscan: transaction.isEtherscan,
3544
+ input: transaction.input || "",
3545
+ token_id: transaction.token_id || "",
3546
+ contract_address: transaction.contract_address || "",
3547
+ nonce: transaction.nonce || "",
3548
+ is_cancel: !!transaction.is_cancel || false,
3549
+ gas: transaction.gas || "",
3550
+ gasPrice: transaction.gasPrice || ""
3551
+ };
3552
+ return finalObject;
3553
+ };
3554
+
3555
+ /**
3556
+ * Ref - https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionreceipt
3557
+ */
3558
+ const getEthTxStatus = async (hash, provider) => {
3559
+ try {
3560
+ const result = await provider.request({
3561
+ method: METHOD_TYPES.ETH_GET_TRANSACTION_RECEIPT,
3562
+ params: [hash]
3563
+ });
3564
+ if (result === null) return TransactionStatus.submitted;
3565
+ if (result && result.status === "0x1") return TransactionStatus.confirmed;
3566
+ if (result && result.status === "0x0") return TransactionStatus.rejected;
3567
+ return undefined;
3568
+ } catch (err) {
3569
+ log.warn("unable to fetch transaction status", err);
3570
+ return undefined;
3500
3571
  }
3501
- configureStandardProvider(providerConfig) {
3502
- const networkClient = createJsonRpcClient(providerConfig, this.config);
3503
- log.info("networkClient", networkClient);
3504
- this.setNetworkClient(networkClient);
3572
+ };
3573
+ function formatDate(inputDate) {
3574
+ const monthList = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
3575
+ const date = new Date(inputDate);
3576
+ const day = date.getDate();
3577
+ const month = monthList[date.getMonth()];
3578
+ const year = date.getFullYear();
3579
+ return `${day} ${month} ${year}`;
3580
+ }
3581
+ function formatTime(time) {
3582
+ return new Date(time).toTimeString().slice(0, 8);
3583
+ }
3584
+ function isAddressByChainId(address, _chainId) {
3585
+ // TOOD: add rsk network checks.
3586
+ return isValidAddress(address);
3587
+ }
3588
+ function toChecksumAddressByChainId(address, chainId) {
3589
+ // TOOD: add rsk network checks.
3590
+ if (!isAddressByChainId(address)) return address;
3591
+ return toChecksumAddress(address);
3592
+ }
3593
+ const GAS_LIMITS = {
3594
+ // maximum gasLimit of a simple send
3595
+ SIMPLE: addHexPrefix(21000 .toString(16)),
3596
+ // a base estimate for token transfers.
3597
+ BASE_TOKEN_ESTIMATE: addHexPrefix(100000 .toString(16))
3598
+ };
3599
+ function bnLessThan(a, b) {
3600
+ if (a === null || a === undefined || b === null || b === undefined) {
3601
+ return null;
3505
3602
  }
3506
- refreshNetwork() {
3507
- this.update({
3508
- chainId: "loading",
3509
- properties: {}
3510
- });
3511
- this.configureProvider();
3512
- this.lookupNetwork();
3603
+ return new BigNumber(a, 10).lt(b, 10);
3604
+ }
3605
+ const getIpfsEndpoint = path => `https://infura-ipfs.io/${path}`;
3606
+ function sanitizeNftMetdataUrl(url) {
3607
+ let finalUri = url;
3608
+ if (url !== null && url !== void 0 && url.startsWith("ipfs")) {
3609
+ const ipfsPath = url.split("ipfs://")[1];
3610
+ finalUri = getIpfsEndpoint(ipfsPath);
3611
+ }
3612
+ return finalUri;
3613
+ }
3614
+ function getChainType(chainId) {
3615
+ if (chainId === MAINNET_CHAIN_ID) {
3616
+ return "mainnet";
3617
+ } else if (TEST_CHAINS.includes(chainId)) {
3618
+ return "testnet";
3513
3619
  }
3620
+ return "custom";
3514
3621
  }
3622
+ const addEtherscanTransactions = async params => {
3623
+ const {
3624
+ txn,
3625
+ lowerCaseSelectedAddress,
3626
+ provider,
3627
+ chainId,
3628
+ blockExplorerUrl
3629
+ } = params;
3630
+ const transactionPromises = await Promise.all(txn.map(async tx => {
3631
+ var _SUPPORTED_NETWORKS$c, _SUPPORTED_NETWORKS$c2;
3632
+ const {
3633
+ category,
3634
+ type
3635
+ } = await determineTransactionType(_objectSpread(_objectSpread({}, tx), {}, {
3636
+ data: tx.input
3637
+ }), provider);
3638
+ tx.transaction_category = tx.transaction_category || category;
3639
+ tx.type_image_link = ((_SUPPORTED_NETWORKS$c = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c === void 0 ? void 0 : _SUPPORTED_NETWORKS$c.logo) || "";
3640
+ tx.type_name = (_SUPPORTED_NETWORKS$c2 = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c2 === void 0 ? void 0 : _SUPPORTED_NETWORKS$c2.ticker;
3641
+ tx.type = type;
3642
+ return tx;
3643
+ }));
3644
+ const finalTxs = transactionPromises.reduce((accumulator, x) => {
3645
+ var _SUPPORTED_NETWORKS$c3, _SUPPORTED_NETWORKS$c4;
3646
+ let totalAmountString = x.value ? new BigNumber(x.value).div(new BigNumber(10).pow(new BigNumber(x.tokenDecimal || 18))).toString() : "";
3647
+ let type = CONTRACT_TYPE_ETH;
3648
+ if (x.contractAddress !== "") {
3649
+ if (x.tokenID) {
3650
+ type = x.tokenValue ? CONTRACT_TYPE_ERC1155 : CONTRACT_TYPE_ERC721;
3651
+ } else {
3652
+ type = CONTRACT_TYPE_ERC20;
3653
+ }
3654
+ }
3655
+ if (type === CONTRACT_TYPE_ERC1155) {
3656
+ totalAmountString = x.tokenValue;
3657
+ }
3658
+ const etherscanTransaction = {
3659
+ type,
3660
+ type_image_link: x.type_image_link || "n/a",
3661
+ type_name: x.tokenName || ((_SUPPORTED_NETWORKS$c3 = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c3 === void 0 ? void 0 : _SUPPORTED_NETWORKS$c3.ticker) || "n/a",
3662
+ symbol: x.tokenSymbol || ((_SUPPORTED_NETWORKS$c4 = SUPPORTED_NETWORKS[chainId]) === null || _SUPPORTED_NETWORKS$c4 === void 0 ? void 0 : _SUPPORTED_NETWORKS$c4.ticker),
3663
+ token_id: x.tokenID || "",
3664
+ total_amount: totalAmountString,
3665
+ created_at: new Date(Number(x.timeStamp) * 1000),
3666
+ from: x.from,
3667
+ to: x.to,
3668
+ transaction_hash: x.hash,
3669
+ status: x.txreceipt_status && x.txreceipt_status === "0" ? TransactionStatus.failed : TransactionStatus.confirmed,
3670
+ isEtherscan: true,
3671
+ input: x.input,
3672
+ contract_address: x.contractAddress,
3673
+ transaction_category: x.transaction_category,
3674
+ gas: `0x${new BigNumber(x.gasUsed || 0, 10).toString(16)}`,
3675
+ gasPrice: `0x${new BigNumber(x.gasPrice || 0, 10).toString(16)}`,
3676
+ chain_id: chainId,
3677
+ currency_amount: "",
3678
+ nonce: x.nonce,
3679
+ from_aa_address: "",
3680
+ is_cancel: false,
3681
+ selected_currency: ""
3682
+ };
3683
+ accumulator.push(formatPastTx({
3684
+ transaction: etherscanTransaction,
3685
+ lowerCaseSelectedAddress,
3686
+ blockExplorerUrl
3687
+ }));
3688
+ return accumulator;
3689
+ }, []);
3690
+ return finalTxs;
3691
+ };
3515
3692
 
3516
3693
  class NftHandler {
3517
3694
  constructor({
@@ -3943,8 +4120,13 @@ class PreferencesController extends BasePreferencesController {
3943
4120
  web3AuthClientId,
3944
4121
  web3AuthNetwork,
3945
4122
  loginMode,
3946
- sessionPubKey
4123
+ sessionPubKey,
4124
+ aaProvider,
4125
+ eoaAddress
3947
4126
  } = params;
4127
+ const {
4128
+ chainId
4129
+ } = this.getProviderConfig();
3948
4130
  await super.init({
3949
4131
  address,
3950
4132
  userInfo,
@@ -3953,7 +4135,10 @@ class PreferencesController extends BasePreferencesController {
3953
4135
  metadata: {
3954
4136
  email: userInfo.email,
3955
4137
  signatures,
3956
- network: web3AuthNetwork
4138
+ network: web3AuthNetwork,
4139
+ eoa_address: eoaAddress,
4140
+ aa_provider: aaProvider,
4141
+ chain_id: chainId
3957
4142
  }
3958
4143
  });
3959
4144
  const {
@@ -3972,9 +4157,17 @@ class PreferencesController extends BasePreferencesController {
3972
4157
  locale,
3973
4158
  address,
3974
4159
  type,
3975
- web3AuthNetwork
4160
+ web3AuthNetwork,
4161
+ metadata: {
4162
+ aa_provider: aaProvider,
4163
+ chain_id: chainId,
4164
+ eoa_address: eoaAddress
4165
+ }
3976
4166
  });
3977
4167
  }
4168
+ if (eoaAddress) this.updateState({
4169
+ eoaAddress
4170
+ }, address);
3978
4171
  this.storeUserLogin({
3979
4172
  verifier: aggregateVerifier || verifier,
3980
4173
  verifierId,
@@ -4971,6 +5164,7 @@ class PendingTransactionTracker extends SafeEventEmitter {
4971
5164
  }
4972
5165
  }
4973
5166
  async _resubmitTx(txMeta, latestBlockNumber) {
5167
+ if (txMeta.userOpHash) return;
4974
5168
  if (!txMeta.firstRetryBlockNumber) {
4975
5169
  this.emit(TX_EVENTS.TX_BLOCK_UPDATE, {
4976
5170
  txMeta,
@@ -5005,7 +5199,7 @@ class PendingTransactionTracker extends SafeEventEmitter {
5005
5199
  const txId = txMeta.id;
5006
5200
 
5007
5201
  // Only check submitted txs
5008
- if (txMeta.status !== TransactionStatus.submitted) return;
5202
+ if (txMeta.status !== TransactionStatus.submitted || txMeta.isUserOperation) return;
5009
5203
 
5010
5204
  // extra check in case there was an uncaught error during the
5011
5205
  // signature and submission process
@@ -5989,4 +6183,4 @@ class TransactionController extends TransactionStateManager {
5989
6183
  }
5990
6184
  }
5991
6185
 
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 };
6186
+ 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 };