区块链数据解析(2):Address
区块链数据解析(2):Address
Data Concept
地址类型
以太坊上的地址主要分为两种,一种是钱包地址,一种是合约地址
- 相同之处
- 数据内容一致,都是 40 个十六进制字符组成的字符串,同时都具备价值存储,价值转移等功能
- 不同之处
- 交易只能由钱包地址发起
- 合约地址被动执行
- 合约是多种功能实现的桥梁,例如 dapp 的各种业务都是通过合约来实现
- 合约是各种价值存储载体,例如 token,nft 等等
通过了解两种地址的相同与不同,我们看看他们对应的结构是怎样的构成,同时了解通过一些分析场景来了解这些数据是如何应用的?我们先看看 wallet address 的情况,再来了解 contract address 以及它的各种实现的分析。
Contract 表现形式
- 在区块链上,合约有多种具体表现形式,例如 erc20 token, nft 或者是一个协议 (protocol ) 的功能性合约
Wallet Address
分析纬度
wallet address 我们提供了以下的这些常用的分析:
Balance
- 通过分析地址持有的热门 token ,知道当前钱包的总价值,可以用来追踪一些大鲸在链上的资金变动情况
Portfolio
- 通过对 address 的组合,分析一个 portfolio 的资产情况,这个 portfolio 可以是个人的投资组合,也可以是实体公司的链上资产组合,例如 CEX , 通过 portfolio 的汇总,可以知道像币安这样的交易所资产的变化情况以及异动。
Tags
- 标签是一种常用的分析场景,链上的地址只是一串数字,需要结合链下的数据对地址赋予意义更加有助于分析地址的情况。同时上面提到的大鲸,CEX 这些都是通过标签归纳得出的数据,从链上是无法直接获取这样的数据。
Balance 取数方法
balance 取数一般有两种方法:
- 从链底层数据 token_transfers/traces 汇总计算
- 通过归档节点从合约获取
这两种方法各有优劣,从链底层数据汇总计算可以方便计算历史每个时刻的持有,有助于分析历史的变化情况,但缺点是需要消耗比较大量的计算资源,同时余额如果是根据合约每日/实时进行 rebalance 的合约会计算不准,例如 SETH 等;从合约获取数据优点是数据准确,但如果要回溯历史上每天的情况成本相对较高,依赖归档节点性能以及合约调用量限制,因此一般用于取最新余额.
余额类型
以以太坊为例子,我们常用的余额类型分三种大类:
- Gas token 余额,在以太坊即 ethers
- ERC20 token 余额
- NFT 余额,包括 ERC721 以及 ERC1155 类型
链底层数据取数
假设取钱包/合约地址为 0x81e4fb0c64bf49f89b57f6648562fc9a791b2e92
持有的 0x15d4c048f83bd7e37d49ea4c83a07267ec4203da
token 最新的余额情况:
1
2
3
4
5
6
7
8
SELECT SUM(CASE
WHEN from_address = '0x81e4fb0c64bf49f89b57f6648562fc9a791b2e92' THEN -amount_raw
ELSE amount_raw
END)/1e8
FROM ethereum_token_transfers
WHERE token_address = '0x15d4c048f83bd7e37d49ea4c83a07267ec4203da'
AND (from_address = '0x81e4fb0c64bf49f89b57f6648562fc9a791b2e92'
OR to_address = '0x81e4fb0c64bf49f89b57f6648562fc9a791b2e92')
合约取数
获取某个区块下用户持有的 ether 情况
使用 python 代码为例调用链上节点数据获取用户余额情况:
1
2
3
def query_eth_balance(wallet_address: str, block_number: int):
balance = w3.eth.get_balance(w3.toChecksumAddress(wallet_address), block_identifier=block_number)
return balance / (10 ** 18)
获取某个区块下用户持有的 ERC20 token 情况
使用 python 代码为例调用合约数据,获取用户 ERC20 某个时刻的持有情况,获取持有的 NFT 也可以通过同样的方法调用:
1
2
3
4
5
def query_erc20_balance(wallet_address: str, token_address: str, token_decimals: int, block_number: int):
erc20_token = w3.eth.contract(address=token_address, abi=erc20_abi)
token_balance_raw = erc20_token.functions.balanceOf(w3.toChecksumAddress(wallet_address)).call(
block_identifier=block_number)
return token_balance_raw / (10 ** token_decimals)
分析场景
查询某个地址当前持有 ERC20 最新余额
1
2
3
4
5
6
7
8
9
SELECT contract_address,
amount AS balance,
value
FROM address_latest_balance
WHERE CHAIN ='Ethereum'
AND wallet_address= lower('0x81e4fb0c64bf49f89b57f6648562fc9a791b2e92')
AND standard = 'ERC20'
ORDER BY 3 DESC
-- 这里使用 footprint 的 address_latest_balance 表进行查询,该表包含了所有地址最新的余额数据
资金流分析
This post is licensed under CC BY 4.0 by the author.