Use dubhe to develop a contract
The template has generated two contract folders for you, and you can see:
- contracts/
- counter: According to dubhe.config.ts configuration, the counter contract is generated. You can modify dubhe.config.ts to help you generate your own contract.
- dubhe-framework: The Dubhe framework contract, you do not need to modify it.
Now letβs remove counter contract and re-complete the development of the counter. The counter has only one function, to add the original number content to the inputted number.
rm -rf contracts/counter
Dubhe generates some code based on the dubhe.config.ts configuration, so we just need to focus on this file.
Delete some code from dubhe.config.ts and the final content is as follows, which you can globally copy into the dubhe.config.ts file
import { DubheConfig } from '@0xobelisk/sui-common';
export const dubheConfig = {
name: 'counter',
description: 'counter contract',
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 counter 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: 'counter',
description: 'counter contract',
schemas: {
booster: {
structure: {
number: 'StorageValue<u32>'
}
}
},
} as DubheConfig;
The name of this Schema is booster, and he has only one number field with storage type StorageValue
, which is used to store u32
.
if the input number == 0, although it will not report an error, but it is a meaningless transaction, so we need to prohibit the input of 0, how to do error handling?
import { DubheConfig } from '@0xobelisk/sui-common';
export const dubheConfig = {
name: 'counter',
description: 'counter contract',
schemas: {
booster: {
structure: {
number: 'StorageValue<u32>'
},
errors: [
{ name: 'InvalidIncrement', message: "Number can't be incremented, must be more than 0" }
]
}
},
} as DubheConfig;
The error handling code has been added, now we also want to add events to the contract to tell us which number was added.
import { DubheConfig } from '@0xobelisk/sui-common';
export const dubheConfig = {
name: 'counter',
description: 'counter contract',
schemas: {
booster: {
structure: {
number: 'StorageValue<u32>'
},
errors: [
{ name: 'InvalidIncrement', message: "Number can't be incremented, must be more than 0" }
],
events: [
{
name: 'Increment',
fields: { value: 'u32' },
},
],
}
},
} as DubheConfig;
Weβre going to use Dubheβs most powerful feature to generate the contractβs frame content.
pnpm dubhe schemagen
You can see the following output:
β pnpm dubhe schemagen
π Starting Schema Generation Process...
π Project Configuration:
ββ Name: counter
ββ Description: counter contract
ββ Network: localnet
ββ Framework ID: 0x417ad1864a56a29ad0b5aaddd2e11bac1eeab6a68883ef53184a4cc5c293fec6
π Starting Move.toml Generation...
ββ Output path: /Users/wangningbo/Project/dubhe-template-project/contracts/counter/Move.toml
β
Move.toml Generation Complete
π Starting Deploy Hook Generation...
ββ Output path: /Users/wangningbo/Project/dubhe-template-project/contracts/counter/sources/scripts/deploy_hook.move
β
Deploy Hook Generation Complete
π¦ Starting Schema Data Generation...
β
Schema Data Generation Complete
π¨ Starting Schema Structure Generation...
β
Schema Structure Generation Complete
π¦ Starting Schema Event Generation...
β
Schema Event Generation Complete
π¦ Starting Schema Error Generation...
β
Schema Error Generation Complete
π Starting DappKey Generation...
ββ Output path: /Users/wangningbo/Project/dubhe-template-project/contracts/counter/sources/codegen/dapp_key.move
β
DappKey Generation Complete
π Starting DappKey Generation...
ββ Output path: /Users/wangningbo/Project/dubhe-template-project/contracts/counter/sources/codegen/schema_hub.move
β
DappKey Generation Complete
βοΈ Starting System Generation...
ββ Generating systems
ββ Output path: /Users/wangningbo/Project/dubhe-template-project/contracts/counter/sources/systems
β
System Generation Complete
β
Schema Generation Process Complete!
Take a look at the file structure of counter, we donβt need to concern ourselves with anything else but our business code systems folder.
β counter tree
βββ Move.toml
βββ sources
βββ codegen
β βββ errors
β β βββ booster_error_invalid_increment.move
β βββ events
β β βββ booster_event_increment.move
β βββ schemas
β βββ booster.move
β βββ default
β βββ dapp
β βββ metadata.move
β βββ schema.move
β βββ system.move
βββ scripts
β βββ deploy_hook.move
β βββ migrate.move
βββ systems
β βββ booster.move
βββ tests
βββ init.move
A Booster Schema has been generated for you, now you need to write your own business code! We create a new move file called booster in the Systems folder.
touch contracts/counter/sources/systems/booster.move
Then write whatβs inside, weβll write the inc side implementation of storing the number plus the number entered. The contents of the file:
module counter::booster {
use counter::booster_schema::Booster;
public entry fun inc(booster: &mut Booster, number: u32) {
}
}
First we do an error check, the input number must be greater than 0.
module counter::booster {
use counter::booster_schema::Booster;
use counter::booster_error_invalid_number;
public entry fun inc(booster: &mut Booster, number: u32) {
// Check if the increment value is valid. Number must be greater than 0.
booster_error_invalid_number::require(number > 0);
}
}
Secondly need to modify the numbers in storage, you have two ways to do this.
// Method 1
let old_number = booster.borrow_number().get();
booster.borrow_mut_number().set(old_number + number);
// Method 2
booster.borrow_mut_number().mutate!(|old_number|
*old_number = *old_number + number
);
We use the second.
module counter::booster {
use counter::booster_schema::Booster;
use counter::booster_error_invalid_number;
public entry fun inc(booster: &mut Booster, number: u32) {
// Check if the increment value is valid. number must be greater than 0.
booster_error_invalid_number::require(number > 0);
// Increment the number.
booster.borrow_mut_number().mutate!(|old_number| *old_number = *old_number + number);
}
}
Finally we add events to the contract.
module counter::booster {
use counter::booster_schema::Booster;
use counter::booster_error_invalid_number;
use counter::booster_event_increment;
public entry fun inc(booster: &mut Booster, number: u32) {
// Check if the increment value is valid. number must be greater than 0.
booster_error_invalid_number::require(number > 0);
// Increment the number.
booster.borrow_mut_number().mutate!(|old_number| *old_number = *old_number + number);
// Emit an event to notify the increment.
booster_event_increment::emit(number);
}
}
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 number in the store to 10.
dubhe-template-project/contracts/counter/sources/scripts/deploy_hook.move
#[allow(lint(share_owned), unused_let_mut)]
module counter::deploy_hook {
use std::ascii::string;
use sui::clock::Clock;
use counter::dapp_system;
use counter::booster_schema::Booster;
public entry fun run(clock: &Clock, ctx: &mut TxContext) {
// Create a dapp.
let mut dapp = dapp_system::create(string(b"counter"),string(b"counter contract"), clock , ctx);
// Create schemas
let mut booster = counter::booster_schema::create(ctx);
// Logic that needs to be automated once the contract is deployed
{
booster.borrow_mut_number().set(0);
};
// Authorize schemas and public share objects
dapp.add_schema<Booster>(booster, ctx);
sui::transfer::public_share_object(dapp);
}
}
Letβs run the Build command to check for syntax errors.
β pnpm dubhe build --network localnet
π Running move build
Active environment switched to [localnet]
Updated Dubhe dependency in /Users/wangningbo/Project/dubhe-template-project/contracts/counter/Move.toml for localnet.
INCLUDING DEPENDENCY Dubhe
INCLUDING DEPENDENCY Sui
INCLUDING DEPENDENCY MoveStdlib
BUILDING counter