events
Overview#
Events in Move provide a mechanism for smart contracts to emit structured notifications about state changes to off-chain systems. Events enable indexers, applications, and users to track on-chain activities without continuously polling resources.
Technical Details#
Events are defined as Move structs and emitted using the event::emit function:
use aptos_framework::event;
struct TransferEvent has drop, store {
from: address,
to: address,
amount: u64
}
public entry fun transfer_with_event(from: &signer, to: address, amount: u64) {
// Transfer logic here
event::emit(TransferEvent {
from: signer::address_of(from),
to,
amount
});
}
Event Properties:
- Stored off-chain in transaction metadata, not on-chain state
- Ordered sequentially within each transaction
- Identified by type and containing transaction
- Queryable via REST API and GraphQL indexer
- Support generic type parameters
- Require
dropandstoreabilities
How Events Work#
When code emits an event during transaction execution:
- Event data is serialized and attached to the transaction
- Validators include events in the committed transaction output
- Indexers process events and make them queryable
- Applications query events via REST or GraphQL APIs
- Events provide an audit trail of contract activity
Unlike state changes that modify resources, events create an append-only log that never changes.
Practical Examples#
Token Transfer Events:
struct CoinTransferEvent has drop, store {
sender: address,
receiver: address,
amount: u64,
coin_type: TypeInfo
}
NFT Marketplace Events:
struct ListingCreatedEvent has drop, store {
seller: address,
token_id: TokenId,
price: u64,
expiration: u64
}
struct PurchaseEvent has drop, store {
buyer: address,
seller: address,
token_id: TokenId,
price: u64
}
DeFi Protocol Events:
struct SwapEvent has drop, store {
user: address,
coin_in_type: TypeInfo,
coin_out_type: TypeInfo,
amount_in: u64,
amount_out: u64,
fee: u64
}
Use Cases#
Events enable powerful off-chain functionality:
-
User Activity Feeds: Display transaction history and account activity in wallets and applications.
-
Real-Time Notifications: Trigger webhooks or push notifications when specific events occur.
-
Analytics Dashboards: Aggregate events to compute metrics like trading volume, user growth, or protocol usage.
-
Compliance and Auditing: Maintain immutable audit trails of all contract interactions for regulatory requirements.
-
State Reconstruction: Replay events to rebuild application state without querying all resources.
-
Cross-Contract Coordination: Monitor events from other contracts to trigger conditional logic.
Best Practices#
Structured Event Design: Design events with all information needed by consumers. Include addresses, amounts, timestamps, and type information.
Consistent Naming: Use descriptive event names with consistent patterns: TransferEvent, MintEvent, BurnEvent.
Emit After Success: Only emit events after operations succeed to avoid confusing off-chain systems with failed attempt notifications.
Version Events: When upgrading contracts, consider versioning events or adding optional fields to maintain backward compatibility with indexers.
Gas Efficiency: Events are relatively cheap but not free. Emit only essential notifications.
Type Information: Include type parameters or TypeInfo when events involve generic types to enable proper deserialization.
Event Querying#
Access events via multiple endpoints:
REST API by Creation Number:
GET /v1/accounts/{address}/events/{creation_number}
REST API by Handle:
GET /v1/accounts/{address}/events/{event_handle}/{field_name}
GraphQL Indexer (when available): Provides complex filtering, aggregation, and joins across multiple event types.
Common Patterns#
Event Handles (Legacy Pattern):
struct EventStore has key {
transfer_events: EventHandle<TransferEvent>
}
Modern Event Emission (Recommended):
// No event handle needed
public entry fun transfer(from: &signer, to: address, amount: u64) {
// Logic
event::emit(TransferEvent { from: signer::address_of(from), to, amount });
}
The modern approach is simpler and more efficient.
Related Concepts#
- Event Handles: Legacy mechanism for organizing events (still supported but not recommended for new code)
- GraphQL Indexer: Query engine for complex event analysis
- REST Event Endpoints: Direct event access via REST API
- Transaction Metadata: Events are stored with transaction results