@exodus/ethereum-api 8.77.1 → 8.77.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,23 @@
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.77.3](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.77.1...@exodus/ethereum-api@8.77.3) (2026-07-11)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **ethereum-api:** detect legacy delegate transactions ([#8357](https://github.com/ExodusMovement/assets/issues/8357)) ([070e529](https://github.com/ExodusMovement/assets/commit/070e5295f21f12695e97e721ff8c0601c553e447))
12
+
13
+
14
+
15
+ ## [8.77.2](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.77.1...@exodus/ethereum-api@8.77.2) (2026-07-10)
16
+
17
+ **Note:** Version bump only for package @exodus/ethereum-api
18
+
19
+
20
+
21
+
22
+
6
23
  ## [8.77.1](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.77.0...@exodus/ethereum-api@8.77.1) (2026-07-09)
7
24
 
8
25
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/ethereum-api",
3
- "version": "8.77.1",
3
+ "version": "8.77.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",
@@ -23,13 +23,13 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@exodus/asset": "^2.0.4",
26
- "@exodus/asset-lib": "^5.9.1",
26
+ "@exodus/asset-lib": "^5.9.2",
27
27
  "@exodus/assets": "^11.4.0",
28
28
  "@exodus/basic-utils": "^3.0.1",
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.24.3",
32
+ "@exodus/ethereum-lib": "^5.25.0",
33
33
  "@exodus/ethereum-meta": "^2.9.1",
34
34
  "@exodus/ethereumholesky-meta": "^2.0.5",
35
35
  "@exodus/ethereumjs": "^1.11.0",
@@ -69,5 +69,5 @@
69
69
  "type": "git",
70
70
  "url": "git+https://github.com/ExodusMovement/assets.git"
71
71
  },
72
- "gitHead": "96337ab20f90e6fa96043f7d569a4f6527c04ebd"
72
+ "gitHead": "ccdff56c057e6c4892b304fa47ecfc6c4389f629"
73
73
  }
@@ -23,7 +23,10 @@ export const isEthereumStakingTx = ({ coinName }) =>
23
23
  export const isEthereumStakingPoolContract = (address) =>
24
24
  typeof address === 'string' && STAKING_MANAGER_CONTRACTS.has(address.toLowerCase())
25
25
  export const isEthereumDelegate = (tx) =>
26
- isEthereumStakingTx(tx) && STAKING_MANAGER_CONTRACTS.has(tx.to) && tx.data?.methodId === DELEGATE
26
+ isEthereumStakingTx(tx) &&
27
+ ((STAKING_MANAGER_CONTRACTS.has(tx.to) && tx.data?.methodId === DELEGATE) ||
28
+ tx.data?.delegate === true ||
29
+ typeof tx.data?.delegate === 'string')
27
30
  export const isEthereumUndelegatePending = (tx) =>
28
31
  isEthereumStakingTx(tx) && tx.data?.methodId === UNSTAKE_PENDING
29
32
  export const isEthereumUndelegate = (tx) =>
@@ -4,12 +4,12 @@ import lodash from 'lodash'
4
4
  import assert from 'minimalistic-assert'
5
5
 
6
6
  import { executeEthLikeFeeMonitorUpdate } from '../fee-utils.js'
7
- import { fromHexToString } from '../number-utils.js'
8
7
  import {
9
8
  filterEffects,
10
9
  getLogItemsFromServerTx,
11
10
  normalizeTransactionsResponse,
12
11
  } from './clarity-utils/index.js'
12
+ import { getBatchedRpcBalances } from './monitor-utils/get-batched-rpc-balances.js'
13
13
  import {
14
14
  checkPendingTransactions,
15
15
  excludeUnchangedTokenBalances,
@@ -364,33 +364,12 @@ export class ClarityMonitor extends BaseMonitor {
364
364
  }
365
365
 
366
366
  async getBalances({ tokens, ourWalletAddress }) {
367
- const batch = Object.create(null)
368
- if (this.rpcBalanceAssetNames.includes(this.asset.name)) {
369
- const request = this.server.getBalanceRequest(ourWalletAddress)
370
- batch[this.asset.name] = request
371
- }
372
-
373
- for (const token of tokens) {
374
- if (this.rpcBalanceAssetNames.includes(token.name) && token.contract.address) {
375
- const request = this.server.balanceOfRequest(ourWalletAddress, token.contract.address)
376
- batch[token.name] = request
377
- }
378
- }
379
-
380
- const pairs = Object.entries(batch)
381
- if (pairs.length === 0) {
382
- return {}
383
- }
384
-
385
- const requests = pairs.map((pair) => pair[1])
386
- const responses = await this.server.sendBatchRequest(requests)
387
- const entries = pairs.map((pair, idx) => {
388
- const balanceHex = responses[idx]
389
- const name = pair[0]
390
- const balance = fromHexToString(balanceHex)
391
- return [name, balance]
367
+ return getBatchedRpcBalances({
368
+ baseAsset: this.asset,
369
+ ourWalletAddress,
370
+ tokens,
371
+ rpcBalanceAssetNames: this.rpcBalanceAssetNames,
392
372
  })
393
- return Object.fromEntries(entries)
394
373
  }
395
374
 
396
375
  getUnknownTokenAddresses({ transactions, tokensByAddress }) {
@@ -2,27 +2,46 @@ import assert from 'minimalistic-assert'
2
2
 
3
3
  import { fromHexToString } from '../../number-utils.js'
4
4
 
5
- export const getBatchedRpcBalances = async ({ baseAsset, tokens, ourWalletAddress }) => {
5
+ export const getBatchedRpcBalances = async ({
6
+ baseAsset,
7
+ tokens,
8
+ ourWalletAddress,
9
+ rpcBalanceAssetNames,
10
+ }) => {
6
11
  assert(baseAsset, 'expected baseAsset')
7
12
  assert(Array.isArray(tokens), 'expected array tokens')
8
13
  assert(ourWalletAddress, 'expected ourWalletAddress')
9
14
 
10
- const [balance, ...tokenBalances] = await tokens
15
+ const batch = (assetName) =>
16
+ !Array.isArray(rpcBalanceAssetNames) || rpcBalanceAssetNames.includes(assetName)
17
+
18
+ const isBaseAssetBatched = batch(baseAsset.name)
19
+
20
+ const rpcRequestAccumulator = tokens
21
+ .filter(({ name, contract }) => batch(name) && contract?.address)
11
22
  .reduce(
12
23
  (acc, { contract: { address: tokenAddress } }) =>
13
24
  acc.balanceOfRequest(ourWalletAddress, tokenAddress),
14
- baseAsset.createRpcRequestAccumulator().getBalanceRequest(ourWalletAddress)
25
+ isBaseAssetBatched
26
+ ? baseAsset.createRpcRequestAccumulator().getBalanceRequest(ourWalletAddress)
27
+ : baseAsset.createRpcRequestAccumulator()
15
28
  )
16
- .flush(baseAsset.server)
29
+
30
+ if (rpcRequestAccumulator.length() === 0) return Object.create(null)
31
+
32
+ const results = await rpcRequestAccumulator.flush(baseAsset.server)
17
33
 
18
34
  return {
19
- [baseAsset.name]: fromHexToString(balance),
35
+ ...(isBaseAssetBatched && { [baseAsset.name]: fromHexToString(results[0]) }),
20
36
  ...Object.fromEntries(
21
- tokens.map(({ name, contract: { address: tokenAddress } }, i) => {
22
- const tokenBalance = tokenBalances[i]?.confirmed?.[tokenAddress]
23
- assert(tokenBalance != null, `missing token balance for ${name} (${tokenAddress})`)
24
- return [name, tokenBalance]
25
- })
37
+ tokens
38
+ .filter(({ name, contract }) => batch(name) && contract?.address)
39
+ .map(({ name, contract: { address: tokenAddress } }, i) => {
40
+ const tokenBalance = results[i + (isBaseAssetBatched ? 1 : 0)]?.confirmed?.[tokenAddress]
41
+
42
+ assert(tokenBalance != null, `missing token balance for ${name} (${tokenAddress})`)
43
+ return [name, tokenBalance]
44
+ })
26
45
  ),
27
46
  }
28
47
  }