@@ -5,12 +5,7 @@ import {
55 BigNumberish ,
66 ByteArray ,
77 CairoEnum ,
8- Calldata ,
9- MultiType ,
108 ParsedStruct ,
11- RawArgs ,
12- RawArgsArray ,
13- StructAbi ,
149} from '../../types' ;
1510import { CairoUint256 } from '../cairoDataTypes/uint256' ;
1611import { CairoUint512 } from '../cairoDataTypes/uint512' ;
@@ -19,30 +14,30 @@ import { decodeShortString } from '../shortString';
1914import { stringFromByteArray } from './byteArray' ;
2015import { addHexPrefix , removeHexPrefix } from '../encode' ;
2116import {
22- isTypeFelt ,
2317 getArrayType ,
2418 isTypeArray ,
2519 isTypeBytes31 ,
2620 isTypeEnum ,
2721 isTypeBool ,
2822 isLen ,
23+ isCairo1Type ,
2924 isTypeByteArray ,
3025 isTypeSecp256k1Point ,
3126 isTypeOption ,
3227 isTypeResult ,
33- isTypeStruct ,
28+ isTypeEthAddress ,
3429 isTypeTuple ,
3530} from './cairo' ;
3631import {
3732 CairoCustomEnum ,
33+ CairoEnumRaw ,
3834 CairoOption ,
3935 CairoOptionVariant ,
4036 CairoResult ,
4137 CairoResultVariant ,
4238} from './enum' ;
4339import extractTupleMemberTypes from './tuple' ;
4440import assert from '../assert' ;
45- import { call } from 'abi-wan-kanabi' ;
4641
4742/**
4843 * Decode base types from calldata
@@ -79,11 +74,11 @@ function decodeBaseTypes(type: string, it: Iterator<string>):
7974
8075 return new CairoUint512 ( limb0 , limb1 , limb2 , limb3 ) . toBigInt ( ) ;
8176
82- case type === 'core::starknet::eth_address::EthAddress' :
77+ case isTypeEthAddress ( type ) :
8378 temp = it . next ( ) . value ;
8479 return BigInt ( temp ) ;
8580
86- case type === 'core::bytes_31::bytes31' :
81+ case isTypeBytes31 ( type ) :
8782 temp = it . next ( ) . value ;
8883 return decodeShortString ( temp ) ;
8984
@@ -102,34 +97,6 @@ function decodeBaseTypes(type: string, it: Iterator<string>):
10297 }
10398}
10499
105- /**
106- * Get the expected calldata length for a given enum variant.
107- * @param variantIndexCalldata The calldata for the variant index.
108- * @param enumName The name of the enum.
109- * @param enums The ABI enums.
110- * @returns The expected calldata length.
111- */
112- function getExpectedCalldataLengthForEnum (
113- variantIndexCalldata : string ,
114- enumName : string ,
115- enums : AbiEnums
116- ) : number {
117- const enumDefinition = enums [ enumName ] ;
118- assert ( enumDefinition , `Enum with name ${ enumName } not found.` ) ;
119-
120- const variantIndex = parseInt ( variantIndexCalldata , 10 ) ;
121- const variant = enumDefinition . variants [ variantIndex ] ;
122-
123- switch ( enumName ) {
124- case 'CairoOption' :
125- return variant . name === 'None' ? 1 : 2 ; // "None" requires only the index, "Some" requires additional data.
126- case 'CairoResult' :
127- return 2 ; // Both "Ok" and "Err" require additional data.
128- default :
129- return 1 ; // Assuming other enums don't have associated data by default.
130- }
131- }
132-
133100/**
134101 * Decodes calldata based on the provided type, using an iterator over the calldata.
135102 * @param calldataIterator Iterator over the encoded calldata strings.
@@ -144,10 +111,11 @@ function decodeCalldataValue(
144111 structs : AbiStructs ,
145112 enums : AbiEnums
146113) :
147- | Boolean
114+ | Boolean
148115 | ParsedStruct
149116 | BigNumberish
150117 | BigNumberish [ ]
118+ | any [ ]
151119 | CairoOption < any >
152120 | CairoResult < any , any >
153121 | CairoEnum
@@ -163,6 +131,7 @@ function decodeCalldataValue(
163131 const high = calldataIterator . next ( ) . value ;
164132 return new CairoUint256 ( low , high ) . toBigInt ( ) ;
165133 }
134+
166135 // type uint512 struct
167136 if ( CairoUint512 . isAbiType ( element . type ) ) {
168137 const limb0 = calldataIterator . next ( ) . value ;
@@ -171,6 +140,7 @@ function decodeCalldataValue(
171140 const limb3 = calldataIterator . next ( ) . value ;
172141 return new CairoUint512 ( limb0 , limb1 , limb2 , limb3 ) . toBigInt ( ) ;
173142 }
143+
174144 // type C1 ByteArray struct, representing a LongString
175145 if ( isTypeByteArray ( element . type ) ) {
176146 const parsedBytes31Arr : BigNumberish [ ] = [ ] ;
@@ -188,9 +158,75 @@ function decodeCalldataValue(
188158 return stringFromByteArray ( myByteArray ) ;
189159 }
190160
191- // type Bytes31 string
192- if ( isTypeBytes31 ( element . type ) ) {
193- return decodeShortString ( calldataIterator . next ( ) . value ) ;
161+ // type struct
162+ if ( structs && element . type in structs && structs [ element . type ] ) {
163+ if ( isTypeEthAddress ( element . type ) ) {
164+ return decodeBaseTypes ( element . type , calldataIterator ) ;
165+ }
166+ return structs [ element . type ] . members . reduce ( ( acc , el ) => {
167+ acc [ el . name ] = decodeCalldataValue ( calldataIterator , el , structs , enums ) ;
168+ return acc ;
169+ } , { } as any ) ;
170+ }
171+
172+ // type Enum (only CustomEnum)
173+ if ( enums && element . type in enums && enums [ element . type ] ) {
174+ const variantNum : number = Number ( calldataIterator . next ( ) . value ) ; // get variant number
175+ const rawEnum = enums [ element . type ] . variants . reduce ( ( acc , variant , num ) => {
176+ if ( num === variantNum ) {
177+ acc [ variant . name ] = decodeCalldataValue (
178+ calldataIterator ,
179+ { name : '' , type : variant . type } ,
180+ structs ,
181+ enums
182+ ) ;
183+ return acc ;
184+ }
185+ acc [ variant . name ] = undefined ;
186+ return acc ;
187+ } , { } as CairoEnumRaw ) ;
188+ // Option
189+ if ( isTypeOption ( element . type ) ) {
190+ const content = variantNum === CairoOptionVariant . Some ? rawEnum . Some : undefined ;
191+ return new CairoOption < Object > ( variantNum , content ) ;
192+ }
193+ // Result
194+ if ( isTypeResult ( element . type ) ) {
195+ let content : Object ;
196+ if ( variantNum === CairoResultVariant . Ok ) {
197+ content = rawEnum . Ok ;
198+ } else {
199+ content = rawEnum . Err ;
200+ }
201+ return new CairoResult < Object , Object > ( variantNum , content ) ;
202+ }
203+ // Cairo custom Enum
204+ const customEnum = new CairoCustomEnum ( rawEnum ) ;
205+ return customEnum ;
206+ }
207+
208+ // type tuple
209+ if ( isTypeTuple ( element . type ) ) {
210+ const memberTypes = extractTupleMemberTypes ( element . type ) ;
211+ return memberTypes . reduce ( ( acc , it : any , idx ) => {
212+ const name = it ?. name ? it . name : idx ;
213+ const type = it ?. type ? it . type : it ;
214+ const el = { name, type } ;
215+ acc [ name ] = decodeCalldataValue ( calldataIterator , el , structs , enums ) ;
216+ return acc ;
217+ } , { } as any ) ;
218+ }
219+
220+ // type c1 array
221+ if ( isTypeArray ( element . type ) ) {
222+ // eslint-disable-next-line no-case-declarations
223+ const parsedDataArr = [ ] ;
224+ const el : AbiEntry = { name : '' , type : getArrayType ( element . type ) } ;
225+ const len = BigInt ( calldataIterator . next ( ) . value ) ; // get length
226+ while ( parsedDataArr . length < len ) {
227+ parsedDataArr . push ( decodeCalldataValue ( calldataIterator , el , structs , enums ) ) ;
228+ }
229+ return parsedDataArr ;
194230 }
195231
196232 // base type
@@ -218,33 +254,19 @@ export default function decodeCalldataField(
218254 let temp = calldataIterator . next ( ) . value ;
219255 return BigInt ( temp ) ;
220256
221- case isTypeArray ( type ) : {
222- const elementType = getArrayType ( type ) ;
223- const elements : any [ ] = [ ] ;
224- let elementResult = calldataIterator . next ( ) ;
225- while ( ! elementResult . done ) {
226- elements . push ( decodeCalldataValue ( elementResult . value , elementType , structs , enums ) ) ;
227- elementResult = calldataIterator . next ( ) ;
228- }
229- return elements ;
230- }
257+ case ( structs && type in structs ) || isTypeTuple ( type ) :
258+ return decodeCalldataValue ( calldataIterator , input , structs , enums ) ;
231259
232- case isTypeStruct ( type , structs ) :
233- case isTypeTuple ( type ) :
234- const structOrTupleResult : RawArgs = { } ;
235- const memberTypes = structs [ type ] ?. members || extractTupleMemberTypes ( type ) ;
236- memberTypes . forEach ( member => {
237- structOrTupleResult [ member . name ] = decodeCalldataValue ( calldataIterator . next ( ) . value , member . type , structs , enums ) ;
238- } ) ;
239- return structOrTupleResult ;
260+ case enums && isTypeEnum ( type , enums ) :
261+ return decodeCalldataValue ( calldataIterator , input , structs , enums ) ;
240262
241- case isTypeFelt ( type ) :
242- case CairoUint256 . isAbiType ( type ) :
243- case isTypeEnum ( type , enums ) :
244- case isTypeBytes31 ( type ) :
245- return decodeCalldataValue ( calldataIterator . next ( ) . value , type , structs , enums ) ;
263+ case isTypeArray ( type ) :
264+ // C1 Array
265+ if ( isCairo1Type ( type ) ) {
266+ return decodeCalldataValue ( calldataIterator , input , structs , enums ) ;
267+ }
246268
247269 default :
248- throw new Error ( `Unsupported or unrecognized type: ${ type } ` ) ;
270+ return decodeBaseTypes ( type , calldataIterator ) ;
249271 }
250272}
0 commit comments