用户登陆
正在加载
基于 Subspace 来 DIY Aragon 消息通知
互联网 · 2020-06-24 14:00:22

封面图来源: Element5 Digital on Unsplash

初衷

我最近加入了一个基于Aragon1的DAO(去中心化自治组织)。 这种类型的DAO是一系列相互关联的智能合约,可以进行链上投票,在成员加入/离开时铸造/燃烧代币,以及在投票成功通过后将DAO资金分配给各以太坊地址。我是DAO的成员之一,我们使用Discord进行讨论以及开展成员活动。我们目前尚没有一种简单的方法来跟踪投票提案创建的时间、投票者及其投票方式。你可以将邮件地址提供给Aragon,有新信息时它会给你发送通知。但我希望能用一种更直接的方法,将通知直接发送到我们的Discord服务器,而不必让DAO成员每次都手动发送消息。也就是说我想要创建ArgoDisco机器人2,所以,我们开始吧。

说明

这里我假设你已经对Etherscan有所了解,看得懂智能合约ABI,并且使用过Javascript和Web3。

目标

从概念上讲,我要构建的东西并不难。 我只做一个机器人程序,能够读取某些智能合约发出的活动信息,然后将这些信息发布到Discord频道。问题是如何将所有这些连接起来?Aragon确实提供了Javascript库3,并且它可能在某个地方提供了这样的功能,但是全部弄清楚这些需要费尽心力,我并不乐意这么做。 我要用Subspace搭建,因为这大约10行代码就能搞定,我们已经准备就绪。

后端

首先,我们要决定我们希望ArgoDisco发送哪些事件的信息通知。 Aragon DAO是一组智能合约合集,一个用于投票,一个用于发送资金,一个用于管理成员代币(还有更多,但目前我们只需要这些)。 从这三个智能合约中,我们希望ArgoDisco在新的投票提案创建、有人投票、发送资金,或者有成员加入或离开时给DAO发送即时通知。因此,我们需要设置4个事件观察对象(observables),每个合约分别跟踪一个事件。然后就可以了吧,应该就这么简单(如下所示)。

const web3 = new Web3("wss://mainnet.infura.io/ws/v3/" + config.infuraToken); const subspace = new Subspace.default(web3); await subspace.init(); votingContract = subspace.contract({abi: votingABI, address: config.votingAddress}); const startVote$ = votingContract.events.StartVote.track({fromBlock: config.lastBlock}); //...more code to post stuff to Discord

确实如此,但是有一个陷阱,我们一步步来,先为 StartVote (开始投票)事件设置观察对象。

我们来看ABI合约,找到StartVote事件信息,我要做的第一件事是跳转到Aragon上的DAO页面,单击“Organization(组织)”,然后查看它列出的应用程序。点击“Voting(投票)”应用程序你会看到投票合约的以太坊地址,之后跳转到therscan获取ABI。我很快发现的问题是...我在合约上只看到了这些信息:

[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"ProxyDeposit","type":"event"}]

在Etherscan中查看合约事件信息似乎可以确认这些事件与DAO创建的提案及投票是一致的,但是它们的命名没什么意义。我们可以从“proxy(代理)”一词中看出端倪。 Aragon使用代理合约来确保其可升级性,而我的DAO合约也不例外。 值得庆幸的是,有一种简单的方法可以解决这个问题。 每个代理合约都指向一个执行合约,并且Etherscan内置了跟踪支持。 如果你还没有在Etherscan的合约选项列表下看到“Read as Proxy”链接,请单击“More Options(更多选项)”,然后单击“Is this a proxy?(这是代理吗)”按钮。

Etherscan将带你进入“Proxy Contract Verification(代理合约验证)”页面,该页面将展示你的代理合约正在使用的执行合约。 点击验证,但愿弹出的信息是告诉你验证成功。:)

完成后,返回主合约页面并单击“Read as Proxyx(Read as Proxy)”。 之后你将看到一条消息,提示“执行合约的ABI在0x1234 ...”。单击该链接,从此处获取合约ABI。我们要找的事件信息就在这里。以下是你要查找的确切信息:

{ "anonymous": false, "inputs": [{"indexed": true, "name": "voteId", "type": "uint256"}, {"indexed": true, "name": "creator", "type": "address"}, {"indexed": false, "name": "metadata", "type": "string"}], "name": "StartVote", "type": "event"},

我们既已有了正确的ABI,还需要记住,当你设置合约目标时,使用你的DAO投票合约的合约地址,而不是你找到ABI的执行合约,这看起来有些让人迷惑对吧?

机器人

现在回到机器人这个话题,我们来过一遍重要的部分。

依赖性和设置

先看这些有点乏味的内容:

const Web3 = require('web3');const Subspace = require('@embarklabs/subspace'); const Discord = require('discord.js');const fs = require('fs');const votingABI = require('./voting.json');const tokensABI = require('./tokens.json');const financeABI = require('./finance.json');var config = require('./bot_config.json');const web3 = new Web3("wss://mainnet.infura.io/ws/v3/" + config.infuraToken);const subspace = new Subspace.default(web3);const bot = new Discord.Client();

首先,依赖性 - Web3js4, Subspace5, 和 Discord.js6, 第三个是我们要给Discord服务器推送信息的代码库。还有fs ,因为稍后我们将做一些简单的文件输入/输出。

接下来,合约ABI。 ArgoDisco读取三个不同的合约事件信息,因此我们有三个合约ABI(作为JSON对象导入)。

最后,我得到了一个配置文件设置,它存储了Discord机器人API密钥、Infura API,合约地址、以太坊地址以及DAO成员的Discord昵称列表。 请参阅此示例以了解如何进行设置。

上线

bot.login(config.botDiscordToken)bot.on('ready', () => { console.log(`Logged in as ${bot.user.tag}!`) const channel = bot.channels.cache.find(channel => channel.name == 'general') channel.send('Howdy') initialize(channel);});

一旦所有依赖关系都消除了,我们来使用上面的代码将机器人连接到我们的Discord服务器。注意,创建Discord机器人帐户,获取机器人API密钥,将机器人邀请到服务器都涉及到许多其他的步骤,这些步骤不在本文的讨论范围之内。更多详细的信息,请阅读这里8或者这里9。

主要告诉机器人使用API密钥登录,然后告诉它连接到“常规”频道,并通过打招呼(Howdy)让所有人知道它的存在。之后将频道目标传递给我通常称作initialize的函数,以达到重要的bits(位)。

新消息报告

await subspace.init(); votingContract = subspace.contract({abi: votingABI, address: config.votingAddress}); const startVote$ = votingContract.events.StartVote.track({fromBlock: config.lastBlock}); startVote$.subscribe(function(vote){ channel.send(`**Vote # ${vote['0']} ${vote['2']}** https://mainnet.aragon.org/?#/arca/0x9b8e397c483449623525efda8f80d9b52481a3a1/vote/${vote['0']}`) console.log(vote) config.lastBlock = vote.blockNumber; fs.writeFile('src/bot_config.json', JSON.stringify(config), ()=> {}); });

启动Subspace,创建Subspace增强的contract对象(合约对象),然后明确观察对象。在这种情况下,它会跟踪我们之前提到的 votingContract (投票合约)上的 StartVote(开始投票)事件信息。

注意:设置观察对象时,我将机器人的配置文件中 fromBlock (起始区块)配置选项设置为lastBlock(截止区块)值,原因如下:

在整个内部重要的bits是channel.send() ,它将通知发布到Discord,然后是fs.writeFile… bit,它将记录区块号,因为事件流从Observable(观察对象)返回到配置文件。跟踪区块号的原因是,Subspace观察对象从以太坊时间(即区块0)开始延续(除非另有说明)。因此,如果你的机器人崩溃或重启,那么观察对象也将重新开始并再次从区块0开始延续事件信息。我们并不希望机器人反复报告相同的事件信息,因此,我们总是将观察对象的配置选项中的 fromBlock (起始区块)设置为lastBlock(截止区块)。这样一来,如果机器人真的重启了,它将从最后一个事件的位置继续报告。

一旦机器人开始运作,你就会在你的Discord频道中看到下图这样的信息:

就是这样了。一旦启动并开始运行,该机器人将忠实地报告其关联的合约事件的每个新的事件信息。按照当前配置,ArgoDisco机器人将在投票开始时、有人投票时、出现新的付款时以及铸造或燃烧通证(代币)时,为DAO成员推送通知。

注意:对于铸造/燃烧代币的事件信息,使用你的DAO关联的ERC20合约,而不是Aragon上的DAO页面链接到的“通证”合约。

我希望上文对你有所帮助,这是一个说明Subspace能如何帮助你的Web3应用程序的真实例子,远远超越简单的Defi仪表盘。

免责声明:
本网站所提供的所有信息仅供参考,不构成任何投资建议。用户在使用本网站的信息时应自行判断和承担风险。币界网不对用户因使用本网站信息而导致的任何损失负责。用户在进行任何投资活动前应自行进行调查和研究,并谨慎决策。币界网不对用户基于本网站信息做出的任何投资决策负责。用户在本网站发布的任何内容均由其个人负责,与币界网无关。
免责声明:本网站、超链接、相关应用程序、论坛、博客等媒体账户以及其他平台和用户发布的所有内容均来源于第三方平台及平台用户。币界网对于网站及其内容不作任何类型的保证,网站所有区块链相关数据以及其他内容资料仅供用户学习及研究之用,不构成任何投资、法律等其他领域的建议和依据。币界网用户以及其他第三方平台在本网站发布的任何内容均由其个人负责,与币界网无关。币界网不对任何因使用本网站信息而导致的任何损失负责。您需谨慎使用相关数据及内容,并自行承担所带来的一切风险。强烈建议您独自对内容进行研究、审查、分析和验证。
s_logo
App内打开