lbry.go/lbrycrd/client.go
2018-02-22 14:17:22 -05:00

170 lines
4.2 KiB
Go

package lbrycrd
import (
"net/url"
"os"
"strconv"
"github.com/lbryio/lbry.go/errors"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcrpcclient"
"github.com/btcsuite/btcutil"
"github.com/go-ini/ini"
)
const DefaultPort = 9245
// MainNetParams define the lbrycrd network. See https://github.com/lbryio/lbrycrd/blob/master/src/chainparams.cpp
var MainNetParams = chaincfg.Params{
PubKeyHashAddrID: 0x55,
ScriptHashAddrID: 0x7a,
PrivateKeyID: 0x1c,
}
func init() {
// Register lbrycrd network
err := chaincfg.Register(&MainNetParams)
if err != nil {
panic("failed to register lbrycrd network: " + err.Error())
}
}
// Client connects to a lbrycrd instance
type Client struct {
*btcrpcclient.Client
}
// New initializes a new Client
func New(lbrycrdURL string) (*Client, error) {
// Connect to local bitcoin core RPC server using HTTP POST mode.
u, err := url.Parse(lbrycrdURL)
if err != nil {
return nil, errors.Err(err)
}
if u.User == nil {
return nil, errors.Err("no userinfo")
}
password, _ := u.User.Password()
connCfg := &btcrpcclient.ConnConfig{
Host: u.Host,
User: u.User.Username(),
Pass: password,
HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode
DisableTLS: true, // Bitcoin core does not provide TLS by default
}
// Notice the notification parameter is nil since notifications are not supported in HTTP POST mode.
client, err := btcrpcclient.New(connCfg, nil)
if err != nil {
return nil, errors.Err(err)
}
// make sure lbrycrd is running and responsive
_, err = client.GetInfo()
if err != nil {
return nil, errors.Err(err)
}
return &Client{client}, nil
}
func NewWithDefaultURL() (*Client, error) {
url, err := getLbrycrdURLFromConfFile()
if err != nil {
return nil, err
}
return New(url)
}
var errInsufficientFunds = errors.Base("insufficient funds")
// SimpleSend is a convenience function to send credits to an address (0 min confirmations)
func (c *Client) SimpleSend(toAddress string, amount float64) (*chainhash.Hash, error) {
decodedAddress, err := btcutil.DecodeAddress(toAddress, &MainNetParams)
if err != nil {
return nil, errors.Err(err)
}
lbcAmount, err := btcutil.NewAmount(amount)
if err != nil {
return nil, errors.Err(err)
}
hash, err := c.Client.SendFromMinConf("", decodedAddress, lbcAmount, 0)
if err != nil {
if err.Error() == "-6: Insufficient funds" {
err = errors.Err(errInsufficientFunds)
}
return nil, errors.Err(err)
}
return hash, nil
}
//func (c *Client) SendWithSplit(toAddress string, amount float64, numUTXOs int) (*chainhash.Hash, error) {
// decodedAddress, err := btcutil.DecodeAddress(toAddress, &MainNetParams)
// if err != nil {
// return nil, errors.Wrap(err, 0)
// }
//
// amountPerAddress, err := btcutil.NewAmount(amount / float64(numUTXOs))
// if err != nil {
// return nil, errors.Wrap(err, 0)
// }
//
// amounts := map[btcutil.Address]btcutil.Amount{}
// for i := 0; i < numUTXOs; i++ {
// addr := decodedAddress // to give it a new address, so
// amounts[addr] = amountPerAddress
// }
//
// hash, err := c.Client.SendManyMinConf("", amounts, 0)
// if err != nil && err.Error() == "-6: Insufficient funds" {
// err = errors.Wrap(errInsufficientFunds, 0)
// }
// return hash, errors.Wrap(err, 0)
//}
func getLbrycrdURLFromConfFile() (string, error) {
if os.Getenv("HOME") == "" {
return "", errors.Err("no $HOME var found")
}
defaultConfFile := os.Getenv("HOME") + "/.lbrycrd/lbrycrd.conf"
if _, err := os.Stat(defaultConfFile); os.IsNotExist(err) {
return "", errors.Err("default lbrycrd conf file not found")
}
cfg, err := ini.Load(defaultConfFile)
if err != nil {
return "", errors.Err(err)
}
section, err := cfg.GetSection("")
if err != nil {
return "", errors.Err(err)
}
username := section.Key("rpcuser").String()
password := section.Key("rpcpassword").String()
host := section.Key("rpchost").String()
if host == "" {
host = "localhost"
}
port := section.Key("rpcport").String()
if port == "" {
port = strconv.Itoa(DefaultPort)
}
userpass := ""
if username != "" || password != "" {
userpass = username + ":" + password + "@"
}
return "rpc://" + userpass + host + ":" + port, nil
}