diff --git a/lib/ain-ocean/src/api/common.rs b/lib/ain-ocean/src/api/common.rs index e6912d918e..b6b4f37b1e 100644 --- a/lib/ain-ocean/src/api/common.rs +++ b/lib/ain-ocean/src/api/common.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use ain_dftx::{Currency, Token}; -use bitcoin::{Address, ScriptBuf}; +use bitcoin::{Address, ScriptBuf, Txid}; use defichain_rpc::json::token::TokenInfo; use rust_decimal::Decimal; use rust_decimal_macros::dec; @@ -114,6 +114,17 @@ pub fn parse_query_height_txno(item: &str) -> Result<(u32, usize)> { Ok((height, txno)) } +pub fn parse_query_height_txid(item: &str) -> Result<(u32, Txid)> { + let mut parts = item.split('-'); + let height = parts.next().context(InvalidAmountSnafu { item })?; + let txid = parts.next().context(InvalidAmountSnafu { item })?; + + let height = height.parse::()?; + let txid = txid.parse::()?; + + Ok((height, txid)) +} + #[must_use] pub fn format_number(v: Decimal) -> String { if v == dec!(0) { diff --git a/lib/ain-ocean/src/api/loan.rs b/lib/ain-ocean/src/api/loan.rs index 51792a55b3..0b4a0bdf37 100644 --- a/lib/ain-ocean/src/api/loan.rs +++ b/lib/ain-ocean/src/api/loan.rs @@ -2,7 +2,7 @@ use std::{str::FromStr, sync::Arc}; use ain_macros::ocean_endpoint; use axum::{routing::get, Extension, Router}; -use bitcoin::{hashes::Hash, Txid}; +use bitcoin::{hashes::Hash, ScriptBuf, Txid}; use defichain_rpc::{ defichain_rpc_json::{ loan::{CollateralTokenDetail, LoanSchemeResult}, @@ -17,7 +17,7 @@ use defichain_rpc::{ }; use futures::future::try_join_all; use log::trace; -use serde::{Serialize, Serializer}; +use serde::{Deserialize, Serialize, Serializer}; use serde_with::skip_serializing_none; use snafu::OptionExt; @@ -25,7 +25,7 @@ use super::{ cache::{get_loan_scheme_cached, get_token_cached}, common::{ from_script, parse_amount, parse_display_symbol, parse_fixed_interval_price, - parse_query_height_txno, Paginate, + parse_query_height_txid, Paginate, }, path::Path, query::{PaginationQuery, Query}, @@ -35,7 +35,7 @@ use super::{ }; use crate::{ error::{ApiError, Error, NotFoundKind, NotFoundSnafu}, - model::{OraclePriceActive, VaultAuctionBatchHistory}, + model::{BlockContext, OraclePriceActive, VaultAuctionBatchHistory}, storage::{RepositoryOps, SortOrder}, Result, }; @@ -488,12 +488,59 @@ async fn get_vault( Ok(Response::new(res)) } +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "camelCase")] +pub struct VaultAuctionBatchHistoryResponse { + pub id: String, + pub key: String, + pub sort: String, + pub vault_id: Txid, + pub index: u32, + pub from: ScriptBuf, + pub address: String, + pub amount: i64, + pub token_id: u64, + pub block: BlockContext, +} + +impl VaultAuctionBatchHistoryResponse { + fn from( + data: ((Txid, [u8; 4], [u8; 4], Txid), VaultAuctionBatchHistory), + address: String, + ) -> Self { + let id = data.0; + let vault_id = id.0; + let batch_index = id.1; + let block_height = id.2; + let txid = id.3; + let history = data.1; + + Self { + id: format!( + "{}-{:?}-{}", + vault_id.clone(), + batch_index.clone(), + txid.clone() + ), + key: format!("{}-{:?}", vault_id.clone(), batch_index.clone()), + sort: format!("{}-{}", hex::encode(block_height), txid), + vault_id, + index: u32::from_be_bytes(batch_index), + from: history.from, + address, + amount: history.amount, + token_id: history.token_id, + block: history.block, + } + } +} + #[ocean_endpoint] async fn list_vault_auction_history( Path((vault_id, height, batch_index)): Path<(Txid, u32, u32)>, Query(query): Query, Extension(ctx): Extension>, -) -> Result> { +) -> Result> { trace!( "Auction history for vault id {}, height {}, batch index {}", vault_id, @@ -503,40 +550,39 @@ async fn list_vault_auction_history( let next = query .next .map(|q| { - let (height, txno) = parse_query_height_txno(&q)?; - Ok::<(u32, usize), Error>((height, txno)) + let (height, txid) = parse_query_height_txid(&q)?; + Ok::<(u32, Txid), Error>((height, txid)) }) .transpose()? - .unwrap_or_default(); + .unwrap_or((u32::MAX, Txid::from_byte_array([0xffu8; 32]))); let size = if query.size > 0 { query.size } else { 20 }; let auctions = ctx .services .auction - .by_height + .by_id .list( - Some((vault_id, batch_index, next.0, next.1)), + Some(( + vault_id, + batch_index.to_be_bytes(), + next.0.to_be_bytes(), + next.1, + )), SortOrder::Descending, )? .take(size) .take_while(|item| match item { - Ok((k, _)) => k.0 == vault_id && k.1 == batch_index, + Ok((k, _)) => k.0 == vault_id && k.1 == batch_index.to_be_bytes() && k.2 == height.to_be_bytes(), // refer to Path /// _ => true, }) .map(|item| { - let (_, id) = item?; - - let auction = ctx - .services - .auction - .by_id - .get(&id)? - .context(NotFoundSnafu { - kind: NotFoundKind::Auction, - })?; - - Ok(auction) + let (id, history) = item?; + let address = from_script(&history.from, ctx.network)?; + Ok(VaultAuctionBatchHistoryResponse::from( + (id, history), + address, + )) }) .collect::>>()?; @@ -611,14 +657,17 @@ async fn map_liquidation_batches( }; let id = ( Txid::from_str(vault_id)?, - batch.index, + batch.index.to_be_bytes(), + [0xffu8, 0xffu8, 0xffu8, 0xffu8], Txid::from_byte_array([0xffu8; 32]), ); let bids = repo .by_id .list(Some(id), SortOrder::Descending)? .take_while(|item| match item { - Ok(((vid, bindex, _), _)) => vid.to_string() == vault_id && bindex == &batch.index, + Ok(((vid, bindex, _, _), _)) => { + vid.to_string() == vault_id && bindex == &batch.index.to_be_bytes() + } _ => true, }) .collect::>(); diff --git a/lib/ain-ocean/src/indexer/auction.rs b/lib/ain-ocean/src/indexer/auction.rs index 0cc7cfb88f..6aaf2d5225 100644 --- a/lib/ain-ocean/src/indexer/auction.rs +++ b/lib/ain-ocean/src/indexer/auction.rs @@ -16,11 +16,6 @@ impl Index for PlaceAuctionBid { trace!("[PlaceAuctionBid] Indexing..."); let auction = VaultAuctionBatchHistory { - id: format!("{}-{}-{}", self.vault_id, self.index, ctx.tx.txid), - key: format!("{}-{}", self.vault_id, self.index), - sort: format!("{}-{}", ctx.block.height, ctx.tx_idx), - vault_id: self.vault_id, - index: ctx.tx_idx, from: self.from, amount: self.token_amount.amount, token_id: self.token_amount.token.0, @@ -28,25 +23,22 @@ impl Index for PlaceAuctionBid { }; trace!("auction : {:?}", auction); - let key = (self.vault_id, self.index, ctx.tx.txid); - services.auction.by_id.put(&key, &auction)?; - services.auction.by_height.put( - &(self.vault_id, self.index, ctx.block.height, ctx.tx_idx), - &key, - ) + let id = ( + self.vault_id, + self.index.to_be_bytes(), + ctx.block.height.to_be_bytes(), + ctx.tx.txid, + ); + services.auction.by_id.put(&id, &auction) } fn invalidate(&self, services: &Arc, ctx: &Context) -> Result<()> { trace!("[PlaceAuctionBid] Invalidating..."); - services - .auction - .by_id - .delete(&(self.vault_id, self.index, ctx.tx.txid))?; - services.auction.by_height.delete(&( + services.auction.by_id.delete(&( self.vault_id, - self.index, - ctx.block.height, - ctx.tx_idx, + self.index.to_be_bytes(), + ctx.block.height.to_be_bytes(), + ctx.tx.txid, )) } } diff --git a/lib/ain-ocean/src/lib.rs b/lib/ain-ocean/src/lib.rs index e0902d44cd..86ad1624a8 100644 --- a/lib/ain-ocean/src/lib.rs +++ b/lib/ain-ocean/src/lib.rs @@ -48,7 +48,6 @@ pub struct BlockService { pub struct AuctionService { by_id: VaultAuctionHistory, - by_height: VaultAuctionHistoryByHeight, } pub struct PoolService { @@ -157,7 +156,6 @@ impl Services { }, auction: AuctionService { by_id: VaultAuctionHistory::new(Arc::clone(&store)), - by_height: VaultAuctionHistoryByHeight::new(Arc::clone(&store)), }, result: TxResult::new(Arc::clone(&store)), pool: PoolService { diff --git a/lib/ain-ocean/src/model/vault_auction_batch_history.rs b/lib/ain-ocean/src/model/vault_auction_batch_history.rs index 0ba11786ce..e3de09459d 100644 --- a/lib/ain-ocean/src/model/vault_auction_batch_history.rs +++ b/lib/ain-ocean/src/model/vault_auction_batch_history.rs @@ -3,17 +3,11 @@ use serde::{Deserialize, Serialize}; use super::BlockContext; -pub type AuctionHistoryKey = (Txid, u32, Txid); // (vault_id, auction_batch_index, txid) -pub type AuctionHistoryByHeightKey = (Txid, u32, u32, usize); // (vault_id, auction_batch_index, block_height, txid) +pub type AuctionHistoryKey = (Txid, [u8; 4], [u8; 4], Txid); // (vault_id, auction_batch_index, block_height, txid) #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct VaultAuctionBatchHistory { - pub id: String, - pub key: String, - pub sort: String, - pub vault_id: Txid, - pub index: usize, pub from: ScriptBuf, pub amount: i64, pub token_id: u64, diff --git a/lib/ain-ocean/src/storage/mod.rs b/lib/ain-ocean/src/storage/mod.rs index 803a4d4c62..054f25d599 100644 --- a/lib/ain-ocean/src/storage/mod.rs +++ b/lib/ain-ocean/src/storage/mod.rs @@ -408,16 +408,7 @@ define_table! { } } -define_table! { - #[derive(Debug)] - pub struct VaultAuctionHistoryByHeight { - key_type = model::AuctionHistoryByHeightKey, - value_type = model::AuctionHistoryKey, - }, - SecondaryIndex = VaultAuctionHistory -} - -pub const COLUMN_NAMES: [&str; 29] = [ +pub const COLUMN_NAMES: [&str; 28] = [ Block::NAME, BlockByHeight::NAME, MasternodeStats::NAME, @@ -446,5 +437,4 @@ pub const COLUMN_NAMES: [&str; 29] = [ TransactionVout::NAME, TxResult::NAME, VaultAuctionHistory::NAME, - VaultAuctionHistoryByHeight::NAME, ];