@exodus/ethereum-api 8.34.7 → 8.34.8

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.
@@ -1,140 +1,71 @@
1
- import { memoize } from '@exodus/basic-utils'
1
+ import BN from 'bn.js'
2
2
 
3
- import { estimateGasLimit, scaleGasLimitEstimate } from '../../gas-estimation.js'
4
- import { getFeeFactoryGasPrices } from '../../get-fee.js'
3
+ import { getServer } from '../../exodus-eth-server/index.js'
4
+ import { estimateGasLimit } from '../../gas-estimation.js'
5
5
  import { createWatchTx as defaultCreateWatch } from '../../watch-tx.js'
6
6
  import { stakingProviderClientFactory } from '../staking-provider-client.js'
7
- import {
8
- amountToCurrency,
9
- DISABLE_BALANCE_CHECKS,
10
- resolveFeeData as defaultResolveFeeData,
11
- } from '../utils/index.js'
7
+ import { amountToCurrency, getEvmStakingServiceFee } from '../utils/index.js'
12
8
  import { MaticStakingApi } from './api.js'
13
9
 
14
- const createStakingApiForFeeAsset = ({ feeAsset: { server } }) =>
15
- new MaticStakingApi(undefined, undefined, server)
10
+ const DISABLE_BALANCE_CHECKS = '0x0'
11
+ const MAX_PRIORITY_FEE_PER_GAS = '0.06 Gwei' // semi-urgent
16
12
 
17
- // TODO: This should be `createMaticStakingService` to avoid confusion with Polygon staking.
18
13
  export function createPolygonStakingService({
19
14
  assetClientInterface,
20
15
  createWatchTx = defaultCreateWatch,
21
- stakingProvider = stakingProviderClientFactory(),
22
16
  }) {
17
+ const stakingApi = new MaticStakingApi()
23
18
  const assetName = 'ethereum'
19
+ const stakingProvider = stakingProviderClientFactory()
24
20
 
25
- const getStakeAssets = memoize(async () => {
26
- const { polygon: asset, [assetName]: feeAsset } =
27
- await assetClientInterface.getAssetsForNetwork({
28
- baseAssetName: assetName,
29
- })
21
+ async function getStakeAssets() {
22
+ const { polygon: asset, ethereum: feeAsset } = await assetClientInterface.getAssetsForNetwork({
23
+ baseAssetName: assetName,
24
+ })
30
25
  return { asset, feeAsset }
31
- })
32
-
33
- const createStakingApi = memoize(async () => {
34
- const { asset, feeAsset } = await getStakeAssets()
35
- return { asset, feeAsset, stakingApi: createStakingApiForFeeAsset({ feeAsset }) }
36
- })
37
-
38
- // Helper function which selects the correct `asset` to use for when
39
- // determining `feeData` for MATIC staking.
40
- const resolveFeeData = async ({ feeData }) => {
41
- const { feeAsset } = await getStakeAssets()
42
- return defaultResolveFeeData({ asset: feeAsset, assetClientInterface, feeData })
43
- }
44
-
45
- const getLatestFeeData = async () => {
46
- const { feeAsset } = await getStakeAssets()
47
- return assetClientInterface.getFeeData({ assetName: feeAsset.name })
48
26
  }
49
27
 
50
- const resolveOptionalFeeData = async ({ feeData }) => {
51
- // If the caller provides truthy `feeData`, we can continue
52
- // as normal.
53
- if (feeData) return feeData
54
-
55
- // If the caller specifically omits `feeData`, then we
56
- // provide a backup without warning. This is useful for
57
- // calls with no expectations on the caller to provide
58
- // `feeData`, i.e. one-shot transactions, or transactions
59
- // which do not render a fee estimation.
60
- return getLatestFeeData()
61
- }
62
-
63
- const getDelegatorAddress = async ({ walletAccount }) => {
28
+ async function delegate({ walletAccount, amount } = {}) {
64
29
  const address = await assetClientInterface.getReceiveAddress({
65
30
  assetName,
66
31
  walletAccount,
67
32
  })
68
- return address.toLowerCase()
69
- }
70
-
71
- async function delegate({ walletAccount, amount, feeData, waitForConfirmation = true } = {}) {
72
- const [delegatorAddress, { asset, stakingApi }] = await Promise.all([
73
- getDelegatorAddress({ walletAccount }),
74
- createStakingApi(),
75
- ])
76
-
77
- // NOTE: We do not provide a silent fallback for `feeData` omission
78
- // for a delegation transaction, since `feeData` is expected
79
- // to have been provided during `estimateDelegateTxFee`.
80
- feeData = await resolveFeeData({ feeData })
33
+ const delegatorAddress = address.toLowerCase()
81
34
 
35
+ const { asset } = await getStakeAssets()
82
36
  amount = amountToCurrency({ asset, amount })
83
37
 
84
38
  const txApproveData = await stakingApi.approveStakeManager(amount)
85
- let { gasPrice, gasLimit, tipGasPrice } = await estimateTxFee({
86
- from: delegatorAddress,
87
- to: stakingApi.polygonContract.address,
88
- txInput: txApproveData,
89
- feeData,
90
- })
39
+ let { gasPrice, gasLimit, tipGasPrice } = await estimateTxFee(
40
+ delegatorAddress,
41
+ stakingApi.polygonContract.address,
42
+ txApproveData
43
+ )
91
44
  await prepareAndSendTx({
92
45
  walletAccount,
93
- waitForConfirmation,
46
+ waitForConfirmation: true,
94
47
  to: stakingApi.polygonContract.address,
95
48
  txData: txApproveData,
96
49
  gasPrice,
97
50
  gasLimit,
98
51
  tipGasPrice,
99
- feeData,
100
52
  })
101
53
 
102
- // NOTE: Whenever we `waitForConfirmation`, we must recalculate
103
- // the `feeData` as this may have changed since our last
104
- // transaction was mined.
105
- //
106
- // In most cases, this shouldn't affect previous estimates,
107
- // since the amount we aren't trying to stake using the
108
- // base currency; however for users with marginal balances,
109
- // an increase in `gasPrice` could result in transaction
110
- // failure.
111
- //
112
- // HACK: This will invaldiate the original estimate in calculated
113
- // in `estimateDelegateTxFee`!
114
- // TODO: Submit these transactions as an atomic bundle.
115
- if (waitForConfirmation) {
116
- feeData = await getLatestFeeData()
117
- }
118
-
119
54
  const txDelegateData = await stakingApi.delegate({ amount })
120
55
 
121
- ;({ gasPrice, gasLimit, tipGasPrice } = await estimateTxFee({
122
- from: delegatorAddress,
123
- to: stakingApi.validatorShareContract.address,
124
- txInput: txDelegateData,
125
- feeData,
126
- }))
56
+ ;({ gasPrice, gasLimit, tipGasPrice } = await estimateTxFee(
57
+ delegatorAddress,
58
+ stakingApi.validatorShareContract.address,
59
+ txDelegateData
60
+ ))
127
61
 
128
62
  const txId = await prepareAndSendTx({
129
63
  walletAccount,
130
- // TOOD: Why shouldn't we wait for confirmation here? Is it because we want to `notifyStaking`?
131
- waitForConfirmation: false,
132
64
  to: stakingApi.validatorShareContract.address,
133
65
  txData: txDelegateData,
134
66
  gasPrice,
135
67
  gasLimit,
136
68
  tipGasPrice,
137
- feeData,
138
69
  })
139
70
 
140
71
  await stakingProvider.notifyStaking({
@@ -147,24 +78,22 @@ export function createPolygonStakingService({
147
78
  return txId
148
79
  }
149
80
 
150
- async function undelegate({ walletAccount, amount, feeData, waitForConfirmation = false } = {}) {
151
- feeData = await resolveOptionalFeeData({ feeData })
152
-
153
- const [delegatorAddress, { asset, stakingApi }] = await Promise.all([
154
- getDelegatorAddress({ walletAccount }),
155
- createStakingApi(),
156
- ])
81
+ async function undelegate({ walletAccount, amount } = {}) {
82
+ const address = await assetClientInterface.getReceiveAddress({
83
+ assetName,
84
+ walletAccount,
85
+ })
86
+ const delegatorAddress = address.toLowerCase()
157
87
 
88
+ const { asset } = await getStakeAssets()
158
89
  amount = amountToCurrency({ asset, amount })
159
90
 
160
91
  const txUndelegateData = await stakingApi.undelegate({ amount })
161
- const { gasPrice, gasLimit, tipGasPrice } = await estimateTxFee({
162
- from: delegatorAddress.toLowerCase(),
163
- to: stakingApi.validatorShareContract.address,
164
- txInput: txUndelegateData,
165
- feeData,
166
- })
167
-
92
+ const { gasPrice, gasLimit, tipGasPrice } = await estimateTxFee(
93
+ delegatorAddress.toLowerCase(),
94
+ stakingApi.validatorShareContract.address,
95
+ txUndelegateData
96
+ )
168
97
  return prepareAndSendTx({
169
98
  walletAccount,
170
99
  to: stakingApi.validatorShareContract.address,
@@ -172,26 +101,22 @@ export function createPolygonStakingService({
172
101
  gasPrice,
173
102
  gasLimit,
174
103
  tipGasPrice,
175
- feeData,
176
- waitForConfirmation,
177
104
  })
178
105
  }
179
106
 
180
- async function claimRewards({ walletAccount, feeData } = {}) {
181
- feeData = await resolveOptionalFeeData({ feeData })
182
-
183
- const [delegatorAddress, { stakingApi }] = await Promise.all([
184
- getDelegatorAddress({ walletAccount }),
185
- createStakingApi(),
186
- ])
107
+ async function claimRewards({ walletAccount } = {}) {
108
+ const address = await assetClientInterface.getReceiveAddress({
109
+ assetName,
110
+ walletAccount,
111
+ })
112
+ const delegatorAddress = address.toLowerCase()
187
113
 
188
114
  const txWithdrawRewardsData = await stakingApi.withdrawRewards()
189
- const { gasPrice, gasLimit, tipGasPrice } = await estimateTxFee({
190
- from: delegatorAddress,
191
- to: stakingApi.validatorShareContract.address,
192
- txInput: txWithdrawRewardsData,
193
- feeData,
194
- })
115
+ const { gasPrice, gasLimit, tipGasPrice } = await estimateTxFee(
116
+ delegatorAddress,
117
+ stakingApi.validatorShareContract.address,
118
+ txWithdrawRewardsData
119
+ )
195
120
  return prepareAndSendTx({
196
121
  walletAccount,
197
122
  to: stakingApi.validatorShareContract.address,
@@ -199,18 +124,17 @@ export function createPolygonStakingService({
199
124
  gasPrice,
200
125
  gasLimit,
201
126
  tipGasPrice,
202
- feeData,
203
127
  })
204
128
  }
205
129
 
206
- async function claimUndelegatedBalance({ walletAccount, unbondNonce, feeData } = {}) {
207
- feeData = await resolveOptionalFeeData({ feeData })
208
-
209
- const [delegatorAddress, { asset, stakingApi }] = await Promise.all([
210
- getDelegatorAddress({ walletAccount }),
211
- createStakingApi(),
212
- ])
130
+ async function claimUndelegatedBalance({ walletAccount, unbondNonce } = {}) {
131
+ const address = await assetClientInterface.getReceiveAddress({
132
+ assetName,
133
+ walletAccount,
134
+ })
135
+ const delegatorAddress = address.toLowerCase()
213
136
 
137
+ const { asset } = await getStakeAssets()
214
138
  const { currency } = asset
215
139
  const unstakedClaimInfo = await fetchUnstakedClaimInfo({
216
140
  stakingApi,
@@ -225,12 +149,11 @@ export function createPolygonStakingService({
225
149
  })
226
150
 
227
151
  const txClaimUndelegatedData = await stakingApi.claimUndelegatedBalance({ unbondNonce })
228
- const { gasPrice, gasLimit, tipGasPrice } = await estimateTxFee({
229
- from: delegatorAddress,
230
- to: stakingApi.validatorShareContract.address,
231
- txInput: txClaimUndelegatedData,
232
- feeData,
233
- })
152
+ const { gasPrice, gasLimit, tipGasPrice, fee } = await estimateTxFee(
153
+ delegatorAddress,
154
+ stakingApi.validatorShareContract.address,
155
+ txClaimUndelegatedData
156
+ )
234
157
  const txId = await prepareAndSendTx({
235
158
  walletAccount,
236
159
  to: stakingApi.validatorShareContract.address,
@@ -238,7 +161,7 @@ export function createPolygonStakingService({
238
161
  gasPrice,
239
162
  gasLimit,
240
163
  tipGasPrice,
241
- feeData,
164
+ fee,
242
165
  })
243
166
 
244
167
  await stakingProvider.notifyUnstaking({
@@ -251,42 +174,31 @@ export function createPolygonStakingService({
251
174
  return txId
252
175
  }
253
176
 
254
- async function estimateDelegateOperation({
255
- walletAccount,
256
- operation,
257
- args,
258
- // NOTE: When estimating transactions, ideally we'd expect the `feeData`
259
- // that we intend to send the transaction using. If this is not
260
- // defined, we'll fallback to a default (with a warning).
261
- feeData,
262
- }) {
263
- // HACK: For delegation transactions, we must fall back to the
264
- // custom implementation, since we can't currently estimate
265
- // the transaction due to a dependence upon approvals.
266
- if (operation === 'delegate') return estimateDelegateTxFee({ feeData })
267
-
268
- const [delegatorAddress, { asset, stakingApi }] = await Promise.all([
269
- getDelegatorAddress({ walletAccount }),
270
- createStakingApi(),
271
- ])
272
-
273
- feeData = await resolveFeeData({ feeData })
274
-
177
+ async function estimateDelegateOperation({ walletAccount, operation, args }) {
275
178
  const delegateOperation = stakingApi[operation]
276
- if (!delegateOperation) return
179
+
180
+ if (!delegateOperation) {
181
+ return
182
+ }
183
+
184
+ const address = await assetClientInterface.getReceiveAddress({
185
+ assetName,
186
+ walletAccount,
187
+ })
188
+ const delegatorAddress = address.toLowerCase()
277
189
 
278
190
  const { amount } = args
279
191
  if (amount) {
192
+ const { asset } = await getStakeAssets()
280
193
  args = { ...args, amount: amountToCurrency({ asset, amount }) }
281
194
  }
282
195
 
283
196
  const operationTxData = await delegateOperation({ ...args, walletAccount })
284
- const { fee } = await estimateTxFee({
285
- from: delegatorAddress,
286
- to: stakingApi.validatorShareContract.address,
287
- txInput: operationTxData,
288
- feeData,
289
- })
197
+ const { fee } = await estimateTxFee(
198
+ delegatorAddress,
199
+ stakingApi.validatorShareContract.address,
200
+ operationTxData
201
+ )
290
202
 
291
203
  return fee
292
204
  }
@@ -301,27 +213,23 @@ export function createPolygonStakingService({
301
213
  * This is just for displaying purposes and it's just an aproximation of the delegate gas cost,
302
214
  * NOT the real fee cost
303
215
  */
304
- async function estimateDelegateTxFee({ feeData } = {}) {
216
+ async function estimateDelegateTxFee() {
305
217
  // approx gas limits
306
218
  const { ethereum } = await assetClientInterface.getAssetsForNetwork({
307
219
  baseAssetName: 'ethereum',
308
220
  })
221
+ const erc20ApproveGas = 4900
222
+ const delegateGas = 240_000
223
+ const gasPrice = parseInt(await getServer(ethereum).gasPrice(), 16)
224
+ const extraPercentage = 20
225
+
226
+ const gasLimit = erc20ApproveGas + delegateGas
227
+ const gasLimitWithBuffer = new BN(gasLimit)
228
+ .imuln(100 + extraPercentage)
229
+ .idivn(100)
230
+ .toString()
309
231
 
310
- feeData = await resolveFeeData({ feeData })
311
-
312
- // TODO: update estimation to use a mock source address for
313
- // deposits so we can simulate the necessary approvals,
314
- // we shouldn't maintain constants like these
315
- const erc20ApproveGas = 80_000
316
- const delegateGas = 250_000
317
-
318
- const { gasPrice } = getFeeFactoryGasPrices({ feeData })
319
-
320
- const gasLimitWithBuffer = scaleGasLimitEstimate({
321
- estimatedGasLimit: BigInt(erc20ApproveGas + delegateGas),
322
- })
323
-
324
- const fee = BigInt(gasLimitWithBuffer) * BigInt(gasPrice.toBaseNumber())
232
+ const fee = new BN(gasLimitWithBuffer).mul(new BN(gasPrice))
325
233
 
326
234
  return {
327
235
  gasLimit: gasLimitWithBuffer,
@@ -330,7 +238,7 @@ export function createPolygonStakingService({
330
238
  }
331
239
  }
332
240
 
333
- async function estimateTxFee({ from, to, txInput, feeData }) {
241
+ async function estimateTxFee(from, to, txInput) {
334
242
  const { ethereum } = await assetClientInterface.getAssetsForNetwork({
335
243
  baseAssetName: 'ethereum',
336
244
  })
@@ -346,7 +254,13 @@ export function createPolygonStakingService({
346
254
  DISABLE_BALANCE_CHECKS
347
255
  )
348
256
 
349
- return ethereum.api.getFee({ asset: ethereum, feeData, gasLimit, amount })
257
+ return getEvmStakingServiceFee({
258
+ amount,
259
+ asset: ethereum,
260
+ assetClientInterface,
261
+ maxPriorityFeePerGas: MAX_PRIORITY_FEE_PER_GAS,
262
+ gasLimit,
263
+ })
350
264
  }
351
265
 
352
266
  async function prepareAndSendTx({
@@ -357,7 +271,6 @@ export function createPolygonStakingService({
357
271
  gasLimit,
358
272
  tipGasPrice,
359
273
  waitForConfirmation = false,
360
- feeData,
361
274
  } = {}) {
362
275
  const { ethereum: asset } = await assetClientInterface.getAssetsForNetwork({
363
276
  baseAssetName: 'ethereum',
@@ -375,7 +288,6 @@ export function createPolygonStakingService({
375
288
  tipGasPrice,
376
289
  },
377
290
  waitForConfirmation,
378
- feeData,
379
291
  }
380
292
 
381
293
  const { txId } = await asset.baseAsset.api.sendTx(sendTxArgs)
@@ -497,8 +409,9 @@ async function fetchRewardsInfo({ stakingApi, delegator, currency }) {
497
409
  }
498
410
  }
499
411
 
500
- export async function getPolygonStakingInfo({ address, asset: { currency, baseAsset: feeAsset } }) {
501
- const stakingApi = createStakingApiForFeeAsset({ feeAsset })
412
+ export async function getPolygonStakingInfo({ address, asset, server }) {
413
+ const { currency } = asset
414
+ const stakingApi = new MaticStakingApi(undefined, undefined, server)
502
415
  const delegator = address.toLowerCase()
503
416
  const [
504
417
  delegatedBalance,
@@ -1,39 +1,73 @@
1
1
  import { isNumberUnit } from '@exodus/currency'
2
2
 
3
- export const DISABLE_BALANCE_CHECKS = '0x0'
4
-
5
3
  export function amountToCurrency({ asset, amount }) {
6
4
  return isNumberUnit(amount) ? amount : asset.currency.parse(amount)
7
5
  }
8
6
 
7
+ // HACK: Empirically, we can observe that a `feeData` object uses
8
+ // stringified values for gas i.e. `baseFeePerGas: "10 gwei"`,
9
+ // however to hook into `asset.api.getFees()`, these values
10
+ // must be expressed using currency objects.
11
+ function maybeNormalizeFeeData({ asset, feeData }) {
12
+ const { baseFeePerGas, tipGasPrice, serverGasPrice, gasPrice, ...extras } = feeData
13
+
14
+ const maybeNormalizeAmount = (amount) =>
15
+ typeof amount === 'string' ? amountToCurrency({ amount, asset }) : amount
16
+
17
+ return {
18
+ ...extras,
19
+ gasPrice: maybeNormalizeAmount(gasPrice),
20
+ baseFeePerGas: maybeNormalizeAmount(baseFeePerGas),
21
+ tipGasPrice: maybeNormalizeAmount(tipGasPrice),
22
+ serverGasPrice: maybeNormalizeAmount(serverGasPrice),
23
+ }
24
+ }
25
+
9
26
  /**
10
- * Previously, EVM staking services would determine `feeData`
11
- * dynamically on behalf of callers, however, this risks invalidating
12
- * fee estimation over the course of a sequence of multiple staking
13
- * transactions.
14
- *
15
- * For example, when determining the amount for a `sendAll`
16
- * transaction, if the gas price were to increase between estimation
17
- * and execution, this would invalidate the previous estimation.
18
- *
19
- * In future usage, we would want assets code to fetch FeeData from ACI,
20
- * construct a transaction including determining the fee and then report
21
- * back to the client what the fee is going to be.
22
- *
23
- * Importantly, the provided `feeData` must be sufficiently
24
- * up-to-date; else, we risk the transactions not being included at all.
27
+ * A common handler for the computation of the `fee`, `gasPrice`,
28
+ * `gasLimit` and `tipGasPrice` or a staking call. Allows the caller
29
+ * to specify a custom `maxPriorityFeePerGas` whilst the current
30
+ * `tipGasPrice` is incompatible with EIP-1559 pricing.
25
31
  */
26
- export const resolveFeeData = async ({
27
- // TODO: maybe asset name would be better
32
+ export async function getEvmStakingServiceFee({
33
+ amount,
28
34
  asset,
29
35
  assetClientInterface,
30
- feeData,
31
- }) => {
32
- if (feeData) return feeData
36
+ maxPriorityFeePerGas: maybeMaxPriorityFeePerGas,
37
+ gasLimit,
38
+ }) {
39
+ const defaultFeeData = await assetClientInterface.getFeeData({
40
+ assetName: asset.name,
41
+ })
42
+
43
+ // HACK: We wish to explicitly enable `useBaseGasPrice`
44
+ // since we're using a custom `tipGasPrice`. This
45
+ // will be compatible during the transition from
46
+ // Magnifier to Clarity, and can be safely removed
47
+ // once `useBaseGasPrice` is the default behaviour
48
+ // (alongside the custom tip).
49
+ const { eip1559Enabled } = defaultFeeData
50
+ const useBaseGasPrice = Boolean(eip1559Enabled) && Boolean(maybeMaxPriorityFeePerGas)
33
51
 
34
- console.warn(
35
- 'The evm staking service was not explicitly passed `feeData`. This can result in transaction nondeterminism.'
36
- )
52
+ const normalizedFeeData = maybeNormalizeFeeData({
53
+ asset,
54
+ feeData: {
55
+ ...defaultFeeData,
56
+ // HACK: The backend currently exports a very large `tipGasPrice` that is
57
+ // compatible with Magnifier's legacy `gasPrice`, but it would
58
+ // be incompatible with EIP-1559, since this would evaluate into
59
+ // a very large `maxPriorityFeePerGas`.
60
+ ...(useBaseGasPrice ? { tipGasPrice: maybeMaxPriorityFeePerGas } : null),
61
+ useBaseGasPrice,
62
+ },
63
+ })
37
64
 
38
- return assetClientInterface.getFeeData({ assetName: asset.name })
65
+ // Returns `fee`, `gasPrice`, `extraFeeData`, and `tipGasPrice`
66
+ // if the config defines we should `useBaseGasPrice`.
67
+ return asset.api.getFee({
68
+ asset,
69
+ feeData: normalizedFeeData,
70
+ gasLimit,
71
+ amount,
72
+ })
39
73
  }
@@ -1,6 +1,4 @@
1
- import { ensureSaneEip1559GasPriceForTipGasPrice } from '../fee-utils.js'
2
1
  import { fetchGasLimit } from '../gas-estimation.js'
3
- import { getFeeFactoryGasPrices } from '../get-fee.js'
4
2
 
5
3
  const getFeeInfo = async function getFeeInfo({
6
4
  assetClientInterface,
@@ -10,48 +8,25 @@ const getFeeInfo = async function getFeeInfo({
10
8
  amount,
11
9
  txInput,
12
10
  feeOpts = {},
13
- feeData,
14
- customFee,
15
11
  }) {
16
- // HACK: Previously, calls `getFeeInfo` were not provided a reference
17
- // to `feeData`. For backwards compatibility, we'll revert to
18
- // legacy behaviour.
19
- // NOTE: This shouldn't actually be used outside of the `assets` repo;
20
- // this is done just for safety.
21
- if (!feeData) {
22
- console.warn('`getFeeInfo` was not explicitly passed a `feeData` object.')
23
- const { name: assetName } = asset
24
- feeData = await assetClientInterface.getFeeData({ assetName })
25
- }
26
-
27
- const {
28
- gasPrice: gasPrice_,
29
- feeData: { tipGasPrice: tipGasPrice_, eip1559Enabled },
30
- } = getFeeFactoryGasPrices({ customFee, feeData })
31
-
32
- const tipGasPrice = feeOpts.tipGasPrice || tipGasPrice_
12
+ const { gasPrice: gasPrice_, tipGasPrice: tipGasPrice_ } = await assetClientInterface.getFeeData({
13
+ assetName: asset.name,
14
+ })
33
15
 
34
- const maybeGasPrice = feeOpts.gasPrice || gasPrice_
16
+ let { gasLimit, gasPrice = gasPrice_, tipGasPrice = tipGasPrice_ } = feeOpts
35
17
 
36
- // HACK: If we've received an invalid combination of `tipGasPrice`
37
- // (maxPriorityFeePerGas) and `gasPrice` (maxFeePerGas), then
38
- // we must normalize these before returning.
39
- const gasPrice = eip1559Enabled
40
- ? ensureSaneEip1559GasPriceForTipGasPrice({ gasPrice: maybeGasPrice, tipGasPrice })
41
- : maybeGasPrice
42
-
43
- const gasLimit =
44
- feeOpts.gasLimit ||
45
- (await fetchGasLimit({
18
+ if (!gasLimit) {
19
+ gasLimit = await fetchGasLimit({
46
20
  asset,
47
21
  fromAddress,
48
22
  toAddress,
49
23
  amount,
50
24
  txInput,
51
25
  throwOnError: false,
52
- }))
26
+ })
27
+ }
53
28
 
54
- return { gasPrice, gasLimit, tipGasPrice, eip1559Enabled }
29
+ return { gasPrice, gasLimit, tipGasPrice }
55
30
  }
56
31
 
57
32
  export default getFeeInfo
@@ -7,11 +7,10 @@ export const resolveNonce = async ({
7
7
  providedNonce,
8
8
  txLog,
9
9
  triedNonce,
10
- tag = 'latest', // use 'pending' for unconfirmed txs
11
10
  }) => {
12
11
  const nonceFromNode =
13
12
  asset.baseAsset?.api?.features?.noHistory || forceFromNode
14
- ? await getNonce({ asset: asset.baseAsset, address: fromAddress, tag })
13
+ ? await getNonce({ asset: asset.baseAsset, address: fromAddress, tag: 'latest' }) // maybe 'pending' to unconfirmed txs
15
14
  : 0
16
15
 
17
16
  const nonceFromLog = [...txLog]