From 977a3f44f5e6f3b0f2c7d4d220da4ab6bbafb1db Mon Sep 17 00:00:00 2001
From: Leon Hudak <33522493+leohhhn@users.noreply.github.com>
Date: Mon, 13 May 2024 16:16:30 +0200
Subject: [PATCH] feat(docs): emit/event docs (#2047)
## Description
This PR adds docs for emit/event. It adds reference docs, and a section
in effective Gno. More practical examples will be added to Gno By
Example.
Closes: #2003
Contributors' checklist...
- [ ] Added new tests, or not needed, or not feasible
- [ ] Provided an example (e.g. screenshot) to aid review or the PR is
self-explanatory
- [ ] Updated the official documentation or not needed
- [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message
was included in the description
- [ ] Added references to related issues and PRs
- [ ] Provided any useful hints for running manual tests
- [ ] Added new benchmarks to [generated
graphs](https://gnoland.github.io/benchmarks), if any. More info
[here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
---------
Co-authored-by: Lee ByeongJun
---
docs/concepts/effective-gno.md | 67 +++++++++++++++++++++++++++++
docs/concepts/stdlibs/coin.md | 3 +-
docs/concepts/stdlibs/events.md | 57 ++++++++++++++++++++++++
docs/reference/stdlibs/std/chain.md | 16 ++++++-
4 files changed, 140 insertions(+), 3 deletions(-)
create mode 100644 docs/concepts/stdlibs/events.md
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