From 7e32e2e0bd6defb998097a4adde8fe026e94255c Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Tue, 8 Aug 2023 18:17:23 +0200 Subject: [PATCH] liquidator: Add telemetry (#668) The DAO would like to know how many potential liquidators are around. --- Cargo.lock | 1 + bin/liquidator/.env.example | 4 +++- bin/liquidator/Cargo.toml | 1 + bin/liquidator/README.md | 11 +++++++--- bin/liquidator/src/main.rs | 14 +++++++++++- bin/liquidator/src/telemetry.rs | 39 +++++++++++++++++++++++++++++++++ lib/client/src/client.rs | 4 ++-- 7 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 bin/liquidator/src/telemetry.rs diff --git a/Cargo.lock b/Cargo.lock index c5f77416f..e8b4ed066 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3077,6 +3077,7 @@ dependencies = [ "bs58 0.3.1", "bytemuck", "bytes 1.3.0", + "chrono", "clap 3.2.23", "dotenv", "fixed 1.11.0", diff --git a/bin/liquidator/.env.example b/bin/liquidator/.env.example index c9ff08c3c..541109bac 100644 --- a/bin/liquidator/.env.example +++ b/bin/liquidator/.env.example @@ -1,4 +1,6 @@ RPC_URL=https://mango.devnet.rpcpool.com -SERUM_PROGRAM=DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY LIQOR_MANGO_ACCOUNT= LIQOR_OWNER=~/.config/solana/user.json +MIN_HEALTH_RATIO=50 +PRIORITIZATION_MICRO_LAMPORTS=1000 +TELEMETRY=true diff --git a/bin/liquidator/Cargo.toml b/bin/liquidator/Cargo.toml index a099d61a2..04f8b2a9f 100644 --- a/bin/liquidator/Cargo.toml +++ b/bin/liquidator/Cargo.toml @@ -20,6 +20,7 @@ async-trait = "0.1" bs58 = "0.3.1" bytemuck = "^1.7.2" bytes = "1.0" +chrono = "0.4" clap = { version = "3.1.8", features = ["derive", "env"] } dotenv = "0.15.0" fixed = { workspace = true, features = ["serde"] } diff --git a/bin/liquidator/README.md b/bin/liquidator/README.md index 9882b5964..0cd1f689a 100644 --- a/bin/liquidator/README.md +++ b/bin/liquidator/README.md @@ -26,7 +26,7 @@ See https://github.com/blockworks-foundation/mango-v4/blob/dev/LICENSE Two branches are relevant here: -- `devnet`: bleeding edge, may be unstable, could be incompatible with deployed program +- `dev`: bleeding edge, may be unstable, could be incompatible with deployed program - `main`: stable, currently running on the `mainnet-beta` cluster ## Setup Environment @@ -40,12 +40,17 @@ The environment variables required are - `LIQOR_MANGO_ACCOUNT` - public key of the mango account - `LIQOR_OWNER` - private key of the owner of the mango account - `RPC_URL` - RPC cluster url -- `SERUM_PROGRAM` - the Openbook program Id the mango group is configured with e.g. primary mango group `78b8f4cGCwmZ9ysPFMWLaLTkkaYnUjwMJYStWe5RTSSX` is configured to work with `srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX` +- `MIN_HEALTH_RATIO` - minimum health ratio the liquidator should retain (default 50%) more advanced parameters -- `MIN_HEALTH_RATIO` - minimum health ratio the liquidator should retain (default 50%) +- `REBALANCE` - if rebalancing should happen (default true) - `REBALANCE_SLIPPAGE_BPS` - slippage liquidator should tolerate when offloading tokens (default 100) +- `PRIORITIZATION_MICRO_LAMPORTS` - how much priority fee to pay (default 0) +- `SNAPSHOT_INTERVAL_SECS` - how frequently to request a full on-chain snapshot (default 5min) +- `PARALLEL_RPC_REQUESTS` - number of allowed parallel rpc calls (default 10) +- `TELEMETRY` - report the liquidator's existence and pubkey occasionally (default true) +- `MOCK_JUPITER` - replace jupiter queries with mocks (for devnet testing only) ```shell cargo run --bin liquidator diff --git a/bin/liquidator/src/main.rs b/bin/liquidator/src/main.rs index 064e49674..261c4220d 100644 --- a/bin/liquidator/src/main.rs +++ b/bin/liquidator/src/main.rs @@ -20,6 +20,7 @@ use tracing::*; pub mod liquidate; pub mod metrics; pub mod rebalance; +pub mod telemetry; pub mod token_swap_info; pub mod trigger_tcs; pub mod util; @@ -95,6 +96,10 @@ struct Cli { /// This is required for devnet testing. #[clap(long, env, value_enum, default_value = "false")] mock_jupiter: BoolArg, + + /// report liquidator's existence and pubkey + #[clap(long, env, value_enum, default_value = "true")] + telemetry: BoolArg, } pub fn encode_address(addr: &Pubkey) -> String { @@ -271,7 +276,7 @@ async fn main() -> anyhow::Result<()> { }); let mut liquidation = Box::new(LiquidationState { - mango_client, + mango_client: mango_client.clone(), account_fetcher, liquidation_config: liq_config, trigger_tcs_config: tcs_config, @@ -483,6 +488,13 @@ async fn main() -> anyhow::Result<()> { } }); + if cli.telemetry == BoolArg::True { + tokio::spawn(telemetry::report_regularly( + mango_client, + cli.min_health_ratio, + )); + } + use futures::StreamExt; let mut jobs: futures::stream::FuturesUnordered<_> = vec![ data_job, diff --git a/bin/liquidator/src/telemetry.rs b/bin/liquidator/src/telemetry.rs new file mode 100644 index 000000000..d7f43f6fc --- /dev/null +++ b/bin/liquidator/src/telemetry.rs @@ -0,0 +1,39 @@ +use mango_v4_client::MangoClient; +use solana_sdk::signer::Signer; +use std::sync::Arc; +use tracing::*; + +pub async fn report_regularly(client: Arc, min_health_ratio: f64) { + let mut interval = tokio::time::interval(std::time::Duration::from_secs(600)); + loop { + interval.tick().await; + if let Err(e) = report(&client, min_health_ratio).await { + warn!("telemetry call failed: {e:?}"); + } + } +} + +async fn report(client: &MangoClient, min_health_ratio: f64) -> anyhow::Result<()> { + let message = serde_json::json!({ + "mango_account_pk": client.mango_account_address.to_string(), + "target_init_health": min_health_ratio, + "timestamp": chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true), + }) + .to_string(); + + let signature = client.owner.sign_message(message.as_bytes()); + let payload = serde_json::json!({ + "wallet_pk": client.owner.pubkey().to_string(), + "message": message, + "signature": signature.to_string(), + }); + + let url = "https://api.mngo.cloud/data/v4/user-data/liquidator-capacity"; + let response = client.http_client.post(url).json(&payload).send().await?; + let res_text = response.text().await?; + if res_text != "null" { + anyhow::bail!("unexpected reporting response: {res_text}"); + } + + Ok(()) +} diff --git a/lib/client/src/client.rs b/lib/client/src/client.rs index bf00463bc..705cea7ad 100644 --- a/lib/client/src/client.rs +++ b/lib/client/src/client.rs @@ -1382,9 +1382,9 @@ impl MangoClient { let response_text = response .text() .await - .context("awaiting body of quote request to jupiter")?; + .context("awaiting body of http request")?; if !status.is_success() { - anyhow::bail!("request failed, status: {status}, body: {response_text}"); + anyhow::bail!("http request failed, status: {status}, body: {response_text}"); } serde_json::from_str::(&response_text) .with_context(|| format!("response has unexpected format, body: {response_text}"))