decred.org/dcrdex@v1.0.5/client/asset/zec/shielded_rpc.go (about) 1 // This code is available on the terms of the project LICENSE.md file, 2 // also available online at https://blueoakcouncil.org/license/1.0.0. 3 4 package zec 5 6 import ( 7 "decred.org/dcrdex/dex" 8 "github.com/btcsuite/btcd/btcutil" 9 ) 10 11 const ( 12 methodZGetAddressForAccount = "z_getaddressforaccount" 13 methodZListUnifiedReceivers = "z_listunifiedreceivers" 14 methodZListAccounts = "z_listaccounts" 15 methodZGetNewAccount = "z_getnewaccount" 16 methodZGetBalanceForAccount = "z_getbalanceforaccount" 17 methodZSendMany = "z_sendmany" 18 methodZValidateAddress = "z_validateaddress" 19 methodZGetOperationResult = "z_getoperationresult" 20 methodZGetNotesCount = "z_getnotescount" 21 methodZListUnspent = "z_listunspent" 22 ) 23 24 type zListAccountsResult struct { 25 Number uint32 `json:"account"` 26 Addresses []struct { 27 Diversifier uint32 `json:"diversifier"` 28 UnifiedAddr string `json:"ua"` 29 } `json:"addresses"` 30 } 31 32 // z_listaccounts 33 func zListAccounts(c rpcCaller) (accts []zListAccountsResult, err error) { 34 return accts, c.CallRPC(methodZListAccounts, nil, &accts) 35 } 36 37 // z_getnewaccount 38 func zGetNewAccount(c rpcCaller) (uint32, error) { 39 var res struct { 40 Number uint32 `json:"account"` 41 } 42 if err := c.CallRPC(methodZGetNewAccount, nil, &res); err != nil { 43 return 0, err 44 } 45 return res.Number, nil 46 } 47 48 type zGetAddressForAccountResult struct { 49 Account uint32 `json:"account"` 50 DiversifierIndex uint32 `json:"diversifier_index"` 51 ReceiverTypes []string `json:"receiver_types"` 52 Address string `json:"address"` 53 } 54 55 // z_getaddressforaccount account ( ["receiver_type", ...] diversifier_index ) 56 func zGetAddressForAccount(c rpcCaller, acctNumber uint32, addrTypes []string) (unified *zGetAddressForAccountResult, err error) { 57 return unified, c.CallRPC(methodZGetAddressForAccount, []any{acctNumber, addrTypes}, &unified) 58 } 59 60 type unifiedReceivers struct { 61 Transparent string `json:"p2pkh"` 62 Orchard string `json:"orchard"` 63 Sapling string `json:"sapling,omitempty"` 64 } 65 66 // z_listunifiedreceivers unified_address 67 func zGetUnifiedReceivers(c rpcCaller, unifiedAddr string) (receivers *unifiedReceivers, err error) { 68 return receivers, c.CallRPC(methodZListUnifiedReceivers, []any{unifiedAddr}, &receivers) 69 } 70 71 type valZat struct { // Ignoring similar fields for Sapling, Transparent... 72 ValueZat uint64 `json:"valueZat"` 73 } 74 75 type poolBalances struct { 76 Orchard uint64 `json:"orchard"` 77 Transparent uint64 `json:"transparent"` 78 Sapling uint64 `json:"sapling"` 79 } 80 81 type zBalancePools struct { 82 Orchard valZat `json:"orchard"` 83 Transparent valZat `json:"transparent"` 84 Sapling valZat `json:"sapling"` 85 } 86 87 type zAccountBalance struct { 88 Pools zBalancePools `json:"pools"` 89 } 90 91 func zGetBalanceForAccount(c rpcCaller, acct uint32, confs int) (*poolBalances, error) { 92 var res zAccountBalance 93 return &poolBalances{ 94 Orchard: res.Pools.Orchard.ValueZat, 95 Transparent: res.Pools.Transparent.ValueZat, 96 Sapling: res.Pools.Sapling.ValueZat, 97 }, c.CallRPC(methodZGetBalanceForAccount, []any{acct, confs}, &res) 98 } 99 100 type zNotesCount struct { 101 Sprout uint32 `json:"sprout"` 102 Sapling uint32 `json:"sapling"` 103 Orchard uint32 `json:"orchard"` 104 } 105 106 func zGetNotesCount(c rpcCaller) (counts *zNotesCount, _ error) { 107 return counts, c.CallRPC(methodZGetNotesCount, []any{minOrchardConfs}, &counts) 108 } 109 110 type zValidateAddressResult struct { 111 IsValid bool `json:"isvalid"` 112 Address string `json:"address"` 113 AddressType string `json:"address_type"` 114 IsMine bool `json:"ismine"` 115 // PayingKey string `json:"payingkey"` 116 // TransmissionKey string `json:"transmissionkey"` 117 Diversifier string `json:"diversifier"` // sapling 118 DiversifiedTransmissionkey string `json:"diversifiedtransmissionkey"` // sapling 119 } 120 121 // z_validateaddress "address" 122 func zValidateAddress(c rpcCaller, addr string) (res *zValidateAddressResult, err error) { 123 return res, c.CallRPC(methodZValidateAddress, []any{addr}, &res) 124 } 125 126 type zSendManyRecipient struct { 127 Address string `json:"address"` 128 Amount float64 `json:"amount"` 129 Memo string `json:"memo,omitempty"` 130 } 131 132 func singleSendManyRecipient(addr string, amt uint64) []*zSendManyRecipient { 133 return []*zSendManyRecipient{ 134 { 135 Address: addr, 136 Amount: btcutil.Amount(amt).ToBTC(), 137 }, 138 } 139 } 140 141 // When sending using z_sendmany and you're not sending a shielded tx to the 142 // same pool, you must specify a lower privacy policy. 143 type privacyPolicy string 144 145 const ( 146 FullPrivacy privacyPolicy = "FullPrivacy" 147 AllowRevealedRecipients privacyPolicy = "AllowRevealedRecipients" 148 AllowRevealedAmounts privacyPolicy = "AllowRevealedAmounts" 149 AllowRevealedSenders privacyPolicy = "AllowRevealedSenders" 150 AllowLinkingAccountAddresses privacyPolicy = "AllowLinkingAccountAddresses" 151 NoPrivacy privacyPolicy = "NoPrivacy" 152 ) 153 154 // z_sendmany "fromaddress" [{"address":... ,"amount":...},...] ( minconf ) ( fee ) ( privacyPolicy ) 155 func zSendMany(c rpcCaller, fromAddress string, recips []*zSendManyRecipient, priv privacyPolicy) (operationID string, err error) { 156 const minConf = 1 157 return operationID, c.CallRPC(methodZSendMany, []any{fromAddress, recips, minConf, nil, priv}, &operationID) 158 } 159 160 type opResult struct { 161 TxID string `json:"txid"` 162 } 163 164 type operationStatus struct { 165 ID string `json:"id"` 166 Status string `json:"status"` // "success", "failed", others? 167 CreationTime int64 `json:"creation_time"` 168 Error *struct { // nil for success 169 Code int32 `json:"code"` 170 Message string `json:"message"` 171 } `json:"error" ` 172 Result *opResult `json:"result"` 173 ExecutionSeconds float64 `json:"execution_secs"` 174 Method string `json:"method"` 175 Params struct { 176 FromAddress string `json:"fromaddress"` 177 Amounts []struct { 178 Address string `json:"address"` 179 Amount float64 `json:"amount"` 180 } `json:"amounts"` 181 MinConf uint32 `json:"minconf"` 182 Fee float64 `json:"fee"` 183 } `json:"params"` 184 } 185 186 // ErrEmptyOpResults is returned when z_getoperationresult returns an empty 187 // array for the specified operation ID. This appears to be normal in some or 188 // all cases when the result is not yet ready. 189 const ErrEmptyOpResults = dex.ErrorKind("no z_getoperationstatus results") 190 191 // z_getoperationresult (["operationid", ... ]) 192 func zGetOperationResult(c rpcCaller, operationID string) (s *operationStatus, err error) { 193 var res []*operationStatus 194 if err := c.CallRPC(methodZGetOperationResult, []any{[]string{operationID}}, &res); err != nil { 195 return nil, err 196 } 197 if len(res) == 0 { 198 return nil, ErrEmptyOpResults 199 } 200 return res[0], nil 201 } 202 203 type zListUnspentResult struct { 204 TxID string `json:"txid"` 205 Pool string `json:"pool"` 206 JSIndex uint32 `json:"jsindex"` 207 JSOutindex uint32 `json:"jsoutindex"` 208 Outindex uint32 `json:"outindex"` 209 Confirmations uint64 `json:"confirmations"` 210 Spendable bool `json:"spendable"` 211 Account uint32 `json:"account"` 212 Address string `json:"address"` 213 Amount float64 `json:"amount"` 214 Memo string `json:"memo"` 215 MemoStr string `json:"memoStr"` 216 Change bool `json:"change"` 217 } 218 219 // z_listunspent ( minconf maxconf includeWatchonly ["zaddr",...] asOfHeight ) 220 func zListUnspent(c rpcCaller) ([]*zListUnspentResult, error) { 221 var res []*zListUnspentResult 222 return res, c.CallRPC(methodZListUnspent, []any{minOrchardConfs}, &res) 223 }