From e9b8ab3b66f9324786f3511e402390216e6534cf Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Fri, 20 Dec 2019 14:10:18 -0800 Subject: [PATCH 1/2] Adding ListAddresses function --- api.go | 9 +++++++++ testing/zcash_client_integration_test.go | 16 +++++++++++++++- zcash_client.go | 14 +++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/api.go b/api.go index ea326c0..6c2beab 100644 --- a/api.go +++ b/api.go @@ -11,6 +11,7 @@ type Method string const ( GetTransaction Method = "gettransaction" + ZListAddresses = "z_listaddresses" ZListReceivedByAddress = "z_listreceivedbyaddress" ZSendMany = "z_sendmany" ZValidateAddress = "z_validateaddress" @@ -46,6 +47,14 @@ func NewZValidateAddress(address string) []byte { return data } +// NewZListAddresses constructs a properly formatted z_listaddresses request +func NewZListAddresses() []byte { + request := setupZcashRequest() + request.Method = ZListAddresses + data, _ := json.Marshal(request) + return data +} + // NewZListReceivedByAddress constructs a properly formatted z_listreceivedbyaddress request func NewZListReceivedByAddress(fromAddress string) []byte { request := setupZcashRequest() diff --git a/testing/zcash_client_integration_test.go b/testing/zcash_client_integration_test.go index 954ee24..b32f648 100644 --- a/testing/zcash_client_integration_test.go +++ b/testing/zcash_client_integration_test.go @@ -1,9 +1,9 @@ package zcash2cwtch import ( - "cwtch.im/zcash2cwtch" "encoding/json" "git.openprivacy.ca/openprivacy/libricochet-go/log" + "git.openprivacy.ca/openprivacy/zcashrpc" "io/ioutil" "testing" ) @@ -13,6 +13,20 @@ type ZcashConfig struct { Password string `json:"password"` } +func TestListAddresses(t *testing.T) { + log.SetLevel(log.LevelDebug) + configFile, _ := ioutil.ReadFile("config.json") + config := ZcashConfig{} + _ = json.Unmarshal(configFile, &config) + + zc := zcashrpc.NewLocalClient(config.Username, config.Password) + result, err := zc.ListAddresses() + t.Logf("Result: %v %v", result, err) + if len(result) == 0 { + t.Errorf("Failed to list zaddresses") + } +} + func TestNewZValidateAddress(t *testing.T) { log.SetLevel(log.LevelDebug) configFile, _ := ioutil.ReadFile("config.json") diff --git a/zcash_client.go b/zcash_client.go index 1300f29..7a1cdcf 100644 --- a/zcash_client.go +++ b/zcash_client.go @@ -13,8 +13,9 @@ import ( // ZcashClient defines an interface for any zcash client to present. type ZcashClient interface { - ListReceivedTransactionsByAddress(string) ([]ZcashTransaction, error) GetTransaction(string) (Transaction, error) + ListAddresses() ([]string, error) + ListReceivedTransactionsByAddress(string) ([]ZcashTransaction, error) SendOne(string, string, string, float64) ([]byte, error) ValidateAddress(address string) (ZValidateAddressResponse, error) } @@ -68,6 +69,17 @@ func (zc *zcashClient) GetTransaction(id string) (Transaction, error) { return transaction, err } +// Returns a list of all the zaddrs in this node’s 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 +} + // 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)) From d663d04e4e426964c31b06971bbd8bd88b64cfa3 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Sat, 21 Dec 2019 15:00:54 -0800 Subject: [PATCH 2/2] Adding getTotalBalance and Enhancing received transactions --- api.go | 20 +++++++++++++++ testing/zcash_client_integration_test.go | 32 ++++++++++++++++++++++++ zcash_client.go | 16 ++++++++++++ 3 files changed, 68 insertions(+) diff --git a/api.go b/api.go index 6c2beab..91e71ce 100644 --- a/api.go +++ b/api.go @@ -11,6 +11,7 @@ type Method string const ( GetTransaction Method = "gettransaction" + ZGetTotalBalance = "z_gettotalbalance" ZListAddresses = "z_listaddresses" ZListReceivedByAddress = "z_listreceivedbyaddress" ZSendMany = "z_sendmany" @@ -55,6 +56,15 @@ func NewZListAddresses() []byte { return data } +// NewZGetTotalBalance constructs a properly formatted z_gettotalbalance request +func NewZGetTotalBalance(minConfirmations int) []byte { + request := setupZcashRequest() + request.Method = ZGetTotalBalance + request.Params = append(request.Params, minConfirmations) + data, _ := json.Marshal(request) + return data +} + // NewZListReceivedByAddress constructs a properly formatted z_listreceivedbyaddress request func NewZListReceivedByAddress(fromAddress string) []byte { request := setupZcashRequest() @@ -99,6 +109,9 @@ type ZcashTransaction struct { Memo Hex `json:"memo"` Change bool `json:"change"` OutIndex int `json:"outindex"` + + // The following parameters are not provided by the zcash node + Address string `json:"address"` } // ZcashResult represents the result of a zcash operation. Result can be any one of a number of defined types. @@ -115,3 +128,10 @@ type ZValidateAddressResponse struct { Diversifier Hex `json:"diversifier"` DiversifiedTransmissionKey Hex `json:"diversifiedtransmissionkey"` } + +// ZGetTotalBalanceResponse encapsulates the result returned from a z_gettotalbalance request +type ZGetTotalBalanceResponse struct { + Transparent string `json:"transparent"` + Private string `json:"private"` + Total string `json:"total"` +} diff --git a/testing/zcash_client_integration_test.go b/testing/zcash_client_integration_test.go index b32f648..9609f29 100644 --- a/testing/zcash_client_integration_test.go +++ b/testing/zcash_client_integration_test.go @@ -13,6 +13,38 @@ type ZcashConfig struct { Password string `json:"password"` } +func TestGetTotalBalance(t *testing.T) { + log.SetLevel(log.LevelDebug) + configFile, _ := ioutil.ReadFile("config.json") + config := ZcashConfig{} + _ = json.Unmarshal(configFile, &config) + + zc := zcashrpc.NewLocalClient(config.Username, config.Password) + result, err := zc.GetTotalBalance(1) + t.Logf("Result: %v %v", result, err) + if err != nil { + t.Errorf("Failed to get total balance: %v %v", result, err) + } +} + +func TestListTransactions(t *testing.T) { + log.SetLevel(log.LevelDebug) + configFile, _ := ioutil.ReadFile("config.json") + config := ZcashConfig{} + _ = json.Unmarshal(configFile, &config) + + zc := zcashrpc.NewLocalClient(config.Username, config.Password) + result, err := zc.ListReceivedTransactionsByAddress("zs1pjv7eneq9jshw0eyywpruv2cetl74sh84ymdnyv4c4vg8vl5k2qmlv0n7ye77g49lhqkg75v52f") + t.Logf("Result: %v %v", result, err) + if len(result) == 0 { + t.Errorf("Failed to list transactions") + } else { + for _, transaction := range result { + t.Logf("Transaction: %v", transaction) + } + } +} + func TestListAddresses(t *testing.T) { log.SetLevel(log.LevelDebug) configFile, _ := ioutil.ReadFile("config.json") diff --git a/zcash_client.go b/zcash_client.go index 7a1cdcf..a3054b4 100644 --- a/zcash_client.go +++ b/zcash_client.go @@ -9,10 +9,12 @@ import ( "io/ioutil" "net" "net/http" + "strconv" ) // ZcashClient defines an interface for any zcash client to present. type ZcashClient interface { + GetTotalBalance(minConfirmations int) (float64, error) GetTransaction(string) (Transaction, error) ListAddresses() ([]string, error) ListReceivedTransactionsByAddress(string) ([]ZcashTransaction, error) @@ -58,6 +60,17 @@ func NewOnionClient(onion string, username, password string, acn connectivity.AC return zc } +// Return the total value of funds stored in the node’s 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) GetTransaction(id string) (Transaction, error) { body, err := zc.sendRequest(NewGetTransaction(id)) @@ -88,6 +101,9 @@ func (zc *zcashClient) ListReceivedTransactionsByAddress(address string) ([]Zcas result := &ZcashResult{Result: &transactions} err = json.Unmarshal(body, &result) } + for i := range transactions { + transactions[i].Address = address + } return transactions, err }