RAN:「保姆级教程」如何用 Dune 分析区块链数据

原文作者:0xPhillan

原文来源:web3edge

原文翻译:老雅痞

Dune可能是目前大众可以使用的最强大的区块链数据分析工具,而且最棒的是:免费!使用Dune,通过公共数据库你可以近乎实时地访问区块链数据,可以使用SQL进行查询。

这是很强大的能量。

Dune在将区块链数据添加到数据库之前,会对其进行解码,这意味着你不必自己上手搞明白字节码。相反,你可以使用Dune的浏览器来浏览数据集、特定的智能合约、事件或调用!

Dune最近发布了V2引擎,将性能提高了10倍,现在就是你学习如何使用Dune的时候了。

在本指南中,你将学到:

第1部分:Dune界面

第2部分:使用SQL构建你自己的查询和图表——从最基础开始

第3部分:将所有内容组织到仪表板中

在此次的分步指南中,我们将为PoolyNFT系列构建包含以下内容的仪表板:

让我们开始吧!

仪表盘

查询

分叉

查询编辑器

数据集浏览器和数据分类

保存你的分叉查询

第2部分:构建你的第一个查询

决定建立哪些查询

寻找正确的信息

准备在Dune中建立你的第一个查询

查询1:以ETH形式筹集的资金

查询2:以美元筹集的资金

?查询2a:以当前ETH价值计算的美元筹款

?查询2b:以购买时的ETH价值计算的美元筹款资金

查询3:支持者总人数

查询4:

?查询4a:使用erc721的排行榜。抽象法

?查询4b:使用poolysupporter的排行榜。解码表

查询5:每个NFT集的最大供应量和剩余供应量

查询6:随着时间的推移,ETH筹集的时间序列图

结束

仪表板

仪表盘是一个查询的集合,它被安排成一系列的图表、计数器和其他信息,给用户提供关于特定兴趣领域的背景资料。下面,我打开了传奇人物@hildobby的以太坊仪表盘。在这里,我们可以看到从Dune的数据库中提取的各种数据,以集合或者时间序列图的形式显示。

在Dune中,每个仪表板都是公开的。这意味着任何人都可以查看和复制你构建的、或其他人构建的所有内容!这大大减少了仪表板的创建时间,并让你可以从其他用户的查询中学习。

查询

如果你还记得,我提到仪表板是查询的集合。如果你单击任何一个仪表板元素的标题,你将被带到该图表的SQL查询:

以太坊价格查询

让我们分叉以太坊价格图表!在查询上按“Fork”后,你将被带到查询编辑器,之前的代码已经复制进去!

查询编辑器

让我在这里向你介绍各种屏幕上的元素:

查询位置和名称——点击保存后可以更改名称!

数据集浏览器-搜索特定数据集

查询窗口-在此处输入你的SQL查询

可视化选择器-选择是否查看查询结果、分叉折线图或创建新的可视化

运行-运行查询窗口中的查询

结果/可视化-查看查询结果或使用查询结果创建的可视化

保存-保存你的查询!

链式选择

数据集搜索

浏览原始区块链数据

浏览解码合约数据

浏览数据的摘要

浏览社区提供的数据

Dune数据集浏览器概述

数据集选择

在数据集选择中,你可以选择想要解析的链。选择“DuneEngineV2(Beta)”可以让你使用Dune的最新增强功能,其中包括多链查询和10倍的性能提升。

数据集资源管理器中的数据集选择选项

如果你选择另一个链,类别选择将消失,而你将看到可以与之交互的合约调用和事件的列表。

选择“1.以太坊”

搜索

在搜索字段中,你可以输入搜索参数,Dune将以你的要求搜索包含该关键字的所有表格。

注意:DuneEngineV2和旧的搜索功能以不同的方式返回结果。旧的搜索返回所有结果的列表,而DuneEngineV2返回一个嵌套的结果列表。我们将使用V2引擎!

DuneEngineV2原始区块链数据概述

这是获取高级区块链数据的一种非常快捷方便的方法。

解码项目

在这里,你将找到已被Dune解码的项目。解码的项目是指Dune团队将项目拆开,贴上标签放入表格,以便用户对某些数据有一个简单的标准化的参考。

你会再次注意到,搜索结果是嵌套的。在最高级别,有你可以搜索的项目,在较低级别,你可以过滤该项目中的特定智能合约,最后我们会看到从该智能合约生成的各种表格。如果单击任何表格,你将看到一个列表,就像原始区块链数据一样。

DuneEngineV2解码项目概述

摘要

摘要可以被认为是连接和组合各种查询和数据块的,以形成唯一表格的自定义表。摘要可帮助用户更轻松地查询他们正在寻找的特定数据,而无需手动组合各种数据。

一般来说,摘要可以分为两大类:

部门摘要:特定部门的数据

项目摘要:项目特定数据

从摘要的子菜单中,可以看到带有标签的摘要列表,这些标签可以指定这个摘要是特定于部门还是特定于项目。

DuneEngineV2摘要概述

社区

社区部分可以被认为是摘要部分的扩展,但由Dune社区成员提供。

你可能想知道为什么社区部分只有一个条目——那是因为DuneEngineV2刚刚发布!随着时间的推移,我们可以期待看到越来越多受信任的社区成员构建的社区数据集。

DuneEngineV2社区概述

数据集浏览器标签

在下图中,你可以看到自DuneEngineV2发布以来,Dune中数据如何汇总的摘要:四个主要数据类别是原始区块链数据、解码项目、摘要和社区,它们以表格的形式保存了各种区块链的数据,可以保存各种数据类型。

DuneEngineV2数据浏览器中的标签概述

保存分叉查询

让我们先保存这个查询。点击保存后,会发生一些事情。首先,要为你的查询命名一个名字。

保存查询弹出窗口

选择名称后,你会注意到:

(1)查询位置和名称已更新,并且(2)你的查询正在运行。这意味着Dune正在从他们的数据库中获取最新数据,该数据库会定期使用来自各种区块链的最新数据进行更新。查询完成运行后,你将看到查询结果(3)。

分叉查询概述

从这里,如果你单击(1)“查询结果”、“折线图”或“新可视化”中的任何一个,(2)结果/可视化框将与(3)显示在其下方的选择设置一起更新。在这里,还有一个“添加到仪表板”按钮,可以快速将你的查询结果或可视化,添加到新的或现有的仪表板——就像之前@hildobby的以太坊仪表板一样!

查询结果和可视化部分

如果你点击(1)右上角的圆圈,然后点击(2)“我的查询”,将打开你帐户的查询列表。

导航到你的查询

查询列表包括你曾经保存在帐户中的所有查询。在下面的顶部屏幕截图中,我们可以看到创建的最新查询:

带有最新查询的查询列表保存在顶部

恭喜,你已经学会使用可视化分叉并保存了你的第一个查询!

分叉Forking是Dune的超级强大的功能之一,它可以帮助你通过建立在其他“巫师”在你之前建立的查询上,轻松而快速地创建新的查询。你可以结合多个分叉的查询来建立你自己的仪表板。

让我们动手并构建一个仪表板——一个查询和可视化的集合——从头开始,不走分叉这条路。这部分将教你在哪里可以找到正确的区块链详细信息以查找你的特定项目,并教你SQL的基础知识。

如何找到特定项目所需的正确信息

一些基本的SQL知识

但首先,我们需要决定仪表板的用途。PoolTogetherDeFi协议的PoolyNFT是第一步。

PoolyNFT铸造页面。来源:https://mint.pooltogether.com/

如果我们在Dune上搜索“Pooly”,果然可以找到一些由社区创建的PoolyNFT追踪器。

在Dune.com上搜索Pooly的结果

我们可以单击@0xbills创建的Pooly仪表板之一,然后单击“Fork”开始工作……

@0xbills通过https://dune.com/0xbills/Pooly-NFT

但是,如果我们从头开始构建它,我们将学习如何成为区块链侦探的同时,学习一些SQL!因此,需要从头开始构建我们自己的查询。

确定要构建的查询

首先,让我们决定想要在仪表板上使用哪些图表。让我们重建Pooly在其主页上构建的视图!仔细看下面两张截图,我们可以看到一些基于链上数据的指标。

带有资金跟踪器的PoolyNFT登录页面

PoolyNFT铸币厂选项和供应

我们可以看到:

筹集的资金与以ETH计价的资金目标

筹集的资金与以美元计价的资金目标

支持者总数

排行榜包括地址、每个地址购买的NFT数量以及按降序排列的总ETH

三种NFT类型中的每一种的最大供应量和剩余供应量

是不是超级棒!但这些只是时间的快照。让我们也给自己另一个挑战:

制作随时间上升的ETH时间序列图

就目前而言,我们无法以与Pooly网站相同的方式构建视图,但我们可以捕获相同数量的数据来构建我们的仪表板。

寻找正确的信息

在我们开始使用Dune之前,我们需要找到正确的信息。从网站上,我们可以看出PoolTogether正在销售三套NFT:

支持者–9个随机收藏品中的1个,价值0.1ETH

律师–1ETH只有一件艺术品

评委——75ETH只有一件艺术品

Pooly是通过一份合约出售所有三种NFT,还是通过三种不同的合约出售?

让我们前往Etherscan,看看是否能找到与Pooly相关的智能合约。打开Etherscan.io后,键入“Pooly”以查看这些智能合约的所有者是否在Etherscan上注册了它们。

在Etherscan上搜索Pooly

找到了!共有三个智能合约,可能对应于三个NFT集合中的每一个。此外,我们现在知道每个Pooly都是一个ERC721代币。

打开三个集合中的每一个,并通过单击鼠标悬停在该地址上时出现的复制图标,来复制智能合约地址。在页面底部我们还可以看到最近的所有交易,这将有助于以后的故障排除。

通过Etherscan查找Pooly合约地址

我们将需要这些合约地址从Dune中提取正确的数据,它们构成了我们所有查询的基础:

0.1ETHPooly支持者:

0x90B3832e2F2aDe2FE382a911805B6933C056D6ed

1.0ETHPoolyLawyer:

0x3545192b340F50d77403DC0A64cf2b32F03d00A9

75ETHPooly法官:

0x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523

准备在Dune中构建你的第一个查询

首先,导航到dune.com,然后单击屏幕右上角的“新查询”。

创建新查询

这将打开查询编辑器,我们就可以开始进行查询工作了!

新的和未触及的新查询窗口

查询1:以ETH筹集的资金

首先,在左上角从“7.Dune引擎V2”改为“1.以太坊”。Pooly在以太坊上,因此我们只需要以太坊数据来进行此查询。另外,“1.以太坊”比刚刚进入测试阶段的DuneEngineV2更成熟。

对于我们的第一个查询,我们将构建一个计数器,显示以ETH计价的募集资金。为此,请将以下代码复制到Dune的查询字段中,然后按“运行”:

selectSUM("value"/1e18)fromethereum.transactionswhere"to"='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'or"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'or"to"='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'

上面的代码是一个SQL查询,它解析Dune的数据库以获取我们请求的特定数据。你可以将Dune的数据库想象为各种表的集合,每个表都包含你可能想要提取的特定信息。使用SQL,你可以实现:

指定你想要的数据

是否要转换该数据

你要从哪个表中获取数据

是否要过滤数据

为了说明上述情况,让我们逐段运行上述代码。将以下代码复制到Dune的查询编辑器并运行它:

select*fromethereum.transactionswhere"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'

你会得到一个包含很多信息的大表:

使用*命令返回表中所有列的示例

现在让我们看一下SQL代码:

SQL代码分解

这段代码的意思是“从以太类别中的事务表中选择所有列,其中to列的值为x3545192b340F50d77403DC0A64cf2b32F03d00A9”,或者使用简单的英语:给我一个表,其中包含与Pooly2(1ETH)智能合约的所有智能合约交互。

你无需运行查询即可查看表中的列。数据浏览器让你通过其漂亮的搜索功能探索各种表头:

使用数据浏览器在“以太坊”中搜索表

我们可以完全删除第3行,以去除过滤器,然而,这将返回一个巨大的表,查询将需要很长的时间来完成。你的查询越精确,它们就会运行得越快!

因为我们只想查询归还筹集的资金,所以不需要所有列。所以让我们调整我们的代码,只抓取“value”列:

select"value"fromethereum.transactionswhere"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'

现在我们只有一个“值”列,而不是我们之前看到的很多:

返回“值”列中的所有条目

但是,你可能会注意到,这些值似乎非常大。那是因为它们是以Wei而非ETH计价的!为了解决这个问题,我们可以简单地将算术运算符应用于“值”列:

select"value"/1e18fromethereum.transactionswhere"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'

这样看起来是不是好多了!SQL中的1e18与10^18相同,我们只是告诉Dune将这个数字除以1,000,000,000,000,000,000,以便我们看到以ETH计价的值而不是Wei。

由于我们只想要总值而不是值列表,我们可以将“value”/1e18包装在SUM()语句中:

selectSUM("value"/1e18)fromethereum.transactionswhere"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'

太棒了,我们现在可以看到在Pooly2上花费的ETH总数!由于我们想要获得所有三个PoolyNFT智能合约的总花费,我们需要再添加两行以包含有关其他智能合约的详细信息:

selectSUM("value"/1e18)fromethereum.transactionswhere"to"='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'or"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'or"to"='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'

最终输出

“?or?”命令与“?where?”命令协同工作,并指定在过滤“to”列中的值时,如果找到第一个值或第二个值或第三个值,则应考虑该行。

我们现在看到,总共花费了773.7ETH用于所有三个Pooly合约。惊人的!让我们去Pooly网站看看是否正确:

将我们的输出与PoolyNFT页面上的官方数据进行比较。资金目标达到-恭喜!

在Pooly网站上,我们看到776.5ETH-恭喜实现目标!但是,哦不,有2.8ETH的差异!好吧——这没什么好担心的。Dune定期同步区块链数据。而且由于他们同步到数据库的数据集非常庞大,因此需要一些时间。我们可以预期数据将在接下来的一两个小时内刷新。

现在我们的查询已经完成,我们需要设置一个计数器以便稍后在我们的仪表板上显示它。在查询结果框下方,单击新的可视化,然后在出现的下拉菜单中单击“计数器”。

向查询添加计数器可视化

将出现一个计数器,如果向下滚动,你会看到各种设置。只需根据自己的喜好调整设置。

计数器可视化标签和标题设置

完成后,单击(1)“添加到仪表板”并选择(2)“新仪表板”。然后(3)为你的仪表板命名并(4)单击“保存仪表板”。新仪表板将出现在你的仪表板列表中。从这里单击(5)你希望将可视化添加到的仪表板上的“添加”。添加后,标签将从“添加add”变为“已添加added”。

将可视化添加到仪表板

如果你在此子菜单中单击仪表板的名称,你将被带到显示我们跟踪器的仪表板。

添加了可视化的仪表板

干得漂亮!

一旦我们完成了所有查询的设置,我们将回到编辑我们的仪表板。

查询2:以美元筹集的资金

我们有两种方法可以解决这个问题:

使用用于购买NFTs的美元资金的当前价值

使用购买时资金的美元价值

如果我们查看Etherscan上的智能合约,我们可以看到大部分776.5ETH已经从智能合约中移出,截至撰写本文时,PolyNFT智能合约中还剩下299.2ETH。

Etherscan.io上的Pooly1/2/3智能合约ETH余额

如果我们查看之前的Pooly网站截图,776.5ETH的价值为1,411,249美元,这暗示着Pooly智能合约所有者可能将资金保留为ETH,而不是美元。

最终,很难说Pooly采用哪种方法,但两种计算美元价值的方法都很有趣:

当前值告诉我们资金现在的价值

购买时的价值告诉我们购买者的预期美元金额

所以……让我们一起创造吧!

查询2a:以当前ETH价值以美元筹集的资金

对于这个,我们将使用我们之前的代码作为基础,并在一些额外的行中插入新代码以获得当前的美元价值。

首先,fork我们刚刚创建的查询:

/1e18)*(????SELECT"price"FROMprices.usd????WHERE"symbol"='WETH'????AND"minute"<now()-interval'1hours'????ORDERBY"minute"DESC????LIMIT1??)fromethereum.transactionswhere"to"='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'or"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'or"to"='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'

你会注意到我们在SUM(“value”/1e18)命令之后添加了一个乘法运算符*和一个大代码块。

在Dune中,你可以突出显示查询的特定部分,并通过单击“运行选择”仅运行该部分。让我们(1)仅突出显示括号内的行并(2)运行该选择:

通过选择查询的一部分,你可以只运行选定的部分。

在查询结果中你将看到WETH的最新美元价格!我们在这里的添加将WETH的最新价格乘以筹集的ETH数量,从而为我们提供美元价值。

让我们分解这个代码块:

先前代码的细分

从price.usd表中选择“价格”列

过滤“WETH”的符号列

仅查看过去1小时的时间条目

按降序排列

将查询限制为一个结果

为了更好地理解这段代码,让我们对查询进行一些小的调整。(1)将“price”替换为*和(2)仅选择第2到5行的代码,然后(3)运行选择:

稍作调整运行上一个查询

在查询结果中,你将看到由五列组成的完整表。首先,让我们检查一下Etherscan.io中的合约地址:

0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2

Etherscan.io上的WETH智能合约

该智能合约控制以太坊区块链上的WETH资产。距离我们的目标更进一步了!现在我们从之前的屏幕截图中知道了表格的来源,该屏幕截图显示了WETH的美元价格。

让我们将注意力转移回上一张表:

查询结果表我们之前的查询

在这里,我们有一个名为“分钟minute”的列,它每分钟跟踪ETH到美元的价值。由于我们将查询限制为“间隔1小时”,因此我们只能获得最新一小时的可用数据。出于我们的目的,我们实际上只需要最新的数据输入,因此将此查询限制在最后一小时会显着加快查询速度。例如,也可以将其更改为“1天”、“3天”或“1周”,以获取更多历史数据。

这里重要的是列名是“分钟”,因此我们的查询引用“分钟”列,不要将其误认为与时间相关的命令。

让我们将我们的代码恢复到我们在本节开头更改的内容并运行查询:

保存查询

结果是已经转移到Pooly1、Poly2和Pooly3智能合约以换取PoolyNFT的ETH的当前美元价值。

为此,我们将再次使用计数器,因此向下滚动并单击从我们之前的查询分叉的计数器,调整数据源和更改标签。

调整计数器可视化

完成后,记得保存并添加到我们的仪表板:

保存查询并将可视化添加到我们之前的仪表板

添加后,它将如下图所示。别担心,在本指南的最后,我们会清理它。现在,不要担心外观!

添加了第二个查询的仪表板

查询2b:筹集的资金以美元计算,购买时为ETH价值

这个查询会稍微复杂一些,因为我们必须查询两个表并组合结果。具体来说,我们将必须获取单个交易并使用交易时的ETH价格转换为每笔交易的ETH价值。

同样,让我们先fork之前的查询,为我们的下一个查询做准备:

分叉上一个查询。

从分叉的代码中,我们要进行以下操作:

withpoolyTransactionsas(select??block_time,??value/1e18asvalue_ethfromethereum.transactionswhere"to"='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'or"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'or"to"='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523')selectsum(value_eth*price)frompoolyTransactionstxleftjoin??(selectminute,pricefromprices.usd???????wheresymbol='WETH'andminute>'2022-05-01')???????aspricesondate_trunc('minute',block_time)=minute

使用购买NFT时的ETH-USD汇率查询。

如果我们在此处运行此代码,我们会看到我们收到了140万美元的美元价值。

让我们把这段代码分成三个部分:

将查询分为三个部分

第1节

在这里,我们构建了我们将引用的第一个表。我们在这里所做的是创建一个我们称之为“poolyTransactions”的辅助表,它将保存来自ethereum.transactions表的block_time和value_eth。对于这个表,我们过滤了我们知道的三个Pooly地址。

这里逐行解释:

第1行:使用poolyTransaction作为-定义名为“poolyTransaction”的辅助表具有以下属性

第3-11行:选择要包含在ethereum.transcations表中的列和过滤器

第5行:value/1e18asvalue_eth——这里我们将列重命名为“value_eth”,以便我们可以在第2节中直接引用它,而不是进行其他计算

第2节

这是我们创建输出表的地方。你会注意到我们正在从poolyTransactions构建一个表,这是我们在第1节中创建的辅助表,但我们还引用了一个我们尚未定义的名为“price”的列。价格实际上只在第19行后面定义!这是可能的,因为我们在第3节中将poolyTransactions与price.usd表中的某些输出连接起来。所以本质上,我们正在使用我们的辅助表?poolyTransactions?以及我们从price.usd中构建的表,创建一个表的下一节。

第3节

这是我们定义一个要与另一个表连接的表的地方。“leftjoin”关键字允许我们这样做:

第18行:leftjoin——关键字用于表示我们想将我们的第一个表与另一个表连接起来。这意味着,我们在第1节中定义的第一个表作为基表。

第19-20行:这里我们定义了我们想要从price.usd创建的表。在第20行中,我们将持续时间限制为“2022-05-01”,因为Pooly智能合约仅在5月份部署,因此如果我们将其限制在更小的时间范围内,可以显着加快查询数据的过程。

第21行:作为价格——这将第19-20行中的表格命名为“价格”,以便于将来参考

第22行:ondata_trunc('minute',block_time)=minute?–这是将我们的辅助表与价格表结合起来的行。这里所说的是从我们的辅助表中取出列“block_time”,并将其截断为仅按照分钟,即删除所有其他不是分钟的数据。price.usd表已经被截断为分钟,所以这里不需要进一步的转换。然后将prices.usd中的分钟列与我们辅助表中的分钟列进行匹配,从而将正确的价格从prices.usd分配到poolyTransactions中对应的分钟时间戳。

在数据集浏览器中查看price.usd表的分钟列

为了更好地可视化第三部分,我重新组织了各个部分以使其更易于理解:

连接命令每一步的可视化

(1)我们创建poolyTransactions表,然后(2)我们告诉SQL将它与另一个表连接起来,(3)我们将它定义为来自prices.usd表的分钟和价格列。然后将我们创建的这个price.usd表连接到左表poolyTransactions上,使用以分钟为单位的时间作为映射变量。要连接表,两个表必须具有完全相同的条目,如果我们将block_time变量截断为分钟,我们会在两个表之间创建匹配的分钟。通过这样做,(5)poolyTransactions表被更新以包括价格列,价格值与相应的日期相匹配。

从这里,我们只需查询连接的poolyTransactions表,并将每一行的value_eth和ETH价格相乘的结果相加。

现在添加一个计数器,保存并添加到仪表板!

向查询添加计数器可视化

计数器可视化设置并添加到仪表板

计数器可视化添加到仪表板

查询3:支持者总数

对于我们的下一个查询,我们想要计算购买PoolyNFT的唯一地址。这意味着即使一个地址购买了所有三种Pooly类型的多个Pooly,它们也应该只计算一次。

为此,让我们首先打开我们的第一个查询,将其分叉,记住,这一步也要保存。

分叉第一个查询

这里我们简单地改变第一行:

selectCOUNT(DISTINCT"from")fromethereum.transactionswhere"to"='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'or"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'or"to"='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'

独特的Pooly支持者查询

COUNT变量计算所有事务,而DISTINCT关键字确保每个唯一条目只计算一次。我们得到的结果是4660个独特的支持者。如果我们将其与Pooly网站上的独特支持者进行比较,我们会发现他们非常接近:

Pooly实时支持者数据

这表明我们的查询是正确的,因为Dune的数据库刷新和最新的区块链状态之间存在一点延迟。

最后,更改可视化计数器并再次添加到仪表板。

调整计数器的可视化设置并添加到仪表板

计数器添加到仪表板

查询4a:使用erc721的排行榜,摘要

接下来,让我们构建排行榜,包括地址、每个地址购买的NFT数量和总ETH以降序排列。

同样,让我们分叉之前的查询,这样我们就不必重新输入过滤后的地址。请记住在继续之前保存此新查询。

查看排行榜,我们需要三个信息。首先是购买者的地址,然后是购买的NFT数量,最后是购买所有NFT所花费的ETH数量。

Pooly排行榜列

在这里,我们正在查看不是购买了但没有持有的情况。完全有可能有人购买了NFT,然后将其移至安全钱包或稍后转售。我们只对首次购买感兴趣。

我们使用以下查询来实现这一点:

withpoolyTransactionsas(select??"from",??hash,??value/1e18asvalue_ethfromethereum.transactionswhere"to"='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'or"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'or"to"='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523')select"from",nfts_purchased,value_ethfrompoolyTransactionsleftjoin??(Selectevt_tx_hash,COUNT("tokenId")asnfts_purchased????Fromerc721."ERC721_evt_Transfer"????Where(contract_address='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'????orcontract_address='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'????orcontract_address='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523')????and"from"='\x0000000000000000000000000000000000000000'????groupby1)????asnfts????onevt_tx_hash=hashORDERBY3desc

Pooly排行榜表

你会注意到这与“购买时以ETH价值以美元筹集的资金”中的查询非常相似,这是因为我们使用了相同的方法:我们首先在poolyTransactions表中收集交易数据,然后我们留下了第二个表——它上面有一个共同的映射值。

在这里,对于第二个表,我们使用erc721.“ERC721_evt_Transfer”表,这是Dune维护的一个摘要,用于跟踪以太坊上的所有NFT传输。如果我们使用数据集浏览器,请输入“erc721”。并滚动到“ERC721_evt_Transfer”,我们可以看到该特定表中包含的所有内容。我们还可以只突出显示第二个表的命令,看看输出是什么:

由于我们只想要智能合约新铸造的NFT,因此我们必须将“发件人”地址指定为空地址。在以太坊上,所有NFT都是从空地址铸造的。通过计算每笔交易的“tokenId”数量,我们可以统计每笔交易铸造的NFT总数。

你还会注意到过滤器的定义方式有些特殊。前三个过滤器现在包含在括号中,而最后一个过滤器位于括号之外。

评估前三个过滤器语句是否用括号括起来

括号决定了计算和/或过滤器命令的顺序,就像在SQL中执行算术命令时一样。如果我们没有将前三个语句括起来,则and条件将仅适用于最后一个过滤器设置。

不使用括号时的评估

由于我们希望将fromnull地址过滤器应用于先前过滤器的所有结果,因此我们需要添加括号。

最后,由于我们使用“COUNT”命令,我们需要指定在哪一列进行计数。为此,我们使用“groupby”命令表示我们要将“tokenId”的计数分组到表中的第一列,即“evt_tx_hash”。

之前提到,我们需要一个通用映射值来将第二个表映射到表。在这里,我们使用交易哈希将每笔交易购买的NFT数量映射到我们的poolyTransactions表,这次我们也要求了交易哈希值。因此,最终,我们将erc721."ERC721_evt_Transfer"表的交易哈希值映射到我们的poolyTransactions表中,其中只包括用于购买poolys的交易。

输出是一个表格,其中包括购买者地址、总共购买的NFT数量以及花费的ETH总价值。

最后,我们告诉Dune为“ORDERBY3desc”,这意味着我们输出表的第三列应该按降序排列:

“ORDERBY3desc”命令。

超棒!我们的排行榜已经完成。让我们将其与PoolyNFT网站上的排行榜进行比较:

将Dune查询排行榜与Pooly网站排行榜进行比较。

并非所有数字都相同,但从这个列表中我们可以看到,一些地址、购买的NFT和总ETH花费的数字确实相同。这又是Dune和实时区块链数据之间的同步时间问题,无需担心。

请记住保存你的查询并将其添加到仪表板。

查询4b:使用poolysupporter的排行榜解码表

除了使用erc721.“ERC721_evt_Transfer”表,我们还可以使用Dune团队整理的poolysupporter.“PoolyNFT_call_mintNFT”解码表。

withpoolyTransactionsas(select??"from",??hash,??value/1e18asvalue_ethfromethereum.transactionswhere"to"='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'or"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'or"to"='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523')select"from",nfts_purchased,value_ethfrompoolyTransactionsleftjoin??(Selectcall_tx_hash,"_numberOfTokens"asnfts_purchased????Frompoolysupporters."PoolyNFT_call_mintNFT"????wherecontract_address='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'????orcontract_address='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'????orcontract_address='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'????)????asnfts????oncall_tx_hash=hashORDERBY3desc

方法与上面相同,只是使用此表我们可以直接返回所有调用mintNFT函数的交易哈希,而不是使用空地址来确定来自erc721的交易。“ERC721_evt_Transfer”表是mint交易。

使用poolysupporters。而不是erc721。

poolysupporter数据集允许我们进行更具体和详细的查询,因为我们可以参考特定的合约调用。

让我们比较两个表的结果以确保没有任何问题:

你看,输出是相同的。

请记住保存你的查询并将其添加到仪表板。

查询5:每个NFT集合的最大供应量和剩余供应量

在查询4的替代版本中,我们使用了poolysupporter函数。你可能已经看到,当你在数据集资源管理器中搜索pooly时,你还会看到一个名为“PoolyNFT_call_maxNFT”的函数。

poolysupporters.PoolyNFT_call_maxNFT函数

你可以得出结论,你可以使用这个函数调用来直接检索最大铸币量的NFT。

使用poolysupporters.PoolyNFT_call_maxNFT没有查询结果

不幸的是,这是不可能的:这个函数是一个“读取”函数,因此在调用这个函数时没有链上记录。请参阅下面的Etherscan:

maxNFT是一个读取函数,它不会在区块链上留下任何记录

maxNFT变量是在部署者合约部署PoolySupporter智能合约时设置的,但不幸的是,在撰写本文时,部署者智能合约尚未解码,因此我们无法从链上数据中获得最大铸币厂数量。

相反,我们必须手动输入每个智能合约的maxNFT数据:

withpoolyContractsas(Select?contract_address,????COUNT("tokenId")asnfts_purchased??????Fromerc721."ERC721_evt_Transfer"??????Where(contract_address='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'??????orcontract_address='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'??????orcontract_address='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523')??????and"from"='\x0000000000000000000000000000000000000000'??????groupby1)select??CASEcontract_address????WHEN'\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'then'Pooly_Supporter'????WHEN'\x3545192b340F50d77403DC0A64cf2b32F03d00A9'then'Pooly_Lawyer'????WHEN'\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'then'Pooly_Judge'????ENDasNFT_name,??nfts_purchased,??CASEmaxNFT_Supply????WHEN'\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'then10000????WHEN'\x3545192b340F50d77403DC0A64cf2b32F03d00A9'then100????WHEN'\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'then10????ENDasNFT_Supply,??CASEmaxNFT_Supply????WHEN'\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'then100-(nfts_purchased/10000.0*100)????WHEN'\x3545192b340F50d77403DC0A64cf2b32F03d00A9'then100-(nfts_purchased/1000.0*100)????WHEN'\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523'then100-(nfts_purchased/10.0*100)????ENDaspercent_supply_remainingfrompoolyContractsleftjoin??(??Select?contract_addressasmaxNFT_Supply??????Fromerc721."ERC721_evt_Transfer"??????Where(contract_address='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'??????orcontract_address='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'??????orcontract_address='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523')??????and"from"='\x0000000000000000000000000000000000000000'??????groupby1??)??asmaxNFT??onmaxNFT_Supply=contract_address??ORDERBY3desc

PoolyNFT供应查询

这是必须有点创意的地方。手动将数字添加到SQL中的特定表条目是一项艰巨的任务,我不得不应用一些技巧来得到这个,以便留下一个易于阅读的表。

在这里,我们将再次使用左连接来组合两个表,但我们还将在四列中的三列上使用CASEWHEN语句来输出我们想要显示的特定信息。我们要做的是首先创建我们的基表,然后创建第二个表,然后将第二个表与第一个表左连接并转换表输入以使其易于阅读,并为我们做一些简单的算术运算。

第二个表的原因是在单个查询中SQL不允许你两次调用列。实际上,我们需要多次调用一列,并分别转换每一列调用。然而,连接表允许我们多次调用第二个表中的列,从而使我们能够为我们需要的列中的特定行创建所需的输出。

上述查询的细分

让我们将这个查询分成四个部分以便于消化。

注意顺序!1、3、2、4!

第1节

在本节中,我们定义了一个名为“poolyContracts”的表,其中我们计算了来自三个Pooly合约地址的空地址的所有单个tokenId,因此仅包括使用erc721.“ERC721_evt_Transfer”表铸造的NFT。然后,我们将它们按第一列分组,从而返回每个池智能合约的铸造NFT。

poolyContracts表

第2节

在这个代码块中,我们强制查询只显示三个合约地址中的每一个。我们通过使用“按1分组”命令来做到这一点,即按第一列的唯一条目对结果进行分组。

第二个表使用“groupby1”命令返回每个合约地址的1个

如果没有groupby命令,查询将返回与这些合约地址相关的所有传输事件,但我们只需要每个出现一次。你将在下一节中看到原因。

第二个表返回一长串没有“groupby1”命令的合约地址

此外,我们将contract_address列重命名为maxNFT_Supply,以便我们可以定义将该表与哪个列连接到poolyContracts表中。

第3节

这就是魔法发生的地方。

在本节中,我们现在可以从连接表中调用列。我们称之为:

合约地址

nfts_purchased

maxNFT_Supply

maxNFT_Supply

你会注意到,我们基本上使用第1、3和4列检索相同的数据3次,而且第3和4列甚至是相同的列!这是可能的,因为我们连接了两个表。如果在连接表之前调用contract_address两次,查询编辑器将返回错误消息。

接下来,你还会注意到第1、3和4列都嵌入了CASEWHEN子句。因为我们创建的前两个表中的每一个只有一个用于每个智能合约的唯一行,所以我们不能使用CASEWHEN语句来指定是否出现特定的智能合约地址,在其位置返回其他内容。

未按nft_supply排序结果的完整表

你将在此处看到第一列,我们告诉查询编辑器将每个智能合约地址替换为相应NFT的名称!

在第三列中,我们将其替换为Pooly网站上列出的已知最大NFT数量。

在第四列中,我们使用一个公式来计算剩余NFT供应的百分比。在这些语句中,至少有一个用于算术运算的数字需要包含一位小数。如果这不包括在内,SQL查询将被解释为想要返回整数,这意味着我们不会为这些计算获得任何小数。通过包含“?.0”,我们向服务器表明我们希望此计算返回一个十进制数。

第4节

最后,我们指出我们希望输出按第三列的降序排序。

按nft_supply降序排序后的全表

这张表也做好了。保存你的查询,对表格进行所需的任何更改并将其添加到仪表板。

将表添加到仪表板

查询6:随时间筹集的ETH时间序列图

在我们的最终查询中,我们将创建一个时间序列图表,显示随着时间的推移通过NFT销售筹集的ETH数量。

select??block_timeastime,??sum(value/1e18)over(orderbydate_trunc('minute',block_time)asc)ascumu_value_ethfromethereum.transactionswhere("to"='\x90B3832e2F2aDe2FE382a911805B6933C056D6ed'or"to"='\x3545192b340F50d77403DC0A64cf2b32F03d00A9'or"to"='\x5663e3E096f1743e77B8F71b5DE0CF9Dfd058523')anddate_trunc('day',block_time)<'2022-06-25’

随着时间的推移,ETH的累计NFT销售额。

这是一段较短的代码,但它包含over命令,这是聚合累积值的重要命令。

在这个查询中,我们首先选择block_time,然后我们以分钟为间隔将ETH值与block_time相加,我们直接按升序排序,并将列命名为cumu_value_eth。

sum(value/1e18)over(orderbydate_trunc('minute',block_time)asc)ascumu_value_eth

此外,我们还在结尾处添加了另一个过滤器,其中规定对于这个查询,封锁时间不应超过2022-06-25,根据Pooly网站,这大概是募捐活动结束的时间。这样,我们的区域图将只显示活动的数据,而不是添加一条平线,随着时间的推移,平线将拖入永恒。

要创建区域图,点击"新可视化",然后在下拉菜单中选择"区域图",最后点击"添加可视化"。

创建面积图可视化

你的面积图应该会自动出现,并带有Dune预先选择的相关设置。

面积图可视化设置并添加到仪表板

如果未预先选择它们,你可以使用图表下方的设置,直到看起来正确为止。

最后,保存你的查询并再次按“添加到仪表板”。

第3部分:清理仪表板

我们构建了很多查询,并直接将它们添加到我们的仪表板中。好吧,让我们来看看它的样子。将最后一个图表添加到仪表板后,只需单击仪表板名称即可。

添加可视化后,单击仪表板的名称将其打开

而且,让我们看看……

清理前的仪表板

这肯定需要在它呈现之前进行清理。

在仪表板屏幕的右上角,单击“编辑”开始编辑。

单击右上角的编辑按钮以编辑仪表板格式

从这里,你可以在移动元素时将单个元素拖放到背景中由红色框显示的网格上,并且可以通过拖动左下角的图标来调整每个元素的大小。简单的!

可视化和其他元素支持拖放和调整大小

要将文本和图像添加到仪表板,请按仪表板编辑屏幕右上角的“添加文本小部件”。

单击“添加文本小部件”以添加文本小部件

在整理时,你可能会注意到这两个查询看起来相同,并且两者都没有真正提供任何有价值的信息......:

两个计数器显示了计算ETH美元价值的不同方法

因为我们不知道PoolTogether何时或如何提取智能合约中的ETH,所以我们可以坚持Pooly网站是如何做的。我们将删除正确的查询并将其替换为另一个查询。

我们开始吧,最后的仪表板:

最后的仪表板

这看起来比以前好多了,而且它也遵循了与Pooly网站相同的格式!

结束

DuneAnalytics是一个强大的平台,可以在合适的人手中提供深度区块链数据能力。我希望通过这篇文章,我能够教你基础知识。从这里开始,你可以接受更大的挑战并制作更好的仪表板。

郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。

链链资讯

[0:0ms0-5:98ms