decred.org/dcrdex@v1.0.5/client/asset/dcr/wallet.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 dcr
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"decred.org/dcrdex/client/asset"
    11  	"decred.org/dcrdex/dex"
    12  	walletjson "decred.org/dcrwallet/v5/rpc/jsonrpc/types"
    13  	"decred.org/dcrwallet/v5/wallet"
    14  	"github.com/decred/dcrd/chaincfg/chainhash"
    15  	"github.com/decred/dcrd/chaincfg/v3"
    16  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    17  	"github.com/decred/dcrd/dcrutil/v4"
    18  	chainjson "github.com/decred/dcrd/rpc/jsonrpc/types/v4"
    19  	"github.com/decred/dcrd/txscript/v4/stdaddr"
    20  	"github.com/decred/dcrd/wire"
    21  )
    22  
    23  // WalletConstructor defines a function that can be invoked to create a custom
    24  // implementation of the Wallet interface.
    25  type WalletConstructor func(settings map[string]string, chainParams *chaincfg.Params, logger dex.Logger) (Wallet, error)
    26  
    27  // customWalletConstructors are functions for setting up custom implementations
    28  // of the Wallet interface that may be used by the ExchangeWallet instead of the
    29  // default rpcWallet implementation.
    30  var customWalletConstructors = map[string]WalletConstructor{}
    31  
    32  // RegisterCustomWallet registers a function that should be used in creating a
    33  // Wallet implementation that the ExchangeWallet of the specified type will use
    34  // in place of the default rpcWallet implementation. External consumers can use
    35  // this function to provide alternative Wallet implementations, and must do so
    36  // before attempting to create an ExchangeWallet instance of this type. It'll
    37  // panic if callers try to register a wallet twice.
    38  func RegisterCustomWallet(constructor WalletConstructor, def *asset.WalletDefinition) {
    39  	for _, availableWallets := range WalletInfo.AvailableWallets {
    40  		if def.Type == availableWallets.Type {
    41  			panic(fmt.Sprintf("wallet type (%q) already registered", def.Type))
    42  		}
    43  	}
    44  	customWalletConstructors[def.Type] = constructor
    45  	WalletInfo.AvailableWallets = append(WalletInfo.AvailableWallets, def)
    46  }
    47  
    48  type TipChangeCallback func(context.Context, *chainhash.Hash, int64, error)
    49  
    50  // BlockHeader is a wire.BlockHeader with the addition of a MedianTime field.
    51  // Implementations must fill in the MedianTime field when returning a
    52  // BlockHeader.
    53  type BlockHeader struct {
    54  	*wire.BlockHeader
    55  	MedianTime    int64
    56  	Confirmations int64
    57  	NextHash      *chainhash.Hash
    58  }
    59  
    60  // AddressInfo is the source account and branch info for an address.
    61  type AddressInfo struct {
    62  	Account string
    63  	Branch  uint32
    64  }
    65  
    66  type XCWalletAccounts struct {
    67  	PrimaryAccount string
    68  	UnmixedAccount string
    69  	TradingAccount string
    70  }
    71  
    72  // ListTransactionsResult is similar to the walletjson.ListTransactionsResult,
    73  // but most fields omitted.
    74  type ListTransactionsResult struct {
    75  	TxID       string
    76  	BlockIndex *int64
    77  	BlockTime  int64
    78  	// Send set to true means that the inputs of the transaction were
    79  	// controlled by the wallet.
    80  	Send   bool `json:"send"`
    81  	Fee    *float64
    82  	TxType *walletjson.ListTransactionsTxType
    83  }
    84  
    85  // Wallet defines methods that the ExchangeWallet uses for communicating with
    86  // a Decred wallet and blockchain.
    87  type Wallet interface {
    88  	// Connect establishes a connection to the wallet.
    89  	Connect(ctx context.Context) error
    90  	// Disconnect shuts down access to the wallet.
    91  	Disconnect()
    92  	// SpvMode returns true if the wallet is connected to the Decred
    93  	// network via SPV peers.
    94  	SpvMode() bool
    95  	// Accounts returns the names of the accounts for use by the exchange
    96  	// wallet.
    97  	Accounts() XCWalletAccounts
    98  	// AddressInfo returns information for the provided address. It is an error
    99  	// if the address is not owned by the wallet.
   100  	AddressInfo(ctx context.Context, address string) (*AddressInfo, error)
   101  	// AccountOwnsAddress checks if the provided address belongs to the
   102  	// specified account.
   103  	AccountOwnsAddress(ctx context.Context, addr stdaddr.Address, acctName string) (bool, error)
   104  	// AccountBalance returns the balance breakdown for the specified account.
   105  	AccountBalance(ctx context.Context, confirms int32, acctName string) (*walletjson.GetAccountBalanceResult, error)
   106  	// LockedOutputs fetches locked outputs for the Wallet.
   107  	LockedOutputs(ctx context.Context, acctName string) ([]chainjson.TransactionInput, error)
   108  	// Unspents fetches unspent outputs for the Wallet.
   109  	Unspents(ctx context.Context, acctName string) ([]*walletjson.ListUnspentResult, error)
   110  	// LockUnspent locks or unlocks the specified outpoint.
   111  	LockUnspent(ctx context.Context, unlock bool, ops []*wire.OutPoint) error
   112  	// UnspentOutput returns information about an unspent tx output, if found
   113  	// and unspent. Use wire.TxTreeUnknown if the output tree is unknown, the
   114  	// correct tree will be returned if the unspent output is found.
   115  	// This method is only guaranteed to return results for outputs that pay to
   116  	// the wallet, although wallets connected to a full node may return results
   117  	// for non-wallet outputs. Returns asset.CoinNotFoundError if the unspent
   118  	// output cannot be located.
   119  	UnspentOutput(ctx context.Context, txHash *chainhash.Hash, index uint32, tree int8) (*TxOutput, error)
   120  	// ExternalAddress returns a new external address.
   121  	ExternalAddress(ctx context.Context, acctName string) (stdaddr.Address, error)
   122  	// InternalAddress returns a change address from the Wallet.
   123  	InternalAddress(ctx context.Context, acctName string) (stdaddr.Address, error)
   124  	// SignRawTransaction signs the provided transaction. SignRawTransaction
   125  	// is not used for redemptions, so previous outpoints and scripts should
   126  	// be known by the wallet.
   127  	// SignRawTransaction should not mutate the input transaction.
   128  	SignRawTransaction(context.Context, *wire.MsgTx) (*wire.MsgTx, error)
   129  	// SendRawTransaction broadcasts the provided transaction to the Decred
   130  	// network.
   131  	SendRawTransaction(ctx context.Context, tx *wire.MsgTx, allowHighFees bool) (*chainhash.Hash, error)
   132  	// GetBlockHeader generates a *BlockHeader for the specified block hash. The
   133  	// returned block header is a wire.BlockHeader with the addition of the
   134  	// block's median time.
   135  	GetBlockHeader(ctx context.Context, blockHash *chainhash.Hash) (*BlockHeader, error)
   136  	// GetBlock returns the *wire.MsgBlock.
   137  	GetBlock(ctx context.Context, blockHash *chainhash.Hash) (*wire.MsgBlock, error)
   138  	// GetTransaction returns the details of a wallet tx, if the wallet contains a
   139  	// tx with the provided hash. Returns asset.CoinNotFoundError if the tx is not
   140  	// found in the wallet.
   141  	GetTransaction(ctx context.Context, txHash *chainhash.Hash) (*WalletTransaction, error)
   142  	// GetBestBlock returns the hash and height of the wallet's best block.
   143  	GetBestBlock(ctx context.Context) (*chainhash.Hash, int64, error)
   144  	// GetBlockHash returns the hash of the mainchain block at the specified height.
   145  	GetBlockHash(ctx context.Context, blockHeight int64) (*chainhash.Hash, error)
   146  	// ListSinceBlock returns all wallet transactions confirmed since the specified
   147  	// height.
   148  	ListSinceBlock(ctx context.Context, start int32) ([]ListTransactionsResult, error)
   149  	// MatchAnyScript looks for any of the provided scripts in the block specified.
   150  	MatchAnyScript(ctx context.Context, blockHash *chainhash.Hash, scripts [][]byte) (bool, error)
   151  	// AccountUnlocked returns true if the account is unlocked.
   152  	AccountUnlocked(ctx context.Context, acctName string) (bool, error)
   153  	// LockAccount locks the account.
   154  	LockAccount(ctx context.Context, acctName string) error
   155  	// UnlockAccount unlocks the account.
   156  	UnlockAccount(ctx context.Context, passphrase []byte, acctName string) error
   157  	// SyncStatus returns the wallet's sync status.
   158  	SyncStatus(ctx context.Context) (*asset.SyncStatus, error)
   159  	// PeerCount returns the number of network peers to which the wallet or its
   160  	// backing node are connected.
   161  	PeerCount(ctx context.Context) (uint32, error)
   162  	// AddressPrivKey fetches the privkey for the specified address.
   163  	AddressPrivKey(ctx context.Context, address stdaddr.Address) (*secp256k1.PrivateKey, error)
   164  	// PurchaseTickets purchases n tickets. vspHost and vspPubKey only
   165  	// needed for internal wallets. Peer-to-peer mixing can be enabled if required.
   166  	PurchaseTickets(ctx context.Context, n int, vspHost, vspPubKey string, isMixing bool) ([]*asset.Ticket, error)
   167  	// Tickets returns current active ticket hashes up until they are voted
   168  	// or revoked. Includes unconfirmed tickets.
   169  	Tickets(ctx context.Context) ([]*asset.Ticket, error)
   170  	// VotingPreferences returns current voting preferences.
   171  	VotingPreferences(ctx context.Context) ([]*walletjson.VoteChoice, []*asset.TBTreasurySpend, []*walletjson.TreasuryPolicyResult, error)
   172  	// SetVotingPreferences sets preferences used when a ticket is chosen to
   173  	// be voted on.
   174  	SetVotingPreferences(ctx context.Context, choices, tspendPolicy, treasuryPolicy map[string]string) error
   175  	SetTxFee(ctx context.Context, feePerKB dcrutil.Amount) error
   176  	StakeInfo(ctx context.Context) (*wallet.StakeInfoData, error)
   177  	Reconfigure(ctx context.Context, cfg *asset.WalletConfig, net dex.Network, currentAddress string) (restart bool, err error)
   178  	WalletOwnsAddress(ctx context.Context, addr stdaddr.Address) (bool, error)
   179  	AddressUsed(ctx context.Context, addrStr string) (bool, error)
   180  }
   181  
   182  // WalletTransaction is a pared down version of walletjson.GetTransactionResult.
   183  type WalletTransaction struct {
   184  	Confirmations int64
   185  	BlockHash     string
   186  	Details       []walletjson.GetTransactionDetailsResult
   187  	MsgTx         *wire.MsgTx
   188  }
   189  
   190  // tipNotifier can be implemented if the Wallet is able to provide a stream of
   191  // blocks as they are finished being processed.
   192  // DRAFT NOTE: This is alternative to NotifyOnTipChange. I prefer this method,
   193  // and would vote to export this interface and get rid of NotifyOnTipChange.
   194  // @itswisdomagain might be using the current API though.
   195  // TODO: Makes sense.
   196  type tipNotifier interface {
   197  	tipFeed() <-chan *block
   198  }
   199  
   200  // FeeRateEstimator is satisfied by a Wallet that can provide fee rate
   201  // estimates.
   202  type FeeRateEstimator interface {
   203  	// EstimateSmartFeeRate returns a smart feerate estimate.
   204  	EstimateSmartFeeRate(ctx context.Context, confTarget int64, mode chainjson.EstimateSmartFeeMode) (float64, error)
   205  }
   206  
   207  // Mempooler is satisfied by a Wallet that can provide mempool info.
   208  type Mempooler interface {
   209  	// GetRawMempool returns hashes for all txs in a node's mempool.
   210  	GetRawMempool(ctx context.Context) ([]*chainhash.Hash, error)
   211  }
   212  
   213  type ticketPager interface {
   214  	TicketPage(ctx context.Context, scanStart int32, n, skipN int) ([]*asset.Ticket, error)
   215  }
   216  
   217  // TxOutput defines properties of a transaction output, including the
   218  // details of the block containing the tx, if mined.
   219  type TxOutput struct {
   220  	*wire.TxOut
   221  	Tree          int8
   222  	Addresses     []string
   223  	Confirmations uint32
   224  }