Skip to content

accounts: add account payments subcommand#1316

Open
Cyberguru1 wants to merge 10 commits into
lightninglabs:masterfrom
Cyberguru1:account-payments
Open

accounts: add account payments subcommand#1316
Cyberguru1 wants to merge 10 commits into
lightninglabs:masterfrom
Cyberguru1:account-payments

Conversation

@Cyberguru1

Copy link
Copy Markdown
Contributor

closes #935

This PR implements the off-chain account payments history subcommand (litcli accounts payments) and its backend support in the Accounts gRPC subserver.

It adds database store methods for BoltStore and SQLStore to fetch account payment hashes in insertion order, exposes the AccountPayments RPC endpoint on the RPC server with support for paginated limits, offsets, reversing order, and concurrently fetching payment details from LND, and updates the release documentation.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request implements a new account payment history feature for the Accounts subserver. By adding a new gRPC endpoint and a corresponding CLI command, users can now efficiently query and paginate through the payment history of their off-chain accounts. The changes include necessary database store updates, permission configurations, and updated protobuf definitions to support this new functionality.

Highlights

  • New CLI Subcommand: Added the 'litcli accounts payments' subcommand to allow users to view the payment history of specific off-chain accounts.
  • RPC Endpoint Implementation: Introduced the 'AccountPayments' gRPC endpoint, supporting pagination, reversed ordering, and the inclusion of incomplete payments.
  • Database Store Updates: Updated both BoltStore and SQLStore to include methods for fetching account payment hashes in insertion order.
  • Testing and Documentation: Added comprehensive integration tests for the new RPC and updated the release notes to reflect the new functionality.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the AccountPayments gRPC endpoint and a corresponding litcli accounts payments subcommand to retrieve the detailed payment history of an off-chain account. The implementation includes backend store updates for both BoltDB and SQL, concurrent payment tracking from LND, and pagination/filtering options. Feedback on the changes highlights two main issues: first, the reversed ordering is implemented as reverse lexicographical rather than the documented reverse chronological order; second, the cleanup function returned by RawClientWithMacAuth is ignored, which could lead to resource leaks.

Comment thread accounts/rpcserver.go Outdated
Comment thread accounts/rpcserver.go Outdated
}

// Fetch the detailed payments concurrently from LND.
rawCtx, _, client := s.service.routerClient.RawClientWithMacAuth(ctx)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The cleanup/cancel function returned by RawClientWithMacAuth is ignored. Ignoring this function can lead to a context or resource leak. It should be captured and deferred.

\trawCtx, cleanup, client := s.service.routerClient.RawClientWithMacAuth(ctx)\n\tdefer cleanup()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RawClientWithMacAuth doesn't return a cleanup function, the second return value is a time.Duration representing the macaroon timeout. Reference

@Cyberguru1
Cyberguru1 force-pushed the account-payments branch 2 times, most recently from 81b3e1f to 69da0b5 Compare May 26, 2026 10:52

@ViktorT-11 ViktorT-11 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot again for the contribution @Cyberguru1 🔥🙏! I've added a few comments below as an initial review.

Comment thread accounts/rpcserver.go Outdated
Comment thread accounts/rpcserver.go Outdated
Comment thread accounts/rpcserver.go Outdated
Comment thread accounts/rpcserver.go Outdated
Comment thread accounts/rpcserver.go Outdated
Comment thread proto/lit-accounts.proto
Comment thread cmd/litcli/accounts.go Outdated
Comment thread accounts/rpcserver.go Outdated
Comment thread accounts/rpcserver.go
Comment thread accounts/store_test.go
@Cyberguru1
Cyberguru1 force-pushed the account-payments branch 2 times, most recently from 23fc956 to fe130cf Compare May 29, 2026 02:22
@Cyberguru1

Copy link
Copy Markdown
Contributor Author

Thanks a lot again for the contribution @Cyberguru1 🔥🙏! I've added a few comments below as an initial review.
Hello @ViktorT-11,

Thanks again for taking the time to review the PR. I’ve addressed the comments you pointed out and pushed the updates.

Regarding the failing CI, I investigated the issue and tried reproducing it locally multiple times, but the tests pass on my end. From the logs, it seems the failure happens while starting the Bob node, where the lit.macaroon file is not yet available when the RPC connection is attempted. It might need a re-run.

Looking forward to a follow-up review.

@Cyberguru1
Cyberguru1 requested a review from ViktorT-11 May 29, 2026 08:25
@Cyberguru1

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the litcli accounts payments subcommand and the corresponding AccountPayments gRPC endpoint to retrieve the detailed, paginated, and sorted off-chain payment history of a single account. The implementation spans store interface updates, Bolt and SQL backend support, concurrent payment tracking from LND, and comprehensive integration tests. Feedback on the changes highlights a potential integer overflow when converting req.IndexOffset to int32, fragile error handling where a single payment tracking failure aborts the entire RPC request, and the use of SELECT * in SQL queries which could break row scanning during future schema migrations.

Comment thread accounts/rpcserver.go
Comment thread accounts/rpcserver.go
Comment thread db/sqlc/accounts_custom.go Outdated
args = append(args, arg.Status.Int16)
}

query := "SELECT * FROM account_payments"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using SELECT * is an anti-pattern when manually scanning rows into a struct. If the database schema is updated in the future (e.g., by adding new columns to the account_payments table), rows.Scan will fail because the number of columns returned won't match the number of destination arguments. Explicitly listing the columns makes the query robust against future schema migrations.

Suggested change
query := "SELECT * FROM account_payments"
query := "SELECT account_id, hash, status, full_amount_msat FROM account_payments"

@ViktorT-11 ViktorT-11 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the updates @Cyberguru1! This is looking much better 🎉. I'm leaving a few more comments, but I think this PR is almost there now 🔥.

Comment thread db/sqlc/accounts_custom.go Outdated
Comment thread cmd/litcli/accounts.go Outdated
Comment thread accounts/rpcserver.go
Comment thread accounts/rpcserver.go
Comment thread cmd/litcli/accounts.go Outdated
Comment thread itest/litd_accounts_test.go
@Cyberguru1
Cyberguru1 force-pushed the account-payments branch 2 times, most recently from eba60ad to efded06 Compare June 2, 2026 06:24
@Cyberguru1

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the litcli accounts payments subcommand and the corresponding AccountPayments gRPC endpoint to fetch paginated, sorted off-chain payment histories for accounts. Feedback highlights a potential resource leak from an ignored cleanup function in rpcserver.go, a potential slice index overflow panic in the KV store pagination logic, and a risk of test flakiness in litd_accounts_test.go due to reusing a timed-out context for cleanup.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread accounts/rpcserver.go
errs []error
)

rawCtx, _, client := s.service.routerClient.RawClientWithMacAuth(ctx)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The second return value of RawClientWithMacAuth is a cleanup/cancel function. Ignoring it with _ can lead to resource leaks (such as unreleased context resources or metadata). It should be deferred to ensure proper cleanup.

Suggested change
rawCtx, _, client := s.service.routerClient.RawClientWithMacAuth(ctx)
rawCtx, cleanup, client := s.service.routerClient.RawClientWithMacAuth(ctx)
defer cleanup()

Comment thread accounts/store_kvdb.go
Comment on lines +476 to +479
end := offset + limit
if limit <= 0 || end > total {
end = total
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If offset + limit overflows int32, end becomes negative, which will cause a panic when slicing matchedPayments[offset:end]. Although total is practically limited by memory and slice size, we can make this calculation completely overflow-safe by avoiding the addition when limit is positive.

Suggested change
end := offset + limit
if limit <= 0 || end > total {
end = total
}
end := total
if limit > 0 && total-offset > limit {
end = offset + limit
}

Comment on lines +395 to +397
_, err = charlie.SettleInvoice(testCtx, &invoicesrpc.SettleInvoiceMsg{
Preimage: preimage[:],
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using testCtx (which has a timeout of defaultTimeout and is used for the entire duration of the test) for the final cleanup step SettleInvoice is risky. If the test runs slowly on CI, testCtx might already be expired by the time we reach the end of the test, causing the cleanup to fail and flaking the test. It is safer to use a fresh context with its own short timeout for this cleanup step.

Suggested change
_, err = charlie.SettleInvoice(testCtx, &invoicesrpc.SettleInvoiceMsg{
Preimage: preimage[:],
})
settleCtx, settleCancel := context.WithTimeout(context.Background(), 5*time.Second)
defer settleCancel()
_, err = charlie.SettleInvoice(settleCtx, &invoicesrpc.SettleInvoiceMsg{
Preimage: preimage[:],
})

@Cyberguru1
Cyberguru1 requested a review from ViktorT-11 June 2, 2026 06:48

@ViktorT-11 ViktorT-11 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally this looks good now! I realized though that the reverse flag doesn't really add any value in litd, and I've left a comment regarding that below. Really sorry for not catching this earlier!

If you agree with my reasoning, I'll also request a review from @bitromortac once that's been addressed, as this PR is generally in a great state now!

Comment thread cmd/litcli/accounts.go Outdated
Comment thread cmd/litcli/accounts.go Outdated
Comment thread db/sqlc/queries/accounts.sql Outdated
@Cyberguru1

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the litcli accounts payments subcommand and the corresponding AccountPayments gRPC endpoint to retrieve the detailed, paginated off-chain payment history of an account. The changes span the database stores (both BoltDB and SQL backends), the RPC server, CLI commands, and integration tests. The review feedback focuses on defensive programming and backend consistency, suggesting that negative offsets be handled safely and that limit/offset behaviors be normalized between the BoltDB and SQL implementations to prevent runtime panics or database errors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread accounts/store_kvdb.go
Comment on lines +467 to +471
// Apply pagination limits and offsets.
total := int32(len(matchedPayments))
if offset >= total {
return nil, nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Defensive programming: Ensure that offset is non-negative before using it for slicing matchedPayments. If a negative offset is passed to ListAccountPayments, it will cause a runtime panic due to out-of-bounds slice indexing.

Suggested change
// Apply pagination limits and offsets.
total := int32(len(matchedPayments))
if offset >= total {
return nil, nil
}
if offset < 0 {
offset = 0
}
total := int32(len(matchedPayments))
if offset >= total {
return nil, nil
}
References
  1. Ensure that invalid inputs or states are safely handled in all cases.

Comment thread accounts/store_sql.go
Comment on lines +803 to +808
dbPayments, err = db.AccountPaymentsPaginated(
ctx, sqlc.AccountPaymentsPaginatedParams{
AccountID: id,
Limit: limit,
Offset: offset,
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Defensive programming and backend consistency: Ensure that offset is non-negative and limit is handled correctly when it is less than or equal to 0. In BoltStore, a limit <= 0 returns all remaining rows, whereas in SQL, LIMIT 0 returns zero rows and a negative limit results in a database error in Postgres. Normalizing these values ensures consistent behavior across both database backends.

		if offset < 0 {
			offset = 0
		}
		if limit <= 0 {
			limit = 2147483647
		}

		var dbPayments []sqlc.AccountPayment
		dbPayments, err = db.AccountPaymentsPaginated(
			ctx, sqlc.AccountPaymentsPaginatedParams{
				AccountID: id,
				Limit:     limit,
				Offset:    offset,
			},
		)
References
  1. Ensure that invalid inputs or states are safely handled in all cases, and maintain behavioral consistency across different database backends.

@Cyberguru1
Cyberguru1 requested a review from ViktorT-11 June 2, 2026 17:46

@ViktorT-11 ViktorT-11 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice looks great, thanks a lot for the fixes 🔥🎉!

LGTM! I'll test this thoroughly tomorrow, but since the itest is quite thorough, I don't think I'll have any additional feedback after the testing round. Meanwhile, I'm requesting a review from @bitromortac.

Comment thread litrpc/lit-accounts.proto Outdated
@ViktorT-11
ViktorT-11 requested a review from bitromortac June 2, 2026 23:56
@lightninglabs-deploy

Copy link
Copy Markdown

@bitromortac: review reminder
@Cyberguru1, remember to re-request review from reviewers when ready

@bitromortac bitromortac left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice addition, the account payment is a useful endpoint. I left a few inline notes: one about how we handle a failed lookup and the rest are small polish and doc things.

One structural thought on the commits: it'd be nice to introduce the unit tests in the same commit as the code they exercise, so each commit stays self-contained.

Thanks for putting this together!

Comment thread accounts/rpcserver.go Outdated
Comment thread accounts/rpcserver.go
Comment thread accounts/rpcserver.go
Comment thread proto/lit-accounts.proto
Comment thread proto/lit-accounts.proto Outdated
Comment thread itest/litd_accounts_test.go
@Cyberguru1

Copy link
Copy Markdown
Contributor Author

Nice addition, the account payment is a useful endpoint. I left a few inline notes: one about how we handle a failed lookup and the rest are small polish and doc things.

One structural thought on the commits: it'd be nice to introduce the unit tests in the same commit as the code they exercise, so each commit stays self-contained.

Thanks for putting this together!

@bitromortac Thanks for the review! 🙏 Addressed the inline notes and folded the test commit into the code commit it exercises, so history's self-contained now.

Looking forward to the next review round! 🚀

@Cyberguru1

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new AccountPayments gRPC endpoint and a corresponding litcli accounts payments subcommand to retrieve the paginated and sorted off-chain payment history of a single account. This is supported by database updates (both Bolt and SQL backends) and concurrent queries to LND's TrackPaymentV2 API. Feedback on the implementation highlights several critical issues: a classic Go goroutine data race where the loop variable entry is captured by reference, and an overly strict error handling strategy where a single failed payment track aborts the entire RPC call. Additionally, defensive checks should be added to prevent runtime panics from negative offsets in the KV store, and concurrent tracking logic can be simplified by removing unused error slices and handling context cancellation more cleanly.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread accounts/rpcserver.go
Comment thread accounts/rpcserver.go
Comment thread accounts/rpcserver.go Outdated
Comment thread accounts/rpcserver.go
Comment thread accounts/rpcserver.go
Comment thread accounts/store_kvdb.go
@Cyberguru1
Cyberguru1 requested a review from bitromortac July 7, 2026 20:05

@bitromortac bitromortac left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the changes. Could you look into the thread #1316 (comment) about skipping pagination if we fail for a single query?

Comment thread accounts/store_kvdb.go Outdated
Comment thread docs/release-notes/release-notes-0.17.0.md Outdated
@Cyberguru1

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds the litcli accounts payments subcommand and the corresponding AccountPayments gRPC endpoint to retrieve paginated off-chain payment history for accounts, supported by both Bolt and SQL database backends. The review feedback highlights a critical issue in the pagination logic where offsets are calculated using successfully fetched LND payments instead of the store's retrieved entries, which can lead to duplicate results or stuck pagination. Additionally, the reviewer recommends adding defensive checks to prevent negative offsets in both database stores and updating the integration tests accordingly.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread accounts/rpcserver.go
Comment on lines +573 to +577
var firstIndexOffset, lastIndexOffset uint64
if len(finalPayments) > 0 {
firstIndexOffset = offset
lastIndexOffset = offset + uint64(len(finalPayments))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The pagination offsets firstIndexOffset and lastIndexOffset should be based on the number of elements retrieved from the store (paymentsFromStore), rather than the number of successfully fetched payments from LND (finalPayments).

If any payments are skipped (e.g., because they are not found in LND), basing the offsets on finalPayments causes two issues:

  1. Duplicate/Overlapping Results: The next query's offset will overlap with the current page, causing already-returned payments to be fetched and returned again.
  2. Stuck Pagination: If an entire page of payments is missing in LND, lastIndexOffset will be 0, making it impossible for the client to paginate past the dead zone to fetch subsequent valid payments.

Using paymentsFromStore ensures that pagination correctly and deterministically advances through the store's index space.

Suggested change
var firstIndexOffset, lastIndexOffset uint64
if len(finalPayments) > 0 {
firstIndexOffset = offset
lastIndexOffset = offset + uint64(len(finalPayments))
}
var firstIndexOffset, lastIndexOffset uint64
if len(paymentsFromStore) > 0 {
firstIndexOffset = offset
lastIndexOffset = offset + uint64(len(paymentsFromStore))
}

Comment thread itest/litd_accounts_test.go Outdated
Comment on lines +457 to +459
require.EqualValues(t.t, 3, paymentsResp.TotalNumPayments)
require.EqualValues(t.t, 0, paymentsResp.FirstIndexOffset)
require.EqualValues(t.t, 2, paymentsResp.LastIndexOffset)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Update the test assertion to expect 3 instead of 2 for LastIndexOffset to align with the pagination offset fix (which bases offsets on the store's index space rather than the successfully fetched LND payments).

Suggested change
require.EqualValues(t.t, 3, paymentsResp.TotalNumPayments)
require.EqualValues(t.t, 0, paymentsResp.FirstIndexOffset)
require.EqualValues(t.t, 2, paymentsResp.LastIndexOffset)
require.EqualValues(t.t, 3, paymentsResp.TotalNumPayments)
require.EqualValues(t.t, 0, paymentsResp.FirstIndexOffset)
require.EqualValues(t.t, 3, paymentsResp.LastIndexOffset)

Comment thread accounts/store_kvdb.go
Comment on lines +452 to +453
func (s *BoltStore) ListAccountPayments(ctx context.Context, id AccountID,
offset, limit int32) ([]*AccountPaymentEntry, error) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Add a defensive check to ensure that offset is non-negative. If a negative offset is passed to ListAccountPayments, it could cause a runtime panic due to out-of-bounds slice indexing.

func (s *BoltStore) ListAccountPayments(ctx context.Context, id AccountID,
	offset, limit int32) ([]*AccountPaymentEntry, error) {

	if offset < 0 {
		return nil, fmt.Errorf("offset cannot be negative")
	}

Comment thread accounts/store_sql.go
Comment on lines +787 to +788
func (s *SQLStore) ListAccountPayments(ctx context.Context, alias AccountID,
offset, limit int32) ([]*AccountPaymentEntry, error) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Add a defensive check to ensure that offset is non-negative. If a negative offset is passed to ListAccountPayments, it could cause database execution errors or unexpected behavior.

func (s *SQLStore) ListAccountPayments(ctx context.Context, alias AccountID,
	offset, limit int32) ([]*AccountPaymentEntry, error) {

	if offset < 0 {
		return nil, fmt.Errorf("offset cannot be negative")
	}

@Cyberguru1
Cyberguru1 requested a review from bitromortac July 17, 2026 08:27
@Cyberguru1
Cyberguru1 force-pushed the account-payments branch 2 times, most recently from 36e894e to 7259911 Compare July 21, 2026 12:22
@Cyberguru1

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the litcli accounts payments subcommand and the corresponding AccountPayments gRPC endpoint to retrieve paginated off-chain payment history for a single account. It adds database store support for both Bolt and SQL backends, along with comprehensive integration tests. The review feedback focuses on optimizing the concurrent payment tracking in the RPC server during context cancellation or timeouts. Specifically, it is recommended to return early when the context is cancelled to avoid redundant error logging and lock contention, and to cleanly propagate the context error after all goroutines have finished.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread accounts/rpcserver.go
Comment thread accounts/rpcserver.go
Comment thread accounts/rpcserver.go
Comment thread accounts/rpcserver.go
@Cyberguru1

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds the AccountPayments gRPC endpoint and corresponding litcli accounts payments subcommand to retrieve the off-chain payment history of an account. The changes include store implementations for both BoltDB and SQL backends supporting pagination and counting, along with comprehensive integration and unit tests. The review feedback highlights opportunities to improve error logging for concurrent operations, resolve an inconsistency in negative limit handling between store backends, and explicitly list columns instead of using SELECT * in SQL queries.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread accounts/rpcserver.go
Comment on lines +583 to +587
if len(errs) > 0 {
return nil, fmt.Errorf(
"failed to fetch payment details: %w", errs[0],
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

When multiple concurrent operations fail, returning only the first error from a non-deterministically ordered slice can make debugging difficult. It would be more informative to log all the errors that occurred.

Suggested change
if len(errs) > 0 {
return nil, fmt.Errorf(
"failed to fetch payment details: %w", errs[0],
)
}
if len(errs) > 0 {
log.Errorf("Encountered %d errors fetching payment details: %v", len(errs), errs)
return nil, fmt.Errorf(
"failed to fetch payment details: %w", errs[0],
)
}

Comment thread accounts/store_kvdb.go
Comment on lines +483 to +485
if limit < 0 || end > total {
end = total
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This implementation handles a negative limit by effectively treating it as 'no limit' (fetching all records from the offset). However, the SQL implementation in store_sql.go passes the limit directly to the database, which will likely result in an error for a negative value. This creates an inconsistency between the two store implementations.

While the RPC layer currently ensures the limit is non-negative, it would be best to make the store implementations consistent. I'd suggest either documenting this behavior in the Store interface and replicating it in the SQL store, or adding a check for a negative limit here and in the SQL store to return an error, as it's an invalid argument.

FROM account_payments;

-- name: AccountPaymentsPaginated :many
SELECT *

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better maintainability and to avoid accidentally fetching more data than needed if the table schema changes, it's a good practice to explicitly list the columns instead of using SELECT *.

SELECT account_id, hash, status, full_amount_msat

@bitromortac bitromortac left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the updates and additional test coverage 🎉. Due to a merge of another PR we need another rebase unfortunately 🙏.

Define the AccountPayments RPC endpoint and its request/response
messages in lit-accounts.proto. This endpoint allows querying
paginated payment history for a specific account.

Also update the frontend JS/TS proto sanitization script to map the
imported lnd.proto file to its flat directory path, fixing app build.
Add SQL queries to select account payments with pagination (limit and
offset), and a query to count the total payments for a given account.
Add sqlc queries to select account payment hashes from the database.
Implement the ListAccountPayments method in the SQLStore, allowing
retrieval of stored payment hashes for SQLite and Postgres backends.

Also define the AccountPaymentEntry helper struct in
accounts/interface.go to wrap payment hashes and details.
Implement ListAccountPayments in the Bolt-based kvdb account store.
The retrieved account payments are sorted in ascending lexicographical
order of their payment hash.
Introduce the ListAccountPayments and CountAccountPayments methods to
the accounts Store interface.

ListAccountPayments enables retrieval of a paginated list of payment
entries associated with a given account ID, supporting offset and
limit. CountAccountPayments returns the total number of payments
associated with the account.
Implement the AccountPayments handler on the Accounts RPC server.

The handler resolves accounts by ID or label, loads its payment hashes,
applies pagination constraints, and fetches complete payment details
concurrently from LND's TrackPaymentV2. It also returns pagination
metadata including the total count of payments.
Introduce the 'payments' subcommand under 'litcli accounts' to query
account payment history. Supports parameters for offset, page size
limits, and counting of total payments.
Register the /litrpc.Accounts/AccountPayments RPC endpoint in the
RequiredPermissions map, requiring read access on the account entity.
Add integration tests inside itest/litd_accounts_test.go to verify
retrieval of account payments against a running LND node, validating
correct responses for ID/label lookup, offsets, pagination limits,
and counting of total payments.
Add release notes for the new accounts payments CLI subcommand and
associated RPC endpoint to the v0.17.1 release notes document.
@Cyberguru1

Copy link
Copy Markdown
Contributor Author

LGTM, thanks for the updates and additional test coverage 🎉. Due to a merge of another PR we need another rebase unfortunately 🙏.

@bitromortac Thanks! 🙏

I've rebased the branch and resolved the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

accounts: Enable showing the history of payments through the accounts cli

4 participants