diff --git a/cmd/loop/lsat.go b/cmd/loop/lsat.go new file mode 100644 index 0000000..88868c9 --- /dev/null +++ b/cmd/loop/lsat.go @@ -0,0 +1,82 @@ +package main + +import ( + "bytes" + "context" + "encoding/hex" + "fmt" + "time" + + "github.com/lightninglabs/loop/looprpc" + "github.com/lightninglabs/loop/lsat" + "github.com/urfave/cli" + "gopkg.in/macaroon.v2" +) + +type printableToken struct { + ID string `json:"id"` + ValidUntil string `json:"valid_until"` + BaseMacaroon string `json:"base_macaroon"` + PaymentHash string `json:"payment_hash"` + PaymentPreimage string `json:"payment_preimage"` + AmountPaid int64 `json:"amount_paid_msat"` + RoutingFeePaid int64 `json:"routing_fee_paid_msat"` + TimeCreated string `json:"time_created"` + Expired bool `json:"expired"` + FileName string `json:"file_name"` +} + +var listAuthCommand = cli.Command{ + Name: "listauth", + Usage: "list all LSAT tokens", + Description: "Shows a list of all LSAT tokens that loopd has paid for", + Action: listAuth, +} + +func listAuth(ctx *cli.Context) error { + client, cleanup, err := getClient(ctx) + if err != nil { + return err + } + defer cleanup() + + resp, err := client.GetLsatTokens( + context.Background(), &looprpc.TokensRequest{}, + ) + if err != nil { + return err + } + + tokens := make([]*printableToken, len(resp.Tokens)) + for i, t := range resp.Tokens { + + mac := &macaroon.Macaroon{} + err := mac.UnmarshalBinary(t.BaseMacaroon) + if err != nil { + return fmt.Errorf("unable to unmarshal macaroon: %v", + err) + } + id, err := lsat.DecodeIdentifier(bytes.NewReader(mac.Id())) + if err != nil { + return fmt.Errorf("unable to decode macaroon ID: %v", + err) + } + tokens[i] = &printableToken{ + ID: hex.EncodeToString(id.TokenID[:]), + ValidUntil: "", + BaseMacaroon: hex.EncodeToString(t.BaseMacaroon), + PaymentHash: hex.EncodeToString(t.PaymentHash), + PaymentPreimage: hex.EncodeToString(t.PaymentPreimage), + AmountPaid: t.AmountPaidMsat, + RoutingFeePaid: t.RoutingFeePaidMsat, + TimeCreated: time.Unix(t.TimeCreated, 0).Format( + time.RFC3339, + ), + Expired: t.Expired, + FileName: t.StorageName, + } + } + + printJSON(tokens) + return nil +} diff --git a/cmd/loop/main.go b/cmd/loop/main.go index 17f3fed..90c895b 100644 --- a/cmd/loop/main.go +++ b/cmd/loop/main.go @@ -1,6 +1,8 @@ package main import ( + "bytes" + "encoding/json" "errors" "fmt" "os" @@ -30,6 +32,21 @@ var ( defaultSwapWaitTime = 30 * time.Minute ) +func printJSON(resp interface{}) { + b, err := json.Marshal(resp) + if err != nil { + fatal(err) + } + + var out bytes.Buffer + err = json.Indent(&out, b, "", "\t") + if err != nil { + fatal(err) + } + out.WriteString("\n") + _, _ = out.WriteTo(os.Stdout) +} + func printRespJSON(resp proto.Message) { jsonMarshaler := &jsonpb.Marshaler{ EmitDefaults: true, @@ -65,7 +82,7 @@ func main() { } app.Commands = []cli.Command{ loopOutCommand, loopInCommand, termsCommand, - monitorCommand, quoteCommand, + monitorCommand, quoteCommand, listAuthCommand, } err := app.Run(os.Args)