@exodus/ethereum-api 8.53.2 → 8.53.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,22 @@
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.53.4](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.53.3...@exodus/ethereum-api@8.53.4) (2025-10-06)
7
+
8
+ **Note:** Version bump only for package @exodus/ethereum-api
9
+
10
+
11
+
12
+
13
+
14
+ ## [8.53.3](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.53.2...@exodus/ethereum-api@8.53.3) (2025-10-02)
15
+
16
+ **Note:** Version bump only for package @exodus/ethereum-api
17
+
18
+
19
+
20
+
21
+
6
22
  ## [8.53.2](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.53.1...@exodus/ethereum-api@8.53.2) (2025-10-01)
7
23
 
8
24
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/ethereum-api",
3
- "version": "8.53.2",
3
+ "version": "8.53.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.26",
30
30
  "@exodus/currency": "^6.0.1",
31
- "@exodus/ethereum-lib": "^5.18.0",
31
+ "@exodus/ethereum-lib": "^5.18.1",
32
32
  "@exodus/ethereum-meta": "^2.9.1",
33
33
  "@exodus/ethereumholesky-meta": "^2.0.5",
34
34
  "@exodus/ethereumjs": "^1.8.0",
@@ -37,7 +37,7 @@
37
37
  "@exodus/safe-string": "^1.2.0",
38
38
  "@exodus/simple-retry": "^0.0.6",
39
39
  "@exodus/solidity-contract": "^1.3.0",
40
- "@exodus/web3-ethereum-utils": "^4.2.1",
40
+ "@exodus/web3-ethereum-utils": "^4.5.1",
41
41
  "bn.js": "^5.2.1",
42
42
  "delay": "^4.0.1",
43
43
  "eventemitter3": "^4.0.7",
@@ -66,5 +66,5 @@
66
66
  "type": "git",
67
67
  "url": "git+https://github.com/ExodusMovement/assets.git"
68
68
  },
69
- "gitHead": "890149adb5b7fe3119024435d31ea3bce79d155c"
69
+ "gitHead": "ec39e0d836ef4a4b3d9669273724407cf6dedd5d"
70
70
  }
@@ -1,5 +1,6 @@
1
- import { isNumberUnit } from '@exodus/currency'
2
- import { isEthereumLikeToken } from '@exodus/ethereum-lib'
1
+ import NumberUnit from '@exodus/currency'
2
+ import { isEthereumLikeToken, parseUnsignedTx } from '@exodus/ethereum-lib'
3
+ import { bufferToHex } from '@exodus/ethereumjs/util'
3
4
  import assert from 'minimalistic-assert'
4
5
 
5
6
  // Returns the most competitively priced pending
@@ -30,38 +31,50 @@ export const getHighestIncentivePendingTxByNonce = async ({
30
31
 
31
32
  export const getOptimisticTxLogEffects = async ({
32
33
  asset,
33
- amount = asset.currency.ZERO,
34
34
  assetClientInterface,
35
35
  confirmations = 0,
36
- feeAmount,
37
36
  fromAddress,
38
- gasLimit,
39
- nonce,
40
37
  txId,
41
- toAddress,
42
- tipGasPrice: maybeTipGasPrice,
38
+ unsignedTx,
43
39
  walletAccount,
44
- methodId,
45
40
  }) => {
46
- assert(isNumberUnit(amount), 'expected NumberUnit amount')
47
41
  assert(asset, 'expected asset')
48
42
  assert(assetClientInterface, 'expected assetClientInterface')
49
43
  assert(Number.isInteger(confirmations), 'expected integer confirmations')
50
- assert(isNumberUnit(feeAmount), 'expected feeAmount')
51
44
  assert(typeof fromAddress === 'string', 'expected string fromAddress')
52
- assert(Number.isInteger(gasLimit), 'expected integer gasLimit')
53
- assert(Number.isInteger(nonce), 'expected integer nonce')
54
- assert(typeof toAddress === 'string', 'expected string toAddress')
55
45
  assert(txId, 'expected txId')
46
+ assert(unsignedTx, 'expected unsignedTx')
56
47
  assert(walletAccount, 'expected walletAccount')
57
48
 
58
- if (maybeTipGasPrice) assert(isNumberUnit(maybeTipGasPrice), 'expected NumberUnit tipGasPrice')
49
+ // this converts an transactionBuffer to values we can use when creating the tx logs
50
+ const parsedTx = parseUnsignedTx({ asset, unsignedTx })
59
51
 
60
- const baseAsset = asset.baseAsset
52
+ const { nonce } = parsedTx
53
+ assert(Number.isInteger(nonce), 'expected integer nonce')
54
+
55
+ const amount = parsedTx.amount || asset.currency.ZERO
56
+ assert(amount instanceof NumberUnit, 'expected NumberUnit amount')
57
+
58
+ const feeAmount = parsedTx.fee
59
+ assert(feeAmount instanceof NumberUnit, 'expected feeAmount')
60
+
61
+ const maybeTipGasPrice = parsedTx.tipGasPrice
62
+ if (maybeTipGasPrice) {
63
+ assert(maybeTipGasPrice instanceof NumberUnit, 'expected NumberUnit tipGasPrice')
64
+ }
65
+
66
+ const gasLimit = parsedTx.gasLimit
67
+ assert(Number.isInteger(gasLimit), 'expected integer gasLimit')
68
+
69
+ const toAddress = parsedTx.to
70
+ assert(typeof toAddress === 'string', 'expected string toAddress')
71
+
72
+ const data = parsedTx.data
73
+ const methodId = data ? bufferToHex(data).slice(0, 10) : undefined
61
74
 
62
- // TODO: This is incorrect for token transfers.
63
75
  const selfSend = fromAddress.toLowerCase() === toAddress.toLowerCase()
64
76
 
77
+ const baseAsset = asset.baseAsset
65
78
  assert(asset.feeAsset.name === baseAsset.name, 'inconsistent feeAsset')
66
79
 
67
80
  const maybeTxToReplace = await getHighestIncentivePendingTxByNonce({
@@ -128,5 +141,5 @@ export const getOptimisticTxLogEffects = async ({
128
141
  },
129
142
  ].filter(Boolean)
130
143
 
131
- return { optimisticTxLogEffects }
144
+ return { optimisticTxLogEffects, nonce }
132
145
  }
@@ -1,5 +1,4 @@
1
1
  import { normalizeTxId, parseUnsignedTx, updateNonce } from '@exodus/ethereum-lib'
2
- import { bufferToHex } from '@exodus/ethereumjs/util'
3
2
  import assert from 'minimalistic-assert'
4
3
 
5
4
  import * as ErrorWrapper from '../error-wrapper.js'
@@ -40,17 +39,8 @@ const txSendFactory = ({ assetClientInterface, createTx }) => {
40
39
 
41
40
  const { unsignedTx } = await resolveUnsignedTx()
42
41
 
43
- // this converts an transactionBuffer to values we can use when creating the tx logs
44
42
  const parsedTx = parseUnsignedTx({ asset, unsignedTx })
45
-
46
- let nonce = parsedTx.nonce
47
-
48
- const tipGasPrice = parsedTx.tipGasPrice
49
- const feeAmount = parsedTx.fee
50
- const gasLimit = parsedTx.gasLimit
51
- const amount = parsedTx.amount
52
43
  const toAddress = parsedTx.to
53
- const data = parsedTx.data
54
44
 
55
45
  // unknown data from buffer...
56
46
  const fromAddress = unsignedTx.txMeta.fromAddress
@@ -66,18 +56,8 @@ const txSendFactory = ({ assetClientInterface, createTx }) => {
66
56
  walletAccount,
67
57
  })
68
58
 
69
- const isPrivate = Boolean(legacyParams?.options?.isPrivate)
70
-
71
- if (isPrivate && typeof baseAsset.broadcastPrivateTx !== 'function') {
72
- throw new Error(
73
- `unable to send private transaction - private mempools are not enabled for ${baseAsset.name}`
74
- )
75
- }
76
-
77
- const broadcastTx = isPrivate ? baseAsset.broadcastPrivateTx : baseAsset.api.broadcastTx
78
-
79
59
  try {
80
- await broadcastTx(rawTx.toString('hex'))
60
+ await baseAsset.api.broadcastTx(rawTx.toString('hex'))
81
61
  } catch (err) {
82
62
  const nonceTooLowErr = err.message.match(/nonce (is |)too low/i)
83
63
  const insufficientFundsErr = err.message.match(/insufficient funds/i)
@@ -108,19 +88,19 @@ const txSendFactory = ({ assetClientInterface, createTx }) => {
108
88
  } else if (nonceTooLowErr && !unsignedTx.txMeta.isHardware) {
109
89
  console.info('trying to send again...') // inject logger factory from platform
110
90
  // let's try to fix the nonce issue
111
- const newNonce = await asset.baseAsset.getNonce({
91
+ const newNonce = await baseAsset.getNonce({
112
92
  asset,
113
93
  fromAddress,
114
94
  walletAccount,
115
- triedNonce: nonce,
95
+ triedNonce: parsedTx.nonce,
116
96
  forceFromNode: true,
117
97
  })
118
98
 
119
- unsignedTx.txData.transactionBuffer = updateNonce(
120
- unsignedTx.txData.transactionBuffer,
121
- newNonce
122
- )
123
- nonce = newNonce
99
+ unsignedTx.txData.transactionBuffer = updateNonce({
100
+ chainId: baseAsset.chainId,
101
+ transactionBuffer: unsignedTx.txData.transactionBuffer,
102
+ newNonce,
103
+ })
124
104
  ;({ txId, rawTx } = await signTx({ asset, unsignedTx, walletAccount }))
125
105
 
126
106
  try {
@@ -141,24 +121,23 @@ const txSendFactory = ({ assetClientInterface, createTx }) => {
141
121
  hint: 'retry:broadcastTx',
142
122
  })
143
123
  }
124
+ } else {
125
+ // If none of the above apply, terminate with a general error.
126
+ throw new ErrorWrapper.EthLikeError({
127
+ message: err.message,
128
+ reason: ErrorWrapper.reasons.broadcastTxFailed,
129
+ hint: 'broadcastTx',
130
+ })
144
131
  }
145
132
  }
146
133
 
147
- const methodId = data ? bufferToHex(data).slice(0, 10) : undefined
148
-
149
- const { optimisticTxLogEffects } = await getOptimisticTxLogEffects({
150
- amount,
134
+ const { nonce, optimisticTxLogEffects } = await getOptimisticTxLogEffects({
151
135
  asset,
152
136
  assetClientInterface,
153
- feeAmount,
154
137
  fromAddress,
155
- gasLimit,
156
- nonce,
157
138
  txId,
158
- toAddress,
159
- tipGasPrice,
139
+ unsignedTx,
160
140
  walletAccount,
161
- methodId,
162
141
  })
163
142
 
164
143
  // NOTE: `optimisticTxLogEffects` **must** be written sequentially.