什麼是Event?
在當前的區塊鏈技術裡面,大部分的公鏈項目都有event 的定義。
它擔任著區塊鏈交互中非常重要的角色。因為在傳統的Web 開發中,客戶端與服務端交互的大部分情況可以讀寫同步響應,而在區塊鍊網絡交互更像一個異步的讀寫分離系統,比較像目前流行的CQRS 架構模式,有很多合約的結果返回是需要等待區塊打包挖掘後產生的,所以在合約中提交event 是一個很重要的與用戶交互的方式。
總結來看,event 有以下2個用途:
- 獲取交易中合約的返回數據;
- 監聽合約的各種操作狀態;
Aptos 架構中的Event 設計
在Aptos 的設計裡面,可以通過fullnode 的rest service 以Node API的形式進行區塊鏈的交互。對於一次tx (transaction),大概經過的步驟:
- 從rest service 代理transaction 到validator 的mempool 組件進行緩存;
- 通過幾個組件的努力,最終區塊達成共識,由Execution 調用Storage 組件進行區塊下交易的永久保存,其中也包括了代表運行結果的event 數據;
- rest service 通過Storage 組件獲取event 的數據;
如何通過Node API 查詢Event?
Chainbase 現在已經提供了穩定高效的fullcode 節點集群,可以註冊生成Aptos Mainnet 的Node API endpoint,參見文檔點擊。
簡單創建後,我們就擁有了自己的Node API 服務: https://aptos-mainnet.s.chainbase.online/{your-api-key}/v1
(注意:需要將{your-api-key} 替換成你的API KEY)
以查詢官方domain 項目Aptos name v1 的域名映射事件為例子。通過鏈上數據的分析,項目的account address 是: 0x867ed1f6bf916171b1de3ee92849b8978b7d1b9e0a8cc982a3d19d535dfd9c0c.
我們先看一下ABI 的事件定義(這也是Aptos 比較友好的地方,可以通過鏈上查詢ABI),通過Get account modules接口。請求:
提取這里關鍵的event 定義的信息,我們通過Get events by event handle構造出可以獲取該事件的請求:
- address =
0x867ed1f6bf916171b1de3ee92849b8978b7d1b9e0a8cc982a3d19d535dfd9c0c
- event_handle =
0x867ed1f6bf916171b1de3ee92849b8978b7d1b9e0a8cc982a3d19d535dfd9c0c::domains::SetNameAddressEventsV1
- field_name =
set_name_events
這樣可以通過Node API 不斷輪詢獲取這些事件的數據。其中domain_name 就是域名,new_address 就是映射的address
Node API 具有局限性
通過上面的例子,我們可以不間斷地獲取最新的事件。但是如果我們希望查詢某個domain 最新的映射地址是什麼,或者希望分析每天domain 的註冊量,類似這樣的需求,基於Node API 是無法被滿足的。
從本質來看,Aptos 的Node API 是為了滿足最基本的區塊鍊網絡交互,其背後的存儲和組件不是為了數據的各種維度的分析、檢索、索引來設計的。
如何使用Chainbase 處理Node API 的局限性
Chainbase Data Cloud通過數據結構化、清洗、索引,計算導入到更加符合數據分析場景的雲端數據倉庫服務,讓用戶可以更加高效、輕鬆地訪問Aptos 的任意數據,並且可以基於SQL 生成定制化的API 服務
- Aptos Raw Data: 如events,transactions,table_items,move_modules,move_resources 等等文檔
- Aptos Abstract Data: 如coin,token 等等文檔
下面我們還是以上面Aptos name v1 的數據場景舉例
當域名=000.apt 的時候,如何查詢address 和expiration time
select JSONExtract(data, 'domain_name', 'String') as domain, JSONExtract(JSONExtract(data, 'new_address', 'String'), 'vec', 'Array(String)') as registered_address, toDateTime(JSONExtract(data, 'expiration_time_secs', 'String')) as expiration, transaction_version from aptos.events where type = '0x867ed1f6bf916171b1de3ee92849b8978b7d1b9e0a8cc982a3d19d535dfd9c0c::domains::SetNameAddressEventV1' and account_address = '0x867ed1f6bf916171b1de3ee92849b8978b7d1b9e0a8cc982a3d19d535dfd9c0c' and domain = '000'
如何查詢已註冊域名的總數
select count(1) from aptos.events where type = '0x867ed1f6bf916171b1de3ee92849b8978b7d1b9e0a8cc982a3d19d535dfd9c0c::domains::RegisterNameEventV1' and account_address = '0x867ed1f6bf916171b1de3ee92849b8978b7d1b9e0a8cc982a3d19d535dfd9c0c'
如何查詢Top 10 holder accounts
select JSONExtract(JSONExtract(data, 'new_address', 'String'), 'vec', 'String') as registered_address, count(*) as holder_total from aptos.events where type = '0x867ed1f6bf916171b1de3ee92849b8978b7d1b9e0a8cc982a3d19d535dfd9c0c::domains::SetNameAddressEventV1' and account_address = '0x867ed1f6bf916171b1de3ee92849b8978b7d1b9e0a8cc982a3d19d535dfd9c0c' and registered_address != "[]" group by registered_address order by holder_total desc limit 10
從上述案例可看到,Chainbase 的Data Cloud 非常快速高效地獲取了Aptos 上的Event 數據,在開發者文檔中,你能獲取更多的案例和代碼,歡迎大家前來探索。
祝你們在Aptos 玩得開心!