2022-09-05 23:57:11 +03:00
"use strict" ;
2022-11-30 23:44:23 +03:00
/ * *
2023-06-02 00:52:58 +03:00
* A fragment is a single item from an ABI , which may represent any of :
*
* - [ Functions ] ( FunctionFragment )
* - [ Events ] ( EventFragment )
* - [ Constructors ] ( ConstructorFragment )
* - Custom [ Errors ] ( ErrorFragment )
* - [ Fallback or Receive ] ( FallbackFragment ) functions
2022-11-30 23:44:23 +03:00
*
2023-02-13 06:14:26 +03:00
* @ _subsection api / abi / abi - coder : Fragments [ about - fragments ]
2022-11-30 23:44:23 +03:00
* /
2022-09-05 23:57:11 +03:00
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
2023-01-31 06:29:09 +03:00
exports . StructFragment = exports . FunctionFragment = exports . FallbackFragment = exports . ConstructorFragment = exports . EventFragment = exports . ErrorFragment = exports . NamedFragment = exports . Fragment = exports . ParamType = void 0 ;
2022-09-05 23:57:11 +03:00
const index _js _1 = require ( "../utils/index.js" ) ;
2022-09-16 05:58:45 +03:00
const index _js _2 = require ( "../hash/index.js" ) ;
2022-09-05 23:57:11 +03:00
;
// [ "a", "b" ] => { "a": 1, "b": 1 }
function setify ( items ) {
const result = new Set ( ) ;
items . forEach ( ( k ) => result . add ( k ) ) ;
return Object . freeze ( result ) ;
}
2023-07-28 21:50:56 +03:00
const _kwVisibDeploy = "external public payable" ;
const KwVisibDeploy = setify ( _kwVisibDeploy . split ( " " ) ) ;
2022-09-05 23:57:11 +03:00
// Visibility Keywords
const _kwVisib = "constant external internal payable private public pure view" ;
const KwVisib = setify ( _kwVisib . split ( " " ) ) ;
2023-01-31 06:29:09 +03:00
const _kwTypes = "constructor error event fallback function receive struct" ;
2022-09-05 23:57:11 +03:00
const KwTypes = setify ( _kwTypes . split ( " " ) ) ;
const _kwModifiers = "calldata memory storage payable indexed" ;
const KwModifiers = setify ( _kwModifiers . split ( " " ) ) ;
const _kwOther = "tuple returns" ;
// All Keywords
const _keywords = [ _kwTypes , _kwModifiers , _kwOther , _kwVisib ] . join ( " " ) ;
const Keywords = setify ( _keywords . split ( " " ) ) ;
// Single character tokens
const SimpleTokens = {
"(" : "OPEN_PAREN" , ")" : "CLOSE_PAREN" ,
"[" : "OPEN_BRACKET" , "]" : "CLOSE_BRACKET" ,
"," : "COMMA" , "@" : "AT"
} ;
// Parser regexes to consume the next token
2023-02-04 11:26:34 +03:00
const regexWhitespacePrefix = new RegExp ( "^(\\s*)" ) ;
const regexNumberPrefix = new RegExp ( "^([0-9]+)" ) ;
const regexIdPrefix = new RegExp ( "^([a-zA-Z$_][a-zA-Z0-9$_]*)" ) ;
// Parser regexs to check validity
const regexId = new RegExp ( "^([a-zA-Z$_][a-zA-Z0-9$_]*)$" ) ;
const regexType = new RegExp ( "^(address|bool|bytes([0-9]*)|string|u?int([0-9]*))$" ) ;
2022-09-05 23:57:11 +03:00
class TokenString {
# offset ;
# tokens ;
get offset ( ) { return this . # offset ; }
get length ( ) { return this . # tokens . length - this . # offset ; }
constructor ( tokens ) {
this . # offset = 0 ;
this . # tokens = tokens . slice ( ) ;
}
clone ( ) { return new TokenString ( this . # tokens ) ; }
reset ( ) { this . # offset = 0 ; }
# subTokenString ( from = 0 , to = 0 ) {
return new TokenString ( this . # tokens . slice ( from , to ) . map ( ( t ) => {
return Object . freeze ( Object . assign ( { } , t , {
match : ( t . match - from ) ,
linkBack : ( t . linkBack - from ) ,
linkNext : ( t . linkNext - from ) ,
} ) ) ;
} ) ) ;
}
// Pops and returns the value of the next token, if it is a keyword in allowed; throws if out of tokens
popKeyword ( allowed ) {
const top = this . peek ( ) ;
if ( top . type !== "KEYWORD" || ! allowed . has ( top . text ) ) {
throw new Error ( ` expected keyword ${ top . text } ` ) ;
}
return this . pop ( ) . text ;
}
// Pops and returns the value of the next token if it is `type`; throws if out of tokens
popType ( type ) {
if ( this . peek ( ) . type !== type ) {
throw new Error ( ` expected ${ type } ; got ${ JSON . stringify ( this . peek ( ) ) } ` ) ;
}
return this . pop ( ) . text ;
}
// Pops and returns a "(" TOKENS ")"
popParen ( ) {
const top = this . peek ( ) ;
if ( top . type !== "OPEN_PAREN" ) {
throw new Error ( "bad start" ) ;
}
const result = this . # subTokenString ( this . # offset + 1 , top . match + 1 ) ;
this . # offset = top . match + 1 ;
return result ;
}
// Pops and returns the items within "(" ITEM1 "," ITEM2 "," ... ")"
popParams ( ) {
const top = this . peek ( ) ;
if ( top . type !== "OPEN_PAREN" ) {
throw new Error ( "bad start" ) ;
}
const result = [ ] ;
while ( this . # offset < top . match - 1 ) {
const link = this . peek ( ) . linkNext ;
result . push ( this . # subTokenString ( this . # offset + 1 , link ) ) ;
this . # offset = link ;
}
this . # offset = top . match + 1 ;
return result ;
}
// Returns the top Token, throwing if out of tokens
peek ( ) {
if ( this . # offset >= this . # tokens . length ) {
throw new Error ( "out-of-bounds" ) ;
}
return this . # tokens [ this . # offset ] ;
}
// Returns the next value, if it is a keyword in `allowed`
peekKeyword ( allowed ) {
const top = this . peekType ( "KEYWORD" ) ;
return ( top != null && allowed . has ( top ) ) ? top : null ;
}
// Returns the value of the next token if it is `type`
peekType ( type ) {
if ( this . length === 0 ) {
return null ;
}
const top = this . peek ( ) ;
return ( top . type === type ) ? top . text : null ;
}
// Returns the next token; throws if out of tokens
pop ( ) {
const result = this . peek ( ) ;
this . # offset ++ ;
return result ;
}
toString ( ) {
const tokens = [ ] ;
for ( let i = this . # offset ; i < this . # tokens . length ; i ++ ) {
const token = this . # tokens [ i ] ;
tokens . push ( ` ${ token . type } : ${ token . text } ` ) ;
}
return ` <TokenString ${ tokens . join ( " " ) } > ` ;
}
}
function lex ( text ) {
const tokens = [ ] ;
const throwError = ( message ) => {
const token = ( offset < text . length ) ? JSON . stringify ( text [ offset ] ) : "$EOI" ;
throw new Error ( ` invalid token ${ token } at ${ offset } : ${ message } ` ) ;
} ;
let brackets = [ ] ;
let commas = [ ] ;
let offset = 0 ;
while ( offset < text . length ) {
// Strip off any leading whitespace
let cur = text . substring ( offset ) ;
2023-02-04 11:26:34 +03:00
let match = cur . match ( regexWhitespacePrefix ) ;
2022-09-05 23:57:11 +03:00
if ( match ) {
offset += match [ 1 ] . length ;
cur = text . substring ( offset ) ;
}
const token = { depth : brackets . length , linkBack : - 1 , linkNext : - 1 , match : - 1 , type : "" , text : "" , offset , value : - 1 } ;
tokens . push ( token ) ;
let type = ( SimpleTokens [ cur [ 0 ] ] || "" ) ;
if ( type ) {
token . type = type ;
token . text = cur [ 0 ] ;
offset ++ ;
if ( type === "OPEN_PAREN" ) {
brackets . push ( tokens . length - 1 ) ;
commas . push ( tokens . length - 1 ) ;
}
else if ( type == "CLOSE_PAREN" ) {
if ( brackets . length === 0 ) {
throwError ( "no matching open bracket" ) ;
}
token . match = brackets . pop ( ) ;
( tokens [ token . match ] ) . match = tokens . length - 1 ;
token . depth -- ;
token . linkBack = commas . pop ( ) ;
( tokens [ token . linkBack ] ) . linkNext = tokens . length - 1 ;
}
else if ( type === "COMMA" ) {
token . linkBack = commas . pop ( ) ;
( tokens [ token . linkBack ] ) . linkNext = tokens . length - 1 ;
commas . push ( tokens . length - 1 ) ;
}
else if ( type === "OPEN_BRACKET" ) {
token . type = "BRACKET" ;
}
else if ( type === "CLOSE_BRACKET" ) {
// Remove the CLOSE_BRACKET
let suffix = tokens . pop ( ) . text ;
if ( tokens . length > 0 && tokens [ tokens . length - 1 ] . type === "NUMBER" ) {
const value = tokens . pop ( ) . text ;
suffix = value + suffix ;
2022-09-16 05:58:45 +03:00
( tokens [ tokens . length - 1 ] ) . value = ( 0 , index _js _1 . getNumber ) ( value ) ;
2022-09-05 23:57:11 +03:00
}
if ( tokens . length === 0 || tokens [ tokens . length - 1 ] . type !== "BRACKET" ) {
throw new Error ( "missing opening bracket" ) ;
}
( tokens [ tokens . length - 1 ] ) . text += suffix ;
}
continue ;
}
2023-02-04 11:26:34 +03:00
match = cur . match ( regexIdPrefix ) ;
2022-09-05 23:57:11 +03:00
if ( match ) {
token . text = match [ 1 ] ;
offset += token . text . length ;
if ( Keywords . has ( token . text ) ) {
token . type = "KEYWORD" ;
continue ;
}
if ( token . text . match ( regexType ) ) {
token . type = "TYPE" ;
continue ;
}
token . type = "ID" ;
continue ;
}
2023-02-04 11:26:34 +03:00
match = cur . match ( regexNumberPrefix ) ;
2022-09-05 23:57:11 +03:00
if ( match ) {
token . text = match [ 1 ] ;
token . type = "NUMBER" ;
offset += token . text . length ;
continue ;
}
throw new Error ( ` unexpected token ${ JSON . stringify ( cur [ 0 ] ) } at position ${ offset } ` ) ;
}
return new TokenString ( tokens . map ( ( t ) => Object . freeze ( t ) ) ) ;
}
// Check only one of `allowed` is in `set`
function allowSingle ( set , allowed ) {
let included = [ ] ;
for ( const key in allowed . keys ( ) ) {
if ( set . has ( key ) ) {
included . push ( key ) ;
}
}
if ( included . length > 1 ) {
throw new Error ( ` conflicting types: ${ included . join ( ", " ) } ` ) ;
}
}
// Functions to process a Solidity Signature TokenString from left-to-right for...
// ...the name with an optional type, returning the name
function consumeName ( type , tokens ) {
if ( tokens . peekKeyword ( KwTypes ) ) {
const keyword = tokens . pop ( ) . text ;
if ( keyword !== type ) {
throw new Error ( ` expected ${ type } , got ${ keyword } ` ) ;
}
}
return tokens . popType ( "ID" ) ;
}
// ...all keywords matching allowed, returning the keywords
function consumeKeywords ( tokens , allowed ) {
const keywords = new Set ( ) ;
while ( true ) {
const keyword = tokens . peekType ( "KEYWORD" ) ;
if ( keyword == null || ( allowed && ! allowed . has ( keyword ) ) ) {
break ;
}
tokens . pop ( ) ;
if ( keywords . has ( keyword ) ) {
throw new Error ( ` duplicate keywords: ${ JSON . stringify ( keyword ) } ` ) ;
}
keywords . add ( keyword ) ;
}
return Object . freeze ( keywords ) ;
}
// ...all visibility keywords, returning the coalesced mutability
function consumeMutability ( tokens ) {
let modifiers = consumeKeywords ( tokens , KwVisib ) ;
// Detect conflicting modifiers
allowSingle ( modifiers , setify ( "constant payable nonpayable" . split ( " " ) ) ) ;
allowSingle ( modifiers , setify ( "pure view payable nonpayable" . split ( " " ) ) ) ;
// Process mutability states
if ( modifiers . has ( "view" ) ) {
return "view" ;
}
if ( modifiers . has ( "pure" ) ) {
return "pure" ;
}
if ( modifiers . has ( "payable" ) ) {
return "payable" ;
}
if ( modifiers . has ( "nonpayable" ) ) {
return "nonpayable" ;
}
// Process legacy `constant` last
if ( modifiers . has ( "constant" ) ) {
return "view" ;
}
return "nonpayable" ;
}
// ...a parameter list, returning the ParamType list
function consumeParams ( tokens , allowIndexed ) {
2022-10-01 08:34:06 +03:00
return tokens . popParams ( ) . map ( ( t ) => ParamType . from ( t , allowIndexed ) ) ;
2022-09-05 23:57:11 +03:00
}
// ...a gas limit, returning a BigNumber or null if none
function consumeGas ( tokens ) {
if ( tokens . peekType ( "AT" ) ) {
tokens . pop ( ) ;
if ( tokens . peekType ( "NUMBER" ) ) {
2022-09-16 05:58:45 +03:00
return ( 0 , index _js _1 . getBigInt ) ( tokens . pop ( ) . text ) ;
2022-09-05 23:57:11 +03:00
}
throw new Error ( "invalid gas" ) ;
}
return null ;
}
function consumeEoi ( tokens ) {
if ( tokens . length ) {
throw new Error ( ` unexpected tokens: ${ tokens . toString ( ) } ` ) ;
}
}
const regexArrayType = new RegExp ( /^(.*)\[([0-9]*)\]$/ ) ;
function verifyBasicType ( type ) {
const match = type . match ( regexType ) ;
2022-11-09 10:57:02 +03:00
( 0 , index _js _1 . assertArgument ) ( match , "invalid type" , "type" , type ) ;
2022-09-05 23:57:11 +03:00
if ( type === "uint" ) {
return "uint256" ;
}
if ( type === "int" ) {
return "int256" ;
}
if ( match [ 2 ] ) {
// bytesXX
const length = parseInt ( match [ 2 ] ) ;
2022-11-09 10:57:02 +03:00
( 0 , index _js _1 . assertArgument ) ( length !== 0 && length <= 32 , "invalid bytes length" , "type" , type ) ;
2022-09-05 23:57:11 +03:00
}
else if ( match [ 3 ] ) {
// intXX or uintXX
const size = parseInt ( match [ 3 ] ) ;
2022-11-09 10:57:02 +03:00
( 0 , index _js _1 . assertArgument ) ( size !== 0 && size <= 256 && ( size % 8 ) === 0 , "invalid numeric width" , "type" , type ) ;
2022-09-05 23:57:11 +03:00
}
return type ;
}
// Make the Fragment constructors effectively private
const _guard = { } ;
const internal = Symbol . for ( "_ethers_internal" ) ;
const ParamTypeInternal = "_ParamTypeInternal" ;
2022-10-01 08:34:06 +03:00
const ErrorFragmentInternal = "_ErrorInternal" ;
const EventFragmentInternal = "_EventInternal" ;
const ConstructorFragmentInternal = "_ConstructorInternal" ;
2023-01-31 06:29:09 +03:00
const FallbackFragmentInternal = "_FallbackInternal" ;
2022-10-01 08:34:06 +03:00
const FunctionFragmentInternal = "_FunctionInternal" ;
const StructFragmentInternal = "_StructInternal" ;
2022-12-30 19:30:03 +03:00
/ * *
2023-06-02 00:52:58 +03:00
* Each input and output of a [ [ Fragment ] ] is an Array of * * ParamType * * .
2022-12-30 19:30:03 +03:00
* /
2022-09-05 23:57:11 +03:00
class ParamType {
2022-12-30 19:30:03 +03:00
/ * *
* The local name of the parameter ( or ` ` "" ` ` if unbound )
* /
2022-09-05 23:57:11 +03:00
name ;
2022-12-30 19:30:03 +03:00
/ * *
* The fully qualified type ( e . g . ` ` "address" ` ` , ` ` "tuple(address)" ` ` ,
* ` ` "uint256[3][]" ` ` )
* /
2022-09-05 23:57:11 +03:00
type ;
2022-12-30 19:30:03 +03:00
/ * *
* The base type ( e . g . ` ` "address" ` ` , ` ` "tuple" ` ` , ` ` "array" ` ` )
* /
2022-09-05 23:57:11 +03:00
baseType ;
2022-12-30 19:30:03 +03:00
/ * *
* True if the parameters is indexed .
*
2023-02-13 06:14:26 +03:00
* For non - indexable types this is ` ` null ` ` .
2022-12-30 19:30:03 +03:00
* /
2022-09-05 23:57:11 +03:00
indexed ;
2022-12-30 19:30:03 +03:00
/ * *
* The components for the tuple .
*
2023-02-13 06:14:26 +03:00
* For non - tuple types this is ` ` null ` ` .
2022-12-30 19:30:03 +03:00
* /
2022-09-05 23:57:11 +03:00
components ;
2022-12-30 19:30:03 +03:00
/ * *
* The array length , or ` ` - 1 ` ` for dynamic - lengthed arrays .
*
2023-02-13 06:14:26 +03:00
* For non - array types this is ` ` null ` ` .
2022-12-30 19:30:03 +03:00
* /
2022-09-05 23:57:11 +03:00
arrayLength ;
2022-12-30 19:30:03 +03:00
/ * *
* The type of each child in the array .
*
2023-02-13 06:14:26 +03:00
* For non - array types this is ` ` null ` ` .
2022-12-30 19:30:03 +03:00
* /
2022-09-05 23:57:11 +03:00
arrayChildren ;
2022-11-30 23:44:23 +03:00
/ * *
* @ private
* /
2022-09-05 23:57:11 +03:00
constructor ( guard , name , type , baseType , indexed , components , arrayLength , arrayChildren ) {
2022-09-16 05:58:45 +03:00
( 0 , index _js _1 . assertPrivate ) ( guard , _guard , "ParamType" ) ;
2022-09-05 23:57:11 +03:00
Object . defineProperty ( this , internal , { value : ParamTypeInternal } ) ;
if ( components ) {
components = Object . freeze ( components . slice ( ) ) ;
}
if ( baseType === "array" ) {
if ( arrayLength == null || arrayChildren == null ) {
throw new Error ( "" ) ;
}
}
else if ( arrayLength != null || arrayChildren != null ) {
throw new Error ( "" ) ;
}
if ( baseType === "tuple" ) {
if ( components == null ) {
throw new Error ( "" ) ;
}
}
else if ( components != null ) {
throw new Error ( "" ) ;
}
( 0 , index _js _1 . defineProperties ) ( this , {
name , type , baseType , indexed , components , arrayLength , arrayChildren
} ) ;
}
2022-12-30 19:30:03 +03:00
/ * *
* Return a string representation of this type .
*
* For example ,
*
* ` ` sighash " => " ( uint256 , address ) " ` `
*
* ` ` "minimal" => "tuple(uint256,address) indexed" ` `
*
* ` ` "full" => "tuple(uint256 foo, address bar) indexed baz" ` `
* /
2022-11-30 23:44:23 +03:00
format ( format ) {
if ( format == null ) {
format = "sighash" ;
}
2022-09-16 05:58:45 +03:00
if ( format === "json" ) {
2023-07-25 00:48:37 +03:00
const name = this . name || "" ;
2023-07-24 07:06:04 +03:00
if ( this . isArray ( ) ) {
const result = JSON . parse ( this . arrayChildren . format ( "json" ) ) ;
result . name = name ;
result . type += ` [ ${ ( this . arrayLength < 0 ? "" : String ( this . arrayLength ) ) } ] ` ;
return JSON . stringify ( result ) ;
}
const result = {
2022-09-05 23:57:11 +03:00
type : ( ( this . baseType === "tuple" ) ? "tuple" : this . type ) ,
2023-07-24 07:06:04 +03:00
name
2022-09-05 23:57:11 +03:00
} ;
if ( typeof ( this . indexed ) === "boolean" ) {
result . indexed = this . indexed ;
}
if ( this . isTuple ( ) ) {
result . components = this . components . map ( ( c ) => JSON . parse ( c . format ( format ) ) ) ;
}
return JSON . stringify ( result ) ;
}
let result = "" ;
// Array
if ( this . isArray ( ) ) {
result += this . arrayChildren . format ( format ) ;
result += ` [ ${ ( this . arrayLength < 0 ? "" : String ( this . arrayLength ) ) } ] ` ;
}
else {
if ( this . isTuple ( ) ) {
2022-09-16 05:58:45 +03:00
result += "(" + this . components . map ( ( comp ) => comp . format ( format ) ) . join ( ( format === "full" ) ? ", " : "," ) + ")" ;
2022-09-05 23:57:11 +03:00
}
else {
result += this . type ;
}
}
2022-09-16 05:58:45 +03:00
if ( format !== "sighash" ) {
2022-09-05 23:57:11 +03:00
if ( this . indexed === true ) {
result += " indexed" ;
}
2022-09-16 05:58:45 +03:00
if ( format === "full" && this . name ) {
2022-09-05 23:57:11 +03:00
result += " " + this . name ;
}
}
return result ;
}
2022-12-30 19:30:03 +03:00
/ * *
* Returns true if % % this % % is an Array type .
*
* This provides a type gaurd ensuring that [ [ arrayChildren ] ]
* and [ [ arrayLength ] ] are non - null .
* /
2022-09-05 23:57:11 +03:00
isArray ( ) {
return ( this . baseType === "array" ) ;
}
2022-12-30 19:30:03 +03:00
/ * *
* Returns true if % % this % % is a Tuple type .
*
* This provides a type gaurd ensuring that [ [ components ] ]
* is non - null .
* /
2022-09-05 23:57:11 +03:00
isTuple ( ) {
return ( this . baseType === "tuple" ) ;
}
2022-12-30 19:30:03 +03:00
/ * *
* Returns true if % % this % % is an Indexable type .
*
* This provides a type gaurd ensuring that [ [ indexed ] ]
* is non - null .
* /
2022-09-05 23:57:11 +03:00
isIndexable ( ) {
return ( this . indexed != null ) ;
}
2022-12-30 19:30:03 +03:00
/ * *
* Walks the * * ParamType * * with % % value % % , calling % % process % %
* on each type , destructing the % % value % % recursively .
* /
2022-09-05 23:57:11 +03:00
walk ( value , process ) {
if ( this . isArray ( ) ) {
if ( ! Array . isArray ( value ) ) {
2023-03-04 04:25:07 +03:00
throw new Error ( "invalid array value" ) ;
2022-09-05 23:57:11 +03:00
}
if ( this . arrayLength !== - 1 && value . length !== this . arrayLength ) {
throw new Error ( "array is wrong length" ) ;
}
2022-09-16 05:58:45 +03:00
const _this = this ;
return value . map ( ( v ) => ( _this . arrayChildren . walk ( v , process ) ) ) ;
2022-09-05 23:57:11 +03:00
}
if ( this . isTuple ( ) ) {
if ( ! Array . isArray ( value ) ) {
2023-03-04 04:25:07 +03:00
throw new Error ( "invalid tuple value" ) ;
2022-09-05 23:57:11 +03:00
}
if ( value . length !== this . components . length ) {
throw new Error ( "array is wrong length" ) ;
}
2022-09-16 05:58:45 +03:00
const _this = this ;
return value . map ( ( v , i ) => ( _this . components [ i ] . walk ( v , process ) ) ) ;
2022-09-05 23:57:11 +03:00
}
return process ( this . type , value ) ;
}
# walkAsync ( promises , value , process , setValue ) {
if ( this . isArray ( ) ) {
if ( ! Array . isArray ( value ) ) {
2023-03-04 04:25:07 +03:00
throw new Error ( "invalid array value" ) ;
2022-09-05 23:57:11 +03:00
}
if ( this . arrayLength !== - 1 && value . length !== this . arrayLength ) {
throw new Error ( "array is wrong length" ) ;
}
const childType = this . arrayChildren ;
const result = value . slice ( ) ;
result . forEach ( ( value , index ) => {
childType . # walkAsync ( promises , value , process , ( value ) => {
result [ index ] = value ;
} ) ;
} ) ;
setValue ( result ) ;
return ;
}
if ( this . isTuple ( ) ) {
const components = this . components ;
// Convert the object into an array
let result ;
if ( Array . isArray ( value ) ) {
result = value . slice ( ) ;
}
else {
if ( value == null || typeof ( value ) !== "object" ) {
2023-03-04 04:25:07 +03:00
throw new Error ( "invalid tuple value" ) ;
2022-09-05 23:57:11 +03:00
}
result = components . map ( ( param ) => {
if ( ! param . name ) {
throw new Error ( "cannot use object value with unnamed components" ) ;
}
if ( ! ( param . name in value ) ) {
throw new Error ( ` missing value for component ${ param . name } ` ) ;
}
return value [ param . name ] ;
} ) ;
}
2022-10-20 12:03:32 +03:00
if ( result . length !== this . components . length ) {
2022-09-05 23:57:11 +03:00
throw new Error ( "array is wrong length" ) ;
}
result . forEach ( ( value , index ) => {
components [ index ] . # walkAsync ( promises , value , process , ( value ) => {
result [ index ] = value ;
} ) ;
} ) ;
setValue ( result ) ;
return ;
}
const result = process ( this . type , value ) ;
if ( result . then ) {
promises . push ( ( async function ( ) { setValue ( await result ) ; } ) ( ) ) ;
}
else {
setValue ( result ) ;
}
}
2022-12-30 19:30:03 +03:00
/ * *
* Walks the * * ParamType * * with % % value % % , asynchronously calling
* % % process % % on each type , destructing the % % value % % recursively .
*
* This can be used to resolve ENS naes by walking and resolving each
* ` ` "address" ` ` type .
* /
2022-09-05 23:57:11 +03:00
async walkAsync ( value , process ) {
const promises = [ ] ;
const result = [ value ] ;
this . # walkAsync ( promises , value , process , ( value ) => {
result [ 0 ] = value ;
} ) ;
if ( promises . length ) {
await Promise . all ( promises ) ;
}
return result [ 0 ] ;
}
2022-12-30 19:30:03 +03:00
/ * *
* Creates a new * * ParamType * * for % % obj % % .
*
* If % % allowIndexed % % then the ` ` indexed ` ` keyword is permitted ,
* otherwise the ` ` indexed ` ` keyword will throw an error .
* /
2022-09-05 23:57:11 +03:00
static from ( obj , allowIndexed ) {
if ( ParamType . isParamType ( obj ) ) {
return obj ;
}
if ( typeof ( obj ) === "string" ) {
2023-07-24 07:06:04 +03:00
try {
return ParamType . from ( lex ( obj ) , allowIndexed ) ;
}
catch ( error ) {
( 0 , index _js _1 . assertArgument ) ( false , "invalid param type" , "obj" , obj ) ;
}
2022-10-01 08:34:06 +03:00
}
else if ( obj instanceof TokenString ) {
let type = "" , baseType = "" ;
let comps = null ;
if ( consumeKeywords ( obj , setify ( [ "tuple" ] ) ) . has ( "tuple" ) || obj . peekType ( "OPEN_PAREN" ) ) {
// Tuple
baseType = "tuple" ;
comps = obj . popParams ( ) . map ( ( t ) => ParamType . from ( t ) ) ;
type = ` tuple( ${ comps . map ( ( c ) => c . format ( ) ) . join ( "," ) } ) ` ;
}
else {
// Normal
type = verifyBasicType ( obj . popType ( "TYPE" ) ) ;
baseType = type ;
}
// Check for Array
let arrayChildren = null ;
let arrayLength = null ;
while ( obj . length && obj . peekType ( "BRACKET" ) ) {
const bracket = obj . pop ( ) ; //arrays[i];
arrayChildren = new ParamType ( _guard , "" , type , baseType , null , comps , arrayLength , arrayChildren ) ;
arrayLength = bracket . value ;
type += bracket . text ;
baseType = "array" ;
comps = null ;
}
let indexed = null ;
const keywords = consumeKeywords ( obj , KwModifiers ) ;
if ( keywords . has ( "indexed" ) ) {
if ( ! allowIndexed ) {
throw new Error ( "" ) ;
}
indexed = true ;
}
const name = ( obj . peekType ( "ID" ) ? obj . pop ( ) . text : "" ) ;
if ( obj . length ) {
throw new Error ( "leftover tokens" ) ;
}
return new ParamType ( _guard , name , type , baseType , indexed , comps , arrayLength , arrayChildren ) ;
2022-09-05 23:57:11 +03:00
}
const name = obj . name ;
2023-02-04 11:26:34 +03:00
( 0 , index _js _1 . assertArgument ) ( ! name || ( typeof ( name ) === "string" && name . match ( regexId ) ) , "invalid name" , "obj.name" , name ) ;
2022-09-05 23:57:11 +03:00
let indexed = obj . indexed ;
if ( indexed != null ) {
2022-11-09 10:57:02 +03:00
( 0 , index _js _1 . assertArgument ) ( allowIndexed , "parameter cannot be indexed" , "obj.indexed" , obj . indexed ) ;
2022-09-05 23:57:11 +03:00
indexed = ! ! indexed ;
}
let type = obj . type ;
let arrayMatch = type . match ( regexArrayType ) ;
if ( arrayMatch ) {
2023-01-27 07:36:26 +03:00
const arrayLength = parseInt ( arrayMatch [ 2 ] || "-1" ) ;
2022-09-05 23:57:11 +03:00
const arrayChildren = ParamType . from ( {
type : arrayMatch [ 1 ] ,
components : obj . components
} ) ;
2023-01-23 00:47:02 +03:00
return new ParamType ( _guard , name || "" , type , "array" , indexed , null , arrayLength , arrayChildren ) ;
2022-09-05 23:57:11 +03:00
}
2023-02-19 06:18:42 +03:00
if ( type === "tuple" || type . startsWith ( "tuple(" /* fix: ) */ ) || type . startsWith ( "(" /* fix: ) */ ) ) {
2022-09-05 23:57:11 +03:00
const comps = ( obj . components != null ) ? obj . components . map ( ( c ) => ParamType . from ( c ) ) : null ;
2023-01-23 00:47:02 +03:00
const tuple = new ParamType ( _guard , name || "" , type , "tuple" , indexed , comps , null , null ) ;
2022-09-05 23:57:11 +03:00
// @TODO: use lexer to validate and normalize type
return tuple ;
}
type = verifyBasicType ( obj . type ) ;
2023-01-23 00:47:02 +03:00
return new ParamType ( _guard , name || "" , type , type , indexed , null , null , null ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-30 19:30:03 +03:00
/ * *
* Returns true if % % value % % is a * * ParamType * * .
* /
2022-09-05 23:57:11 +03:00
static isParamType ( value ) {
return ( value && value [ internal ] === ParamTypeInternal ) ;
}
}
exports . ParamType = ParamType ;
2022-12-30 19:30:03 +03:00
/ * *
* An abstract class to represent An individual fragment from a parse ABI .
* /
2022-09-05 23:57:11 +03:00
class Fragment {
2022-12-30 19:30:03 +03:00
/ * *
* The type of the fragment .
* /
2022-09-05 23:57:11 +03:00
type ;
2022-12-30 19:30:03 +03:00
/ * *
* The inputs for the fragment .
* /
2022-09-05 23:57:11 +03:00
inputs ;
2022-11-30 23:44:23 +03:00
/ * *
* @ private
* /
2022-09-05 23:57:11 +03:00
constructor ( guard , type , inputs ) {
2022-09-16 05:58:45 +03:00
( 0 , index _js _1 . assertPrivate ) ( guard , _guard , "Fragment" ) ;
2022-09-05 23:57:11 +03:00
inputs = Object . freeze ( inputs . slice ( ) ) ;
( 0 , index _js _1 . defineProperties ) ( this , { type , inputs } ) ;
}
2022-12-30 19:30:03 +03:00
/ * *
* Creates a new * * Fragment * * for % % obj % % , wich can be any supported
* ABI frgament type .
* /
2022-09-05 23:57:11 +03:00
static from ( obj ) {
if ( typeof ( obj ) === "string" ) {
2023-01-31 06:29:09 +03:00
// Try parsing JSON...
2022-10-01 08:34:06 +03:00
try {
Fragment . from ( JSON . parse ( obj ) ) ;
}
catch ( e ) { }
2023-01-31 06:29:09 +03:00
// ...otherwise, use the human-readable lexer
2022-10-01 08:34:06 +03:00
return Fragment . from ( lex ( obj ) ) ;
2022-09-05 23:57:11 +03:00
}
if ( obj instanceof TokenString ) {
2023-01-31 06:29:09 +03:00
// Human-readable ABI (already lexed)
const type = obj . peekKeyword ( KwTypes ) ;
2022-10-01 08:34:06 +03:00
switch ( type ) {
case "constructor" : return ConstructorFragment . from ( obj ) ;
case "error" : return ErrorFragment . from ( obj ) ;
case "event" : return EventFragment . from ( obj ) ;
2023-01-31 06:29:09 +03:00
case "fallback" :
case "receive" :
return FallbackFragment . from ( obj ) ;
2022-10-01 08:34:06 +03:00
case "function" : return FunctionFragment . from ( obj ) ;
case "struct" : return StructFragment . from ( obj ) ;
}
2022-09-05 23:57:11 +03:00
}
2023-01-31 06:29:09 +03:00
else if ( typeof ( obj ) === "object" ) {
// JSON ABI
2022-10-01 08:34:06 +03:00
switch ( obj . type ) {
case "constructor" : return ConstructorFragment . from ( obj ) ;
case "error" : return ErrorFragment . from ( obj ) ;
case "event" : return EventFragment . from ( obj ) ;
2023-01-31 06:29:09 +03:00
case "fallback" :
case "receive" :
return FallbackFragment . from ( obj ) ;
2022-10-01 08:34:06 +03:00
case "function" : return FunctionFragment . from ( obj ) ;
case "struct" : return StructFragment . from ( obj ) ;
}
2023-01-31 06:29:09 +03:00
( 0 , index _js _1 . assert ) ( false , ` unsupported type: ${ obj . type } ` , "UNSUPPORTED_OPERATION" , {
operation : "Fragment.from"
} ) ;
2022-09-05 23:57:11 +03:00
}
2023-01-31 06:29:09 +03:00
( 0 , index _js _1 . assertArgument ) ( false , "unsupported frgament object" , "obj" , obj ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-30 19:30:03 +03:00
/ * *
* Returns true if % % value % % is a [ [ ConstructorFragment ] ] .
* /
2022-09-05 23:57:11 +03:00
static isConstructor ( value ) {
2022-10-01 08:34:06 +03:00
return ConstructorFragment . isFragment ( value ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-30 19:30:03 +03:00
/ * *
* Returns true if % % value % % is an [ [ ErrorFragment ] ] .
* /
2022-09-05 23:57:11 +03:00
static isError ( value ) {
2022-10-01 08:34:06 +03:00
return ErrorFragment . isFragment ( value ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-30 19:30:03 +03:00
/ * *
* Returns true if % % value % % is an [ [ EventFragment ] ] .
* /
2022-09-05 23:57:11 +03:00
static isEvent ( value ) {
2022-10-01 08:34:06 +03:00
return EventFragment . isFragment ( value ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-30 19:30:03 +03:00
/ * *
* Returns true if % % value % % is a [ [ FunctionFragment ] ] .
* /
2022-09-05 23:57:11 +03:00
static isFunction ( value ) {
2022-10-01 08:34:06 +03:00
return FunctionFragment . isFragment ( value ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-30 19:30:03 +03:00
/ * *
* Returns true if % % value % % is a [ [ StructFragment ] ] .
* /
2022-09-05 23:57:11 +03:00
static isStruct ( value ) {
2022-10-01 08:34:06 +03:00
return StructFragment . isFragment ( value ) ;
2022-09-05 23:57:11 +03:00
}
}
exports . Fragment = Fragment ;
2022-12-30 19:30:03 +03:00
/ * *
* An abstract class to represent An individual fragment
* which has a name from a parse ABI .
* /
2022-09-05 23:57:11 +03:00
class NamedFragment extends Fragment {
2022-12-30 19:30:03 +03:00
/ * *
* The name of the fragment .
* /
2022-09-05 23:57:11 +03:00
name ;
2022-11-30 23:44:23 +03:00
/ * *
* @ private
* /
2022-09-05 23:57:11 +03:00
constructor ( guard , type , name , inputs ) {
super ( guard , type , inputs ) ;
2023-02-04 11:26:34 +03:00
( 0 , index _js _1 . assertArgument ) ( typeof ( name ) === "string" && name . match ( regexId ) , "invalid identifier" , "name" , name ) ;
2022-09-05 23:57:11 +03:00
inputs = Object . freeze ( inputs . slice ( ) ) ;
( 0 , index _js _1 . defineProperties ) ( this , { name } ) ;
}
}
exports . NamedFragment = NamedFragment ;
function joinParams ( format , params ) {
2022-09-16 05:58:45 +03:00
return "(" + params . map ( ( p ) => p . format ( format ) ) . join ( ( format === "full" ) ? ", " : "," ) + ")" ;
2022-09-05 23:57:11 +03:00
}
2022-12-30 19:30:03 +03:00
/ * *
* A Fragment which represents a //Custom Error//.
* /
2022-09-05 23:57:11 +03:00
class ErrorFragment extends NamedFragment {
2022-11-30 23:44:23 +03:00
/ * *
* @ private
* /
2022-09-05 23:57:11 +03:00
constructor ( guard , name , inputs ) {
2022-09-16 05:58:45 +03:00
super ( guard , "error" , name , inputs ) ;
2022-10-01 08:34:06 +03:00
Object . defineProperty ( this , internal , { value : ErrorFragmentInternal } ) ;
2022-09-05 23:57:11 +03:00
}
2022-12-30 19:30:03 +03:00
/ * *
* The Custom Error selector .
* /
2022-09-16 05:58:45 +03:00
get selector ( ) {
return ( 0 , index _js _2 . id ) ( this . format ( "sighash" ) ) . substring ( 0 , 10 ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a string representation of this fragment as % % format % % .
* /
2022-11-30 23:44:23 +03:00
format ( format ) {
if ( format == null ) {
format = "sighash" ;
}
2022-09-16 05:58:45 +03:00
if ( format === "json" ) {
2022-09-05 23:57:11 +03:00
return JSON . stringify ( {
type : "error" ,
name : this . name ,
inputs : this . inputs . map ( ( input ) => JSON . parse ( input . format ( format ) ) ) ,
} ) ;
}
const result = [ ] ;
2022-09-16 05:58:45 +03:00
if ( format !== "sighash" ) {
2022-09-05 23:57:11 +03:00
result . push ( "error" ) ;
}
result . push ( this . name + joinParams ( format , this . inputs ) ) ;
return result . join ( " " ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a new * * ErrorFragment * * for % % obj % % .
* /
2022-10-01 08:34:06 +03:00
static from ( obj ) {
if ( ErrorFragment . isFragment ( obj ) ) {
return obj ;
}
if ( typeof ( obj ) === "string" ) {
return ErrorFragment . from ( lex ( obj ) ) ;
}
else if ( obj instanceof TokenString ) {
const name = consumeName ( "error" , obj ) ;
const inputs = consumeParams ( obj ) ;
consumeEoi ( obj ) ;
return new ErrorFragment ( _guard , name , inputs ) ;
}
return new ErrorFragment ( _guard , obj . name , obj . inputs ? obj . inputs . map ( ParamType . from ) : [ ] ) ;
2022-09-05 23:57:11 +03:00
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns ` ` true ` ` and provides a type guard if % % value % % is an
* * * ErrorFragment * * .
* /
2022-10-01 08:34:06 +03:00
static isFragment ( value ) {
return ( value && value [ internal ] === ErrorFragmentInternal ) ;
2022-09-05 23:57:11 +03:00
}
}
exports . ErrorFragment = ErrorFragment ;
2022-12-30 19:30:03 +03:00
/ * *
* A Fragment which represents an Event .
* /
2022-09-05 23:57:11 +03:00
class EventFragment extends NamedFragment {
2023-06-02 00:52:58 +03:00
/ * *
* Whether this event is anonymous .
* /
2022-09-05 23:57:11 +03:00
anonymous ;
2022-11-30 23:44:23 +03:00
/ * *
* @ private
* /
2022-09-05 23:57:11 +03:00
constructor ( guard , name , inputs , anonymous ) {
2022-09-16 05:58:45 +03:00
super ( guard , "event" , name , inputs ) ;
2022-10-01 08:34:06 +03:00
Object . defineProperty ( this , internal , { value : EventFragmentInternal } ) ;
2022-09-05 23:57:11 +03:00
( 0 , index _js _1 . defineProperties ) ( this , { anonymous } ) ;
}
2022-12-30 19:30:03 +03:00
/ * *
* The Event topic hash .
* /
2022-09-16 05:58:45 +03:00
get topicHash ( ) {
return ( 0 , index _js _2 . id ) ( this . format ( "sighash" ) ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a string representation of this event as % % format % % .
* /
2022-11-30 23:44:23 +03:00
format ( format ) {
if ( format == null ) {
format = "sighash" ;
}
2022-09-16 05:58:45 +03:00
if ( format === "json" ) {
2022-09-05 23:57:11 +03:00
return JSON . stringify ( {
type : "event" ,
anonymous : this . anonymous ,
name : this . name ,
inputs : this . inputs . map ( ( i ) => JSON . parse ( i . format ( format ) ) )
} ) ;
}
const result = [ ] ;
2022-09-16 05:58:45 +03:00
if ( format !== "sighash" ) {
2022-09-05 23:57:11 +03:00
result . push ( "event" ) ;
}
result . push ( this . name + joinParams ( format , this . inputs ) ) ;
2022-09-16 05:58:45 +03:00
if ( format !== "sighash" && this . anonymous ) {
2022-09-05 23:57:11 +03:00
result . push ( "anonymous" ) ;
}
return result . join ( " " ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Return the topic hash for an event with % % name % % and % % params % % .
* /
2023-02-02 12:05:47 +03:00
static getTopicHash ( name , params ) {
params = ( params || [ ] ) . map ( ( p ) => ParamType . from ( p ) ) ;
const fragment = new EventFragment ( _guard , name , params , false ) ;
return fragment . topicHash ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a new * * EventFragment * * for % % obj % % .
* /
2022-10-01 08:34:06 +03:00
static from ( obj ) {
if ( EventFragment . isFragment ( obj ) ) {
return obj ;
}
if ( typeof ( obj ) === "string" ) {
2023-07-24 07:06:04 +03:00
try {
return EventFragment . from ( lex ( obj ) ) ;
}
catch ( error ) {
( 0 , index _js _1 . assertArgument ) ( false , "invalid event fragment" , "obj" , obj ) ;
}
2022-10-01 08:34:06 +03:00
}
else if ( obj instanceof TokenString ) {
const name = consumeName ( "event" , obj ) ;
const inputs = consumeParams ( obj , true ) ;
const anonymous = ! ! consumeKeywords ( obj , setify ( [ "anonymous" ] ) ) . has ( "anonymous" ) ;
consumeEoi ( obj ) ;
return new EventFragment ( _guard , name , inputs , anonymous ) ;
}
return new EventFragment ( _guard , obj . name , obj . inputs ? obj . inputs . map ( ( p ) => ParamType . from ( p , true ) ) : [ ] , ! ! obj . anonymous ) ;
2022-09-05 23:57:11 +03:00
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns ` ` true ` ` and provides a type guard if % % value % % is an
* * * EventFragment * * .
* /
2022-10-01 08:34:06 +03:00
static isFragment ( value ) {
return ( value && value [ internal ] === EventFragmentInternal ) ;
2022-09-05 23:57:11 +03:00
}
}
exports . EventFragment = EventFragment ;
2022-12-30 19:30:03 +03:00
/ * *
* A Fragment which represents a constructor .
* /
2022-09-05 23:57:11 +03:00
class ConstructorFragment extends Fragment {
2023-06-02 00:52:58 +03:00
/ * *
* Whether the constructor can receive an endowment .
* /
2022-09-05 23:57:11 +03:00
payable ;
2023-06-02 00:52:58 +03:00
/ * *
* The recommended gas limit for deployment or ` ` null ` ` .
* /
2022-09-05 23:57:11 +03:00
gas ;
2022-11-30 23:44:23 +03:00
/ * *
* @ private
* /
2022-09-05 23:57:11 +03:00
constructor ( guard , type , inputs , payable , gas ) {
super ( guard , type , inputs ) ;
2022-10-01 08:34:06 +03:00
Object . defineProperty ( this , internal , { value : ConstructorFragmentInternal } ) ;
2022-09-05 23:57:11 +03:00
( 0 , index _js _1 . defineProperties ) ( this , { payable , gas } ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a string representation of this constructor as % % format % % .
* /
2022-11-30 23:44:23 +03:00
format ( format ) {
( 0 , index _js _1 . assert ) ( format != null && format !== "sighash" , "cannot format a constructor for sighash" , "UNSUPPORTED_OPERATION" , { operation : "format(sighash)" } ) ;
2022-09-16 05:58:45 +03:00
if ( format === "json" ) {
2022-09-05 23:57:11 +03:00
return JSON . stringify ( {
type : "constructor" ,
stateMutability : ( this . payable ? "payable" : "undefined" ) ,
payable : this . payable ,
gas : ( ( this . gas != null ) ? this . gas : undefined ) ,
inputs : this . inputs . map ( ( i ) => JSON . parse ( i . format ( format ) ) )
} ) ;
}
const result = [ ` constructor ${ joinParams ( format , this . inputs ) } ` ] ;
2023-11-01 23:17:49 +03:00
if ( this . payable ) {
result . push ( "payable" ) ;
}
2022-09-05 23:57:11 +03:00
if ( this . gas != null ) {
result . push ( ` @ ${ this . gas . toString ( ) } ` ) ;
}
return result . join ( " " ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a new * * ConstructorFragment * * for % % obj % % .
* /
2022-10-01 08:34:06 +03:00
static from ( obj ) {
if ( ConstructorFragment . isFragment ( obj ) ) {
return obj ;
}
if ( typeof ( obj ) === "string" ) {
2023-07-24 07:06:04 +03:00
try {
return ConstructorFragment . from ( lex ( obj ) ) ;
}
catch ( error ) {
( 0 , index _js _1 . assertArgument ) ( false , "invalid constuctor fragment" , "obj" , obj ) ;
}
2022-10-01 08:34:06 +03:00
}
else if ( obj instanceof TokenString ) {
consumeKeywords ( obj , setify ( [ "constructor" ] ) ) ;
const inputs = consumeParams ( obj ) ;
2023-07-28 21:50:56 +03:00
const payable = ! ! consumeKeywords ( obj , KwVisibDeploy ) . has ( "payable" ) ;
2022-10-01 08:34:06 +03:00
const gas = consumeGas ( obj ) ;
consumeEoi ( obj ) ;
return new ConstructorFragment ( _guard , "constructor" , inputs , payable , gas ) ;
}
return new ConstructorFragment ( _guard , "constructor" , obj . inputs ? obj . inputs . map ( ParamType . from ) : [ ] , ! ! obj . payable , ( obj . gas != null ) ? obj . gas : null ) ;
2022-09-05 23:57:11 +03:00
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns ` ` true ` ` and provides a type guard if % % value % % is a
* * * ConstructorFragment * * .
* /
2022-10-01 08:34:06 +03:00
static isFragment ( value ) {
return ( value && value [ internal ] === ConstructorFragmentInternal ) ;
2022-09-05 23:57:11 +03:00
}
}
exports . ConstructorFragment = ConstructorFragment ;
2023-01-31 06:29:09 +03:00
/ * *
* A Fragment which represents a method .
* /
class FallbackFragment extends Fragment {
/ * *
* If the function can be sent value during invocation .
* /
payable ;
constructor ( guard , inputs , payable ) {
super ( guard , "fallback" , inputs ) ;
Object . defineProperty ( this , internal , { value : FallbackFragmentInternal } ) ;
( 0 , index _js _1 . defineProperties ) ( this , { payable } ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a string representation of this fallback as % % format % % .
* /
2023-01-31 06:29:09 +03:00
format ( format ) {
const type = ( ( this . inputs . length === 0 ) ? "receive" : "fallback" ) ;
if ( format === "json" ) {
const stateMutability = ( this . payable ? "payable" : "nonpayable" ) ;
return JSON . stringify ( { type , stateMutability } ) ;
}
return ` ${ type } () ${ this . payable ? " payable" : "" } ` ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a new * * FallbackFragment * * for % % obj % % .
* /
2023-01-31 06:29:09 +03:00
static from ( obj ) {
if ( FallbackFragment . isFragment ( obj ) ) {
return obj ;
}
if ( typeof ( obj ) === "string" ) {
2023-07-24 07:06:04 +03:00
try {
return FallbackFragment . from ( lex ( obj ) ) ;
}
catch ( error ) {
( 0 , index _js _1 . assertArgument ) ( false , "invalid fallback fragment" , "obj" , obj ) ;
}
2023-01-31 06:29:09 +03:00
}
else if ( obj instanceof TokenString ) {
const errorObj = obj . toString ( ) ;
const topIsValid = obj . peekKeyword ( setify ( [ "fallback" , "receive" ] ) ) ;
( 0 , index _js _1 . assertArgument ) ( topIsValid , "type must be fallback or receive" , "obj" , errorObj ) ;
const type = obj . popKeyword ( setify ( [ "fallback" , "receive" ] ) ) ;
// receive()
if ( type === "receive" ) {
const inputs = consumeParams ( obj ) ;
( 0 , index _js _1 . assertArgument ) ( inputs . length === 0 , ` receive cannot have arguments ` , "obj.inputs" , inputs ) ;
consumeKeywords ( obj , setify ( [ "payable" ] ) ) ;
consumeEoi ( obj ) ;
return new FallbackFragment ( _guard , [ ] , true ) ;
}
// fallback() [payable]
// fallback(bytes) [payable] returns (bytes)
let inputs = consumeParams ( obj ) ;
if ( inputs . length ) {
( 0 , index _js _1 . assertArgument ) ( inputs . length === 1 && inputs [ 0 ] . type === "bytes" , "invalid fallback inputs" , "obj.inputs" , inputs . map ( ( i ) => i . format ( "minimal" ) ) . join ( ", " ) ) ;
}
else {
inputs = [ ParamType . from ( "bytes" ) ] ;
}
const mutability = consumeMutability ( obj ) ;
( 0 , index _js _1 . assertArgument ) ( mutability === "nonpayable" || mutability === "payable" , "fallback cannot be constants" , "obj.stateMutability" , mutability ) ;
if ( consumeKeywords ( obj , setify ( [ "returns" ] ) ) . has ( "returns" ) ) {
const outputs = consumeParams ( obj ) ;
( 0 , index _js _1 . assertArgument ) ( outputs . length === 1 && outputs [ 0 ] . type === "bytes" , "invalid fallback outputs" , "obj.outputs" , outputs . map ( ( i ) => i . format ( "minimal" ) ) . join ( ", " ) ) ;
}
consumeEoi ( obj ) ;
return new FallbackFragment ( _guard , inputs , mutability === "payable" ) ;
}
if ( obj . type === "receive" ) {
return new FallbackFragment ( _guard , [ ] , true ) ;
}
if ( obj . type === "fallback" ) {
const inputs = [ ParamType . from ( "bytes" ) ] ;
const payable = ( obj . stateMutability === "payable" ) ;
return new FallbackFragment ( _guard , inputs , payable ) ;
}
( 0 , index _js _1 . assertArgument ) ( false , "invalid fallback description" , "obj" , obj ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns ` ` true ` ` and provides a type guard if % % value % % is a
* * * FallbackFragment * * .
* /
2023-01-31 06:29:09 +03:00
static isFragment ( value ) {
return ( value && value [ internal ] === FallbackFragmentInternal ) ;
}
}
exports . FallbackFragment = FallbackFragment ;
2022-12-30 19:30:03 +03:00
/ * *
* A Fragment which represents a method .
* /
2022-09-05 23:57:11 +03:00
class FunctionFragment extends NamedFragment {
2022-12-30 19:30:03 +03:00
/ * *
* If the function is constant ( e . g . ` ` pure ` ` or ` ` view ` ` functions ) .
* /
2022-09-05 23:57:11 +03:00
constant ;
2022-12-30 19:30:03 +03:00
/ * *
* The returned types for the result of calling this function .
* /
2022-09-05 23:57:11 +03:00
outputs ;
2022-12-30 19:30:03 +03:00
/ * *
* The state mutability ( e . g . ` ` payable ` ` , ` ` nonpayable ` ` , ` ` view ` `
* or ` ` pure ` ` )
* /
2022-09-05 23:57:11 +03:00
stateMutability ;
2022-12-30 19:30:03 +03:00
/ * *
2023-01-31 06:29:09 +03:00
* If the function can be sent value during invocation .
2022-12-30 19:30:03 +03:00
* /
2022-09-05 23:57:11 +03:00
payable ;
2022-12-30 19:30:03 +03:00
/ * *
2023-06-02 00:52:58 +03:00
* The recommended gas limit to send when calling this function .
2022-12-30 19:30:03 +03:00
* /
2022-09-05 23:57:11 +03:00
gas ;
2022-11-30 23:44:23 +03:00
/ * *
* @ private
* /
2022-09-05 23:57:11 +03:00
constructor ( guard , name , stateMutability , inputs , outputs , gas ) {
2022-09-16 05:58:45 +03:00
super ( guard , "function" , name , inputs ) ;
2022-10-01 08:34:06 +03:00
Object . defineProperty ( this , internal , { value : FunctionFragmentInternal } ) ;
2022-09-05 23:57:11 +03:00
outputs = Object . freeze ( outputs . slice ( ) ) ;
const constant = ( stateMutability === "view" || stateMutability === "pure" ) ;
const payable = ( stateMutability === "payable" ) ;
( 0 , index _js _1 . defineProperties ) ( this , { constant , gas , outputs , payable , stateMutability } ) ;
}
2022-12-30 19:30:03 +03:00
/ * *
* The Function selector .
* /
2022-09-16 05:58:45 +03:00
get selector ( ) {
return ( 0 , index _js _2 . id ) ( this . format ( "sighash" ) ) . substring ( 0 , 10 ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a string representation of this function as % % format % % .
* /
2022-11-30 23:44:23 +03:00
format ( format ) {
if ( format == null ) {
format = "sighash" ;
}
2022-09-16 05:58:45 +03:00
if ( format === "json" ) {
2022-09-05 23:57:11 +03:00
return JSON . stringify ( {
type : "function" ,
name : this . name ,
constant : this . constant ,
stateMutability : ( ( this . stateMutability !== "nonpayable" ) ? this . stateMutability : undefined ) ,
payable : this . payable ,
gas : ( ( this . gas != null ) ? this . gas : undefined ) ,
inputs : this . inputs . map ( ( i ) => JSON . parse ( i . format ( format ) ) ) ,
outputs : this . outputs . map ( ( o ) => JSON . parse ( o . format ( format ) ) ) ,
} ) ;
}
const result = [ ] ;
2022-09-16 05:58:45 +03:00
if ( format !== "sighash" ) {
2022-09-05 23:57:11 +03:00
result . push ( "function" ) ;
}
result . push ( this . name + joinParams ( format , this . inputs ) ) ;
2022-09-16 05:58:45 +03:00
if ( format !== "sighash" ) {
2022-09-05 23:57:11 +03:00
if ( this . stateMutability !== "nonpayable" ) {
result . push ( this . stateMutability ) ;
}
if ( this . outputs && this . outputs . length ) {
result . push ( "returns" ) ;
result . push ( joinParams ( format , this . outputs ) ) ;
}
if ( this . gas != null ) {
result . push ( ` @ ${ this . gas . toString ( ) } ` ) ;
}
}
return result . join ( " " ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Return the selector for a function with % % name % % and % % params % % .
* /
2023-02-02 12:05:47 +03:00
static getSelector ( name , params ) {
params = ( params || [ ] ) . map ( ( p ) => ParamType . from ( p ) ) ;
const fragment = new FunctionFragment ( _guard , name , "view" , params , [ ] , null ) ;
return fragment . selector ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a new * * FunctionFragment * * for % % obj % % .
* /
2022-10-01 08:34:06 +03:00
static from ( obj ) {
if ( FunctionFragment . isFragment ( obj ) ) {
return obj ;
}
if ( typeof ( obj ) === "string" ) {
2023-07-24 07:06:04 +03:00
try {
return FunctionFragment . from ( lex ( obj ) ) ;
}
catch ( error ) {
( 0 , index _js _1 . assertArgument ) ( false , "invalid function fragment" , "obj" , obj ) ;
}
2022-10-01 08:34:06 +03:00
}
else if ( obj instanceof TokenString ) {
const name = consumeName ( "function" , obj ) ;
const inputs = consumeParams ( obj ) ;
const mutability = consumeMutability ( obj ) ;
let outputs = [ ] ;
if ( consumeKeywords ( obj , setify ( [ "returns" ] ) ) . has ( "returns" ) ) {
outputs = consumeParams ( obj ) ;
}
const gas = consumeGas ( obj ) ;
consumeEoi ( obj ) ;
return new FunctionFragment ( _guard , name , mutability , inputs , outputs , gas ) ;
}
2023-04-06 11:37:10 +03:00
let stateMutability = obj . stateMutability ;
// Use legacy Solidity ABI logic if stateMutability is missing
if ( stateMutability == null ) {
stateMutability = "payable" ;
if ( typeof ( obj . constant ) === "boolean" ) {
stateMutability = "view" ;
if ( ! obj . constant ) {
stateMutability = "payable" ;
if ( typeof ( obj . payable ) === "boolean" && ! obj . payable ) {
stateMutability = "nonpayable" ;
}
}
}
else if ( typeof ( obj . payable ) === "boolean" && ! obj . payable ) {
stateMutability = "nonpayable" ;
}
}
// @TODO: verifyState for stateMutability (e.g. throw if
// payable: false but stateMutability is "nonpayable")
return new FunctionFragment ( _guard , obj . name , stateMutability , obj . inputs ? obj . inputs . map ( ParamType . from ) : [ ] , obj . outputs ? obj . outputs . map ( ParamType . from ) : [ ] , ( obj . gas != null ) ? obj . gas : null ) ;
2022-09-05 23:57:11 +03:00
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns ` ` true ` ` and provides a type guard if % % value % % is a
* * * FunctionFragment * * .
* /
2022-10-01 08:34:06 +03:00
static isFragment ( value ) {
return ( value && value [ internal ] === FunctionFragmentInternal ) ;
2022-09-05 23:57:11 +03:00
}
}
exports . FunctionFragment = FunctionFragment ;
2022-12-30 19:30:03 +03:00
/ * *
* A Fragment which represents a structure .
* /
2022-09-05 23:57:11 +03:00
class StructFragment extends NamedFragment {
2022-11-30 23:44:23 +03:00
/ * *
* @ private
* /
2022-10-01 08:34:06 +03:00
constructor ( guard , name , inputs ) {
super ( guard , "struct" , name , inputs ) ;
Object . defineProperty ( this , internal , { value : StructFragmentInternal } ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a string representation of this struct as % % format % % .
* /
2022-09-05 23:57:11 +03:00
format ( ) {
throw new Error ( "@TODO" ) ;
}
2023-06-02 00:52:58 +03:00
/ * *
* Returns a new * * StructFragment * * for % % obj % % .
* /
2022-10-01 08:34:06 +03:00
static from ( obj ) {
if ( typeof ( obj ) === "string" ) {
2023-07-24 07:06:04 +03:00
try {
return StructFragment . from ( lex ( obj ) ) ;
}
catch ( error ) {
( 0 , index _js _1 . assertArgument ) ( false , "invalid struct fragment" , "obj" , obj ) ;
}
2022-10-01 08:34:06 +03:00
}
else if ( obj instanceof TokenString ) {
const name = consumeName ( "struct" , obj ) ;
const inputs = consumeParams ( obj ) ;
consumeEoi ( obj ) ;
return new StructFragment ( _guard , name , inputs ) ;
}
return new StructFragment ( _guard , obj . name , obj . inputs ? obj . inputs . map ( ParamType . from ) : [ ] ) ;
2022-09-05 23:57:11 +03:00
}
2023-06-02 00:52:58 +03:00
// @TODO: fix this return type
/ * *
* Returns ` ` true ` ` and provides a type guard if % % value % % is a
* * * StructFragment * * .
* /
2022-10-01 08:34:06 +03:00
static isFragment ( value ) {
return ( value && value [ internal ] === StructFragmentInternal ) ;
2022-09-05 23:57:11 +03:00
}
}
exports . StructFragment = StructFragment ;
//# sourceMappingURL=fragments.js.map