2022-09-05 23:57:11 +03:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
exports . Transaction = void 0 ;
const index _js _1 = require ( "../address/index.js" ) ;
const index _js _2 = require ( "../crypto/index.js" ) ;
const index _js _3 = require ( "../utils/index.js" ) ;
const accesslist _js _1 = require ( "./accesslist.js" ) ;
const address _js _1 = require ( "./address.js" ) ;
const BN _0 = BigInt ( 0 ) ;
const BN _2 = BigInt ( 2 ) ;
const BN _27 = BigInt ( 27 ) ;
const BN _28 = BigInt ( 28 ) ;
const BN _35 = BigInt ( 35 ) ;
const BN _MAX _UINT = BigInt ( "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ) ;
function handleAddress ( value ) {
if ( value === "0x" ) {
return null ;
}
return ( 0 , index _js _1 . getAddress ) ( value ) ;
}
function handleAccessList ( value , param ) {
try {
return ( 0 , accesslist _js _1 . accessListify ) ( value ) ;
}
catch ( error ) {
2022-11-30 23:44:23 +03:00
( 0 , index _js _3 . assertArgument ) ( false , error . message , param , value ) ;
2022-09-05 23:57:11 +03:00
}
}
function handleNumber ( _value , param ) {
if ( _value === "0x" ) {
return 0 ;
}
2022-09-16 05:58:45 +03:00
return ( 0 , index _js _3 . getNumber ) ( _value , param ) ;
2022-09-05 23:57:11 +03:00
}
function handleUint ( _value , param ) {
if ( _value === "0x" ) {
return BN _0 ;
}
2022-09-16 05:58:45 +03:00
const value = ( 0 , index _js _3 . getBigInt ) ( _value , param ) ;
2022-11-09 10:57:02 +03:00
( 0 , index _js _3 . assertArgument ) ( value <= BN _MAX _UINT , "value exceeds uint size" , param , value ) ;
2022-09-05 23:57:11 +03:00
return value ;
}
function formatNumber ( _value , name ) {
2022-09-16 05:58:45 +03:00
const value = ( 0 , index _js _3 . getBigInt ) ( _value , "value" ) ;
2022-12-10 02:24:58 +03:00
const result = ( 0 , index _js _3 . toBeArray ) ( value ) ;
2022-11-09 10:57:02 +03:00
( 0 , index _js _3 . assertArgument ) ( result . length <= 32 , ` value too large ` , ` tx. ${ name } ` , value ) ;
2022-09-05 23:57:11 +03:00
return result ;
}
function formatAccessList ( value ) {
return ( 0 , accesslist _js _1 . accessListify ) ( value ) . map ( ( set ) => [ set . address , set . storageKeys ] ) ;
}
function _parseLegacy ( data ) {
const fields = ( 0 , index _js _3 . decodeRlp ) ( data ) ;
2022-11-09 10:57:02 +03:00
( 0 , index _js _3 . assertArgument ) ( Array . isArray ( fields ) && ( fields . length === 9 || fields . length === 6 ) , "invalid field count for legacy transaction" , "data" , data ) ;
2022-09-05 23:57:11 +03:00
const tx = {
type : 0 ,
nonce : handleNumber ( fields [ 0 ] , "nonce" ) ,
gasPrice : handleUint ( fields [ 1 ] , "gasPrice" ) ,
gasLimit : handleUint ( fields [ 2 ] , "gasLimit" ) ,
to : handleAddress ( fields [ 3 ] ) ,
value : handleUint ( fields [ 4 ] , "value" ) ,
2022-11-30 23:44:23 +03:00
data : ( 0 , index _js _3 . hexlify ) ( fields [ 5 ] ) ,
2022-09-05 23:57:11 +03:00
chainId : BN _0
} ;
// Legacy unsigned transaction
if ( fields . length === 6 ) {
return tx ;
}
const v = handleUint ( fields [ 6 ] , "v" ) ;
const r = handleUint ( fields [ 7 ] , "r" ) ;
const s = handleUint ( fields [ 8 ] , "s" ) ;
if ( r === BN _0 && s === BN _0 ) {
// EIP-155 unsigned transaction
tx . chainId = v ;
}
else {
// Compute the EIP-155 chain ID (or 0 for legacy)
let chainId = ( v - BN _35 ) / BN _2 ;
if ( chainId < BN _0 ) {
chainId = BN _0 ;
}
tx . chainId = chainId ;
// Signed Legacy Transaction
2022-11-09 10:57:02 +03:00
( 0 , index _js _3 . assertArgument ) ( chainId !== BN _0 || ( v === BN _27 || v === BN _28 ) , "non-canonical legacy v" , "v" , fields [ 6 ] ) ;
2022-09-05 23:57:11 +03:00
tx . signature = index _js _2 . Signature . from ( {
r : ( 0 , index _js _3 . zeroPadValue ) ( fields [ 7 ] , 32 ) ,
s : ( 0 , index _js _3 . zeroPadValue ) ( fields [ 8 ] , 32 ) ,
v
} ) ;
tx . hash = ( 0 , index _js _2 . keccak256 ) ( data ) ;
}
return tx ;
}
function _serializeLegacy ( tx , sig ) {
const fields = [
formatNumber ( tx . nonce || 0 , "nonce" ) ,
formatNumber ( tx . gasPrice || 0 , "gasPrice" ) ,
formatNumber ( tx . gasLimit || 0 , "gasLimit" ) ,
( ( tx . to != null ) ? ( 0 , index _js _1 . getAddress ) ( tx . to ) : "0x" ) ,
formatNumber ( tx . value || 0 , "value" ) ,
( tx . data || "0x" ) ,
] ;
let chainId = BN _0 ;
2023-03-20 19:53:37 +03:00
if ( tx . chainId != BN _0 ) {
2022-09-05 23:57:11 +03:00
// A chainId was provided; if non-zero we'll use EIP-155
2022-09-16 05:58:45 +03:00
chainId = ( 0 , index _js _3 . getBigInt ) ( tx . chainId , "tx.chainId" ) ;
2022-09-05 23:57:11 +03:00
// We have a chainId in the tx and an EIP-155 v in the signature,
// make sure they agree with each other
2022-11-09 10:57:02 +03:00
( 0 , index _js _3 . assertArgument ) ( ! sig || sig . networkV == null || sig . legacyChainId === chainId , "tx.chainId/sig.v mismatch" , "sig" , sig ) ;
2022-09-05 23:57:11 +03:00
}
2023-03-20 19:53:37 +03:00
else if ( tx . signature ) {
// No explicit chainId, but EIP-155 have a derived implicit chainId
const legacy = tx . signature . legacyChainId ;
2022-09-05 23:57:11 +03:00
if ( legacy != null ) {
chainId = legacy ;
}
}
// Requesting an unsigned transaction
if ( ! sig ) {
// We have an EIP-155 transaction (chainId was specified and non-zero)
if ( chainId !== BN _0 ) {
2022-12-10 02:24:58 +03:00
fields . push ( ( 0 , index _js _3 . toBeArray ) ( chainId ) ) ;
2022-09-05 23:57:11 +03:00
fields . push ( "0x" ) ;
fields . push ( "0x" ) ;
}
return ( 0 , index _js _3 . encodeRlp ) ( fields ) ;
}
2023-03-20 19:53:37 +03:00
// @TODO: We should probably check that tx.signature, chainId, and sig
// match but that logic could break existing code, so schedule
// this for the next major bump.
// Compute the EIP-155 v
2022-09-05 23:57:11 +03:00
let v = BigInt ( 27 + sig . yParity ) ;
if ( chainId !== BN _0 ) {
v = index _js _2 . Signature . getChainIdV ( chainId , sig . v ) ;
}
else if ( BigInt ( sig . v ) !== v ) {
2022-11-09 10:57:02 +03:00
( 0 , index _js _3 . assertArgument ) ( false , "tx.chainId/sig.v mismatch" , "sig" , sig ) ;
2022-09-05 23:57:11 +03:00
}
2023-03-20 19:53:37 +03:00
// Add the signature
2022-12-10 02:24:58 +03:00
fields . push ( ( 0 , index _js _3 . toBeArray ) ( v ) ) ;
fields . push ( ( 0 , index _js _3 . toBeArray ) ( sig . r ) ) ;
fields . push ( ( 0 , index _js _3 . toBeArray ) ( sig . s ) ) ;
2022-09-05 23:57:11 +03:00
return ( 0 , index _js _3 . encodeRlp ) ( fields ) ;
}
function _parseEipSignature ( tx , fields , serialize ) {
let yParity ;
try {
yParity = handleNumber ( fields [ 0 ] , "yParity" ) ;
if ( yParity !== 0 && yParity !== 1 ) {
throw new Error ( "bad yParity" ) ;
}
}
catch ( error ) {
2022-11-09 10:57:02 +03:00
( 0 , index _js _3 . assertArgument ) ( false , "invalid yParity" , "yParity" , fields [ 0 ] ) ;
2022-09-05 23:57:11 +03:00
}
const r = ( 0 , index _js _3 . zeroPadValue ) ( fields [ 1 ] , 32 ) ;
const s = ( 0 , index _js _3 . zeroPadValue ) ( fields [ 2 ] , 32 ) ;
const signature = index _js _2 . Signature . from ( { r , s , yParity } ) ;
tx . signature = signature ;
}
function _parseEip1559 ( data ) {
2022-09-16 05:58:45 +03:00
const fields = ( 0 , index _js _3 . decodeRlp ) ( ( 0 , index _js _3 . getBytes ) ( data ) . slice ( 1 ) ) ;
2022-11-09 10:57:02 +03:00
( 0 , index _js _3 . assertArgument ) ( Array . isArray ( fields ) && ( fields . length === 9 || fields . length === 12 ) , "invalid field count for transaction type: 2" , "data" , ( 0 , index _js _3 . hexlify ) ( data ) ) ;
2022-09-05 23:57:11 +03:00
const maxPriorityFeePerGas = handleUint ( fields [ 2 ] , "maxPriorityFeePerGas" ) ;
const maxFeePerGas = handleUint ( fields [ 3 ] , "maxFeePerGas" ) ;
const tx = {
type : 2 ,
chainId : handleUint ( fields [ 0 ] , "chainId" ) ,
nonce : handleNumber ( fields [ 1 ] , "nonce" ) ,
maxPriorityFeePerGas : maxPriorityFeePerGas ,
maxFeePerGas : maxFeePerGas ,
gasPrice : null ,
gasLimit : handleUint ( fields [ 4 ] , "gasLimit" ) ,
to : handleAddress ( fields [ 5 ] ) ,
value : handleUint ( fields [ 6 ] , "value" ) ,
2022-11-30 23:44:23 +03:00
data : ( 0 , index _js _3 . hexlify ) ( fields [ 7 ] ) ,
2022-09-05 23:57:11 +03:00
accessList : handleAccessList ( fields [ 8 ] , "accessList" ) ,
} ;
// Unsigned EIP-1559 Transaction
if ( fields . length === 9 ) {
return tx ;
}
tx . hash = ( 0 , index _js _2 . keccak256 ) ( data ) ;
_parseEipSignature ( tx , fields . slice ( 9 ) , _serializeEip1559 ) ;
return tx ;
}
function _serializeEip1559 ( tx , sig ) {
const fields = [
formatNumber ( tx . chainId || 0 , "chainId" ) ,
formatNumber ( tx . nonce || 0 , "nonce" ) ,
formatNumber ( tx . maxPriorityFeePerGas || 0 , "maxPriorityFeePerGas" ) ,
formatNumber ( tx . maxFeePerGas || 0 , "maxFeePerGas" ) ,
formatNumber ( tx . gasLimit || 0 , "gasLimit" ) ,
( ( tx . to != null ) ? ( 0 , index _js _1 . getAddress ) ( tx . to ) : "0x" ) ,
formatNumber ( tx . value || 0 , "value" ) ,
( tx . data || "0x" ) ,
( formatAccessList ( tx . accessList || [ ] ) )
] ;
if ( sig ) {
fields . push ( formatNumber ( sig . yParity , "yParity" ) ) ;
2022-12-10 02:24:58 +03:00
fields . push ( ( 0 , index _js _3 . toBeArray ) ( sig . r ) ) ;
fields . push ( ( 0 , index _js _3 . toBeArray ) ( sig . s ) ) ;
2022-09-05 23:57:11 +03:00
}
return ( 0 , index _js _3 . concat ) ( [ "0x02" , ( 0 , index _js _3 . encodeRlp ) ( fields ) ] ) ;
}
function _parseEip2930 ( data ) {
2022-09-16 05:58:45 +03:00
const fields = ( 0 , index _js _3 . decodeRlp ) ( ( 0 , index _js _3 . getBytes ) ( data ) . slice ( 1 ) ) ;
2022-11-09 10:57:02 +03:00
( 0 , index _js _3 . assertArgument ) ( Array . isArray ( fields ) && ( fields . length === 8 || fields . length === 11 ) , "invalid field count for transaction type: 1" , "data" , ( 0 , index _js _3 . hexlify ) ( data ) ) ;
2022-09-05 23:57:11 +03:00
const tx = {
type : 1 ,
chainId : handleUint ( fields [ 0 ] , "chainId" ) ,
nonce : handleNumber ( fields [ 1 ] , "nonce" ) ,
gasPrice : handleUint ( fields [ 2 ] , "gasPrice" ) ,
gasLimit : handleUint ( fields [ 3 ] , "gasLimit" ) ,
to : handleAddress ( fields [ 4 ] ) ,
value : handleUint ( fields [ 5 ] , "value" ) ,
2022-11-30 23:44:23 +03:00
data : ( 0 , index _js _3 . hexlify ) ( fields [ 6 ] ) ,
2022-09-05 23:57:11 +03:00
accessList : handleAccessList ( fields [ 7 ] , "accessList" )
} ;
// Unsigned EIP-2930 Transaction
if ( fields . length === 8 ) {
return tx ;
}
tx . hash = ( 0 , index _js _2 . keccak256 ) ( data ) ;
_parseEipSignature ( tx , fields . slice ( 8 ) , _serializeEip2930 ) ;
return tx ;
}
function _serializeEip2930 ( tx , sig ) {
const fields = [
formatNumber ( tx . chainId || 0 , "chainId" ) ,
formatNumber ( tx . nonce || 0 , "nonce" ) ,
formatNumber ( tx . gasPrice || 0 , "gasPrice" ) ,
formatNumber ( tx . gasLimit || 0 , "gasLimit" ) ,
( ( tx . to != null ) ? ( 0 , index _js _1 . getAddress ) ( tx . to ) : "0x" ) ,
formatNumber ( tx . value || 0 , "value" ) ,
( tx . data || "0x" ) ,
( formatAccessList ( tx . accessList || [ ] ) )
] ;
if ( sig ) {
fields . push ( formatNumber ( sig . yParity , "recoveryParam" ) ) ;
2022-12-10 02:24:58 +03:00
fields . push ( ( 0 , index _js _3 . toBeArray ) ( sig . r ) ) ;
fields . push ( ( 0 , index _js _3 . toBeArray ) ( sig . s ) ) ;
2022-09-05 23:57:11 +03:00
}
return ( 0 , index _js _3 . concat ) ( [ "0x01" , ( 0 , index _js _3 . encodeRlp ) ( fields ) ] ) ;
}
2022-12-03 05:27:06 +03:00
/ * *
* A * * Transaction * * describes an operation to be executed on
* Ethereum by an Externally Owned Account ( EOA ) . It includes
* who ( the [ [ to ] ] address ) , what ( the [ [ data ] ] ) and how much ( the
* [ [ value ] ] in ether ) the operation should entail .
2022-12-10 02:24:58 +03:00
*
* @ example :
* tx = new Transaction ( )
* //_result:
*
* tx . data = "0x1234" ;
* //_result:
2022-12-03 05:27:06 +03:00
* /
2022-09-05 23:57:11 +03:00
class Transaction {
2022-11-30 23:44:23 +03:00
# type ;
# to ;
# data ;
# nonce ;
# gasLimit ;
# gasPrice ;
# maxPriorityFeePerGas ;
# maxFeePerGas ;
# value ;
# chainId ;
# sig ;
# accessList ;
2022-12-03 05:27:06 +03:00
/ * *
* The transaction type .
*
* If null , the type will be automatically inferred based on
* explicit properties .
* /
2022-11-30 23:44:23 +03:00
get type ( ) { return this . # type ; }
2022-09-05 23:57:11 +03:00
set type ( value ) {
switch ( value ) {
case null :
2022-11-30 23:44:23 +03:00
this . # type = null ;
2022-09-05 23:57:11 +03:00
break ;
case 0 :
case "legacy" :
2022-11-30 23:44:23 +03:00
this . # type = 0 ;
2022-09-05 23:57:11 +03:00
break ;
case 1 :
case "berlin" :
case "eip-2930" :
2022-11-30 23:44:23 +03:00
this . # type = 1 ;
2022-09-05 23:57:11 +03:00
break ;
case 2 :
case "london" :
case "eip-1559" :
2022-11-30 23:44:23 +03:00
this . # type = 2 ;
2022-09-05 23:57:11 +03:00
break ;
default :
2022-11-30 23:44:23 +03:00
( 0 , index _js _3 . assertArgument ) ( false , "unsupported transaction type" , "type" , value ) ;
2022-09-05 23:57:11 +03:00
}
}
2022-12-03 05:27:06 +03:00
/ * *
* The name of the transaction type .
* /
get typeName ( ) {
switch ( this . type ) {
case 0 : return "legacy" ;
case 1 : return "eip-2930" ;
case 2 : return "eip-1559" ;
}
return null ;
}
/ * *
* The ` ` to ` ` address for the transaction or ` ` null ` ` if the
* transaction is an ` ` init ` ` transaction .
* /
2022-11-30 23:44:23 +03:00
get to ( ) { return this . # to ; }
2022-09-05 23:57:11 +03:00
set to ( value ) {
2022-11-30 23:44:23 +03:00
this . # to = ( value == null ) ? null : ( 0 , index _js _1 . getAddress ) ( value ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* The transaction nonce .
* /
2022-11-30 23:44:23 +03:00
get nonce ( ) { return this . # nonce ; }
set nonce ( value ) { this . # nonce = ( 0 , index _js _3 . getNumber ) ( value , "value" ) ; }
2022-12-03 05:27:06 +03:00
/ * *
* The gas limit .
* /
2022-11-30 23:44:23 +03:00
get gasLimit ( ) { return this . # gasLimit ; }
set gasLimit ( value ) { this . # gasLimit = ( 0 , index _js _3 . getBigInt ) ( value ) ; }
2022-12-03 05:27:06 +03:00
/ * *
* The gas price .
*
* On legacy networks this defines the fee that will be paid . On
* EIP - 1559 networks , this should be ` ` null ` ` .
* /
2022-09-05 23:57:11 +03:00
get gasPrice ( ) {
2022-11-30 23:44:23 +03:00
const value = this . # gasPrice ;
2022-09-05 23:57:11 +03:00
if ( value == null && ( this . type === 0 || this . type === 1 ) ) {
return BN _0 ;
}
return value ;
}
set gasPrice ( value ) {
2022-11-30 23:44:23 +03:00
this . # gasPrice = ( value == null ) ? null : ( 0 , index _js _3 . getBigInt ) ( value , "gasPrice" ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* The maximum priority fee per unit of gas to pay . On legacy
* networks this should be ` ` null ` ` .
* /
2022-09-05 23:57:11 +03:00
get maxPriorityFeePerGas ( ) {
2022-11-30 23:44:23 +03:00
const value = this . # maxPriorityFeePerGas ;
if ( value == null ) {
if ( this . type === 2 ) {
return BN _0 ;
}
return null ;
2022-09-05 23:57:11 +03:00
}
return value ;
}
set maxPriorityFeePerGas ( value ) {
2022-11-30 23:44:23 +03:00
this . # maxPriorityFeePerGas = ( value == null ) ? null : ( 0 , index _js _3 . getBigInt ) ( value , "maxPriorityFeePerGas" ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* The maximum total fee per unit of gas to pay . On legacy
* networks this should be ` ` null ` ` .
* /
2022-09-05 23:57:11 +03:00
get maxFeePerGas ( ) {
2022-11-30 23:44:23 +03:00
const value = this . # maxFeePerGas ;
if ( value == null ) {
if ( this . type === 2 ) {
return BN _0 ;
}
return null ;
2022-09-05 23:57:11 +03:00
}
return value ;
}
set maxFeePerGas ( value ) {
2022-11-30 23:44:23 +03:00
this . # maxFeePerGas = ( value == null ) ? null : ( 0 , index _js _3 . getBigInt ) ( value , "maxFeePerGas" ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* The transaction data . For ` ` init ` ` transactions this is the
* deployment code .
* /
2022-11-30 23:44:23 +03:00
get data ( ) { return this . # data ; }
set data ( value ) { this . # data = ( 0 , index _js _3 . hexlify ) ( value ) ; }
2022-12-03 05:27:06 +03:00
/ * *
* The amount of ether to send in this transactions .
* /
2022-11-30 23:44:23 +03:00
get value ( ) { return this . # value ; }
2022-09-05 23:57:11 +03:00
set value ( value ) {
2022-11-30 23:44:23 +03:00
this . # value = ( 0 , index _js _3 . getBigInt ) ( value , "value" ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* The chain ID this transaction is valid on .
* /
2022-11-30 23:44:23 +03:00
get chainId ( ) { return this . # chainId ; }
set chainId ( value ) { this . # chainId = ( 0 , index _js _3 . getBigInt ) ( value ) ; }
2022-12-03 05:27:06 +03:00
/ * *
* If signed , the signature for this transaction .
* /
2022-11-30 23:44:23 +03:00
get signature ( ) { return this . # sig || null ; }
2022-09-05 23:57:11 +03:00
set signature ( value ) {
2022-11-30 23:44:23 +03:00
this . # sig = ( value == null ) ? null : index _js _2 . Signature . from ( value ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* The access list .
*
* An access list permits discounted ( but pre - paid ) access to
* bytecode and state variable access within contract execution .
* /
2022-09-05 23:57:11 +03:00
get accessList ( ) {
2022-11-30 23:44:23 +03:00
const value = this . # accessList || null ;
if ( value == null ) {
if ( this . type === 1 || this . type === 2 ) {
return [ ] ;
}
return null ;
2022-09-05 23:57:11 +03:00
}
return value ;
}
set accessList ( value ) {
2022-11-30 23:44:23 +03:00
this . # accessList = ( value == null ) ? null : ( 0 , accesslist _js _1 . accessListify ) ( value ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* Creates a new Transaction with default values .
* /
2022-09-05 23:57:11 +03:00
constructor ( ) {
2022-11-30 23:44:23 +03:00
this . # type = null ;
this . # to = null ;
this . # nonce = 0 ;
this . # gasLimit = BigInt ( 0 ) ;
this . # gasPrice = null ;
this . # maxPriorityFeePerGas = null ;
this . # maxFeePerGas = null ;
this . # data = "0x" ;
this . # value = BigInt ( 0 ) ;
this . # chainId = BigInt ( 0 ) ;
this . # sig = null ;
this . # accessList = null ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* The transaction hash , if signed . Otherwise , ` ` null ` ` .
* /
2022-09-05 23:57:11 +03:00
get hash ( ) {
if ( this . signature == null ) {
2022-10-20 12:03:32 +03:00
return null ;
2022-09-05 23:57:11 +03:00
}
return ( 0 , index _js _2 . keccak256 ) ( this . serialized ) ;
}
2022-12-03 05:27:06 +03:00
/ * *
* The pre - image hash of this transaction .
*
* This is the digest that a [ [ Signer ] ] must sign to authorize
* this transaction .
* /
2022-09-05 23:57:11 +03:00
get unsignedHash ( ) {
return ( 0 , index _js _2 . keccak256 ) ( this . unsignedSerialized ) ;
}
2022-12-03 05:27:06 +03:00
/ * *
* The sending address , if signed . Otherwise , ` ` null ` ` .
* /
2022-09-05 23:57:11 +03:00
get from ( ) {
if ( this . signature == null ) {
return null ;
}
2022-10-20 12:03:32 +03:00
return ( 0 , address _js _1 . recoverAddress ) ( this . unsignedHash , this . signature ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* The public key of the sender , if signed . Otherwise , ` ` null ` ` .
* /
2022-09-05 23:57:11 +03:00
get fromPublicKey ( ) {
if ( this . signature == null ) {
return null ;
}
2022-11-30 23:44:23 +03:00
return index _js _2 . SigningKey . recoverPublicKey ( this . unsignedHash , this . signature ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* Returns true if signed .
*
* This provides a Type Guard that properties requiring a signed
* transaction are non - null .
* /
2022-09-05 23:57:11 +03:00
isSigned ( ) {
2022-12-03 05:27:06 +03:00
//isSigned(): this is SignedTransaction {
2022-09-05 23:57:11 +03:00
return this . signature != null ;
}
2022-12-03 05:27:06 +03:00
/ * *
* The serialized transaction .
*
* This throws if the transaction is unsigned . For the pre - image ,
* use [ [ unsignedSerialized ] ] .
* /
2022-09-05 23:57:11 +03:00
get serialized ( ) {
2022-11-30 23:44:23 +03:00
( 0 , index _js _3 . assert ) ( this . signature != null , "cannot serialize unsigned transaction; maybe you meant .unsignedSerialized" , "UNSUPPORTED_OPERATION" , { operation : ".serialized" } ) ;
switch ( this . inferType ( ) ) {
2022-09-05 23:57:11 +03:00
case 0 :
return _serializeLegacy ( this , this . signature ) ;
case 1 :
return _serializeEip2930 ( this , this . signature ) ;
case 2 :
return _serializeEip1559 ( this , this . signature ) ;
}
2022-11-30 23:44:23 +03:00
( 0 , index _js _3 . assert ) ( false , "unsupported transaction type" , "UNSUPPORTED_OPERATION" , { operation : ".serialized" } ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* The transaction pre - image .
*
* The hash of this is the digest which needs to be signed to
* authorize this transaction .
* /
2022-09-05 23:57:11 +03:00
get unsignedSerialized ( ) {
2022-11-30 23:44:23 +03:00
switch ( this . inferType ( ) ) {
2022-09-05 23:57:11 +03:00
case 0 :
return _serializeLegacy ( this ) ;
case 1 :
return _serializeEip2930 ( this ) ;
case 2 :
return _serializeEip1559 ( this ) ;
}
2022-11-30 23:44:23 +03:00
( 0 , index _js _3 . assert ) ( false , "unsupported transaction type" , "UNSUPPORTED_OPERATION" , { operation : ".unsignedSerialized" } ) ;
}
/ * *
* Return the most "likely" type ; currently the highest
2022-12-03 05:27:06 +03:00
* supported transaction type .
2022-11-30 23:44:23 +03:00
* /
inferType ( ) {
return ( this . inferTypes ( ) . pop ( ) ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-03 05:27:06 +03:00
/ * *
* Validates the explicit properties and returns a list of compatible
* transaction types .
* /
2022-09-05 23:57:11 +03:00
inferTypes ( ) {
// Checks that there are no conflicting properties set
const hasGasPrice = this . gasPrice != null ;
const hasFee = ( this . maxFeePerGas != null || this . maxPriorityFeePerGas != null ) ;
const hasAccessList = ( this . accessList != null ) ;
//if (hasGasPrice && hasFee) {
// throw new Error("transaction cannot have gasPrice and maxFeePerGas");
//}
if ( this . maxFeePerGas != null && this . maxPriorityFeePerGas != null ) {
2022-11-30 23:44:23 +03:00
( 0 , index _js _3 . assert ) ( this . maxFeePerGas >= this . maxPriorityFeePerGas , "priorityFee cannot be more than maxFee" , "BAD_DATA" , { value : this } ) ;
2022-09-05 23:57:11 +03:00
}
//if (this.type === 2 && hasGasPrice) {
// throw new Error("eip-1559 transaction cannot have gasPrice");
//}
2022-11-30 23:44:23 +03:00
( 0 , index _js _3 . assert ) ( ! hasFee || ( this . type !== 0 && this . type !== 1 ) , "transaction type cannot have maxFeePerGas or maxPriorityFeePerGas" , "BAD_DATA" , { value : this } ) ;
( 0 , index _js _3 . assert ) ( this . type !== 0 || ! hasAccessList , "legacy transaction cannot have accessList" , "BAD_DATA" , { value : this } ) ;
2022-09-05 23:57:11 +03:00
const types = [ ] ;
// Explicit type
if ( this . type != null ) {
types . push ( this . type ) ;
}
else {
if ( hasFee ) {
types . push ( 2 ) ;
}
else if ( hasGasPrice ) {
types . push ( 1 ) ;
if ( ! hasAccessList ) {
types . push ( 0 ) ;
}
}
else if ( hasAccessList ) {
types . push ( 1 ) ;
types . push ( 2 ) ;
}
else {
types . push ( 0 ) ;
types . push ( 1 ) ;
types . push ( 2 ) ;
}
}
types . sort ( ) ;
return types ;
}
2022-12-03 05:27:06 +03:00
/ * *
* Returns true if this transaction is a legacy transaction ( i . e .
* ` ` type === 0 ` ` ) .
*
* This provides a Type Guard that the related properties are
* non - null .
* /
2022-09-16 05:58:45 +03:00
isLegacy ( ) {
return ( this . type === 0 ) ;
}
2022-12-03 05:27:06 +03:00
/ * *
* Returns true if this transaction is berlin hardform transaction ( i . e .
* ` ` type === 1 ` ` ) .
*
* This provides a Type Guard that the related properties are
* non - null .
* /
2022-09-16 05:58:45 +03:00
isBerlin ( ) {
return ( this . type === 1 ) ;
}
2022-12-03 05:27:06 +03:00
/ * *
* Returns true if this transaction is london hardform transaction ( i . e .
* ` ` type === 2 ` ` ) .
*
* This provides a Type Guard that the related properties are
* non - null .
* /
2022-09-16 05:58:45 +03:00
isLondon ( ) {
return ( this . type === 2 ) ;
}
2022-12-03 05:27:06 +03:00
/ * *
* Create a copy of this transaciton .
* /
2022-09-05 23:57:11 +03:00
clone ( ) {
return Transaction . from ( this ) ;
}
2022-12-03 05:27:06 +03:00
/ * *
* Return a JSON - friendly object .
* /
2022-10-20 12:03:32 +03:00
toJSON ( ) {
const s = ( v ) => {
if ( v == null ) {
return null ;
}
return v . toString ( ) ;
} ;
return {
type : this . type ,
to : this . to ,
2022-11-30 23:44:23 +03:00
// from: this.from,
2022-10-20 12:03:32 +03:00
data : this . data ,
nonce : this . nonce ,
gasLimit : s ( this . gasLimit ) ,
gasPrice : s ( this . gasPrice ) ,
maxPriorityFeePerGas : s ( this . maxPriorityFeePerGas ) ,
maxFeePerGas : s ( this . maxFeePerGas ) ,
value : s ( this . value ) ,
chainId : s ( this . chainId ) ,
sig : this . signature ? this . signature . toJSON ( ) : null ,
accessList : this . accessList
} ;
}
2022-12-03 05:27:06 +03:00
/ * *
* Create a * * Transaction * * from a serialized transaction or a
* Transaction - like object .
* /
2022-09-05 23:57:11 +03:00
static from ( tx ) {
2022-12-03 05:27:06 +03:00
if ( tx == null ) {
return new Transaction ( ) ;
}
2022-09-05 23:57:11 +03:00
if ( typeof ( tx ) === "string" ) {
2022-09-16 05:58:45 +03:00
const payload = ( 0 , index _js _3 . getBytes ) ( tx ) ;
2022-09-05 23:57:11 +03:00
if ( payload [ 0 ] >= 0x7f ) { // @TODO: > vs >= ??
return Transaction . from ( _parseLegacy ( payload ) ) ;
}
switch ( payload [ 0 ] ) {
case 1 : return Transaction . from ( _parseEip2930 ( payload ) ) ;
case 2 : return Transaction . from ( _parseEip1559 ( payload ) ) ;
}
2022-11-30 23:44:23 +03:00
( 0 , index _js _3 . assert ) ( false , "unsupported transaction type" , "UNSUPPORTED_OPERATION" , { operation : "from" } ) ;
2022-09-05 23:57:11 +03:00
}
const result = new Transaction ( ) ;
if ( tx . type != null ) {
result . type = tx . type ;
}
if ( tx . to != null ) {
result . to = tx . to ;
}
if ( tx . nonce != null ) {
result . nonce = tx . nonce ;
}
if ( tx . gasLimit != null ) {
result . gasLimit = tx . gasLimit ;
}
if ( tx . gasPrice != null ) {
result . gasPrice = tx . gasPrice ;
}
if ( tx . maxPriorityFeePerGas != null ) {
result . maxPriorityFeePerGas = tx . maxPriorityFeePerGas ;
}
if ( tx . maxFeePerGas != null ) {
result . maxFeePerGas = tx . maxFeePerGas ;
}
if ( tx . data != null ) {
result . data = tx . data ;
}
if ( tx . value != null ) {
result . value = tx . value ;
}
if ( tx . chainId != null ) {
result . chainId = tx . chainId ;
}
if ( tx . signature != null ) {
result . signature = index _js _2 . Signature . from ( tx . signature ) ;
}
if ( tx . accessList != null ) {
result . accessList = tx . accessList ;
}
if ( tx . hash != null ) {
2023-01-17 21:53:49 +03:00
( 0 , index _js _3 . assertArgument ) ( result . isSigned ( ) , "unsigned transaction cannot define hash" , "tx" , tx ) ;
2022-11-30 23:44:23 +03:00
( 0 , index _js _3 . assertArgument ) ( result . hash === tx . hash , "hash mismatch" , "tx" , tx ) ;
2022-09-05 23:57:11 +03:00
}
if ( tx . from != null ) {
2023-01-17 21:53:49 +03:00
( 0 , index _js _3 . assertArgument ) ( result . isSigned ( ) , "unsigned transaction cannot define from" , "tx" , tx ) ;
2022-11-30 23:44:23 +03:00
( 0 , index _js _3 . assertArgument ) ( result . from . toLowerCase ( ) === ( tx . from || "" ) . toLowerCase ( ) , "from mismatch" , "tx" , tx ) ;
2022-09-05 23:57:11 +03:00
}
return result ;
}
}
exports . Transaction = Transaction ;
//# sourceMappingURL=transaction.js.map