From 99180e115f9ce46cdeb4de2e008e773c4479e111 Mon Sep 17 00:00:00 2001 From: Dario Anongba Varela Date: Wed, 22 Apr 2026 16:10:24 +0000 Subject: [PATCH] refactor(types): prototype inner-wrapper macro --- CHANGELOG.md | 1 + src/lib.rs | 3 ++ src/macros.rs | 27 +++++++++++++ src/types/amount.rs | 24 +----------- src/types/balance.rs | 18 +-------- src/types/chain.rs | 82 ++-------------------------------------- src/types/changeset.rs | 24 +----------- src/types/checkpoint.rs | 18 +-------- src/types/fee.rs | 42 ++------------------ src/types/psbt.rs | 22 +---------- src/types/script.rs | 22 +---------- src/types/transaction.rs | 42 ++------------------ 12 files changed, 52 insertions(+), 273 deletions(-) create mode 100644 src/macros.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 6061a93..74d6903 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Expand Node and regtest integration coverage for wallet address lifecycle, output introspection, and fee calculation APIs ([#22](https://github.com/bitcoindevkit/bdk-wasm/issues/22)) - Audit and refresh Rust and Node development dependencies to their latest compatible releases ([#24](https://github.com/bitcoindevkit/bdk-wasm/issues/24)) +- Prototype a declarative macro for tuple-wrapper `Deref`/`From` boilerplate while keeping `wasm_bindgen` getters explicit ([#25](https://github.com/bitcoindevkit/bdk-wasm/issues/25)) ### Dependencies diff --git a/src/lib.rs b/src/lib.rs index 785d8ce..c27a4f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,6 @@ +#[macro_use] +mod macros; + pub mod bitcoin; pub mod types; mod utils; diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..f1fdbac --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,27 @@ +macro_rules! impl_inner_wrapper { + ($name:ident, $inner:ty) => { + impl ::std::ops::Deref for $name { + type Target = $inner; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl From<$inner> for $name { + fn from(inner: $inner) -> Self { + Self(inner) + } + } + }; + + ($name:ident, $inner:ty, into_inner) => { + impl_inner_wrapper!($name, $inner); + + impl From<$name> for $inner { + fn from(value: $name) -> Self { + value.0 + } + } + }; +} diff --git a/src/types/amount.rs b/src/types/amount.rs index f20ebbe..2a3837d 100644 --- a/src/types/amount.rs +++ b/src/types/amount.rs @@ -1,5 +1,3 @@ -use std::ops::Deref; - use bdk_wallet::{ bitcoin::{Amount as BdkAmount, Denomination as BdkDenomination}, IsDust, @@ -18,6 +16,8 @@ use crate::types::{BdkError, BdkErrorCode, ScriptBuf}; #[derive(Clone, Copy, Serialize)] pub struct Amount(BdkAmount); +impl_inner_wrapper!(Amount, BdkAmount, into_inner); + #[wasm_bindgen] impl Amount { pub fn from_btc(btc: f64) -> Result { @@ -55,26 +55,6 @@ impl Amount { } } -impl Deref for Amount { - type Target = BdkAmount; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl From for Amount { - fn from(inner: BdkAmount) -> Self { - Amount(inner) - } -} - -impl From for BdkAmount { - fn from(amount: Amount) -> Self { - amount.0 - } -} - impl From for BdkError { fn from(e: ParseAmountError) -> Self { use ParseAmountError::*; diff --git a/src/types/balance.rs b/src/types/balance.rs index c4f2b0b..d1fcfea 100644 --- a/src/types/balance.rs +++ b/src/types/balance.rs @@ -1,5 +1,3 @@ -use std::ops::Deref; - use bdk_wallet::Balance as BdkBalance; use wasm_bindgen::prelude::wasm_bindgen; @@ -10,6 +8,8 @@ use super::Amount; #[derive(Clone)] pub struct Balance(BdkBalance); +impl_inner_wrapper!(Balance, BdkBalance); + #[wasm_bindgen] impl Balance { /// All coinbase outputs not yet matured @@ -51,17 +51,3 @@ impl Balance { self.0.total().into() } } - -impl Deref for Balance { - type Target = BdkBalance; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl From for Balance { - fn from(inner: BdkBalance) -> Self { - Balance(inner) - } -} diff --git a/src/types/chain.rs b/src/types/chain.rs index 9a3b7f9..c2e5324 100644 --- a/src/types/chain.rs +++ b/src/types/chain.rs @@ -1,5 +1,3 @@ -use std::ops::Deref; - use bdk_wallet::{ chain::{ spk_client::{ @@ -21,25 +19,7 @@ use super::{ConfirmationBlockTime, Txid}; #[wasm_bindgen] pub struct SyncRequest(BdkSyncRequest<(KeychainKind, u32)>); -impl Deref for SyncRequest { - type Target = BdkSyncRequest<(KeychainKind, u32)>; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl From> for SyncRequest { - fn from(inner: BdkSyncRequest<(KeychainKind, u32)>) -> Self { - SyncRequest(inner) - } -} - -impl From for BdkSyncRequest<(KeychainKind, u32)> { - fn from(request: SyncRequest) -> Self { - request.0 - } -} +impl_inner_wrapper!(SyncRequest, BdkSyncRequest<(KeychainKind, u32)>, into_inner); /// Data required to perform a spk-based blockchain client full scan. /// @@ -50,50 +30,14 @@ impl From for BdkSyncRequest<(KeychainKind, u32)> { #[wasm_bindgen] pub struct FullScanRequest(BdkFullScanRequest); -impl Deref for FullScanRequest { - type Target = BdkFullScanRequest; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl From> for FullScanRequest { - fn from(inner: BdkFullScanRequest) -> Self { - FullScanRequest(inner) - } -} - -impl From for BdkFullScanRequest { - fn from(request: FullScanRequest) -> Self { - request.0 - } -} +impl_inner_wrapper!(FullScanRequest, BdkFullScanRequest, into_inner); /// An update to [`Wallet`]. #[wasm_bindgen] #[derive(Clone)] pub struct Update(BdkUpdate); -impl Deref for Update { - type Target = BdkUpdate; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl From for Update { - fn from(inner: BdkUpdate) -> Self { - Update(inner) - } -} - -impl From for BdkUpdate { - fn from(update: Update) -> Self { - update.0 - } -} +impl_inner_wrapper!(Update, BdkUpdate, into_inner); impl From> for Update { fn from(result: BdkFullScanResponse) -> Self { @@ -111,13 +55,7 @@ impl From for Update { #[wasm_bindgen] pub struct ChainPosition(BdkChainPosition); -impl Deref for ChainPosition { - type Target = BdkChainPosition; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} +impl_inner_wrapper!(ChainPosition, BdkChainPosition, into_inner); #[wasm_bindgen] impl ChainPosition { @@ -189,15 +127,3 @@ impl ChainPosition { } } } - -impl From> for ChainPosition { - fn from(inner: BdkChainPosition) -> Self { - ChainPosition(inner) - } -} - -impl From for BdkChainPosition { - fn from(chain_position: ChainPosition) -> Self { - chain_position.0 - } -} diff --git a/src/types/changeset.rs b/src/types/changeset.rs index ce6dd6b..4ae0a28 100644 --- a/src/types/changeset.rs +++ b/src/types/changeset.rs @@ -1,5 +1,3 @@ -use std::ops::Deref; - use bdk_wallet::{ chain::Merge, serde_json::{from_str, to_string}, @@ -14,6 +12,8 @@ use crate::result::JsResult; #[derive(PartialEq)] pub struct ChangeSet(BdkChangeSet); +impl_inner_wrapper!(ChangeSet, BdkChangeSet, into_inner); + #[wasm_bindgen] impl ChangeSet { /// Merge another [`ChangeSet`] into itself. @@ -35,23 +35,3 @@ impl ChangeSet { Ok(ChangeSet(from_str(val)?)) } } - -impl Deref for ChangeSet { - type Target = BdkChangeSet; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl From for ChangeSet { - fn from(inner: BdkChangeSet) -> Self { - ChangeSet(inner) - } -} - -impl From for BdkChangeSet { - fn from(changeset: ChangeSet) -> Self { - changeset.0 - } -} diff --git a/src/types/checkpoint.rs b/src/types/checkpoint.rs index 9112e10..d477a77 100644 --- a/src/types/checkpoint.rs +++ b/src/types/checkpoint.rs @@ -1,5 +1,3 @@ -use std::ops::Deref; - use bdk_wallet::chain::CheckPoint as BdkCheckPoint; use wasm_bindgen::prelude::wasm_bindgen; @@ -13,6 +11,8 @@ use super::BlockId; #[derive(Clone)] pub struct CheckPoint(BdkCheckPoint); +impl_inner_wrapper!(CheckPoint, BdkCheckPoint); + #[wasm_bindgen] impl CheckPoint { /// Get the [`BlockId`] of the checkpoint. @@ -46,17 +46,3 @@ impl CheckPoint { self.0.get(height).map(Into::into) } } - -impl Deref for CheckPoint { - type Target = BdkCheckPoint; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl From for CheckPoint { - fn from(inner: BdkCheckPoint) -> Self { - CheckPoint(inner) - } -} diff --git a/src/types/fee.rs b/src/types/fee.rs index ee86124..28eb155 100644 --- a/src/types/fee.rs +++ b/src/types/fee.rs @@ -1,5 +1,5 @@ use bdk_wallet::bitcoin::FeeRate as BdkFeeRate; -use std::{collections::HashMap, ops::Deref}; +use std::collections::HashMap; use wasm_bindgen::prelude::wasm_bindgen; @@ -7,13 +7,7 @@ use wasm_bindgen::prelude::wasm_bindgen; #[wasm_bindgen] pub struct FeeEstimates(HashMap); -impl Deref for FeeEstimates { - type Target = HashMap; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} +impl_inner_wrapper!(FeeEstimates, HashMap, into_inner); #[wasm_bindgen] impl FeeEstimates { @@ -24,18 +18,6 @@ impl FeeEstimates { } } -impl From> for FeeEstimates { - fn from(inner: HashMap) -> Self { - FeeEstimates(inner) - } -} - -impl From for HashMap { - fn from(fee_estimates: FeeEstimates) -> Self { - fee_estimates.0 - } -} - /// Represents fee rate. /// /// This is an integer newtype representing fee rate in `sat/kwu`. It provides protection against mixing @@ -44,13 +26,7 @@ impl From for HashMap { #[derive(Clone, Copy)] pub struct FeeRate(BdkFeeRate); -impl Deref for FeeRate { - type Target = BdkFeeRate; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} +impl_inner_wrapper!(FeeRate, BdkFeeRate, into_inner); #[wasm_bindgen] impl FeeRate { @@ -74,15 +50,3 @@ impl FeeRate { self.0.to_sat_per_vb_floor() } } - -impl From for FeeRate { - fn from(inner: BdkFeeRate) -> Self { - FeeRate(inner) - } -} - -impl From for BdkFeeRate { - fn from(fee_rate: FeeRate) -> Self { - fee_rate.0 - } -} diff --git a/src/types/psbt.rs b/src/types/psbt.rs index e48386e..aed2537 100644 --- a/src/types/psbt.rs +++ b/src/types/psbt.rs @@ -1,5 +1,5 @@ use bdk_wallet::serde_json::to_string; -use std::ops::{Deref, DerefMut}; +use std::ops::DerefMut; use std::str::FromStr; use bdk_wallet::{ @@ -19,13 +19,7 @@ use super::{Address, Amount, FeeRate, Transaction}; #[derive(Clone)] pub struct Psbt(BdkPsbt); -impl Deref for Psbt { - type Target = BdkPsbt; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} +impl_inner_wrapper!(Psbt, BdkPsbt, into_inner); impl DerefMut for Psbt { fn deref_mut(&mut self) -> &mut Self::Target { @@ -122,18 +116,6 @@ impl Psbt { } } -impl From for Psbt { - fn from(inner: BdkPsbt) -> Self { - Psbt(inner) - } -} - -impl From for BdkPsbt { - fn from(psbt: Psbt) -> Self { - psbt.0 - } -} - /// A Transaction recipient #[wasm_bindgen] #[derive(Clone)] diff --git a/src/types/script.rs b/src/types/script.rs index bdaf011..4010834 100644 --- a/src/types/script.rs +++ b/src/types/script.rs @@ -1,5 +1,3 @@ -use std::ops::Deref; - use bdk_wallet::bitcoin::ScriptBuf as BdkScriptBuf; use wasm_bindgen::prelude::wasm_bindgen; @@ -16,13 +14,7 @@ use crate::{ #[derive(Clone)] pub struct ScriptBuf(BdkScriptBuf); -impl Deref for ScriptBuf { - type Target = BdkScriptBuf; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} +impl_inner_wrapper!(ScriptBuf, BdkScriptBuf, into_inner); #[wasm_bindgen] impl ScriptBuf { @@ -74,15 +66,3 @@ impl ScriptBuf { self.0.minimal_non_dust_custom(dust_relay_fee.into()).into() } } - -impl From for ScriptBuf { - fn from(inner: BdkScriptBuf) -> Self { - ScriptBuf(inner) - } -} - -impl From for BdkScriptBuf { - fn from(script_buf: ScriptBuf) -> Self { - script_buf.0 - } -} diff --git a/src/types/transaction.rs b/src/types/transaction.rs index 5a255d7..39ca807 100644 --- a/src/types/transaction.rs +++ b/src/types/transaction.rs @@ -1,4 +1,4 @@ -use std::{ops::Deref, str::FromStr}; +use std::str::FromStr; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsError; @@ -16,13 +16,7 @@ use super::{TxIn, TxOut}; #[derive(Clone)] pub struct Transaction(BdkTransaction); -impl Deref for Transaction { - type Target = BdkTransaction; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} +impl_inner_wrapper!(Transaction, BdkTransaction, into_inner); #[wasm_bindgen] impl Transaction { @@ -144,30 +138,12 @@ impl Transaction { } } -impl From for Transaction { - fn from(inner: BdkTransaction) -> Self { - Transaction(inner) - } -} - -impl From for BdkTransaction { - fn from(tx: Transaction) -> Self { - tx.0 - } -} - /// A bitcoin transaction hash/transaction ID. #[wasm_bindgen] #[derive(Clone, Copy)] pub struct Txid(BdkTxid); -impl Deref for Txid { - type Target = BdkTxid; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} +impl_inner_wrapper!(Txid, BdkTxid, into_inner); #[wasm_bindgen] impl Txid { @@ -182,15 +158,3 @@ impl Txid { self.0.to_string() } } - -impl From for Txid { - fn from(inner: BdkTxid) -> Self { - Txid(inner) - } -} - -impl From for BdkTxid { - fn from(txid: Txid) -> Self { - txid.0 - } -}