@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.
@@ -70,7 +70,7 @@ export const HACK_maybeRefineSendAllAmount = async ({
70
70
  const txSendFactory = ({ assetClientInterface, createUnsignedTx }) => {
71
71
  assert(assetClientInterface, 'assetClientInterface is required')
72
72
  assert(createUnsignedTx, 'createUnsignedTx is required')
73
- return async ({ asset, walletAccount, address, amount, feeData: maybeFeeData, options = {} }) => {
73
+ return async ({ asset, walletAccount, address, amount, options = {} }) => {
74
74
  const {
75
75
  nft,
76
76
  bumpTxId,
@@ -93,18 +93,13 @@ const txSendFactory = ({ assetClientInterface, createUnsignedTx }) => {
93
93
 
94
94
  const assets = await assetClientInterface.getAssetsForNetwork({ baseAssetName: baseAsset.name })
95
95
 
96
- const feeData =
97
- maybeFeeData ||
98
- (await assetClientInterface.getFeeData({
99
- assetName: baseAsset.name,
100
- }))
101
-
102
- const { eip1559Enabled } = feeData
103
-
104
96
  const fromAddress = await assetClientInterface.getReceiveAddress({
105
97
  assetName: baseAsset.name,
106
98
  walletAccount,
107
99
  })
100
+ const feeData = await assetClientInterface.getFeeData({
101
+ assetName: baseAsset.name,
102
+ })
108
103
 
109
104
  let contractAddress
110
105
  if (nft) {
@@ -117,6 +112,8 @@ const txSendFactory = ({ assetClientInterface, createUnsignedTx }) => {
117
112
 
118
113
  let bumpNonce
119
114
 
115
+ let eip1559Enabled = feeData.eip1559Enabled
116
+
120
117
  const baseAssetTxLog = await assetClientInterface.getTxLog({
121
118
  assetName: baseAsset.name,
122
119
  walletAccount,
@@ -126,47 +123,36 @@ const txSendFactory = ({ assetClientInterface, createUnsignedTx }) => {
126
123
  let replacedTx, replacedTokenTx
127
124
  if (bumpTxId) {
128
125
  replacedTx = baseAssetTxLog.get(bumpTxId)
129
-
130
126
  if (!replacedTx || !replacedTx.pending) {
131
127
  throw new Error(`Cannot bump transaction ${bumpTxId}: not found or confirmed`)
132
128
  }
133
129
 
134
130
  if (replacedTx.tokens.length > 0) {
135
- const [tokenAssetName] = replacedTx.tokens
136
131
  const tokenTxSet = await assetClientInterface.getTxLog({
137
- assetName: tokenAssetName,
132
+ assetName: replacedTx.tokens[0],
138
133
  walletAccount,
139
134
  })
140
135
  replacedTokenTx = tokenTxSet.get(bumpTxId)
141
136
 
142
137
  if (replacedTokenTx) {
143
- // Attempt to overwrite the asset to reflect the fact that
144
- // we're performing a token transaction.
145
- asset = assets[tokenAssetName]
146
- if (!asset) {
147
- console.warn(
148
- `unable to find ${tokenAssetName} during token bump transaction: asset was not available in assetsForNetwork`
149
- )
150
- }
138
+ asset = assets[replacedTx.tokens[0]]
151
139
  }
152
-
153
- // TODO: Should we `throw` if we can't find the asset?
154
140
  }
155
141
 
156
142
  address = (replacedTokenTx || replacedTx).to
157
143
  amount = (replacedTokenTx || replacedTx).coinAmount.negate()
158
144
  feeOpts.gasLimit = replacedTx.data.gasLimit
159
145
 
160
- const { gasPrice: currentGasPrice, baseFeePerGas: currentBaseFee } = feeData
146
+ const { gasPrice: currentGasPrice } = feeData
161
147
  const { bumpedGasPrice, bumpedTipGasPrice } = calculateBumpedGasPrice({
162
148
  baseAsset,
163
149
  tx: replacedTx,
164
150
  currentGasPrice,
165
- currentBaseFee,
166
151
  eip1559Enabled,
167
152
  })
168
153
  feeOpts.gasPrice = bumpedGasPrice
169
154
  feeOpts.tipGasPrice = bumpedTipGasPrice
155
+ eip1559Enabled = feeData.eip1559Enabled && feeOpts.tipGasPrice
170
156
  bumpNonce = replacedTx.data.nonce
171
157
  txInput = replacedTokenTx ? null : replacedTx.data.data || '0x'
172
158
  if (bumpNonce === undefined) {
@@ -174,40 +160,9 @@ const txSendFactory = ({ assetClientInterface, createUnsignedTx }) => {
174
160
  }
175
161
  }
176
162
 
177
- // If we have evaluated a bump transaction and the `providedNonce` differs
178
- // from the `bumpNonce`, we've encountered a conflict and cannot respect
179
- // the caller's request.
180
- if (
181
- typeof bumpNonce === 'number' &&
182
- typeof providedNonce === 'number' &&
183
- bumpNonce !== providedNonce
184
- )
185
- throw new ErrorWrapper.EthLikeError({
186
- message: new Error('incorrect nonce for replacement transaction'),
187
- reason: ErrorWrapper.reasons.bumpTxFailed,
188
- hint: 'providedNonce',
189
- })
190
-
191
- // Choose a nonce that compensates for transctions which are currently
192
- // in pending; for example, when we send transactions at low gas which
193
- // will be stored by `geth` for execution at a later point in time.
194
- //
195
- // When we are not intentionally bumping a transaction, users are
196
- // appending a new transaction to the chain - therefore we should
197
- // be mindful of nonces belonging to us which are currently pending.
198
163
  const resolvedNonce =
199
- providedNonce ??
200
164
  bumpNonce ??
201
- (await resolveNonce({
202
- asset,
203
- fromAddress,
204
- txLog: baseAssetTxLog,
205
- // For assets where we'll fall back to querying the coin node, we
206
- // search for pending transactions. For base assets with history,
207
- // we'll fall back to the `TxLog` since this also has a knowledge
208
- // of which transactions are currently in pending.
209
- tag: 'pending',
210
- }))
165
+ (await resolveNonce({ asset, fromAddress, providedNonce, txLog: baseAssetTxLog }))
211
166
 
212
167
  const createTxParams = {
213
168
  assetClientInterface,
@@ -217,15 +172,14 @@ const txSendFactory = ({ assetClientInterface, createUnsignedTx }) => {
217
172
  amount,
218
173
  nonce: resolvedNonce,
219
174
  fromAddress,
175
+ eip1559Enabled,
220
176
  customFee,
221
177
  feeOpts,
222
178
  txInput,
223
179
  keepTxInput,
224
180
  isSendAll,
225
181
  createUnsignedTx,
226
- feeData,
227
182
  }
228
-
229
183
  let { txId, rawTx, nonce, gasLimit, tipGasPrice, gasPrice } = await createTx(createTxParams)
230
184
 
231
185
  const feeAmount = gasPrice.mul(gasLimit)
@@ -370,13 +324,13 @@ const createTx = async ({
370
324
  amount,
371
325
  nonce,
372
326
  txInput,
327
+ eip1559Enabled = true,
373
328
  keepTxInput = false,
374
- customFee,
329
+ customFee: customGasPrice,
375
330
  isSendAll,
376
331
  fromAddress,
377
332
  feeOpts,
378
333
  createUnsignedTx,
379
- feeData,
380
334
  }) => {
381
335
  assert(
382
336
  nonce !== undefined && typeof nonce === 'number',
@@ -392,7 +346,7 @@ const createTx = async ({
392
346
  ? asset.contract.transfer.build(toAddress.toLowerCase(), amount.toBaseString())
393
347
  : txInput
394
348
 
395
- let { gasLimit, gasPrice, tipGasPrice, eip1559Enabled } = await getFeeInfo({
349
+ let { gasLimit, gasPrice, tipGasPrice } = await getFeeInfo({
396
350
  assetClientInterface,
397
351
  asset,
398
352
  fromAddress,
@@ -400,8 +354,6 @@ const createTx = async ({
400
354
  amount,
401
355
  txInput,
402
356
  feeOpts,
403
- feeData,
404
- customFee,
405
357
  })
406
358
 
407
359
  const isContractToAddress = await isContractAddressCached({ asset, address: toAddress })
@@ -415,16 +367,22 @@ const createTx = async ({
415
367
  // versus estimations, anyway.
416
368
  const isSendAllBaseAsset = isSendAll && !isToken && !isContractToAddress
417
369
 
418
- // For native send all transactions, we have to make sure that
419
- // the `tipGasPrice` is equal to the `gasPrice`, since this is
420
- // effectively like saying that the `maxFeePerGas` is equal
421
- // to the `maxPriorityFeePerGas`. We do this so that for a
422
- // fixed gas cost transaction, no dust balance should remain,
423
- // since any deviation in the underlying `baseFeePerGas` will
424
- // result only affect the tip for the miner - no dust remains.
425
- if (eip1559Enabled && isSendAllBaseAsset) {
426
- // force consuming all gas
427
- tipGasPrice = gasPrice
370
+ if (eip1559Enabled) {
371
+ if (customGasPrice) {
372
+ gasPrice = customGasPrice // aka maxFeePerGas
373
+
374
+ // We must ensure maxPriorityFeePerGas <= maxFeePerGas or our transaction library throws an error
375
+ // It's a bit counterintuitive since maxPriorityFeePerGas should only contain the tip,
376
+ // so we should be subtracting the base gas price from the custom gas price to keep just the tip
377
+ // but the fee is also limited by our maxFeePerGas above, so that implicitly captures the max tip.
378
+ // Setting this tipGasPrice to undefined will result in a legacy transaction (not an EIP1559 anymore)
379
+ tipGasPrice = customGasPrice // aka maxPriorityFeePerGas
380
+ }
381
+
382
+ if (isSendAllBaseAsset) {
383
+ // force consuming all gas
384
+ tipGasPrice = gasPrice
385
+ }
428
386
  }
429
387
 
430
388
  // HACK: If we are handling a send all transaction, we must ensure
@@ -0,0 +1,2 @@
1
+ /* global WebSocket */
2
+ export default WebSocket
@@ -0,0 +1,2 @@
1
+ /* global WebSocket */
2
+ export default WebSocket
@@ -0,0 +1,2 @@
1
+ // Uses cjs to optimize out requiring / bundling ws
2
+ export { default } from './websocket.cjs'
@@ -0,0 +1,21 @@
1
+ /**
2
+ * This is a "light" version of @exodus/core resolution to select the native WebSocket on BE
3
+ * It's a workaround until https://github.com/ExodusMovement/assets/pull/72 is merged.
4
+ *
5
+ * Based on https://github.com/ExodusMovement/fetch/blob/master/core.js , note that chooses native on Desktop
6
+ */
7
+ if (typeof process !== 'undefined' && (process.type === 'renderer' || process.type === 'worker')) {
8
+ // THIS IS FOR DESKTOP
9
+ if (process.env.EXODUS_DISABLE_WS) {
10
+ module.exports = globalThis.WebSocket
11
+ } else {
12
+ module.exports = require('ws')
13
+ }
14
+ // eslint-disable-next-line no-undef
15
+ } else if (typeof WebSocket === 'undefined') {
16
+ // THIS IS FOR UNIT TESTING.
17
+ module.exports = require('ws')
18
+ } else {
19
+ // THIS IS FOR BE
20
+ module.exports = globalThis.WebSocket
21
+ }