-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathbtcrpc.go
194 lines (165 loc) · 4.09 KB
/
btcrpc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
Package btcrpc implements RPC methods to interact with the bitcoin node bitcoind.
See informations in the pages link below about Bitcoin development.
https://bitcoin.org/en/development
*/
package btcrpc
import (
"encoding/json"
"errors"
jsonrpc "github.com/KeisukeYamashita/go-jsonrpc"
)
/*
BasicAuth is for Bitcoin Node supports basic auth.
Some nodes do not need this. In that case, leave these blank.
*/
type BasicAuth struct {
Username string
Password string
}
/*
RPCClient ...
*/
type RPCClient struct {
*jsonrpc.RPCClient
}
/*
RPCer ...
*/
type RPCer interface {
GetBlockHash(height int32) (string, error)
}
/*
NewRPCClient creates JSONRPC clients for your bitcoin node.
*/
func NewRPCClient(endpoint string, basicAuth *BasicAuth) *RPCClient {
c := new(RPCClient)
c.RPCClient = jsonrpc.NewRPCClient(endpoint)
c.RPCClient.SetBasicAuth(basicAuth.Username, basicAuth.Password)
return c
}
/*
GetNewAddress gets new address associated with the account name given.
If the account name is blank(nil), if will also returns a addresss with no associated account.
*/
func (c *RPCClient) GetNewAddress(account string) (string, error) {
resp, err := c.RPCClient.Call("getnewaddress", account)
if err != nil {
return "", err
}
if resp.Error != nil {
return "", errors.New(resp.Error.Message)
}
var address string
resp.GetObject(&address)
return address, nil
}
/*
GetBalance gets the balance of the address.
It is only possible to get the balance which is made by this node, otherwise it will return 0.00.
*/
func (c *RPCClient) GetBalance(address string) (float32, error) {
resp, err := c.RPCClient.Call("getbalance", address)
if err != nil {
return -1, err
}
if resp.Error != nil {
return -1, errors.New(resp.Error.Message)
}
var balance float32
resp.GetObject(&balance)
return balance, nil
}
/*
GetBlockHash gets the block hash(id) associated with the block height.
*/
func (c *RPCClient) GetBlockHash(height int32) (string, error) {
resp, err := c.RPCClient.Call("getblockhash", height)
if err != nil {
return "", err
}
if resp.Error != nil {
return "", errors.New(resp.Error.Message)
}
var hash string
resp.GetObject(&hash)
return hash, nil
}
/*
GetBlock gets the block information associated with the block hash(id).
It contains a lot of infos about transactions.
*/
func (c *RPCClient) GetBlock(h string) (*Block, error) {
resp, err := c.RPCClient.Call("getblock", h)
if err != nil {
return nil, err
}
if resp.Error != nil {
return nil, errors.New(resp.Error.Message)
}
jsonData, err := json.Marshal(resp.Result)
if err != nil {
return nil, err
}
var block Block
json.Unmarshal(jsonData, &block)
return &block, nil
}
/*
GetBlockCount gets the latest block height.
Note that The methods name is "Count" not "Height".
*/
func (c *RPCClient) GetBlockCount() (int32, error) {
resp, err := c.RPCClient.Call("getblockcount")
if err != nil {
return -1, err
}
if resp.Error != nil {
return -1, errors.New(resp.Error.Message)
}
var count int32
resp.GetObject(&count)
return count, nil
}
/*
GetRawTransactions gets the raw transactions associated with the transaction hashes(ids).
*/
func (c *RPCClient) GetRawTransactions(txids []string) ([]string, error) {
rawTxs := make([]string, len(txids))
for i, txid := range txids {
resp, err := c.RPCClient.Call("getrawtransaction", txid)
if err != nil {
return nil, err
}
if resp.Error != nil {
return nil, errors.New(resp.Error.Message)
}
var rawTx string
resp.GetObject(&rawTx)
rawTxs[i] = rawTx
}
return rawTxs, nil
}
/*
DecodeRawTransactions decodes the raw transactions to human readable transactions.
*/
func (c *RPCClient) DecodeRawTransactions(rawTxs []string) ([]*Transaction, error) {
txs := make([]*Transaction, len(rawTxs))
for i, rawTx := range rawTxs {
resp, err := c.RPCClient.Call("decoderawtransaction", rawTx)
if err != nil {
return nil, err
}
if resp.Error != nil {
return nil, errors.New(resp.Error.Message)
}
jsonData, err := json.Marshal(resp.Result)
if err != nil {
return nil, err
}
var tx Transaction
json.Unmarshal(jsonData, &tx)
txs[i] = &tx
}
return txs, nil
}