Skip to content

Commit

Permalink
started implemented confirmation
Browse files Browse the repository at this point in the history
  • Loading branch information
nlordell committed Jan 6, 2020
1 parent 6cf9102 commit 6785cf5
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Implementation for setting up, signing, estimating gas and sending
//! transactions on the Ethereum network.
pub mod confirm;

use crate::errors::ExecutionError;
use crate::future::{CompatCallFuture, CompatSendTxWithConfirmation, MaybeReady, Web3Unpin};
use crate::sign::TransactionData;
Expand Down Expand Up @@ -99,6 +101,14 @@ pub struct TransactionBuilder<T: Transport> {
/// Optional nonce to use. Defaults to the signing account's current
/// transaction count.
pub nonce: Option<U256>,
/// Optional block confirmations to wait for. Defaults to 1 confirmation
/// which means waiting the transaction to be mined in a single block. Use 0
/// to send the transaction and only place it in the mem-pool and not wait
/// for it to be mined.
pub confirmations: Option<usize>,
/// Options poll timeout used for waiting for block confirmations. Defaults
/// to 7 seconds.
pub poll_timeout: Option<Duration>,
}

impl<T: Transport> TransactionBuilder<T> {
Expand All @@ -113,6 +123,8 @@ impl<T: Transport> TransactionBuilder<T> {
value: None,
data: None,
nonce: None,
confirmations: None,
poll_timeout: None,
}
}

Expand Down
77 changes: 77 additions & 0 deletions src/transaction/confirm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//! Transaction confirmation implementation. This is a re-implementation of
//! `web3` confirmation future to fix issues with development nodes like Ganache
//! where the transaction gets mined right away, so waiting for 1 confirmation
//! would require another transaction to be sent so a new block could mine.
//! Additionally, waiting for 0 confirmations in `web3` means that the tx is
//! just sent to the mem-pool but does not wait for it to get mined. Hopefully
//! some of this can move upstream into the `web3` crate.
#![allow(missing_docs)]

use crate::errors::ExecutionError;
use crate::future::CompatCallFuture;
use futures::future::{Either, TryJoin};
use futures::ready;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::num::NonZeroUsize;
use web3::api::Web3;
use web3::types::{TransactionReceipt, H256, U256};
use web3::Transport;

pub struct ConfirmFuture<T: Transport> {
web3: Web3<T>,
tx: H256,
confirmations: NonZeroUsize,
state: ConfirmState<T>,
}

impl<T: Transport> ConfirmFuture<T> {
pub fn new(web3: Web3<T>, tx: H256, confirmations: usize) -> Either<
}

impl<T: Transport> ConfirmFuture<T> {
fn state_mut(self: Pin<&mut Self>) -> &mut ConfirmState<T> {
// NOTE: this is safe as the `state` field does not need to be pinned
unsafe { &mut self.get_unchecked_mut().state }
}
}

impl<T: Transport> Future for ConfirmFuture<T> {
type Output = Result<TransactionResult, ExecutionError>;

fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
loop {
match self.as_mut().state_mut() {
ConfirmState::Checking(ref mut check) => {
let (block_num, tx) = match ready!(Pin::new(check).poll(cx)) {
Ok(result) => result,
Err(err) => return Poll::Ready(Err(err.into())),
};
let tx_block_num = tx.and_then(|tx| tx.block_number).unwrap_or(block_num);

if block_num + 1 >= tx_block_num + self.confirmations.get() {
return Poll::Ready
}
todo!()
}
ConfirmState::WaitingForBlocks(ref mut wait) => todo!(),
}
}
}
}

enum ConfirmState<T: Transport> {
Checking(CheckFuture<T>),
WaitingForBlocks(WaitForBlocksFuture<T>),
}

type CheckFuture<T> = TryJoin<CompatCallFuture<T, U256>, CompatCallFuture<T, TransactionReceipt>>;

struct WaitForBlocksFuture<T>(T);

pub enum TransactionResult {
Hash(H256),
Receipt(TransactionReceipt),
}

0 comments on commit 6785cf5

Please sign in to comment.