@exodus/ethereum-lib 5.11.0 → 5.13.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 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.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-lib@5.12.0...@exodus/ethereum-lib@5.13.0) (2025-06-18)
7
+
8
+
9
+ ### Features
10
+
11
+
12
+ * feat: allow transactionBuffer in unsignedTx (#5883)
13
+
14
+ * feat: remove eth sepolia and goerli (#5885)
15
+
16
+
17
+
18
+ ## [5.12.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-lib@5.11.0...@exodus/ethereum-lib@5.12.0) (2025-06-11)
19
+
20
+
21
+ ### Features
22
+
23
+
24
+ * feat: ethereum api use balances and nonces data (#5727)
25
+
26
+
27
+
6
28
  ## [5.11.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-lib@5.10.2...@exodus/ethereum-lib@5.11.0) (2025-05-29)
7
29
 
8
30
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/ethereum-lib",
3
- "version": "5.11.0",
3
+ "version": "5.13.0",
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,9 +24,9 @@
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
- "@exodus/models": "^12.0.1",
29
+ "@exodus/models": "^12.13.0",
30
30
  "@exodus/solidity-contract": "^1.1.3",
31
31
  "base-x": "^3.0.2",
32
32
  "lodash": "^4.17.15",
@@ -50,5 +50,5 @@
50
50
  "type": "git",
51
51
  "url": "git+https://github.com/ExodusMovement/assets.git"
52
52
  },
53
- "gitHead": "45be970be70f9211b8a6489566c352f4caeb82dc"
53
+ "gitHead": "4c871b4f5c3ed6a503547eb1b749a746770d2e5f"
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/',
@@ -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
  }
@@ -13,12 +13,8 @@ const base16 = baseX('0123456789abcdef')
13
13
  /* @deprecated */
14
14
  export const isEthereumToken = (asset) => asset.assetType === 'ETHEREUM_ERC20'
15
15
  /* @deprecated */
16
- export const isEthereumGoerliToken = (asset) => asset.assetType === 'ETHEREUM_GOERLI_ERC20'
17
- /* @deprecated */
18
16
  export const isEthereumHoleskyToken = (asset) => asset.assetType === 'ETHEREUM_HOLESKY_ERC20'
19
17
  /* @deprecated */
20
- export const isEthereumSepoliaToken = (asset) => asset.assetType === 'ETHEREUM_SEPOLIA_ERC20'
21
- /* @deprecated */
22
18
  export const isBscToken = (asset) => asset.assetType === 'BSC_BEP20'
23
19
  /* @deprecated */
24
20
  export const isPolygonToken = (asset) => asset.assetType === 'MATIC_ERC20'