diff --git a/src/subcommand/preview.rs b/src/subcommand/preview.rs
index 0234571aa6..208a921851 100644
--- a/src/subcommand/preview.rs
+++ b/src/subcommand/preview.rs
@@ -88,6 +88,7 @@ impl Preview {
no_limit: false,
destination: None,
alignment: None,
+ postage: Some(TransactionBuilder::DEFAULT_TARGET_POSTAGE),
},
)),
}
diff --git a/src/subcommand/wallet/inscribe.rs b/src/subcommand/wallet/inscribe.rs
index 871a389258..0a44117e73 100644
--- a/src/subcommand/wallet/inscribe.rs
+++ b/src/subcommand/wallet/inscribe.rs
@@ -58,6 +58,8 @@ pub(crate) struct Inscribe {
pub(crate) destination: Option
,
#[clap(long, help = "Send any alignment output to .")]
pub(crate) alignment: Option,
+ #[clap(long, help = "Amount of postage to include in the inscription. Default `10000 sats`")]
+ pub(crate) postage: Option,
}
impl Inscribe {
@@ -102,6 +104,10 @@ impl Inscribe {
self.commit_fee_rate.unwrap_or(self.fee_rate),
self.fee_rate,
self.no_limit,
+ match self.postage {
+ Some(postage) => postage,
+ _ => TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ },
)?;
utxos.insert(
@@ -172,6 +178,7 @@ impl Inscribe {
commit_fee_rate: FeeRate,
reveal_fee_rate: FeeRate,
no_limit: bool,
+ postage: Amount,
) -> Result<(SatPoint, Transaction, Transaction, TweakedKeyPair)> {
let satpoint = if let Some(satpoint) = satpoint {
satpoint
@@ -245,7 +252,7 @@ impl Inscribe {
alignment,
change,
commit_fee_rate,
- reveal_fee + TransactionBuilder::TARGET_POSTAGE,
+ reveal_fee + postage,
)?;
let (vout, output) = unsigned_commit_tx
@@ -413,6 +420,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
false,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
)
.unwrap();
@@ -445,6 +453,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
false,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
)
.unwrap();
@@ -481,6 +490,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
false,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
)
.unwrap_err()
.to_string();
@@ -524,6 +534,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
false,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
)
.is_ok())
}
@@ -562,6 +573,7 @@ mod tests {
FeeRate::try_from(fee_rate).unwrap(),
FeeRate::try_from(fee_rate).unwrap(),
false,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
)
.unwrap();
@@ -626,6 +638,7 @@ mod tests {
FeeRate::try_from(commit_fee_rate).unwrap(),
FeeRate::try_from(fee_rate).unwrap(),
false,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
)
.unwrap();
@@ -676,6 +689,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
false,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
)
.unwrap_err()
.to_string();
@@ -709,6 +723,7 @@ mod tests {
FeeRate::try_from(1.0).unwrap(),
FeeRate::try_from(1.0).unwrap(),
true,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
)
.unwrap();
diff --git a/src/subcommand/wallet/send.rs b/src/subcommand/wallet/send.rs
index 324f6c0896..56b3b7b86b 100644
--- a/src/subcommand/wallet/send.rs
+++ b/src/subcommand/wallet/send.rs
@@ -13,6 +13,10 @@ pub(crate) struct Send {
fee_rate: FeeRate,
#[clap(long, help = "Send any alignment output to .")]
pub(crate) alignment: Option,
+ #[clap(long, help = "Target amount of postage to include in the sent output. Default `10000 sats`")]
+ pub(crate) target_postage: Option,
+ #[clap(long, help = "Maximum amount of postage to include in the sent output. Default `20000 sats`")]
+ pub(crate) max_postage: Option,
}
#[derive(Serialize, Deserialize)]
@@ -91,6 +95,14 @@ impl Send {
self.alignment,
change,
self.fee_rate,
+ match self.target_postage {
+ Some(target_postage) => target_postage,
+ _ => TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ },
+ match self.max_postage {
+ Some(max_postage) => max_postage,
+ _ => TransactionBuilder::DEFAULT_MAX_POSTAGE,
+ },
)?;
let signed_tx = client
diff --git a/src/subcommand/wallet/transaction_builder.rs b/src/subcommand/wallet/transaction_builder.rs
index 2db6656391..e41769ca36 100644
--- a/src/subcommand/wallet/transaction_builder.rs
+++ b/src/subcommand/wallet/transaction_builder.rs
@@ -108,6 +108,8 @@ pub struct TransactionBuilder {
unused_change_addresses: Vec,
utxos: BTreeSet,
target: Target,
+ target_postage: Amount,
+ max_postage: Amount,
}
type Result = std::result::Result;
@@ -115,9 +117,9 @@ type Result = std::result::Result;
impl TransactionBuilder {
const ADDITIONAL_INPUT_VBYTES: f64 = 58.0;
const ADDITIONAL_OUTPUT_VBYTES: f64 = 43.0;
- const MAX_POSTAGE: Amount = Amount::from_sat(2 * 10_000);
const SCHNORR_SIGNATURE_SIZE: usize = 64;
- pub(crate) const TARGET_POSTAGE: Amount = Amount::from_sat(10_000);
+ pub(crate) const DEFAULT_MAX_POSTAGE: Amount = Amount::from_sat(2 * 10_000);
+ pub(crate) const DEFAULT_TARGET_POSTAGE: Amount = Amount::from_sat(10_000);
pub fn build_transaction_with_postage(
outgoing: SatPoint,
@@ -127,6 +129,8 @@ impl TransactionBuilder {
alignment: Option,
change: [Address; 2],
fee_rate: FeeRate,
+ target_postage: Amount,
+ max_postage: Amount,
) -> Result {
Self::new(
outgoing,
@@ -137,6 +141,8 @@ impl TransactionBuilder {
change,
fee_rate,
Target::Postage,
+ target_postage,
+ max_postage,
)?
.build_transaction()
}
@@ -169,6 +175,8 @@ impl TransactionBuilder {
change,
fee_rate,
Target::Value(output_value),
+ Amount::from_sat(0),
+ Amount::from_sat(0),
)?
.build_transaction()
}
@@ -193,6 +201,8 @@ impl TransactionBuilder {
change: [Address; 2],
fee_rate: FeeRate,
target: Target,
+ target_postage: Amount,
+ max_postage: Amount,
) -> Result {
if change.contains(&recipient) {
return Err(Error::DuplicateAddress(recipient));
@@ -215,6 +225,8 @@ impl TransactionBuilder {
alignment,
unused_change_addresses: change.to_vec(),
target,
+ target_postage,
+ max_postage,
})
}
@@ -377,7 +389,7 @@ impl TransactionBuilder {
if let Some(excess) = value.checked_sub(self.fee_rate.fee(self.estimate_vbytes())) {
let (max, target) = match self.target {
- Target::Postage => (Self::MAX_POSTAGE, Self::TARGET_POSTAGE),
+ Target::Postage => (self.max_postage, self.target_postage),
Target::Value(value) => (value, value),
};
@@ -591,7 +603,7 @@ impl TransactionBuilder {
match self.target {
Target::Postage => {
assert!(
- Amount::from_sat(output.value) <= Self::MAX_POSTAGE + slop,
+ Amount::from_sat(output.value) <= self.max_postage + slop,
"invariant: excess postage is stripped"
);
}
@@ -755,6 +767,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.select_outgoing()
@@ -799,6 +813,8 @@ mod tests {
(change(1), Amount::from_sat(1_724)),
],
target: Target::Postage,
+ target_postage: TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ max_postage: TransactionBuilder::DEFAULT_MAX_POSTAGE,
};
pretty_assert_eq!(
@@ -828,6 +844,8 @@ mod tests {
None,
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.is_explicitly_rbf())
@@ -846,6 +864,8 @@ mod tests {
None,
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Ok(Transaction {
version: 1,
@@ -870,6 +890,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.select_outgoing()
@@ -895,6 +917,8 @@ mod tests {
None,
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Ok(Transaction {
version: 1,
@@ -918,6 +942,8 @@ mod tests {
None,
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Err(Error::NotEnoughCardinalUtxos),
)
@@ -939,6 +965,8 @@ mod tests {
None,
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Err(Error::NotEnoughCardinalUtxos),
)
@@ -960,6 +988,8 @@ mod tests {
None,
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Ok(Transaction {
version: 1,
@@ -967,7 +997,7 @@ mod tests {
input: vec![tx_in(outpoint(1)), tx_in(outpoint(2))],
output: vec![
tx_out(4_950, change(1)),
- tx_out(TransactionBuilder::TARGET_POSTAGE.to_sat(), recipient()),
+ tx_out(TransactionBuilder::DEFAULT_TARGET_POSTAGE.to_sat(), recipient()),
tx_out(14_831, change(0)),
],
})
@@ -988,6 +1018,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.build()
@@ -1008,6 +1040,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.build()
@@ -1028,6 +1062,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.build()
@@ -1048,6 +1084,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.select_outgoing()
@@ -1074,6 +1112,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.select_outgoing()
@@ -1097,13 +1137,15 @@ mod tests {
None,
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Ok(Transaction {
version: 1,
lock_time: PackedLockTime::ZERO,
input: vec![tx_in(outpoint(1))],
output: vec![
- tx_out(TransactionBuilder::TARGET_POSTAGE.to_sat(), recipient()),
+ tx_out(TransactionBuilder::DEFAULT_TARGET_POSTAGE.to_sat(), recipient()),
tx_out(989_870, change(1))
],
})
@@ -1124,6 +1166,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.select_outgoing()
@@ -1145,6 +1189,8 @@ mod tests {
None,
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Ok(Transaction {
version: 1,
@@ -1171,6 +1217,8 @@ mod tests {
None,
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Ok(Transaction {
version: 1,
@@ -1195,6 +1243,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.select_outgoing()
@@ -1224,6 +1274,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.select_outgoing()
@@ -1251,6 +1303,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.select_outgoing()
@@ -1275,6 +1329,8 @@ mod tests {
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Postage,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap()
.select_outgoing()
@@ -1309,6 +1365,8 @@ mod tests {
(change(1), Amount::from_sat(1_774)),
],
target: Target::Postage,
+ target_postage: TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ max_postage: TransactionBuilder::DEFAULT_MAX_POSTAGE,
}
.build()
.unwrap();
@@ -1339,6 +1397,8 @@ mod tests {
(change(0), Amount::from_sat(1_774)),
],
target: Target::Postage,
+ target_postage: TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ max_postage: TransactionBuilder::DEFAULT_MAX_POSTAGE,
}
.build()
.unwrap();
@@ -1360,6 +1420,8 @@ mod tests {
alignment(),
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Err(Error::NotEnoughCardinalUtxos)
)
@@ -1378,6 +1440,8 @@ mod tests {
alignment(),
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Err(Error::UtxoContainsAdditionalInscription {
outgoing_satpoint: satpoint(1, 0),
@@ -1401,6 +1465,8 @@ mod tests {
alignment(),
[change(0), change(1)],
fee_rate,
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
)
.unwrap();
@@ -1593,6 +1659,8 @@ mod tests {
alignment(),
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Ok(Transaction {
version: 1,
@@ -1721,6 +1789,8 @@ mod tests {
alignment(),
[change(0), change(1)],
FeeRate::try_from(250.0).unwrap(),
+ TransactionBuilder::DEFAULT_TARGET_POSTAGE,
+ TransactionBuilder::DEFAULT_MAX_POSTAGE,
),
Ok(Transaction {
version: 1,