@exodus/ethereum-api 8.41.0 → 8.42.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 +10 -0
- package/package.json +2 -2
- package/src/allowance/index.js +59 -30
- package/src/create-asset-utils.js +31 -0
- package/src/create-asset.js +4 -0
- package/src/index.js +1 -0
- package/src/tx-send/tx-send.js +1 -11
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
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.42.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.41.0...@exodus/ethereum-api@8.42.0) (2025-07-10)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
* feat: rig `getNonce` to evm asset api (#6047)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
6
16
|
## [8.41.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.40.1...@exodus/ethereum-api@8.41.0) (2025-07-01)
|
|
7
17
|
|
|
8
18
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/ethereum-api",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.42.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",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"type": "git",
|
|
64
64
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "6bd56e57bee720ffef602f57421eae67e42e190c"
|
|
67
67
|
}
|
package/src/allowance/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { isNumberUnit } from '@exodus/currency'
|
|
2
|
+
import assert from 'minimalistic-assert'
|
|
3
|
+
|
|
1
4
|
import { getServer } from '../exodus-eth-server/index.js'
|
|
2
5
|
import { fetchGasLimit } from '../gas-estimation.js'
|
|
3
6
|
import { ALLOWANCE_TX_TIMEOUT, APPROVAL_GAS_LIMIT, ZERO_ALLOWANCE_ASSETS } from './constants.js'
|
|
@@ -27,6 +30,52 @@ export async function isSpendingApprovalRequired({
|
|
|
27
30
|
return tokenAmount.gt(allowance)
|
|
28
31
|
}
|
|
29
32
|
|
|
33
|
+
export const buildApproveTx = async ({
|
|
34
|
+
spenderAddress,
|
|
35
|
+
asset,
|
|
36
|
+
feeData,
|
|
37
|
+
fromAddress,
|
|
38
|
+
approveAmount = asset.currency.ZERO,
|
|
39
|
+
gasLimit,
|
|
40
|
+
txInput,
|
|
41
|
+
}) => {
|
|
42
|
+
assert(asset, 'expected asset')
|
|
43
|
+
assert(feeData, 'expected feeData')
|
|
44
|
+
assert(isNumberUnit(approveAmount), 'expected approveAmount')
|
|
45
|
+
assert(typeof spenderAddress === 'string', 'expected spenderAddress')
|
|
46
|
+
|
|
47
|
+
const baseAsset = asset.baseAsset
|
|
48
|
+
const toAddress = asset.contract.address
|
|
49
|
+
|
|
50
|
+
if (!txInput) txInput = asset.contract.approve.build(spenderAddress, approveAmount.toBaseString())
|
|
51
|
+
|
|
52
|
+
if (!gasLimit)
|
|
53
|
+
gasLimit = await fetchGasLimit({
|
|
54
|
+
asset: baseAsset,
|
|
55
|
+
amount: baseAsset.currency.ZERO,
|
|
56
|
+
toAddress,
|
|
57
|
+
txInput,
|
|
58
|
+
feeData,
|
|
59
|
+
isContract: true,
|
|
60
|
+
fromAddress,
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
asset: baseAsset.name,
|
|
65
|
+
receiver: {
|
|
66
|
+
address: toAddress,
|
|
67
|
+
amount: baseAsset.currency.ZERO,
|
|
68
|
+
},
|
|
69
|
+
txInput,
|
|
70
|
+
gasPrice: feeData.gasPrice,
|
|
71
|
+
tipGasPrice: feeData.tipGasPrice,
|
|
72
|
+
gasLimit,
|
|
73
|
+
silent: true,
|
|
74
|
+
fromAddress,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// @deprecated use buildApproveTx instead
|
|
30
79
|
export const createApprove =
|
|
31
80
|
({ sendTx }) =>
|
|
32
81
|
async ({
|
|
@@ -36,43 +85,23 @@ export const createApprove =
|
|
|
36
85
|
fromAddress,
|
|
37
86
|
approveAmount,
|
|
38
87
|
gasLimit,
|
|
39
|
-
txInput
|
|
40
|
-
...
|
|
88
|
+
txInput,
|
|
89
|
+
...extras
|
|
41
90
|
}) => {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const toAddress = asset.contract.address
|
|
47
|
-
const gasLimitOptions = {
|
|
48
|
-
asset: baseAsset,
|
|
49
|
-
amount: baseAsset.currency.ZERO,
|
|
50
|
-
toAddress,
|
|
51
|
-
txInput,
|
|
91
|
+
const approveTx = await buildApproveTx({
|
|
92
|
+
spenderAddress,
|
|
93
|
+
asset,
|
|
52
94
|
feeData,
|
|
53
|
-
isContract: true,
|
|
54
95
|
fromAddress,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
gasLimit = gasLimit || (await fetchGasLimit(gasLimitOptions))
|
|
58
|
-
|
|
59
|
-
const txData = await sendTx({
|
|
60
|
-
asset: baseAsset.name,
|
|
61
|
-
receiver: {
|
|
62
|
-
address: toAddress,
|
|
63
|
-
amount: baseAsset.currency.ZERO,
|
|
64
|
-
},
|
|
65
|
-
txInput,
|
|
66
|
-
gasPrice: feeData.gasPrice,
|
|
96
|
+
approveAmount,
|
|
67
97
|
gasLimit,
|
|
68
|
-
|
|
69
|
-
fromAddress,
|
|
70
|
-
...rest,
|
|
98
|
+
txInput,
|
|
71
99
|
})
|
|
72
100
|
|
|
73
|
-
|
|
101
|
+
const txData = await sendTx({ ...extras, ...approveTx })
|
|
102
|
+
|
|
103
|
+
if (!txData || !txData.txId)
|
|
74
104
|
throw new Error(`Failed to approve ${asset.displayTicker} - ${spenderAddress}`)
|
|
75
|
-
}
|
|
76
105
|
|
|
77
106
|
return txData
|
|
78
107
|
}
|
|
@@ -6,6 +6,7 @@ import { createEthereumHooks } from './hooks/index.js'
|
|
|
6
6
|
import { ClarityMonitor } from './tx-log/clarity-monitor.js'
|
|
7
7
|
import { EthereumMonitor } from './tx-log/ethereum-monitor.js'
|
|
8
8
|
import { EthereumNoHistoryMonitor } from './tx-log/ethereum-no-history-monitor.js'
|
|
9
|
+
import { resolveNonce } from './tx-send/nonce-utils.js'
|
|
9
10
|
|
|
10
11
|
// Determines the appropriate `monitorType`, `serverUrl` and `monitorInterval`
|
|
11
12
|
// to use for a given config.
|
|
@@ -151,3 +152,33 @@ export const createHistoryMonitorFactory = ({
|
|
|
151
152
|
return monitor
|
|
152
153
|
}
|
|
153
154
|
}
|
|
155
|
+
|
|
156
|
+
export const getNonceFactory = ({ assetClientInterface, useAbsoluteBalanceAndNonce }) => {
|
|
157
|
+
assert(assetClientInterface, 'expected assetClientInterface')
|
|
158
|
+
assert(typeof useAbsoluteBalanceAndNonce === 'boolean', 'expected useAbsoluteBalanceAndNonce')
|
|
159
|
+
|
|
160
|
+
const getNonce = async ({ asset, fromAddress, walletAccount }) => {
|
|
161
|
+
assert(asset, 'expected asset')
|
|
162
|
+
assert(typeof fromAddress === 'string', 'expected fromAddress')
|
|
163
|
+
assert(walletAccount, 'expected walletAccount')
|
|
164
|
+
|
|
165
|
+
const txLog = await assetClientInterface.getTxLog({
|
|
166
|
+
assetName: asset.baseAsset.name,
|
|
167
|
+
walletAccount,
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
return resolveNonce({
|
|
171
|
+
asset,
|
|
172
|
+
fromAddress,
|
|
173
|
+
txLog,
|
|
174
|
+
// For assets where we'll fall back to querying the coin node, we
|
|
175
|
+
// search for pending transactions. For base assets with history,
|
|
176
|
+
// we'll fall back to the `TxLog` since this also has a knowledge
|
|
177
|
+
// of which transactions are currently in pending.
|
|
178
|
+
tag: 'pending',
|
|
179
|
+
useAbsoluteNonce: useAbsoluteBalanceAndNonce,
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return { getNonce }
|
|
184
|
+
}
|
package/src/create-asset.js
CHANGED
|
@@ -24,6 +24,7 @@ import { addressHasHistoryFactory } from './address-has-history.js'
|
|
|
24
24
|
import {
|
|
25
25
|
createHistoryMonitorFactory,
|
|
26
26
|
createTransactionPrivacyFactory,
|
|
27
|
+
getNonceFactory,
|
|
27
28
|
resolveMonitorSettings,
|
|
28
29
|
} from './create-asset-utils.js'
|
|
29
30
|
import { createTokenFactory } from './create-token-factory.js'
|
|
@@ -237,6 +238,8 @@ export const createAssetFactory = ({
|
|
|
237
238
|
? getL1GetFeeFactory({ asset, originalGetFee })
|
|
238
239
|
: originalGetFee
|
|
239
240
|
|
|
241
|
+
const { getNonce } = getNonceFactory({ assetClientInterface, useAbsoluteBalanceAndNonce })
|
|
242
|
+
|
|
240
243
|
const api = {
|
|
241
244
|
addressHasHistory,
|
|
242
245
|
broadcastTx: (...args) => server.sendRawTransaction(...args),
|
|
@@ -293,6 +296,7 @@ export const createAssetFactory = ({
|
|
|
293
296
|
broadcastPrivateBundle,
|
|
294
297
|
broadcastPrivateTx,
|
|
295
298
|
forceGasLimitEstimation,
|
|
299
|
+
getNonce,
|
|
296
300
|
privacyServer,
|
|
297
301
|
server,
|
|
298
302
|
...(erc20FuelBuffer && { erc20FuelBuffer }),
|
package/src/index.js
CHANGED
package/src/tx-send/tx-send.js
CHANGED
|
@@ -204,17 +204,7 @@ const txSendFactory = ({ assetClientInterface, createUnsignedTx, useAbsoluteBala
|
|
|
204
204
|
const resolvedNonce =
|
|
205
205
|
providedNonce ??
|
|
206
206
|
bumpNonce ??
|
|
207
|
-
(await
|
|
208
|
-
asset,
|
|
209
|
-
fromAddress,
|
|
210
|
-
txLog: baseAssetTxLog,
|
|
211
|
-
// For assets where we'll fall back to querying the coin node, we
|
|
212
|
-
// search for pending transactions. For base assets with history,
|
|
213
|
-
// we'll fall back to the `TxLog` since this also has a knowledge
|
|
214
|
-
// of which transactions are currently in pending.
|
|
215
|
-
tag: 'pending',
|
|
216
|
-
useAbsoluteNonce: useAbsoluteBalanceAndNonce,
|
|
217
|
-
}))
|
|
207
|
+
(await asset.baseAsset.getNonce({ asset, fromAddress, walletAccount }))
|
|
218
208
|
|
|
219
209
|
const createTxParams = {
|
|
220
210
|
assetClientInterface,
|