diff --git a/.gitignore b/.gitignore index 50456fb..ff50a6d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ ## Intellij Idea ################# *.iml - +/.idea ################# ## Eclipse ################# diff --git a/README.md b/README.md index 8fcce5a..1e8c4af 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,32 @@ You can register observers to capture events of wallets, and alerts: walletListener.addObserver(new Observer() { @Override public void update(Observable o, Object arg) { - System.out.println("Amount of transaction: " + ((Transaction)arg).getAmount()); + Transaction tx = (Transaction) arg; + BigDecimal amount = tx.getDetails().get(0).getAmount(); //amount of transaction + String txId = tx.getTxid(); //id of transaction + Transaction txDetails = tx.getDetails().get(0); //transaction details + + if (tx.getDetails().size() == 2) { + //both side of translation inside your bitcoind node + String sendToAddress = txDetails.getAddress(); + String receiveAddress = tx.getDetails().get(1).getAddress(); + BigDecimal fee = tx.getFee(); + } else { + //one side of translation outside of your bitcoind node + switch (txDetails.getCategory()) { + case RECEIVE: //your account on bitcoind receive bitcoin + String receiveAddress = txDetails.getAddress(); + break; + case SEND: //your account on bitcoind send bitcoin + //the address to which the coins was sent + String sendToAddress = txDetails.getAddress(); + //account in your bitcoind from which the coins was sent + String sendFromAccountName = txDetails.getAccount(); + BigDecimal fee = txDetails.getFee(); + break; + default: + //Strange transaction: MOVE or CONFLICTED + } } }); @@ -68,4 +93,16 @@ Make sure to close sockets later: walletListener.stop(); ``` +### Logs and exception handling + +All log files are written via log4j DailyRollingFileAppender and saved in /var/log/bitcoin-rpc/ folder. + +Library can generate listed below types of Runtime exception: + +- AuthenticationException +- CallApiCryptoCurrencyRpcException +- CryptoCurrencyRpcException (base class) +- InsufficientFundsException +- RpcInvalidResponseException + > Written with [StackEdit](https://stackedit.io/). diff --git a/pom.xml b/pom.xml index 34ba417..58c9b2e 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.nitinsurana Litecoin-Bitcoin-RPC-Java-Connector - 2.0.0 + 2.2.16 jar Litecoin-Bitcoin-RPC-Java-Connector @@ -75,8 +75,8 @@ maven-compiler-plugin 2.0.2 - 1.6 - 1.6 + 1.8 + 1.8 @@ -148,17 +148,24 @@ gson 2.3.1 + + org.apache.httpcomponents + httpclient + 4.4.1 + + + commons-io + commons-io + 2.4 + + log4j log4j 1.2.17 - - net.sourceforge.htmlunit - htmlunit - 2.15 - compile - + + junit junit diff --git a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/APICalls.java b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/APICalls.java index eda4529..f87016d 100644 --- a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/APICalls.java +++ b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/APICalls.java @@ -23,11 +23,13 @@ public enum APICalls { SEND_RAW_TRANSACTION("sendrawtransaction"), SET_ACCOUNT("setaccount"), SEND_TO_ADDRESS("sendtoaddress"), + MOVE("move"), GET_ADDRESSES_BY_ACCOUNT("getaddressesbyaccount"), GET_RECEIVED_BY_ACCOUNT("getreceivedbyaccount"), GET_RECEIVED_BY_ADDRESS("getreceivedbyaddress"), GET_BALANCE("getbalance"), GET_TRANSACTION("gettransaction"), + GET_INFO("getinfo"), GET_CONNECTION_COUNT("getconnectioncount"), BACKUP_WALLET("backupwallet"), DECODE_RAW_TRANSACTION("decoderawtransaction"), @@ -37,7 +39,16 @@ public enum APICalls { CREATE_RAW_TRANSACTION("createrawtransaction"), SIGN_RAW_TRANSACTION("signrawtransaction"), VALIDATE_ADDRESS("validateaddress"), - ENCRYPT_WALLET("encryptwallet"); + ENCRYPT_WALLET("encryptwallet"), + WALLET_PASSPHRASE("walletpassphrase"), + + //OMNI + OMNI_SEND("omni_send"), + OMNI_GETINFO("omni_getinfo"), + OMNI_GETBALANCE("omni_getbalance"), + OMNI_GETALLBALANCESFORID("omni_getallbalancesforid"), + OMNI_GETTRANSACTION("omni_gettransaction"), + OMNI_LISTTRANSACTIONS("omni_listtransactions"); private String value; diff --git a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/CryptoCurrencyRPC.java b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/CryptoCurrencyRPC.java index 1624e09..97569f6 100644 --- a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/CryptoCurrencyRPC.java +++ b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/CryptoCurrencyRPC.java @@ -1,57 +1,105 @@ package com.nitinsurana.bitcoinlitecoin.rpcconnector; -import com.gargoylesoftware.htmlunit.*; +import java.net.*; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.AuthenticationException; +import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CallApiCryptoCurrencyRpcException; import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException; import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcExceptionHandler; -import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CallApiCryptoCurrencyRpcException; import com.nitinsurana.bitcoinlitecoin.rpcconnector.pojo.Transaction; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpHost; +import org.apache.http.HttpStatus; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.AuthCache; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; import org.apache.log4j.Logger; import java.math.BigDecimal; -import java.net.URL; import java.util.Arrays; import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; public class CryptoCurrencyRPC { public static final Logger LOG = Logger.getLogger("rpcLogger"); - private WebClient client; - private String baseUrl; - private CryptoCurrencyRpcExceptionHandler cryptoCurrencyRpcExceptionHandler = new CryptoCurrencyRpcExceptionHandler(); - private Gson gson = new Gson(); + protected CryptoCurrencyRpcExceptionHandler cryptoCurrencyRpcExceptionHandler = new CryptoCurrencyRpcExceptionHandler(); + protected Gson gson = new Gson(); + protected JsonParser jsonParser = new JsonParser(); + + private static final String CHARACTER_ENCODING = "UTF-8"; + private String uri; + private CloseableHttpClient httpClient; + private HttpHost targetHost; + private HttpClientContext context; + private AtomicLong id = new AtomicLong(1L); + protected String cryptoCurrency; - public CryptoCurrencyRPC(String rpcUser, String rpcPassword, String rpcHost, String rpcPort) throws AuthenticationException { - client = new WebClient(BrowserVersion.CHROME); - client.getOptions().setThrowExceptionOnFailingStatusCode(false); - client.getOptions().setThrowExceptionOnScriptError(false); - client.getOptions().setPrintContentOnFailingStatusCode(false); - client.getOptions().setJavaScriptEnabled(false); - client.getOptions().setCssEnabled(false); - baseUrl = new String("http://" + rpcUser + ":" + rpcPassword + "@" + rpcHost + ":" + rpcPort + "/"); + private String passphrase; + private int timeToUnlockWalle; + public CryptoCurrencyRPC(final String rpcUser, final String rpcPassword, String rpcHost, String rpcPort, + String passphrase, int timeToUnlockWalle, String cryptoCurrency) { + String host; try { - if (client.getPage(baseUrl).getWebResponse().getStatusCode() == 401) { //401 is Http Unauthorized - throw new AuthenticationException(); - } - } catch (Exception ex) { - LOG.error(ex.getMessage(), ex); + URL url = new URL(rpcHost); + this.uri = url.getPath(); + host=url.getHost(); + } catch (MalformedURLException ex) { + this.uri = "/"; + host=rpcHost; } + + httpClient = HttpClients.createDefault(); + targetHost = new HttpHost(host, Integer.parseInt(rpcPort), "http"); + context = HttpClientContext.create(); + if (rpcUser != null && rpcPassword != null) { + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), + new UsernamePasswordCredentials(rpcUser, rpcPassword)); + + AuthCache authCache = new BasicAuthCache(); + BasicScheme basicAuth = new BasicScheme(); + authCache.put(targetHost, basicAuth); + context.setCredentialsProvider(credsProvider); + context.setAuthCache(authCache); + } + + this.passphrase = passphrase; + this.timeToUnlockWalle=timeToUnlockWalle; + this.cryptoCurrency = cryptoCurrency; } - /** - * Safely copies wallet.dat to destination, which can be a directory or a - * path with filename. - * - * @param destination - * @return - * @throws Exception - */ + public CryptoCurrencyRPC(final String rpcUser, final String rpcPassword, String rpcHost, String rpcPort) { + this(rpcUser, rpcPassword, rpcHost, rpcPort, null, 0, "BTC"); + } + + public CryptoCurrencyRPC(final String rpcUser, final String rpcPassword, String rpcHost, String rpcPort, String cryptoCurrency) { + this(rpcUser, rpcPassword, rpcHost, rpcPort, null, 0, cryptoCurrency); + } + + /** + * Safely copies wallet.dat to destination, which can be a directory or a + * path with filename. + * + * @param destination + * @return + * @throws Exception + */ public boolean backupWallet(String destination) throws CryptoCurrencyRpcException { JsonObject jsonObj = callAPIMethod(APICalls.BACKUP_WALLET, destination); if (jsonObj.get("error") == null) { @@ -81,11 +129,18 @@ public JsonObject decodeRawTransaction(String hex) throws CryptoCurrencyRpcExcep * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException */ public String dumpPrivateKey(String address) throws CryptoCurrencyRpcException { + unlockWallets(); JsonObject jsonObj = callAPIMethod(APICalls.DUMP_PRIVATE_KEY, address); cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); return jsonObj.get("result").getAsString(); } + public String encryptWallet(String passphrase) throws CryptoCurrencyRpcException { + JsonObject jsonObj = callAPIMethod(APICalls.ENCRYPT_WALLET, passphrase); + cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); + return jsonObj.get("result").getAsString(); + } + /** * Returns raw transaction representation for given transaction id. * @@ -190,6 +245,19 @@ public String getNewAddress() throws CryptoCurrencyRpcException { return jsonObj.get("result").getAsString(); } + + /** + * Returns an object containing various state info. + * + * @return + * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException + */ + public String getInfo() throws CryptoCurrencyRpcException { + JsonObject jsonObj = callAPIMethod(APICalls.GET_INFO); + cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); + return jsonObj.toString(); + } + /** * Returns a new address for receiving payments. * @@ -228,9 +296,11 @@ public BigDecimal getReceivedByAddress(String address) throws CryptoCurrencyRpcE public Transaction getTransaction(String txid) throws CryptoCurrencyRpcException { JsonObject jsonObj = callAPIMethod(APICalls.GET_TRANSACTION, txid); cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); - return gson.fromJson(jsonObj.get("result").getAsJsonObject(), Transaction.class); + return gson.fromJson(jsonObj.get("result").getAsJsonObject(), Transaction.class) + .andSetCryptoCurrency(cryptoCurrency); } + /** * Returns Object that has account names as keys, account balances as * values. @@ -281,11 +351,27 @@ public JsonArray listReceivedByAddress() throws CryptoCurrencyRpcException { * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException */ public String sendFrom(String fromAccount, String toAddress, BigDecimal amount) throws CryptoCurrencyRpcException { + unlockWallets(); JsonObject response = callAPIMethod(APICalls.SEND_FROM, fromAccount, toAddress, amount); cryptoCurrencyRpcExceptionHandler.checkException(response); return response.get("result").getAsString(); } + /** + * Move from one account in your wallet to another + * + * @param fromAccount + * @param toAccount + * @param amount + * @return + * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException + */ + public boolean move(String fromAccount, String toAccount, BigDecimal amount, String comment) throws CryptoCurrencyRpcException { + JsonObject response = callAPIMethod(APICalls.MOVE, fromAccount, toAccount, amount, 1, comment); + cryptoCurrencyRpcExceptionHandler.checkException(response); + return response.get("result").getAsBoolean(); + } + /** * < amount > is a real and is rounded to the nearest 0.00000001 * @@ -295,6 +381,7 @@ public String sendFrom(String fromAccount, String toAddress, BigDecimal amount) * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException */ public String sendToAddress(String toAddress, BigDecimal amount) throws CryptoCurrencyRpcException { + unlockWallets(); JsonObject jsonObj = callAPIMethod(APICalls.SEND_TO_ADDRESS, toAddress, amount); cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); return jsonObj.get("result").getAsString(); @@ -306,6 +393,29 @@ public boolean validateAddress(String address) throws CryptoCurrencyRpcException return jsonObj.get("result").getAsJsonObject().get("isvalid").getAsBoolean(); } + public JsonObject checkAndValidateAddress(String address) throws CryptoCurrencyRpcException { + JsonObject jsonObj = callAPIMethod(APICalls.VALIDATE_ADDRESS, address); + cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); + return jsonObj.get("result").getAsJsonObject(); + } + + /** + * Unlock wallet + * @param passphrase + * @param timeout in seconds + * @return + * @throws CryptoCurrencyRpcException + */ + public boolean wallePassphrase(String passphrase, int timeout) throws CryptoCurrencyRpcException { + try { + JsonObject jsonObj = callAPIMethod(APICalls.WALLET_PASSPHRASE, passphrase, timeout); + cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); + return true; + } catch (Exception ex) { + return false; + } + } + /** * Sets the account associated with the given address. Assigning address * that is already assigned to the same account will create a new address @@ -324,6 +434,7 @@ public void setAccount(String address, String account) throws CryptoCurrencyRpcE /** * Returns up to [count] most recent transactions skipping the first [from] * transactions for account [account]. + * Sorting does not work correctly. https://github.com/bitcoin/bitcoin/issues/2853 * * @param account * @param count @@ -334,8 +445,8 @@ public void setAccount(String address, String account) throws CryptoCurrencyRpcE public List listTransactions(String account, int count, int from) throws CryptoCurrencyRpcException { JsonObject jsonObj = callAPIMethod(APICalls.LIST_TRANSACTIONS, account, count, from); cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); - - return Arrays.asList(gson.fromJson(jsonObj.get("result").getAsJsonArray(), Transaction[].class)); + return Arrays.stream(gson.fromJson(jsonObj.get("result").getAsJsonArray(), Transaction[].class)) + .map(tx -> tx.andSetCryptoCurrency(cryptoCurrency)).collect(Collectors.toList()); } /** @@ -419,7 +530,8 @@ public Transaction createRawTransaction(JsonObject[] prevOut, JsonObject out) th JsonObject jsonObj = callAPIMethod(APICalls.CREATE_RAW_TRANSACTION, prevOut, out); cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); - return gson.fromJson(jsonObj.get("result").getAsJsonObject(), Transaction.class); + return gson.fromJson(jsonObj.get("result").getAsJsonObject(), Transaction.class) + .andSetCryptoCurrency(cryptoCurrency); } /** @@ -431,10 +543,12 @@ public Transaction createRawTransaction(JsonObject[] prevOut, JsonObject out) th * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException */ public Transaction signRawTransaction(String hexString) throws CryptoCurrencyRpcException { + unlockWallets(); JsonObject jsonObj = callAPIMethod(APICalls.SIGN_RAW_TRANSACTION,hexString); cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); - return gson.fromJson(jsonObj.get("result").getAsJsonObject(), Transaction.class); + return gson.fromJson(jsonObj.get("result").getAsJsonObject(), Transaction.class) + .andSetCryptoCurrency(cryptoCurrency); } /** @@ -446,37 +560,81 @@ public Transaction signRawTransaction(String hexString) throws CryptoCurrencyRpc * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException */ public String sendRawTransaction(String hexString) throws CryptoCurrencyRpcException { + unlockWallets(); JsonObject jsonObj = callAPIMethod(APICalls.SEND_RAW_TRANSACTION,hexString); cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); return jsonObj.get("result").getAsString(); } - private JsonObject callAPIMethod(APICalls callMethod, Object... params) throws CallApiCryptoCurrencyRpcException { + + //Implementation from https://github.com/SulacoSoft/BitcoindConnector4J repository + protected JsonObject callAPIMethod(APICalls callMethod, Object... params) throws CallApiCryptoCurrencyRpcException { try { - JsonObject jsonObj = null; - WebRequest req = new WebRequest(new URL(baseUrl)); - req.setAdditionalHeader("Content-type", "application/json"); - req.setHttpMethod(HttpMethod.POST); - JSONRequestBody body = new JSONRequestBody(); - body.setMethod(callMethod.toString()); - if (params != null && params.length > 0) { - body.setParams(params); + String jsonRequest = String.format("{\"jsonrpc\": \"2.0\", \"method\": \"%s\", \"params\": [%s], \"id\": %s}", + callMethod.toString(), buildParamsString(params), id.getAndIncrement()); + + HttpPost httpPost = new HttpPost(uri); + httpPost.setEntity(new ByteArrayEntity(jsonRequest.getBytes(CHARACTER_ENCODING))); + CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context); + try { + checkHttpErrors(response.getStatusLine().getStatusCode()); + + String jsonResponse = IOUtils.toString(response.getEntity().getContent(), CHARACTER_ENCODING); + logRequest(callMethod.toString(), jsonResponse, params); + + return jsonParser.parse(jsonResponse).getAsJsonObject(); + } finally { + response.close(); + } + } catch (Throwable e) { + throw new CallApiCryptoCurrencyRpcException(e.getMessage()); + } + + } + + protected void unlockWallets() { + if (passphrase != null) { + wallePassphrase(passphrase, timeToUnlockWalle); + } + } + + private String buildParamsString(Object[] args) { + StringBuilder params = new StringBuilder(); + if (args != null && args.length > 0) { + for (int i = 0; i < args.length; i++) { + if (i > 0) + params.append(","); + Object arg = args[i]; + if (arg instanceof String) + params.append(String.format("\"%s\"", arg)); + else + params.append(String.format("%s", arg)); } - req.setRequestBody(new Gson().toJson(body, JSONRequestBody.class)); - WebResponse resp = client.getPage(req).getWebResponse(); - jsonObj = new JsonParser().parse(resp.getContentAsString()).getAsJsonObject(); + } + return params.toString(); + } + private void checkHttpErrors(int statusCode) { + if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_INTERNAL_SERVER_ERROR) { + if (statusCode == HttpStatus.SC_UNAUTHORIZED) + throw new CryptoCurrencyRpcException(String.format( + "Bitcoind JSON-RPC HTTP error (Probably an incorrect username or password). HTTP Status-Code %s", + statusCode)); + else + throw new CryptoCurrencyRpcException(String.format("Bitcoind JSON-RPC HTTP error. HTTP Status-Code %s", + statusCode)); + } + } + + private void logRequest(String callMethod, String jsonResponse, Object[] params) { + if (!callMethod.equals(APICalls.LIST_TRANSACTIONS.toString())) { StringBuffer buffer = new StringBuffer(""); for (Object item : params) { - buffer.append(item.toString() + " | "); + buffer.append(item).append(" | "); } LOG.info("Bitcoin RPC Request: Method: " + callMethod + " Params: " + buffer.toString() + - "\nBitcoin RPC Response : " + jsonObj); - - return jsonObj; - } catch (Exception e) { - throw new CallApiCryptoCurrencyRpcException(e.getMessage()); + "\nBitcoin RPC Response : " + jsonResponse); } } } diff --git a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/MockCryptoCurrencyRpc.java b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/MockCryptoCurrencyRpc.java new file mode 100644 index 0000000..9a3940b --- /dev/null +++ b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/MockCryptoCurrencyRpc.java @@ -0,0 +1,146 @@ +package com.nitinsurana.bitcoinlitecoin.rpcconnector; + +import com.google.gson.JsonArray; +import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException; +import com.nitinsurana.bitcoinlitecoin.rpcconnector.pojo.Transaction; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Random; + +/** + * Created by d.romantsov on 20.03.2017. + */ +public class MockCryptoCurrencyRpc extends CryptoCurrencyRPC { + private Random random = new Random(); + + public MockCryptoCurrencyRpc() { + super(null, null, "localhost", "1245", null, 0, "MOCK"); + } + + private Transaction getMockTransaction() { + Transaction tx = new Transaction(); + tx.setAccount("mockAccount"); + tx.setAddress("n1v1XpeNaC124r9DXcBAka2XgJpcMpUBMB"); + tx.setCategory(random.nextBoolean() ? Transaction.Category.RECEIVE: Transaction.Category.SEND); + tx.setAmount(new BigDecimal(random.nextDouble())); + tx.setFee(new BigDecimal(random.nextDouble()/10)); + tx.setTimereceived(new Date().getTime() - random.nextInt(10000)); + return tx; + } + + @Override + public List listTransactions(String account, int count, int from) throws CryptoCurrencyRpcException { + ArrayList txs= new ArrayList(); + txs.add(getMockTransaction()); + txs.add(getMockTransaction()); + txs.add(getMockTransaction()); + txs.add(getMockTransaction()); + txs.add(getMockTransaction()); + txs.add(getMockTransaction()); + return txs; + } + + @Override + public boolean backupWallet(String destination) throws CryptoCurrencyRpcException { + return true; + } + + @Override + public String dumpPrivateKey(String address) throws CryptoCurrencyRpcException { + return address; + } + + @Override + public String encryptWallet(String passphrase) throws CryptoCurrencyRpcException { + return passphrase; + } + + @Override + public String getAccount(String address) throws CryptoCurrencyRpcException { + return "mockAccount"; + } + + @Override + public String getAccountAddress(String account) throws CryptoCurrencyRpcException { + return "n1v1XpeNaC124r9DXcBAka2XgJpcMpUBMB"; + } + + @Override + public JsonArray getAddressesByAccount(String account) throws CryptoCurrencyRpcException { + return new JsonArray(); + } + + @Override + public BigDecimal getBalance(String account) throws CryptoCurrencyRpcException { + return BigDecimal.TEN; + } + + @Override + public BigDecimal getBalance() throws CryptoCurrencyRpcException { + return BigDecimal.TEN; + } + + @Override + public BigDecimal getReceivedByAccount(String account) throws CryptoCurrencyRpcException { + return BigDecimal.TEN; + } + + @Override + public String getNewAddress() throws CryptoCurrencyRpcException { + return "n1v1XpeNaC124r9DXcBAka2XgJpcMpUBMB"; + } + + @Override + public String getInfo() throws CryptoCurrencyRpcException { + return "MockInfo"; + } + + @Override + public String getNewAddress(String account) throws CryptoCurrencyRpcException { + return "n1v1XpeNaC124r9DXcBAka2XgJpcMpUBMB"; + } + + @Override + public BigDecimal getReceivedByAddress(String address) throws CryptoCurrencyRpcException { + return BigDecimal.TEN; + } + + @Override + public Transaction getTransaction(String txid) throws CryptoCurrencyRpcException { + return getMockTransaction(); + } + + @Override + public String sendFrom(String fromAccount, String toAddress, BigDecimal amount) throws CryptoCurrencyRpcException { + return "asdasdasdasdasd"; + } + + @Override + public boolean move(String fromAccount, String toAccount, BigDecimal amount, String comment) throws CryptoCurrencyRpcException { + return true; + } + + @Override + public String sendToAddress(String toAddress, BigDecimal amount) throws CryptoCurrencyRpcException { + return "asdasdasdasdasd"; + } + + @Override + public boolean validateAddress(String address) throws CryptoCurrencyRpcException { + return true; + } + + + @Override + public boolean wallePassphrase(String passphrase, int timeout) throws CryptoCurrencyRpcException { + return true; + } + + @Override + public void setAccount(String address, String account) throws CryptoCurrencyRpcException { + + } +} diff --git a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/OmniCryptoCurrencyRPC.java b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/OmniCryptoCurrencyRPC.java new file mode 100644 index 0000000..3f062ff --- /dev/null +++ b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/OmniCryptoCurrencyRPC.java @@ -0,0 +1,82 @@ +package com.nitinsurana.bitcoinlitecoin.rpcconnector; + +import com.google.gson.JsonObject; +import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException; +import com.nitinsurana.bitcoinlitecoin.rpcconnector.pojo.OmniTransaction; +import com.nitinsurana.bitcoinlitecoin.rpcconnector.pojo.Transaction; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Created by d.romantsov on 25.05.2016. + */ +public class OmniCryptoCurrencyRPC extends CryptoCurrencyRPC { + private Long tokenId; + + public OmniCryptoCurrencyRPC(String rpcUser, String rpcPassword, String rpcHost, String rpcPort, long tokenId) { + super(rpcUser, rpcPassword, rpcHost, rpcPort); + this.tokenId = tokenId; + } + + @Override + public String sendFrom(String fromAccount, String toAddress, BigDecimal amount) throws CryptoCurrencyRpcException { + JsonObject response = callAPIMethod(APICalls.OMNI_SEND, fromAccount, toAddress, tokenId, amount.toPlainString()); + cryptoCurrencyRpcExceptionHandler.checkException(response); + return response.get("result").getAsString(); + } + + @Override + public String getInfo() throws CryptoCurrencyRpcException { + JsonObject jsonObj = callAPIMethod(APICalls.OMNI_GETINFO); + cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); + return jsonObj.toString(); + } + + @Override + public BigDecimal getBalance(String account) throws CryptoCurrencyRpcException { + JsonObject jsonObj = callAPIMethod(APICalls.OMNI_GETBALANCE, account, tokenId); + cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); + return jsonObj.getAsJsonObject("result").get("balance").getAsBigDecimal(); + } + + @Override + public BigDecimal getBalance() throws CryptoCurrencyRpcException { + JsonObject jsonObj = callAPIMethod(APICalls.OMNI_GETALLBALANCESFORID, tokenId); + cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); + return jsonObj.get("result").getAsJsonObject().get("balance").getAsBigDecimal(); + } + + @Override + public OmniTransaction getTransaction(String txid) throws CryptoCurrencyRpcException { + JsonObject jsonObj = callAPIMethod(APICalls.OMNI_GETTRANSACTION, txid); + cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); + OmniTransaction tx = gson.fromJson(jsonObj.get("result").getAsJsonObject(), OmniTransaction.class); + tx.setCryptoCurrency(cryptoCurrency); + return tx; + } + + @Override + public List listTransactions(String account, int count, int from) throws CryptoCurrencyRpcException { + JsonObject jsonObj = callAPIMethod(APICalls.OMNI_LISTTRANSACTIONS, account, count, from); + cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); + return Arrays.stream(gson.fromJson(jsonObj.get("result").getAsJsonArray(), OmniTransaction[].class)).map(tx -> tx.andSetCryptoCurrency(cryptoCurrency)).collect(Collectors.toList()); + } + + @Override + public String sendRawTransaction(String hexString) throws CryptoCurrencyRpcException { + throw new UnsupportedOperationException(); + } + + @Override + public String sendToAddress(String toAddress, BigDecimal amount) throws CryptoCurrencyRpcException { + throw new UnsupportedOperationException(); + } + + @Override + public Transaction signRawTransaction(String hexString) throws CryptoCurrencyRpcException { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/AlertListener.java b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/AlertListener.java index 749bfb4..ec52cda 100644 --- a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/AlertListener.java +++ b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/AlertListener.java @@ -15,15 +15,13 @@ public class AlertListener extends Observable implements Observer { public AlertListener(int port) throws IOException { alertListener = new BitcoinDListener(port); + alertListener.addObserver(this); + listener = new Thread((Runnable) alertListener, "alertListener"); + listener.start(); } @Override public synchronized void addObserver(Observer o) { - if (null == listener) { - alertListener.addObserver(this); - listener = new Thread((Runnable) alertListener, "alertListener"); - listener.start(); - } super.addObserver(o); } diff --git a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/BitcoinDListener.java b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/BitcoinDListener.java index 8adcac5..50678c6 100644 --- a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/BitcoinDListener.java +++ b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/BitcoinDListener.java @@ -45,16 +45,17 @@ public void run() { if ((line = reader.readLine()) != null) { setChanged(); notifyObservers(line); - connection.close(); } } catch (IOException e) { e.printStackTrace(); } finally { // sockets are closed when complete. try { - if (connection != null) + if (connection != null) { connection.close(); + } } catch (IOException e) { + e.printStackTrace(); } } } diff --git a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/WalletListener.java b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/WalletListener.java index 502d621..675c523 100644 --- a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/WalletListener.java +++ b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/WalletListener.java @@ -23,15 +23,13 @@ public class WalletListener extends Observable implements Observer { public WalletListener(final CryptoCurrencyRPC client, int port) throws IOException { walletListener = new BitcoinDListener(port); this.client = client; + walletListener.addObserver(this); + listener = new Thread((Runnable) walletListener, "walletListener"); + listener.start(); } @Override public synchronized void addObserver(Observer o) { - if (listener == null) { - walletListener.addObserver(this); - listener = new Thread((Runnable) walletListener, "walletListener"); - listener.start(); - } super.addObserver(o); } diff --git a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/pojo/OmniTransaction.java b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/pojo/OmniTransaction.java new file mode 100644 index 0000000..0e5fb1b --- /dev/null +++ b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/pojo/OmniTransaction.java @@ -0,0 +1,34 @@ +package com.nitinsurana.bitcoinlitecoin.rpcconnector.pojo; + +/** + * Created by d.romantsov on 25.05.2016. + */ +public class OmniTransaction extends Transaction { + private String sendingaddress; + private String referenceaddress; + private Long propertyid; + + public String getReferenceaddress() { + return referenceaddress; + } + + public void setReferenceaddress(String referenceaddress) { + this.referenceaddress = referenceaddress; + } + + public String getSendingaddress() { + return sendingaddress; + } + + public void setSendingaddress(String sendingaddress) { + this.sendingaddress = sendingaddress; + } + + public Long getPropertyid() { + return propertyid; + } + + public void setPropertyid(Long propertyid) { + this.propertyid = propertyid; + } +} diff --git a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/pojo/Transaction.java b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/pojo/Transaction.java index 7b943b7..3301d4a 100644 --- a/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/pojo/Transaction.java +++ b/src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/pojo/Transaction.java @@ -64,8 +64,16 @@ public static Category fromString(String text) { private String otheraccount; private String comment; private String to; - - + private boolean isMine; + private String cryptoCurrency; + + public boolean isMine() { + return isMine; + } + + public void setMine(boolean mine) { + isMine = mine; + } public String getOtheraccount() { return otheraccount; } @@ -143,7 +151,20 @@ public Transaction setBlock(long block) { this.block = block; return this; } - + + public String getCryptoCurrency() { + return cryptoCurrency; + } + + public Transaction andSetCryptoCurrency(String cryptoCurrency) { + this.cryptoCurrency = cryptoCurrency; + return this; + } + + public void setCryptoCurrency(String cryptoCurrency) { + this.cryptoCurrency = cryptoCurrency; + } + public String getHex() { return hex; } diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties index 5a60bda..465f679 100644 --- a/src/main/resources/log4j.properties +++ b/src/main/resources/log4j.properties @@ -21,5 +21,5 @@ log4j.appender.applog=org.apache.log4j.DailyRollingFileAppender log4j.appender.applog.encoding=UTF-8 log4j.appender.applog.layout=org.apache.log4j.PatternLayout log4j.appender.applog.layout.ConversionPattern=%d{yyyy:MM:dd_HH:mm} %m%n -log4j.appender.applog.File=/var/log/bitcoin-rpc/daily/day.log -log4j.appender.applog.DatePattern='.'yyyyMM:dd_HH:mm'.log' \ No newline at end of file +log4j.appender.applog.File=/var/log/bitcoin-rpc/daily/d +log4j.appender.applog.DatePatctern='.'yyyyMM:dd'.log' \ No newline at end of file diff --git a/src/test/java/com/nitinsurana/litecoinrpcconnector/ApiTest.java b/src/test/java/com/nitinsurana/litecoinrpcconnector/ApiTest.java new file mode 100644 index 0000000..78f71ba --- /dev/null +++ b/src/test/java/com/nitinsurana/litecoinrpcconnector/ApiTest.java @@ -0,0 +1,16 @@ +package com.nitinsurana.litecoinrpcconnector; + +import com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC; +import org.junit.Test; + +/** + * Created by d.romantsov on 16.11.2016. + */ +public class ApiTest { + CryptoCurrencyRPC rpc = new CryptoCurrencyRPC("rpcuser", "rpcpassword", "localhost", "18332"); + + @Test + public void testWalletPassphrase() throws Exception { + //rpc.wallePassphrase("dsd", 32); + } +}