@exodus/ethereum-api 8.61.2 → 8.62.0
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 +20 -0
- package/package.json +3 -3
- package/src/create-asset.js +2 -0
- package/src/eth-like-util.js +27 -0
- package/src/index.js +1 -0
- package/src/tx-create.js +5 -2
- package/src/tx-log/get-optimistic-txlog-effects.js +5 -44
- package/src/tx-log/index.js +1 -4
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.62.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.61.3...@exodus/ethereum-api@8.62.0) (2025-12-22)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
* feat: Add EIP-7702 delegation detection (#7141)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## [8.61.3](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.61.2...@exodus/ethereum-api@8.61.3) (2025-12-17)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
* fix: prevent acceleration of replaced evm transactions (#6964)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
6
26
|
## [8.61.2](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.61.1...@exodus/ethereum-api@8.61.2) (2025-12-15)
|
|
7
27
|
|
|
8
28
|
**Note:** Version bump only for package @exodus/ethereum-api
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/ethereum-api",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.62.0",
|
|
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",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@exodus/bip44-constants": "^195.0.0",
|
|
30
30
|
"@exodus/crypto": "^1.0.0-rc.26",
|
|
31
31
|
"@exodus/currency": "^6.0.1",
|
|
32
|
-
"@exodus/ethereum-lib": "^5.20.
|
|
32
|
+
"@exodus/ethereum-lib": "^5.20.2",
|
|
33
33
|
"@exodus/ethereum-meta": "^2.9.1",
|
|
34
34
|
"@exodus/ethereumholesky-meta": "^2.0.5",
|
|
35
35
|
"@exodus/ethereumjs": "^1.8.0",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"type": "git",
|
|
68
68
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "5702f44af435bd6781879ba3e9b2f28fba655c6c"
|
|
71
71
|
}
|
package/src/create-asset.js
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
} from './create-asset-utils.js'
|
|
30
30
|
import { createTokenFactory } from './create-token-factory.js'
|
|
31
31
|
import { createCustomFeesApi } from './custom-fees.js'
|
|
32
|
+
import { getEIP7702Delegation } from './eth-like-util.js'
|
|
32
33
|
import { createEvmServer } from './exodus-eth-server/index.js'
|
|
33
34
|
import { createFeeData } from './fee-data/index.js'
|
|
34
35
|
import { createGetBalanceForAddress } from './get-balance-for-address.js'
|
|
@@ -302,6 +303,7 @@ export const createAssetFactory = ({
|
|
|
302
303
|
broadcastPrivateBundle,
|
|
303
304
|
broadcastPrivateTx,
|
|
304
305
|
forceGasLimitEstimation,
|
|
306
|
+
getEIP7702Delegation: (addr) => getEIP7702Delegation({ asset: base, address: addr }),
|
|
305
307
|
getNonce,
|
|
306
308
|
privacyServer,
|
|
307
309
|
server,
|
package/src/eth-like-util.js
CHANGED
|
@@ -10,6 +10,8 @@ import { fromHexToString } from './number-utils.js'
|
|
|
10
10
|
export const FORWARDER_CONTRACT_CODE =
|
|
11
11
|
'0x5836818037808036817364b29dc43e817817cf77468c8dda63d98ce08fb25af43d91908282803e602b57fd5bf3'
|
|
12
12
|
|
|
13
|
+
export const EIP7702_DELEGATION_DESIGNATOR = '0xef0100'
|
|
14
|
+
|
|
13
15
|
// @Deprecated
|
|
14
16
|
export async function isContract(baseAssetName, address) {
|
|
15
17
|
return getServerByName(baseAssetName).isContract(address)
|
|
@@ -177,3 +179,28 @@ export const getERC20Params = async ({ asset, address, paramNames = DEFAULT_PARA
|
|
|
177
179
|
|
|
178
180
|
return response
|
|
179
181
|
}
|
|
182
|
+
|
|
183
|
+
export async function getEIP7702Delegation({ asset, address }) {
|
|
184
|
+
const server = getServer(asset)
|
|
185
|
+
const code = await server.getCode(address)
|
|
186
|
+
|
|
187
|
+
// No code at all
|
|
188
|
+
if (!code || code === '0x' || code === '0x0') {
|
|
189
|
+
return { isDelegated: false, delegatedAddress: null }
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// EIP-7702 delegation code must be exactly 23 bytes (46 hex chars + "0x" prefix = 48 chars)
|
|
193
|
+
// Format: 0xef0100 (3 bytes) + address (20 bytes)
|
|
194
|
+
if (code.length !== 48) {
|
|
195
|
+
return { isDelegated: false, delegatedAddress: null }
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Check for EIP-7702 delegation designator prefix
|
|
199
|
+
if (!code.toLowerCase().startsWith(EIP7702_DELEGATION_DESIGNATOR)) {
|
|
200
|
+
return { isDelegated: false, delegatedAddress: null }
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Extract the 20-byte delegated address
|
|
204
|
+
const delegatedAddress = '0x' + code.slice(8, 48)
|
|
205
|
+
return { isDelegated: true, delegatedAddress }
|
|
206
|
+
}
|
package/src/index.js
CHANGED
package/src/tx-create.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
currency2buffer,
|
|
3
|
+
getHighestIncentiveTxByNonce,
|
|
4
|
+
isEthereumLikeToken,
|
|
5
|
+
} from '@exodus/ethereum-lib'
|
|
2
6
|
import createEthereumJsTx from '@exodus/ethereum-lib/src/unsigned-tx/create-ethereumjs-tx.js'
|
|
3
7
|
import assert from 'minimalistic-assert'
|
|
4
8
|
|
|
@@ -6,7 +10,6 @@ import { ensureSaneEip1559GasPriceForTipGasPrice } from './fee-utils.js'
|
|
|
6
10
|
import { fetchGasLimit } from './gas-estimation.js'
|
|
7
11
|
import { getAggregateTransactionPricing, getExtraFeeData } from './get-fee.js'
|
|
8
12
|
import { getNftArguments } from './nft-utils.js'
|
|
9
|
-
import { getHighestIncentiveTxByNonce } from './tx-log/index.js'
|
|
10
13
|
import {
|
|
11
14
|
assertTxAttributes,
|
|
12
15
|
isValidTxType,
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { SynchronizedTime } from '@exodus/basic-utils'
|
|
2
2
|
import NumberUnit from '@exodus/currency'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getHighestIncentiveTxByNonce,
|
|
5
|
+
isEthereumLikeToken,
|
|
6
|
+
parseUnsignedTx,
|
|
7
|
+
} from '@exodus/ethereum-lib'
|
|
4
8
|
import { bufferToHex } from '@exodus/ethereumjs/util'
|
|
5
9
|
import assert from 'minimalistic-assert'
|
|
6
10
|
|
|
@@ -10,49 +14,6 @@ import {
|
|
|
10
14
|
maticDelegateOptimisticSideEffectTxLogs,
|
|
11
15
|
} from '../staking/matic/matic-staking-utils.js'
|
|
12
16
|
|
|
13
|
-
// Returns the most competitively priced pending
|
|
14
|
-
// transaction from the `TxLog` for a given `nonce`.
|
|
15
|
-
//
|
|
16
|
-
// NOTE: If a transaction was successfully included,
|
|
17
|
-
// it is the de-facto highest incentive
|
|
18
|
-
// transaction - irrespective of other
|
|
19
|
-
// attempts for that nonce.
|
|
20
|
-
export const getHighestIncentiveTxByNonce = async ({
|
|
21
|
-
assetClientInterface,
|
|
22
|
-
asset,
|
|
23
|
-
nonce,
|
|
24
|
-
walletAccount,
|
|
25
|
-
}) => {
|
|
26
|
-
assert(assetClientInterface, 'expected assetClientInterface')
|
|
27
|
-
assert(asset, 'expected asset')
|
|
28
|
-
assert(Number.isInteger(nonce), 'expected integer nonce')
|
|
29
|
-
assert(walletAccount, 'expected walletAccount')
|
|
30
|
-
|
|
31
|
-
const txLogSendsByFeeAmountDesc = [
|
|
32
|
-
...(await assetClientInterface.getTxLog({ assetName: asset.name, walletAccount })),
|
|
33
|
-
]
|
|
34
|
-
.filter((tx) => tx.data.nonce === nonce && tx.sent)
|
|
35
|
-
.sort((a, b) => (a.feeAmount.gt(b.feeAmount) ? -1 : b.feeAmount.gt(a.feeAmount) ? 1 : 0))
|
|
36
|
-
|
|
37
|
-
// If any of the transactions competing for this `nonce`
|
|
38
|
-
// were successful, then we can return this transaction
|
|
39
|
-
// as it effectively had the highest game-theoretical
|
|
40
|
-
// incentive regardless of other (potentially higher fee)
|
|
41
|
-
// transactions that were sent.
|
|
42
|
-
//
|
|
43
|
-
// https://github.com/ExodusMovement/exodus-hydra/blob/e59004097f15974a975d14e1823de5d7b1c28308/features/activity-txs/redux/utils/activity-formatters/format-tx-activity.js#L13
|
|
44
|
-
const maybeConfirmedTx = txLogSendsByFeeAmountDesc.find((tx) => !tx.failed && !tx.pending)
|
|
45
|
-
if (maybeConfirmedTx) return maybeConfirmedTx
|
|
46
|
-
|
|
47
|
-
// https://github.com/ExodusMovement/assets/blob/fbe3702861cba3b21885a65b15f038fcd8541891/shield/asset-lib/src/balances-utils.js#L26
|
|
48
|
-
const isUnconfirmed = (tx) => !tx.failed && tx.pending
|
|
49
|
-
|
|
50
|
-
// NOTE: When trying to find the highest incentive of a
|
|
51
|
-
// transaction, consider those which are either still
|
|
52
|
-
// pending.
|
|
53
|
-
return txLogSendsByFeeAmountDesc.find(isUnconfirmed)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
17
|
export const getOptimisticTxLogEffects = async ({
|
|
57
18
|
asset,
|
|
58
19
|
assetClientInterface,
|
package/src/tx-log/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
export { EthereumMonitor } from './ethereum-monitor.js'
|
|
2
2
|
export { EthereumNoHistoryMonitor } from './ethereum-no-history-monitor.js'
|
|
3
3
|
export { ClarityMonitor } from './clarity-monitor.js'
|
|
4
|
-
export {
|
|
5
|
-
getOptimisticTxLogEffects,
|
|
6
|
-
getHighestIncentiveTxByNonce,
|
|
7
|
-
} from './get-optimistic-txlog-effects.js'
|
|
4
|
+
export { getOptimisticTxLogEffects } from './get-optimistic-txlog-effects.js'
|