Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
canonbrother committed Mar 8, 2024
1 parent 4350428 commit 1023816
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 28 deletions.
8 changes: 6 additions & 2 deletions lib/Cargo.lock

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

3 changes: 2 additions & 1 deletion lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ substrate-bn = "0.6"
#### Ocean dependencies
bitcoin = "0.31"
cached = { version = "0.48", features = ["async"] }
defichain-rpc = { version = "0.18.0", git = "https://github.com/defich/rust-defichain-rpc.git" }
# defichain-rpc = { version = "0.18.0", git = "https://github.com/defich/rust-defichain-rpc.git" }
defichain-rpc = { rev = "31019a1", git = "https://github.com/defich/rust-defichain-rpc.git" }

### Local crates
ain-cpp-imports = { path = "./ain-cpp-imports" }
Expand Down
2 changes: 2 additions & 0 deletions lib/ain-ocean/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ rust_decimal = { version = "1.34", features = ["serde", "serde-float", "serde-wi
rust_decimal_macros = "1.34"
clap = { version = "4.5.0", features = ["derive"] }
num_cpus.workspace = true
petgraph = { version = "0.6.4", features = ["serde-1"] }
parking_lot.workspace = true

[dev-dependencies]
tempdir.workspace = true
Expand Down
18 changes: 17 additions & 1 deletion lib/ain-ocean/src/api/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use std::sync::Arc;

use anyhow::format_err;
use cached::proc_macro::cached;
use defichain_rpc::{defichain_rpc_json::token::TokenInfo, TokenRPC};
use defichain_rpc::{
defichain_rpc_json::{
poolpair::PoolPairsResult, token::TokenInfo
}, json::poolpair::PoolPairPagination, PoolPairRPC, TokenRPC};

use super::AppContext;
use crate::Result;
Expand All @@ -23,3 +26,16 @@ pub async fn get_token_cached(ctx: &Arc<AppContext>, symbol: &str) -> Result<(St
.ok_or(format_err!("Error getting token info"))?;
Ok(token)
}

#[cached(
result = true,
key = "String",
convert = r#"{ format!("listpoolpairs") }"#
)]
pub async fn list_pool_pairs_cached(ctx: &Arc<AppContext>) -> Result<PoolPairsResult> {
let pool_pairs = ctx
.client
.list_pool_pairs(Some(PoolPairPagination {start: 0, including_start: true, limit: 1000}), Some(true))
.await?;
Ok(pool_pairs)
}
2 changes: 1 addition & 1 deletion lib/ain-ocean/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod poolpairs;
// mod prices;
// mod rawtx;
mod cache;
mod common;
pub mod common;
mod path;
mod query;
mod response;
Expand Down
186 changes: 165 additions & 21 deletions lib/ain-ocean/src/api/poolpairs.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
use std::sync::Arc;
use std::{sync::Arc, time::Duration};

use ain_macros::ocean_endpoint;
use axum::{routing::get, Extension, Router};
use bitcoin::hex::parse;
use defichain_rpc::{
json::poolpair::{PoolPairInfo, PoolPairsResult},
json::token::TokenInfo,
RpcApi,
};
use log::debug;
use serde::{Deserialize, Serialize};
use serde_json::json;

use super::{
common::{parse_dat_symbol, parse_display_symbol},
cache::{get_token_cached, list_pool_pairs_cached},
common::parse_dat_symbol,
path::Path,
query::{PaginationQuery, Query},
response::{ApiPagedResponse, Response},
Expand All @@ -24,7 +26,7 @@ use crate::{
model::{BlockContext, PoolSwap},
repository::{InitialKeyProvider, PoolSwapRepository, RepositoryOps},
storage::SortOrder,
Result,
Result, TokenIdentifier,
};

// #[derive(Deserialize)]
Expand All @@ -43,12 +45,6 @@ use crate::{
// token_id: String,
// }

// #[derive(Deserialize)]
// struct BestPath {
// from_token_id: String,
// to_token_id: String,
// }

// #[derive(Debug, Deserialize)]
// struct DexPrices {
// denomination: Option<String>,
Expand Down Expand Up @@ -431,18 +427,166 @@ async fn list_pool_swaps_verbose(
// format!("Swappable tokens for token id {}", token_id)
// }

// #[ocean_endpoint]
// async fn get_best_path(
// Query(BestPath {
// from_token_id,
// to_token_id,
// }): Query<BestPath>,
// ) -> String {
// format!(
// "Best path from token id {} to {}",
// from_token_id, to_token_id
// )
// }
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BestSwapPathResponse {
from_token: String,
to_token: String,
best_path: Vec<String>,
estimated_return: String,
estimated_return_less_dex_fees: String
}

#[ocean_endpoint]
async fn get_best_path(
Path(from_token_id): Path<String>,
Path(to_token_id): Path<String>,
Extension(ctx): Extension<Arc<AppContext>>,
) -> Result<BestSwapPathResponse> {
let res = get_all_swap_paths(&ctx, from_token_id, to_token_id);

// dummy first
Ok(BestSwapPathResponse{
from_token: "1".to_string(),
to_token: "1".to_string(),
best_path: vec!["1".to_string()],
estimated_return: "1".to_string(),
estimated_return_less_dex_fees: "1".to_string(),
})
}

fn to_token_identifier(id: &String, info: &TokenInfo) -> TokenIdentifier {
TokenIdentifier {
id: id.to_owned(),
name: info.name.to_owned(),
symbol: info.symbol.to_owned(),
display_symbol: parse_dat_symbol(info.symbol.as_str()),
}
}


#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SwapPathPoolPairResponse {
pool_pair_id: String,
symbol: String,
token_a: TokenIdentifier,
token_b: TokenIdentifier,
price_ratio: PoolPairPriceRatioResponse,
commission_fee_in_pct: String,
estimated_dex_fees_in_pct: Option<PoolPairPriceRatioResponse>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SwapPathsResponse {
from_token: TokenIdentifier,
to_token: TokenIdentifier,
paths: Vec<Vec<SwapPathPoolPairResponse>>,
}

async fn compute_paths_between_tokens(ctx: &Arc<AppContext>, from_token_id: String, to_token_id: String) -> Result<bool> {
Ok(true)
}

async fn get_token_identifier(ctx: &Arc<AppContext>, id: String) -> Result<TokenIdentifier> {
let (id, token) = get_token_cached(ctx, &id).await?;
Ok(TokenIdentifier{
id,
name: token.name,
symbol: token.symbol.clone(),
display_symbol: parse_dat_symbol(&token.symbol),
})

}

async fn get_all_swap_paths(ctx: &Arc<AppContext>, from_token_id: String, to_token_id: String) -> Result<SwapPathsResponse> {
assert!(from_token_id != to_token_id);

sync_graph_if_empty(ctx).await;

let mut res = SwapPathsResponse {
from_token: get_token_identifier(ctx, from_token_id.clone()).await?,
to_token: get_token_identifier(ctx, to_token_id.clone()).await?,
paths: vec![],
};

if !ctx.services.token_graph.lock().contains_node(from_token_id.parse::<u32>()?)
|| !ctx.services.token_graph.lock().contains_node(to_token_id.parse::<u32>()?) {
return Ok(res)
}

// res.paths = compute_paths_between_tokens(from_token_id, to_token_id).await?;

return Ok(res)
}

async fn sync_graph_if_empty(ctx: &Arc<AppContext>) {
if ctx.services.token_graph.lock().node_count() == 0 {
sync_token_graph(ctx).await;
}
}

async fn sync_token_graph(ctx: &Arc<AppContext>) {
let mut interval = tokio::time::interval(Duration::from_secs(120));

loop {
// wait 120s
interval.tick().await;
// then
let pools = list_pool_pairs_cached(ctx).await.unwrap();

// addTokensAndConnectionsToGraph
for (k, v) in pools.0 {
// isPoolPairIgnored
if !v.status {
continue;
}
if ctx.network == "mainnet" && k == "48" {
continue;
}
let id_token_a = v.id_token_a.parse::<u32>().unwrap();
let id_token_b = v.id_token_b.parse::<u32>().unwrap();
let graph = &ctx.services.token_graph;
if !graph.lock().contains_node(id_token_a) {
graph.lock().add_node(id_token_a);
}
if !graph.lock().contains_node(id_token_b) {
graph.lock().add_node(id_token_b);
}
if !graph.lock().contains_edge(id_token_a, id_token_b) {
graph.lock().add_edge(id_token_a, id_token_b, ());
}
}

// updateTokensToSwappableTokens
let mut token_identifiers = vec![];
let token_ids = &ctx.services.token_graph.lock().nodes().collect::<Vec<_>>();
for id in token_ids {
let (id, token) = get_token_cached(ctx, id.to_string().as_str()).await.unwrap();
let token_identifier = to_token_identifier(&id, &token);
token_identifiers.push(token_identifier);
}

let token_identifiers_cloned = token_identifiers.clone();

// index each token to their swappable tokens
for token_identifier in token_identifiers {
ctx
.services
.tokens_to_swappable_tokens
.lock()
.insert(
token_identifier.clone().id,
token_identifiers_cloned
.clone()
.into_iter()
.filter(|t| t.id != token_identifier.id) // exclude tokens from their own 'swappables' list
.collect::<Vec<_>>(),
);
}
} // end of loop
}

// #[ocean_endpoint]
// async fn get_all_paths(
Expand Down
20 changes: 18 additions & 2 deletions lib/ain-ocean/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
pub mod error;
mod indexer;

use std::{path::PathBuf, sync::Arc};
use std::{collections::HashMap, path::PathBuf, sync::Arc};
use parking_lot::Mutex;
use petgraph::graphmap::UnGraphMap;
use serde::Serialize;

pub use api::ocean_router;
pub use api::{ocean_router, common::parse_display_symbol};
use error::Error;
pub use indexer::{index_block, invalidate_block, transaction::index_transaction, tx_result};
use repository::{
Expand Down Expand Up @@ -59,13 +62,24 @@ pub struct TransactionService {
vout_by_id: TransactionVoutRepository,
}


#[derive(Clone, Debug, Serialize)]
pub struct TokenIdentifier {
pub id: String,
pub name: String,
pub symbol: String,
pub display_symbol: String,
}

pub struct Services {
pub masternode: MasternodeService,
pub block: BlockService,
pub auction: AuctionService,
pub result: TxResultRepository,
pub pool: PoolService,
pub transaction: TransactionService,
pub token_graph: Mutex<UnGraphMap<u32, ()>>,
pub tokens_to_swappable_tokens: Mutex<HashMap<String, Vec<TokenIdentifier>>>,
}

impl Services {
Expand Down Expand Up @@ -95,6 +109,8 @@ impl Services {
vin_by_id: TransactionVinRepository::new(Arc::clone(&store)),
vout_by_id: TransactionVoutRepository::new(Arc::clone(&store)),
},
token_graph: Mutex::new(UnGraphMap::new()),
tokens_to_swappable_tokens: Mutex::new(HashMap::new()),
}
}
}

0 comments on commit 1023816

Please sign in to comment.