查看原文
其他

在 Motoko 中动态创建容器智能合约

DFINITY 2022-07-07


在我最新的一篇博文中,我分享了一个在 NodeJS 上下文中在互联网计算机上查询智能合约的解决方案。
那篇文章是系列文章中的第一篇,它将展示我为名为 Papyrs 的新项目开发的各种脚本 —— Papyrs 是一个开源、隐私优先、去中心化的互联网计算机上的博客平台,它 100% 存在于链上。
我打算分享我如何查询剩余 Cycles 和更新用户容器的代码,但首先我将分享架构的基础 —— 即演示允许程序动态创建容器的代码。
架构
与将用户数据集中在单个或分布式数据库中的 web2 项目不同,我对 Papyrs 的数据持久性采用了一种更具未来感的方法。
一个主要 actor 充当管理器,在创建对象时动态地为每个用户的每个单一数据持久性生成一个去中心化的、安全的简单键值数据库。


在接下来的章节中,我将通过在 Motoko 开发的示例项目来介绍这样的解决方案。
关于这个架构的更多细节,你可以阅读我写的一篇文章,互联网计算机 - Web App 去中心化数据库架构:
  • medium.com/geekculture/internet-computer-web-app-decentralized-database-architecture-8647d1a437b8


Bucket
每个用户都会获得一个专用的容器智能合约,我将其命名 bucket(桶)为遵循 DFINITY 在 GitHub 上提供的参与者类示例的约定,在论坛上,它有时也可能被称为“儿童”容器。
出于演示目的,我认为这样的存储桶 - an actor - 可以公开一个函数,say Hello。此外,为了预测我未来的写作,它还接收一个 user 作为参数并包含一个不稳定的 version 数字,每次安装新的容器代码时都会增加该数字。
请注意,我使用用户 Text 类型只是为了简化示例,在实际用例中,我会使用一个 Principal


Manager
Manager —— 或 Main actor —— 包含更多的逻辑,所以我将把它分解成几个步骤,然后再完整呈现。
如前所述,它会创建动态容器,因此,根据用例,它可以或应该跟踪已创建的那些 —— 例如,通过将已创建的容器 ID 堆叠在一个 Hashmap
但是,为了简单起见,在本文中,我只跟踪在稳定变量的帮助下初始化的最后一个智能合约 canisterId


要创建一个新的容器,我们主要需要两件事:
  • Bucket —— 即上一章的 actor

  • Cycles 库


因为我们在同一个项目中实现了 bucket 的代码,所以可以用一个相对的导入路径来包含它,每次调用 Bucket.Bucket(param)都会实例化一个新的存储桶 —— 即动态创建一个新的容器智能合约。
该库用于与它创建的存储桶共享管理器的 cycles,根据文档,相关的计算成本为 100,000,000,000 个 cycles,即大约 0.142 美元。


虽然这可能是故事的结尾,但我想为这个谜题添加另一部分。
确实,设置可以修改存储桶的控制器可能会很有趣 —— 例如,允许您的主体或 manager 之一更新容器的代码可能会很有趣。
为此,我们首先需要将互联网计算机的规范以新 Motoko 的形式添加到项目中 module,您可以转换 candid 文件或获取我在 Papyrs 中使用的文件。
最后,我们可以声明一个变量,该变量将用于调用 IC 管理容器地址(aaaaa-aa),并使用它来有效地更新新创建的容器的设置。


Web 应用程序
随着两个容器智能合约的实施,我们可以开发一个虚拟前端来测试它们的功能,它可以包含两个动作:一个是创建一个 bucket,另一个是调用它 —— 即调用它的函数 say


如果您曾经使用 dfx 命令行创建过示例项目,您会觉得以下内容很熟悉,我创建了一个名为 buckets_sample 的项目,Dfx 会自动安装依赖项和暴露 main actor。
因此,调用管理器以实例化新容器的 JavaScript 函数使用这些预制方法,我还将 bucket(创建的最后一个容器的主体 ID)保存在全局变量中以供重用。


相反,创建新示例项目的过程并不知道我们要动态创建容器,这就是为什么我们必须为我们之前编码的 bucket 生成 candid 的接口和相关的 JavaScript 代码。
目前除了以下解决方法之外,没有其他方法可以生成这些文件:
1. 编辑配置 dfx.json 以列出 bucket actor。


2. 运行 dfx deploy 命令生成文件,该命令将以错误结束(错误:无效数据:预期的参数,但没有找到。)可以安全地忽略。
3. 还原 dfx.json 中的更改。
4. 将生成的文件复制到源文件夹,以便我们可以在 Web 应用程序中使用它们。


有点胡说八道,但这就是诀窍。
感谢新生成的声明文件,我们可以创建一个自定义函数,为我们动态生成的 bucket 实例化一个 actor —— 容器 ID。


请注意,在上面的代码片段中,我是如何明确地 import 另一个 idlFactory 与 bucket 的定义相匹配的。
我们最终可以实现调用 say 函数,这也就结束了 demo 应用的开发。


Demo
一切告一段落,示例项目终于可以测试了。
init 按钮动态创建一个新的容器,在控制台解析它的 ID,“say” 按钮调用新 bucket 的函数。


结论
我花了比预期更长的时间来写这篇文章,我希望它有用,我期待分享更多我在开发 Papyrs 时学到的技巧。
说到这,如果您有任何相关的问题或建议可以制作有趣的博客文章,请联系并告诉我。
到无限和超越,David!



如需更多冒险,请在 Twitter 上关注我(@daviddalbusco)。
在 smartcontracts.org 上开始构建,并在 forum.dfinity.org 上加入开发者社区。


作者:David Dal Busco翻译:Catherine

-              -


“以太坊杀手” Dfinity 用 Logo 诉讼打击 Facebook 的 Meta

Web3 游戏的去中心化层

无桥加密:直接区块链集成的承诺





你关心的 DFINITY 内容
技术进展 | 项目信息 | 全球活动


长按关注 DFINITY 微信公众号

随时答疑解惑


*添加小助手微信 comiocn 进交流社群


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存