|
| 1 | +use { |
| 2 | + crate::chain::ethereum::{InstrumentedSignablePythContract, PythContractCall}, |
| 3 | + anyhow::{anyhow, Result}, |
| 4 | + ethers::middleware::Middleware, |
| 5 | + std::sync::Arc, |
| 6 | + tracing, |
| 7 | +}; |
| 8 | + |
| 9 | +pub async fn send_and_confirm(contract_call: PythContractCall) -> Result<()> { |
| 10 | + let call_name = contract_call.function.name.as_str(); |
| 11 | + let pending_tx = contract_call |
| 12 | + .send() |
| 13 | + .await |
| 14 | + .map_err(|e| anyhow!("Error submitting transaction({}) {:?}", call_name, e))?; |
| 15 | + |
| 16 | + let tx_result = pending_tx |
| 17 | + .await |
| 18 | + .map_err(|e| { |
| 19 | + anyhow!( |
| 20 | + "Error waiting for transaction({}) receipt: {:?}", |
| 21 | + call_name, |
| 22 | + e |
| 23 | + ) |
| 24 | + })? |
| 25 | + .ok_or_else(|| { |
| 26 | + anyhow!( |
| 27 | + "Can't verify the transaction({}), probably dropped from mempool", |
| 28 | + call_name |
| 29 | + ) |
| 30 | + })?; |
| 31 | + |
| 32 | + tracing::info!( |
| 33 | + transaction_hash = &tx_result.transaction_hash.to_string(), |
| 34 | + "Confirmed transaction({}). Receipt: {:?}", |
| 35 | + call_name, |
| 36 | + tx_result, |
| 37 | + ); |
| 38 | + Ok(()) |
| 39 | +} |
| 40 | + |
| 41 | +/// Estimate the cost (in wei) of a transaction consuming gas_used gas. |
| 42 | +pub async fn estimate_tx_cost( |
| 43 | + contract: Arc<InstrumentedSignablePythContract>, |
| 44 | + use_legacy_tx: bool, |
| 45 | + gas_used: u128, |
| 46 | +) -> Result<u128> { |
| 47 | + let middleware = contract.client(); |
| 48 | + |
| 49 | + let gas_price: u128 = if use_legacy_tx { |
| 50 | + middleware |
| 51 | + .get_gas_price() |
| 52 | + .await |
| 53 | + .map_err(|e| anyhow!("Failed to fetch gas price. error: {:?}", e))? |
| 54 | + .try_into() |
| 55 | + .map_err(|e| anyhow!("gas price doesn't fit into 128 bits. error: {:?}", e))? |
| 56 | + } else { |
| 57 | + // This is not obvious but the implementation of estimate_eip1559_fees in ethers.rs |
| 58 | + // for a middleware that has a GasOracleMiddleware inside is to ignore the passed-in callback |
| 59 | + // and use whatever the gas oracle returns. |
| 60 | + let (max_fee_per_gas, max_priority_fee_per_gas) = |
| 61 | + middleware.estimate_eip1559_fees(None).await?; |
| 62 | + |
| 63 | + (max_fee_per_gas + max_priority_fee_per_gas) |
| 64 | + .try_into() |
| 65 | + .map_err(|e| anyhow!("gas price doesn't fit into 128 bits. error: {:?}", e))? |
| 66 | + }; |
| 67 | + |
| 68 | + Ok(gas_price * gas_used) |
| 69 | +} |
0 commit comments