soroban-cli icon indicating copy to clipboard operation
soroban-cli copied to clipboard

Add self-describing events formats

Open leighmcculloch opened this issue 4 months ago • 1 comments
trafficstars

In protocol 23 contracts that use the new event definitions will include information in the contract spec about the shape of their events.

This prototype exists that show how by combining the event contract spec information with raw XDR events, a self-describing format for events can be generated:

  • https://github.com/leighmcculloch/exp-sep48-derived-events-example

I propose we incorporate this ability, to convert events from their raw format into a self-describing JSON format, be something we implement in the CLI and offer it as the default rendering of events when using stellar events and stellar contract invoke.

As part of this work it would be worth thinking of the derived output as a format that should eventually become standardised, and so it may be worth as part of development writing a SEP that captures it.

Note: The act of marrying the event spec with a raw event will be something that SDKs that generate bindings for events will also need to do.

Current Output Today

The output formats for events today contain no context for what the data being displayed means. Parameter values are shown, but not parameter names.

stellar events

Plain format

Event 0002480158929850368-0000000000 [CONTRACT]:
  Ledger:   577457 (closed at 2025-07-22T04:25:38Z)
  Contract: CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC
  Topics:
            Symbol(ScSymbol(StringM(transfer)))
            Address(Account(AccountId(PublicKeyTypeEd25519(Uint256(6dd03abefa152019c5acd5bd7b158891ee664dc70a0805d3a67436fbbcc4c242)))))
            Address(Account(AccountId(PublicKeyTypeEd25519(Uint256(4a041fb650130ffda6f0726fccd535cefbf2505a13f091a960aa2cca997c9121)))))
            String(ScString(StringM(native)))
  Value: I128(Int128Parts { hi: 0, lo: 99999999900 })

JSON format

{
  "type": "contract",
  "ledger": 577462,
  "ledgerClosedAt": "2025-07-22T04:26:03Z",
  "id": "0002480180404682752-0000000002",
  "contractId": "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC",
  "topic": [
    "AAAADwAAAANmZWUA",
    "AAAAEgAAAAAAAAAAvTfezXr4MS4ZsNWiaBTpG+RhNJ4lPwoF2fQk4ZxSI78="
  ],
  "value": "AAAACgAAAAAAAAAAAAAAAAAXcn0="
}

stellar contract invoke

📅 CDHXZ22IGK5O7BXHLTPIHWZVDIG3W2W2J57N2FZ4Z6UTHIPEZXY4DIYQ - Success - Event: [{"symbol":"hello"},{"address":"CDHXZ22IGK5O7BXHLTPIHWZVDIG3W2W2J57N2FZ4Z6UTHIPEZXY4DIYQ"}] = {"map":[{"key":{"symbol":"name"},"val":{"string":"me"}}]}

Proposed Output

Event Definition

An approve event as defined in SEP-41.

#[contractevent]
pub struct Approve {
    #[topic]
    pub from: Address,
    #[topic]
    pub spender: Address,
    pub amount: i128,
    pub live_until_ledger: u32,
}

Raw Event (XDR-JSON)

{
  "ext": "v0",
  "contract_id": "CBUZJXHZ6PBS2YR3SEJZ3CIGMQBYP6367D3KQAR2NB3U2I5AOWLC4DU2",
  "type_": "contract",
  "body": {
    "v0": {
      "topics": [
        { "symbol": "approve" },
        { "address": "GBMBVAHBE6D4AJXJJVTBQTVU4G7SN4FEIJOL5YTOHZ4WCUMKQ52ANL2B" },
        { "address": "GCAN5IE4PWMWSMFZCYQRCJM73MCPG5JD2R7WF5HIFHHHDBWSDJFIWX7X" }
      ],
      "data": {
        "vec": [
          { "i128": "10000" },
          { "u32": 1998742 }
        ]
      }
    }
  }
}

Contract Spec (SEP-48, XDR-JSON)

{
  "event_v0": {
    "name": "approve",
    "prefix_topics": ["approve"],
    "params": [
      { "name": "from", "type_":"address", "location": "topic_list" },
      { "name": "spender", "type_":"address", "location": "topic_list" },
      { "name": "amount", "type_":"i128", "location": "data" },
      { "name": "live_until_ledger", "type_":"u32", "location": "data" }
    ],
    "data_format": "vec"
  }
}

Output

And generating output, something like the following formats:

Multi-Line

Event 0002480158929850368-0000000000 [CONTRACT]:
  Ledger:   577457 (closed at 2025-07-22T04:25:38Z)
  Contract: CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC
  Event: approve
  Params:
    from: { "address": "GBMBVAHBE6D4AJXJJVTBQTVU4G7SN4FEIJOL5YTOHZ4WCUMKQ52ANL2B" }
    spender: { "address": "GCAN5IE4PWMWSMFZCYQRCJM73MCPG5JD2R7WF5HIFHHHDBWSDJFIWX7X" }
    amount: { "i128": "10000" }
    live_until_ledger: { "u32": 1998742 }

Single-Line

📅 CDHXZ22IGK5O7BXHLTPIHWZVDIG3W2W2J57N2FZ4Z6UTHIPEZXY4DIYQ - Success - Event: hello, from: { "address": "GBMBVAHBE6D4AJXJJVTBQTVU4G7SN4FEIJOL5YTOHZ4WCUMKQ52ANL2B" }, spender: { "address": "GCAN5IE4PWMWSMFZCYQRCJM73MCPG5JD2R7WF5HIFHHHDBWSDJFIWX7X" }, amount: { "i128": "10000" }, live_until_ledger: { "u32": 1998742 }

JSON

{
  "contract_id": "CBUZJXHZ6PBS2YR3SEJZ3CIGMQBYP6367D3KQAR2NB3U2I5AOWLC4DU2",
  "event_type": "approve",
  "params": {
    "from": { "address": "GBMBVAHBE6D4AJXJJVTBQTVU4G7SN4FEIJOL5YTOHZ4WCUMKQ52ANL2B" },
    "spender": { "address": "GCAN5IE4PWMWSMFZCYQRCJM73MCPG5JD2R7WF5HIFHHHDBWSDJFIWX7X" },
    "amount": { "i128": "10000" },
    "live_until_ledger": { "u32": 1998742 }
  }
}

leighmcculloch avatar Jul 22 '25 04:07 leighmcculloch

That would be a nice DX improvement 👍 Also the stellar events could have a bit more settings to filter events (by contract/address a minima).

tupui avatar Aug 27 '25 11:08 tupui