diff --git a/examples/deploy.rs b/examples/deploy.rs index 490821a..403c102 100644 --- a/examples/deploy.rs +++ b/examples/deploy.rs @@ -4,7 +4,9 @@ use argh::FromArgs; use bitcoin::secp256k1::Secp256k1; use bitcoin::{Address, Network, PrivateKey}; use log::{debug, info}; -use ord_rs::wallet::{CreateCommitTransactionArgsV2, RevealTransactionArgs}; +use ord_rs::wallet::{ + CreateCommitTransactionArgsV2, RevealTransactionArgs, SignCommitTransactionArgs, +}; use ord_rs::{Brc20, OrdTransactionBuilder}; use utils::rpc_client; @@ -83,26 +85,37 @@ async fn main() -> anyhow::Result<()> { _ => panic!("invalid script type"), }; - let commit_tx = builder - .build_commit_transaction_with_fixed_fees( - network, - CreateCommitTransactionArgsV2 { + let commit_tx = builder.build_commit_transaction_with_fixed_fees( + network, + CreateCommitTransactionArgsV2 { + inputs: inputs.clone(), + inscription: Brc20::deploy(ticker, amount, Some(limit), None), + txin_script_pubkey: sender_address.script_pubkey(), + leftovers_recipient: sender_address.clone(), + commit_fee, + reveal_fee, + }, + )?; + let signed_commit_tx = builder + .sign_commit_transaction( + commit_tx.unsigned_tx, + SignCommitTransactionArgs { inputs, - inscription: Brc20::deploy(ticker, amount, Some(limit), None), txin_script_pubkey: sender_address.script_pubkey(), - leftovers_recipient: sender_address.clone(), - commit_fee, - reveal_fee, }, ) .await?; - debug!("commit transaction: {commit_tx:?}"); + + debug!("commit transaction: {signed_commit_tx:?}"); let commit_txid = if args.dry_run { - commit_tx.tx.txid() + signed_commit_tx.txid() } else { - info!("broadcasting Commit transaction: {}", commit_tx.tx.txid()); - rpc_client::broadcast_transaction(&commit_tx.tx, network).await? + info!( + "broadcasting Commit transaction: {}", + signed_commit_tx.txid() + ); + rpc_client::broadcast_transaction(&signed_commit_tx, network).await? }; info!("Commit transaction broadcasted: {}", commit_txid); diff --git a/examples/mint.rs b/examples/mint.rs index 8550509..7c39ad9 100644 --- a/examples/mint.rs +++ b/examples/mint.rs @@ -4,7 +4,9 @@ use argh::FromArgs; use bitcoin::secp256k1::Secp256k1; use bitcoin::{Address, Network, PrivateKey}; use log::{debug, info}; -use ord_rs::wallet::{CreateCommitTransactionArgsV2, RevealTransactionArgs}; +use ord_rs::wallet::{ + CreateCommitTransactionArgsV2, RevealTransactionArgs, SignCommitTransactionArgs, +}; use ord_rs::{Brc20, OrdTransactionBuilder}; use self::utils::rpc_client; @@ -78,26 +80,37 @@ async fn main() -> anyhow::Result<()> { _ => panic!("invalid script type"), }; - let commit_tx = builder - .build_commit_transaction_with_fixed_fees( - network, - CreateCommitTransactionArgsV2 { + let commit_tx = builder.build_commit_transaction_with_fixed_fees( + network, + CreateCommitTransactionArgsV2 { + inputs: inputs.clone(), + inscription: Brc20::mint(ticker, amount), + txin_script_pubkey: sender_address.script_pubkey(), + leftovers_recipient: sender_address.clone(), + commit_fee, + reveal_fee, + }, + )?; + + let signed_commit_tx = builder + .sign_commit_transaction( + commit_tx.unsigned_tx, + SignCommitTransactionArgs { inputs, - inscription: Brc20::mint(ticker, amount), txin_script_pubkey: sender_address.script_pubkey(), - leftovers_recipient: sender_address.clone(), - commit_fee, - reveal_fee, }, ) .await?; - debug!("commit transaction: {commit_tx:?}"); + debug!("commit transaction: {signed_commit_tx:?}"); let commit_txid = if args.dry_run { - commit_tx.tx.txid() + signed_commit_tx.txid() } else { - info!("broadcasting Commit transaction: {}", commit_tx.tx.txid()); - rpc_client::broadcast_transaction(&commit_tx.tx, network).await? + info!( + "broadcasting Commit transaction: {}", + signed_commit_tx.txid() + ); + rpc_client::broadcast_transaction(&signed_commit_tx, network).await? }; info!("Commit transaction broadcasted: {}", commit_txid); diff --git a/examples/transfer.rs b/examples/transfer.rs index 645a441..909fc6e 100644 --- a/examples/transfer.rs +++ b/examples/transfer.rs @@ -4,7 +4,9 @@ use argh::FromArgs; use bitcoin::secp256k1::Secp256k1; use bitcoin::{Address, Network, PrivateKey}; use log::{debug, info}; -use ord_rs::wallet::{CreateCommitTransactionArgsV2, RevealTransactionArgs}; +use ord_rs::wallet::{ + CreateCommitTransactionArgsV2, RevealTransactionArgs, SignCommitTransactionArgs, +}; use ord_rs::{Brc20, OrdTransactionBuilder}; use self::utils::rpc_client; @@ -77,26 +79,37 @@ async fn main() -> anyhow::Result<()> { _ => panic!("invalid script type"), }; - let commit_tx = builder - .build_commit_transaction_with_fixed_fees( - network, - CreateCommitTransactionArgsV2 { + let commit_tx = builder.build_commit_transaction_with_fixed_fees( + network, + CreateCommitTransactionArgsV2 { + inputs: inputs.clone(), + inscription: Brc20::transfer(ticker, amount), + txin_script_pubkey: sender_address.script_pubkey(), + leftovers_recipient: sender_address.clone(), + commit_fee, + reveal_fee, + }, + )?; + debug!("commit transaction: {commit_tx:?}"); + + let signed_commit_tx = builder + .sign_commit_transaction( + commit_tx.unsigned_tx, + SignCommitTransactionArgs { inputs, - inscription: Brc20::transfer(ticker, amount), txin_script_pubkey: sender_address.script_pubkey(), - leftovers_recipient: sender_address.clone(), - commit_fee, - reveal_fee, }, ) .await?; - debug!("commit transaction: {commit_tx:?}"); let commit_txid = if args.dry_run { - commit_tx.tx.txid() + signed_commit_tx.txid() } else { - info!("broadcasting Commit transaction: {}", commit_tx.tx.txid()); - rpc_client::broadcast_transaction(&commit_tx.tx, network).await? + info!( + "broadcasting Commit transaction: {}", + signed_commit_tx.txid() + ); + rpc_client::broadcast_transaction(&signed_commit_tx, network).await? }; info!("Commit transaction broadcasted: {}", commit_txid); diff --git a/rust-toolchain.toml b/rust-toolchain.toml deleted file mode 100644 index 8dfb7ab..0000000 --- a/rust-toolchain.toml +++ /dev/null @@ -1,4 +0,0 @@ -[toolchain] -channel = "nightly" -components = ["rustfmt"] -profile = "minimal" diff --git a/src/lib.rs b/src/lib.rs index ff2e8a1..f453f3b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,8 +31,10 @@ pub use inscription::brc20::Brc20; pub use inscription::nft::Nft; pub use inscription::Inscription; pub use result::OrdResult; +pub use utils::constants; pub use utils::fees::{self, MultisigConfig}; pub use wallet::{ CreateCommitTransaction, CreateCommitTransactionArgs, ExternalSigner, OrdParser, - OrdTransactionBuilder, RevealTransactionArgs, Utxo, Wallet, WalletType, + OrdTransactionBuilder, RevealTransactionArgs, SignCommitTransactionArgs, Utxo, Wallet, + WalletType, }; diff --git a/src/wallet.rs b/src/wallet.rs index d128946..e21d03b 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -4,6 +4,7 @@ mod parser; pub use builder::signer::{ExternalSigner, Wallet, WalletType}; pub use builder::{ CreateCommitTransaction, CreateCommitTransactionArgs, CreateCommitTransactionArgsV2, - OrdTransactionBuilder, RedeemScriptPubkey, RevealTransactionArgs, ScriptType, Utxo, + OrdTransactionBuilder, RedeemScriptPubkey, RevealTransactionArgs, ScriptType, + SignCommitTransactionArgs, Utxo, }; pub use parser::OrdParser; diff --git a/src/wallet/builder.rs b/src/wallet/builder.rs index 0729487..b73b62c 100644 --- a/src/wallet/builder.rs +++ b/src/wallet/builder.rs @@ -46,14 +46,25 @@ where pub multisig_config: Option, } +pub struct SignCommitTransactionArgs { + /// UTXOs to be used as inputs of the transaction + pub inputs: Vec, + /// Script pubkey of the inputs + pub txin_script_pubkey: ScriptBuf, +} + #[derive(Debug, Clone)] pub struct CreateCommitTransaction { - /// The transaction to be broadcasted - pub tx: Transaction, + /// The unsigned commit transaction + pub unsigned_tx: Transaction, /// The redeem script to be used in the reveal transaction pub redeem_script: ScriptBuf, /// Balance to be passed to reveal transaction pub reveal_balance: Amount, + /// Commit transaction fee + pub commit_fee: Amount, + /// Reveal transaction fee + pub reveal_fee: Amount, } /// Arguments for creating a reveal transaction @@ -91,7 +102,7 @@ impl OrdTransactionBuilder { } /// Creates the commit transaction. - pub async fn build_commit_transaction( + pub fn build_commit_transaction( &mut self, network: Network, recipient_address: Address, @@ -210,22 +221,30 @@ impl OrdTransactionBuilder { output: tx_out, }; + Ok(CreateCommitTransaction { + unsigned_tx, + redeem_script, + reveal_balance: Amount::from_sat(reveal_balance), + commit_fee, + reveal_fee, + }) + } + + /// Sign the commit transaction + pub async fn sign_commit_transaction( + &mut self, + unsigned_tx: Transaction, + args: SignCommitTransactionArgs, + ) -> OrdResult { // sign transaction and update witness - let tx = self - .signer + self.signer .sign_commit_transaction( &self.public_key, &args.inputs, unsigned_tx, &args.txin_script_pubkey, ) - .await?; - - Ok(CreateCommitTransaction { - tx, - redeem_script, - reveal_balance: Amount::from_sat(reveal_balance), - }) + .await } /// Create the reveal transaction @@ -314,7 +333,7 @@ impl OrdTransactionBuilder { } /// Creates the commit transaction with predetermined commit and reveal fees. - pub async fn build_commit_transaction_with_fixed_fees( + pub fn build_commit_transaction_with_fixed_fees( &mut self, network: Network, args: CreateCommitTransactionArgsV2, @@ -408,21 +427,12 @@ impl OrdTransactionBuilder { output: tx_out, }; - // sign transaction and update witness - let tx = self - .signer - .sign_commit_transaction( - &self.public_key, - &args.inputs, - unsigned_tx, - &args.txin_script_pubkey, - ) - .await?; - Ok(CreateCommitTransaction { - tx, + unsigned_tx, redeem_script, reveal_balance: Amount::from_sat(reveal_balance), + reveal_fee: args.reveal_fee, + commit_fee: args.commit_fee, }) } } @@ -481,15 +491,14 @@ mod test { let mut builder = OrdTransactionBuilder::p2wsh(private_key); - let commit_transaction_args = CreateCommitTransactionArgsV2 { - inputs: vec![Utxo { - id: Txid::from_str( - "791b415dc6946d864d368a0e5ec5c09ee2ad39cf298bc6e3f9aec293732cfda7", - ) + let inputs = vec![Utxo { + id: Txid::from_str("791b415dc6946d864d368a0e5ec5c09ee2ad39cf298bc6e3f9aec293732cfda7") .unwrap(), // the transaction that funded our wallet - index: 1, - amount: Amount::from_sat(8_000), - }], + index: 1, + amount: Amount::from_sat(8_000), + }]; + let commit_transaction_args = CreateCommitTransactionArgsV2 { + inputs: inputs.clone(), txin_script_pubkey: address.script_pubkey(), inscription: Brc20::transfer("mona".to_string(), 100), leftovers_recipient: address.clone(), @@ -498,12 +507,21 @@ mod test { }; let tx_result = builder .build_commit_transaction_with_fixed_fees(Network::Testnet, commit_transaction_args) + .unwrap(); + + // sign + let sign_args = SignCommitTransactionArgs { + inputs, + txin_script_pubkey: address.script_pubkey(), + }; + let tx = builder + .sign_commit_transaction(tx_result.unsigned_tx, sign_args) .await .unwrap(); assert!(builder.taproot_payload.is_none()); - let witness = tx_result.tx.input[0].witness.clone().to_vec(); + let witness = tx.input[0].witness.clone().to_vec(); assert_eq!(witness.len(), 2); assert_eq!(witness[0], hex!("30440220708c02ce8166b739f4190bf98538c897f676adc1304bb368ebe910f817fd489602205d708a826b416c2852a6bd7ea464fde8ef3a08eb2fc085ec9e71ed71f6dc582901")); assert_eq!( @@ -519,23 +537,20 @@ mod test { ); // txin - assert_eq!(tx_result.tx.input.len(), 1); - assert_eq!( - tx_result.tx.input[0].sequence, - Sequence::from_consensus(0xffffffff) - ); + assert_eq!(tx.input.len(), 1); + assert_eq!(tx.input[0].sequence, Sequence::from_consensus(0xffffffff)); assert_eq!( - tx_result.tx.input[0].previous_output.txid, + tx.input[0].previous_output.txid, Txid::from_str("791b415dc6946d864d368a0e5ec5c09ee2ad39cf298bc6e3f9aec293732cfda7",) .unwrap() ); // txout - assert_eq!(tx_result.tx.output.len(), 2); - assert_eq!(tx_result.tx.output[0].value, Amount::from_sat(5_033)); - assert_eq!(tx_result.tx.output[1].value, Amount::from_sat(467)); + assert_eq!(tx.output.len(), 2); + assert_eq!(tx.output[0].value, Amount::from_sat(5_033)); + assert_eq!(tx.output[1].value, Amount::from_sat(467)); - let tx_id = tx_result.tx.txid(); + let tx_id = tx.txid(); let recipient_address = Address::from_str("tb1qax89amll2uas5k92tmuc8rdccmqddqw94vrr86") .unwrap() .require_network(Network::Testnet) @@ -585,15 +600,14 @@ mod test { let mut builder = OrdTransactionBuilder::p2tr(private_key); + let inputs = vec![Utxo { + id: Txid::from_str("791b415dc6946d864d368a0e5ec5c09ee2ad39cf298bc6e3f9aec293732cfda7") + .unwrap(), // the transaction that funded our wallet + index: 1, + amount: Amount::from_sat(8_000), + }]; let commit_transaction_args = CreateCommitTransactionArgsV2 { - inputs: vec![Utxo { - id: Txid::from_str( - "791b415dc6946d864d368a0e5ec5c09ee2ad39cf298bc6e3f9aec293732cfda7", - ) - .unwrap(), // the transaction that funded our walle - index: 1, - amount: Amount::from_sat(8_000), - }], + inputs: inputs.clone(), txin_script_pubkey: address.script_pubkey(), inscription: Brc20::transfer("mona".to_string(), 100), leftovers_recipient: address.clone(), @@ -602,12 +616,21 @@ mod test { }; let tx_result = builder .build_commit_transaction_with_fixed_fees(Network::Testnet, commit_transaction_args) - .await .unwrap(); assert!(builder.taproot_payload.is_some()); - let witness = tx_result.tx.input[0].witness.clone().to_vec(); + // sign + let sign_args = SignCommitTransactionArgs { + inputs, + txin_script_pubkey: address.script_pubkey(), + }; + let tx = builder + .sign_commit_transaction(tx_result.unsigned_tx, sign_args) + .await + .unwrap(); + + let witness = tx.input[0].witness.clone().to_vec(); assert_eq!(witness.len(), 2); assert_eq!( witness[1], @@ -630,7 +653,7 @@ mod test { bitcoin::opcodes::all::OP_PUSHBYTES_32.to_u8() ); - let tx_id = tx_result.tx.txid(); + let tx_id = tx.txid(); let recipient_address = Address::from_str("tb1qax89amll2uas5k92tmuc8rdccmqddqw94vrr86") .unwrap() .require_network(Network::Testnet)