SHOWING: First 60
);
}
#[test]
fn change_addresses_must_be_unique() {
pretty_assert_eq!(
TransactionBuilder::new(
satpoint(1, 0),
BTreeMap::new(),
vec![(outpoint(1), Amount::from_sat(1000))]
.into_iter()
.collect(),
BTreeSet::new(),
recipient(),
[change(0), change(0)],
FeeRate::try_from(0.0).unwrap(),
Target::Value(Amount::from_sat(1000))
)
.build_transaction(),
Err(Error::DuplicateAddress(change(0)))
);
}
#[test]
fn output_over_value_because_fees_prevent_excess_value_stripping() {
pretty_assert_eq!(
TransactionBuilder::new(
satpoint(1, 0),
BTreeMap::new(),
vec![(outpoint(1), Amount::from_sat(2000))]
.into_iter()
.collect(),
BTreeSet::new(),
recipient(),
[change(0), change(1)],
FeeRate::try_from(2.0).unwrap(),
Target::Value(Amount::from_sat(1500))
)
.build_transaction(),
Ok(Transaction {
#44,982,873text ),
Error::ValueOverflow => write!(f, "arithmetic overflow calculating value"),
Error::DuplicateAddress(address) => write!(f, "duplicate input address: {address}"),
}
}
}
impl std::error::Error for Error {}
#[derive(Debug, PartialEq)]
pub struct TransactionBuilder {
amounts: BTreeMap<OutPoint, Amount>,
change_addresses: BTreeSet<Address>,
fee_rate: FeeRate,
inputs: Vec<OutPoint>,
inscriptions: BTreeMap<SatPoint, InscriptionId>,
outgoing: SatPoint,
outputs: Vec<(Address, Amount)>,
recipient: Address,
unused_change_addresses: Vec<Address>,
utxos: BTreeSet<OutPoint>,
locked_utxos: BTreeSet<OutPoint>,
target: Target,
}
type Result<T> = std::result::Result<T, Error>;
impl TransactionBuilder {
const ADDITIONAL_INPUT_VBYTES: usize = 58;
const ADDITIONAL_OUTPUT_VBYTES: usize = 43;
const SCHNORR_SIGNATURE_SIZE: usize = 64;
pub(crate) const TARGET_POSTAGE: Amount = Amount::from_sat(10_000);
pub(crate) const MAX_POSTAGE: Amount = Amount::from_sat(2 * 10_000);
#44,982,872text (outpoint(1), Amount::from_sat(3_003)), // 1. satpoint is selected 1st leaving us needing 7154 more
(outpoint(5), Amount::from_sat(3_004)),
(outpoint(4), Amount::from_sat(3_001)), // 4. smallest utxo >= 1259 is selected 4th, filling deficit
(outpoint(3), Amount::from_sat(3_005)), // 3. next biggest utxo is selected 3rd leaving us needing 1259 more
(outpoint(6), Amount::from_sat(3_002)),
];
let tx_builder = TransactionBuilder::new(
satpoint(1, 0),
BTreeMap::new(),
utxos.clone().into_iter().collect(),
BTreeSet::new(),
recipient(),
[change(0), change(1)],
FeeRate::try_from(1.0).unwrap(),
Target::Value(Amount::from_sat(10_000)),
)
.select_outgoing()
.unwrap()
.add_value()
.unwrap();
utxos.remove(4);
utxos.remove(3);
utxos.remove(1);
utxos.remove(0);
assert_eq!(
tx_builder.utxos,
utxos.iter().map(|(outpoint, _ranges)| *outpoint).collect()
);
assert_eq!(
tx_builder.inputs,
#44,982,871text#44,775,230dmt-mint.nat#44,700,469tapdmt-mint.nat#44,700,468tapdmt-mint.nat#44,700,467tapdmt-mint.nat#44,700,466tapdmt-mint.nat#44,700,465tapdmt-mint.nat#44,700,464tapdmt-mint.nat#44,700,463tapdmt-mint.nat#44,700,462tapdmt-mint.nat#44,700,461tapdmt-mint.nat#44,700,460tapmint100,000,000,000.shid#42,896,543brc-20mint100,000,000,000.shid#42,896,542brc-20mint100,000,000,000.shid#42,896,541brc-20mint100,000,000,000.shid#42,896,540brc-20mint100,000,000,000.shid#42,896,539brc-20mint100,000,000,000.shid#42,896,538brc-20mint100,000,000,000.shid#42,896,537brc-20mint100,000,000,000.shid#42,896,536brc-2019453.bitmap#12,249,811text1818181.bitmap#12,249,799texttransfer500.btoc#12,249,458brc-20transfer500.btoc#12,244,861brc-20transfer500.btoc#12,230,560brc-20transfer500.btoc#12,228,278brc-20transfer1.btoc#12,210,185brc-20