本文翻译自@0xPhillan,原文链接:
Dune是一款非常强大的、面向大众的、完全免费的区块链链上数据分析工具,你可以通过SQL查询Dune公开的数据库,获得链上数据,并根据你的奇思妙想定制一个分析仪表板。Dune帮我们收集归类好了链上数据,我们只要学习一些简单的SQL,就可以成长为链上数据分析师啦!
本教程将手把手带你从头开始,以Pooly NFT为例,做一个NFT分析板!内容包括:项目募集资金(ETH本位和U本位),支持者数量(去重复的唯一地址),消费排行榜,剩余供应量百分比,总募集资金随时间的变化等,适用于调研和分析新开放mint的NFT。
Pooly NFT的mint即将截止,抓紧时间mint一个吧!
在本指南中,你将学到:
Pooly NFT系列构建查询和仪表盘:
让我们开始吧~!
打开Dune的网站时,会看到以下窗口。窗口顶部可以在仪表板、查询和分析师(Wizard)中切换浏览,你可以看看最新最火的仪表板,看看大家都在关心、查询什么数据,也可以慕名来看某个大神的分析板。也可以在右边按关键字搜索,或者按分类、热度查询。
仪表板是一系列查询的组合。查询是一个个具体的信息检索,比如查询某个人的年龄、身高、体重、血压等,把这些集合到一起变成一个体检报告,就是对一个人身体情况的基本描述,而仪表板就是这个体检报告。下面一个示例是大神@hildobby的以太坊仪表板。这里我们可以看到从 Dune 数据库中提取的各种数据,以总和、时间序列图的形式呈现。
在 Dune 中,每个仪表板的发布都是公开的,可以查看和复制其他人构建的查询或者仪表板,方便我们学习其他大神的分析,站在巨人的肩膀上看得更远。
前面提到过,仪表盘是查询的集合,如果你点击仪表盘中的任意部分,就会进入SQL查询:
我们可以看到查询界面主要由两部分组成:上方黑色区域是查询编辑器,作为输入部分,下方是结果输出区域。这里就是我们的主战场了,输入SQL代码,从Dune的数据库中摘取想要的数据。
可以简单理解为全套复制。可以将整个仪表板或仅图表的查询全套复制到自己的帐户,这跟GitHub一样。如果你只复制SQL代码,可能会忽略到数据集的选择,运行就会出错,但是通过单击右上角的“分叉”(Fork),把所有内容都复制到一个新窗口就不会出岔,你可以再次基础上继续编辑。
下图是一个以太坊价格表的查询,对这个查询点击“分叉”按钮,界面会来到一个新的查询编辑器,之前的查询代码已经全都复制进去了。
下面介绍查询界面的各个元素,对应下图的数字标记:
1、查询文件位置和名称
2、数据集浏览器 - 搜索特定数据集
3、查询窗口 - 在此处输入您的 SQL 查询
4、可视化选择器 - 选择是否查看查询结果、分叉折线图或创建新的可视化
5、运行 - 运行黑色窗口的SQL代码
6、结果/可视化 - 查看查询结果或使用查询结果创建的可视化
7、保存 - 保存查询
数据集浏览器中有六个功能区域:
在数据集选择中选择要解析的链。在以太坊上就选以太坊,在Polygon上就选Polygon,如果选择“Dune Engine V2(Beta)”就能使用 Dune 的最新增强功能,如多链查询,同时性能上有10 倍的提升,让数据查询更高效。
比如选择以太坊,可以看到很多合约调用和事件列表,有的是已经总结好的一些表。
在搜索框中输入搜索想要找的能容,比如想搜有关池子的,就搜索“Pool”,Dune 会搜索包含该关键字的所有数据表。用V2搜索的话,会和之前的链搜索结果不同,细微的区别可以自己发掘体验一下。
在原始区块链数据这栏里可以轻松找到 Dune 支持的各种区块链的查询,在原始表里选择想要的特定表列,或者过滤筛选特定的搜索结果精确获得链上数据。
解码项目是 Dune 团队将项目拆解、标记并分门别类,以便用户使用。对于解码项目,可以过筛选项目中特定的智能合约,从智能合约中又可以获得各种数据表格,就像处理原始区块链数据一样。
抽象可以理解为连接、组合各种查询和数据的自定义表。抽象可帮助用户更轻松地查询他们正在寻找的特定数据,而无需手动组合各种数据。
一般来说,抽象可以分为两大类:
从抽象子菜单中,我们可以看到带有类别抽象或是项目抽象标签的抽象列表。
社区部分可以认为是抽象部分的扩展,但数据聚合由 Dune 社区成员提供。目前只有一个条目“flashbots”是因为 Dune Engine V2 刚刚发布!随着时间的推移,我们可以期待看到越来越多靠谱的社区成员构建的社区数据集。
下图可以看到 Dune Engine V2 发布时在 Dune 中如何汇总数据。四个主要数据类别是:原始区块链数据、解码项目、抽象和社区;不同链分类;以及保存数据的类型。
以上就是对Dune各个部分的简单介绍了,相信能给大家留下一个简单的印象了,接下来在教大家自己动手做查询之前,我们先来学一个更重要的,怎么分叉(抄)别人的代码!
找个你想要的分叉的查询,点击分叉,保存查询时要先为查询命名。
保存完后就如下图, (1) 处查询文件位置和名称已更新,并且 (2) 输出框显示正在运行,这是 Dune 正在从他们的数据库中获取最新数据,该数据库会定期使用来自各种区块链的最新数据进行更新。
查询完成运行后,在 (3)处可以看到查询结果。
接下来对查询结果进行可视化编辑,在“查询结果”、“折线图”或“新可视化”中选择任何一个, 在(3)的设置里进行设置,命名等,2里面的结果会实时更新。这里还有一个“添加到仪表板”按钮,可以将新的查询结果或可视化结果添加到新的或现有的仪表板。
分叉完我下次打开Dune要如何查看我的查询呢?只要点击右上角的小圆圈就可以了。
查询列表包括之前保存在帐户中的所有查询。在下面的顶部屏幕截图中,我们可以看到创建的最新查询:
这就完成一个分叉并保存了一个查询!
分叉是 Dune 很牛逼的一个地方,它可以帮你通过借鉴其他大神构建过的内容,轻松快速地创建新查询,也可以组合多个分叉查询来构建自己的仪表板!
接下来将教你不通过分叉,自己动手从零开始建立一个自己的仪表板!
这节教你:
第二部分的内容以Pool Together DeFi 协议的 Pooly NFT为主题!(快到mint截止时间了,抓紧去mint一个吧!)
我们可以在 Dune 上先尝试着搜索一下“Pooly”,ok果然可以找到一些由社区创建的 Pooly NFT 追踪器。但是我们的目标是从头开始构建一个仪表板,学习如何搜索分析链上数据!
第一步,要构思一下这个仪表板从哪些角度来对目标项目进行分析,这里我们可以通过浏览Pooly NFT的官网来给一些参考思路。
我们可以在官网看到:
我们可以将这些指标作为我们仪表板中的内容!更进一步地,我们还可以添加
接下来我们将用Dune实现这些链上信息的检索提取,并做成我们的仪表板!
在使用Dune查找数据前,我们必须先找到正确的信息,比如目标代币或者NFT的合约地址。从PoolTogether上可以看出来,一共有三种NFT在售:
那么Pooly 是通过一份合约出售所有三种 NFT,还是通过三种不同的合约出售?我们要先弄明白这点。由于这是在以太坊主网上发行的NFT,我们到Eherscan上找找Pooly相关的智能合约。打开Etherscan,输入“Pooly”查看智能合约的所有者是否在 Etherscan 注册了它们。
OK,可以发现确实有三个智能合约,可能对应于三个 NFT 集合中的每一个。此外,我们现在知道每个 Pooly 都是一个 ERC721 代币。
打开三个集合中的每一个,并通过单击将鼠标悬停在地址上时出现的复制图标来复制智能合约地址,在页面底部我们还可以看到所有最近的交易。
我们需要这些智能合约地址,以便从Dune中提取正确的数据,把这些准备好:
0.1 ETH Pooly 支持者:
0x90B3832e2F2aDe2FE382a911805B6933C056D6ed
1.0 ETH Pooly 律师:
0x3545192b340F50d77403DC0A64cf2b32F03d00A9
75 ETH Pooly 法官:
0x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523
首先,到 dune.com 并单击屏幕右上角的“新建查询”。
打开查询编辑器,开始处理我们的查询!
首先,左上角从“7. Dune Engine V2 (Beta)”切换到“1. Ethereum”。Pooly 发布在以太坊上,因此我们只需要以太坊数据来进行此查询。而且“1.以太坊”中的表格比刚刚进入测试阶段的Dune Engine V2更成熟。
对于第一个查询,我们将构建一个计数器,用来显示以 ETH 计价的募集资金。
将以下代码复制到 Dune 的查询框中,按“运行”(或 CTRL+Enter):
select SUM("value"/1e18) from ethereum.transactions
where "to" = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or "to" = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'
上面的代码是一个 SQL 查询,它解析 Dune 的数据库以获取我们请求的特定数据。可以将 Dune 的数据库想象为各种表的集合,每个表都包含您可能想要提取的特定信息。使用 SQL,你可以
为了具体说明上述操作,让我们逐段运行上述代码。将以下代码复制到 Dune 的查询编辑器并运行它:
select * from ethereum.transactions
where "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
你会得到一个包含很多信息的大表:
让我们看一下 SQL 代码:
这段代码在说:
“从以太坊类别中的交易表中选择所有列,其中to列中的值为*\x3545192b340F50d77403DC0A64cf2b32F03d00A9* ”
说人话:给我看所有与 Pooly2 有关的智能合约交互记录
数据集浏览器这里已经有很多做好的表,可以直接搜索相关的表:
上述代码中,第三行起到过滤的作用,如果把它删去,搜索结果会返回以太坊上所有的交易记录,返回结果会非常慢,因为数据太多。显然查询越精准,运行速度越快。
因为我们只关心筹集的资金,不需要所有信息。所以让我们调整我们的代码,只抓取“value”列:
select "value" from ethereum.transactions
where "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
这样就只返回了一列值,需要注意的是合约地址这里,开头的0都需要替换成\
这些值看起来都非常大,这是因为他的计算单位是Wei而不是ETH,我们对这个值的数据处理一下就行,换算成ETH:
select "value"/1e18 from ethereum.transactions
where "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
这样我们看到的计价单位就是ETH,而不是Wei了。
而我们想要的是个总值,即求和,所以可以先加再转换单位,将“value”/1e18 包装在 SUM() 语句中:
select SUM("value"/1e18) from ethereum.transactions
where "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
这样我们就可以看到在 Pooly2 上花费的 ETH 总数!我们想要获得所有三个 Pooly NFT的总金额,需要把另外两个NFT的信息也加进来:
select SUM("value"/1e18) from ethereum.transactions
where "to" = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or "to" = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'
代码中“where”起筛选作用,“or”表示或集,但凡有一个是就算进来。
现在看到总共有 773.7 ETH 花费于所有三个 Pooly NFT上,与官网数据对比一下:
在 Pooly 网站上,我们看到 776.5 ETH ——恭喜实现目标!和我们计算的有 2.8 ETH 的差异,但是问题不大,Dune 会定期同步区块链数据,而且由于他们同步到数据库的数据集非常庞大,因此需要一些时间,数据将在接下来的一两个小时内刷新。
现在查询已经完成,设置一个计数器以便稍后在我们的仪表板上显示它。如下图,在查询结果框下方,单击新的可视化,在出现的下拉菜单中单击“计数器”。
最后,点击“添加可视化”:
出现一个计数器,向下滚动会看到各种设置,根据自己的喜好调整设置。
完成后,点击 (1)“添加到仪表板”并选择 (2)“新仪表板”,然后 (3) 为仪表板命名,点击 (4) “保存仪表板”。新仪表板将出现在您的仪表板列表中。从这里单击 (5),将可视化结果添加到的仪表板上的“添加”。
打开自己的仪表板,可以看到:
这个问题分两种情况分析:
如果我们查看 Etherscan 上的智能合约,可以看到大部分 ETH 已经从智能合约中移出,截至撰写本文时,Poly NFT 智能合约中还剩下 299.2 ETH。
如果我们查看之前的 Pooly 网站截图,776.5 ETH 的价值为 1,411,249 美元(1,817 美元/ETH),这暗示着 Pooly项目方可能将资金保留为 ETH,而不是美元。
很难说 Pooly 采用哪种方法,但两种计算美元价值的方法都很有趣:
那两种都来计算一下吧!
首先,fork 我们刚刚创建的查询,以此为基础做一些改变:
然后调整代码如下所示:
select SUM("value"/1e18) * (
SELECT "price" FROM prices.usd
WHERE "symbol" = 'WETH'
AND "minute" < now() - interval '1 hours'
ORDER BY "minute" DESC
LIMIT 1
)
from ethereum.transactions
where "to" = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or "to" = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'
注意我们在**SUM("value"/1e18)命令之后添加了一个乘法运算符***和一个大块代码。
在Dune,可以选中部分代码,点进仅运行选中部分。如下图选中(1),点(2)执行选中的部分:
在查询结果中可以看到 WETH 的最新美元价格,把 WETH 的最新价格乘以筹集的 ETH 数量就是它当前的美元价值。
让我们分解这部分代码:
为了更好地理解这段代码,(1)用**“*”替换“price”**(返回所有列); (2) 仅选择第 2 到 5 行的代码,(3) 运行:
在查询结果中看到由五列组成的完整表。首先检查一下 Etherscan.io 中的WETH合约地址:
这就是Dune中搜索的数据来源,现在回到刚刚搜出来的结果:
这里几列数据,第一列“minute”,指以分钟为单位的时间列,我们设了一小时的时间限制,所以只会返回最近一小时内的数据。查询限制根据需要,可做任意更改。第二列是价格,第三列是精确到多少位小数,第四列是代币合约地址,第五列是代币简称。
好,恢复前面的代码,再次运行查询:
运算结果是Pooly NFT总ETH对应的当前美元价值。
类似的,给他加个计数器,向下滚动并(1)单击计数器,(2)调整数据源和(3)更改标签。
完成后,记得保存并添加到我们的仪表板:
添加后,它将如下图所示:
这个查询会稍微复杂一些,因为我们必须查询两个表并组合结果,我们要获取每个交易并使用交易时的 ETH 价格转换每笔交易的美金价值。
同样,让我们先 fork 之前的查询:
从分叉的代码中,我们要进行以下操作:
with poolyTransactions as
(
select
block_time,
value/1e18 as value_eth
from ethereum.transactions
where "to" = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or "to" = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'
)
select
sum(value_eth * price)
from poolyTransactions tx
left join
(select minute, price from prices.usd
where symbol = 'WETH' and minute > '2022-05-01')
as prices on date_trunc('minute', block_time) = minute
运行代码,可以看到价值是140万美元。剖析这段代码,可以分成三个部分:
第 1 部分
第一部分构建了我们将引用的第一个表,命名为“poolyTransactions”,保存来自 ethereum.transactions 的 block_time 和 value_eth(以 wei 为单位的值除以 10^18转换为ETH,我们给它一个自定义的名称value_eth)。这个表中我们过滤已知的三个 Pooly NFT地址。
这里逐行解释:
第 2 部分
这部分逻辑还是比较简单的,价格乘以数量,从 poolyTransactions 这个表中选择数据。比较神奇的地方是调用了一个还没定义的“price”,这个price在第3部分会定义。
第 3 部分
这是我们定义两个表连接的地方。“left join”关键字允许我们这样做:
第三部分可能稍复杂些,我将各个部分重新组织如下图,便于理解:
(1) 创建 poolyTransactions 表1,然后 (2) 告诉 SQL 将它与另一个表2连接起来,(3) 表2是我们从 prices.usd 表中获得分钟和价格列。(4)把从 price.usd创建的表2连接到表 1poolyTransactions 上,使用以分钟为单位的时间作为映射变量,连接两表,两个表之间必须具有完全相同的一项作为桥梁。这里我们将 block_time 变量截断为分钟,在两个表之间创建匹配的时间项。通过以上操作,(5) poolyTransactions 表更新,将ETH的数量和对应当时的价格联系在了一起。
然后我们只需查询poolyTransactions 表,并将每一行的 value_eth 和 ETH 价格相乘的结果相加。
现在添加一个计数器,保存总金额并添加到前面的仪表板中!
我们想要知道购买了 Pooly NFT 的唯一地址(即支持总数),就是说即使一个地址购买了所有三种 Pooly 类型的多个 Pooly,也只算一次。
为了减少重复写代码,我们分叉第一个查询。
这里我们简单地改变第一行:
select COUNT(DISTINCT "from") from ethereum.transactions
where "to" = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or "to" = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'
COUNT会对括号内变量计数,而 DISTINCT 关键字去掉重复计算,得到的结果是 4660 个支持者。将其与 Pooly 网站上的唯一支持者进行比较,发现结果非常接近:
这表明我们的查询是正确的,因为 Dune 的数据库刷新和最新的区块链状态之间存在一点延迟。
同样的,更改计数器可视化并再次添加到仪表板。
接下来我们构建一个排行榜,内容包括地址、每个地址购买的 NFT 数量和总消费的ETH,以消费降序排列。那么我们需要的数据首先是购买者的地址,然后是购买的 NFT 数量,最后是购买所有 NFT 所花费的 ETH 数量。
我们这里查询的不是NFT持有情况,而是mint情况,可能有的用户mint完了就转走或者卖掉了,这我们不关心,我们只想知道首次mint的情况如何。通过以下代码实现:
with poolyTransactions as
(
select
"from",
hash,
value/1e18 as value_eth
from ethereum.transactions
where "to" = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or "to" = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'
)
select
"from", nfts_purchased, value_eth
from poolyTransactions
left join
(Select evt_tx_hash, COUNT("tokenId") as nfts_purchased
From erc721."ERC721_evt_Transfer"
Where (contract_address = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or contract_address = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or contract_address = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523')
and "from" = '\x0000000000000000000000000000000000000000'
group by 1)
as nfts
on evt_tx_hash = hash
ORDER BY 3 desc
这个表看起来会和“筹集的资金按购买时的ETH价格来计算”这个表非常相似,我们用了相同的方法:首先在 poolyTransactions 表中收集交易数据,然后留下个共同的映射值,让它和表2连接起来。表2我们使用的是erc721."ERC721_evt_Transfer",这是Dune维护的一个抽象,用于追踪以太坊上NFT的转移。在数据集浏览器中输入“erc721”,找到“ERC721_evt_Transfer”,可以看到该表具体包含什么内容。我们选中这部分代码,选择部分执行,可以看看我们从这个表中究竟要获得什么:
由于我们只关心新mint的NFT,所以限制“from”为空地址。以太坊上所有NFT都是从空地址发起铸造的。通过计算每笔交易的“tokenId”数量,就可以统计出一共有多少个NFT被mint了。
细心的话你会发现or的三个限制条件是在圆括号内的,而and这个限制条件是在圆括号外的。
括号决定了计算和/或过滤器命令的顺序,就像在 SQL 中执行算术命令时一样。如果我们没有将前三个语句括起来,则“and”条件将仅适用于最后一个过滤器设置。这里圆括号把前三个地址限制绑在一起,和后面“from”条件限制做一个交集。如果不加括号,如下图,那么“and”这个限制条件就会和最后一行“or”绑在一起,和前两个“or”无关。
我们使用“COUNT”命令计算了NFT数量,怎么将它和对应的被统计的地址联系在一起呢?这里使用了“group by”命令,表示我们要把count结果汇总到哪一列上。这里我们汇总到第一列,即“evt_tx_hash”。
之前说过,两个表要连接在一起,必须要有一个共同的映射,也就是要有重叠部分。这里两个表的重叠部分就是交易哈希值。最终,我们把erc721."ERC721_evt_Transfer"这个表(命名为nfts)和poolyTransactions表连接在了一起,输出的是一个表格,包括购买者地址,总购买NFT数量以及总消费ETH的金额。
最后我们还给了个命令“ORDER BY 3 desc”,意思是按第三列排序,也就是按消费ETH排序,可以一眼看到谁开销最多。
OK!排行榜做完了,和Pooly NFT网站上比一比:
老样子,还是由于同步时间问题有些许区别,但从这个列表中我们可以看到,一些地址、购买的 NFT 和总 ETH 花费的数字确实相同。成功!同样不要忘记把结果添加到仪表板!
除了使用 erc721."ERC721_evt_Transfer" 表,我们还可以使用 Dune 团队整理的 poolysupporter."PoolyNFT_call_mintNFT" 解码表。
with poolyTransactions as
(
select
"from",
hash,
value/1e18 as value_eth
from ethereum.transactions
where "to" = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or "to" = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'
)
select
"from", nfts_purchased, value_eth
from poolyTransactions
left join
(Select call_tx_hash, "_numberOfTokens" as nfts_purchased
From poolysupporters."PoolyNFT_call_mintNFT"
where contract_address = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or contract_address = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or contract_address = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'
)
as nfts
on call_tx_hash = hash
ORDER BY 3 desc
方法与上面相同。小区别是不用通过空地址来判断mint的情况,在解码表里直接看谁调用了mint函数就可以。
poolysupporter 数据集允许我们进行更具体和详细的查询,因为我们可以参考特定的合约调用。将两个结果对比一下:
果然一样!
在查询 4 中,我们使用了 poolysupporter 函数,在数据集资源管理器中搜索 pooly 时,你可能注意到了一个名为“PoolyNFT_call_maxNFT”的函数。
望文生义,你会觉得这个函数能直接检索NFT的最大可mint量。
很可惜,没有查询结果,从Etherscan上来看,这个函数是一个可读函数,调用的时候是没有链上记录的:
maxNFT 变量是在合约部署者部署 Pooly Supporter 智能合约时设置的,但这个智能合约尚未解码,无法直接从链上数据读取出最大供应量,这里我们只能从官方获取消息,手动填入最大供应量:
with poolyContracts as
(
Select contract_address,
COUNT("tokenId") as nfts_purchased
From erc721."ERC721_evt_Transfer"
Where (contract_address = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or contract_address = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or contract_address = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523')
and "from" = '\x0000000000000000000000000000000000000000'
group by 1
)
select
CASE contract_address
WHEN '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed' then 'Pooly_Supporter'
WHEN '\x3545192b340F50d77403DC0A64cf2b32F03d00A9' then 'Pooly_Lawyer'
WHEN '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523' then 'Pooly_Judge'
END as NFT_name,
nfts_purchased,
CASE maxNFT_Supply
WHEN '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed' then 10000
WHEN '\x3545192b340F50d77403DC0A64cf2b32F03d00A9' then 100
WHEN '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523' then 10
END as NFT_Supply,
CASE maxNFT_Supply
WHEN '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed' then 100-(nfts_purchased/10000.0*100)
WHEN '\x3545192b340F50d77403DC0A64cf2b32F03d00A9' then 100-(nfts_purchased/1000.0*100)
WHEN '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523' then 100-(nfts_purchased/10.0*100)
END as percent_supply_remaining
from poolyContracts
left join
(
Select contract_address as maxNFT_Supply
From erc721."ERC721_evt_Transfer"
Where (contract_address = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or contract_address = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or contract_address = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523')
and "from" = '\x0000000000000000000000000000000000000000'
group by 1
)
as maxNFT
on maxNFT_Supply = contract_address
ORDER BY 3 desc
手动将数字添加到 SQL 中的特定表条目并不简单,这里用了一些小技巧。
首先再次将两个表连接起来,然后用一些case when的语句来输出特定信息。具体分析,我们把代码拆解为4个部分:
第 1 部分
先定义了一个名为poolyContracts”的表,按三个NFT的每个合约地址,计算了tokenId个数, 也就是每种NFTmint了多少个,通过group by 1 把他们对应起来了。
第 2 部分
把erc721这个表中,三个NFT mint的事件摘出来。不使用group by 1的话就会每mint一个NFT,就报一遍这个NFT的名字(合约地址),使用group by 1,就只会显示一次,重复不显示。
把“contract_address”这一栏命名为maxNFT_Supply,方便后面用于两个表的连接。
第 3 部分
这部分是比较神奇的地方,这个连接起来的表,有四个变量:
我们这里相当于把一份数据拷贝成三份,每份后面都会对应一个操作。实际上1,3,4是一样的数据,3和4甚至名字都一样,但是他们分别来自两个表里,不会冲突。
选择1,3,4,分别嵌入CASE WHEN的语句,我们不能用CASE WHEN对一个数据集做三次申明,所以前面拷贝成了三份。
第一个CASE,把三个NFT地址替换成对应的NFT名称;第二个CASE,手动标上每个NFT的最大供应量;第三个CASE,计算了三个NFT的剩余量百分比。
需要注意的是,在进行运算时运算的数字要包含一位小数,否则SQL会以为我们想要返回整数,我们可以添加个“.0”,告诉SQL我们要返回一个精确到一位小数的结果。
第 4 部分
最后给他按供应排个序,也就是按第三列数据降序排列。
ok,这个查询就做完了,添加到仪表板中。
最后一个查询,我们来关心一个项目方募集的金额随时间的变化情况。
select
block_time as time,
sum(value/1e18) over (order by date_trunc('minute', block_time) asc) as cumu_value_eth
from ethereum.transactions
where ("to" = '\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'
or "to" = '\x3545192b340F50d77403DC0A64cf2b32F03d00A9'
or "to" = '\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523')
and date_trunc('day', block_time) < '2022-06-25’
这段代码不长,用了一个“over”的手法,这是求累积值的一个重要命令。
在这个查询中我们以分钟为间隔将 ETH 值(即value/ 1e18 )按block_time累加,按时间升序排列,并命名为cumu_value_eth。
sum(value/1e18) over (order by date_trunc('minute', block_time) asc) as cu
另外在末尾添加了个限制,让查询时间不超过2022.6.25,这是Pooly筹款活动结束的时间。我们的这个查询就只会显示活动时间内的金额变化。如何创建一个面积图:(1) 单击“新建可视化”,然后在 (2) 下拉菜单中选择“面积图”,最后 (3) 单击“添加可视化”。
这样面积图就会出现!并带有 Dune 默认的相关设置。
在下面的设置自由发挥,完成后保存到仪表板中不要忘了!
至此我们就完成了Pooly NFT看板的绝大部分内容了!最后来一点美观的整理!
第 3 部分:清理仪表板
我们构建了很多查询,并直接将它们添加到我们的仪表板中。好吧,让我们来看看它的样子。将最后一个图表添加到仪表板后,只需单击仪表板名称即可。
先来看看现在啥样:
其实我觉得这样已经挺棒了^_^
追求更美观的话点击右上角编辑
然后就可以随意地拖拉每个元素,任意放大缩小,这都很简单,自由发挥吧!
再加点小图片,美化一下……
感觉又专业又好看!
Dune Analytics 是一个强大的链上数据分析平台,而且完全免费,在追求数据自由的Web3,每个人都可以成为链上数据分析师,这对每个人来说都不遥远,完全可以做到!
参考链接: