..Default::default() }); context.mine_blocks(1); let inscription_id = InscriptionId { txid, index: 0 }; context.index.assert_inscription_location( inscription_id, SatPoint { outpoint: OutPoint { txid, vout: 0 }, offset: 0, }, Some(50 * COIN_VALUE), ); } } #[test] fn inscription_with_pointer_into_fee_ignored_and_assigned_default_location() { for context in Context::configurations() { context.mine_blocks(1); let inscription = Inscription { content_type: Some("text/plain".into()), body: Some("hello".into()), pointer: Some((25 * COIN_VALUE).to_le_bytes().to_vec()), ..Default::default() }; let txid = context.rpc_server.broadcast_tx(TransactionTemplate { inputs: &[(1, 0, 0, inscription.to_witness())], fee: 25 * COIN_VALUE, ..Default::default() }); context.mine_blocks(1); let inscription_id = InscriptionId { txid, index: 0 };#45,024,080text script_sig: ScriptBuf::new(), sequence: Sequence::MAX, witness: witness.clone(), }); } let value_per_output = (total_value - template.fee) / template.outputs as u64; assert_eq!( value_per_output * template.outputs as u64 + template.fee, total_value ); let mut tx = Transaction { version: 0, lock_time: LockTime::ZERO, input, output: (0..template.outputs) .map(|i| TxOut { value: template .output_values .get(i) .cloned() .unwrap_or(value_per_output), script_pubkey: script::Builder::new().into_script(), }) .collect(), }; if let Some(script_pubkey) = template.op_return { tx.output.insert( template.op_return_index.unwrap_or(tx.output.len()), TxOut { value: 0, script_pubkey, }, ); } self.mempool.push(tx.clone()); tx.txid() } pub(crate) fn mempool(&self) -> &[Transaction] {#45,024,079text let acme_cache = if let Some(acme_cache) = acme_cache { acme_cache.clone() } else { options.data_dir()?.join("acme-cache") }; Ok(acme_cache) } fn acme_domains(&self) -> Result<Vec<String>> { if !self.acme_domain.is_empty() { Ok(self.acme_domain.clone()) } else { Ok(vec![System::new() .host_name() .ok_or(anyhow!("no hostname found"))?]) } } fn http_port(&self) -> Option<u16> { if self.http || self.http_port.is_some() || (self.https_port.is_none() && !self.https) { Some(self.http_port.unwrap_or(80)) } else { None } } fn https_port(&self) -> Option<u16> { if self.https || self.https_port.is_some() { Some(self.https_port.unwrap_or(443)) } else { None } } fn acceptor(&self, options: &Options) -> Result<AxumAcceptor> { let config = AcmeConfig::new(self.acme_domains()?) .contact(&self.acme_contact) .cache_option(Some(DirCache::new(Self::acme_cache( self.acme_cache.as_ref(),#45,024,042textuse {super::*, crate::wallet::Wallet}; #[derive(Debug, Parser)] pub(crate) struct Sats { #[arg( long, help = "Find satoshis listed in first column of tab-separated value file <TSV>." )] tsv: Option<PathBuf>, } #[derive(Serialize, Deserialize)] pub struct OutputTsv { pub sat: String, pub output: OutPoint, } #[derive(Serialize, Deserialize)] pub struct OutputRare { pub sat: Sat, pub output: OutPoint, pub offset: u64, pub rarity: Rarity, } impl Sats { pub(crate) fn run(&self, options: Options) -> SubcommandResult { let index = Index::open(&options)?; if !index.has_sat_index() { bail!("sats requires index created with `--index-sats` flag"); } index.update()?; let utxos = index.get_unspent_output_ranges(Wallet::load(&options)?)?; if let Some(path) = &self.tsv { let mut output = Vec::new(); for (outpoint, sat) in sats_from_tsv( utxos, &fs::read_to_string(path) .with_context(|| format!("I/O error reading `{}`", path.display()))?,#45,024,031text server.assert_response_regex( format!("/preview/{inscription_id}"), StatusCode::OK, format!(r".*<audio .*>\s*<source src=/content/{inscription_id}>.*"), ); } #[test] fn font_preview() { let server = TestServer::new_with_regtest(); server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { inputs: &[(1, 0, 0, inscription("font/ttf", "hello").to_witness())], ..Default::default() }); let inscription_id = InscriptionId { txid, index: 0 }; server.mine_blocks(1); server.assert_response_regex( format!("/preview/{inscription_id}"), StatusCode::OK, format!(r".*src: url\(/content/{inscription_id}\).*"), ); } #[test] fn pdf_preview() { let server = TestServer::new_with_regtest(); server.mine_blocks(1); let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate { inputs: &[( 1, 0, 0, inscription("application/pdf", "hello").to_witness(),#45,023,991text let string = $string; if !regex.is_match(string.as_ref()) { panic!( "Regex:\n\n{}\n\n…did not match string:\n\n{}", regex, string ); } }; } type Inscribe = ord::subcommand::wallet::inscribe::Output; fn inscribe(rpc_server: &test_bitcoincore_rpc::Handle) -> (InscriptionId, Txid) { rpc_server.mine_blocks(1); let output = CommandBuilder::new("wallet inscribe --fee-rate 1 --file foo.txt") .write("foo.txt", "FOO") .rpc_server(rpc_server) .run_and_deserialize_output::<Inscribe>(); rpc_server.mine_blocks(1); assert_eq!(output.inscriptions.len(), 1); (output.inscriptions[0].id, output.reveal) } fn envelope(payload: &[&[u8]]) -> bitcoin::Witness { let mut builder = bitcoin::script::Builder::new() .push_opcode(bitcoin::opcodes::OP_FALSE) .push_opcode(bitcoin::opcodes::all::OP_IF); for data in payload { let mut buf = bitcoin::script::PushBytesBuf::new(); buf.extend_from_slice(data).unwrap(); builder = builder.push_slice(buf); #45,023,974text ..Default::default() }); context.mine_blocks(1); let id = RuneId { height: 2, index: 1, }; context.assert_runes( [( id, RuneEntry { etching: txid0, rune: Rune(RUNE), supply: u128::max_value(), timestamp: 2, ..Default::default() }, )], [( OutPoint { txid: txid0, vout: 0, }, vec![(id, u128::max_value())], )], ); let txid1 = context.rpc_server.broadcast_tx(TransactionTemplate { inputs: &[(2, 1, 0, Witness::new())], outputs: 2, op_return: Some( Runestone { edicts: vec![ Edict { id: id.into(), amount: 1000, output: 0, }, Edict { id: id.into(), amount: 0, output: 3, }, ], ..Default::default() } .encipher(), ), ..Default::default()#45,023,973textdmt-mint.nat#44,718,412tapdmt-mint.nat#44,718,279tapdmt-mint.nat#44,718,270tapdmt-mint.nat#44,718,253tapdmt-mint.nat#44,718,252tapdmt-mint.nat#44,718,214tapdmt-mint.nat#44,718,198tapdmt-mint.nat#44,718,145tapdmt-mint.nat#44,718,092tapdmt-mint.nat#44,718,080tapdmt-mint.nat#44,713,362tapdmt-mint.nat#44,713,254tapdmt-mint.nat#44,713,231tapdmt-mint.nat#44,713,032tapdmt-mint.nat#44,713,001tapdmt-mint.nat#44,712,926tapdmt-mint.nat#44,712,901tapdmt-mint.nat#44,712,883tapdmt-mint.nat#44,712,757tapdmt-mint.nat#44,712,738tapdmt-mint.nat#42,529,782tapdmt-mint.nat#42,529,727tapdmt-mint.nat#42,529,404tapdmt-mint.nat#42,529,274tapdmt-mint.nat#42,529,028tapdmt-mint.nat#42,528,823tapdmt-mint.nat#42,528,763tapdmt-mint.nat#42,528,675tapdmt-mint.nat#42,528,579tapdmt-mint.nat#42,524,788tapdmt-mint.nat#42,524,765tapdmt-mint.nat#42,524,753tapdmt-mint.nat#42,524,736tapdmt-mint.nat#42,524,726tapdmt-mint.nat#42,524,709tapdmt-mint.nat#42,524,703tapdmt-mint.nat#42,524,701tapdmt-mint.nat#42,522,335tapdmt-mint.nat#42,522,313tapdmt-mint.nat#42,522,277tapdmt-mint.nat#42,522,273tapdmt-mint.nat#42,522,271tapdmt-mint.nat#42,521,204tapdmt-mint.nat#42,521,194tapdmt-mint.nat#42,520,041tapdmt-mint.nat#42,520,040tapdmt-mint.nat#42,520,039tapdmt-mint.nat#42,512,467tapdmt-mint.nat#42,512,456tapdmt-mint.nat#42,512,446tapdmt-mint.nat#42,512,437tapdmt-mint.nat#42,512,415tapdmt-mint.nat#42,511,710tap