2023-02-18 08:22:12 -08:00
|
|
|
use crate::{
|
|
|
|
account_write_filter::{self, AccountWriteRoute},
|
2023-03-10 04:38:11 -08:00
|
|
|
grpc_plugin_source::FilterConfig,
|
2023-02-18 08:22:12 -08:00
|
|
|
mango::GroupConfig,
|
|
|
|
mango_v3_perp_crank_sink::MangoV3PerpCrankSink,
|
2023-03-09 07:20:49 -08:00
|
|
|
metrics,
|
|
|
|
states::TransactionSendRecord,
|
2023-03-10 04:38:11 -08:00
|
|
|
websocket_source::{self, KeeperConfig},
|
2023-02-18 08:22:12 -08:00
|
|
|
};
|
2023-03-14 05:39:19 -07:00
|
|
|
use async_channel::unbounded;
|
2023-03-09 07:08:03 -08:00
|
|
|
use log::*;
|
2023-03-09 07:20:49 -08:00
|
|
|
use solana_client::tpu_client::TpuClient;
|
|
|
|
use solana_quic_client::{QuicConfig, QuicConnectionManager, QuicPool};
|
|
|
|
use solana_sdk::{
|
|
|
|
hash::Hash, instruction::Instruction, pubkey::Pubkey, signature::Keypair, signer::Signer,
|
|
|
|
transaction::Transaction,
|
|
|
|
};
|
2023-03-14 05:39:19 -07:00
|
|
|
use std::{
|
|
|
|
str::FromStr,
|
|
|
|
sync::{
|
|
|
|
atomic::{AtomicBool, AtomicU64, Ordering},
|
|
|
|
Arc,
|
|
|
|
},
|
|
|
|
time::Duration,
|
|
|
|
};
|
|
|
|
use tokio::sync::{mpsc::UnboundedSender, RwLock};
|
2023-02-18 08:22:12 -08:00
|
|
|
|
2023-03-06 00:37:42 -08:00
|
|
|
pub fn start(
|
2023-03-10 04:38:11 -08:00
|
|
|
config: KeeperConfig,
|
2023-03-06 00:37:42 -08:00
|
|
|
exit_signal: Arc<AtomicBool>,
|
|
|
|
blockhash: Arc<RwLock<Hash>>,
|
2023-03-06 02:05:25 -08:00
|
|
|
tpu_client: Arc<TpuClient<QuicPool, QuicConnectionManager, QuicConfig>>,
|
2023-03-06 00:37:42 -08:00
|
|
|
group: &GroupConfig,
|
|
|
|
identity: &Keypair,
|
|
|
|
) {
|
2023-02-18 08:22:12 -08:00
|
|
|
let perp_queue_pks: Vec<_> = group
|
|
|
|
.perp_markets
|
|
|
|
.iter()
|
|
|
|
.map(|m| {
|
|
|
|
(
|
|
|
|
Pubkey::from_str(&m.public_key).unwrap(),
|
|
|
|
Pubkey::from_str(&m.events_key).unwrap(),
|
|
|
|
)
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
let group_pk = Pubkey::from_str(&group.public_key).unwrap();
|
2023-03-06 00:37:42 -08:00
|
|
|
let cache_pk = Pubkey::from_str(&group.cache_key).unwrap();
|
2023-02-18 08:22:12 -08:00
|
|
|
let mango_program_id = Pubkey::from_str(&group.mango_program_id).unwrap();
|
|
|
|
let filter_config = FilterConfig {
|
2023-03-06 00:37:42 -08:00
|
|
|
program_ids: vec![group.mango_program_id.clone()],
|
2023-03-09 07:20:49 -08:00
|
|
|
account_ids: group
|
|
|
|
.perp_markets
|
|
|
|
.iter()
|
|
|
|
.map(|m| m.events_key.clone())
|
|
|
|
.collect(),
|
2023-02-18 08:22:12 -08:00
|
|
|
};
|
|
|
|
|
2023-03-06 00:37:42 -08:00
|
|
|
let (instruction_sender, instruction_receiver) = unbounded::<Vec<Instruction>>();
|
|
|
|
let identity = Keypair::from_bytes(identity.to_bytes().as_slice()).unwrap();
|
2023-03-14 05:39:19 -07:00
|
|
|
tokio::spawn(async move {
|
|
|
|
info!(
|
|
|
|
"crank-tx-sender signing with keypair pk={:?}",
|
|
|
|
identity.pubkey()
|
|
|
|
);
|
|
|
|
loop {
|
|
|
|
if exit_signal.load(Ordering::Acquire) {
|
|
|
|
break;
|
|
|
|
}
|
2023-03-09 07:20:49 -08:00
|
|
|
|
2023-03-14 05:39:19 -07:00
|
|
|
if let Ok(ixs) = instruction_receiver.recv().await {
|
|
|
|
// TODO add priority fee
|
2023-03-09 07:20:49 -08:00
|
|
|
|
2023-03-14 05:39:19 -07:00
|
|
|
let tx = Transaction::new_signed_with_payer(
|
|
|
|
&ixs,
|
|
|
|
Some(&identity.pubkey()),
|
|
|
|
&[&identity],
|
|
|
|
*blockhash.read().await,
|
|
|
|
);
|
|
|
|
// TODO: find perp market pk and resolve import issue between solana program versions
|
|
|
|
// tx_record_sx.send(TransactionSendRecord {
|
|
|
|
// signature: tx.signatures[0],
|
|
|
|
// sent_at: Utc::now(),
|
|
|
|
// sent_slot: current_slot.load(Ordering::Acquire),
|
|
|
|
// market_maker: identity.pubkey(),
|
|
|
|
// market: c.perp_market_pk,
|
|
|
|
// });
|
|
|
|
let ok = tpu_client.send_transaction(&tx);
|
|
|
|
trace!("send tx={:?} ok={ok}", tx.signatures[0]);
|
2023-03-06 00:37:42 -08:00
|
|
|
}
|
2023-03-14 05:39:19 -07:00
|
|
|
}
|
|
|
|
});
|
2023-03-06 00:37:42 -08:00
|
|
|
|
|
|
|
tokio::spawn(async move {
|
2023-03-09 07:20:49 -08:00
|
|
|
let metrics_tx = metrics::start(
|
|
|
|
metrics::MetricsConfig {
|
|
|
|
output_stdout: true,
|
|
|
|
output_http: false,
|
|
|
|
},
|
|
|
|
"crank".into(),
|
|
|
|
);
|
|
|
|
|
|
|
|
let routes = vec![AccountWriteRoute {
|
|
|
|
matched_pubkeys: perp_queue_pks
|
|
|
|
.iter()
|
|
|
|
.map(|(_, evq_pk)| evq_pk.clone())
|
|
|
|
.collect(),
|
|
|
|
sink: Arc::new(MangoV3PerpCrankSink::new(
|
|
|
|
perp_queue_pks,
|
|
|
|
group_pk,
|
|
|
|
cache_pk,
|
|
|
|
mango_program_id,
|
|
|
|
instruction_sender,
|
|
|
|
)),
|
|
|
|
timeout_interval: Duration::default(),
|
|
|
|
}];
|
|
|
|
|
|
|
|
let (account_write_queue_sender, slot_queue_sender) =
|
|
|
|
account_write_filter::init(routes, metrics_tx.clone()).expect("filter initializes");
|
|
|
|
|
|
|
|
info!("start processing grpc events");
|
|
|
|
|
|
|
|
// grpc_plugin_source::process_events(
|
|
|
|
// &config,
|
|
|
|
// &filter_config,
|
|
|
|
// account_write_queue_sender,
|
|
|
|
// slot_queue_sender,
|
|
|
|
// metrics_tx.clone(),
|
|
|
|
// ).await;
|
|
|
|
|
|
|
|
websocket_source::process_events(
|
2023-03-10 04:38:11 -08:00
|
|
|
config,
|
2023-03-09 07:20:49 -08:00
|
|
|
&filter_config,
|
|
|
|
account_write_queue_sender,
|
|
|
|
slot_queue_sender,
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
});
|
2023-02-18 08:22:12 -08:00
|
|
|
}
|