diff --git a/docs/concepts/effective-gno.md b/docs/concepts/effective-gno.md index 17e4ba28de6..1152146ce51 100644 --- a/docs/concepts/effective-gno.md +++ b/docs/concepts/effective-gno.md @@ -413,6 +413,73 @@ actual logic. This way, `privateMethod` can only be called from within the realm, and it can use the caller's address for authentication or authorization checks. +### Emit Gno events to make life off-chain easier + +Gno provides users the ability to log specific occurrences that happened in their +on-chain apps. An `event` log is stored in the ABCI results of each block, and +these logs can be indexed, filtered, and searched by external services, allowing +them to monitor the behaviour of on-chain apps. + +It is good practice to emit events when any major action in your code is +triggered. For example, good times to emit an event is after a balance transfer, +ownership change, profile created, etc. Alternatively, you can view event emission +as a way to include data for monitoring purposes, given the indexable nature of +events. + +Events consist of a type and a slice of strings representing `key:value` pairs. +They are emitted with the `Emit()` function, contained in the `std` package in +the Gno standard library: + +```go +package events + +import ( + "std" +) + +var owner std.Address + +func init() { + owner = std.PrevRealm().Addr() +} + +func ChangeOwner(newOwner std.Address) { + caller := std.PrevRealm().Addr() + + if caller != owner { + panic("access denied") + } + + owner = newOwner + std.Emit("OwnershipChange", "newOwner", newOwner.String()) +} + +``` +If `ChangeOwner()` was called in, for example, block #43, getting the `BlockResults` +of block #43 will contain the following data: + +```json +{ + "Events": [ + { + "@type": "/tm.gnoEvent", + "type": "OwnershipChange", + "pkg_path": "gno.", + "func": "ChangeOwner", + "attrs": [ + { + "key": "newOwner", + "value": "g1zzqd6phlfx0a809vhmykg5c6m44ap9756s7cjj" + } + ] + } + // other events + ] +} +``` + +Read more about events [here](./stdlibs/events.md). + ### Contract-level access control In Gno, it's a good practice to design your contract as an application with its diff --git a/docs/concepts/stdlibs/coin.md b/docs/concepts/stdlibs/coin.md index 7a610866fd2..46c7c519f7c 100644 --- a/docs/concepts/stdlibs/coin.md +++ b/docs/concepts/stdlibs/coin.md @@ -30,7 +30,6 @@ The `Coins` slice can be included in a transaction made by a user addresses or a Coins in this set are then available for access by specific types of Bankers, which can manipulate them depending on access rights. -[//]: # (TODO ADD LINK TO Effective GNO) -Read more about coins in the [Effective Gno](https://docs.gno.land/concepts/effective-gno/#native-tokens) section. +Read more about coins in the [Effective Gno](../effective-gno.md#coins) section. The Coin(s) API can be found in under the `std` package [reference](../../reference/stdlibs/std/coin.md). diff --git a/docs/concepts/stdlibs/events.md b/docs/concepts/stdlibs/events.md new file mode 100644 index 00000000000..ca97c7ee731 --- /dev/null +++ b/docs/concepts/stdlibs/events.md @@ -0,0 +1,57 @@ +--- +id: events +--- + +# Gno Events + +## Overview + +Events in Gno are a fundamental aspect of interacting with and monitoring +on-chain applications. They serve as a bridge between the on-chain environment +and off-chain services, making it simpler for developers, analytics tools, and +monitoring services to track and respond to activities happening in Gno.land. + +Gno events are pieces of data that log specific activities or changes occurring +within the state of an on-chain app. These activities are user-defined; they might +be token transfers, changes in ownership, updates in user profiles, and more. +Each event is recorded in the ABCI results of each block, ensuring that action +that happened is verifiable and accessible to off-chain services. + +## Emitting Events + +To emit an event, you can use the `Emit()` function from the `std` package +provided in the Gno standard library. The `Emit()` function takes in a string +representing the type of event, and an even number of arguments after representing +`key:value` pairs. + +Read more about events & `Emit()` in +[Effective Gno](../effective-gno.md#emit-gno-events-to-make-life-off-chain-easier), +and the `Emit()` reference [here](../../reference/stdlibs/std/chain.md#emit). + +## Data contained in a Gno Event + +An event contained in an ABCI response of a block will include the following +data: + +``` json +{ + "@type": "/tm.gnoEvent", // TM2 type + "type": "OwnershipChange", // Type/name of event defined in Gno + "pkg_path": "gno.land/r/demo/example", // Path of the emitter + "func": "ChangeOwner", // Gno function that emitted the event + "attrs": [ // Slice of key:value pairs emitted + { + "key": "oldOwner", + "value": "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5" + }, + { + "key": "newOwner", + "value": "g1zzqd6phlfx0a809vhmykg5c6m44ap9756s7cjj" + } + ] +} +``` + +You can fetch the ABCI response of a specific block by using the `/block_results` +RPC endpoint. + diff --git a/docs/reference/stdlibs/std/chain.md b/docs/reference/stdlibs/std/chain.md index bda09b2fe80..06c40d63afc 100644 --- a/docs/reference/stdlibs/std/chain.md +++ b/docs/reference/stdlibs/std/chain.md @@ -28,6 +28,19 @@ std.AssertOriginCall() ``` --- +## Emit +```go +func Emit(typ string, attrs ...string) +``` +Emits a Gno event. Takes in a **string** type (event identifier), and an even number of string +arguments acting as key-value pairs to be included in the emitted event. + +#### Usage +```go +std.Emit("MyEvent", "myKey1", "myValue1", "myKey2", "myValue2") +``` +--- + ## CurrentRealmPath ```go func CurrentRealmPath() string @@ -117,7 +130,8 @@ currentRealm := std.CurrentRealm() ```go func PrevRealm() Realm ``` -Returns the previous caller realm (can be realm or EOA). If caller is am EOA, `pkgpath` will be empty. +Returns the previous caller realm (can be code or user realm). If caller is a +user realm, `pkgpath` will be empty. #### Usage ```go