11package commands
22
33import (
4+ "encoding/hex"
45 "fmt"
56
67 "github.com/lightninglabs/taproot-assets/taprpc/rfqrpc"
@@ -15,6 +16,7 @@ var rfqCommands = []cli.Command{
1516 Category : "Channels" ,
1617 Subcommands : []cli.Command {
1718 acceptedQuotesCommand ,
19+ forwardsCommand ,
1820 },
1921 },
2022}
@@ -45,3 +47,123 @@ func acceptedQuotes(ctx *cli.Context) error {
4547
4648 return nil
4749}
50+
51+ const (
52+ minTimestampName = "min_timestamp"
53+ maxTimestampName = "max_timestamp"
54+ peerName = "peer"
55+ )
56+
57+ var forwardsCommand = cli.Command {
58+ Name : "forwards" ,
59+ ShortName : "f" ,
60+ Usage : "query historical RFQ asset forwards" ,
61+ Description : `
62+ Query historical records of asset forwards that were executed by the RFQ
63+ system. This provides accounting and record-keeping for edge nodes that
64+ perform asset swaps. Forwards are recorded when opened and updated when
65+ they settle or fail.
66+ ` ,
67+ Flags : []cli.Flag {
68+ cli.Uint64Flag {
69+ Name : minTimestampName ,
70+ Usage : "minimum Unix timestamp in seconds; only " +
71+ "forwards opened at or after this time are " +
72+ "returned" ,
73+ },
74+ cli.Uint64Flag {
75+ Name : maxTimestampName ,
76+ Usage : "maximum Unix timestamp in seconds; only " +
77+ "forwards opened at or before this time are " +
78+ "returned" ,
79+ },
80+ cli.StringFlag {
81+ Name : peerName ,
82+ Usage : "filter by peer public key" ,
83+ },
84+ cli.StringFlag {
85+ Name : assetIDName ,
86+ Usage : "filter by asset ID" ,
87+ },
88+ cli.StringFlag {
89+ Name : groupKeyName ,
90+ Usage : "filter by asset group key" ,
91+ },
92+ cli.IntFlag {
93+ Name : limitName ,
94+ Usage : "maximum number of records to return" ,
95+ Value : 100 ,
96+ },
97+ cli.IntFlag {
98+ Name : offsetName ,
99+ Usage : "number of records to skip" ,
100+ Value : 0 ,
101+ },
102+ },
103+ Action : queryForwards ,
104+ }
105+
106+ func queryForwards (ctx * cli.Context ) error {
107+ ctxc := getContext ()
108+ client , cleanUp := getRfqClient (ctx )
109+ defer cleanUp ()
110+
111+ req := & rfqrpc.QueryRfqForwardsRequest {
112+ MinTimestamp : ctx .Uint64 (minTimestampName ),
113+ MaxTimestamp : ctx .Uint64 (maxTimestampName ),
114+ Limit : int32 (ctx .Int (limitName )),
115+ Offset : int32 (ctx .Int (offsetName )),
116+ }
117+
118+ // Parse peer if provided.
119+ if peerStr := ctx .String (peerName ); peerStr != "" {
120+ peerBytes , err := hex .DecodeString (peerStr )
121+ if err != nil {
122+ return fmt .Errorf ("invalid peer hex: %w" , err )
123+ }
124+ req .Peer = peerBytes
125+ }
126+
127+ // Parse asset specifier if provided.
128+ assetIDStr := ctx .String (assetIDName )
129+ groupKeyStr := ctx .String (groupKeyName )
130+
131+ // Check for mutual exclusivity.
132+ if assetIDStr != "" && groupKeyStr != "" {
133+ return fmt .Errorf ("cannot specify both --%s and --%s" ,
134+ assetIDName , groupKeyName )
135+ }
136+
137+ if assetIDStr != "" || groupKeyStr != "" {
138+ req .AssetSpecifier = & rfqrpc.AssetSpecifier {}
139+
140+ if assetIDStr != "" {
141+ assetID , err := hex .DecodeString (assetIDStr )
142+ if err != nil {
143+ return fmt .Errorf ("invalid asset ID hex: %w" ,
144+ err )
145+ }
146+ req .AssetSpecifier .Id = & rfqrpc.AssetSpecifier_AssetId {
147+ AssetId : assetID ,
148+ }
149+ } else if groupKeyStr != "" {
150+ groupKey , err := hex .DecodeString (groupKeyStr )
151+ if err != nil {
152+ return fmt .Errorf ("invalid group key hex: %w" ,
153+ err )
154+ }
155+ req .AssetSpecifier .Id = & rfqrpc.AssetSpecifier_GroupKey {
156+ GroupKey : groupKey ,
157+ }
158+ }
159+ }
160+
161+ resp , err := client .QueryRfqForwards (ctxc , req )
162+ if err != nil {
163+ return fmt .Errorf ("unable to query forwards: %w" , err )
164+ }
165+
166+ printRespJSON (resp )
167+
168+ return nil
169+ }
0 commit comments