bitcoin-client
bitcoin client library for price ticker and wallet
git clone https://9o.is/git/bitcoin-client.git
JsonRPC.scala
(5950B)
1 package inc.pyc.bitcoin
2
3 import net.liftweb._
4 import net.liftweb.json.JsonAST._
5 import scala.math.BigDecimal.int2bigDecimal
6 import scala.math.BigInt.int2bigInt
7
8 sealed trait JsonMessage
9
10 /**
11 * For more information, visit
12 * http://json-rpc.org/wiki/specification
13 */
14 object JsonRPC {
15 implicit val formats = json.DefaultFormats
16
17 // JSON-RPC MESSAGES
18 case class JsonNotification(jsonrpc: String, method: String, params: JArray) extends JsonMessage
19 case class JsonRequest(jsonrpc: String, id: String, method: String, params: JArray) extends JsonMessage
20 case class JsonResponse(jsonrpc: String, id: String, error: Option[JValue], result: Option[JValue]) extends JsonMessage {
21 def either: Either[String, JValue] =
22 (result, error) match {
23 case (Some(result), _) => Right(result)
24 case (_, Some(error)) => Left((error \ "message").extract[String])
25 case _ => Left("Unknown response")
26 }
27 }
28
29 // JsonMessage to JValue implicit
30 implicit def jsonRequestToJValue(r: JsonRequest): JValue = {
31 JObject(List(
32 JField("jsonrpc", JString(r.jsonrpc)),
33 JField("id", JString(r.id)),
34 JField("method", JString(r.method)),
35 JField("params", r.params)))
36 }
37 }
38
39 trait WalletMessage
40 trait NotificationMessage extends WalletMessage
41
42 /**
43 * For more information, visit
44 * https://en.bitcoin.it/wiki/API_reference_(JSON-RPC)
45 */
46 object BitcoinJsonRPC {
47 import JsonRPC._
48
49 // BITCOIN TRANSACTIONS
50 case class RawTransaction(hex: String, txid: String, version: BigDecimal, locktime: BigDecimal, vin: Seq[VIn], vout: Seq[VOut])
51 case class VIn(txid: String, vout: Int, scriptSig: ScriptSig, sequence: BigDecimal)
52 case class VOut(value: BigDecimal, n: BigDecimal, scriptPubKey: ScriptPubKey)
53 case class ScriptSig(asm: String, hex: String)
54 case class ScriptPubKey(asm: String, hex: String, reqSigs: BigDecimal, `type`: String, addresses: Seq[String])
55 case class UnspentTransaction(txid: String, account: String, address: String, amount: BigDecimal, confirmations: BigDecimal)
56 case class SignedTransaction(hex: String, complete: Boolean)
57 case class TransactionNotification(txid: String, account: String, address: String,
58 category: String, amount: BigDecimal, confirmations: BigDecimal, timereceived: BigDecimal)
59
60 // OTHER BITCOIN MESSAGES
61 case class AddressValidation(isvalid: Boolean, address: String,
62 ismine: Option[Boolean], pubkey: Option[String], iscompressed: Option[Boolean])
63
64 // ACTOR MESSAGES
65 // notifications
66 case class ReceivedPayment(txId: String, address: String, amount: BigDecimal, confirmations: BigDecimal) extends NotificationMessage
67
68 // requests
69 sealed trait RequestMessage extends WalletMessage
70 case class CreateRawTransaction(inputs: Seq[(String, BigDecimal)], receivers: Seq[(String, BigDecimal)]) extends RequestMessage
71 case object GetBalance extends RequestMessage
72 case object GetNewAddress extends RequestMessage
73 case class GetRawTransaction(transactionHash: String) extends RequestMessage
74 case class ListUnspentTransactions(minConfirmations: BigDecimal = 1, maxConfirmations: BigDecimal = 999999) extends RequestMessage
75 case class SendRawTransaction(signedTransaction: String) extends RequestMessage
76 case class SignRawTransaction(transaction: String) extends RequestMessage
77 case class WalletPassPhrase(walletPass: String, timeout: BigDecimal) extends RequestMessage
78 case class ValidateAddress(address: String) extends RequestMessage
79
80
81 /**
82 * Constructs JSON-RPC messages out of the existing actor messages related
83 * to Bitcoin's standard rpc-json commands.
84 */
85 object JsonMessage {
86 def createRawTransaction(inputs: Seq[(String, BigDecimal)], receivers: Seq[(String, BigDecimal)]) =
87 JsonRequest("1.0", Utils.getUUID, "createrawtransaction", JArray(
88 inputs.map(i => JObject(List("txid" -> i._1, "vout" -> i._2))).toList ::
89 receivers.map(r => JObject(List(r._1 -> r._2))).toList))
90
91 def getBalance =
92 JsonRequest("1.0", Utils.getUUID, "getbalance", Seq())
93
94 def getNewAddress =
95 JsonRequest("1.0", Utils.getUUID, "getnewaddress", Seq())
96
97 def getRawTransaction(transactionHash: String) =
98 JsonRequest("1.0", Utils.getUUID, "getrawtransaction", JArray(List(transactionHash, 1)))
99
100 def listUnspentTransactions(minConfirmations: BigDecimal, maxConfirmations: BigDecimal, addresses: Seq[String] = Seq.empty[String]) = {
101 val params =
102 if (addresses.isEmpty) JArray(List(minConfirmations, maxConfirmations))
103 else JArray(List(minConfirmations, maxConfirmations, addresses))
104 JsonRequest("1.0", Utils.getUUID, "listunspent", params)
105 }
106
107 def sendRawTransaction(signedTransaction: String) =
108 JsonRequest("1.0", Utils.getUUID, "sendrawtransaction", Seq(signedTransaction))
109
110 def signRawTransaction(transaction: String) =
111 JsonRequest("1.0", Utils.getUUID, "signrawtransaction", Seq(transaction))
112
113 def walletPassPhrase(walletPass: String, timeout: BigDecimal) =
114 JsonRequest("1.0", Utils.getUUID, "walletpassphrase", JArray(List(walletPass, timeout)))
115
116 def validateAddress(address: String) =
117 JsonRequest("1.0", Utils.getUUID, "validateaddress", Seq(address))
118 }
119
120 private object Utils {
121 def getUUID = java.util.UUID.randomUUID.toString
122 }
123
124 // JValue implicits
125 implicit def intToJInt(i: Int): JInt = JInt(i)
126 implicit def stringToJString(s: String): JString = JString(s)
127 implicit def stringToJField(m: (String, String)): JField = JField(m._1, m._2)
128
129 // BigDecimal to JValue implicits
130 implicit def bigdecimalToJField(m: (String, BigDecimal)): JField = JField(m._1, m._2)
131 implicit def bigdecimalToJDouble(d: BigDecimal): JDouble = JDouble(d.doubleValue)
132
133 // Scala collections to JArray implicits
134 implicit def listToJArray(l: List[JValue]): JArray = JArray(l)
135 implicit def seqStringToJArray(l: Seq[String]): JArray = JArray(l.map(JString).toList)
136 }