Ich habe Probleme bei der Kommunikation zwischen Java und Bitcoin - jede JSON-RPC-Bibliothek, die ich versuche, hat einige Probleme. Kann jemand eine funktionierende Implementierung selbst der grundlegendsten JSON-RPC-Kommunikation zwischen Java und Bitcoin bereitstellen?
Hier ist ein früher experimenteller Client, mit dem ich vor einiger Zeit herumgespielt hatte . Es unterstützt getInfo, getBalance und getNewAddress und kann einfach erweitert werden. Um es auszuführen, müssen die Anmeldeinformationen für Ihre lokale Bitcoin mit den Werten in der Client-Klasse übereinstimmen:
httpclient.getCredentialsProvider().setCredentials(new AuthScope("localhost", 8332),
new UsernamePasswordCredentials("btc", "123"));
Fühlen Sie sich frei, diesen Code in irgendeiner Weise zu verwenden, aber verstehen Sie, dass es am Anfang nur 5 Minuten Arbeit sind, keine realistische Client-Implementierung. Hoffe, es hilft Ihnen, einige Ideen zu generieren!
Gerne können Sie auch https://github.com/clanie/bitcoind-client ausprobieren – es befindet sich in einer frühen Entwicklungsphase, unterstützt aber bereits fast alle von Bitcoin bereitgestellten Methoden.
Ich hatte das gleiche Problem und habe hier eine Implementierung erstellt: https://github.com/johannbarbie/BitcoindClient4J
Da dies wie eine Sammlung von Links aussieht, füge ich einfach einen weiteren hinzu:
Bibliothek unter Apache-Lizenz: https://github.com/SulacoSoft/BitcoindConnector4J
https://github.com/nitinsurana/Litecoin-Bitcoin-RPC-Java-Connector
Es verwendet Htmlunit anstelle der Apache Http Library, wodurch es etwas einfacher zu verstehen und zu erweitern ist.
Ich habe es tatsächlich für Litecoin für eines meiner Projekte geschrieben und getestet. Aber es wurde erweitert, um Bitcoin zu unterstützen, und alle RPC-Methoden sind verfügbar.
Da ich nirgendwo ein funktionierendes Code-Snippet finden konnte, ist hier ein vollständiges funktionierendes Beispiel (in Scala):
Zuerst habe ich ein Hilfsobjekt erstellt:
import java.net.URL
import java.net.HttpURLConnection
import org.apache.commons.io.IOUtils
object CurlJsonData {
def curl(url:String, jsonEncodedString:String) = {
val httpcon = new URL(url).openConnection.asInstanceOf[HttpURLConnection]
httpcon.setDoOutput(true);
httpcon.setRequestProperty("Content-Type", "application/json");
httpcon.setRequestProperty("Accept", "application/json");
httpcon.setRequestMethod("POST");
httpcon.connect;
val outputBytes = jsonEncodedString.getBytes("UTF-8");
// 'using' method from: https://stackoverflow.com/a/5218279/243233
using(httpcon.getOutputStream){os =>
os.write(outputBytes)
}
val code = httpcon.getResponseCode
val isError = code >= 400 && code <= 500
val resp = using{
if (isError) httpcon.getErrorStream else httpcon.getInputStream
}{is =>
val writer = new StringWriter;
IOUtils.copy(is, writer, "UTF-8");
writer.toString;
}
httpcon.disconnect
if (isError) throw new Exception(
s"Resp code $code. Error: ${resp.take(200)}"
) else resp
}
}
Dann habe ich es wie folgt verwendet:
import java.net.Authenticator
import java.net.PasswordAuthentication
val rpcuser = "alice";
val rpcpassword = "secret";
Authenticator.setDefault(
new Authenticator {
override def getPasswordAuthentication:PasswordAuthentication = {
new PasswordAuthentication (rpcuser, rpcpassword.toCharArray)
}
}
)
CurlJsonData.curl(
"http://localhost:8332",
"""{"method":"getblockchaininfo","params":[],"id":1,"jsonrpc":"1.0"}"""
)
Eines der Probleme von Java ist die Ausführlichkeit der Sprache. Es ist jedoch auch wahr, dass das Leben der Sprache in diesen sehr alt ist.
Ich habe das Problem, mit der Bitcoin-RPC-Schnittstelle für eines meiner Nebenprojekte auf c-Lightning zu sprechen, und ich konnte keine saubere Bibliothek finden, die auch mit anderen vom Bitcoin-Kern abgeleiteten RPC-Schnittstellen wie Litecoin kommunizieren kann. Außerdem habe ich auch eine Bibliothek gefunden, die einfach wie eine Python-Bibliothek ist.
Mein Ergebnis der Entwicklung einer Bibliothek, die diese Anforderung erfüllt, heißt lite-bitcoin-rpc und ist auf GitHub https://github.com/clightning4j/lite-bitcoin-rpc verfügbar
Dies ist eine einfache Bibliothek, da sie die Möglichkeit bietet, den JSON-Wrapper in eine Java-Klasse zu schreiben und ihn zum Decodieren der Antwort zu verwenden. Der Endbenutzer muss nur eine Karte mit Parametern fühlen und die Java-Klasse erstellen, in der die vom Bitcoin-Kern empfangene JSON-Nutzlast decodiert wird.
Ein Beispiel findet sich im Testverzeichnis https://github.com/clightning4j/lite-bitcoin-rpc/tree/main/lib/src/test
und ein Codebeispiel sein kann
public class LiteBitcoinRPCTest {
private LiteBitcoinRPC bitcoinRPC;
public LiteBitcoinRPCTest() {
this.bitcoinRPC = new LiteBitcoinRPC("sandbox", "sandbox", "http://127.0.0.1:18333/");
}
@Test
public void getBlockchainInfo() {
try {
BlockchainInfo info =
bitcoinRPC.makeBitcoinRequest("getblockchaininfo", BlockchainInfo.class);
TestCase.assertEquals(info.getChain(), "regtest");
} catch (Exception e) {
e.printStackTrace();
TestCase.fail(e.getLocalizedMessage());
}
}
@Test
public void estimateFeeRateWithError() {
Parameters parameters = new Parameters("estimatesmartfee");
parameters.addParameter("conf_target", 6);
try {
BitcoinEstimateFee feee = bitcoinRPC.makeBitcoinRequest(parameters, BitcoinEstimateFee.class);
TestCase.assertFalse(feee.getErrors().isEmpty());
} catch (LiteBitcoinRPCException | BitcoinCoreException e) {
TestCase.fail(e.getMessage());
}
}
Wenn Scala nicht Ihr Ding ist, hier ist der Code von Jus12 in Kotlin:
package com.my.blockchainparser
import java.net.Authenticator
import java.net.PasswordAuthentication
import java.net.URL
import java.net.HttpURLConnection
fun main(args: Array<String>) {
val rpcuser = "user"
val rpcpassword = "password"
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication {
return PasswordAuthentication(rpcuser, rpcpassword.toCharArray())
}
})
System.out.println(curl(
"http://localhost:8332",
"""{"method":"getblockchaininfo","params":[],"id":1,"jsonrpc":"1.0"}"""
))
}
fun curl(url:String, jsonEncodedString:String): String {
val httpcon = URL(url).openConnection() as HttpURLConnection
httpcon.setDoOutput(true);
httpcon.setRequestProperty("Content-Type", "application/json");
httpcon.setRequestProperty("Accept", "application/json");
httpcon.setRequestMethod("POST");
httpcon.connect();
val outputBytes = jsonEncodedString.toByteArray();
httpcon.getOutputStream().use {
it.write(outputBytes)
}
val code = httpcon.getResponseCode()
val isError = code >= 400 && code <= 500
val text = (if (isError) httpcon.getErrorStream() else httpcon.getInputStream())
?.bufferedReader()?.use {
it.readText()
} ?: "no connection"
if (isError) throw Exception(
"Resp code $code. Error: ${text.take(200)}"
)
return text
}
jurv