@toruslabs/ethereum-controllers 5.10.1 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ethereumControllers.cjs.js +114 -432
- package/dist/ethereumControllers.esm.js +63 -351
- package/dist/ethereumControllers.umd.min.js +1 -1
- package/dist/ethereumControllers.umd.min.js.LICENSE.txt +7 -2
- package/dist/lib.cjs/Account/AccountTrackerController.js +160 -0
- package/dist/lib.cjs/Block/PollingBlockTracker.js +85 -0
- package/dist/lib.cjs/Currency/CurrencyController.js +111 -0
- package/dist/lib.cjs/Gas/GasFeeController.js +214 -0
- package/dist/lib.cjs/Gas/gasUtil.js +148 -0
- package/dist/lib.cjs/Keyring/KeyringController.js +93 -0
- package/dist/lib.cjs/Message/AbstractMessageController.js +107 -0
- package/dist/lib.cjs/Message/AddChainController.js +78 -0
- package/dist/lib.cjs/Message/MessageController.js +77 -0
- package/dist/lib.cjs/Message/PersonalMessageController.js +77 -0
- package/dist/lib.cjs/Message/SwitchChainController.js +78 -0
- package/dist/lib.cjs/Message/TypedMessageController.js +81 -0
- package/dist/lib.cjs/Message/utils.js +112 -0
- package/dist/lib.cjs/Network/NetworkController.js +201 -0
- package/dist/lib.cjs/Network/cacheIdentifier.js +112 -0
- package/dist/lib.cjs/Network/createEthereumMiddleware.js +302 -0
- package/dist/lib.cjs/Network/createJsonRpcClient.js +64 -0
- package/dist/lib.cjs/Nfts/NftHandler.js +180 -0
- package/dist/lib.cjs/Nfts/NftsController.js +213 -0
- package/dist/lib.cjs/Preferences/PreferencesController.js +476 -0
- package/dist/lib.cjs/Tokens/TokenHandler.js +51 -0
- package/dist/lib.cjs/Tokens/TokenRatesController.js +112 -0
- package/dist/lib.cjs/Tokens/TokensController.js +259 -0
- package/dist/lib.cjs/Transaction/NonceTracker.js +150 -0
- package/dist/lib.cjs/Transaction/PendingTransactionTracker.js +222 -0
- package/dist/lib.cjs/Transaction/TransactionController.js +515 -0
- package/dist/lib.cjs/Transaction/TransactionGasUtil.js +81 -0
- package/dist/lib.cjs/Transaction/TransactionStateHistoryHelper.js +42 -0
- package/dist/lib.cjs/Transaction/TransactionStateManager.js +296 -0
- package/dist/lib.cjs/Transaction/TransactionUtils.js +341 -0
- package/dist/lib.cjs/index.js +171 -0
- package/dist/lib.cjs/utils/abis.js +510 -0
- package/dist/lib.cjs/utils/constants.js +362 -0
- package/dist/lib.cjs/utils/contractAddresses.js +16 -0
- package/dist/lib.cjs/utils/conversionUtils.js +232 -0
- package/dist/lib.cjs/utils/helpers.js +244 -0
- package/dist/lib.cjs/utils/lodashUtils.js +25 -0
- package/dist/lib.esm/Account/AccountTrackerController.js +158 -0
- package/dist/lib.esm/Block/PollingBlockTracker.js +83 -0
- package/dist/lib.esm/Currency/CurrencyController.js +109 -0
- package/dist/lib.esm/Gas/GasFeeController.js +212 -0
- package/dist/lib.esm/Gas/gasUtil.js +141 -0
- package/dist/lib.esm/Keyring/KeyringController.js +91 -0
- package/dist/lib.esm/Message/AbstractMessageController.js +105 -0
- package/dist/lib.esm/Message/AddChainController.js +76 -0
- package/dist/lib.esm/Message/MessageController.js +75 -0
- package/dist/lib.esm/Message/PersonalMessageController.js +75 -0
- package/dist/lib.esm/Message/SwitchChainController.js +76 -0
- package/dist/lib.esm/Message/TypedMessageController.js +79 -0
- package/dist/lib.esm/Message/utils.js +105 -0
- package/dist/lib.esm/Network/NetworkController.js +199 -0
- package/dist/lib.esm/Network/cacheIdentifier.js +107 -0
- package/dist/lib.esm/Network/createEthereumMiddleware.js +289 -0
- package/dist/lib.esm/Network/createJsonRpcClient.js +60 -0
- package/dist/lib.esm/Nfts/NftHandler.js +178 -0
- package/dist/lib.esm/Nfts/NftsController.js +211 -0
- package/dist/lib.esm/Preferences/PreferencesController.js +474 -0
- package/dist/lib.esm/Tokens/TokenHandler.js +49 -0
- package/dist/lib.esm/Tokens/TokenRatesController.js +109 -0
- package/dist/lib.esm/Tokens/TokensController.js +257 -0
- package/dist/lib.esm/Transaction/NonceTracker.js +148 -0
- package/dist/lib.esm/Transaction/PendingTransactionTracker.js +220 -0
- package/dist/lib.esm/Transaction/TransactionController.js +513 -0
- package/dist/lib.esm/Transaction/TransactionGasUtil.js +79 -0
- package/dist/lib.esm/Transaction/TransactionStateHistoryHelper.js +38 -0
- package/dist/lib.esm/Transaction/TransactionStateManager.js +294 -0
- package/dist/lib.esm/Transaction/TransactionUtils.js +326 -0
- package/dist/lib.esm/index.js +33 -0
- package/dist/lib.esm/utils/abis.js +505 -0
- package/dist/lib.esm/utils/constants.js +323 -0
- package/dist/lib.esm/utils/contractAddresses.js +14 -0
- package/dist/lib.esm/utils/conversionUtils.js +218 -0
- package/dist/lib.esm/utils/helpers.js +227 -0
- package/dist/lib.esm/utils/lodashUtils.js +21 -0
- package/dist/types/Account/AccountTrackerController.d.ts +5 -5
- package/dist/types/Block/PollingBlockTracker.d.ts +1 -2
- package/dist/types/Currency/CurrencyController.d.ts +1 -1
- package/dist/types/Gas/GasFeeController.d.ts +3 -3
- package/dist/types/Gas/gasUtil.d.ts +1 -1
- package/dist/types/Keyring/KeyringController.d.ts +3 -5
- package/dist/types/Message/AbstractMessageController.d.ts +5 -6
- package/dist/types/Message/AddChainController.d.ts +4 -4
- package/dist/types/Message/MessageController.d.ts +4 -4
- package/dist/types/Message/PersonalMessageController.d.ts +4 -4
- package/dist/types/Message/SwitchChainController.d.ts +4 -4
- package/dist/types/Message/TypedMessageController.d.ts +6 -7
- package/dist/types/Message/utils.d.ts +2 -7
- package/dist/types/Network/NetworkController.d.ts +4 -4
- package/dist/types/Network/cacheIdentifier.d.ts +1 -1
- package/dist/types/Network/createEthereumMiddleware.d.ts +2 -18
- package/dist/types/Network/createJsonRpcClient.d.ts +2 -2
- package/dist/types/Nfts/NftsController.d.ts +2 -2
- package/dist/types/Preferences/PreferencesController.d.ts +4 -4
- package/dist/types/Tokens/TokensController.d.ts +3 -3
- package/dist/types/Transaction/NonceTracker.d.ts +5 -5
- package/dist/types/Transaction/PendingTransactionTracker.d.ts +5 -5
- package/dist/types/Transaction/TransactionController.d.ts +12 -12
- package/dist/types/Transaction/TransactionGasUtil.d.ts +4 -4
- package/dist/types/Transaction/TransactionStateManager.d.ts +3 -3
- package/dist/types/Transaction/TransactionUtils.d.ts +1 -1
- package/dist/types/index.d.ts +12 -14
- package/dist/types/utils/constants.d.ts +1 -5
- package/dist/types/utils/helpers.d.ts +7 -4
- package/dist/types/utils/interfaces.d.ts +43 -23
- package/package.json +22 -10
- package/dist/types/Message/DecryptMessageController.d.ts +0 -20
- package/dist/types/Message/EncryptionPublicKeyController.d.ts +0 -20
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import _objectSpread from '@babel/runtime/helpers/objectSpread2';
|
|
2
|
+
import { BaseTransactionStateManager, randomId, TransactionStatus, omitBy, transactionMatchesNetwork, pickBy, TX_EVENTS } from '@toruslabs/base-controllers';
|
|
3
|
+
import { mapValues, keyBy, sortBy } from '../utils/lodashUtils.js';
|
|
4
|
+
import { snapshotFromTxMeta, replayHistory, generateHistoryEntry } from './TransactionStateHistoryHelper.js';
|
|
5
|
+
import { normalizeAndValidateTxParams, getFinalStates } from './TransactionUtils.js';
|
|
6
|
+
|
|
7
|
+
class TransactionStateManager extends BaseTransactionStateManager {
|
|
8
|
+
constructor({
|
|
9
|
+
config,
|
|
10
|
+
state,
|
|
11
|
+
getCurrentChainId
|
|
12
|
+
}) {
|
|
13
|
+
super({
|
|
14
|
+
config,
|
|
15
|
+
state,
|
|
16
|
+
getCurrentChainId
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
generateTxMeta(opts = {}) {
|
|
20
|
+
var _opts$transaction;
|
|
21
|
+
const chainId = this.getCurrentChainId();
|
|
22
|
+
if (chainId === "loading") throw new Error("Torus is having trouble connecting to the network");
|
|
23
|
+
let dappSuggestedGasFees = null;
|
|
24
|
+
|
|
25
|
+
// If we are dealing with a transaction suggested by a dapp and not
|
|
26
|
+
// an internally created transaction, we need to keep record of
|
|
27
|
+
// the originally submitted gasParams.
|
|
28
|
+
if (opts.transaction && typeof opts.origin === "string" && opts.origin !== "torus") {
|
|
29
|
+
if (typeof opts.transaction.gasPrice !== "undefined") {
|
|
30
|
+
dappSuggestedGasFees = {
|
|
31
|
+
gasPrice: opts.transaction.gasPrice
|
|
32
|
+
};
|
|
33
|
+
} else if (typeof opts.transaction.maxFeePerGas !== "undefined" || typeof opts.transaction.maxPriorityFeePerGas !== "undefined") {
|
|
34
|
+
dappSuggestedGasFees = {
|
|
35
|
+
maxPriorityFeePerGas: opts.transaction.maxPriorityFeePerGas,
|
|
36
|
+
maxFeePerGas: opts.transaction.maxFeePerGas
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (typeof opts.transaction.gas !== "undefined") {
|
|
40
|
+
dappSuggestedGasFees = _objectSpread(_objectSpread({}, dappSuggestedGasFees), {}, {
|
|
41
|
+
gas: opts.transaction.gas
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return _objectSpread({
|
|
46
|
+
id: ((_opts$transaction = opts.transaction) === null || _opts$transaction === void 0 ? void 0 : _opts$transaction.id) || randomId(),
|
|
47
|
+
time: Date.now(),
|
|
48
|
+
status: TransactionStatus.unapproved,
|
|
49
|
+
loadingDefaults: true,
|
|
50
|
+
chainId,
|
|
51
|
+
dappSuggestedGasFees
|
|
52
|
+
}, opts);
|
|
53
|
+
}
|
|
54
|
+
addTransactionToState(txMeta) {
|
|
55
|
+
if (txMeta.transaction) {
|
|
56
|
+
txMeta.transaction = normalizeAndValidateTxParams(txMeta.transaction, false);
|
|
57
|
+
}
|
|
58
|
+
this.once(`${txMeta.id}:signed`, () => {
|
|
59
|
+
this.removeAllListeners(`${txMeta.id}:rejected`);
|
|
60
|
+
});
|
|
61
|
+
this.once(`${txMeta.id}:rejected`, () => {
|
|
62
|
+
this.removeAllListeners(`${txMeta.id}:signed`);
|
|
63
|
+
});
|
|
64
|
+
// initialize history
|
|
65
|
+
txMeta.history = [];
|
|
66
|
+
// capture initial snapshot of txMeta for history
|
|
67
|
+
const snapshot = snapshotFromTxMeta(txMeta);
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
|
+
txMeta.history.push(snapshot);
|
|
70
|
+
const transactions = this.getTransactions({
|
|
71
|
+
filterToCurrentNetwork: false
|
|
72
|
+
});
|
|
73
|
+
const {
|
|
74
|
+
txHistoryLimit
|
|
75
|
+
} = this.config;
|
|
76
|
+
|
|
77
|
+
// checks if the length of the tx history is longer then desired persistence
|
|
78
|
+
// limit and then if it is removes the oldest confirmed or rejected tx.
|
|
79
|
+
// Pending or unapproved transactions will not be removed by this
|
|
80
|
+
// operation. For safety of presenting a fully functional transaction UI
|
|
81
|
+
// representation, this function will not break apart transactions with the
|
|
82
|
+
// same nonce, per network. Not accounting for transactions of the same
|
|
83
|
+
// nonce and network combo can result in confusing or broken experiences
|
|
84
|
+
// in the UI.
|
|
85
|
+
//
|
|
86
|
+
// we will send UI only collected groups of transactions *per page* so at
|
|
87
|
+
// some point in the future, this persistence limit can be adjusted. When
|
|
88
|
+
// we do that I think we should figure out a better storage solution for
|
|
89
|
+
// transaction history entries.
|
|
90
|
+
const nonceNetworkSet = new Set();
|
|
91
|
+
const txsToDelete = transactions.reverse().filter(tx => {
|
|
92
|
+
const {
|
|
93
|
+
nonce
|
|
94
|
+
} = tx.transaction;
|
|
95
|
+
const {
|
|
96
|
+
chainId,
|
|
97
|
+
status
|
|
98
|
+
} = tx;
|
|
99
|
+
const key = `${nonce}-${chainId}`;
|
|
100
|
+
if (nonceNetworkSet.has(key)) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
if (nonceNetworkSet.size < txHistoryLimit - 1 || getFinalStates().includes(status) === false) {
|
|
104
|
+
nonceNetworkSet.add(key);
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
}).map(tx => tx.id);
|
|
109
|
+
this._deleteTransactions(txsToDelete);
|
|
110
|
+
this._addTransactionsToState([txMeta]);
|
|
111
|
+
return txMeta;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
Removes transaction from the given address for the current network
|
|
116
|
+
from the txList
|
|
117
|
+
*/
|
|
118
|
+
wipeTransactions(address) {
|
|
119
|
+
const {
|
|
120
|
+
transactions
|
|
121
|
+
} = this.state;
|
|
122
|
+
const chainId = this.getCurrentChainId();
|
|
123
|
+
this.update({
|
|
124
|
+
transactions: omitBy(transactions, txMeta => {
|
|
125
|
+
const transactionMatch = transactionMatchesNetwork(txMeta, chainId);
|
|
126
|
+
return txMeta.transaction.from === address && transactionMatch;
|
|
127
|
+
})
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
getTransactions({
|
|
131
|
+
searchCriteria = {},
|
|
132
|
+
initialList = undefined,
|
|
133
|
+
filterToCurrentNetwork = true,
|
|
134
|
+
limit = undefined
|
|
135
|
+
} = {}) {
|
|
136
|
+
const chainId = this.getCurrentChainId();
|
|
137
|
+
// searchCriteria is an object that might have values that aren't predicate
|
|
138
|
+
// methods. When providing any other value type (string, number, etc), we
|
|
139
|
+
// consider this shorthand for "check the value at key for strict equality
|
|
140
|
+
// with the provided value". To conform this object to be only methods, we
|
|
141
|
+
// mapValues (lodash) such that every value on the object is a method that
|
|
142
|
+
// returns a boolean.
|
|
143
|
+
const predicateMethods = mapValues(searchCriteria, predicate => typeof predicate === "function" ? predicate : v => v === predicate);
|
|
144
|
+
|
|
145
|
+
// If an initial list is provided we need to change it back into an object
|
|
146
|
+
// first, so that it matches the shape of our state. This is done by the
|
|
147
|
+
// lodash keyBy method. This is the edge case for this method, typically
|
|
148
|
+
// initialList will be undefined.
|
|
149
|
+
const transactionsToFilter = initialList ? keyBy(initialList, "id") : this.state.transactions;
|
|
150
|
+
|
|
151
|
+
// Combine sortBy and pickBy to transform our state object into an array of
|
|
152
|
+
// matching transactions that are sorted by time.
|
|
153
|
+
const filteredTransactions = sortBy(Object.values(pickBy(transactionsToFilter, txMeta => {
|
|
154
|
+
// default matchesCriteria to the value of transactionMatchesNetwork
|
|
155
|
+
// when filterToCurrentNetwork is true.
|
|
156
|
+
const transactionMatches = transactionMatchesNetwork(txMeta, chainId);
|
|
157
|
+
if (filterToCurrentNetwork && !transactionMatches) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
// iterate over the predicateMethods keys to check if the transaction
|
|
161
|
+
// matches the searchCriteria
|
|
162
|
+
for (const [key, predicate] of Object.entries(predicateMethods)) {
|
|
163
|
+
// We return false early as soon as we know that one of the specified
|
|
164
|
+
// search criteria do not match the transaction. This prevents
|
|
165
|
+
// needlessly checking all criteria when we already know the criteria
|
|
166
|
+
// are not fully satisfied. We check both txParams and the base
|
|
167
|
+
// object as predicate keys can be either.
|
|
168
|
+
if (key in txMeta.transaction) {
|
|
169
|
+
if (predicate(txMeta.transaction[key]) === false) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
} else if (predicate(txMeta[key]) === false) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
177
|
+
})), "time");
|
|
178
|
+
if (limit !== undefined) {
|
|
179
|
+
// We need to have all transactions of a given nonce in order to display
|
|
180
|
+
// necessary details in the UI. We use the size of this set to determine
|
|
181
|
+
// whether we have reached the limit provided, thus ensuring that all
|
|
182
|
+
// transactions of nonces we include will be sent to the UI.
|
|
183
|
+
const nonces = new Set();
|
|
184
|
+
const txs = [];
|
|
185
|
+
// By default, the transaction list we filter from is sorted by time ASC.
|
|
186
|
+
// To ensure that filtered results prefers the newest transactions we
|
|
187
|
+
// iterate from right to left, inserting transactions into front of a new
|
|
188
|
+
// array. The original order is preserved, but we ensure that newest txs
|
|
189
|
+
// are preferred.
|
|
190
|
+
for (let i = filteredTransactions.length - 1; i > -1; i -= 1) {
|
|
191
|
+
const txMeta = filteredTransactions[i];
|
|
192
|
+
const {
|
|
193
|
+
nonce
|
|
194
|
+
} = txMeta.transaction;
|
|
195
|
+
if (!nonces.has(nonce)) {
|
|
196
|
+
if (nonces.size < limit) {
|
|
197
|
+
nonces.add(nonce);
|
|
198
|
+
} else {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Push transaction into the beginning of our array to ensure the
|
|
203
|
+
// original order is preserved.
|
|
204
|
+
txs.unshift(txMeta);
|
|
205
|
+
}
|
|
206
|
+
return txs;
|
|
207
|
+
}
|
|
208
|
+
return filteredTransactions;
|
|
209
|
+
}
|
|
210
|
+
getApprovedTransactions(address) {
|
|
211
|
+
const searchCriteria = {
|
|
212
|
+
status: TransactionStatus.approved
|
|
213
|
+
};
|
|
214
|
+
if (address) {
|
|
215
|
+
searchCriteria.from = address;
|
|
216
|
+
}
|
|
217
|
+
return this.getTransactions({
|
|
218
|
+
searchCriteria
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
getSubmittedTransactions(address) {
|
|
222
|
+
const searchCriteria = {
|
|
223
|
+
status: TransactionStatus.submitted
|
|
224
|
+
};
|
|
225
|
+
if (address) {
|
|
226
|
+
searchCriteria.from = address;
|
|
227
|
+
}
|
|
228
|
+
return this.getTransactions({
|
|
229
|
+
searchCriteria
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
getPendingTransactions(address) {
|
|
233
|
+
const submitted = this.getSubmittedTransactions(address);
|
|
234
|
+
const approved = this.getApprovedTransactions(address);
|
|
235
|
+
return [...submitted, ...approved];
|
|
236
|
+
}
|
|
237
|
+
getConfirmedTransactions(address) {
|
|
238
|
+
const searchCriteria = {
|
|
239
|
+
status: TransactionStatus.confirmed
|
|
240
|
+
};
|
|
241
|
+
if (address) {
|
|
242
|
+
searchCriteria.from = address;
|
|
243
|
+
}
|
|
244
|
+
return this.getTransactions({
|
|
245
|
+
searchCriteria
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
getUnapprovedTxList() {
|
|
249
|
+
const chainId = this.getCurrentChainId();
|
|
250
|
+
return pickBy(this.state.transactions, transaction => {
|
|
251
|
+
const transactionMatches = transactionMatchesNetwork(transaction, chainId);
|
|
252
|
+
return transaction.status === TransactionStatus.unapproved && transactionMatches;
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
updateTransactionInState(txMeta, note) {
|
|
256
|
+
// validate txParams
|
|
257
|
+
if (txMeta.transaction) {
|
|
258
|
+
txMeta.transaction = normalizeAndValidateTxParams(txMeta.transaction, false);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// create txMeta snapshot for history
|
|
262
|
+
const currentState = snapshotFromTxMeta(txMeta);
|
|
263
|
+
// recover previous tx state obj
|
|
264
|
+
const previousState = replayHistory(txMeta.history);
|
|
265
|
+
// generate history entry and add to history
|
|
266
|
+
const entry = generateHistoryEntry(previousState, currentState, note);
|
|
267
|
+
if (entry.length > 0) {
|
|
268
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
269
|
+
txMeta.history.push(entry);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// commit txMeta to state
|
|
273
|
+
this.updateTransaction(txMeta);
|
|
274
|
+
}
|
|
275
|
+
_setTransactionStatus(txId, status, isFinalStep) {
|
|
276
|
+
const txMeta = this.getTransaction(txId);
|
|
277
|
+
if (!txMeta) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
txMeta.status = status;
|
|
281
|
+
this.updateTransactionInState(txMeta);
|
|
282
|
+
this.emit(TX_EVENTS.TX_STATUS_UPDATE, {
|
|
283
|
+
txId,
|
|
284
|
+
status
|
|
285
|
+
});
|
|
286
|
+
if (this.isFinalState(status) || isFinalStep) {
|
|
287
|
+
this.emit(`${txMeta.id}:finished`, txMeta);
|
|
288
|
+
} else {
|
|
289
|
+
this.emit(`${txMeta.id}:${status}`, txId);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export { TransactionStateManager };
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { isHexString, addHexPrefix, isValidAddress } from '@ethereumjs/util';
|
|
2
|
+
import { randomId, TransactionStatus, TRANSACTION_TYPES } from '@toruslabs/base-controllers';
|
|
3
|
+
import { rpcErrors } from '@web3auth/auth';
|
|
4
|
+
import { Interface } from 'ethers';
|
|
5
|
+
import log from 'loglevel';
|
|
6
|
+
import { erc20Abi, erc721Abi, erc1155Abi } from '../utils/abis.js';
|
|
7
|
+
import { CONTRACT_TYPE_ERC20, CONTRACT_TYPE_ERC721, CONTRACT_TYPE_ERC1155, METHOD_TYPES, CONTRACT_TYPE_ETH, TRANSACTION_ENVELOPE_TYPES } from '../utils/constants.js';
|
|
8
|
+
|
|
9
|
+
const erc20Interface = new Interface(erc20Abi);
|
|
10
|
+
const erc721Interface = new Interface(erc721Abi);
|
|
11
|
+
const erc1155Interface = new Interface(erc1155Abi);
|
|
12
|
+
|
|
13
|
+
// functions that handle normalizing of that key in txParams
|
|
14
|
+
|
|
15
|
+
const normalizers = {
|
|
16
|
+
from: (from, LowerCase = true) => LowerCase ? addHexPrefix(from).toLowerCase() : addHexPrefix(from),
|
|
17
|
+
to: (to, LowerCase = true) => LowerCase ? addHexPrefix(to).toLowerCase() : addHexPrefix(to),
|
|
18
|
+
nonce: nonce => addHexPrefix(nonce),
|
|
19
|
+
customNonceValue: nonce => addHexPrefix(nonce),
|
|
20
|
+
value: value => addHexPrefix(value),
|
|
21
|
+
data: data => addHexPrefix(data),
|
|
22
|
+
gas: gas => addHexPrefix(gas),
|
|
23
|
+
gasPrice: gasPrice => addHexPrefix(gasPrice),
|
|
24
|
+
type: addHexPrefix,
|
|
25
|
+
maxFeePerGas: addHexPrefix,
|
|
26
|
+
maxPriorityFeePerGas: addHexPrefix
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* normalizes txParams
|
|
31
|
+
*/
|
|
32
|
+
function normalizeTxParameters(txParameters, lowerCase = true) {
|
|
33
|
+
// apply only keys in the normalizers
|
|
34
|
+
const normalizedTxParameters = {
|
|
35
|
+
id: txParameters.id || randomId(),
|
|
36
|
+
from: txParameters.from
|
|
37
|
+
};
|
|
38
|
+
for (const key in normalizers) {
|
|
39
|
+
const currentKey = key;
|
|
40
|
+
if (txParameters[currentKey])
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
+
normalizedTxParameters[currentKey] = normalizers[currentKey](txParameters[currentKey], lowerCase);
|
|
43
|
+
}
|
|
44
|
+
return normalizedTxParameters;
|
|
45
|
+
}
|
|
46
|
+
function transactionMatchesNetwork(transaction, chainId) {
|
|
47
|
+
if (typeof transaction.chainId !== "undefined") {
|
|
48
|
+
return transaction.chainId === chainId;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Determines if the maxFeePerGas and maxPriorityFeePerGas fields are supplied
|
|
55
|
+
* and valid inputs. This will return false for non hex string inputs.
|
|
56
|
+
* the transaction to check
|
|
57
|
+
* @returns true if transaction uses valid EIP1559 fields
|
|
58
|
+
*/
|
|
59
|
+
function isEIP1559Transaction(transaction) {
|
|
60
|
+
var _transaction$transact, _transaction$transact2;
|
|
61
|
+
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));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Determine if the maxFeePerGas and maxPriorityFeePerGas fields are not
|
|
66
|
+
* supplied and that the gasPrice field is valid if it is provided. This will
|
|
67
|
+
* return false if gasPrice is a non hex string.
|
|
68
|
+
* transaction -
|
|
69
|
+
* the transaction to check
|
|
70
|
+
* @returns true if transaction uses valid Legacy fields OR lacks
|
|
71
|
+
* EIP1559 fields
|
|
72
|
+
*/
|
|
73
|
+
function isLegacyTransaction(transaction) {
|
|
74
|
+
return typeof transaction.transaction.maxFeePerGas === "undefined" && typeof transaction.transaction.maxPriorityFeePerGas === "undefined" && (typeof transaction.transaction.gasPrice === "undefined" || isHexString(addHexPrefix(transaction.transaction.gasPrice)));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Given two fields, ensure that the second field is not included in txParams,
|
|
79
|
+
* and if it is throw an invalidParams error.
|
|
80
|
+
*/
|
|
81
|
+
function ensureMutuallyExclusiveFieldsNotProvided(txParams, fieldBeingValidated, mutuallyExclusiveField) {
|
|
82
|
+
if (typeof txParams[mutuallyExclusiveField] !== "undefined") {
|
|
83
|
+
throw rpcErrors.invalidParams(`Invalid transaction params: specified ${fieldBeingValidated} but also included ${mutuallyExclusiveField}, these cannot be mixed`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Ensures that the provided value for field is a string, throws an
|
|
89
|
+
* invalidParams error if field is not a string.
|
|
90
|
+
*/
|
|
91
|
+
function ensureFieldIsString(txParams, field) {
|
|
92
|
+
if (typeof txParams[field] !== "string") {
|
|
93
|
+
throw rpcErrors.invalidParams(`Invalid transaction params: ${field} is not a string. got: (${txParams[field]})`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Ensures that the provided txParams has the proper 'type' specified for the
|
|
99
|
+
* given field, if it is provided. If types do not match throws an
|
|
100
|
+
* invalidParams error.
|
|
101
|
+
*/
|
|
102
|
+
function ensureProperTransactionEnvelopeTypeProvided(txParams, field) {
|
|
103
|
+
switch (field) {
|
|
104
|
+
case "maxFeePerGas":
|
|
105
|
+
case "maxPriorityFeePerGas":
|
|
106
|
+
if (txParams.type && txParams.type !== TRANSACTION_ENVELOPE_TYPES.FEE_MARKET) {
|
|
107
|
+
throw rpcErrors.invalidParams(`Invalid transaction envelope type: specified type "${txParams.type}" but ` + `including maxFeePerGas and maxPriorityFeePerGas requires type: "${TRANSACTION_ENVELOPE_TYPES.FEE_MARKET}"`);
|
|
108
|
+
}
|
|
109
|
+
break;
|
|
110
|
+
case "gasPrice":
|
|
111
|
+
default:
|
|
112
|
+
if (txParams.type && txParams.type === TRANSACTION_ENVELOPE_TYPES.FEE_MARKET) {
|
|
113
|
+
throw rpcErrors.invalidParams(`Invalid transaction envelope type: specified type "${txParams.type}" but ` + "included a gasPrice instead of maxFeePerGas and maxPriorityFeePerGas");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* validates the from field in txParams
|
|
120
|
+
*/
|
|
121
|
+
function validateFrom(txParams) {
|
|
122
|
+
if (!(typeof txParams.from === "string")) {
|
|
123
|
+
throw rpcErrors.invalidParams(`Invalid "from" address "${txParams.from}": not a string.`);
|
|
124
|
+
}
|
|
125
|
+
if (!isValidAddress(txParams.from)) {
|
|
126
|
+
throw rpcErrors.invalidParams('Invalid "from" address.');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* validates the to field in txParams
|
|
132
|
+
*/
|
|
133
|
+
function validateRecipient(txParameters) {
|
|
134
|
+
if (txParameters.to === "0x" || txParameters.to === null) {
|
|
135
|
+
if (txParameters.data) {
|
|
136
|
+
delete txParameters.to;
|
|
137
|
+
} else {
|
|
138
|
+
throw rpcErrors.invalidParams('Invalid "to" address.');
|
|
139
|
+
}
|
|
140
|
+
} else if (txParameters.to !== undefined && !isValidAddress(txParameters.to)) {
|
|
141
|
+
throw rpcErrors.invalidParams('Invalid "to" address.');
|
|
142
|
+
}
|
|
143
|
+
return txParameters;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Validates the given tx parameters
|
|
148
|
+
* @throws if the tx params contains invalid fields
|
|
149
|
+
*/
|
|
150
|
+
function validateTxParameters(txParams, eip1559Compatibility = true) {
|
|
151
|
+
if (!txParams || typeof txParams !== "object" || Array.isArray(txParams)) {
|
|
152
|
+
throw rpcErrors.invalidParams("Invalid transaction params: must be an object.");
|
|
153
|
+
}
|
|
154
|
+
if (!txParams.to && !txParams.data) {
|
|
155
|
+
throw rpcErrors.invalidParams('Invalid transaction params: must specify "data" for contract deployments, or "to" (and optionally "data") for all other types of transactions.');
|
|
156
|
+
}
|
|
157
|
+
if (isEIP1559Transaction({
|
|
158
|
+
transaction: txParams
|
|
159
|
+
}) && !eip1559Compatibility) {
|
|
160
|
+
throw rpcErrors.invalidParams("Invalid transaction params: params specify an EIP-1559 transaction but the current network does not support EIP-1559");
|
|
161
|
+
}
|
|
162
|
+
Object.entries(txParams).forEach(([key, value]) => {
|
|
163
|
+
// validate types
|
|
164
|
+
switch (key) {
|
|
165
|
+
case "from":
|
|
166
|
+
validateFrom(txParams);
|
|
167
|
+
break;
|
|
168
|
+
case "to":
|
|
169
|
+
validateRecipient(txParams);
|
|
170
|
+
break;
|
|
171
|
+
case "gasPrice":
|
|
172
|
+
ensureProperTransactionEnvelopeTypeProvided(txParams, "gasPrice");
|
|
173
|
+
ensureMutuallyExclusiveFieldsNotProvided(txParams, "gasPrice", "maxFeePerGas");
|
|
174
|
+
ensureMutuallyExclusiveFieldsNotProvided(txParams, "gasPrice", "maxPriorityFeePerGas");
|
|
175
|
+
ensureFieldIsString(txParams, "gasPrice");
|
|
176
|
+
break;
|
|
177
|
+
case "maxFeePerGas":
|
|
178
|
+
ensureProperTransactionEnvelopeTypeProvided(txParams, "maxFeePerGas");
|
|
179
|
+
ensureMutuallyExclusiveFieldsNotProvided(txParams, "maxFeePerGas", "gasPrice");
|
|
180
|
+
ensureFieldIsString(txParams, "maxFeePerGas");
|
|
181
|
+
break;
|
|
182
|
+
case "maxPriorityFeePerGas":
|
|
183
|
+
ensureProperTransactionEnvelopeTypeProvided(txParams, "maxPriorityFeePerGas");
|
|
184
|
+
ensureMutuallyExclusiveFieldsNotProvided(txParams, "maxPriorityFeePerGas", "gasPrice");
|
|
185
|
+
ensureFieldIsString(txParams, "maxPriorityFeePerGas");
|
|
186
|
+
break;
|
|
187
|
+
case "value":
|
|
188
|
+
ensureFieldIsString(txParams, "value");
|
|
189
|
+
if (value.toString().includes("-")) {
|
|
190
|
+
throw rpcErrors.invalidParams(`Invalid transaction value "${value}": not a positive number.`);
|
|
191
|
+
}
|
|
192
|
+
if (value.toString().includes(".")) {
|
|
193
|
+
throw rpcErrors.invalidParams(`Invalid transaction value of "${value}": number must be in wei.`);
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
196
|
+
case "chainId":
|
|
197
|
+
if (typeof value !== "number" && typeof value !== "string") {
|
|
198
|
+
throw rpcErrors.invalidParams(`Invalid transaction params: ${key} is not a Number or hex string. got: (${value})`);
|
|
199
|
+
}
|
|
200
|
+
break;
|
|
201
|
+
default:
|
|
202
|
+
ensureFieldIsString(txParams, key);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
function normalizeAndValidateTxParams(txParams, lowerCase = true) {
|
|
207
|
+
const normalizedTxParams = normalizeTxParameters(txParams, lowerCase);
|
|
208
|
+
validateTxParameters(normalizedTxParams);
|
|
209
|
+
return normalizedTxParams;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @returns an array of states that can be considered final
|
|
214
|
+
*/
|
|
215
|
+
function getFinalStates() {
|
|
216
|
+
return [TransactionStatus.rejected,
|
|
217
|
+
// the user has responded no!
|
|
218
|
+
TransactionStatus.confirmed,
|
|
219
|
+
// the tx has been included in a block.
|
|
220
|
+
TransactionStatus.failed,
|
|
221
|
+
// the tx failed for some reason, included on tx data.
|
|
222
|
+
TransactionStatus.dropped // the tx nonce was already used
|
|
223
|
+
];
|
|
224
|
+
}
|
|
225
|
+
function parseStandardTokenTransactionData(data) {
|
|
226
|
+
try {
|
|
227
|
+
const txDesc = erc20Interface.parseTransaction({
|
|
228
|
+
data
|
|
229
|
+
});
|
|
230
|
+
if (txDesc) return {
|
|
231
|
+
name: txDesc.name,
|
|
232
|
+
methodParams: txDesc.args.toArray(),
|
|
233
|
+
type: CONTRACT_TYPE_ERC20
|
|
234
|
+
};
|
|
235
|
+
} catch {
|
|
236
|
+
// ignore and next try to parse with erc721 ABI
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
const txDesc = erc721Interface.parseTransaction({
|
|
240
|
+
data
|
|
241
|
+
});
|
|
242
|
+
if (txDesc) return {
|
|
243
|
+
name: txDesc.name,
|
|
244
|
+
methodParams: txDesc.args.toArray(),
|
|
245
|
+
type: CONTRACT_TYPE_ERC721
|
|
246
|
+
};
|
|
247
|
+
} catch {
|
|
248
|
+
// ignore and next try to parse with erc1155 ABI
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
const txDesc = erc1155Interface.parseTransaction({
|
|
252
|
+
data
|
|
253
|
+
});
|
|
254
|
+
if (txDesc) return {
|
|
255
|
+
name: txDesc.name,
|
|
256
|
+
methodParams: txDesc.args.toArray(),
|
|
257
|
+
type: CONTRACT_TYPE_ERC1155
|
|
258
|
+
};
|
|
259
|
+
} catch {
|
|
260
|
+
// ignore and return undefined
|
|
261
|
+
}
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
const readAddressAsContract = async (provider, address) => {
|
|
265
|
+
let contractCode;
|
|
266
|
+
try {
|
|
267
|
+
contractCode = await provider.request({
|
|
268
|
+
method: METHOD_TYPES.ETH_GET_CODE,
|
|
269
|
+
params: [address, "latest"]
|
|
270
|
+
});
|
|
271
|
+
} catch (e) {
|
|
272
|
+
contractCode = null;
|
|
273
|
+
}
|
|
274
|
+
const isContractAddress = contractCode ? contractCode !== "0x" && contractCode !== "0x0" : false;
|
|
275
|
+
return {
|
|
276
|
+
contractCode,
|
|
277
|
+
isContractAddress
|
|
278
|
+
};
|
|
279
|
+
};
|
|
280
|
+
async function determineTransactionType(txParams, provider) {
|
|
281
|
+
const {
|
|
282
|
+
data,
|
|
283
|
+
to
|
|
284
|
+
} = txParams;
|
|
285
|
+
let name = "";
|
|
286
|
+
let methodParams = [];
|
|
287
|
+
let type = "";
|
|
288
|
+
try {
|
|
289
|
+
({
|
|
290
|
+
name,
|
|
291
|
+
methodParams,
|
|
292
|
+
type
|
|
293
|
+
} = data && parseStandardTokenTransactionData(data) || {});
|
|
294
|
+
} catch (error) {
|
|
295
|
+
log.debug("Failed to parse transaction data", error);
|
|
296
|
+
}
|
|
297
|
+
let result;
|
|
298
|
+
let contractCode = "";
|
|
299
|
+
if (data && !to) {
|
|
300
|
+
result = TRANSACTION_TYPES.DEPLOY_CONTRACT;
|
|
301
|
+
} else {
|
|
302
|
+
const {
|
|
303
|
+
contractCode: resultCode,
|
|
304
|
+
isContractAddress
|
|
305
|
+
} = await readAddressAsContract(provider, to);
|
|
306
|
+
contractCode = resultCode;
|
|
307
|
+
if (isContractAddress) {
|
|
308
|
+
const valueExists = txParams.value && Number(txParams.value) !== 0;
|
|
309
|
+
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 => {
|
|
310
|
+
var _name;
|
|
311
|
+
return x.toLowerCase() === ((_name = name) === null || _name === void 0 ? void 0 : _name.toLowerCase());
|
|
312
|
+
});
|
|
313
|
+
result = data && tokenMethodName && !valueExists ? tokenMethodName : TRANSACTION_TYPES.CONTRACT_INTERACTION;
|
|
314
|
+
} else {
|
|
315
|
+
result = TRANSACTION_TYPES.SENT_ETHER;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
type: type || CONTRACT_TYPE_ETH,
|
|
320
|
+
category: result,
|
|
321
|
+
methodParams,
|
|
322
|
+
getCodeResponse: contractCode
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export { determineTransactionType, ensureFieldIsString, ensureMutuallyExclusiveFieldsNotProvided, getFinalStates, isEIP1559Transaction, isLegacyTransaction, normalizeAndValidateTxParams, normalizeTxParameters, parseStandardTokenTransactionData, readAddressAsContract, transactionMatchesNetwork, validateFrom, validateRecipient, validateTxParameters };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export { AccountTrackerController } from './Account/AccountTrackerController.js';
|
|
2
|
+
export { PollingBlockTracker } from './Block/PollingBlockTracker.js';
|
|
3
|
+
export { CurrencyController } from './Currency/CurrencyController.js';
|
|
4
|
+
export { GasFeeController } from './Gas/GasFeeController.js';
|
|
5
|
+
export { KeyringController } from './Keyring/KeyringController.js';
|
|
6
|
+
export { AbstractMessageController } from './Message/AbstractMessageController.js';
|
|
7
|
+
export { AddChainController } from './Message/AddChainController.js';
|
|
8
|
+
export { MessageController } from './Message/MessageController.js';
|
|
9
|
+
export { PersonalMessageController } from './Message/PersonalMessageController.js';
|
|
10
|
+
export { SwitchChainController } from './Message/SwitchChainController.js';
|
|
11
|
+
export { TypedMessageController } from './Message/TypedMessageController.js';
|
|
12
|
+
export { normalizeMessageData, validateAddChainData, validateAddress, validateSignMessageData, validateSwitchChainData, validateTypedSignMessageDataV4 } from './Message/utils.js';
|
|
13
|
+
export { createEthereumMiddleware, createGetAccountsMiddleware, createPendingNonceMiddleware, createPendingTxMiddleware, createProcessAddEthereumChain, createProcessEthSignMessage, createProcessPersonalMessage, createProcessSwitchEthereumChain, createProcessTransactionMiddleware, createProcessTypedMessageV4, createRequestAccountsMiddleware, formatTxMetaForRpcResult } from './Network/createEthereumMiddleware.js';
|
|
14
|
+
export { createChainIdMiddleware, createJsonRpcClient, createProviderConfigMiddleware } from './Network/createJsonRpcClient.js';
|
|
15
|
+
export { NetworkController } from './Network/NetworkController.js';
|
|
16
|
+
export { NftHandler } from './Nfts/NftHandler.js';
|
|
17
|
+
export { NftsController } from './Nfts/NftsController.js';
|
|
18
|
+
export { PreferencesController } from './Preferences/PreferencesController.js';
|
|
19
|
+
export { TokenHandler } from './Tokens/TokenHandler.js';
|
|
20
|
+
export { DEFAULT_CURRENCY, TokenRatesController } from './Tokens/TokenRatesController.js';
|
|
21
|
+
export { TokensController } from './Tokens/TokensController.js';
|
|
22
|
+
export { NonceTracker } from './Transaction/NonceTracker.js';
|
|
23
|
+
export { PendingTransactionTracker } from './Transaction/PendingTransactionTracker.js';
|
|
24
|
+
export { TransactionController } from './Transaction/TransactionController.js';
|
|
25
|
+
export { TransactionGasUtil } from './Transaction/TransactionGasUtil.js';
|
|
26
|
+
export { generateHistoryEntry, replayHistory, snapshotFromTxMeta } from './Transaction/TransactionStateHistoryHelper.js';
|
|
27
|
+
export { TransactionStateManager } from './Transaction/TransactionStateManager.js';
|
|
28
|
+
export { determineTransactionType, ensureFieldIsString, ensureMutuallyExclusiveFieldsNotProvided, getFinalStates, isEIP1559Transaction, isLegacyTransaction, normalizeAndValidateTxParams, normalizeTxParameters, parseStandardTokenTransactionData, readAddressAsContract, transactionMatchesNetwork, validateFrom, validateRecipient, validateTxParameters } from './Transaction/TransactionUtils.js';
|
|
29
|
+
export { erc1155Abi, erc20Abi, erc721Abi, singleBalanceCheckerAbi } from './utils/abis.js';
|
|
30
|
+
export { ARBITRUM_MAINNET_CHAIN_ID, ARBITRUM_TESTNET_CHAIN_ID, AVALANCHE_MAINNET_CHAIN_ID, AVALANCHE_TESTNET_CHAIN_ID, BASE_CHAIN_ID, BASE_TESTNET_CHAIN_ID, 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, ERC1155_INTERFACE_ID, ERC721_ENUMERABLE_INTERFACE_ID, ERC721_INTERFACE_ID, ERC721_METADATA_INTERFACE_ID, ETHERSCAN_SUPPORTED_CHAINS, GAS_ESTIMATE_TYPES, LOCALHOST, MAINNET_CHAIN_ID, MESSAGE_EVENTS, METHOD_TYPES, MessageStatus, OLD_ERC721_LIST, OPTIMISM_MAINNET_CHAIN_ID, OPTIMISM_TESTNET_CHAIN_ID, POLYGON_AMOY_CHAIN_ID, POLYGON_CHAIN_ID, SEPOLIA_CHAIN_ID, SIMPLEHASH_SUPPORTED_CHAINS, SUPPORTED_NETWORKS, TEST_CHAINS, TRANSACTION_ENVELOPE_TYPES, XDAI_CHAIN_ID } from './utils/constants.js';
|
|
31
|
+
export { addCurrencies, conversionGTE, conversionGreaterThan, conversionLTE, conversionLessThan, conversionMax, conversionUtil, decGWEIToHexWEI, getBigNumber, hexWEIToDecGWEI, multiplyCurrencies, subtractCurrencies, toNegative } from './utils/conversionUtils.js';
|
|
32
|
+
export { BNToHex, GAS_LIMITS, addEtherscanTransactions, bnLessThan, formatDate, formatPastTx, formatTime, getChainType, getEthTxStatus, getEtherScanHashLink, getIpfsEndpoint, hexToBn, idleTimeTracker, isAddressByChainId, sanitizeNftMetdataUrl, toChecksumAddressByChainId } from './utils/helpers.js';
|
|
33
|
+
import '@toruslabs/base-controllers';
|