Hello,
I’m playing a bit around smart contract to familiarize myself with dapp principle and I am stuck trying to deserialize my contract state.
I have a website with the nodeJS SDK, the browser app and a smartcontract V1 on the TestNet.
I can instantiate the smartcontract with the following call :
concordiumHelpers.detectConcordiumProvider()
.then((provider) => {
provider
.connect()
.then((acc) => {
console.log("Account selected in the extension " + acc);
provider.sendTransaction(
acc,
concordiumSDK.AccountTransactionType.InitializeSmartContractInstance,
{
amount: new concordiumSDK.GtuAmount(0n),
moduleRef: new concordiumSDK.ModuleReference(
'6dd75e22895dc69e471a8a9f4199959f2779507850c4dfb7702d41655e458169'
),
contractName: 'tictactoebet',
maxContractExecutionEnergy: 30000n
} as concordiumSDK.InitContractPayload,
{
game_name: 'Game 1',
end: '2022-09-12T11:30:25Z',
},
'//8CAQAAAAwAAAB0aWN0YWN0b2ViZXQBABQAAgAAAAkAAABnYW1lX25hbWUWAgMAAABlbmQNBAAAAAMAAABiZXQEFAACAAAABAAAAG5hbWUWAhAAAABwbGF5ZXJfdG9fYmV0X29uFQIAAAADAAAAT25lAgMAAABUd28CFQUAAAALAAAAT25seUFjY291bnQCCgAAAEJldFRvb0xhdGUCCQAAAEJldENsb3NlZAIKAAAAQWxyZWFkeUJldAIQAAAATWlzc2luZ1BhcmFtZXRlcgIEAAAAam9pbgQUAAEAAAAEAAAAbmFtZRYCFQQAAAALAAAAT25seUFjY291bnQCCQAAAExvYmJ5RnVsbAIOAAAAQWxyZWFkeUFQbGF5ZXICEAAAAE1pc3NpbmdQYXJhbWV0ZXICBAAAAHZpZXcBFAAGAAAACQAAAGdhbWVfbmFtZRYCCgAAAGdhbWVfc3RhdGUVBAAAABEAAABXYWl0aW5nRm9yUGxheWVycwIFAAAAUmVhZHkCCgAAAEluUHJvZ3Jlc3MCCAAAAEZpbmlzaGVkAgkAAABiZXRfc3RhdGUVAgAAAAQAAABPcGVuAgYAAABDbG9zZWQCBwAAAHBsYXllcnMQAhQABAAAAAcAAABhY2NvdW50CwYAAABhbW91bnQKBAAAAG5hbWUWAggAAABwb3NpdGlvbhUCAAAAAwAAAE9uZQIDAAAAVHdvAggAAABnYW1ibGVycxACFAAEAAAABwAAAGFjY291bnQLBgAAAGFtb3VudAoGAAAAYmV0X29uFQIAAAADAAAAT25lAgMAAABUd28CBAAAAG5hbWUWAgMAAABlbmQNCgAAAHZpZXdfc3Rha2UBCg=='
)
.then((transaction_address) => {
console.log("Init contract response : " + transaction_address);
id = setInterval(checkTransactionStatus, 2000, transaction_address);
})
.catch((error) => console.log(error));
});
});
I get the index id that I can use later to call my smart contract instance.
I can call the view function of my contract to get the state to display in my page, but I’m a little bit stuck when trying to deserialize the response with the contract schema.
concordiumHelpers.detectConcordiumProvider()
.then((provider) => {
provider
.connect()
.then((acc) => {
console.log("Account selected in the extension " + acc);
provider.getJsonRpcClient().invokeContract({
method: `tictactoebet.view`,
contract: { index: index, subindex: 0n },
})
.then((view_state) => {
let rawContractState = Buffer.from(view_state.returnValue, 'hex');
let schema = Buffer.from('//8CAQAAAAwAAAB0aWN0YWN0b2ViZXQBABQAAgAAAAkAAABnYW1lX25hbWUWAgMAAABlbmQNBAAAAAMAAABiZXQEFAACAAAABAAAAG5hbWUWAhAAAABwbGF5ZXJfdG9fYmV0X29uFQIAAAADAAAAT25lAgMAAABUd28CFQUAAAALAAAAT25seUFjY291bnQCCgAAAEJldFRvb0xhdGUCCQAAAEJldENsb3NlZAIKAAAAQWxyZWFkeUJldAIQAAAATWlzc2luZ1BhcmFtZXRlcgIEAAAAam9pbgQUAAEAAAAEAAAAbmFtZRYCFQQAAAALAAAAT25seUFjY291bnQCCQAAAExvYmJ5RnVsbAIOAAAAQWxyZWFkeUFQbGF5ZXICEAAAAE1pc3NpbmdQYXJhbWV0ZXICBAAAAHZpZXcBFAAGAAAACQAAAGdhbWVfbmFtZRYCCgAAAGdhbWVfc3RhdGUVBAAAABEAAABXYWl0aW5nRm9yUGxheWVycwIFAAAAUmVhZHkCCgAAAEluUHJvZ3Jlc3MCCAAAAEZpbmlzaGVkAgkAAABiZXRfc3RhdGUVAgAAAAQAAABPcGVuAgYAAABDbG9zZWQCBwAAAHBsYXllcnMQAhQABAAAAAcAAABhY2NvdW50CwYAAABhbW91bnQKBAAAAG5hbWUWAggAAABwb3NpdGlvbhUCAAAAAwAAAE9uZQIDAAAAVHdvAggAAABnYW1ibGVycxACFAAEAAAABwAAAGFjY291bnQLBgAAAGFtb3VudAoGAAAAYmV0X29uFQIAAAADAAAAT25lAgMAAABUd28CBAAAAG5hbWUWAgMAAABlbmQNCgAAAHZpZXdfc3Rha2UBCg==', 'base64');
let state = concordiumSDK.deserializeContractState("tictactoebet", schema, rawContractState);
})
.catch((error) => console.log(error));
});
});
I’m try to follow this concordium-node-sdk-js/packages/common at 780163f40afb00572bf6f20ed1f786bffa9c4663 · Concordium/concordium-node-sdk-js · GitHub
Raw data returned : '0600000047616d6520310000000000000000000068fc763183010000'
hexadecimal schema: ffff02010000000c000000746963746163746f6562657401001400020000000900000067616d655f6e616d65160203000000656e640d040000000300000062657404140002000000040000006e616d65160210000000706c617965725f746f5f6265745f6f6e1502000000030000004f6e65020300000054776f0215050000000b0000004f6e6c794163636f756e74020a000000426574546f6f4c6174650209000000426574436c6f736564020a000000416c726561647942657402100000004d697373696e67506172616d6574657202040000006a6f696e04140001000000040000006e616d65160215040000000b0000004f6e6c794163636f756e7402090000004c6f62627946756c6c020e000000416c726561647941506c6179657202100000004d697373696e67506172616d65746572020400000076696577011400060000000900000067616d655f6e616d6516020a00000067616d655f737461746515040000001100000057616974696e67466f72506c617965727302050000005265616479020a000000496e50726f6772657373020800000046696e697368656402090000006265745f73746174651502000000040000004f70656e0206000000436c6f7365640207000000706c61796572731002140004000000070000006163636f756e740b06000000616d6f756e740a040000006e616d65160208000000706f736974696f6e1502000000030000004f6e65020300000054776f020800000067616d626c6572731002140004000000070000006163636f756e740b06000000616d6f756e740a060000006265745f6f6e1502000000030000004f6e65020300000054776f02040000006e616d65160203000000656e640d0a000000766965775f7374616b65010a
Result:
Error: unable to deserialize state, due to: unable to parse schema: ParseError
at I.deserializeContractState (concordium.min.js:2:11127)
The js seems to point to webassembly rust code in the rust-binding crate: concordium-node-sdk-js\packages\rust-bindings\src\aux_functions.rs:557
I reproduced the parse error with this sample test:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deserialize_state_aux() {
let contract_name = "tictactoebet";
let state_bytes = "0600000047616d6520310000000000000000000068fc763183010000".to_string();
let schema = "ffff02010000000c000000746963746163746f6562657401001400020000000900000067616d655f6e616d65160203000000656e640d040000000300000062657404140002000000040000006e616d65160210000000706c617965725f746f5f6265745f6f6e1502000000030000004f6e65020300000054776f0215050000000b0000004f6e6c794163636f756e74020a000000426574546f6f4c6174650209000000426574436c6f736564020a000000416c726561647942657402100000004d697373696e67506172616d6574657202040000006a6f696e04140001000000040000006e616d65160215040000000b0000004f6e6c794163636f756e7402090000004c6f62627946756c6c020e000000416c726561647941506c6179657202100000004d697373696e67506172616d65746572020400000076696577011400060000000900000067616d655f6e616d6516020a00000067616d655f737461746515040000001100000057616974696e67466f72506c617965727302050000005265616479020a000000496e50726f6772657373020800000046696e697368656402090000006265745f73746174651502000000040000004f70656e0206000000436c6f7365640207000000706c61796572731002140004000000070000006163636f756e740b06000000616d6f756e740a040000006e616d65160208000000706f736974696f6e1502000000030000004f6e65020300000054776f020800000067616d626c6572731002140004000000070000006163636f756e740b06000000616d6f756e740a060000006265745f6f6e1502000000030000004f6e65020300000054776f02040000006e616d65160203000000656e640d0a000000766965775f7374616b65010a".to_string();
let result = deserialize_state_aux(contract_name, state_bytes, schema);
dbg!(result); // ParseError
}
}
I see in the code contract V0, does this method works for smart-contract V1 ?
Is there another way to de-serialize data from the nodeJS SDK ?
Am I missing something obvious here ?
Thanks for any help