Repository navigation
feat(backend): async campaign exports, deposit watcher, fraud detection and API docs - #1397
Merged
joelpeace48-cell merged 1 commit intoSep 26, 2026
Conversation
…er and API docs - Campaign export worker: POST /campaigns/:id/exports queues a CSV/JSON export on the durable job queue and returns 202; poll /campaigns/:id/exports/:jobId for status and the download URL. Export queries are shared with the synchronous endpoint. - Horizon deposit watcher: streams payments for OPERATOR_DEPOSIT_ACCOUNTS, records incoming reward-token deposits idempotently, persists cursors and reconnects with backoff. - Fraud detection: flags clusters of distinct accounts signing up from one IP subnet or proxy exit node, with an admin review API. - API docs: OpenAPI document generated from openapi.yaml plus the Zod request schemas, served with Swagger UI at /docs/api.
|
@leojay-net 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! 🚀 |
| handleRecord(record, account); | ||
| } catch (err) { | ||
| metrics.errors++; | ||
| logger.error?.({ err, account }, 'depositWatcher:handle_error'); |
| onerror: (/** @type {unknown} */ err) => { | ||
| metrics.errors++; | ||
| state.connected = false; | ||
| logger.warn?.({ err, account }, 'depositWatcher:stream_error'); |
| }); | ||
| } catch (err) { | ||
| metrics.errors++; | ||
| logger.error?.({ err, account }, 'depositWatcher:connect_failed'); |
joelpeace48-cell
merged commit Sep 26, 2026
d5284bd
into
FinesseStudioLab:main
9 of 25 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Backend work for the growth engine and analytics area, one feature per issue. Details are in
docs/BACKEND_ANALYTICS_AND_GROWTH.md.Campaign export analytics worker
POST /api/v1/campaigns/:id/exports(formatcsv/json, optionalfrom/to) creates anexport_jobsrow, queues it and returns202with ajobIdandstatusUrl, so heavy exports no longer run inside the HTTP request.GET /campaigns/:id/exports/:jobIdreportsqueued → running → completed | failed(withdownloadUrlwhen done);GET /campaigns/:id/exportslists recent jobs.jobs/campaignExportWorker.json the existing durable job queue (retries with backoff, dead-lettering) and uploads through the configured storage adapter. Redelivery of a finished job is a no-op.services/campaignExportData.jsand are shared with the existing synchronousGET /campaigns/:id/exportendpoint, which behaves as before.queue.enqueue, so it can be moved to BullMQ later without changing the API.Stellar Horizon account balance watcher
services/horizonDepositWatcher.jsstreams payments (Horizon SSE) for each address inOPERATOR_DEPOSIT_ACCOUNTSand records incoming deposits of the reward asset (REWARD_TOKEN_CODE/REWARD_TOKEN_ISSUER, default XLM). It also handlescreate_accountand path payments, and ignores outgoing payments and transfers between watched accounts.GET /api/v1/operator/deposits,GET /operator/deposits/:txHash(verify a deposit by transaction hash) andGET /operator/watcher/status. The watcher only starts when accounts are configured and jobs are enabled.OpenAPI documentation generator and Swagger UI
GET /docs/apiand the generated document atGET /docs/api/openapi.json.openapi.yaml(always wins), component schemas derived from the Zod request schemas inschemas.js(so documented bodies match runtime validation), and path items for the router-mounted endpoints added here. It is validated with the OpenAPI parser andopenapi.yamlitself is unchanged, so the generated SDK is unaffected. The existing/docsUI keeps working.Automated fraud detection for anomalous IP clusters
/24IPv4,/64IPv6 — only the prefix is stored). When distinct accounts from one prefix reachFRAUD_SUBNET_THRESHOLDwithinFRAUD_WINDOW_HOURS, or accounts share an address onFRAUD_PROXY_EXIT_LIST(IPs or IPv4 CIDRs), a flag is raised.GET /api/v1/admin/fraud/flagsandPATCH /admin/fraud/flags/:id.Also adds migrations 041–043, the new env vars to
backend/.env.example, and a changelog entry.Testing
The new tests cover the subnet/proxy rules and windowing, deposit parsing/idempotency/cursor
resume/reconnect, the export worker (success, retry, failure, redelivery) and its HTTP flow, and
the generated docs endpoints.
routes/campaignExport.test.jshas 3 failing tests that areidentical with and without this change.
Closes #1260
Closes #1261
Closes #1259
Closes #1258