Skip to content

Commit 81bb790

Browse files
committed
cmd+itest: use new tapchannelrpc.AddInvoice RPC
1 parent 29fb8fe commit 81bb790

File tree

2 files changed

+50
-270
lines changed

2 files changed

+50
-270
lines changed

cmd/litcli/ln.go

Lines changed: 29 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,18 @@ import (
55
"context"
66
"crypto/rand"
77
"encoding/hex"
8-
"encoding/json"
98
"errors"
109
"fmt"
1110
"strconv"
12-
"time"
1311

1412
"github.com/lightninglabs/taproot-assets/asset"
15-
"github.com/lightninglabs/taproot-assets/rfqmsg"
13+
"github.com/lightninglabs/taproot-assets/rfq"
1614
"github.com/lightninglabs/taproot-assets/taprpc"
17-
"github.com/lightninglabs/taproot-assets/taprpc/rfqrpc"
1815
tchrpc "github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc"
1916
"github.com/lightningnetwork/lnd/cmd/commands"
2017
"github.com/lightningnetwork/lnd/lnrpc"
2118
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
2219
"github.com/lightningnetwork/lnd/lntypes"
23-
"github.com/lightningnetwork/lnd/lnwire"
2420
"github.com/lightningnetwork/lnd/record"
2521
"github.com/urfave/cli"
2622
"google.golang.org/grpc"
@@ -160,64 +156,6 @@ func fundChannel(c *cli.Context) error {
160156
return nil
161157
}
162158

163-
type assetBalance struct {
164-
AssetID string
165-
Name string
166-
LocalBalance uint64
167-
RemoteBalance uint64
168-
Channel *lnrpc.Channel
169-
}
170-
171-
type channelBalResp struct {
172-
Assets map[string]*assetBalance `json:"assets"`
173-
}
174-
175-
func computeAssetBalances(lnd lnrpc.LightningClient) (*channelBalResp, error) {
176-
ctxb := context.Background()
177-
openChans, err := lnd.ListChannels(
178-
ctxb, &lnrpc.ListChannelsRequest{},
179-
)
180-
if err != nil {
181-
return nil, fmt.Errorf("unable to fetch channels: %w", err)
182-
}
183-
184-
balanceResp := &channelBalResp{
185-
Assets: make(map[string]*assetBalance),
186-
}
187-
for _, openChan := range openChans.Channels {
188-
if len(openChan.CustomChannelData) == 0 {
189-
continue
190-
}
191-
192-
var assetData rfqmsg.JsonAssetChannel
193-
err = json.Unmarshal(openChan.CustomChannelData, &assetData)
194-
if err != nil {
195-
return nil, fmt.Errorf("unable to unmarshal asset "+
196-
"data: %w", err)
197-
}
198-
199-
for _, assetOutput := range assetData.Assets {
200-
assetID := assetOutput.AssetInfo.AssetGenesis.AssetID
201-
assetName := assetOutput.AssetInfo.AssetGenesis.Name
202-
203-
balance, ok := balanceResp.Assets[assetID]
204-
if !ok {
205-
balance = &assetBalance{
206-
AssetID: assetID,
207-
Name: assetName,
208-
Channel: openChan,
209-
}
210-
balanceResp.Assets[assetID] = balance
211-
}
212-
213-
balance.LocalBalance += assetOutput.LocalBalance
214-
balance.RemoteBalance += assetOutput.RemoteBalance
215-
}
216-
}
217-
218-
return balanceResp, nil
219-
}
220-
221159
var (
222160
assetIDFlag = cli.StringFlag{
223161
Name: "asset_id",
@@ -550,6 +488,8 @@ func addInvoice(ctx *cli.Context) error {
550488

551489
var (
552490
assetAmount uint64
491+
preimage []byte
492+
descHash []byte
553493
err error
554494
)
555495
switch {
@@ -565,167 +505,56 @@ func addInvoice(ctx *cli.Context) error {
565505
return fmt.Errorf("asset_amount argument missing")
566506
}
567507

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-
)
508+
if ctx.IsSet("preimage") {
509+
preimage, err = hex.DecodeString(ctx.String("preimage"))
510+
if err != nil {
511+
return fmt.Errorf("unable to parse preimage: %w", err)
512+
}
574513
}
575514

576-
lndConn, cleanup, err := connectClient(ctx, false)
515+
descHash, err = hex.DecodeString(ctx.String("description_hash"))
577516
if err != nil {
578-
return fmt.Errorf("unable to make rpc con: %w", err)
517+
return fmt.Errorf("unable to parse description_hash: %w", err)
579518
}
580519

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

585525
assetIDBytes, err := hex.DecodeString(assetIDStr)
586526
if err != nil {
587527
return fmt.Errorf("unable to decode assetID: %v", err)
588528
}
589529

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-
608530
var assetID asset.ID
609531
copy(assetID[:], assetIDBytes)
610532

611533
tapdConn, cleanup, err := connectTapdClient(ctx)
612534
if err != nil {
613535
return fmt.Errorf("error creating tapd connection: %w", err)
614536
}
615-
616537
defer cleanup()
617538

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,
641-
},
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-
},
539+
channelsClient := tchrpc.NewTaprootAssetChannelsClient(tapdConn)
540+
resp, err := channelsClient.AddInvoice(ctxb, &tchrpc.AddInvoiceRequest{
541+
AssetId: assetIDBytes,
542+
AssetAmount: assetAmount,
543+
InvoiceRequest: &lnrpc.Invoice{
544+
Memo: ctx.String("memo"),
545+
RPreimage: preimage,
546+
DescriptionHash: descHash,
547+
FallbackAddr: ctx.String("fallback_addr"),
548+
Expiry: expirySeconds,
549+
Private: ctx.Bool("private"),
550+
IsAmp: ctx.Bool("amp"),
701551
},
702-
}
703-
704-
invoiceResp, err := lndClient.AddInvoice(ctxb, invoice)
705-
if err != nil {
706-
return err
707-
}
708-
709-
printRespJSON(invoiceResp)
710-
711-
return nil
712-
}
713-
714-
func getOurPolicy(lndClient lnrpc.LightningClient, chanID uint64,
715-
remotePubKey string) (*lnrpc.RoutingPolicy, error) {
716-
717-
ctxb := context.Background()
718-
edge, err := lndClient.GetChanInfo(ctxb, &lnrpc.ChanInfoRequest{
719-
ChanId: chanID,
720552
})
721553
if err != nil {
722-
return nil, fmt.Errorf("unable to fetch channel: %w", err)
554+
return fmt.Errorf("error adding invoice: %w", err)
723555
}
724556

725-
policy := edge.Node1Policy
726-
if edge.Node1Pub == remotePubKey {
727-
policy = edge.Node2Policy
728-
}
557+
printRespJSON(resp)
729558

730-
return policy, nil
559+
return nil
731560
}

0 commit comments

Comments
 (0)