diff --git a/.gitignore b/.gitignore index 26154489a5..ee4580c20f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ /target /test-times.txt /tmp +inscription_satpoint.txt diff --git a/docs/src/guides/inscriptions.md b/docs/src/guides/inscriptions.md index c8824b5077..e9fe3e2993 100644 --- a/docs/src/guides/inscriptions.md +++ b/docs/src/guides/inscriptions.md @@ -166,7 +166,7 @@ Creating Inscriptions To create an inscription with the contents of `FILE`, run: ``` -ord wallet inscribe FILE +ord wallet inscribe --fee-rate FEE_RATE FILE ``` Ord will output two transactions IDs, one for the commit transaction, and one diff --git a/src/index.rs b/src/index.rs index e4c02d853c..eb79d8f2a4 100644 --- a/src/index.rs +++ b/src/index.rs @@ -568,7 +568,6 @@ impl Index { .open_table(SATPOINT_TO_INSCRIPTION_ID)?, outpoint, )? - .into_iter() .map(|(_satpoint, inscription_id)| inscription_id) .collect(), ) diff --git a/src/index/updater.rs b/src/index/updater.rs index 5d56e4e9ab..ad109378f1 100644 --- a/src/index/updater.rs +++ b/src/index/updater.rs @@ -102,6 +102,7 @@ impl Updater { let mut uncommitted = 0; let mut value_cache = HashMap::new(); + loop { let block = match rx.recv() { Ok(block) => block, @@ -113,10 +114,21 @@ impl Updater { &mut outpoint_sender, &mut value_receiver, &mut wtx, - block, + &block, &mut value_cache, )?; + if self.height.checked_sub(1).is_some() { + log::info!( + target: "new_inscription_satpoint", + "{{\"height\":{},\"block_hash\":\"{}\",\"prev_block_hash\":\"{}\",\"tx_count\":{}}}", + &self.height - 1, + &block.header.block_hash(), + &block.header.prev_blockhash, + &block.txdata.len(), + ); + } + if let Some(progress_bar) = &mut progress_bar { progress_bar.inc(1); @@ -333,7 +345,7 @@ impl Updater { outpoint_sender: &mut Sender, value_receiver: &mut Receiver, wtx: &mut WriteTransaction, - block: BlockData, + block: &BlockData, value_cache: &mut HashMap, ) -> Result<()> { // If value_receiver still has values something went wrong with the last block diff --git a/src/index/updater/inscription_updater.rs b/src/index/updater/inscription_updater.rs index 575ccf7ca7..56309308dd 100644 --- a/src/index/updater/inscription_updater.rs +++ b/src/index/updater/inscription_updater.rs @@ -4,6 +4,7 @@ pub(super) struct Flotsam { inscription_id: InscriptionId, offset: u64, origin: Origin, + tx_in: Option, } enum Origin { @@ -87,6 +88,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { offset: input_value + old_satpoint.offset, inscription_id, origin: Origin::Old(old_satpoint), + tx_in: None, }); } @@ -115,6 +117,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { inscription_id: txid.into(), offset: 0, origin: Origin::New(input_value - tx.output.iter().map(|txout| txout.value).sum::()), + tx_in: tx.input.get(0).cloned(), }); }; @@ -239,6 +242,37 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { self.satpoint_to_id.insert(&new_satpoint, &inscription_id)?; self.id_to_satpoint.insert(&inscription_id, &new_satpoint)?; + let inscription_id = InscriptionId::load(inscription_id); + let satpoint = SatPoint::load(new_satpoint); + let inscription_entry = self.id_to_entry.get(&inscription_id.store())?.unwrap(); + let inscription_number = InscriptionEntry::load(inscription_entry.value()).number; + + if let Some(tx_in) = flotsam.tx_in { + let inscription = Inscription::from_tx_input(&tx_in).unwrap(); + let content_type = inscription.content_type().unwrap_or(""); + let content_len = inscription.body().map_or(0, |body| body.len()); + + log::info!( + target: "new_inscription_satpoint", + "{},{},{},{},{},{}", + self.height, + satpoint, + inscription_id, + inscription_number, + content_type, + content_len, + ); + } else { + log::info!( + target: "new_inscription_satpoint", + "{},{},{},{}", + self.height, + satpoint, + inscription_id, + inscription_number, + ); + } + Ok(()) } } diff --git a/src/inscription.rs b/src/inscription.rs index d0fba77016..4d32b12f23 100644 --- a/src/inscription.rs +++ b/src/inscription.rs @@ -30,6 +30,17 @@ impl Inscription { pub(crate) fn from_transaction(tx: &Transaction) -> Option { InscriptionParser::parse(&tx.input.get(0)?.witness).ok() + // for input in &tx.input { + // if let Some(inscription) = Inscription::from_tx_input(input) { + // return Some(inscription); + // } + // } + + // None + } + + pub(crate) fn from_tx_input(tx_in: &TxIn) -> Option { + InscriptionParser::parse(&tx_in.witness).ok() } pub(crate) fn from_file(chain: Chain, path: impl AsRef) -> Result { @@ -389,6 +400,17 @@ mod tests { ); } + #[test] + fn no_content_type_and_no_body() { + assert_eq!( + InscriptionParser::parse(&envelope(&[b"ord"])), + Ok(Inscription { + content_type: None, + body: None, + }), + ); + } + #[test] fn valid_body_in_multiple_pushes() { assert_eq!( diff --git a/src/lib.rs b/src/lib.rs index ca7229fe56..37ce5f10c8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,8 +54,8 @@ use { env, ffi::OsString, fmt::{self, Display, Formatter}, - fs::{self, File}, - io, + fs::{self, File, OpenOptions}, + io::{self, Write}, net::{TcpListener, ToSocketAddrs}, ops::{Add, AddAssign, Sub}, path::{Path, PathBuf}, @@ -144,7 +144,20 @@ fn timestamp(seconds: u32) -> DateTime { const INTERRUPT_LIMIT: u64 = 5; pub fn main() { - env_logger::init(); + let inscription_satpoint_logs_file = OpenOptions::new() + .write(true) + .append(true) + .create(true) + .open("inscription_satpoint.txt") + .unwrap(); + + env_logger::builder() + .filter(Some("new_inscription_satpoint"), log::LevelFilter::Info) + .target(env_logger::Target::Pipe(Box::new( + inscription_satpoint_logs_file, + ))) + .format(|buf, record| writeln!(buf, "{}", record.args())) + .init(); ctrlc::set_handler(move || { LISTENERS diff --git a/src/subcommand.rs b/src/subcommand.rs index cc1848b252..655a6b25fa 100644 --- a/src/subcommand.rs +++ b/src/subcommand.rs @@ -12,6 +12,7 @@ pub mod subsidy; pub mod supply; pub mod traits; pub mod wallet; +pub mod witness; fn print_json(output: impl Serialize) -> Result { serde_json::to_writer_pretty(io::stdout(), &output)?; @@ -45,6 +46,8 @@ pub(crate) enum Subcommand { Traits(traits::Traits), #[clap(subcommand, about = "Wallet commands")] Wallet(wallet::Wallet), + #[clap(subcommand, about = "Extract witness content from inscription")] + Witness(witness::Witness), } impl Subcommand { @@ -67,6 +70,7 @@ impl Subcommand { Self::Supply => supply::run(), Self::Traits(traits) => traits.run(), Self::Wallet(wallet) => wallet.run(options), + Self::Witness(witness) => witness.run(options), } } } diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 63adafb300..cee9d0070e 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -12,12 +12,12 @@ use { }, axum::{ body, - extract::{Extension, Path, Query}, + extract::{Extension, Path, Query, RawBody}, headers::UserAgent, http::{header, HeaderMap, HeaderValue, StatusCode, Uri}, response::{IntoResponse, Redirect, Response}, - routing::get, - Router, TypedHeader, + routing::{get, post}, + Json, Router, TypedHeader, }, axum_server::Handle, rust_embed::RustEmbed, @@ -27,7 +27,7 @@ use { caches::DirCache, AcmeConfig, }, - std::{cmp::Ordering, str}, + std::{cmp::Ordering, str, collections::HashMap}, tokio_stream::StreamExt, tower_http::{ compression::CompressionLayer, @@ -87,11 +87,34 @@ impl Display for StaticHtml { } } +#[derive(Serialize, Deserialize, Clone)] +struct InscriptionData { + number: u64, + id: InscriptionId, + owner_address: Address, + location: SatPoint, + genesis_height: u64, + genesis_transaction: Txid, + creator_address: Address, + content_length: usize, + content_type: String, +} + +#[derive(Serialize)] +struct InscriptionsDataResult { + inscriptions: HashMap, +} + +#[derive(Serialize, Deserialize, Debug)] +struct InscriptionsDataRequest { + ids: Vec, +} + #[derive(Debug, Parser)] pub(crate) struct Server { #[clap( long, - default_value = "0.0.0.0", + default_value = "127.0.0.1", help = "Listen on
for incoming requests." )] address: String, @@ -154,6 +177,7 @@ impl Server { .route("/feed.xml", get(Self::feed)) .route("/input/:block/:transaction/:input", get(Self::input)) .route("/inscription/:inscription_id", get(Self::inscription)) + .route("/inscriptions-data/", post(Self::inscriptions_data)) .route("/inscriptions", get(Self::inscriptions)) .route("/inscriptions/:from", get(Self::inscriptions_from)) .route("/install.sh", get(Self::install_script)) @@ -768,7 +792,7 @@ impl Server { .get_inscription_by_id(inscription_id)? .ok_or_not_found(|| format!("inscription {inscription_id}"))?; - return match inscription.media() { + match inscription.media() { Media::Audio => Ok(PreviewAudioHtml { inscription_id }.into_response()), Media::Iframe => Ok( Self::content_response(inscription) @@ -809,7 +833,101 @@ impl Server { } Media::Unknown => Ok(PreviewUnknownHtml.into_response()), Media::Video => Ok(PreviewVideoHtml { inscription_id }.into_response()), + } + } + + async fn inscriptions_data( + Extension(page_config): Extension>, + Extension(index): Extension>, + RawBody(body): RawBody, + ) -> ServerResult> { + let body_bytes = hyper::body::to_bytes(body).await.unwrap().to_vec(); + let body_string = String::from_utf8(body_bytes).unwrap(); + let request_body = serde_json::from_str::(&body_string).unwrap(); + + let inscriptions = request_body.ids; + let mut data_map: HashMap = HashMap::new(); + + for inscription_id in inscriptions.into_iter() { + match Server::get_inscription_data(&index, page_config.chain, inscription_id).await { + Ok(inscription_data) => { + data_map.insert(inscription_id, inscription_data); + } + Err(_) => { + // skip broken inscriptions + continue; + } + } + } + + let inscription_data_result = InscriptionsDataResult { + inscriptions: data_map, }; + + Ok(Json(inscription_data_result)) + } + + async fn get_inscription_data( + index: &Arc, + chain: Chain, + inscription_id: InscriptionId, + ) -> Result { + let entry = index.get_inscription_entry(inscription_id)?.unwrap(); + + let inscription = index.get_inscription_by_id(inscription_id)?.unwrap(); + + let satpoint = index + .get_inscription_satpoint_by_id(inscription_id)? + .unwrap(); + + let output = index + .get_transaction(satpoint.outpoint.txid)? + .unwrap() + .output + .into_iter() + .nth(satpoint.outpoint.vout.try_into().unwrap()) + .unwrap(); + + let previous_outpoint = index + .get_transaction(inscription_id.txid)? + .unwrap() + .input + .into_iter() + .nth(inscription_id.index.try_into().unwrap()) + .unwrap() + .previous_output; + + let previous_output = index + .get_transaction(previous_outpoint.txid)? + .unwrap() + .output + .into_iter() + .nth(previous_outpoint.vout.try_into().unwrap()) + .unwrap(); + + let owner_address = chain + .address_from_script(&output.script_pubkey) + .ok() + .unwrap(); + + let creator_address = chain + .address_from_script(&previous_output.script_pubkey) + .ok() + .unwrap(); + + let inscription_data = InscriptionData { + number: entry.number, + id: inscription_id, + owner_address, + genesis_height: entry.height, + genesis_transaction: inscription_id.txid, + creator_address, + location: satpoint, + content_length: inscription.content_length().unwrap_or(0), + content_type: inscription.content_type().unwrap_or("").to_string(), + }; + + Ok(inscription_data) } async fn inscription( diff --git a/src/subcommand/wallet.rs b/src/subcommand/wallet.rs index 0404f2ad24..914805d5af 100644 --- a/src/subcommand/wallet.rs +++ b/src/subcommand/wallet.rs @@ -15,6 +15,7 @@ use { }; pub mod balance; +pub mod cardinals; pub mod create; pub(crate) mod inscribe; pub mod inscriptions; @@ -46,8 +47,10 @@ pub(crate) enum Wallet { Send(send::Send), #[clap(about = "See wallet transactions")] Transactions(transactions::Transactions), - #[clap(about = "List wallet outputs")] + #[clap(about = "List all unspent outputs in wallet")] Outputs, + #[clap(about = "List unspent cardinal outputs in wallet")] + Cardinals, } impl Wallet { @@ -63,6 +66,7 @@ impl Wallet { Self::Send(send) => send.run(options), Self::Transactions(transactions) => transactions.run(options), Self::Outputs => outputs::run(options), + Self::Cardinals => cardinals::run(options), } } } @@ -136,7 +140,7 @@ fn derive_and_import_descriptor( active: Some(true), range: None, next_index: None, - internal: Some(!change), + internal: Some(change), label: None, })?; diff --git a/src/subcommand/wallet/cardinals.rs b/src/subcommand/wallet/cardinals.rs new file mode 100644 index 0000000000..32076229a1 --- /dev/null +++ b/src/subcommand/wallet/cardinals.rs @@ -0,0 +1,37 @@ +use {super::*, crate::wallet::Wallet, std::collections::BTreeSet}; + +#[derive(Serialize, Deserialize)] +pub struct Cardinal { + pub output: OutPoint, + pub amount: u64, +} + +pub(crate) fn run(options: Options) -> Result { + let index = Index::open(&options)?; + index.update()?; + + let inscribed_utxos = index + .get_inscriptions(None)? + .keys() + .map(|satpoint| satpoint.outpoint) + .collect::>(); + + let cardinal_utxos = index + .get_unspent_outputs(Wallet::load(&options)?)? + .iter() + .filter_map(|(output, amount)| { + if inscribed_utxos.contains(output) { + None + } else { + Some(Cardinal { + output: *output, + amount: amount.to_sat(), + }) + } + }) + .collect::>(); + + print_json(cardinal_utxos)?; + + Ok(()) +} diff --git a/src/subcommand/wallet/inscribe.rs b/src/subcommand/wallet/inscribe.rs index d9b537f82d..1df5c15061 100644 --- a/src/subcommand/wallet/inscribe.rs +++ b/src/subcommand/wallet/inscribe.rs @@ -30,11 +30,7 @@ struct Output { pub(crate) struct Inscribe { #[clap(long, help = "Inscribe ")] pub(crate) satpoint: Option, - #[clap( - long, - default_value = "1.0", - help = "Use fee rate of sats/vB" - )] + #[clap(long, help = "Use fee rate of sats/vB")] pub(crate) fee_rate: FeeRate, #[clap( long, diff --git a/src/subcommand/wallet/transaction_builder.rs b/src/subcommand/wallet/transaction_builder.rs index aed340be39..11f73d4f65 100644 --- a/src/subcommand/wallet/transaction_builder.rs +++ b/src/subcommand/wallet/transaction_builder.rs @@ -427,7 +427,6 @@ impl TransactionBuilder { version: 1, lock_time: PackedLockTime::ZERO, input: (0..inputs) - .into_iter() .map(|_| TxIn { previous_output: OutPoint::null(), script_sig: Script::new(), diff --git a/src/subcommand/witness.rs b/src/subcommand/witness.rs new file mode 100644 index 0000000000..fec8cd0cef --- /dev/null +++ b/src/subcommand/witness.rs @@ -0,0 +1,21 @@ +use super::*; + +pub(crate) mod ctype; +pub(crate) mod file; + +#[derive(Debug, Parser)] +pub(crate) enum Witness { + #[clap(about = "Display the content type from an inscription")] + Ctype(ctype::Ctype), + #[clap(about = "Write the inscription content to a file")] + File(file::File), +} + +impl Witness { + pub(crate) fn run(self, options: Options) -> Result { + match self { + Self::Ctype(ctype) => ctype.run(options), + Self::File(file) => file.run(options), + } + } +} diff --git a/src/subcommand/witness/ctype.rs b/src/subcommand/witness/ctype.rs new file mode 100644 index 0000000000..d99b3916d6 --- /dev/null +++ b/src/subcommand/witness/ctype.rs @@ -0,0 +1,24 @@ +use super::*; + +#[derive(Debug, Parser)] +pub(crate) struct Ctype { + #[clap(help = "The inscription to extract the content type.")] + inscription_id: String, +} + +impl Ctype { + pub(crate) fn run(self, options: Options) -> Result { + let inscription_id = InscriptionId::from_str(self.inscription_id.as_str())?; + + let index = Index::open(&options)?; + index.update()?; + + let inscription = index + .get_inscription_by_id(inscription_id)? + .ok_or_else(|| anyhow!("Inscription {} not found", inscription_id))?; + + println!("{}", inscription.content_type().unwrap()); + + Ok(()) + } +} diff --git a/src/subcommand/witness/file.rs b/src/subcommand/witness/file.rs new file mode 100644 index 0000000000..006957b6b4 --- /dev/null +++ b/src/subcommand/witness/file.rs @@ -0,0 +1,33 @@ +use std::io::Write; + +use super::*; + +#[derive(Debug, Parser)] +pub(crate) struct File { + #[clap(help = "The inscription to extract the content.")] + inscription_id: String, + #[clap(help = "The name of the file to be created with the inscription content.")] + filename: String, +} + +impl File { + pub(crate) fn run(self, options: Options) -> Result { + let inscription_id = InscriptionId::from_str(self.inscription_id.as_str())?; + + let index = Index::open(&options)?; + index.update()?; + + let inscription = index + .get_inscription_by_id(inscription_id)? + .ok_or_else(|| anyhow!("Inscription {} not found", inscription_id))?; + + let mut file = fs::File::create(self.filename)?; + if let Some(content_bytes) = inscription.body() { + file.write_all(content_bytes)?; + } + + println!("{}", file.metadata()?.len()); + + Ok(()) + } +} diff --git a/src/templates.rs b/src/templates.rs index f4344309e6..7a8858a869 100644 --- a/src/templates.rs +++ b/src/templates.rs @@ -137,7 +137,7 @@ mod tests { rare.txt
- +
diff --git a/static/index.css b/static/index.css index a8faeb6616..36a1551793 100644 --- a/static/index.css +++ b/static/index.css @@ -4,8 +4,8 @@ --dark-fg: #98a3ad; --epic: darkorchid; --legendary: gold; - --light-bg: #292c2f; - --light-fg: #a1adb8; + --light-bg: #000000; + --light-fg: #ffffff; --link: #4169e1; --mythic: #f2a900; --rare: cornflowerblue; @@ -48,10 +48,6 @@ a:hover { text-decoration: underline; } -a:visited { - color: var(--link); -} - dt { font-weight: bold; margin-top: 0.5rem; @@ -70,6 +66,15 @@ nav > :first-child { font-weight: bold; } +nav a:hover { + color: var(--link); + text-decoration: none; +} + +nav a { + color: var(--light-fg); +} + form { display: flex; flex-grow: 1; @@ -87,6 +92,17 @@ input[type=text] { min-width: 0; } +input[type=submit] { + background: none; + border: none; + color: var(--light-fg); + cursor: pointer; + font-weight: bold; + font: inherit; + outline: inherit; + padding: 0; +} + dl { overflow-wrap: break-word; } diff --git a/templates/page.html b/templates/page.html index 8e5a25ed1e..6d1faccff3 100644 --- a/templates/page.html +++ b/templates/page.html @@ -25,7 +25,7 @@ %% }
- +
diff --git a/tests/lib.rs b/tests/lib.rs index 710e6b2a88..0639c15570 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -48,7 +48,7 @@ struct Inscribe { fn inscribe(rpc_server: &test_bitcoincore_rpc::Handle) -> Inscribe { rpc_server.mine_blocks(1); - let output = CommandBuilder::new("wallet inscribe foo.txt") + let output = CommandBuilder::new("wallet inscribe --fee-rate 1 foo.txt") .write("foo.txt", "FOO") .rpc_server(rpc_server) .output(); diff --git a/tests/wallet.rs b/tests/wallet.rs index 31dc1d96a0..3e04064183 100644 --- a/tests/wallet.rs +++ b/tests/wallet.rs @@ -1,6 +1,7 @@ use super::*; mod balance; +mod cardinals; mod create; mod inscribe; mod inscriptions; diff --git a/tests/wallet/cardinals.rs b/tests/wallet/cardinals.rs new file mode 100644 index 0000000000..19053f4389 --- /dev/null +++ b/tests/wallet/cardinals.rs @@ -0,0 +1,23 @@ +use { + super::*, + ord::subcommand::wallet::{cardinals::Cardinal, outputs::Output}, +}; + +#[test] +fn cardinals() { + let rpc_server = test_bitcoincore_rpc::spawn(); + create_wallet(&rpc_server); + + // this creates 2 more cardinal outputs and one inscribed output + inscribe(&rpc_server); + + let all_outputs = CommandBuilder::new("wallet outputs") + .rpc_server(&rpc_server) + .output::>(); + + let cardinal_outputs = CommandBuilder::new("wallet cardinals") + .rpc_server(&rpc_server) + .output::>(); + + assert_eq!(all_outputs.len() - cardinal_outputs.len(), 1); +} diff --git a/tests/wallet/inscribe.rs b/tests/wallet/inscribe.rs index 16b486037e..50ecca7dda 100644 --- a/tests/wallet/inscribe.rs +++ b/tests/wallet/inscribe.rs @@ -42,7 +42,7 @@ fn inscribe_works_with_huge_expensive_inscriptions() { fn inscribe_fails_if_bitcoin_core_is_too_old() { let rpc_server = test_bitcoincore_rpc::builder().version(230000).build(); - CommandBuilder::new("wallet inscribe hello.txt") + CommandBuilder::new("wallet inscribe hello.txt --fee-rate 1") .write("hello.txt", "HELLOWORLD") .expected_exit_code(1) .expected_stderr("error: Bitcoin Core 24.0.0 or newer required, current version is 23.0.0\n") @@ -58,7 +58,7 @@ fn inscribe_no_backup() { create_wallet(&rpc_server); assert_eq!(rpc_server.descriptors().len(), 2); - CommandBuilder::new("wallet inscribe hello.txt --no-backup") + CommandBuilder::new("wallet inscribe hello.txt --no-backup --fee-rate 1") .write("hello.txt", "HELLOWORLD") .rpc_server(&rpc_server) .output::(); @@ -72,7 +72,7 @@ fn inscribe_unknown_file_extension() { create_wallet(&rpc_server); rpc_server.mine_blocks(1); - CommandBuilder::new("wallet inscribe pepe.xyz") + CommandBuilder::new("wallet inscribe pepe.xyz --fee-rate 1") .write("pepe.xyz", [1; 520]) .rpc_server(&rpc_server) .expected_exit_code(1) @@ -88,7 +88,7 @@ fn inscribe_exceeds_chain_limit() { create_wallet(&rpc_server); rpc_server.mine_blocks(1); - CommandBuilder::new("--chain signet wallet inscribe degenerate.png") + CommandBuilder::new("--chain signet wallet inscribe degenerate.png --fee-rate 1") .write("degenerate.png", [1; 1025]) .rpc_server(&rpc_server) .expected_exit_code(1) @@ -106,7 +106,7 @@ fn regtest_has_no_content_size_limit() { create_wallet(&rpc_server); rpc_server.mine_blocks(1); - CommandBuilder::new("--chain regtest wallet inscribe degenerate.png") + CommandBuilder::new("--chain regtest wallet inscribe degenerate.png --fee-rate 1") .write("degenerate.png", [1; 1025]) .rpc_server(&rpc_server) .stdout_regex(".*") @@ -121,7 +121,7 @@ fn mainnet_has_no_content_size_limit() { create_wallet(&rpc_server); rpc_server.mine_blocks(1); - CommandBuilder::new("wallet inscribe degenerate.png") + CommandBuilder::new("wallet inscribe degenerate.png --fee-rate 1") .write("degenerate.png", [1; 1025]) .rpc_server(&rpc_server) .stdout_regex(".*") @@ -136,7 +136,7 @@ fn inscribe_does_not_use_inscribed_sats_as_cardinal_utxos() { rpc_server.mine_blocks_with_subsidy(1, 100); CommandBuilder::new( - "wallet inscribe degenerate.png" + "wallet inscribe degenerate.png --fee-rate 1" ) .rpc_server(&rpc_server) .write("degenerate.png", [1; 100]) @@ -156,12 +156,14 @@ fn refuse_to_reinscribe_sats() { rpc_server.mine_blocks_with_subsidy(1, 100); - CommandBuilder::new(format!("wallet inscribe --satpoint {reveal}:0:0 hello.txt")) - .write("hello.txt", "HELLOWORLD") - .rpc_server(&rpc_server) - .expected_exit_code(1) - .expected_stderr(format!("error: sat at {reveal}:0:0 already inscribed\n")) - .run(); + CommandBuilder::new(format!( + "wallet inscribe --satpoint {reveal}:0:0 hello.txt --fee-rate 1" + )) + .write("hello.txt", "HELLOWORLD") + .rpc_server(&rpc_server) + .expected_exit_code(1) + .expected_stderr(format!("error: sat at {reveal}:0:0 already inscribed\n")) + .run(); } #[test] @@ -181,7 +183,7 @@ fn refuse_to_inscribe_already_inscribed_utxo() { }; CommandBuilder::new(format!( - "wallet inscribe --satpoint {output}:55555 hello.txt" + "wallet inscribe --satpoint {output}:55555 hello.txt --fee-rate 1" )) .write("hello.txt", "HELLOWORLD") .rpc_server(&rpc_server) @@ -198,11 +200,12 @@ fn inscribe_with_optional_satpoint_arg() { create_wallet(&rpc_server); let txid = rpc_server.mine_blocks(1)[0].txdata[0].txid(); - let Inscribe { inscription, .. } = - CommandBuilder::new(format!("wallet inscribe foo.txt --satpoint {txid}:0:0")) - .write("foo.txt", "FOO") - .rpc_server(&rpc_server) - .output(); + let Inscribe { inscription, .. } = CommandBuilder::new(format!( + "wallet inscribe foo.txt --satpoint {txid}:0:0 --fee-rate 1" + )) + .write("foo.txt", "FOO") + .rpc_server(&rpc_server) + .output(); rpc_server.mine_blocks(1); @@ -262,10 +265,12 @@ fn inscribe_with_commit_fee_rate() { create_wallet(&rpc_server); rpc_server.mine_blocks(1); - CommandBuilder::new("--index-sats wallet inscribe degenerate.png --commit-fee-rate 2.0") - .write("degenerate.png", [1; 520]) - .rpc_server(&rpc_server) - .output::(); + CommandBuilder::new( + "--index-sats wallet inscribe degenerate.png --commit-fee-rate 2.0 --fee-rate 1", + ) + .write("degenerate.png", [1; 520]) + .rpc_server(&rpc_server) + .output::(); let tx1 = &rpc_server.mempool()[0]; let mut fee = 0; @@ -307,7 +312,7 @@ fn inscribe_with_wallet_named_foo() { rpc_server.mine_blocks(1); - CommandBuilder::new("--wallet foo wallet inscribe degenerate.png") + CommandBuilder::new("--wallet foo wallet inscribe degenerate.png --fee-rate 1") .write("degenerate.png", [1; 520]) .rpc_server(&rpc_server) .output::(); @@ -319,14 +324,14 @@ fn inscribe_with_dry_run_flag() { create_wallet(&rpc_server); rpc_server.mine_blocks(1); - CommandBuilder::new("wallet inscribe --dry-run degenerate.png") + CommandBuilder::new("wallet inscribe --dry-run degenerate.png --fee-rate 1") .write("degenerate.png", [1; 520]) .rpc_server(&rpc_server) .output::(); assert!(rpc_server.mempool().is_empty()); - CommandBuilder::new("wallet inscribe degenerate.png") + CommandBuilder::new("wallet inscribe degenerate.png --fee-rate 1") .write("degenerate.png", [1; 520]) .rpc_server(&rpc_server) .output::(); @@ -340,11 +345,12 @@ fn inscribe_with_dry_run_flag_fees_inscrease() { create_wallet(&rpc_server); rpc_server.mine_blocks(1); - let total_fee_dry_run = CommandBuilder::new("wallet inscribe --dry-run degenerate.png") - .write("degenerate.png", [1; 520]) - .rpc_server(&rpc_server) - .output::() - .fees; + let total_fee_dry_run = + CommandBuilder::new("wallet inscribe --dry-run degenerate.png --fee-rate 1") + .write("degenerate.png", [1; 520]) + .rpc_server(&rpc_server) + .output::() + .fees; let total_fee_normal = CommandBuilder::new("wallet inscribe --dry-run degenerate.png --fee-rate 1.1") @@ -368,7 +374,7 @@ fn inscribe_to_specific_destination() { .address; let txid = CommandBuilder::new(format!( - "wallet inscribe --destination {destination} degenerate.png" + "wallet inscribe --destination {destination} degenerate.png --fee-rate 1" )) .write("degenerate.png", [1; 520]) .rpc_server(&rpc_server) @@ -390,7 +396,7 @@ fn inscribe_with_no_limit() { rpc_server.mine_blocks(1); let four_megger = std::iter::repeat(0).take(4_000_000).collect::>(); - CommandBuilder::new("wallet inscribe --no-limit degenerate.png") + CommandBuilder::new("wallet inscribe --no-limit degenerate.png --fee-rate 1") .write("degenerate.png", four_megger) .rpc_server(&rpc_server); }