/// Sends a transaction which changes blockchain state.
/// `options` takes a vector of `SendTxOption` for configuration
/// unlike the lower level eth_send_transaction() this call builds
/// the transaction abstracting away details like chain id, gas,
/// and network id.
/// WARNING: you must specify networkID in situations where a single
/// node is operating no more than one chain. Otherwise it is possible
/// for the full node to trick the client into signing transactions
/// on unintended chains potentially to their benefit
Sends a transaction which changes blockchain state.
`options` takes a vector of `SendTxOption` for configuration
unlike the lower level eth_send_transaction() this call builds
the transaction abstracting away details like chain id, gas,
and network id.
WARNING: you must specify networkID in situations where a single
node is operating no more than one chain. Otherwise it is possible
for the full node to trick the client into signing transactions
on unintended chains potentially to their benefit
Sends a transaction which changes blockchain state . ` options ` takes a vector of ` SendTxOption ` for configuration unlike the lower level eth_send_transaction () this call builds the transaction abstracting away details like chain id gas and network id . WARNING : you must specify networkID in situations where a single node is operating no more than one chain . Otherwise it is possible for the full node to trick the client into signing transactions on unintended chains potentially to their benefit
pub async fn send_transaction(
        &self,
        to_address: Address,
        data: Vec<u8>,
        value: Uint256,
        own_address: Address,
        secret: PrivateKey,
        options: Vec<SendTxOption>,
    ) -> Result<Uint256, Web3Error> {
        let mut gas_price = None;
        let mut gas_price_multiplier = 1u64.into();
        let mut gas_limit = None;
        let mut network_id = None;
        let our_balance = self.eth_get_balance(own_address).await?;
        let mut nonce = self.eth_get_transaction_count(own_address).await?;
        for option in options {
            match option {
                SendTxOption::GasPrice(gp) => gas_price = Some(gp),
                SendTxOption::GasPriceMultiplier(gpm) => gas_price_multiplier = gpm,
                SendTxOption::GasLimit(gl) => gas_limit = Some(gl),
                SendTxOption::NetworkId(ni) => network_id = Some(ni),
                SendTxOption::Nonce(n) => nonce = n,
            }
        }
        let mut gas_price = if let Some(gp) = gas_price {
            gp
        } else {
            self.eth_gas_price().await? * gas_price_multiplier
        };
        let gas_limit = if let Some(gl) = gas_limit {
            gl
        } else {
            // Geth and parity behave differently for the Estimate gas call
            // Parity / OpenEthereum will allow you to specify no gas price
            // and no gas amount the estimate gas call will then return the
            // amount of gas the transaction would take. This is reasonable behavior
            // from an endpoint that's supposed to let you estimate gas usage
            //
            // The gas price is of course irrelevant unless someone goes out of their
            // way to design a contract that fails a low gas prices. Geth and Parity
            // can't simulate an actual transaction market accurately.
            //
            // Geth on the other hand insists that you provide a gas price (any price)
            // and a gas value. Otherwise it will not provide an estimate.
            //
            // If this value is too low Geth will fail, if this value is higher than
            // your balance Geth will once again fail. So Geth at this juncture won't
            // tell you what the transaction would cost, just that you can't afford it.
            //
            // So if yes you could set these values to none if making a parity request
            let gas_price: Uint256 = 1u8.into();
            // Geth represents gas as a u64 it will truncate leading zeros but not take
            // a value larger than u64::MAX, likewise the command will fail if we can't
            // actually pay that fee. This operation maximizes the info we can get
            let gas_limit = min((u64::MAX - 1).into(), our_balance.clone());
            self.eth_estimate_gas(TransactionRequest {
                from: Some(own_address),
                to: to_address,
                nonce: Some(nonce.clone().into()),
                gas_price: Some(gas_price.into()),
                gas: Some(gas_limit.into()),
                value: Some(value.clone().into()),
                data: Some(data.clone().into()),
            })
            .await?
        };
        let network_id = if let Some(ni) = network_id {
            ni
        } else {
            self.net_version().await?
        };
        // this is an edge case where we are about to send a transaction that can't possibly
        // be valid, we simply don't have the the funds to pay the full gas amount we are promising
        // in this case we reduce the gas price to exactly what we can afford.
        if gas_price.clone() * gas_limit.clone() > our_balance {
            gas_price = our_balance / gas_limit.clone();
        }
        let transaction = Transaction {
            to: to_address,
            nonce,
            gas_price,
            gas_limit,
            value,
            data,
            signature: None,
        };
        let transaction = transaction.sign(&secret, Some(network_id));
        self.eth_send_raw_transaction(
            transaction
                .to_bytes()
                .expect("transaction.to_bytes() failed"),
        )
        .await
    }
pub async fn send_transaction ( & self , to_address : Address , data : Vec < u8 > , value : Uint256 , own_address : Address , secret : PrivateKey , options : Vec < SendTxOption > , ) -> Result < Uint256 , Web3Error > { let mut gas_price = None ; let mut gas_price_multiplier = 1u64 . into ( ) ; let mut gas_limit = None ; let mut network_id = None ; let our_balance = self . eth_get_balance ( own_address ) . await ? ; let mut nonce = self . eth_get_transaction_count ( own_address ) . await ? ; for option in options { match option { SendTxOption :: GasPrice ( gp ) => gas_price = Some ( gp ) , SendTxOption :: GasPriceMultiplier ( gpm ) => gas_price_multiplier = gpm , SendTxOption :: GasLimit ( gl ) => gas_limit = Some ( gl ) , SendTxOption :: NetworkId ( ni ) => network_id = Some ( ni ) , SendTxOption :: Nonce ( n ) => nonce = n , } } let mut gas_price = if let Some ( gp ) = gas_price { gp } else { self . eth_gas_price ( ) . await ? * gas_price_multiplier } ; let gas_limit = if let Some ( gl ) = gas_limit { gl } else { // Geth and parity behave differently for the Estimate gas call // Parity / OpenEthereum will allow you to specify no gas price // and no gas amount the estimate gas call will then return the // amount of gas the transaction would take. This is reasonable behavior // from an endpoint that's supposed to let you estimate gas usage // // The gas price is of course irrelevant unless someone goes out of their // way to design a contract that fails a low gas prices. Geth and Parity // can't simulate an actual transaction market accurately. // // Geth on the other hand insists that you provide a gas price (any price) // and a gas value. Otherwise it will not provide an estimate. // // If this value is too low Geth will fail, if this value is higher than // your balance Geth will once again fail. So Geth at this juncture won't // tell you what the transaction would cost, just that you can't afford it. // // So if yes you could set these values to none if making a parity request let gas_price : Uint256 = 1u8 . into ( ) ; // Geth represents gas as a u64 it will truncate leading zeros but not take // a value larger than u64::MAX, likewise the command will fail if we can't // actually pay that fee. This operation maximizes the info we can get let gas_limit = min ( ( u64 :: MAX - 1 ) . into ( ) , our_balance . clone ( ) ) ; self . eth_estimate_gas ( TransactionRequest { from : Some ( own_address ) , to : to_address , nonce : Some ( nonce . clone ( ) . into ( ) ) , gas_price : Some ( gas_price . into ( ) ) , gas : Some ( gas_limit . into ( ) ) , value : Some ( value . clone ( ) . into ( ) ) , data : Some ( data . clone ( ) . into ( ) ) , } ) . await ? } ; let network_id = if let Some ( ni ) = network_id { ni } else { self . net_version ( ) . await ? } ; // this is an edge case where we are about to send a transaction that can't possibly // be valid, we simply don't have the the funds to pay the full gas amount we are promising // in this case we reduce the gas price to exactly what we can afford. if gas_price . clone ( ) * gas_limit . clone ( ) > our_balance { gas_price = our_balance / gas_limit . clone ( ) ; } let transaction = Transaction { to : to_address , nonce , gas_price , gas_limit , value , data , signature : None , } ; let transaction = transaction . sign ( & secret , Some ( network_id ) ) ; self . eth_send_raw_transaction ( transaction . to_bytes ( ) . expect ( " " ) , ) . await }
Sends a transaction which changes blockchain state.
Sends a transaction which changes blockchain state .
&self
to_address
Address
data
Vec<u8>
value
Uint256
own_address
Address
secret
PrivateKey
options
Vec<SendTxOption>