Skip to content

feat: add backend proxy for Horizon transaction history - #278

Merged
jhayniffy merged 1 commit into
InsurNiffy:mainfrom
code-with-flex:feat/horizon
Mar 29, 2026
Merged

feat: add backend proxy for Horizon transaction history#278
jhayniffy merged 1 commit into
InsurNiffy:mainfrom
code-with-flex:feat/horizon

Conversation

@code-with-flex

Copy link
Copy Markdown
Contributor

Description

Adds a backend proxy for Horizon transaction history scoped to a wallet address. The proxy keeps Horizon API keys server-side, filters the response to payment-relevant operation types only, applies per-wallet sliding-window rate limiting backed by Redis, and caches filtered results for 15 seconds to reduce Horizon load while staying within the finality lag window.

Related Issue

Closes #204

Changes Made

  • horizon/horizon.service.ts — Fetches from the configured HORIZON_URL (resolved via existing NetworkConfig), strips _links, DEX fields, account-management fields, and all other internal Horizon metadata. Caches filtered responses for 15 seconds in Redis. Validates account address format before making any outbound request.
  • horizon/filters/horizon-field.filter.ts — Pure function that filters to payment, path_payment_strict_receive, path_payment_strict_send, and create_account operation types, and allowlists only the fields required by the frontend. Includes inline documentation of every forwarded and stripped field.
  • horizon/dto/horizon-transaction.dto.ts — Response shape with JSDoc explaining each forwarded field, why others are stripped, and the Horizon finality lag (~5–15 seconds ingestion delay after ledger close) with guidance for the frontend.
  • horizon/horizon-rate-limit.service.ts — Sliding-window rate limiter using Redis sorted sets: 30 requests per 60-second window per wallet address. Fails open if Redis is unavailable.
  • horizon/horizon.controller.tsGET /api/horizon/transactions?account=<address> with optional cursor and limit params. Returns 429 with Retry-After header on rate limit breach. Never includes API keys in response headers or error bodies.
  • horizon/horizon.module.ts — Module wiring CacheModule (for RedisService), controller, and providers.
  • app.module.tsHorizonModule added to imports.
  • horizon/__tests__/horizon.integration.spec.ts — Integration tests using mocked fetch and a mocked RedisService. No real Horizon credentials needed.

Acceptance Criteria

  • Frontend receives filtered transaction data without direct Horizon access
  • Rate limits prevent abuse without blocking normal usage patterns (30 req/60 s per wallet, fails open on Redis unavailability)
  • Mocked integration tests pass in CI without real Horizon credentials
  • Horizon API keys are never present in response headers or error bodies
  • Horizon finality lag is documented in the DTO file with frontend guidance

@drips-wave

drips-wave Bot commented Mar 29, 2026

Copy link
Copy Markdown

@code-with-flex Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@jhayniffy
jhayniffy merged commit 4add46e into InsurNiffy:main Mar 29, 2026
1 of 6 checks passed
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.

Backend — Horizon proxy: filtered transaction history without exposing API keys

2 participants