Skip to content

Commit

Permalink
feat(devx) update using events guide
Browse files Browse the repository at this point in the history
  • Loading branch information
lucas-tortora committed Dec 11, 2024
1 parent 9b5d6e4 commit aaa1ebb
Showing 1 changed file with 102 additions and 44 deletions.
146 changes: 102 additions & 44 deletions docs/content/developer/iota-101/using-events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,20 @@ An event object in IOTA consists of the following attributes:
- `bcs`: Binary canonical serialization value.
- `timestampMs`: Unix epoch timestamp in milliseconds.

## Exploring Available Events
### Exploring Available Events

To subscribe to on-chain events, you first need to identify which events are available. While you can easily track events emitted by your own code, discovering events from external packages can be more challenging. The IOTA RPC provides the [`queryEvents`](/iota-api-ref#iotax_queryevents) method, which allows you to query on-chain packages and obtain a list of events you can subscribe to.
To [subscribe to on-chain events](#subscriging-to-events), you first need to identify which events are available. While you can easily track events emitted by your own code, discovering events from external packages can be more challenging. The IOTA RPC provides the [`queryEvents`](/iota-api-ref#iotax_queryevents) method, which allows you to query on-chain packages and obtain a list of events you can subscribe to.

## Applying Event Filters
### Applying Event Filters

When targeting specific events for querying or subscribing, you can use filters to refine your results. Although the filtering options for querying and subscribing are similar, there are notable differences to be aware of.
When targeting specific events for [querying](#query-events) or [subscribing](#subscriging-to-events), you can use [filters](#filtering-events) to refine your results. Although the filtering options for querying and subscribing are similar, there are notable differences to be aware of.

## Emitting Events in Move

To emit events from your Move modules, you need to use the [`iota::event`](../../references/framework/iota-framework/event.mdx) module.
Emitting events allows external applications to subscribe and respond to specific on-chain activities.


First, import the `event` module in your Move code:

```move
Expand All @@ -49,57 +50,104 @@ use iota::event;

Then, within your function, you can emit an event using the [`emit`](../../references/framework/iota-framework/event.mdx#function-emit) function. For example:

```move
/// Take coin from `DonutShop` and transfer it to tx sender.
/// Requires authorization with `ShopOwnerCap`.
public fun collect_profits( _: &ShopOwnerCap, shop: &mut DonutShop, ctx: &mut TxContext ) {
let amount = balance::value(&shop.balance);
let profits = coin::take(&mut shop.balance, amount, ctx);
// simply create new type instance and emit it.
event::emit(ProfitsCollected { amount });
transfer::public_transfer(profits, tx_context::sender(ctx));
}
```move file=<rootDir>/examples/trading/contracts/escrow/sources/lock.move#L42-L63
```

## Subscribing to Events
## Querying Events

### IOTA RPC

The IOTA RPC provides a [queryEvents](../../references/iota-api-ref#iotax_queryEvents) method to query on-chain packages and return available events. As an example, the following `curl` command queries the Deepbook package on Mainnet for a specific type of event:

```sh
curl -X POST https://api.testnet.iota.cafe:443 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "iotax_queryEvents",
"params": [
{
"MoveModule": {
"package": "0x0000000000000000000000000000000000000000000000000000000000000002",
"module": "display",
"type": "0x0000…0002::display::Display<0xba68…286b::testnet_nft::TestnetNFT>"
}
},
null,
3,
false
]
}'
```

To react to events emitted by Move modules, you need to subscribe to them.
IOTA full nodes support event subscriptions via JSON-RPC notifications over WebSocket. You can interact with the [RPC directly][iotax_subscribeEvent](/iota-api-ref#iotax_subscribeevent), [iotax_subscribeTransaction](/iota-api-ref#iotax_subscribetransaction) or use an SDK like the [IOTA TypeScript SDK](../../references/ts-sdk/typescript/index.mdx).
The TypeScript SDK provides a wrapper for the `iotax_queryEvents` method: [`client.queryEvents`](../../references/ts-sdk/api/client/classes/IotaClient#queryevents).

The following excerpt from one of the examples uses the TypeScript SDK to create an asynchronous subscription to the filter identified in the filter.
### Rust

```move
let unsubscribe = await provider.subscribeEvent({
filter: { <PACKAGE_ID> },
onMessage: (event) => {
console.log("subscribeEvent", JSON.stringify(event, null, 2))
You can use the following as an example on how to query for events using the `query_events` function. You should update
the `PACKAGE_ID_CONST` with a package of your choice.

```rust
use iota_sdk::{rpc_types::EventFilter, types::Identifier, IotaClientBuilder};

const PACKAGE_ID_CONST: &str = "";

#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let iota_testnet = IotaClientBuilder::default()
.build("https://api.testnet.iota.cafe:443")
.await?;

let events = iota_testnet
.event_api()
.query_events(
EventFilter::MoveModule {
package: PACKAGE_ID_CONST.parse()?,
module: Identifier::new("dev_trophy")?,
},
None,
None,
false,
)
.await?;

for event in events.data {
println!("Event: {:?}", event.parsed_json);
}
});

Ok(())
}
```

Move smart contracts can call other smart contracts that emit events. For example, `0x107a::nft` calls the `0x2::display::new_with_fields` smart contract and emits a `0x2::display::DisplayCreated` event. Note that using package and transaction module to query for `0x2::display` misses the following event even though it is actually an event the `0x2` package emits. The current workaround for this issue is to know all the `packageId`s you care about and search those in the `queryEvent` call.
### Query Events with GraphQL

```json
{
"id": {
"txDigest": "DrZmtQDDCUKooLzFCi29VhUB4w6AT8phCsT9d62BAf8g",
"eventSeq": "0"
},
"packageId": "0x000000000000000000000000000000000000000000000000000000000000107a",
"transactionModule": "nft",
"sender": "0x0000000000000000000000000000000000000000000000000000000000000000",
"type": "0x2::display::DisplayCreated<0x107a::nft::Nft>",
"parsedJson": {
"id": "0xa12d72c159d57d4c7f540b2b9e985327628d856b20c1d6cdfd3028a2a605abfe"
},
"bcs": "CFbAeqXAwwkyTxUD36FtzTGEcMGrVj4zgcTR1G7AaRjb",
"timestampMs": "1521456213521"
}
You can use GraphQL to query events instead of JSON RPC. The following example queries are in the
[`iota-graphql-rpc` crate](https://github.com/iotaledger/iota/tree/develop/crates/iota-graphql-rpc/examples/event_connection) in the IOTA repo.

#### Event Connection

```graphql file=<rootDir>/crates/iota-graphql-rpc/examples/event_connection/event_connection.graphql
```

#### Filter Events By Sender

```graphql file=<rootDir>/crates/iota-graphql-rpc/examples/event_connection/filter_by_sender.graphql
```

#### Filter Events By Emitting Package and Type

```graphql file=<rootDir>/crates/iota-graphql-rpc/examples/event_connection/filter_by_sender.graphql
```

## Examples
:::tip

The [TypeScript SDK](../../references/ts-sdk/api/graphql/classes/IotaGraphQLClient) provides functionality to
interact with the IOTA GraphQL service.

### Subscribe to Event
:::

## Subscribing to Events

This example leverages the IOTA TypeScript SDK to subscribe to events the package with ID `<PACKAGE_ID>` emits. Each time the event fires, the code displays the response to the console.

Expand Down Expand Up @@ -199,9 +247,19 @@ subscribeEvent {
</TabItem>
</Tabs>

## Monitoring Events

Firing events is not very useful in a vacuum. You also need the ability to respond to those events.
There are two methods from which to choose when you need to monitor on-chain events:
- Incorporate a [custom indexer](../advanced/custom-indexer.mdx) to take advantage of IOTA's micro-data ingestion framework.
- Poll the IOTA network on a schedule to query events.

Using a custom indexer provides a near-real time monitoring of events, so is most useful when your project requires immediate reaction to the firing of events. Polling the network is most useful when the events you're monitoring don't fire often or the need to act on those events are not immediate. The following section provides a polling example.


## Filtering Events

You can filter events when querying or subscribing to receive only the events you are interested in.
You can filter events when [querying](#querying-events) or [subscribing](#subscribing-to-events) to receive only the events you are interested in.

:::info

Expand Down

0 comments on commit aaa1ebb

Please sign in to comment.