Serialization#
Data serialization#
starknet.py serializes python values to Cairo values and deserializes Cairo values to python values.
Attention
Serializing short strings to felts has been deprecated. Please use starknet_py.cairo.felt.encode_shortstring to create numeric value from string before passing value to serializer.
Expected Cairo type |
Accepted python types |
Example python values |
Comment |
---|---|---|---|
felt |
int |
|
Provided int must be in range [0;P) - P being the Prime used in cairo-vm. |
tuple |
any iterable of matching size |
|
Can nest other types apart from pointers |
named tuple |
dict or NamedTuple or |
|
|
struct |
dict with keys matching struct |
|
Can nest other types apart from pointers |
pointer/array (adds |
any iterable |
|
|
uint256 |
int or dict with |
|
Cairo type |
Python type |
---|---|
felt |
int |
tuple |
tuple |
named tuple |
|
struct |
dict with keys matching struct |
pointer/array |
list |
uint256 |
int |
Working with shortstrings#
To make working with short strings easier we provide some utility functions to translate between them and felt values. You can read more about how cairo treats shortstrings in the documentation.
Conversion functions and references:
from starknet_py.cairo.felt import decode_shortstring, encode_shortstring
# Convert a string literal to its felt value
encoded = encode_shortstring("myshortstring")
assert encoded == 0x6D7973686F7274737472696E67
# Decode a felt into a string
decoded = decode_shortstring(encoded)
assert decoded == "myshortstring"
Creating serializers from abi#
For most use cases using high level Contract
is enough - it handles serialization
and deserialization for you. If you need more flexibility you can use lower level serialization API, see Serializers
for more details.
AbiParser
transforms ABI into
Abi class
that can be used for creating serializers. This way you can
easily deserialize events or serialize function’s inputs. Remember to use the proper version of AbiParser
which depends on parsed ABI version.
Serializing function inputs and outputs#
from starknet_py.abi.v2 import AbiParser
"""
#[external(v0)]
fn test(ref self: ContractState, ref arg: felt252, arg1: felt252, arg2: felt252) -> felt252 {
let mut x = self.my_storage_var.read();
x += 1;
self.my_storage_var.write(x);
x + internal_func()
}
"""
abi = AbiParser(raw_abi_string).parse()
from starknet_py.serialization.factory import serializer_for_function_v1
# You can create serializer for function inputs/outputs by passing Abi.Function object to serializer_for_function
function_serializer = serializer_for_function_v1(abi.functions["test"])
# You can call function serializer like you would a normal function
assert [111, 222, 333] == function_serializer.serialize(arg=111, arg1=222, arg2=333)
assert [111, 222, 333] == function_serializer.serialize(111, 222, 333)
assert [111, 222, 333] == function_serializer.serialize(111, 222, arg2=333)
# You can use deserialized result from function serializer like a tuple
result = function_serializer.deserialize([1])
(success,) = result
assert success == 1
Serializing events#
Events emitted by contracts can also be serialized, having provided the correct ABI
from starknet_py.serialization import serializer_for_event
"""
#[event]
#[derive(Drop, starknet::Event)]
struct Approval {
owner: ContractAddress,
spender: ContractAddress,
value: u256,
}
"""
# You can create serializer for events by passing Abi.Event object to serializer_for_event
event_serializer = serializer_for_event(
abi.events["contracts_v2::erc20::ERC20::Approval"]
)
assert [1, 2, 3, 4] == event_serializer.serialize(
{"owner": 1, "spender": 2, "value": 3 + 4 * 2**128}
)
assert {
"owner": 1,
"spender": 2,
"value": 3 + 4 * 2**128,
} == event_serializer.deserialize([1, 2, 3, 4]).as_dict()