@@ -5,12 +5,7 @@ import {
5
5
BigNumberish ,
6
6
ByteArray ,
7
7
CairoEnum ,
8
- Calldata ,
9
- MultiType ,
10
8
ParsedStruct ,
11
- RawArgs ,
12
- RawArgsArray ,
13
- StructAbi ,
14
9
} from '../../types' ;
15
10
import { CairoUint256 } from '../cairoDataTypes/uint256' ;
16
11
import { CairoUint512 } from '../cairoDataTypes/uint512' ;
@@ -19,30 +14,30 @@ import { decodeShortString } from '../shortString';
19
14
import { stringFromByteArray } from './byteArray' ;
20
15
import { addHexPrefix , removeHexPrefix } from '../encode' ;
21
16
import {
22
- isTypeFelt ,
23
17
getArrayType ,
24
18
isTypeArray ,
25
19
isTypeBytes31 ,
26
20
isTypeEnum ,
27
21
isTypeBool ,
28
22
isLen ,
23
+ isCairo1Type ,
29
24
isTypeByteArray ,
30
25
isTypeSecp256k1Point ,
31
26
isTypeOption ,
32
27
isTypeResult ,
33
- isTypeStruct ,
28
+ isTypeEthAddress ,
34
29
isTypeTuple ,
35
30
} from './cairo' ;
36
31
import {
37
32
CairoCustomEnum ,
33
+ CairoEnumRaw ,
38
34
CairoOption ,
39
35
CairoOptionVariant ,
40
36
CairoResult ,
41
37
CairoResultVariant ,
42
38
} from './enum' ;
43
39
import extractTupleMemberTypes from './tuple' ;
44
40
import assert from '../assert' ;
45
- import { call } from 'abi-wan-kanabi' ;
46
41
47
42
/**
48
43
* Decode base types from calldata
@@ -79,11 +74,11 @@ function decodeBaseTypes(type: string, it: Iterator<string>):
79
74
80
75
return new CairoUint512 ( limb0 , limb1 , limb2 , limb3 ) . toBigInt ( ) ;
81
76
82
- case type === 'core::starknet::eth_address::EthAddress' :
77
+ case isTypeEthAddress ( type ) :
83
78
temp = it . next ( ) . value ;
84
79
return BigInt ( temp ) ;
85
80
86
- case type === 'core::bytes_31::bytes31' :
81
+ case isTypeBytes31 ( type ) :
87
82
temp = it . next ( ) . value ;
88
83
return decodeShortString ( temp ) ;
89
84
@@ -102,34 +97,6 @@ function decodeBaseTypes(type: string, it: Iterator<string>):
102
97
}
103
98
}
104
99
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
-
133
100
/**
134
101
* Decodes calldata based on the provided type, using an iterator over the calldata.
135
102
* @param calldataIterator Iterator over the encoded calldata strings.
@@ -144,10 +111,11 @@ function decodeCalldataValue(
144
111
structs : AbiStructs ,
145
112
enums : AbiEnums
146
113
) :
147
- | Boolean
114
+ | Boolean
148
115
| ParsedStruct
149
116
| BigNumberish
150
117
| BigNumberish [ ]
118
+ | any [ ]
151
119
| CairoOption < any >
152
120
| CairoResult < any , any >
153
121
| CairoEnum
@@ -163,6 +131,7 @@ function decodeCalldataValue(
163
131
const high = calldataIterator . next ( ) . value ;
164
132
return new CairoUint256 ( low , high ) . toBigInt ( ) ;
165
133
}
134
+
166
135
// type uint512 struct
167
136
if ( CairoUint512 . isAbiType ( element . type ) ) {
168
137
const limb0 = calldataIterator . next ( ) . value ;
@@ -171,6 +140,7 @@ function decodeCalldataValue(
171
140
const limb3 = calldataIterator . next ( ) . value ;
172
141
return new CairoUint512 ( limb0 , limb1 , limb2 , limb3 ) . toBigInt ( ) ;
173
142
}
143
+
174
144
// type C1 ByteArray struct, representing a LongString
175
145
if ( isTypeByteArray ( element . type ) ) {
176
146
const parsedBytes31Arr : BigNumberish [ ] = [ ] ;
@@ -188,9 +158,75 @@ function decodeCalldataValue(
188
158
return stringFromByteArray ( myByteArray ) ;
189
159
}
190
160
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 ;
194
230
}
195
231
196
232
// base type
@@ -218,33 +254,19 @@ export default function decodeCalldataField(
218
254
let temp = calldataIterator . next ( ) . value ;
219
255
return BigInt ( temp ) ;
220
256
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 ) ;
231
259
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 ) ;
240
262
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
+ }
246
268
247
269
default :
248
- throw new Error ( `Unsupported or unrecognized type: ${ type } ` ) ;
270
+ return decodeBaseTypes ( type , calldataIterator ) ;
249
271
}
250
272
}
0 commit comments