@exodus/ethereum-api 8.34.3 → 8.34.4

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.34.4](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.34.3...@exodus/ethereum-api@8.34.4) (2025-05-07)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+
12
+ * fix: remove fixed gas limit tokens on evm (#5543)
13
+
14
+
15
+
6
16
  ## [8.34.3](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.34.2...@exodus/ethereum-api@8.34.3) (2025-04-29)
7
17
 
8
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/ethereum-api",
3
- "version": "8.34.3",
3
+ "version": "8.34.4",
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",
@@ -28,7 +28,7 @@
28
28
  "@exodus/bip44-constants": "^195.0.0",
29
29
  "@exodus/crypto": "^1.0.0-rc.13",
30
30
  "@exodus/currency": "^6.0.1",
31
- "@exodus/ethereum-lib": "^5.10.1",
31
+ "@exodus/ethereum-lib": "^5.10.2",
32
32
  "@exodus/ethereum-meta": "^2.5.0",
33
33
  "@exodus/ethereumholesky-meta": "^2.0.2",
34
34
  "@exodus/ethereumjs": "^1.0.0",
@@ -64,5 +64,5 @@
64
64
  "type": "git",
65
65
  "url": "git+https://github.com/ExodusMovement/assets.git"
66
66
  },
67
- "gitHead": "5513269ef920bfdd91701a8108fe73336d105866"
67
+ "gitHead": "ef3710f80aaff8c5d84bc53026800f9a1c0e029f"
68
68
  }
package/src/fee-utils.js CHANGED
@@ -54,3 +54,14 @@ export const ensureSaneEip1559GasPriceForTipGasPrice = ({ gasPrice, tipGasPrice
54
54
  if (!tipGasPrice || tipGasPrice.lt(gasPrice)) return gasPrice
55
55
  return tipGasPrice
56
56
  }
57
+
58
+ export const getNormalizedFeeDataForCustomFee = ({ customFee, feeData }) => {
59
+ const { eip1559Enabled } = feeData
60
+ // We must ensure maxPriorityFeePerGas <= maxFeePerGas or our transaction library throws an error
61
+ // It's a bit counterintuitive since maxPriorityFeePerGas should only contain the tip,
62
+ // so we should be subtracting the base gas price from the custom gas price to keep just the tip
63
+ // but the fee is also limited by our maxFeePerGas above, so that implicitly captures the max tip.
64
+ // Setting this tipGasPrice to undefined will result in a legacy transaction (not an EIP1559 anymore)
65
+ if (eip1559Enabled && customFee) return { ...feeData, tipGasPrice: customFee }
66
+ return feeData
67
+ }
@@ -1,6 +1,5 @@
1
1
  import { currency2buffer, isEthereumLikeToken } from '@exodus/ethereum-lib'
2
2
  import { bufferToHex, toBuffer } from '@exodus/ethereumjs/util'
3
- import BN from 'bn.js'
4
3
 
5
4
  import { estimateGas, isContractAddressCached } from './eth-like-util.js'
6
5
 
@@ -11,6 +10,11 @@ const GAS_PER_NON_ZERO_BYTE = 16
11
10
 
12
11
  export const DEFAULT_CONTRACT_GAS_LIMIT = 1e6
13
12
 
13
+ // HACK: RPCs generally provide imprecise estimates
14
+ // for `gasUsed` (often these are insufficient).
15
+ export const scaleGasLimitEstimate = ({ estimatedGasLimit, extraPercentage = EXTRA_PERCENTAGE }) =>
16
+ Number((BigInt(estimatedGasLimit) * BigInt(100 + extraPercentage)) / BigInt(100))
17
+
14
18
  // Starting with geth v1.9.14, if gasPrice is set for eth_estimateGas call, the call allowance will
15
19
  // be calculated with account's balance divided by gasPrice. If user's balance is too low,
16
20
  // the gasEstimation will fail. If gasPrice is set to '0x0', the account's balance is not
@@ -22,7 +26,7 @@ export async function estimateGasLimit(
22
26
  amount,
23
27
  data,
24
28
  gasPrice = '0x',
25
- extraPercentage = EXTRA_PERCENTAGE
29
+ extraPercentage
26
30
  ) {
27
31
  const opts = {
28
32
  from: fromAddress,
@@ -33,10 +37,11 @@ export async function estimateGasLimit(
33
37
  }
34
38
 
35
39
  const estimatedGas = await estimateGas({ asset, ...opts })
36
- return new BN(estimatedGas.slice(2), 16)
37
- .imuln(100 + extraPercentage)
38
- .idivn(100)
39
- .toNumber()
40
+
41
+ return scaleGasLimitEstimate({
42
+ estimatedGasLimit: BigInt(estimatedGas),
43
+ extraPercentage,
44
+ })
40
45
  }
41
46
 
42
47
  export function resolveDefaultTxInput({ asset, toAddress, amount }) {
@@ -5,14 +5,6 @@ import { EXTRA_PERCENTAGE, fetchGasLimit, resolveDefaultTxInput } from './gas-es
5
5
  import { getFeeFactory } from './get-fee.js'
6
6
  import { getNftArguments } from './nft-utils.js'
7
7
 
8
- const FIXED_TRANSFER_GAS_LIMIT_ASSETS = new Set([
9
- 'amp',
10
- 'tetherusd',
11
- 'usdcoin',
12
- 'snx',
13
- 'geminidollar',
14
- ])
15
-
16
8
  const UNKNOWN_ADDRESS_EXTRA_PERCENTAGE = {
17
9
  usdt_bsc_ddedf0f8: 80,
18
10
  }
@@ -24,12 +16,6 @@ export async function resolveExtraPercentage({ asset, fromAddress, toAddress })
24
16
 
25
17
  const isToken = asset.name !== asset.baseAsset.name
26
18
 
27
- const isFixedGasLimitToken = isToken && FIXED_TRANSFER_GAS_LIMIT_ASSETS.has(asset.name)
28
-
29
- if (isFixedGasLimitToken) {
30
- return 0
31
- }
32
-
33
19
  // calling forwarder contracts with a bumped gas limit causes 'Out Of Gas' error on chain
34
20
  const hasForwarderContract =
35
21
  !isToken && toAddress ? await isForwarderContractCached({ asset, address: toAddress }) : false
package/src/get-fee.js CHANGED
@@ -1,6 +1,10 @@
1
1
  import { calculateBumpedGasPrice, calculateExtraEth } from '@exodus/ethereum-lib'
2
2
 
3
- import { ensureSaneEip1559GasPriceForTipGasPrice, resolveGasPrice } from './fee-utils.js'
3
+ import {
4
+ ensureSaneEip1559GasPriceForTipGasPrice,
5
+ getNormalizedFeeDataForCustomFee,
6
+ resolveGasPrice,
7
+ } from './fee-utils.js'
4
8
 
5
9
  // Move to meta?
6
10
  const taxes = {
@@ -21,6 +25,20 @@ const getExtraFeeData = ({ asset, amount }) => {
21
25
  }
22
26
  }
23
27
 
28
+ export const getFeeFactoryGasPrices = ({ customFee, feeData }) => {
29
+ feeData = getNormalizedFeeDataForCustomFee({ customFee, feeData })
30
+ const gasPrice = customFee || resolveGasPrice({ feeData })
31
+ const { tipGasPrice, eip1559Enabled } = feeData
32
+
33
+ // The `gasPrice` must be at least the `tipGasPrice`.
34
+ return {
35
+ gasPrice: eip1559Enabled
36
+ ? ensureSaneEip1559GasPriceForTipGasPrice({ gasPrice, tipGasPrice })
37
+ : gasPrice,
38
+ feeData,
39
+ }
40
+ }
41
+
24
42
  export const getFeeFactory =
25
43
  ({ gasLimit: defaultGasLimit }) =>
26
44
  ({
@@ -32,26 +50,13 @@ export const getFeeFactory =
32
50
  amount,
33
51
  calculateEffectiveFee,
34
52
  }) => {
35
- const { eip1559Enabled } = feeData
36
-
37
- // HACK: For EIP-1559 transactions, we forcibly coerce the
38
- // tipGasPrice to be the `customFee`, where defined:
39
- // https://github.com/ExodusMovement/assets/blob/b805d1de0e67013ece2a1460389fb4328445eac1/ethereum/ethereum-api/src/tx-send/tx-send.js#L302C5-L311C6
40
- //
41
- // Therefore to compute the true fee at send time, we
42
- // must also enforce the relationship here!
43
- if (eip1559Enabled && customFee) {
44
- feeData = { ...feeData, tipGasPrice: customFee }
45
- }
46
-
47
- const { baseFeePerGas, tipGasPrice } = feeData
48
-
49
- let gasPrice = customFee || resolveGasPrice({ feeData })
50
-
51
- // The `gasPrice` must be at least the `tipGasPrice`.
52
- if (eip1559Enabled) {
53
- gasPrice = ensureSaneEip1559GasPriceForTipGasPrice({ gasPrice, tipGasPrice })
54
- }
53
+ const {
54
+ feeData: { baseFeePerGas, tipGasPrice, eip1559Enabled },
55
+ gasPrice,
56
+ } = getFeeFactoryGasPrices({
57
+ customFee,
58
+ feeData,
59
+ })
55
60
 
56
61
  const gasLimit = providedGasLimit || asset.gasLimit || defaultGasLimit
57
62
 
package/src/index.js CHANGED
@@ -81,6 +81,8 @@ export {
81
81
 
82
82
  export { reasons as errorReasons, withErrorReason, EthLikeError } from './error-wrapper.js'
83
83
 
84
+ // TODO: `getFeeInfo` is not consumed by third parties and should
85
+ // be considered an internal API.
84
86
  export { txSendFactory, getFeeInfo } from './tx-send/index.js'
85
87
 
86
88
  export { createAssetFactory } from './create-asset.js'
@@ -4,6 +4,7 @@ import { retry } from '@exodus/simple-retry'
4
4
 
5
5
  import { getServerByName } from '../../exodus-eth-server/index.js'
6
6
 
7
+ // TODO: Shouldn't this be a function of `ethereumStakingState.minDelegateAmount`?
7
8
  const MIN_AMOUNT = '0.1'
8
9
  const RETRY_DELAYS = ['10s']
9
10
 
@@ -1,7 +1,7 @@
1
1
  import { estimateGasLimit } from '../../gas-estimation.js'
2
2
  import { createWatchTx as defaultCreateWatch } from '../../watch-tx.js'
3
3
  import { stakingProviderClientFactory } from '../staking-provider-client.js'
4
- import { amountToCurrency, getEvmStakingServiceFee } from '../utils/index.js'
4
+ import { amountToCurrency, DISABLE_BALANCE_CHECKS, resolveFeeData } from '../utils/index.js'
5
5
  import { EthereumStaking } from './api.js'
6
6
 
7
7
  const WETH9_ADDRESS = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
@@ -20,8 +20,6 @@ const MINIMUM_DELEGATION_GAS_LIMIT = 180_000
20
20
 
21
21
  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
22
 
23
- const DISABLE_BALANCE_CHECKS = '0x0'
24
-
25
23
  export function createEthereumStakingService({
26
24
  asset,
27
25
  assetClientInterface,
@@ -31,17 +29,27 @@ export function createEthereumStakingService({
31
29
  const staking = new EthereumStaking(asset, undefined, asset.server)
32
30
  const minAmount = staking.minAmount
33
31
 
34
- async function delegate({ walletAccount, amount } = Object.create(null)) {
35
- const address = await assetClientInterface.getReceiveAddress({
36
- assetName: asset.name,
37
- walletAccount,
38
- })
32
+ const getTransactionProps = async ({ feeData, walletAccount }) => {
33
+ let address
34
+ ;[address, feeData] = await Promise.all([
35
+ assetClientInterface.getReceiveAddress({
36
+ assetName: asset.name,
37
+ walletAccount,
38
+ }),
39
+ resolveFeeData({ asset, assetClientInterface, feeData }),
40
+ ])
41
+
39
42
  const delegatorAddress = address.toLowerCase()
43
+ return { delegatorAddress, feeData }
44
+ }
45
+
46
+ async function delegate({ walletAccount, amount, feeData } = Object.create(null)) {
40
47
  amount = amountToCurrency({ asset, amount })
41
48
 
42
- const { to, data } = await staking.stake({
43
- amount,
44
- })
49
+ let delegatorAddress
50
+ ;({ feeData, delegatorAddress } = await getTransactionProps({ feeData, walletAccount }))
51
+
52
+ const { to, data } = await staking.stake({ amount })
45
53
 
46
54
  console.log(
47
55
  `delegator address ${delegatorAddress} staking ${amount.toDefaultString({
@@ -49,12 +57,14 @@ export function createEthereumStakingService({
49
57
  })}`
50
58
  )
51
59
 
52
- const { gasPrice, gasLimit, tipGasPrice } = await estimateTxFee(
53
- delegatorAddress,
60
+ const { gasPrice, gasLimit, tipGasPrice } = await estimateTxFee({
61
+ from: delegatorAddress,
54
62
  to,
55
63
  amount,
56
- data
57
- )
64
+ txInput: data,
65
+ feeData,
66
+ })
67
+
58
68
  const txId = await prepareAndSendTx({
59
69
  asset,
60
70
  walletAccount,
@@ -64,6 +74,7 @@ export function createEthereumStakingService({
64
74
  gasPrice,
65
75
  gasLimit,
66
76
  tipGasPrice,
77
+ feeData,
67
78
  })
68
79
 
69
80
  // Goerli is not supported
@@ -83,32 +94,36 @@ export function createEthereumStakingService({
83
94
  resquestedAmount,
84
95
  pendingAmount,
85
96
  minAmount,
97
+ feeData,
86
98
  }) {
87
99
  const leftOver = pendingAmount.sub(resquestedAmount)
88
100
 
89
- if (leftOver.isPositive && leftOver.lt(minAmount)) {
101
+ if (leftOver.isPositive && leftOver.lt(minAmount))
90
102
  throw new Error(`Pending balance less than min stake amount ${minAmount}`)
91
- }
92
103
 
93
104
  const inactiveAmountToUnstake = pendingAmount.lte(resquestedAmount)
94
105
  ? pendingAmount
95
106
  : resquestedAmount
107
+
108
+ feeData = await resolveFeeData({ asset, assetClientInterface, feeData })
109
+
96
110
  const { to, data } = await staking.unstakePending({
97
111
  address: delegatorAddress,
98
112
  amount: inactiveAmountToUnstake,
99
113
  })
100
114
 
101
- const { fee, gasLimit, gasPrice, tipGasPrice } = await estimateTxFee(
102
- delegatorAddress,
115
+ const { fee, gasLimit, gasPrice, tipGasPrice } = await estimateTxFee({
116
+ from: delegatorAddress,
103
117
  to,
104
- null,
105
- data
106
- )
118
+ amount: null,
119
+ txInput: data,
120
+ feeData,
121
+ })
107
122
 
108
123
  return { to, txData: data, gasLimit, gasPrice, tipGasPrice, fee }
109
124
  }
110
125
 
111
- async function getUndelegateData({ delegatorAddress, resquestedAmount, pendingAmount }) {
126
+ async function getUndelegateData({ delegatorAddress, resquestedAmount, pendingAmount, feeData }) {
112
127
  const canUnstake = resquestedAmount.gt(pendingAmount)
113
128
 
114
129
  if (!canUnstake) {
@@ -117,17 +132,21 @@ export function createEthereumStakingService({
117
132
  }
118
133
 
119
134
  const activeAmountToUnstake = resquestedAmount.sub(pendingAmount)
135
+
136
+ feeData = await resolveFeeData({ asset, assetClientInterface, feeData })
137
+
120
138
  const { to, data } = await staking.unstake({
121
139
  address: delegatorAddress,
122
140
  amount: activeAmountToUnstake,
123
141
  })
124
142
 
125
- const { fee, gasLimit, gasPrice, tipGasPrice } = await estimateTxFee(
126
- delegatorAddress,
143
+ const { fee, gasLimit, gasPrice, tipGasPrice } = await estimateTxFee({
144
+ from: delegatorAddress,
127
145
  to,
128
- null,
129
- data
130
- )
146
+ amount: null,
147
+ txInput: data,
148
+ feeData,
149
+ })
131
150
 
132
151
  return { to, txData: data, gasLimit, gasPrice, tipGasPrice, fee }
133
152
  }
@@ -137,12 +156,10 @@ export function createEthereumStakingService({
137
156
  * Fee estimation depends on the executed txs. Can be both.
138
157
  * @returns total undelegete fee
139
158
  */
140
- async function estimateUndelegate({ walletAccount, amount: resquestedAmount }) {
141
- const address = await assetClientInterface.getReceiveAddress({
142
- assetName: asset.name,
143
- walletAccount,
144
- })
145
- const delegatorAddress = address.toLowerCase()
159
+ async function estimateUndelegate({ walletAccount, amount: resquestedAmount, feeData }) {
160
+ let delegatorAddress
161
+ ;({ feeData, delegatorAddress } = await getTransactionProps({ feeData, walletAccount }))
162
+
146
163
  const pendingAmount = await staking.pendingBalanceOf(delegatorAddress)
147
164
 
148
165
  let undelegatePendingFee = asset.currency.ZERO
@@ -155,6 +172,7 @@ export function createEthereumStakingService({
155
172
  resquestedAmount,
156
173
  pendingAmount,
157
174
  minAmount,
175
+ feeData,
158
176
  })
159
177
  undelegatePendingFee = fee
160
178
  } catch (err) {
@@ -168,12 +186,15 @@ export function createEthereumStakingService({
168
186
  resquestedAmount,
169
187
  pendingAmount,
170
188
  minAmount,
189
+ feeData,
171
190
  })
172
191
 
173
192
  return undelegatePendingFee.add(undelegateFee)
174
193
  }
175
194
 
176
- async function undelegate({ walletAccount, amount } = Object.create(null)) {
195
+ async function undelegate(
196
+ { walletAccount, amount, feeData, waitForConfirmation = true } = Object.create(null)
197
+ ) {
177
198
  /*
178
199
  unstakePending balance (not yet in validator) + unstake balance (in validator)
179
200
  1. give priority to unstakePending (based on the amount)
@@ -181,11 +202,9 @@ export function createEthereumStakingService({
181
202
  */
182
203
  const resquestedAmount = amountToCurrency({ asset, amount })
183
204
 
184
- const address = await assetClientInterface.getReceiveAddress({
185
- assetName: asset.name,
186
- walletAccount,
187
- })
188
- const delegatorAddress = address.toLowerCase()
205
+ let delegatorAddress
206
+ ;({ feeData, delegatorAddress } = await getTransactionProps({ feeData, walletAccount }))
207
+
189
208
  const pendingAmount = await staking.pendingBalanceOf(delegatorAddress)
190
209
 
191
210
  console.log(
@@ -201,14 +220,24 @@ export function createEthereumStakingService({
201
220
  resquestedAmount,
202
221
  pendingAmount,
203
222
  minAmount,
223
+ feeData,
204
224
  })
205
225
 
206
226
  txId = await prepareAndSendTx({
207
227
  asset,
208
228
  walletAccount,
209
- waitForConfirmation: true, // wait for tx confirmation in the client
229
+ waitForConfirmation,
210
230
  ...undelegatePendingData,
231
+ feeData,
211
232
  })
233
+
234
+ // If we are waiting for confirmation, then sufficient time
235
+ // will have elapsed for us to re-estimate `feeData`.
236
+ //
237
+ // NOTE: This will invalidate previous transaction fee estimates!
238
+ if (waitForConfirmation) {
239
+ feeData = await assetClientInterface.getFeeData({ assetName: asset.name })
240
+ }
212
241
  }
213
242
 
214
243
  // may need also to unstake
@@ -216,6 +245,7 @@ export function createEthereumStakingService({
216
245
  delegatorAddress,
217
246
  resquestedAmount,
218
247
  pendingAmount,
248
+ feeData,
219
249
  })
220
250
 
221
251
  if (undelegateData.fee) {
@@ -223,6 +253,7 @@ export function createEthereumStakingService({
223
253
  asset,
224
254
  walletAccount,
225
255
  ...undelegateData,
256
+ feeData,
226
257
  })
227
258
  }
228
259
 
@@ -238,26 +269,24 @@ export function createEthereumStakingService({
238
269
  return txId
239
270
  }
240
271
 
241
- async function claimUndelegatedBalance({ walletAccount } = Object.create(null)) {
242
- // claim withdrawable balance (of a previous unstake)
243
- const address = await assetClientInterface.getReceiveAddress({
244
- assetName: asset.name,
245
- walletAccount,
246
- })
247
- const delegatorAddress = address.toLowerCase()
272
+ async function claimUndelegatedBalance({ walletAccount, feeData } = Object.create(null)) {
273
+ let delegatorAddress
274
+ ;({ feeData, delegatorAddress } = await getTransactionProps({ feeData, walletAccount }))
248
275
 
249
276
  const withdrawRequest = await staking.claimWithdrawRequest({
250
277
  address: delegatorAddress,
251
278
  })
279
+
252
280
  if (withdrawRequest) {
253
281
  const { to, data } = withdrawRequest
254
282
 
255
- const { gasLimit, gasPrice, tipGasPrice } = await estimateTxFee(
256
- delegatorAddress,
283
+ const { gasLimit, gasPrice, tipGasPrice } = await estimateTxFee({
284
+ from: delegatorAddress,
257
285
  to,
258
- null,
259
- data
260
- )
286
+ amount: null,
287
+ txInput: data,
288
+ feeData,
289
+ })
261
290
  return prepareAndSendTx({
262
291
  asset,
263
292
  walletAccount,
@@ -266,24 +295,21 @@ export function createEthereumStakingService({
266
295
  gasLimit,
267
296
  gasPrice,
268
297
  tipGasPrice,
298
+ feeData,
269
299
  })
270
300
  }
271
301
  }
272
302
 
273
- async function estimateDelegateOperation({ walletAccount, operation, args }) {
303
+ async function estimateDelegateOperation({ walletAccount, operation, args, feeData }) {
274
304
  const requestedAmount = args.amount
275
305
  ? amountToCurrency({ asset, amount: args.amount })
276
306
  : asset.currency.ZERO
277
307
 
278
- if (operation === 'undelegate') {
279
- return estimateUndelegate({ walletAccount, amount: requestedAmount })
280
- }
308
+ let delegatorAddress
309
+ ;({ delegatorAddress, feeData } = await getTransactionProps({ feeData, walletAccount }))
281
310
 
282
- const address = await assetClientInterface.getReceiveAddress({
283
- assetName: asset.name,
284
- walletAccount,
285
- })
286
- const delegatorAddress = address.toLowerCase()
311
+ if (operation === 'undelegate')
312
+ return estimateUndelegate({ walletAccount, amount: requestedAmount, feeData })
287
313
 
288
314
  const NAMING_MAP = {
289
315
  delegate: 'stake',
@@ -293,14 +319,18 @@ export function createEthereumStakingService({
293
319
 
294
320
  const delegateOperation = staking[NAMING_MAP[operation]].bind(staking)
295
321
 
296
- if (!delegateOperation) {
297
- throw new Error('Invalid staking operation')
298
- }
322
+ if (!delegateOperation) throw new Error('Invalid staking operation')
299
323
 
300
324
  const { amount, data } = await delegateOperation({ ...args, amount: requestedAmount })
301
325
 
302
326
  const { fee } = await (operation === 'claimUndelegatedBalance'
303
- ? estimateTxFee(delegatorAddress, staking.accountingAddress, amount, data)
327
+ ? estimateTxFee({
328
+ from: delegatorAddress,
329
+ to: staking.accountingAddress,
330
+ amount,
331
+ txInput: data,
332
+ feeData,
333
+ })
304
334
  : // The `gasUsed` of a delegation transaction can vary
305
335
  // significantly depending upon whether it will result
306
336
  // in the activation of new slots (i.e. validator creation).
@@ -314,17 +344,18 @@ export function createEthereumStakingService({
314
344
  // 2. Originate the transaction from the WETH contract,
315
345
  // which guarantees deep native ether liquidity which
316
346
  // exceeds any rational user deposit.
317
- estimateTxFee(
318
- WETH9_ADDRESS,
319
- staking.poolAddress,
320
- amount.add(asset.currency.defaultUnit(SLOT_ACTIVATION_PROXIMITY_ETH)),
321
- data
322
- ))
347
+ estimateTxFee({
348
+ from: WETH9_ADDRESS,
349
+ to: staking.poolAddress,
350
+ amount: amount.add(asset.currency.defaultUnit(SLOT_ACTIVATION_PROXIMITY_ETH)),
351
+ txInput: data,
352
+ feeData,
353
+ }))
323
354
 
324
355
  return fee
325
356
  }
326
357
 
327
- async function estimateTxFee(from, to, amount, txInput) {
358
+ async function estimateTxFee({ from, to, amount, txInput, feeData }) {
328
359
  amount = amount || asset.currency.ZERO
329
360
  from = from.toLowerCase()
330
361
 
@@ -347,17 +378,14 @@ export function createEthereumStakingService({
347
378
  EthereumStaking.isDelegationTransactonCalldata(txInput) ? MINIMUM_DELEGATION_GAS_LIMIT : 0
348
379
  )
349
380
 
350
- const feeData = await getEvmStakingServiceFee({
351
- amount,
381
+ const getFeeResult = await asset.api.getFee({
352
382
  asset,
353
- assetClientInterface,
383
+ feeData,
354
384
  gasLimit,
385
+ amount,
355
386
  })
356
387
 
357
- return {
358
- ...feeData,
359
- gasLimit,
360
- }
388
+ return { ...getFeeResult, gasLimit }
361
389
  }
362
390
 
363
391
  /** Returns the minimum possible amount that can be staked. */
@@ -369,9 +397,12 @@ export function createEthereumStakingService({
369
397
  async function getDelegateSelectAllAmount({
370
398
  walletAccount,
371
399
  spendableForStaking = asset.currency.ZERO,
400
+ feeData,
372
401
  }) {
373
402
  const minAmount = getMinAmount()
374
403
 
404
+ ;({ feeData } = await getTransactionProps({ feeData, walletAccount }))
405
+
375
406
  // If the caller hasn't specified a value of `spendableForStaking`
376
407
  // which satisfies the minimum amount, then we'll coerce this value
377
408
  // up to the minimum amount so we can at least provide a rational
@@ -389,6 +420,7 @@ export function createEthereumStakingService({
389
420
  args: {
390
421
  amount: spendableForStaking,
391
422
  },
423
+ feeData,
392
424
  })
393
425
 
394
426
  // If the `spendableForStaking` is insufficient to cover both the
@@ -420,6 +452,7 @@ export function createEthereumStakingService({
420
452
  gasLimit,
421
453
  tipGasPrice,
422
454
  waitForConfirmation = false,
455
+ feeData,
423
456
  } = Object.create(null)
424
457
  ) {
425
458
  const sendTxArgs = {
@@ -436,6 +469,7 @@ export function createEthereumStakingService({
436
469
  // HACK: Override the `tipGasPrice` to use a custom `maxPriorityFeePerGas`.
437
470
  tipGasPrice,
438
471
  },
472
+ feeData,
439
473
  }
440
474
 
441
475
  const { txId } = await asset.baseAsset.api.sendTx(sendTxArgs)