Skip to content

Commit d0cc7d0

Browse files
committed
feat: add from_string to Transaction
1 parent 0c18032 commit d0cc7d0

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

bdk-ffi/src/bdk.udl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ interface TransactionError {
264264
ParseFailed();
265265
UnsupportedSegwitFlag(u8 flag);
266266
OtherTransactionErr();
267+
InvalidHexString();
267268
};
268269

269270
// ------------------------------------------------------------------------

bdk-ffi/src/bitcoin.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use bdk_wallet::bitcoin::consensus::encode::serialize;
1414
use bdk_wallet::bitcoin::consensus::Decodable;
1515
use bdk_wallet::bitcoin::hashes::sha256::Hash as BitcoinSha256Hash;
1616
use bdk_wallet::bitcoin::hashes::sha256d::Hash as BitcoinDoubleSha256Hash;
17+
use bdk_wallet::bitcoin::hex::FromHex;
1718
use bdk_wallet::bitcoin::io::Cursor;
1819
use bdk_wallet::bitcoin::secp256k1::Secp256k1;
1920
use bdk_wallet::bitcoin::Amount as BdkAmount;
@@ -333,6 +334,13 @@ impl Transaction {
333334
Ok(Transaction(tx))
334335
}
335336

337+
/// Creates a new `Transaction` instance from a hexadecimal string representation.
338+
#[uniffi::constructor]
339+
pub fn from_string(tx_hex: String) -> Result<Self, TransactionError> {
340+
let tx_bytes = Vec::from_hex(&tx_hex).map_err(|_| TransactionError::InvalidHexString)?;
341+
Self::new(tx_bytes)
342+
}
343+
336344
/// Computes the Txid.
337345
/// Hashes the transaction excluding the segwit data (i.e. the marker, flag bytes, and the witness fields themselves).
338346
pub fn compute_txid(&self) -> Arc<Txid> {
@@ -677,6 +685,8 @@ impl_hash_like!(TxMerkleNode, BitcoinDoubleSha256Hash);
677685
mod tests {
678686
use crate::bitcoin::Address;
679687
use crate::bitcoin::Network;
688+
use crate::bitcoin::Transaction;
689+
use crate::error::TransactionError;
680690

681691
#[test]
682692
fn test_is_valid_for_network() {
@@ -1032,4 +1042,41 @@ mod tests {
10321042
let segwit_data = segwit.to_address_data();
10331043
println!("Segwit data: {:#?}", segwit_data);
10341044
}
1045+
1046+
#[test]
1047+
fn test_transaction_from_string() {
1048+
// A simple transaction hex (mainnet coinbase transaction)
1049+
let tx_hex = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000";
1050+
1051+
// Test successful parsing
1052+
let tx = Transaction::from_string(tx_hex.to_string()).unwrap();
1053+
1054+
// Verify the transaction was parsed correctly
1055+
assert_eq!(tx.version(), 1);
1056+
assert_eq!(tx.input().len(), 1);
1057+
assert_eq!(tx.output().len(), 1);
1058+
assert!(tx.is_coinbase());
1059+
1060+
// Test that serializing and re-parsing gives the same result
1061+
let serialized = tx.serialize();
1062+
let tx2 = Transaction::new(serialized).unwrap();
1063+
assert_eq!(
1064+
tx.compute_txid().to_string(),
1065+
tx2.compute_txid().to_string()
1066+
);
1067+
1068+
// Test invalid hex string
1069+
let invalid_hex = "invalid_hex_string";
1070+
let result = Transaction::from_string(invalid_hex.to_string());
1071+
assert!(result.is_err());
1072+
match result.unwrap_err() {
1073+
TransactionError::InvalidHexString => {}
1074+
_ => panic!("Expected InvalidHexString error"),
1075+
}
1076+
1077+
// Test hex string with invalid transaction data
1078+
let invalid_tx_hex = "deadbeef";
1079+
let result = Transaction::from_string(invalid_tx_hex.to_string());
1080+
assert!(result.is_err());
1081+
}
10351082
}

bdk-ffi/src/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,9 @@ pub enum TransactionError {
768768
// This is required because the bdk::bitcoin::consensus::encode::Error is non-exhaustive
769769
#[error("other transaction error")]
770770
OtherTransactionErr,
771+
772+
#[error("invalid hex string")]
773+
InvalidHexString,
771774
}
772775

773776
#[derive(Debug, thiserror::Error, uniffi::Error)]

0 commit comments

Comments
 (0)