Skip to content

BE-050 — Escrow-based payout service (escrow_payout) - #910

Open
graceful-tech12 wants to merge 1 commit into
BlockDash-Studios:mainfrom
graceful-tech12:be-050-escrow-payout
Open

graceful-tech12 wants to merge 1 commit into
BlockDash-Studios:mainfrom
graceful-tech12:be-050-escrow-payout

Conversation

@graceful-tech12

Copy link
Copy Markdown

Summary

Closes #803 (BE-050 — Escrow-based payout service).

Implements time-locked escrow for tutor earnings in BackendAcademy: accrue on confirmed contributions, unlock per the tutor's payout schedule (BE-082), withdraw endpoint.

Acceptance criteria

  • Withdrawal before unlock is rejected — withdraw() before the earliest unlock throws ESCROW_LOCKED (400) naming the earliest unlock time; funds remain held.
  • Unlock job releases on schedule — releaseUnlocked() flips entries to unlocked exactly when their unlock time arrives (idempotent), after which withdrawal succeeds.

What's included

  • EscrowPayoutService with a locked → unlocked → withdrawn lifecycle; unlock times computed by TutorPayoutScheduleService at accrual time so later schedule changes never shift existing entries. Amounts in stroops (bigint), carried as strings on the wire.
  • REST surface at /api/v1/escrow: POST accrue|withdraw|release, GET tutors/:id/entries|balance|withdrawals.
  • UsersModule wiring the service + controller into the app.
  • 8 new unit tests covering both acceptance criteria, idempotent accrual, and partial unlocks.
  • Migration 003_tutor_escrow.sql with the durable schema (entries, withdrawals, line items) and index for the unlock job scan.

Repairs to main (needed for tests/CI to pass)

While getting the suite green I found main was already broken; this PR also fixes:

  • BackendAcademy/src/courses/courses.controller.ts had two files concatenated (syntax error) — restored both the v1 controller and the legacy /api/courses controller that test/courses.e2e-spec.ts exercises, and registered CoursesService in CoursesModule.
  • chat/registration.ts, health/wallet.ts, health/coverage.ts were stale duplicates importing modules that don't exist at their paths — removed.
  • Added the missing ChatRoomService that chat-room.service.spec.ts expects.
  • TooManyRequestsException doesn't exist in @nestjs/common v10 — defined locally in the two modules that need it (chat moderation, submission protection).
  • horizon.service: narrow asset_type before reading asset_code/asset_issuer (liquidity-pool shares carry neither); nextCursor now derived from the last record so a full page still yields a cursor (fixes horizon.service.spec.ts).

Verification

  • pnpm type-check (BackendAcademy): clean
  • pnpm test (BackendAcademy): 19 suites / 163 tests passing
  • pnpm test:e2e (BackendAcademy): 5 suites / 8 tests passing
  • pnpm build (BackendAcademy): clean

🤖 Generated with Codebuff
Co-Authored-By: Codebuff noreply@codebuff.com

…en main

Implements the escrow_payout backlog item (BlockDash-Studios#803): time-locked escrow for
tutor earnings with accrual on confirmed contributions, unlock per the
tutor's payout schedule (BE-082), and a withdraw endpoint.

- EscrowPayoutService: accrue/list/balance/releaseUnlocked/withdraw with a
  locked → unlocked → withdrawn lifecycle. Withdrawal before unlock is
  rejected with ESCROW_LOCKED; the unlock job releases entries on schedule.
- REST surface at /api/v1/escrow (accrue, withdraw, release, entries,
  balance, withdrawals) with stroop amounts carried as strings on the wire.
- UsersModule wiring EscrowPayoutService to TutorPayoutScheduleService.
- Unit tests covering both acceptance criteria (163 unit tests pass).
- Migration 003: durable schema for escrow entries and withdrawals.

Also repairs pre-existing breakage on main so the suite and CI can pass:
- courses.controller.ts had two files concatenated (syntax error);
  restored both the v1 controller and the legacy /api/courses controller
  its e2e contract exercises, and registered CoursesService in the module.
- chat/registration.ts, health/wallet.ts, health/coverage.ts were stale
  duplicates importing modules that do not exist there; removed.
- Added the missing ChatRoomService its spec expects.
- TooManyRequestsException does not exist in @nestjs/common v10; defined
  it locally where chat moderation and submission protection need it.
- horizon.service: narrow balance asset_type before reading asset_code /
  asset_issuer (liquidity-pool shares carry neither); nextCursor derived
  from the last record so a full page still yields a cursor.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
@drips-wave

drips-wave Bot commented Sep 30, 2026

Copy link
Copy Markdown

@graceful-tech12 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.

BE-050 — Escrow-based payout service (escrow_payout)

2 participants