Cùng Khám Phá Các Tính Năng Hay Của Dfuse
Bài đăng này đã không được cập nhật trong 4 năm
Các Trạng Thái Của Một Transaction Ethereum Và Cách Điều Hướng Chúng Bằng Dfuse
Như bài trước thì mình đã làm rõ được các trạng thái trong lifecycle của một transaction và giới thiệu về Dfuse. Hiện dfuse đang hỗ trợ cho 2 nền tảng là Ethereum và EOSIO thì trong bài viết này mình sẽ đi vào cách sử dụng của thằng dfuse trên nền tảng Ethereum.
Tạo tài khoản free
1. đăng ký
Mọi người truy cập đến https://app.dfuse.io để tạo tại khoản
Tại thời điểm viết bài này thì mình không đăng ký (Sign Up) bằng email được có thể là do lỗi tạm thời của nhà phát triển. Ngoài cách đăng ký bình thường thì vẫn có 2 cách Oauth là bằng Google và Github, mình lựa chọn bằng google
Điền các thông tin cần thiết và chọn "Create Account"
Sau khi tạo xong sẽ có giao diện như sau
2. tạo API key
Truy cập https://app.dfuse.io/keys --> chọn "CREATE NEW KEY"
kết quả sẽ như sau
3. Các cách Authentication
Có 2 loại key trong cách sử dụng dfuse:
- Loại có thể tồn tại lâu API key - sẽ có dạng
server_abcdef123123123000000000000000000
, từ loại này thì có thể tạo ra được loại key tồn tại thời gian ngắn JWT. - Loại tồn tại trong thời gian ngắn JWT - sẽ có dạng như sau:
eyJhbGciOiJLTVNFUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTYxMzI4MjAsImp0aSI6IjQwNWVmOTUxLTAwZTYtNGJmNC1hZWMxLTU0NTU1ZWMzMTUwMiIsImlhdCI6MTU1NjA0NjQyMCwiaXNzIjoiZGZ1c2UuaW8iLCJzdWIiOiJ1aWQ6MHdlbnU2NmUwNzU4OWRhODY4MWNlIiwiYWtpIjoiM2NhYWEzYzA3M2FlZjVkMmYxOGUwNjJmZDkzYzg3YzMzYWIxYzA1YzEzNjI3NjU2OTgzN2Y5NDc5NzZlMjM0YSIsInRpZXIiOiJmcmVlLXYxIiwic3RibGsiOi0zNjAwLCJ2IjoxfQ.000HeTujIuS_LRvvPN6ZRCmtoZqZyV6P1enNBviwK8v7Tf7BLHJIrEpQoEREKSIMdZWPrMQl_OE55yJP0MxUDA
Thì từ API key chúng ta có thể lấy được JWT bằng cách tạo request lên https://auth.dfuse.io/v1/auth/issue
curl -XPOST \
-H "Content-Type: application/json" \
--data '{"api_key":"<API-KEY>"}' \
"https://auth.dfuse.io/v1/auth/issue"
Response trả về
{
"token":"eyJhbGciOiJLTVNFUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTYxMzI4MjAsImp0aSI6IjQwNWVmOTUxLTAwZTYtNGJmNC1hZWMxLTU0NTU1ZWMzMTUwMiIsImlhdCI6MTU1NjA0NjQyMCwiaXNzIjoiZGZ1c2UuaW8iLCJzdWIiOiJ1aWQ6MHdlbnU2NmUwNzU4OWRhODY4MWNlIiwiYWtpIjoiM2NhYWEzYzA3M2FlZjVkMmYxOGUwNjJmZDkzYzg3YzMzYWIxYzA1YzEzNjI3NjU2OTgzN2Y5NDc5NzZlMjM0YSIsInRpZXIiOiJmcmVlLXYxIiwic3RibGsiOi0zNjAwLCJ2IjoxfQ.000HeTujIuS_LRvvPN6ZRCmtoZqZyV6P1enNBviwK8v7Tf7BLHJIrEpQoEREKSIMdZWPrMQl_OE55yJP0MxUDA",
"expires_at":1556132820
}
Hãy nhớ rằng loại JWT này sẽ có thời gian hết hạn, trường response expires_at
ở trên chính là thời gian mà token này hết hạn. Vì vậy trước khi sử dụng chúng ta cần xem lại trường này xem ngày hiện tại đã hết hoặc gần hết chưa để tạo một token mới. Cách đơn giản để xem thời gian hết hạn là sử dụng các trang convert timestamp online here
REST Authentication
Đối với REST API chúng ta có thể set token vào header của request như sau
curl -H "Authorization: Bearer <YOURTOKENHERE>" -u https://mainnet.eos.dfuse.io/v0/state/... [ ... ]
WebSocket Authentication
Con trong websocket thì ta sử dụng như sau
ws wss://mainnet.eos.dfuse.io/v1/stream?token=<YOURTOKENHERE>
Explore ETH thông qua dfuse
Cách tốt nhất để biết dfuse có thể làm được những gì đó chính là hãy dùng thử các tính năng của nó. GraphiQL là một công cụ cho phép bạn có thể viết và thực thi query GraphQL từ browser. Nó thì đã được tích hợp sẵn xác thực JWT ẩn danh nên vấn đề xác thực chúng ta không cần quan tâm, công việc bây giờ là cần tìm hiểu về documented GraphQL schema để có thể viết được các câu query như mong muốn. Cái này thì có hỗ trợ Ctrl+<Space>
nha, để truy cập GraphiQL thì bấm vào link ảnh bên dưới.
Dưới đây sẽ là một vài ví dụ
Fetch
-
Get thông tin của transaction bằng mã hash
{ transaction(hash: "0x1f73b43dc9c48cc131a931fac7095de9e5eba0c5184ec0c5c5f1f32efa2a6bab") { from to gasPrice(encoding: ETHER) } }
- Get block
{ blockByNumber(number: 7280000) { hash header { parentHash difficulty } } }
Stream
- Stream blocks (sau mỗi 12s sẽ get về một lần)
subscription{ blocks(lowBlockNum:-1){ node{ number hash transactionTraces { edges { node { hash } } } uncles { hash } } } }
-
Stream transactions bằng câu lệnh query
subscription { searchTransactions(indexName: CALLS, query: "-value:0", lowBlockNum: -1) { undo cursor node { block { number } matchingCalls { from to value(encoding: ETHER) } } } }
Search
Các truy vấn tìm kiếm (hoặc stream data thông qua subscription GraphQL hay paginated phân trang thông qua GraphQL query) thì được xây dựng bằng dfuse Search Query Language. Hãy xem tài liệu tại Ethereum Search Terms Reference để biết danh sách đầy đủ các thuật ngữ sẽ được chấp nhận.
Mọi người có thể truyền các truy vấn tìm kiếm nào vào trực tiếp https://ethq.app hoặc truyền vào các phần tham số của phương thức searchTransaction
trong GraphiQL.
Dfuse thì có 2 kiểu indexe riêng biệt là: CALLS và LOGS
-
Tìm kiếm các transactions có transfer ETHER( tức là amount khác 0) từ một địa chỉa hoặc đến một địa chỉ nào đó.
# with indexName = CALLS -value:0 (to:0x32be343b94f860124dc4fee278fdcbd38c102d88 OR from:0x32be343b94f860124dc4fee278fdcbd38c102d88)
-
Tìm kiếm các giao dịch có chứa method
transfer(address, uint256)
trên token contract ERC-20 đã biết# with indexName = CALLS method:'transfer(address,uint256)' to:0xdac17f958d2ee523a2206206994597c13d831ec7
Method cũng có thể được chỉ định với tiền tố 8 bit of hàm băm keccak, ví dụ:
method:a9059cbb
-
Tìm kiếm các transaction được ký bởi một địa chỉ nhất định :
# with indexName = CALLS signer:0x59a5208B32e627891C389EbafC644145224006E8
-
Tìm kiếm các transaction cung cấp đầu vào cho một contract nhất định:
# with indexName = CALLS input.0:0x84ae8708798c74ef8d00f540c4012963955106ff to:0x06012c8cf97bead5deae237070f9587f8e7a266d
-
Tìm kiếm các giao dịch khớp với một topic cụ thể trong logs của các cuộc gọi đến EVM:
# with indexName = LOGS topic.0:0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
-
Tìm kiếm các giao dịch khớp với một đoạn dữ liệu cụ thể (32 byte) trong logs của EVM:
# with indexName = LOGS data.0:0x0000000000000000000000004a220e6096b25eadb88358cb44068a3248254675
Bắt đầu nhanh với JavaScript
Bài demo này mình sẽ hướng dẫn trong môi trường node về cách để theo dõi khi có bất kỳ một transaction mới được gửi lên mạng. Dfuse hiện hỗ trợ cho Ethereum là mạng mainnet
và ropsten
. Chúng ta có thể test thử 2 mạng này
1. create project
mkdir -p example-dfuse-javascript
cd example-dfuse-javascript
npm init -y
2. get API key Dfuse
Như hướng dẫn get key ở trên mình xin phép không nhắc lại phần này nữa mọi người có thể kéo lên trên và thực hiện tương tự
3. add các thư viện cần thiết
Install package dfuse
npm install @dfuse/client
Trong môi trường nodejs
bạn sẽ cần thêm 2 thư viện nữa dó là node-fetch
package phục vụ cho request HTTP và ws
phục vụ cho connect WebSocket.
npm install node-fetch ws
4. Create the client
Đầu tiên cần tạo một file main để cho ứng dụng có thể chạy. mình sẽ tạo file có tên app.js
, sau khi tạo xong sẽ là các import và thiết lập API cho client
// app.js
const { createDfuseClient } = require("@dfuse/client")
const client = createDfuseClient({
apiKey: process.env.DFUSE_API_KEY,
network: "mainnet.eth.dfuse.io", // ở đây có thể để là ropsten nếu trong môi trường test
})
Để sử dụng đươc biện môi tường DFUSE_API_KEY
như trên chúng ta cần tạo file biến môi trường .env
và cài đặt thêm package dotenv
# file .env
# nhớ thay API-KEY của bạn vào đây nha
DFUSE_API_KEY=server_abcdef12345678900000000000
5. Định nghĩa GraphQL operation
Đầu tiên hãy chúng ta cần định nghĩa GraphQL operation dưới dạng string mà chúng ta sẽ sử dụng để thực hiện subscription GraphQL. Ở đây chúng ta sẽ định nghĩa những thành phần nào mà ta muốn nhận về sau khi đã subscription.
// app.js
...
const operation = `subscription($cursor: String!) {
searchTransactions(indexName:CALLS, query:"-value:0 type:call", lowBlockNum: -1, cursor: $cursor) {
undo cursor
node { hash matchingCalls { from to value(encoding:ETHER) } }
}
}`
...
Tiếp đến là chúng ta cần subscription GraphQL để stream transfers. Sẽ cần sử dụng đến thao tác searchTransactions
với query "-value:0 type:call"
. Query này có thể hiểu là sẽ nhận về tất cả các transaction gửi lên mạng mà trường value
có gá trị khác 0
// app.js
...
async function main() {
const stream = await client.graphql(operation, (message) => {
if (message.type === "data") {
const { undo, cursor, node: { hash, value, matchingCalls }} = message.data.searchTransactions
matchingCalls.forEach(({ from, to, value }) => {
console.log(`Transfer ${from} -> ${to} [${value} Ether]${undo ? " REVERTED" : ""}`)
})
stream.mark({ cursor })
}
if (message.type === "error") {
console.log("An error occurred", message.errors, message.terminal)
}
if (message.type === "complete") {
console.log("Completed")
}
})
// Nó sẽ đợi đến khi nào srteam hoàn tất hoặc mãi mãi
await stream.join()
await client.release()
main().catch((error) => console.log("Unexpected error", error))
}
...
File app.js đầy đủ
global.fetch = require('node-fetch');
global.WebSocket = require('ws');
const dotenv = require('dotenv');
dotenv.config();
const { createDfuseClient } = require('@dfuse/client');
const client = createDfuseClient({
apiKey: process.env.DFUSE_API_KEY,
// network: 'ropsten.eth.dfuse.io'
network: 'mainnet.eth.dfuse.io'
});
const operation = `subscription($cursor: String!) {
searchTransactions(indexName:CALLS, query:"-value:0 type:call", lowBlockNum: -1, cursor: $cursor) {
undo cursor
node { hash matchingCalls { from to value(encoding:ETHER) } }
}
}`;
async function main() {
const stream = await client.graphql(operation, (message) => {
if (message.type === 'data') {
const {
undo,
cursor,
node: { hash, value, matchingCalls }
} = message.data.searchTransactions;
matchingCalls.forEach(({ from, to, value }) => {
console.log(`Transfer ${from} -> ${to} [${value} Ether]${undo ? ' REVERTED' : ''}`);
});
stream.mark({ cursor });
}
if (message.type === 'error') {
console.log('An error occurred', message.errors, message.terminal);
}
if (message.type === 'complete') {
console.log('Completed');
}
});
await stream.join();
await client.release();
}
main().catch((error) => console.log('Unexpected error', error));
kết qủa chạy ứng dụng sẽ như sau
Track transaction lifecycle real-time
trong docs của dfuse thì có một mẫu và bài hướng dẫn chi tiết về cách tracking lifecycle của một transaction các bạn có thể đón đọc tại https://docs.dfuse.io/guides/ethereum/tutorials/lifecycle/
Và có thể xem chi tiết code bằng cách clone docs và vào thư mục như đường dẫn bên dưới đây
git clone https://github.com/dfuse-io/docs.git
cd docs/tutorials/eth/lifecycle
Kết luận
Bài viết là những suy nghĩ và những tính năng hay mình chọn lọc được từ docs của dfuse rất mong có thể cho bạn cái nhìn tổng quát và biết cách sử dụng thằng này. Rất vui và hiện gặp lại các bạn trong những bài viết tiếp theo
Nguồn : https://docs.dfuse.io/
All rights reserved