Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sat ranges to output #3817

Merged
merged 9 commits into from
Jun 28, 2024
4 changes: 2 additions & 2 deletions src/subcommand/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub(crate) enum Subcommand {
#[command(about = "Mint a rune")]
Mint(mint::Mint),
#[command(about = "List all unspent outputs in wallet")]
Outputs,
Outputs(outputs::Outputs),
#[command(about = "List pending etchings")]
Pending(pending::Pending),
#[command(about = "Generate receive address")]
Expand Down Expand Up @@ -113,7 +113,7 @@ impl WalletCommand {
Subcommand::Inscriptions => inscriptions::run(wallet),
Subcommand::Label => label::run(wallet),
Subcommand::Mint(mint) => mint.run(wallet),
Subcommand::Outputs => outputs::run(wallet),
Subcommand::Outputs(outputs) => outputs.run(wallet),
Subcommand::Pending(pending) => pending.run(wallet),
Subcommand::Receive(receive) => receive.run(wallet),
Subcommand::Resume(resume) => resume.run(wallet),
Expand Down
2 changes: 1 addition & 1 deletion src/subcommand/wallet/label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct Line {
pub(crate) fn run(wallet: Wallet) -> SubcommandResult {
let mut lines: Vec<Line> = Vec::new();

let sat_ranges = wallet.get_output_sat_ranges()?;
let sat_ranges = wallet.get_wallet_sat_ranges()?;

let mut inscriptions_by_output: BTreeMap<OutPoint, BTreeMap<u64, Vec<InscriptionId>>> =
BTreeMap::new();
Expand Down
38 changes: 29 additions & 9 deletions src/subcommand/wallet/outputs.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
use super::*;

#[derive(Debug, Parser)]
pub(crate) struct Outputs {
#[arg(short, long, help = "Show list of sat <RANGES> in outputs.")]
ranges: bool,
}

#[derive(Serialize, Deserialize)]
pub struct Output {
pub output: OutPoint,
pub amount: u64,
pub sat_ranges: Vec<String>,
}

pub(crate) fn run(wallet: Wallet) -> SubcommandResult {
let mut outputs = Vec::new();
for (output, txout) in wallet.utxos() {
outputs.push(Output {
output: *output,
amount: txout.value,
});
}
impl Outputs {
pub(crate) fn run(&self, wallet: Wallet) -> SubcommandResult {
let mut outputs = Vec::new();
for (output, txout) in wallet.utxos() {
let sat_ranges = if wallet.has_sat_index() && self.ranges {
wallet
.get_output_sat_ranges(output)?
.into_iter()
.map(|(start, end)| format!("{start}-{end}"))
.collect()
} else {
Vec::new()
};

Ok(Some(Box::new(outputs)))
outputs.push(Output {
output: *output,
amount: txout.value,
sat_ranges,
});
}

Ok(Some(Box::new(outputs)))
}
}
2 changes: 1 addition & 1 deletion src/subcommand/wallet/sats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl Sats {
"sats requires index created with `--index-sats` flag"
);

let haystacks = wallet.get_output_sat_ranges()?;
let haystacks = wallet.get_wallet_sat_ranges()?;

if let Some(path) = &self.tsv {
let tsv = fs::read_to_string(path)
Expand Down
19 changes: 18 additions & 1 deletion src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub(crate) struct Wallet {
}

impl Wallet {
pub(crate) fn get_output_sat_ranges(&self) -> Result<Vec<(OutPoint, Vec<(u64, u64)>)>> {
pub(crate) fn get_wallet_sat_ranges(&self) -> Result<Vec<(OutPoint, Vec<(u64, u64)>)>> {
ensure!(
self.has_sat_index,
"ord index must be built with `--index-sats` to use `--sat`"
Expand All @@ -90,6 +90,23 @@ impl Wallet {
Ok(output_sat_ranges)
}

pub(crate) fn get_output_sat_ranges(&self, output: &OutPoint) -> Result<Vec<(u64, u64)>> {
ensure!(
self.has_sat_index,
"ord index must be built with `--index-sats` to see sat ranges"
);

if let Some(info) = self.output_info.get(output) {
if let Some(sat_ranges) = &info.sat_ranges {
Ok(sat_ranges.clone())
} else {
bail!("output {output} in wallet but is spent according to ord server");
}
} else {
bail!("output {output} not found in wallet");
}
}

pub(crate) fn find_sat_in_outputs(&self, sat: Sat) -> Result<SatPoint> {
ensure!(
self.has_sat_index,
Expand Down
22 changes: 22 additions & 0 deletions tests/wallet/outputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,25 @@ fn outputs_includes_unbound_outputs() {
assert_eq!(output[0].output, outpoint);
assert_eq!(output[0].amount, amount);
}

#[test]
fn outputs_includes_sat_ranges() {
let core = mockcore::spawn();

let ord = TestServer::spawn_with_server_args(&core, &["--index-sats"], &[]);

create_wallet(&core, &ord);

let coinbase_tx = &core.mine_blocks_with_subsidy(1, 1_000_000)[0].txdata[0];
let outpoint = OutPoint::new(coinbase_tx.txid(), 0);
let amount = coinbase_tx.output[0].value;

let output = CommandBuilder::new("wallet outputs --ranges")
.core(&core)
.ord(&ord)
.run_and_deserialize_output::<Vec<Output>>();

assert_eq!(output[0].output, outpoint);
assert_eq!(output[0].amount, amount);
assert_eq!(output[0].sat_ranges, vec!["5000000000-5001000000"]);
}
Loading