From aaa1ebb8e11982725a931a962a3b0d97466234c0 Mon Sep 17 00:00:00 2001 From: Lucas Tortora Date: Wed, 11 Dec 2024 14:54:14 -0300 Subject: [PATCH] feat(devx) update using events guide --- .../developer/iota-101/using-events.mdx | 146 ++++++++++++------ 1 file changed, 102 insertions(+), 44 deletions(-) diff --git a/docs/content/developer/iota-101/using-events.mdx b/docs/content/developer/iota-101/using-events.mdx index f808f9e1e07..bd240f6045e 100644 --- a/docs/content/developer/iota-101/using-events.mdx +++ b/docs/content/developer/iota-101/using-events.mdx @@ -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 @@ -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=/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: { }, - 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=/crates/iota-graphql-rpc/examples/event_connection/event_connection.graphql +``` + +#### Filter Events By Sender + +```graphql file=/crates/iota-graphql-rpc/examples/event_connection/filter_by_sender.graphql +``` + +#### Filter Events By Emitting Package and Type + +```graphql file=/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 `` emits. Each time the event fires, the code displays the response to the console. @@ -199,9 +247,19 @@ subscribeEvent { +## 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