Socket
Socket
Sign inDemoInstall

@ethereumjs/tx

Package Overview
Dependencies
17
Maintainers
4
Versions
37
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.2.0 to 5.0.0-rc.1

dist/cjs/baseTransaction.d.ts

48

package.json
{
"name": "@ethereumjs/tx",
"version": "4.2.0",
"description": "A simple module for creating, manipulating and signing Ethereum transactions",
"version": "5.0.0-rc.1",
"description": "Implementation of the various Ethereum Transaction Types",
"keywords": [

@@ -30,4 +30,11 @@ "ethereum",

],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "commonjs",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"exports": {
".": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js"
}
},
"files": [

@@ -40,4 +47,4 @@ "dist",

"clean": "../../config/cli/clean-package.sh",
"coverage": "../../config/cli/coverage.sh",
"docs:build": "typedoc --options typedoc.js",
"coverage": "npx vitest run --coverage.enabled --coverage.reporter=lcov",
"docs:build": "typedoc --options typedoc.cjs",
"examples": "ts-node ../../scripts/examples-runner.ts -- tx",

@@ -48,15 +55,21 @@ "lint": "../../config/cli/lint.sh",

"prepublishOnly": "../../config/cli/prepublish.sh",
"tape": "tape -r ts-node/register",
"test": "npm run test:node && npm run test:browser && npm run test:txTests",
"test:browser": "karma start karma.conf.js",
"test:node": "tape -r ts-node/register -- 'test/**/*.spec.ts'",
"test:txTests": "tape -r ts-node/register ./test/transactionRunner.ts",
"test": "npm run test:node && npm run test:browser",
"test:browser": "npx vitest run --config=./vitest.config.browser.ts --browser.name=chrome --browser.headless",
"test:node": "npx vitest run",
"tsc": "../../config/cli/ts-compile.sh"
},
"dependencies": {
"@ethereumjs/common": "^3.2.0",
"@ethereumjs/rlp": "^4.0.1",
"@ethereumjs/util": "^8.1.0",
"ethereum-cryptography": "^2.0.0"
"@ethereumjs/common": "4.0.0-rc.1",
"@ethereumjs/rlp": "5.0.0-rc.1",
"@ethereumjs/util": "9.0.0-rc.1",
"ethereum-cryptography": "^2.1.2"
},
"peerDependencies": {
"c-kzg": "^2.1.0"
},
"peerDependenciesMeta": {
"c-kzg": {
"optional": true
}
},
"devDependencies": {

@@ -66,8 +79,7 @@ "@types/minimist": "^1.2.0",

"minimist": "^1.2.0",
"node-dir": "^0.1.16",
"testdouble": "^3.17.2"
"node-dir": "^0.1.16"
},
"engines": {
"node": ">=14"
"node": ">=18"
}
}

@@ -9,2 +9,4 @@ # @ethereumjs/tx

Note: this README has been updated containing the changes from our next breaking release round [UNRELEASED] targeted for Summer 2023. See the README files from the [maintenance-v6](https://github.com/ethereumjs/ethereumjs-monorepo/tree/maintenance-v6/) branch for documentation matching our latest releases.
| Implements schema and functions related to Ethereum's transaction. |

@@ -36,3 +38,3 @@ | ------------------------------------------------------------------ |

1. Install an additional dependency that supports the `kzg` interface defined in [the kzg interface](./src/kzg/kzg.ts). You can install the default option [c-kzg](https://github.com/ethereum/c-kzg-4844) by simply running `npm install c-kzg`.
2. Download the trusted setup required for the KZG module. It can be found [here](../client/lib/trustedSetups/trusted_setup.txt) within the client package.
2. Download the trusted setup required for the KZG module. It can be found [here](../client/src/trustedSetups/trusted_setup.txt) within the client package.

@@ -44,2 +46,4 @@ #### Global Initialization

```typescript
import { initKZG } from '@ethereumjs/util'
// Make the kzg library available globally

@@ -59,4 +63,4 @@ import * as kzg from 'c-kzg'

- `public static fromTxData(txData: TxData, opts: TxOptions = {})`: instantiate from a data dictionary
- `public static fromSerializedTx(serialized: Buffer, opts: TxOptions = {})`: instantiate from a serialized tx
- `public static fromValuesArray(values: Buffer[], opts: TxOptions = {})`: instantiate from a values array
- `public static fromSerializedTx(serialized: Uint8Array, opts: TxOptions = {})`: instantiate from a serialized tx
- `public static fromValuesArray(values: Uint8Array[], opts: TxOptions = {})`: instantiate from a values array

@@ -69,8 +73,6 @@ See one of the code examples on the tx types below on how to use.

The `Transaction` constructor receives a parameter of an [`@ethereumjs/common`](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/common) object that lets you specify the chain and hardfork to be used. If there is no `Common` provided the chain ID provided as a parameter on typed tx or the chain ID derived from the `v` value on signed EIP-155 conforming legacy txs will be taken (introduced in `v3.2.1`). In other cases the chain defaults to `mainnet`.
The `LegacyTransaction` constructor receives a parameter of an [`@ethereumjs/common`](https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/common) object that lets you specify the chain and hardfork to be used. If there is no `Common` provided the chain ID provided as a parameter on typed tx or the chain ID derived from the `v` value on signed EIP-155 conforming legacy txs will be taken (introduced in `v3.2.1`). In other cases the chain defaults to `mainnet`.
Base default HF (determined by `Common`): `merge`
Base default HF (determined by `Common`): `Hardfork.Shanghai`
Starting with `v3.2.1` the tx library now deviates from the default HF for typed tx using the following rule: "The default HF is the default HF from `Common` if the tx type is active on that HF. Otherwise it is set to the first greater HF where the tx is active."
Hardforks adding features and/or tx types:

@@ -85,13 +87,4 @@

| `london` | `v3.2.0` | `EIP-1559` Transactions |
| `cancun` | `v5.0.0` | `EIP-4844` Transactions |
### Standalone EIPs
The following "standalone" EIPs are supported by the library can be manually activated using a respectively initialized `Common` instance, e.g.:
```typescript
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London, eips: [3860] })
```
- [EIP-3860](https://eips.ethereum.org/EIPS/eip-3855): Limit and meter initcode (`experimental`)
### Transaction Types

@@ -104,3 +97,4 @@

- `AccessListEIP2930Transaction` ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930), optional access lists)
- `Transaction`, the Ethereum standard tx up to `berlin`, now referred to as legacy txs with the introduction of tx types
- `BlobEIP4844Transaction` ([EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), blob transactions)
- `LegacyTransaction`, the Ethereum standard tx up to `berlin`, now referred to as legacy txs with the introduction of tx types

@@ -110,7 +104,9 @@ #### Blob Transactions (EIP-4844)

- Class: `BlobEIP4844Transaction`
- Activation: `sharding`
- Type: `5`
- Activation: `cancun`
- Type: `3`
This library supports an experimental version of the blob transaction type introduced with [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) as being specified in the [01d3209](https://github.com/ethereum/EIPs/commit/01d320998d1d53d95f347b5f43feaf606f230703) EIP version from February 8, 2023 and deployed along `eip4844-devnet-4` (January 2023), see PR [#2349](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2349).
This library supports the blob transaction type introduced with [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) as being specified in the [b9a5a11](https://github.com/ethereum/EIPs/commit/b9a5a117ab7e1dc18f937841d00598b527c306e7) EIP version from July 2023 deployed along [4844-devnet-7](https://github.com/ethpandaops/4844-testnet) (July 2023), see PR [#2349](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2349) and following.
**Note:** 4844 support is not yet completely stable and there will still be (4844-)breaking changes along all types of library releases.
**Note:** This functionality needs a manual KZG library installation and global initialization, see [KZG Setup](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/tx/README.md#kzg-setup) for instructions.

@@ -124,3 +120,4 @@

import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { BlobEIP4844Transaction, initKZG } from '@ethereumjs/tx'
import { BlobEIP4844Transaction } from '@ethereumjs/tx'
import { initKZG } from '@ethereumjs/util'
import * as kzg from 'c-kzg'

@@ -149,2 +146,3 @@

blobs: ['0xghi...'], // Test with empty array on a first run
proofs: ['0xabcd...'], //
}

@@ -155,4 +153,6 @@

Note that `versionedHashes` and `kzgCommitments` have a real length of 32 bytes and `blobs` have a real length of `4096` bytes and values are trimmed here for brevity.
Note that `versionedHashes` and `kzgCommitments` have a real length of 32 bytes, `blobs` have a real length of `4096` bytes and values are trimmed here for brevity.
Alternatively, you can pass a `blobsData` property with an array of strings corresponding to a set of blobs and the `fromTxData` constructor will derive the corresponding `blobs`, `versionedHashes`, `kzgCommitments`, and `kzgProofs` for you.
See the [Blob Transaction Tests](./test/eip4844.spec.ts) for examples of usage in instantiating, serializing, and deserializing these transactions.

@@ -238,3 +238,3 @@

- Class: `Transaction`
- Class: `LegacyTransaction`
- Activation: `chainstart` (with modifications along the road, see HF section below)

@@ -248,3 +248,3 @@ - Type: `0` (internal)

import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { Transaction } from '@ethereumjs/tx'
import { LegacyTransaction } from '@ethereumjs/tx'

@@ -261,3 +261,3 @@ const txParams = {

const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul })
const tx = Transaction.fromTxData(txParams, { common })
const tx = LegacyTransaction.fromTxData(txParams, { common })

@@ -297,5 +297,5 @@ const privateKey = Buffer.from(

- `public static fromTxData(txData: TxData | AccessListEIP2930TxData, txOptions: TxOptions = {}): TypedTransaction`
- `public static fromSerializedData(data: Buffer, txOptions: TxOptions = {}): TypedTransaction`
- `public static fromBlockBodyData(data: Buffer | Buffer[], txOptions: TxOptions = {})`
- `public static async fromEthersProvider(provider: string | ethers.providers.JsonRpcProvider, txHash: string, txOptions?: TxOptions)`
- `public static fromSerializedData(data: Uint8Array, txOptions: TxOptions = {}): TypedTransaction`
- `public static fromBlockBodyData(data: Uint8Array | Uint8Array[], txOptions: TxOptions = {})`
- `public static async fromJsonRpcProvider(provider: string | EthersProvider, txHash: string, txOptions?: TxOptions)`

@@ -309,4 +309,5 @@ ### Sending a Transaction

```typescript
import { Transaction } from '@ethereumjs/tx'
import { Common } from '@ethereumjs/common'
import { LegacyTransaction } from '@ethereumjs/tx'
import { hexToBytes } from '@ethereumjs/util'

@@ -328,4 +329,4 @@ const from = 'PUBLIC_KEY'

const tx = Transaction.fromTxData(txData, { common })
const signedTx = tx.sign(Buffer.from(PRIV_KEY, 'hex'))
const tx = LegacyTransaction.fromTxData(txData, { common })
const signedTx = tx.sign(hexToBytes(PRIV_KEY))
```

@@ -353,2 +354,8 @@

## Browser
With the breaking release round in Summer 2023 we have added hybrid ESM/CJS builds for all our libraries (see section below) and have eliminated many of the caveats which had previously prevented a frictionless browser usage.
It is now easily possible to run a browser build of one of the EthereumJS libraries within a modern browser using the provided ESM build. For a setup example see [./examples/browser.html](./examples/browser.html).
## Special Topics

@@ -358,3 +365,3 @@

To sign a tx with a hardware or external wallet use `tx.getMessageToSign(false)` to return an [EIP-155](https://eips.ethereum.org/EIPS/eip-155) compliant unsigned tx.
To sign a tx with a hardware or external wallet use `tx.getMessageToSign()` to return an [EIP-155](https://eips.ethereum.org/EIPS/eip-155) compliant unsigned tx.

@@ -366,5 +373,5 @@ A legacy transaction will return a Buffer list of the values, and a Typed Transaction ([EIP-2718](https://eips.ethereum.org/EIPS/eip-2718)) will return the serialized output.

```typescript
import { Transaction, FeeMarketEIP1559Transaction } from '@ethereumjs/tx'
import { Chain, Common } from '@ethereumjs/common'
import { bufArrToArr } from '@ethereumjs/util'
import { LegacyTransaction, FeeMarketEIP1559Transaction } from '@ethereumjs/tx'
import { bytesToHex } from '@ethereumjs/util'
import { RLP } from '@ethereumjs/rlp'

@@ -374,7 +381,7 @@ import Eth from '@ledgerhq/hw-app-eth'

const eth = new Eth(transport)
const common = new Common({ chain: Chain.Rinkeby })
const common = new Common({ chain: Chain.Sepolia })
let txData: any = { value: 1 }
let tx: Transaction | FeeMarketEIP1559Transaction
let unsignedTx: Buffer[] | Buffer
let unsignedTx: Uint8Array[] | Uint8Array
let signedTx: typeof tx

@@ -385,10 +392,10 @@ const bip32Path = "44'/60'/0'/0/0"

// Signing a legacy tx
tx = Transaction.fromTxData(txData, { common })
unsignedTx = tx.getMessageToSign(false)
unsignedTx = Buffer.from(RLP.encode(bufArrToArr(unsignedTx))) // ledger signTransaction API expects it to be serialized
tx = LegacyTransaction.fromTxData(txData, { common })
unsignedTx = tx.getMessageToSign()
unsignedTx = RLP.encode(unsignedTx) // ledger signTransaction API expects it to be serialized
let { v, r, s } = await eth.signTransaction(bip32Path, unsignedTx)
txData = { ...txData, v, r, s }
signedTx = Transaction.fromTxData(txData, { common })
let from = signedTx.getSenderAddress().toString()
console.log(`signedTx: 0x${signedTx.serialize().toString('hex')}\nfrom: ${from}`)
signedTx = LegacyTransaction.fromTxData(txData, { common })
let from = bytesToHex(signedTx.getSenderAddress())
console.log(`signedTx: ${bytesToHex(signedTx.serialize())}\nfrom: ${from}`)

@@ -398,8 +405,8 @@ // Signing a 1559 tx

tx = FeeMarketEIP1559Transaction.fromTxData(txData, { common })
unsignedTx = tx.getMessageToSign(false)
unsignedTx = tx.getMessageToSign()
;({ v, r, s } = await eth.signTransaction(bip32Path, unsignedTx)) // this syntax is: object destructuring - assignment without declaration
txData = { ...txData, v, r, s }
signedTx = FeeMarketEIP1559Transaction.fromTxData(txData, { common })
from = signedTx.getSenderAddress().toString()
console.log(`signedTx: ${signedTx.serialize().toString('hex')}\nfrom: ${from}`)
from = bytesToHex(signedTx.getSenderAddress())
console.log(`signedTx: ${bytesToHex(signedTx.serialize())}\nfrom: ${from}`)
}

@@ -423,3 +430,3 @@

const opts = { common: this._common, freeze: false }
const tx = Transaction.fromTxData(txParams, opts)
const tx = LegacyTransaction.fromTxData(txParams, opts)

@@ -439,2 +446,26 @@ // override getSenderAddress

### Hybrid CJS/ESM Builds
With the breaking releases from Summer 2023 we have started to ship our libraries with both CommonJS (`cjs` folder) and ESM builds (`esm` folder), see `package.json` for the detailed setup.
If you use an ES6-style `import` in your code files from the ESM build will be used:
```typescript
import { EthereumJSClass } from '@ethereumjs/[PACKAGE_NAME]'
```
If you use Node.js specific `require` the CJS build will be used:
```typescript
const { EthereumJSClass } = require('@ethereumjs/[PACKAGE_NAME]')
```
Using ESM will give you additional advantages over CJS beyond browser usage like static code analysis / Tree Shaking which CJS can not provide.
### Buffer -> Uint8Array
With the breaking releases from Summer 2023 we have removed all Node.js specific `Buffer` usages from our libraries and replace these with [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) representations, which are available both in Node.js and the browser (`Buffer` is a subclass of `Uint8Array`).
We have converted existing Buffer conversion methods to Uint8Array conversion methods in the [@ethereumjs/util](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/util) `bytes` module, see the respective README section for guidance.
### BigInt Support

@@ -441,0 +472,0 @@

@@ -1,2 +0,2 @@

import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { Chain, Common } from '@ethereumjs/common'
import {

@@ -7,27 +7,27 @@ Address,

SECP256K1_ORDER_DIV_2,
bufferToBigInt,
bufferToHex,
bigIntToHex,
bytesToBigInt,
bytesToHex,
ecsign,
publicToAddress,
toBuffer,
unpadBuffer,
toBytes,
unpadBytes,
} from '@ethereumjs/util'
import { Capability } from './types'
import { checkMaxInitCodeSize } from './util'
import { Capability, TransactionType } from './types.js'
import { checkMaxInitCodeSize } from './util.js'
import type {
AccessListEIP2930TxData,
AccessListEIP2930ValuesArray,
FeeMarketEIP1559TxData,
FeeMarketEIP1559ValuesArray,
JsonTx,
Transaction,
TransactionInterface,
TxData,
TxOptions,
TxValuesArray,
} from './types'
} from './types.js'
import type { Hardfork } from '@ethereumjs/common'
import type { BigIntLike } from '@ethereumjs/util'
interface TransactionCache {
hash: Buffer | undefined
hash: Uint8Array | undefined
dataFee?: {

@@ -46,4 +46,6 @@ value: bigint

*/
export abstract class BaseTransaction<TransactionObject> {
private readonly _type: number
export abstract class BaseTransaction<T extends TransactionType>
implements TransactionInterface<T>
{
protected readonly _type: TransactionType

@@ -54,3 +56,3 @@ public readonly nonce: bigint

public readonly value: bigint
public readonly data: Buffer
public readonly data: Uint8Array

@@ -87,30 +89,22 @@ public readonly v?: bigint

/**
* The default HF if the tx type is active on that HF
* or the first greater HF where the tx is active.
*
* @hidden
*/
protected DEFAULT_HARDFORK: string | Hardfork = Hardfork.Merge
constructor(txData: TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData, opts: TxOptions) {
constructor(txData: TxData[T], opts: TxOptions) {
const { nonce, gasLimit, to, value, data, v, r, s, type } = txData
this._type = Number(bufferToBigInt(toBuffer(type)))
this._type = Number(bytesToBigInt(toBytes(type)))
this.txOptions = opts
const toB = toBuffer(to === '' ? '0x' : to)
const vB = toBuffer(v === '' ? '0x' : v)
const rB = toBuffer(r === '' ? '0x' : r)
const sB = toBuffer(s === '' ? '0x' : s)
const toB = toBytes(to === '' ? '0x' : to)
const vB = toBytes(v === '' ? '0x' : v)
const rB = toBytes(r === '' ? '0x' : r)
const sB = toBytes(s === '' ? '0x' : s)
this.nonce = bufferToBigInt(toBuffer(nonce === '' ? '0x' : nonce))
this.gasLimit = bufferToBigInt(toBuffer(gasLimit === '' ? '0x' : gasLimit))
this.nonce = bytesToBigInt(toBytes(nonce === '' ? '0x' : nonce))
this.gasLimit = bytesToBigInt(toBytes(gasLimit === '' ? '0x' : gasLimit))
this.to = toB.length > 0 ? new Address(toB) : undefined
this.value = bufferToBigInt(toBuffer(value === '' ? '0x' : value))
this.data = toBuffer(data === '' ? '0x' : data)
this.value = bytesToBigInt(toBytes(value === '' ? '0x' : value))
this.data = toBytes(data === '' ? '0x' : data)
this.v = vB.length > 0 ? bufferToBigInt(vB) : undefined
this.r = rB.length > 0 ? bufferToBigInt(rB) : undefined
this.s = sB.length > 0 ? bufferToBigInt(sB) : undefined
this.v = vB.length > 0 ? bytesToBigInt(vB) : undefined
this.r = rB.length > 0 ? bytesToBigInt(rB) : undefined
this.s = sB.length > 0 ? bytesToBigInt(sB) : undefined

@@ -155,3 +149,3 @@ this._validateCannotExceedMaxInteger({ value: this.value, r: this.r, s: this.s })

*
* See `Capabilites` in the `types` module for a reference
* See `Capabilities` in the `types` module for a reference
* on all supported capabilities.

@@ -164,11 +158,12 @@ */

/**
* Checks if the transaction has the minimum amount of gas required
* (DataFee + TxFee + Creation Fee).
* Validates the transaction signature and minimum gas requirements.
* @returns {string[]} an array of error strings
*/
validate(): boolean
validate(stringError: false): boolean
validate(stringError: true): string[]
validate(stringError: boolean = false): boolean | string[] {
getValidationErrors(): string[] {
const errors = []
if (this.isSigned() && !this.verifySignature()) {
errors.push('Invalid Signature')
}
if (this.getBaseFee() > this.gasLimit) {

@@ -178,7 +173,13 @@ errors.push(`gasLimit is too low. given ${this.gasLimit}, need at least ${this.getBaseFee()}`)

if (this.isSigned() && !this.verifySignature()) {
errors.push('Invalid Signature')
}
return errors
}
return stringError ? errors : errors.length === 0
/**
* Validates the transaction signature and minimum gas requirements.
* @returns {boolean} true if the transaction is valid, false otherwise
*/
isValid(): boolean {
const errors = this.getValidationErrors()
return errors.length === 0
}

@@ -252,7 +253,7 @@

toCreationAddress(): boolean {
return this.to === undefined || this.to.buf.length === 0
return this.to === undefined || this.to.bytes.length === 0
}
/**
* Returns a Buffer Array of the raw Buffers of this transaction, in order.
* Returns a Uint8Array Array of the raw Bytes of this transaction, in order.
*

@@ -262,7 +263,7 @@ * Use {@link BaseTransaction.serialize} to add a transaction to a block

*
* For an unsigned tx this method uses the empty Buffer values for the
* For an unsigned tx this method uses the empty Bytes values for the
* signature parameters `v`, `r` and `s` for encoding. For an EIP-155 compliant
* representation for external signing use {@link BaseTransaction.getMessageToSign}.
*/
abstract raw(): TxValuesArray | AccessListEIP2930ValuesArray | FeeMarketEIP1559ValuesArray
abstract raw(): TxValuesArray[T]

@@ -272,15 +273,14 @@ /**

*/
abstract serialize(): Buffer
abstract serialize(): Uint8Array
// Returns the unsigned tx (hashed or raw), which is used to sign the transaction.
//
// Note: do not use code docs here since VS Studio is then not able to detect the
// comments from the inherited methods
abstract getMessageToSign(hashMessage: false): Buffer | Buffer[]
abstract getMessageToSign(hashMessage?: true): Buffer
// Returns the raw unsigned tx, which is used to sign the transaction.
abstract getMessageToSign(): Uint8Array | Uint8Array[]
abstract hash(): Buffer
// Returns the hashed unsigned tx, which is used to sign the transaction.
abstract getHashedMessageToSign(): Uint8Array
abstract getMessageToVerifySignature(): Buffer
abstract hash(): Uint8Array
abstract getMessageToVerifySignature(): Uint8Array
public isSigned(): boolean {

@@ -302,3 +302,3 @@ const { v, r, s } = this

const publicKey = this.getSenderPublicKey()
return unpadBuffer(publicKey).length !== 0
return unpadBytes(publicKey).length !== 0
} catch (e: any) {

@@ -319,3 +319,3 @@ return false

*/
abstract getSenderPublicKey(): Buffer
abstract getSenderPublicKey(): Uint8Array

@@ -331,3 +331,3 @@ /**

*/
sign(privateKey: Buffer): TransactionObject {
sign(privateKey: Uint8Array): Transaction[T] {
if (privateKey.length !== 32) {

@@ -344,3 +344,3 @@ const msg = this._errorMsg('Private key must be 32 bytes in length.')

if (
this.type === 0 &&
this.type === TransactionType.Legacy &&
this.common.gteHardfork('spuriousDragon') &&

@@ -353,3 +353,3 @@ !this.supports(Capability.EIP155ReplayProtection)

const msgHash = this.getMessageToSign(true)
const msgHash = this.getHashedMessageToSign()
const { v, r, s } = ecsign(msgHash, privateKey)

@@ -372,6 +372,18 @@ const tx = this._processSignature(v, r, s)

*/
abstract toJSON(): JsonTx
toJSON(): JsonTx {
return {
type: bigIntToHex(BigInt(this.type)),
nonce: bigIntToHex(this.nonce),
gasLimit: bigIntToHex(this.gasLimit),
to: this.to !== undefined ? this.to.toString() : undefined,
value: bigIntToHex(this.value),
data: bytesToHex(this.data),
v: this.v !== undefined ? bigIntToHex(this.v) : undefined,
r: this.r !== undefined ? bigIntToHex(this.r) : undefined,
s: this.s !== undefined ? bigIntToHex(this.s) : undefined,
}
}
// Accept the v,r,s values from the `sign` method, and convert this into a TransactionObject
protected abstract _processSignature(v: bigint, r: Buffer, s: Buffer): TransactionObject
// Accept the v,r,s values from the `sign` method, and convert this into a T
protected abstract _processSignature(v: bigint, r: Uint8Array, s: Uint8Array): Transaction[T]

@@ -389,3 +401,3 @@ /**

if (chainId !== undefined) {
const chainIdBigInt = bufferToBigInt(toBuffer(chainId))
const chainIdBigInt = bytesToBigInt(toBytes(chainId))
if (common) {

@@ -403,3 +415,3 @@ if (common.chainId() !== chainIdBigInt) {

// -> Instantiate Common with chain ID
return new Common({ chain: chainIdBigInt, hardfork: this.DEFAULT_HARDFORK })
return new Common({ chain: chainIdBigInt })
} else {

@@ -414,3 +426,3 @@ // No Common, chain ID not supported by Common

},
{ baseChain: this.DEFAULT_CHAIN, hardfork: this.DEFAULT_HARDFORK }
{ baseChain: this.DEFAULT_CHAIN }
)

@@ -422,5 +434,3 @@ }

// -> return Common provided or create new default Common
return (
common?.copy() ?? new Common({ chain: this.DEFAULT_CHAIN, hardfork: this.DEFAULT_HARDFORK })
)
return common?.copy() ?? new Common({ chain: this.DEFAULT_CHAIN })
}

@@ -527,3 +537,3 @@ }

try {
hash = this.isSigned() ? bufferToHex(this.hash()) : 'not available (unsigned)'
hash = this.isSigned() ? bytesToHex(this.hash()) : 'not available (unsigned)'
} catch (e: any) {

@@ -530,0 +540,0 @@ hash = 'error'

import { RLP } from '@ethereumjs/rlp'
import {
MAX_INTEGER,
arrToBufArr,
bigIntToHex,
bigIntToUnpaddedBuffer,
bufArrToArr,
bufferToBigInt,
bigIntToUnpaddedBytes,
bytesToBigInt,
bytesToHex,
concatBytes,
ecrecover,
toBuffer,
equalsBytes,
hexToBytes,
toBytes,
validateNoLeadingZeroes,
} from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak'
import { keccak256 } from 'ethereum-cryptography/keccak.js'
import { BaseTransaction } from './baseTransaction'
import { AccessLists } from './util'
import { BaseTransaction } from './baseTransaction.js'
import { TransactionType } from './types.js'
import { AccessLists } from './util.js'
import type {
AccessList,
AccessListBuffer,
FeeMarketEIP1559TxData,
FeeMarketEIP1559ValuesArray,
AccessListBytes,
TxData as AllTypesTxData,
TxValuesArray as AllTypesTxValuesArray,
JsonTx,
TxOptions,
} from './types'
} from './types.js'
import type { Common } from '@ethereumjs/common'
const TRANSACTION_TYPE = 2
const TRANSACTION_TYPE_BUFFER = Buffer.from(TRANSACTION_TYPE.toString(16).padStart(2, '0'), 'hex')
type TxData = AllTypesTxData[TransactionType.FeeMarketEIP1559]
type TxValuesArray = AllTypesTxValuesArray[TransactionType.FeeMarketEIP1559]
const TRANSACTION_TYPE_BYTES = hexToBytes(
'0x' + TransactionType.FeeMarketEIP1559.toString(16).padStart(2, '0')
)
/**

@@ -37,5 +44,5 @@ * Typed transaction with a new gas fee market mechanism

*/
export class FeeMarketEIP1559Transaction extends BaseTransaction<FeeMarketEIP1559Transaction> {
export class FeeMarketEIP1559Transaction extends BaseTransaction<TransactionType.FeeMarketEIP1559> {
public readonly chainId: bigint
public readonly accessList: AccessListBuffer
public readonly accessList: AccessListBytes
public readonly AccessListJSON: AccessList

@@ -48,10 +55,2 @@ public readonly maxPriorityFeePerGas: bigint

/**
* The default HF if the tx type is active on that HF
* or the first greater HF where the tx is active.
*
* @hidden
*/
protected DEFAULT_HARDFORK = 'london'
/**
* Instantiate a transaction from a data dictionary.

@@ -66,3 +65,3 @@ *

*/
public static fromTxData(txData: FeeMarketEIP1559TxData, opts: TxOptions = {}) {
public static fromTxData(txData: TxData, opts: TxOptions = {}) {
return new FeeMarketEIP1559Transaction(txData, opts)

@@ -77,12 +76,12 @@ }

*/
public static fromSerializedTx(serialized: Buffer, opts: TxOptions = {}) {
if (!serialized.slice(0, 1).equals(TRANSACTION_TYPE_BUFFER)) {
public static fromSerializedTx(serialized: Uint8Array, opts: TxOptions = {}) {
if (equalsBytes(serialized.subarray(0, 1), TRANSACTION_TYPE_BYTES) === false) {
throw new Error(
`Invalid serialized tx input: not an EIP-1559 transaction (wrong tx type, expected: ${TRANSACTION_TYPE}, received: ${serialized
.slice(0, 1)
.toString('hex')}`
`Invalid serialized tx input: not an EIP-1559 transaction (wrong tx type, expected: ${
TransactionType.FeeMarketEIP1559
}, received: ${bytesToHex(serialized.subarray(0, 1))}`
)
}
const values = arrToBufArr(RLP.decode(serialized.slice(1)))
const values = RLP.decode(serialized.subarray(1))

@@ -93,3 +92,3 @@ if (!Array.isArray(values)) {

return FeeMarketEIP1559Transaction.fromValuesArray(values as any, opts)
return FeeMarketEIP1559Transaction.fromValuesArray(values as TxValuesArray, opts)
}

@@ -103,3 +102,3 @@

*/
public static fromValuesArray(values: FeeMarketEIP1559ValuesArray, opts: TxOptions = {}) {
public static fromValuesArray(values: TxValuesArray, opts: TxOptions = {}) {
if (values.length !== 9 && values.length !== 12) {

@@ -131,3 +130,3 @@ throw new Error(

{
chainId: bufferToBigInt(chainId),
chainId: bytesToBigInt(chainId),
nonce,

@@ -141,3 +140,3 @@ maxPriorityFeePerGas,

accessList: accessList ?? [],
v: v !== undefined ? bufferToBigInt(v) : undefined, // EIP2930 supports v's with value 0 (empty Buffer)
v: v !== undefined ? bytesToBigInt(v) : undefined, // EIP2930 supports v's with value 0 (empty Uint8Array)
r,

@@ -157,4 +156,4 @@ s,

*/
public constructor(txData: FeeMarketEIP1559TxData, opts: TxOptions = {}) {
super({ ...txData, type: TRANSACTION_TYPE }, opts)
public constructor(txData: TxData, opts: TxOptions = {}) {
super({ ...txData, type: TransactionType.FeeMarketEIP1559 }, opts)
const { chainId, accessList, maxFeePerGas, maxPriorityFeePerGas } = txData

@@ -177,5 +176,5 @@

this.maxFeePerGas = bufferToBigInt(toBuffer(maxFeePerGas === '' ? '0x' : maxFeePerGas))
this.maxPriorityFeePerGas = bufferToBigInt(
toBuffer(maxPriorityFeePerGas === '' ? '0x' : maxPriorityFeePerGas)
this.maxFeePerGas = bytesToBigInt(toBytes(maxFeePerGas === '' ? '0x' : maxFeePerGas))
this.maxPriorityFeePerGas = bytesToBigInt(
toBytes(maxPriorityFeePerGas === '' ? '0x' : maxPriorityFeePerGas)
)

@@ -245,3 +244,3 @@

/**
* Returns a Buffer Array of the raw Buffers of the EIP-1559 transaction, in order.
* Returns a Uint8Array Array of the raw Bytes of the EIP-1559 transaction, in order.
*

@@ -254,20 +253,20 @@ * Format: `[chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data,

*
* For an unsigned tx this method uses the empty Buffer values for the
* For an unsigned tx this method uses the empty Bytes values for the
* signature parameters `v`, `r` and `s` for encoding. For an EIP-155 compliant
* representation for external signing use {@link FeeMarketEIP1559Transaction.getMessageToSign}.
*/
raw(): FeeMarketEIP1559ValuesArray {
raw(): TxValuesArray {
return [
bigIntToUnpaddedBuffer(this.chainId),
bigIntToUnpaddedBuffer(this.nonce),
bigIntToUnpaddedBuffer(this.maxPriorityFeePerGas),
bigIntToUnpaddedBuffer(this.maxFeePerGas),
bigIntToUnpaddedBuffer(this.gasLimit),
this.to !== undefined ? this.to.buf : Buffer.from([]),
bigIntToUnpaddedBuffer(this.value),
bigIntToUnpaddedBytes(this.chainId),
bigIntToUnpaddedBytes(this.nonce),
bigIntToUnpaddedBytes(this.maxPriorityFeePerGas),
bigIntToUnpaddedBytes(this.maxFeePerGas),
bigIntToUnpaddedBytes(this.gasLimit),
this.to !== undefined ? this.to.bytes : new Uint8Array(0),
bigIntToUnpaddedBytes(this.value),
this.data,
this.accessList,
this.v !== undefined ? bigIntToUnpaddedBuffer(this.v) : Buffer.from([]),
this.r !== undefined ? bigIntToUnpaddedBuffer(this.r) : Buffer.from([]),
this.s !== undefined ? bigIntToUnpaddedBuffer(this.s) : Buffer.from([]),
this.v !== undefined ? bigIntToUnpaddedBytes(this.v) : new Uint8Array(0),
this.r !== undefined ? bigIntToUnpaddedBytes(this.r) : new Uint8Array(0),
this.s !== undefined ? bigIntToUnpaddedBytes(this.s) : new Uint8Array(0),
]

@@ -286,12 +285,9 @@ }

*/
serialize(): Buffer {
serialize(): Uint8Array {
const base = this.raw()
return Buffer.concat([
TRANSACTION_TYPE_BUFFER,
Buffer.from(RLP.encode(bufArrToArr(base as Buffer[]))),
])
return concatBytes(TRANSACTION_TYPE_BYTES, RLP.encode(base))
}
/**
* Returns the serialized unsigned tx (hashed or raw), which can be used
* Returns the raw serialized unsigned tx, which can be used
* to sign the transaction (e.g. for sending to a hardware wallet).

@@ -303,21 +299,23 @@ *

* ```javascript
* const serializedMessage = tx.getMessageToSign(false) // use this for the HW wallet input
* const serializedMessage = tx.getMessageToSign() // use this for the HW wallet input
* ```
*
* @param hashMessage - Return hashed message if set to true (default: true)
*/
getMessageToSign(hashMessage = true): Buffer {
getMessageToSign(): Uint8Array {
const base = this.raw().slice(0, 9)
const message = Buffer.concat([
TRANSACTION_TYPE_BUFFER,
Buffer.from(RLP.encode(bufArrToArr(base as Buffer[]))),
])
if (hashMessage) {
return Buffer.from(keccak256(message))
} else {
return message
}
const message = concatBytes(TRANSACTION_TYPE_BYTES, RLP.encode(base))
return message
}
/**
* Returns the hashed serialized unsigned tx, which can be used
* to sign the transaction (e.g. for sending to a hardware wallet).
*
* Note: in contrast to the legacy tx the raw message format is already
* serialized and doesn't need to be RLP encoded any more.
*/
getHashedMessageToSign(): Uint8Array {
return keccak256(this.getMessageToSign())
}
/**
* Computes a sha3-256 hash of the serialized tx.

@@ -328,3 +326,3 @@ *

*/
public hash(): Buffer {
public hash(): Uint8Array {
if (!this.isSigned()) {

@@ -337,3 +335,3 @@ const msg = this._errorMsg('Cannot call hash method if transaction is not signed')

if (!this.cache.hash) {
this.cache.hash = Buffer.from(keccak256(this.serialize()))
this.cache.hash = keccak256(this.serialize())
}

@@ -343,3 +341,3 @@ return this.cache.hash

return Buffer.from(keccak256(this.serialize()))
return keccak256(this.serialize())
}

@@ -350,4 +348,4 @@

*/
public getMessageToVerifySignature(): Buffer {
return this.getMessageToSign()
public getMessageToVerifySignature(): Uint8Array {
return this.getHashedMessageToSign()
}

@@ -358,3 +356,3 @@

*/
public getSenderPublicKey(): Buffer {
public getSenderPublicKey(): Uint8Array {
if (!this.isSigned()) {

@@ -374,4 +372,4 @@ const msg = this._errorMsg('Cannot call this method if transaction is not signed')

v! + BigInt(27), // Recover the 27 which was stripped from ecsign
bigIntToUnpaddedBuffer(r!),
bigIntToUnpaddedBuffer(s!)
bigIntToUnpaddedBytes(r!),
bigIntToUnpaddedBytes(s!)
)

@@ -384,3 +382,3 @@ } catch (e: any) {

_processSignature(v: bigint, r: Buffer, s: Buffer) {
protected _processSignature(v: bigint, r: Uint8Array, s: Uint8Array) {
const opts = { ...this.txOptions, common: this.common }

@@ -400,4 +398,4 @@

v: v - BigInt(27), // This looks extremely hacky: @ethereumjs/util actually adds 27 to the value, the recovery bit is either 0 or 1.
r: bufferToBigInt(r),
s: bufferToBigInt(s),
r: bytesToBigInt(r),
s: bytesToBigInt(s),
},

@@ -413,16 +411,10 @@ opts

const accessListJSON = AccessLists.getAccessListJSON(this.accessList)
const baseJson = super.toJSON()
return {
...baseJson,
chainId: bigIntToHex(this.chainId),
nonce: bigIntToHex(this.nonce),
maxPriorityFeePerGas: bigIntToHex(this.maxPriorityFeePerGas),
maxFeePerGas: bigIntToHex(this.maxFeePerGas),
gasLimit: bigIntToHex(this.gasLimit),
to: this.to !== undefined ? this.to.toString() : undefined,
value: bigIntToHex(this.value),
data: '0x' + this.data.toString('hex'),
accessList: accessListJSON,
v: this.v !== undefined ? bigIntToHex(this.v) : undefined,
r: this.r !== undefined ? bigIntToHex(this.r) : undefined,
s: this.s !== undefined ? bigIntToHex(this.s) : undefined,
}

@@ -429,0 +421,0 @@ }

import { RLP } from '@ethereumjs/rlp'
import {
MAX_INTEGER,
arrToBufArr,
bigIntToHex,
bigIntToUnpaddedBuffer,
bufArrToArr,
bufferToBigInt,
bigIntToUnpaddedBytes,
bytesToBigInt,
bytesToHex,
concatBytes,
ecrecover,
toBuffer,
equalsBytes,
hexToBytes,
toBytes,
validateNoLeadingZeroes,
} from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak'
import { keccak256 } from 'ethereum-cryptography/keccak.js'
import { BaseTransaction } from './baseTransaction'
import { AccessLists } from './util'
import { BaseTransaction } from './baseTransaction.js'
import { TransactionType } from './types.js'
import { AccessLists } from './util.js'
import type {
AccessList,
AccessListBuffer,
AccessListEIP2930TxData,
AccessListEIP2930ValuesArray,
AccessListBytes,
TxData as AllTypesTxData,
TxValuesArray as AllTypesTxValuesArray,
JsonTx,
TxOptions,
} from './types'
} from './types.js'
import type { Common } from '@ethereumjs/common'
const TRANSACTION_TYPE = 1
const TRANSACTION_TYPE_BUFFER = Buffer.from(TRANSACTION_TYPE.toString(16).padStart(2, '0'), 'hex')
type TxData = AllTypesTxData[TransactionType.AccessListEIP2930]
type TxValuesArray = AllTypesTxValuesArray[TransactionType.AccessListEIP2930]
const TRANSACTION_TYPE_BYTES = hexToBytes(
'0x' + TransactionType.AccessListEIP2930.toString(16).padStart(2, '0')
)
/**

@@ -37,5 +44,5 @@ * Typed transaction with optional access lists

*/
export class AccessListEIP2930Transaction extends BaseTransaction<AccessListEIP2930Transaction> {
export class AccessListEIP2930Transaction extends BaseTransaction<TransactionType.AccessListEIP2930> {
public readonly chainId: bigint
public readonly accessList: AccessListBuffer
public readonly accessList: AccessListBytes
public readonly AccessListJSON: AccessList

@@ -47,10 +54,2 @@ public readonly gasPrice: bigint

/**
* The default HF if the tx type is active on that HF
* or the first greater HF where the tx is active.
*
* @hidden
*/
protected DEFAULT_HARDFORK = 'berlin'
/**
* Instantiate a transaction from a data dictionary.

@@ -65,3 +64,3 @@ *

*/
public static fromTxData(txData: AccessListEIP2930TxData, opts: TxOptions = {}) {
public static fromTxData(txData: TxData, opts: TxOptions = {}) {
return new AccessListEIP2930Transaction(txData, opts)

@@ -76,12 +75,12 @@ }

*/
public static fromSerializedTx(serialized: Buffer, opts: TxOptions = {}) {
if (!serialized.slice(0, 1).equals(TRANSACTION_TYPE_BUFFER)) {
public static fromSerializedTx(serialized: Uint8Array, opts: TxOptions = {}) {
if (equalsBytes(serialized.subarray(0, 1), TRANSACTION_TYPE_BYTES) === false) {
throw new Error(
`Invalid serialized tx input: not an EIP-2930 transaction (wrong tx type, expected: ${TRANSACTION_TYPE}, received: ${serialized
.slice(0, 1)
.toString('hex')}`
`Invalid serialized tx input: not an EIP-2930 transaction (wrong tx type, expected: ${
TransactionType.AccessListEIP2930
}, received: ${bytesToHex(serialized.subarray(0, 1))}`
)
}
const values = arrToBufArr(RLP.decode(Uint8Array.from(serialized.slice(1))))
const values = RLP.decode(Uint8Array.from(serialized.subarray(1)))

@@ -92,3 +91,3 @@ if (!Array.isArray(values)) {

return AccessListEIP2930Transaction.fromValuesArray(values as any, opts)
return AccessListEIP2930Transaction.fromValuesArray(values as TxValuesArray, opts)
}

@@ -102,3 +101,3 @@

*/
public static fromValuesArray(values: AccessListEIP2930ValuesArray, opts: TxOptions = {}) {
public static fromValuesArray(values: TxValuesArray, opts: TxOptions = {}) {
if (values.length !== 8 && values.length !== 11) {

@@ -119,3 +118,3 @@ throw new Error(

{
chainId: bufferToBigInt(chainId),
chainId: bytesToBigInt(chainId),
nonce,

@@ -128,3 +127,3 @@ gasPrice,

accessList: accessList ?? emptyAccessList,
v: v !== undefined ? bufferToBigInt(v) : undefined, // EIP2930 supports v's with value 0 (empty Buffer)
v: v !== undefined ? bytesToBigInt(v) : undefined, // EIP2930 supports v's with value 0 (empty Uint8Array)
r,

@@ -144,4 +143,4 @@ s,

*/
public constructor(txData: AccessListEIP2930TxData, opts: TxOptions = {}) {
super({ ...txData, type: TRANSACTION_TYPE }, opts)
public constructor(txData: TxData, opts: TxOptions = {}) {
super({ ...txData, type: TransactionType.AccessListEIP2930 }, opts)
const { chainId, accessList, gasPrice } = txData

@@ -165,3 +164,3 @@

this.gasPrice = bufferToBigInt(toBuffer(gasPrice === '' ? '0x' : gasPrice))
this.gasPrice = bytesToBigInt(toBytes(gasPrice === '' ? '0x' : gasPrice))

@@ -217,3 +216,3 @@ this._validateCannotExceedMaxInteger({

/**
* Returns a Buffer Array of the raw Buffers of the EIP-2930 transaction, in order.
* Returns a Uint8Array Array of the raw Bytess of the EIP-2930 transaction, in order.
*

@@ -226,19 +225,19 @@ * Format: `[chainId, nonce, gasPrice, gasLimit, to, value, data, accessList,

*
* For an unsigned tx this method uses the empty Buffer values for the
* For an unsigned tx this method uses the empty Bytes values for the
* signature parameters `v`, `r` and `s` for encoding. For an EIP-155 compliant
* representation for external signing use {@link AccessListEIP2930Transaction.getMessageToSign}.
*/
raw(): AccessListEIP2930ValuesArray {
raw(): TxValuesArray {
return [
bigIntToUnpaddedBuffer(this.chainId),
bigIntToUnpaddedBuffer(this.nonce),
bigIntToUnpaddedBuffer(this.gasPrice),
bigIntToUnpaddedBuffer(this.gasLimit),
this.to !== undefined ? this.to.buf : Buffer.from([]),
bigIntToUnpaddedBuffer(this.value),
bigIntToUnpaddedBytes(this.chainId),
bigIntToUnpaddedBytes(this.nonce),
bigIntToUnpaddedBytes(this.gasPrice),
bigIntToUnpaddedBytes(this.gasLimit),
this.to !== undefined ? this.to.bytes : new Uint8Array(0),
bigIntToUnpaddedBytes(this.value),
this.data,
this.accessList,
this.v !== undefined ? bigIntToUnpaddedBuffer(this.v) : Buffer.from([]),
this.r !== undefined ? bigIntToUnpaddedBuffer(this.r) : Buffer.from([]),
this.s !== undefined ? bigIntToUnpaddedBuffer(this.s) : Buffer.from([]),
this.v !== undefined ? bigIntToUnpaddedBytes(this.v) : new Uint8Array(0),
this.r !== undefined ? bigIntToUnpaddedBytes(this.r) : new Uint8Array(0),
this.s !== undefined ? bigIntToUnpaddedBytes(this.s) : new Uint8Array(0),
]

@@ -257,12 +256,9 @@ }

*/
serialize(): Buffer {
serialize(): Uint8Array {
const base = this.raw()
return Buffer.concat([
TRANSACTION_TYPE_BUFFER,
Buffer.from(RLP.encode(bufArrToArr(base as Buffer[]))),
])
return concatBytes(TRANSACTION_TYPE_BYTES, RLP.encode(base))
}
/**
* Returns the serialized unsigned tx (hashed or raw), which can be used
* Returns the raw serialized unsigned tx, which can be used
* to sign the transaction (e.g. for sending to a hardware wallet).

@@ -274,21 +270,23 @@ *

* ```javascript
* const serializedMessage = tx.getMessageToSign(false) // use this for the HW wallet input
* const serializedMessage = tx.getMessageToSign() // use this for the HW wallet input
* ```
*
* @param hashMessage - Return hashed message if set to true (default: true)
*/
getMessageToSign(hashMessage = true): Buffer {
getMessageToSign(): Uint8Array {
const base = this.raw().slice(0, 8)
const message = Buffer.concat([
TRANSACTION_TYPE_BUFFER,
Buffer.from(RLP.encode(bufArrToArr(base as Buffer[]))),
])
if (hashMessage) {
return Buffer.from(keccak256(message))
} else {
return message
}
const message = concatBytes(TRANSACTION_TYPE_BYTES, RLP.encode(base))
return message
}
/**
* Returns the hashed serialized unsigned tx, which can be used
* to sign the transaction (e.g. for sending to a hardware wallet).
*
* Note: in contrast to the legacy tx the raw message format is already
* serialized and doesn't need to be RLP encoded any more.
*/
getHashedMessageToSign(): Uint8Array {
return keccak256(this.getMessageToSign())
}
/**
* Computes a sha3-256 hash of the serialized tx.

@@ -299,3 +297,3 @@ *

*/
public hash(): Buffer {
public hash(): Uint8Array {
if (!this.isSigned()) {

@@ -308,3 +306,3 @@ const msg = this._errorMsg('Cannot call hash method if transaction is not signed')

if (!this.cache.hash) {
this.cache.hash = Buffer.from(keccak256(this.serialize()))
this.cache.hash = keccak256(this.serialize())
}

@@ -314,3 +312,3 @@ return this.cache.hash

return Buffer.from(keccak256(this.serialize()))
return keccak256(this.serialize())
}

@@ -321,4 +319,4 @@

*/
public getMessageToVerifySignature(): Buffer {
return this.getMessageToSign()
public getMessageToVerifySignature(): Uint8Array {
return this.getHashedMessageToSign()
}

@@ -329,3 +327,3 @@

*/
public getSenderPublicKey(): Buffer {
public getSenderPublicKey(): Uint8Array {
if (!this.isSigned()) {

@@ -345,4 +343,4 @@ const msg = this._errorMsg('Cannot call this method if transaction is not signed')

v! + BigInt(27), // Recover the 27 which was stripped from ecsign
bigIntToUnpaddedBuffer(r!),
bigIntToUnpaddedBuffer(s!)
bigIntToUnpaddedBytes(r!),
bigIntToUnpaddedBytes(s!)
)

@@ -355,3 +353,3 @@ } catch (e: any) {

_processSignature(v: bigint, r: Buffer, s: Buffer) {
protected _processSignature(v: bigint, r: Uint8Array, s: Uint8Array) {
const opts = { ...this.txOptions, common: this.common }

@@ -370,4 +368,4 @@

v: v - BigInt(27), // This looks extremely hacky: @ethereumjs/util actually adds 27 to the value, the recovery bit is either 0 or 1.
r: bufferToBigInt(r),
s: bufferToBigInt(s),
r: bytesToBigInt(r),
s: bytesToBigInt(s),
},

@@ -383,15 +381,9 @@ opts

const accessListJSON = AccessLists.getAccessListJSON(this.accessList)
const baseJson = super.toJSON()
return {
...baseJson,
chainId: bigIntToHex(this.chainId),
nonce: bigIntToHex(this.nonce),
gasPrice: bigIntToHex(this.gasPrice),
gasLimit: bigIntToHex(this.gasLimit),
to: this.to !== undefined ? this.to.toString() : undefined,
value: bigIntToHex(this.value),
data: '0x' + this.data.toString('hex'),
accessList: accessListJSON,
v: this.v !== undefined ? bigIntToHex(this.v) : undefined,
r: this.r !== undefined ? bigIntToHex(this.r) : undefined,
s: this.s !== undefined ? bigIntToHex(this.s) : undefined,
}

@@ -398,0 +390,0 @@ }

@@ -1,6 +0,6 @@

import { TypeOutput, setLengthLeft, toBuffer, toType } from '@ethereumjs/util'
import { TypeOutput, setLengthLeft, toBytes, toType } from '@ethereumjs/util'
import type { TxData } from './types'
import type { TypedTxData } from './types.js'
export const normalizeTxParams = (_txParams: any): TxData => {
export const normalizeTxParams = (_txParams: any): TypedTxData => {
const txParams = Object.assign({}, _txParams)

@@ -18,3 +18,3 @@

txParams.to !== null && txParams.to !== undefined
? setLengthLeft(toBuffer(txParams.to), 20)
? setLengthLeft(toBytes(txParams.to), 20)
: null

@@ -32,3 +32,3 @@

if (txParams.v !== '0x') {
if (txParams.v !== '0x' || txParams.r !== '0x' || txParams.s !== '0x') {
txParams.v = toType(txParams.v, TypeOutput.BigInt)

@@ -35,0 +35,0 @@ }

@@ -1,5 +0,6 @@

export { FeeMarketEIP1559Transaction } from './eip1559Transaction'
export { AccessListEIP2930Transaction } from './eip2930Transaction'
export { Transaction } from './legacyTransaction'
export { TransactionFactory } from './transactionFactory'
export * from './types'
export { FeeMarketEIP1559Transaction } from './eip1559Transaction.js'
export { AccessListEIP2930Transaction } from './eip2930Transaction.js'
export { BlobEIP4844Transaction } from './eip4844Transaction.js'
export { LegacyTransaction } from './legacyTransaction.js'
export { TransactionFactory } from './transactionFactory.js'
export * from './types.js'
import { RLP } from '@ethereumjs/rlp'
import {
MAX_INTEGER,
arrToBufArr,
bigIntToHex,
bigIntToUnpaddedBuffer,
bufArrToArr,
bufferToBigInt,
bigIntToUnpaddedBytes,
bytesToBigInt,
ecrecover,
toBuffer,
unpadBuffer,
toBytes,
unpadBytes,
validateNoLeadingZeroes,
} from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak'
import { keccak256 } from 'ethereum-cryptography/keccak.js'
import { BaseTransaction } from './baseTransaction'
import { Capability } from './types'
import { BaseTransaction } from './baseTransaction.js'
import { Capability, TransactionType } from './types.js'
import type { JsonTx, TxData, TxOptions, TxValuesArray } from './types'
import type {
TxData as AllTypesTxData,
TxValuesArray as AllTypesTxValuesArray,
JsonTx,
TxOptions,
} from './types.js'
import type { Common } from '@ethereumjs/common'
const TRANSACTION_TYPE = 0
type TxData = AllTypesTxData[TransactionType.Legacy]
type TxValuesArray = AllTypesTxValuesArray[TransactionType.Legacy]

@@ -33,3 +37,3 @@ function meetsEIP155(_v: bigint, chainId: bigint) {

*/
export class Transaction extends BaseTransaction<Transaction> {
export class LegacyTransaction extends BaseTransaction<TransactionType.Legacy> {
public readonly gasPrice: bigint

@@ -48,3 +52,3 @@

public static fromTxData(txData: TxData, opts: TxOptions = {}) {
return new Transaction(txData, opts)
return new LegacyTransaction(txData, opts)
}

@@ -57,4 +61,4 @@

*/
public static fromSerializedTx(serialized: Buffer, opts: TxOptions = {}) {
const values = arrToBufArr(RLP.decode(Uint8Array.from(serialized))) as Buffer[]
public static fromSerializedTx(serialized: Uint8Array, opts: TxOptions = {}) {
const values = RLP.decode(serialized)

@@ -65,3 +69,3 @@ if (!Array.isArray(values)) {

return this.fromValuesArray(values, opts)
return this.fromValuesArray(values as TxValuesArray, opts)
}

@@ -75,3 +79,3 @@

public static fromValuesArray(values: TxValuesArray, opts: TxOptions = {}) {
// If length is not 6, it has length 9. If v/r/s are empty Buffers, it is still an unsigned transaction
// If length is not 6, it has length 9. If v/r/s are empty Uint8Arrays, it is still an unsigned transaction
// This happens if you get the RLP data from `raw()`

@@ -88,3 +92,3 @@ if (values.length !== 6 && values.length !== 9) {

return new Transaction(
return new LegacyTransaction(
{

@@ -113,7 +117,7 @@ nonce,

public constructor(txData: TxData, opts: TxOptions = {}) {
super({ ...txData, type: TRANSACTION_TYPE }, opts)
super({ ...txData, type: TransactionType.Legacy }, opts)
this.common = this._validateTxV(this.v, opts.common)
this.gasPrice = bufferToBigInt(toBuffer(txData.gasPrice === '' ? '0x' : txData.gasPrice))
this.gasPrice = bytesToBigInt(toBytes(txData.gasPrice === '' ? '0x' : txData.gasPrice))

@@ -150,3 +154,3 @@ if (this.gasPrice * this.gasLimit > MAX_INTEGER) {

/**
* Returns a Buffer Array of the raw Buffers of the legacy transaction, in order.
* Returns a Uint8Array Array of the raw Bytes of the legacy transaction, in order.
*

@@ -159,3 +163,3 @@ * Format: `[nonce, gasPrice, gasLimit, to, value, data, v, r, s]`

*
* For an unsigned tx this method returns the empty Buffer values
* For an unsigned tx this method returns the empty Bytes values
* for the signature parameters `v`, `r` and `s`. For an EIP-155 compliant

@@ -166,11 +170,11 @@ * representation have a look at {@link Transaction.getMessageToSign}.

return [
bigIntToUnpaddedBuffer(this.nonce),
bigIntToUnpaddedBuffer(this.gasPrice),
bigIntToUnpaddedBuffer(this.gasLimit),
this.to !== undefined ? this.to.buf : Buffer.from([]),
bigIntToUnpaddedBuffer(this.value),
bigIntToUnpaddedBytes(this.nonce),
bigIntToUnpaddedBytes(this.gasPrice),
bigIntToUnpaddedBytes(this.gasLimit),
this.to !== undefined ? this.to.bytes : new Uint8Array(0),
bigIntToUnpaddedBytes(this.value),
this.data,
this.v !== undefined ? bigIntToUnpaddedBuffer(this.v) : Buffer.from([]),
this.r !== undefined ? bigIntToUnpaddedBuffer(this.r) : Buffer.from([]),
this.s !== undefined ? bigIntToUnpaddedBuffer(this.s) : Buffer.from([]),
this.v !== undefined ? bigIntToUnpaddedBytes(this.v) : new Uint8Array(0),
this.r !== undefined ? bigIntToUnpaddedBytes(this.r) : new Uint8Array(0),
this.s !== undefined ? bigIntToUnpaddedBytes(this.s) : new Uint8Array(0),
]

@@ -184,31 +188,12 @@ }

*
* For an unsigned tx this method uses the empty Buffer values for the
* For an unsigned tx this method uses the empty Uint8Array values for the
* signature parameters `v`, `r` and `s` for encoding. For an EIP-155 compliant
* representation for external signing use {@link Transaction.getMessageToSign}.
*/
serialize(): Buffer {
return Buffer.from(RLP.encode(bufArrToArr(this.raw())))
serialize(): Uint8Array {
return RLP.encode(this.raw())
}
private _getMessageToSign() {
const values = [
bigIntToUnpaddedBuffer(this.nonce),
bigIntToUnpaddedBuffer(this.gasPrice),
bigIntToUnpaddedBuffer(this.gasLimit),
this.to !== undefined ? this.to.buf : Buffer.from([]),
bigIntToUnpaddedBuffer(this.value),
this.data,
]
if (this.supports(Capability.EIP155ReplayProtection)) {
values.push(bigIntToUnpaddedBuffer(this.common.chainId()))
values.push(unpadBuffer(toBuffer(0)))
values.push(unpadBuffer(toBuffer(0)))
}
return values
}
/**
* Returns the unsigned tx (hashed or raw), which can be used
* Returns the raw unsigned tx, which can be used
* to sign the transaction (e.g. for sending to a hardware wallet).

@@ -220,22 +205,36 @@ *

* ```javascript
* import { bufArrToArr } from '@ethereumjs/util'
* import { RLP } from '@ethereumjs/rlp'
* const message = tx.getMessageToSign(false)
* const serializedMessage = Buffer.from(RLP.encode(bufArrToArr(message))) // use this for the HW wallet input
* const message = tx.getMessageToSign()
* const serializedMessage = RLP.encode(message)) // use this for the HW wallet input
* ```
*
* @param hashMessage - Return hashed message if set to true (default: true)
*/
getMessageToSign(hashMessage: false): Buffer[]
getMessageToSign(hashMessage?: true): Buffer
getMessageToSign(hashMessage = true) {
const message = this._getMessageToSign()
if (hashMessage) {
return Buffer.from(keccak256(RLP.encode(bufArrToArr(message))))
} else {
return message
getMessageToSign(): Uint8Array[] {
const message = [
bigIntToUnpaddedBytes(this.nonce),
bigIntToUnpaddedBytes(this.gasPrice),
bigIntToUnpaddedBytes(this.gasLimit),
this.to !== undefined ? this.to.bytes : new Uint8Array(0),
bigIntToUnpaddedBytes(this.value),
this.data,
]
if (this.supports(Capability.EIP155ReplayProtection)) {
message.push(bigIntToUnpaddedBytes(this.common.chainId()))
message.push(unpadBytes(toBytes(0)))
message.push(unpadBytes(toBytes(0)))
}
return message
}
/**
* Returns the hashed serialized unsigned tx, which can be used
* to sign the transaction (e.g. for sending to a hardware wallet).
*/
getHashedMessageToSign() {
const message = this.getMessageToSign()
return keccak256(RLP.encode(message))
}
/**
* The amount of gas paid for the data in this tx

@@ -271,3 +270,3 @@ */

*/
hash(): Buffer {
hash(): Uint8Array {
if (!this.isSigned()) {

@@ -280,3 +279,3 @@ const msg = this._errorMsg('Cannot call hash method if transaction is not signed')

if (!this.cache.hash) {
this.cache.hash = Buffer.from(keccak256(RLP.encode(bufArrToArr(this.raw()))))
this.cache.hash = keccak256(RLP.encode(this.raw()))
}

@@ -286,3 +285,3 @@ return this.cache.hash

return Buffer.from(keccak256(RLP.encode(bufArrToArr(this.raw()))))
return keccak256(RLP.encode(this.raw()))
}

@@ -298,4 +297,3 @@

}
const message = this._getMessageToSign()
return Buffer.from(keccak256(RLP.encode(bufArrToArr(message))))
return this.getHashedMessageToSign()
}

@@ -306,3 +304,3 @@

*/
getSenderPublicKey(): Buffer {
getSenderPublicKey(): Uint8Array {
const msgHash = this.getMessageToVerifySignature()

@@ -318,4 +316,4 @@

v!,
bigIntToUnpaddedBuffer(r!),
bigIntToUnpaddedBuffer(s!),
bigIntToUnpaddedBytes(r!),
bigIntToUnpaddedBytes(s!),
this.supports(Capability.EIP155ReplayProtection) ? this.common.chainId() : undefined

@@ -332,3 +330,3 @@ )

*/
protected _processSignature(v: bigint, r: Buffer, s: Buffer) {
protected _processSignature(v: bigint, r: Uint8Array, s: Uint8Array) {
if (this.supports(Capability.EIP155ReplayProtection)) {

@@ -340,3 +338,3 @@ v += this.common.chainId() * BigInt(2) + BigInt(8)

return Transaction.fromTxData(
return LegacyTransaction.fromTxData(
{

@@ -350,4 +348,4 @@ nonce: this.nonce,

v,
r: bufferToBigInt(r),
s: bufferToBigInt(s),
r: bytesToBigInt(r),
s: bytesToBigInt(s),
},

@@ -362,12 +360,6 @@ opts

toJSON(): JsonTx {
const baseJson = super.toJSON()
return {
nonce: bigIntToHex(this.nonce),
...baseJson,
gasPrice: bigIntToHex(this.gasPrice),
gasLimit: bigIntToHex(this.gasLimit),
to: this.to !== undefined ? this.to.toString() : undefined,
value: bigIntToHex(this.value),
data: '0x' + this.data.toString('hex'),
v: this.v !== undefined ? bigIntToHex(this.v) : undefined,
r: this.r !== undefined ? bigIntToHex(this.r) : undefined,
s: this.s !== undefined ? bigIntToHex(this.s) : undefined,
}

@@ -379,3 +371,3 @@ }

*/
private _validateTxV(_v?: bigint, common?: Common): Common {
protected _validateTxV(_v?: bigint, common?: Common): Common {
let chainIdBigInt

@@ -382,0 +374,0 @@ const v = _v !== undefined ? Number(_v) : undefined

@@ -1,15 +0,18 @@

import { bufferToBigInt, fetchFromProvider, getProvider, toBuffer } from '@ethereumjs/util'
import { fetchFromProvider, getProvider } from '@ethereumjs/util'
import { FeeMarketEIP1559Transaction } from './eip1559Transaction'
import { AccessListEIP2930Transaction } from './eip2930Transaction'
import { normalizeTxParams } from './fromRpc'
import { Transaction } from './legacyTransaction'
import { FeeMarketEIP1559Transaction } from './eip1559Transaction.js'
import { AccessListEIP2930Transaction } from './eip2930Transaction.js'
import { BlobEIP4844Transaction } from './eip4844Transaction.js'
import { normalizeTxParams } from './fromRpc.js'
import { LegacyTransaction } from './legacyTransaction.js'
import {
TransactionType,
isAccessListEIP2930TxData,
isBlobEIP4844TxData,
isFeeMarketEIP1559TxData,
isLegacyTxData,
} from './types.js'
import type {
AccessListEIP2930TxData,
FeeMarketEIP1559TxData,
TxData,
TxOptions,
TypedTransaction,
} from './types'
import type { Transaction, TxData, TxOptions, TypedTxData } from './types.js'
import type { EthersProvider } from '@ethereumjs/util'

@@ -26,19 +29,20 @@ export class TransactionFactory {

*/
public static fromTxData(
txData: TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData,
public static fromTxData<T extends TransactionType>(
txData: TypedTxData,
txOptions: TxOptions = {}
): TypedTransaction {
): Transaction[T] {
if (!('type' in txData) || txData.type === undefined) {
// Assume legacy transaction
return Transaction.fromTxData(<TxData>txData, txOptions)
return LegacyTransaction.fromTxData(txData, txOptions) as Transaction[T]
} else {
const txType = Number(bufferToBigInt(toBuffer(txData.type)))
if (txType === 0) {
return Transaction.fromTxData(<TxData>txData, txOptions)
} else if (txType === 1) {
return AccessListEIP2930Transaction.fromTxData(<AccessListEIP2930TxData>txData, txOptions)
} else if (txType === 2) {
return FeeMarketEIP1559Transaction.fromTxData(<FeeMarketEIP1559TxData>txData, txOptions)
if (isLegacyTxData(txData)) {
return LegacyTransaction.fromTxData(txData, txOptions) as Transaction[T]
} else if (isAccessListEIP2930TxData(txData)) {
return AccessListEIP2930Transaction.fromTxData(txData, txOptions) as Transaction[T]
} else if (isFeeMarketEIP1559TxData(txData)) {
return FeeMarketEIP1559Transaction.fromTxData(txData, txOptions) as Transaction[T]
} else if (isBlobEIP4844TxData(txData)) {
return BlobEIP4844Transaction.fromTxData(txData, txOptions) as Transaction[T]
} else {
throw new Error(`Tx instantiation with type ${txType} not supported`)
throw new Error(`Tx instantiation with type ${(txData as TypedTxData)?.type} not supported`)
}

@@ -51,13 +55,18 @@ }

*
* @param data - The data Buffer
* @param data - The data Uint8Array
* @param txOptions - The transaction options
*/
public static fromSerializedData(data: Buffer, txOptions: TxOptions = {}): TypedTransaction {
public static fromSerializedData<T extends TransactionType>(
data: Uint8Array,
txOptions: TxOptions = {}
): Transaction[T] {
if (data[0] <= 0x7f) {
// Determine the type.
switch (data[0]) {
case 1:
return AccessListEIP2930Transaction.fromSerializedTx(data, txOptions)
case 2:
return FeeMarketEIP1559Transaction.fromSerializedTx(data, txOptions)
case TransactionType.AccessListEIP2930:
return AccessListEIP2930Transaction.fromSerializedTx(data, txOptions) as Transaction[T]
case TransactionType.FeeMarketEIP1559:
return FeeMarketEIP1559Transaction.fromSerializedTx(data, txOptions) as Transaction[T]
case TransactionType.BlobEIP4844:
return BlobEIP4844Transaction.fromSerializedTx(data, txOptions) as Transaction[T]
default:

@@ -67,3 +76,3 @@ throw new Error(`TypedTransaction with ID ${data[0]} unknown`)

} else {
return Transaction.fromSerializedTx(data, txOptions)
return LegacyTransaction.fromSerializedTx(data, txOptions) as Transaction[T]
}

@@ -74,15 +83,15 @@ }

* When decoding a BlockBody, in the transactions field, a field is either:
* A Buffer (a TypedTransaction - encoded as TransactionType || rlp(TransactionPayload))
* A Buffer[] (Legacy Transaction)
* A Uint8Array (a TypedTransaction - encoded as TransactionType || rlp(TransactionPayload))
* A Uint8Array[] (Legacy Transaction)
* This method returns the right transaction.
*
* @param data - A Buffer or Buffer[]
* @param data - A Uint8Array or Uint8Array[]
* @param txOptions - The transaction options
*/
public static fromBlockBodyData(data: Buffer | Buffer[], txOptions: TxOptions = {}) {
if (Buffer.isBuffer(data)) {
public static fromBlockBodyData(data: Uint8Array | Uint8Array[], txOptions: TxOptions = {}) {
if (data instanceof Uint8Array) {
return this.fromSerializedData(data, txOptions)
} else if (Array.isArray(data)) {
// It is a legacy transaction
return Transaction.fromValuesArray(data, txOptions)
return LegacyTransaction.fromValuesArray(data, txOptions)
} else {

@@ -95,3 +104,3 @@ throw new Error('Cannot decode transaction: unknown type input')

* Method to retrieve a transaction from the provider
* @param provider - An Ethers JsonRPCProvider
* @param provider - a url string for a JSON-RPC provider or an Ethers JsonRPCProvider object
* @param txHash - Transaction hash

@@ -101,4 +110,4 @@ * @param txOptions - The transaction options

*/
public static async fromEthersProvider(
provider: string | any,
public static async fromJsonRpcProvider(
provider: string | EthersProvider,
txHash: string,

@@ -115,3 +124,3 @@ txOptions?: TxOptions

}
return TransactionFactory.fromRPCTx(txData, txOptions)
return TransactionFactory.fromRPC(txData, txOptions)
}

@@ -126,8 +135,8 @@

*/
public static async fromRPCTx(
txData: TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData,
public static async fromRPC<T extends TransactionType>(
txData: TxData[T],
txOptions: TxOptions = {}
) {
): Promise<Transaction[T]> {
return TransactionFactory.fromTxData(normalizeTxParams(txData), txOptions)
}
}

@@ -1,7 +0,16 @@

import type { FeeMarketEIP1559Transaction } from './eip1559Transaction'
import type { AccessListEIP2930Transaction } from './eip2930Transaction'
import type { Transaction } from './legacyTransaction'
import type { Common } from '@ethereumjs/common'
import type { AddressLike, BigIntLike, BufferLike, PrefixedHexString } from '@ethereumjs/util'
import { bytesToBigInt, toBytes } from '@ethereumjs/util'
import type { FeeMarketEIP1559Transaction } from './eip1559Transaction.js'
import type { AccessListEIP2930Transaction } from './eip2930Transaction.js'
import type { BlobEIP4844Transaction } from './eip4844Transaction.js'
import type { LegacyTransaction } from './legacyTransaction.js'
import type { AccessList, AccessListBytes, Common } from '@ethereumjs/common'
import type { Address, AddressLike, BigIntLike, BytesLike } from '@ethereumjs/util'
export type {
AccessList,
AccessListBytes,
AccessListBytesItem,
AccessListItem,
} from '@ethereumjs/common'
/**

@@ -72,21 +81,3 @@ * Can be used in conjunction with {@link Transaction.supports}

/*
* Access List types
*/
export type AccessListItem = {
address: PrefixedHexString
storageKeys: PrefixedHexString[]
}
/*
* An Access List as a tuple of [address: Buffer, storageKeys: Buffer[]]
*/
export type AccessListBufferItem = [Buffer, Buffer[]]
export type AccessListBuffer = AccessListBufferItem[]
export type AccessList = AccessListItem[]
export function isAccessListBuffer(
input: AccessListBuffer | AccessList
): input is AccessListBuffer {
export function isAccessListBytes(input: AccessListBytes | AccessList): input is AccessListBytes {
if (input.length === 0) {

@@ -102,4 +93,4 @@ return true

export function isAccessList(input: AccessListBuffer | AccessList): input is AccessList {
return !isAccessListBuffer(input) // This is exactly the same method, except the output is negated.
export function isAccessList(input: AccessListBytes | AccessList): input is AccessList {
return !isAccessListBytes(input) // This is exactly the same method, except the output is negated.
}

@@ -109,15 +100,92 @@

* Encompassing type for all transaction types.
*
* Note that this also includes legacy txs which are
* referenced as {@link Transaction} for compatibility reasons.
*/
export type TypedTransaction =
| Transaction
| AccessListEIP2930Transaction
| FeeMarketEIP1559Transaction
export enum TransactionType {
Legacy = 0,
AccessListEIP2930 = 1,
FeeMarketEIP1559 = 2,
BlobEIP4844 = 3,
}
export interface Transaction {
[TransactionType.Legacy]: LegacyTransaction
[TransactionType.FeeMarketEIP1559]: FeeMarketEIP1559Transaction
[TransactionType.AccessListEIP2930]: AccessListEIP2930Transaction
[TransactionType.BlobEIP4844]: BlobEIP4844Transaction
}
export type TypedTransaction = Transaction[TransactionType]
export function isLegacyTx(tx: TypedTransaction): tx is LegacyTransaction {
return tx.type === TransactionType.Legacy
}
export function isAccessListEIP2930Tx(tx: TypedTransaction): tx is AccessListEIP2930Transaction {
return tx.type === TransactionType.AccessListEIP2930
}
export function isFeeMarketEIP1559Tx(tx: TypedTransaction): tx is FeeMarketEIP1559Transaction {
return tx.type === TransactionType.FeeMarketEIP1559
}
export function isBlobEIP4844Tx(tx: TypedTransaction): tx is BlobEIP4844Transaction {
return tx.type === TransactionType.BlobEIP4844
}
export interface TransactionInterface<T extends TransactionType> {
supports(capability: Capability): boolean
type: number
getBaseFee(): bigint
getDataFee(): bigint
getUpfrontCost(): bigint
toCreationAddress(): boolean
raw(): TxValuesArray[T]
serialize(): Uint8Array
getMessageToSign(): Uint8Array | Uint8Array[]
getHashedMessageToSign(): Uint8Array
hash(): Uint8Array
getMessageToVerifySignature(): Uint8Array
getValidationErrors(): string[]
isSigned(): boolean
isValid(): boolean
verifySignature(): boolean
getSenderAddress(): Address
getSenderPublicKey(): Uint8Array
sign(privateKey: Uint8Array): Transaction[T]
toJSON(): JsonTx
errorStr(): string
}
export interface TxData {
[TransactionType.Legacy]: LegacyTxData
[TransactionType.AccessListEIP2930]: AccessListEIP2930TxData
[TransactionType.FeeMarketEIP1559]: FeeMarketEIP1559TxData
[TransactionType.BlobEIP4844]: BlobEIP4844TxData
}
export type TypedTxData = TxData[TransactionType]
export function isLegacyTxData(txData: TypedTxData): txData is LegacyTxData {
const txType = Number(bytesToBigInt(toBytes(txData.type)))
return txType === TransactionType.Legacy
}
export function isAccessListEIP2930TxData(txData: TypedTxData): txData is AccessListEIP2930TxData {
const txType = Number(bytesToBigInt(toBytes(txData.type)))
return txType === TransactionType.AccessListEIP2930
}
export function isFeeMarketEIP1559TxData(txData: TypedTxData): txData is FeeMarketEIP1559TxData {
const txType = Number(bytesToBigInt(toBytes(txData.type)))
return txType === TransactionType.FeeMarketEIP1559
}
export function isBlobEIP4844TxData(txData: TypedTxData): txData is BlobEIP4844TxData {
const txType = Number(bytesToBigInt(toBytes(txData.type)))
return txType === TransactionType.BlobEIP4844
}
/**
* Legacy {@link Transaction} Data
*/
export type TxData = {
export type LegacyTxData = {
/**

@@ -151,3 +219,3 @@ * The transaction's nonce.

*/
data?: BufferLike
data?: BytesLike

@@ -179,3 +247,3 @@ /**

*/
export interface AccessListEIP2930TxData extends TxData {
export interface AccessListEIP2930TxData extends LegacyTxData {
/**

@@ -189,3 +257,3 @@ * The transaction's chain ID

*/
accessList?: AccessListBuffer | AccessList | null
accessList?: AccessListBytes | AccessList | null
}

@@ -213,41 +281,105 @@

/**
* Buffer values array for a legacy {@link Transaction}
* {@link BlobEIP4844Transaction} data.
*/
export type TxValuesArray = Buffer[]
export interface BlobEIP4844TxData extends FeeMarketEIP1559TxData {
/**
* The versioned hashes used to validate the blobs attached to a transaction
*/
versionedHashes?: BytesLike[]
/**
* The maximum fee per data gas paid for the transaction
*/
maxFeePerDataGas?: BigIntLike
/**
* The blobs associated with a transaction
*/
blobs?: BytesLike[]
/**
* The KZG commitments corresponding to the versioned hashes for each blob
*/
kzgCommitments?: BytesLike[]
/**
* The KZG proofs associated with the transaction
*/
kzgProofs?: BytesLike[]
/**
* An array of arbitrary strings that blobs are to be constructed from
*/
blobsData?: string[]
}
export interface TxValuesArray {
[TransactionType.Legacy]: LegacyTxValuesArray
[TransactionType.AccessListEIP2930]: AccessListEIP2930TxValuesArray
[TransactionType.FeeMarketEIP1559]: FeeMarketEIP1559TxValuesArray
[TransactionType.BlobEIP4844]: BlobEIP4844TxValuesArray
}
/**
* Buffer values array for an {@link AccessListEIP2930Transaction}
* Bytes values array for a legacy {@link Transaction}
*/
export type AccessListEIP2930ValuesArray = [
Buffer,
Buffer,
Buffer,
Buffer,
Buffer,
Buffer,
Buffer,
AccessListBuffer,
Buffer?,
Buffer?,
Buffer?
type LegacyTxValuesArray = Uint8Array[]
/**
* Bytes values array for an {@link AccessListEIP2930Transaction}
*/
type AccessListEIP2930TxValuesArray = [
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
AccessListBytes,
Uint8Array?,
Uint8Array?,
Uint8Array?
]
/**
* Buffer values array for a {@link FeeMarketEIP1559Transaction}
* Bytes values array for a {@link FeeMarketEIP1559Transaction}
*/
export type FeeMarketEIP1559ValuesArray = [
Buffer,
Buffer,
Buffer,
Buffer,
Buffer,
Buffer,
Buffer,
Buffer,
AccessListBuffer,
Buffer?,
Buffer?,
Buffer?
type FeeMarketEIP1559TxValuesArray = [
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
AccessListBytes,
Uint8Array?,
Uint8Array?,
Uint8Array?
]
/**
* Bytes values array for a {@link BlobEIP4844Transaction}
*/
type BlobEIP4844TxValuesArray = [
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
Uint8Array,
AccessListBytes,
Uint8Array,
Uint8Array[],
Uint8Array?,
Uint8Array?,
Uint8Array?
]
export type BlobEIP4844NetworkValuesArray = [
BlobEIP4844TxValuesArray,
Uint8Array[],
Uint8Array[],
Uint8Array[]
]
type JsonAccessListItem = { address: string; storageKeys: string[] }

@@ -254,0 +386,0 @@

@@ -1,6 +0,6 @@

import { bufferToHex, setLengthLeft, toBuffer } from '@ethereumjs/util'
import { bytesToHex, hexToBytes, setLengthLeft } from '@ethereumjs/util'
import { isAccessList } from './types'
import { isAccessList } from './types.js'
import type { AccessList, AccessListBuffer, AccessListItem } from './types'
import type { AccessList, AccessListBytes, AccessListItem } from './types.js'
import type { Common } from '@ethereumjs/common'

@@ -21,3 +21,3 @@

export class AccessLists {
public static getAccessListData(accessList: AccessListBuffer | AccessList) {
public static getAccessListData(accessList: AccessListBytes | AccessList) {
let AccessListJSON

@@ -27,12 +27,12 @@ let bufferAccessList

AccessListJSON = accessList
const newAccessList: AccessListBuffer = []
const newAccessList: AccessListBytes = []
for (let i = 0; i < accessList.length; i++) {
const item: AccessListItem = accessList[i]
const addressBuffer = toBuffer(item.address)
const storageItems: Buffer[] = []
const addressBytes = hexToBytes(item.address)
const storageItems: Uint8Array[] = []
for (let index = 0; index < item.storageKeys.length; index++) {
storageItems.push(toBuffer(item.storageKeys[index]))
storageItems.push(hexToBytes(item.storageKeys[index]))
}
newAccessList.push([addressBuffer, storageItems])
newAccessList.push([addressBytes, storageItems])
}

@@ -46,6 +46,6 @@ bufferAccessList = newAccessList

const data = bufferAccessList[i]
const address = bufferToHex(data[0])
const address = bytesToHex(data[0])
const storageKeys: string[] = []
for (let item = 0; item < data[1].length; item++) {
storageKeys.push(bufferToHex(data[1][item]))
storageKeys.push(bytesToHex(data[1][item]))
}

@@ -67,7 +67,7 @@ const jsonItem: AccessListItem = {

public static verifyAccessList(accessList: AccessListBuffer) {
public static verifyAccessList(accessList: AccessListBytes) {
for (let key = 0; key < accessList.length; key++) {
const accessListItem = accessList[key]
const address = <Buffer>accessListItem[0]
const storageSlots = <Buffer[]>accessListItem[1]
const address = accessListItem[0]
const storageSlots = accessListItem[1]
if ((<any>accessListItem)[2] !== undefined) {

@@ -89,3 +89,3 @@ throw new Error(

public static getAccessListJSON(accessList: AccessListBuffer) {
public static getAccessListJSON(accessList: AccessListBytes) {
const accessListJSON = []

@@ -95,9 +95,9 @@ for (let index = 0; index < accessList.length; index++) {

const JSONItem: any = {
address: '0x' + setLengthLeft(<Buffer>item[0], 20).toString('hex'),
address: bytesToHex(setLengthLeft(item[0], 20)),
storageKeys: [],
}
const storageSlots: Buffer[] = item[1]
const storageSlots: Uint8Array[] = item[1]
for (let slot = 0; slot < storageSlots.length; slot++) {
const storageSlot = storageSlots[slot]
JSONItem.storageKeys.push('0x' + setLengthLeft(storageSlot, 32).toString('hex'))
JSONItem.storageKeys.push(bytesToHex(setLengthLeft(storageSlot, 32)))
}

@@ -109,3 +109,3 @@ accessListJSON.push(JSONItem)

public static getDataFeeEIP2930(accessList: AccessListBuffer, common: Common): number {
public static getDataFeeEIP2930(accessList: AccessListBytes, common: Common): number {
const accessListStorageKeyCost = common.param('gasPrices', 'accessListStorageKeyCost')

@@ -112,0 +112,0 @@ const accessListAddressCost = common.param('gasPrices', 'accessListAddressCost')

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc