@exodus/ethereum-api 8.46.1 → 8.47.1

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,26 @@
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.47.1](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.47.0...@exodus/ethereum-api@8.47.1) (2025-09-08)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+
12
+ * fix: enable proper handling of null responses for batch requests (#6414)
13
+
14
+
15
+
16
+ ## [8.47.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.46.1...@exodus/ethereum-api@8.47.0) (2025-09-08)
17
+
18
+
19
+ ### Features
20
+
21
+
22
+ * feat: add `EthLikeFeeData` to respect `min`, `max` and `multiplier` for EIP-1559 transactions (#6254)
23
+
24
+
25
+
6
26
  ## [8.46.1](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.46.0...@exodus/ethereum-api@8.46.1) (2025-09-03)
7
27
 
8
28
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/ethereum-api",
3
- "version": "8.46.1",
3
+ "version": "8.47.1",
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",
@@ -64,5 +64,5 @@
64
64
  "type": "git",
65
65
  "url": "git+https://github.com/ExodusMovement/assets.git"
66
66
  },
67
- "gitHead": "e84949a7310f03feb4893668abd44fe537bf250c"
67
+ "gitHead": "fbda86007124112138bfe661e1b25655e6107762"
68
68
  }
@@ -29,7 +29,7 @@ import {
29
29
  import { createTokenFactory } from './create-token-factory.js'
30
30
  import { createCustomFeesApi } from './custom-fees.js'
31
31
  import { createEvmServer } from './exodus-eth-server/index.js'
32
- import { createFeeData } from './fee-data-factory.js'
32
+ import { createFeeData } from './fee-data/index.js'
33
33
  import { createGetBalanceForAddress } from './get-balance-for-address.js'
34
34
  import { getBalancesFactory } from './get-balances.js'
35
35
  import { getFeeFactory } from './get-fee.js'
@@ -34,7 +34,7 @@ export default class ApiCoinNodesServer extends EventEmitter {
34
34
  if (isEmpty(batch)) return batch
35
35
  const responses = await this.request(batch)
36
36
  const isValid = responses.every((response) => {
37
- return !isNaN(response?.id) && response?.result
37
+ return !isNaN(response?.id) && response?.result !== undefined
38
38
  })
39
39
  if (responses.length !== batch.length || !isValid) {
40
40
  throw new Error('Bad rpc batch response')
@@ -181,7 +181,7 @@ export default class ClarityServer extends EventEmitter {
181
181
  const responses = await this.sendRpcRequest(batch)
182
182
  // FIXME: this falls apart if responses is not an array
183
183
  const isValid = responses.every((response) => {
184
- return !isNaN(response?.id) && response?.result
184
+ return !isNaN(response?.id) && response?.result !== undefined
185
185
  })
186
186
  if (responses.length !== batch.length || !isValid) {
187
187
  throw new Error('Bad Response')
@@ -0,0 +1,81 @@
1
+ import { FeeData } from '@exodus/asset-lib'
2
+ import {
3
+ mapCurrency as defaultMapCurrency,
4
+ modelToJSON,
5
+ } from '@exodus/asset-lib/src/utils/index.js'
6
+ import { isNumberUnit } from '@exodus/currency'
7
+ import lodash from 'lodash'
8
+
9
+ const { isEmpty, isEqual } = lodash
10
+
11
+ const PRE_EIP1559_UNIT_KEYS_GUARD = ['gasPrice']
12
+ const EIP1559_UNIT_KEYS_GUARD = ['gasPrice', 'baseFeePerGas']
13
+
14
+ export const bound = ({ val, multiplier, max, min }) => {
15
+ if (!isNumberUnit(val)) return val
16
+
17
+ if (multiplier) {
18
+ val = val.mul(multiplier)
19
+ }
20
+
21
+ if (max) {
22
+ val = val.lte(max) ? val : max
23
+ }
24
+
25
+ if (min) {
26
+ val = val.gte(min) ? val : min
27
+ }
28
+
29
+ return val
30
+ }
31
+
32
+ const mapCurrency = ({ currency, config }) => {
33
+ const { eip1559Enabled } = config
34
+ return defaultMapCurrency(
35
+ config,
36
+ [currency],
37
+ eip1559Enabled ? EIP1559_UNIT_KEYS_GUARD : PRE_EIP1559_UNIT_KEYS_GUARD
38
+ )
39
+ }
40
+
41
+ const boundFactory =
42
+ ({ config }) =>
43
+ (val) => {
44
+ const { multiplier, max, min } = config
45
+ return bound({ val, multiplier, max, min })
46
+ }
47
+
48
+ export class EthLikeFeeData extends FeeData {
49
+ constructor({ currency, config }) {
50
+ super({ currency, config, mainKey: 'gasPrice' })
51
+ Object.assign(this, mapCurrency({ currency, config }))
52
+ }
53
+
54
+ update(config = {}) {
55
+ if (isEmpty(config)) return this
56
+
57
+ config = super.update(config)
58
+
59
+ if (config.eip1559Enabled) {
60
+ const bound = boundFactory({ config })
61
+
62
+ const { baseFeePerGas, tipGasPrice = this.currency.ZERO } = config
63
+
64
+ const enforcedEffectiveGasPrice = bound(baseFeePerGas.add(tipGasPrice))
65
+
66
+ // When the `effectiveGasPrice` is lower, we'll increase the
67
+ // `tipGasPrice` to ensure we meet the `enforcedEffectiveGasPrice`.
68
+ //
69
+ // Conversely, when the `effectiveGasPrice` is too high, we'll
70
+ // try to reduce the `tipGasPrice` where possible, but whilst
71
+ // maintaining the `baseFeePerGas`, since this is the minimum
72
+ // for the current network.
73
+ Object.assign(config, {
74
+ tipGasPrice: enforcedEffectiveGasPrice.sub(baseFeePerGas).clampLowerZero(),
75
+ })
76
+ }
77
+
78
+ if (isEqual(this.toJSON(), modelToJSON({ ...config }))) return this
79
+ return new this.constructor({ config, currency: this.currency })
80
+ }
81
+ }
@@ -1,7 +1,8 @@
1
- import { FeeData } from '@exodus/asset-lib'
2
1
  import assert from 'minimalistic-assert'
3
2
 
4
- const createFeeDataConfigDefaults = ({ currency, feeDataConfig }) => {
3
+ import { EthLikeFeeData } from './EthLikeFeeData.js'
4
+
5
+ export const createFeeDataConfigDefaults = ({ currency, feeDataConfig }) => {
5
6
  const shared = {
6
7
  tipGasPrice: '0 Gwei',
7
8
  fuelThreshold: '0 Gwei',
@@ -48,9 +49,6 @@ const createFeeDataConfigDefaults = ({ currency, feeDataConfig }) => {
48
49
  }
49
50
 
50
51
  export const createFeeData = ({ currency, feeDataConfig }) => {
51
- return new FeeData({
52
- config: createFeeDataConfigDefaults({ currency, feeDataConfig }),
53
- mainKey: 'gasPrice',
54
- currency,
55
- })
52
+ const config = createFeeDataConfigDefaults({ currency, feeDataConfig })
53
+ return new EthLikeFeeData({ config, currency })
56
54
  }