У меня проблемы со связью между Java и bitcoind — каждая библиотека JSON RPC, которую я пробую, имеет некоторые проблемы. Может ли кто-нибудь предоставить рабочую реализацию даже самой простой связи JSON RPC между Java и bitcoind?
Вот ранний экспериментальный клиент, с которым я некоторое время назад поигрался . Он поддерживает getInfo, getBalance и getNewAddress и может быть легко расширен. Чтобы запустить его, учетные данные для вашего локального биткойна должны совпадать со значениями в клиентском классе:
httpclient.getCredentialsProvider().setCredentials(new AuthScope("localhost", 8332),
new UsernamePasswordCredentials("btc", "123"));
Не стесняйтесь использовать этот код как угодно, но помните, что это всего лишь 5 минут работы на старте, а не реальная клиентская реализация. Надеюсь, это поможет вам генерировать некоторые идеи!
Вы также можете попробовать https://github.com/clanie/bitcoind-client — он находится на ранней стадии разработки, но уже поддерживает почти все методы, предоставляемые bitcoind.
У меня была такая же проблема, и я создал реализацию здесь: https://github.com/johannbarbie/BitcoindClient4J .
Поскольку это похоже на набор ссылок, я просто добавлю еще одну:
Библиотека под лицензией Apache: https://github.com/SulacoSoft/BitcoindConnector4J
https://github.com/nitinsurana/Litecoin-Bitcoin-RPC-Java-Connector
Он использует Htmunit вместо Apache Http Library, что упрощает его понимание и расширение.
На самом деле я написал и протестировал его для Litecoin для одного из моих проектов. Но он был расширен для поддержки биткойнов, и доступны все методы RPC.
Так как я нигде не смог найти рабочий фрагмент кода, вот полный рабочий пример (на Scala):
Сначала я создал вспомогательный объект:
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
}
}
Затем я использовал его следующим образом:
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"}"""
)
Одной из проблем Java является многословность языка. Однако верно также и то, что жизнь языка в этом очень старая.
Я столкнулся с проблемой общения с интерфейсом rpc биткойна для одного из моих побочных проектов на c-lightning, и я не смог найти чистую библиотеку, которая могла бы также взаимодействовать с другими интерфейсами rpc, полученными из ядра биткойна, такими как litecoin. Кроме того, я также нашел библиотеку, которая проста, как библиотека Python.
Мой результат разработки библиотеки, соответствующей этому требованию, называется lite-bitcoin-rpc и доступен на GitHub https://github.com/clightning4j/lite-bitcoin-rpc .
Это простая библиотека, поскольку with дает возможность написать оболочку JSON в классе Java и использовать ее для декодирования ответа. Конечному пользователю нужно только нащупать карту с параметрами и создать класс Java, в котором декодируется полезная нагрузка JSON, полученная от ядра биткойна.
Пример можно найти в тестовом каталоге https://github.com/clightning4j/lite-bitcoin-rpc/tree/main/lib/src/test .
а пример кода можно
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());
}
}
Если вам не нравится Scala, вот код Jus12 на 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
}
Лурф Юрв