@exodus/ethereum-api 8.40.0 → 8.41.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/package.json +4 -5
- package/src/create-asset-plugin-factory.js +0 -6
- package/src/create-asset-utils.js +19 -7
- package/src/create-asset.js +22 -12
- package/src/gas-estimation.js +11 -10
- package/src/get-balances.js +2 -9
- package/src/get-fee-async.js +13 -81
- package/src/get-fee.js +1 -1
- package/src/index.js +1 -3
- package/src/staking/ethereum/service.js +6 -6
- package/src/staking/matic/service.js +7 -7
- package/src/tx-create.js +352 -0
- package/src/tx-log/clarity-monitor.js +6 -5
- package/src/tx-log/ethereum-monitor.js +5 -4
- package/src/tx-log/monitor-utils/get-fee-amount.js +4 -1
- package/src/tx-send/index.js +0 -1
- package/src/tx-send/nonce-utils.js +1 -1
- package/src/tx-send/tx-send.js +84 -376
- package/src/tx-send/get-fee-info.js +0 -58
package/src/tx-create.js
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { calculateBumpedGasPrice, currency2buffer, isEthereumLikeToken } from '@exodus/ethereum-lib'
|
|
2
|
+
import createEthereumJsTx from '@exodus/ethereum-lib/src/unsigned-tx/create-ethereumjs-tx.js'
|
|
3
|
+
import assert from 'minimalistic-assert'
|
|
4
|
+
|
|
5
|
+
import * as ErrorWrapper from './error-wrapper.js'
|
|
6
|
+
import { isContractAddressCached } from './eth-like-util.js'
|
|
7
|
+
import { ensureSaneEip1559GasPriceForTipGasPrice } from './fee-utils.js'
|
|
8
|
+
import { ARBITRARY_ADDRESS, fetchGasLimit, resolveDefaultTxInput } from './gas-estimation.js'
|
|
9
|
+
import { getFeeFactoryGasPrices } from './get-fee.js'
|
|
10
|
+
import { getNftArguments } from './nft-utils.js'
|
|
11
|
+
import { resolveNonce } from './tx-send/nonce-utils.js'
|
|
12
|
+
|
|
13
|
+
async function createUnsignedTxWithFees({
|
|
14
|
+
asset,
|
|
15
|
+
chainId,
|
|
16
|
+
to, // the tx to address, it could be the reciver address for native sending, the token contract, the DEX contract, etc
|
|
17
|
+
value, // the value of the tx in NU, it can be the value in eth or 0 when calling contracts
|
|
18
|
+
data, // the data of the tx in hex string, it can be 0x for native sending or the params when sending to a contract
|
|
19
|
+
gasLimit,
|
|
20
|
+
eip1559Enabled,
|
|
21
|
+
gasPrice, // eip 1559: `maxFeePerGas`
|
|
22
|
+
tipGasPrice, // eip 1559: `maxPriorityPerGas`
|
|
23
|
+
nonce,
|
|
24
|
+
bumpTxId,
|
|
25
|
+
coinAmount, // coinAmount
|
|
26
|
+
fromAddress, // user's sending address
|
|
27
|
+
toAddress, // user's receiver address
|
|
28
|
+
}) {
|
|
29
|
+
assert(asset, 'asset is required')
|
|
30
|
+
assert(typeof chainId === 'number', 'chainId is required')
|
|
31
|
+
assert(to, 'to is required')
|
|
32
|
+
assert(value, 'value is required')
|
|
33
|
+
assert(data, 'data is required')
|
|
34
|
+
assert(gasLimit, 'gasLimit is required')
|
|
35
|
+
assert(gasPrice, 'gasPrice is required')
|
|
36
|
+
assert(coinAmount, 'coinAmount is required')
|
|
37
|
+
assert(fromAddress, 'fromAddress is required')
|
|
38
|
+
assert(toAddress, 'toAddress is required')
|
|
39
|
+
assert(typeof eip1559Enabled === 'boolean', 'eip1559Enabled is required')
|
|
40
|
+
|
|
41
|
+
const ethjsTx = createEthereumJsTx({
|
|
42
|
+
txData: {
|
|
43
|
+
nonce,
|
|
44
|
+
gasPrice: currency2buffer(gasPrice),
|
|
45
|
+
tipGasPrice: tipGasPrice ? currency2buffer(tipGasPrice) : undefined,
|
|
46
|
+
gasLimit,
|
|
47
|
+
to,
|
|
48
|
+
value: currency2buffer(value),
|
|
49
|
+
data,
|
|
50
|
+
chainId,
|
|
51
|
+
},
|
|
52
|
+
txMeta: {
|
|
53
|
+
eip1559Enabled,
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
const transactionBuffer = ethjsTx.serialize()
|
|
57
|
+
|
|
58
|
+
const baseFee = gasPrice.mul(gasLimit)
|
|
59
|
+
const optimismL1DataFee = asset.baseAsset.estimateL1DataFee
|
|
60
|
+
? await asset.baseAsset.estimateL1DataFee({
|
|
61
|
+
unsignedTx: { txData: { transactionBuffer, chainId } },
|
|
62
|
+
})
|
|
63
|
+
: undefined
|
|
64
|
+
|
|
65
|
+
const l1DataFee = optimismL1DataFee
|
|
66
|
+
? asset.baseAsset.currency.baseUnit(optimismL1DataFee)
|
|
67
|
+
: asset.baseAsset.currency.ZERO
|
|
68
|
+
|
|
69
|
+
const fee = baseFee.add(l1DataFee)
|
|
70
|
+
|
|
71
|
+
const unsignedTx = {
|
|
72
|
+
txData: { transactionBuffer, chainId },
|
|
73
|
+
txMeta: {
|
|
74
|
+
bumpTxId,
|
|
75
|
+
eip1559Enabled,
|
|
76
|
+
fromAddress,
|
|
77
|
+
toAddress,
|
|
78
|
+
amount: coinAmount.toDefaultString({ unit: true }),
|
|
79
|
+
fee: fee.toDefaultString({ unit: true }),
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
return { unsignedTx }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const createBumpUnsignedTx = async ({
|
|
86
|
+
fromAddress,
|
|
87
|
+
chainId,
|
|
88
|
+
asset,
|
|
89
|
+
bumpTxId,
|
|
90
|
+
baseAssetTxLog,
|
|
91
|
+
assetClientInterface,
|
|
92
|
+
walletAccount,
|
|
93
|
+
feeData,
|
|
94
|
+
nonce: providedNonce,
|
|
95
|
+
}) => {
|
|
96
|
+
const baseAsset = asset.baseAsset
|
|
97
|
+
const replacedTx = baseAssetTxLog.get(bumpTxId)
|
|
98
|
+
const assets = await assetClientInterface.getAssetsForNetwork({ baseAssetName: baseAsset.name })
|
|
99
|
+
if (!replacedTx || !replacedTx.pending) {
|
|
100
|
+
throw new Error(`Cannot bump transaction ${bumpTxId}: not found or confirmed`)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let replacedTokenTx
|
|
104
|
+
if (replacedTx.tokens.length > 0) {
|
|
105
|
+
const [tokenAssetName] = replacedTx.tokens
|
|
106
|
+
const tokenTxSet = await assetClientInterface.getTxLog({
|
|
107
|
+
assetName: tokenAssetName,
|
|
108
|
+
walletAccount,
|
|
109
|
+
})
|
|
110
|
+
replacedTokenTx = tokenTxSet.get(bumpTxId)
|
|
111
|
+
|
|
112
|
+
if (replacedTokenTx) {
|
|
113
|
+
// Attempt to overwrite the asset to reflect the fact that
|
|
114
|
+
// we're performing a token transaction.
|
|
115
|
+
asset = assets[tokenAssetName]
|
|
116
|
+
if (!asset) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
`unable to find ${tokenAssetName} during token bump transaction: asset was not available in assetsForNetwork`
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const toAddress = (replacedTokenTx || replacedTx).to
|
|
125
|
+
const isToken = isEthereumLikeToken(asset)
|
|
126
|
+
const txToAddress = isToken ? asset.contract.address : toAddress
|
|
127
|
+
const coinAmount = (replacedTokenTx || replacedTx).coinAmount.negate()
|
|
128
|
+
const gasLimit = replacedTx.data.gasLimit
|
|
129
|
+
|
|
130
|
+
const value = isToken ? baseAsset.currency.ZERO : coinAmount
|
|
131
|
+
|
|
132
|
+
const {
|
|
133
|
+
gasPrice: currentGasPrice,
|
|
134
|
+
baseFeePerGas: currentBaseFee,
|
|
135
|
+
eip1559Enabled,
|
|
136
|
+
tipGasPrice: currentTipGasPrice,
|
|
137
|
+
} = feeData
|
|
138
|
+
const { bumpedGasPrice, bumpedTipGasPrice } = calculateBumpedGasPrice({
|
|
139
|
+
baseAsset,
|
|
140
|
+
tx: replacedTx,
|
|
141
|
+
currentGasPrice,
|
|
142
|
+
currentBaseFee,
|
|
143
|
+
currentTipGasPrice,
|
|
144
|
+
eip1559Enabled,
|
|
145
|
+
})
|
|
146
|
+
const gasPrice = bumpedGasPrice
|
|
147
|
+
const tipGasPrice = bumpedTipGasPrice
|
|
148
|
+
const nonce = replacedTx.data.nonce
|
|
149
|
+
const data = replacedTokenTx
|
|
150
|
+
? asset.contract.transfer.build(toAddress.toLowerCase(), coinAmount.toBaseString())
|
|
151
|
+
: replacedTx.data.data || '0x'
|
|
152
|
+
|
|
153
|
+
if (nonce === undefined) {
|
|
154
|
+
throw new Error(`Cannot bump transaction ${bumpTxId}: data object seems to be corrupted`)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// If we have evaluated a bump transaction and the `providedNonce` differs
|
|
158
|
+
// from the `bumpNonce`, we've encountered a conflict and cannot respect
|
|
159
|
+
// the caller's request.
|
|
160
|
+
if (typeof nonce === 'number' && typeof providedNonce === 'number' && nonce !== providedNonce)
|
|
161
|
+
throw new ErrorWrapper.EthLikeError({
|
|
162
|
+
message: new Error('incorrect nonce for replacement transaction'),
|
|
163
|
+
reason: ErrorWrapper.reasons.bumpTxFailed,
|
|
164
|
+
hint: 'providedNonce',
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
return createUnsignedTxWithFees({
|
|
168
|
+
asset,
|
|
169
|
+
chainId,
|
|
170
|
+
to: txToAddress,
|
|
171
|
+
value,
|
|
172
|
+
data,
|
|
173
|
+
gasLimit,
|
|
174
|
+
gasPrice,
|
|
175
|
+
tipGasPrice,
|
|
176
|
+
nonce,
|
|
177
|
+
bumpTxId,
|
|
178
|
+
coinAmount,
|
|
179
|
+
fromAddress,
|
|
180
|
+
toAddress,
|
|
181
|
+
eip1559Enabled,
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export const createTxFactory = ({ chainId, assetClientInterface, useAbsoluteNonce }) => {
|
|
186
|
+
assert(assetClientInterface, 'assetClientInterface is required')
|
|
187
|
+
assert(typeof chainId === 'number', 'chainId is required')
|
|
188
|
+
return async ({
|
|
189
|
+
asset,
|
|
190
|
+
walletAccount,
|
|
191
|
+
feeData,
|
|
192
|
+
nft, // when sending nfts
|
|
193
|
+
fromAddress: providedFromAddress, // wallet from address
|
|
194
|
+
toAddress: providedToAddress, // user's to address, not the token or the dex contract
|
|
195
|
+
contractAddress: providedContractAddress, // Provided when swapping a token via the DEX contract, not via the token's contract
|
|
196
|
+
txInput: providedTxInput, // Provided when swapping via a DEX contract
|
|
197
|
+
gasLimit: providedGasLimit, // Provided by exchange when known
|
|
198
|
+
amount: providedAmount, // The NU amount to be sent, to be included in the tx value or tx input
|
|
199
|
+
nonce: providedNonce,
|
|
200
|
+
tipGasPrice: providedTipGasPrice,
|
|
201
|
+
gasPrice: providedGasPrice,
|
|
202
|
+
bip70,
|
|
203
|
+
isExchange,
|
|
204
|
+
customFee,
|
|
205
|
+
isSendAll,
|
|
206
|
+
bumpTxId,
|
|
207
|
+
keepTxInput, // @deprecated this flag is used by swaps when swapping a token via DEX. The asset is token but the tx TO address is not the token address. Update swap to use `contractAddress`
|
|
208
|
+
}) => {
|
|
209
|
+
assert(asset, 'asset is required')
|
|
210
|
+
assert(feeData, 'feeData is required')
|
|
211
|
+
const fromAddress = providedFromAddress || ARBITRARY_ADDRESS
|
|
212
|
+
|
|
213
|
+
const baseAssetTxLog = await assetClientInterface.getTxLog({
|
|
214
|
+
assetName: asset.baseAsset.name,
|
|
215
|
+
walletAccount,
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
if (bumpTxId) {
|
|
219
|
+
return createBumpUnsignedTx({
|
|
220
|
+
chainId,
|
|
221
|
+
asset,
|
|
222
|
+
fromAddress,
|
|
223
|
+
bumpTxId,
|
|
224
|
+
baseAssetTxLog,
|
|
225
|
+
assetClientInterface,
|
|
226
|
+
walletAccount,
|
|
227
|
+
feeData,
|
|
228
|
+
nonce: providedNonce,
|
|
229
|
+
})
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const toAddress = providedToAddress || ARBITRARY_ADDRESS
|
|
233
|
+
const {
|
|
234
|
+
gasPrice: maybeGasPrice,
|
|
235
|
+
feeData: { tipGasPrice: maybeTipGasPrice, eip1559Enabled },
|
|
236
|
+
} = getFeeFactoryGasPrices({ customFee, feeData })
|
|
237
|
+
|
|
238
|
+
const isToken = isEthereumLikeToken(asset)
|
|
239
|
+
|
|
240
|
+
const resolvedGasPrice = providedGasPrice ?? maybeGasPrice
|
|
241
|
+
|
|
242
|
+
const txToAddress =
|
|
243
|
+
providedContractAddress ?? (isToken && !keepTxInput ? asset.contract.address : toAddress)
|
|
244
|
+
|
|
245
|
+
const isContractToAddress = await isContractAddressCached({ asset, address: txToAddress })
|
|
246
|
+
|
|
247
|
+
// HACK: We cannot ensure the no dust invariant for `isSendAll`
|
|
248
|
+
// transactions to contract addresses, since we may be
|
|
249
|
+
// performing a raw token transaction and the parameter
|
|
250
|
+
// applies to the token and not the native amount.
|
|
251
|
+
//
|
|
252
|
+
// Contracts have nondeterministic gas most of the time
|
|
253
|
+
// versus estimations, anyway.
|
|
254
|
+
const isSendAllBaseAsset = isSendAll && !isToken && !isContractToAddress
|
|
255
|
+
|
|
256
|
+
// For native send all transactions, we have to make sure that
|
|
257
|
+
// the `tipGasPrice` is equal to the `gasPrice`, since this is
|
|
258
|
+
// effectively like saying that the `maxFeePerGas` is equal
|
|
259
|
+
// to the `maxPriorityFeePerGas`. We do this so that for a
|
|
260
|
+
// fixed gas cost transaction, no dust balance should remain,
|
|
261
|
+
// since any deviation in the underlying `baseFeePerGas` will
|
|
262
|
+
// result only affect the tip for the miner - no dust remains.
|
|
263
|
+
const tipGasPrice =
|
|
264
|
+
providedTipGasPrice ??
|
|
265
|
+
(eip1559Enabled && isSendAllBaseAsset ? resolvedGasPrice : maybeTipGasPrice)
|
|
266
|
+
|
|
267
|
+
const gasPrice = eip1559Enabled
|
|
268
|
+
? ensureSaneEip1559GasPriceForTipGasPrice({
|
|
269
|
+
gasPrice: resolvedGasPrice,
|
|
270
|
+
tipGasPrice,
|
|
271
|
+
})
|
|
272
|
+
: resolvedGasPrice
|
|
273
|
+
|
|
274
|
+
const nonce =
|
|
275
|
+
providedNonce ??
|
|
276
|
+
(await resolveNonce({
|
|
277
|
+
asset,
|
|
278
|
+
fromAddress,
|
|
279
|
+
txLog: baseAssetTxLog,
|
|
280
|
+
// For assets where we'll fall back to querying the coin node, we
|
|
281
|
+
// search for pending transactions. For base assets with history,
|
|
282
|
+
// we'll fall back to the `TxLog` since this also has a knowledge
|
|
283
|
+
// of which transactions are currently in pending.
|
|
284
|
+
tag: 'pending',
|
|
285
|
+
useAbsoluteNonce,
|
|
286
|
+
}))
|
|
287
|
+
|
|
288
|
+
if (nft) {
|
|
289
|
+
const {
|
|
290
|
+
contractAddress: txToAddress,
|
|
291
|
+
gasLimit,
|
|
292
|
+
txInput,
|
|
293
|
+
} = await getNftArguments({
|
|
294
|
+
asset,
|
|
295
|
+
nft,
|
|
296
|
+
fromAddress,
|
|
297
|
+
toAddress: providedToAddress,
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
const value = asset.baseAsset.currency.ZERO
|
|
301
|
+
|
|
302
|
+
return createUnsignedTxWithFees({
|
|
303
|
+
chainId,
|
|
304
|
+
asset,
|
|
305
|
+
to: txToAddress,
|
|
306
|
+
value,
|
|
307
|
+
data: txInput,
|
|
308
|
+
gasLimit,
|
|
309
|
+
gasPrice,
|
|
310
|
+
tipGasPrice,
|
|
311
|
+
nonce,
|
|
312
|
+
coinAmount: value,
|
|
313
|
+
fromAddress,
|
|
314
|
+
toAddress,
|
|
315
|
+
eip1559Enabled,
|
|
316
|
+
})
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const amount = providedAmount ?? asset.currency.ZERO
|
|
320
|
+
|
|
321
|
+
const value = isToken ? asset.baseAsset.currency.ZERO : amount
|
|
322
|
+
const txInput = providedTxInput || resolveDefaultTxInput({ asset, toAddress, amount })
|
|
323
|
+
const gasLimit =
|
|
324
|
+
providedGasLimit ??
|
|
325
|
+
(await fetchGasLimit({
|
|
326
|
+
asset,
|
|
327
|
+
feeData,
|
|
328
|
+
fromAddress: providedFromAddress,
|
|
329
|
+
toAddress: providedToAddress,
|
|
330
|
+
txInput: providedTxInput,
|
|
331
|
+
contractAddress: txToAddress,
|
|
332
|
+
bip70,
|
|
333
|
+
amount,
|
|
334
|
+
}))
|
|
335
|
+
|
|
336
|
+
return createUnsignedTxWithFees({
|
|
337
|
+
asset,
|
|
338
|
+
chainId,
|
|
339
|
+
to: txToAddress,
|
|
340
|
+
value,
|
|
341
|
+
data: txInput,
|
|
342
|
+
gasLimit,
|
|
343
|
+
gasPrice,
|
|
344
|
+
tipGasPrice,
|
|
345
|
+
nonce,
|
|
346
|
+
coinAmount: amount,
|
|
347
|
+
fromAddress,
|
|
348
|
+
toAddress,
|
|
349
|
+
eip1559Enabled,
|
|
350
|
+
})
|
|
351
|
+
}
|
|
352
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseMonitor } from '@exodus/asset-lib'
|
|
2
|
-
import { getAssetAddresses
|
|
2
|
+
import { getAssetAddresses } from '@exodus/ethereum-lib'
|
|
3
3
|
import lodash from 'lodash'
|
|
4
4
|
|
|
5
5
|
import { executeEthLikeFeeMonitorUpdate } from '../fee-utils.js'
|
|
@@ -16,10 +16,11 @@ import {
|
|
|
16
16
|
const { isEmpty } = lodash
|
|
17
17
|
|
|
18
18
|
export class ClarityMonitor extends BaseMonitor {
|
|
19
|
-
constructor({ server, config, ...args }) {
|
|
19
|
+
constructor({ server, config, rpcBalanceAssetNames, ...args }) {
|
|
20
20
|
super(args)
|
|
21
21
|
this.config = { GAS_PRICE_FROM_WEBSOCKET: true, ...config }
|
|
22
22
|
this.server = server
|
|
23
|
+
this.rpcBalanceAssetNames = rpcBalanceAssetNames
|
|
23
24
|
this.getAllLogItemsByAsset = getAllLogItemsByAsset
|
|
24
25
|
this.deriveDataNeededForTick = getDeriveDataNeededForTick(this.aci)
|
|
25
26
|
this.deriveTransactionsToCheck = getDeriveTransactionsToCheck({
|
|
@@ -201,7 +202,7 @@ export class ClarityMonitor extends BaseMonitor {
|
|
|
201
202
|
const asset = this.asset
|
|
202
203
|
const newAccountState = Object.create(null)
|
|
203
204
|
const balances = await this.getBalances({ tokens, ourWalletAddress })
|
|
204
|
-
if (
|
|
205
|
+
if (this.rpcBalanceAssetNames.includes(asset.name)) {
|
|
205
206
|
const balance = balances[asset.name]
|
|
206
207
|
newAccountState.balance = asset.currency.baseUnit(balance)
|
|
207
208
|
}
|
|
@@ -244,13 +245,13 @@ export class ClarityMonitor extends BaseMonitor {
|
|
|
244
245
|
|
|
245
246
|
async getBalances({ tokens, ourWalletAddress }) {
|
|
246
247
|
const batch = Object.create(null)
|
|
247
|
-
if (
|
|
248
|
+
if (this.rpcBalanceAssetNames.includes(this.asset.name)) {
|
|
248
249
|
const request = this.server.getBalanceRequest(ourWalletAddress)
|
|
249
250
|
batch[this.asset.name] = request
|
|
250
251
|
}
|
|
251
252
|
|
|
252
253
|
for (const token of tokens) {
|
|
253
|
-
if (
|
|
254
|
+
if (this.rpcBalanceAssetNames.includes(token.name) && token.contract.address) {
|
|
254
255
|
const request = this.server.balanceOfRequest(ourWalletAddress, token.contract.address)
|
|
255
256
|
batch[token.name] = request
|
|
256
257
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseMonitor } from '@exodus/asset-lib'
|
|
2
|
-
import { getAssetAddresses
|
|
2
|
+
import { getAssetAddresses } from '@exodus/ethereum-lib'
|
|
3
3
|
import lodash from 'lodash'
|
|
4
4
|
|
|
5
5
|
import { executeEthLikeFeeMonitorUpdate } from '../fee-utils.js'
|
|
@@ -25,7 +25,7 @@ const { isEmpty } = lodash
|
|
|
25
25
|
// formatting, and populating-to-state all ETH/ETC/ERC20 transactions.
|
|
26
26
|
|
|
27
27
|
export class EthereumMonitor extends BaseMonitor {
|
|
28
|
-
constructor({ server, config, webSocketEnabled = true, ...args }) {
|
|
28
|
+
constructor({ server, config, rpcBalanceAssetNames, webSocketEnabled = true, ...args }) {
|
|
29
29
|
super(args)
|
|
30
30
|
this.server = server
|
|
31
31
|
this.config = { GAS_PRICE_FROM_WEBSOCKET: true, ...config }
|
|
@@ -38,6 +38,7 @@ export class EthereumMonitor extends BaseMonitor {
|
|
|
38
38
|
this.addHook('after-stop', (...args) => this.afterStop(...args))
|
|
39
39
|
this.subscribedToGasPriceMap = new Map()
|
|
40
40
|
this._webSocketEnabled = webSocketEnabled
|
|
41
|
+
this.rpcBalanceAssetNames = rpcBalanceAssetNames
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
setServer(config = {}) {
|
|
@@ -215,7 +216,7 @@ export class EthereumMonitor extends BaseMonitor {
|
|
|
215
216
|
const asset = this.asset
|
|
216
217
|
const newAccountState = Object.create(null)
|
|
217
218
|
const server = this.server
|
|
218
|
-
if (
|
|
219
|
+
if (this.rpcBalanceAssetNames.includes(asset.name)) {
|
|
219
220
|
const result = await server.getBalanceProxied(ourWalletAddress)
|
|
220
221
|
const balance = fromHexToString(result)
|
|
221
222
|
newAccountState.balance = asset.currency.baseUnit(balance)
|
|
@@ -223,7 +224,7 @@ export class EthereumMonitor extends BaseMonitor {
|
|
|
223
224
|
|
|
224
225
|
const tokenBalancePairs = await Promise.all(
|
|
225
226
|
tokens
|
|
226
|
-
.filter((token) =>
|
|
227
|
+
.filter((token) => this.rpcBalanceAssetNames.includes(token.name) && token.contract.address)
|
|
227
228
|
.map(async (token) => {
|
|
228
229
|
const { confirmed } = await server.balanceOf(ourWalletAddress, token.contract.address)
|
|
229
230
|
const value = token.currency.baseUnit(confirmed[token.contract.address] || 0)
|
|
@@ -7,5 +7,8 @@ export default function getFeeAmount(asset, serverTx) {
|
|
|
7
7
|
// genesis, coinbase, uncles
|
|
8
8
|
if (!gasPrice) return asset.currency.ZERO
|
|
9
9
|
|
|
10
|
-
return asset.currency
|
|
10
|
+
return asset.currency
|
|
11
|
+
.baseUnit(gasUsed || gasLimit)
|
|
12
|
+
.mul(gasPrice)
|
|
13
|
+
.add(asset.currency.baseUnit(serverTx.extraData?.l1Fee || 0))
|
|
11
14
|
}
|
package/src/tx-send/index.js
CHANGED