Skip to content

Commit 3d37c50

Browse files
committed
Update support for txout
1 parent 1a6accb commit 3d37c50

3 files changed

Lines changed: 52 additions & 28 deletions

File tree

src/main/java/com/danubetech/btc/connection/impl/BitcoindRPCBitcoinConnection.java

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.danubetech.btc.connection.impl;
22

3-
import com.danubetech.btc.connection.*;
3+
import com.danubetech.btc.connection.BitcoinConnection;
4+
import com.danubetech.btc.connection.Network;
45
import com.danubetech.btc.connection.records.Block;
56
import com.danubetech.btc.connection.records.Tx;
67
import com.danubetech.btc.connection.records.TxIn;
@@ -40,16 +41,16 @@ public Map<String, Object> getMetadata() {
4041
public Block getBlockByBlockHeight(Integer blockHeight) {
4142
BitcoinJSONRPCClient bitcoinJSONRPCClient = this.getBitcoinJsonRpcClient();
4243
wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient.Block bitcoinjBlock = bitcoinJSONRPCClient.getBlock(blockHeight);
43-
List<Tx> txs = bitcoinjBlock.tx().stream().map(tx -> txFromBitcoinjRawTransaction(bitcoinJSONRPCClient, tx)).toList();
44-
Block block = blockFromBitcoinjBlock(bitcoinjBlock);
44+
List<Tx> txs = bitcoinjBlock.tx().stream().map(tx -> txFromBitcoinRawTransaction(bitcoinJSONRPCClient, tx)).toList();
45+
Block block = blockFromBitcoinBlock(bitcoinjBlock);
4546
if (log.isDebugEnabled()) log.debug("getBlockByBlockHeight for {}: {}", blockHeight, block);
4647
return block;
4748
}
4849

4950
@Override
5051
public Tx getTransactionById(String txId) {
5152
BitcoinJSONRPCClient bitcoinJSONRPCClient = this.getBitcoinJsonRpcClient();
52-
Tx tx = txFromBitcoinjRawTransaction(bitcoinJSONRPCClient, txId);
53+
Tx tx = txFromBitcoinRawTransaction(bitcoinJSONRPCClient, txId);
5354
if (log.isDebugEnabled()) log.debug("getTransactionById for {}: {}", txId, tx);
5455
return tx;
5556
}
@@ -62,7 +63,7 @@ public Block getBlockByTargetTime(Long targetTime) {
6263
for (int blockHeight=blocks-1; blockHeight>=0; blockHeight--) {
6364
wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient.Block bitcoinjBlock = bitcoinJSONRPCClient.getBlock(blockHeight);
6465
if (bitcoinjBlock.time().getTime() < targetTime) {
65-
block = blockFromBitcoinjBlock(bitcoinjBlock);
66+
block = blockFromBitcoinBlock(bitcoinjBlock);
6667
break;
6768
}
6869
}
@@ -78,7 +79,7 @@ public Block getBlockByMinConfirmations(Integer minConfirmations) {
7879
for (int blockHeight=blocks-1; blockHeight>=0; blockHeight--) {
7980
wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient.Block bitcoinjBlock = bitcoinJSONRPCClient.getBlock(blockHeight);
8081
if (bitcoinjBlock.confirmations() >= minConfirmations) {
81-
block = blockFromBitcoinjBlock(bitcoinjBlock);
82+
block = blockFromBitcoinBlock(bitcoinjBlock);
8283
break;
8384
}
8485
}
@@ -90,31 +91,33 @@ public Block getBlockByMinConfirmations(Integer minConfirmations) {
9091
* Helper methods
9192
*/
9293

93-
private static Block blockFromBitcoinjBlock(wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient.Block bitcoinjBlock) {
94+
private static Block blockFromBitcoinBlock(wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient.Block bitcoinjBlock) {
9495
return new Block(bitcoinjBlock.height(), bitcoinjBlock.hash(), bitcoinjBlock.time().getTime(), bitcoinjBlock.confirmations());
9596
}
9697

97-
private static Tx txFromBitcoinjRawTransaction(BitcoinJSONRPCClient bitcoinJSONRPCClient, String txId) {
98+
private static Tx txFromBitcoinRawTransaction(BitcoinJSONRPCClient bitcoinJSONRPCClient, String txId) {
9899
if (Tx.COINBASE_TX_IDENTIFIER.equals(txId) || Tx.GENESIS_TX_IDENTIFIER.equals(txId)) {
99100
return new Tx(txId, null, null);
100101
}
101-
wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient.RawTransaction bitcoinjRawTransaction = bitcoinJSONRPCClient.getRawTransaction(txId);
102-
List<TxIn> txIns = bitcoinjRawTransaction.vIn().stream().map(BitcoindRPCBitcoinConnection::txInFromBitcoinjIn).toList();
103-
List<TxOut> txOuts = bitcoinjRawTransaction.vOut().stream().map(BitcoindRPCBitcoinConnection::txOutFromBitcoinjOut).toList();
102+
wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient.RawTransaction bitcoinRawTransaction = bitcoinJSONRPCClient.getRawTransaction(txId);
103+
List<TxIn> txIns = bitcoinRawTransaction.vIn().stream().map(BitcoindRPCBitcoinConnection::txInFromBitcoinIn).toList();
104+
List<TxOut> txOuts = bitcoinRawTransaction.vOut().stream().map(BitcoindRPCBitcoinConnection::txOutFromBitcoinOut).toList();
104105
return new Tx(txId, txIns, txOuts);
105106
}
106107

107-
private static TxIn txInFromBitcoinjIn(wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient.RawTransaction.In in) {
108+
private static TxIn txInFromBitcoinIn(wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient.RawTransaction.In in) {
108109
var txId = in.txid();
109110
Integer vout = txId == null ? null : in.getTransactionOutput().n();
110111
return new TxIn(txId, vout);
111112
}
112113

113-
private static TxOut txOutFromBitcoinjOut(wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient.RawTransaction.Out out) {
114-
String txId = out.transaction().txId();
114+
private static TxOut txOutFromBitcoinOut(wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient.RawTransaction.Out out) {
115+
String scriptPubKey = out.scriptPubKey().hex();
116+
String scriptPubKeyAsm = out.scriptPubKey().asm();
117+
String scriptPubKeyType = out.scriptPubKey().type();
115118
String scriptPubKeyAddress = out.scriptPubKey().mapStr("address");
116-
String asm = out.scriptPubKey().asm();
117-
return new TxOut(txId, scriptPubKeyAddress, asm);
119+
Long value = out.value().longValue();
120+
return new TxOut(scriptPubKey, scriptPubKeyAsm, scriptPubKeyType, scriptPubKeyAddress, value);
118121
}
119122

120123
/*

src/main/java/com/danubetech/btc/connection/impl/EsploraElectrsRESTBitcoinConnection.java

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.net.HttpURLConnection;
1919
import java.net.URI;
2020
import java.nio.charset.StandardCharsets;
21+
import java.util.ArrayList;
2122
import java.util.List;
2223
import java.util.Map;
2324

@@ -54,26 +55,42 @@ public Block getBlockByBlockHeight(Integer blockHeight) {
5455
URI apiEndpoint1 = URI.create(this.apiEndpointBase + "block-height/" + blockHeight);
5556
Map<String, Object> response1 = readObject(apiEndpoint1);
5657
URI apiEndpoint2 = URI.create(this.apiEndpointBase + "block/" + response1.get("height") + "/txs");
57-
List<Object> response2 = readArray(apiEndpoint2);
58+
List<Map<String, Object>> response2 = readArray(apiEndpoint2);
5859
Integer responseBlockHeight = ((Number) response1.get("height")).intValue();
5960
String responseHash = (String) response1.get("id");
6061
throw new RuntimeException("Not implemented");
6162
}
6263

64+
@Override
65+
public Tx getTransactionById(String txid) {
66+
URI apiEndpoint = URI.create(this.apiEndpointBase + "tx/" + txid);
67+
Map<String, Object> response = readObject(apiEndpoint);
68+
Tx tx = EsploraElectrsRESTBitcoinConnection.txFromMap(response);
69+
if (log.isDebugEnabled()) log.debug("getTransactionById for {}: {}", txid, tx);
70+
return tx;
71+
}
72+
6373
@Override
6474
public List<Tx> getAddressTransactions(String address) {
6575
URI apiEndpoint = URI.create(this.apiEndpointBase + "address/" + address + "/txs");
66-
List<Object> response = readArray(apiEndpoint);
67-
List<Tx> txs = response.stream().map(Map.class::cast).map(EsploraElectrsRESTBitcoinConnection::txFromMap).toList();
76+
List<Map<String, Object>> response = readArray(apiEndpoint);
77+
List<Tx> txs = response.stream().map(EsploraElectrsRESTBitcoinConnection::txFromMap).toList();
6878
if (log.isDebugEnabled()) log.debug("getAddressTransactions for {}: {}", address, txs);
6979
return txs;
7080
}
7181

7282
@Override
7383
public List<TxOut> getAddressUtxos(String address) {
7484
URI apiEndpoint = URI.create(this.apiEndpointBase + "address/" + address + "/utxo");
75-
List<Object> response = readArray(apiEndpoint);
76-
List<TxOut> txOuts = response.stream().map(Map.class::cast).map(EsploraElectrsRESTBitcoinConnection::txOutFromMap).toList();
85+
List<Map<String, Object>> response = readArray(apiEndpoint);
86+
List<TxOut> txOuts = new ArrayList<>();
87+
for (Map<String, Object> responseEntry : response) {
88+
String txId = (String) responseEntry.get("txid");
89+
int vout = ((Number) responseEntry.get("vout")).intValue();
90+
Tx tx = this.getTransactionById(txId);
91+
TxOut txOut = tx.txOuts().get(vout);
92+
txOuts.add(txOut);
93+
}
7794
if (log.isDebugEnabled()) log.debug("getAddressUtxos for {}: {}", address, txOuts);
7895
return txOuts;
7996
}
@@ -117,10 +134,12 @@ private static TxIn txInFromMap(Map<String, Object> map) {
117134
}
118135

119136
private static TxOut txOutFromMap(Map<String, Object> map) {
120-
String txId = (String) map.get("txid");
137+
String scriptPubKey = (String) map.get("scriptpubkey");
138+
String scriptPubKeyAsm = (String) map.get("scriptpubkey_asm");
139+
String scriptPubKeyType = (String) map.get("scriptpubkey_type");
121140
String scriptPubKeyAddress = (String) map.get("scriptpubkey_address");
122-
String asm = (String) map.get("scriptpubkey_asm");
123-
return new TxOut(txId, scriptPubKeyAddress, asm);
141+
Long value = ((Number) map.get("value")).longValue();
142+
return new TxOut(scriptPubKey, scriptPubKeyAsm, scriptPubKeyType, scriptPubKeyAddress, value);
124143
}
125144

126145
private static String readString(URI uri) {
@@ -154,9 +173,9 @@ private static Map<String, Object> readObject(URI uri) {
154173
}
155174
}
156175

157-
private static List<Object> readArray(URI uri) {
176+
private static List<Map<String, Object>> readArray(URI uri) {
158177
try {
159-
return (List<Object>) jsonMapper.readValue(readString(uri), List.class);
178+
return (List<Map<String, Object>>) jsonMapper.readValue(readString(uri), List.class);
160179
} catch (JsonProcessingException ex) {
161180
throw new RuntimeException("Cannot parse array response from " + uri + "; " + ex.getMessage(), ex);
162181
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.danubetech.btc.connection.records;
22

33
public record TxOut(
4-
String txId,
4+
String scriptPubKey,
5+
String scriptPubKeyAsm,
6+
String scriptPubKeyType,
57
String scriptPubKeyAddress,
6-
String asm) {
8+
Long value) {
79
}

0 commit comments

Comments
 (0)