liquidator: Add telemetry (#668)

The DAO would like to know how many potential liquidators are around.
This commit is contained in:
Christian Kamm 2023-08-08 18:17:23 +02:00 committed by GitHub
parent 4810b6afbc
commit 7e32e2e0bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 7 deletions

1
Cargo.lock generated
View File

@ -3077,6 +3077,7 @@ dependencies = [
"bs58 0.3.1",
"bytemuck",
"bytes 1.3.0",
"chrono",
"clap 3.2.23",
"dotenv",
"fixed 1.11.0",

View File

@ -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

View File

@ -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"] }

View File

@ -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

View File

@ -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,

View File

@ -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<MangoClient>, 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(())
}

View File

@ -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::<T>(&response_text)
.with_context(|| format!("response has unexpected format, body: {response_text}"))