@exodus/ethereum-api 8.54.1 → 8.56.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 +26 -0
- package/package.json +4 -4
- package/src/staking/ethereum/service.js +55 -17
- package/src/tx-send/tx-send.js +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,32 @@
|
|
|
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.56.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.55.0...@exodus/ethereum-api@8.56.0) (2025-11-04)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
* feat: monad-testnet (#6706)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## [8.55.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.54.1...@exodus/ethereum-api@8.55.0) (2025-11-03)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
* feat: bump @exodus/safe-string@1.2.1 (#6775)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Bug Fixes
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
* fix: enable `update-nonce` to work for `unsignedTx`s that lack a `transactionBuffer` (#6832)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
6
32
|
## [8.54.1](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.54.0...@exodus/ethereum-api@8.54.1) (2025-10-24)
|
|
7
33
|
|
|
8
34
|
**Note:** Version bump only for package @exodus/ethereum-api
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/ethereum-api",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.56.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,13 +29,13 @@
|
|
|
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.18.
|
|
32
|
+
"@exodus/ethereum-lib": "^5.18.5",
|
|
33
33
|
"@exodus/ethereum-meta": "^2.9.1",
|
|
34
34
|
"@exodus/ethereumholesky-meta": "^2.0.5",
|
|
35
35
|
"@exodus/ethereumjs": "^1.8.0",
|
|
36
36
|
"@exodus/fetch": "^1.3.0",
|
|
37
37
|
"@exodus/models": "^12.13.0",
|
|
38
|
-
"@exodus/safe-string": "^1.2.
|
|
38
|
+
"@exodus/safe-string": "^1.2.1",
|
|
39
39
|
"@exodus/simple-retry": "^0.0.6",
|
|
40
40
|
"@exodus/solidity-contract": "^1.3.0",
|
|
41
41
|
"@exodus/web3-ethereum-utils": "^4.5.1",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"type": "git",
|
|
68
68
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "7d384b740c90be9f6c39a4dcfe33508b27b5ea7a"
|
|
71
71
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { memoize } from '@exodus/basic-utils'
|
|
2
|
+
import assert from 'minimalistic-assert'
|
|
3
|
+
|
|
1
4
|
import { estimateGasLimit, scaleGasLimitEstimate } from '../../gas-estimation.js'
|
|
2
5
|
import { createWatchTx as defaultCreateWatch } from '../../watch-tx.js'
|
|
3
6
|
import { stakingProviderClientFactory } from '../staking-provider-client.js'
|
|
@@ -20,20 +23,34 @@ const MINIMUM_DELEGATION_GAS_LIMIT = 180_000
|
|
|
20
23
|
|
|
21
24
|
const EXTRA_GAS_LIMIT = 20_000 // extra gas Limit to prevent tx failing if something change on pool state (till tx is in mempool)
|
|
22
25
|
|
|
26
|
+
const getStakingApi = memoize(
|
|
27
|
+
(asset) => new EthereumStaking(asset, undefined, asset.server),
|
|
28
|
+
(asset) => asset.name
|
|
29
|
+
)
|
|
30
|
+
|
|
23
31
|
export function createEthereumStakingService({
|
|
24
|
-
asset,
|
|
32
|
+
asset: deprectedArg, // @deprecated use `assetName` instead
|
|
33
|
+
assetName,
|
|
25
34
|
assetClientInterface,
|
|
26
35
|
createWatchTx = defaultCreateWatch,
|
|
27
36
|
stakingProvider = stakingProviderClientFactory(),
|
|
28
37
|
}) {
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
if (deprectedArg && !assetName) {
|
|
39
|
+
console.log('using deprecated ARG `asset` instead of `assetName`')
|
|
40
|
+
assetName = deprectedArg.name
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const getAsset = memoize(async (baseAssetName) => {
|
|
44
|
+
const { [assetName]: asset } = await assetClientInterface.getAssetsForNetwork({ baseAssetName })
|
|
45
|
+
return asset
|
|
46
|
+
})
|
|
31
47
|
|
|
32
48
|
const getTransactionProps = async ({ feeData, walletAccount }) => {
|
|
49
|
+
const asset = await getAsset(assetName)
|
|
33
50
|
let address
|
|
34
51
|
;[address, feeData] = await Promise.all([
|
|
35
52
|
assetClientInterface.getReceiveAddress({
|
|
36
|
-
assetName
|
|
53
|
+
assetName,
|
|
37
54
|
walletAccount,
|
|
38
55
|
}),
|
|
39
56
|
resolveFeeData({ asset, assetClientInterface, feeData }),
|
|
@@ -44,6 +61,8 @@ export function createEthereumStakingService({
|
|
|
44
61
|
}
|
|
45
62
|
|
|
46
63
|
async function delegate({ walletAccount, amount, feeData } = Object.create(null)) {
|
|
64
|
+
const asset = await getAsset(assetName)
|
|
65
|
+
const staking = getStakingApi(asset)
|
|
47
66
|
amount = amountToCurrency({ asset, amount })
|
|
48
67
|
|
|
49
68
|
let delegatorAddress
|
|
@@ -78,10 +97,10 @@ export function createEthereumStakingService({
|
|
|
78
97
|
})
|
|
79
98
|
|
|
80
99
|
// Goerli is not supported
|
|
81
|
-
if (
|
|
100
|
+
if (assetName === 'ethereum') {
|
|
82
101
|
await stakingProvider.notifyStaking({
|
|
83
102
|
txId,
|
|
84
|
-
asset:
|
|
103
|
+
asset: assetName,
|
|
85
104
|
delegator: delegatorAddress,
|
|
86
105
|
amount: amount.toBaseString(),
|
|
87
106
|
})
|
|
@@ -97,6 +116,8 @@ export function createEthereumStakingService({
|
|
|
97
116
|
minAmount,
|
|
98
117
|
feeData,
|
|
99
118
|
}) {
|
|
119
|
+
const asset = await getAsset(assetName)
|
|
120
|
+
const staking = getStakingApi(asset)
|
|
100
121
|
const leftOver = pendingAmount.sub(resquestedAmount)
|
|
101
122
|
|
|
102
123
|
if (leftOver.isPositive && leftOver.lt(minAmount)) {
|
|
@@ -126,6 +147,8 @@ export function createEthereumStakingService({
|
|
|
126
147
|
}
|
|
127
148
|
|
|
128
149
|
async function getUndelegateData({ delegatorAddress, resquestedAmount, pendingAmount, feeData }) {
|
|
150
|
+
const asset = await getAsset(assetName)
|
|
151
|
+
const staking = getStakingApi(asset)
|
|
129
152
|
const canUnstake = resquestedAmount.gt(pendingAmount)
|
|
130
153
|
|
|
131
154
|
if (!canUnstake) {
|
|
@@ -159,6 +182,10 @@ export function createEthereumStakingService({
|
|
|
159
182
|
* @returns total undelegete fee
|
|
160
183
|
*/
|
|
161
184
|
async function estimateUndelegate({ walletAccount, amount: resquestedAmount, feeData }) {
|
|
185
|
+
const asset = await getAsset(assetName)
|
|
186
|
+
const staking = getStakingApi(asset)
|
|
187
|
+
const minAmount = getMinAmount(asset)
|
|
188
|
+
|
|
162
189
|
let delegatorAddress
|
|
163
190
|
;({ feeData, delegatorAddress } = await getTransactionProps({ feeData, walletAccount }))
|
|
164
191
|
|
|
@@ -197,6 +224,10 @@ export function createEthereumStakingService({
|
|
|
197
224
|
async function undelegate(
|
|
198
225
|
{ walletAccount, amount, feeData, waitForConfirmation = true } = Object.create(null)
|
|
199
226
|
) {
|
|
227
|
+
const asset = await getAsset(assetName)
|
|
228
|
+
const staking = getStakingApi(asset)
|
|
229
|
+
const minAmount = getMinAmount(asset)
|
|
230
|
+
|
|
200
231
|
/*
|
|
201
232
|
unstakePending balance (not yet in validator) + unstake balance (in validator)
|
|
202
233
|
1. give priority to unstakePending (based on the amount)
|
|
@@ -238,7 +269,7 @@ export function createEthereumStakingService({
|
|
|
238
269
|
//
|
|
239
270
|
// NOTE: This will invalidate previous transaction fee estimates!
|
|
240
271
|
if (waitForConfirmation) {
|
|
241
|
-
feeData = await assetClientInterface.getFeeData({ assetName
|
|
272
|
+
feeData = await assetClientInterface.getFeeData({ assetName })
|
|
242
273
|
}
|
|
243
274
|
}
|
|
244
275
|
|
|
@@ -260,10 +291,10 @@ export function createEthereumStakingService({
|
|
|
260
291
|
}
|
|
261
292
|
|
|
262
293
|
// Testnet assets do not support delegations tracking
|
|
263
|
-
if (txId &&
|
|
294
|
+
if (txId && assetName === 'ethereum') {
|
|
264
295
|
await stakingProvider.notifyUnstaking({
|
|
265
296
|
txId,
|
|
266
|
-
asset:
|
|
297
|
+
asset: assetName,
|
|
267
298
|
delegator: delegatorAddress,
|
|
268
299
|
amount: resquestedAmount.toBaseString(),
|
|
269
300
|
})
|
|
@@ -273,6 +304,9 @@ export function createEthereumStakingService({
|
|
|
273
304
|
}
|
|
274
305
|
|
|
275
306
|
async function claimUndelegatedBalance({ walletAccount, feeData } = Object.create(null)) {
|
|
307
|
+
const asset = await getAsset(assetName)
|
|
308
|
+
const staking = getStakingApi(asset)
|
|
309
|
+
|
|
276
310
|
let delegatorAddress
|
|
277
311
|
;({ feeData, delegatorAddress } = await getTransactionProps({ feeData, walletAccount }))
|
|
278
312
|
|
|
@@ -304,6 +338,9 @@ export function createEthereumStakingService({
|
|
|
304
338
|
}
|
|
305
339
|
|
|
306
340
|
async function estimateDelegateOperation({ walletAccount, operation, args, feeData }) {
|
|
341
|
+
const asset = await getAsset(assetName)
|
|
342
|
+
const staking = getStakingApi(asset)
|
|
343
|
+
|
|
307
344
|
const requestedAmount = args.amount
|
|
308
345
|
? amountToCurrency({ asset, amount: args.amount })
|
|
309
346
|
: asset.currency.ZERO
|
|
@@ -360,6 +397,8 @@ export function createEthereumStakingService({
|
|
|
360
397
|
}
|
|
361
398
|
|
|
362
399
|
async function estimateTxFee({ from, to, amount, txInput, feeData }) {
|
|
400
|
+
const asset = await getAsset(assetName)
|
|
401
|
+
|
|
363
402
|
amount = amount || asset.currency.ZERO
|
|
364
403
|
from = from.toLowerCase()
|
|
365
404
|
|
|
@@ -395,18 +434,17 @@ export function createEthereumStakingService({
|
|
|
395
434
|
}
|
|
396
435
|
|
|
397
436
|
/** Returns the minimum possible amount that can be staked. */
|
|
398
|
-
function getMinAmount() {
|
|
399
|
-
|
|
437
|
+
function getMinAmount(asset) {
|
|
438
|
+
assert(asset, 'getMinAmount: `asset` is required')
|
|
439
|
+
return getStakingApi(asset).minAmount
|
|
400
440
|
}
|
|
401
441
|
|
|
402
442
|
/** Determine the maximum possible stake for a given spendable amount. */
|
|
403
|
-
async function getDelegateSelectAllAmount({
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
feeData,
|
|
407
|
-
}) {
|
|
408
|
-
const minAmount = getMinAmount()
|
|
443
|
+
async function getDelegateSelectAllAmount({ walletAccount, spendableForStaking, feeData }) {
|
|
444
|
+
const asset = await getAsset(assetName)
|
|
445
|
+
const minAmount = getMinAmount(asset)
|
|
409
446
|
|
|
447
|
+
if (!spendableForStaking) spendableForStaking = asset.currency.ZERO
|
|
410
448
|
;({ feeData } = await getTransactionProps({ feeData, walletAccount }))
|
|
411
449
|
|
|
412
450
|
// If the caller hasn't specified a value of `spendableForStaking`
|
package/src/tx-send/tx-send.js
CHANGED
|
@@ -37,6 +37,10 @@ const txSendFactory = ({ assetClientInterface, createTx }) => {
|
|
|
37
37
|
})
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
// NOTE: An `unsignedTx.txData.transactionBuffer` may be optional
|
|
41
|
+
// in `unsignedTx`, since a `providedUnsignedTx` may be
|
|
42
|
+
// truthy but composed only of `legacyParams`:
|
|
43
|
+
// https://github.com/ExodusMovement/assets/blob/4e3e873e3f5bfa8fce36f60be7d95a3dba9546e4/ethereum/ethereum-lib/src/unsigned-tx/parse-unsigned-tx.js#L104C5-L104C6
|
|
40
44
|
const { unsignedTx } = await resolveUnsignedTx()
|
|
41
45
|
|
|
42
46
|
const parsedTx = parseUnsignedTx({ asset, unsignedTx })
|
|
@@ -96,10 +100,11 @@ const txSendFactory = ({ assetClientInterface, createTx }) => {
|
|
|
96
100
|
forceFromNode: true,
|
|
97
101
|
})
|
|
98
102
|
|
|
103
|
+
// TODO: should return an unsignedTx -> i.e. completely replicate the transaction
|
|
99
104
|
unsignedTx.txData.transactionBuffer = updateNonce({
|
|
100
105
|
chainId: baseAsset.chainId,
|
|
101
|
-
transactionBuffer: unsignedTx.txData.transactionBuffer,
|
|
102
106
|
newNonce,
|
|
107
|
+
unsignedTx,
|
|
103
108
|
})
|
|
104
109
|
;({ txId, rawTx } = await signTx({ asset, unsignedTx, walletAccount }))
|
|
105
110
|
|