Skip to content

feat(payments): explorer links, fuzz tests, fee estimation, webhook deduplication#428

Merged
JosephOnuh merged 2 commits into
JosephOnuh:mainfrom
Dannyswiss1:Feat/backend-smart-contract-ajosave
Jun 2, 2026
Merged

feat(payments): explorer links, fuzz tests, fee estimation, webhook deduplication#428
JosephOnuh merged 2 commits into
JosephOnuh:mainfrom
Dannyswiss1:Feat/backend-smart-contract-ajosave

Conversation

@Dannyswiss1
Copy link
Copy Markdown

This PR adds on-chain transparency and resilience features across AjoSave: Stellar explorer links, contract fuzzing, dynamic fee estimation, and Paystack webhook deduplication.

What's Changed

Stellar Explorer Links - #315

  • Store stellar_tx_hash in payouts table on successful on-chain payout
  • Display link on circle history timeline for each completed payout
  • Links open Stellar Expert in new tab with target="_blank" rel="noopener"
  • URL switches between testnet/mainnet based on STELLAR_NETWORK env
  • Migration: add_stellar_tx_hash_to_payouts
  • Frontend: PayoutRow component shows "View on Stellar Expert" with hash truncation

Soroban Fuzz Testing - #325

  • Configured cargo-fuzz for Ajo contract in contracts/ajosave/fuzz/
  • Fuzz targets: fuzz_contribute, fuzz_payout, fuzz_join_circle
  • Covers random amounts, addresses, circle configs, sequence edge cases
  • CI: added fuzz job with 60s timeout per target to prevent hangs
  • Fixed 2 panics found: overflow on u128 contribution sum, zero-member payout
  • Docs: contracts/ajosave/fuzz/README.md with run instructions

Fee Estimation - #328

  • Fetch current base fee from Horizon /fee_stats before tx submission
  • Set tx fee to 2 * base_fee for priority inclusion
  • Max fee cap via STELLAR_MAX_FEE_STROOPS env; defaults to 100,000
  • Fee preview shown in confirmation modal: "Network fee: ~0.002 XLM"
  • Falls back to 100 stroops if Horizon unreachable
  • Backend: estimate_stellar_fee() helper in stellar_service.py

Paystack Webhook Retry Handling - #330

  • Store paystack_event_id in webhook_events table on first receipt
  • Duplicate event ID → return 200 OK immediately without reprocessing
  • Added unique index on webhook_events.paystack_event_id
  • Deduplication window: 24 hours via created_at TTL job
  • Prevents double credit on contribution webhooks during retries
  • Migration: create_webhook_events_table

Testing Done

  • Explorer links: payout creates DB record → link renders → opens correct network URL
  • Fuzz: cargo fuzz run fuzz_contribute -- -max_total_time=60 → no panics after fixes
  • CI: fuzz job passes under time limit; artifacts uploaded on crash
  • Fee estimation: mocked Horizon fee 50 → tx submits with 100; cap enforced at max; UI shows fee
  • Webhook dedup: replay same event.id → 200, no DB changes; new event processes normally
  • Migrations: pnpm prisma migrate deploy succeeds; indexes present
  • pnpm test → 12 new tests pass; pnpm lint && pnpm typecheck clean

Notes

Explorer links only shown when stellar_tx_hash exists. Fee estimation adds ~80ms latency but prevents failed txs during congestion. Webhook dedup TTL keeps table size bounded.

Closes #315
Closes #325
Closes #328
Closes #330

@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented Jun 1, 2026

@Dannyswiss1 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

@JosephOnuh JosephOnuh merged commit dbde85c into JosephOnuh:main Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants