├── .gitattributes ├── .gitignore ├── README.md ├── nbactions-release-profile.xml ├── nbactions-sonatype-oss-release.xml ├── nbactions.xml ├── pom.xml ├── pom.xml.releaseBackup └── src ├── main ├── java │ └── com │ │ └── nitinsurana │ │ └── bitcoinlitecoin │ │ └── rpcconnector │ │ ├── APICalls.java │ │ ├── CryptoCurrencyRPC.java │ │ ├── JSONRequestBody.java │ │ ├── events │ │ ├── AlertListener.java │ │ ├── BitcoinDListener.java │ │ └── WalletListener.java │ │ ├── exception │ │ ├── AuthenticationException.java │ │ ├── CallApiCryptoCurrencyRpcException.java │ │ ├── CryptoCurrencyRpcException.java │ │ ├── CryptoCurrencyRpcExceptionHandler.java │ │ ├── InsufficientFundsException.java │ │ └── RpcInvalidResponseException.java │ │ └── pojo │ │ └── Transaction.java └── resources │ └── log4j.properties └── test └── java └── com └── nitinsurana └── litecoinrpcconnector └── AppTest.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Intellij Idea 3 | ################# 4 | *.iml 5 | 6 | ################# 7 | ## Eclipse 8 | ################# 9 | 10 | *.pydevproject 11 | .project 12 | .metadata 13 | bin/ 14 | tmp/ 15 | *.tmp 16 | *.bak 17 | *.swp 18 | *~.nib 19 | local.properties 20 | .classpath 21 | .settings/ 22 | .loadpath 23 | 24 | # External tool builders 25 | .externalToolBuilders/ 26 | 27 | # Locally stored "Eclipse launch configurations" 28 | *.launch 29 | 30 | # CDT-specific 31 | .cproject 32 | 33 | # PDT-specific 34 | .buildpath 35 | 36 | 37 | ################# 38 | ## Visual Studio 39 | ################# 40 | 41 | ## Ignore Visual Studio temporary files, build results, and 42 | ## files generated by popular Visual Studio add-ons. 43 | 44 | # User-specific files 45 | *.suo 46 | *.user 47 | *.sln.docstates 48 | 49 | # Build results 50 | 51 | [Dd]ebug/ 52 | [Rr]elease/ 53 | x64/ 54 | build/ 55 | [Bb]in/ 56 | [Oo]bj/ 57 | 58 | # MSTest test Results 59 | [Tt]est[Rr]esult*/ 60 | [Bb]uild[Ll]og.* 61 | 62 | *_i.c 63 | *_p.c 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.pch 68 | *.pdb 69 | *.pgc 70 | *.pgd 71 | *.rsp 72 | *.sbr 73 | *.tlb 74 | *.tli 75 | *.tlh 76 | *.tmp 77 | *.tmp_proj 78 | *.log 79 | *.vspscc 80 | *.vssscc 81 | .builds 82 | *.pidb 83 | *.log 84 | *.scc 85 | 86 | # Visual C++ cache files 87 | ipch/ 88 | *.aps 89 | *.ncb 90 | *.opensdf 91 | *.sdf 92 | *.cachefile 93 | 94 | # Visual Studio profiler 95 | *.psess 96 | *.vsp 97 | *.vspx 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | *.ncrunch* 114 | .*crunch*.local.xml 115 | 116 | # Installshield output folder 117 | [Ee]xpress/ 118 | 119 | # DocProject is a documentation generator add-in 120 | DocProject/buildhelp/ 121 | DocProject/Help/*.HxT 122 | DocProject/Help/*.HxC 123 | DocProject/Help/*.hhc 124 | DocProject/Help/*.hhk 125 | DocProject/Help/*.hhp 126 | DocProject/Help/Html2 127 | DocProject/Help/html 128 | 129 | # Click-Once directory 130 | publish/ 131 | 132 | # Publish Web Output 133 | *.Publish.xml 134 | *.pubxml 135 | 136 | # NuGet Packages Directory 137 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 138 | #packages/ 139 | 140 | # Windows Azure Build Output 141 | csx 142 | *.build.csdef 143 | 144 | # Windows Store app package directory 145 | AppPackages/ 146 | 147 | # Others 148 | sql/ 149 | *.Cache 150 | ClientBin/ 151 | [Ss]tyle[Cc]op.* 152 | ~$* 153 | *~ 154 | *.dbmdl 155 | *.[Pp]ublish.xml 156 | *.pfx 157 | *.publishsettings 158 | 159 | # RIA/Silverlight projects 160 | Generated_Code/ 161 | 162 | # Backup & report files from converting an old project file to a newer 163 | # Visual Studio version. Backup files are not needed, because we have git ;-) 164 | _UpgradeReport_Files/ 165 | Backup*/ 166 | UpgradeLog*.XML 167 | UpgradeLog*.htm 168 | 169 | # SQL Server files 170 | App_Data/*.mdf 171 | App_Data/*.ldf 172 | 173 | ############# 174 | ## Windows detritus 175 | ############# 176 | 177 | # Windows image file caches 178 | Thumbs.db 179 | ehthumbs.db 180 | 181 | # Folder config file 182 | Desktop.ini 183 | 184 | # Recycle Bin used on file shares 185 | $RECYCLE.BIN/ 186 | 187 | # Mac crap 188 | .DS_Store 189 | 190 | 191 | ############# 192 | ## Python 193 | ############# 194 | 195 | *.py[co] 196 | 197 | # Packages 198 | *.egg 199 | *.egg-info 200 | dist/ 201 | build/ 202 | eggs/ 203 | parts/ 204 | var/ 205 | sdist/ 206 | develop-eggs/ 207 | .installed.cfg 208 | 209 | # Installer logs 210 | pip-log.txt 211 | 212 | # Unit test / coverage reports 213 | .coverage 214 | .tox 215 | 216 | #Translations 217 | *.mo 218 | 219 | #Mr Developer 220 | .mr.developer.cfg 221 | /target 222 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | This project is a java library that is intended to provide a wrapper around JSON-RPC provided by Bitcoin/Litecoin. 5 | 6 | It has been tested on Litecoin. I wrote it for one of my projects. 7 | 8 | The main dependencies of this project are 9 | 10 | * **Htmlunit** 11 | * **Google Gson** 12 | 13 | Since this was intended for use in a proprietary project, I've tried to write as much javadoc as possible as to what the method does. 14 | 15 | JSON-RPC calls for Litecoin & Bitcoin are same as you can see below, so this work shall work with both. If it doesn't please let me know by filing an issue. 16 | 17 | [Litecoin RPC API Calls](https://litecoin.info/Litecoin_API) 18 | 19 | [Bitcoin RPC API Calls](https://en.bitcoin.it/wiki/API_reference_%28JSON-RPC%29) 20 | 21 | This project assumes that the one who uses it has a preliminary knowledge about Bitcoin/Litecoin and how to start the RPC server. 22 | 23 | [Running Litecoin](https://litecoin.info/Litecoin.conf) 24 | 25 | [Running Bitcoin](https://en.bitcoin.it/wiki/Running_Bitcoin) 26 | 27 | 28 | 29 | Sample Usage 30 | =========== 31 | 32 | public static void main(String[] args) throws Exception { 33 | final String rpcUser = "rpcuser"; 34 | final String rpcPassword = "password"; 35 | final String rpcHost = "localhost"; 36 | final String rpcPort = "9332"; 37 | CryptoCurrencyRPC cryptoCurrencyRPC = new CryptoCurrencyRPC(rpcUser, rpcPassword, rpcHost, rpcPort); 38 | 39 | cryptoCurrencyRPC.setAccount("account","LCYEnDaddressENBYCEYD235NSD"); 40 | 41 | //Similarly, all the API methods can be called. 42 | } 43 | 44 | ### Blockchain Events 45 | (part of the code was taken from https://github.com/johannbarbie/BitcoindClient4J) 46 | 47 | The library also captures notifications from Bitcoind using the startup configuration. Launch your deamon with those parameters: 48 | ```bash 49 | ./bitcoind -walletnotify="echo '%s' | nc 127.0.0.1 4002" 50 | -alertnotify="echo '%s' | nc 127.0.0.1 4003" 51 | -daemon 52 | ``` 53 | 54 | You can register observers to capture events of wallets, and alerts: 55 | ```java 56 | WalletListener walletListener = new WalletListener(cryptoCurrencyRPC, 4002); 57 | walletListener.addObserver(new Observer() { 58 | @Override 59 | public void update(Observable o, Object arg) { 60 | System.out.println("Amount of transaction: " + ((Transaction)arg).getAmount()); 61 | } 62 | }); 63 | 64 | ``` 65 | 66 | Make sure to close sockets later: 67 | ```java 68 | walletListener.stop(); 69 | ``` 70 | 71 | License 72 | ======= 73 | Copyright (c) 2014-2015 Nitin Surana | Licensed under the MIT license. 74 | 75 | 76 | > Written with [StackEdit](https://stackedit.io/). 77 | -------------------------------------------------------------------------------- /nbactions-release-profile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | run 5 | 6 | jar 7 | 8 | 9 | process-classes 10 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 11 | 12 | 13 | -classpath %classpath com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC 14 | java 15 | 16 | 17 | 18 | debug 19 | 20 | jar 21 | 22 | 23 | process-classes 24 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 25 | 26 | 27 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath 28 | com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC 29 | java 30 | true 31 | 32 | 33 | 34 | profile 35 | 36 | jar 37 | 38 | 39 | process-classes 40 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 41 | 42 | 43 | -classpath %classpath com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC 44 | java 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /nbactions-sonatype-oss-release.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | run 5 | 6 | jar 7 | 8 | 9 | process-classes 10 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 11 | 12 | 13 | -classpath %classpath com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC 14 | java 15 | 16 | 17 | 18 | debug 19 | 20 | jar 21 | 22 | 23 | process-classes 24 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 25 | 26 | 27 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath 28 | com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC 29 | java 30 | true 31 | 32 | 33 | 34 | profile 35 | 36 | jar 37 | 38 | 39 | process-classes 40 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 41 | 42 | 43 | -classpath %classpath com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC 44 | java 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /nbactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | run 5 | 6 | jar 7 | 8 | 9 | process-classes 10 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 11 | 12 | 13 | -classpath %classpath com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC 14 | java 15 | 16 | 17 | 18 | debug 19 | 20 | jar 21 | 22 | 23 | process-classes 24 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 25 | 26 | 27 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath 28 | com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC 29 | java 30 | true 31 | 32 | 33 | 34 | profile 35 | 36 | jar 37 | 38 | 39 | process-classes 40 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 41 | 42 | 43 | -classpath %classpath com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC 44 | java 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | com.nitinsurana 5 | Litecoin-Bitcoin-RPC-Java-Connector 6 | 2.0.0 7 | jar 8 | 9 | Litecoin-Bitcoin-RPC-Java-Connector 10 | Java Wrapper around the JSON-RPC provided by Bitcoin/Litecoin 11 | http://nitinsurana.com 12 | 13 | 14 | 15 | org.sonatype.oss 16 | oss-parent 17 | 7 18 | 19 | 20 | 21 | 22 | MIT License 23 | http://www.opensource.org/licenses/mit-license.php 24 | repo 25 | 26 | 27 | 28 | 29 | 30 | https://github.com/coding-idiot/Litecoin-Bitcoin-RPC-Java-Connector 31 | 32 | scm:git:git@github.com:coding-idiot/Litecoin-Bitcoin-RPC-Java-Connector.git 33 | scm:git:git@github.com:coding-idiot/Litecoin-Bitcoin-RPC-Java-Connector.git 34 | 35 | 36 | 37 | 38 | nitin.cool4urchat@gmail.com 39 | Nitin Surana 40 | https://nitinsurana.com 41 | coding_idiot 42 | 43 | 44 | 45 | 46 | UTF-8 47 | 48 | 49 | 50 | 51 | 52 | org.apache.maven.plugins 53 | maven-jar-plugin 54 | 2.6 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.apache.maven.plugins 62 | maven-shade-plugin 63 | 1.6 64 | 65 | 66 | package 67 | 68 | shade 69 | 70 | 71 | 72 | 73 | 74 | org.apache.maven.plugins 75 | maven-compiler-plugin 76 | 2.0.2 77 | 78 | 1.6 79 | 1.6 80 | 81 | 82 | 83 | maven-dependency-plugin 84 | 2.10 85 | 86 | 87 | install 88 | 89 | copy-dependencies 90 | 91 | 92 | ${project.build.directory}/lib 93 | 94 | 95 | 96 | 97 | 98 | org.apache.maven.plugins 99 | maven-jar-plugin 100 | 2.6 101 | 102 | 103 | 104 | true 105 | lib/ 106 | com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC 107 | 108 | 109 | 110 | 111 | 112 | org.apache.maven.plugins 113 | maven-javadoc-plugin 114 | 115 | 116 | 117 | jar 118 | 119 | 120 | -Xdoclint:none 121 | 122 | 123 | 124 | 125 | 126 | org.apache.maven.plugins 127 | maven-source-plugin 128 | 2.4 129 | 130 | 131 | 132 | jar 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | org.apache.commons 143 | commons-lang3 144 | 3.4 145 | 146 | 147 | com.google.code.gson 148 | gson 149 | 2.3.1 150 | 151 | 152 | log4j 153 | log4j 154 | 1.2.17 155 | 156 | 157 | net.sourceforge.htmlunit 158 | htmlunit 159 | 2.15 160 | compile 161 | 162 | 163 | junit 164 | junit 165 | 4.12 166 | test 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /pom.xml.releaseBackup: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | com.nitinsurana 5 | Litecoin-Bitcoin-RPC-Java-Connector 6 | 2.0.0-SNAPSHOT 7 | jar 8 | 9 | Litecoin-Bitcoin-RPC-Java-Connector 10 | Java Wrapper around the JSON-RPC provided by Bitcoin/Litecoin 11 | http://nitinsurana.com 12 | 13 | 14 | org.sonatype.oss 15 | oss-parent 16 | 7 17 | 18 | 19 | 20 | 21 | MIT License 22 | http://www.opensource.org/licenses/mit-license.php 23 | repo 24 | 25 | 26 | 27 | 28 | 29 | https://github.com/coding-idiot/Litecoin-Bitcoin-RPC-Java-Connector 30 | 31 | scm:git:git@github.com:coding-idiot/Litecoin-Bitcoin-RPC-Java-Connector.git 32 | scm:git:git@github.com:coding-idiot/Litecoin-Bitcoin-RPC-Java-Connector.git 33 | 34 | 35 | 36 | 37 | nitin.cool4urchat@gmail.com 38 | Nitin Surana 39 | https://nitinsurana.com 40 | coding_idiot 41 | 42 | 43 | 44 | 45 | UTF-8 46 | 47 | 48 | 49 | 50 | org.apache.maven.plugins 51 | maven-compiler-plugin 52 | 2.0.2 53 | 54 | 1.6 55 | 1.6 56 | 57 | 58 | 59 | maven-dependency-plugin 60 | 61 | 62 | install 63 | 64 | copy-dependencies 65 | 66 | 67 | ${project.build.directory}/lib 68 | 69 | 70 | 71 | 72 | 73 | org.apache.maven.plugins 74 | maven-jar-plugin 75 | 76 | 77 | 78 | true 79 | lib/ 80 | com.nitinsurana.bitcoinlitecoin.rpcconnector.App 81 | 82 | 83 | 84 | 85 | 86 | org.apache.maven.plugins 87 | maven-javadoc-plugin 88 | 89 | 90 | 91 | jar 92 | 93 | 94 | 95 | 96 | 97 | org.apache.maven.plugins 98 | maven-source-plugin 99 | 100 | 101 | 102 | jar 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | org.apache.commons 113 | commons-lang3 114 | 3.2.1 115 | 116 | 117 | com.google.code.gson 118 | gson 119 | 2.2.4 120 | 121 | 122 | log4j 123 | log4j 124 | 1.2.17 125 | 126 | 127 | net.sourceforge.htmlunit 128 | htmlunit 129 | 2.12 130 | compile 131 | 132 | 133 | junit 134 | junit 135 | 4.11 136 | test 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/APICalls.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package com.nitinsurana.bitcoinlitecoin.rpcconnector; 7 | 8 | /** 9 | * 10 | * @author hp 11 | */ 12 | public enum APICalls { 13 | 14 | GET_NEW_ADDRESS("getnewaddress"), 15 | DUMP_PRIVATE_KEY("dumpprivkey"), 16 | GET_ACCOUNT("getaccount"), 17 | GET_ACCOUNT_ADDRESS("getaccountaddress"), 18 | LIST_ACCOUNTS("listaccounts"), 19 | LIST_ADDRESS_GROUPINGS("listaddressgroupings"), 20 | LIST_RECEIVED_BY_ACCOUNT("listreceivedbyaccount"), 21 | LIST_RECEIVED_BY_ADDRESS("listreceivedbyaddress"), 22 | SEND_FROM("sendfrom"), 23 | SEND_RAW_TRANSACTION("sendrawtransaction"), 24 | SET_ACCOUNT("setaccount"), 25 | SEND_TO_ADDRESS("sendtoaddress"), 26 | GET_ADDRESSES_BY_ACCOUNT("getaddressesbyaccount"), 27 | GET_RECEIVED_BY_ACCOUNT("getreceivedbyaccount"), 28 | GET_RECEIVED_BY_ADDRESS("getreceivedbyaddress"), 29 | GET_BALANCE("getbalance"), 30 | GET_TRANSACTION("gettransaction"), 31 | GET_CONNECTION_COUNT("getconnectioncount"), 32 | BACKUP_WALLET("backupwallet"), 33 | DECODE_RAW_TRANSACTION("decoderawtransaction"), 34 | GET_RAW_TRANSACTION("getrawtransaction"), 35 | LIST_TRANSACTIONS("listtransactions"), 36 | LIST_UNSPENT("listunspent"), 37 | CREATE_RAW_TRANSACTION("createrawtransaction"), 38 | SIGN_RAW_TRANSACTION("signrawtransaction"), 39 | VALIDATE_ADDRESS("validateaddress"), 40 | ENCRYPT_WALLET("encryptwallet"); 41 | 42 | private String value; 43 | 44 | private APICalls(String value) { 45 | this.value = value; 46 | } 47 | 48 | @Override 49 | public String toString() { 50 | //Using in BitcoinRPC#callAPIMethod(..) 51 | return value; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/CryptoCurrencyRPC.java: -------------------------------------------------------------------------------- 1 | package com.nitinsurana.bitcoinlitecoin.rpcconnector; 2 | 3 | import com.gargoylesoftware.htmlunit.*; 4 | import com.google.gson.Gson; 5 | import com.google.gson.JsonArray; 6 | import com.google.gson.JsonObject; 7 | import com.google.gson.JsonParser; 8 | import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.AuthenticationException; 9 | import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException; 10 | import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcExceptionHandler; 11 | import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CallApiCryptoCurrencyRpcException; 12 | import com.nitinsurana.bitcoinlitecoin.rpcconnector.pojo.Transaction; 13 | import org.apache.log4j.Logger; 14 | 15 | import java.math.BigDecimal; 16 | import java.net.URL; 17 | import java.util.Arrays; 18 | import java.util.List; 19 | 20 | public class CryptoCurrencyRPC { 21 | 22 | public static final Logger LOG = Logger.getLogger("rpcLogger"); 23 | 24 | private WebClient client; 25 | private String baseUrl; 26 | private CryptoCurrencyRpcExceptionHandler cryptoCurrencyRpcExceptionHandler = new CryptoCurrencyRpcExceptionHandler(); 27 | private Gson gson = new Gson(); 28 | 29 | public CryptoCurrencyRPC(String rpcUser, String rpcPassword, String rpcHost, String rpcPort) throws AuthenticationException { 30 | client = new WebClient(BrowserVersion.CHROME); 31 | client.getOptions().setThrowExceptionOnFailingStatusCode(false); 32 | client.getOptions().setThrowExceptionOnScriptError(false); 33 | client.getOptions().setPrintContentOnFailingStatusCode(false); 34 | client.getOptions().setJavaScriptEnabled(false); 35 | client.getOptions().setCssEnabled(false); 36 | baseUrl = new String("http://" + rpcUser + ":" + rpcPassword + "@" + rpcHost + ":" + rpcPort + "/"); 37 | 38 | try { 39 | if (client.getPage(baseUrl).getWebResponse().getStatusCode() == 401) { //401 is Http Unauthorized 40 | throw new AuthenticationException(); 41 | } 42 | } catch (Exception ex) { 43 | LOG.error(ex.getMessage(), ex); 44 | } 45 | } 46 | 47 | /** 48 | * Safely copies wallet.dat to destination, which can be a directory or a 49 | * path with filename. 50 | * 51 | * @param destination 52 | * @return 53 | * @throws Exception 54 | */ 55 | public boolean backupWallet(String destination) throws CryptoCurrencyRpcException { 56 | JsonObject jsonObj = callAPIMethod(APICalls.BACKUP_WALLET, destination); 57 | if (jsonObj.get("error") == null) { 58 | return true; 59 | } 60 | return false; 61 | } 62 | 63 | /** 64 | * Produces a human-readable JSON object for a raw transaction. 65 | * 66 | * @param hex 67 | * @return 68 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 69 | */ 70 | public JsonObject decodeRawTransaction(String hex) throws CryptoCurrencyRpcException { 71 | JsonObject jsonObj = callAPIMethod(APICalls.DECODE_RAW_TRANSACTION, hex); 72 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 73 | return jsonObj.get("result").getAsJsonObject(); 74 | } 75 | 76 | /** 77 | * Reveals the private key corresponding to
78 | * 79 | * @param address 80 | * @return 81 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 82 | */ 83 | public String dumpPrivateKey(String address) throws CryptoCurrencyRpcException { 84 | JsonObject jsonObj = callAPIMethod(APICalls.DUMP_PRIVATE_KEY, address); 85 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 86 | return jsonObj.get("result").getAsString(); 87 | } 88 | 89 | /** 90 | * Returns raw transaction representation for given transaction id. 91 | * 92 | * @param txid 93 | * @return returns the hex string for the given transaction id 94 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 95 | */ 96 | public String getRawTransaction(String txid) throws CryptoCurrencyRpcException { 97 | JsonObject jsonObj = callAPIMethod(APICalls.GET_RAW_TRANSACTION, txid); 98 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 99 | return jsonObj.get("result").getAsString(); 100 | } 101 | 102 | /** 103 | * Returns the account associated with the given address. 104 | * 105 | * @param address 106 | * @return 107 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 108 | */ 109 | public String getAccount(String address) throws CryptoCurrencyRpcException { 110 | JsonObject jsonObj = callAPIMethod(APICalls.GET_ACCOUNT, address); 111 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 112 | return jsonObj.get("result").getAsString(); 113 | } 114 | 115 | /** 116 | * Returns the current Litecoin address for receiving payments to this 117 | * account. 118 | * 119 | * @param account 120 | * @return 121 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 122 | */ 123 | public String getAccountAddress(String account) throws CryptoCurrencyRpcException { 124 | JsonObject jsonObj = callAPIMethod(APICalls.GET_ACCOUNT_ADDRESS, account); 125 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 126 | return jsonObj.get("result").getAsString(); 127 | } 128 | 129 | /** 130 | * Returns the list of addresses for the given account. 131 | * 132 | * @param account 133 | * @return 134 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 135 | */ 136 | public JsonArray getAddressesByAccount(String account) throws CryptoCurrencyRpcException { 137 | JsonObject jsonObj = callAPIMethod(APICalls.GET_ADDRESSES_BY_ACCOUNT, account); 138 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 139 | return jsonObj.get("result").getAsJsonArray(); 140 | } 141 | 142 | /** 143 | * Returns the balance in the account. 144 | * 145 | * @param account 146 | * @return 147 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 148 | */ 149 | public BigDecimal getBalance(String account) throws CryptoCurrencyRpcException { 150 | JsonObject jsonObj = callAPIMethod(APICalls.GET_BALANCE, account); 151 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 152 | return jsonObj.get("result").getAsBigDecimal(); 153 | } 154 | 155 | /** 156 | * Returns the wallet's total available balance. 157 | * 158 | * @return 159 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 160 | */ 161 | public BigDecimal getBalance() throws CryptoCurrencyRpcException { 162 | JsonObject jsonObj = callAPIMethod(APICalls.GET_BALANCE); 163 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 164 | return jsonObj.get("result").getAsBigDecimal(); 165 | } 166 | 167 | /** 168 | * Returns the total amount received by addresses with [account] in 169 | * transactions 170 | * 171 | * @param account 172 | * @return 173 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 174 | */ 175 | public BigDecimal getReceivedByAccount(String account) throws CryptoCurrencyRpcException { 176 | JsonObject jsonObj = callAPIMethod(APICalls.GET_RECEIVED_BY_ACCOUNT, account); 177 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 178 | return jsonObj.get("result").getAsBigDecimal(); 179 | } 180 | 181 | /** 182 | * Returns a new address for receiving payments. 183 | * 184 | * @return 185 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 186 | */ 187 | public String getNewAddress() throws CryptoCurrencyRpcException { 188 | JsonObject jsonObj = callAPIMethod(APICalls.GET_NEW_ADDRESS); 189 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 190 | return jsonObj.get("result").getAsString(); 191 | } 192 | 193 | /** 194 | * Returns a new address for receiving payments. 195 | * 196 | * @param account 197 | * @return 198 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 199 | */ 200 | public String getNewAddress(String account) throws CryptoCurrencyRpcException { 201 | JsonObject jsonObj = callAPIMethod(APICalls.GET_NEW_ADDRESS, account); 202 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 203 | return jsonObj.get("result").getAsString(); 204 | } 205 | 206 | /** 207 | * Returns the total amount received by
in transactions 208 | * 209 | * @param address 210 | * @return 211 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 212 | */ 213 | public BigDecimal getReceivedByAddress(String address) throws CryptoCurrencyRpcException { 214 | JsonObject jsonObj = callAPIMethod(APICalls.GET_RECEIVED_BY_ADDRESS, address); 215 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 216 | return jsonObj.get("result").getAsBigDecimal(); 217 | } 218 | 219 | /** 220 | * Returns an object about the given transaction containing: amount, 221 | * confirmations, txid, time[1], details (an array of objects containing: 222 | * account, address, category, amount, fee) 223 | * 224 | * @param txid 225 | * @return 226 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 227 | */ 228 | public Transaction getTransaction(String txid) throws CryptoCurrencyRpcException { 229 | JsonObject jsonObj = callAPIMethod(APICalls.GET_TRANSACTION, txid); 230 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 231 | return gson.fromJson(jsonObj.get("result").getAsJsonObject(), Transaction.class); 232 | } 233 | 234 | /** 235 | * Returns Object that has account names as keys, account balances as 236 | * values. 237 | * 238 | * @return 239 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 240 | */ 241 | public JsonObject listAccounts() throws CryptoCurrencyRpcException { 242 | JsonObject jsonObj = callAPIMethod(APICalls.LIST_ACCOUNTS); 243 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 244 | return jsonObj.get("result").getAsJsonObject(); 245 | } 246 | 247 | /** 248 | * Returns an array of objects containing: account, amount, confirmations 249 | * 250 | * @return 251 | */ 252 | public JsonArray listReceivedByAccount() throws CryptoCurrencyRpcException { 253 | JsonObject jsonObj = callAPIMethod(APICalls.LIST_RECEIVED_BY_ACCOUNT); 254 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 255 | return jsonObj.get("result").getAsJsonArray(); 256 | } 257 | 258 | /** 259 | * Returns an array of objects containing: address, account, amount, 260 | * confirmations 261 | * 262 | * @return 263 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 264 | */ 265 | public JsonArray listReceivedByAddress() throws CryptoCurrencyRpcException { 266 | JsonObject jsonObj = callAPIMethod(APICalls.LIST_RECEIVED_BY_ADDRESS); 267 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 268 | return jsonObj.get("result").getAsJsonArray(); 269 | } 270 | 271 | /** 272 | * is a real and is rounded to 8 decimal places. Will send the 273 | * given amount to the given address, ensuring the account has a valid 274 | * balance using [minconf] confirmations. Returns the transaction ID if 275 | * successful 276 | * 277 | * @param fromAccount 278 | * @param toAddress 279 | * @param amount 280 | * @return 281 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 282 | */ 283 | public String sendFrom(String fromAccount, String toAddress, BigDecimal amount) throws CryptoCurrencyRpcException { 284 | JsonObject response = callAPIMethod(APICalls.SEND_FROM, fromAccount, toAddress, amount); 285 | cryptoCurrencyRpcExceptionHandler.checkException(response); 286 | return response.get("result").getAsString(); 287 | } 288 | 289 | /** 290 | * < amount > is a real and is rounded to the nearest 0.00000001 291 | * 292 | * @param toAddress 293 | * @param amount 294 | * @return TransactionID 295 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 296 | */ 297 | public String sendToAddress(String toAddress, BigDecimal amount) throws CryptoCurrencyRpcException { 298 | JsonObject jsonObj = callAPIMethod(APICalls.SEND_TO_ADDRESS, toAddress, amount); 299 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 300 | return jsonObj.get("result").getAsString(); 301 | } 302 | 303 | public boolean validateAddress(String address) throws CryptoCurrencyRpcException { 304 | JsonObject jsonObj = callAPIMethod(APICalls.VALIDATE_ADDRESS, address); 305 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 306 | return jsonObj.get("result").getAsJsonObject().get("isvalid").getAsBoolean(); 307 | } 308 | 309 | /** 310 | * Sets the account associated with the given address. Assigning address 311 | * that is already assigned to the same account will create a new address 312 | * associated with that account. 313 | * 314 | * @param address 315 | * @param account 316 | * 317 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 318 | */ 319 | public void setAccount(String address, String account) throws CryptoCurrencyRpcException { 320 | JsonObject jsonObj = callAPIMethod(APICalls.SET_ACCOUNT, address, account); 321 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 322 | } 323 | 324 | /** 325 | * Returns up to [count] most recent transactions skipping the first [from] 326 | * transactions for account [account]. 327 | * 328 | * @param account 329 | * @param count 330 | * @param from 331 | * @return 332 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 333 | */ 334 | public List listTransactions(String account, int count, int from) throws CryptoCurrencyRpcException { 335 | JsonObject jsonObj = callAPIMethod(APICalls.LIST_TRANSACTIONS, account, count, from); 336 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 337 | 338 | return Arrays.asList(gson.fromJson(jsonObj.get("result").getAsJsonArray(), Transaction[].class)); 339 | } 340 | 341 | /** 342 | * Returns all unspent outputs with at least [minconf] and at most [maxconf] 343 | * confirmations. 344 | * 345 | * @param minconf 346 | * @param maxconf 347 | * @return 348 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 349 | */ 350 | public JsonArray listUnspent(int minconf, int maxconf) throws CryptoCurrencyRpcException { 351 | JsonObject jsonObj = callAPIMethod(APICalls.LIST_UNSPENT, minconf, maxconf); 352 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 353 | 354 | return jsonObj.get("result").getAsJsonArray(); 355 | } 356 | 357 | /** 358 | * Returns all unspent outputs with at least [minconf] and at most 9999999 359 | * confirmations; Further limited to outputs that pay at least one of the 360 | * given addresses in the [address] array. 361 | * 362 | * @param minconf 363 | * @param address 364 | * @return 365 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 366 | */ 367 | public JsonArray listUnspent(int minconf, String[] address) throws CryptoCurrencyRpcException { 368 | JsonObject jsonObj = callAPIMethod(APICalls.LIST_UNSPENT, minconf, address); 369 | 370 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 371 | return jsonObj.get("result").getAsJsonArray(); 372 | } 373 | 374 | 375 | /** 376 | * Returns all unspent outputs with at least [minconf] and at most 9999999 377 | * confirmations. 378 | * 379 | * @param minconf 380 | * @return 381 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 382 | */ 383 | public JsonArray listUnspent(int minconf) throws CryptoCurrencyRpcException { 384 | JsonObject jsonObj = callAPIMethod(APICalls.LIST_UNSPENT, minconf); 385 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 386 | return jsonObj.get("result").getAsJsonArray(); 387 | } 388 | 389 | /** 390 | * Returns all unspent outputs with at least [minconf] and at most [maxconf] 391 | * confirmations; Further limited to outputs that pay at least one of the 392 | * given addresses in the [address] array. 393 | * 394 | * @param minconf 395 | * @param maxconf 396 | * @param address 397 | * @return 398 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 399 | */ 400 | public JsonArray listUnspent(int minconf, int maxconf, String[] address) throws CryptoCurrencyRpcException { 401 | JsonObject jsonObj = callAPIMethod(APICalls.LIST_UNSPENT, minconf, maxconf, address); 402 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 403 | 404 | return jsonObj.get("result").getAsJsonArray(); 405 | } 406 | 407 | /** 408 | * Returns an unsigned transaction that spends the outputs [prevOut] to new 409 | * outputs [Out] and encodes it as hex format. 410 | * 411 | * @param prevOut is an array of JsonObjects, each with the properties 412 | * "txid" and "vout". 413 | * @param out is an JsonObject with the receiving addresses as properties 414 | * and the receiving amount as value of each property(=address) 415 | * @return 416 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 417 | */ 418 | public Transaction createRawTransaction(JsonObject[] prevOut, JsonObject out) throws CryptoCurrencyRpcException { 419 | JsonObject jsonObj = callAPIMethod(APICalls.CREATE_RAW_TRANSACTION, prevOut, out); 420 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 421 | 422 | return gson.fromJson(jsonObj.get("result").getAsJsonObject(), Transaction.class); 423 | } 424 | 425 | /** 426 | * Returns a signed transaction in hex format using private keys stored in 427 | * the wallet and the output from createRawTransaction() 428 | * 429 | * @param hexString 430 | * @return 431 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 432 | */ 433 | public Transaction signRawTransaction(String hexString) throws CryptoCurrencyRpcException { 434 | JsonObject jsonObj = callAPIMethod(APICalls.SIGN_RAW_TRANSACTION,hexString); 435 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 436 | 437 | return gson.fromJson(jsonObj.get("result").getAsJsonObject(), Transaction.class); 438 | } 439 | 440 | /** 441 | * Validates a signed transaction in hex format and broadcasts it to the 442 | * network. 443 | * 444 | * @param hexString 445 | * @return 446 | * @throws com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException 447 | */ 448 | public String sendRawTransaction(String hexString) throws CryptoCurrencyRpcException { 449 | JsonObject jsonObj = callAPIMethod(APICalls.SEND_RAW_TRANSACTION,hexString); 450 | cryptoCurrencyRpcExceptionHandler.checkException(jsonObj); 451 | 452 | return jsonObj.get("result").getAsString(); 453 | } 454 | 455 | private JsonObject callAPIMethod(APICalls callMethod, Object... params) throws CallApiCryptoCurrencyRpcException { 456 | try { 457 | JsonObject jsonObj = null; 458 | WebRequest req = new WebRequest(new URL(baseUrl)); 459 | req.setAdditionalHeader("Content-type", "application/json"); 460 | req.setHttpMethod(HttpMethod.POST); 461 | JSONRequestBody body = new JSONRequestBody(); 462 | body.setMethod(callMethod.toString()); 463 | if (params != null && params.length > 0) { 464 | body.setParams(params); 465 | } 466 | req.setRequestBody(new Gson().toJson(body, JSONRequestBody.class)); 467 | WebResponse resp = client.getPage(req).getWebResponse(); 468 | jsonObj = new JsonParser().parse(resp.getContentAsString()).getAsJsonObject(); 469 | 470 | StringBuffer buffer = new StringBuffer(""); 471 | for (Object item : params) { 472 | buffer.append(item.toString() + " | "); 473 | } 474 | LOG.info("Bitcoin RPC Request: Method: " + callMethod + " Params: " + buffer.toString() + 475 | "\nBitcoin RPC Response : " + jsonObj); 476 | 477 | return jsonObj; 478 | } catch (Exception e) { 479 | throw new CallApiCryptoCurrencyRpcException(e.getMessage()); 480 | } 481 | } 482 | } 483 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/JSONRequestBody.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package com.nitinsurana.bitcoinlitecoin.rpcconnector; 7 | 8 | /** 9 | * 10 | * @author hp 11 | */ 12 | public class JSONRequestBody { 13 | 14 | private String method, id; 15 | private Object[] params = new Object[]{}; 16 | 17 | public String getMethod() { 18 | return method; 19 | } 20 | 21 | public void setMethod(String method) { 22 | this.method = method; 23 | } 24 | 25 | public String getId() { 26 | return id; 27 | } 28 | 29 | public void setId(String id) { 30 | this.id = id; 31 | } 32 | 33 | public Object[] getParams() { 34 | return params; 35 | } 36 | 37 | public void setParams(Object[] params) { 38 | this.params = params; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/AlertListener.java: -------------------------------------------------------------------------------- 1 | package com.nitinsurana.bitcoinlitecoin.rpcconnector.events; 2 | 3 | import java.io.IOException; 4 | import java.util.Observable; 5 | import java.util.Observer; 6 | 7 | /** 8 | * The class, which allows to subscribe to notifications of events related to Bitcoin network. 9 | * Bitcoind must be configured with -alertnotify parameter. 10 | */ 11 | public class AlertListener extends Observable implements Observer { 12 | 13 | final private Observable alertListener; 14 | public Thread listener = null; 15 | 16 | public AlertListener(int port) throws IOException { 17 | alertListener = new BitcoinDListener(port); 18 | } 19 | 20 | @Override 21 | public synchronized void addObserver(Observer o) { 22 | if (null == listener) { 23 | alertListener.addObserver(this); 24 | listener = new Thread((Runnable) alertListener, "alertListener"); 25 | listener.start(); 26 | } 27 | super.addObserver(o); 28 | } 29 | 30 | @Override 31 | public void update(Observable o, Object arg) { 32 | final String value = ((String) arg).trim(); 33 | setChanged(); 34 | notifyObservers(value); 35 | } 36 | 37 | public void stop(){ 38 | listener.interrupt(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/BitcoinDListener.java: -------------------------------------------------------------------------------- 1 | package com.nitinsurana.bitcoinlitecoin.rpcconnector.events; 2 | 3 | import org.apache.log4j.Logger; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.net.ServerSocket; 9 | import java.net.Socket; 10 | import java.util.Observable; 11 | 12 | /** 13 | * Basic class for implementation CryptoCurrencyListener's. Contains work with ports and streams. 14 | */ 15 | public class BitcoinDListener extends Observable implements Runnable { 16 | public static final Logger LOG = Logger.getLogger("rpcLogger"); 17 | private final ServerSocket server; 18 | private int port; 19 | 20 | public BitcoinDListener(int port) throws IOException { 21 | server = new ServerSocket(port); 22 | this.port = port; 23 | } 24 | 25 | public BitcoinDListener(ServerSocket server) throws IOException { 26 | this.server = server; 27 | this.port = server.getLocalPort(); 28 | } 29 | 30 | @Override 31 | public void run() { 32 | LOG.info("Thread " + Thread.currentThread().getName() 33 | + " started listening on " + port); 34 | while (!Thread.currentThread().isInterrupted()) { 35 | Socket connection = null; 36 | try { 37 | connection = server.accept(); 38 | } catch (IOException e1) { 39 | e1.printStackTrace(); 40 | break; 41 | } 42 | try { 43 | BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); 44 | String line; 45 | if ((line = reader.readLine()) != null) { 46 | setChanged(); 47 | notifyObservers(line); 48 | connection.close(); 49 | } 50 | } catch (IOException e) { 51 | e.printStackTrace(); 52 | } finally { 53 | // sockets are closed when complete. 54 | try { 55 | if (connection != null) 56 | connection.close(); 57 | } catch (IOException e) { 58 | } 59 | } 60 | } 61 | LOG.warn("Thread " + Thread.currentThread().getName() + " exited"); 62 | } 63 | 64 | @Override 65 | protected void finalize() throws Throwable { 66 | server.close(); 67 | LOG.info("Thread " + Thread.currentThread().getName() + " shutting down."); 68 | super.finalize(); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/events/WalletListener.java: -------------------------------------------------------------------------------- 1 | package com.nitinsurana.bitcoinlitecoin.rpcconnector.events; 2 | 3 | import com.nitinsurana.bitcoinlitecoin.rpcconnector.CryptoCurrencyRPC; 4 | import com.nitinsurana.bitcoinlitecoin.rpcconnector.exception.CryptoCurrencyRpcException; 5 | import com.nitinsurana.bitcoinlitecoin.rpcconnector.pojo.Transaction; 6 | import org.apache.log4j.Logger; 7 | 8 | import java.io.IOException; 9 | import java.util.Observable; 10 | import java.util.Observer; 11 | 12 | /** 13 | * The class allows you to subscribe to the events associated with purses. 14 | * Bitcoind must be configured with -walletnotify parameter. 15 | */ 16 | public class WalletListener extends Observable implements Observer { 17 | public static final Logger LOG = Logger.getLogger("rpcLogger"); 18 | 19 | final private Observable walletListener; 20 | final private CryptoCurrencyRPC client; 21 | public Thread listener = null; 22 | 23 | public WalletListener(final CryptoCurrencyRPC client, int port) throws IOException { 24 | walletListener = new BitcoinDListener(port); 25 | this.client = client; 26 | } 27 | 28 | @Override 29 | public synchronized void addObserver(Observer o) { 30 | if (listener == null) { 31 | walletListener.addObserver(this); 32 | listener = new Thread((Runnable) walletListener, "walletListener"); 33 | listener.start(); 34 | } 35 | super.addObserver(o); 36 | } 37 | 38 | @Override 39 | public void update(Observable o, Object arg) { 40 | final String value = ((String) arg).trim(); 41 | new Thread() { 42 | public void run() { 43 | try { 44 | Transaction tx = client.getTransaction(value); 45 | LOG.info("WalletEvent. TxId: " + tx.getTxid() + " Amount: " + tx.getAmount()); 46 | setChanged(); 47 | notifyObservers(tx); 48 | } catch (CryptoCurrencyRpcException e) { 49 | e.printStackTrace(); 50 | } 51 | 52 | } 53 | }.start(); 54 | } 55 | 56 | public void stop(){ 57 | listener.interrupt(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/exception/AuthenticationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package com.nitinsurana.bitcoinlitecoin.rpcconnector.exception; 7 | 8 | /** 9 | * 10 | * @author hp 11 | */ 12 | public class AuthenticationException extends CryptoCurrencyRpcException { 13 | 14 | public AuthenticationException() { 15 | super("Invalid RPC Credentials"); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/exception/CallApiCryptoCurrencyRpcException.java: -------------------------------------------------------------------------------- 1 | package com.nitinsurana.bitcoinlitecoin.rpcconnector.exception; 2 | 3 | /** 4 | * Created by d.romantsov on 26.05.2015. 5 | */ 6 | public class CallApiCryptoCurrencyRpcException extends CryptoCurrencyRpcException { 7 | public CallApiCryptoCurrencyRpcException(String message) { 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/exception/CryptoCurrencyRpcException.java: -------------------------------------------------------------------------------- 1 | package com.nitinsurana.bitcoinlitecoin.rpcconnector.exception; 2 | 3 | /** 4 | * Created by d.romantsov on 22.05.2015. 5 | */ 6 | public class CryptoCurrencyRpcException extends RuntimeException { 7 | 8 | public CryptoCurrencyRpcException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/exception/CryptoCurrencyRpcExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.nitinsurana.bitcoinlitecoin.rpcconnector.exception; 2 | 3 | import com.google.gson.JsonObject; 4 | 5 | /** 6 | * Created by d.romantsov on 22.05.2015. 7 | */ 8 | public class CryptoCurrencyRpcExceptionHandler { 9 | 10 | public void checkException(JsonObject response) throws CryptoCurrencyRpcException { 11 | if (response.get("error") != null && response.get("error").isJsonObject() == true) { 12 | JsonObject errorJson = response.get("error").getAsJsonObject(); 13 | String message = errorJson.get("message").getAsString(); 14 | 15 | int code = errorJson.get("code").getAsInt(); 16 | switch (code) { 17 | case -6: 18 | throw new InsufficientFundsException(message); 19 | default: 20 | throw new CryptoCurrencyRpcException(message); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/exception/InsufficientFundsException.java: -------------------------------------------------------------------------------- 1 | package com.nitinsurana.bitcoinlitecoin.rpcconnector.exception; 2 | 3 | /** 4 | * Created by d.romantsov on 22.05.2015. 5 | */ 6 | public class InsufficientFundsException extends CryptoCurrencyRpcException { 7 | public InsufficientFundsException(String message) { 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/exception/RpcInvalidResponseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package com.nitinsurana.bitcoinlitecoin.rpcconnector.exception; 7 | 8 | /** 9 | * 10 | * @author hp 11 | */ 12 | public class RpcInvalidResponseException extends CryptoCurrencyRpcException { 13 | 14 | public RpcInvalidResponseException(String message) { 15 | super(message); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/nitinsurana/bitcoinlitecoin/rpcconnector/pojo/Transaction.java: -------------------------------------------------------------------------------- 1 | package com.nitinsurana.bitcoinlitecoin.rpcconnector.pojo; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.math.BigDecimal; 6 | import java.util.Date; 7 | import java.util.List; 8 | 9 | public class Transaction { 10 | 11 | public enum Category { 12 | @SerializedName("receive") 13 | RECEIVE, 14 | @SerializedName("send") 15 | SEND, 16 | @SerializedName("conflicted") 17 | CONFLICTED, 18 | @SerializedName("move") 19 | MOVE; 20 | 21 | /*private String text; 22 | 23 | Category(String text) { 24 | this.text = text; 25 | } 26 | 27 | final String value() { 28 | return this.text; 29 | } 30 | 31 | public String getText() { 32 | return this.text; 33 | } 34 | 35 | public static Category fromString(String text) { 36 | if (text != null) { 37 | for (Category b : Category.values()) { 38 | if (text.equalsIgnoreCase(b.text)) { 39 | return b; 40 | } 41 | } 42 | } 43 | return null; 44 | }*/ 45 | } 46 | 47 | 48 | private BigDecimal fee; 49 | private BigDecimal amount; 50 | private long blockindex; 51 | private Category category; 52 | private long confirmations; 53 | private long time; 54 | private long timereceived; 55 | private long blocktime; 56 | private List walletconflicts; 57 | private List details; 58 | private String address; 59 | private String txid; 60 | private long block; 61 | private String hex; 62 | private String blockhash; 63 | private String account; 64 | private String otheraccount; 65 | private String comment; 66 | private String to; 67 | 68 | 69 | public String getOtheraccount() { 70 | return otheraccount; 71 | } 72 | public Transaction setOtheraccount(String otheraccount) { 73 | this.otheraccount = otheraccount; 74 | return this; 75 | } 76 | public String getComment() { 77 | return comment; 78 | } 79 | public Transaction setComment(String comment) { 80 | this.comment = comment; 81 | return this; 82 | } 83 | public BigDecimal getFee() { 84 | return fee; 85 | } 86 | public Transaction setFee(BigDecimal fee) { 87 | this.fee = fee; 88 | return this; 89 | } 90 | public BigDecimal getAmount() { 91 | return amount; 92 | } 93 | public Transaction setAmount(BigDecimal amount) { 94 | this.amount = amount; 95 | return this; 96 | } 97 | public long getBlockindex() { 98 | return blockindex; 99 | } 100 | public List getWalletconflicts() { 101 | return walletconflicts; 102 | } 103 | public Transaction setWalletconflicts(List walletconflicts) { 104 | this.walletconflicts = walletconflicts; 105 | return this; 106 | } 107 | public Transaction setBlockindex(long blockindex) { 108 | this.blockindex = blockindex; 109 | return this; 110 | } 111 | public Category getCategory() { 112 | return category; 113 | } 114 | public Transaction setCategory(Category category) { 115 | this.category = category; 116 | return this; 117 | } 118 | public long getConfirmations() { 119 | return confirmations; 120 | } 121 | public Transaction setConfirmations(long confirmations) { 122 | this.confirmations = confirmations; 123 | return this; 124 | } 125 | public String getAddress() { 126 | return address; 127 | } 128 | public Transaction setAddress(String address) { 129 | this.address = address; 130 | return this; 131 | } 132 | public String getTxid() { 133 | return txid; 134 | } 135 | public Transaction setTxid(String txid) { 136 | this.txid = txid; 137 | return this; 138 | } 139 | public long getBlock() { 140 | return block; 141 | } 142 | public Transaction setBlock(long block) { 143 | this.block = block; 144 | return this; 145 | } 146 | 147 | public String getHex() { 148 | return hex; 149 | } 150 | public Transaction setHex(String hex) { 151 | this.hex = hex; 152 | return this; 153 | } 154 | public String getBlockhash() { 155 | return blockhash; 156 | } 157 | public Transaction setBlockhash(String blockhash) { 158 | this.blockhash = blockhash; 159 | return this; 160 | } 161 | public List getDetails() { 162 | return details; 163 | } 164 | public Transaction setDetails(List details) { 165 | this.details = details; 166 | return this; 167 | } 168 | public String getAccount() { 169 | return account; 170 | } 171 | public Transaction setAccount(String account) { 172 | this.account = account; 173 | return this; 174 | } 175 | public long getTime() { 176 | return time; 177 | } 178 | public Transaction setTime(long time) { 179 | this.time = time; 180 | return this; 181 | } 182 | public Date getDateTime() { 183 | return new Date(getTime()*1000); 184 | } 185 | 186 | public long getTimereceived() { 187 | return timereceived; 188 | } 189 | public Transaction setTimereceived(long timereceived) { 190 | this.timereceived = timereceived; 191 | return this; 192 | } 193 | public long getBlocktime() { 194 | return blocktime; 195 | } 196 | public Transaction setBlocktime(long blocktime) { 197 | this.blocktime = blocktime; 198 | return this; 199 | } 200 | public String getTo() { 201 | return to; 202 | } 203 | public Transaction setTo(String to) { 204 | this.to = to; 205 | return this; 206 | } 207 | 208 | 209 | } 210 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Loggers configuration 2 | log4j.logger.rpcLogger = stdout, file, applog 3 | 4 | # Console output 5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 6 | log4j.appender.stdout.Target=System.out 7 | log4j.appender.stdout.Threshold=WARN 8 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.stdout.layout.ConversionPattern=%d - %m%n 10 | 11 | #Log to a separate file 12 | log4j.appender.file=org.apache.log4j.RollingFileAppender 13 | log4j.appender.file.File=/var/log/bitcoin-rpc/coin.log 14 | log4j.appender.file.MaxFileSize=50000KB 15 | log4j.appender.file.MaxBackupIndex=50 16 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 17 | log4j.appender.file.layout.ConversionPattern=%d - %m%n 18 | 19 | #Logging to another separate file 20 | log4j.appender.applog=org.apache.log4j.DailyRollingFileAppender 21 | log4j.appender.applog.encoding=UTF-8 22 | log4j.appender.applog.layout=org.apache.log4j.PatternLayout 23 | log4j.appender.applog.layout.ConversionPattern=%d{yyyy:MM:dd_HH:mm} %m%n 24 | log4j.appender.applog.File=/var/log/bitcoin-rpc/daily/day.log 25 | log4j.appender.applog.DatePattern='.'yyyyMM:dd_HH:mm'.log' -------------------------------------------------------------------------------- /src/test/java/com/nitinsurana/litecoinrpcconnector/AppTest.java: -------------------------------------------------------------------------------- 1 | //package com.nitinsurana.litecoinrpcconnector; 2 | // 3 | //import com.google.gson.JsonObject; 4 | //import junit.framework.Test; 5 | //import junit.framework.TestCase; 6 | //import junit.framework.TestSuite; 7 | //import org.junit.Before; 8 | //import org.junit.BeforeClass; 9 | // 10 | ///** 11 | // * Unit test for simple App. 12 | // */ 13 | //public class AppTest 14 | // extends TestCase { 15 | // 16 | // String txnId = "1a89f40ffc8695867827316fe99dbca1c9cc28bc295085b6a5587b4320acd185"; 17 | // 18 | // /** 19 | // * Create the test case 20 | // * 21 | // * @param testName name of the test case 22 | // */ 23 | // public AppTest(String testName) { 24 | // super(testName); 25 | // } 26 | // 27 | // /** 28 | // * @return the suite of tests being tested 29 | // */ 30 | // public static Test suite() { 31 | // return new TestSuite(AppTest.class); 32 | // } 33 | // App app; 34 | // 35 | // @Before 36 | // public void init() throws AuthenticationException { 37 | // final String rpcUser = "Nitin"; 38 | // final String rpcPassword = "magicmaker07"; 39 | // final String rpcHost = "localhost"; 40 | // final String rpcPort = "9332"; 41 | // app = new App(rpcUser, rpcPassword, rpcHost, rpcPort); 42 | //// app=new App(null, null, null, null) 43 | // } 44 | // 45 | // @org.junit.Test 46 | // public void testBackupWallet() throws Exception { 47 | // assertTrue(app.backupWallet("c:/nitin.xzy")); 48 | // assertFalse(app.backupWallet(null)); 49 | // assertFalse(app.backupWallet("")); 50 | // } 51 | // 52 | // @org.junit.Test 53 | // public void testGetRawTransaction() throws Exception { 54 | // assertNotNull(app.getRawTransaction(txnId)); 55 | // } 56 | // 57 | // @org.junit.Test 58 | // public void testDecodeRawTransaction() throws Exception { 59 | //// String txnId = "1a89f40ffc8695867827316fe99dbca1c9cc28bc295085b6a5587b4320acd185"; 60 | // String hex = app.getRawTransaction(txnId); 61 | // assertTrue(app.decodeRawTransaction(txnId) instanceof JsonObject); 62 | // } 63 | // 64 | // @org.junit.Test(expected = RpcInvalidResponseException.class) 65 | // public void testDumpPrivateKey() throws Exception { 66 | // String s = app.dumpPrivateKey("LMNtL3ta9Ff69frtecAuZ1LrW63R7fJ2TBD1"); 67 | // assertNotNull(s); 68 | // //Below should throw Exception 69 | // app.dumpPrivateKey("LMNtL3ta9Fasdff69frtecAuZ1LrW63R7fJ2TBD1"); 70 | // } 71 | // 72 | // /** 73 | // * Rigourous Test :-) 74 | // */ 75 | // public void testApp() { 76 | // assertTrue(true); 77 | // } 78 | //} 79 | --------------------------------------------------------------------------------