Skip to content

Commit

Permalink
rpc: get_raw_tx: Initial impl for 2 return types.
Browse files Browse the repository at this point in the history
  • Loading branch information
ceyhunsen committed Sep 5, 2024
1 parent d966d87 commit 472d5dc
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 17 deletions.
116 changes: 107 additions & 9 deletions src/rpc/adapter/rawtransactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,88 @@
use crate::utils::encode_to_hex;
use crate::Client;
use bitcoin::{consensus::encode::deserialize_hex, BlockHash, Transaction, Txid};
use bitcoin::{consensus::encode::deserialize_hex, hex::DisplayHex, BlockHash, Transaction, Txid};
use bitcoincore_rpc::{Error, RpcApi};
use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer};
use std::str::FromStr;

#[derive(Clone, PartialEq, Eq, Debug, Deserialize)]
pub enum GetrawtransactionReturn {
NoneVerbose(String),
Verbose(Box<bitcoincore_rpc::json::GetRawTransactionResult>),
}
impl Serialize for GetrawtransactionReturn {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
GetrawtransactionReturn::NoneVerbose(stri) => serializer.serialize_str(stri),
GetrawtransactionReturn::Verbose(strct) => {
let mut state = serializer.serialize_struct("GetRawTransactionResult", 14)?;

if strct.in_active_chain.is_some() {
state.serialize_field("in_active_chain", &strct.in_active_chain)?;
}
state
.serialize_field("hex", &strct.hex.to_hex_string(bitcoin::hex::Case::Lower))?;
state.serialize_field("txid", &strct.txid)?;
state.serialize_field("hash", &strct.hash)?;
state.serialize_field("size", &strct.size)?;
state.serialize_field("vsize", &strct.vsize)?;
state.serialize_field("version", &strct.version)?;
state.serialize_field("locktime", &strct.locktime)?;

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
struct Vin {
sequence: u32,
}
let vins: Vec<Vin> = strct
.vin
.iter()
.map(|vin| Vin {
sequence: vin.sequence,
})
.collect();
state.serialize_field("vin", &vins)?;

state.serialize_field("vout", &strct.vout)?;
if strct.blockhash.is_some() {
state.serialize_field("blockhash", &strct.blockhash)?;
}
if strct.confirmations.is_some() {
state.serialize_field("confirmations", &strct.confirmations)?;
}
if strct.time.is_some() {
state.serialize_field("time", &strct.time)?;
}
if strct.blocktime.is_some() {
state.serialize_field("blocktime", &strct.blocktime)?;
}
state.end()
}
}
}
}
pub fn getrawtransaction(
client: &Client,
txid: String,
verbose: Option<bool>,
blockhash: Option<BlockHash>,
) -> Result<String, Error> {
) -> Result<GetrawtransactionReturn, Error> {
let txid = Txid::from_str(&txid).unwrap();

let res: String = match verbose {
let res: GetrawtransactionReturn = match verbose {
None | Some(false) => {
let tx = client.get_raw_transaction(&txid, blockhash.as_ref())?;

encode_to_hex(&tx)
GetrawtransactionReturn::NoneVerbose(encode_to_hex(&tx))
}
Some(true) => {
let tx = client.get_raw_transaction_info(&txid, blockhash.as_ref())?;
let tx: bitcoincore_rpc::json::GetRawTransactionResult =
client.get_raw_transaction_info(&txid, blockhash.as_ref())?;

serde_json::to_string_pretty(&tx).unwrap()
GetrawtransactionReturn::Verbose(Box::new(tx))
}
};

Expand Down Expand Up @@ -67,11 +127,13 @@ pub fn signrawtransactionwithwallet(
mod tests {
use crate::{
ledger,
rpc::adapter::GetrawtransactionReturn,
utils::{decode_from_hex, encode_to_hex},
Client, RpcApiWrapper,
};
use bitcoin::{
absolute::LockTime, transaction::Version, Amount, OutPoint, Transaction, TxIn, TxOut, Txid,
absolute::LockTime, consensus::Decodable, transaction::Version, Amount, OutPoint,
Transaction, TxIn, TxOut, Txid,
};
use bitcoincore_rpc::RpcApi;

Expand All @@ -96,9 +158,45 @@ mod tests {
let tx = client.get_raw_transaction(&txid, None).unwrap();

let encoded_tx = super::getrawtransaction(&client, txid.to_string(), None, None).unwrap();
let encoded_tx = decode_from_hex(encoded_tx).unwrap();

assert_eq!(tx, encoded_tx);
if let GetrawtransactionReturn::NoneVerbose(encoded_tx) = encoded_tx {
assert_eq!(tx, decode_from_hex(encoded_tx).unwrap());
} else {
panic!("");
}
}

#[test]
fn getrawtransactionverbose() {
let client = Client::new("getrawtransaction", bitcoincore_rpc::Auth::None).unwrap();

let address = client.get_new_address(None, None).unwrap().assume_checked();
let txid = client
.send_to_address(
&address,
Amount::from_sat(0x45),
None,
None,
None,
None,
None,
None,
)
.unwrap();

let tx = client.get_raw_transaction(&txid, None).unwrap();

let encoded_tx =
super::getrawtransaction(&client, txid.to_string(), Some(true), None).unwrap();

if let GetrawtransactionReturn::Verbose(encoded_tx) = encoded_tx {
assert_eq!(
tx,
Transaction::consensus_decode(&mut encoded_tx.hex.as_slice()).unwrap()
);
} else {
panic!("Should be verbose variant");
}
}

#[test]
Expand Down
17 changes: 9 additions & 8 deletions src/rpc/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
//! This crate implements [`jsonrpsee`] traits, using [`adapter`] functions.
//! This is the entry point for the RPC calls.
use super::adapter;
use super::adapter::{self, GetrawtransactionReturn};
use crate::Client;
use bitcoin::BlockHash;
use bitcoin::{BlockHash, Txid};
use bitcoincore_rpc::json::GetTransactionResult;
use jsonrpsee::core::async_trait;
use jsonrpsee::proc_macros::rpc;
use jsonrpsee::types::ErrorObjectOwned;
Expand Down Expand Up @@ -57,7 +58,7 @@ pub trait Rpc {
txid: String,
verbose: Option<bool>,
blockhash: Option<BlockHash>,
) -> Result<String, ErrorObjectOwned>;
) -> Result<GetrawtransactionReturn, ErrorObjectOwned>;

#[method(name = "sendrawtransaction")]
async fn sendrawtransaction(
Expand All @@ -79,7 +80,7 @@ pub trait Rpc {
txid: String,
include_watchonly: Option<bool>,
verbose: Option<bool>,
) -> Result<String, ErrorObjectOwned>;
) -> Result<GetTransactionResult, ErrorObjectOwned>;

#[method(name = "sendtoaddress")]
async fn sendtoaddress(
Expand All @@ -93,7 +94,7 @@ pub trait Rpc {
conf_target: Option<u32>,
estimate_mode: Option<&str>,
avoid_reuse: Option<bool>,
) -> Result<String, ErrorObjectOwned>;
) -> Result<Txid, ErrorObjectOwned>;

#[method(name = "fundrawtransaction")]
async fn fundrawtransaction(
Expand Down Expand Up @@ -165,7 +166,7 @@ impl RpcServer for Client {
txid: String,
verbose: Option<bool>,
blockhash: Option<BlockHash>,
) -> Result<String, ErrorObjectOwned> {
) -> Result<GetrawtransactionReturn, ErrorObjectOwned> {
to_jsonrpsee_error(adapter::getrawtransaction(self, txid, verbose, blockhash))
}

Expand All @@ -190,7 +191,7 @@ impl RpcServer for Client {
txid: String,
include_watchonly: Option<bool>,
verbose: Option<bool>,
) -> Result<String, ErrorObjectOwned> {
) -> Result<GetTransactionResult, ErrorObjectOwned> {
to_jsonrpsee_error(adapter::gettransaction(
self,
txid,
Expand All @@ -210,7 +211,7 @@ impl RpcServer for Client {
conf_target: Option<u32>,
estimate_mode: Option<&str>,
avoid_reuse: Option<bool>,
) -> Result<String, ErrorObjectOwned> {
) -> Result<Txid, ErrorObjectOwned> {
to_jsonrpsee_error(adapter::sendtoaddress(
self,
address,
Expand Down

0 comments on commit 472d5dc

Please sign in to comment.