Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: event & emit in gno #853

Closed
wants to merge 6 commits into from
Closed

Conversation

anarcher
Copy link
Contributor

@anarcher anarcher commented May 27, 2023

Description

This is an implementation PR for #575.
I think Events can be indexed by indexers by default, so I think they should be a structured data type, unlike logs.
In the future, #546 will allow us to view events directly. For now, I think it would be helpful for debugging to be able to view events when doing a gnokey maketx call, like this :

$ gnokey maketx call -config ~/tmp/maketx.local.toml  -pkgpath "gno.land/r/test/event5" -func "Hello"  -broadcast  anarcher
Enter password.
("hello world!" string)
OK!
GAS WANTED: 2000000
GAS USED:   111997
EVENTS:   [type: gno-hello, attributes: [[world: hello world! foo: bar sender: g1ts24jjaxvqjcskdbqzu24r9e4n62ggye520ocv5]

Here's an example of its use in gno

package event

import "std"

const EventAttrKeySender = "sender"


func Hello() string {

     std.EmitEvent("hello",
             "world", "hello world!",
             "foo", "bar",
             EventAttrKeySender, string(std.GetOrigCaller()),
     )
     
     return "hello world!"
}

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

Maintainers Checklist

  • Checked that the author followed the guidelines in CONTRIBUTING.md
  • Checked the conventional-commit (especially PR title and verb, presence of BREAKING CHANGE: in the body)
  • Ensured that this PR is not a significant change or confirmed that the review/consideration process was appropriate for the change

@anarcher anarcher requested review from jaekwon and moul as code owners May 27, 2023 17:04
@github-actions github-actions bot added 📦 🌐 tendermint v2 Issues or PRs tm2 related 📦 🤖 gnovm Issues or PRs gnovm related labels May 27, 2023
@moul
Copy link
Member

moul commented May 28, 2023

What about an API like this instead:

package event

import "std"

type helloEvent struct {
	World string
	Foo string
	Nb int
}


func Hello() string {
	std.Emit("hello", helloEvent{
			World: "yellow world",
			Foo: "bar",
			Nb: 42,
	}

	return "hello world!"
}

@anarcher
Copy link
Contributor Author

anarcher commented May 28, 2023

I think it's an interesting interface :-)
Personally, I don't think there's much need to leave the event UX flexible (I hope there's not a lot of logic and exceptions and processing costs in event handling) (more personally, I hope contract authors(included me) don't create a lot of events haha :-)
If we get a custom event based on Struct, at least we should make this custom event amino encodable/decodable (I don't know how to do that yet), or we should convert the gno-defined event to an AttributedEvent (which is included in amino in this PR).
And I would like the event itself to have only a type for the event and one-dimensional key-value data (I don't think there is much value to be gained from complex nested (multidimensional) data, neither for reading nor for indexing). I also think it would be more useful if all events were of the same structure (a list of one-dimensional key-value types).

However, if we think the above design is more useful, we could probably create it with some limitations(which is probably hard to express in code?). :-)

@harry-hov
Copy link
Contributor

I think the event API introduced in this PR is good. It looks more familiar to cosmos.

@anarcher
Copy link
Contributor Author

anarcher commented May 28, 2023

What if we provided evnet.AddAttribute()?

helloEvent := std.NewEvent("hello")
helloEvent.AddAttribute("world", "hello world!")
helloEvent.AddAttribute("foo", "bar")

std.EmitEvent(helloEvent)

@anarcher anarcher changed the title WIP: feat: event & emit in gno feat: event & emit in gno May 30, 2023
@jaekwon
Copy link
Contributor

jaekwon commented Jun 2, 2023

So many options.

What if we provided evnet.AddAttribute()?

helloEvent := std.NewEvent("hello")
helloEvent.AddAttribute("world", "hello world!")
helloEvent.AddAttribute("foo", "bar")

std.EmitEvent(helloEvent)

I like this.
NewEventAttribute seems cumbersome to use. It would be easier to have Emit(type, attrs... string) and split even/odd.
But alternatively I like the above AddAttribute approach. Either way, without the need to expose the EventAttribute type.

Copy link
Contributor

@jaekwon jaekwon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above comment

@anarcher
Copy link
Contributor Author

anarcher commented Jun 4, 2023

I like this.
NewEventAttribute seems cumbersome to use. It would be easier to have Emit(type, attrs... string) and split even/odd.
But alternatively I like the above AddAttribute approach. Either way, without the need to expose the EventAttribute type.

I agree. Added Event.AddAttribute(). I'm also going to add std.NewEvent(type string, attires... string), and I think it would be fine to support both.

@anarcher anarcher changed the title feat: event & emit in gno WIP: feat: event & emit in gno Jun 4, 2023
@anarcher
Copy link
Contributor Author

anarcher commented Jun 5, 2023

I changed it to the following interface.

NewEventAttribute seems cumbersome to use. It would be easier to have Emit(type, attrs... string) and split even/odd.

const EventHello = "hello"
const EventAttrKeySender = "sender"

std.EmitEvent(EventHello,
                "world", "hello world!",
                "foo", "bar",
                EventAttrKeySender, string(std.GetOrigCaller()),
)

I think this interface concise and useful too . Thank you, jaekwon.

@anarcher anarcher changed the title WIP: feat: event & emit in gno feat: event & emit in gno Jun 5, 2023
@anarcher anarcher changed the title feat: event & emit in gno feat: event & emit in gno Jun 5, 2023
@anarcher anarcher requested a review from a team as a code owner September 3, 2023 12:00
@github-actions github-actions bot added the 📦 ⛰️ gno.land Issues or PRs gno.land package related label Sep 3, 2023
@moul moul added this to the 🚀 main.gno.land milestone Sep 6, 2023
@moul moul added this to the 🚀 main.gno.land milestone Sep 6, 2023
moul added a commit that referenced this pull request Apr 30, 2024
# Description

Succeed in my predecessor's legacy.

I have implemented the output to show the path where the event occurred,
as discussed in #1833. Also made it print the timestamp or block height
together.

## Key Changes

In this change, event emission functionality has been added to the Gno.
The main changes include:

1. Introducing of the `emitEvent` function:
- The `emitEvent` function emits an event based on the given type and
attributes
    - Attributes are passed as an even-length of array key-value pairs
- When emitting an event, the current _package path_, _timestamp_, and
_block height_ information are recorded along with the event(discussed
in #1833). This metadata provides additional context about where the
event occured.

2. Additional of event-related types and functions in the `sdk`
packages:
- `NewEvent` creates a new `Event` object based on the provided
information.
- `ArributedEvent` struct contains informations such as event type,
package path, block height, timestamp and attributes. But I'm not sure
how to utilize the `eventType` yet. So, I've just put it as a
placeholder which will be a disscussion for another time.
- `EventArribute` represents an attribute of an event and consists of a
key-value pair
- `NewEventArribute` creates a new `EventAttribute` object based on the
given key-value pair.

## Example

```go
package ee

import (
	"std"
)

const (
	EventSender = "sender"
	EventReceiver = "receiver"
)

func Sender(){
    SubSender()
    SubReceiver()
}

func SubSender() {
    std.Emit(
        EventSender,
		"key1", "value1",
		"key2", "value2",
		"key3", "value3",
    )  
}

func SubReceiver() {
    std.Emit(
        EventReceiver,
        "bar", "baz",
    )
}

func Receiver() {
    std.Emit(
        EventReceiver,
        "foo", "bar",
    )
}
```

### Result

```json
[
  "{\"type\":\"sender\",\"pkg_path\":\"gno.land/r/demo/ee\",\"identifier\":\"SubSender\",\"timestamp\":1713846501,\"attributes\":[{\"key\":\"key1\",\"value\":\"value1\"},{\"key\":\"key2\",\"value\":\"value2\"},{\"key\":\"key3\",\"value\":\"value3\"}]}",
  "{\"type\":\"receiver\",\"pkg_path\":\"gno.land/r/demo/ee\",\"identifier\":\"SubReceiver\",\"timestamp\":1713846501,\"attributes\":[{\"key\":\"bar\",\"value\":\"baz\"}]}"
]
```

## Related Issue/PR

#575 emit & event built-in functions (@r3v4s)
#853 feat: event & emit in gno (@anarcher) <- previous work.
#975 [META] Gno Wishlist / Feature Request Dump (@zivkovicmilos)

---------

Co-authored-by: n3wbie <[email protected]>
Co-authored-by: Manfred Touron <[email protected]>
gfanton pushed a commit to gfanton/gno that referenced this pull request May 1, 2024
)

# Description

Succeed in my predecessor's legacy.

I have implemented the output to show the path where the event occurred,
as discussed in gnolang#1833. Also made it print the timestamp or block height
together.

## Key Changes

In this change, event emission functionality has been added to the Gno.
The main changes include:

1. Introducing of the `emitEvent` function:
- The `emitEvent` function emits an event based on the given type and
attributes
    - Attributes are passed as an even-length of array key-value pairs
- When emitting an event, the current _package path_, _timestamp_, and
_block height_ information are recorded along with the event(discussed
in gnolang#1833). This metadata provides additional context about where the
event occured.

2. Additional of event-related types and functions in the `sdk`
packages:
- `NewEvent` creates a new `Event` object based on the provided
information.
- `ArributedEvent` struct contains informations such as event type,
package path, block height, timestamp and attributes. But I'm not sure
how to utilize the `eventType` yet. So, I've just put it as a
placeholder which will be a disscussion for another time.
- `EventArribute` represents an attribute of an event and consists of a
key-value pair
- `NewEventArribute` creates a new `EventAttribute` object based on the
given key-value pair.

## Example

```go
package ee

import (
	"std"
)

const (
	EventSender = "sender"
	EventReceiver = "receiver"
)

func Sender(){
    SubSender()
    SubReceiver()
}

func SubSender() {
    std.Emit(
        EventSender,
		"key1", "value1",
		"key2", "value2",
		"key3", "value3",
    )  
}

func SubReceiver() {
    std.Emit(
        EventReceiver,
        "bar", "baz",
    )
}

func Receiver() {
    std.Emit(
        EventReceiver,
        "foo", "bar",
    )
}
```

### Result

```json
[
  "{\"type\":\"sender\",\"pkg_path\":\"gno.land/r/demo/ee\",\"identifier\":\"SubSender\",\"timestamp\":1713846501,\"attributes\":[{\"key\":\"key1\",\"value\":\"value1\"},{\"key\":\"key2\",\"value\":\"value2\"},{\"key\":\"key3\",\"value\":\"value3\"}]}",
  "{\"type\":\"receiver\",\"pkg_path\":\"gno.land/r/demo/ee\",\"identifier\":\"SubReceiver\",\"timestamp\":1713846501,\"attributes\":[{\"key\":\"bar\",\"value\":\"baz\"}]}"
]
```

## Related Issue/PR

gnolang#575 emit & event built-in functions (@r3v4s)
gnolang#853 feat: event & emit in gno (@anarcher) <- previous work.
gnolang#975 [META] Gno Wishlist / Feature Request Dump (@zivkovicmilos)

---------

Co-authored-by: n3wbie <[email protected]>
Co-authored-by: Manfred Touron <[email protected]>
@zivkovicmilos
Copy link
Member

@anarcher
Closing this PR in favor of #1653 🙏

Thank you for the contribution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📦 🌐 tendermint v2 Issues or PRs tm2 related 📦 ⛰️ gno.land Issues or PRs gno.land package related 📦 🤖 gnovm Issues or PRs gnovm related
Projects
Status: Done
Status: 🚀 Needed for Launch
Status: Done
Status: No status
Development

Successfully merging this pull request may close these issues.

5 participants