Skip to content

Commit

Permalink
Merge pull request #932 from PhilippeR26/decodeParameters
Browse files Browse the repository at this point in the history
feat: add provider.decodeParameters
  • Loading branch information
tabaktoni authored Jan 23, 2024
2 parents 12fa1bc + be6eec9 commit 5f20945
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 0 deletions.
78 changes: 78 additions & 0 deletions __tests__/cairo1v2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
compiledC210,
compiledC210Casm,
compiledComplexSierra,
compiledHelloSierra,
getTestAccount,
getTestProvider,
} from './config/fixtures';
Expand Down Expand Up @@ -673,6 +674,83 @@ describe('Cairo 1', () => {
expect(callDataFromObject).toStrictEqual(expectedResult);
expect(callDataFromArray).toStrictEqual(expectedResult);
});

test('myCallData.decodeParameters for Cairo 1', async () => {
const Cairo1HelloAbi = compiledHelloSierra;
const Cairo1Abi = compiledC1v2;
const helloCallData = new CallData(Cairo1HelloAbi.abi);
const c1v2CallData = new CallData(Cairo1Abi.abi);

const res2 = helloCallData.decodeParameters('hello::hello::UserData', ['0x123456', '0x1']);
expect(res2).toEqual({ address: 1193046n, is_claimed: true });
const res3 = helloCallData.decodeParameters(
['hello::hello::UserData', 'hello::hello::UserData'],
['0x123456', '0x1', '0x98765', '0x0']
);
expect(res3).toEqual([
{ address: 1193046n, is_claimed: true },
{ address: 624485n, is_claimed: false },
]);
const res4 = helloCallData.decodeParameters('core::integer::u8', ['0x123456']);
expect(res4).toBe(1193046n);
const res5 = helloCallData.decodeParameters('core::bool', ['0x1']);
expect(res5).toBe(true);
const res6 = helloCallData.decodeParameters('core::felt252', ['0x123456']);
expect(res6).toBe(1193046n);
const res7 = helloCallData.decodeParameters('core::integer::u256', ['0x123456', '0x789']);
expect(num.toHex(res7.toString())).toBe('0x78900000000000000000000000000123456');
const res8 = helloCallData.decodeParameters('core::array::Array::<core::integer::u16>', [
'2',
'0x123456',
'0x789',
]);
expect(res8).toEqual([1193046n, 1929n]);
const res9 = helloCallData.decodeParameters('core::array::Span::<core::integer::u16>', [
'2',
'0x123456',
'0x789',
]);
expect(res9).toEqual([1193046n, 1929n]);
const res10 = helloCallData.decodeParameters('(core::felt252, core::integer::u16)', [
'0x123456',
'0x789',
]);
expect(res10).toEqual({ '0': 1193046n, '1': 1929n });
const res11 = helloCallData.decodeParameters('core::starknet::eth_address::EthAddress', [
'0x123456',
]);
expect(res11).toBe(1193046n);
const res12 = helloCallData.decodeParameters(
'core::starknet::contract_address::ContractAddress',
['0x123456']
);
expect(res12).toBe(1193046n);
const res13 = helloCallData.decodeParameters('core::starknet::class_hash::ClassHash', [
'0x123456',
]);
expect(res13).toBe(1193046n);
const res14 = c1v2CallData.decodeParameters('core::option::Option::<core::integer::u8>', [
'0',
'0x12',
]);
expect(res14).toEqual({ Some: 18n, None: undefined });
const res15 = c1v2CallData.decodeParameters(
'core::result::Result::<hello_res_events_newTypes::hello_res_events_newTypes::Order, core::integer::u16>',
['0', '0x12', '0x345']
);
expect(res15).toEqual({ Ok: { p1: 18n, p2: 837n }, Err: undefined });
const res16 = c1v2CallData.decodeParameters(
'hello_res_events_newTypes::hello_res_events_newTypes::MyEnum',
['0', '0x12', '0x5678']
);
expect(res16).toEqual({
variant: {
Response: { p1: 18n, p2: 22136n },
Warning: undefined,
Error: undefined,
},
});
});
});

describe('Cairo1 Account contract', () => {
Expand Down
69 changes: 69 additions & 0 deletions __tests__/contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,75 @@ describe('Complex interaction', () => {
expect(callDataFromArray).toStrictEqual(expectedResult);
});

test('myCallData.decodeParameters for Cairo 0', async () => {
const myCallData = new CallData(erc20Echo20Contract.abi);

const res0 = myCallData.decodeParameters('felt', ['474107654995566025798705']);
expect(res0).toBe(474107654995566025798705n);
const res1 = myCallData.decodeParameters('StructY', [
'474107654995566025798705',
'3534634645645',
]);
expect(res1).toEqual({ y1: 474107654995566025798705n, y2: 3534634645645n });

const res2 = myCallData.decodeParameters('Uint256', ['47410765', '35346645']);
expect(res2).toEqual({ low: 47410765n, high: 35346645n });
const res3 = myCallData.decodeParameters('Struct32', ['47410765', '35346645', '1', '2', '3']);
expect(res3).toEqual({ b: 47410765n, c: { '0': 35346645n, '1': 1n, '2': 2n, '3': 3n } });

const res4 = myCallData.decodeParameters('(felt, felt, felt, felt)', [
'47410765',
'35346645',
'1',
'2',
]);
expect(res4).toEqual({ '0': 47410765n, '1': 35346645n, '2': 1n, '3': 2n });

const res5 = myCallData.decodeParameters('Struct2', ['47410765', '35346645', '1', '2', '3']);
expect(res5).toEqual({
info: { discount_fix_bps: 47410765n, discount_transfer_bps: 35346645n },
data: 1n,
data2: { min: 2n, max: 3n },
});
const res6 = myCallData.decodeParameters('Struct3', [
'47410765',
'35346645',
'1',
'2',
'3',
'4',
]);
expect(res6).toEqual({
a: 47410765n,
b: { b: 35346645n, c: { '0': 1n, '1': 2n, '2': 3n, '3': 4n } },
});
const res7 = myCallData.decodeParameters('(t1: felt, t2: StructX, t3: felt)', [
'47410765',
'35346645',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
]);
expect(res7).toEqual({
t1: 47410765n,
t2: {
x1: 35346645n,
x2: { y1: 1n, y2: 2n },
x3: {
tx1: { '0': 3n, '1': 4n },
tx2: { tx21: { tx211: 5n, tx212: 6n }, tx22: { '0': 7n, '1': 8n } },
},
},
t3: 9n,
});
});

test('invoke compiled data', async () => {
const result = await erc20Echo20Contract.iecho(CallData.compile(request));
const transaction = await provider.waitForTransaction(result.transaction_hash);
Expand Down
26 changes: 26 additions & 0 deletions src/utils/calldata/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
Abi,
AbiEnums,
AbiStructs,
AllowArray,
Args,
ArgsOrCalldata,
Calldata,
Expand Down Expand Up @@ -325,4 +326,29 @@ export class CallData {
const calldata = CallData.compile(raw);
return calldata.map((it) => toHex(it));
}

/**
* Parse the elements of a contract response and structure them into one or several Result.
* In Cairo 0, arrays are not supported.
* @param typeCairo string or string[] - Cairo type name, ex : "hello::hello::UserData"
* @param response string[] - serialized data corresponding to typeCairo.
* @return Result or Result[] - parsed response corresponding to typeData.
* @example
* const res2=helloCallData.decodeParameters("hello::hello::UserData",["0x123456","0x1"]);
* result = { address: 1193046n, is_claimed: true }
*/
public decodeParameters(typeCairo: AllowArray<string>, response: string[]): AllowArray<Result> {
const typeCairoArray = Array.isArray(typeCairo) ? typeCairo : [typeCairo];
const responseIterator = response.flat()[Symbol.iterator]();
const decodedArray = typeCairoArray.map(
(typeParam) =>
responseParser(
responseIterator,
{ name: '', type: typeParam },
this.structs,
this.enums
) as Result
);
return decodedArray.length === 1 ? decodedArray[0] : decodedArray;
}
}

0 comments on commit 5f20945

Please sign in to comment.