Documentation Index
Fetch the complete documentation index at: https://docs.near.org/llms.txt
Use this file to discover all available pages before exploring further.
Smart contracts can emit events — structured log messages that follow NEP-297 and are stored on-chain. Events allow indexers, frontends, and external services to track meaningful contract activity without parsing arbitrary log strings.
An event is a log line prefixed with EVENT_JSON: followed by a JSON object with a fixed schema:
EVENT_JSON:{"standard":"nep171","version":"1.0.0","event":"nft_mint","data":[{"owner_id":"alice.near","token_ids":["1"]}]}
Defining and Emitting Events
The near-sdk provides a high-level macro-based API for defining and emitting events. Annotate an enum with #[near(event_json(standard = "..."))] and mark each variant with #[event_version("...")].use near_sdk::near;
use near_sdk::serde::Serialize;
#[derive(Serialize)]
pub struct MintData {
pub owner_id: String,
pub token_ids: Vec<String>,
}
#[derive(Serialize)]
pub struct TransferData {
pub old_owner_id: String,
pub new_owner_id: String,
pub token_ids: Vec<String>,
}
#[near(event_json(standard = "nep171"))]
pub enum NftEvent {
#[event_version("1.0.0")]
NftMint(Vec<MintData>),
#[event_version("1.0.0")]
NftTransfer(Vec<TransferData>),
}
Call .emit() on an event variant to write it to the on-chain log:use near_sdk::near;
#[near(contract_state)]
#[derive(Default)]
pub struct Contract {}
#[near]
impl Contract {
pub fn mint(&mut self, owner_id: String, token_id: String) {
// ... minting logic ...
NftEvent::NftMint(vec![MintData {
owner_id,
token_ids: vec![token_id],
}])
.emit();
}
pub fn transfer(&mut self, old_owner_id: String, new_owner_id: String, token_id: String) {
// ... transfer logic ...
NftEvent::NftTransfer(vec![TransferData {
old_owner_id,
new_owner_id,
token_ids: vec![token_id],
}])
.emit();
}
}
The macro automatically serializes the enum variant to the EVENT_JSON: format and calls env::log_str under the hood.You can emit multiple data entries in a single event by passing a Vec with more than one element. This keeps gas costs lower than emitting one event per entry.
In the JavaScript SDK, emit events by calling near.log() with a string formatted as EVENT_JSON: followed by a JSON payload matching the NEP-297 schema.import { NearBindgen, call, near } from 'near-sdk-js'
@NearBindgen({})
class Contract {
@call({})
mint({ owner_id, token_id }: { owner_id: string; token_id: string }) {
// ... minting logic ...
const event = {
standard: 'nep171',
version: '1.0.0',
event: 'nft_mint',
data: [{ owner_id, token_ids: [token_id] }],
}
near.log(`EVENT_JSON:${JSON.stringify(event)}`)
}
}
Custom Events
You are not limited to standard NEP events. Define your own standard name for application-specific activity:
use near_sdk::near;
use near_sdk::serde::Serialize;
#[derive(Serialize)]
pub struct OrderPlaced {
pub order_id: u64,
pub buyer: String,
pub amount: u128,
}
#[near(event_json(standard = "my-marketplace"))]
pub enum MarketplaceEvent {
#[event_version("1.0.0")]
OrderPlaced(Vec<OrderPlaced>),
}
// In your contract method:
MarketplaceEvent::OrderPlaced(vec![OrderPlaced {
order_id: 42,
buyer: "alice.near".to_string(),
amount: 1_000_000,
}])
.emit();
const event = {
standard: 'my-marketplace',
version: '1.0.0',
event: 'order_placed',
data: [{ order_id: 42, buyer: 'alice.near', amount: '1000000' }],
}
near.log(`EVENT_JSON:${JSON.stringify(event)}`)
Standard Events (FT & NFT)
If you are implementing Fungible Tokens or Non-Fungible Tokens, the standard events are already defined:
Using the standard event names ensures compatibility with explorers and indexers that already know how to parse them.
Consuming Events with Indexers
Emitted events are stored as transaction logs on-chain and can be consumed by any indexer that listens for EVENT_JSON: prefixed log lines. See the NFT Indexer tutorial for a step-by-step example of parsing NFT events from the blockchain.