suix_queryEvents - Query Events with Fil...
Query and filter Sui blockchain events using suix_queryEvents RPC method. Search events by package, module, sender, transaction with pagination support using Dwellir's high-performance Sui infrastructure.
Queries and filters events emitted by transactions on the Sui blockchain with support for various search criteria and pagination.
Overview
The suix_queryEvents method is essential for monitoring smart contract activity, tracking specific events, and building event-driven applications on Sui. Events are emitted by Move modules during transaction execution and provide structured data about what happened during contract interactions. This method enables filtering by event type, sender, package, time range, and more.
Code Examples
Common Use Cases
1. DeFi Protocol Monitoring
async function monitorDEXActivity(dexPackageId) {
const monitor = new EventMonitor(client);
// Monitor swap events
monitor.onEvent(`${dexPackageId}::dex::SwapExecuted`, async (event) => {
const swap = event.parsedJson;
console.log(`🔄 Swap: ${swap.amountIn} ${swap.tokenIn} -> ${swap.amountOut} ${swap.tokenOut}`);
// Check for large trades
if (parseInt(swap.amountIn) > 1000000000) { // Large SUI trades
console.log('🚨 Large trade detected!');
// Send alert to monitoring system
}
});
// Monitor liquidity events
monitor.onEvent(`${dexPackageId}::pool::LiquidityAdded`, async (event) => {
console.log('💧 Liquidity added:', event.parsedJson);
});
await monitor.startMonitoring({ Package: dexPackageId });
}2. NFT Marketplace Tracking
async function trackNFTSales(marketplacePackage) {
const analytics = new EventAnalytics(client);
const salesEvents = await analytics.client.getEventsByType(
`${marketplacePackage}::marketplace::ItemSold`
);
const salesAnalysis = {
totalSales: salesEvents.length,
totalVolume: 0,
averagePrice: 0,
topCollections: {},
priceDistribution: { under1: 0, under10: 0, under100: 0, over100: 0 }
};
salesEvents.forEach(event => {
const sale = event.parsedJson;
const price = parseInt(sale.price) / 1000000000; // Convert MIST to SUI
salesAnalysis.totalVolume += price;
// Track collections
const collection = sale.collection || 'Unknown';
salesAnalysis.topCollections[collection] =
(salesAnalysis.topCollections[collection] || 0) + 1;
// Price distribution
if (price < 1) salesAnalysis.priceDistribution.under1++;
else if (price < 10) salesAnalysis.priceDistribution.under10++;
else if (price < 100) salesAnalysis.priceDistribution.under100++;
else salesAnalysis.priceDistribution.over100++;
});
salesAnalysis.averagePrice = salesAnalysis.totalVolume / salesAnalysis.totalSales;
return salesAnalysis;
}3. User Activity Analysis
async function analyzeUserActivity(userAddress) {
const userEvents = await getAllEventsPaginated(
{ Sender: userAddress },
20
);
const activity = {
totalTransactions: userEvents.length,
uniqueContracts: new Set(),
activityByHour: {},
mostUsedContracts: {},
eventTypes: {}
};
userEvents.forEach(event => {
// Track contracts used
activity.uniqueContracts.add(event.packageId);
// Track contract usage frequency
const contract = event.packageId;
activity.mostUsedContracts[contract] =
(activity.mostUsedContracts[contract] || 0) + 1;
// Track event types
activity.eventTypes[event.type] =
(activity.eventTypes[event.type] || 0) + 1;
// Activity by hour
const timestamp = parseInt(event.timestampMs || '0');
if (timestamp > 0) {
const hour = new Date(timestamp).getHours();
activity.activityByHour[hour] =
(activity.activityByHour[hour] || 0) + 1;
}
});
activity.uniqueContracts = activity.uniqueContracts.size;
return activity;
}4. Smart Contract Audit Trail
async function auditSmartContract(packageId, moduleNames) {
const auditTrail = {
package: packageId,
modules: {},
securityEvents: [],
adminActions: [],
upgradeEvents: [],
totalInteractions: 0
};
for (const moduleName of moduleNames) {
const moduleEvents = await getAllEventsPaginated({
MoveModule: { package: packageId, module: moduleName }
}, 50);
auditTrail.modules[moduleName] = {
totalEvents: moduleEvents.length,
uniqueSenders: new Set(moduleEvents.map(e => e.sender)).size,
eventTypes: {},
recentActivity: []
};
moduleEvents.forEach(event => {
auditTrail.totalInteractions++;
// Categorize events
const eventType = event.type.split('::').pop();
auditTrail.modules[moduleName].eventTypes[eventType] =
(auditTrail.modules[moduleName].eventTypes[eventType] || 0) + 1;
// Check for security-relevant events
if (eventType.toLowerCase().includes('admin') ||
eventType.toLowerCase().includes('owner') ||
eventType.toLowerCase().includes('upgrade')) {
if (eventType.toLowerCase().includes('upgrade')) {
auditTrail.upgradeEvents.push({
timestamp: event.timestampMs,
event: eventType,
sender: event.sender,
data: event.parsedJson
});
} else {
auditTrail.adminActions.push({
timestamp: event.timestampMs,
event: eventType,
sender: event.sender,
data: event.parsedJson
});
}
}
// Recent activity (last 24 hours)
const dayAgo = Date.now() - (24 * 60 * 60 * 1000);
if (parseInt(event.timestampMs || '0') > dayAgo) {
auditTrail.modules[moduleName].recentActivity.push({
timestamp: event.timestampMs,
type: eventType,
sender: event.sender
});
}
});
}
return auditTrail;
}Best Practices
1. Efficient Event Filtering
// Use specific filters to reduce data transfer and improve performance
const specificFilter = {
And: [
{ Package: '0x2' },
{ MoveEventType: '0x2::coin::CoinCreated' }
]
};
// Avoid overly broad queries
const tooBoard = { All: [] }; // Can return massive amounts of data2. Event Data Parsing
function safeParseEventData(event) {
try {
return {
type: event.type,
data: event.parsedJson,
timestamp: parseInt(event.timestampMs || '0'),
sender: event.sender,
package: event.packageId,
module: event.transactionModule
};
} catch (error) {
console.warn('Failed to parse event:', error);
return {
type: event.type || 'Unknown',
data: null,
error: error.message
};
}
}3. Performance Optimization
// Use pagination for large datasets
async function efficientEventQuery(filter, maxEvents = 10000) {
const events = [];
let cursor = null;
let retrieved = 0;
while (retrieved < maxEvents) {
const batchSize = Math.min(100, maxEvents - retrieved);
const result = await client.queryEvents({
query: filter,
cursor: cursor,
limit: batchSize,
order: 'descending'
});
if (!result.data.length) break;
events.push(...result.data);
retrieved += result.data.length;
if (!result.hasNextPage) break;
cursor = result.nextCursor;
// Small delay to prevent overwhelming the RPC
await new Promise(resolve => setTimeout(resolve, 100));
}
return events;
}Related Methods
- sui_getTransactionBlock - Get transaction details including events
- suix_queryTransactionBlocks - Query transactions that emitted events
- sui_getObject - Get object details related to events
Notes
- Events are immutable once emitted by transactions
- Pagination is essential for large result sets to avoid timeouts
- Event data structure depends on the Move module that emitted it
- Timestamps are in milliseconds since Unix epoch
- BCS encoding provides raw event data for custom parsing
- Filter combinations using And/Or can create complex queries
Need help? Contact our support team or check the Sui documentation.
suix_getValidatorsApy - Get Validator AP...
Get detailed validator APY (Annual Percentage Yield) information for staking rewards on Sui blockchain using Dwellir's high-performance Sui RPC infrastructure.
suix_queryTransactionBlocks - Query Tran...
Query and filter Sui transactions using suix_queryTransactionBlocks RPC method. Search by sender, recipient, transaction kind, time range with pagination support using Dwellir's high-performance Sui infrastructure.