2
0
mirror of https://github.com/lightninglabs/loop synced 2024-11-13 13:10:30 +00:00
loop/client/swap_server_client.go
2019-03-06 15:53:23 -08:00

144 lines
3.4 KiB
Go

package client
import (
"context"
"crypto/tls"
"encoding/hex"
"errors"
"fmt"
"github.com/lightninglabs/loop/looprpc"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcutil"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
type swapServerClient interface {
GetUnchargeTerms(ctx context.Context) (
*UnchargeTerms, error)
NewUnchargeSwap(ctx context.Context,
swapHash lntypes.Hash, amount btcutil.Amount,
receiverKey [33]byte) (
*newUnchargeResponse, error)
}
type grpcSwapServerClient struct {
server looprpc.SwapServerClient
conn *grpc.ClientConn
}
func newSwapServerClient(address string, insecure bool) (*grpcSwapServerClient, error) {
serverConn, err := getSwapServerConn(address, insecure)
if err != nil {
return nil, err
}
server := looprpc.NewSwapServerClient(serverConn)
return &grpcSwapServerClient{
conn: serverConn,
server: server,
}, nil
}
func (s *grpcSwapServerClient) GetUnchargeTerms(ctx context.Context) (
*UnchargeTerms, error) {
rpcCtx, rpcCancel := context.WithTimeout(ctx, serverRPCTimeout)
defer rpcCancel()
quoteResp, err := s.server.UnchargeQuote(rpcCtx,
&looprpc.ServerUnchargeQuoteRequest{},
)
if err != nil {
return nil, err
}
dest, err := hex.DecodeString(quoteResp.SwapPaymentDest)
if err != nil {
return nil, err
}
if len(dest) != 33 {
return nil, errors.New("invalid payment dest")
}
var destArray [33]byte
copy(destArray[:], dest)
return &UnchargeTerms{
MinSwapAmount: btcutil.Amount(quoteResp.MinSwapAmount),
MaxSwapAmount: btcutil.Amount(quoteResp.MaxSwapAmount),
PrepayAmt: btcutil.Amount(quoteResp.PrepayAmt),
SwapFeeBase: btcutil.Amount(quoteResp.SwapFeeBase),
SwapFeeRate: quoteResp.SwapFeeRate,
CltvDelta: quoteResp.CltvDelta,
SwapPaymentDest: destArray,
}, nil
}
func (s *grpcSwapServerClient) NewUnchargeSwap(ctx context.Context,
swapHash lntypes.Hash, amount btcutil.Amount, receiverKey [33]byte) (
*newUnchargeResponse, error) {
rpcCtx, rpcCancel := context.WithTimeout(ctx, serverRPCTimeout)
defer rpcCancel()
swapResp, err := s.server.NewUnchargeSwap(rpcCtx,
&looprpc.ServerUnchargeSwapRequest{
SwapHash: swapHash[:],
Amt: uint64(amount),
ReceiverKey: receiverKey[:],
},
)
if err != nil {
return nil, err
}
var senderKey [33]byte
copy(senderKey[:], swapResp.SenderKey)
// Validate sender key.
_, err = btcec.ParsePubKey(senderKey[:], btcec.S256())
if err != nil {
return nil, fmt.Errorf("invalid sender key: %v", err)
}
return &newUnchargeResponse{
swapInvoice: swapResp.SwapInvoice,
prepayInvoice: swapResp.PrepayInvoice,
senderKey: senderKey,
expiry: swapResp.Expiry,
}, nil
}
func (s *grpcSwapServerClient) Close() {
s.conn.Close()
}
// getSwapServerConn returns a connection to the swap server.
func getSwapServerConn(address string, insecure bool) (*grpc.ClientConn, error) {
// Create a dial options array.
opts := []grpc.DialOption{}
if insecure {
opts = append(opts, grpc.WithInsecure())
} else {
creds := credentials.NewTLS(&tls.Config{})
opts = append(opts, grpc.WithTransportCredentials(creds))
}
conn, err := grpc.Dial(address, opts...)
if err != nil {
return nil, fmt.Errorf("unable to connect to RPC server: %v", err)
}
return conn, nil
}
type newUnchargeResponse struct {
swapInvoice string
prepayInvoice string
senderKey [33]byte
expiry int32
}