Skip to content

Commit 39795af

Browse files
Merge pull request #28 from Concordium/add-deserialization-of-contract-state
Add deserialization of contract state
2 parents 17342bb + e8b3f76 commit 39795af

13 files changed

+152
-6
lines changed

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44
[submodule "deps/concordium-base"]
55
path = deps/concordium-base
66
url = https://github.com/Concordium/concordium-base.git
7+
[submodule "deps/concordium-contracts-common"]
8+
path = deps/concordium-contracts-common
9+
url = https://github.com/Concordium/concordium-contracts-common.git
10+

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# Changelog
22

3-
## Unreleased
3+
## 0.6.0 2022-02-02
44

55
### Added
66

7+
- Function to deserialize contract state.
78
- Support for register data transaction.
89

910
## 0.5.1 2021-11-19

Cargo.lock

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ version = "0"
4444
path = "deps/concordium-base/rust-src/ps_sig"
4545
version = "0"
4646

47+
[dependencies.concordium-contracts-common]
48+
features = ["derive-serde"]
49+
path = "deps/concordium-contracts-common"
50+
version = "2.0.0"
51+
4752
[lib]
4853
name = "node_sdk_helpers"
4954
crate-type = ["cdylib"]

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,16 @@ const updateContractTransaction: AccountTransaction = {
666666

667667
Finally, to actually update the contract on the chain, send the constructed `updateContractTransaction` to the chain using `sendAccountTransaction`. (See [Send Account Transaction](#Send-Account-Transaction) for how to do this)
668668

669+
## Deserialize contract state
670+
The following example demonstrates how to deserialize a contract's state:
671+
672+
```js
673+
const contractName = "my-contract-name"
674+
const schema = Buffer.from(schemaSource); // Load schema from file
675+
const rawContractState = Buffer.from(stateSource); // Could be getinstanceInfo(...).model
676+
const state = deserializeContractState(contractName, schema, rawContractState);
677+
```
678+
669679
# Build
670680

671681
## Building for a release

deps/concordium-contracts-common

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@concordium/node-sdk",
3-
"version": "0.5.1",
3+
"version": "0.6.0",
44
"description": "Helpers for interacting with the Concordium node",
55
"repository": {
66
"type": "git",

rust-src/aux_functions.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ use std::collections::BTreeMap;
77
type ExampleCurve = G1;
88
use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};
99
use sha2::{Digest, Sha256};
10+
use concordium_contracts_common::{from_bytes, Cursor, schema};
11+
use hex;
12+
13+
use anyhow::{bail, Result, anyhow};
14+
use id::{account_holder::create_unsigned_credential, constants::AttributeKind, types::*};
15+
use pedersen_scheme::Value;
1016

1117
#[derive(SerdeSerialize, SerdeDeserialize)]
1218
pub struct CredId {
@@ -18,10 +24,6 @@ pub struct CredId {
1824
pub cred_id: ExampleCurve,
1925
}
2026

21-
use anyhow::{bail, Result};
22-
use id::{account_holder::create_unsigned_credential, constants::AttributeKind, types::*};
23-
use pedersen_scheme::Value;
24-
2527
pub fn generate_unsigned_credential_aux(input: &str) -> Result<String> {
2628
let v: SerdeValue = from_str(input)?;
2729
let ip_info: IpInfo<Bls12> = try_get(&v, "ipInfo")?;
@@ -176,3 +178,21 @@ pub fn get_credential_deployment_info_aux(
176178
let cdi_json = json!(cdi);
177179
Ok(cdi_json.to_string())
178180
}
181+
182+
/// Given the bytes of a contract's state, deserialize them to a json object, using the provided schema.
183+
/// Both the state bytes and the schema are given as hex-encoded strings.
184+
pub fn deserialize_state_aux(
185+
contract_name: &str,
186+
state_bytes: String,
187+
schema: String,
188+
) -> Result<String> {
189+
let module_schema: schema::Module = match from_bytes(&hex::decode(schema)?) {
190+
Ok(o) => o,
191+
Err(e) => return Err(anyhow!("unable to parse schema: {:#?}", e))
192+
};
193+
let mut state_cursor = Cursor::new(hex::decode(state_bytes)?);
194+
let contract_schema = module_schema.contracts.get(contract_name).ok_or(anyhow!("Unable to get contract schema: not included in module schema"))?;
195+
let state_schema = contract_schema.state.as_ref().ok_or(anyhow!("Unable to get state schema: not included in contract schema"))?;
196+
Ok(state_schema.to_json(&mut state_cursor).expect("Unable to parse state to json").to_string())
197+
}
198+

rust-src/external_functions.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,16 @@ pub fn get_credential_deployment_info_ext(
3333
Err(e) => format!("unable to get credential due to: {}", e),
3434
}
3535
}
36+
37+
#[wasm_bindgen(js_name = deserializeState)]
38+
pub fn deserialize_state(
39+
contract_name: &str,
40+
state_bytes: String,
41+
schema: String,
42+
) -> String {
43+
match deserialize_state_aux(contract_name, state_bytes, schema) {
44+
Ok(s) => s.to_string(),
45+
Err(e) => format!("{}", e),
46+
}
47+
}
48+

src/deserialization.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import * as wasm from '../pkg/node_sdk_helpers';
2+
import { Buffer } from 'buffer/';
3+
4+
/**
5+
* Given a contract's raw state, its name and its schema, return the state as a JSON object.
6+
* The return type is any, and the actual type should be determined by using the schema.
7+
*/
8+
export function deserializeContractState(
9+
contractName: string,
10+
schema: Buffer,
11+
state: Buffer
12+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
13+
): any {
14+
const serializedState = wasm.deserializeState(
15+
contractName,
16+
state.toString('hex'),
17+
schema.toString('hex')
18+
);
19+
try {
20+
return JSON.parse(serializedState);
21+
} catch (e) {
22+
throw new Error(
23+
'unable to deserialize state, due to: ' + serializedState
24+
); // In this case serializedState is the error message from the rust module
25+
}
26+
}

0 commit comments

Comments
 (0)