Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions itest/assets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1423,8 +1423,10 @@ func sendAssetKeySendPayment(t *testing.T, src, dst *HarnessNode, amt uint64,
return
}

result, _, err := getAssetPaymentResult(t, stream, false)
require.NoError(t, err)
tapResult := getAssetPaymentResult(t, stream, false)
require.NoError(t, tapResult.err)

result := tapResult.lndResult
if result.Status == lnrpc.Payment_FAILED {
t.Logf("Failure reason: %v", result.FailureReason)
}
Expand Down Expand Up @@ -1755,12 +1757,13 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
sendReq.MaxShardSizeMsat = 80_000_000
}

var rfqBytes, peerPubKey []byte
var rfqBytes []byte
cfg.rfq.WhenSome(func(i rfqmsg.ID) {
rfqBytes = make([]byte, len(i[:]))
copy(rfqBytes, i[:])
})

var peerPubKey []byte
if rfqPeer != nil {
peerPubKey = rfqPeer.PubKey[:]
}
Expand All @@ -1785,7 +1788,7 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,

// If an error is returned by the RPC method (meaning the stream itself
// was established, no network or auth error), we expect the error to be
// returned on the first read on the stream.
// returned on the stream.
if cfg.errSubStr != "" {
msg, err := stream.Recv()

Expand All @@ -1804,14 +1807,18 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
rateVal rfqmath.FixedPoint[rfqmath.BigInt]
)

result, rateVal, err := getAssetPaymentResult(
tapResult := getAssetPaymentResult(
t, stream, cfg.payStatus == lnrpc.Payment_IN_FLIGHT,
)
require.NoError(t, err)
require.NoError(t, tapResult.err)

result := tapResult.lndResult
require.Equal(t, cfg.payStatus, result.Status)
require.Equal(t, cfg.failureReason, result.FailureReason)

amountMsat := lnwire.MilliSatoshi(decodedInvoice.NumMsat)

rateVal = tapResult.assetRate
milliSatsFP := rfqmath.MilliSatoshiToUnits(amountMsat, rateVal)
numUnits = milliSatsFP.ScaleTo(0).ToUint64()

Expand Down
42 changes: 35 additions & 7 deletions itest/litd_accounts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,10 +445,24 @@ func getPaymentResult(stream routerrpc.Router_SendPaymentV2Client,
}
}

// TapPaymentResult encapsulates all the information related to the outcome of
// a tap asset payment. It may also contain an error, in which case the rest of
// the values should be ignored, even if set.
type TapPaymentResult struct {
// lndResult contains the lnd part of the payment result.
lndResult *lnrpc.Payment

// assetRate contains the asset rate that was used to convert the assets
// to sats.
assetRate rfqmath.FixedPoint[rfqmath.BigInt]

// err contains the returned error from the payment.
err error
}

func getAssetPaymentResult(t *testing.T,
s tapchannelrpc.TaprootAssetChannels_SendPaymentClient,
isHodl bool) (*lnrpc.Payment, rfqmath.FixedPoint[rfqmath.BigInt],
error) {
isHodl bool) TapPaymentResult {

// No idea why it makes a difference whether we wait before calling
// s.Recv() or not, but it does. Without the sleep, the test will fail
Expand All @@ -461,7 +475,11 @@ func getAssetPaymentResult(t *testing.T,
for {
msg, err := s.Recv()
if err != nil {
return nil, rateVal, err
return TapPaymentResult{
lndResult: nil,
assetRate: rateVal,
err: err,
}
}

// Ignore RFQ quote acceptance messages read from the send
Expand Down Expand Up @@ -501,19 +519,29 @@ func getAssetPaymentResult(t *testing.T,

payment := msg.GetPaymentResult()
if payment == nil {
return nil, rateVal,
fmt.Errorf("unexpected message: %v", msg)
err := fmt.Errorf("unexpected message: %v", msg)
return TapPaymentResult{
lndResult: nil,
assetRate: rateVal,
err: err,
}
}

result := TapPaymentResult{
lndResult: payment,
assetRate: rateVal,
err: nil,
}

// If this is a hodl payment, then we'll return the first
// expected response. Otherwise, we'll wait until the in flight
// clears to we can observe the other payment states.
switch {
case isHodl:
return payment, rateVal, nil
return result

case payment.Status != lnrpc.Payment_IN_FLIGHT:
return payment, rateVal, nil
return result
}
}
}
36 changes: 36 additions & 0 deletions itest/litd_custom_channels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2959,6 +2959,42 @@ func testCustomChannelsLiquidityEdgeCasesCore(ctx context.Context,
payInvoiceWithSatoshi(
t.t, dave, invoiceResp, withFeeLimit(100_000_000),
)

logBalance(t.t, nodes, assetID, "after policy checks")

resBuy, err := daveTap.RfqClient.AddAssetBuyOrder(
ctx, &rfqrpc.AddAssetBuyOrderRequest{
AssetSpecifier: &assetSpecifier,
AssetMaxAmt: 1_000,
Expiry: uint64(inOneHour.Unix()),
PeerPubKey: charlie.PubKey[:],
TimeoutSeconds: 100,
},
)
require.NoError(t.t, err)

scid := resBuy.GetAcceptedQuote().Scid

invResp := createAssetInvoice(
t.t, charlie, dave, 1_000, assetID,
withInvGroupKey(groupID), withRouteHints([]*lnrpc.RouteHint{
{
HopHints: []*lnrpc.HopHint{
{
NodeId: charlie.PubKeyStr,
ChanId: scid,
},
},
},
}),
)

payInvoiceWithAssets(
t.t, charlie, dave, invResp.PaymentRequest, assetID,
withGroupKey(groupID),
)

logBalance(t.t, nodes, assetID, "after invoice with route hints")
}

// testCustomChannelsLiquidityEdgeCases is a test that runs through some
Expand Down
Loading