Codec & schema
Schemas are used in various places in the Lisk SDK to encode and decode the data that is retrieved or pushed to the database.
Schemas are specifically used in the following:
-
modules to define the accountSchema, which consists of module-specific properties that are added to each account by the module.
-
assets, for the schema, which defines the data structure and formats of the transaction asset.
-
modules and/or assets, to decode/encode other specific data from the database, such as blocks, transactions, account state, and chain state data.
Schema Format
Schemas must be defined as shown below, which is a modified JSON (JavaScript Object Notation), schema (see the JSON schema reference).
It is required to use camelCase for the key naming. |
If the data type of a property is either an object or an array , the type property must be used instead of dataType .
|
export const lnsAccountPropsSchema = {
$id: 'lisk/lns/lnsAccount',
type: 'object',
required: ['ownNodes', 'reverseLookup'],
properties: {
reverseLookup: {
dataType: 'bytes',
fieldNumber: 1,
},
ownNodes: {
type: 'array',
fieldNumber: 2,
items: {
dataType: 'bytes',
},
},
},
default: {
ownNodes: [],
reverseLookup: EMPTY_BUFFER,
},
};
$id
Unique identifier of the schema throughout the system.
The $id property is directly inherited from the JSON-schema.
You can read more about the id
property on https://json-schema.org/understanding-json-schema/structuring.html#id.
In general, adhere to the following criteria:
-
Use unique IDs across the system.
-
Use path like format for easy readability, (it is not an actual requirement).
-
in order to ensure no mixing of any schema with other registered schemas occurs, use one fixed identifier for your app in each ID.
-
`
required
Required schema properties.
Regarding account and asset schemas:
If the schema is used for serialization it is recommended to put all properties as required to guarantee the uniqueness of encoding.
|
Data types
The application data is stored in specific data types and structures in the database.
A schema always defines the data types that will be used in the database to store specific data. When the data is retrieved from the database by a module or plugin of the blockchain application, it is returned as a JavaScript object or JSON, depending on the context:
- JavaScript object
-
These data types are used internally in the blockchain application to handle data from the database.
- JSON
-
Data that is provided by actions and events is always returned in JSON format.
Data type | JavaScript object | JSON |
---|---|---|
string |
string |
string |
uint32 |
number |
number |
sint32 |
number |
number |
uint64 |
BigInt |
string |
sint64 |
BigInt |
string |
bytes |
Buffer |
string in hex format |
boolean |
boolean |
boolean |
Decoding and encoding data
With the API client
Please refer to the dedicated guide Decoding & encoding data.
With lisk-codec
To conveniently decode and encode the data structures stored on the blockchain, such as blocks, transactions, account state, and chain state, use the codec
library.
The library can be imported from the following NPM packages:
-
lisk-sdk
-
@liskhq/lisk-client
-
@liskhq/lisk-codec
codec
library from the lisk-sdk
packageconst {
codec,
} = require('lisk-sdk');
const CHAIN_STATE_KEY = "myContext:moreContext";
const schema = {
$id: "lisk/myContext/moreContext",
type: "object",
required: ["myCounter"],
properties: {
myCounter: {
dataType: "uint32",
fieldNumber: 1,
},
},
default: {
myCounter: 0
}
};
// Get data from the database
let counterBuffer = await stateStore.chain.get(
CHAIN_STATE_KEY
);
// Decode the retrieved data with the schema
let counter = codec.decode(
schema,
counterBuffer
);
// Mutate the retrieved data
counter.myCounter++;
// Post the data back to the database
await stateStore.chain.set(
CHAIN_STATE_KEY,
// Encode the data again before sending it to the DB
codec.encode(schema, counter)
);
Converting between formats
Account addresses are stored as binary data in the database. However, in other parts of the application, the data is expected as a hexadecimal string, which is more human-readable.
On the other hand, the node API always returns the data such as blocks and transactions in hex string. However, please be aware that to decode transactions or blocks, they need to be in Buffer
format.
In these cases, it is necessary to convert between Buffer
and String
as described below: