@ethereumjs/tx
Advanced tools
Comparing version 5.3.0 to 5.4.0
@@ -41,9 +41,9 @@ "use strict"; | ||
const toB = (0, util_1.toBytes)(to === '' ? '0x' : to); | ||
const vB = (0, util_1.toBytes)(v === '' ? '0x' : v); | ||
const rB = (0, util_1.toBytes)(r === '' ? '0x' : r); | ||
const sB = (0, util_1.toBytes)(s === '' ? '0x' : s); | ||
this.nonce = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(nonce === '' ? '0x' : nonce)); | ||
this.gasLimit = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(gasLimit === '' ? '0x' : gasLimit)); | ||
const vB = (0, util_1.toBytes)(v); | ||
const rB = (0, util_1.toBytes)(r); | ||
const sB = (0, util_1.toBytes)(s); | ||
this.nonce = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(nonce)); | ||
this.gasLimit = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(gasLimit)); | ||
this.to = toB.length > 0 ? new util_1.Address(toB) : undefined; | ||
this.value = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(value === '' ? '0x' : value)); | ||
this.value = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(value)); | ||
this.data = (0, util_1.toBytes)(data === '' ? '0x' : data); | ||
@@ -248,3 +248,3 @@ this.v = vB.length > 0 ? (0, util_1.bytesToBigInt)(vB) : undefined; | ||
if (common.chainId() !== chainIdBigInt) { | ||
const msg = this._errorMsg(`The chain ID does not match the chain ID of Common. Got: ${chainIdBigInt}, expected: ${common.chainId}`); | ||
const msg = this._errorMsg(`The chain ID does not match the chain ID of Common. Got: ${chainIdBigInt}, expected: ${common.chainId()}`); | ||
throw new Error(msg); | ||
@@ -251,0 +251,0 @@ } |
@@ -32,3 +32,3 @@ "use strict"; | ||
this.chainId = this.common.chainId(); | ||
if (this.common.isActivatedEIP(1559) === false) { | ||
if (!this.common.isActivatedEIP(1559)) { | ||
throw new Error('EIP-1559 not enabled on Common'); | ||
@@ -43,4 +43,4 @@ } | ||
util_js_1.AccessLists.verifyAccessList(this.accessList); | ||
this.maxFeePerGas = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(maxFeePerGas === '' ? '0x' : maxFeePerGas)); | ||
this.maxPriorityFeePerGas = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(maxPriorityFeePerGas === '' ? '0x' : maxPriorityFeePerGas)); | ||
this.maxFeePerGas = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(maxFeePerGas)); | ||
this.maxPriorityFeePerGas = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(maxPriorityFeePerGas)); | ||
this._validateCannotExceedMaxInteger({ | ||
@@ -47,0 +47,0 @@ maxFeePerGas: this.maxFeePerGas, |
@@ -62,3 +62,3 @@ import { BaseTransaction } from './baseTransaction.js'; | ||
/** | ||
* Returns a Uint8Array Array of the raw Bytess of the EIP-2930 transaction, in order. | ||
* Returns a Uint8Array Array of the raw Bytes of the EIP-2930 transaction, in order. | ||
* | ||
@@ -65,0 +65,0 @@ * Format: `[chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, |
@@ -42,3 +42,3 @@ "use strict"; | ||
util_js_1.AccessLists.verifyAccessList(this.accessList); | ||
this.gasPrice = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(gasPrice === '' ? '0x' : gasPrice)); | ||
this.gasPrice = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(gasPrice)); | ||
this._validateCannotExceedMaxInteger({ | ||
@@ -133,3 +133,3 @@ gasPrice: this.gasPrice, | ||
/** | ||
* Returns a Uint8Array Array of the raw Bytess of the EIP-2930 transaction, in order. | ||
* Returns a Uint8Array Array of the raw Bytes of the EIP-2930 transaction, in order. | ||
* | ||
@@ -136,0 +136,0 @@ * Format: `[chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, |
import { BaseTransaction } from './baseTransaction.js'; | ||
import { TransactionType } from './types.js'; | ||
import type { AccessList, AccessListBytes, TxData as AllTypesTxData, TxValuesArray as AllTypesTxValuesArray, JsonTx, TxOptions } from './types.js'; | ||
import type { AccessList, AccessListBytes, TxData as AllTypesTxData, TxValuesArray as AllTypesTxValuesArray, JsonBlobTxNetworkWrapper, JsonTx, TxOptions } from './types.js'; | ||
import type { Common } from '@ethereumjs/common'; | ||
@@ -138,2 +138,10 @@ declare type TxData = AllTypesTxData[TransactionType.BlobEIP4844]; | ||
getSenderPublicKey(): Uint8Array; | ||
/** | ||
* Returns the EIP 4844 transaction network wrapper in JSON format similar to toJSON, including | ||
* blobs, commitments, and proofs fields | ||
* @param serialized a buffer representing a serialized BlobTransactionNetworkWrapper | ||
* @param opts any TxOptions defined | ||
* @returns JsonBlobTxNetworkWrapper with blobs, KZG commitments, and KZG proofs fields | ||
*/ | ||
static networkWrapperToJson(serialized: Uint8Array, opts?: TxOptions): JsonBlobTxNetworkWrapper; | ||
toJSON(): JsonTx; | ||
@@ -140,0 +148,0 @@ addSignature(v: bigint, r: Uint8Array | bigint, s: Uint8Array | bigint, convertV?: boolean): BlobEIP4844Transaction; |
@@ -57,6 +57,6 @@ "use strict"; | ||
this.chainId = this.common.chainId(); | ||
if (this.common.isActivatedEIP(1559) === false) { | ||
if (!this.common.isActivatedEIP(1559)) { | ||
throw new Error('EIP-1559 not enabled on Common'); | ||
} | ||
if (this.common.isActivatedEIP(4844) === false) { | ||
if (!this.common.isActivatedEIP(4844)) { | ||
throw new Error('EIP-4844 not enabled on Common'); | ||
@@ -71,4 +71,4 @@ } | ||
util_js_1.AccessLists.verifyAccessList(this.accessList); | ||
this.maxFeePerGas = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(maxFeePerGas === '' ? '0x' : maxFeePerGas)); | ||
this.maxPriorityFeePerGas = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(maxPriorityFeePerGas === '' ? '0x' : maxPriorityFeePerGas)); | ||
this.maxFeePerGas = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(maxFeePerGas)); | ||
this.maxPriorityFeePerGas = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(maxPriorityFeePerGas)); | ||
this._validateCannotExceedMaxInteger({ | ||
@@ -382,2 +382,26 @@ maxFeePerGas: this.maxFeePerGas, | ||
} | ||
/** | ||
* Returns the EIP 4844 transaction network wrapper in JSON format similar to toJSON, including | ||
* blobs, commitments, and proofs fields | ||
* @param serialized a buffer representing a serialized BlobTransactionNetworkWrapper | ||
* @param opts any TxOptions defined | ||
* @returns JsonBlobTxNetworkWrapper with blobs, KZG commitments, and KZG proofs fields | ||
*/ | ||
static networkWrapperToJson(serialized, opts) { | ||
const tx = this.fromSerializedBlobTxNetworkWrapper(serialized, opts); | ||
const accessListJSON = util_js_1.AccessLists.getAccessListJSON(tx.accessList); | ||
const baseJson = tx.toJSON(); | ||
return { | ||
...baseJson, | ||
chainId: (0, util_1.bigIntToHex)(tx.chainId), | ||
maxPriorityFeePerGas: (0, util_1.bigIntToHex)(tx.maxPriorityFeePerGas), | ||
maxFeePerGas: (0, util_1.bigIntToHex)(tx.maxFeePerGas), | ||
accessList: accessListJSON, | ||
maxFeePerBlobGas: (0, util_1.bigIntToHex)(tx.maxFeePerBlobGas), | ||
blobVersionedHashes: tx.blobVersionedHashes.map((hash) => (0, util_1.bytesToHex)(hash)), | ||
blobs: tx.blobs.map((bytes) => (0, util_1.bytesToHex)(bytes)), | ||
kzgCommitments: tx.kzgCommitments.map((bytes) => (0, util_1.bytesToHex)(bytes)), | ||
kzgProofs: tx.kzgProofs.map((bytes) => (0, util_1.bytesToHex)(bytes)), | ||
}; | ||
} | ||
toJSON() { | ||
@@ -384,0 +408,0 @@ const accessListJSON = util_js_1.AccessLists.getAccessListJSON(this.accessList); |
export { FeeMarketEIP1559Transaction } from './eip1559Transaction.js'; | ||
export { AccessListEIP2930Transaction } from './eip2930Transaction.js'; | ||
export { BlobEIP4844Transaction } from './eip4844Transaction.js'; | ||
export { EOACodeEIP7702Transaction } from './eip7702Transaction.js'; | ||
export { LegacyTransaction } from './legacyTransaction.js'; | ||
@@ -5,0 +6,0 @@ export { TransactionFactory } from './transactionFactory.js'; |
@@ -17,3 +17,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TransactionFactory = exports.LegacyTransaction = exports.BlobEIP4844Transaction = exports.AccessListEIP2930Transaction = exports.FeeMarketEIP1559Transaction = void 0; | ||
exports.TransactionFactory = exports.LegacyTransaction = exports.EOACodeEIP7702Transaction = exports.BlobEIP4844Transaction = exports.AccessListEIP2930Transaction = exports.FeeMarketEIP1559Transaction = void 0; | ||
var eip1559Transaction_js_1 = require("./eip1559Transaction.js"); | ||
@@ -25,2 +25,4 @@ Object.defineProperty(exports, "FeeMarketEIP1559Transaction", { enumerable: true, get: function () { return eip1559Transaction_js_1.FeeMarketEIP1559Transaction; } }); | ||
Object.defineProperty(exports, "BlobEIP4844Transaction", { enumerable: true, get: function () { return eip4844Transaction_js_1.BlobEIP4844Transaction; } }); | ||
var eip7702Transaction_js_1 = require("./eip7702Transaction.js"); | ||
Object.defineProperty(exports, "EOACodeEIP7702Transaction", { enumerable: true, get: function () { return eip7702Transaction_js_1.EOACodeEIP7702Transaction; } }); | ||
var legacyTransaction_js_1 = require("./legacyTransaction.js"); | ||
@@ -27,0 +29,0 @@ Object.defineProperty(exports, "LegacyTransaction", { enumerable: true, get: function () { return legacyTransaction_js_1.LegacyTransaction; } }); |
@@ -30,3 +30,3 @@ "use strict"; | ||
this.keccakFunction = this.common.customCrypto.keccak256 ?? keccak_js_1.keccak256; | ||
this.gasPrice = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(txData.gasPrice === '' ? '0x' : txData.gasPrice)); | ||
this.gasPrice = (0, util_1.bytesToBigInt)((0, util_1.toBytes)(txData.gasPrice)); | ||
if (this.gasPrice * this.gasLimit > util_1.MAX_INTEGER) { | ||
@@ -33,0 +33,0 @@ const msg = this._errorMsg('gas limit * gasPrice cannot exceed MAX_INTEGER (2^256-1)'); |
import { FeeMarketEIP1559Transaction } from './eip1559Transaction.js'; | ||
import { AccessListEIP2930Transaction } from './eip2930Transaction.js'; | ||
import { BlobEIP4844Transaction } from './eip4844Transaction.js'; | ||
import { EOACodeEIP7702Transaction } from './eip7702Transaction.js'; | ||
import { LegacyTransaction } from './legacyTransaction.js'; | ||
@@ -33,3 +34,3 @@ import { TransactionType } from './types.js'; | ||
*/ | ||
static fromBlockBodyData(data: Uint8Array | Uint8Array[], txOptions?: TxOptions): FeeMarketEIP1559Transaction | LegacyTransaction | AccessListEIP2930Transaction | BlobEIP4844Transaction; | ||
static fromBlockBodyData(data: Uint8Array | Uint8Array[], txOptions?: TxOptions): FeeMarketEIP1559Transaction | LegacyTransaction | AccessListEIP2930Transaction | BlobEIP4844Transaction | EOACodeEIP7702Transaction; | ||
/** | ||
@@ -42,3 +43,3 @@ * Method to retrieve a transaction from the provider | ||
*/ | ||
static fromJsonRpcProvider(provider: string | EthersProvider, txHash: string, txOptions?: TxOptions): Promise<FeeMarketEIP1559Transaction | LegacyTransaction | AccessListEIP2930Transaction | BlobEIP4844Transaction>; | ||
static fromJsonRpcProvider(provider: string | EthersProvider, txHash: string, txOptions?: TxOptions): Promise<FeeMarketEIP1559Transaction | LegacyTransaction | AccessListEIP2930Transaction | BlobEIP4844Transaction | EOACodeEIP7702Transaction>; | ||
/** | ||
@@ -45,0 +46,0 @@ * Method to decode data retrieved from RPC, such as `eth_getTransactionByHash` |
@@ -8,2 +8,3 @@ "use strict"; | ||
const eip4844Transaction_js_1 = require("./eip4844Transaction.js"); | ||
const eip7702Transaction_js_1 = require("./eip7702Transaction.js"); | ||
const fromRpc_js_1 = require("./fromRpc.js"); | ||
@@ -39,2 +40,5 @@ const legacyTransaction_js_1 = require("./legacyTransaction.js"); | ||
} | ||
else if ((0, types_js_1.isEOACodeEIP7702TxData)(txData)) { | ||
return eip7702Transaction_js_1.EOACodeEIP7702Transaction.fromTxData(txData, txOptions); | ||
} | ||
else { | ||
@@ -61,2 +65,4 @@ throw new Error(`Tx instantiation with type ${txData?.type} not supported`); | ||
return eip4844Transaction_js_1.BlobEIP4844Transaction.fromSerializedTx(data, txOptions); | ||
case types_js_1.TransactionType.EOACodeEIP7702: | ||
return eip7702Transaction_js_1.EOACodeEIP7702Transaction.fromSerializedTx(data, txOptions); | ||
default: | ||
@@ -63,0 +69,0 @@ throw new Error(`TypedTransaction with ID ${data[0]} unknown`); |
import type { FeeMarketEIP1559Transaction } from './eip1559Transaction.js'; | ||
import type { AccessListEIP2930Transaction } from './eip2930Transaction.js'; | ||
import type { BlobEIP4844Transaction } from './eip4844Transaction.js'; | ||
import type { EOACodeEIP7702Transaction } from './eip7702Transaction.js'; | ||
import type { LegacyTransaction } from './legacyTransaction.js'; | ||
import type { AccessList, AccessListBytes, Common, Hardfork } from '@ethereumjs/common'; | ||
import type { Address, AddressLike, BigIntLike, BytesLike } from '@ethereumjs/util'; | ||
export type { AccessList, AccessListBytes, AccessListBytesItem, AccessListItem, } from '@ethereumjs/common'; | ||
import type { AccessList, AccessListBytes, AuthorizationList, AuthorizationListBytes, Common, Hardfork } from '@ethereumjs/common'; | ||
import type { Address, AddressLike, BigIntLike, BytesLike, PrefixedHexString } from '@ethereumjs/util'; | ||
export type { AccessList, AccessListBytes, AccessListBytesItem, AccessListItem, AuthorizationList, AuthorizationListBytes, AuthorizationListBytesItem, AuthorizationListItem, } from '@ethereumjs/common'; | ||
/** | ||
@@ -32,3 +33,8 @@ * Can be used in conjunction with {@link Transaction[TransactionType].supports} | ||
*/ | ||
EIP2930AccessLists = 2930 | ||
EIP2930AccessLists = 2930, | ||
/** | ||
* Tx supports setting EOA code | ||
* See [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) | ||
*/ | ||
EIP7702EOACode = 7702 | ||
} | ||
@@ -70,2 +76,4 @@ /** | ||
export declare function isAccessList(input: AccessListBytes | AccessList): input is AccessList; | ||
export declare function isAuthorizationListBytes(input: AuthorizationListBytes | AuthorizationList): input is AuthorizationListBytes; | ||
export declare function isAuthorizationList(input: AuthorizationListBytes | AuthorizationList): input is AuthorizationList; | ||
export interface TransactionCache { | ||
@@ -86,3 +94,4 @@ hash?: Uint8Array; | ||
FeeMarketEIP1559 = 2, | ||
BlobEIP4844 = 3 | ||
BlobEIP4844 = 3, | ||
EOACodeEIP7702 = 4 | ||
} | ||
@@ -94,2 +103,3 @@ export interface Transaction { | ||
[TransactionType.BlobEIP4844]: BlobEIP4844Transaction; | ||
[TransactionType.EOACodeEIP7702]: EOACodeEIP7702Transaction; | ||
} | ||
@@ -101,2 +111,3 @@ export declare type TypedTransaction = Transaction[TransactionType]; | ||
export declare function isBlobEIP4844Tx(tx: TypedTransaction): tx is BlobEIP4844Transaction; | ||
export declare function isEOACodeEIP7702Tx(tx: TypedTransaction): tx is EOACodeEIP7702Transaction; | ||
export interface TransactionInterface<T extends TransactionType = TransactionType> { | ||
@@ -158,2 +169,5 @@ readonly common: Common; | ||
} | ||
export interface EIP7702CompatibleTx<T extends TransactionType = TransactionType> extends EIP1559CompatibleTx<T> { | ||
readonly authorizationList: AuthorizationListBytes; | ||
} | ||
export interface TxData { | ||
@@ -164,2 +178,3 @@ [TransactionType.Legacy]: LegacyTxData; | ||
[TransactionType.BlobEIP4844]: BlobEIP4844TxData; | ||
[TransactionType.EOACodeEIP7702]: EOACodeEIP7702TxData; | ||
} | ||
@@ -171,2 +186,3 @@ export declare type TypedTxData = TxData[TransactionType]; | ||
export declare function isBlobEIP4844TxData(txData: TypedTxData): txData is BlobEIP4844TxData; | ||
export declare function isEOACodeEIP7702TxData(txData: TypedTxData): txData is EOACodeEIP7702TxData; | ||
/** | ||
@@ -191,3 +207,3 @@ * Legacy {@link Transaction} Data | ||
*/ | ||
to?: AddressLike; | ||
to?: AddressLike | ''; | ||
/** | ||
@@ -200,3 +216,3 @@ * The amount of Ether sent. | ||
*/ | ||
data?: BytesLike; | ||
data?: BytesLike | ''; | ||
/** | ||
@@ -279,2 +295,8 @@ * EC recovery ID. | ||
} | ||
/** | ||
* {@link EOACodeEIP7702Tx} data. | ||
*/ | ||
export interface EOACodeEIP7702TxData extends FeeMarketEIP1559TxData { | ||
authorizationList?: AuthorizationListBytes | AuthorizationList | never; | ||
} | ||
export interface TxValuesArray { | ||
@@ -285,2 +307,3 @@ [TransactionType.Legacy]: LegacyTxValuesArray; | ||
[TransactionType.BlobEIP4844]: BlobEIP4844TxValuesArray; | ||
[TransactionType.EOACodeEIP7702]: EOACodeEIP7702TxValuesArray; | ||
} | ||
@@ -325,2 +348,20 @@ /** | ||
/** | ||
* Bytes values array for a {@link EOACodeEIP7702Transaction} | ||
*/ | ||
declare type EOACodeEIP7702TxValuesArray = [ | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
AccessListBytes, | ||
AuthorizationListBytes, | ||
Uint8Array?, | ||
Uint8Array?, | ||
Uint8Array? | ||
]; | ||
/** | ||
* Bytes values array for a {@link BlobEIP4844Transaction} | ||
@@ -363,19 +404,25 @@ */ | ||
export interface JsonTx { | ||
nonce?: string; | ||
gasPrice?: string; | ||
gasLimit?: string; | ||
to?: string; | ||
data?: string; | ||
v?: string; | ||
r?: string; | ||
s?: string; | ||
value?: string; | ||
chainId?: string; | ||
nonce?: PrefixedHexString; | ||
gasPrice?: PrefixedHexString; | ||
gasLimit?: PrefixedHexString; | ||
to?: PrefixedHexString; | ||
data?: PrefixedHexString; | ||
v?: PrefixedHexString; | ||
r?: PrefixedHexString; | ||
s?: PrefixedHexString; | ||
value?: PrefixedHexString; | ||
chainId?: PrefixedHexString; | ||
accessList?: JsonAccessListItem[]; | ||
type?: string; | ||
maxPriorityFeePerGas?: string; | ||
maxFeePerGas?: string; | ||
maxFeePerBlobGas?: string; | ||
blobVersionedHashes?: string[]; | ||
authorizationList?: AuthorizationList; | ||
type?: PrefixedHexString; | ||
maxPriorityFeePerGas?: PrefixedHexString; | ||
maxFeePerGas?: PrefixedHexString; | ||
maxFeePerBlobGas?: PrefixedHexString; | ||
blobVersionedHashes?: PrefixedHexString[]; | ||
} | ||
export declare type JsonBlobTxNetworkWrapper = JsonTx & { | ||
blobs: PrefixedHexString[]; | ||
kzgCommitments: PrefixedHexString[]; | ||
kzgProofs: PrefixedHexString[]; | ||
}; | ||
export interface JsonRpcTx { | ||
@@ -382,0 +429,0 @@ blockHash: string | null; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isBlobEIP4844TxData = exports.isFeeMarketEIP1559TxData = exports.isAccessListEIP2930TxData = exports.isLegacyTxData = exports.isBlobEIP4844Tx = exports.isFeeMarketEIP1559Tx = exports.isAccessListEIP2930Tx = exports.isLegacyTx = exports.TransactionType = exports.isAccessList = exports.isAccessListBytes = exports.Capability = void 0; | ||
exports.isEOACodeEIP7702TxData = exports.isBlobEIP4844TxData = exports.isFeeMarketEIP1559TxData = exports.isAccessListEIP2930TxData = exports.isLegacyTxData = exports.isEOACodeEIP7702Tx = exports.isBlobEIP4844Tx = exports.isFeeMarketEIP1559Tx = exports.isAccessListEIP2930Tx = exports.isLegacyTx = exports.TransactionType = exports.isAuthorizationList = exports.isAuthorizationListBytes = exports.isAccessList = exports.isAccessListBytes = exports.Capability = void 0; | ||
const util_1 = require("@ethereumjs/util"); | ||
@@ -31,2 +31,7 @@ /** | ||
Capability[Capability["EIP2930AccessLists"] = 2930] = "EIP2930AccessLists"; | ||
/** | ||
* Tx supports setting EOA code | ||
* See [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) | ||
*/ | ||
Capability[Capability["EIP7702EOACode"] = 7702] = "EIP7702EOACode"; | ||
})(Capability = exports.Capability || (exports.Capability = {})); | ||
@@ -48,2 +53,17 @@ function isAccessListBytes(input) { | ||
exports.isAccessList = isAccessList; | ||
function isAuthorizationListBytes(input) { | ||
if (input.length === 0) { | ||
return true; | ||
} | ||
const firstItem = input[0]; | ||
if (Array.isArray(firstItem)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
exports.isAuthorizationListBytes = isAuthorizationListBytes; | ||
function isAuthorizationList(input) { | ||
return !isAuthorizationListBytes(input); // This is exactly the same method, except the output is negated. | ||
} | ||
exports.isAuthorizationList = isAuthorizationList; | ||
/** | ||
@@ -58,2 +78,3 @@ * Encompassing type for all transaction types. | ||
TransactionType[TransactionType["BlobEIP4844"] = 3] = "BlobEIP4844"; | ||
TransactionType[TransactionType["EOACodeEIP7702"] = 4] = "EOACodeEIP7702"; | ||
})(TransactionType = exports.TransactionType || (exports.TransactionType = {})); | ||
@@ -76,2 +97,6 @@ function isLegacyTx(tx) { | ||
exports.isBlobEIP4844Tx = isBlobEIP4844Tx; | ||
function isEOACodeEIP7702Tx(tx) { | ||
return tx.type === TransactionType.EOACodeEIP7702; | ||
} | ||
exports.isEOACodeEIP7702Tx = isEOACodeEIP7702Tx; | ||
function isLegacyTxData(txData) { | ||
@@ -97,2 +122,7 @@ const txType = Number((0, util_1.bytesToBigInt)((0, util_1.toBytes)(txData.type))); | ||
exports.isBlobEIP4844TxData = isBlobEIP4844TxData; | ||
function isEOACodeEIP7702TxData(txData) { | ||
const txType = Number((0, util_1.bytesToBigInt)((0, util_1.toBytes)(txData.type))); | ||
return txType === TransactionType.EOACodeEIP7702; | ||
} | ||
exports.isEOACodeEIP7702TxData = isEOACodeEIP7702TxData; | ||
//# sourceMappingURL=types.js.map |
@@ -1,2 +0,2 @@ | ||
import type { AccessList, AccessListBytes, TransactionType } from './types.js'; | ||
import type { AccessList, AccessListBytes, AuthorizationList, AuthorizationListBytes, TransactionType } from './types.js'; | ||
import type { Common } from '@ethereumjs/common'; | ||
@@ -13,3 +13,11 @@ export declare function checkMaxInitCodeSize(common: Common, length: number): void; | ||
} | ||
export declare class AuthorizationLists { | ||
static getAuthorizationListData(authorizationList: AuthorizationListBytes | AuthorizationList): { | ||
AuthorizationListJSON: AuthorizationList; | ||
authorizationList: AuthorizationListBytes; | ||
}; | ||
static verifyAuthorizationList(authorizationList: AuthorizationListBytes): void; | ||
static getDataFeeEIP7702(authorityList: AuthorizationListBytes, common: Common): number; | ||
} | ||
export declare function txTypeBytes(txType: TransactionType): Uint8Array; | ||
//# sourceMappingURL=util.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.txTypeBytes = exports.AccessLists = exports.checkMaxInitCodeSize = void 0; | ||
exports.txTypeBytes = exports.AuthorizationLists = exports.AccessLists = exports.checkMaxInitCodeSize = void 0; | ||
const util_1 = require("@ethereumjs/util"); | ||
@@ -104,6 +104,94 @@ const types_js_1 = require("./types.js"); | ||
exports.AccessLists = AccessLists; | ||
class AuthorizationLists { | ||
static getAuthorizationListData(authorizationList) { | ||
let AuthorizationListJSON; | ||
let bufferAuthorizationList; | ||
if ((0, types_js_1.isAuthorizationList)(authorizationList)) { | ||
AuthorizationListJSON = authorizationList; | ||
const newAuthorizationList = []; | ||
const jsonItems = ['chainId', 'address', 'nonce', 'yParity', 'r', 's']; | ||
for (let i = 0; i < authorizationList.length; i++) { | ||
const item = authorizationList[i]; | ||
for (const key of jsonItems) { | ||
// @ts-ignore TODO why does TsScript fail here? | ||
if (item[key] === undefined) { | ||
throw new Error(`EIP-7702 authorization list invalid: ${key} is not defined`); | ||
} | ||
} | ||
const chainId = (0, util_1.hexToBytes)(item.chainId); | ||
const addressBytes = (0, util_1.hexToBytes)(item.address); | ||
const nonceList = []; | ||
for (let j = 0; j < item.nonce.length; j++) { | ||
nonceList.push((0, util_1.hexToBytes)(item.nonce[j])); | ||
} | ||
const yParity = (0, util_1.hexToBytes)(item.yParity); | ||
const r = (0, util_1.hexToBytes)(item.r); | ||
const s = (0, util_1.hexToBytes)(item.s); | ||
newAuthorizationList.push([chainId, addressBytes, nonceList, yParity, r, s]); | ||
} | ||
bufferAuthorizationList = newAuthorizationList; | ||
} | ||
else { | ||
bufferAuthorizationList = authorizationList ?? []; | ||
// build the JSON | ||
const json = []; | ||
for (let i = 0; i < bufferAuthorizationList.length; i++) { | ||
const data = bufferAuthorizationList[i]; | ||
const chainId = (0, util_1.bytesToHex)(data[0]); | ||
const address = (0, util_1.bytesToHex)(data[1]); | ||
const nonces = data[2]; | ||
const nonceList = []; | ||
for (let j = 0; j < nonces.length; j++) { | ||
nonceList.push((0, util_1.bytesToHex)(nonces[j])); | ||
} | ||
const yParity = (0, util_1.bytesToHex)(data[3]); | ||
const r = (0, util_1.bytesToHex)(data[4]); | ||
const s = (0, util_1.bytesToHex)(data[5]); | ||
const jsonItem = { | ||
chainId, | ||
address, | ||
nonce: nonceList, | ||
yParity, | ||
r, | ||
s, | ||
}; | ||
json.push(jsonItem); | ||
} | ||
AuthorizationListJSON = json; | ||
} | ||
return { | ||
AuthorizationListJSON, | ||
authorizationList: bufferAuthorizationList, | ||
}; | ||
} | ||
static verifyAuthorizationList(authorizationList) { | ||
for (let key = 0; key < authorizationList.length; key++) { | ||
const authorizationListItem = authorizationList[key]; | ||
const address = authorizationListItem[1]; | ||
const nonceList = authorizationListItem[2]; | ||
const yParity = authorizationListItem[3]; | ||
const r = authorizationListItem[4]; | ||
const s = authorizationListItem[5]; | ||
(0, util_1.validateNoLeadingZeroes)({ yParity, r, s }); | ||
if (address.length !== 20) { | ||
throw new Error('Invalid EIP-7702 transaction: address length should be 20 bytes'); | ||
} | ||
if (nonceList.length > 1) { | ||
throw new Error('Invalid EIP-7702 transaction: nonce list should consist of at most 1 item'); | ||
} | ||
else if (nonceList.length === 1) { | ||
(0, util_1.validateNoLeadingZeroes)({ nonce: nonceList[0] }); | ||
} | ||
} | ||
} | ||
static getDataFeeEIP7702(authorityList, common) { | ||
const perAuthBaseCost = common.param('gasPrices', 'perAuthBaseCost'); | ||
return authorityList.length * Number(perAuthBaseCost); | ||
} | ||
} | ||
exports.AuthorizationLists = AuthorizationLists; | ||
function txTypeBytes(txType) { | ||
return (0, util_1.hexToBytes)('0x' + txType.toString(16).padStart(2, '0')); | ||
return (0, util_1.hexToBytes)(`0x${txType.toString(16).padStart(2, '0')}`); | ||
} | ||
exports.txTypeBytes = txTypeBytes; | ||
//# sourceMappingURL=util.js.map |
@@ -38,9 +38,9 @@ import { Chain, Common } from '@ethereumjs/common'; | ||
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 = bytesToBigInt(toBytes(nonce === '' ? '0x' : nonce)); | ||
this.gasLimit = bytesToBigInt(toBytes(gasLimit === '' ? '0x' : gasLimit)); | ||
const vB = toBytes(v); | ||
const rB = toBytes(r); | ||
const sB = toBytes(s); | ||
this.nonce = bytesToBigInt(toBytes(nonce)); | ||
this.gasLimit = bytesToBigInt(toBytes(gasLimit)); | ||
this.to = toB.length > 0 ? new Address(toB) : undefined; | ||
this.value = bytesToBigInt(toBytes(value === '' ? '0x' : value)); | ||
this.value = bytesToBigInt(toBytes(value)); | ||
this.data = toBytes(data === '' ? '0x' : data); | ||
@@ -245,3 +245,3 @@ this.v = vB.length > 0 ? bytesToBigInt(vB) : undefined; | ||
if (common.chainId() !== chainIdBigInt) { | ||
const msg = this._errorMsg(`The chain ID does not match the chain ID of Common. Got: ${chainIdBigInt}, expected: ${common.chainId}`); | ||
const msg = this._errorMsg(`The chain ID does not match the chain ID of Common. Got: ${chainIdBigInt}, expected: ${common.chainId()}`); | ||
throw new Error(msg); | ||
@@ -248,0 +248,0 @@ } |
@@ -29,3 +29,3 @@ import { RLP } from '@ethereumjs/rlp'; | ||
this.chainId = this.common.chainId(); | ||
if (this.common.isActivatedEIP(1559) === false) { | ||
if (!this.common.isActivatedEIP(1559)) { | ||
throw new Error('EIP-1559 not enabled on Common'); | ||
@@ -40,4 +40,4 @@ } | ||
AccessLists.verifyAccessList(this.accessList); | ||
this.maxFeePerGas = bytesToBigInt(toBytes(maxFeePerGas === '' ? '0x' : maxFeePerGas)); | ||
this.maxPriorityFeePerGas = bytesToBigInt(toBytes(maxPriorityFeePerGas === '' ? '0x' : maxPriorityFeePerGas)); | ||
this.maxFeePerGas = bytesToBigInt(toBytes(maxFeePerGas)); | ||
this.maxPriorityFeePerGas = bytesToBigInt(toBytes(maxPriorityFeePerGas)); | ||
this._validateCannotExceedMaxInteger({ | ||
@@ -44,0 +44,0 @@ maxFeePerGas: this.maxFeePerGas, |
@@ -62,3 +62,3 @@ import { BaseTransaction } from './baseTransaction.js'; | ||
/** | ||
* Returns a Uint8Array Array of the raw Bytess of the EIP-2930 transaction, in order. | ||
* Returns a Uint8Array Array of the raw Bytes of the EIP-2930 transaction, in order. | ||
* | ||
@@ -65,0 +65,0 @@ * Format: `[chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, |
@@ -39,3 +39,3 @@ import { RLP } from '@ethereumjs/rlp'; | ||
AccessLists.verifyAccessList(this.accessList); | ||
this.gasPrice = bytesToBigInt(toBytes(gasPrice === '' ? '0x' : gasPrice)); | ||
this.gasPrice = bytesToBigInt(toBytes(gasPrice)); | ||
this._validateCannotExceedMaxInteger({ | ||
@@ -130,3 +130,3 @@ gasPrice: this.gasPrice, | ||
/** | ||
* Returns a Uint8Array Array of the raw Bytess of the EIP-2930 transaction, in order. | ||
* Returns a Uint8Array Array of the raw Bytes of the EIP-2930 transaction, in order. | ||
* | ||
@@ -133,0 +133,0 @@ * Format: `[chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, |
import { BaseTransaction } from './baseTransaction.js'; | ||
import { TransactionType } from './types.js'; | ||
import type { AccessList, AccessListBytes, TxData as AllTypesTxData, TxValuesArray as AllTypesTxValuesArray, JsonTx, TxOptions } from './types.js'; | ||
import type { AccessList, AccessListBytes, TxData as AllTypesTxData, TxValuesArray as AllTypesTxValuesArray, JsonBlobTxNetworkWrapper, JsonTx, TxOptions } from './types.js'; | ||
import type { Common } from '@ethereumjs/common'; | ||
@@ -138,2 +138,10 @@ declare type TxData = AllTypesTxData[TransactionType.BlobEIP4844]; | ||
getSenderPublicKey(): Uint8Array; | ||
/** | ||
* Returns the EIP 4844 transaction network wrapper in JSON format similar to toJSON, including | ||
* blobs, commitments, and proofs fields | ||
* @param serialized a buffer representing a serialized BlobTransactionNetworkWrapper | ||
* @param opts any TxOptions defined | ||
* @returns JsonBlobTxNetworkWrapper with blobs, KZG commitments, and KZG proofs fields | ||
*/ | ||
static networkWrapperToJson(serialized: Uint8Array, opts?: TxOptions): JsonBlobTxNetworkWrapper; | ||
toJSON(): JsonTx; | ||
@@ -140,0 +148,0 @@ addSignature(v: bigint, r: Uint8Array | bigint, s: Uint8Array | bigint, convertV?: boolean): BlobEIP4844Transaction; |
@@ -54,6 +54,6 @@ import { RLP } from '@ethereumjs/rlp'; | ||
this.chainId = this.common.chainId(); | ||
if (this.common.isActivatedEIP(1559) === false) { | ||
if (!this.common.isActivatedEIP(1559)) { | ||
throw new Error('EIP-1559 not enabled on Common'); | ||
} | ||
if (this.common.isActivatedEIP(4844) === false) { | ||
if (!this.common.isActivatedEIP(4844)) { | ||
throw new Error('EIP-4844 not enabled on Common'); | ||
@@ -68,4 +68,4 @@ } | ||
AccessLists.verifyAccessList(this.accessList); | ||
this.maxFeePerGas = bytesToBigInt(toBytes(maxFeePerGas === '' ? '0x' : maxFeePerGas)); | ||
this.maxPriorityFeePerGas = bytesToBigInt(toBytes(maxPriorityFeePerGas === '' ? '0x' : maxPriorityFeePerGas)); | ||
this.maxFeePerGas = bytesToBigInt(toBytes(maxFeePerGas)); | ||
this.maxPriorityFeePerGas = bytesToBigInt(toBytes(maxPriorityFeePerGas)); | ||
this._validateCannotExceedMaxInteger({ | ||
@@ -379,2 +379,26 @@ maxFeePerGas: this.maxFeePerGas, | ||
} | ||
/** | ||
* Returns the EIP 4844 transaction network wrapper in JSON format similar to toJSON, including | ||
* blobs, commitments, and proofs fields | ||
* @param serialized a buffer representing a serialized BlobTransactionNetworkWrapper | ||
* @param opts any TxOptions defined | ||
* @returns JsonBlobTxNetworkWrapper with blobs, KZG commitments, and KZG proofs fields | ||
*/ | ||
static networkWrapperToJson(serialized, opts) { | ||
const tx = this.fromSerializedBlobTxNetworkWrapper(serialized, opts); | ||
const accessListJSON = AccessLists.getAccessListJSON(tx.accessList); | ||
const baseJson = tx.toJSON(); | ||
return { | ||
...baseJson, | ||
chainId: bigIntToHex(tx.chainId), | ||
maxPriorityFeePerGas: bigIntToHex(tx.maxPriorityFeePerGas), | ||
maxFeePerGas: bigIntToHex(tx.maxFeePerGas), | ||
accessList: accessListJSON, | ||
maxFeePerBlobGas: bigIntToHex(tx.maxFeePerBlobGas), | ||
blobVersionedHashes: tx.blobVersionedHashes.map((hash) => bytesToHex(hash)), | ||
blobs: tx.blobs.map((bytes) => bytesToHex(bytes)), | ||
kzgCommitments: tx.kzgCommitments.map((bytes) => bytesToHex(bytes)), | ||
kzgProofs: tx.kzgProofs.map((bytes) => bytesToHex(bytes)), | ||
}; | ||
} | ||
toJSON() { | ||
@@ -381,0 +405,0 @@ const accessListJSON = AccessLists.getAccessListJSON(this.accessList); |
export { FeeMarketEIP1559Transaction } from './eip1559Transaction.js'; | ||
export { AccessListEIP2930Transaction } from './eip2930Transaction.js'; | ||
export { BlobEIP4844Transaction } from './eip4844Transaction.js'; | ||
export { EOACodeEIP7702Transaction } from './eip7702Transaction.js'; | ||
export { LegacyTransaction } from './legacyTransaction.js'; | ||
@@ -5,0 +6,0 @@ export { TransactionFactory } from './transactionFactory.js'; |
export { FeeMarketEIP1559Transaction } from './eip1559Transaction.js'; | ||
export { AccessListEIP2930Transaction } from './eip2930Transaction.js'; | ||
export { BlobEIP4844Transaction } from './eip4844Transaction.js'; | ||
export { EOACodeEIP7702Transaction } from './eip7702Transaction.js'; | ||
export { LegacyTransaction } from './legacyTransaction.js'; | ||
@@ -5,0 +6,0 @@ export { TransactionFactory } from './transactionFactory.js'; |
@@ -27,3 +27,3 @@ import { RLP } from '@ethereumjs/rlp'; | ||
this.keccakFunction = this.common.customCrypto.keccak256 ?? keccak256; | ||
this.gasPrice = bytesToBigInt(toBytes(txData.gasPrice === '' ? '0x' : txData.gasPrice)); | ||
this.gasPrice = bytesToBigInt(toBytes(txData.gasPrice)); | ||
if (this.gasPrice * this.gasLimit > MAX_INTEGER) { | ||
@@ -30,0 +30,0 @@ const msg = this._errorMsg('gas limit * gasPrice cannot exceed MAX_INTEGER (2^256-1)'); |
import { FeeMarketEIP1559Transaction } from './eip1559Transaction.js'; | ||
import { AccessListEIP2930Transaction } from './eip2930Transaction.js'; | ||
import { BlobEIP4844Transaction } from './eip4844Transaction.js'; | ||
import { EOACodeEIP7702Transaction } from './eip7702Transaction.js'; | ||
import { LegacyTransaction } from './legacyTransaction.js'; | ||
@@ -33,3 +34,3 @@ import { TransactionType } from './types.js'; | ||
*/ | ||
static fromBlockBodyData(data: Uint8Array | Uint8Array[], txOptions?: TxOptions): FeeMarketEIP1559Transaction | LegacyTransaction | AccessListEIP2930Transaction | BlobEIP4844Transaction; | ||
static fromBlockBodyData(data: Uint8Array | Uint8Array[], txOptions?: TxOptions): FeeMarketEIP1559Transaction | LegacyTransaction | AccessListEIP2930Transaction | BlobEIP4844Transaction | EOACodeEIP7702Transaction; | ||
/** | ||
@@ -42,3 +43,3 @@ * Method to retrieve a transaction from the provider | ||
*/ | ||
static fromJsonRpcProvider(provider: string | EthersProvider, txHash: string, txOptions?: TxOptions): Promise<FeeMarketEIP1559Transaction | LegacyTransaction | AccessListEIP2930Transaction | BlobEIP4844Transaction>; | ||
static fromJsonRpcProvider(provider: string | EthersProvider, txHash: string, txOptions?: TxOptions): Promise<FeeMarketEIP1559Transaction | LegacyTransaction | AccessListEIP2930Transaction | BlobEIP4844Transaction | EOACodeEIP7702Transaction>; | ||
/** | ||
@@ -45,0 +46,0 @@ * Method to decode data retrieved from RPC, such as `eth_getTransactionByHash` |
@@ -5,5 +5,6 @@ import { fetchFromProvider, getProvider } from '@ethereumjs/util'; | ||
import { BlobEIP4844Transaction } from './eip4844Transaction.js'; | ||
import { EOACodeEIP7702Transaction } from './eip7702Transaction.js'; | ||
import { normalizeTxParams } from './fromRpc.js'; | ||
import { LegacyTransaction } from './legacyTransaction.js'; | ||
import { TransactionType, isAccessListEIP2930TxData, isBlobEIP4844TxData, isFeeMarketEIP1559TxData, isLegacyTxData, } from './types.js'; | ||
import { TransactionType, isAccessListEIP2930TxData, isBlobEIP4844TxData, isEOACodeEIP7702TxData, isFeeMarketEIP1559TxData, isLegacyTxData, } from './types.js'; | ||
export class TransactionFactory { | ||
@@ -36,2 +37,5 @@ // It is not possible to instantiate a TransactionFactory object. | ||
} | ||
else if (isEOACodeEIP7702TxData(txData)) { | ||
return EOACodeEIP7702Transaction.fromTxData(txData, txOptions); | ||
} | ||
else { | ||
@@ -58,2 +62,4 @@ throw new Error(`Tx instantiation with type ${txData?.type} not supported`); | ||
return BlobEIP4844Transaction.fromSerializedTx(data, txOptions); | ||
case TransactionType.EOACodeEIP7702: | ||
return EOACodeEIP7702Transaction.fromSerializedTx(data, txOptions); | ||
default: | ||
@@ -60,0 +66,0 @@ throw new Error(`TypedTransaction with ID ${data[0]} unknown`); |
import type { FeeMarketEIP1559Transaction } from './eip1559Transaction.js'; | ||
import type { AccessListEIP2930Transaction } from './eip2930Transaction.js'; | ||
import type { BlobEIP4844Transaction } from './eip4844Transaction.js'; | ||
import type { EOACodeEIP7702Transaction } from './eip7702Transaction.js'; | ||
import type { LegacyTransaction } from './legacyTransaction.js'; | ||
import type { AccessList, AccessListBytes, Common, Hardfork } from '@ethereumjs/common'; | ||
import type { Address, AddressLike, BigIntLike, BytesLike } from '@ethereumjs/util'; | ||
export type { AccessList, AccessListBytes, AccessListBytesItem, AccessListItem, } from '@ethereumjs/common'; | ||
import type { AccessList, AccessListBytes, AuthorizationList, AuthorizationListBytes, Common, Hardfork } from '@ethereumjs/common'; | ||
import type { Address, AddressLike, BigIntLike, BytesLike, PrefixedHexString } from '@ethereumjs/util'; | ||
export type { AccessList, AccessListBytes, AccessListBytesItem, AccessListItem, AuthorizationList, AuthorizationListBytes, AuthorizationListBytesItem, AuthorizationListItem, } from '@ethereumjs/common'; | ||
/** | ||
@@ -32,3 +33,8 @@ * Can be used in conjunction with {@link Transaction[TransactionType].supports} | ||
*/ | ||
EIP2930AccessLists = 2930 | ||
EIP2930AccessLists = 2930, | ||
/** | ||
* Tx supports setting EOA code | ||
* See [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) | ||
*/ | ||
EIP7702EOACode = 7702 | ||
} | ||
@@ -70,2 +76,4 @@ /** | ||
export declare function isAccessList(input: AccessListBytes | AccessList): input is AccessList; | ||
export declare function isAuthorizationListBytes(input: AuthorizationListBytes | AuthorizationList): input is AuthorizationListBytes; | ||
export declare function isAuthorizationList(input: AuthorizationListBytes | AuthorizationList): input is AuthorizationList; | ||
export interface TransactionCache { | ||
@@ -86,3 +94,4 @@ hash?: Uint8Array; | ||
FeeMarketEIP1559 = 2, | ||
BlobEIP4844 = 3 | ||
BlobEIP4844 = 3, | ||
EOACodeEIP7702 = 4 | ||
} | ||
@@ -94,2 +103,3 @@ export interface Transaction { | ||
[TransactionType.BlobEIP4844]: BlobEIP4844Transaction; | ||
[TransactionType.EOACodeEIP7702]: EOACodeEIP7702Transaction; | ||
} | ||
@@ -101,2 +111,3 @@ export declare type TypedTransaction = Transaction[TransactionType]; | ||
export declare function isBlobEIP4844Tx(tx: TypedTransaction): tx is BlobEIP4844Transaction; | ||
export declare function isEOACodeEIP7702Tx(tx: TypedTransaction): tx is EOACodeEIP7702Transaction; | ||
export interface TransactionInterface<T extends TransactionType = TransactionType> { | ||
@@ -158,2 +169,5 @@ readonly common: Common; | ||
} | ||
export interface EIP7702CompatibleTx<T extends TransactionType = TransactionType> extends EIP1559CompatibleTx<T> { | ||
readonly authorizationList: AuthorizationListBytes; | ||
} | ||
export interface TxData { | ||
@@ -164,2 +178,3 @@ [TransactionType.Legacy]: LegacyTxData; | ||
[TransactionType.BlobEIP4844]: BlobEIP4844TxData; | ||
[TransactionType.EOACodeEIP7702]: EOACodeEIP7702TxData; | ||
} | ||
@@ -171,2 +186,3 @@ export declare type TypedTxData = TxData[TransactionType]; | ||
export declare function isBlobEIP4844TxData(txData: TypedTxData): txData is BlobEIP4844TxData; | ||
export declare function isEOACodeEIP7702TxData(txData: TypedTxData): txData is EOACodeEIP7702TxData; | ||
/** | ||
@@ -191,3 +207,3 @@ * Legacy {@link Transaction} Data | ||
*/ | ||
to?: AddressLike; | ||
to?: AddressLike | ''; | ||
/** | ||
@@ -200,3 +216,3 @@ * The amount of Ether sent. | ||
*/ | ||
data?: BytesLike; | ||
data?: BytesLike | ''; | ||
/** | ||
@@ -279,2 +295,8 @@ * EC recovery ID. | ||
} | ||
/** | ||
* {@link EOACodeEIP7702Tx} data. | ||
*/ | ||
export interface EOACodeEIP7702TxData extends FeeMarketEIP1559TxData { | ||
authorizationList?: AuthorizationListBytes | AuthorizationList | never; | ||
} | ||
export interface TxValuesArray { | ||
@@ -285,2 +307,3 @@ [TransactionType.Legacy]: LegacyTxValuesArray; | ||
[TransactionType.BlobEIP4844]: BlobEIP4844TxValuesArray; | ||
[TransactionType.EOACodeEIP7702]: EOACodeEIP7702TxValuesArray; | ||
} | ||
@@ -325,2 +348,20 @@ /** | ||
/** | ||
* Bytes values array for a {@link EOACodeEIP7702Transaction} | ||
*/ | ||
declare type EOACodeEIP7702TxValuesArray = [ | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
AccessListBytes, | ||
AuthorizationListBytes, | ||
Uint8Array?, | ||
Uint8Array?, | ||
Uint8Array? | ||
]; | ||
/** | ||
* Bytes values array for a {@link BlobEIP4844Transaction} | ||
@@ -363,19 +404,25 @@ */ | ||
export interface JsonTx { | ||
nonce?: string; | ||
gasPrice?: string; | ||
gasLimit?: string; | ||
to?: string; | ||
data?: string; | ||
v?: string; | ||
r?: string; | ||
s?: string; | ||
value?: string; | ||
chainId?: string; | ||
nonce?: PrefixedHexString; | ||
gasPrice?: PrefixedHexString; | ||
gasLimit?: PrefixedHexString; | ||
to?: PrefixedHexString; | ||
data?: PrefixedHexString; | ||
v?: PrefixedHexString; | ||
r?: PrefixedHexString; | ||
s?: PrefixedHexString; | ||
value?: PrefixedHexString; | ||
chainId?: PrefixedHexString; | ||
accessList?: JsonAccessListItem[]; | ||
type?: string; | ||
maxPriorityFeePerGas?: string; | ||
maxFeePerGas?: string; | ||
maxFeePerBlobGas?: string; | ||
blobVersionedHashes?: string[]; | ||
authorizationList?: AuthorizationList; | ||
type?: PrefixedHexString; | ||
maxPriorityFeePerGas?: PrefixedHexString; | ||
maxFeePerGas?: PrefixedHexString; | ||
maxFeePerBlobGas?: PrefixedHexString; | ||
blobVersionedHashes?: PrefixedHexString[]; | ||
} | ||
export declare type JsonBlobTxNetworkWrapper = JsonTx & { | ||
blobs: PrefixedHexString[]; | ||
kzgCommitments: PrefixedHexString[]; | ||
kzgProofs: PrefixedHexString[]; | ||
}; | ||
export interface JsonRpcTx { | ||
@@ -382,0 +429,0 @@ blockHash: string | null; |
@@ -28,2 +28,7 @@ import { bytesToBigInt, toBytes } from '@ethereumjs/util'; | ||
Capability[Capability["EIP2930AccessLists"] = 2930] = "EIP2930AccessLists"; | ||
/** | ||
* Tx supports setting EOA code | ||
* See [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) | ||
*/ | ||
Capability[Capability["EIP7702EOACode"] = 7702] = "EIP7702EOACode"; | ||
})(Capability || (Capability = {})); | ||
@@ -43,2 +48,15 @@ export function isAccessListBytes(input) { | ||
} | ||
export function isAuthorizationListBytes(input) { | ||
if (input.length === 0) { | ||
return true; | ||
} | ||
const firstItem = input[0]; | ||
if (Array.isArray(firstItem)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
export function isAuthorizationList(input) { | ||
return !isAuthorizationListBytes(input); // This is exactly the same method, except the output is negated. | ||
} | ||
/** | ||
@@ -53,2 +71,3 @@ * Encompassing type for all transaction types. | ||
TransactionType[TransactionType["BlobEIP4844"] = 3] = "BlobEIP4844"; | ||
TransactionType[TransactionType["EOACodeEIP7702"] = 4] = "EOACodeEIP7702"; | ||
})(TransactionType || (TransactionType = {})); | ||
@@ -67,2 +86,5 @@ export function isLegacyTx(tx) { | ||
} | ||
export function isEOACodeEIP7702Tx(tx) { | ||
return tx.type === TransactionType.EOACodeEIP7702; | ||
} | ||
export function isLegacyTxData(txData) { | ||
@@ -84,2 +106,6 @@ const txType = Number(bytesToBigInt(toBytes(txData.type))); | ||
} | ||
export function isEOACodeEIP7702TxData(txData) { | ||
const txType = Number(bytesToBigInt(toBytes(txData.type))); | ||
return txType === TransactionType.EOACodeEIP7702; | ||
} | ||
//# sourceMappingURL=types.js.map |
@@ -1,2 +0,2 @@ | ||
import type { AccessList, AccessListBytes, TransactionType } from './types.js'; | ||
import type { AccessList, AccessListBytes, AuthorizationList, AuthorizationListBytes, TransactionType } from './types.js'; | ||
import type { Common } from '@ethereumjs/common'; | ||
@@ -13,3 +13,11 @@ export declare function checkMaxInitCodeSize(common: Common, length: number): void; | ||
} | ||
export declare class AuthorizationLists { | ||
static getAuthorizationListData(authorizationList: AuthorizationListBytes | AuthorizationList): { | ||
AuthorizationListJSON: AuthorizationList; | ||
authorizationList: AuthorizationListBytes; | ||
}; | ||
static verifyAuthorizationList(authorizationList: AuthorizationListBytes): void; | ||
static getDataFeeEIP7702(authorityList: AuthorizationListBytes, common: Common): number; | ||
} | ||
export declare function txTypeBytes(txType: TransactionType): Uint8Array; | ||
//# sourceMappingURL=util.d.ts.map |
@@ -1,3 +0,3 @@ | ||
import { bytesToHex, hexToBytes, setLengthLeft } from '@ethereumjs/util'; | ||
import { isAccessList } from './types.js'; | ||
import { bytesToHex, hexToBytes, setLengthLeft, validateNoLeadingZeroes, } from '@ethereumjs/util'; | ||
import { isAccessList, isAuthorizationList } from './types.js'; | ||
export function checkMaxInitCodeSize(common, length) { | ||
@@ -99,5 +99,92 @@ const maxInitCodeSize = common.param('vm', 'maxInitCodeSize'); | ||
} | ||
export class AuthorizationLists { | ||
static getAuthorizationListData(authorizationList) { | ||
let AuthorizationListJSON; | ||
let bufferAuthorizationList; | ||
if (isAuthorizationList(authorizationList)) { | ||
AuthorizationListJSON = authorizationList; | ||
const newAuthorizationList = []; | ||
const jsonItems = ['chainId', 'address', 'nonce', 'yParity', 'r', 's']; | ||
for (let i = 0; i < authorizationList.length; i++) { | ||
const item = authorizationList[i]; | ||
for (const key of jsonItems) { | ||
// @ts-ignore TODO why does TsScript fail here? | ||
if (item[key] === undefined) { | ||
throw new Error(`EIP-7702 authorization list invalid: ${key} is not defined`); | ||
} | ||
} | ||
const chainId = hexToBytes(item.chainId); | ||
const addressBytes = hexToBytes(item.address); | ||
const nonceList = []; | ||
for (let j = 0; j < item.nonce.length; j++) { | ||
nonceList.push(hexToBytes(item.nonce[j])); | ||
} | ||
const yParity = hexToBytes(item.yParity); | ||
const r = hexToBytes(item.r); | ||
const s = hexToBytes(item.s); | ||
newAuthorizationList.push([chainId, addressBytes, nonceList, yParity, r, s]); | ||
} | ||
bufferAuthorizationList = newAuthorizationList; | ||
} | ||
else { | ||
bufferAuthorizationList = authorizationList ?? []; | ||
// build the JSON | ||
const json = []; | ||
for (let i = 0; i < bufferAuthorizationList.length; i++) { | ||
const data = bufferAuthorizationList[i]; | ||
const chainId = bytesToHex(data[0]); | ||
const address = bytesToHex(data[1]); | ||
const nonces = data[2]; | ||
const nonceList = []; | ||
for (let j = 0; j < nonces.length; j++) { | ||
nonceList.push(bytesToHex(nonces[j])); | ||
} | ||
const yParity = bytesToHex(data[3]); | ||
const r = bytesToHex(data[4]); | ||
const s = bytesToHex(data[5]); | ||
const jsonItem = { | ||
chainId, | ||
address, | ||
nonce: nonceList, | ||
yParity, | ||
r, | ||
s, | ||
}; | ||
json.push(jsonItem); | ||
} | ||
AuthorizationListJSON = json; | ||
} | ||
return { | ||
AuthorizationListJSON, | ||
authorizationList: bufferAuthorizationList, | ||
}; | ||
} | ||
static verifyAuthorizationList(authorizationList) { | ||
for (let key = 0; key < authorizationList.length; key++) { | ||
const authorizationListItem = authorizationList[key]; | ||
const address = authorizationListItem[1]; | ||
const nonceList = authorizationListItem[2]; | ||
const yParity = authorizationListItem[3]; | ||
const r = authorizationListItem[4]; | ||
const s = authorizationListItem[5]; | ||
validateNoLeadingZeroes({ yParity, r, s }); | ||
if (address.length !== 20) { | ||
throw new Error('Invalid EIP-7702 transaction: address length should be 20 bytes'); | ||
} | ||
if (nonceList.length > 1) { | ||
throw new Error('Invalid EIP-7702 transaction: nonce list should consist of at most 1 item'); | ||
} | ||
else if (nonceList.length === 1) { | ||
validateNoLeadingZeroes({ nonce: nonceList[0] }); | ||
} | ||
} | ||
} | ||
static getDataFeeEIP7702(authorityList, common) { | ||
const perAuthBaseCost = common.param('gasPrices', 'perAuthBaseCost'); | ||
return authorityList.length * Number(perAuthBaseCost); | ||
} | ||
} | ||
export function txTypeBytes(txType) { | ||
return hexToBytes('0x' + txType.toString(16).padStart(2, '0')); | ||
return hexToBytes(`0x${txType.toString(16).padStart(2, '0')}`); | ||
} | ||
//# sourceMappingURL=util.js.map |
{ | ||
"name": "@ethereumjs/tx", | ||
"version": "5.3.0", | ||
"version": "5.4.0", | ||
"description": "Implementation of the various Ethereum Transaction Types", | ||
@@ -23,7 +23,3 @@ "keywords": [ | ||
"email": "alex@rtfs.hu", | ||
"url": "https://github.com/axic", | ||
"additions": 27562, | ||
"contributions": 22, | ||
"deletions": 42613, | ||
"hireable": true | ||
"url": "https://github.com/axic" | ||
} | ||
@@ -55,4 +51,4 @@ ], | ||
"prepublishOnly": "../../config/cli/prepublish.sh", | ||
"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": "npm run test:node", | ||
"test:browser": "npx vitest run --config=./vitest.config.browser.mts", | ||
"test:node": "npx vitest run", | ||
@@ -62,6 +58,6 @@ "tsc": "../../config/cli/ts-compile.sh" | ||
"dependencies": { | ||
"@ethereumjs/common": "^4.3.0", | ||
"@ethereumjs/common": "^4.4.0", | ||
"@ethereumjs/rlp": "^5.0.2", | ||
"@ethereumjs/util": "^9.0.3", | ||
"ethereum-cryptography": "^2.1.3" | ||
"@ethereumjs/util": "^9.1.0", | ||
"ethereum-cryptography": "^2.2.1" | ||
}, | ||
@@ -71,3 +67,3 @@ "devDependencies": { | ||
"@types/node-dir": "^0.0.34", | ||
"kzg-wasm": "^0.3.1", | ||
"kzg-wasm": "^0.4.0", | ||
"minimist": "^1.2.0", | ||
@@ -74,0 +70,0 @@ "node-dir": "^0.1.16" |
@@ -105,2 +105,3 @@ # @ethereumjs/tx | ||
- `FeeMarketEIP1559Transaction` ([EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), gas fee market) | ||
- `EOACodeEIP7702Transaction` (experimental) ([EIP-7702](https://eips.ethereum.org/EIPS/eip-7702), EOA code delegation) | ||
- `AccessListEIP2930Transaction` ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930), optional access lists) | ||
@@ -211,2 +212,45 @@ - `BlobEIP4844Transaction` ([EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), blob transactions) | ||
#### EOA Code Transaction (EIP-7702) (outdated) | ||
- Class: `EOACodeEIP7702Transaction` | ||
- Activation: `prague` (or per EIP setting) | ||
- Type: `4` | ||
This library suppports a non-final version of [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) starting with `v5.4.0`. This tx type allows to run code in the context of an EOA and therefore extend the functionality which can be "reached" from respectively integrated into the scope of an otherwise limited EOA account. | ||
The following is a simple example how to use an `EOACodeEIP7702Transaction` with one autorization list item: | ||
```ts | ||
// ./examples/EOACodeTx.ts | ||
import { Chain, Common, Hardfork } from '@ethereumjs/common' | ||
import { EOACodeEIP7702Transaction } from '@ethereumjs/tx' | ||
import type { PrefixedHexString } from '@ethereumjs/util' | ||
const ones32 = `0x${'01'.repeat(32)}` as PrefixedHexString | ||
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Cancun, eips: [7702] }) | ||
const tx = EOACodeEIP7702Transaction.fromTxData( | ||
{ | ||
authorizationList: [ | ||
{ | ||
chainId: '0x1', | ||
address: `0x${'20'.repeat(20)}`, | ||
nonce: ['0x1'], | ||
yParity: '0x1', | ||
r: ones32, | ||
s: ones32, | ||
}, | ||
], | ||
}, | ||
{ common } | ||
) | ||
console.log( | ||
`EIP-7702 EOA code tx created with ${tx.authorizationList.length} authorization list item(s).` | ||
) | ||
``` | ||
Note: Things move fast with `EIP-7702` and the currently released implementation is based on [this](https://github.com/ethereum/EIPs/blob/14400434e1199c57d912082127b1d22643788d11/EIPS/eip-7702.md) commit and therefore already outdated. An up-to-date version will be released along our breaking release round planned for early September 2024. | ||
#### Access List Transactions (EIP-2930) | ||
@@ -213,0 +257,0 @@ |
@@ -86,10 +86,10 @@ import { Chain, Common } from '@ethereumjs/common' | ||
const toB = toBytes(to === '' ? '0x' : to) | ||
const vB = toBytes(v === '' ? '0x' : v) | ||
const rB = toBytes(r === '' ? '0x' : r) | ||
const sB = toBytes(s === '' ? '0x' : s) | ||
const vB = toBytes(v) | ||
const rB = toBytes(r) | ||
const sB = toBytes(s) | ||
this.nonce = bytesToBigInt(toBytes(nonce === '' ? '0x' : nonce)) | ||
this.gasLimit = bytesToBigInt(toBytes(gasLimit === '' ? '0x' : gasLimit)) | ||
this.nonce = bytesToBigInt(toBytes(nonce)) | ||
this.gasLimit = bytesToBigInt(toBytes(gasLimit)) | ||
this.to = toB.length > 0 ? new Address(toB) : undefined | ||
this.value = bytesToBigInt(toBytes(value === '' ? '0x' : value)) | ||
this.value = bytesToBigInt(toBytes(value)) | ||
this.data = toBytes(data === '' ? '0x' : data) | ||
@@ -382,3 +382,3 @@ | ||
const msg = this._errorMsg( | ||
`The chain ID does not match the chain ID of Common. Got: ${chainIdBigInt}, expected: ${common.chainId}` | ||
`The chain ID does not match the chain ID of Common. Got: ${chainIdBigInt}, expected: ${common.chainId()}` | ||
) | ||
@@ -385,0 +385,0 @@ throw new Error(msg) |
@@ -157,3 +157,3 @@ import { RLP } from '@ethereumjs/rlp' | ||
if (this.common.isActivatedEIP(1559) === false) { | ||
if (!this.common.isActivatedEIP(1559)) { | ||
throw new Error('EIP-1559 not enabled on Common') | ||
@@ -170,6 +170,4 @@ } | ||
this.maxFeePerGas = bytesToBigInt(toBytes(maxFeePerGas === '' ? '0x' : maxFeePerGas)) | ||
this.maxPriorityFeePerGas = bytesToBigInt( | ||
toBytes(maxPriorityFeePerGas === '' ? '0x' : maxPriorityFeePerGas) | ||
) | ||
this.maxFeePerGas = bytesToBigInt(toBytes(maxFeePerGas)) | ||
this.maxPriorityFeePerGas = bytesToBigInt(toBytes(maxPriorityFeePerGas)) | ||
@@ -176,0 +174,0 @@ this._validateCannotExceedMaxInteger({ |
@@ -154,3 +154,3 @@ import { RLP } from '@ethereumjs/rlp' | ||
this.gasPrice = bytesToBigInt(toBytes(gasPrice === '' ? '0x' : gasPrice)) | ||
this.gasPrice = bytesToBigInt(toBytes(gasPrice)) | ||
@@ -196,3 +196,3 @@ this._validateCannotExceedMaxInteger({ | ||
/** | ||
* Returns a Uint8Array Array of the raw Bytess of the EIP-2930 transaction, in order. | ||
* Returns a Uint8Array Array of the raw Bytes of the EIP-2930 transaction, in order. | ||
* | ||
@@ -199,0 +199,0 @@ * Format: `[chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, |
@@ -35,2 +35,3 @@ import { RLP } from '@ethereumjs/rlp' | ||
BlobEIP4844NetworkValuesArray, | ||
JsonBlobTxNetworkWrapper, | ||
JsonTx, | ||
@@ -112,7 +113,7 @@ TxOptions, | ||
if (this.common.isActivatedEIP(1559) === false) { | ||
if (!this.common.isActivatedEIP(1559)) { | ||
throw new Error('EIP-1559 not enabled on Common') | ||
} | ||
if (this.common.isActivatedEIP(4844) === false) { | ||
if (!this.common.isActivatedEIP(4844)) { | ||
throw new Error('EIP-4844 not enabled on Common') | ||
@@ -129,6 +130,4 @@ } | ||
this.maxFeePerGas = bytesToBigInt(toBytes(maxFeePerGas === '' ? '0x' : maxFeePerGas)) | ||
this.maxPriorityFeePerGas = bytesToBigInt( | ||
toBytes(maxPriorityFeePerGas === '' ? '0x' : maxPriorityFeePerGas) | ||
) | ||
this.maxFeePerGas = bytesToBigInt(toBytes(maxFeePerGas)) | ||
this.maxPriorityFeePerGas = bytesToBigInt(toBytes(maxPriorityFeePerGas)) | ||
@@ -373,3 +372,2 @@ this._validateCannotExceedMaxInteger({ | ||
*/ | ||
public static fromSerializedBlobTxNetworkWrapper( | ||
@@ -562,2 +560,32 @@ serialized: Uint8Array, | ||
/** | ||
* Returns the EIP 4844 transaction network wrapper in JSON format similar to toJSON, including | ||
* blobs, commitments, and proofs fields | ||
* @param serialized a buffer representing a serialized BlobTransactionNetworkWrapper | ||
* @param opts any TxOptions defined | ||
* @returns JsonBlobTxNetworkWrapper with blobs, KZG commitments, and KZG proofs fields | ||
*/ | ||
public static networkWrapperToJson( | ||
serialized: Uint8Array, | ||
opts?: TxOptions | ||
): JsonBlobTxNetworkWrapper { | ||
const tx = this.fromSerializedBlobTxNetworkWrapper(serialized, opts) | ||
const accessListJSON = AccessLists.getAccessListJSON(tx.accessList) | ||
const baseJson = tx.toJSON() | ||
return { | ||
...baseJson, | ||
chainId: bigIntToHex(tx.chainId), | ||
maxPriorityFeePerGas: bigIntToHex(tx.maxPriorityFeePerGas), | ||
maxFeePerGas: bigIntToHex(tx.maxFeePerGas), | ||
accessList: accessListJSON, | ||
maxFeePerBlobGas: bigIntToHex(tx.maxFeePerBlobGas), | ||
blobVersionedHashes: tx.blobVersionedHashes.map((hash) => bytesToHex(hash)), | ||
blobs: tx.blobs!.map((bytes) => bytesToHex(bytes)), | ||
kzgCommitments: tx.kzgCommitments!.map((bytes) => bytesToHex(bytes)), | ||
kzgProofs: tx.kzgProofs!.map((bytes) => bytesToHex(bytes)), | ||
} | ||
} | ||
toJSON(): JsonTx { | ||
@@ -564,0 +592,0 @@ const accessListJSON = AccessLists.getAccessListJSON(this.accessList) |
export { FeeMarketEIP1559Transaction } from './eip1559Transaction.js' | ||
export { AccessListEIP2930Transaction } from './eip2930Transaction.js' | ||
export { BlobEIP4844Transaction } from './eip4844Transaction.js' | ||
export { EOACodeEIP7702Transaction } from './eip7702Transaction.js' | ||
export { LegacyTransaction } from './legacyTransaction.js' | ||
export { TransactionFactory } from './transactionFactory.js' | ||
export * from './types.js' |
@@ -118,3 +118,3 @@ import { RLP } from '@ethereumjs/rlp' | ||
this.keccakFunction = this.common.customCrypto.keccak256 ?? keccak256 | ||
this.gasPrice = bytesToBigInt(toBytes(txData.gasPrice === '' ? '0x' : txData.gasPrice)) | ||
this.gasPrice = bytesToBigInt(toBytes(txData.gasPrice)) | ||
@@ -121,0 +121,0 @@ if (this.gasPrice * this.gasLimit > MAX_INTEGER) { |
@@ -6,2 +6,3 @@ import { fetchFromProvider, getProvider } from '@ethereumjs/util' | ||
import { BlobEIP4844Transaction } from './eip4844Transaction.js' | ||
import { EOACodeEIP7702Transaction } from './eip7702Transaction.js' | ||
import { normalizeTxParams } from './fromRpc.js' | ||
@@ -13,2 +14,3 @@ import { LegacyTransaction } from './legacyTransaction.js' | ||
isBlobEIP4844TxData, | ||
isEOACodeEIP7702TxData, | ||
isFeeMarketEIP1559TxData, | ||
@@ -47,2 +49,4 @@ isLegacyTxData, | ||
return BlobEIP4844Transaction.fromTxData(txData, txOptions) as Transaction[T] | ||
} else if (isEOACodeEIP7702TxData(txData)) { | ||
return EOACodeEIP7702Transaction.fromTxData(txData, txOptions) as Transaction[T] | ||
} else { | ||
@@ -73,2 +77,4 @@ throw new Error(`Tx instantiation with type ${(txData as TypedTxData)?.type} not supported`) | ||
return BlobEIP4844Transaction.fromSerializedTx(data, txOptions) as Transaction[T] | ||
case TransactionType.EOACodeEIP7702: | ||
return EOACodeEIP7702Transaction.fromSerializedTx(data, txOptions) as Transaction[T] | ||
default: | ||
@@ -75,0 +81,0 @@ throw new Error(`TypedTransaction with ID ${data[0]} unknown`) |
135
src/types.ts
@@ -6,5 +6,19 @@ import { bytesToBigInt, toBytes } from '@ethereumjs/util' | ||
import type { BlobEIP4844Transaction } from './eip4844Transaction.js' | ||
import type { EOACodeEIP7702Transaction } from './eip7702Transaction.js' | ||
import type { LegacyTransaction } from './legacyTransaction.js' | ||
import type { AccessList, AccessListBytes, Common, Hardfork } from '@ethereumjs/common' | ||
import type { Address, AddressLike, BigIntLike, BytesLike } from '@ethereumjs/util' | ||
import type { | ||
AccessList, | ||
AccessListBytes, | ||
AuthorizationList, | ||
AuthorizationListBytes, | ||
Common, | ||
Hardfork, | ||
} from '@ethereumjs/common' | ||
import type { | ||
Address, | ||
AddressLike, | ||
BigIntLike, | ||
BytesLike, | ||
PrefixedHexString, | ||
} from '@ethereumjs/util' | ||
export type { | ||
@@ -15,2 +29,6 @@ AccessList, | ||
AccessListItem, | ||
AuthorizationList, | ||
AuthorizationListBytes, | ||
AuthorizationListBytesItem, | ||
AuthorizationListItem, | ||
} from '@ethereumjs/common' | ||
@@ -46,2 +64,8 @@ | ||
EIP2930AccessLists = 2930, | ||
/** | ||
* Tx supports setting EOA code | ||
* See [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) | ||
*/ | ||
EIP7702EOACode = 7702, | ||
} | ||
@@ -99,2 +123,21 @@ | ||
export function isAuthorizationListBytes( | ||
input: AuthorizationListBytes | AuthorizationList | ||
): input is AuthorizationListBytes { | ||
if (input.length === 0) { | ||
return true | ||
} | ||
const firstItem = input[0] | ||
if (Array.isArray(firstItem)) { | ||
return true | ||
} | ||
return false | ||
} | ||
export function isAuthorizationList( | ||
input: AuthorizationListBytes | AuthorizationList | ||
): input is AuthorizationList { | ||
return !isAuthorizationListBytes(input) // This is exactly the same method, except the output is negated. | ||
} | ||
export interface TransactionCache { | ||
@@ -117,2 +160,3 @@ hash?: Uint8Array | ||
BlobEIP4844 = 3, | ||
EOACodeEIP7702 = 4, | ||
} | ||
@@ -125,2 +169,3 @@ | ||
[TransactionType.BlobEIP4844]: BlobEIP4844Transaction | ||
[TransactionType.EOACodeEIP7702]: EOACodeEIP7702Transaction | ||
} | ||
@@ -146,2 +191,6 @@ | ||
export function isEOACodeEIP7702Tx(tx: TypedTransaction): tx is EOACodeEIP7702Transaction { | ||
return tx.type === TransactionType.EOACodeEIP7702 | ||
} | ||
export interface TransactionInterface<T extends TransactionType = TransactionType> { | ||
@@ -213,2 +262,8 @@ readonly common: Common | ||
export interface EIP7702CompatibleTx<T extends TransactionType = TransactionType> | ||
extends EIP1559CompatibleTx<T> { | ||
// ChainID, Address, [nonce], y_parity, r, s | ||
readonly authorizationList: AuthorizationListBytes | ||
} | ||
export interface TxData { | ||
@@ -219,2 +274,3 @@ [TransactionType.Legacy]: LegacyTxData | ||
[TransactionType.BlobEIP4844]: BlobEIP4844TxData | ||
[TransactionType.EOACodeEIP7702]: EOACodeEIP7702TxData | ||
} | ||
@@ -244,2 +300,7 @@ | ||
export function isEOACodeEIP7702TxData(txData: TypedTxData): txData is EOACodeEIP7702TxData { | ||
const txType = Number(bytesToBigInt(toBytes(txData.type))) | ||
return txType === TransactionType.EOACodeEIP7702 | ||
} | ||
/** | ||
@@ -267,3 +328,3 @@ * Legacy {@link Transaction} Data | ||
*/ | ||
to?: AddressLike | ||
to?: AddressLike | '' | ||
@@ -278,3 +339,3 @@ /** | ||
*/ | ||
data?: BytesLike | ||
data?: BytesLike | '' | ||
@@ -367,2 +428,9 @@ /** | ||
/** | ||
* {@link EOACodeEIP7702Tx} data. | ||
*/ | ||
export interface EOACodeEIP7702TxData extends FeeMarketEIP1559TxData { | ||
authorizationList?: AuthorizationListBytes | AuthorizationList | never | ||
} | ||
export interface TxValuesArray { | ||
@@ -373,2 +441,3 @@ [TransactionType.Legacy]: LegacyTxValuesArray | ||
[TransactionType.BlobEIP4844]: BlobEIP4844TxValuesArray | ||
[TransactionType.EOACodeEIP7702]: EOACodeEIP7702TxValuesArray | ||
} | ||
@@ -417,2 +486,21 @@ | ||
/** | ||
* Bytes values array for a {@link EOACodeEIP7702Transaction} | ||
*/ | ||
type EOACodeEIP7702TxValuesArray = [ | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
Uint8Array, | ||
AccessListBytes, | ||
AuthorizationListBytes, | ||
Uint8Array?, | ||
Uint8Array?, | ||
Uint8Array? | ||
] | ||
/** | ||
* Bytes values array for a {@link BlobEIP4844Transaction} | ||
@@ -455,20 +543,27 @@ */ | ||
export interface JsonTx { | ||
nonce?: string | ||
gasPrice?: string | ||
gasLimit?: string | ||
to?: string | ||
data?: string | ||
v?: string | ||
r?: string | ||
s?: string | ||
value?: string | ||
chainId?: string | ||
accessList?: JsonAccessListItem[] | ||
type?: string | ||
maxPriorityFeePerGas?: string | ||
maxFeePerGas?: string | ||
maxFeePerBlobGas?: string | ||
blobVersionedHashes?: string[] | ||
nonce?: PrefixedHexString | ||
gasPrice?: PrefixedHexString | ||
gasLimit?: PrefixedHexString | ||
to?: PrefixedHexString | ||
data?: PrefixedHexString | ||
v?: PrefixedHexString | ||
r?: PrefixedHexString | ||
s?: PrefixedHexString | ||
value?: PrefixedHexString | ||
chainId?: PrefixedHexString | ||
accessList?: JsonAccessListItem[] // TODO should this not be AccessList? | ||
authorizationList?: AuthorizationList | ||
type?: PrefixedHexString | ||
maxPriorityFeePerGas?: PrefixedHexString | ||
maxFeePerGas?: PrefixedHexString | ||
maxFeePerBlobGas?: PrefixedHexString | ||
blobVersionedHashes?: PrefixedHexString[] | ||
} | ||
export type JsonBlobTxNetworkWrapper = JsonTx & { | ||
blobs: PrefixedHexString[] | ||
kzgCommitments: PrefixedHexString[] | ||
kzgProofs: PrefixedHexString[] | ||
} | ||
/* | ||
@@ -475,0 +570,0 @@ * Based on https://ethereum.org/en/developers/docs/apis/json-rpc/ |
117
src/util.ts
@@ -1,7 +0,20 @@ | ||
import { bytesToHex, hexToBytes, setLengthLeft } from '@ethereumjs/util' | ||
import { | ||
type PrefixedHexString, | ||
bytesToHex, | ||
hexToBytes, | ||
setLengthLeft, | ||
validateNoLeadingZeroes, | ||
} from '@ethereumjs/util' | ||
import { isAccessList } from './types.js' | ||
import { isAccessList, isAuthorizationList } from './types.js' | ||
import type { AccessList, AccessListBytes, AccessListItem, TransactionType } from './types.js' | ||
import type { Common } from '@ethereumjs/common' | ||
import type { | ||
AccessList, | ||
AccessListBytes, | ||
AccessListItem, | ||
AuthorizationList, | ||
AuthorizationListBytes, | ||
TransactionType, | ||
} from './types.js' | ||
import type { AuthorizationListItem, Common } from '@ethereumjs/common' | ||
@@ -45,3 +58,3 @@ export function checkMaxInitCodeSize(common: Common, length: number) { | ||
const address = bytesToHex(data[0]) | ||
const storageKeys: string[] = [] | ||
const storageKeys: PrefixedHexString[] = [] | ||
for (let item = 0; item < data[1].length; item++) { | ||
@@ -120,4 +133,96 @@ storageKeys.push(bytesToHex(data[1][item])) | ||
export class AuthorizationLists { | ||
public static getAuthorizationListData( | ||
authorizationList: AuthorizationListBytes | AuthorizationList | ||
) { | ||
let AuthorizationListJSON | ||
let bufferAuthorizationList | ||
if (isAuthorizationList(authorizationList)) { | ||
AuthorizationListJSON = authorizationList | ||
const newAuthorizationList: AuthorizationListBytes = [] | ||
const jsonItems = ['chainId', 'address', 'nonce', 'yParity', 'r', 's'] | ||
for (let i = 0; i < authorizationList.length; i++) { | ||
const item: AuthorizationListItem = authorizationList[i] | ||
for (const key of jsonItems) { | ||
// @ts-ignore TODO why does TsScript fail here? | ||
if (item[key] === undefined) { | ||
throw new Error(`EIP-7702 authorization list invalid: ${key} is not defined`) | ||
} | ||
} | ||
const chainId = hexToBytes(item.chainId) | ||
const addressBytes = hexToBytes(item.address) | ||
const nonceList = [] | ||
for (let j = 0; j < item.nonce.length; j++) { | ||
nonceList.push(hexToBytes(item.nonce[j])) | ||
} | ||
const yParity = hexToBytes(item.yParity) | ||
const r = hexToBytes(item.r) | ||
const s = hexToBytes(item.s) | ||
newAuthorizationList.push([chainId, addressBytes, nonceList, yParity, r, s]) | ||
} | ||
bufferAuthorizationList = newAuthorizationList | ||
} else { | ||
bufferAuthorizationList = authorizationList ?? [] | ||
// build the JSON | ||
const json: AuthorizationList = [] | ||
for (let i = 0; i < bufferAuthorizationList.length; i++) { | ||
const data = bufferAuthorizationList[i] | ||
const chainId = bytesToHex(data[0]) | ||
const address = bytesToHex(data[1]) | ||
const nonces = data[2] | ||
const nonceList: PrefixedHexString[] = [] | ||
for (let j = 0; j < nonces.length; j++) { | ||
nonceList.push(bytesToHex(nonces[j])) | ||
} | ||
const yParity = bytesToHex(data[3]) | ||
const r = bytesToHex(data[4]) | ||
const s = bytesToHex(data[5]) | ||
const jsonItem: AuthorizationListItem = { | ||
chainId, | ||
address, | ||
nonce: nonceList, | ||
yParity, | ||
r, | ||
s, | ||
} | ||
json.push(jsonItem) | ||
} | ||
AuthorizationListJSON = json | ||
} | ||
return { | ||
AuthorizationListJSON, | ||
authorizationList: bufferAuthorizationList, | ||
} | ||
} | ||
public static verifyAuthorizationList(authorizationList: AuthorizationListBytes) { | ||
for (let key = 0; key < authorizationList.length; key++) { | ||
const authorizationListItem = authorizationList[key] | ||
const address = authorizationListItem[1] | ||
const nonceList = authorizationListItem[2] | ||
const yParity = authorizationListItem[3] | ||
const r = authorizationListItem[4] | ||
const s = authorizationListItem[5] | ||
validateNoLeadingZeroes({ yParity, r, s }) | ||
if (address.length !== 20) { | ||
throw new Error('Invalid EIP-7702 transaction: address length should be 20 bytes') | ||
} | ||
if (nonceList.length > 1) { | ||
throw new Error('Invalid EIP-7702 transaction: nonce list should consist of at most 1 item') | ||
} else if (nonceList.length === 1) { | ||
validateNoLeadingZeroes({ nonce: nonceList[0] }) | ||
} | ||
} | ||
} | ||
public static getDataFeeEIP7702(authorityList: AuthorizationListBytes, common: Common): number { | ||
const perAuthBaseCost = common.param('gasPrices', 'perAuthBaseCost') | ||
return authorityList.length * Number(perAuthBaseCost) | ||
} | ||
} | ||
export function txTypeBytes(txType: TransactionType): Uint8Array { | ||
return hexToBytes('0x' + txType.toString(16).padStart(2, '0')) | ||
return hexToBytes(`0x${txType.toString(16).padStart(2, '0')}`) | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
784708
160
11623
530
Updated@ethereumjs/common@^4.4.0
Updated@ethereumjs/util@^9.1.0
Updatedethereum-cryptography@^2.2.1