Substreams – Tác giả: Wisdom Nwokocha – Ngày 03/01/2024
Thư viện Substream-Sink là một công cụ giúp tạo các sink trong TypeScript một cách dễ dàng để định tuyến dữ liệu blockchain đến bất kỳ điểm đích nào bạn cần.
Dù bạn cần truyền dữ liệu đến cơ sở dữ liệu, hàng đợi tin nhắn hay tệp văn bản, thư viện Substreams-Sink đều có thể hỗ trợ bạn.
Bài viết này sẽ hướng dẫn cách cài đặt Substreams-Sink, những lợi ích của nó, cũng như cách tạo và sử dụng sink.
Substreams là gì?
Substreams là một công nghệ lập chỉ mục (indexing technology) được xây dựng trên nền tảng Firehose, cho phép các nhà phát triển viết mã chạy trên máy chủ Firehose để xác định chính xác dữ liệu cần truyền đến nhiều loại sink khác nhau.
Ví dụ:
Một nhà phát triển có thể sử dụng Substreams để tạo luồng dữ liệu sau:
- Tất cả các giao dịch mới trên blockchain, giúp cung cấp dữ liệu thời gian thực cho một ví điện tử hoặc sàn giao dịch.
- Tất cả các sự kiện liên quan đến một hợp đồng thông minh cụ thể, giúp hiển thị thông tin trên một bảng điều khiển theo dõi hoạt động của hợp đồng.
- Tất cả dữ liệu liên quan đến một công cụ phân tích nhất định, giúp cập nhật số liệu phân tích theo thời gian thực.
Substreams sink là gì?
Sink là điểm đến cuối cùng của dữ liệu blockchain thu thập được thông qua Substreams. Chúng có thể định tuyến dữ liệu đến bất kỳ đâu, bao gồm cơ sở dữ liệu, giải pháp hàng đợi tin nhắn, giải pháp ghi log, v.v.
Một số điểm đến phổ biến mà sink có thể gửi dữ liệu tới:
- Lưu trữ vào cơ sở dữ liệu SQL hoặc NoSQL, như MySQL, PostgreSQL, MongoDB và Redis.
- Gửi tin nhắn đến các giải pháp hàng đợi tin nhắn, như RabbitMQ và Kafka, giúp tách rời các ứng dụng và tăng khả năng mở rộng.
- Gửi dữ liệu đến giải pháp ghi log, như Elasticsearch, giúp debug và khắc phục sự cố ứng dụng.
- Gửi tin nhắn đến kênh Discord, giúp tạo bot thông báo các sự kiện blockchain theo thời gian thực.
- Và nhiều nơi khác!
Các sink có thể được phát triển bằng bất kỳ ngôn ngữ lập trình nào. Tuy nhiên, Thư viện Substream-Sink mang lại nhiều lợi ích, bao gồm:
- Loại bỏ mã trùng lặp giữa các sink.
- Tích hợp nhiều tùy chọn dòng lệnh (CLI options) có sẵn.
- Hỗ trợ Prometheus metrics để giám sát hiệu suất.
- Cung cấp bộ ghi log (logger) tích hợp sẵn.
- Xử lý cursor tự động.
- Giúp cập nhật và đồng bộ giữa các sink trong quá trình phát triển.
- Giảm mã mẫu (boilerplate code) khi tạo sink mới.
💡 Nhờ có Thư viện Substream-Sink, các nhà phát triển có thể dễ dàng tạo các sink để định tuyến dữ liệu blockchain đến bất kỳ điểm đích nào mong muốn.
Tạo sink của riêng bạn
Phần này hướng dẫn cách nhanh chóng tạo một sink ghi vào tệp văn bản bằng TypeScript, sử dụng Thư viện Substreams-Sink.
Yêu cầu trước khi bắt đầu:
- Node.js
- TypeScript
- Substream CLI
Các bước thực hiện:
1. Tạo một dự án Node.js mới: ( trong ví dụ này, chúng ta sẽ tạo 1 text file sink)
mkdir substreams-sink-text
cd substreams-sink-text
npm init -y
2. Cài đặt thư viện substreams-sink:
npm install substreams-sink
3. Cài đặt TypeScript và các thư viện liên quan:
npm install -D typescript ts-node
4. Thêm lệnh build và start vào tệp package.json:
{
"scripts": {
"start": "node index.js",
"build": "tsc"
}
}
5. Tạo tệp tsconfig.json với nội dung sau:
{
"extends": "@tsconfig/recommended/tsconfig.json",
"compilerOptions": {
"target": "ESNext",
"module": "nodenext",
"moduleResolution": "nodenext",
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"verbatimModuleSyntax": true,
},
}
6. Tạo tệp index.ts và thêm đoạn mã sau:
import { setup, logger, commander, http } from "substreams-sink";
import fs from "fs";
import pkg from "./package.json" assert { type: "json" };
logger.setName(pkg.name);
export { logger };
// Add cli options
const program = commander.program(pkg);
const command = commander.run(program, pkg);
command.requiredOption('--text-file-path <string>', 'Path for the text file');
command.action(action);
program.parse();
// Custom user options interface
interface ActionOptions extends commander.RunOptions {
textFilePath: string
}
async function action(options: ActionOptions) {
// Setup sink for Block Emitter
const { emitter, substreamPackage, moduleHash, startCursor } = await setup(options);
// Get command options
const { textFilePath } = options;
// Stream Blocks
emitter.on("anyMessage", (message) => {
let text = JSON.stringify(message.operations);
logger.info(text);
fs.appendFileSync(textFilePath, `${text}\n`);
});
// Setup HTTP server & Prometheus metrics
http.listen(options);
// Start streaming
await emitter.start();
http.server.close();
}import { setup, logger, commander, http } from "substreams-sink";
import fs from "fs";
import pkg from "./package.json" assert { type: "json" };
logger.setName(pkg.name);
export { logger };
// Add cli options
const program = commander.program(pkg);
const command = commander.run(program, pkg);
command.requiredOption('--text-file-path <string>', 'Path for the text file');
command.action(action);
program.parse();
// Custom user options interface
interface ActionOptions extends commander.RunOptions {
textFilePath: string
}
async function action(options: ActionOptions) {
// Setup sink for Block Emitter
const { emitter, substreamPackage, moduleHash, startCursor } = await setup(options);
// Get command options
const { textFilePath } = options;
// Stream Blocks
emitter.on("anyMessage", (message) => {
let text = JSON.stringify(message.operations);
logger.info(text);
fs.appendFileSync(textFilePath, `${text}\n`);
});
// Setup HTTP server & Prometheus metrics
http.listen(options);
// Start streaming
await emitter.start();
http.server.close();
}
Giải thích chi tiết về mã nguồn
import { setup, logger, commander, http } from "substreams-sink";
import fs from "fs";
import pkg from "./package.json" assert { type: "json" };
logger.setName(pkg.name);
export { logger };
Đoạn mã này import các thư viện cần thiết cho Substreams sink, bao gồm:
- setup(): Hàm thiết lập sink.
- logger: Đối tượng ghi log.
- commander: Thư viện xử lý dòng lệnh.
- http: Thư viện HTTP.
- fs: Thư viện hỗ trợ ghi dữ liệu vào tệp.
Biến pkg chứa nội dung của tệp package.json, được sử dụng để thiết lập tên cho logger.
// Add cli options
const program = commander.program(pkg);
const command = commander.run(program, pkg);
command.requiredOption('--text-file-path <string>', 'Path for the text file');
command.action(action);
program.parse();
Đoạn mã này thêm một tùy chọn dòng lệnh cho sink để nhận đường dẫn tệp. Đồng thời, nó cũng phân tích các tùy chọn dòng lệnh để sử dụng trong chương trình.
// Custom user options interface
interface ActionOptions extends commander.RunOptions {
textFilePath: string
}
Đoạn mã này định nghĩa một giao diện tùy chỉnh ActionOptions mở rộng từ commander.RunOptions.
Giao diện này bao gồm một thuộc tính mới là textFilePath, dùng để chỉ đường dẫn tệp nơi lưu dữ liệu.
async function action(options: ActionOptions) {
// Setup sink for Block Emitter
const { emitter, substreamPackage, moduleHash, startCursor } = await setup(options);
Đoạn mã này thiết lập sink cho bộ phát block (Block Emitter).
Hàm setup() trả về một đối tượng chứa các thuộc tính sau:
- emitter: Đối tượng phát block.
- substreamPackage: Đối tượng gói Substreams.
- moduleHash: Hash của module Substreams.
- startCursor: Cursor bắt đầu cho luồng dữ liệu.
// Get command options
const { textFilePath } = options;
Đoạn mã này lấy đường dẫn tệp từ các tùy chọn dòng lệnh.
// Stream Blocks
emitter.on("anyMessage", (message) => {
let text = JSON.stringify(message.operations);
logger.info(text);
fs.appendFileSync(textFilePath, `${text}\\n`);
});
Stream dữ liệu blockchain vào tệp
typescript
CopyEdit
emitter.on("anyMessage", (message) => {
let text = JSON.stringify(message.operations);
logger.info(text);
fs.appendFileSync(textFilePath, `${text}\n`);
});
Đoạn mã này truyền trực tuyến các khối từ bộ phát khối (emitter), mỗi khi có tin nhắn mới, nó Chuyển đổi nội dung tin nhắn thành định dạng JSON và Ghi dữ liệu vào tệp văn bản bằng fs.appendFileSync().
// Setup HTTP server & Prometheus metrics
http.listen(options);
Đoạn mã này khởi động máy chủ HTTP và tích hợp Prometheus metrics để theo dõi hiệu suất.
// Start streaming
await emitter.start();
http.server.close();
Đoạn mã này bắt đầu phát block và đóng máy chủ HTTP sau khi hoàn thành streaming.
Kết luận
Thư viện Substreams-Sink rất dễ sử dụng và cung cấp nhiều tính năng hữu ích như tích hợp logging, hỗ trợ Prometheus metrics, và tối ưu hóa hiệu suất.
Chúng tôi mong muốn phát triển thêm nhiều sink sử dụng Substreams-Sink Library và khuyến khích cộng đồng áp dụng thư viện này để tạo ra các giải pháp định tuyến dữ liệu blockchain mới.Từ khóa: dApps, Firehose, Substreams Development, Substreams Sink, Web3 Analytics
No Comments