Skip to content

Feat/organizer functions - #109

Merged
manoahLinks merged 2 commits into
mainfrom
feat/organizer-functions
Jul 21, 2026
Merged

Feat/organizer functions#109
manoahLinks merged 2 commits into
mainfrom
feat/organizer-functions

Conversation

@manoahLinks

Copy link
Copy Markdown
Contributor

closes #37
closes #46

Bull queue that withdraws an organizer's escrowed USDC from the Diamond
via withdrawTicketBalance, signed by the organizer's Circle wallet (they
are the ticket admin) and paid to that same wallet. Escrow only accrues
for refundable crypto events; non-refundable crypto pays instantly at
mint and fiat splits to the organizer's bank at purchase, so neither
touches this queue.

Engine + producer only — the trigger (organizer request endpoint /
cron) and the Payout-record lifecycle land in #46.

- PayoutQueueService: producer, one job per ticket type (the on-chain
  unit), eager BlockchainTransaction (WITHDRAW) audit row
- PayoutProcessor: zero-balance no-op preflight, organizer-signed
  withdraw, terminal-vs-retryable revert classification
  (InsufficientWithdrawBalance/etc → UnrecoverableError,
  WithdrawPeriodNotReached → retry), webhook-or-poll completion
- PayoutFinalizerService: parses TicketBalanceWithdrawn, audit-logs
  tx hash + destination + amount
- circle-webhook.processor: route confirmed WITHDRAW txs to finalizer

Tests: payout.processor (7); suite green (140).
Crypto-only payout flow that gives the #37 withdraw engine its trigger.

- POST /organizer/payouts/request: validates ownership, event status,
  on-chain refund window (getRefundPeriod), duplicate guard, and escrow
  > 0; creates a Payout (USDC/CRYPTO, amount = summed on-chain escrow),
  fans out enqueuePayout per ticket type holding a balance, flips to
  PROCESSING
- GET /organizer/payouts: status filter, pagination, all-time summary
  (totalPaid / pendingAmount / totalPayouts)
- PayoutFinalizerService: wire the #37 seam — once an event's escrow is
  fully drained, close its active Payout to COMPLETED + processedAt +
  providerReference (compare-and-set, idempotent)

Fiat revenue already settles to the organizer's bank at purchase via
split subaccounts, so only escrowed refundable-crypto revenue is
withdrawable here.

Tests: payouts.service (7) + payout-finalizer (3); suite green (150).

Closes #37
Closes #46
@manoahLinks
manoahLinks merged commit c2a8c84 into main Jul 21, 2026
3 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.

Organizer: Request payout + payout history Blockchain: Bull queue — payout (withdrawTicketBalance on-chain)

1 participant