DAOSpace前端插件方案【WIP】
- 1 一、需求描述
- 2 二、需求分析
- 3 三、概要设计
- 4 四、详细设计
- 4.1 1、扩展点管理
- 4.1.1 1.1 扩展点资源定义
- 4.1.2 1.2 扩展点合约接口
- 4.1.3 1.3 扩展点前端功能
- 4.2 2、插件市场
- 4.2.1 2.1 插件市场资源定义
- 4.2.2 2.2 插件市场合约接口
- 4.2.3 2.3 插件的配置文件
- 4.2.4 2.4 插件部署Cli
- 4.2.5 2.5 插件的安装与卸载
- 4.2.6 2.6 插件市场界面
- 4.3 3、应用插件开发
- 4.3.1 3.1 应用插件的配置
- 4.3.2 3.2 应用插件前端开发
- 4.1 1、扩展点管理
- 5 五、参考资料
一、需求描述
去中心化公司治理协作平台。类似Web2的钉钉和飞书。功能包括:
沟通管理,协作管理,组织管理,制度管理,财务管理,这么多的功能如何满足,
我们需要一个可以扩展的系统,通过给DAO安装子应用或者插件来扩充功能。
对于新功能通过子应用来扩展,对于已有功能的不同实现通过插件来扩展。
二、需求分析
1、用例图
对于DAO按功能分,包括:财务管理、成员管理、插件管理、模块升级管理
和配置管理等。
2、能力树
starcoin中权限控制通过能力来实现,能力可用派生子能力,子能力也可以派生子子能力,这样就形成能力树。通过能力树实现权力的下放。
三、概要设计
1、架构图
DAOSpace内部有插件的注册表,任何用户都可以开发插件,注册到DAOSpace, 。
应用插件前端采用微前端架构,主应用从DAO合约中读取该合约安装的应用插件和其他插件,完成主应用的初始化,包括应用插件的注册,路由绑定等。当用户切换浏览器地址时,微前端框架根据注册的路由启动对应的应用插件。应用插件通过应用插件合约接口完成业务功能。
应用插件是对DAO功能的扩展,类似钉钉和飞书的应用,有自己的界面,可以完成1到多个独立的功能。
应用插件也可以暴露1到多个扩展点,供其他插件来扩展。
2、领域类图
1个插件实现1到n个扩展点,1个扩展点可以被多个插件实现
1个插件使用0到n个扩展点,1个扩展点可以被多个插件使用
1个插件定义0到n个扩展点,1个扩展点只能被0到1个插件定义
1个插件有0到n个版本
用户可以对AppVersion和PluginVersion进行Star和评论
3、应用扩展点
扩展点名称:0x1::DAOSpace::App
扩展点接口定义:
import React from 'react';
export interface IApp {
name: string,
activeWhen: string,
entry: React.ReactNode
}
export interface IDAO {
registerApp(app: IApp)
}
扩展点接口通过TypeScript Declaration files定义,实现应用扩展点的插件为应用插件,主要用于扩展DAOSpace功能。
插件运行在浏览器的VM中。
注意:
由于Move不支持合约动态调用合约代码,所以扩展点定义的接口都是通过JS实现。所有动态调用需求都由前端中转。
四、详细设计
1、扩展点管理
1.1 扩展点资源定义
module ExtensionPoint {
struct ExtensionPoint<ExtT> has key {
id: u64, //扩展点的ID,按注册顺序自增
name: vector<u8>, //名字,例如 DAOSpace.IApp/v1
describe: vector<u8>, //描述
protobuf: vector<u8>, //扩展点接口定义,通过protobuf定义
created_at: u64, //创建时间
}
struct ExtensionPointRegistry has key{
next_id: u64,
}
}
1.2 扩展点合约接口
module ExtensionPoint {
// 初始化 Registry
public(script) fun init()
// 注册扩展点
public(script) fun registerExtensionPoint<ExtT>(name: vector<u8>, describe: vector<u8>, protobuf:vector<u8>): u64;
}
1.3 扩展点前端功能
1.3.1 分页展示所有扩展点
列表:
详情:
1.3.2 创建新的扩展点
2、插件市场
2.1 插件市场资源定义
module PluginMarketplace {
struct PluginRegistry has key{
next_plugin_id: u64,
}
struct PluginVersion<AppT> has key{
number: u64, // 数字版本号,例如1,2,3
version: vector<u8>, //插件版本号,例如v0.1.1
required_caps: vector<vector<u8>>, //依赖的能力
export_caps: vector<vector<u8>>, //导出的能力
implement_extpoints: vector<vector<u8>>, //实现的扩展点
depend_extpoints: vector<vector<u8>>, //依赖的扩展点
contract_module: vector<u8>, // 合约模块, 格式:${address}::${module}
js_entry_uri: vector<u8>, // 前端JS代码资源URI,例如:"https://cdn.xxxx.xxxx/xxxx/xxxxx.js"
}
struct Star has key{
addr: address, // Star人的钱包地址,可以是短地址,例如 zhangsan.stc
created_at: u64, //创建时间
}
struct Comment has key{
addr: address, // 评论人的钱包地址,可以是短地址,例如 zhangsan.stc
content: vector<u8> //评论内容
created_at: u64, //创建时间
}
struct PluginInfo<AppT> has key{
id: u64, //插件ID
name: vector<u8>, //插件名称
describe: vector<u8>, //插件描述
next_version_number: u64, //下一个版本号
versions: vector<PluginVersion>, //插件的所有版本
stars: vector<Star>,// 插件的所有star
comments: vector<Comment>, // 插件的所有评论
git_repo: vector<u8>, // git仓库代码
created_at: u64, //插件创建时间
update_at: u64, //插件最后一次更新时间
}
}
2.2 插件市场合约接口
module PluginMarketplace {
// 初始化 Registry
public(script) fun init()
// 注册插件,获取插件ID和所有权
public(script) fun register_plugin(sender: signer, plugin_name: vector<u8>): u64 acquires PluginRegistry
// 发布插件版本
public(script) fun publish_plugin(sender: signer, plugin_id: u64, version: PluginVersion): u64 acquires PluginRegistry
}
2.3 插件的配置文件
dao_plugin.json 为插件的配置文件:
{
"id": 1, // 在DAOSpace注册的插件ID
"name": "hello-world", // 插件名称
"version": "v0.1.1" // 插件版本
"icon": "ipfs://xxxxxxxxx/xxxxxxx.svg"
"implements": [
"0x1::ExtensionPoint::IApp" // 实现应用接口
],
"depends": [
"0x1::Starcoin::IToken" // 依赖Token接口
],
"required_caps": [
"0x1::DAOSpace::DAOUpgradeModuleCap", // 需要DAO升级能力
"0x1::DAOSpace::DAOMemberCap" // 需要DAO成员管理能力
],
"contact": "./constract/Move.toml",
"web": "./web/package.json"
}
2.4 插件部署Cli
daospace-cli plugin deploy -n <env> ./dao_plugin.json
部署逻辑:
将插件的合约部署STC链上,
将插件打包后的静态资源发布到IPFS或者AR网络,
调用publish_plugin_version
合约方法,发布新版本。
2.5 插件的安装与卸载
合约端:
module ${PluginName}{
// 安装插件
public(script) fun setup<DaoT>(sender: signer, dao: DaoT)
// 卸载插件
public(script) fun teardown<DaoT>(sender: signer, dao: DaoT)
}
web端:
// 所有前端插件JS加载后的对象,需要暴露下面两个方法
// 用于完成插件的初始化和卸载。
// 插件加载后运行在独立的VM中
// 前端VM技术参考:https://www.garfishjs.org/blog
interface IPlugin {
// 前端插件安装方法
void setup(depends: ExtensionPoint[])
// 前端插件卸载方法
void teardown()
}
2.6 插件市场界面
2.5.1 插件市场
2.5.2 创建插件
2.5.3 上传插件
2.5.4 对插件点赞
2.5.5 对插件进行评论
3、应用插件开发
1个应用插件就是一个Dapp,包括前端页面和后端合约代码,扩展DAO的一个功能,例如成员管理、Grant管理等。
每个DAO可以安装多个应用插件,每个应用插件安装时获取声明的能力,如果DAO中某种能力只有一个实例,那么只有获取对应能力的应用插件才能安装,其他同类型的应用插件由于获取不到需要的能力,所以不能安装。
一个应用插件可以将一个能力封装后,提供更多能力和扩展点。这样就可以安装其他插件。
3.1 应用插件的配置
所有实现了应用扩展点接口的插件为应用插件。
应用插件的 dao_plugin.json 配置:
{
"id": 1, // 在DAOSpace注册的插件ID
"name": "hello-world", // 插件名称
"version": "v0.1.1" // 插件版本
"icon": "ipfs://xxxxxxxxx/xxxxxxx.svg"
"implements": [
"0x1::ExtensionPoint::IApp" // 实现应用扩展点接口
],
"required_caps": [
"0x1::DAOSpace::DAOUpgradeModuleCap", // 需要DAO升级能力
"0x1::DAOSpace::DAOMemberCap" // 需要DAO成员管理能力
],
"contact": "./constract/Move.toml",
"web": "./web/package.json"
}
3.2 应用插件前端开发
应用插件的前端部分为一个微前端应用,支持远程加载,微前端框架选用阿里开源的qiankun。
五、参考资料
2、https://www.dingtalk.com/ 《钉钉首页》
3、https://www.feishu.cn/ 《飞书首页》
4、https://blog.csdn.net/blog_jihq/article/details/80669616 《组件、插件、模块、子应用、库、框架等概念辨析》
5、https://juejin.cn/post/7121883538311348238 《除了 Qiankun, 这些微前端框架或许更适合你「建议收藏」》
6、https://qiankun.umijs.org/zh/guide 《阿里微前端框架qiankun》
7、https://micro-zoe.github.io/micro-app/docs.html#/ 《京东微前端框架 MicroApp》
8、https://www.garfishjs.org/guide/start/ 《字节微前端框架 Garfish》
9、https://www.garfishjs.org/blog 《微前端架构设计》
10、https://mp.weixin.qq.com/s/dbu2yocUqz60kp_eSlMQCA 《DeFi应用架构设计之道》
11、https://starcoin.org/zh/developer/how_to_dapp/how_to_dapp/ 《Dapp开发指南》
12、npm: protobufjs 《protobuf JS库》
13、https://www.zhihu.com/question/20628768