Skip to content

feat(payouts): enforce configurable minimum payout via MIN_STELLAR_PAYOUT#525

Open
Petah1 wants to merge 1 commit into
ANYTECHS:mainfrom
Petah1:feat/min-payout-enforcement
Open

feat(payouts): enforce configurable minimum payout via MIN_STELLAR_PAYOUT#525
Petah1 wants to merge 1 commit into
ANYTECHS:mainfrom
Petah1:feat/min-payout-enforcement

Conversation

@Petah1

@Petah1 Petah1 commented Jun 25, 2026

Copy link
Copy Markdown

Closes #368


Summary

  • Centralized configConfigService now exposes minStellarPayout, loaded from MIN_STELLAR_PAYOUT (default 5). A constructor validates the value at application startup: if the env var is missing, zero, negative, or non-numeric the process fails immediately with a descriptive error rather than silently accepting a broken threshold.

  • Single enforcement pointPayoutsService.assertMinimumPayout(amount) is the only place the check lives. It throws BadRequestException with a dynamic message that reflects the configured value:

    { "message": "Minimum payout amount is 5 USD equivalent." }
  • All payout entry points protected — the guard is called before any balance query, Stellar account load, transaction build, signing, or on-chain submission in:

    Method Guard position
    requestPayout after availableBalance computed, before fee calc
    requestPayoutWithDetails after conflict check, before all DB reads
    initiateStellarPayout after amount-match check, before balance/TX
    processPayout after status/wallet checks, before platform secret/TX
    batchProcessPayouts per-payout, after status/wallet checks, before TX
  • Backward compatible — existing behaviour is unchanged; operators can lower or raise the threshold via the env var with no code changes.

  • Removed the previous ad-hoc parseFloat(process.env.MIN_PAYOUT_AMOUNT ?? '10') in requestPayoutWithDetails — all paths now use the same threshold from config.

  • Fixed pre-existing duplicate import { FeeService } in payouts.service.ts.

Test plan

  • ConfigService startup throws when MIN_STELLAR_PAYOUT is "", "0", "-5", "abc"
  • ConfigService uses default 5 when env var is absent
  • requestPayoutWithDetails rejects amount below threshold; error message contains configured value
  • requestPayoutWithDetails proceeds when amount equals or exceeds threshold
  • requestPayoutWithDetails does not query DB or create payout when validation fails
  • requestPayout rejects when available balance is below threshold; payout not created
  • requestPayout proceeds when balance exactly equals threshold
  • initiateStellarPayout rejects below-threshold amount; no balance query or TX built
  • initiateStellarPayout proceeds when amount equals threshold
  • processPayout rejects below-threshold payout amount; no payout.update called
  • Dynamic threshold test: error message reflects a changed minStellarPayout value at runtime

…YOUT

Load the minimum payout threshold from the MIN_STELLAR_PAYOUT environment
variable (default 5) through the centralized ConfigService. Validate at
application startup that the configured value is a positive finite number,
throwing immediately if it is not.

Add a private assertMinimumPayout() guard in PayoutsService and call it
at every payout entry point — requestPayout, requestPayoutWithDetails,
initiateStellarPayout, processPayout, and batchProcessPayouts — before any
balance query, Stellar account load, transaction build, signing, or
on-chain submission. Replace the ad-hoc MIN_PAYOUT_AMOUNT env read in
requestPayoutWithDetails with the centralized guard.

Error message is dynamic and reflects the configured threshold:
  "Minimum payout amount is <N> USD equivalent."
@drips-wave

drips-wave Bot commented Jun 25, 2026

Copy link
Copy Markdown

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

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.

Implement Minimum Stellar Payout Threshold

1 participant