Skip to content

Commit

Permalink
RBF initial implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
cryptoquick committed Dec 13, 2023
1 parent 003ff90 commit 1bf71e5
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"files.autoSave": "onFocusChange",
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"rust-analyzer.cargo.features": "all", // Enable only for desktop
"rust-analyzer.check.allTargets": true,
"rust-analyzer.cargo.features": "all", // Enable only for desktop
// "rust-analyzer.cargo.target": "wasm32-unknown-unknown", // Enable only for web
// "rust-analyzer.check.noDefaultFeatures": true, // Enable for web
// "rust-analyzer.runnables.extraArgs": ["--release"], // Enable for web
Expand Down
31 changes: 21 additions & 10 deletions lib/web/bitcoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,6 @@ export const sendSats = async (
await BMC.send_sats(descriptor, changeDescriptor, address, amount, feeRate)
);

export const drainWallet = async (
destination: string,
descriptor: string,
changeDescriptor?: string,
feeRate?: number
): Promise<TransactionData> =>
JSON.parse(
await BMC.drain_wallet(destination, descriptor, changeDescriptor, feeRate)
);

export const fundVault = async (
descriptor: string,
changeDescriptor: string,
Expand All @@ -92,6 +82,27 @@ export const getAssetsVault = async (
await BMC.get_assets_vault(rgbAssetsDescriptorXpub, rgbUdasDescriptorXpub)
);

export const drainWallet = async (
destination: string,
descriptor: string,
changeDescriptor?: string,
feeRate?: number
): Promise<TransactionData> =>
JSON.parse(
await BMC.drain_wallet(destination, descriptor, changeDescriptor, feeRate)
);

export const bumpFee = async (
txid: string,
feeRate: number,
descriptor: string,
changeDescriptor: string,
broadcast: boolean
): Promise<TransactionData> =>
JSON.parse(
await BMC.bump_fee(txid, feeRate, descriptor, changeDescriptor, broadcast)
);

// Core type interfaces based on structs defined within the bitmask-core Rust crate:
// https://github.com/diba-io/bitmask-core/blob/development/src/structs.rs

Expand Down
50 changes: 49 additions & 1 deletion src/bitcoin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ::psbt::Psbt;
use amplify::hex::ToHex;
use argon2::Argon2;
use bdk::{wallet::AddressIndex, FeeRate, LocalUtxo, SignOptions, TransactionDetails};
use bitcoin::{consensus::encode, psbt::PartiallySignedTransaction};
use bitcoin::{consensus::encode, psbt::PartiallySignedTransaction, Txid};
use rand::{rngs::StdRng, Rng, SeedableRng};
use serde_encrypt::{
serialize::impls::BincodeSerializer, shared_key::SharedKey, traits::SerdeEncryptSharedKey,
Expand Down Expand Up @@ -113,6 +113,9 @@ pub enum BitcoinError {
/// PSBT decode error
#[error(transparent)]
BitcoinPsbtDecodeError(#[from] bitcoin::consensus::encode::Error),
/// Txid parse error
#[error(transparent)]
TxidParseError(#[from] bitcoin::hashes::hex::Error),
}

/// Bitcoin Wallet Operations
Expand Down Expand Up @@ -598,3 +601,48 @@ pub async fn drain_wallet(
Err(BitcoinError::DrainWalletNoTxDetails)
}
}

pub async fn bump_fee(
txid: String,
fee_rate: f32,
descriptor: &SecretString,
change_descriptor: &SecretString,
broadcast: bool,
) -> Result<TransactionDetails, BitcoinError> {
let txid = Txid::from_str(&txid)?;

let wallet = get_wallet(descriptor, Some(change_descriptor)).await?;
sync_wallet(&wallet).await?;

let (mut psbt, details) = {
let wallet_lock = wallet.lock().await;
let mut builder = wallet_lock.build_fee_bump(txid)?;
builder.fee_rate(FeeRate::from_sat_per_vb(fee_rate));
builder.finish()?
};

if broadcast {
let _finalized = wallet
.lock()
.await
.sign(&mut psbt, SignOptions::default())?;
let tx = psbt.extract_tx();
let blockchain = get_blockchain().await;
blockchain.broadcast(&tx).await?;

let sent = tx.output.iter().fold(0, |sum, output| output.value + sum);

let details = TransactionDetails {
txid: tx.txid(),
transaction: Some(tx),
received: 0,
sent,
fee: details.fee,
confirmation_time: None,
};

Ok(details)
} else {
Ok(details)
}
}
72 changes: 50 additions & 22 deletions src/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,21 +294,21 @@ pub mod bitcoin {
}

#[wasm_bindgen]
pub fn drain_wallet(
destination: String,
pub fn fund_vault(
descriptor: String,
change_descriptor: Option<String>,
change_descriptor: String,
asset_address: String,
uda_address: String,
fee_rate: Option<f32>,
) -> Promise {
set_panic_hook();

future_to_promise(async move {
let change_descriptor = change_descriptor.map(SecretString);

match crate::bitcoin::drain_wallet(
&destination,
match crate::bitcoin::fund_vault(
&SecretString(descriptor),
change_descriptor.as_ref(),
&SecretString(change_descriptor),
&asset_address,
&uda_address,
fee_rate,
)
.await
Expand All @@ -322,21 +322,43 @@ pub mod bitcoin {
}

#[wasm_bindgen]
pub fn fund_vault(
pub fn get_assets_vault(
rgb_assets_descriptor_xpub: String,
rgb_udas_descriptor_xpub: String,
) -> Promise {
set_panic_hook();

future_to_promise(async move {
match crate::bitcoin::get_assets_vault(
&SecretString(rgb_assets_descriptor_xpub),
&SecretString(rgb_udas_descriptor_xpub),
)
.await
{
Ok(result) => Ok(JsValue::from_string(
serde_json::to_string(&result).unwrap(),
)),
Err(err) => Err(JsValue::from_string(err.to_string())),
}
})
}

#[wasm_bindgen]
pub fn drain_wallet(
destination: String,
descriptor: String,
change_descriptor: String,
asset_address_1: String,
uda_address_1: String,
change_descriptor: Option<String>,
fee_rate: Option<f32>,
) -> Promise {
set_panic_hook();

future_to_promise(async move {
match crate::bitcoin::fund_vault(
let change_descriptor = change_descriptor.map(SecretString);

match crate::bitcoin::drain_wallet(
&destination,
&SecretString(descriptor),
&SecretString(change_descriptor),
&asset_address_1,
&uda_address_1,
change_descriptor.as_ref(),
fee_rate,
)
.await
Expand All @@ -350,16 +372,22 @@ pub mod bitcoin {
}

#[wasm_bindgen]
pub fn get_assets_vault(
rgb_assets_descriptor_xpub: String,
rgb_udas_descriptor_xpub: String,
pub fn bump_fee(
txid: String,
fee_rate: f32,
descriptor: String,
change_descriptor: String,
broadcast: bool,
) -> Promise {
set_panic_hook();

future_to_promise(async move {
match crate::bitcoin::get_assets_vault(
&SecretString(rgb_assets_descriptor_xpub),
&SecretString(rgb_udas_descriptor_xpub),
match crate::bitcoin::bump_fee(
txid,
fee_rate,
&SecretString(descriptor),
&SecretString(change_descriptor),
broadcast,
)
.await
{
Expand Down

0 comments on commit 1bf71e5

Please sign in to comment.