Schemas & Codec

A "schema" is just a declarative format for describing the structure of data. Since data can be of various types, such as personal data, financial data, etc., it is essential for a software to pre-define the types of data it will process. With schemas, custom properties can be defined to fulfill various configuration and business logic requirements.

Schemas play a vital role within the Lisk SDK, as they are utilized in different areas to encode and decode data that is retrieved or pushed to the blockchain. Schemas also provide the ability to validate diverse types of data in the Lisk blockchain.

In Lisk SDK, schemas are mainly used in the following:

  • Modules: whereby modules can have various data structures which are used for storing, validating, and configuring the business logic of a module.

    • For example, the schema of the Token module defines properties used by the Token module commands, the configurations applied to the module, and the request and response schemas for the endpoints among various other properties.

  • Plugins: whereby plugins can also have similar needs of storing data in variables, validating it, or using schema to configure a plugin.

    • For example, the Faucet plugin used to seed newly created accounts uses various schemas as defined in its particular schemas.ts file.

  • Codec: Schemas are also used to encode or decode data such as blocks, transactions, account state, blockchain state data, etc. For more information, see the Lisk Validator reference.

  • Lisk Validator: The Lisk validator also relies on pre-defined schemas. It used each schema to validate the data passed to it according to its pre-defined schema. For more information, see the Lisk Codec reference.

Data types

A schema always defines the data types that will be used to store specific data. When the data is retrieved from the data store by a module or from an external database by a plugin, it is returned as a JavaScript object or JSON (JavaScript Object Notation), depending on the context:

  • JavaScript object: These data types are used internally in the Lisk application to handle data from the data stores.

  • JSON: Data that is provided by actions and events is always returned in JSON format.

Table 1. Data types of the different data structures
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

Schema Format

Schemas can be defined as shown below. For more information, see the JSON schema reference.

Please note the following:

  • 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.

Example of a token-transfer transaction schema from the Token module
export const transferParamsSchema = {
	$id: '/lisk/transferParams',
	title: 'Transfer transaction params',
	type: 'object',
	required: ['tokenID', 'amount', 'recipientAddress', 'data'],
	properties: {
		tokenID: {
			dataType: 'bytes',
			fieldNumber: 1,
			minLength: TOKEN_ID_LENGTH,
			maxLength: TOKEN_ID_LENGTH,
		},
		amount: {
			dataType: 'uint64',
			fieldNumber: 2,
		},
		recipientAddress: {
			dataType: 'bytes',
			fieldNumber: 3,
			format: 'lisk32',
		},
		data: {
			dataType: 'string',
			fieldNumber: 4,
			minLength: 0,
			maxLength: MAX_DATA_LENGTH,
		},
	},
};

$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 JSON $id reference page.

Whilst defining IDs, adhere to the following criteria:

  • Use unique IDs across the system.

  • Use the path-like format for readability; while this may not be a necessary convention to follow, it does however aid in defining unique IDs. You can also create a series of unique IDs as well.

  • To avoid overlapping schemas with each other, use a fixed identifier for your app in each ID e.g. /lisk/, etc.

Example of $id
$id: '/lisk/transferParams'

type

The root type of the schema must be type object. Inside the object, the properties can be of any type as mentioned in Data types. For more information, see the "type" keyword.

Example of type
type: 'object'

required

By default, the properties defined by the properties keyword are not required. However, one can provide a list of required properties using the required keyword. For more information, see the "required" keyword.

Example of required
required: ['tokenID', 'amount', 'recipientAddress', 'data']
If the schema is used for serialization it is recommended to put all properties as required to guarantee the uniqueness of encoding.

properties

The properties (key-value pairs) on an object are defined using the properties keyword. The value of properties is an object, where each key is the name of a property and each value is a schema used to validate that property. For more information, see the "properties" keyword.

Example of properties
properties: {
    myCounter: {
        dataType: "uint32",
        fieldNumber: 1,
    },
},

default

Defines the default values of properties.

Example of default
properties: {
    myCounter: {
        dataType: "uint32",
        fieldNumber: 1,
    },
},
default: {
  myCounter: 0
}

Codec

A codec is a device or computer program that encodes or decodes a data stream or signal. In Lisk, the codec is essential for validating, transforming, encoding, and decoding data for the Lisk protocol.

Lisk uses the lisk-codec package to encode, decode and perform the aforementioned operations on different objects such as the following:

  • Accounts [1]

  • Transactions [2]

  • Blocks [3]

  • Multi-signature registration

  • Validator info and validator keys

  • Modules

  • Plugins

  • …​ and many more.

By default, the lisk-codec package can be found in the following NPM packages:

  • lisk-sdk

  • @liskhq/lisk-client

  • @liskhq/lisk-codec

To see a complete reference of the lisk-codec package, see Lisk Codec reference.

In case, it is required to install lisk-codec, the following command can be used:

npm install --save @liskhq/lisk-codec
To learn about how codec and schemas are used to encode and decode data, checkout out our dedicated guide: Decoding & encoding data.

1. Check out the sample usage of the account schemas with a codec: Encode & decode an account’s schema.
2. Check out the sample usage of transaction schemas with a codec: Encode & decode a transaction’s schema.
3. Check out the sample usage of block schemas with a codec: Encode & decode a block’s schema.