Lightweight p2p SPV wallet and library in Go. It connects directly to the bitcoin p2p network to fetch headers, merkle blocks, and transactions.
It uses a number of utilities from btcsuite but natively handles blockchain and wallet.
Library Usage:
// Create a new config
config := spvwallet.NewDefaultConfig()
// Select network
config.Params = &chaincfg.TestNet3Params
// Select wallet datastore
sqliteDatastore, _ := db.Create(config.RepoPath)
config.DB = sqliteDatastore
// Create the wallet
wallet, _ := spvwallet.NewSPVWallet(config)
// Start it!
go wallet.Start()
Easy peasy
The wallet implements the following interface:
type BitcoinWallet interface {
// Start the wallet
Start()
// Return the network parameters
Params() *chaincfg.Params
// Returns the type of crytocurrency this wallet implements
CurrencyCode() string
// Check if this amount is considered dust
IsDust(amount int64) bool
// Get the master private key
MasterPrivateKey() *hd.ExtendedKey
// Get the master public key
MasterPublicKey() *hd.ExtendedKey
// Get the current address for the given purpose
CurrentAddress(purpose spvwallet.KeyPurpose) btc.Address
// Returns a fresh address that has never been returned by this function
NewAddress(purpose spvwallet.KeyPurpose) btc.Address
// Parse the address string and return an address interface
DecodeAddress(addr string) (btc.Address, error)
// Turn the given output script into an address
ScriptToAddress(script []byte) (btc.Address, error)
// Turn the given address into an output script
AddressToScript(addr btc.Address) ([]byte, error)
// Returns if the wallet has the key for the given address
HasKey(addr btc.Address) bool
// Get the confirmed and unconfirmed balances
Balance() (confirmed, unconfirmed int64)
// Returns a list of transactions for this wallet
Transactions() ([]spvwallet.Txn, error)
// Get info on a specific transaction
GetTransaction(txid chainhash.Hash) (spvwallet.Txn, error)
// Get the height of the blockchain
ChainTip() uint32
// Get the current fee per byte
GetFeePerByte(feeLevel spvwallet.FeeLevel) uint64
// Send bitcoins to an external wallet
Spend(amount int64, addr btc.Address, feeLevel spvwallet.FeeLevel) (*chainhash.Hash, error)
// Bump the fee for the given transaction
BumpFee(txid chainhash.Hash) (*chainhash.Hash, error)
// Calculates the estimated size of the transaction and returns the total fee for the given feePerByte
EstimateFee(ins []spvwallet.TransactionInput, outs []spvwallet.TransactionOutput, feePerByte uint64) uint64
// Build and broadcast a transaction that sweeps all coins from an address. If it is a p2sh multisig, the redeemScript must be included
SweepAddress(utxos []spvwallet.Utxo, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel spvwallet.FeeLevel) (*chainhash.Hash, error)
// Create a signature for a multisig transaction
CreateMultisigSignature(ins []spvwallet.TransactionInput, outs []spvwallet.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]spvwallet.Signature, error)
// Combine signatures and optionally broadcast
Multisign(ins []spvwallet.TransactionInput, outs []spvwallet.TransactionOutput, sigs1 []spvwallet.Signature, sigs2 []spvwallet.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error)
// Generate a multisig script from public keys. If a timeout is included the returned script should be a timelocked escrow which releases using the timeoutKey.
GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error)
// Add a script to the wallet and get notifications back when coins are received or spent from it
AddWatchedScript(script []byte) error
// Add a callback for incoming transactions
AddTransactionListener(func(spvwallet.TransactionCallback))
// Use this to re-download merkle blocks in case of missed transactions
ReSyncBlockchain(fromHeight int32)
// Return the number of confirmations and the height for a transaction
GetConfirmations(txid chainhash.Hash) (confirms, atHeight uint32, err error)
// Cleanly disconnect from the wallet
Close()
}
To create a wallet binary:
make install
Usage:
Usage:
spvwallet [OPTIONS] <command>
Help Options:
-h, --help Show this help message
Available commands:
addwatchedscript add a script to watch
balance get the wallet balance
bumpfee bump the tx fee
chaintip return the height of the chain
createmultisigsignature create a p2sh multisig signature
currentaddress get the current bitcoin address
dumpheaders print the header database
estimatefee estimate the fee for a tx
getconfirmations get the number of confirmations for a tx
getfeeperbyte get the current bitcoin fee
gettransaction get a specific transaction
haskey does key exist
masterprivatekey get the wallet's master private key
masterpublickey get the wallet's master public key
multisign combine multisig signatures
newaddress get a new bitcoin address
peers get info about peers
resyncblockchain re-download the chain of headers
spend send bitcoins
start start the wallet
stop stop the wallet
sweepaddress sweep all coins from an address
transactions get a list of transactions
version print the version number
Finally a gRPC API is available on port 8234. The same interface is exposed via the API plus a streaming wallet notifier which fires when a new transaction (either incoming or outgoing) is recorded then again when it gains its first confirmation.