Skip to content

Commit a871b08

Browse files
committed
feat: add id_from_pos support
1 parent 6fe96fd commit a871b08

File tree

4 files changed

+101
-0
lines changed

4 files changed

+101
-0
lines changed

src/api.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,17 @@ pub trait ElectrumApi {
200200
/// Returns the merkle path for the transaction `txid` confirmed in the block at `height`.
201201
fn transaction_get_merkle(&self, txid: &Txid, height: usize) -> Result<GetMerkleRes, Error>;
202202

203+
/// Returns a transaction hash, given a block `height` and a `tx_pos` in the block.
204+
fn txid_from_pos(&self, height: usize, tx_pos: usize) -> Result<Txid, Error>;
205+
206+
/// Returns a transaction hash and a merkle path, given a block `height` and a `tx_pos` in the
207+
/// block.
208+
fn txid_from_pos_with_merkle(
209+
&self,
210+
height: usize,
211+
tx_pos: usize,
212+
) -> Result<TxidFromPosRes, Error>;
213+
203214
/// Returns the capabilities of the server.
204215
fn server_features(&self) -> Result<ServerFeaturesRes, Error>;
205216

src/client.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,20 @@ impl ElectrumApi for Client {
327327
impl_inner_call!(self, transaction_get_merkle, txid, height)
328328
}
329329

330+
#[inline]
331+
fn txid_from_pos(&self, height: usize, tx_pos: usize) -> Result<Txid, Error> {
332+
impl_inner_call!(self, txid_from_pos, height, tx_pos)
333+
}
334+
335+
#[inline]
336+
fn txid_from_pos_with_merkle(
337+
&self,
338+
height: usize,
339+
tx_pos: usize,
340+
) -> Result<TxidFromPosRes, Error> {
341+
impl_inner_call!(self, txid_from_pos_with_merkle, height, tx_pos)
342+
}
343+
330344
#[inline]
331345
fn server_features(&self) -> Result<ServerFeaturesRes, Error> {
332346
impl_inner_call!(self, server_features)

src/raw_client.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,38 @@ impl<T: Read + Write> ElectrumApi for RawClient<T> {
11021102
Ok(serde_json::from_value(result)?)
11031103
}
11041104

1105+
fn txid_from_pos(&self, height: usize, tx_pos: usize) -> Result<Txid, Error> {
1106+
let params = vec![Param::Usize(height), Param::Usize(tx_pos)];
1107+
let req = Request::new_id(
1108+
self.last_id.fetch_add(1, Ordering::SeqCst),
1109+
"blockchain.transaction.id_from_pos",
1110+
params,
1111+
);
1112+
let result = self.call(req)?;
1113+
1114+
Ok(serde_json::from_value(result)?)
1115+
}
1116+
1117+
fn txid_from_pos_with_merkle(
1118+
&self,
1119+
height: usize,
1120+
tx_pos: usize,
1121+
) -> Result<TxidFromPosRes, Error> {
1122+
let params = vec![
1123+
Param::Usize(height),
1124+
Param::Usize(tx_pos),
1125+
Param::Bool(true),
1126+
];
1127+
let req = Request::new_id(
1128+
self.last_id.fetch_add(1, Ordering::SeqCst),
1129+
"blockchain.transaction.id_from_pos",
1130+
params,
1131+
);
1132+
let result = self.call(req)?;
1133+
1134+
Ok(serde_json::from_value(result)?)
1135+
}
1136+
11051137
fn server_features(&self) -> Result<ServerFeaturesRes, Error> {
11061138
let req = Request::new_id(
11071139
self.last_id.fetch_add(1, Ordering::SeqCst),
@@ -1396,6 +1428,39 @@ mod test {
13961428
));
13971429
}
13981430

1431+
#[test]
1432+
fn test_txid_from_pos() {
1433+
use bitcoin::Txid;
1434+
1435+
let client = RawClient::new(get_test_server(), None).unwrap();
1436+
1437+
let txid =
1438+
Txid::from_str("1f7ff3c407f33eabc8bec7d2cc230948f2249ec8e591bcf6f971ca9366c8788d")
1439+
.unwrap();
1440+
let resp = client.txid_from_pos(630000, 68).unwrap();
1441+
assert_eq!(resp, txid);
1442+
}
1443+
1444+
#[test]
1445+
fn test_txid_from_pos_with_merkle() {
1446+
use bitcoin::Txid;
1447+
1448+
let client = RawClient::new(get_test_server(), None).unwrap();
1449+
1450+
let txid =
1451+
Txid::from_str("1f7ff3c407f33eabc8bec7d2cc230948f2249ec8e591bcf6f971ca9366c8788d")
1452+
.unwrap();
1453+
let resp = client.txid_from_pos_with_merkle(630000, 68).unwrap();
1454+
assert_eq!(resp.tx_hash, txid);
1455+
assert_eq!(
1456+
resp.merkle[0],
1457+
[
1458+
34, 65, 51, 64, 49, 139, 115, 189, 185, 246, 70, 225, 168, 193, 217, 195, 47, 66,
1459+
179, 240, 153, 24, 114, 215, 144, 196, 212, 41, 39, 155, 246, 25
1460+
]
1461+
);
1462+
}
1463+
13991464
#[test]
14001465
fn test_ping() {
14011466
let client = RawClient::new(get_test_server(), None).unwrap();

src/types.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,17 @@ pub struct GetMerkleRes {
240240
pub merkle: Vec<[u8; 32]>,
241241
}
242242

243+
/// Response to a [`txid_from_pos_with_merkle`](../client/struct.Client.html#method.txid_from_pos_with_merkle)
244+
/// request.
245+
#[derive(Clone, Debug, Deserialize)]
246+
pub struct TxidFromPosRes {
247+
/// Txid of the transaction.
248+
pub tx_hash: Txid,
249+
/// The merkle path of the transaction.
250+
#[serde(deserialize_with = "from_hex_array")]
251+
pub merkle: Vec<[u8; 32]>,
252+
}
253+
243254
/// Notification of a new block header
244255
#[derive(Clone, Debug, Deserialize)]
245256
pub struct HeaderNotification {

0 commit comments

Comments
 (0)