transfer100.wzrd#76,467,384brc-20Inscription #65832467#65,832,467png#65,798,853textInscription #65014324#65,014,324svgInscription #65014323#65,014,323svgInscription #65014322#65,014,322svgInscription #65014321#65,014,321svgInscription #65014320#65,014,320svgInscription #65014319#65,014,319svg#64,375,661mint1,000..bet#59,148,683brc-20mint1,000..420#59,085,823brc-20Inscription #50149017#50,149,017htmlInscription #50118697#50,118,697html fn select_cardinal_utxo( &mut self, target_value: Amount, prefer_under: bool, ) -> Result<(OutPoint, Amount)> { tprintln!( "looking for {} cardinal worth {target_value}", if prefer_under { "smaller" } else { "bigger" } ); let inscribed_utxos = self .inscriptions .keys() .map(|satpoint| satpoint.outpoint) .collect::<BTreeSet<OutPoint>>(); let mut best_match = None; for utxo in &self.utxos { if inscribed_utxos.contains(utxo) || self.locked_utxos.contains(utxo) { continue; } let current_value = self.amounts[utxo]; let (_, best_value) = match best_match { Some(prev) => prev, None => { best_match = Some((*utxo, current_value)); (*utxo, current_value) } }; let abs_diff = |a: Amount, b: Amount| -> Amount { max(a, b) - min(a, b) }; let is_closer = abs_diff(current_value, target_value) < abs_diff(best_value, target_value); let not_preference_but_closer = if prefer_under { #44,979,203text } let expected_fee = self.fee_rate.fee(modified_tx.vsize()); assert_eq!( actual_fee, expected_fee, "invariant: fee estimation is correct", ); for tx_out in &transaction.output { assert!( Amount::from_sat(tx_out.value) >= tx_out.script_pubkey.dust_value(), "invariant: all outputs are above dust limit", ); } Ok(transaction) } fn calculate_sat_offset(&self) -> u64 { let mut sat_offset = 0; for outpoint in &self.inputs { if *outpoint == self.outgoing.outpoint { return sat_offset + self.outgoing.offset; } else { sat_offset += self.amounts[outpoint].to_sat(); } } panic!("Could not find outgoing sat in inputs"); } /// Cardinal UTXOs are those that contain no inscriptions and can therefore /// be used to pad transactions. Sometimes multiple of these UTXOs are needed /// and depending on the context we want to select either ones above or /// under (when trying to consolidate dust outputs) the target value. #44,979,202text ) } #[test] fn excess_additional_postage_is_stripped() { let utxos = vec![ (outpoint(1), Amount::from_sat(5_000)), (outpoint(2), Amount::from_sat(25_000)), ]; pretty_assert_eq!( TransactionBuilder::new( satpoint(1, 4_950), BTreeMap::new(), utxos.into_iter().collect(), BTreeSet::new(), recipient(), [change(0), change(1)], FeeRate::try_from(1.0).unwrap(), Target::Postage, ) .build_transaction(), Ok(Transaction { version: 1, lock_time: LockTime::ZERO, 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(14_831, change(0)), ], }) ) } #[test] #[should_panic(expected = "invariant: outgoing sat is contained in utxos")] fn invariant_satpoint_outpoint_is_contained_in_utxos() { TransactionBuilder::new( #44,979,199textdmt-mint.magic#44,751,043tapdmt-mint.magic#44,751,042tapdmt-mint.magic#44,751,041tapdmt-mint.magic#44,751,035tapdmt-mint.magic#44,751,034tapdmt-mint.magic#44,751,031tapdmt-mint.magic#44,751,030taptoken-mint1.tapart tapx 44226185#44,520,782tapdmt-mint.nat#44,347,641tapdmt-mint.nat#44,347,639tapdmt-mint.nat#44,347,637tapdmt-mint.nat#44,347,631tapdmt-mint.nat#44,347,628tapdmt-mint.nat#44,347,626tapdmt-mint.nat#44,347,622tapdmt-mint.nat#44,347,620tapdmt-mint.nat#44,347,618tapdmt-mint.nat#44,347,614tapdmt-mint.nat#44,347,610tapdmt-mint.nat#44,347,609tapdmt-mint.nat#44,347,606tapdmt-mint.nat#44,347,602tapdmt-mint.nat#44,347,600tapdmt-mint.nat#44,347,597tapdmt-mint.nat#44,347,590tapdmt-mint.nat#44,347,588tapdmt-mint.nat#44,347,587tapdmt-mint.nat#44,347,583tapdmt-mint.nat#44,347,575tapdmt-mint.nat#44,347,574tapdmt-mint.nat#44,347,569tapdmt-mint.nat#44,347,565tapdmt-mint.nat#44,347,564tapdmt-mint.nat#44,347,563tapdmt-mint.nat#44,347,554tapdmt-mint.nat#44,347,550tapdmt-mint.nat#44,347,542tapdmt-mint.nat#44,347,538tapdmt-mint.nat#44,347,535tapdmt-mint.nat#44,347,526tapdmt-mint.nat#44,347,525tapdmt-mint.nat#44,347,523tapdmt-mint.nat#44,347,521tap