Skip to main content

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.

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();

Standard Events (FT & NFT)

If you are implementing Fungible Tokens or Non-Fungible Tokens, the standard events are already defined:
  • NEP-141 (FT): ft_transfer, ft_mint, ft_burn — see the Fungible Token docs.
  • NEP-171 (NFT): nft_mint, nft_transfer, nft_burn — see the Non-Fungible Token docs.
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.