Skip to content

Commit 45f4f62

Browse files
author
pythcoiner
committed
add txids param to listspendtxs
1 parent 501dce4 commit 45f4f62

File tree

4 files changed

+78
-9
lines changed

4 files changed

+78
-9
lines changed

doc/API.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,14 @@ This command does not return anything for now.
210210

211211
List stored Spend transactions.
212212

213-
#### Request
214213

215-
This command does not take any parameter for now.
214+
If `txids` is specified, only list transactions whose `txid` is in `txids`(empty list of `txids` is not allowed).
216215

217-
| Field | Type | Description |
218-
| ------------- | ----------------- | ----------------------------------------------------------- |
216+
#### Request
217+
218+
| Field | Type | Description |
219+
| ------------- | -------------------------- | ------------------------------------ |
220+
| `txids` | array of string (optional) | Ids of the transactions to retrieve |
219221

220222
#### Response
221223

src/commands/mod.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -580,13 +580,25 @@ impl DaemonControl {
580580
}
581581
}
582582

583-
pub fn list_spend(&self) -> ListSpendResult {
583+
pub fn list_spend(&self, txids: Option<Vec<bitcoin::Txid>>) -> ListSpendResult {
584584
let mut db_conn = self.db.connection();
585-
let spend_txs = db_conn
586-
.list_spend()
585+
let spend_psbts = db_conn.list_spend();
586+
587+
let txids_set: Option<HashSet<_>> =
588+
txids.as_ref().map(|list| list.iter().cloned().collect());
589+
590+
let spend_txs = spend_psbts
587591
.into_iter()
592+
.filter(|(psbt, _)| {
593+
if let Some(set) = &txids_set {
594+
set.contains(&psbt.unsigned_tx.txid())
595+
} else {
596+
true
597+
}
598+
})
588599
.map(|(psbt, updated_at)| ListSpendEntry { psbt, updated_at })
589600
.collect();
601+
590602
ListSpendResult { spend_txs }
591603
}
592604

src/jsonrpc/api.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::{
1010
str::FromStr,
1111
};
1212

13-
use miniscript::bitcoin::{self, psbt::Psbt};
13+
use miniscript::bitcoin::{self, psbt::Psbt, Txid};
1414

1515
fn create_spend(control: &DaemonControl, params: Params) -> Result<serde_json::Value, Error> {
1616
let destinations = params
@@ -226,6 +226,34 @@ fn list_confirmed(control: &DaemonControl, params: Params) -> Result<serde_json:
226226
))
227227
}
228228

229+
fn list_spendtxs(
230+
control: &DaemonControl,
231+
params: Option<Params>,
232+
) -> Result<serde_json::Value, Error> {
233+
let txids: Option<Vec<bitcoin::Txid>> = if let Some(p) = params {
234+
let tx_ids = p.get(0, "txids");
235+
if let Some(ids) = tx_ids {
236+
let ids: Vec<Txid> = ids
237+
.as_array()
238+
.and_then(|arr| {
239+
arr.iter()
240+
.map(|entry| entry.as_str().and_then(|e| bitcoin::Txid::from_str(e).ok()))
241+
.collect()
242+
})
243+
.ok_or_else(|| Error::invalid_params("Invalid 'txids' parameter."))?;
244+
if ids.is_empty() {
245+
return Err(Error::invalid_params("Invalid 'txids' parameter."));
246+
}
247+
Some(ids)
248+
} else {
249+
None
250+
}
251+
} else {
252+
None
253+
};
254+
Ok(serde_json::json!(&control.list_spend(txids)))
255+
}
256+
229257
fn list_transactions(control: &DaemonControl, params: Params) -> Result<serde_json::Value, Error> {
230258
let txids: Vec<bitcoin::Txid> = params
231259
.get(0, "txids")
@@ -391,7 +419,7 @@ pub fn handle_request(control: &DaemonControl, req: Request) -> Result<Response,
391419
})?;
392420
list_confirmed(control, params)?
393421
}
394-
"listspendtxs" => serde_json::json!(&control.list_spend()),
422+
"listspendtxs" => list_spendtxs(control, req.params)?,
395423
"listtransactions" => {
396424
let params = req.params.ok_or_else(|| {
397425
Error::invalid_params(

tests/test_rpc.py

+27
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,33 @@ def test_list_spend(lianad, bitcoind):
457457
lianad.rpc.updatespend(res["psbt"])
458458
lianad.rpc.updatespend(res_b["psbt"])
459459

460+
# Check 'txids' parameter
461+
list_res = lianad.rpc.listspendtxs()["spend_txs"]
462+
463+
txid = bitcoind.rpc.decodepsbt(list_res[0]['psbt'])['tx']['txid']
464+
465+
filtered_res = lianad.rpc.listspendtxs(txids=[txid])
466+
assert filtered_res['spend_txs'][0]['psbt'] == list_res[0]['psbt']
467+
assert len(filtered_res) == 1
468+
469+
with pytest.raises(RpcError, match="Invalid params: Invalid 'txids' parameter."):
470+
lianad.rpc.listspendtxs(txids=[])
471+
472+
with pytest.raises(RpcError, match="Invalid params: Invalid 'txids' parameter."):
473+
lianad.rpc.listspendtxs(txids=[txid, 123])
474+
475+
with pytest.raises(RpcError, match="Invalid params: Invalid 'txids' parameter."):
476+
lianad.rpc.listspendtxs(txids=[0])
477+
478+
with pytest.raises(RpcError, match="Invalid params: Invalid 'txids' parameter."):
479+
lianad.rpc.listspendtxs(txids=[123])
480+
481+
with pytest.raises(RpcError, match="Invalid params: Invalid 'txids' parameter."):
482+
lianad.rpc.listspendtxs(txids=['abc'])
483+
484+
with pytest.raises(RpcError, match="Invalid params: Invalid 'txids' parameter."):
485+
lianad.rpc.listspendtxs(txids=['123'])
486+
460487
# Listing all Spend transactions will list them both. It'll tell us which one has
461488
# change and which one doesn't.
462489
list_res = lianad.rpc.listspendtxs()["spend_txs"]

0 commit comments

Comments
 (0)