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
122 changes: 122 additions & 0 deletions cmd/commands/rfq.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package commands

import (
"encoding/hex"
"fmt"

"github.com/lightninglabs/taproot-assets/taprpc/rfqrpc"
Expand All @@ -15,6 +16,7 @@ var rfqCommands = []cli.Command{
Category: "Channels",
Subcommands: []cli.Command{
acceptedQuotesCommand,
forwardsCommand,
},
},
}
Expand Down Expand Up @@ -45,3 +47,123 @@ func acceptedQuotes(ctx *cli.Context) error {

return nil
}

const (
minTimestampName = "min_timestamp"
maxTimestampName = "max_timestamp"
peerName = "peer"
)

var forwardsCommand = cli.Command{
Name: "forwards",
ShortName: "f",
Usage: "query historical RFQ asset forwards",
Description: `
Query historical records of asset forwards that were executed by the RFQ
system. This provides accounting and record-keeping for edge nodes that
perform asset swaps. Forwards are recorded when opened and updated when
they settle or fail.
`,
Flags: []cli.Flag{
cli.Uint64Flag{
Name: minTimestampName,
Usage: "minimum Unix timestamp in seconds; only " +
"forwards opened at or after this time are " +
"returned",
},
cli.Uint64Flag{
Name: maxTimestampName,
Usage: "maximum Unix timestamp in seconds; only " +
"forwards opened at or before this time are " +
"returned",
},
cli.StringFlag{
Name: peerName,
Usage: "filter by peer public key",
},
cli.StringFlag{
Name: assetIDName,
Usage: "filter by asset ID",
},
cli.StringFlag{
Name: groupKeyName,
Usage: "filter by asset group key",
},
cli.IntFlag{
Name: limitName,
Usage: "maximum number of records to return",
Value: 100,
},
cli.IntFlag{
Name: offsetName,
Usage: "number of records to skip",
Value: 0,
},
},
Action: queryForwards,
}

func queryForwards(ctx *cli.Context) error {
ctxc := getContext()
client, cleanUp := getRfqClient(ctx)
defer cleanUp()

req := &rfqrpc.QueryRfqForwardsRequest{
MinTimestamp: ctx.Uint64(minTimestampName),
MaxTimestamp: ctx.Uint64(maxTimestampName),
Limit: int32(ctx.Int(limitName)),
Offset: int32(ctx.Int(offsetName)),
}

// Parse peer if provided.
if peerStr := ctx.String(peerName); peerStr != "" {
peerBytes, err := hex.DecodeString(peerStr)
if err != nil {
return fmt.Errorf("invalid peer hex: %w", err)
}
req.Peer = peerBytes
}

// Parse asset specifier if provided.
assetIDStr := ctx.String(assetIDName)
groupKeyStr := ctx.String(groupKeyName)

// Check for mutual exclusivity.
if assetIDStr != "" && groupKeyStr != "" {
return fmt.Errorf("cannot specify both --%s and --%s",
assetIDName, groupKeyName)
}

if assetIDStr != "" || groupKeyStr != "" {
req.AssetSpecifier = &rfqrpc.AssetSpecifier{}

if assetIDStr != "" {
assetID, err := hex.DecodeString(assetIDStr)
if err != nil {
return fmt.Errorf("invalid asset ID hex: %w",
err)
}
req.AssetSpecifier.Id = &rfqrpc.AssetSpecifier_AssetId{
AssetId: assetID,
}
} else if groupKeyStr != "" {
groupKey, err := hex.DecodeString(groupKeyStr)
if err != nil {
return fmt.Errorf("invalid group key hex: %w",
err)
}
req.AssetSpecifier.Id = &rfqrpc.AssetSpecifier_GroupKey{
GroupKey: groupKey,
}
}
}

resp, err := client.QueryRfqForwards(ctxc, req)
if err != nil {
return fmt.Errorf("unable to query forwards: %w", err)
}

printRespJSON(resp)

return nil
}
24 changes: 24 additions & 0 deletions docs/release-notes/release-notes-0.8.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,27 @@

## Functional Enhancements

- [RFQ Forward History Tracking](https://github.com/lightninglabs/taproot-assets/pull/1921):
Routing nodes can now track and query historical RFQ asset forward events.
When a node successfully routes an asset payment, the forward event is logged.
This provides edge nodes with an audit trail of their swap activity.

## RPC Additions

- [QueryRfqForwards RPC](https://github.com/lightninglabs/taproot-assets/pull/1921):
New RPC endpoint `rfqrpc.QueryRfqForwards` allows querying historical RFQ
forward events with filtering and pagination support. Filters include:
timestamp range (min/max), peer public key, asset ID, and asset group key.

## tapcli Additions

- [tapcli rfqrpc forwards](https://github.com/lightninglabs/taproot-assets/pull/1921):
New CLI command `tapcli rfqrpc forwards` (alias: `f`) to query RFQ forward
history. Supports flags for filtering by timestamp (`--min-timestamp`,
`--max-timestamp`), peer (`--peer`), asset ID (`--asset-id`), and asset
group key (`--group-key`). Includes pagination support via `--limit` and
`--offset` flags.

# Improvements

## Functional Updates
Expand Down Expand Up @@ -112,8 +129,15 @@
creation hits an unreachable mailbox courier with the upfront connection
check skipped, ensuring mailbox subscription failures do not crash tapd.

- [RFQ Forwards Integration Test](https://github.com/lightninglabs/taproot-assets/pull/1921):
New integration test `testRfqForwardHistory` verifies that RFQ forwards are
properly logged when routing asset payments.

## Database

- [rfq_forwards table](https://github.com/lightninglabs/taproot-assets/pull/1921):
New database table `rfq_forwards` stores historical RFQ forward events.

## Code Health

## Tooling and Documentation
Expand Down
Loading
Loading