Skip to content

feat: add /api/v1/usertransactions endpoint#65

Open
xbuddhi wants to merge 1 commit into
mainfrom
feat/api-user-transactions
Open

feat: add /api/v1/usertransactions endpoint#65
xbuddhi wants to merge 1 commit into
mainfrom
feat/api-user-transactions

Conversation

@xbuddhi

@xbuddhi xbuddhi commented Jul 6, 2026

Copy link
Copy Markdown

Summary

Adds a new wallet-HMAC-authenticated endpoint so Send-API users can fetch a Telegram user's transaction history.

POST /api/v1/usertransactions — registered alongside the other send-API routes (gated behind IsAPISendEnabled()), using the same WalletHMACMiddleware auth as /api/v1/send and /api/v1/userbalance.

Request

{ "telegram_id": 123456789, "limit": 100, "offset": 0 }
  • limit defaults to 100, capped at 250 (reuses maxAnalyticsLimit)
  • offset capped at maxAnalyticsOffset

Response

{
  "success": true,
  "telegram_id": 123456789,
  "count": 1,
  "limit": 100,
  "offset": 0,
  "transactions": [
    {
      "id": 42, "time": "2026-07-06T12:00:00Z", "direction": "outgoing",
      "from_id": 123456789, "to_id": 987654321,
      "from_user": "@alice", "to_user": "@bob",
      "type": "api_send", "amount": 1000, "amount_lkr": "...",
      "memo": "...", "success": true
    }
  ],
  "message": "Transactions retrieved successfully"
}

Behavior

  • Queries internal bot transactions where the user is sender or recipient (from_id = ? OR to_id = ?), newest first.
  • Each row gets a direction field (incoming/outgoing) relative to the queried user.
  • Unknown user returns 200 with success:false and an empty array — same pattern as /api/v1/userbalance — so callers can distinguish "no user" from "no transactions".
  • Returns internal bot transactions only (tips, sends, api_sends); external LNbits Lightning payments remain covered by the analytics API's GetUserTransactionHistory.

HMAC signing

Same scheme as the rest of the send API: POST/api/v1/usertransactions{timestamp}{body}.

Test plan

  • go build ./... passes
  • go vet ./internal/api/... passes
  • Manual: sign a request with a whitelisted wallet secret and verify a known user's transactions return

Summary by CodeRabbit

  • New Features

    • Added a new endpoint for viewing a user’s transaction history.
    • Supports pagination and returns transaction details such as direction, amount, memo, participants, and status.
    • The endpoint is available when API sending is enabled.
  • Bug Fixes

    • Improved validation and error handling for invalid requests and missing user IDs.
    • Ensures transaction results are returned in a consistent, paginated order.

…tion history

Wallet-HMAC authenticated (same auth as the send API). Returns internal
bot transactions for a given Telegram user ID, filtered by sender or
recipient, newest first, with limit/offset pagination and a per-tx
direction (incoming/outgoing) relative to the queried user.
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new /api/v1/usertransactions API endpoint that returns a user's transaction history by Telegram ID with pagination. Introduces request/response DTOs, a handler that validates input, verifies user existence, queries the database, and maps results. Registers the route in main.go under wallet-HMAC protection.

Changes

User Transactions Endpoint

Layer / File(s) Summary
DTOs and request validation
internal/api/user_transactions.go
Defines UserTransactionsRequest, UserTransactionData, and UserTransactionsResponse structs; decodes JSON body, validates telegram_id, and applies default/capped limit/offset.
User lookup and transaction query
internal/api/user_transactions.go
Verifies the user exists via telegram.GetUserByTelegramID; queries transactions filtered by from_id/to_id with ordering and pagination; maps DB rows to response data (direction, formatted amount/time); returns JSON success or error responses.
Route registration
main.go
Registers a wallet-HMAC protected POST route for /api/v1/usertransactions in startApiServer, delegating to apiService.UserTransactions, gated by IsAPISendEnabled.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Service as Service.UserTransactions
  participant Telegram as telegram.GetUserByTelegramID
  participant DB as Database

  Client->>Service: POST /api/v1/usertransactions
  Service->>Service: decode JSON, validate telegram_id, apply limit/offset
  Service->>Telegram: GetUserByTelegramID(telegram_id)
  Telegram-->>Service: user or error
  alt user not found
    Service-->>Client: success=false, empty transactions
  else user found
    Service->>DB: query transactions by from_id/to_id with pagination
    DB-->>Service: transaction rows
    Service->>Service: map rows to UserTransactionData
    Service-->>Client: success=true, transactions list
  end
Loading

Possibly related PRs

  • CeyLabs/BitcoinDeepaBot#50: Both PRs modify startApiServer to register new /api/v1 endpoints protected by the wallet-HMAC middleware, wiring apiService handlers.

Suggested labels: Review effort 4/5, Possible security concern

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding the /api/v1/usertransactions endpoint.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/api-user-transactions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@xbuddhi xbuddhi requested a review from helloscoopa July 6, 2026 13:05

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (2)
internal/api/user_transactions.go (2)

65-71: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded default limit not tied to a named constant.

limit defaults to a bare 100, while the cap uses the named maxAnalyticsLimit constant. Consider a named constant (e.g. defaultTransactionsLimit) for consistency and to make the default/cap relationship self-documenting.

♻️ Suggested tweak
+const defaultUserTransactionsLimit = 100
+
 	limit := req.Limit
 	if limit <= 0 {
-		limit = 100
+		limit = defaultUserTransactionsLimit
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/api/user_transactions.go` around lines 65 - 71, The transaction
limit fallback in the request handling logic uses a bare 100, while the upper
bound already relies on maxAnalyticsLimit. Introduce a named constant for the
default in the same area as the limit normalization in the user transaction
handler, and use it when limit <= 0 so the default and cap are both
self-documenting and consistent.

99-103: 🚀 Performance & Scalability | 🔵 Trivial

Consider indexing from_id/to_id for this query pattern.

An OR-based filter across two columns generally can't be satisfied efficiently by a single composite index and often forces a full scan as the transactions table grows. If this table doesn't already have indexes on from_id and to_id, this endpoint could become a slow query under load.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/api/user_transactions.go` around lines 99 - 103, The query in the
transactions lookup uses an OR filter on from_id and to_id, so add dedicated
indexes for both columns in the Transactions model/migration rather than
changing the query logic. Update the schema definition associated with
s.Bot.DB.Transactions, ensuring from_id and to_id are individually indexed so
the Where("from_id = ? OR to_id = ?") pattern can use them efficiently.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/api/user_transactions.go`:
- Around line 65-71: The transaction limit fallback in the request handling
logic uses a bare 100, while the upper bound already relies on
maxAnalyticsLimit. Introduce a named constant for the default in the same area
as the limit normalization in the user transaction handler, and use it when
limit <= 0 so the default and cap are both self-documenting and consistent.
- Around line 99-103: The query in the transactions lookup uses an OR filter on
from_id and to_id, so add dedicated indexes for both columns in the Transactions
model/migration rather than changing the query logic. Update the schema
definition associated with s.Bot.DB.Transactions, ensuring from_id and to_id are
individually indexed so the Where("from_id = ? OR to_id = ?") pattern can use
them efficiently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ddcd8a3c-deae-4fec-8617-f5309fcee553

📥 Commits

Reviewing files that changed from the base of the PR and between 76e2bfb and b1c32ee.

📒 Files selected for processing (2)
  • internal/api/user_transactions.go
  • main.go

@helloscoopa helloscoopa 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.

LGTM!

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.

2 participants