Register a Kind
This guide walks you through writing a kind contract and registering it in the Kind Registry.
In this example, we'll build a kind contract for dice. Each dice object is modeled with a single element:
face: the number of dots representing its current value
The kind contract will implement two asset functions:
meta(): returns metadata in JSON format that describes the object tokenpicture(): generates an image of the dice
Before You Begin
Make sure you have:
- Bun installed (for scaffolding a project from the template repository)
- A wallet set up and funded with tokens
Write the Kind Contract
1. Initialize a project
Scaffold a kind contract project from the template:
bun create everytemplate/kind dice-kindBuild the project to verify it compiles:
cd dice-kind
bun run build2. Implement contract logic
Edit assembly/index.ts to implement the asset functions. The final code looks like this (see dice-kind for the full repo):
@kind
class Dice {
face!: Bytes32;
meta(): Json {
let data = json.create("{}");
json.setString(data, "/name", `Dice #${object.id()}`);
json.setString(data, "/description", "A dice");
json.setString(data, "/image", object.assetUri2("picture"));
return data;
}
picture(): Image {
let canvas = image.create(800, 800, 2);
const COLOR_WHITE = new PixelRgb8(255, 255, 255);
const COLOR_BLACK = new PixelRgb8(0, 0, 0);
const COLOR_RED = new PixelRgb8(255, 0, 0);
image.drawFilledRectMut(canvas, new Rect(0, 0, 800, 800), COLOR_WHITE);
image.drawHollowRectMut(canvas, new Rect(50, 50, 700, 700), COLOR_BLACK);
let dots = (this.face.extractU8(31) % 6) + 1;
switch (dots) {
case 1:
image.drawFilledCircleMut(canvas, new PointI32(400, 400), 50, COLOR_RED);
break;
case 2:
image.drawFilledCircleMut(canvas, new PointI32(200, 200), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(600, 600), 50, COLOR_BLACK);
break;
case 3:
image.drawFilledCircleMut(canvas, new PointI32(200, 200), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(400, 400), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(600, 600), 50, COLOR_BLACK);
break;
case 4:
image.drawFilledCircleMut(canvas, new PointI32(200, 200), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(600, 200), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(200, 600), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(600, 600), 50, COLOR_BLACK);
break;
case 5:
image.drawFilledCircleMut(canvas, new PointI32(200, 200), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(600, 200), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(400, 400), 50, COLOR_RED);
image.drawFilledCircleMut(canvas, new PointI32(200, 600), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(600, 600), 50, COLOR_BLACK);
break;
case 6:
image.drawFilledCircleMut(canvas, new PointI32(200, 200), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(200, 400), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(200, 600), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(600, 200), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(600, 400), 50, COLOR_BLACK);
image.drawFilledCircleMut(canvas, new PointI32(600, 600), 50, COLOR_BLACK);
break;
}
return canvas;
}
}Now build the contract. If successful, you will find index.wasm in the build directory:
bun run build3. Meet kind-as and OVM
This code is written in AssemblyScript and can be compiled with kind-as.
The code interprets the face value as the number of dots and draws them by calling image functions. The resulting contract is executed on the OVM (Object Virtual Machine) of the Every chain, which provides host functions for generating JSON and image assets verifiably.
Register the Kind
1. Register the code (as matter)
Register the wasm file as a matter:
every matter register build/index.wasm --account eve --network devnetYou’ll see output including the matter hash:
Register matter: form=1 mime=application/wasm blob=6876B build/index.wasm
Transaction submitted: 0xed68e949abedf05768384b912b01dee2198612e35b1215709903cd53173c2cde
MatterRegistered ['...','0x1dea6f244d8636df267f8589beb433407d12b05b82432a83419254ad2754daa9']2. Register the data (as matter)
Create a data file shared by all objects of this kind. For now, use an empty JSON file:
echo '{}' > data.jsonRegister it as matter:
every matter register data.json --account eve --network devnetYou’ll see output including its matter hash:
Register matter: form=1 mime=application/json blob=3B data.json
MatterRegistered ['...','0x56c792cfe063dde75e9e6afb371542ea141c62c342820ce9b0394992c7f40d35']3. Register the kind
With both code and data registered, register the kind:
every kind register \
0x1dea6f244d8636df267f8589beb433407d12b05b82432a83419254ad2754daa9 \
0x56c792cfe063dde75e9e6afb371542ea141c62c342820ce9b0394992c7f40d35 \
'[1]' \
'[]' \
--foundry --account eve --universe sepoliaThe four arguments are:
<code>: matter hash of the contract code<data>: matter hash of the shared data'[1]': element types array'[]': supported relation IDs (empty for now)
Sample output:
Transaction sending...
Transaction sent: 0xd91f6effaee287da8f593461fe30e3fa121ae031f455b9e309bb3346d5017216
Waiting for confirmation...
Confirmed in: block 52991, hash 0xdf7addfd547e0360226188362e12252109958cd2677d024e691caa9e583291fe
KindRegistered {id:17n,desc:{traits:0,rev:1,kindRev:1,setRev:1,kindId:2n,setId:2n},code:'0x1dea6f244d8636df267f8589beb433407d12b05b82432a83419254ad2754daa9',data:'0x56c792cfe063dde75e9e6afb371542ea141c62c342820ce9b0394992c7f40d35',elemSpec:[1],rels:[],owner:'0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'}The KindRegistered event confirms that the kind has been successfully registered. In this example, the kind was assigned an ID of 17.