@exodus/ethereum-api 8.62.2 → 8.62.3
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
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.62.3](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.62.2...@exodus/ethereum-api@8.62.3) (2026-01-13)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
* fix: enfore sanity checking about clarity string numerics for canonical tx props (#7262)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
6
16
|
## [8.62.2](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.62.1...@exodus/ethereum-api@8.62.2) (2026-01-07)
|
|
7
17
|
|
|
8
18
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/ethereum-api",
|
|
3
|
-
"version": "8.62.
|
|
3
|
+
"version": "8.62.3",
|
|
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",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"type": "git",
|
|
68
68
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "d1618b4c41ccde490c3e4aaa8dd239c0c5393a7b"
|
|
71
71
|
}
|
|
@@ -23,6 +23,14 @@ const MINIMUM_DELEGATION_GAS_LIMIT = 180_000
|
|
|
23
23
|
|
|
24
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)
|
|
25
25
|
|
|
26
|
+
// Estimates based on real life transaction averages.
|
|
27
|
+
// Overestimated averages by 4x.
|
|
28
|
+
const STAKING_OPERATION_FALLBACK_FEE_ESTIMATES = {
|
|
29
|
+
delegate: '0.00081512',
|
|
30
|
+
undelegate: '0.000554',
|
|
31
|
+
claimUndelegatedBalance: '0.0001800912',
|
|
32
|
+
}
|
|
33
|
+
|
|
26
34
|
const getStakingApi = memoize(
|
|
27
35
|
(asset) => new EthereumStaking(asset, undefined, asset.server),
|
|
28
36
|
(asset) => asset.name
|
|
@@ -346,61 +354,76 @@ export function createEthereumStakingService({
|
|
|
346
354
|
|
|
347
355
|
async function estimateDelegateOperation({ walletAccount, operation, args, feeData }) {
|
|
348
356
|
const asset = await getAsset(assetName)
|
|
349
|
-
const staking = getStakingApi(asset)
|
|
350
|
-
|
|
351
|
-
const requestedAmount = args.amount
|
|
352
|
-
? amountToCurrency({ asset, amount: args.amount })
|
|
353
|
-
: asset.currency.ZERO
|
|
354
357
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
if (operation === 'undelegate') {
|
|
359
|
-
return estimateUndelegate({ walletAccount, amount: requestedAmount, feeData })
|
|
360
|
-
}
|
|
358
|
+
try {
|
|
359
|
+
const staking = getStakingApi(asset)
|
|
361
360
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
claimUndelegatedBalance: 'claimWithdrawRequest',
|
|
366
|
-
}
|
|
361
|
+
const requestedAmount = args.amount
|
|
362
|
+
? amountToCurrency({ asset, amount: args.amount })
|
|
363
|
+
: asset.currency.ZERO
|
|
367
364
|
|
|
368
|
-
|
|
365
|
+
let delegatorAddress
|
|
366
|
+
;({ delegatorAddress, feeData } = await getTransactionProps({ feeData, walletAccount }))
|
|
369
367
|
|
|
370
|
-
|
|
368
|
+
if (operation === 'undelegate') {
|
|
369
|
+
return estimateUndelegate({ walletAccount, amount: requestedAmount, feeData })
|
|
370
|
+
}
|
|
371
371
|
|
|
372
|
-
|
|
372
|
+
const NAMING_MAP = {
|
|
373
|
+
delegate: 'stake',
|
|
374
|
+
undelegate: 'unstake',
|
|
375
|
+
claimUndelegatedBalance: 'claimWithdrawRequest',
|
|
376
|
+
}
|
|
373
377
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
//
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
to
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
378
|
+
const delegateOperation = staking[NAMING_MAP[operation]].bind(staking)
|
|
379
|
+
|
|
380
|
+
if (!delegateOperation) throw new Error('Invalid staking operation')
|
|
381
|
+
|
|
382
|
+
const { amount, data } = await delegateOperation({ ...args, amount: requestedAmount })
|
|
383
|
+
|
|
384
|
+
const { fee } = await (operation === 'claimUndelegatedBalance'
|
|
385
|
+
? estimateTxFee({
|
|
386
|
+
from: delegatorAddress,
|
|
387
|
+
to: staking.accountingAddress,
|
|
388
|
+
amount,
|
|
389
|
+
txInput: data,
|
|
390
|
+
feeData,
|
|
391
|
+
})
|
|
392
|
+
: // The `gasUsed` of a delegation transaction can vary
|
|
393
|
+
// significantly depending upon whether it will result
|
|
394
|
+
// in the activation of new slots (i.e. validator creation).
|
|
395
|
+
//
|
|
396
|
+
// This can result in transaction `revert` due to slippage
|
|
397
|
+
// from incompatible transaction ordering.
|
|
398
|
+
//
|
|
399
|
+
// To mitigate this, we:
|
|
400
|
+
// 1. Simulate the delegation at an amplified deposit amount
|
|
401
|
+
// to show enhanced fees close to a proximity buffer.
|
|
402
|
+
// 2. Originate the transaction from the WETH contract,
|
|
403
|
+
// which guarantees deep native ether liquidity which
|
|
404
|
+
// exceeds any rational user deposit.
|
|
405
|
+
estimateTxFee({
|
|
406
|
+
from: WETH9_ADDRESS,
|
|
407
|
+
to: staking.poolAddress,
|
|
408
|
+
amount: amount.add(asset.currency.defaultUnit(SLOT_ACTIVATION_PROXIMITY_ETH)),
|
|
409
|
+
txInput: data,
|
|
410
|
+
feeData,
|
|
411
|
+
}))
|
|
412
|
+
|
|
413
|
+
return fee
|
|
414
|
+
} catch (error) {
|
|
415
|
+
const fallbackFee = STAKING_OPERATION_FALLBACK_FEE_ESTIMATES[operation]
|
|
416
|
+
if (fallbackFee) {
|
|
417
|
+
console.warn(
|
|
418
|
+
`ETH staking fee estimation failed for '${operation}', using fallback:`,
|
|
419
|
+
error.message
|
|
420
|
+
)
|
|
421
|
+
return asset.currency.defaultUnit(fallbackFee)
|
|
422
|
+
}
|
|
402
423
|
|
|
403
|
-
|
|
424
|
+
error.message = `StakingFeeEstimationError: Failed to estimate fee for '${operation}' (and no fallback configured). Cause: ${error.message}`
|
|
425
|
+
throw error
|
|
426
|
+
}
|
|
404
427
|
}
|
|
405
428
|
|
|
406
429
|
async function estimateTxFee({ from, to, amount, txInput, feeData }) {
|
|
@@ -9,9 +9,10 @@ import isConsideredSentTokenTx from '../monitor-utils/is-considered-sent-token-t
|
|
|
9
9
|
import filterEffects from './filter-effects.js'
|
|
10
10
|
import getNamesOfTokensTransferredByServerTx from './get-names-of-tokens-transferred-by-server-tx.js'
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
// and transforms it into Tx models to update the exodus state.
|
|
12
|
+
const isFiniteInteger = (n) => Number.isFinite(n) && Number.isInteger(n)
|
|
14
13
|
|
|
14
|
+
// This function takes a server transaction object fetched from clarity,
|
|
15
|
+
// and transforms it into Tx models to update the exodus state.
|
|
15
16
|
export default function getLogItemsFromServerTx({
|
|
16
17
|
serverTx,
|
|
17
18
|
asset,
|
|
@@ -93,8 +94,8 @@ export default function getLogItemsFromServerTx({
|
|
|
93
94
|
nonceChange: nonceUpdate,
|
|
94
95
|
...methodId,
|
|
95
96
|
...(sent?.length > 0 ? { sent } : undefined),
|
|
96
|
-
blockNumber,
|
|
97
|
-
transactionIndex,
|
|
97
|
+
...(isFiniteInteger(blockNumber) ? { blockNumber } : null),
|
|
98
|
+
...(isFiniteInteger(transactionIndex) ? { transactionIndex } : null),
|
|
98
99
|
},
|
|
99
100
|
...(ourWalletWasSender
|
|
100
101
|
? { from: [], to: toAddress, feeAmount, feeCoinName: asset.feeAsset.name }
|
|
@@ -159,8 +160,8 @@ export default function getLogItemsFromServerTx({
|
|
|
159
160
|
gasLimit,
|
|
160
161
|
balanceChange,
|
|
161
162
|
...methodId,
|
|
162
|
-
blockNumber,
|
|
163
|
-
transactionIndex,
|
|
163
|
+
...(isFiniteInteger(blockNumber) ? { blockNumber } : null),
|
|
164
|
+
...(isFiniteInteger(transactionIndex) ? { transactionIndex } : null),
|
|
164
165
|
},
|
|
165
166
|
...(isConsideredSent
|
|
166
167
|
? { from: [], to: tokenTransferToAddress, feeAmount, feeCoinName: token.feeAsset.name }
|
|
@@ -4,19 +4,17 @@
|
|
|
4
4
|
// array is a transfer for that asset. If we sent more than we received, the value is negative.
|
|
5
5
|
|
|
6
6
|
export default function getValueOfTransfers(ourWalletAddress, asset, transfers) {
|
|
7
|
-
return transfers
|
|
8
|
-
|
|
9
|
-
const transferAmount = asset.currency.baseUnit(value)
|
|
7
|
+
return transfers.reduce((balanceDifference, { from, to, value }) => {
|
|
8
|
+
const transferAmount = asset.currency.baseUnit(value)
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
if (from === ourWalletAddress) {
|
|
11
|
+
balanceDifference = balanceDifference.sub(transferAmount)
|
|
12
|
+
}
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
if (to === ourWalletAddress) {
|
|
15
|
+
balanceDifference = balanceDifference.add(transferAmount)
|
|
16
|
+
}
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
.to(asset.ticker)
|
|
18
|
+
return balanceDifference
|
|
19
|
+
}, asset.currency.ZERO)
|
|
22
20
|
}
|