Bài viết này cung cấp một hướng dẫn đầy đủ về cách lắng nghe và xử lý các sự kiện (events) được phát ra từ smart contract trên blockchain bằng thư viện Web3.js. Việc nắm bắt các sự kiện này rất quan trọng để xây dựng các ứng dụng phi tập trung (DApps) phản ứng theo thời gian thực với các thay đổi trên blockchain. Chúng ta sẽ khám phá các phương pháp lọc log, sử dụng filter và các ví dụ thực tế để theo dõi các sự kiện mới nhất từ smart contract của bạn một cách hiệu quả.
Trong thế giới blockchain, các sự kiện (events) đóng vai trò như những thông báo được phát ra từ các smart contract khi có một trạng thái nào đó thay đổi. Ví dụ, khi một token được chuyển từ ví A sang ví B, một sự kiện "Transfer" sẽ được phát ra. Việc lắng nghe và xử lý các sự kiện này cho phép DApps phản ứng một cách linh hoạt và kịp thời với các thay đổi, chẳng hạn như cập nhật giao diện người dùng, kích hoạt các quy trình nghiệp vụ hoặc ghi lại dữ liệu vào cơ sở dữ liệu.
Web3.js cung cấp nhiều cách để lắng nghe và xử lý các sự kiện. Dưới đây là một số phương pháp phổ biến:
contract.events
Đây là cách tiếp cận phổ biến nhất, cho phép bạn lắng nghe một sự kiện cụ thể từ một instance của contract. Nó sử dụng WebSocket để theo dõi các sự kiện mới theo thời gian thực. Ví dụ:
contract.events.MyEvent({
filter: {myIndexedParam: [value1, value2]}, // Optional filter
fromBlock: 'latest' // Start listening from last block
}, function(error, event){
if (!error)
console.log(event);
})
.on('data', function(event){
console.log(event); // Same results as the optional callback above
})
.on('changed', function(event){
// Remove event from local database
})
.on('error', function(error, receipt) {
console.log(error, receipt);
});
Đoạn code trên sẽ lắng nghe sự kiện MyEvent
, áp dụng một filter (nếu có) và bắt đầu theo dõi từ block mới nhất. Các callback function on('data')
, on('changed')
, và on('error')
cho phép bạn xử lý các sự kiện khác nhau.
web3.eth.subscribe('logs')
Phương pháp này cung cấp một cách linh hoạt hơn để theo dõi các sự kiện, cho phép bạn lọc theo địa chỉ contract và các "topic" (chữ ký của sự kiện). Đây là một ví dụ:
web3.eth.subscribe('logs', {
address: '0x1234567890123456789012345678901234567890',
topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'] // Transfer event signature
}, function(error, result){
if (!error)
console.log(result);
})
.on("data", function(log){
console.log(log);
})
.on("changed", function(log){
//
});
Trong ví dụ trên, chúng ta đang đăng ký để nhận tất cả các log từ contract có địa chỉ được chỉ định và có topic đầu tiên là chữ ký của sự kiện "Transfer".
Để lấy các sự kiện đã xảy ra trong quá khứ, bạn có thể sử dụng filter và phương thức getPastEvents
:
contract.getPastEvents('MyEvent', {
filter: { myIndexedParam: [value1, value2] }, // Optional filter
fromBlock: 0, // get all events from genesis
toBlock: 'latest' // get all events up to the latest block
}, function(error, events){
console.log(events); // Same results as the optional callback above
})
.then(function(events){
console.log(events) // return array
});
Điều này cho phép bạn truy xuất tất cả các sự kiện MyEvent
từ block 0 đến block mới nhất, áp dụng một filter tùy chọn.
Khi bạn nhận được một sự kiện, bạn cần giải mã dữ liệu để hiểu được ý nghĩa của nó. Dữ liệu sự kiện thường được mã hóa theo chuẩn ABI (Application Binary Interface). Web3.js cung cấp các công cụ để giải mã dữ liệu này. Ví dụ:
const eventJsonInterface = [{"indexed": true,"name": "from","type": "address"},{"indexed": true,"name": "to","type": "address"},{"indexed": false,"name": "value","type": "uint256"}];
const log = receipt.logs[0];
const decodedLog = web3.eth.abi.decodeLog(
eventJsonInterface,
log.data,
log.topics
);
console.log(decodedLog);
Giả sử bạn muốn theo dõi tất cả các giao dịch chuyển token ERC-20. Bạn có thể sử dụng phương pháp web3.eth.subscribe('logs')
để lắng nghe sự kiện "Transfer" từ contract ERC-20. Bạn sẽ cần ABI của ERC-20 và địa chỉ contract:
const web3 = new Web3(new Web3.providers.WebsocketProvider('YOUR_WEB3_PROVIDER'));
const contractAddress = 'YOUR_CONTRACT_ADDRESS'; // Địa chỉ contract ERC-20
const subscription = web3.eth.subscribe('logs', {
address: contractAddress,
topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'] // Transfer event signature
}, (error, result) => {
if (error) {
console.error(error);
}
}).on("data", async (log) => {
try {
const transferEventABI = [{"indexed": true,"name": "from","type": "address"},{"indexed": true,"name": "to","type": "address"},{"indexed": false,"name": "value","type": "uint256"}];
const decodedLog = web3.eth.abi.decodeLog(transferEventABI, log.data, log.topics);
const { from, to, value } = decodedLog;
console.log(`Transfer: From ${from} to ${to} value: ${value}`);
} catch (error) {
console.error('Error decoding log:', error);
}
});
Với đoạn code trên, bạn sẽ nhận được thông tin chi tiết về mỗi giao dịch chuyển token, bao gồm địa chỉ người gửi, địa chỉ người nhận và giá trị token được chuyển.
Việc lắng nghe và xử lý các sự kiện là một phần quan trọng của việc phát triển DApps trên blockchain. Với Web3.js, bạn có thể dễ dàng theo dõi các thay đổi trạng thái của smart contract và xây dựng các ứng dụng phản ứng một cách linh hoạt với thế giới blockchain.
Bài viết liên quan