From 9d498044299f7d0c1caeb3b09ab9633cc5a4bd5b Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Wed, 22 Jan 2025 09:54:59 +0100 Subject: [PATCH] assetclient: fix wrong fee limit --- assets/client.go | 34 +++++++++++++++++++--- assets/client_test.go | 67 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 assets/client_test.go diff --git a/assets/client.go b/assets/client.go index 4024e30b..9a80547e 100644 --- a/assets/client.go +++ b/assets/client.go @@ -16,6 +16,7 @@ import ( "github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc" "github.com/lightninglabs/taproot-assets/taprpc/universerpc" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/macaroons" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -105,9 +106,12 @@ func (c *TapdClient) GetRfqForAsset(ctx context.Context, expiry int64, feeLimitMultiplier float64) ( *rfqrpc.PeerAcceptedSellQuote, error) { - feeLimit, err := lnrpc.UnmarshallAmt( - int64(satAmount)+int64(satAmount.MulF64(feeLimitMultiplier)), 0, - ) + // paymentMaxAmt is the maximum amount we are willing to pay for the + // payment. + // E.g. on a 250k sats payment we'll multiply the sat amount by 1.2. + // The resulting maximum amount we're willing to pay is 300k sats. + // The response asset amount will be for those 300k sats. + paymentMaxAmt, err := getPaymentMaxAmount(satAmount, feeLimitMultiplier) if err != nil { return nil, err } @@ -120,7 +124,7 @@ func (c *TapdClient) GetRfqForAsset(ctx context.Context, }, }, PeerPubKey: peerPubkey, - PaymentMaxAmt: uint64(feeLimit), + PaymentMaxAmt: uint64(paymentMaxAmt), Expiry: uint64(expiry), TimeoutSeconds: uint32(c.cfg.RFQtimeout.Seconds()), }) @@ -180,6 +184,28 @@ func (c *TapdClient) GetAssetName(ctx context.Context, return assetName, nil } +// getPaymentMaxAmount returns the milisat amount we are willing to pay for the +// payment. +func getPaymentMaxAmount(satAmount btcutil.Amount, feeLimitMultiplier float64) ( + lnwire.MilliSatoshi, error) { + + if satAmount == 0 { + return 0, fmt.Errorf("satAmount cannot be zero") + } + if feeLimitMultiplier < 1 { + return 0, fmt.Errorf("feeLimitMultiplier must be at least 1") + } + + // paymentMaxAmt is the maximum amount we are willing to pay for the + // payment. + // E.g. on a 250k sats payment we'll multiply the sat amount by 1.2. + // The resulting maximum amount we're willing to pay is 300k sats. + // The response asset amount will be for those 300k sats. + return lnrpc.UnmarshallAmt( + int64(satAmount.MulF64(feeLimitMultiplier)), 0, + ) +} + func getClientConn(config *TapdConfig) (*grpc.ClientConn, error) { // Load the specified TLS certificate and build transport credentials. creds, err := credentials.NewClientTLSFromFile(config.TLSPath, "") diff --git a/assets/client_test.go b/assets/client_test.go new file mode 100644 index 00000000..d783b9d5 --- /dev/null +++ b/assets/client_test.go @@ -0,0 +1,67 @@ +package assets + +import ( + "testing" + + "github.com/btcsuite/btcd/btcutil" + "github.com/lightningnetwork/lnd/lnwire" +) + +func TestGetPaymentMaxAmount(t *testing.T) { + tests := []struct { + satAmount btcutil.Amount + feeLimitMultiplier float64 + expectedAmount lnwire.MilliSatoshi + expectError bool + }{ + { + satAmount: btcutil.Amount(250000), + feeLimitMultiplier: 1.2, + expectedAmount: lnwire.MilliSatoshi(300000000), + expectError: false, + }, + { + satAmount: btcutil.Amount(100000), + feeLimitMultiplier: 1.5, + expectedAmount: lnwire.MilliSatoshi(150000000), + expectError: false, + }, + { + satAmount: btcutil.Amount(50000), + feeLimitMultiplier: 2.0, + expectedAmount: lnwire.MilliSatoshi(100000000), + expectError: false, + }, + { + satAmount: btcutil.Amount(0), + feeLimitMultiplier: 1.2, + expectedAmount: lnwire.MilliSatoshi(0), + expectError: true, + }, + { + satAmount: btcutil.Amount(250000), + feeLimitMultiplier: 0.8, + expectedAmount: lnwire.MilliSatoshi(0), + expectError: true, + }, + } + + for _, test := range tests { + result, err := getPaymentMaxAmount( + test.satAmount, test.feeLimitMultiplier, + ) + if test.expectError { + if err == nil { + t.Fatalf("expected error but got none") + } + } else { + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if result != test.expectedAmount { + t.Fatalf("expected %v, got %v", + test.expectedAmount, result) + } + } + } +}