Skip to content

Commit 3fa4a1d

Browse files
committed
cmd+itest: use new tapchannelrpc.AddInvoice RPC
1 parent 0ce9bf1 commit 3fa4a1d

File tree

2 files changed

+48
-193
lines changed

2 files changed

+48
-193
lines changed

cmd/litcli/ln.go

Lines changed: 28 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,16 @@ import (
99
"errors"
1010
"fmt"
1111
"strconv"
12-
"time"
1312

1413
"github.com/lightninglabs/taproot-assets/asset"
14+
"github.com/lightninglabs/taproot-assets/rfq"
1515
"github.com/lightninglabs/taproot-assets/rfqmsg"
1616
"github.com/lightninglabs/taproot-assets/taprpc"
17-
"github.com/lightninglabs/taproot-assets/taprpc/rfqrpc"
1817
tchrpc "github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc"
1918
"github.com/lightningnetwork/lnd/cmd/commands"
2019
"github.com/lightningnetwork/lnd/lnrpc"
2120
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
2221
"github.com/lightningnetwork/lnd/lntypes"
23-
"github.com/lightningnetwork/lnd/lnwire"
2422
"github.com/lightningnetwork/lnd/record"
2523
"github.com/urfave/cli"
2624
"google.golang.org/grpc"
@@ -550,6 +548,8 @@ func addInvoice(ctx *cli.Context) error {
550548

551549
var (
552550
assetAmount uint64
551+
preimage []byte
552+
descHash []byte
553553
err error
554554
)
555555
switch {
@@ -565,148 +565,53 @@ func addInvoice(ctx *cli.Context) error {
565565
return fmt.Errorf("asset_amount argument missing")
566566
}
567567

568-
expiry := time.Now().Add(300 * time.Second)
569-
if ctx.IsSet("expiry") {
570-
expirySeconds := ctx.Uint64("expiry")
571-
expiry = time.Now().Add(
572-
time.Duration(expirySeconds) * time.Second,
573-
)
568+
if ctx.IsSet("preimage") {
569+
preimage, err = hex.DecodeString(ctx.String("preimage"))
570+
if err != nil {
571+
return fmt.Errorf("unable to parse preimage: %w", err)
572+
}
574573
}
575574

576-
lndConn, cleanup, err := connectClient(ctx, false)
575+
descHash, err = hex.DecodeString(ctx.String("description_hash"))
577576
if err != nil {
578-
return fmt.Errorf("unable to make rpc con: %w", err)
577+
return fmt.Errorf("unable to parse description_hash: %w", err)
579578
}
580579

581-
defer cleanup()
582-
583-
lndClient := lnrpc.NewLightningClient(lndConn)
580+
expirySeconds := int64(rfq.DefaultInvoiceExpiry.Seconds())
581+
if ctx.IsSet("expiry") {
582+
expirySeconds = ctx.Int64("expiry")
583+
}
584584

585585
assetIDBytes, err := hex.DecodeString(assetIDStr)
586586
if err != nil {
587587
return fmt.Errorf("unable to decode assetID: %v", err)
588588
}
589589

590-
// First, based on the asset ID and amount, we'll make sure that this
591-
// channel even has enough funds to send.
592-
assetBalances, err := computeAssetBalances(lndClient)
593-
if err != nil {
594-
return fmt.Errorf("unable to compute asset balances: %w", err)
595-
}
596-
597-
balance, ok := assetBalances.Assets[assetIDStr]
598-
if !ok {
599-
return fmt.Errorf("unable to send asset_id=%v, not in "+
600-
"channel", assetIDStr)
601-
}
602-
603-
if balance.RemoteBalance == 0 {
604-
return fmt.Errorf("no remote asset balance available for "+
605-
"receiving asset_id=%v", assetIDStr)
606-
}
607-
608590
var assetID asset.ID
609591
copy(assetID[:], assetIDBytes)
610592

611593
tapdConn, cleanup, err := connectTapdClient(ctx)
612594
if err != nil {
613595
return fmt.Errorf("error creating tapd connection: %w", err)
614596
}
615-
616597
defer cleanup()
617598

618-
peerPubKey, err := hex.DecodeString(balance.Channel.RemotePubkey)
619-
if err != nil {
620-
return fmt.Errorf("unable to decode peer pubkey: %w", err)
621-
}
622-
623-
rfqClient := rfqrpc.NewRfqClient(tapdConn)
624-
625-
timeoutSeconds := uint32(60)
626-
fmt.Printf("Asking peer %x for quote to buy assets to receive for "+
627-
"invoice over %d units; waiting up to %ds\n", peerPubKey,
628-
assetAmount, timeoutSeconds)
629-
630-
resp, err := rfqClient.AddAssetBuyOrder(
631-
ctxb, &rfqrpc.AddAssetBuyOrderRequest{
632-
AssetSpecifier: &rfqrpc.AssetSpecifier{
633-
Id: &rfqrpc.AssetSpecifier_AssetIdStr{
634-
AssetIdStr: assetIDStr,
635-
},
636-
},
637-
MinAssetAmount: assetAmount,
638-
Expiry: uint64(expiry.Unix()),
639-
PeerPubKey: peerPubKey,
640-
TimeoutSeconds: timeoutSeconds,
599+
channelsClient := tchrpc.NewTaprootAssetChannelsClient(tapdConn)
600+
resp, err := channelsClient.AddInvoice(ctxb, &tchrpc.AddInvoiceRequest{
601+
AssetId: assetIDBytes,
602+
AssetAmount: assetAmount,
603+
InvoiceRequest: &lnrpc.Invoice{
604+
Memo: ctx.String("memo"),
605+
RPreimage: preimage,
606+
DescriptionHash: descHash,
607+
FallbackAddr: ctx.String("fallback_addr"),
608+
Expiry: expirySeconds,
609+
Private: ctx.Bool("private"),
610+
IsAmp: ctx.Bool("amp"),
641611
},
642-
)
643-
if err != nil {
644-
return fmt.Errorf("error adding sell order: %w", err)
645-
}
646-
647-
var acceptedQuote *rfqrpc.PeerAcceptedBuyQuote
648-
switch r := resp.Response.(type) {
649-
case *rfqrpc.AddAssetBuyOrderResponse_AcceptedQuote:
650-
acceptedQuote = r.AcceptedQuote
651-
652-
case *rfqrpc.AddAssetBuyOrderResponse_InvalidQuote:
653-
return fmt.Errorf("peer %v sent back an invalid quote, "+
654-
"status: %v", r.InvalidQuote.Peer,
655-
r.InvalidQuote.Status.String())
656-
657-
case *rfqrpc.AddAssetBuyOrderResponse_RejectedQuote:
658-
return fmt.Errorf("peer %v rejected the quote, code: %v, "+
659-
"error message: %v", r.RejectedQuote.Peer,
660-
r.RejectedQuote.ErrorCode, r.RejectedQuote.ErrorMessage)
661-
662-
default:
663-
return fmt.Errorf("unexpected response type: %T", r)
664-
}
665-
666-
msatPerUnit := acceptedQuote.AskPrice
667-
numMSats := lnwire.MilliSatoshi(assetAmount * msatPerUnit)
668-
669-
descHash, err := hex.DecodeString(ctx.String("description_hash"))
670-
if err != nil {
671-
return fmt.Errorf("unable to parse description_hash: %w", err)
672-
}
673-
674-
ourPolicy, err := getOurPolicy(
675-
lndClient, balance.Channel.ChanId, balance.Channel.RemotePubkey,
676-
)
677-
if err != nil {
678-
return fmt.Errorf("unable to get our policy: %w", err)
679-
}
680-
681-
hopHint := &lnrpc.HopHint{
682-
NodeId: balance.Channel.RemotePubkey,
683-
ChanId: acceptedQuote.Scid,
684-
FeeBaseMsat: uint32(ourPolicy.FeeBaseMsat),
685-
FeeProportionalMillionths: uint32(ourPolicy.FeeRateMilliMsat),
686-
CltvExpiryDelta: ourPolicy.TimeLockDelta,
687-
}
688-
689-
invoice := &lnrpc.Invoice{
690-
Memo: ctx.String("memo"),
691-
ValueMsat: int64(numMSats),
692-
DescriptionHash: descHash,
693-
FallbackAddr: ctx.String("fallback_addr"),
694-
Expiry: int64(ctx.Uint64("expiry")),
695-
Private: ctx.Bool("private"),
696-
IsAmp: ctx.Bool("amp"),
697-
RouteHints: []*lnrpc.RouteHint{
698-
{
699-
HopHints: []*lnrpc.HopHint{hopHint},
700-
},
701-
},
702-
}
703-
704-
invoiceResp, err := lndClient.AddInvoice(ctxb, invoice)
705-
if err != nil {
706-
return err
707-
}
612+
})
708613

709-
printRespJSON(invoiceResp)
614+
printRespJSON(resp)
710615

711616
return nil
712617
}

itest/assets_test.go

Lines changed: 20 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/davecgh/go-spew/spew"
2020
"github.com/lightninglabs/taproot-assets/itest"
2121
"github.com/lightninglabs/taproot-assets/proof"
22+
"github.com/lightninglabs/taproot-assets/rfq"
2223
"github.com/lightninglabs/taproot-assets/rfqmsg"
2324
"github.com/lightninglabs/taproot-assets/tapchannel"
2425
"github.com/lightninglabs/taproot-assets/tapfreighter"
@@ -779,91 +780,40 @@ func createAssetInvoice(t *testing.T, dstRfqPeer, dst *HarnessNode,
779780
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
780781
defer cancel()
781782

782-
timeoutSeconds := uint32(60)
783-
expiry := time.Now().Add(time.Duration(timeoutSeconds) * time.Second)
783+
timeoutSeconds := int64(rfq.DefaultInvoiceExpiry.Seconds())
784784

785785
t.Logf("Asking peer %x for quote to buy assets to receive for "+
786786
"invoice over %d units; waiting up to %ds",
787787
dstRfqPeer.PubKey[:], assetAmount, timeoutSeconds)
788788

789789
dstTapd := newTapClient(t, dst)
790-
resp, err := dstTapd.AddAssetBuyOrder(
791-
ctxt, &rfqrpc.AddAssetBuyOrderRequest{
792-
AssetSpecifier: &rfqrpc.AssetSpecifier{
793-
Id: &rfqrpc.AssetSpecifier_AssetId{
794-
AssetId: assetID,
795-
},
796-
},
797-
MinAssetAmount: assetAmount,
798-
Expiry: uint64(expiry.Unix()),
799-
PeerPubKey: dstRfqPeer.PubKey[:],
800-
TimeoutSeconds: timeoutSeconds,
801-
},
802-
)
803-
require.NoError(t, err)
804-
805-
var acceptedQuote *rfqrpc.PeerAcceptedBuyQuote
806-
switch r := resp.Response.(type) {
807-
case *rfqrpc.AddAssetBuyOrderResponse_AcceptedQuote:
808-
acceptedQuote = r.AcceptedQuote
809-
810-
case *rfqrpc.AddAssetBuyOrderResponse_InvalidQuote:
811-
t.Fatalf("peer %v sent back an invalid quote, "+
812-
"status: %v", r.InvalidQuote.Peer,
813-
r.InvalidQuote.Status.String())
814-
815-
case *rfqrpc.AddAssetBuyOrderResponse_RejectedQuote:
816-
t.Fatalf("peer %v rejected the quote, code: %v, "+
817-
"error message: %v", r.RejectedQuote.Peer,
818-
r.RejectedQuote.ErrorCode, r.RejectedQuote.ErrorMessage)
819790

820-
default:
821-
t.Fatalf("unexpected response type: %T", r)
822-
}
823-
824-
mSatPerUnit := acceptedQuote.AskPrice
825-
numMSats := lnwire.MilliSatoshi(assetAmount * mSatPerUnit)
826-
827-
t.Logf("Got quote for %d sats at %v msat/unit from peer %x with SCID "+
828-
"%d", numMSats.ToSatoshis(), mSatPerUnit, dstRfqPeer.PubKey[:],
829-
acceptedQuote.Scid)
830-
831-
peerChannels, err := dst.ListChannels(ctxt, &lnrpc.ListChannelsRequest{
832-
Peer: dstRfqPeer.PubKey[:],
791+
resp, err := dstTapd.AddInvoice(ctxt, &tchrpc.AddInvoiceRequest{
792+
AssetId: assetID,
793+
AssetAmount: assetAmount,
794+
InvoiceRequest: &lnrpc.Invoice{
795+
Memo: fmt.Sprintf("this is an asset invoice over "+
796+
"%d units", assetAmount),
797+
Expiry: timeoutSeconds,
798+
},
833799
})
834800
require.NoError(t, err)
835-
require.Len(t, peerChannels.Channels, 1)
836-
peerChannel := peerChannels.Channels[0]
837801

838-
ourPolicy, err := getOurPolicy(
839-
dst, peerChannel.ChanId, dstRfqPeer.PubKeyStr,
840-
)
802+
decodedInvoice, err := dst.DecodePayReq(ctxt, &lnrpc.PayReqString{
803+
PayReq: resp.InvoiceResult.PaymentRequest,
804+
})
841805
require.NoError(t, err)
842806

843-
hopHint := &lnrpc.HopHint{
844-
NodeId: dstRfqPeer.PubKeyStr,
845-
ChanId: acceptedQuote.Scid,
846-
FeeBaseMsat: uint32(ourPolicy.FeeBaseMsat),
847-
FeeProportionalMillionths: uint32(ourPolicy.FeeRateMilliMsat),
848-
CltvExpiryDelta: ourPolicy.TimeLockDelta,
849-
}
807+
mSatPerUnit := resp.AcceptedBuyQuote.AskPrice
808+
numMSats := lnwire.MilliSatoshi(assetAmount * mSatPerUnit)
850809

851-
invoice := &lnrpc.Invoice{
852-
Memo: fmt.Sprintf("this is an asset invoice over "+
853-
"%d units", assetAmount),
854-
ValueMsat: int64(numMSats),
855-
Expiry: int64(timeoutSeconds),
856-
RouteHints: []*lnrpc.RouteHint{
857-
{
858-
HopHints: []*lnrpc.HopHint{hopHint},
859-
},
860-
},
861-
}
810+
require.EqualValues(t, numMSats, decodedInvoice.NumMsat)
862811

863-
invoiceResp, err := dst.AddInvoice(ctxb, invoice)
864-
require.NoError(t, err)
812+
t.Logf("Got quote for %d sats at %v msat/unit from peer %x with SCID "+
813+
"%d", decodedInvoice.NumMsat, mSatPerUnit, dstRfqPeer.PubKey[:],
814+
resp.AcceptedBuyQuote.Scid)
865815

866-
return invoiceResp
816+
return resp.InvoiceResult
867817
}
868818

869819
func waitForSendEvent(t *testing.T,

0 commit comments

Comments
 (0)