Title: feat: Repayment and Fund Distribution Logic — Contract and Backend
Labels: contracts, backend, core, priority-high
Description:
The current lifecycle ends at FINANCED. This issue adds the most
critical missing piece: the debtor repays the invoice amount, and
the escrow contract automatically distributes principal plus yield
to the lender's wallet.
What Needs to Be Done:
Smart Contract (contracts/escrow/src/lib.rs):
- Add to EscrowState: repaid_amount, total_due, repaid_at
- repay_invoice(debtor, invoice_id, amount)
- Debtor transfers USDC to contract
- Tracks partial repayments
- When fully repaid, marks ready for distribution
- distribute_funds(invoice_id)
- Admin/oracle triggers fund release
- Transfers principal + yield_amount to lender wallet
- Updates escrow status to Released
- Events:
("escrow", "repaid") → { invoice_id, debtor, amount, total_repaid }
("escrow", "distributed") → { invoice_id, lender, principal, yield }
Backend:
- POST /invoices/:id/repay
- Debtor submits repayment proof
- Calls escrow repay_invoice() on-chain
- Stores tx_hash
- Creates audit log entry
- POST /admin/invoices/:id/distribute
- Admin triggers fund distribution after repayment confirmed
- Calls escrow distribute_funds() on-chain
- Updates invoice status to PAID
- Dispatches payment.confirmed webhook to lender
Key Files:
- contracts/escrow/src/lib.rs (update)
- contracts/escrow/src/test.rs (update)
- apps/backend/src/payments/repayment.service.ts (new)
- apps/backend/src/payments/payments.controller.ts (update)
Acceptance Criteria:
- Debtor can only repay a FINANCED invoice
- Partial repayments tracked until fully repaid
- Distribution only callable after full repayment
- Cannot repay an already PAID or DEFAULTED invoice
- Stellar tx_hash stored for every on-chain call
- Audit log entry for repayment and distribution
- Webhook dispatched to lender on distribution
- cargo test 95%+ for new contract functions
- Unit tests cover both contract and backend paths
Security Notes:
- require_auth() on repay_invoice and distribute_funds
- Distribution only after full repayment on-chain — no partial release
- DB status only updated after chain confirmation
Branch: feat/repayment-distribution
Commit: feat(repayment): add debtor repayment flow and automated lender fund distribution
Title: feat: Repayment and Fund Distribution Logic — Contract and Backend
Labels: contracts, backend, core, priority-high
Description:
The current lifecycle ends at FINANCED. This issue adds the most
critical missing piece: the debtor repays the invoice amount, and
the escrow contract automatically distributes principal plus yield
to the lender's wallet.
What Needs to Be Done:
Smart Contract (contracts/escrow/src/lib.rs):
("escrow", "repaid") → { invoice_id, debtor, amount, total_repaid }
("escrow", "distributed") → { invoice_id, lender, principal, yield }
Backend:
Key Files:
Acceptance Criteria:
Security Notes:
Branch: feat/repayment-distribution
Commit: feat(repayment): add debtor repayment flow and automated lender fund distribution