Skip to content
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

Allow signing deployment transactions with a private key #473

Merged
merged 4 commits into from
Mar 16, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions src/contract/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use crate::{
types::{Address, Bytes, TransactionReceipt, TransactionRequest},
Transport,
};
#[cfg(feature = "signing")]
use crate::{signing::Key, types::TransactionParameters};
use futures::{Future, TryFutureExt};
use std::{collections::HashMap, time};

Expand Down Expand Up @@ -94,6 +96,62 @@ impl<T: Transport> Builder<T> {
.await
}

/// Execute deployment passing code and constructor parameters.
///
/// Unlike the above `sign_and_execute`, this method allows the
/// caller to pass in a private key to sign the transaction with
/// and therefore allows deploying from an account that the
/// ethereum node doesn't need to know the private key for.
tomusdrw marked this conversation as resolved.
Show resolved Hide resolved
///
/// An optional `chain_id` parameter can be passed to provide
/// replay protection for transaction signatures. Passing `None`
/// would create a transaction WITHOUT replay protection and
/// should be avoided.
/// You can obtain `chain_id` of the network you are connected
/// to using `web3.eth().chain_id()` method.
#[cfg(feature = "signing")]
pub async fn sign_with_key_and_execute<P, V, K>(
self,
code: V,
params: P,
from: K,
chain_id: Option<u64>,
) -> Result<Contract<T>, Error>
where
P: Tokenize,
V: AsRef<str>,
K: Key,
{
let transport = self.eth.transport().clone();
let poll_interval = self.poll_interval;
let confirmations = self.confirmations;

self.do_execute(code, params, from.address(), move |tx| async move {
let tx = TransactionParameters {
nonce: tx.nonce,
to: tx.to,
gas: tx.gas.unwrap_or(1_000_000.into()),
gas_price: tx.gas_price,
value: tx.value.unwrap_or(0.into()),
data: tx
.data
.expect("Tried to deploy a contract but transaction data wasn't set"),
chain_id,
};
let signed_tx = crate::api::Accounts::new(transport.clone())
.sign_transaction(tx, from)
.await?;
confirm::send_raw_transaction_with_confirmation(
transport,
signed_tx.raw_transaction,
poll_interval,
confirmations,
)
.await
})
.await
}

async fn do_execute<P, V, Ft>(
self,
code: V,
Expand Down