-
Notifications
You must be signed in to change notification settings - Fork 469
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
extends logs with extra metadata and query params #651
Changes from all commits
cff96ae
2800e9c
d838f47
4c51bc1
4e96eed
14ec346
959ee97
ae21f76
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,8 @@ use crate::{ | |
contract::tokens::{Detokenize, Tokenize}, | ||
futures::Future, | ||
types::{ | ||
AccessList, Address, BlockId, Bytes, CallRequest, FilterBuilder, TransactionCondition, TransactionReceipt, | ||
TransactionRequest, H256, U256, U64, | ||
AccessList, Address, BlockId, BlockNumber, Bytes, CallRequest, FilterBuilder, LogWithMeta, | ||
TransactionCondition, TransactionReceipt, TransactionRequest, H256, U256, U64, | ||
}, | ||
Transport, | ||
}; | ||
|
@@ -279,7 +279,16 @@ impl<T: Transport> Contract<T> { | |
} | ||
|
||
/// Find events matching the topics. | ||
pub async fn events<A, B, C, R>(&self, event: &str, topic0: A, topic1: B, topic2: C) -> Result<Vec<R>> | ||
pub async fn events<A, B, C, R>( | ||
&self, | ||
event: &str, | ||
from_block: Option<BlockNumber>, | ||
to_block: Option<BlockNumber>, | ||
block_hash: Option<H256>, | ||
Comment on lines
+285
to
+287
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having 7 parameters, and 3 of them being optional is a bit too much. I'd like to propose a helper struct with a builder to amalgamate them. pub struct BlockRange {
from_block: Option<BlockNumber>,
to_block: Option<BlockNumber>,
block_hash: Option<H256>,
}
impl BlockRange {
// set both `from_block` and `to_block`
pub fn range(from: BlockNumber, to: BlockNumber) -> Self;
// set just `from_block`
pub fn from(BlockNumber) -> Self;
// set just `to_block`
pub fn to(BlockNumber) -> Self;
// set just `block_hash`
pub fn hash(H256) -> Self;
// look for one exact block (set both `from/to` and `hash`).
pub fn exact(BlockNumber, H256) -> Self;
// applies the parameters to given filter
pub (crate) fn apply_to(&self, b: FilterBuilder) -> FilterBuilder;
} |
||
topic0: A, | ||
topic1: B, | ||
topic2: C, | ||
) -> Result<Vec<LogWithMeta<R>>> | ||
where | ||
A: Tokenize, | ||
B: Tokenize, | ||
|
@@ -310,7 +319,15 @@ impl<T: Transport> Contract<T> { | |
|
||
let logs = self | ||
.eth | ||
.logs(FilterBuilder::default().topic_filter(filter).build()) | ||
.logs( | ||
FilterBuilder::default() | ||
.address(vec![self.address]) | ||
.topic_filter(filter) | ||
.from_block(from_block) | ||
.to_block(to_block) | ||
.block_hash(block_hash) | ||
.build(), | ||
) | ||
.await?; | ||
logs.into_iter() | ||
.map(move |l| { | ||
|
@@ -319,9 +336,14 @@ impl<T: Transport> Contract<T> { | |
data: l.data.0, | ||
})?; | ||
|
||
R::from_tokens(log.params.into_iter().map(|x| x.value).collect::<Vec<_>>()) | ||
let event_data = R::from_tokens(log.params.into_iter().map(|x| x.value).collect::<Vec<_>>())?; | ||
|
||
Ok(LogWithMeta { | ||
transaction_hash: l.transaction_hash, | ||
event_data, | ||
}) | ||
}) | ||
.collect::<Result<Vec<R>>>() | ||
.collect::<Result<Vec<LogWithMeta<R>>>>() | ||
} | ||
} | ||
|
||
|
@@ -349,6 +371,15 @@ mod contract_signing { | |
// TODO [ToDr] SendTransactionWithConfirmation should support custom error type (so that we can return | ||
// `contract::Error` instead of more generic `Error`. | ||
.map_err(|err| crate::error::Error::Decoder(format!("{:?}", err)))?; | ||
self.sign_raw(fn_data, options, key).await | ||
} | ||
|
||
async fn sign_raw( | ||
&self, | ||
fn_data: Vec<u8>, | ||
options: Options, | ||
key: impl signing::Key, | ||
) -> crate::Result<SignedTransaction> { | ||
let accounts = Accounts::new(self.eth.transport().clone()); | ||
let mut tx = TransactionParameters { | ||
nonce: options.nonce, | ||
|
@@ -385,10 +416,24 @@ mod contract_signing { | |
self.eth.send_raw_transaction(signed.raw_transaction).await | ||
} | ||
|
||
/// Submit contract call transaction to the transaction pool. | ||
/// | ||
/// Note this function DOES NOT wait for any confirmations, so there is no guarantees that the call is actually executed. | ||
/// If you'd rather wait for block inclusion, please use [`signed_call_raw_with_confirmations`] instead. | ||
pub async fn signed_call_raw( | ||
&self, | ||
fn_data: Vec<u8>, | ||
options: Options, | ||
key: impl signing::Key, | ||
) -> crate::Result<H256> { | ||
let signed = self.sign_raw(fn_data, options, key).await?; | ||
self.eth.send_raw_transaction(signed.raw_transaction).await | ||
} | ||
|
||
/// Submit contract call transaction to the transaction pool and wait for the transaction to be included in a block. | ||
/// | ||
/// This function will wait for block inclusion of the transaction before returning. | ||
// If you'd rather just submit transaction and receive it's hash, please use [`signed_call`] instead. | ||
/// If you'd rather just submit transaction and receive it's hash, please use [`signed_call`] instead. | ||
pub async fn signed_call_with_confirmations( | ||
&self, | ||
func: &str, | ||
|
@@ -408,6 +453,29 @@ mod contract_signing { | |
) | ||
.await | ||
} | ||
|
||
/// Submit contract call transaction to the transaction pool and wait for the transaction to be included in a block. | ||
/// | ||
/// This function will wait for block inclusion of the transaction before returning. | ||
/// If you'd rather just submit transaction and receive it's hash, please use [`signed_call`] instead. | ||
pub async fn signed_call_raw_with_confirmations( | ||
&self, | ||
fn_data: Vec<u8>, | ||
options: Options, | ||
confirmations: usize, | ||
key: impl signing::Key, | ||
) -> crate::Result<TransactionReceipt> { | ||
let poll_interval = time::Duration::from_secs(1); | ||
let signed = self.sign_raw(fn_data, options, key).await?; | ||
|
||
confirm::send_raw_transaction_with_confirmation( | ||
self.eth.transport().clone(), | ||
signed.raw_transaction, | ||
poll_interval, | ||
confirmations, | ||
) | ||
.await | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
use crate::types::{BlockNumber, Bytes, Index, H160, H256, U256, U64}; | ||
use crate::{ | ||
contract::tokens::Detokenize, | ||
types::{BlockNumber, Bytes, Index, H160, H256, U256, U64}, | ||
}; | ||
use serde::{Deserialize, Serialize, Serializer}; | ||
|
||
/// A log produced by a transaction. | ||
|
@@ -54,6 +57,17 @@ impl Log { | |
} | ||
} | ||
|
||
/// A log produced when a specific contract event was emitted. | ||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | ||
pub struct LogWithMeta<R: Detokenize> { | ||
/// Transaction hash necessary to retrieve `calldata`. | ||
#[serde(rename = "transactionHash")] | ||
pub transaction_hash: Option<H256>, | ||
|
||
/// A tuple from the event signature (e.g. `(uint256, bytes)`). | ||
pub event_data: R, | ||
} | ||
|
||
#[derive(Default, Debug, PartialEq, Clone)] | ||
struct ValueOrArray<T>(Vec<T>); | ||
|
||
|
@@ -106,27 +120,33 @@ impl FilterBuilder { | |
/// Sets `from_block`. The fields `from_block` and `block_hash` are | ||
/// mutually exclusive. Setting `from_block` will clear a previously set | ||
/// `block_hash`. | ||
pub fn from_block(mut self, block: BlockNumber) -> Self { | ||
self.filter.block_hash = None; | ||
self.filter.from_block = Some(block); | ||
pub fn from_block(mut self, block: Option<BlockNumber>) -> Self { | ||
if let Some(block) = block { | ||
self.filter.block_hash = None; | ||
self.filter.from_block = Some(block); | ||
} | ||
Comment on lines
+123
to
+127
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method should not be changed, the builder should only take values that are defined, not |
||
self | ||
} | ||
|
||
/// Sets `to_block`. The fields `to_block` and `block_hash` are mutually | ||
/// exclusive. Setting `to_block` will clear a previously set `block_hash`. | ||
pub fn to_block(mut self, block: BlockNumber) -> Self { | ||
self.filter.block_hash = None; | ||
self.filter.to_block = Some(block); | ||
pub fn to_block(mut self, block: Option<BlockNumber>) -> Self { | ||
if let Some(block) = block { | ||
self.filter.block_hash = None; | ||
self.filter.to_block = Some(block); | ||
} | ||
Comment on lines
+133
to
+137
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. |
||
self | ||
} | ||
|
||
/// Sets `block_hash`. The field `block_hash` and the pair `from_block` and | ||
/// `to_block` are mutually exclusive. Setting `block_hash` will clear a | ||
/// previously set `from_block` and `to_block`. | ||
pub fn block_hash(mut self, hash: H256) -> Self { | ||
self.filter.from_block = None; | ||
self.filter.to_block = None; | ||
self.filter.block_hash = Some(hash); | ||
pub fn block_hash(mut self, hash: Option<H256>) -> Self { | ||
if let Some(_block_hash) = hash { | ||
self.filter.from_block = None; | ||
self.filter.to_block = None; | ||
self.filter.block_hash = hash; | ||
} | ||
Comment on lines
+144
to
+149
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto. |
||
self | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation should be updated.