JSON parameters#
This guide explains how to interact with the CIS-2 smart contract functions by providing input JSON parameters. This guide uses the cis2-multi smart contract as a starting point, and then continues with a couple of custom input types.
See also
For a guide on how to interact with a smart contract using JSON parameters see Passing parameters in JSON format.
A smart contract implementing CIS-2 must export the following functions: transfer()
, updateOperator()
, balanceOf()
, operatorOf()
, and tokenMetadata()
. This topic briefly describes what the required functions do and how to interact with them using JSON parameters one by one.
transfer() and TransferParams#
Use the transfer()
function to transfer some amount of token A from one account to another. The parameter to the transfer function is an array of Transfer
s which is defined in CIS-2.
pub struct Transfer<T: IsTokenId, A: IsTokenAmount> {
/// The ID of the token being transferred.
pub token_id: T,
/// The amount of tokens being transferred.
pub amount: A,
/// The address owning the tokens being transferred.
pub from: Address,
/// The address receiving the tokens being transferred.
pub to: Receiver,
/// Additional data to include in the transfer.
/// Can be used for additional arguments.
pub data: AdditionalData,
}
The data types are self-explanatory, but token_id
is a generic type, meaning any ID type can be used. One last thing to note is that from
and to
can be both contract and account addresses.
#[receive(
contract = "cis-2",
name = "transfer",
parameter = "TransferParameter",
error = "ContractError",
enable_logger,
mutable
)]
In order to call the transfer()
function, TransferParameter
must provide the JSON object that includes the necessary elements of the Transfer
struct.
[
{
"token_id": "<TOKEN-ID>",
"amount": "<AMOUNT>",
"from": {
"Account": [
"<OWNER-ADDRESS>"
]
},
"to": {
"Account": [
"<RECIPIENT-ADDRESS>"
]
},
"data": ""
},
{
"token_id": "<TOKEN-ID>",
"amount": "<AMOUNT>",
"from": {
"Account": [
"<OWNER-ADDRESS>"
]
},
"to": {
"Contract": [
{
"index": <CONTRACT-INDEX>,
"subindex": <CONTRACT-SUBINDEX>
},
"onReceivingCIS2"
]
},
"data": ""
},
]
updateOperator() and UpdateOperatorParams#
Use the updateOperator()
function to assign/remove another address to act as an operator for an address.
UpdateOperatorParams
in updateOperator()
function is an array of UpdateOperator
values.
/// A single update of an operator.
#[derive(Debug, Serialize)]
pub struct UpdateOperator {
/// The update for this operator.
pub update: OperatorUpdate,
/// The address which is either added or removed as an operator.
/// Note: The address for whom this will become an operator is the sender of
/// the contract transaction.
pub operator: Address,
}
The OperatorUpdate
(the action to execute) is either UpdateOperator::Add
or UpdateOperator::Remove
and the operator to either add or remove is any Address
.
#[receive(
contract = "cis-2",
name = "updateOperator",
parameter = "UpdateOperatorParams",
error = "ContractError",
enable_logger,
mutable
)]
In order to add a contract with index 3
and subindex 0
as an operator the following JSON parameter should be used.
[
{
"update": {
"Add": []
},
"operator": {
"Contract": [
{
"index": 3,
"subindex": 0
}
]
}
}
]
balanceOf() and ContractBalanceOfQueryParams#
Use the balanceOf()
function to get a balance of a token in a given address. The balanceOf()
function is essentially a view function that returns ContractBalanceOfQueryResponse
which is an array of the token amounts of given addresses.
#[derive(Debug, Serialize)]
pub struct BalanceOfQuery<T: IsTokenId> {
/// The ID of the token for which to query the balance of.
pub token_id: T,
/// The address for which to query the balance of.
pub address: Address,
}
ContractBalanceOfQueryParams
is essentially BalanceQueryParams
which is an array of BalanceQuery
structs. As you can see in the details above, it accepts a generic type of token_id
and a type of address like an Account
or Contract
.
#[receive(
contract = "cis-2",
name = "balanceOf",
parameter = "ContractBalanceOfQueryParams",
return_value = "ContractBalanceOfQueryResponse",
error = "ContractError"
)]
In order to query the balance of account 3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G
of token "ff
and balance of account 3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G
of token "aa"
the following JSON parameter should be used.
[
{
"address": {
"Account": [
"3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G"
]
},
"token_id": "ff"
},
{
"address": {
"Account": [
"3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G"
]
},
"token_id": "aa"
}
]
operatorOf() and OperatorOfQueryParams#
Use the operatorOf()
function to check whether an address is an operator of a given contract address added by the updateOperator()
. It is a view function that returns OperatorOfQueryResponse
which is an array of booleans for the given addresses (if the address is_operator()
of the given contract index true
, else false
).
/// A query for the operator of a given address for a given token.
#[derive(Debug, Serialize)]
pub struct OperatorOfQuery {
/// The ID of the token for which to query the balance of.
pub owner: Address,
/// The address for which to check for being an operator of the owner.
pub address: Address,
}
OperatorOfQueryParams
is a vector of the OperatorOfQuery
struct shown above. It takes two arguments: the contract address, and the account address to check whether it is the operator or not.
#[receive(
contract = "cis-2",
name = "operatorOf",
parameter = "OperatorOfQueryParams",
return_value = "OperatorOfQueryResponse",
error = "ContractError"
)]
In order to check whether the contract at index 3
and subindex 0
is an operator of account 3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G
the following JSON should be used.
[
{
"owner": {
"Account": [
"3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G"
]
},
"address": {
"Contract": [
{
"index": 3,
"subindex": 0
}
]
}
}
]
tokenMetadata() and ContractTokenMetadataQueryParams#
Use the tokenMetadata()
function to retrieve the metadata URL of a token. It is a view function that returns a vector of TokenMetadataQueryResponse
which holds a MetadataUrl
struct that stores the URL and the hash.
/// The parameter type for the contract function `tokenMetadata`.
#[derive(Debug, Serialize)]
pub struct TokenMetadataQueryParams<T: IsTokenId> {
/// List of balance queries.
#[concordium(size_length = 2)]
pub queries: Vec<T>,
}
ContractTokenMetadataQueryParams
is an array of the TokenMetadataQueryParams
struct shown above. It takes the tokenId
as input, and since it is a generic type <T>
the tokenId could be anything.
#[receive(
contract = "cis-2",
name = "tokenMetadata",
parameter = "ContractTokenMetadataQueryParams",
return_value = "TokenMetadataQueryResponse",
error = "ContractError"
)]
In order to call the tokenMetadata()
function, provide a JSON array of token IDs to query as shown below.
[
"0000",
"ffac",
...
]