@exodus/ethereum-lib 5.17.3 → 5.18.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,24 @@
|
|
|
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.18.1](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-lib@5.18.0...@exodus/ethereum-lib@5.18.1) (2025-10-02)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @exodus/ethereum-lib
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [5.18.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-lib@5.17.3...@exodus/ethereum-lib@5.18.0) (2025-09-26)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
* feat(ethereum): use methodId in new staking txs shape (#6335)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
6
24
|
## [5.17.3](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-lib@5.17.2...@exodus/ethereum-lib@5.17.3) (2025-09-25)
|
|
7
25
|
|
|
8
26
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/ethereum-lib",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.18.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",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"type": "git",
|
|
51
51
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "f6ea2714c95f2e7ec71ffecdc589726b7974511e"
|
|
54
54
|
}
|
|
@@ -6,6 +6,59 @@ import assert from 'minimalistic-assert'
|
|
|
6
6
|
|
|
7
7
|
const { isEmpty } = lodash
|
|
8
8
|
|
|
9
|
+
const getEthereumJsTxDefsByEip1559 = ({ eip1559Enabled }) => {
|
|
10
|
+
assert(typeof eip1559Enabled === 'boolean', 'expected eip1559Enabled')
|
|
11
|
+
|
|
12
|
+
const EthereumJsTransactionClass = eip1559Enabled ? FeeMarketEIP1559Transaction : Transaction
|
|
13
|
+
const hardfork = eip1559Enabled ? Hardfork.London : Hardfork.Istanbul
|
|
14
|
+
|
|
15
|
+
return { EthereumJsTransactionClass, hardfork }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const getEthereumJsTxDefsByTransactionBuffer = ({ transactionBuffer }) => {
|
|
19
|
+
assert(Buffer.isBuffer(transactionBuffer), 'expected Buffer transactionBuffer')
|
|
20
|
+
|
|
21
|
+
return getEthereumJsTxDefsByEip1559({
|
|
22
|
+
eip1559Enabled: FeeMarketEIP1559Transaction.isEip1559SerializedTx(transactionBuffer),
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const getEthereumJsTxCommon = ({ chainId, ethereumJsTxDefs }) => {
|
|
27
|
+
assert(ethereumJsTxDefs, 'expected ethereumJsTxDefs')
|
|
28
|
+
|
|
29
|
+
const { hardfork } = ethereumJsTxDefs
|
|
30
|
+
|
|
31
|
+
return Common.custom(
|
|
32
|
+
...[typeof chainId === 'number' && { chainId }, { hardfork }].filter(Boolean)
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const getEthereumJsTxByTransactionBuffer = ({ chainId, transactionBuffer }) => {
|
|
37
|
+
assert(typeof chainId === 'number', 'expected chainId')
|
|
38
|
+
|
|
39
|
+
const ethereumJsTxDefs = getEthereumJsTxDefsByTransactionBuffer({ transactionBuffer })
|
|
40
|
+
const { EthereumJsTransactionClass } = ethereumJsTxDefs
|
|
41
|
+
|
|
42
|
+
return EthereumJsTransactionClass.fromSerializedTx(transactionBuffer, {
|
|
43
|
+
common: getEthereumJsTxCommon({ chainId, ethereumJsTxDefs }),
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const getEthereumJsTxByTransactionProps = ({
|
|
48
|
+
chainId,
|
|
49
|
+
eip1559Enabled = false,
|
|
50
|
+
transactionProps,
|
|
51
|
+
}) => {
|
|
52
|
+
assert(typeof chainId === 'number', 'expected chainId')
|
|
53
|
+
|
|
54
|
+
const ethereumJsTxDefs = getEthereumJsTxDefsByEip1559({ eip1559Enabled })
|
|
55
|
+
const { EthereumJsTransactionClass } = ethereumJsTxDefs
|
|
56
|
+
|
|
57
|
+
return EthereumJsTransactionClass.fromTxData(transactionProps, {
|
|
58
|
+
common: getEthereumJsTxCommon({ chainId, ethereumJsTxDefs }),
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
9
62
|
const parseBufferToJsTx = (unsignedTx) => {
|
|
10
63
|
const { transactionBuffer, chainId, ...legacyTxData } = unsignedTx.txData
|
|
11
64
|
assert(
|
|
@@ -13,21 +66,10 @@ const parseBufferToJsTx = (unsignedTx) => {
|
|
|
13
66
|
'Cannot create ethereum js tx when transactionBuffer and other fields are provided!'
|
|
14
67
|
)
|
|
15
68
|
assert(chainId, 'chainId must be provided when parsing from transaction buffer!!!')
|
|
16
|
-
if (FeeMarketEIP1559Transaction.isEip1559SerializedTx(transactionBuffer)) {
|
|
17
|
-
return FeeMarketEIP1559Transaction.fromSerializedTx(transactionBuffer, {
|
|
18
|
-
common: Common.custom(
|
|
19
|
-
{
|
|
20
|
-
chainId,
|
|
21
|
-
},
|
|
22
|
-
{ hardfork: Hardfork.London }
|
|
23
|
-
),
|
|
24
|
-
})
|
|
25
|
-
}
|
|
26
69
|
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}),
|
|
70
|
+
return getEthereumJsTxByTransactionBuffer({
|
|
71
|
+
transactionBuffer,
|
|
72
|
+
chainId,
|
|
31
73
|
})
|
|
32
74
|
}
|
|
33
75
|
|
|
@@ -36,58 +78,77 @@ export default function createEthereumJsTx(unsignedTx) {
|
|
|
36
78
|
txData: { transactionBuffer, ...legacyTxData },
|
|
37
79
|
} = unsignedTx
|
|
38
80
|
|
|
39
|
-
if (transactionBuffer)
|
|
40
|
-
return parseBufferToJsTx(unsignedTx)
|
|
41
|
-
}
|
|
81
|
+
if (transactionBuffer) return parseBufferToJsTx(unsignedTx)
|
|
42
82
|
|
|
43
83
|
const {
|
|
44
84
|
chainId,
|
|
45
85
|
nonce: providedNonce,
|
|
46
|
-
gasPrice,
|
|
47
86
|
gasLimit: providedGasLimit,
|
|
48
|
-
tipGasPrice,
|
|
49
87
|
data: providedData,
|
|
50
|
-
|
|
88
|
+
|
|
89
|
+
/* exodus eip1559 */
|
|
90
|
+
gasPrice,
|
|
91
|
+
tipGasPrice,
|
|
92
|
+
|
|
93
|
+
/* web3 eip1559 */
|
|
94
|
+
// NOTE: In Web3 EIP-1559, `maxFeePerGas` is mandatory, whilst
|
|
95
|
+
// `maxPriorityFeePerGas` can default to zero. If a third
|
|
96
|
+
// party transaction intends to do EIP-1559, they *must*
|
|
97
|
+
// have defined a `maxFeePerGas`.
|
|
98
|
+
maxFeePerGas,
|
|
99
|
+
maxPriorityFeePerGas,
|
|
100
|
+
|
|
51
101
|
...txData
|
|
52
102
|
} = legacyTxData
|
|
53
103
|
|
|
54
104
|
const bufferData = toBuffer(providedData)
|
|
55
|
-
|
|
56
105
|
const gasLimit = toBuffer(providedGasLimit)
|
|
57
106
|
const data = bufferData.equals(Buffer.from([0])) ? Buffer.alloc(0) : bufferData
|
|
58
107
|
const nonce = providedNonce === 0 ? Buffer.alloc(0) : toBuffer(providedNonce)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (unsignedTx.txMeta.eip1559Enabled && isEip1559Tx) {
|
|
66
|
-
return FeeMarketEIP1559Transaction.fromTxData(
|
|
67
|
-
{
|
|
68
|
-
maxFeePerGas: gasPrice,
|
|
69
|
-
maxPriorityFeePerGas: tipGasPrice,
|
|
70
|
-
nonce,
|
|
71
|
-
gasLimit,
|
|
72
|
-
data,
|
|
73
|
-
value,
|
|
74
|
-
// `maxPriorityFeePerGas`, `maxFeePerGas` set in `txData` below take precedence over ^.
|
|
75
|
-
...txData,
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
common: Common.custom(
|
|
79
|
-
{
|
|
80
|
-
chainId,
|
|
81
|
-
},
|
|
82
|
-
{ hardfork: Hardfork.London }
|
|
83
|
-
),
|
|
84
|
-
}
|
|
85
|
-
)
|
|
108
|
+
|
|
109
|
+
const commonTransactionProps = {
|
|
110
|
+
...txData,
|
|
111
|
+
nonce,
|
|
112
|
+
gasLimit,
|
|
113
|
+
data,
|
|
86
114
|
}
|
|
87
115
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
116
|
+
const createNonEip1559Transaction = () => {
|
|
117
|
+
assert(gasPrice, 'expected gasPrice')
|
|
118
|
+
|
|
119
|
+
return getEthereumJsTxByTransactionProps({
|
|
120
|
+
chainId,
|
|
121
|
+
transactionProps: { ...commonTransactionProps, gasPrice },
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// If a non-EIP-1559 style transaction has been supplied,
|
|
126
|
+
// then create a legacy trasaction.
|
|
127
|
+
if (!unsignedTx.txMeta.eip1559Enabled) return createNonEip1559Transaction()
|
|
128
|
+
|
|
129
|
+
// Internally, Exodus uses the convention that an EIP-1559
|
|
130
|
+
// transaction must use `gasPrice` and `tipGasPrice`. Web3
|
|
131
|
+
// can provide a `maxFeePerGas` and optional
|
|
132
|
+
// `maxPriorityFeePerGas`.
|
|
133
|
+
//
|
|
134
|
+
// Likewise, if a `maxFeePerGas` has been omitted, the
|
|
135
|
+
// transaction *must* have defined a `gasPrice`.
|
|
136
|
+
if (tipGasPrice || !maxFeePerGas) assert(gasPrice, 'expected gasPrice')
|
|
137
|
+
|
|
138
|
+
// If neither properties were truthy, attempt to construct
|
|
139
|
+
// a legacy transaction.
|
|
140
|
+
if (!(tipGasPrice || maxFeePerGas)) return createNonEip1559Transaction()
|
|
141
|
+
|
|
142
|
+
// Create an EIP-1559 style transaction.
|
|
143
|
+
return getEthereumJsTxByTransactionProps({
|
|
144
|
+
chainId,
|
|
145
|
+
eip1559Enabled: true,
|
|
146
|
+
transactionProps: {
|
|
147
|
+
...commonTransactionProps,
|
|
148
|
+
// NOTE: Here we force the appropriate conventions for gas.
|
|
149
|
+
...(maxFeePerGas
|
|
150
|
+
? { maxFeePerGas, maxPriorityFeePerGas } /* web3 */
|
|
151
|
+
: { maxFeePerGas: gasPrice, maxPriorityFeePerGas: tipGasPrice }) /* exodus */,
|
|
152
|
+
},
|
|
153
|
+
})
|
|
93
154
|
}
|
package/src/unsigned-tx/index.js
CHANGED
|
@@ -2,6 +2,10 @@ export { default as createUnsignedTxFactory } from './create-unsigned-tx.js'
|
|
|
2
2
|
export { default as parseUnsignedTx } from './parse-unsigned-tx.js'
|
|
3
3
|
export { default as signUnsignedTx, signUnsignedTxWithSigner } from './sign-unsigned-tx.js'
|
|
4
4
|
export { default as createAndSignTxFactory } from './create-and-sign-tx.js'
|
|
5
|
-
export {
|
|
5
|
+
export {
|
|
6
|
+
default as createEthereumJsTx,
|
|
7
|
+
getEthereumJsTxByTransactionBuffer,
|
|
8
|
+
getEthereumJsTxByTransactionProps,
|
|
9
|
+
} from './create-ethereumjs-tx.js'
|
|
6
10
|
export { signHardwareFactory } from './sign-hardware.js'
|
|
7
11
|
export { default as updateNonce } from './update-nonce.js'
|
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import assert from 'minimalistic-assert'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
if (FeeMarketEIP1559Transaction.isEip1559SerializedTx(transactionBuffer)) {
|
|
5
|
-
const transaction = FeeMarketEIP1559Transaction.fromSerializedTx(transactionBuffer)
|
|
6
|
-
return FeeMarketEIP1559Transaction.fromTxData({
|
|
7
|
-
...transaction.toJSON(),
|
|
8
|
-
nonce: newNonce,
|
|
9
|
-
}).serialize()
|
|
10
|
-
}
|
|
3
|
+
import { getEthereumJsTxByTransactionBuffer } from './create-ethereumjs-tx.js'
|
|
11
4
|
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
const updateNonce = ({ chainId, transactionBuffer, newNonce }) => {
|
|
6
|
+
assert(Buffer.isBuffer(transactionBuffer), 'expected Buffer transactionBuffer')
|
|
7
|
+
assert(typeof newNonce === 'number', 'expected number newNonce')
|
|
8
|
+
assert(typeof chainId === 'number', 'expected number chainId')
|
|
9
|
+
|
|
10
|
+
const transaction = getEthereumJsTxByTransactionBuffer({
|
|
11
|
+
chainId,
|
|
12
|
+
transactionBuffer,
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
// NOTE: Here we use the `static` `fromTxData` function via
|
|
16
|
+
// the `transaction` instance.
|
|
17
|
+
return transaction.constructor
|
|
18
|
+
.fromTxData({ ...transaction.toJSON(), nonce: newNonce })
|
|
19
|
+
.serialize()
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
export default updateNonce
|