Skip to content

Commit

Permalink
Add spent txs to get_transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
Duddino committed Oct 6, 2024
1 parent a0d7d98 commit dee5082
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 59 deletions.
2 changes: 1 addition & 1 deletion MPW
5 changes: 5 additions & 0 deletions src-tauri/src/address_index/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod types;
use block_source::BlockSource;
use database::Database;
use futures::StreamExt;
use types::Vin;

pub struct AddressIndex<D: Database, B: BlockSource> {
database: D,
Expand All @@ -35,6 +36,10 @@ impl<D: Database + Send, B: BlockSource + Send> AddressIndex<D, B> {
pub async fn get_address_txids(&self, address: &str) -> crate::error::Result<Vec<String>> {
self.database.get_address_txids(address).await
}

pub async fn get_txid_from_vin(&self, vin: &Vin) -> crate::error::Result<Option<String>> {
self.database.get_txid_from_vin(vin).await
}
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/address_index/pivx_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl PIVXRpc {
let res = self.client.request(rpc, params).await;
match res {
Ok(res) => Ok(res),
Err(_) => {res.unwrap(); Err(PIVXErrors::InvalidResponse)},
Err(_) => Err(PIVXErrors::InvalidResponse),
}
}
}
Expand Down
15 changes: 7 additions & 8 deletions src-tauri/src/address_index/sql_lite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@ COMMIT;
}

fn connect(&self) -> crate::error::Result<Connection> {
Ok(Connection::open(&self.path)?)
Ok(Connection::open(&self.path)?)
}
}

impl Database for SqlLite {
async fn get_address_txids(&self, address: &str) -> crate::error::Result<Vec<String>> {
let mut connection = self.connect()?;
let mut stmt = connection
.prepare("SELECT txid FROM transactions WHERE address=?1")?;
let mut connection = self.connect()?;
let mut stmt = connection.prepare("SELECT txid FROM transactions WHERE address=?1")?;
let mut rows = stmt.query([address])?;
let mut txids = vec![];
while let Some(row) = rows.next()? {
Expand All @@ -52,7 +51,7 @@ impl Database for SqlLite {
where
I: Iterator<Item = Tx>,
{
let mut connection = self.connect()?;
let mut connection = self.connect()?;
let connection = connection.transaction()?;
for tx in txs {
let txid = &tx.txid;
Expand All @@ -74,9 +73,9 @@ impl Database for SqlLite {
}

async fn get_txid_from_vin(&self, vin: &Vin) -> crate::error::Result<Option<String>> {
let mut connection = self.connect()?;
let mut stmt = connection
.prepare("SELECT spender_txid FROM vin WHERE txid=?1 AND n=?2;")?;
let mut connection = self.connect()?;
let mut stmt =
connection.prepare("SELECT spender_txid FROM vin WHERE txid=?1 AND n=?2;")?;
let mut rows = stmt.query(params![vin.txid, vin.n])?;

if let Some(row) = rows.next()? {
Expand Down
8 changes: 4 additions & 4 deletions src-tauri/src/binary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ impl Binary {
}

//#[cfg(test)]
// pub fn get_data_dir() -> Result<PathBuf, PIVXErrors> {
// use tempdir::TempDir;
// Ok(TempDir::new("pivx-rust")?.into_path())
// }
// pub fn get_data_dir() -> Result<PathBuf, PIVXErrors> {
// use tempdir::TempDir;
// Ok(TempDir::new("pivx-rust")?.into_path())
// }

fn new_by_path<T: BinaryDefinition + Send>(
path: &str,
Expand Down
149 changes: 105 additions & 44 deletions src-tauri/src/explorer/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
use jsonrpsee::rpc_params;
use address_index::address_extractor;
use error::PIVXErrors;
use futures::{StreamExt, TryStreamExt};
use tokio::sync::OnceCell;
use jsonrpsee::rpc_params;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use tokio::sync::OnceCell;
// TODO: remove this import
use crate::*;

use crate::address_index::{
block_source::BlockSource, database::Database, pivx_rpc::PIVXRpc, AddressIndex,
block_source::BlockSource,
database::Database,
pivx_rpc::PIVXRpc,
sql_lite::SqlLite,
types::{Tx, Vin},
AddressIndex,
};
use global_function_macro::generate_global_functions;


//#[derive(Deserialize, Serialize)]
type TxHexWithBlockCount = (String, u64, u64);
/*struct TxHexWithBlockCount {
hex: String,
time: u64,
height: u64,
}*/

pub struct Explorer<D, B>
where
Expand Down Expand Up @@ -39,23 +53,25 @@ where
static EXPLORER: OnceCell<DefaultExplorer> = OnceCell::const_new();

async fn get_explorer() -> &'static DefaultExplorer {
EXPLORER.get_or_init(|| async {
let pivx_definition = PIVXDefinition;
let pivx = binary::Binary::new_by_fetching(&pivx_definition)
.await
.expect("Failed to run PIVX");
let pivx_rpc = PIVXRpc::new(&format!("http://127.0.0.1:{}", RPC_PORT))
.await
.unwrap();
let mut address_index = AddressIndex::new(
SqlLite::new(PathBuf::from("/home/duddino/test.sqlite"))
EXPLORER
.get_or_init(|| async {
let pivx_definition = PIVXDefinition;
let pivx = binary::Binary::new_by_fetching(&pivx_definition)
.await
.unwrap(),
pivx_rpc.clone(),
);
std::mem::forget(pivx);
Explorer::new(address_index, pivx_rpc)
}).await
.expect("Failed to run PIVX");
let pivx_rpc = PIVXRpc::new(&format!("http://127.0.0.1:{}", RPC_PORT))
.await
.unwrap();
let mut address_index = AddressIndex::new(
SqlLite::new(PathBuf::from("/home/duddino/test.sqlite"))
.await
.unwrap(),
pivx_rpc.clone(),
);
std::mem::forget(pivx);
Explorer::new(address_index, pivx_rpc)
})
.await
}

#[generate_global_functions]
Expand All @@ -71,35 +87,81 @@ where
.await?;
let json: serde_json::Value = self
.pivx_rpc
.call("getblock", rpc_params![block_hash])
.call("getblock", rpc_params![block_hash, 2])
.await?;
Ok(json.to_string())
Ok(json.to_string())
}

pub async fn get_block_count(&self) -> crate::error::Result<u64> {
Ok(self.pivx_rpc.call("getblockcount", rpc_params![]).await?)
Ok(self.pivx_rpc.call("getblockcount", rpc_params![]).await?)
}

/// Gets all raw transactions containing one of `address`
/// TODO: add also spent txs
pub async fn get_txs(&self, addresses: Vec<&str>) -> crate::error::Result<Vec<String>> {
let mut txs = vec![];
for address in addresses {
for txid in self.address_index.get_address_txids(address).await? {
txs.push(self.get_transaction(&txid).await?);
}
}
Ok(txs)
pub async fn get_txs(
&self,
addresses: Vec<&str>,
) -> crate::error::Result<Vec<TxHexWithBlockCount>> {
let mut txs = vec![];
for address in addresses {
for txid in self.address_index.get_address_txids(address).await? {
if let Some(tx) = self.get_transaction(&txid).await.ok() {
txs.push(tx);
}
}
}
Ok(txs)
}

pub async fn get_tx_from_vin(
&self,
vin: Vin,
) -> crate::error::Result<Option<TxHexWithBlockCount>> {
let txid = self.address_index.get_txid_from_vin(&vin).await?;
if let Some(txid) = txid {
Ok(self.get_transaction(&txid).await.ok())
} else {
Ok(None)
}
}

/// Gets raw transaction in hex format
pub async fn get_transaction(&self, txid: &str) -> crate::error::Result<String> {
pub async fn get_transaction(&self, txid: &str) -> crate::error::Result<TxHexWithBlockCount> {
use serde::Deserialize;
#[derive(Deserialize)]
struct TxResponse {
hex: String,
blockhash: String,
confirmations: u64,
}
#[derive(Deserialize)]
struct BlockResponse {
height: u64,
time: u64,
}

Ok(self.pivx_rpc.call("getrawtransaction", rpc_params![txid]).await?)
let TxResponse {
hex,
blockhash,
confirmations,
} = self
.pivx_rpc
.call("getrawtransaction", rpc_params![txid, true])
.await?;
if confirmations == 0 {
return Err(PIVXErrors::InvalidResponse);
}
let BlockResponse { height, time } = self
.pivx_rpc
.call("getblock", rpc_params![blockhash])
.await?;
Ok((hex, height, time))
}

pub async fn send_transaction(&self, transaction: &str) -> crate::error::Result<String> {
Ok(self.pivx_rpc.call("sendtransaction", rpc_params![transaction]).await?)
Ok(self
.pivx_rpc
.call("sendrawtransaction", rpc_params![transaction])
.await?)
}
}

Expand All @@ -109,8 +171,8 @@ mod test {
use std::time::Duration;
#[tokio::test]
async fn temp_test() -> crate::error::Result<()> {
use std::path::PathBuf;
use crate::*;
use crate::*;
use std::path::PathBuf;
let pivx_definition = PIVXDefinition;
let pivx = binary::Binary::new_by_fetching(&pivx_definition)
.await
Expand All @@ -124,12 +186,11 @@ mod test {
.unwrap(),
pivx_rpc.clone(),
);
let explorer = Explorer::new(address_index, pivx_rpc);
tokio::time::sleep(Duration::from_secs(60)).await;
std::mem::forget(pivx);

println!("{}", explorer.get_block(123).await?);
Ok(())
}
let explorer = Explorer::new(address_index, pivx_rpc);
tokio::time::sleep(Duration::from_secs(60)).await;
std::mem::forget(pivx);

println!("{}", explorer.get_block(123).await?);
Ok(())
}
}
9 changes: 8 additions & 1 deletion src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,14 @@ fn main() {
use explorer::auto_generated::*;

tauri::Builder::default()
.invoke_handler(tauri::generate_handler![explorer_get_block, explorer_get_block_count, explorer_get_txs, explorer_get_transaction, explorer_send_transaction])
.invoke_handler(tauri::generate_handler![
explorer_get_block,
explorer_get_block_count,
explorer_get_txs,
explorer_get_transaction,
explorer_send_transaction,
explorer_get_tx_from_vin
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Expand Down

0 comments on commit dee5082

Please sign in to comment.