zcashrpc/zcash_client.go

160 lines
5.1 KiB
Go
Raw Normal View History

2019-12-01 21:24:59 +00:00
package zcashrpc
2019-08-23 20:51:21 +00:00
import (
"bytes"
"encoding/base64"
"encoding/json"
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
"git.openprivacy.ca/openprivacy/libricochet-go/log"
"io/ioutil"
"net"
"net/http"
"strconv"
2019-08-23 20:51:21 +00:00
)
2019-12-01 21:24:59 +00:00
// ZcashClient defines an interface for any zcash client to present.
2019-08-23 20:51:21 +00:00
type ZcashClient interface {
GetTotalBalance(minConfirmations int) (float64, error)
2019-09-14 01:13:29 +00:00
GetTransaction(string) (Transaction, error)
2019-12-20 22:10:18 +00:00
ListAddresses() ([]string, error)
ListReceivedTransactionsByAddress(string) ([]ZcashTransaction, error)
GetBlock(int) (Block, error)
2019-12-01 21:24:59 +00:00
SendOne(string, string, string, float64) ([]byte, error)
ValidateAddress(address string) (ZValidateAddressResponse, error)
}
type zcashClient struct {
client http.Client
address string
auth string
2019-08-23 20:51:21 +00:00
}
2019-12-01 21:24:59 +00:00
// NewLocalClient creates a new Zcash rpc client over a local address
func NewLocalClient(username, password string) ZcashClient {
zc := new(zcashClient)
zc.address = "127.0.0.1:8232"
zc.client = http.Client{
Transport: &http.Transport{
Dial: func(network, addr string) (net.Conn, error) {
conn, err := net.Dial("tcp", zc.address)
return conn, err
},
},
}
zc.auth = base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
return zc
2019-08-23 20:51:21 +00:00
}
2019-12-01 21:24:59 +00:00
// NewOnionClient creates a new Zcash rpc client over an onion address
func NewOnionClient(onion string, username, password string, acn connectivity.ACN) ZcashClient {
zc := new(zcashClient)
zc.address = onion + ".onion:9878"
2019-08-23 20:51:21 +00:00
zc.client = http.Client{
Transport: &http.Transport{
Dial: func(network, addr string) (net.Conn, error) {
conn, _, err := acn.Open(onion)
return conn, err
},
},
}
zc.auth = base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
return zc
}
// Return the total value of funds stored in the nodes wallet. Set the minimum number of confirmations a private or transparent transaction must have in order to be included in the balance. Use 0 to count unconfirmed transactions.
func (zc *zcashClient) GetTotalBalance(minConfirmations int) (float64, error) {
body, err := zc.sendRequest(NewZGetTotalBalance(minConfirmations))
var totalBalance ZGetTotalBalanceResponse
if err == nil {
result := &ZcashResult{Result: &totalBalance}
err = json.Unmarshal(body, &result)
}
return strconv.ParseFloat(totalBalance.Private, 64)
}
// GetTransaction returns a specific transaction given an id
func (zc *zcashClient) GetBlock(id int) (Block, error) {
body, err := zc.sendRequest(NewGetBlock(id))
block := Block{}
if err == nil {
result := &ZcashResult{Result: &block}
err = json.Unmarshal(body, &result)
}
return block, err
}
2019-12-01 21:24:59 +00:00
// GetTransaction returns a specific transaction given an id
func (zc *zcashClient) GetTransaction(id string) (Transaction, error) {
body, err := zc.sendRequest(NewGetTransaction(id))
transaction := Transaction{}
if err == nil {
result := &ZcashResult{Result: &transaction}
err = json.Unmarshal(body, &result)
2019-09-14 01:13:29 +00:00
}
2019-12-01 21:24:59 +00:00
return transaction, err
}
2019-12-20 22:10:18 +00:00
// Returns a list of all the zaddrs in this nodes wallet for which you have a spending key.
func (zc *zcashClient) ListAddresses() ([]string, error) {
body, err := zc.sendRequest(NewZListAddresses())
var addresses []string
if err == nil {
result := &ZcashResult{Result: &addresses}
err = json.Unmarshal(body, &result)
}
return addresses, err
}
2019-12-01 21:24:59 +00:00
// ListReceivedTransactionsByAddress returns all the transactions received by a given zcash address
func (zc *zcashClient) ListReceivedTransactionsByAddress(address string) ([]ZcashTransaction, error) {
body, err := zc.sendRequest(NewZListReceivedByAddress(address))
var transactions []ZcashTransaction
if err == nil {
result := &ZcashResult{Result: &transactions}
err = json.Unmarshal(body, &result)
2019-09-14 01:13:29 +00:00
}
for i := range transactions {
transactions[i].Address = address
}
2019-12-01 21:24:59 +00:00
return transactions, err
}
// SendOne uses z_sendmany to send a single payment to the given address from the given fromAddress
func (zc *zcashClient) SendOne(fromAddress string, toaddress string, memo string, amount float64) ([]byte, error) {
jsonStr := NewZSendMany(fromAddress, []ZcashAmount{NewZcashAmount(toaddress, memo, amount)})
log.Debugf("Zcash SendMany %s", jsonStr)
return zc.sendRequest(jsonStr)
}
// ValidateAddress returns the result of a z_validateaddress call
func (zc *zcashClient) ValidateAddress(address string) (ZValidateAddressResponse, error) {
body, err := zc.sendRequest(NewZValidateAddress(address))
var validation ZValidateAddressResponse
if err == nil {
result := &ZcashResult{Result: &validation}
log.Debugf("Result: %s", body)
err = json.Unmarshal(body, &result)
2019-09-14 01:13:29 +00:00
}
2019-12-01 21:24:59 +00:00
return validation, err
2019-09-14 01:13:29 +00:00
}
2019-12-01 21:24:59 +00:00
func (zc *zcashClient) sendRequest(jsonStr []byte) ([]byte, error) {
req, err := http.NewRequest("POST", "http://"+zc.address, bytes.NewBuffer(jsonStr))
2019-08-23 20:51:21 +00:00
if err != nil {
return nil, err
}
req.Header.Add("Authorization", "Basic "+zc.auth)
log.Debugf("Sending request to zcash server %v", req)
resp, err := zc.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
log.Debugf("Got response from zcash server %s", body)
2019-12-01 21:24:59 +00:00
return body, nil
2019-08-23 20:51:21 +00:00
}