@exodus/ethereum-api 8.57.1 → 8.58.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 +16 -0
- package/package.json +3 -3
- package/src/error-wrapper.js +1 -0
- package/src/fee-utils.js +1 -0
- package/src/get-fee.js +55 -8
- package/src/staking/matic/service.js +2 -2
- package/src/tx-create.js +66 -39
- package/src/tx-log/get-optimistic-txlog-effects.js +25 -8
- package/src/tx-log/index.js +1 -1
- package/src/tx-send/tx-send.js +1 -1
- package/src/tx-type/index.js +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [8.58.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.57.0...@exodus/ethereum-api@8.58.0) (2025-11-10)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
* feat: enable implicit transaction bumps (#6798)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
* fix: correct response to insufficient evm nonce during txSend (#6901)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
## [8.57.1](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.57.0...@exodus/ethereum-api@8.57.1) (2025-11-10)
|
|
7
23
|
|
|
8
24
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/ethereum-api",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.58.0",
|
|
4
4
|
"description": "Transaction monitors, fee monitors, RPC with the blockchain node, and other networking code for Ethereum and EVM-based blockchains",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@exodus/bip44-constants": "^195.0.0",
|
|
30
30
|
"@exodus/crypto": "^1.0.0-rc.26",
|
|
31
31
|
"@exodus/currency": "^6.0.1",
|
|
32
|
-
"@exodus/ethereum-lib": "^5.
|
|
32
|
+
"@exodus/ethereum-lib": "^5.19.0",
|
|
33
33
|
"@exodus/ethereum-meta": "^2.9.1",
|
|
34
34
|
"@exodus/ethereumholesky-meta": "^2.0.5",
|
|
35
35
|
"@exodus/ethereumjs": "^1.8.0",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"type": "git",
|
|
68
68
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "e56c423be0eaf19f1396830fbafd13ab64efa465"
|
|
71
71
|
}
|
package/src/error-wrapper.js
CHANGED
package/src/fee-utils.js
CHANGED
package/src/get-fee.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
calculateBumpedGasPrice,
|
|
3
|
+
calculateBumpedGasPriceForFeeData,
|
|
4
|
+
calculateExtraEth,
|
|
5
|
+
} from '@exodus/ethereum-lib'
|
|
6
|
+
import assert from 'minimalistic-assert'
|
|
2
7
|
|
|
3
8
|
import {
|
|
4
9
|
ensureSaneEip1559GasPriceForTipGasPrice,
|
|
@@ -26,27 +31,68 @@ export const getExtraFeeData = ({ asset, amount }) => {
|
|
|
26
31
|
}
|
|
27
32
|
}
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
feeData = getNormalizedFeeDataForCustomFee({ customFee, feeData })
|
|
31
|
-
const gasPrice = customFee || resolveGasPrice({ feeData })
|
|
34
|
+
const getGasPricesResult = ({ gasPrice, feeData }) => {
|
|
32
35
|
const { tipGasPrice, eip1559Enabled } = feeData
|
|
33
|
-
|
|
34
|
-
// The `gasPrice` must be at least the `tipGasPrice`.
|
|
35
36
|
return {
|
|
36
37
|
gasPrice: eip1559Enabled
|
|
37
|
-
?
|
|
38
|
+
? // NOTE: The `gasPrice` must be at least the `tipGasPrice`.
|
|
39
|
+
ensureSaneEip1559GasPriceForTipGasPrice({ gasPrice, tipGasPrice })
|
|
38
40
|
: gasPrice,
|
|
39
41
|
feeData,
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
|
|
45
|
+
const getGasPricesForTxToReplace = ({ baseAsset, feeData, txToReplace }) => {
|
|
46
|
+
const { eip1559Enabled } = feeData
|
|
47
|
+
|
|
48
|
+
const effectiveGasPrice = resolveGasPrice({ feeData })
|
|
49
|
+
const { tipGasPrice: effectiveTipGasPrice } = feeData
|
|
50
|
+
|
|
51
|
+
const { bumpedGasPrice, bumpedTipGasPrice } = calculateBumpedGasPriceForFeeData({
|
|
52
|
+
baseAsset,
|
|
53
|
+
feeData,
|
|
54
|
+
tx: txToReplace,
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const gasPrice = bumpedGasPrice.gt(effectiveGasPrice) ? bumpedGasPrice : effectiveGasPrice
|
|
58
|
+
if (!eip1559Enabled) return getGasPricesResult({ gasPrice, feeData })
|
|
59
|
+
|
|
60
|
+
const tipGasPrice = bumpedTipGasPrice.gt(effectiveTipGasPrice)
|
|
61
|
+
? bumpedTipGasPrice
|
|
62
|
+
: effectiveTipGasPrice
|
|
63
|
+
|
|
64
|
+
return getGasPricesResult({
|
|
65
|
+
gasPrice,
|
|
66
|
+
feeData: { ...feeData, tipGasPrice },
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const getAggregateTransactionPricing = ({ baseAsset, customFee, feeData, txToReplace }) => {
|
|
71
|
+
assert(baseAsset, 'expected baseAsset')
|
|
72
|
+
|
|
73
|
+
if (customFee) {
|
|
74
|
+
return getGasPricesResult({
|
|
75
|
+
gasPrice: customFee,
|
|
76
|
+
feeData: getNormalizedFeeDataForCustomFee({ customFee, feeData }),
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (txToReplace) return getGasPricesForTxToReplace({ baseAsset, feeData, txToReplace })
|
|
81
|
+
|
|
82
|
+
return getGasPricesResult({
|
|
83
|
+
gasPrice: resolveGasPrice({ feeData }),
|
|
84
|
+
feeData,
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
43
88
|
export const getFeeFactory =
|
|
44
89
|
() =>
|
|
45
90
|
({ asset, feeData, customFee, txInput, gasLimit: providedGasLimit, amount }) => {
|
|
46
91
|
const {
|
|
47
92
|
feeData: { tipGasPrice, eip1559Enabled },
|
|
48
93
|
gasPrice,
|
|
49
|
-
} =
|
|
94
|
+
} = getAggregateTransactionPricing({
|
|
95
|
+
baseAsset: asset.baseAsset,
|
|
50
96
|
customFee,
|
|
51
97
|
feeData,
|
|
52
98
|
})
|
|
@@ -63,6 +109,7 @@ export const getFeeFactory =
|
|
|
63
109
|
return { ...maybeReturnTipGasPrice, fee, gasPrice, extraFeeData }
|
|
64
110
|
}
|
|
65
111
|
|
|
112
|
+
// TODO: sanity check this usage
|
|
66
113
|
// Used in Mobile
|
|
67
114
|
export const getExtraFeeForBump = ({ tx, feeData, balance, unconfirmedBalance }) => {
|
|
68
115
|
if (!balance || !unconfirmedBalance) return null
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { memoize } from '@exodus/basic-utils'
|
|
2
2
|
|
|
3
3
|
import { estimateGasLimit, scaleGasLimitEstimate } from '../../gas-estimation.js'
|
|
4
|
-
import {
|
|
4
|
+
import { getAggregateTransactionPricing } from '../../get-fee.js'
|
|
5
5
|
import { createWatchTx as defaultCreateWatch } from '../../watch-tx.js'
|
|
6
6
|
import { stakingProviderClientFactory } from '../staking-provider-client.js'
|
|
7
7
|
import {
|
|
@@ -315,7 +315,7 @@ export function createPolygonStakingService({
|
|
|
315
315
|
const erc20ApproveGas = 80_000
|
|
316
316
|
const delegateGas = 250_000
|
|
317
317
|
|
|
318
|
-
const { gasPrice } =
|
|
318
|
+
const { gasPrice } = getAggregateTransactionPricing({ baseAsset: ethereum, feeData })
|
|
319
319
|
|
|
320
320
|
const gasLimitWithBuffer = scaleGasLimitEstimate({
|
|
321
321
|
estimatedGasLimit: BigInt(erc20ApproveGas + delegateGas),
|
package/src/tx-create.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { currency2buffer, isEthereumLikeToken } from '@exodus/ethereum-lib'
|
|
2
2
|
import createEthereumJsTx from '@exodus/ethereum-lib/src/unsigned-tx/create-ethereumjs-tx.js'
|
|
3
3
|
import assert from 'minimalistic-assert'
|
|
4
4
|
|
|
5
5
|
import { ensureSaneEip1559GasPriceForTipGasPrice } from './fee-utils.js'
|
|
6
6
|
import { fetchGasLimit } from './gas-estimation.js'
|
|
7
|
-
import {
|
|
7
|
+
import { getAggregateTransactionPricing, getExtraFeeData } from './get-fee.js'
|
|
8
8
|
import { getNftArguments } from './nft-utils.js'
|
|
9
|
-
import {
|
|
9
|
+
import { getHighestIncentiveTxByNonce } from './tx-log/index.js'
|
|
10
10
|
import {
|
|
11
11
|
assertTxAttributes,
|
|
12
12
|
isValidTxType,
|
|
13
13
|
resolveTxAttributesByTxType,
|
|
14
14
|
resolveTxFromAddress,
|
|
15
|
+
resolveTxNonce,
|
|
15
16
|
TX_TYPE_TRANSFER,
|
|
16
17
|
} from './tx-type/index.js'
|
|
17
18
|
|
|
@@ -105,19 +106,40 @@ async function createUnsignedTxWithFees({
|
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
const resolveTxFactoryGasPrices = ({
|
|
109
|
+
const resolveTxFactoryGasPrices = async ({
|
|
110
|
+
assetClientInterface,
|
|
111
|
+
baseAsset,
|
|
109
112
|
customFee: providedCustomFee,
|
|
110
113
|
feeData,
|
|
111
114
|
gasPrice: providedGasPrice,
|
|
112
115
|
tipGasPrice: providedTipGasPrice,
|
|
116
|
+
txToReplace,
|
|
117
|
+
nonce,
|
|
118
|
+
walletAccount,
|
|
113
119
|
}) => {
|
|
114
|
-
assert(
|
|
120
|
+
assert(assetClientInterface, 'expected assetClientInterface')
|
|
121
|
+
assert(baseAsset, 'expected baseAsset')
|
|
122
|
+
assert(feeData, 'expected feeData')
|
|
123
|
+
assert(Number.isInteger(nonce), 'expected integer nonce')
|
|
124
|
+
assert(walletAccount, 'expected walletAccount')
|
|
115
125
|
|
|
116
126
|
const {
|
|
117
127
|
gasPrice: maybeGasPrice,
|
|
118
128
|
feeData: { tipGasPrice: maybeTipGasPrice, eip1559Enabled },
|
|
119
|
-
} =
|
|
129
|
+
} = getAggregateTransactionPricing({
|
|
130
|
+
baseAsset,
|
|
131
|
+
customFee: providedCustomFee,
|
|
132
|
+
feeData,
|
|
133
|
+
txToReplace,
|
|
134
|
+
})
|
|
120
135
|
|
|
136
|
+
// When we determine the `gasPrice` for a transaction, we must be
|
|
137
|
+
// cognizant of any transactions which are pending for the current
|
|
138
|
+
// `nonce`, as this may be higher compared to the current `gasPrice`
|
|
139
|
+
// that we are recommending from the network.
|
|
140
|
+
//
|
|
141
|
+
// In this instance, the `gasPrice` we recommend should be
|
|
142
|
+
// sufficient to avoid `replacement transaction underpriced` errors.
|
|
121
143
|
const resolvedGasPrice = providedGasPrice ?? maybeGasPrice
|
|
122
144
|
|
|
123
145
|
if (!eip1559Enabled) return { eip1559Enabled, resolvedGasPrice }
|
|
@@ -212,14 +234,7 @@ const createBumpUnsignedTx = async ({
|
|
|
212
234
|
|
|
213
235
|
const gasLimit = replacedTx.data.gasLimit
|
|
214
236
|
|
|
215
|
-
const {
|
|
216
|
-
gasPrice: currentGasPrice,
|
|
217
|
-
baseFeePerGas: currentBaseFee,
|
|
218
|
-
eip1559Enabled,
|
|
219
|
-
tipGasPrice: currentTipGasPrice,
|
|
220
|
-
} = feeData
|
|
221
|
-
|
|
222
|
-
const maybeHighestIncentivePendingTxForNonce = await getHighestIncentivePendingTxByNonce({
|
|
237
|
+
const maybeTxToReplace = await getHighestIncentiveTxByNonce({
|
|
223
238
|
assetClientInterface,
|
|
224
239
|
asset,
|
|
225
240
|
nonce: resolvedTxAttributes.nonce,
|
|
@@ -227,31 +242,23 @@ const createBumpUnsignedTx = async ({
|
|
|
227
242
|
})
|
|
228
243
|
|
|
229
244
|
assert(
|
|
230
|
-
|
|
245
|
+
maybeTxToReplace,
|
|
231
246
|
`unable to resolve pending transaction for nonce ${resolvedTxAttributes.nonce}`
|
|
232
247
|
)
|
|
233
248
|
|
|
234
|
-
const {
|
|
235
|
-
baseAsset,
|
|
236
|
-
// HACK: Although the `bumpTxId` defines the characteristics of
|
|
237
|
-
// of a transaction the user would like to accelerate, for
|
|
238
|
-
// acceleration to be successful, the transaction must be
|
|
239
|
-
// priced to exceed the miner incentive of whichever
|
|
240
|
-
// transaction is currently pending at the specified nonce.
|
|
241
|
-
tx: maybeHighestIncentivePendingTxForNonce,
|
|
242
|
-
currentGasPrice,
|
|
243
|
-
currentBaseFee,
|
|
244
|
-
currentTipGasPrice,
|
|
249
|
+
const {
|
|
245
250
|
eip1559Enabled,
|
|
251
|
+
resolvedGasPrice: gasPrice,
|
|
252
|
+
resolvedTipGasPrice: tipGasPrice,
|
|
253
|
+
} = await resolveTxFactoryGasPrices({
|
|
254
|
+
assetClientInterface,
|
|
255
|
+
baseAsset,
|
|
256
|
+
feeData,
|
|
257
|
+
nonce,
|
|
258
|
+
txToReplace: maybeTxToReplace,
|
|
259
|
+
walletAccount,
|
|
246
260
|
})
|
|
247
261
|
|
|
248
|
-
const { resolvedGasPrice: gasPrice, resolvedTipGasPrice: tipGasPrice } =
|
|
249
|
-
resolveTxFactoryGasPrices({
|
|
250
|
-
feeData,
|
|
251
|
-
gasPrice: bumpedGasPrice,
|
|
252
|
-
tipGasPrice: bumpedTipGasPrice,
|
|
253
|
-
})
|
|
254
|
-
|
|
255
262
|
return createUnsignedTxWithFees({
|
|
256
263
|
...resolvedTxAttributes,
|
|
257
264
|
asset,
|
|
@@ -289,10 +296,11 @@ export const createTxFactory = ({ chainId, assetClientInterface, useAbsoluteNonc
|
|
|
289
296
|
assert(walletAccount, 'walletAccount is required')
|
|
290
297
|
assert(isValidTxType(txType), 'invalid txType')
|
|
291
298
|
|
|
292
|
-
const
|
|
299
|
+
const baseAsset = asset.baseAsset
|
|
300
|
+
const feeData = await assetClientInterface.getFeeConfig({ assetName: baseAsset.name })
|
|
293
301
|
|
|
294
302
|
const baseAssetTxLog = await assetClientInterface.getTxLog({
|
|
295
|
-
assetName:
|
|
303
|
+
assetName: baseAsset.name,
|
|
296
304
|
walletAccount,
|
|
297
305
|
})
|
|
298
306
|
|
|
@@ -318,15 +326,34 @@ export const createTxFactory = ({ chainId, assetClientInterface, useAbsoluteNonc
|
|
|
318
326
|
})
|
|
319
327
|
}
|
|
320
328
|
|
|
329
|
+
const nonce = await resolveTxNonce({
|
|
330
|
+
asset,
|
|
331
|
+
fromAddress,
|
|
332
|
+
nonce: providedNonce,
|
|
333
|
+
walletAccount,
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
const maybeTxToReplace = await getHighestIncentiveTxByNonce({
|
|
337
|
+
assetClientInterface,
|
|
338
|
+
asset: baseAsset,
|
|
339
|
+
nonce,
|
|
340
|
+
walletAccount,
|
|
341
|
+
})
|
|
342
|
+
|
|
321
343
|
const {
|
|
322
344
|
eip1559Enabled,
|
|
323
345
|
resolvedGasPrice: gasPrice,
|
|
324
346
|
resolvedTipGasPrice: tipGasPrice,
|
|
325
|
-
} = resolveTxFactoryGasPrices({
|
|
347
|
+
} = await resolveTxFactoryGasPrices({
|
|
348
|
+
assetClientInterface,
|
|
349
|
+
baseAsset,
|
|
326
350
|
customFee: providedCustomFee,
|
|
327
351
|
feeData,
|
|
328
352
|
gasPrice: providedGasPrice,
|
|
353
|
+
nonce,
|
|
329
354
|
tipGasPrice: providedTipGasPrice,
|
|
355
|
+
txToReplace: maybeTxToReplace,
|
|
356
|
+
walletAccount,
|
|
330
357
|
})
|
|
331
358
|
|
|
332
359
|
if (nft) {
|
|
@@ -342,10 +369,10 @@ export const createTxFactory = ({ chainId, assetClientInterface, useAbsoluteNonc
|
|
|
342
369
|
})
|
|
343
370
|
|
|
344
371
|
const resolvedTxAttributes = await resolveTxAttributesByTxType({
|
|
345
|
-
asset:
|
|
372
|
+
asset: baseAsset,
|
|
346
373
|
assetClientInterface,
|
|
347
374
|
fromAddress,
|
|
348
|
-
nonce
|
|
375
|
+
nonce,
|
|
349
376
|
txInput,
|
|
350
377
|
toAddress: providedToAddress,
|
|
351
378
|
txToAddress,
|
|
@@ -369,7 +396,7 @@ export const createTxFactory = ({ chainId, assetClientInterface, useAbsoluteNonc
|
|
|
369
396
|
assetClientInterface,
|
|
370
397
|
amount: providedAmount,
|
|
371
398
|
fromAddress,
|
|
372
|
-
nonce
|
|
399
|
+
nonce,
|
|
373
400
|
txInput: providedTxInput,
|
|
374
401
|
toAddress: providedToAddress,
|
|
375
402
|
txType,
|
|
@@ -6,7 +6,12 @@ import assert from 'minimalistic-assert'
|
|
|
6
6
|
|
|
7
7
|
// Returns the most competitively priced pending
|
|
8
8
|
// transaction from the `TxLog` for a given `nonce`.
|
|
9
|
-
|
|
9
|
+
//
|
|
10
|
+
// NOTE: If a transaction was successfully included,
|
|
11
|
+
// it is the de-facto highest incentive
|
|
12
|
+
// transaction - irrespective of other
|
|
13
|
+
// attempts for that nonce.
|
|
14
|
+
export const getHighestIncentiveTxByNonce = async ({
|
|
10
15
|
assetClientInterface,
|
|
11
16
|
asset,
|
|
12
17
|
nonce,
|
|
@@ -17,17 +22,29 @@ export const getHighestIncentivePendingTxByNonce = async ({
|
|
|
17
22
|
assert(Number.isInteger(nonce), 'expected integer nonce')
|
|
18
23
|
assert(walletAccount, 'expected walletAccount')
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
const isUnconfirmed = (tx) => !tx.failed && tx.pending
|
|
22
|
-
|
|
23
|
-
const [maybeHighestIncentiveTx] = [
|
|
25
|
+
const txLogSendsByFeeAmountDesc = [
|
|
24
26
|
...(await assetClientInterface.getTxLog({ assetName: asset.name, walletAccount })),
|
|
25
27
|
]
|
|
26
|
-
.filter(isUnconfirmed)
|
|
27
28
|
.filter((tx) => tx.data.nonce === nonce && tx.sent)
|
|
28
29
|
.sort((a, b) => (a.feeAmount.gt(b.feeAmount) ? -1 : b.feeAmount.gt(a.feeAmount) ? 1 : 0))
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
// If any of the transactions competing for this `nonce`
|
|
32
|
+
// were successful, then we can return this transaction
|
|
33
|
+
// as it effectively had the highest game-theoretical
|
|
34
|
+
// incentive regardless of other (potentially higher fee)
|
|
35
|
+
// transactions that were sent.
|
|
36
|
+
//
|
|
37
|
+
// https://github.com/ExodusMovement/exodus-hydra/blob/e59004097f15974a975d14e1823de5d7b1c28308/features/activity-txs/redux/utils/activity-formatters/format-tx-activity.js#L13
|
|
38
|
+
const maybeConfirmedTx = txLogSendsByFeeAmountDesc.find((tx) => !tx.failed && !tx.pending)
|
|
39
|
+
if (maybeConfirmedTx) return maybeConfirmedTx
|
|
40
|
+
|
|
41
|
+
// https://github.com/ExodusMovement/assets/blob/fbe3702861cba3b21885a65b15f038fcd8541891/shield/asset-lib/src/balances-utils.js#L26
|
|
42
|
+
const isUnconfirmed = (tx) => !tx.failed && tx.pending
|
|
43
|
+
|
|
44
|
+
// NOTE: When trying to find the highest incentive of a
|
|
45
|
+
// transaction, consider those which are either still
|
|
46
|
+
// pending.
|
|
47
|
+
return txLogSendsByFeeAmountDesc.find(isUnconfirmed)
|
|
31
48
|
}
|
|
32
49
|
|
|
33
50
|
export const getOptimisticTxLogEffects = async ({
|
|
@@ -77,7 +94,7 @@ export const getOptimisticTxLogEffects = async ({
|
|
|
77
94
|
|
|
78
95
|
const baseAsset = asset.baseAsset
|
|
79
96
|
|
|
80
|
-
const maybeTxToReplace = await
|
|
97
|
+
const maybeTxToReplace = await getHighestIncentiveTxByNonce({
|
|
81
98
|
asset,
|
|
82
99
|
assetClientInterface,
|
|
83
100
|
nonce,
|
package/src/tx-log/index.js
CHANGED
|
@@ -3,5 +3,5 @@ export { EthereumNoHistoryMonitor } from './ethereum-no-history-monitor.js'
|
|
|
3
3
|
export { ClarityMonitor } from './clarity-monitor.js'
|
|
4
4
|
export {
|
|
5
5
|
getOptimisticTxLogEffects,
|
|
6
|
-
|
|
6
|
+
getHighestIncentiveTxByNonce,
|
|
7
7
|
} from './get-optimistic-txlog-effects.js'
|
package/src/tx-send/tx-send.js
CHANGED
|
@@ -63,7 +63,7 @@ const txSendFactory = ({ assetClientInterface, createTx }) => {
|
|
|
63
63
|
const insufficientFundsErr = err.message.match(/insufficient funds/i)
|
|
64
64
|
const txAlreadyExists = nonceTooLowErr
|
|
65
65
|
? await transactionExists({ asset, txId })
|
|
66
|
-
: err.message.match(/already known/i)
|
|
66
|
+
: err.message.match(/already known/i) || err.message.match(/transaction already imported/i)
|
|
67
67
|
|
|
68
68
|
if (txAlreadyExists) {
|
|
69
69
|
console.info('tx already broadcast') // inject logger factory from platform
|
package/src/tx-type/index.js
CHANGED
|
@@ -121,7 +121,12 @@ export const resolveTxFromAddress = async ({
|
|
|
121
121
|
})
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
const resolveTxNonce = async ({
|
|
124
|
+
export const resolveTxNonce = async ({
|
|
125
|
+
asset,
|
|
126
|
+
fromAddress,
|
|
127
|
+
nonce: providedNonce,
|
|
128
|
+
walletAccount,
|
|
129
|
+
}) => {
|
|
125
130
|
assert(asset, 'expected asset')
|
|
126
131
|
assert(typeof fromAddress === 'string', 'expected string fromAddress')
|
|
127
132
|
assert(walletAccount, 'expected walletAccount')
|