Skip to content

feat: add idempotent pledge endpoint with Idempotency-Key (#560) - #1

Open
David-Adegboyega wants to merge 78 commits into
mainfrom
feat/560-idempotent-pledge-endpoint
Open

feat: add idempotent pledge endpoint with Idempotency-Key (#560)#1
David-Adegboyega wants to merge 78 commits into
mainfrom
feat/560-idempotent-pledge-endpoint

Conversation

@David-Adegboyega

Copy link
Copy Markdown
Owner

Summary

Implement idempotent pledge creation using the Idempotency-Key header.

Changes

  • Added idempotency middleware (middleware/idempotencyMiddleware.ts)
  • Added 24-hour response caching using Redis when available, with in-memory LRU fallback
  • Prevented duplicate database writes for cached requests
  • Added comprehensive tests in api.test.ts
  • Updated OpenAPI documentation in openapi.ts
  • Updated README.md and CHANGELOG.md

Testing

npm test

Pre-existing test failures (11 files) remain unchanged; no new regressions introduced.

Security

  • Cache keys are namespaced by API key (user identity), campaign ID, and idempotency key, preventing cross-user cache access.
  • Duplicate writes are prevented by returning cached responses before reaching the database layer.
  • Authentication and authorisation remain unchanged; no sensitive data exposed through cache lookups.

Performance

  • O(1) cache lookups using Redis (production) or in-memory LRU cache (dev/test).
  • Minimal network calls; Redis writes fail silently to avoid blocking the response.
  • No extra database work for duplicate requests with the same idempotency key.

Related Issue

Closes ritik4ever#560

cyber-excel10 and others added 30 commits July 24, 2026 16:11
- Fixed import path in seedDeterministic.ts (../db → ./db)
- Added documentation to README under 'Run locally' section
- npm run seed now works with --count flag support

Fixes ritik4ever#230
Bumps [soroban-sdk](https://github.com/stellar/rs-soroban-sdk) from 21.7.7 to 27.0.2.
- [Release notes](https://github.com/stellar/rs-soroban-sdk/releases)
- [Commits](stellar/rs-soroban-sdk@v21.7.7...v27.0.2)

---
updated-dependencies:
- dependency-name: soroban-sdk
  dependency-version: 27.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Closes ritik4ever#583

The POST /api/campaigns/:id/claim endpoint now checks if the campaign
has already been claimed before processing. If claimedAt is already
set, the endpoint returns a 409 Conflict with CAMPAIGN_ALREADY_CLAIMED
error code.

Changes:
- campaignStore.ts: reconcileOnChainClaim throws toServiceError with
  409 / CAMPAIGN_ALREADY_CLAIMED instead of silently returning campaign
- api.test.ts: duplicate claim test expects 409 with error code/message
  verification, plus history check (1 claim event before/after)
- mutation.test.ts: "second claim is idempotent" updated to assert 409
  throw with "Campaign already claimed" message
Replace stale integration-test-only deliverables doc with a
comprehensive project-wide checklist covering backend, frontend,
contracts, testing, CI/CD, infrastructure, and documentation.

- Mark all confirmed deliverables as completed
- Flag integration test suite as empty (utils exist, tests pending)
- Flag contributor summary frontend wiring as incomplete
- Add effort estimates for all planned items

Close ritik4ever#662
… toast (ritik4ever#610)

- Reset pledgeAmount to default ('25') and pledgeToken to empty after successful onPledge
- Update success toast to show pledged amount and asset code (e.g. 'Pledged 50 USDC. Tx: ...')
- Error path preserved: form values retained on failure for retry

Closes ritik4ever#610
Configure Renovate bot for npm (frontend, backend) and Cargo (contracts)
with grouped patch updates (auto-merge) and individual major PRs assigned
to maintainers, matching the project's existing Dependabot schedule.

Closes ritik4ever#633
Splits CreateCampaignForm into Basics, Funding, Rewards, and Review
steps with a progress indicator and back/forward navigation. Back
navigation preserves already-entered data, the Review step renders a
full preview before submission, and the layout is responsive down to
mobile widths.

- Adds a category field and optional reward tiers to the Basics/
  Rewards steps for richer campaign setup.
- Wires up maxPerContributor (already supported by the backend
  schema) end-to-end from the Funding step to the create payload.
- Rewrites the component's test suites (unit, validation, a11y) to
  exercise the new step-by-step flow.

Resolves ritik4ever#588
- Adds Freighter pledge and refund sequence diagrams with PNG fallbacks (ritik4ever#652)
- Expands OPEN_SOURCE_ISSUES.md to 20+ issues with difficulty tags (ritik4ever#664)
…validation (ritik4ever#569)

- Set Express JSON body parser default limit to 64KB (from 16KB)
- Return 413 with descriptive error message including the limit
- Add description field validation (required, max 5000 chars) to createCampaignPayloadSchema
- Add basic title validation (required, max 200 chars)
- Document 413 responses on all 5 POST endpoints in OpenAPI spec
- Fix pre-existing cache.ts build blockers (duplicate import, missing catch blocks)
- Add getCampaignAnalytics() function to campaignStore.ts
- Implement funding_gap calculation (target - pledged)
- Add comprehensive unit tests covering:
  - Campaign with partial funding
  - Fully funded campaign (gap = 0)
  - Empty campaign (gap = target)
  - Non-existent campaign (returns undefined)

This is a ~10% contribution toward the larger analytics feature,
implementing the simplest metric that reuses existing campaign data
without additional database queries.
…rd dismiss

- Create Toast.tsx component with success/error/warning/info variants
- Add Escape key dismissal for keyboard accessibility
- Error toasts persist until manually dismissed
- Queue limits visible toasts to max 3, removing oldest non-error first
- Auto-dismiss non-error toasts after 5 seconds (10s with link)
- Add warning variant with CSS variables and styles for both themes
- Update ToastContainer to use Toast component internally
- Update tests and stories for new warning variant and queue behavior

Closes ritik4ever#613
- Add getTrendingCampaigns() to campaignStore: queries open campaigns
  only (not funded/claimed/failed), counts non-refunded pledges in last
  24h per campaign, computes velocity = recent_pledges / hours_open,
  returns top 10 sorted by velocity desc
- Add trending LRU cache (10-min TTL) to campaignCache.ts with
  getTrendingCacheEntry / setTrendingCacheEntry / invalidateTrendingCache
- Register GET /api/campaigns/trending route in index.ts with X-Cache
  HIT/MISS header; route placed before /:id to avoid param capture
…4ever#653)

- Add self-audit checklist covering reentrancy, access control, integer overflow, flash loan vectors, and front-running with severity ratings and mitigations
- Add findings register for tracking open items
- Add external audit firm template with scope, threat model, focus areas, deliverables, and acceptance criteria
- Add audit sign-off section for deployment readiness
- Document all 19 contract functions with signatures, parameters, return types, error codes with recovery actions, and gas estimates with 20% headroom
- Document 10 event types with full payload schemas and topic signatures
- Add 5 worked examples covering full campaign lifecycle, cancel+refund, deadline extension governance, multi-token campaigns, and read-only queries
- Include type definitions for Campaign, DeployInfo, and ExtensionRequest
- Rewrite INDEX.md as a full documentation index mapping all 45+ markdown files
- Organize into sections: Quick Start, Architecture & Design (incl. ADRs), Smart Contract, Backend, Frontend, Security, Operations, Feature Docs, GitHub Templates, Changelog
- Add one-line description for every file with relative links
- Link INDEX.md from README.md via a prominent callout at the top of the architecture section
[FEATURE] Add multi-wallet support (Rabet, xBull, LOBSTR)
… updates

Bumps the npm-minor-patch group with 7 updates in the /frontend directory:

| Package | From | To |
| --- | --- | --- |
| [@tanstack/react-virtual](https://github.com/TanStack/virtual/tree/HEAD/packages/react-virtual) | `3.14.3` | `3.14.9` |
| [@types/dompurify](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/dompurify) | `3.0.5` | `3.2.0` |
| [axios](https://github.com/axios/axios) | `1.18.1` | `1.19.0` |
| [recharts](https://github.com/recharts/recharts) | `3.9.0` | `3.10.1` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.0.1` | `26.1.2` |
| [autoprefixer](https://github.com/postcss/autoprefixer) | `10.5.1` | `10.5.4` |
| [postcss](https://github.com/postcss/postcss) | `8.5.15` | `8.5.25` |



Updates `@tanstack/react-virtual` from 3.14.3 to 3.14.9
- [Release notes](https://github.com/TanStack/virtual/releases)
- [Changelog](https://github.com/TanStack/virtual/blob/main/packages/react-virtual/CHANGELOG.md)
- [Commits](https://github.com/TanStack/virtual/commits/@tanstack/react-virtual@3.14.9/packages/react-virtual)

Updates `@types/dompurify` from 3.0.5 to 3.2.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/dompurify)

Updates `axios` from 1.18.1 to 1.19.0
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](axios/axios@v1.18.1...v1.19.0)

Updates `recharts` from 3.9.0 to 3.10.1
- [Release notes](https://github.com/recharts/recharts/releases)
- [Changelog](https://github.com/recharts/recharts/blob/main/CHANGELOG.md)
- [Commits](recharts/recharts@v3.9.0...v3.10.1)

Updates `@types/node` from 26.0.1 to 26.1.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `autoprefixer` from 10.5.1 to 10.5.4
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](postcss/autoprefixer@10.5.1...10.5.4)

Updates `postcss` from 8.5.15 to 8.5.25
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](postcss/postcss@8.5.15...8.5.25)

---
updated-dependencies:
- dependency-name: "@tanstack/react-virtual"
  dependency-version: 3.14.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-minor-patch
- dependency-name: "@types/dompurify"
  dependency-version: 3.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: axios
  dependency-version: 1.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: recharts
  dependency-version: 3.10.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: "@types/node"
  dependency-version: 26.1.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm-minor-patch
- dependency-name: autoprefixer
  dependency-version: 10.5.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-patch
- dependency-name: postcss
  dependency-version: 8.5.25
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…ver#587)

- Add getCampaignTimeline() to eventHistory.ts with UNION ALL query merging pledges and campaign_events
- Cursor-based pagination using base64-encoded timestamp:source:source_id composite cursor
- Each timeline item has type field: pledge, status_change, update, comment
- Add parseTimelineQuery validation to schemas.ts
- Add GET /api/campaigns/:id/timeline route to index.ts
- Response schema: { data: TimelineItem[], pagination: { nextCursor: string?, hasMore: boolean } }
feat: document backend API with OpenAPI 3.1
ritik4ever and others added 30 commits July 31, 2026 04:29
…-troubleshooting

docs: add troubleshooting guide with 10 documented issues
…-categories

Docs/faq expand user categories
…aigns-endpoint

Fix ritik4ever#564: Prevent concurrent pledges from exceeding maxPerContributor…
fix: GET /api/campaigns returns incorrect status when deadline is exa…
…rogress

feat: implement animated FundingProgress component
…n-timeline

feat: add GET /api/campaigns/:id/timeline unified event feed (ritik4ever#587)
…yarn/frontend/npm-minor-patch-9e0d8042cc

chore(deps): bump the npm-minor-patch group across 1 directory with 7 updates
…nsion

feat: expand INDEX.md as comprehensive navigation guide (ritik4ever#657)
feat: Add CONTRACT_ABI.md with full function reference (ritik4ever#656)
…udit-checklist

feat: Add security audit checklist and external audit template (ritik4ever#653)
…campaigns-endpoint

feat: add GET /api/campaigns/trending endpoint (ritik4ever#580)
…-assets

feat: Add GET /api/assets endpoint
…fication-system

Add toast notification system with warning variant, queue, and keyboard dismiss
…tics-funding-gap

test(analytics): add coverage for funding_gap metric
…-limits-569

feat(backend): add request body size limits and campaign description validation (ritik4ever#569)
…-664

feat(docs): Add sequence diagrams and expand open source issues (ritik4ever#652, ritik4ever#664)
…ion-wizard-588

[FEATURE] Add campaign creation wizard (multi-step form)
…vate-bot-config-633

feat: add Renovate bot configuration for automated dependency updates
…ge-walkthrough

docs: add Freighter pledge signing walkthrough (ritik4ever#648)
…clear-after-submit

fix: reset pledge form after successful submission and show amount in toast (ritik4ever#610)
docs: rewrite DELIVERABLES.md with accurate completion status
…AndBacklogPrioritization

docs: Triage TODO.md and add backlog priorities
…history-storage

docs(adr): add ADR-0004 for event history storage
…m-409

fix(campaign): return 409 on double claim instead of 200
…ntracts/soroban-sdk-27.0.2

chore(deps): bump soroban-sdk from 21.7.7 to 27.0.2 in /contracts
…ed-script

fix: add seedDeterministic script to populate dev database via CLI
…ntrolled basis points (default 50 = 0.5%) and fee recipient address, plus pre-existing bug fixes.

Adds PlatformFeeBps / FeeRecipient storage keys, admin setters/getters, modified claim() with proportional fee deduction, FeeCollected event, and fixes pre-existing compile errors in refund_contributor and contribute().

Closes ritik4ever#553
 Implement configurable platform fee on campaign claims with admin-controlled basis points (default 50 = 0.5%) and fee recipient address, plus pre-existing bug fixes.
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.

[FEATURE] Add idempotent pledge endpoint with idempotency key