NEP-297: Events
NEP-297 events standard on NEAR: the EVENT_JSON: log prefix, standard/version/event/data fields, token event names, and how it differs from Solidity events.
Intermediate6 min read3-question check
NEAR has no native event type. A contract can only write log lines (strings) to the receipt outcome. NEP-297 standardises one format for those lines so indexers, explorers and wallets can recognise structured events without knowing anything about your contract.
An event is a single log line made of the prefix EVENT_JSON: followed immediately by a JSON object with four fields: standard, version, event and (optionally) data.
EVENT_JSON:{
"standard": "nep141",
"version": "1.0.0",
"event": "ft_transfer",
"data": [
{ "old_owner_id": "alice.near", "new_owner_id": "bob.near", "amount": "1000000", "memo": "lunch" }
]
}| Field | Meaning |
|---|---|
standard | Name of the standard, lowercase, e.g. nep141, nep171, nep245 — or your own name for custom events. |
version | Semver of that standard’s event format, e.g. 1.0.0. Lets consumers handle format changes. |
event | Event type, e.g. ft_mint, ft_transfer, ft_burn, nft_mint, nft_transfer, nft_burn. |
data | Payload defined by the standard. The token standards use an array, so one log can describe several mints/transfers. |
Emitting events in Rust#
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Dex {
event Swap(address indexed trader, address tokenIn, address tokenOut,
uint256 amountIn, uint256 amountOut);
function swap(/* ... */) external {
// ...
emit Swap(msg.sender, address(0), address(0), 0, 0);
}
}use near_sdk::json_types::U128;
use near_sdk::{env, near, AccountId};
#[near(event_json(standard = "mydex"))]
pub enum DexEvent {
#[event_version("1.0.0")]
Swap { trader: AccountId, token_in: AccountId, token_out: AccountId, amount_in: U128, amount_out: U128 },
}
#[near(contract_state)]
#[derive(Default)]
pub struct Dex {}
#[near]
impl Dex {
pub fn swap(&mut self, token_in: AccountId, token_out: AccountId, amount_in: U128) {
let amount_out = U128(0); // ...do the swap...
DexEvent::Swap {
trader: env::predecessor_account_id(),
token_in,
token_out,
amount_in,
amount_out,
}
.emit();
// logs: EVENT_JSON:{"standard":"mydex","version":"1.0.0","event":"swap","data":{...}}
}
}emit ↔ .emit(), which serialises the variant and calls env::log_str with the EVENT_JSON: prefix for you.
For token standards use the ready-made types in near-contract-standards (e.g. FtMint, FtTransfer, NftMint), which produce exactly the shapes wallets expect — and the reference FungibleToken / NonFungibleToken already emit transfer events.
Check yourself
3 questions · progress saved in this browser