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

fix: add check for failed transactions #52

Merged
merged 3 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
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
43 changes: 42 additions & 1 deletion bot/src/bot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ use starknet_id::encode;
use tokio::time::{sleep, Duration as TokioDuration};

use crate::logger::Logger;
use crate::models::TxResult;
use crate::models::{
AggregateResult, AggregateResults, DomainAggregateResult, MetadataDoc, Unzip5,
};
use crate::starknet_utils::check_pending_transactions;
use crate::starknet_utils::create_jsonrpc_client;
use crate::starknetid_utils::get_renewal_price;
use crate::utils::{from_uint256, hex_to_bigdecimal, to_uint256};
Expand Down Expand Up @@ -383,6 +385,8 @@ pub async fn renew_domains(
aggregate_results.domains.len()
));
let mut nonce = account.get_nonce().await.unwrap();
let mut tx_results = Vec::<TxResult>::new();

// If we have: i32 more than 75 domains to renew we make multiple transactions to avoid hitting the 3M steps limit
while !aggregate_results.domains.is_empty()
&& !aggregate_results.renewers.is_empty()
Expand Down Expand Up @@ -420,6 +424,13 @@ pub async fn renew_domains(
domains_to_renew.len(),
nonce,
));
tx_results.push(TxResult {
tx_hash,
reverted: None,
revert_reason: None,
domains_renewed: domains_to_renew.len(),
});

// We only inscrease nonce if no error occurred in the previous transaction
nonce += FieldElement::ONE;
}
Expand All @@ -434,12 +445,42 @@ pub async fn renew_domains(
} else {
logger.severe(format!(
"Error while renewing domains: {:?} for domains: {:?}",
e, domains_to_renew
e,
domains_to_renew.len()
));
return Err(e);
}
}
}

check_pending_transactions(config, &mut tx_results).await;

let filtered_results: Vec<&TxResult> = tx_results
.iter()
.filter(|tx| tx.reverted.is_some())
.collect();

let failed_count = filtered_results
.iter()
.rev()
.take(3)
.filter(|tx| tx.reverted == Some(true))
.count();

// If 3 transactions have failed, we stop the process
if failed_count == 3 {
logger.severe("The last 3 transactions have failed. Stopping process.");
logger.info(format!("Sent {:?} transactions", tx_results.len()));
filtered_results.iter().rev().take(3).for_each(|failure| {
logger.severe(format!(
"Transaction 0x{:x} with {:?} domains has failed with reason: {:?}",
failure.tx_hash, failure.domains_renewed, failure.revert_reason
));
});
logger.severe("Stopping process.");
break;
}

println!("Waiting for 1 minute before sending the next transaction...");
sleep(TokioDuration::from_secs(60)).await;
}
Expand Down
10 changes: 9 additions & 1 deletion bot/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bigdecimal::BigDecimal;
use bson::DateTime;
use mongodb::Database;
use serde::{Deserialize, Serialize};
use starknet::core::types::FieldElement;
use starknet::core::types::{FieldElement, TransactionExecutionStatus};

pub struct AppState {
pub db: Database,
Expand Down Expand Up @@ -90,6 +90,14 @@ pub struct States {
pub states: HashMap<String, State>,
}

#[derive(Debug, Clone)]
pub struct TxResult {
pub tx_hash: FieldElement,
pub reverted: Option<bool>,
pub revert_reason: Option<String>,
pub domains_renewed: usize,
}

pub trait Unzip5 {
type A;
type B;
Expand Down
60 changes: 58 additions & 2 deletions bot/src/starknet_utils.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,63 @@
use crate::config::Config;
use starknet::providers::{jsonrpc::HttpTransport, JsonRpcClient};
use crate::{config::Config, models::TxResult};
use starknet::{
core::types::{
MaybePendingTransactionReceipt, PendingTransactionReceipt, TransactionExecutionStatus,
TransactionReceipt,
},
providers::{jsonrpc::HttpTransport, JsonRpcClient, Provider},
};
use url::Url;

pub fn create_jsonrpc_client(conf: &Config) -> JsonRpcClient<HttpTransport> {
JsonRpcClient::new(HttpTransport::new(Url::parse(&conf.rpc.rpc_url).unwrap()))
}

pub async fn check_pending_transactions(conf: &Config, tx_results: &mut Vec<TxResult>) {
let client = create_jsonrpc_client(conf);
for tx_result in tx_results.iter_mut() {
if tx_result.reverted.is_none() {
match client.get_transaction_receipt(tx_result.tx_hash).await {
Ok(receipt) => match receipt {
MaybePendingTransactionReceipt::PendingReceipt(pending_receipt) => {
if let PendingTransactionReceipt::Invoke(invocation) = pending_receipt {
match invocation.execution_result.status() {
TransactionExecutionStatus::Succeeded => {
tx_result.reverted = Some(false);
}
TransactionExecutionStatus::Reverted => {
tx_result.reverted = Some(true);
tx_result.revert_reason = invocation
.execution_result
.revert_reason()
.map(|s| s.to_owned());
}
}
}
}
MaybePendingTransactionReceipt::Receipt(receipt) => {
if let TransactionReceipt::Invoke(invocation) = receipt {
match invocation.execution_result.status() {
TransactionExecutionStatus::Succeeded => {
tx_result.reverted = Some(false);
}
TransactionExecutionStatus::Reverted => {
tx_result.reverted = Some(true);
tx_result.revert_reason = invocation
.execution_result
.revert_reason()
.map(|s| s.to_owned());
}
}
}
}
},
Err(e) => {
eprintln!(
"Error checking status for tx_hash {}: {}",
tx_result.tx_hash, e
);
}
}
}
}
}
Loading