liquidator: Add telemetry (#668)
The DAO would like to know how many potential liquidators are around.
This commit is contained in:
parent
4810b6afbc
commit
7e32e2e0bd
|
@ -3077,6 +3077,7 @@ dependencies = [
|
||||||
"bs58 0.3.1",
|
"bs58 0.3.1",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"bytes 1.3.0",
|
"bytes 1.3.0",
|
||||||
|
"chrono",
|
||||||
"clap 3.2.23",
|
"clap 3.2.23",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
"fixed 1.11.0",
|
"fixed 1.11.0",
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
RPC_URL=https://mango.devnet.rpcpool.com
|
RPC_URL=https://mango.devnet.rpcpool.com
|
||||||
SERUM_PROGRAM=DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY
|
|
||||||
LIQOR_MANGO_ACCOUNT=
|
LIQOR_MANGO_ACCOUNT=
|
||||||
LIQOR_OWNER=~/.config/solana/user.json
|
LIQOR_OWNER=~/.config/solana/user.json
|
||||||
|
MIN_HEALTH_RATIO=50
|
||||||
|
PRIORITIZATION_MICRO_LAMPORTS=1000
|
||||||
|
TELEMETRY=true
|
||||||
|
|
|
@ -20,6 +20,7 @@ async-trait = "0.1"
|
||||||
bs58 = "0.3.1"
|
bs58 = "0.3.1"
|
||||||
bytemuck = "^1.7.2"
|
bytemuck = "^1.7.2"
|
||||||
bytes = "1.0"
|
bytes = "1.0"
|
||||||
|
chrono = "0.4"
|
||||||
clap = { version = "3.1.8", features = ["derive", "env"] }
|
clap = { version = "3.1.8", features = ["derive", "env"] }
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
fixed = { workspace = true, features = ["serde"] }
|
fixed = { workspace = true, features = ["serde"] }
|
||||||
|
|
|
@ -26,7 +26,7 @@ See https://github.com/blockworks-foundation/mango-v4/blob/dev/LICENSE
|
||||||
|
|
||||||
Two branches are relevant here:
|
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
|
- `main`: stable, currently running on the `mainnet-beta` cluster
|
||||||
|
|
||||||
## Setup Environment
|
## Setup Environment
|
||||||
|
@ -40,12 +40,17 @@ The environment variables required are
|
||||||
- `LIQOR_MANGO_ACCOUNT` - public key of the mango account
|
- `LIQOR_MANGO_ACCOUNT` - public key of the mango account
|
||||||
- `LIQOR_OWNER` - private key of the owner of the mango account
|
- `LIQOR_OWNER` - private key of the owner of the mango account
|
||||||
- `RPC_URL` - RPC cluster url
|
- `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
|
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)
|
- `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
|
```shell
|
||||||
cargo run --bin liquidator
|
cargo run --bin liquidator
|
||||||
|
|
|
@ -20,6 +20,7 @@ use tracing::*;
|
||||||
pub mod liquidate;
|
pub mod liquidate;
|
||||||
pub mod metrics;
|
pub mod metrics;
|
||||||
pub mod rebalance;
|
pub mod rebalance;
|
||||||
|
pub mod telemetry;
|
||||||
pub mod token_swap_info;
|
pub mod token_swap_info;
|
||||||
pub mod trigger_tcs;
|
pub mod trigger_tcs;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
@ -95,6 +96,10 @@ struct Cli {
|
||||||
/// This is required for devnet testing.
|
/// This is required for devnet testing.
|
||||||
#[clap(long, env, value_enum, default_value = "false")]
|
#[clap(long, env, value_enum, default_value = "false")]
|
||||||
mock_jupiter: BoolArg,
|
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 {
|
pub fn encode_address(addr: &Pubkey) -> String {
|
||||||
|
@ -271,7 +276,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut liquidation = Box::new(LiquidationState {
|
let mut liquidation = Box::new(LiquidationState {
|
||||||
mango_client,
|
mango_client: mango_client.clone(),
|
||||||
account_fetcher,
|
account_fetcher,
|
||||||
liquidation_config: liq_config,
|
liquidation_config: liq_config,
|
||||||
trigger_tcs_config: tcs_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;
|
use futures::StreamExt;
|
||||||
let mut jobs: futures::stream::FuturesUnordered<_> = vec![
|
let mut jobs: futures::stream::FuturesUnordered<_> = vec![
|
||||||
data_job,
|
data_job,
|
||||||
|
|
|
@ -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(())
|
||||||
|
}
|
|
@ -1382,9 +1382,9 @@ impl MangoClient {
|
||||||
let response_text = response
|
let response_text = response
|
||||||
.text()
|
.text()
|
||||||
.await
|
.await
|
||||||
.context("awaiting body of quote request to jupiter")?;
|
.context("awaiting body of http request")?;
|
||||||
if !status.is_success() {
|
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)
|
serde_json::from_str::<T>(&response_text)
|
||||||
.with_context(|| format!("response has unexpected format, body: {response_text}"))
|
.with_context(|| format!("response has unexpected format, body: {response_text}"))
|
||||||
|
|
Loading…
Reference in New Issue