diff --git a/markets.json b/markets.json index c4d88b4..6e8d5b7 100644 --- a/markets.json +++ b/markets.json @@ -31,6 +31,10 @@ "name": "BONK/USDC", "address": "8PhnCfgqpgFM7ZJvttGdBVMXHuU4Q23ACxCvWkbs1M71" }, + { + "name": "BONK/USDC", + "address": "7tV5jsyNUg9j1AARv56b7AirdpLBecibRXLEJtycEgpP" + }, { "name": "RAY/USDC", "address": "DZjbn4XC8qoHKikZqzmhemykVzmossoayV9ffbsUqxVj" diff --git a/src/database/fetch.rs b/src/database/fetch.rs index bdb257b..eeb588e 100644 --- a/src/database/fetch.rs +++ b/src/database/fetch.rs @@ -281,43 +281,77 @@ pub async fn fetch_coingecko_24h_volume( pub async fn fetch_coingecko_24h_high_low( pool: &Pool, - market_names: &Vec<&str>, + market_address_strings: &Vec<&str>, ) -> anyhow::Result> { let client = pool.get().await?; - let stmt = r#"select - r.market_name as "market_name!", - coalesce(c.high, r.high) as "high!", - coalesce(c.low, r.low) as "low!", - r."close" as "close!" - from + let stmt = r#" + with markets as ( + select market, "close" from ( + select + ofe.market, + price as "close", + instruction_num, + row_number() over (partition by ofe.market order by ofe.instruction_num desc) as row_num + from openbook.openbook_fill_events ofe + join ( + select market, max(block_datetime) as max_time + from openbook.openbook_fill_events ofe + where market in (SELECT unnest($1::text[])) + group by market + ) x + on ofe.block_datetime = x.max_time + and ofe.market = x.market + ) x2 where row_num = 1 + ) + select + m.market as "address!", + coalesce(a.high, m."close") as "high!", + coalesce(a.low, m."close") as "low!", + coalesce(a."close", m."close") as "close!" + from markets m + left join + ( + select * from ( - SELECT * - from - openbook.candles - where (market_name, start_time, resolution) in ( - select market_name, max(start_time), resolution - from openbook.candles - where "resolution" = '1M' - and market_name = any($1) - group by market_name, resolution - ) - ) as r - left join ( - SELECT - market_name, - max(start_time) as "start_time", - max(high) as "high", - min(low) as "low" - from - openbook.candles - where - "resolution" = '1M' - and "start_time" >= current_timestamp - interval '1 day' - group by market_name - ) c on r.market_name = c.market_name"#; + select + g.market, + g.high, + g.low, + ofe.price as close, + row_number() over (partition by ofe.market order by ofe.instruction_num desc) as row_num + from openbook.openbook_fill_events ofe + join ( + select + market, + max(price) as "high", + min(price) as "low", + max(block_datetime) as max_time, + max(seq_num) as seq_num + from openbook.openbook_fill_events ofe + where ofe.block_datetime > current_timestamp - interval '1 day' + and market in (SELECT unnest($1::text[])) + group by market + ) g + on g.market = ofe.market + and g.max_time = ofe.block_datetime + and g.seq_num = ofe.seq_num + join ( + select + market, + max(block_datetime) as max_time + from openbook.openbook_fill_events ofe + where market in (SELECT unnest($1::text[])) + group by market + ) b + on b.market = ofe.market + and b.max_time = ofe.block_datetime + ) a2 + where a2.row_num = 1 + ) a + on a.market = m.market"#; - let rows = client.query(stmt, &[&market_names]).await?; + let rows = client.query(stmt, &[&market_address_strings]).await?; Ok(rows .into_iter() diff --git a/src/server/coingecko.rs b/src/server/coingecko.rs index b639e40..729fed1 100644 --- a/src/server/coingecko.rs +++ b/src/server/coingecko.rs @@ -7,8 +7,8 @@ use openbook_candles::{ database::fetch::{fetch_coingecko_24h_high_low, fetch_coingecko_24h_volume}, structs::{ coingecko::{ - CoinGecko24HourVolume, CoinGeckoOrderBook, CoinGeckoPair, CoinGeckoTicker, - PgCoinGecko24HighLow, + CoinGeckoOrderBook, CoinGeckoPair, CoinGeckoTicker, PgCoinGecko24HighLow, + PgCoinGecko24HourVolume, }, slab::get_orderbooks_with_depth, }, @@ -51,12 +51,11 @@ pub async fn pairs(context: web::Data) -> Result) -> Result { // let client = RpcClient::new(context.rpc_url.clone()); let markets = &context.markets; - let market_names = markets.iter().map(|x| x.name.as_str()).collect(); let market_addresses = markets.iter().map(|x| x.address.as_str()).collect(); // let bba_fut = get_best_bids_and_asks(client, markets); let volume_fut = fetch_coingecko_24h_volume(&context.pool, &market_addresses); - let high_low_fut = fetch_coingecko_24h_high_low(&context.pool, &market_names); + let high_low_fut = fetch_coingecko_24h_high_low(&context.pool, &market_addresses); let (volume_query, high_low_quey) = join!(volume_fut, high_low_fut,); @@ -70,31 +69,27 @@ pub async fn tickers(context: web::Data) -> Result = raw_volumes - .into_iter() - .map(|v| v.convert_to_readable(markets)) - .collect(); + let default_volume = PgCoinGecko24HourVolume::default(); let tickers = markets .iter() .enumerate() .map(|(_index, m)| { - let name = m.name.clone(); let high_low = high_low .iter() - .find(|x| x.market_name == name) + .find(|x| x.address == m.address) .unwrap_or(&default_hl); - let volume = volumes + let volume = raw_volumes .iter() - .find(|x| x.market_name == name) + .find(|x| x.address == m.address) .unwrap_or(&default_volume); CoinGeckoTicker { ticker_id: m.name.clone(), + address: m.address.clone(), base_currency: m.base_mint_key.clone(), target_currency: m.quote_mint_key.clone(), last_price: high_low.close.to_string(), - base_volume: volume.base_volume.to_string(), - target_volume: volume.target_volume.to_string(), + base_volume: volume.base_size.to_string(), + target_volume: volume.quote_size.to_string(), high: high_low.high.to_string(), low: high_low.low.to_string(), } diff --git a/src/structs/coingecko.rs b/src/structs/coingecko.rs index f7c7673..47ac9f7 100644 --- a/src/structs/coingecko.rs +++ b/src/structs/coingecko.rs @@ -1,8 +1,6 @@ use serde::Serialize; use tokio_postgres::Row; -use super::markets::MarketInfo; - #[derive(Debug, Clone, Serialize)] pub struct CoinGeckoOrderBook { pub ticker_id: String, @@ -22,6 +20,7 @@ pub struct CoinGeckoPair { #[derive(Debug, Clone, Serialize)] pub struct CoinGeckoTicker { pub ticker_id: String, + pub address: String, pub base_currency: String, pub target_currency: String, pub last_price: String, @@ -33,21 +32,13 @@ pub struct CoinGeckoTicker { pub low: String, } +#[derive(Debug, Default)] pub struct PgCoinGecko24HourVolume { pub address: String, pub base_size: f64, pub quote_size: f64, } impl PgCoinGecko24HourVolume { - pub fn convert_to_readable(&self, markets: &Vec) -> CoinGecko24HourVolume { - let market = markets.iter().find(|m| m.address == self.address).unwrap(); - CoinGecko24HourVolume { - market_name: market.name.clone(), - base_volume: self.base_size, - target_volume: self.quote_size, - } - } - pub fn from_row(row: Row) -> Self { PgCoinGecko24HourVolume { address: row.get(0), @@ -57,16 +48,9 @@ impl PgCoinGecko24HourVolume { } } -#[derive(Debug, Default)] -pub struct CoinGecko24HourVolume { - pub market_name: String, - pub base_volume: f64, - pub target_volume: f64, -} - #[derive(Debug, Default)] pub struct PgCoinGecko24HighLow { - pub market_name: String, + pub address: String, pub high: f64, pub low: f64, pub close: f64, @@ -75,7 +59,7 @@ pub struct PgCoinGecko24HighLow { impl PgCoinGecko24HighLow { pub fn from_row(row: Row) -> Self { PgCoinGecko24HighLow { - market_name: row.get(0), + address: row.get(0), high: row.get(1), low: row.get(2), close: row.get(3),