wallet

package
v0.0.0-...-7df67f7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 24, 2024 License: MIT Imports: 15 Imported by: 3

Documentation

Index

Constants

View Source
const (
	Bitcoin     CoinType = 0
	Litecoin    CoinType = 1
	Dash        CoinType = 5 // TODO: impl
	Zcash       CoinType = 133
	BitcoinCash CoinType = 145
	Ethereum    CoinType = 60

	TestnetBitcoin     = 1000000
	TestnetLitecoin    = 1000001
	TestnetZcash       = 1000133
	TestnetBitcoinCash = 1000145
	TestnetEthereum    = 1000060
)
View Source
const (
	EXTERNAL KeyPurpose = 0
	INTERNAL KeyPurpose = 1
	// Aliases
	RECEIVING = EXTERNAL
	CHANGE    = INTERNAL
)

Variables

View Source
var (
	// ErrDustAmount is returned if an output amount is below the dust threshold
	ErrDustAmount error = errors.New("amount is below network dust threshold")

	// ErrInsufficientFunds is returned when the wallet is unable to send the
	// amount specified due to the balance being too low
	ErrInsufficientFunds = errors.New("ERROR_INSUFFICIENT_FUNDS")

	// ErrWalletFnNotImplemented is returned from some unimplemented functions.
	// This is due to a concrete wallet not implementing the functionality or
	// temporarily during development.
	ErrWalletFnNotImplemented = errors.New("wallet function is not implemented")
)

Errors

Functions

func NewOutPoint

func NewOutPoint(txid string, out uint32) (*wire.OutPoint, error)

func NewOutPointFromString

func NewOutPointFromString(outpoint string) (*wire.OutPoint, error)

NewOutPointFromString returns a new bitcoin transaction outpoint parsed from the provided string, which should be in the format "hash:index".

Types

type AddressHistory

type AddressHistory struct {
	Height int64
	TxHash chainhash.Hash
}

type Cfg

type Cfg interface {
	PutCreationDate(date time.Time) error
	GetCreationDate() (time.Time, error)
}

type Coin

type Coin interface {
	String() string
	CurrencyCode() string
}

type CoinType

type CoinType uint32

func (*CoinType) CurrencyCode

func (c *CoinType) CurrencyCode() string

func (*CoinType) String

func (c *CoinType) String() string

type Datastore

type Datastore interface {
	Cfg() Cfg
	Enc() Enc
	Utxos() Utxos
	Stxos() Stxos
	Txns() Txns
	Keys() Keys
	Subscriptions() Subscriptions
}

type ElectrumWallet

type ElectrumWallet interface {

	// Start the wallet
	Start()

	// Return the creation date of the wallet
	CreationDate() time.Time

	// Return the network parameters
	Params() *chaincfg.Params

	// Returns the type of crytocurrency this wallet implements
	CurrencyCode() string

	// Check if this amount is considered dust < 1000 sats/equivalent for now
	IsDust(amount int64) bool

	// GetAddress gets an address given a KeyPath. It is used for Rescan
	GetAddress(kp *KeyPath) (btcutil.Address, error)

	// GetUnusedAddress returns an address suitable for receiving payments.
	// `purpose` specifies whether the address should be internal or external.
	// This function will return the same address so long as that address is
	// not invloved in a transaction. Whenever the returned address has been
	// used in a broadcasted tx this function should start returning a new,
	// unused address.
	GetUnusedAddress(purpose KeyPurpose) (btcutil.Address, error)

	// GetUnusedLegacyAddress returns an address suitable for receiving payments
	// from legacy wallets, exchanges, etc. It will only give out external addr-
	// esses for receiving funds; not change addresses.
	GetUnusedLegacyAddress() (btcutil.Address, error)

	// GetPrivKeyForAddress gets the wallet private key-pair as a WIF given an
	// wallet address and the wallet password.
	GetPrivKeyForAddress(pw string, address btcutil.Address) (string, error)

	// Marks the address as used (involved in at least one transaction)
	MarkAddressUsed(address btcutil.Address) error

	// DecodeAddress parses the address string and return an address.
	DecodeAddress(addr string) (btcutil.Address, error)

	// ScriptToAddress takes a raw output script (the full script, not just a
	// hash160) and returns the corresponding address.
	ScriptToAddress(script []byte) (btcutil.Address, error)

	// Turn the given address into an output script
	AddressToScript(address btcutil.Address) ([]byte, error)

	// Add a subscription to the wallet. These addresses will be used to
	// subscribe to ElectrumX and get notifications back from ElectrumX
	// when coins are received. If already stored this is a no-op.
	AddSubscription(subscription *Subscription) error

	// Remove a subscription from the wallet.
	RemoveSubscription(scriptPubKey string)

	// Returns the ElectrumX subscribed subscription in db that has scriptPubKey
	// as a key.
	GetSubscription(scriptPubKey string) (*Subscription, error)

	// Returns the ElectrumX subscribed subscription in db that has electrumScripthash
	// as a key.
	GetSubscriptionForElectrumScripthash(electrumScripthash string) (*Subscription, error)

	// Returns all the ElectrumX subscribed subscriptions in db.
	ListSubscriptions() ([]*Subscription, error)

	// Returns if the wallet has the HD key for the given address
	HasAddress(address btcutil.Address) bool

	// Returns a list of addresses for this wallet
	ListAddresses() []btcutil.Address

	//Returns true if the address is a wallet address
	IsMine(address btcutil.Address) bool

	// Balance returns the confirmed & unconfirmed aggregate balance for the wallet.
	// For utxo based wallets if a spend of confirmed coins is made, the resulting
	// "change" should be also counted as confirmed even if the spending transaction
	// is unconfirmed. The reason for this that if the spend never confirms, no coins
	// will be lost to the wallet.
	//
	// This command uses the local wallet. We can also get from ElectrumX but on a per
	// address basis.
	Balance() (int64, int64, int64, error)

	// Sign an unsigned transaction with the wallet and return singned tx and
	// the change output index
	SignTx(pw string, info *SigningInfo) ([]byte, error)

	// Returns a list of transactions for this wallet - currently unused
	ListTransactions() ([]Txn, error)

	// Does the wallet have a specific transaction?
	HasTransaction(txid string) (bool, *Txn)

	// Get info on a specific transaction - currently unused
	GetTransaction(txid string) (*Txn, error)

	// Return the calculated confirmed txids and heights for an address - unused
	GetWalletAddressHistory(address btcutil.Address) ([]AddressHistory, error)

	// Add a transaction to the database
	AddTransaction(tx *wire.MsgTx, height int64, timestamp time.Time) error

	// List all unspent outputs in the wallet irrespective of status
	ListUnspent() ([]Utxo, error)

	// List all unspent outputs in the wallet that have been mined once or more
	// times
	ListConfirmedUnspent() ([]Utxo, error)

	// List all unspent outputs that are frozen (temporarily) in the wallet
	ListFrozenUnspent() ([]Utxo, error)

	// List all spent
	ListSpent() ([]Stxo, error)

	// Set the utxo as temporarily unspendable
	FreezeUTXO(op *wire.OutPoint) error

	// Set the utxo as spendable again
	UnFreezeUTXO(op *wire.OutPoint) error

	// Make a new spending transaction
	Spend(pw string, amount int64, toAddress btcutil.Address, feeLevel FeeLevel) (int, *wire.MsgTx, error)

	// Calculates the estimated size of the transaction and returns the total fee for the given feePerByte
	EstimateFee(ins []InputInfo, outs []TransactionOutput, feePerByte int64) int64

	// Build a transaction that sweeps all coins from a non-wallet private key
	SweepCoins(coins []InputInfo, feeLevel FeeLevel, maxTxInputs int) ([]*wire.MsgTx, error)

	// CPFP logic; rbf not supported
	BumpFee(txid string) (*wire.MsgTx, error)

	// Update the height of the tip from the headers chain & the blockchain sync status.
	UpdateTip(newTip int64, synced bool)

	// Cleanly disconnect from the wallet
	Close()
}

type Enc

type Enc interface {
	PutEncrypted(b []byte, pw string) error
	GetDecrypted(pw string) ([]byte, error)
}

type ExchangeRates

type ExchangeRates interface {

	/* Fetch the exchange rate for the given currency
	   It is OK if this returns from a cache. */
	GetExchangeRate(currencyCode string) (float64, error)

	// Update the prices with the current exchange rate before returning
	GetLatestRate(currencyCode string) (float64, error)

	// Returns all available rates
	GetAllRates(cacheOK bool) (map[string]float64, error)

	/* Return the number of currency units per coin. For example, in bitcoin
	   this is 100m satoshi per BTC. This is used when converting from fiat
	   to the smaller currency unit. */
	UnitsPerCoin() int64
}

type FeeLevel

type FeeLevel int
const (
	PRIORITY       FeeLevel = 0
	NORMAL         FeeLevel = 1
	ECONOMIC       FeeLevel = 2
	FEE_BUMP       FeeLevel = 3
	SUPER_ECONOMIC FeeLevel = 4
)

type FeeProvider

type FeeProvider struct {
	MaxFee      int64
	PriorityFee int64
	NormalFee   int64
	EconomicFee int64
	FeeAPI      string

	HttpClient HttpClient
	// contains filtered or unexported fields
}

func DefaultFeeProvider

func DefaultFeeProvider() *FeeProvider

December 2023

func NewFeeProvider

func NewFeeProvider(maxFee, priorityFee, normalFee, economicFee int64, feeAPI string, proxy proxy.Dialer) *FeeProvider

func (*FeeProvider) GetFeePerByte

func (fp *FeeProvider) GetFeePerByte(feeLevel FeeLevel) int64

type Fees

type Fees struct {
	Priority int64 `json:"priority"`
	Normal   int64 `json:"normal"`
	Economic int64 `json:"economic"`
}

type HttpClient

type HttpClient interface {
	Get(string) (*http.Response, error)
}

type InputInfo

type InputInfo struct {
	Outpoint      *wire.OutPoint
	Height        int64
	Value         int64
	KeyPair       *btcutil.WIF
	LinkedAddress btcutil.Address
	PkScript      []byte
}

func (*InputInfo) String

func (info *InputInfo) String() string

type KeyPath

type KeyPath struct {
	Purpose KeyPurpose
	Index   int
}

type KeyPurpose

type KeyPurpose int

The end leaves on the HD wallet have only two possible values. External keys are those given to other people for the purpose of receiving transactions. These may include keys used for refund addresses. Internal keys are used only by the wallet, primarily for change addresses but could also be used for shuffling around UTXOs.

type Keys

type Keys interface {
	// Put a bip32 key path into the database
	Put(hash160 []byte, keyPath KeyPath) error

	// Mark the key as used
	MarkKeyAsUsed(scriptAddress []byte) error

	// Fetch the last index for the given key purpose
	// The bool should state whether the key has been used or not
	GetLastKeyIndex(purpose KeyPurpose) (int, bool, error)

	// Returns the path for the given key
	GetPathForKey(scriptAddress []byte) (KeyPath, error)

	// Get a list of unused key indexes for the given purpose
	GetUnused(purpose KeyPurpose) ([]int, error)

	// Fetch all key paths
	GetAll() ([]KeyPath, error)

	// Get the number of unused keys following the last used key
	// for each key purpose.
	GetLookaheadWindows() map[KeyPurpose]int

	// Debug dump
	GetDbg() string
}

Keys provides a database interface for the wallet to: - Track used keys by key path - Manage the look ahead window.

No HD keys are stored in the database. All HD keys are derived 'on the fly'

type SigningInfo

type SigningInfo struct {
	UnsignedTx *wire.MsgTx
	VerifyTx   bool
}

type StatusCode

type StatusCode string
const (
	StatusUnconfirmed StatusCode = "UNCONFIRMED"
	StatusPending     StatusCode = "PENDING"
	StatusConfirmed   StatusCode = "CONFIRMED"
	StatusStuck       StatusCode = "STUCK"
	StatusDead        StatusCode = "DEAD"
	StatusError       StatusCode = "ERROR"
)

type Stxo

type Stxo struct {
	// When it used to be a UTXO
	Utxo Utxo

	// The height at which it was spent
	SpendHeight int64

	// The tx that consumed it
	SpendTxid chainhash.Hash
}

func (*Stxo) IsEqual

func (stxo *Stxo) IsEqual(alt *Stxo) bool

type Stxos

type Stxos interface {
	// Put a stxo to the database
	Put(stxo Stxo) error

	// Fetch all stxos from the db
	GetAll() ([]Stxo, error)

	// Delete a stxo from the db
	Delete(stxo Stxo) error
}

type Subscription

type Subscription struct {
	// wallet subscribe watch list public key script; hex string
	PkScript string
	// electrum 1.4 protocol 'scripthash'; hex string
	ElectrumScripthash string
	// address
	Address string // encoded legacy or bech address
}

func (*Subscription) IsEqual

func (s *Subscription) IsEqual(alt *Subscription) bool

type Subscriptions

type Subscriptions interface {
	// Add a subscription.
	Put(subscription *Subscription) error

	// Return the subscription for the scriptPubKey
	Get(scriptPubKey string) (*Subscription, error)

	// Return the subscription for the electrumScripthash (not indexed)
	GetElectrumScripthash(electrumScripthash string) (*Subscription, error)

	// Return all subscriptions
	GetAll() ([]*Subscription, error)

	// Delete a subscription
	Delete(scriptPubkey string) error
}

Subscriptions is used to track ElectrumX scriptHash status change subscriptions made to ElectrumX nodes.

type TransactionOutput

type TransactionOutput struct {
	Address btcutil.Address
	Value   int64
	Index   uint32
}

type Txn

type Txn struct {
	// Transaction ID
	Txid string

	// The value relevant to the wallet
	Value int64

	// The height at which it was mined
	Height int64

	// The time the transaction was first seen
	Timestamp time.Time

	// This transaction only involves a watch only address
	WatchOnly bool

	// The number of confirmations on a transaction. This does not need to be saved in
	// the database but should be calculated when the Transactions() method is called.
	Confirmations int64

	// The state of the transaction (confirmed, unconfirmed, dead, etc). Implementations
	// have some flexibility in describing their transactions. Like confirmations, this
	// is best calculated when the Transactions() method is called.
	Status StatusCode

	// If the Status is Error the ErrorMessage should describe the problem
	ErrorMessage string

	// Raw transaction bytes
	Bytes []byte

	FromAddress string
	ToAddress   string

	Outputs []TransactionOutput
}

type Txns

type Txns interface {
	// Put a new transaction to the database
	Put(raw []byte, txid string, value int64, height int64, timestamp time.Time, watchOnly bool) error

	// Fetch a tx and it's metadata given a hash
	Get(txid string) (Txn, error)

	// Fetch all transactions from the db
	GetAll(includeWatchOnly bool) ([]Txn, error)

	// Update the height of a transaction
	UpdateHeight(txid string, height int, timestamp time.Time) error

	// Delete a transaction from the db
	Delete(txid string) error
}

type Utxo

type Utxo struct {
	// Previous txid and output index
	Op wire.OutPoint

	// Block height where this tx was confirmed, 0 for unconfirmed
	AtHeight int64

	// Coin value
	Value int64

	// Output script
	ScriptPubkey []byte

	// The primary purpose is track multisig UTXOs which must have
	// separate handling to spend. Currently unused.
	// [multisig ideas in separate branch on github]
	//
	// Keeping for some future external Tx ideas. External meaning tx's created
	// external to this wallet that we may want to ask the Electrum server to
	// watch out for..
	WatchOnly bool

	// If true this utxo has been used in a new input by software outside the
	// wallet; in an HTLC contract perhaps. Utxo will not be selected for a new
	// wallet transaction while frozen.
	//
	// It is the outside software's responsibility to set this.
	Frozen bool
}

func (*Utxo) IsEqual

func (utxo *Utxo) IsEqual(alt *Utxo) bool

type Utxos

type Utxos interface {
	// Put a utxo to the database
	Put(utxo Utxo) error

	// Fetch all utxos from the db
	GetAll() ([]Utxo, error)

	// Make a utxo watch-only because we have no key for it but want to watch
	// it's status. [Implemented in DB. Not used by the wallet at this time]
	SetWatchOnly(utxo Utxo) error

	// Make a utxo unspendable - we do have the key
	Freeze(utxo Utxo) error

	// Make a frozen utxo spendable again - we do have the key
	UnFreeze(utxo Utxo) error

	// Delete a utxo from the db
	Delete(utxo Utxo) error
}

type WalletConfig

type WalletConfig struct {
	// The blockchain, Bitcoin, Dash, etc
	Chain CoinType

	// Network parameters. Set mainnet, testnet using this.
	Params *chaincfg.Params

	// Store the seed in encrypted storage
	StoreEncSeed bool

	DbType string

	// Location of the data directory
	DataDir string

	// An implementation of the Datastore interface
	DB Datastore

	// The default fee-per-byte for each level
	LowFee    int64
	MediumFee int64
	HighFee   int64

	// The highest allowable fee-per-byte
	MaxFee int64

	// If not testing do not overwrite existing wallet files
	Testing bool
}

Directories

Path Synopsis
cmd
boltdmp Module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL