...
代码块 |
---|
module rooch_demo::editor { use std::string::{String, utf8}; use aptos_std::table::{Self, Table}; use aptos_framework::timestamp; const EDITOR_ADDRESS:address = @rooch_demo; const ERR_NOT_CONTRACT_OWNER: u64 = 0; const DRIVE_ALREADY_REGISTERED: u64 = 0 1; const ERR_ALREADY_INITIALIZED: u64 = 2; struct File has store, copy, drop { id: u64, name: String, content_type: vector<u8>, content_hash: vector<u8>, owner: address, create_time: u64, last_update_time: u64, } struct Folder has store, copy, drop { id: u64, name: String, file_ids: vector<u64>, folder_ids: vector<u64>, owner: address, create_time: u64, last_update_time: u64, } struct Drive has key, store { name: String, files: Table<u64, File>, folders: Table<u64, Folder>, root_folder_id: u64, next_file_id: u64, private: bool, public_key: String, owner: address, } struct Element has store, copy, drop { id: u128, type: u16, attributes: SimpleMap<String, String>, children_ids: vector<u64>, text: String, } struct Document has store, copy, drop { drive_address: u64, file: File, title: vector<u8>, elements: Table<u64, Element>, root_element_id: u64 } struct EditingDocument store { drive_address: address, file_id: u64, state_channel_id: u64 } struct DocumentEditor has store { editingDocuments: Table<u64, EditingDoc<Document>> } public fun drive_registerinitialize(account: &signer,) name:{ vector<u8>, public_key: vector<u8>, private: bool) { let account_addr = Signer::address_of(account); let assert!(account_addr ==EDITOR_ADDRESS, signerErrors::requires_address_of(account(ERR_NOT_CONTRACT_OWNER)); assert!(!exists<Server>exists<DocumentEditor>(account_addr), errorErrors::already_existspublished(DRIVEERR_ALREADY_REGISTEREDINITIALIZED)); let drive = Drive {move_to(account, DocumentEditor{ name: utf8(name), files: table::editingDocuments: table::new<u64, File>EditingDoc<Document>>(), }) folders: table::new<u64, Folder>(), } public fun root_folder_iddrive_register(account: 0&signer, name: vector<u8>, public_key: vector<u8>, private: bool) { next_file_id: 0, let addr = signer::address_of(account); private: private, assert!(!exists<Server>(addr), error::already_exists(DRIVE_ALREADY_REGISTERED)); public_key: public_key, let drive = Drive { owner: account, }; name: utf8(name), let rootFolder = Folder { id: 0files: table::new<u64, File>(), folders: nametable::new<u64, utf8Folder>(b'/'), filesroot_folder_id: vector::empty<u64>()0, folders next_file_id: vector::empty<u64>()0, ownerprivate: accountprivate, createpublic_timekey: timestamp::now_microseconds()public_key, last_update_timeowner: 0account, }; let rootFolder = Folder { vector::append<address>(&mut drive.folders, rootFolder); id: 0, drive.root_folder_id = rootFolder.id; drive.next_file_id = drive.next_file_id + 1;name: utf8(b'/'), files: vector::empty<u64>(), move_to(account, drive); folders } } |
聊天合约类图:
...
代码块 |
---|
module rooch_demo::chat {: vector::empty<u64>(), use std::vector; use std::string::{String, utf8};owner: account, use aptos_std::table::{Self, Table}; use rooch::state_channel::{Self, StateChannel};create_time: timestamp::now_microseconds(), const SERVERlast_ALREADYupdate_REGISTEREDtime: u640, = 0; const CHAT_ACCOUNT_ALREADY_REGISTERED: u64 = 1; } struct Message has store { vector::append<address>(&mut drive.folders, rootFolder); drive.root_folder_id: u64, = rootFolder.id; type: u16, drive.next_file_id = drive.next_file_id + 1; props: SimpleMap<String, String> content: Stringmove_to(account, drive); } publish_time: u64} |
聊天合约类图:
...
代码块 |
---|
module rooch_demo::chat { }use std::vector; use std::string::{String, utf8}; struct ChatGroup has store { use aptos_std::table::{Self, Table}; id: u64, use rooch::state_channel::{Self, StateChannel}; name: String, const SERVER_ALREADY_REGISTERED: u64 = 0; admins: vector<address> const CHAT_ACCOUNT_ALREADY_REGISTERED: u64 = 1; messages: Table<u64, Message>, struct Message has server_id: u64,store { public_keyid: Stringu64, create_timetype: u64u16, } props: SimpleMap<String, String> struct ChatSession hascontent: storeString,copy,drop { chatpublish_group_idtime: u64, } state_channel_id: u64 } struct ChatGroup has store { struct Server has key { id: u64, name: String, chatGroupsadmins: vector<ChatGroup>,vector<address> chatSessionsmessages: Table<u64, ChatSession>Message>, adminsserver_id: vector<address>u64, next_chat_group_idpublic_key: u64String, } create_time: u64, } struct ChatAccountChatSession has keystore,copy,drop { namechat_group_id: Stringu64, groupsstate_channel_id: Table<u64,u64 PrivateKey>, } sessions: vector<ChatSession>, struct }Server has key { public fun server_register(accountname: &signerString, name: vector<u8>) { chatGroups: vector<ChatGroup>, let addr = signer::address_of(account); chatSessions: Table<u64, ChatSession>, assert!(!exists<Server>(addr), error::already_exists(SERVER_ALREADY_REGISTERED)); admins: vector<address>, next_chat_group_id: u64, let server = Server {} struct name: utf8(name), ChatAccount has key { chatGroupsname: vector::empty<ChatGroup>()String, chatSessionsgroups: table::new<u64Table<u64, ChatSession>()PrivateKey>, adminssessions: vector::empty<address>()vector<ChatSession>, } next_chat_group_id: 0, public fun server_register(account: &signer, name: vector<u8>) { }; let addr = vectorsigner::append<address>(&mut server.admins, addraddress_of(account); assert!(!exists<Server>(addr), error::already_exists(SERVER_ALREADY_REGISTERED)); move_to(account, server); } let server = Server public{ fun chat_account_register(account: &signer, name: vector<u8>) { name: utf8(name), let addr = signer::address_of(account); assert!(!exists<ChatAccount>(addr), error::already_exists(CHAT_ACCOUNT_ALREADY_REGISTERED));chatGroups: vector::empty<ChatGroup>(), chatSessions: table::new<u64, ChatSession>(), let chat_account = ChatAccount{ admins: vector::empty<address>(), name: utf8(name), next_chat_group_id: 0, groups: table::new<u64, PrivateKey>(), }; sessions: table::new<u64, ChatSession>(),vector::append<address>(&mut server.admins, addr); }; move_to(account, chat_accountserver); } } |
MoveCraft合约类图:
...
代码块 |
---|
module rooch_demo::movecraft { use std::vector; public use std::string::{String, utf8}; fun chat_account_register(account: &signer, name: vector<u8>) { let addr use= aptos_std::table::{Self, Table};signer::address_of(account); use rooch::state_channel::{Self, StateChannel}assert!(!exists<ChatAccount>(addr), error::already_exists(CHAT_ACCOUNT_ALREADY_REGISTERED)); const SERVER_ALREADY_REGISTERED: u64 = 0; let const CHAT_ACCOUNT_ALREADY_REGISTERED: u64 = 1;chat_account = ChatAccount{ struct Vector3 has store,copy,drop {name: utf8(name), xgroups: u128table::new<u64, PrivateKey>(), y: u128, sessions: table::new<u64, ChatSession>(), z: u128, }; } move_to(account, chat_account); struct Position has store,copy,drop} } |
MoveCraft合约类图:
...
代码块 |
---|
module rooch_demo::movecraft { x: u128,use std::vector; y: u128, use std::string::{String, utf8}; } use aptos_std::table::{Self, Table}; struct Rectangle has store,copy,drop { use rooch::state_channel::{Self, StateChannel}; top_left: Position, const SERVER_ALREADY_REGISTERED: u64 = 0; bottom_right: Position, const CHAT_ACCOUNT_ALREADY_REGISTERED: u64 = }1; struct BlockVector3 has store,copy,drop { idx: u64u128, typey: u16u128, propsz: SimpleMap<String, String>, u128, create_time: u64 } struct LandPosition has store,copy,drop { idx: u64u128, namey: Stringu128, } boundary: vector<Rectangle> struct Rectangle messages: Table<u64, Message>,has store,copy,drop { worldtop_addressleft: addressPosition, owner: address, create_time: u64bottom_right: Position, } struct LandSessionBlock has store,copy,drop { world_addressid: addressu64, land_idtype: u64u16, channel_idprops: u64SimpleMap<String, String>, create_time: u64, } struct WorldLand has keystore { nameid: Stringu64, typename: u8String, seedboundary: u128,vector<Rectangle> blocksmessages: Table<Vector3Table<u64, Block>Message>, landsworld_address: Table<u64, Land>address, sessionsowner: vector<LandSession>address, next_chat_group_idcreate_time: u64, } struct GameAccountInventory has keystore { nameblocks: StringSimpleMap<u16, vector<Block>>, } sessions: vector<LandSession>, } struct LandSession has store,copy,drop { public fun world_register(accountaddress: &signeraddress, name: vector<u8>) { land_id: u64, let addr = signer::address_of(account); channel_id: u64, assert!(!exists<Server>(addr), error::already_exists(SERVER_ALREADY_REGISTERED)); create_time: u64, } letstruct serverWorld =has Serverkey { name: utf8(name)String, chatGroupstype: vector::empty<ChatGroup>()u8, chatSessionsseed: table::new<u64u128, ChatSession>(), adminsblocks: vector::empty<address>()Table<Vector3, Block>, next_lands: Table<u64, Land>, sessions: vector<LandSession>, next_chat_group_id: 0u64, } }; struct vector::append<address>(&mut server.admins, addr);GameAccount has key { name: String, move_to(accountsessions: vector<LandSession>, server); } public fun game_accountworld_register(account: &signer, name: vector<u8>) { let addr = signer::address_of(account); assert!(!exists<ChatAccount>exists<Server>(addr), error::already_exists(CHATSERVER_ACCOUNT_ALREADY_REGISTERED)); let chat_accountserver = Server ChatAccount{ name: utf8(name), groupschatGroups: tablevector::new<u64, PrivateKey>empty<ChatGroup>(), sessionschatSessions: table::new<u64, ChatSession>(), admins: vector::empty<address>(), next_chat_group_id: 0, }; move_to(account, chat_accountvector::append<address>(&mut server.admins, addr); } } |
1.2 给Dapp合约调用的合约接口
1.2.1 创建状态通道
代码块 |
---|
rooch::state_channel::create |
类型参数:
...
类型参数
...
约束
...
描述
...
StateT
...
store
...
状态类型
参数:
...
参数名称
...
类型
...
描述
...
init_state
...
StateT
...
初始状态
返回值:
...
返回值
...
类型
...
能力
...
描述
...
state_channel_id
...
u256
...
状态通道ID
业务逻辑:
使用一个自定义的初始状态来创建一个状态通道。状态通道的合约代码通过状态的模块自动提取。
示例:
协同编辑器创建状态通道
...
move_to(account, server);
}
public fun game_account_register(account: &signer, name: vector<u8>) {
let addr = signer::address_of(account);
assert!(!exists<ChatAccount>(addr), error::already_exists(CHAT_ACCOUNT_ALREADY_REGISTERED));
let chat_account = ChatAccount{
name: utf8(name),
groups: table::new<u64, PrivateKey>(),
sessions: table::new<u64, ChatSession>(),
};
move_to(account, chat_account);
}
} |
1.2 给Dapp合约调用的合约接口
1.2.1 创建状态通道
代码块 |
---|
rooch::state_channel::create |
类型参数:
类型参数 | 约束 | 描述 |
---|---|---|
| store | 状态类型 |
参数:
参数名称 | 类型 | 描述 |
---|---|---|
init_state |
| 初始状态 |
返回值:
返回值 | 类型 | 能力 | 描述 |
---|---|---|---|
state_channel_id | u256 | 状态通道ID |
业务逻辑:
使用一个自定义的初始状态来创建一个状态通道。状态通道的合约代码通过状态的模块自动提取。
示例:
协同编辑器创建状态通道
代码块 |
---|
module rooch_demo::editor {
use rooch::state_channel::{Self, StateChannel};
const ERR_FILE_NOT_EXISTS: u64 = 5;
public fun open_document(account: &signer, drive_address: address, file_id: u64) {
assert!(drive_file_exists(drive_address, file_id), Errors::requires_address(ERR_FILE_NOT_EXISTS));
let editor = borrow_global_mut<DocumentEditor>(EDITOR_ADDRESS);
let doc = document_create(account, drive_address, file_id)
let ch_id = state_channel::create<Document>(doc);
let editing_doc = EditingDocument{
drive_address: drive_address,
file_id: file_id,
state_channel_id: ch_id
}
save_editing_doc(editor, editing_doc)
}
} |
聊天示例:
代码块 |
---|
module rooch_demo::chat {
use std::vector;
use std::string::{String, utf8};
use rooch::state_channel::{Self, StateChannel};
public fun chat_session_create(account: &signer, server_address: address, chat_group_id: u64) {
let addr = signer::address_of(account);
let server = borrow_global_mut<Server>(server_address);
let chat_account = borrow_global_mut<ChatAccount>(addr);
let chat_group = server_borrow_chat_group(server, chat_group_id);
let ch_id = state_channel::create<ChatGroup>(chat_group);
let session = ChatSession{
server_address: server_address,
chat_group_id: chat_group_id,
state_channel_id: ch_id
}
server_add_chat_session(server, copy session)
chat_account_add_chat_session(chat_account, copy session)
}
} |
MoveCraft示例:
代码块 |
---|
module rooch_demo::movecraft { use std::vector; use std::string::{String, utf8}; let editor = borrow_global_mut<DocumentEditor>(EDITOR_ADDRESS)use rooch::state_channel::{Self, StateChannel}; let docpublic =fun documentland_session_create(account: &signer, driveworld_address: address, fileland_id: u64) { let ch_idaddr = state_channelsigner::create<Document>(doc); address_of(account); let editing_doc = EditingDocument{ let world drive_address: drive_address,= borrow_global_mut<World>(world_address); let game_account = file_id: file_id,borrow_global_mut<GameAccount>(addr); let land = stateworld_channel_id: chborrow_land(server, land_id); } let ch_id save_editing_doc(editor, editing_doc)= state_channel::create<Land>(land); } } |
聊天示例:
代码块 |
---|
module rooch_demo::chat { use std::vector; let session use std::string::{String, utf8};= LandSession{ use rooch::state_channel::{Self, StateChannel};world_address: world_address, public fun chat_session_create(account: &signer, server_address: address, chat_group_id: u64) {land_id: land_id, let addr = signer::address_of(account);state_channel_id: ch_id } let server = borrow_global_mut<Server>(server_address); let chat_account = borrow_global_mut<ChatAccount>(addr); world_add_land_session(world, copy session) let chat_group = server_borrow_chat_group(server, chat_group_id); game_account_add_land_session(game_account, copy session) let ch_id = state_channel::create<ChatGroup>(chat_group); let session = ChatSession{ } } |
1.2.2 加入状态通道
代码块 |
---|
rooch::state_channel::join |
类型参数:
类型参数 | 约束 | 描述 |
---|---|---|
| store | 状态类型 |
参数:
参数名称 | 类型 | 描述 |
---|---|---|
sender | &signer | 发起方 |
state_channel_id |
| 状态通道ID |
deposit | Token<TokenType> | 质押Token |
assets | Assets | 带入状态通道的资产 |
事件:
事件名称 | 事件数据 | 描述 |
---|---|---|
state_channel_join_event | { “member_address“: “vector<u8>“, “input_assets“: Assets } | 加入状态通道事件 |
返回值:
无
业务逻辑:
加入某个状态通道,指定需要带入的资产
示例:
协同编辑器,加入状态通道
代码块 |
---|
module rooch_demo::editor { use server_address: server_address, rooch::state_channel::{Self, StateChannel}; const chatERR_FILE_groupNOT_idEXISTS: chat_group_id, u64 = 5; public fun stateediting_channeldocument_id: chjoin(account: &signer, doc_id: u64) { } let editor = borrow_global_mut<DocumentEditor>(EDITOR_ADDRESS); let editing_doc server_add_chat_session(server, copy session)= table::borrow<u64, EditingDocument>(&editor.editingDocuments, doc_id) chat_account_add_chat_session(chat_account, copy session)state_channel::join(account, editing_doc.channel_id); } } |
MoveCraft示例:聊天合约,加入群聊
代码块 |
---|
module rooch_demo::movecraftchat { use std::vector; use std::string::{String, utf8}; use rooch::state_channel::{Self, StateChannel}; public fun landchat_session_createjoin(account: &signer, world_address: address, landchat_group_id: u64) { let addr = signer::address_of(account); let world = borrow_global_mut<World>(world_address::address_of(account); let gamechat_account = borrow_global_mut<GameAccount>mut<ChatAccount>(addr); let landsession = worldchat_account_borrow_chat_landsession(serverchat_account, landchat_group_id); let ch_id = state_channel::create<Land>(landjoin<ChatGroup>(account, session.state_channel_id); } } |
MoveCraft合约,加入地块
代码块 |
---|
module rooch_demo::movecraft { use std::vector; let session = LandSession{ use std::string::{String, utf8}; use world_address: world_address,rooch::state_channel::{Self, StateChannel}; public fun land_session_idjoin(account: &signer, land_id,: u64) { let addr = state_channel_id: ch_idsigner::address_of(account); } let game_account = borrow_global_mut<GameAccount>(addr); let session = worldgame_addaccount_landborrow_session(worldgame_account, copy session)land_id); game_account_add_land_session(game_account, copy session) let inventory } } |
1.2.2 加入状态通道
代码块 |
---|
join_state_channel |
类型参数:
...
类型参数
...
约束
...
描述
...
StateT
...
store
...
状态类型
参数:
...
参数名称
...
类型
...
描述
...
sender
...
signer
...
发起方
...
state_channel_id
...
u256
...
状态通道ID
...
assets
...
Assets
...
带入状态通道的资产
事件:
...
事件名称
...
事件数据
...
描述
...
join_state_channel_event
...
{
“member_address“: “vector<u8>“,
“input_assets“: Assets
}
...
加入状态通道事件
返回值:
无
业务逻辑:
...
= game_account_get_inventory(game_account)
state_channel::join<Inventory>(account, session.state_channel_id, inventory);
}
} |
1.2.3 离开状态通道
代码块 |
---|
leave_state_channel |
...