Skip to main content
Version: 5.14.1

Data transformation

This guide is the most important of all this documentation. Take your time, and read it carefully...

Cairo contracts and JavaScript/TypeScript languages do not have the same types of data. To exchange data with Starknet, the data have to be transformed and formatted in a list of numbers.

So, it's necessary to prepare the data before sending them to a contract. On the other side, when a contract sends data to your DAPP (result of a call), you also have to transform them before using them in your code.

In Starknet.js, you can perform these transformations manually, but you can take advantage of methods that performs these transformations.

Types of data


Cairo has 2 versions, involving 2 types of data:

  • Cairo 0: here, everything is felt, an integer on 251 bits.
    Available: array, struct, tuple, named tuple, a mix of these elements.
  • Cairo 1: with plethora of literal types: u8, u16, u32, usize, u64, u128, felt252, u256, bool, address.
    Available: array, struct, tuple, a mix of these elements.

Starknet.js is compatible with both versions.


Starknet is waiting a list of felts, and answers with the same format.

JavaScript / TypeScript

These types does not exist in JS/TS - you have Number, bigInt, string, array, objects... and types defined in libraries.

In Starknet.js, it's a bit ... complicated, you have the BigNumberish type and it can include:

  • String representing a number: "123", "0xabc2"
  • Number (max 53 bits): 123
  • BigInt (max 255 bits): 12345612345n
import { BigNumberish } from 'starknet';
const decimals: BigNumberish = 18;

Preparation of data before delivery

If your Cairo smart-contract is waiting a:

felt, u8, u16, u32, usize, u64, u128, felt252, address

Starknet is waiting a felt.
You can send to Starknet.js methods: bigNumberish.

await myContract.my_function(12, '13', '0xe', 15n);


Starknet is waiting a felt, containing 0 or 1.
You can send to Starknet.js methods: boolean, bigNumberish.

await myContract.my_function(true, 1);


Starknet is waiting 2 felts, the first including the lowest 128 bits, the second including the 128 highest bits.
You can send to Starknet.js methods: bigNumberish (Cairo 1 only), Uint256 object (both Cairo 0 & 1).

await myContract0.my_function({ low: 100, high: 0 }); // Cairo 0 & 1 contract
await myContract1.my_function(cairo.uint256(100)); // Cairo 0 & 1 contract
await myContract2.my_function(12345678, '13456789765', '0xe23a40b543f', 1534566734334n); // Cairo 1 contract

In specific cases that we will see hereunder, you can use an object, with the following format:

const a1: Uint256 = cairo.uint256(
const a2: Uint256 = {
low: '0xeb5337d9a885be319366b5205a414fdd',
high: '0x05f7cd1fd465baff2ba9d2d1501ad0a2',
const a3: Uint256 = { low: a1.low, high: a1.high };


Starknet is waiting a felt, including 31 ASCII characters max. You can send to Starknet.js methods: string, bigNumberish.

await myContract.my_function('Token', '0x0x534e5f4d41494e');

To encode yourself a string:

const encStr: string = shortString.encodeShortString('Stark');

To decode yourself a string:

const decStr: string = shortString.decodeShortString('0x7572692f706963742f7433382e6a7067');

the result is: "uri/pict/t38.jpg"


longString is a string that may contain more than 31 characters. Starknet is waiting an array of felt: string_len, string1, string2, ...
You can send to Starknet.js methods: string, bigNumberish[].

await myContract.my_function('http://addressOfMyERC721pictures/image1.jpg');

If you want to split yourself your longString in 31 chars substrings:

const splitted: string[] = shortString.splitLongString(

If you want to split yourself your longString in an array of felts:

const longString: string[] = shortString
.map((str) => shortString.encodeShortString(str));


Starknet is waiting a list of felts.
You can send to Starknet.js methods: cairo.tuple(), object.

const myTpl = cairo.tuple('0x0a', 200);
await myContract.my_function(myTpl);

To construct yourself your tuple:

const myTpl = { '0': '0x0a', '1': 200 };

named tuple

Only for Cairo 0.

Starknet is waiting a list of felts.
You can send to Starknet.js methods: an object, cairo.tuple(), list of bigNumberish.
From this ABI:

"name": "data2",
"type": "(min: felt, max: felt)"

you can create this code:

const namedTup = { min: '0x4e65ac6', max: 296735486n };
await myContract.my_function(namedTup);

It's not mandatory to create an object conform to the Cairo 0 named tuple, you can just use the cairo.tuple() function.


Starknet is waiting a list of felts.
You can send to Starknet.js methods: an object.

const myStruct = { type: 'TR1POST', tries: 8, isBridged: true };
await myContract.my_function(myStruct);


Starknet is waiting an array of felt: array_len, array1, array2, ...
You can send to Starknet.js methods: bigNumberish[].

Const myArray = [10, "0xaa", 567n];
await myContract.my_function(myArray);

Do not add the array_len parameter before your array ; Starknet.js will manage automatically this element.

complex types

You can mix and nest literals, arrays, structs and tuples.

Starknet is waiting a list of felt.
All these examples are valid:

type Order2 = {
p1: BigNumberish;
p2: BigNumberish[];
}; // struct
const myOrder2: Order2 = {
p1: 17,
p2: [234, 467456745457n, '0x56ec'],
const param1 = cairo.tuple(cairo.tuple(34, '0x5e'), 234n);
const param2 = [
[200, 201],
[202, 203],
[204, 205],
const param3 = [myOrder2, myOrder2];
const param4 = [cairo.tuple(251, 40000n), cairo.tuple(252, 40001n)];
await myContract.my_function(param1, param2, param3, param4);

Authorized types for Starknet.js methods

There are 12 methods using contract parameters. Some types are authorized for each method:

list of parameters

Only meta-class methods are using a list of parameters (as illustrated in the previous chapter).
A Meta-Class is a Class which has any of its properties determined at run-time. The Contract object uses a Contract's ABI to determine what methods are available.

await myContract.my_function('TOKEN', '13', [10, 11, 12], 135438734812n);
// or
const functionName = 'my_function';
await myContract[functionName]('TOKEN', '13', [10, 11, 12], 135438734812n);

Array of parameters

An array of parameters can be used as input:

const myParams = [{ x: 100, y: 200 }, 13, [10, 11, 12], cairo.uint256('0x295fa652e32b')];
const txResp = await account0.execute({
contractAddress: testAddress,
entrypoint: 'change_activity',
calldata: myParams,

All Starknet.js methods accepts this type of input, except meta-class, that needs 3 dots prefix:

const myParams = ['TOKEN', '13', [10, 11, 12], 135438734812n];
await myContract.my_function(...myParams);
// or
const functionName = 'my_function';
await myContract[functionName](...myParams);

Objects properties have to be ordered in accordance with the ABI.

Object (without ABI conformity check)

Use of objects allows a clear representation of the list of parameters:

const myParams = {
name: 'TOKEN',
decimals: '13',
amount: 135438734812n,
const deployResponse = await myAccount.deployContract({
classHash: contractClassHash,
constructorCalldata: myParams,

This type is available for: CallData.compile(), hash.calculateContractAddressFromHash, account.deployContract, account.deployAccount, account.execute

Objects properties have to be ordered in accordance with the ABI.

Object (with ABI conformity check)

This is the recommended type of inputs to use, especially for complex ABI.

const myFalseUint256 = { high: 1, low: 23456 }; // wrong order ; should be low first
type Order2 = {
p1: BigNumberish;
p2: BigNumberish[];
const myOrder2bis: Order2 = {
// wrong order ; p1 should be first
p2: [234, 467456745457n, '0x56ec'],
p1: '17',
const functionParameters: RawArgsObject = {
//wrong order ; all properties are mixed
active: true,
symbol: 'NIT',
initial_supply: myFalseUint256,
recipient: account0.address,
decimals: 18,
tupoftup: cairo.tuple(cairo.tuple(34, '0x5e'), myFalseUint256),
card: myOrder2bis,
longText: 'Zorg is back, for ever, here and everywhere',
array1: [100, 101, 102],
array2: [
[200, 201],
[202, 203],
[204, 205],
array3: [myOrder2bis, myOrder2bis],
array4: [myFalseUint256, myFalseUint256],
tuple1: cairo.tuple(40000n, myOrder2bis, [54, 55n, '0xae'], 'texte'),
name: 'niceToken',
array5: [cairo.tuple(251, 40000n), cairo.tuple(252, 40001n)],
const contractCallData: CallData = new CallData(compiledContractSierra.abi);
const myCalldata: Calldata = contractCallData.compile('constructor', functionParameters);
const deployResponse = await account0.deployContract({
classHash: contractClassHash,
constructorCalldata: myCalldata,
// or
const myCall: Call = myContract.populate('setup_elements', functionParameters);
const tx = await account0.execute(myCall);
// or
const myCall: Call = myContract.populate('get_elements', functionParameters);
const res = await myContract.get_elements(...myCall.calldata);

It can be used only with methods that knows the abi: Contract.populate, myCallData.compile.
Starknet.js will perform a full check of conformity with the ABI of the contract, reorder the objects properties if necessary, stop if something is wrong or missing, remove not requested properties, convert everything to Starknet format.
Starknet.js will alert earlier of errors in your parameters (with human comprehensible words), before call to Starknet. So, no more incomprehensible Starknet messages due to parameters construction.

If a property array_len has been added before an array , this property is ignored as it's automatically managed by Starknet.js.

Call, or Call[]

A Call is an object with this format:

type Call = {
contractAddress: string;
entrypoint: string;
calldata?: RawArgs;

and is only authorized with Account.execute . It can be generated manually or by Contract.populate():

const myCall: Call = myContract.populate('get_component', [100, recipient]);
// or
const myCall: Call = {
contractAddress: tokenContract.address,
entrypoint: 'get_component',
calldata: CallData.compile([100, recipient]),

const tx = await account0.execute(myCall);

It's particularly interesting when you want to invoke a function several times in the same transaction:

const myCall1: Call = myContract.populate('mint', { type: 7, qty: 10 });
const myCall2: Call = myContract.populate('mint', { type: 21, qty: 3 });
const myCall3: Call = myContract.populate('mint', { type: 2, qty: 1 });
const tx = await account0.execute([myCall1, myCall2, myCall3]);

Array of strings (representing numbers)

This type is particularly useful when you need the maximum of performance and speed in your code ; You have no automatic transformation, no checks with ABI, no parsing.

You provide to starknet.js the low level data expected by Starknet:

const specialParameters: Calldata = [
const getResponse = await myAccount.get_bal(specialParameters, { parseRequest: false });

To use with parseRequest: false (see hereunder).

summary table for arguments

These types of arguments can't be used at your convenience everywhere. Here is a table showing which types can be used in which function:

Functionarray of parametersordered objectnon ordered objectCall & MultiCalllist of parametersarray of strings (*)array of strings (**)
TypeScript type[]
{} RawArgsArray{} RawArgsObjectCall & Call[]...Calldatastring[]string[]
contract.metaClass() contract[metaclass]()✔️✔️✔️ / contract.invoke✔️✔️✔️

(with 3 params, incl. calldata)



account.deployContract / Account✔️✔️✔️
hash. calculateContract AddressFromHash✔️✔️✔️

(*) = with parseRequest: false
(**) = result of Calldata.compile, myCallData.compile, myContract.populate().calldata

Receive data from a Cairo contract

When you perform a call, the result depends of the contract language:

  • In Cairo 0, then answer is an object, with keys using the Cairo variables names. Example:
const amount = res.amount;
  • In Cairo 1, the result is a variable:
const amount =;
Type in Cairo 1Cairo 1 codeType expected in JS/TSJS/TS function to recover data
u8, u16, u32, usize, u64, u128, felt252, addressfunc get_v()->u128bigintconst res: bigint =
string representing an hex numberconst
const address: string = num.toHex(res);
u8, u16, u32, usizefunc get_v() -> u16number (53 bits max)const
const total: number = Number(res)
u256 (255 bits max)func get_v() -> u256bigintconst res: bigint =
array of u8, u16, u32, usize, u64, u128, felt252, addressfunc get_v() -> Array<u64>bigint[]const res: bigint[] =
shortString (31 ASCII characters max)func get_v() -> felt252stringconst
const title:string = shortString.decodeShortstring(res)
longStringfunc get_v() -> Array<felt252>stringconst
const longString = (shortStr: bigint) => { return shortString.decodeShortString( num.toHex( shortStr)) }).join("");
Tuplefunc get_v() -> (felt252, u8)Object {"0": bigint, "1": bigint}const res =
const res0: bigint = res["0"];
const results: bigint[] = Object.values(res)
Struct func get_v() -> MyStructMyStruct = { account: bigint, amount: bigint}const res: MyStruct =
complex arrayfunc get_v() -> Array<fMyStruct>MyStruct[]const res: MyStruct[] =

If you don't know if your Contract object is interacting with a Cairo 0 or a Cairo 1 contract, you have these methods:

import { cairo } from 'starknet';
const isCairo1: boolean = myContract.isCairo1();
const isAbiCairo1: boolean = cairo.isCairo1Abi(myAbi);

Parse configuration


If for any reason (mainly for speed of processing), you want to define yourself the low level parameters to send to Starknet, you can use the parseRequest option.
Parameters are an array of strings (representing numbers).

const txH = await myContract.send_tk(['2036735872918048433518', '5130580', '18'], {
parseRequest: false,


If for any reason, you want to receive a low level answer from Starknet, you can use the parseResponse option.

const result = await'get_bals', 100n, { parseResponse: false });

answer is an array of strings (representing numbers).


As seen above, the strings returned by Starknet are not automatically parsed, because ABI do not inform when a contract returns a string.
But there is a way to have an automatic parse of a string:

As an example, if a contract returns a struct containing a shortString and a longString:

{ name: felt252, description: Array<felt252> }

You can automate the strings parse with:

const formatAnswer = { name: 'string', description: 'string' };
const result = await myContract.get_text(calldata, {
parseRequest: true,
parseResponse: true,
formatResponse: formatAnswer,

The result will be an object, with 2 strings:

{ name: "Organic", description: "The best way to read a long string!!!" }