Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/ain-ocean/src/api/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ mod tests {
fn should_next_with_value() {
let items: Vec<Item> = vec![Item::new("0", "a"), Item::new("1", "b")];

let next = ApiPagedResponse::next(items, Some("b")).page.next;
let next = ApiPagedResponse::next(items, Some("b".to_string()))
.page
.next;
assert_eq!(next, Some("b".into()));
}

Expand Down
83 changes: 72 additions & 11 deletions lib/ain-ocean/src/api/transactions.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,85 @@
use std::sync::Arc;

use axum::{extract::Path, routing::get, Router};
use defichain_rpc::{Client, RpcApi};
use axum::{
extract::{Path, Query},
routing::get,
Json, Router,
};
use bitcoin::Txid;
use serde::Deserialize;

use crate::{
api_paged_response::ApiPagedResponse,
api_query::PaginationQuery,
model::{Transaction, TransactionVin, TransactionVout},
repository::RepositoryOps,
Result, SERVICES,
};

#[derive(Deserialize)]
struct TransactionId {
id: String,
id: Txid,
}

async fn get_transaction(Path(TransactionId { id }): Path<TransactionId>) -> String {
format!("Details of transaction with id {}", id)
async fn get_transaction(
Path(TransactionId { id }): Path<TransactionId>,
Comment thread
nagarajm22 marked this conversation as resolved.
) -> Result<Json<Option<Transaction>>> {
format!("Details of transaction with id {}", id);
let transactions = SERVICES.transaction.by_id.get(&id)?;
Ok(Json(transactions))
}

async fn get_vins(Path(TransactionId { id }): Path<TransactionId>) -> String {
format!("Vins for transaction with id {}", id)
async fn get_vins(
Query(query): Query<PaginationQuery>,
) -> Result<Json<ApiPagedResponse<TransactionVin>>> {
let transaction_list = SERVICES
.transaction
.vin_by_id
.list(None)?
.take(query.size)
.map(|item| {
let (txid, id) = item?;
let b = SERVICES
.transaction
.vin_by_id
.get(&txid)?
.ok_or("Missing block index")?;

Ok(b)
})
.collect::<Result<Vec<_>>>()?;

Ok(Json(ApiPagedResponse::of(
transaction_list,
query.size,
|transaction_list| transaction_list.id.clone(),
)))
}

async fn get_vouts(Path(TransactionId { id }): Path<TransactionId>) -> String {
format!("Vouts for transaction with id {}", id)
//get list of vout transaction, by passing id which contains txhash + vout_idx
async fn get_vouts(
Query(query): Query<PaginationQuery>,
) -> Result<Json<ApiPagedResponse<TransactionVout>>> {
let transaction_list = SERVICES
.transaction
.vout_by_id
.list(None)?
.take(query.size)
.map(|item| {
let (txid, id) = item?;
let b = SERVICES
.transaction
.vout_by_id
.get(&txid)?
.ok_or("Missing block index")?;

Ok(b)
})
.collect::<Result<Vec<_>>>()?;

Ok(Json(ApiPagedResponse::of(
transaction_list,
query.size,
|transaction_list| transaction_list.id.clone(),
)))
}

pub fn router(state: Arc<Client>) -> Router {
Expand Down
1 change: 1 addition & 0 deletions lib/ain-ocean/src/indexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod auction;
mod masternode;
mod oracle;
mod pool;
pub mod transaction;
pub mod tx_result;

use defichain_rpc::RpcApi;
Expand Down
94 changes: 94 additions & 0 deletions lib/ain-ocean/src/indexer/transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use bitcoin::{blockdata::locktime::absolute::LockTime, Txid};
use dftx_rs::{Block, Transaction};
use log::debug;

use super::BlockContext;
use crate::{
indexer::Result,
model::{
Transaction as TrasnactionMapper, TransactionVin, TransactionVinScript, TransactionVinVout,
TransactionVinVoutScript, TransactionVout, TransactionVoutScript,
},
repository::RepositoryOps,
SERVICES,
};

pub fn index_transactions(ctx: &BlockContext, tx: Transaction) -> Result<()> {
debug!("[CreateTransaction] Indexing...");
let tx_id = tx.txid();

let lock_time_as_i32 = match tx.lock_time {
LockTime::Blocks(value) => value.to_consensus_u32(),
LockTime::Seconds(value) => value.to_consensus_u32(),
};
let total_vout_value: u64 = tx.output.iter().map(|output| output.value.to_sat()).sum();
let weight = tx.weight();
let weight_i32 = weight.to_vbytes_ceil() as i32;

let trx = TrasnactionMapper {
id: tx_id,
order: 0,
block: ctx.clone(),
txid: tx_id.to_string(),
hash: ctx.hash.to_string(),
version: tx.version.0,
size: tx.total_size() as i32,
v_size: tx.vsize() as i32,
weight: weight_i32,
total_vout_value: total_vout_value.to_string(),
lock_time: lock_time_as_i32 as i32,
vin_count: tx.input.len() as i32,
vout_count: tx.output.len() as i32,
};
// Index transaction
SERVICES.transaction.by_id.put(&tx_id, &trx)?;
// Indexing transaction vin
for (vin_idx, vin) in tx.input.iter().enumerate() {
let trx_vin = TransactionVin {
id: format!("{}-{}", tx_id, vin_idx),
txid: tx_id.to_string(),
coinbase: vin.script_sig.to_string(),
vout: TransactionVinVout {
id: format!("{}-{}-vout", tx_id, vin_idx),
txid: tx_id.to_string(),
n: vin.previous_output.vout as i32,
value: "0".to_string(),
token_id: 0,
script: TransactionVinVoutScript {
hex: vin.script_sig.to_string(),
},
},
script: TransactionVinScript {
hex: vin.script_sig.to_string(),
},
tx_in_witness: vec![],
sequence: vin.sequence.to_string(),
};

SERVICES.transaction.vin_by_id.put(&tx_id, &trx_vin)?;
}
// Index transaction vout
for (vout_idx, vout) in tx.output.iter().enumerate() {
let trx_vout = TransactionVout {
id: format!("{}-{}", tx_id, vout_idx),
txid: tx_id.to_string(),
n: vout_idx as i32,
value: vout.value.to_string(),
token_id: 0,
script: TransactionVoutScript {
hex: vout.script_pubkey.to_string(),
r#type: "pubkey".to_string(),
},
};
SERVICES.transaction.vout_by_id.put(&tx_id, &trx_vout)?;
// .put(&format!("{}-{}", tx_id, vout_idx), &trx_vout)?; //need
}

Ok(())
}

pub fn invalidate_transaction(ctx: &BlockContext, tx: Txid, idx: usize) -> Result<()> {
debug!("[CreateMasternode] Invalidating...");
SERVICES.transaction.by_id.delete(&tx)?;
Ok(())
}
22 changes: 20 additions & 2 deletions lib/ain-ocean/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@ use std::{path::PathBuf, sync::Arc};

pub use api::ocean_router;
use error::OceanError;
pub use indexer::{index_block, invalidate_block, tx_result, BlockV2Info};
pub use indexer::{
index_block, invalidate_block,
transaction::{index_transactions, invalidate_transaction},
tx_result, BlockV2Info,
};
use model::TransactionVin;
use repository::{
AuctionHistoryByHeightRepository, AuctionHistoryRepository, BlockByHeightRepository,
BlockRepository, MasternodeByHeightRepository, MasternodeRepository, MasternodeStatsRepository,
PoolSwapRepository, RawBlockRepository, TxResultRepository,
PoolSwapRepository, RawBlockRepository, TransactionRepository, TransactionVinRepository,
TransactionVoutRepository, TxResultRepository,
};
pub mod api;
mod model;
Expand Down Expand Up @@ -50,13 +56,20 @@ pub struct PoolService {
by_id: PoolSwapRepository,
}

pub struct TransactionService {
by_id: TransactionRepository,
vin_by_id: TransactionVinRepository,
vout_by_id: TransactionVoutRepository,
}

pub struct Services {
masternode: MasternodeService,
block: BlockService,
auction: AuctionService,
result: TxResultRepository,
pool: PoolService,
client: Arc<Client>,
transaction: TransactionService,
}

impl Services {
Expand Down Expand Up @@ -89,6 +102,11 @@ impl Services {
pool: PoolService {
by_id: PoolSwapRepository::new(Arc::clone(&store)),
},
transaction: TransactionService {
by_id: TransactionRepository::new(Arc::clone(&store)),
vin_by_id: TransactionVinRepository::new(Arc::clone(&store)),
vout_by_id: TransactionVoutRepository::new(Arc::clone(&store)),
},
client,
})
}
Expand Down
3 changes: 2 additions & 1 deletion lib/ain-ocean/src/model/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use bitcoin::Txid;
use serde::{Deserialize, Serialize};

use super::BlockContext;

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
pub id: String,
pub id: Txid,
pub order: i32,
pub block: BlockContext,
pub txid: String,
Expand Down
26 changes: 26 additions & 0 deletions lib/ain-ocean/src/repository/transaction.rs
Original file line number Diff line number Diff line change
@@ -1 +1,27 @@
use std::sync::Arc;

use ain_db::LedgerColumn;
use ain_macros::Repository;
use bitcoin::{BlockHash, Txid};

use super::RepositoryOps;
use crate::{
model::Transaction,
storage::{columns, ocean_store::OceanStore},
Result,
};
#[derive(Repository)]
#[repository(K = "Txid", V = "Transaction")]
pub struct TransactionRepository {
pub store: Arc<OceanStore>,
col: LedgerColumn<columns::Transaction>,
}

impl TransactionRepository {
pub fn new(store: Arc<OceanStore>) -> Self {
Self {
col: store.column(),
store,
}
}
}
27 changes: 27 additions & 0 deletions lib/ain-ocean/src/repository/transaction_vin.rs
Original file line number Diff line number Diff line change
@@ -1 +1,28 @@
use std::sync::Arc;

use ain_db::LedgerColumn;
use ain_macros::Repository;
use bitcoin::Txid;

use super::RepositoryOps;
use crate::{
model::TransactionVin,
storage::{columns, ocean_store::OceanStore},
Result,
};

#[derive(Repository)]
#[repository(K = "Txid", V = "TransactionVin")]
pub struct TransactionVinRepository {
pub store: Arc<OceanStore>,
col: LedgerColumn<columns::TransactionVin>,
}

impl TransactionVinRepository {
pub fn new(store: Arc<OceanStore>) -> Self {
Self {
col: store.column(),
store,
}
}
}
27 changes: 27 additions & 0 deletions lib/ain-ocean/src/repository/transaction_vout.rs
Original file line number Diff line number Diff line change
@@ -1 +1,28 @@
use std::sync::Arc;

use ain_db::LedgerColumn;
use ain_macros::Repository;
use bitcoin::Txid;

use super::RepositoryOps;
use crate::{
model::TransactionVout,
storage::{columns, ocean_store::OceanStore},
Result,
};

#[derive(Repository)]
#[repository(K = "Txid", V = "TransactionVout")]
pub struct TransactionVoutRepository {
pub store: Arc<OceanStore>,
col: LedgerColumn<columns::TransactionVout>,
}

impl TransactionVoutRepository {
pub fn new(store: Arc<OceanStore>) -> Self {
Self {
col: store.column(),
store,
}
}
}
20 changes: 18 additions & 2 deletions lib/ain-ocean/src/storage/columns/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use ain_db::{Column, ColumnName, TypedColumn};
use bitcoin::{BlockHash, Txid};

use crate::model;
#[derive(Debug)]
pub struct Transaction;

Expand All @@ -8,9 +10,23 @@ impl ColumnName for Transaction {
}

impl Column for Transaction {
type Index = String;
type Index = Txid;
}

impl TypedColumn for Transaction {
type Type = String;
type Type = model::Transaction;
}

pub struct TransactionByBlockHash;

impl ColumnName for TransactionByBlockHash {
const NAME: &'static str = "transaction_by_block_hash";
}

impl Column for TransactionByBlockHash {
type Index = BlockHash;
Comment thread
nagarajm22 marked this conversation as resolved.
}

impl TypedColumn for TransactionByBlockHash {
type Type = model::Transaction;
}
Loading