Skip to content

Commit

Permalink
Merge pull request #1 from sol-farm/atrix
Browse files Browse the repository at this point in the history
add support for parsing atrix api
  • Loading branch information
bonedaddy authored Mar 31, 2022
2 parents 8fcf601 + 7822994 commit dddcbb4
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,22 @@

A set of rust crates for working with DeFi protocols across the Solana ecosystem.

# Supported Protocols

* Orca
* Raydium
* Atrix

# Crates

## `so-defi-config`

Configuration parsing create that supports parsing the output from the various API's offered by the following protocols:

* Orca
* Raydium
* Atrix

Provides helpers for parsing the configuration api's available from Orca, and Raydium.

# Usage
Expand Down
2 changes: 1 addition & 1 deletion config/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "so-defi-config"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
authors = ["Tulip Protocol"]
description = "configuration crate for so-defi"
Expand Down
254 changes: 254 additions & 0 deletions config/src/atrix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
//! provides helepr functions for parsing atrix's configuration api

use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// the hostname and main path for Atrix's
pub const ATRIX_API: &str = "https://api.atrix.finance/api";

/// a common type used to denote the raydium api version
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Version {
pub major: i64,
pub minor: i64,
pub patch: i64,
}

pub mod tvl_list {
//! configuration helpers for the atrix's tvl api request

use super::*;
pub const ATRIX_API_TVL_LIST: &str = "tvl";

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TvlList {
pub tvl: f64,
pub pools: Vec<Pool>,
pub farms: Vec<Farm>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Pool {
pub pool_key: String,
pub tvl: Option<f64>,
pub lp_mint: String,
pub lp_supply: f64,
pub coin_mint: String,
pub coin_tokens: f64,
pub coin_decimals: i64,
pub pc_mint: String,
pub pc_tokens: f64,
pub pc_decimals: i64,
pub farms: Vec<Farm>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Farm {
pub key: String,
pub tvl: f64,
pub apy: f64,
}

pub fn api_url() -> String {
format_api_url(ATRIX_API_TVL_LIST)
}

pub async fn fetch_async() -> Result<TvlList> {
let client = reqwest::Client::builder().build()?;
let res = client.get(api_url()).send().await?;
let data = res.json::<TvlList>().await?;
Ok(data)
}
pub fn fetch() -> Result<TvlList> {
let client = reqwest::blocking::Client::builder().build()?;
let res = client.get(api_url()).send()?;
let data = res.json::<TvlList>()?;
Ok(data)
}

#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_api_url() {
assert_eq!(api_url(), "https://api.atrix.finance/api/tvl");
}

#[tokio::test]
async fn test_fetch_async() {
let results = fetch_async().await.unwrap();
assert!(results.pools.len() > 0);
}
#[test]
fn test_fetch() {
let results = fetch().unwrap();
assert!(results.pools.len() > 0);
}
}
}

pub mod pools_list {
//! configuration helpers for the raydium pairs api request

use super::*;
pub const ATRIX_API_POOLS_LIST: &str = "pools";

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PoolsList {
pub pools: Vec<Pool>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Pool {
pub id: String,
#[serde(rename = "created_at")]
pub created_at: String,
#[serde(rename = "coin_mint")]
pub coin_mint: String,
#[serde(rename = "pc_mint")]
pub pc_mint: String,
pub market: String,
#[serde(rename = "open_orders")]
pub open_orders: String,
#[serde(rename = "pool_coin_account")]
pub pool_coin_account: String,
#[serde(rename = "pool_pc_account")]
pub pool_pc_account: String,
#[serde(rename = "pool_lp_account")]
pub pool_lp_account: String,
#[serde(rename = "lp_mint")]
pub lp_mint: String,
#[serde(rename = "pool_type")]
pub pool_type: i64,
#[serde(rename = "stableswap_amp_coef")]
pub stableswap_amp_coef: i64,
#[serde(rename = "pool_coin_amt")]
pub pool_coin_amt: String,
#[serde(rename = "pool_pc_amt")]
pub pool_pc_amt: String,
pub farms: Vec<Farm>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Farm {
pub key: String,
pub tvl: f64,
pub apy: f64,
}

pub fn api_url() -> String {
format_api_url(ATRIX_API_POOLS_LIST)
}

pub async fn fetch_async() -> Result<PoolsList> {
let client = reqwest::Client::builder().build()?;
let res = client.get(api_url()).send().await?;
let data = res.json::<PoolsList>().await?;
Ok(data)
}
pub fn fetch() -> Result<PoolsList> {
let client = reqwest::blocking::Client::builder().build()?;
let res = client.get(api_url()).send()?;
let data = res.json::<PoolsList>()?;
Ok(data)
}

#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_api_url() {
assert_eq!(api_url(), "https://api.atrix.finance/api/pools");
}

#[tokio::test]
async fn test_fetch_async() {
let result = fetch_async().await.unwrap();
assert!(result.pools.len() > 0);
}
#[test]
fn test_fetch() {
let result = fetch().unwrap();
assert!(result.pools.len() > 0);
}
}
}

pub mod farms_list {
//! configuration helpers for raydium farms

use super::*;
pub const ATRIX_API_FARMS_LIST: &str = "farms";

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FarmList {
pub farms: Vec<Farm>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Farm {
pub id: String,
#[serde(rename = "created_at")]
pub created_at: String,
#[serde(rename = "farm_stake_token_account")]
pub farm_stake_token_account: String,
#[serde(rename = "crop_accounts")]
pub crop_accounts: Vec<Option<String>>,
pub authority: String,
#[serde(rename = "stake_mint")]
pub stake_mint: String,
pub apy: f64,
pub tvl: f64,
}

pub fn api_url() -> String {
format_api_url(ATRIX_API_FARMS_LIST)
}

pub async fn fetch_async() -> Result<FarmList> {
let client = reqwest::Client::builder().build()?;
let res = client.get(api_url()).send().await?;
let data = res.json::<FarmList>().await?;
Ok(data)
}
pub fn fetch() -> Result<FarmList> {
let client = reqwest::blocking::Client::builder().build()?;
let res = client.get(api_url()).send()?;
let data = res.json::<FarmList>()?;
Ok(data)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_api_url() {
assert_eq!(api_url(), "https://api.atrix.finance/api/farms");
}

#[tokio::test]
async fn test_fetch_async() {
let result = fetch_async().await.unwrap();
assert!(result.farms.len() > 0);
}
#[test]
fn test_fetch() {
let result = fetch().unwrap();
assert!(result.farms.len() > 0);
}
}
}

/// basic helper function that combines the main api path
/// and the request path
pub fn format_api_url(request: &str) -> String {
format!("{}/{}", ATRIX_API, request)
}
1 change: 1 addition & 0 deletions config/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! provides helpers for parsing configuration data related to the Orca and Raydium AMMs from their respective configuration api

pub mod atrix;
pub mod orca;
pub mod raydium;
20 changes: 5 additions & 15 deletions config/src/orca.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,37 +211,27 @@ mod test {
async fn test_orca_config() {
let orca_config = OrcaConfigsApiResponse::fetch_orca_config().await.unwrap();

let pool_config = orca_config
.find_pool("SOL/USDC", false, false)
.unwrap();
let pool_config = orca_config.find_pool("SOL/USDC", false, false).unwrap();
assert_eq!(
pool_config.account,
"6fTRDD7sYxCN7oyoSQaN1AWC3P2m8A6gVZzGrpej9DvL".to_string()
);

let pool_config = orca_config
.find_pool("SOL/USDC", false, true)
.unwrap();
let pool_config = orca_config.find_pool("SOL/USDC", false, true).unwrap();
assert_eq!(
pool_config.account,
"EGZ7tiLeH62TPV1gL8WwbXGzEPa9zmcpVnnkPKKnrE2U".to_string()
);

let aquafarm_config = orca_config
.find_aquafarm("SOL/USDC", false)
.unwrap();
let aquafarm_config = orca_config.find_aquafarm("SOL/USDC", false).unwrap();
assert_eq!(aquafarm_config.0, pool_config);
println!(
"sol/usdc aquafarm information\npool {:#?}\nfarm {:#?}",
aquafarm_config.0, aquafarm_config.1
);

let pool_config = orca_config
.find_pool("LIQ/USDC", false, true)
.unwrap();
let doubledip_config = orca_config
.find_double_dip("LIQ/USDC", false)
.unwrap();
let pool_config = orca_config.find_pool("LIQ/USDC", false, true).unwrap();
let doubledip_config = orca_config.find_double_dip("LIQ/USDC", false).unwrap();
assert_eq!(doubledip_config.0, pool_config);
println!(
"liq/usdc doubledip information\npool {:#?}\nfarm {:#?}\ndouble dip {:#?}",
Expand Down
7 changes: 5 additions & 2 deletions config/src/raydium.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! provides helepr functions for parsing raydium's configuration api

use anyhow::{Result};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

Expand Down Expand Up @@ -273,7 +273,10 @@ pub mod liquidity_list {
let liquidity = fetch_async().await.unwrap();
let mut ok = false;
for liquidity in liquidity.un_official.iter() {
if liquidity.id.eq(&"C614Uy93kGJrmuMRkPBUXtYu6E9MMRieKLcK3YUZGgxG") {
if liquidity
.id
.eq(&"C614Uy93kGJrmuMRkPBUXtYu6E9MMRieKLcK3YUZGgxG")
{
println!("found it {:#?}", liquidity);
ok = true;
break;
Expand Down

0 comments on commit dddcbb4

Please sign in to comment.