2023-02-15 08:08:55 -08:00
|
|
|
use std::{
|
2023-03-14 05:39:19 -07:00
|
|
|
sync::{
|
|
|
|
atomic::{AtomicBool, Ordering},
|
|
|
|
Arc,
|
|
|
|
},
|
2023-02-15 08:08:55 -08:00
|
|
|
time::Duration,
|
|
|
|
};
|
|
|
|
|
|
|
|
use chrono::Utc;
|
2023-03-14 05:39:19 -07:00
|
|
|
use dashmap::DashMap;
|
2023-03-15 08:13:25 -07:00
|
|
|
use log::{debug, warn};
|
2023-03-14 05:39:19 -07:00
|
|
|
use solana_client::{nonblocking::rpc_client::RpcClient, rpc_config::RpcBlockConfig};
|
2023-06-15 01:41:58 -07:00
|
|
|
use solana_lite_rpc_core::notifications::NotificationMsg;
|
2023-02-15 08:08:55 -08:00
|
|
|
use solana_sdk::{
|
|
|
|
commitment_config::{CommitmentConfig, CommitmentLevel},
|
|
|
|
signature::Signature,
|
2023-04-08 09:40:28 -07:00
|
|
|
slot_history::Slot,
|
2023-02-15 08:08:55 -08:00
|
|
|
};
|
2023-03-15 08:13:25 -07:00
|
|
|
use solana_transaction_status::{
|
|
|
|
RewardType, TransactionDetails, UiConfirmedBlock, UiTransactionEncoding,
|
|
|
|
};
|
2023-02-15 08:08:55 -08:00
|
|
|
|
2023-03-14 05:39:19 -07:00
|
|
|
use crate::states::{BlockData, TransactionConfirmRecord, TransactionSendRecord};
|
|
|
|
|
2023-04-06 07:52:14 -07:00
|
|
|
use tokio::{
|
|
|
|
sync::broadcast::Sender, sync::mpsc::UnboundedReceiver, task::JoinHandle, time::Instant,
|
|
|
|
};
|
2023-02-15 08:08:55 -08:00
|
|
|
|
2023-03-14 05:39:19 -07:00
|
|
|
pub async fn process_blocks(
|
2023-03-15 08:13:25 -07:00
|
|
|
block: &UiConfirmedBlock,
|
2023-03-14 05:39:19 -07:00
|
|
|
tx_confirm_records: Sender<TransactionConfirmRecord>,
|
|
|
|
tx_block_data: Sender<BlockData>,
|
|
|
|
transaction_map: Arc<DashMap<Signature, (TransactionSendRecord, Instant)>>,
|
|
|
|
slot: u64,
|
2023-06-29 04:49:19 -07:00
|
|
|
commitment: CommitmentLevel,
|
2023-02-15 08:08:55 -08:00
|
|
|
) {
|
2023-03-14 05:39:19 -07:00
|
|
|
let mut mm_transaction_count: u64 = 0;
|
2023-03-15 08:13:25 -07:00
|
|
|
let rewards = block.rewards.as_ref().unwrap();
|
2023-03-14 05:39:19 -07:00
|
|
|
let slot_leader = match rewards
|
|
|
|
.iter()
|
|
|
|
.find(|r| r.reward_type == Some(RewardType::Fee))
|
2023-02-15 08:08:55 -08:00
|
|
|
{
|
2023-03-14 05:39:19 -07:00
|
|
|
Some(x) => x.pubkey.clone(),
|
|
|
|
None => "".to_string(),
|
|
|
|
};
|
|
|
|
|
2023-03-15 08:13:25 -07:00
|
|
|
if let Some(transactions) = &block.transactions {
|
2023-03-14 05:39:19 -07:00
|
|
|
let nb_transactions = transactions.len();
|
|
|
|
let mut cu_consumed: u64 = 0;
|
|
|
|
for solana_transaction_status::EncodedTransactionWithStatusMeta {
|
|
|
|
transaction, meta, ..
|
|
|
|
} in transactions
|
|
|
|
{
|
2023-03-15 08:13:25 -07:00
|
|
|
let transaction = match transaction.decode() {
|
|
|
|
Some(tx) => tx,
|
|
|
|
None => {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
for signature in &transaction.signatures {
|
|
|
|
let transaction_record_op = {
|
|
|
|
let rec = transaction_map.get(&signature);
|
|
|
|
match rec {
|
|
|
|
Some(x) => Some(x.clone()),
|
|
|
|
None => None,
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// add CU in counter
|
|
|
|
if let Some(meta) = &meta {
|
|
|
|
match meta.compute_units_consumed {
|
|
|
|
solana_transaction_status::option_serializer::OptionSerializer::Some(x) => {
|
|
|
|
cu_consumed = cu_consumed.saturating_add(x);
|
2023-02-15 08:08:55 -08:00
|
|
|
}
|
2023-03-15 08:13:25 -07:00
|
|
|
_ => {}
|
2023-02-15 08:08:55 -08:00
|
|
|
}
|
2023-03-15 08:13:25 -07:00
|
|
|
}
|
|
|
|
if let Some(transaction_record) = transaction_record_op {
|
|
|
|
let transaction_record = transaction_record.0;
|
|
|
|
mm_transaction_count += 1;
|
2023-03-14 05:39:19 -07:00
|
|
|
|
2023-04-06 07:52:14 -07:00
|
|
|
match tx_confirm_records.send(TransactionConfirmRecord {
|
|
|
|
signature: transaction_record.signature.to_string(),
|
|
|
|
confirmed_slot: Some(slot),
|
|
|
|
confirmed_at: Some(Utc::now().to_string()),
|
|
|
|
sent_at: transaction_record.sent_at.to_string(),
|
|
|
|
sent_slot: transaction_record.sent_slot,
|
|
|
|
successful: if let Some(meta) = &meta {
|
|
|
|
meta.status.is_ok()
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
},
|
|
|
|
error: if let Some(meta) = &meta {
|
|
|
|
meta.err.as_ref().map(|x| x.to_string())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
},
|
|
|
|
block_hash: Some(block.blockhash.clone()),
|
|
|
|
market: transaction_record.market.map(|x| x.to_string()),
|
|
|
|
market_maker: transaction_record.market_maker.map(|x| x.to_string()),
|
|
|
|
keeper_instruction: transaction_record.keeper_instruction,
|
|
|
|
slot_processed: Some(slot),
|
|
|
|
slot_leader: Some(slot_leader.clone()),
|
|
|
|
timed_out: false,
|
|
|
|
priority_fees: transaction_record.priority_fees,
|
|
|
|
}) {
|
2023-03-15 08:13:25 -07:00
|
|
|
Ok(_) => {}
|
|
|
|
Err(e) => {
|
|
|
|
warn!("Tx confirm record channel broken {}", e.to_string());
|
|
|
|
}
|
2023-03-14 05:39:19 -07:00
|
|
|
}
|
2023-02-15 08:08:55 -08:00
|
|
|
}
|
2023-03-15 08:13:25 -07:00
|
|
|
|
|
|
|
transaction_map.remove(&signature);
|
2023-02-15 08:08:55 -08:00
|
|
|
}
|
|
|
|
}
|
2023-03-14 05:39:19 -07:00
|
|
|
// push block data
|
|
|
|
{
|
|
|
|
let _ = tx_block_data.send(BlockData {
|
2023-03-15 08:13:25 -07:00
|
|
|
block_hash: block.blockhash.clone(),
|
2023-03-14 05:39:19 -07:00
|
|
|
block_leader: slot_leader,
|
|
|
|
block_slot: slot,
|
|
|
|
block_time: if let Some(time) = block.block_time {
|
|
|
|
time as u64
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
},
|
2023-06-29 04:49:19 -07:00
|
|
|
number_of_mango_simulation_txs: mm_transaction_count,
|
2023-03-14 05:39:19 -07:00
|
|
|
total_transactions: nb_transactions as u64,
|
2023-06-29 04:49:19 -07:00
|
|
|
cu_consumed: 0,
|
|
|
|
cu_consumed_by_mango_simulations: cu_consumed,
|
|
|
|
commitment,
|
2023-03-14 05:39:19 -07:00
|
|
|
});
|
2023-02-15 08:08:55 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-08 09:40:28 -07:00
|
|
|
async fn get_blocks_with_retry(
|
|
|
|
client: Arc<RpcClient>,
|
|
|
|
start_block: u64,
|
|
|
|
commitment_confirmation: CommitmentConfig,
|
|
|
|
) -> Result<Vec<Slot>, ()> {
|
|
|
|
const N_TRY_REQUEST_BLOCKS: u64 = 4;
|
|
|
|
for _ in 0..N_TRY_REQUEST_BLOCKS {
|
2023-04-15 03:17:15 -07:00
|
|
|
let block_slots = client
|
|
|
|
.get_blocks_with_commitment(start_block, None, commitment_confirmation)
|
2023-04-08 09:40:28 -07:00
|
|
|
.await;
|
|
|
|
|
|
|
|
match block_slots {
|
|
|
|
Ok(slots) => {
|
|
|
|
return Ok(slots);
|
2023-04-15 03:17:15 -07:00
|
|
|
}
|
2023-04-08 09:40:28 -07:00
|
|
|
Err(error) => {
|
|
|
|
warn!("Failed to download blocks: {}, retry", error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
|
2023-06-15 01:41:58 -07:00
|
|
|
pub fn confirmation_by_lite_rpc_notification_stream(
|
|
|
|
tx_record_rx: UnboundedReceiver<TransactionSendRecord>,
|
|
|
|
notification_stream: UnboundedReceiver<NotificationMsg>,
|
|
|
|
tx_confirm_records: tokio::sync::broadcast::Sender<TransactionConfirmRecord>,
|
|
|
|
tx_block_data: tokio::sync::broadcast::Sender<BlockData>,
|
|
|
|
exit_signal: Arc<AtomicBool>,
|
|
|
|
) -> Vec<JoinHandle<()>> {
|
2023-06-23 06:30:02 -07:00
|
|
|
let transaction_map: Arc<DashMap<String, (TransactionSendRecord, Instant)>> =
|
|
|
|
Arc::new(DashMap::new());
|
2023-06-15 01:41:58 -07:00
|
|
|
|
|
|
|
let confirming_task = {
|
|
|
|
let transaction_map = transaction_map.clone();
|
|
|
|
let tx_confirm_records = tx_confirm_records.clone();
|
2023-06-15 03:00:37 -07:00
|
|
|
let exit_signal = exit_signal.clone();
|
2023-06-15 01:41:58 -07:00
|
|
|
tokio::spawn(async move {
|
|
|
|
let mut tx_record_rx = tx_record_rx;
|
|
|
|
let mut notification_stream = notification_stream;
|
2023-06-23 06:30:02 -07:00
|
|
|
|
2023-06-15 03:00:37 -07:00
|
|
|
while !transaction_map.is_empty() || !exit_signal.load(Ordering::Relaxed) {
|
2023-06-15 01:41:58 -07:00
|
|
|
tokio::select! {
|
|
|
|
transaction_record = tx_record_rx.recv() => {
|
|
|
|
if let Some(transaction_record) = transaction_record{
|
|
|
|
transaction_map
|
|
|
|
.insert(transaction_record.signature.to_string(), (transaction_record, Instant::now()));
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
notification = notification_stream.recv() => {
|
|
|
|
if let Some(notification) = notification {
|
2023-06-23 06:30:02 -07:00
|
|
|
|
2023-06-15 01:41:58 -07:00
|
|
|
match notification {
|
|
|
|
NotificationMsg::BlockNotificationMsg(block_notification) => {
|
2023-06-27 01:44:59 -07:00
|
|
|
if block_notification.commitment != CommitmentLevel::Finalized {
|
|
|
|
continue;
|
|
|
|
}
|
2023-06-15 01:41:58 -07:00
|
|
|
let _ = tx_block_data.send(BlockData {
|
|
|
|
block_hash: block_notification.blockhash.to_string(),
|
|
|
|
block_leader: block_notification.block_leader,
|
|
|
|
block_slot: block_notification.slot,
|
|
|
|
block_time: block_notification.block_time,
|
2023-06-29 04:49:19 -07:00
|
|
|
number_of_mango_simulation_txs: block_notification.transaction_found,
|
2023-06-15 01:41:58 -07:00
|
|
|
total_transactions: block_notification.total_transactions,
|
2023-06-26 05:56:29 -07:00
|
|
|
cu_consumed: block_notification.total_cu_consumed,
|
2023-06-29 04:49:19 -07:00
|
|
|
cu_consumed_by_mango_simulations: block_notification.cu_consumed_by_txs,
|
|
|
|
commitment: block_notification.commitment,
|
2023-06-15 01:41:58 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
NotificationMsg::UpdateTransactionMsg(tx_update_notifications) => {
|
|
|
|
|
|
|
|
for tx_notification in tx_update_notifications {
|
2023-06-27 01:44:59 -07:00
|
|
|
if tx_notification.commitment != CommitmentLevel::Finalized {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-06-15 01:41:58 -07:00
|
|
|
if let Some(value) = transaction_map.get(&tx_notification.signature) {
|
|
|
|
let (tx_sent_record, _) = value.clone();
|
|
|
|
let error = match &tx_notification.transaction_status {
|
|
|
|
Err(e) => {
|
|
|
|
Some(e.to_string())
|
|
|
|
},
|
|
|
|
_ => None
|
|
|
|
};
|
|
|
|
let _ = tx_confirm_records.send(TransactionConfirmRecord {
|
2023-06-20 06:19:18 -07:00
|
|
|
signature: tx_notification.signature.clone(),
|
2023-06-15 01:41:58 -07:00
|
|
|
confirmed_slot: Some(tx_notification.slot),
|
|
|
|
confirmed_at: Some(Utc::now().to_string()),
|
|
|
|
sent_at: tx_sent_record.sent_at.to_string(),
|
|
|
|
sent_slot: tx_sent_record.sent_slot,
|
|
|
|
successful: tx_notification.transaction_status.is_ok(),
|
|
|
|
error,
|
|
|
|
block_hash: Some(tx_notification.blockhash),
|
|
|
|
market: tx_sent_record.market.map(|x| x.to_string()),
|
|
|
|
market_maker: tx_sent_record.market_maker.map(|x| x.to_string()),
|
|
|
|
keeper_instruction: tx_sent_record.keeper_instruction.clone(),
|
|
|
|
slot_processed: Some(tx_notification.slot),
|
|
|
|
slot_leader: Some(tx_notification.leader.to_string()),
|
|
|
|
timed_out: false,
|
|
|
|
priority_fees: tx_sent_record.priority_fees,
|
|
|
|
});
|
|
|
|
}
|
2023-06-20 06:19:18 -07:00
|
|
|
|
|
|
|
transaction_map.remove(&tx_notification.signature);
|
2023-06-15 01:41:58 -07:00
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => {
|
|
|
|
// others do nothing
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_ = tokio::time::sleep(Duration::from_secs(1)) => {
|
|
|
|
// timeout
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-06-15 03:00:37 -07:00
|
|
|
log::info!("stopped processing the transactions");
|
2023-06-15 01:41:58 -07:00
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
let cleaner_jh = {
|
|
|
|
let transaction_map = transaction_map.clone();
|
|
|
|
let exit_signal = exit_signal.clone();
|
|
|
|
let tx_confirm_records = tx_confirm_records.clone();
|
|
|
|
tokio::spawn(async move {
|
|
|
|
loop {
|
|
|
|
tokio::time::sleep(Duration::from_secs(60)).await;
|
|
|
|
{
|
|
|
|
let mut to_remove = vec![];
|
|
|
|
|
|
|
|
for tx_data in transaction_map.iter() {
|
|
|
|
let sent_record = &tx_data.0;
|
|
|
|
let instant = tx_data.1;
|
|
|
|
let signature = tx_data.key();
|
|
|
|
let remove = instant.elapsed() > Duration::from_secs(120);
|
|
|
|
|
|
|
|
// add to timeout if not retaining
|
|
|
|
if remove {
|
|
|
|
let _ = tx_confirm_records.send(TransactionConfirmRecord {
|
|
|
|
signature: signature.to_string(),
|
|
|
|
confirmed_slot: None,
|
|
|
|
confirmed_at: None,
|
|
|
|
sent_at: sent_record.sent_at.to_string(),
|
|
|
|
sent_slot: sent_record.sent_slot,
|
|
|
|
successful: false,
|
|
|
|
error: Some("timeout".to_string()),
|
|
|
|
block_hash: None,
|
|
|
|
market: sent_record.market.map(|x| x.to_string()),
|
|
|
|
market_maker: sent_record.market_maker.map(|x| x.to_string()),
|
|
|
|
keeper_instruction: sent_record.keeper_instruction.clone(),
|
|
|
|
slot_processed: None,
|
|
|
|
slot_leader: None,
|
|
|
|
timed_out: true,
|
|
|
|
priority_fees: sent_record.priority_fees,
|
|
|
|
});
|
|
|
|
to_remove.push(signature.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for signature in to_remove {
|
|
|
|
transaction_map.remove(&signature);
|
|
|
|
}
|
|
|
|
|
|
|
|
// if exit and all the transactions are processed
|
2023-06-15 03:00:37 -07:00
|
|
|
if exit_signal.load(Ordering::Relaxed) && transaction_map.is_empty() {
|
2023-06-15 01:41:58 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
};
|
|
|
|
vec![confirming_task, cleaner_jh]
|
|
|
|
}
|
|
|
|
|
2023-06-29 04:49:19 -07:00
|
|
|
#[deprecated]
|
2023-03-14 05:39:19 -07:00
|
|
|
pub fn confirmations_by_blocks(
|
|
|
|
client: Arc<RpcClient>,
|
|
|
|
mut tx_record_rx: UnboundedReceiver<TransactionSendRecord>,
|
2023-03-16 08:25:26 -07:00
|
|
|
tx_confirm_records: tokio::sync::broadcast::Sender<TransactionConfirmRecord>,
|
|
|
|
tx_block_data: tokio::sync::broadcast::Sender<BlockData>,
|
2023-03-14 05:39:19 -07:00
|
|
|
from_slot: u64,
|
2023-03-15 08:13:25 -07:00
|
|
|
exit_signal: Arc<AtomicBool>,
|
2023-03-14 05:39:19 -07:00
|
|
|
) -> Vec<JoinHandle<()>> {
|
|
|
|
let transaction_map = Arc::new(DashMap::new());
|
2023-02-15 08:08:55 -08:00
|
|
|
|
2023-03-14 05:39:19 -07:00
|
|
|
let map_filler_jh = {
|
|
|
|
let transaction_map = transaction_map.clone();
|
2023-03-15 08:13:25 -07:00
|
|
|
let exit_signal = exit_signal.clone();
|
2023-03-14 05:39:19 -07:00
|
|
|
tokio::spawn(async move {
|
2023-02-15 08:08:55 -08:00
|
|
|
loop {
|
2023-03-15 08:13:25 -07:00
|
|
|
match tokio::time::timeout(tokio::time::Duration::from_secs(1), tx_record_rx.recv())
|
|
|
|
.await
|
|
|
|
{
|
|
|
|
Ok(tx_record) => match tx_record {
|
|
|
|
Some(tx_record) => {
|
|
|
|
debug!(
|
|
|
|
"add to queue len={} sig={}",
|
|
|
|
transaction_map.len() + 1,
|
|
|
|
tx_record.signature
|
|
|
|
);
|
|
|
|
transaction_map
|
|
|
|
.insert(tx_record.signature, (tx_record, Instant::now()));
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
exit_signal.store(true, Ordering::Relaxed);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(_) => {
|
|
|
|
// on timeout just check if services are being stopped
|
|
|
|
if exit_signal.load(Ordering::Relaxed) {
|
|
|
|
break;
|
|
|
|
}
|
2023-02-15 08:08:55 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-03-14 05:39:19 -07:00
|
|
|
})
|
2023-02-15 08:08:55 -08:00
|
|
|
};
|
|
|
|
|
2023-03-14 05:39:19 -07:00
|
|
|
let cleaner_jh = {
|
|
|
|
let transaction_map = transaction_map.clone();
|
2023-03-15 08:13:25 -07:00
|
|
|
let exit_signal = exit_signal.clone();
|
2023-02-15 08:08:55 -08:00
|
|
|
let tx_confirm_records = tx_confirm_records.clone();
|
2023-03-14 05:39:19 -07:00
|
|
|
tokio::spawn(async move {
|
|
|
|
loop {
|
|
|
|
tokio::time::sleep(Duration::from_secs(60)).await;
|
|
|
|
{
|
2023-03-15 08:13:25 -07:00
|
|
|
let mut to_remove = vec![];
|
|
|
|
|
|
|
|
for tx_data in transaction_map.iter() {
|
|
|
|
let sent_record = &tx_data.0;
|
|
|
|
let instant = tx_data.1;
|
|
|
|
let signature = tx_data.key();
|
|
|
|
let remove = instant.elapsed() > Duration::from_secs(120);
|
2023-02-15 08:08:55 -08:00
|
|
|
|
2023-03-14 05:39:19 -07:00
|
|
|
// add to timeout if not retaining
|
2023-03-15 08:13:25 -07:00
|
|
|
if remove {
|
2023-04-06 07:52:14 -07:00
|
|
|
let _ = tx_confirm_records.send(TransactionConfirmRecord {
|
|
|
|
signature: signature.to_string(),
|
|
|
|
confirmed_slot: None,
|
|
|
|
confirmed_at: None,
|
|
|
|
sent_at: sent_record.sent_at.to_string(),
|
|
|
|
sent_slot: sent_record.sent_slot,
|
|
|
|
successful: false,
|
|
|
|
error: Some("timeout".to_string()),
|
|
|
|
block_hash: None,
|
|
|
|
market: sent_record.market.map(|x| x.to_string()),
|
|
|
|
market_maker: sent_record.market_maker.map(|x| x.to_string()),
|
|
|
|
keeper_instruction: sent_record.keeper_instruction.clone(),
|
|
|
|
slot_processed: None,
|
|
|
|
slot_leader: None,
|
|
|
|
timed_out: true,
|
|
|
|
priority_fees: sent_record.priority_fees,
|
|
|
|
});
|
2023-03-15 08:13:25 -07:00
|
|
|
to_remove.push(signature.clone());
|
2023-02-15 08:08:55 -08:00
|
|
|
}
|
2023-03-15 08:13:25 -07:00
|
|
|
}
|
2023-02-15 08:08:55 -08:00
|
|
|
|
2023-03-15 08:13:25 -07:00
|
|
|
for signature in to_remove {
|
|
|
|
transaction_map.remove(&signature);
|
|
|
|
}
|
2023-02-15 08:08:55 -08:00
|
|
|
|
2023-03-14 05:39:19 -07:00
|
|
|
// if exit and all the transactions are processed
|
2023-03-15 08:13:25 -07:00
|
|
|
if exit_signal.load(Ordering::Relaxed) && transaction_map.len() == 0 {
|
2023-03-14 05:39:19 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
};
|
2023-02-15 08:08:55 -08:00
|
|
|
|
2023-03-14 05:39:19 -07:00
|
|
|
let block_confirmation_jh = {
|
2023-03-15 08:13:25 -07:00
|
|
|
let exit_signal = exit_signal.clone();
|
2023-03-14 05:39:19 -07:00
|
|
|
tokio::spawn(async move {
|
|
|
|
let mut start_block = from_slot;
|
|
|
|
let mut start_instant = tokio::time::Instant::now();
|
|
|
|
let refresh_in = Duration::from_secs(10);
|
|
|
|
let commitment_confirmation = CommitmentConfig {
|
|
|
|
commitment: CommitmentLevel::Confirmed,
|
|
|
|
};
|
|
|
|
loop {
|
2023-03-15 08:13:25 -07:00
|
|
|
if exit_signal.load(Ordering::Relaxed) && transaction_map.len() == 0 {
|
2023-03-14 05:39:19 -07:00
|
|
|
break;
|
|
|
|
}
|
2023-02-15 08:08:55 -08:00
|
|
|
|
2023-03-14 05:39:19 -07:00
|
|
|
let wait_duration = tokio::time::Instant::now() - start_instant;
|
|
|
|
if wait_duration < refresh_in {
|
|
|
|
tokio::time::sleep(refresh_in - wait_duration).await;
|
2023-02-15 08:08:55 -08:00
|
|
|
}
|
2023-03-14 05:39:19 -07:00
|
|
|
start_instant = tokio::time::Instant::now();
|
2023-02-15 08:08:55 -08:00
|
|
|
|
2023-04-15 03:17:15 -07:00
|
|
|
let block_slots =
|
|
|
|
get_blocks_with_retry(client.clone(), start_block, commitment_confirmation)
|
|
|
|
.await;
|
2023-04-08 09:40:28 -07:00
|
|
|
if block_slots.is_err() {
|
|
|
|
break;
|
2023-04-08 08:08:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
let block_slots = block_slots.unwrap();
|
2023-03-14 05:39:19 -07:00
|
|
|
if block_slots.is_empty() {
|
|
|
|
continue;
|
|
|
|
}
|
2023-04-15 03:17:15 -07:00
|
|
|
start_block = *block_slots.last().unwrap() + 1;
|
2023-02-15 08:08:55 -08:00
|
|
|
|
2023-03-14 05:39:19 -07:00
|
|
|
let blocks = block_slots.iter().map(|slot| {
|
|
|
|
client.get_block_with_config(
|
|
|
|
*slot,
|
|
|
|
RpcBlockConfig {
|
2023-03-15 08:13:25 -07:00
|
|
|
encoding: Some(UiTransactionEncoding::Base64),
|
|
|
|
transaction_details: Some(TransactionDetails::Full),
|
|
|
|
rewards: Some(true),
|
2023-03-14 05:39:19 -07:00
|
|
|
commitment: Some(commitment_confirmation),
|
2023-03-15 08:13:25 -07:00
|
|
|
max_supported_transaction_version: Some(0),
|
2023-03-14 05:39:19 -07:00
|
|
|
},
|
|
|
|
)
|
|
|
|
});
|
|
|
|
let blocks = futures::future::join_all(blocks).await;
|
|
|
|
for block_slot in blocks.iter().zip(block_slots) {
|
|
|
|
let block = match block_slot.0 {
|
|
|
|
Ok(x) => x,
|
|
|
|
Err(_) => continue,
|
|
|
|
};
|
|
|
|
let tx_confirm_records = tx_confirm_records.clone();
|
|
|
|
let tx_block_data = tx_block_data.clone();
|
|
|
|
let transaction_map = transaction_map.clone();
|
|
|
|
process_blocks(
|
2023-03-15 08:13:25 -07:00
|
|
|
block,
|
2023-03-14 05:39:19 -07:00
|
|
|
tx_confirm_records,
|
|
|
|
tx_block_data,
|
|
|
|
transaction_map,
|
|
|
|
block_slot.1,
|
2023-06-29 04:49:19 -07:00
|
|
|
commitment_confirmation.commitment,
|
2023-03-14 05:39:19 -07:00
|
|
|
)
|
|
|
|
.await;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
};
|
|
|
|
vec![map_filler_jh, cleaner_jh, block_confirmation_jh]
|
2023-02-15 08:08:55 -08:00
|
|
|
}
|