implement mango v4 crank

This commit is contained in:
Maximilian Schneider 2023-02-03 20:55:59 +09:00
parent e22d30b9fd
commit 0a09ad81ae
4 changed files with 72 additions and 23 deletions

View File

@ -1,6 +1,6 @@
use log::*;
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_sdk::{clock::DEFAULT_MS_PER_SLOT, hash::Hash};
use solana_sdk::{clock::DEFAULT_MS_PER_SLOT, commitment_config::CommitmentConfig, hash::Hash};
use std::{
sync::{Arc, RwLock},
time::Duration,
@ -10,9 +10,10 @@ use tokio::{spawn, time::sleep};
const RETRY_INTERVAL: Duration = Duration::from_millis(5 * DEFAULT_MS_PER_SLOT);
pub async fn poll_loop(blockhash: Arc<RwLock<Hash>>, client: Arc<RpcClient>) {
let cfg = CommitmentConfig::processed();
loop {
let old_blockhash = *blockhash.read().unwrap();
if let Ok(new_blockhash) = client.get_latest_blockhash().await {
if let Ok((new_blockhash, _)) = client.get_latest_blockhash_with_commitment(cfg).await {
if new_blockhash != old_blockhash {
debug!("new blockhash ({:?})", blockhash);
*blockhash.write().unwrap() = new_blockhash;

View File

@ -24,7 +24,7 @@ use std::{
net::SocketAddr,
str::FromStr,
sync::Arc,
sync::{Mutex, atomic::AtomicBool},
sync::{atomic::AtomicBool, Mutex},
time::Duration,
};
use tokio::{
@ -34,14 +34,14 @@ use tokio::{
use tokio_tungstenite::tungstenite::{protocol::Message, Error};
use serde::Deserialize;
use solana_geyser_connector_lib::{
metrics::{MetricType, MetricU64},
FilterConfig, StatusResponse,
};
use solana_geyser_connector_lib::{
fill_event_filter::{self, FillCheckpoint},
grpc_plugin_source, metrics, websocket_source, MetricsConfig, SourceConfig,
};
use solana_geyser_connector_lib::{
metrics::{MetricType, MetricU64},
FilterConfig, StatusResponse,
};
#[derive(Clone, Debug, Deserialize)]
#[serde(tag = "command")]
@ -109,10 +109,11 @@ async fn main() -> anyhow::Result<()> {
&Keypair::new(),
Some(rpc_timeout),
);
let group_pk = Pubkey::from_str(&config.mango_group).unwrap();
let group_context = Arc::new(
MangoGroupContext::new_from_rpc(
&client.rpc_async(),
Pubkey::from_str(&config.mango_group).unwrap(),
group_pk
)
.await?,
);
@ -157,11 +158,14 @@ async fn main() -> anyhow::Result<()> {
})
.collect();
let (account_write_queue_sender, slot_queue_sender, instruction_receiver) = transaction_builder::init(
perp_queue_pks.clone(),
serum_queue_pks.clone(),
metrics_tx.clone()
).expect("init transaction builder");
let (account_write_queue_sender, slot_queue_sender, instruction_receiver) =
transaction_builder::init(
perp_queue_pks.clone(),
serum_queue_pks.clone(),
group_pk,
metrics_tx.clone(),
)
.expect("init transaction builder");
transaction_sender::init(instruction_receiver, blockhash, rpc_client, Keypair::new());

View File

@ -1,4 +1,5 @@
use crate::Pubkey;
use bytemuck::cast_ref;
use solana_geyser_connector_lib::{
chain_data::{AccountData, ChainData, SlotData},
metrics::Metrics,
@ -10,19 +11,19 @@ use anchor_lang::AccountDeserialize;
use log::*;
use solana_sdk::{
account::{ReadableAccount, WritableAccount},
instruction::{Instruction, AccountMeta},
stake_history::Epoch,
instruction::Instruction,
};
use std::{
borrow::BorrowMut,
collections::{HashMap, HashSet},
collections::{HashMap, HashSet}, iter::{once, empty},
convert::TryFrom
};
pub enum EventQueueFilterMessage {}
pub fn init(
perp_queue_pks: Vec<(Pubkey, Pubkey)>,
serum_queue_pks: Vec<(Pubkey, Pubkey)>,
group_pk: Pubkey,
metrics_sender: Metrics,
) -> anyhow::Result<(
async_channel::Sender<AccountWrite>,
@ -94,13 +95,14 @@ pub fn init(
for mkt in all_queue_pks.iter() {
let last_evq_version = last_evq_versions.get(&mkt.1.to_string()).unwrap_or(&(0, 0));
let mkt_pk = mkt.1;
let mkt_pk = mkt.0;
let evq_pk = mkt.1;
match chain_cache.account(&mkt_pk) {
match chain_cache.account(&evq_pk) {
Ok(account_info) => {
// only process if the account state changed
let evq_version = (account_info.slot, account_info.write_version);
let evq_pk_string = mkt.1.to_string();
let evq_pk_string = evq_pk.to_string();
trace!("evq {} write_version {:?}", evq_pk_string, evq_version);
if evq_version == *last_evq_version {
continue;
@ -110,7 +112,7 @@ pub fn init(
let account = &account_info.account;
let is_perp = mango_v4::check_id(account.owner());
if is_perp {
let event_queue = mango_v4::state::EventQueue::try_deserialize(
let event_queue: mango_v4::state::EventQueue = mango_v4::state::EventQueue::try_deserialize(
account.data().borrow_mut(),
)
.unwrap();
@ -119,6 +121,48 @@ pub fn init(
evq_pk_string,
event_queue.header.seq_num
);
if !event_queue.empty() {
let mango_accounts: HashSet<_> = event_queue.iter().take(10).flat_map(|e| match mango_v4::state::EventType::try_from(e.event_type).expect("mango v4 event") {
mango_v4::state::EventType::Fill => {
let fill: &mango_v4::state::FillEvent = cast_ref(e);
vec![fill.maker, fill.taker]
}
mango_v4::state::EventType::Out => {
let out: &mango_v4::state::OutEvent = cast_ref(e);
vec![out.owner]
}
mango_v4::state::EventType::Liquidate => vec![]
})
.collect();
let mut ams: Vec<_> = anchor_lang::ToAccountMetas::to_account_metas(
&mango_v4::accounts::PerpConsumeEvents {
group: group_pk,
perp_market: mkt_pk,
event_queue: evq_pk,
},
None,
);
ams.append(&mut mango_accounts
.iter()
.map(|pk| AccountMeta { pubkey: *pk, is_signer: false, is_writable: true })
.collect());
let ix = Instruction {
program_id: mango_v4::id(),
accounts: ams,
data: anchor_lang::InstructionData::data(&mango_v4::instruction::PerpConsumeEvents {
limit: 10,
}),
};
instruction_sender.send(vec![ix]).await;
}
match seq_num_cache.get(&evq_pk_string) {
Some(old_seq_num) => match perp_events_cache.get(&evq_pk_string) {
Some(old_events) => {}

View File

@ -1,9 +1,9 @@
use std::sync::{Arc, RwLock};
use solana_client::{nonblocking::rpc_client::RpcClient, rpc_config::RpcSendTransactionConfig};
use solana_sdk::{
hash::Hash, instruction::Instruction, signature::Keypair, signature::Signer,
transaction::Transaction,
};
use std::sync::{Arc, RwLock};
use tokio::spawn;
pub async fn send_loop(