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  }