@exodus/ethereum-lib 5.12.0 → 5.13.1

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,28 @@
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
+ ## [5.13.1](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-lib@5.13.0...@exodus/ethereum-lib@5.13.1) (2025-06-23)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+
12
+ * fix: basemainnet main asset rpc only (#5904)
13
+
14
+
15
+
16
+ ## [5.13.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-lib@5.12.0...@exodus/ethereum-lib@5.13.0) (2025-06-18)
17
+
18
+
19
+ ### Features
20
+
21
+
22
+ * feat: allow transactionBuffer in unsignedTx (#5883)
23
+
24
+ * feat: remove eth sepolia and goerli (#5885)
25
+
26
+
27
+
6
28
  ## [5.12.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-lib@5.11.0...@exodus/ethereum-lib@5.12.0) (2025-06-11)
7
29
 
8
30
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/ethereum-lib",
3
- "version": "5.12.0",
3
+ "version": "5.13.1",
4
4
  "description": "Ethereum utils, such as for cryptography, address encoding/decoding, transaction building, etc.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -24,7 +24,7 @@
24
24
  "@exodus/basic-utils": "^3.0.1",
25
25
  "@exodus/crypto": "^1.0.0-rc.18",
26
26
  "@exodus/currency": "^6.0.1",
27
- "@exodus/ethereumjs": "^1.5.0",
27
+ "@exodus/ethereumjs": "^1.6.0",
28
28
  "@exodus/key-utils": "^3.7.0",
29
29
  "@exodus/models": "^12.13.0",
30
30
  "@exodus/solidity-contract": "^1.1.3",
@@ -50,5 +50,5 @@
50
50
  "type": "git",
51
51
  "url": "git+https://github.com/ExodusMovement/assets.git"
52
52
  },
53
- "gitHead": "2172464a34a03cb2c2401f80db89d4609cb0528f"
53
+ "gitHead": "ff29985705f3a5b14aba9fff28709fa2ef395a45"
54
54
  }
package/src/constants.js CHANGED
@@ -12,21 +12,11 @@ const CHAIN_DATA = {
12
12
  serverUrl: 'https://getc.a.exodus.io/wallet/v1/',
13
13
  confirmationsNumber: 5000,
14
14
  },
15
- ethereumgoerli: {
16
- chainId: 5,
17
- serverUrl: 'https://geth-goerli-testnet-d.a.exodus.io/wallet/v1/',
18
- confirmationsNumber: 30,
19
- },
20
15
  ethereumholesky: {
21
16
  chainId: 17_000,
22
17
  serverUrl: 'https://geth-holesky-testnet-d.a.exodus.io/wallet/v1/',
23
18
  confirmationsNumber: 30,
24
19
  },
25
- ethereumsepolia: {
26
- chainId: 11_155_111,
27
- serverUrl: 'https://geth-sepolia-testnet-d.a.exodus.io/wallet/v1/',
28
- confirmationsNumber: 30,
29
- },
30
20
  bsc: {
31
21
  chainId: 56,
32
22
  serverUrl: 'https://bsc-clarity.a.exodus.io/',
@@ -146,7 +136,3 @@ export const CONFIRMATIONS_NUMBER = mapValues(
146
136
  export const ETHEREUM_LIKE_ASSETS = Object.keys(CHAIN_DATA)
147
137
 
148
138
  export const BUMP_RATE = 1.2
149
- /* @deprecated */
150
- export const ETHEREUM_LIKE_NO_HISTORY_ASSET_NAMES = Object.keys(CHAIN_DATA).filter(
151
- (key) => CHAIN_DATA[key].monitorType === 'no-history'
152
- )
@@ -1,24 +1,63 @@
1
1
  import { Common, Hardfork } from '@exodus/ethereumjs/common'
2
2
  import { FeeMarketEIP1559Transaction, Transaction } from '@exodus/ethereumjs/tx'
3
+ import { toBuffer } from '@exodus/ethereumjs/util'
4
+ import lodash from 'lodash'
5
+ import assert from 'minimalistic-assert'
6
+
7
+ const { isEmpty } = lodash
8
+
9
+ const parseBufferToJsTx = (unsignedTx) => {
10
+ const { transactionBuffer, ...legacyTxData } = unsignedTx.txData
11
+ assert(
12
+ isEmpty(legacyTxData),
13
+ 'Cannot create ethereum js tx when transactionBuffer and other fields are provided!'
14
+ )
15
+
16
+ if (FeeMarketEIP1559Transaction.isEip1559SerializedTx(transactionBuffer))
17
+ return FeeMarketEIP1559Transaction.fromSerializedTx(transactionBuffer)
18
+ return Transaction.fromSerializedTx(transactionBuffer)
19
+ }
3
20
 
4
21
  export default function createEthereumJsTx(unsignedTx) {
5
22
  const {
6
- txData: { chainId, ...txData },
7
- txMeta: { eip1559Enabled },
23
+ txData: { transactionBuffer, ...legacyTxData },
8
24
  } = unsignedTx
9
- const { gasPrice, tipGasPrice } = txData
10
25
 
26
+ if (transactionBuffer) {
27
+ return parseBufferToJsTx(unsignedTx)
28
+ }
29
+
30
+ const {
31
+ chainId,
32
+ nonce: providedNonce,
33
+ gasPrice,
34
+ gasLimit: providedGasLimit,
35
+ tipGasPrice,
36
+ data: providedData,
37
+ value,
38
+ ...txData
39
+ } = legacyTxData
40
+
41
+ const bufferData = toBuffer(providedData)
42
+
43
+ const gasLimit = toBuffer(providedGasLimit)
44
+ const data = bufferData.equals(Buffer.from([0])) ? Buffer.alloc(0) : bufferData
45
+ const nonce = providedNonce === 0 ? Buffer.alloc(0) : toBuffer(providedNonce)
11
46
  /*
12
47
  EIP1559 is not supported by all ethereum-like assets.
13
48
  e.g BSC does not support EIP1559 at the moment, prevent building an EIP1559 transaction
14
49
  if `tipGasPrice` or `maxPriorityFeePerGas` is set.
15
50
  */
16
51
  const isEip1559Tx = !!(unsignedTx.txData.tipGasPrice || unsignedTx.txData.maxPriorityFeePerGas)
17
- if (eip1559Enabled && isEip1559Tx) {
52
+ if (unsignedTx.txMeta.eip1559Enabled && isEip1559Tx) {
18
53
  return FeeMarketEIP1559Transaction.fromTxData(
19
54
  {
20
55
  maxFeePerGas: gasPrice,
21
56
  maxPriorityFeePerGas: tipGasPrice,
57
+ nonce,
58
+ gasLimit,
59
+ data,
60
+ value,
22
61
  // `maxPriorityFeePerGas`, `maxFeePerGas` set in `txData` below take precedence over ^.
23
62
  ...txData,
24
63
  },
@@ -34,5 +73,8 @@ export default function createEthereumJsTx(unsignedTx) {
34
73
  }
35
74
 
36
75
  // Legacy tx
37
- return Transaction.fromTxData(txData, { common: Common.custom({ chainId }) })
76
+ return Transaction.fromTxData(
77
+ { nonce, gasPrice, tipGasPrice, gasLimit, data, value, ...txData },
78
+ { common: Common.custom({ chainId }) }
79
+ )
38
80
  }
@@ -1,34 +1,108 @@
1
+ import { FeeMarketEIP1559Transaction, Transaction } from '@exodus/ethereumjs/tx'
1
2
  import { bufferToInt } from '@exodus/ethereumjs/util'
3
+ import lodash from 'lodash'
4
+ import assert from 'minimalistic-assert'
2
5
 
3
6
  import { buffer2currency, isToken } from '../utils/index.js'
4
7
 
5
- export default function parseUnsignedTx(asset, unsignedTx) {
6
- const { txData } = unsignedTx
7
- const _isToken = isToken(asset)
8
+ const { isEmpty } = lodash
9
+
10
+ const getCommonTransactionProps = ({ transaction, baseAsset }) => {
11
+ return {
12
+ data: transaction.data,
13
+ to: transaction.to.toString('hex'),
14
+ gasLimit: transaction.gasLimit.toNumber(),
15
+ value: baseAsset.currency.baseUnit(transaction.value),
16
+ nonce: transaction.nonce.toNumber(),
17
+ }
18
+ }
19
+
20
+ const parseBuffer = (asset, unsignedTx) => {
21
+ const { transactionBuffer, ...legacyTxData } = unsignedTx.txData
8
22
  const baseAsset = asset.baseAsset
9
- const gasPrice = buffer2currency({ asset: baseAsset, value: txData.gasPrice })
10
- const gasLimit = bufferToInt(txData.gasLimit)
23
+ assert(
24
+ isEmpty(legacyTxData),
25
+ 'Cannot parse tx when transactionBuffer and other fields are provided!'
26
+ )
27
+ if (FeeMarketEIP1559Transaction.isEip1559SerializedTx(transactionBuffer)) {
28
+ const transaction = FeeMarketEIP1559Transaction.fromSerializedTx(transactionBuffer)
29
+ return {
30
+ ...getCommonTransactionProps({ transaction, baseAsset }),
31
+ tipGasPrice: baseAsset.currency.baseUnit(transaction.maxPriorityFeePerGas),
32
+ gasPrice: baseAsset.currency.baseUnit(transaction.maxFeePerGas),
33
+ eip1559Enabled: true,
34
+ }
35
+ }
36
+
37
+ const transaction = Transaction.fromSerializedTx(transactionBuffer)
38
+ return {
39
+ ...getCommonTransactionProps({ transaction, baseAsset }),
40
+ gasPrice: baseAsset.currency.baseUnit(transaction.gasPrice),
41
+ eip1559Enabled: false,
42
+ }
43
+ }
44
+
45
+ function resolveToAmount({ asset, data, value, to: rawTo }) {
46
+ const _isToken = isToken(asset)
11
47
 
12
- let { to, data, value } = txData
13
- let amount
14
- const fee = gasPrice.mul(gasLimit)
15
48
  if (_isToken) {
16
49
  const { method, values } = asset.contract.decodeInput(data)
17
- if (method === 'transfer' || method === 'approve') {
18
- to = values[0]
19
- amount = asset.currency.baseUnit(values[1])
20
- } else {
21
- to = values[0]
22
- amount = asset.currency.ZERO
23
- }
24
- } else {
25
- amount = buffer2currency({ asset, value })
50
+ if (method === 'transfer' || method === 'approve')
51
+ return {
52
+ to: values[0],
53
+ amount: asset.currency.baseUnit(values[1]),
54
+ }
55
+
56
+ return { to: values[0], amount: asset.currency.ZERO }
57
+ }
58
+
59
+ return {
60
+ amount: value,
61
+ to: rawTo,
26
62
  }
63
+ }
64
+
65
+ export default function parseUnsignedTx({ asset, unsignedTx }) {
66
+ assert(asset, 'asset is required')
67
+ assert(unsignedTx, 'unsignedTx is required')
68
+ const baseAsset = asset.baseAsset
69
+ const txData = unsignedTx.txData
70
+ const {
71
+ to: rawTo,
72
+ data,
73
+ value,
74
+ gasLimit,
75
+ gasPrice,
76
+ tipGasPrice,
77
+ eip1559Enabled,
78
+ nonce,
79
+ } = txData.transactionBuffer
80
+ ? parseBuffer(asset, unsignedTx)
81
+ : {
82
+ data: txData.data,
83
+ to: txData.to,
84
+ value: buffer2currency({ asset: baseAsset, value: txData.value }),
85
+ gasPrice: buffer2currency({ asset: baseAsset, value: txData.gasPrice }),
86
+ tipGasPrice: txData.tipGasPrice
87
+ ? buffer2currency({ asset: baseAsset, value: txData.tipGasPrice })
88
+ : undefined,
89
+ eip1559Enabled: Boolean(txData.tipGasPrice),
90
+ gasLimit: bufferToInt(txData.gasLimit),
91
+ nonce: bufferToInt(txData.nonce),
92
+ }
93
+
94
+ const fee = gasPrice.mul(gasLimit)
95
+ const { to, amount } = resolveToAmount({ asset, data, value, to: rawTo })
27
96
 
28
97
  return {
29
98
  to,
30
99
  amount,
31
100
  fee,
101
+ gasLimit,
102
+ gasPrice,
103
+ tipGasPrice,
104
+ eip1559Enabled,
105
+ nonce,
32
106
  from: null, // TODO: how?
33
107
  }
34
108
  }
@@ -2,9 +2,6 @@ import { FeeMarketEIP1559Transaction, Transaction } from '@exodus/ethereumjs/tx'
2
2
  import { padToEven, toBuffer } from '@exodus/ethereumjs/util'
3
3
  import baseX from 'base-x'
4
4
 
5
- // eslint-disable-next-line @exodus/import/no-deprecated
6
- import { ETHEREUM_LIKE_NO_HISTORY_ASSET_NAMES } from '../constants.js'
7
-
8
5
  export { default as calculateExtraEth } from './calculate-extra-eth.js'
9
6
 
10
7
  const base10 = baseX('0123456789')
@@ -13,12 +10,8 @@ const base16 = baseX('0123456789abcdef')
13
10
  /* @deprecated */
14
11
  export const isEthereumToken = (asset) => asset.assetType === 'ETHEREUM_ERC20'
15
12
  /* @deprecated */
16
- export const isEthereumGoerliToken = (asset) => asset.assetType === 'ETHEREUM_GOERLI_ERC20'
17
- /* @deprecated */
18
13
  export const isEthereumHoleskyToken = (asset) => asset.assetType === 'ETHEREUM_HOLESKY_ERC20'
19
14
  /* @deprecated */
20
- export const isEthereumSepoliaToken = (asset) => asset.assetType === 'ETHEREUM_SEPOLIA_ERC20'
21
- /* @deprecated */
22
15
  export const isBscToken = (asset) => asset.assetType === 'BSC_BEP20'
23
16
  /* @deprecated */
24
17
  export const isPolygonToken = (asset) => asset.assetType === 'MATIC_ERC20'
@@ -144,6 +137,7 @@ export const isRpcBalanceAsset = (asset) =>
144
137
  [
145
138
  'ethereumarbone',
146
139
  'fantommainnet',
140
+ 'basemainnet',
147
141
  'matic',
148
142
  'optimism',
149
143
  'ousd_ethereum_48fcf72d',
@@ -151,7 +145,7 @@ export const isRpcBalanceAsset = (asset) =>
151
145
  'weth',
152
146
  ...customTokensWithRpcBalance,
153
147
  // eslint-disable-next-line @exodus/import/no-deprecated
154
- ].includes(asset.name) || ETHEREUM_LIKE_NO_HISTORY_ASSET_NAMES.includes(asset.baseAsset.name)
148
+ ].includes(asset.name)
155
149
 
156
150
  export const getAssetAddresses = (asset) => {
157
151
  // It seems to be two schemas of assets. The original and the transformed by the client.