From 605ceebd2c8ebddb32141d40561e2b796eeb3d31 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Thu, 23 Mar 2023 12:12:41 -0600 Subject: [PATCH 1/7] events --- book/events/events.md | 0 book/events/logs-and-filtering.md | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 book/events/events.md create mode 100644 book/events/logs-and-filtering.md diff --git a/book/events/events.md b/book/events/events.md new file mode 100644 index 000000000..e69de29bb diff --git a/book/events/logs-and-filtering.md b/book/events/logs-and-filtering.md new file mode 100644 index 000000000..a72cd8130 --- /dev/null +++ b/book/events/logs-and-filtering.md @@ -0,0 +1,5 @@ +# Logs and filtering + +```rust +{{#include ../../examples/events/examples/filtering.rs}} +``` From d73e76cc96db5a18551644932cc68305083e4185 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Thu, 23 Mar 2023 12:15:29 -0600 Subject: [PATCH 2/7] events --- book/SUMMARY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/SUMMARY.md b/book/SUMMARY.md index 0bf0bae0e..8ab35ad27 100644 --- a/book/SUMMARY.md +++ b/book/SUMMARY.md @@ -38,8 +38,8 @@ - [Events](./contracts/events.md) - [Events with meta](./contracts/events-with-meta.md) - [Methods](contracts/methods.md) -- [Events]() - - [Logs and filtering]() +- [Events](./events/events.md) + - [Logs and filtering](events/logs-and-filtering.md) - [Solidity topics]() - [Subscriptions]() - [Watch blocks]() From 0e2a6827941629f8247b8681630a80434c91d4b7 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Thu, 23 Mar 2023 13:32:37 -0600 Subject: [PATCH 3/7] event contnent --- book/SUMMARY.md | 2 +- book/events/events.md | 105 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/book/SUMMARY.md b/book/SUMMARY.md index 8ab35ad27..e09d7cc9a 100644 --- a/book/SUMMARY.md +++ b/book/SUMMARY.md @@ -41,7 +41,7 @@ - [Events](./events/events.md) - [Logs and filtering](events/logs-and-filtering.md) - [Solidity topics]() -- [Subscriptions]() +- [Subscriptions](./subscriptions/subscriptions.md) - [Watch blocks]() - [Subscribe events by type]() - [Subscribe logs]() diff --git a/book/events/events.md b/book/events/events.md index e69de29bb..e53b2f9af 100644 --- a/book/events/events.md +++ b/book/events/events.md @@ -0,0 +1,105 @@ +# Ethers-rs: Working with Events + +In this section we will discuss how to monitor, subscribe, and listen to events using the ethers-rs library. Events are an essential part of smart contract development, as they allow you to track specific occurrences on the blockchain, such as transactions, state changes, or function calls. + +## Overview + +ethers-rs provides a simple and efficient way to interact with events emitted by smart contracts. You can listen to events, filter them based on certain conditions, and subscribe to event streams for real-time updates. The key components you will work with are: + +1. Event: A struct representing an event emitted by a smart contract. +2. EventWatcher: A struct that allows you to monitor and filter events. +3. SubscriptionStream: A stream of events you can subscribe to for real-time updates. + +## Getting Started + +Before diving into event handling, ensure you have ethers-rs added to your project's dependencies in Cargo.toml: + +```toml +[dependencies] +ethers = { version = "2.0.0.", features = ["full"] } +Now, let's import the necessary components from the ethers-rs library: +``` + +```rust +use ethers::{ +prelude::\*, +contract::{Contract, EthEvent}, +}; +``` + +### Listening to Events + +To listen to events, you'll need to instantiate a Contract object and use the event method to create an Event struct. You'll also need to define a struct that implements the EthEvent trait, representing the specific event you want to listen to. + +Consider a simple smart contract that emits an event called ValueChanged: + +```solidity +pragma solidity ^0.8.0; + +contract SimpleStorage { + + uint256 public value; + event ValueChanged(uint256 newValue); + + function setValue(uint256 _value) public { + value = _value; + emit ValueChanged(_value); + } + +} +``` + +First, define a struct representing the ValueChanged event: + +```rust +#[derive(Debug, Clone, EthEvent)] +pub struct ValueChanged { +pub new_value: U256, +} +``` + +Then, create an instance of the Contract object and listen for the ValueChanged event: + +```rust +async fn main() -> Result<(), Box> { + let provider = Provider::::try_from("http://localhost:8545")?; + let contract_address = "0xcontract_address_here".parse()?; + let contract = Contract::from_json(provider, + contract_address, + include_bytes!("../contracts/abis/SimpleStorage.json"))?; + + let event = contract.event::()?; + + // Your code to handle the event goes here. + + Ok(()) + +} +``` + +### Filtering Events + +You can filter events based on specific conditions using the EventWatcher struct. To create an EventWatcher, call the watcher method on your Event object: + +```rust +let watcher = event.watcher().from_block(5).to_block(10); +``` + +In this example, the EventWatcher will only monitor events from block 5 to block 10. + +### Subscribing to Events + +To receive real-time updates for an event, create a SubscriptionStream by calling the subscribe method on your EventWatcher: + +```rust +let mut stream = watcher.subscribe().await?; +``` + +You can now listen to events as they are emitted by the smart contract: + +```rust +while let Some(event) = stream.next().await { + match event { + Ok(log) => {println!("New event: {:?}", log)}, + Err(e) => {println!("Error: {:?}", e)}, +``` From bb52b27265f82a183c7d24e790c192bfbe990621 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Thu, 23 Mar 2023 13:50:28 -0600 Subject: [PATCH 4/7] subscriptions --- .DS_Store | Bin 0 -> 6148 bytes book/SUMMARY.md | 7 +- book/subscriptions/events-by-type.md | 5 + book/subscriptions/logs.md | 5 + book/subscriptions/multiple-subscriptions.md | 58 +++++++++ book/subscriptions/subscriptions.md | 126 +++++++++++++++++++ book/subscriptions/watch-blocks.md | 5 + 7 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 .DS_Store create mode 100644 book/subscriptions/events-by-type.md create mode 100644 book/subscriptions/logs.md create mode 100644 book/subscriptions/multiple-subscriptions.md create mode 100644 book/subscriptions/subscriptions.md create mode 100644 book/subscriptions/watch-blocks.md diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8e180ebe452b6434dd4ce40b164de753c1a4b1ae GIT binary patch literal 6148 zcmeH~F%H5o3`K3|P>H1@V-^m;4WbH8zy(n0Mx_pjJxAx;@j_un75YZ@kDXeyZ)j=} z(f&CeMLH2_;ihu1urNj5$RIO*_wjL?hIyW>2-{Q&N3+{TfwU7dX@}M|k@PKw?Mn9`1(yWD95xEmcv0@k78dFp$7c3A_N& C`Vz1J literal 0 HcmV?d00001 diff --git a/book/SUMMARY.md b/book/SUMMARY.md index e09d7cc9a..63ffba6fd 100644 --- a/book/SUMMARY.md +++ b/book/SUMMARY.md @@ -42,9 +42,10 @@ - [Logs and filtering](events/logs-and-filtering.md) - [Solidity topics]() - [Subscriptions](./subscriptions/subscriptions.md) - - [Watch blocks]() - - [Subscribe events by type]() - - [Subscribe logs]() + - [Watch blocks](./subscriptions/watch-blocks.md) + - [Subscribe events by type](./subscriptions/events-by-type.md) + - [Subscribe logs](./subscriptions/logs.md) + - [Mulitple subscriptions](./subscriptions/multiple-subscriptions.md) - [Queries]() - [Blocks]() - [Contracts]() diff --git a/book/subscriptions/events-by-type.md b/book/subscriptions/events-by-type.md new file mode 100644 index 000000000..81450a33f --- /dev/null +++ b/book/subscriptions/events-by-type.md @@ -0,0 +1,5 @@ +# Subscribe events by type + +```rust +{{#include ../../examples/subscriptions/examples/subscribe_events_by_type.rs}} +``` diff --git a/book/subscriptions/logs.md b/book/subscriptions/logs.md new file mode 100644 index 000000000..60878fc67 --- /dev/null +++ b/book/subscriptions/logs.md @@ -0,0 +1,5 @@ +# Subscribe logs + +```rust +{{#include ../../examples/subscriptions/examples/subscribe_logs.rs}} +``` diff --git a/book/subscriptions/multiple-subscriptions.md b/book/subscriptions/multiple-subscriptions.md new file mode 100644 index 000000000..bb963fae3 --- /dev/null +++ b/book/subscriptions/multiple-subscriptions.md @@ -0,0 +1,58 @@ +# Mulitple Multiple Subscriptions + +You may need to handle multiple subscriptions simultaneously in your application. To manage multiple SubscriptionStreams, you can use the futures crate to efficiently process updates from all streams concurrently: + +```toml +[dependencies] +futures = "0.3" +``` + +Then, import the necessary components: + +```rust +use futures::{stream, StreamExt, TryStreamExt}; +``` + +Create multiple subscription streams and merge them into a single stream using the stream::select_all function: + +```rust +async fn main() -> Result<(), Box> { + // Create multiple subscription streams. + let mut block_stream = provider.subscribe_blocks().await?; + let mut log_stream = provider.subscribe_logs(filter).await?; + let mut event_stream = watcher.subscribe().await?; + + // Merge the streams into a single stream. + let mut combined_stream = stream::select_all(vec![ + block_stream.map_ok(|block| EventType::Block(block)), + log_stream.map_ok(|log| EventType::Log(log)), + event_stream.map_ok(|event| EventType::Event(event)), + ]); + + // Your code to handle the events goes here. + + Ok(()) + +} +``` + +Now, you can listen to updates from all the subscription streams concurrently: + +```rust +while let Some(event) = combined_stream.next().await { + match event { + Ok(event) => match event { + EventType::Block(block) => println!("New block: {:?}", block), + EventType::Log(log) => println!("New log: {:?}", log), + EventType::Event(event) => println!("New event: {:?}", event), + }, + Err(e) => { + eprintln!("Error: {:?}", e); + } + } +} +``` + +This approach allows you to efficiently handle multiple subscriptions in your application and react to various network activities in a unified manner. + +By leveraging the powerful subscription capabilities of ethers-rs, you can create responsive and dynamic applications that stay up-to-date with the latest events on the Ethereum network. The library's flexibility and ease of use make it an ideal choice for developers looking to build robust and performant applications that interact with smart contracts and the Ethereum blockchain. diff --git a/book/subscriptions/subscriptions.md b/book/subscriptions/subscriptions.md new file mode 100644 index 000000000..92365e13f --- /dev/null +++ b/book/subscriptions/subscriptions.md @@ -0,0 +1,126 @@ +## Ethers-rs: Subscriptions + +In this section of the mdbook, we will discuss how to use `ethers-rs` to subscribe and listen to blocks, events, and logs. Subscriptions provide a way to receive real-time updates on various activities on the Ethereum blockchain, allowing you to monitor the network and react to changes as they happen. + +## Overview + +ethers-rs offers a convenient way to work with subscriptions, enabling you to listen to new blocks, transaction receipts, and logs. The main components you will work with are: + +1. Provider: The main struct used to interact with the Ethereum network. +2. SubscriptionStream: A stream of updates you can subscribe to for real-time notifications. + +## Getting Started + +Before working with subscriptions, make sure you have ethers-rs added to your project's dependencies in Cargo.toml: + +```toml +[dependencies] +ethers = { version = "2.0.0", features = ["full"] } +``` + +Next, import the necessary components from the ethers-rs library: + +```rust +use ethers::{prelude::\*,types::H256,}; +``` + +## Subscribing to New Blocks + +To subscribe to new blocks, create a Provider instance and call the subscribe_blocks method: + +```rust +async fn main() -> Result<(), Box> { +let provider = Provider::::try_from("http://localhost:8545")?; + + let mut stream = provider.subscribe_blocks().await?; + + // Your code to handle new blocks goes here. + + Ok(()) + +} +``` + +You can now listen to new blocks as they are mined: + +```rust +while let Some(block) = stream.next().await { + match block { + Ok(block) => { + println!("New block: {:?}", block); + } + Err(e) => { + eprintln!("Error: {:?}", e); + } + } +} +``` + +### Subscribing to Logs + +To subscribe to logs, create a Filter object that specifies the criteria for the logs you want to listen to. Then, pass the filter to the Provider's subscribe_logs method: + +```rust +async fn main() -> Result<(), Box> { + let provider = Provider::::try_from("http://localhost:8545")?; + + let filter = Filter::new().address("0xcontract_address_here".parse()?); + + let mut stream = provider.subscribe_logs(filter).await?; + + // Your code to handle logs goes here. + + Ok(()) + +} +``` + +You can now listen to logs that match your filter criteria: + +```rust +while let Some(log) = stream.next().await { + match log { + Ok(log) => { + println!("New log: {:?}", log); + } + Err(e) => { + eprintln!("Error: {:?}", e); + } + } +} +``` + +### Subscribing to Events + +As we discussed in the previous section on events, you can subscribe to specific events emitted by smart contracts using the EventWatcher struct. To create a SubscriptionStream, call the subscribe method on your EventWatcher: + +```rust +let mut stream = watcher.subscribe().await?; +``` + +Now, you can listen to events as they are emitted by the smart contract: + +```rust +while let Some(event) = stream.next().await { + match event { + Ok(log) => { + println!("New event: {:?}", log); + } + Err(e) => { + eprintln!("Error: {:?}", e); + } + } +} +``` + +By using the subscription features provided by ethers-rs, you can efficiently monitor and react to various activities on the Ethereum network. Subscriptions are a powerful tool for building responsive and dynamic applications that can interact with smart contracts and stay up-to-date with the latest network events. + +### Unsubscribing from Subscriptions + +In some cases, you may want to stop listening to a subscription. To do this, simply drop the SubscriptionStream: + +```rust +drop(stream); +``` + +This will stop the stream from receiving any further updates. diff --git a/book/subscriptions/watch-blocks.md b/book/subscriptions/watch-blocks.md new file mode 100644 index 000000000..60233b0d4 --- /dev/null +++ b/book/subscriptions/watch-blocks.md @@ -0,0 +1,5 @@ +# Watch blocks + +```rust +{{#include ../../examples/subscriptions/examples/subscribe_blocks.rs}} +``` From 4dcb1a9441e350d28cd7c5f6955df88b10362444 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Thu, 23 Mar 2023 13:51:25 -0600 Subject: [PATCH 5/7] remove DS-Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 8e180ebe452b6434dd4ce40b164de753c1a4b1ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~F%H5o3`K3|P>H1@V-^m;4WbH8zy(n0Mx_pjJxAx;@j_un75YZ@kDXeyZ)j=} z(f&CeMLH2_;ihu1urNj5$RIO*_wjL?hIyW>2-{Q&N3+{TfwU7dX@}M|k@PKw?Mn9`1(yWD95xEmcv0@k78dFp$7c3A_N& C`Vz1J From 0d866dc8636be609952ac0800600af02800c12b6 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Thu, 23 Mar 2023 13:55:42 -0600 Subject: [PATCH 6/7] clean up sections --- book/subscriptions/logs.md | 36 ++++++++++++++- book/subscriptions/subscriptions.md | 68 +---------------------------- book/subscriptions/watch-blocks.md | 34 ++++++++++++++- 3 files changed, 69 insertions(+), 69 deletions(-) diff --git a/book/subscriptions/logs.md b/book/subscriptions/logs.md index 60878fc67..0d0c091f6 100644 --- a/book/subscriptions/logs.md +++ b/book/subscriptions/logs.md @@ -1,4 +1,38 @@ -# Subscribe logs +# Subscribing to Logs + +To subscribe to logs, create a Filter object that specifies the criteria for the logs you want to listen to. Then, pass the filter to the Provider's subscribe_logs method: + +```rust +async fn main() -> Result<(), Box> { + let provider = Provider::::try_from("http://localhost:8545")?; + + let filter = Filter::new().address("0xcontract_address_here".parse()?); + + let mut stream = provider.subscribe_logs(filter).await?; + + // Your code to handle logs goes here. + + Ok(()) + +} +``` + +You can now listen to logs that match your filter criteria: + +```rust +while let Some(log) = stream.next().await { + match log { + Ok(log) => { + println!("New log: {:?}", log); + } + Err(e) => { + eprintln!("Error: {:?}", e); + } + } +} +``` + +Here is another example of subscribing to logs: ```rust {{#include ../../examples/subscriptions/examples/subscribe_logs.rs}} diff --git a/book/subscriptions/subscriptions.md b/book/subscriptions/subscriptions.md index 92365e13f..9b25f5eb3 100644 --- a/book/subscriptions/subscriptions.md +++ b/book/subscriptions/subscriptions.md @@ -1,6 +1,6 @@ ## Ethers-rs: Subscriptions -In this section of the mdbook, we will discuss how to use `ethers-rs` to subscribe and listen to blocks, events, and logs. Subscriptions provide a way to receive real-time updates on various activities on the Ethereum blockchain, allowing you to monitor the network and react to changes as they happen. +Here we will discuss how to use `ethers-rs` to subscribe and listen to blocks, events, and logs. Subscriptions provide a way to receive real-time updates on various activities on the Ethereum blockchain, allowing you to monitor the network and react to changes as they happen. ## Overview @@ -24,72 +24,6 @@ Next, import the necessary components from the ethers-rs library: use ethers::{prelude::\*,types::H256,}; ``` -## Subscribing to New Blocks - -To subscribe to new blocks, create a Provider instance and call the subscribe_blocks method: - -```rust -async fn main() -> Result<(), Box> { -let provider = Provider::::try_from("http://localhost:8545")?; - - let mut stream = provider.subscribe_blocks().await?; - - // Your code to handle new blocks goes here. - - Ok(()) - -} -``` - -You can now listen to new blocks as they are mined: - -```rust -while let Some(block) = stream.next().await { - match block { - Ok(block) => { - println!("New block: {:?}", block); - } - Err(e) => { - eprintln!("Error: {:?}", e); - } - } -} -``` - -### Subscribing to Logs - -To subscribe to logs, create a Filter object that specifies the criteria for the logs you want to listen to. Then, pass the filter to the Provider's subscribe_logs method: - -```rust -async fn main() -> Result<(), Box> { - let provider = Provider::::try_from("http://localhost:8545")?; - - let filter = Filter::new().address("0xcontract_address_here".parse()?); - - let mut stream = provider.subscribe_logs(filter).await?; - - // Your code to handle logs goes here. - - Ok(()) - -} -``` - -You can now listen to logs that match your filter criteria: - -```rust -while let Some(log) = stream.next().await { - match log { - Ok(log) => { - println!("New log: {:?}", log); - } - Err(e) => { - eprintln!("Error: {:?}", e); - } - } -} -``` - ### Subscribing to Events As we discussed in the previous section on events, you can subscribe to specific events emitted by smart contracts using the EventWatcher struct. To create a SubscriptionStream, call the subscribe method on your EventWatcher: diff --git a/book/subscriptions/watch-blocks.md b/book/subscriptions/watch-blocks.md index 60233b0d4..8102f706d 100644 --- a/book/subscriptions/watch-blocks.md +++ b/book/subscriptions/watch-blocks.md @@ -1,4 +1,36 @@ -# Watch blocks +# Subscribing to New Blocks + +To subscribe to new blocks, create a Provider instance and call the subscribe_blocks method: + +```rust +async fn main() -> Result<(), Box> { +let provider = Provider::::try_from("http://localhost:8545")?; + + let mut stream = provider.subscribe_blocks().await?; + + // Your code to handle new blocks goes here. + + Ok(()) + +} +``` + +You can now listen to new blocks as they are mined: + +```rust +while let Some(block) = stream.next().await { + match block { + Ok(block) => { + println!("New block: {:?}", block); + } + Err(e) => { + eprintln!("Error: {:?}", e); + } + } +} +``` + +Here is another example of subscribing to new blocks: ```rust {{#include ../../examples/subscriptions/examples/subscribe_blocks.rs}} From 3b7f3e530ccadc9f6a97952cd48f7c8d943633a1 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Sun, 26 Mar 2023 15:56:44 -0600 Subject: [PATCH 7/7] Jame's Feedback --- book/events/events.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/book/events/events.md b/book/events/events.md index e53b2f9af..d9bf385a2 100644 --- a/book/events/events.md +++ b/book/events/events.md @@ -17,13 +17,13 @@ Before diving into event handling, ensure you have ethers-rs added to your proje ```toml [dependencies] ethers = { version = "2.0.0.", features = ["full"] } -Now, let's import the necessary components from the ethers-rs library: ``` +Now, let's import the necessary components from the ethers-rs library: + ```rust use ethers::{ -prelude::\*, -contract::{Contract, EthEvent}, +prelude::contract::{Contract, EthEvent}, }; ``` @@ -54,7 +54,7 @@ First, define a struct representing the ValueChanged event: ```rust #[derive(Debug, Clone, EthEvent)] pub struct ValueChanged { -pub new_value: U256, + pub new_value: U256, } ```