Skip to main content

hylo_sdk/
stability_pool_client.rs

1use crate::stability_pool::client::{accounts, args};
2use crate::stability_pool::events::StabilityPoolStats;
3use crate::util::{
4  simulation_config, ProgramClient, EXCHANGE_LOOKUP_TABLE, SOL_USD_PYTH_FEED,
5  STABILITY_POOL_LOOKUP_TABLE,
6};
7use crate::{exchange, pda, stability_pool};
8
9use std::sync::Arc;
10
11use anchor_client::solana_sdk::signature::{Keypair, Signature};
12use anchor_client::Program;
13use anchor_lang::prelude::Pubkey;
14use anchor_lang::AnchorDeserialize;
15use anchor_spl::token;
16use anyhow::{anyhow, Result};
17use base64::prelude::{Engine, BASE64_STANDARD};
18
19pub struct StabilityPoolClient {
20  program: Program<Arc<Keypair>>,
21  keypair: Arc<Keypair>,
22}
23
24impl ProgramClient for StabilityPoolClient {
25  const PROGRAM_ID: Pubkey = stability_pool::ID;
26
27  fn build_client(
28    program: Program<Arc<Keypair>>,
29    keypair: Arc<Keypair>,
30  ) -> StabilityPoolClient {
31    StabilityPoolClient { program, keypair }
32  }
33
34  fn program(&self) -> &Program<Arc<Keypair>> {
35    &self.program
36  }
37
38  fn keypair(&self) -> Arc<Keypair> {
39    self.keypair.clone()
40  }
41}
42
43impl StabilityPoolClient {
44  /// Rebalances stability pool by swapping stablecoin to levercoin.
45  ///
46  /// # Errors
47  /// - Transaction failure
48  pub async fn rebalance_stable_to_lever(&self) -> Result<Signature> {
49    let accounts = accounts::RebalanceStableToLever {
50      payer: self.program.payer(),
51      pool_config: pda::pool_config(),
52      hylo: pda::hylo(),
53      stablecoin_mint: pda::hyusd(),
54      stablecoin_pool: pda::hyusd_pool(),
55      pool_auth: pda::pool_auth(),
56      levercoin_pool: pda::xsol_pool(),
57      fee_auth: pda::fee_auth(pda::hyusd()),
58      fee_vault: pda::fee_vault(pda::hyusd()),
59      levercoin_mint: pda::xsol(),
60      sol_usd_pyth_feed: SOL_USD_PYTH_FEED,
61      stablecoin_auth: pda::hyusd_auth(),
62      levercoin_auth: pda::xsol_auth(),
63      hylo_event_authority: pda::event_auth(exchange::ID),
64      hylo_exchange_program: exchange::ID,
65      token_program: token::ID,
66      event_authority: pda::event_auth(stability_pool::ID),
67      program: stability_pool::ID,
68    };
69    let args = args::RebalanceStableToLever {};
70    let instructions = self
71      .program
72      .request()
73      .accounts(accounts)
74      .args(args)
75      .instructions()?;
76    let lookup_tables = self
77      .load_multiple_lookup_tables(&[
78        EXCHANGE_LOOKUP_TABLE,
79        STABILITY_POOL_LOOKUP_TABLE,
80      ])
81      .await?;
82    let sig = self
83      .send_v0_transaction(&instructions, &lookup_tables)
84      .await?;
85    Ok(sig)
86  }
87
88  /// Rebalances levercoin from the stability pool back to stablecoin.
89  ///
90  /// # Errors
91  /// - Transaction failure
92  pub async fn rebalance_lever_to_stable(&self) -> Result<Signature> {
93    let accounts = accounts::RebalanceLeverToStable {
94      payer: self.program.payer(),
95      pool_config: pda::pool_config(),
96      hylo: pda::hylo(),
97      stablecoin_mint: pda::hyusd(),
98      stablecoin_pool: pda::hyusd_pool(),
99      pool_auth: pda::pool_auth(),
100      levercoin_pool: pda::xsol_pool(),
101      fee_auth: pda::fee_auth(pda::hyusd()),
102      fee_vault: pda::fee_vault(pda::hyusd()),
103      levercoin_mint: pda::xsol(),
104      sol_usd_pyth_feed: SOL_USD_PYTH_FEED,
105      stablecoin_auth: pda::hyusd_auth(),
106      levercoin_auth: pda::xsol_auth(),
107      hylo_event_authority: pda::event_auth(exchange::ID),
108      hylo_exchange_program: exchange::ID,
109      token_program: token::ID,
110      event_authority: pda::event_auth(stability_pool::ID),
111      program: stability_pool::ID,
112    };
113    let args = args::RebalanceLeverToStable {};
114    let instructions = self
115      .program
116      .request()
117      .accounts(accounts)
118      .args(args)
119      .instructions()?;
120    let lookup_tables = self
121      .load_multiple_lookup_tables(&[
122        EXCHANGE_LOOKUP_TABLE,
123        STABILITY_POOL_LOOKUP_TABLE,
124      ])
125      .await?;
126    let sig = self
127      .send_v0_transaction(&instructions, &lookup_tables)
128      .await?;
129    Ok(sig)
130  }
131
132  /// Simulates the `get_stats` instruction on the stability pool.
133  ///
134  /// # Errors
135  /// - Simulation failure
136  /// - Return data access or deserialization
137  pub async fn simulate_get_stats(&self) -> Result<StabilityPoolStats> {
138    let accounts = accounts::GetStats {
139      pool_config: pda::pool_config(),
140      hylo: pda::hylo(),
141      stablecoin_mint: pda::hyusd(),
142      levercoin_mint: pda::xsol(),
143      pool_auth: pda::pool_auth(),
144      stablecoin_pool: pda::hyusd_pool(),
145      levercoin_pool: pda::xsol_pool(),
146      lp_token_mint: pda::shyusd(),
147      sol_usd_pyth_feed: SOL_USD_PYTH_FEED,
148    };
149    let args = args::GetStats {};
150    let tx = self
151      .program
152      .request()
153      .accounts(accounts)
154      .args(args)
155      .signed_transaction()
156      .await?;
157    let rpc = self.program.rpc();
158    let (data, _) = rpc
159      .simulate_transaction_with_config(&tx, simulation_config())
160      .await?
161      .value
162      .return_data
163      .ok_or(anyhow!("No return data for `get_stats`"))?
164      .data;
165    let bytes = BASE64_STANDARD.decode(data)?;
166    let stats = StabilityPoolStats::try_from_slice(&bytes)?;
167    Ok(stats)
168  }
169}