You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

180 lines
4.0 KiB

package lndclient
import (
"context"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/lightninglabs/loop/utils"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lnwallet"
"google.golang.org/grpc"
)
// WalletKitClient exposes wallet functionality.
type WalletKitClient interface {
DeriveNextKey(ctx context.Context, family int32) (
*keychain.KeyDescriptor, error)
DeriveKey(ctx context.Context, locator *keychain.KeyLocator) (
*keychain.KeyDescriptor, error)
NextAddr(ctx context.Context) (btcutil.Address, error)
PublishTransaction(ctx context.Context, tx *wire.MsgTx) error
SendOutputs(ctx context.Context, outputs []*wire.TxOut,
feeRate lnwallet.SatPerKWeight) (*wire.MsgTx, error)
EstimateFee(ctx context.Context, confTarget int32) (lnwallet.SatPerKWeight,
error)
}
type walletKitClient struct {
client walletrpc.WalletKitClient
}
func newWalletKitClient(conn *grpc.ClientConn) *walletKitClient {
return &walletKitClient{
client: walletrpc.NewWalletKitClient(conn),
}
}
func (m *walletKitClient) DeriveNextKey(ctx context.Context, family int32) (
*keychain.KeyDescriptor, error) {
rpcCtx, cancel := context.WithTimeout(ctx, rpcTimeout)
defer cancel()
resp, err := m.client.DeriveNextKey(rpcCtx, &walletrpc.KeyReq{
KeyFamily: family,
})
if err != nil {
return nil, err
}
key, err := btcec.ParsePubKey(resp.RawKeyBytes, btcec.S256())
if err != nil {
return nil, err
}
return &keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(resp.KeyLoc.KeyFamily),
Index: uint32(resp.KeyLoc.KeyIndex),
},
PubKey: key,
}, nil
}
func (m *walletKitClient) DeriveKey(ctx context.Context, in *keychain.KeyLocator) (
*keychain.KeyDescriptor, error) {
rpcCtx, cancel := context.WithTimeout(ctx, rpcTimeout)
defer cancel()
resp, err := m.client.DeriveKey(rpcCtx, &signrpc.KeyLocator{
KeyFamily: int32(in.Family),
KeyIndex: int32(in.Index),
})
if err != nil {
return nil, err
}
key, err := btcec.ParsePubKey(resp.RawKeyBytes, btcec.S256())
if err != nil {
return nil, err
}
return &keychain.KeyDescriptor{
KeyLocator: *in,
PubKey: key,
}, nil
}
func (m *walletKitClient) NextAddr(ctx context.Context) (
btcutil.Address, error) {
rpcCtx, cancel := context.WithTimeout(ctx, rpcTimeout)
defer cancel()
resp, err := m.client.NextAddr(rpcCtx, &walletrpc.AddrRequest{})
if err != nil {
return nil, err
}
addr, err := btcutil.DecodeAddress(resp.Addr, nil)
if err != nil {
return nil, err
}
return addr, nil
}
func (m *walletKitClient) PublishTransaction(ctx context.Context,
tx *wire.MsgTx) error {
txHex, err := utils.EncodeTx(tx)
if err != nil {
return err
}
rpcCtx, cancel := context.WithTimeout(ctx, rpcTimeout)
defer cancel()
_, err = m.client.PublishTransaction(rpcCtx, &walletrpc.Transaction{
TxHex: txHex,
})
return err
}
func (m *walletKitClient) SendOutputs(ctx context.Context,
outputs []*wire.TxOut, feeRate lnwallet.SatPerKWeight) (
*wire.MsgTx, error) {
rpcOutputs := make([]*signrpc.TxOut, len(outputs))
for i, output := range outputs {
rpcOutputs[i] = &signrpc.TxOut{
PkScript: output.PkScript,
Value: output.Value,
}
}
rpcCtx, cancel := context.WithTimeout(ctx, rpcTimeout)
defer cancel()
resp, err := m.client.SendOutputs(rpcCtx, &walletrpc.SendOutputsRequest{
Outputs: rpcOutputs,
SatPerKw: int64(feeRate),
})
if err != nil {
return nil, err
}
tx, err := utils.DecodeTx(resp.RawTx)
if err != nil {
return nil, err
}
return tx, nil
}
func (m *walletKitClient) EstimateFee(ctx context.Context, confTarget int32) (
lnwallet.SatPerKWeight, error) {
rpcCtx, cancel := context.WithTimeout(ctx, rpcTimeout)
defer cancel()
resp, err := m.client.EstimateFee(rpcCtx, &walletrpc.EstimateFeeRequest{
ConfTarget: int32(confTarget),
})
if err != nil {
return 0, err
}
return lnwallet.SatPerKWeight(resp.SatPerKw), nil
}