Use dubhe to develop a contract
Letβs develop one of the simplest examples, called Distributed Messaging, or dms for short. The contract will have a schema called message, which will have a field called content, which will store the message content. The contract will have a method called send, which will take a string as a parameter and store it in the content field of the mailbox schema. The contract will also have an event called MessageSent, which will be triggered when a message is sent.
Dubhe generates some code based on the dubhe.config.ts configuration, so we just need to focus on this file.
import { DubheConfig } from '@0xobelisk/sui-common';
export const dubheConfig = {
name: 'template',
description: 'template',
schemas: {},
} as DubheConfig;
Letβs go over whatβs in dubheConfig
- name: The name of the contract project.
- description: The description of the contract project.
- schemas: The schema of the contract project. Refer to the Schemas section for details of schema.
To complete dms contract I need a Schema to store the numbers, now letβs complete the Schema.
import { DubheConfig } from '@0xobelisk/sui-common';
export const dubheConfig = {
name: 'dms',
description: 'Distributed Messaging',
schemas: {
message: {
content: 'StorageValue<String>'
}
},
} as DubheConfig;
The name of this Schema is message, and he has only one number field with storage type StorageValue
, which is used to store String
.
Now we need to generate the contract frame content using Dubheβs most powerful feature.
β dubhe-template-project pnpm dubhe schemagen
π Starting Schema Generation Process...
π Project Configuration:
ββ Name: dms
ββ Description: Distributed Messaging
ββ Network: testnet
π Starting Move.toml Generation...
ββ Output path: /Volumes/project/dubhe-template-project/contracts/dms/Move.toml
β
Move.toml Generation Complete
π Starting Deploy Hook Generation...
ββ Output path: /Volumes/project/dubhe-template-project/contracts/dms/sources/scripts/deploy_hook.move
β
Deploy Hook Generation Complete
π¨ Starting Schema Structure Generation...
ββ Generating schema: message
ββ Output path: /Volumes/project/dubhe-template-project/contracts/dms/sources/codegen/schemas/message.move
ββ Structure fields: 1
β
Schema Structure Generation Complete
π Starting Init Generation...
ββ Output path: /Volumes/project/dubhe-template-project/contracts/dms/sources/tests/init.move
β
Deploy Hook Generation Complete
βοΈ Starting System Generation...
ββ Generating systems
ββ Output path: /Volumes/project/dubhe-template-project/contracts/dms/sources/systems
β
System Generation Complete
β
Schema Generation Process Complete!
Take a look at the file structure of dms, we donβt need to concern ourselves with anything else but our business code systems folder.
β dms tree
βββ Move.toml
βββ sources
βββ codegen
β βββ schemas
β βββ default
β β βββ dapp
β β βββ metadata.move
β β βββ schema.move
β β βββ system.move
β βββ message.move
βββ scripts
β βββ deploy_hook.move
β βββ migrate.move
βββ systems
βββ tests
βββ init.move
9 directories, 8 files
A Message Schema has been generated for you, now you need to write your own business code! We create a new move file called message in the Systems folder.
touch contracts/counter/sources/systems/message.move
This can be easily achieved with the help of Dubheβs code generation. The contents of the file:
module dms::message_system {
use std::ascii::String;
use dms::message_schema::Message;
public entry fun send(message: &mut Message, content: String) {
message.content().set(content);
}
}
Letβs add an error handler so that the length of the content doesnβt exceed 12, how to do error handling?
import { DubheConfig } from '@0xobelisk/sui-common';
export const dubheConfig = {
name: 'dms',
description: 'Distributed Messaging',
schemas: {
message: {
content: 'StorageValue<String>'
}
},
errors: {
InvalidContentLength: "Content length must be less than 12"
}
} as DubheConfig;
The error handling code has been added, now we also want to add events to the contract to tell us who sent what message.
import { DubheConfig } from '@0xobelisk/sui-common';
export const dubheConfig = {
name: 'dms',
description: 'Distributed Messaging',
schemas: {
message: {
content: 'StorageValue<String>'
}
},
errors: {
InvalidContentLength: "Content length must be less than 12"
},
events: {
MessageSent: {
sender: "address",
content: "String"
}
}
} as DubheConfig;
Execute the schemagen command here.
β dubhe-template-project pnpm dubhe schemagen
π Starting Schema Generation Process...
π Project Configuration:
ββ Name: dms
ββ Description: Distributed Messaging
ββ Network: testnet
π Starting Deploy Hook Generation...
ββ Output path: /Volumes/project/dubhe-template-project/contracts/dms/sources/scripts/deploy_hook.move
β
Deploy Hook Generation Complete
π¦ Starting Schema Event Generation...
ββ Generating MessageSent event: [object Object]
β
Schema Event Generation Complete
π¨ Starting Schema Structure Generation...
ββ Generating schema: message
ββ Output path: /Volumes/project/dubhe-template-project/contracts/dms/sources/codegen/schemas/message.move
ββ Structure fields: 1
β
Schema Structure Generation Complete
π¦ Starting Schema Error Generation...
ββ Generating InvalidContentLength message: Content length must be less than 12
β
Schema Error Generation Complete
π Starting Init Generation...
ββ Output path: /Volumes/project/dubhe-template-project/contracts/dms/sources/tests/init.move
β
Deploy Hook Generation Complete
βοΈ Starting System Generation...
ββ Generating systems
ββ Output path: /Volumes/project/dubhe-template-project/contracts/dms/sources/systems
β
System Generation Complete
β
Schema Generation Process Complete!
Errors and events are already generated.
First we do an error check, the input content must be greater than 0.
module dms::message_system {
use std::ascii::String;
use dms::message_schema::Message;
use dms::invalid_content_length_error;
public entry fun send(message: &mut Message, content: String) {
invalid_content_length_error::require(content.length() < 12);
message.content().set(content);
}
}
Finally we add events to the contract.
module dms::message_system {
use std::ascii::String;
use dms::message_schema::Message;
use dms::invalid_content_length_error;
use dms::message_sent_event;
public entry fun send(message: &mut Message, content: String, ctx: &mut TxContext) {
invalid_content_length_error::require(content.length() < 12);
message.content().set(content);
message_sent_event::emit(ctx.sender(), content);
}
}
By this point we need to write the contents of the deploy_hook, which will be automatically executed for you when the contract is deployed, now we initialise the content in the store to Hello World!
.
dubhe-template-project/contracts/counter/sources/scripts/deploy_hook.move
#[allow(lint(share_owned), unused_let_mut)]
module dms::deploy_hook {
use std::ascii::string;
use sui::clock::Clock;
use dms::dapp_system;
use dms::message_schema::Message;
public entry fun run(clock: &Clock, ctx: &mut TxContext) {
// Create a dapp.
let mut dapp = dapp_system::create(string(b"dms"),string(b"Distributed Messaging"), clock , ctx);
// Create schemas
let mut message = dms::message_schema::create(ctx);
// Logic that needs to be automated once the contract is deployed
{
message.content().set(string(b"Hello, World!"));
};
// Authorize schemas and public share objects
dapp.add_schema<Message>(message, ctx);
sui::transfer::public_share_object(dapp);
}
}
Letβs run the Build command to check for syntax errors.
β dubhe-template-project pnpm dubhe build --network localnet
π Running move build
INCLUDING DEPENDENCY Dubhe
INCLUDING DEPENDENCY Sui
INCLUDING DEPENDENCY MoveStdlib
BUILDING dms
Total number of linter warnings suppressed: 1 (unique lints: 1)