Skip to content

feat(full-stack): implement escrow referral and affiliate system — on-chain referral code registry, backend fee-split earning accounting, batch payout, and frontend referral dashboard #1549

Description

@Chibey-max

Overview

Growth depends on word-of-mouth. A referral system lets existing users earn rewards when people they bring in successfully complete escrows. This requires: on-chain referral code binding (so the referral is tamper-proof), backend fee-split accounting, and a frontend dashboard showing earnings and referral activity.

What to build

Contracts (new referral_registry contract):

  • register_code(referrer: Address, code: Symbol) — registers a unique referral code linked to a Stellar address; codes are globally unique; max 1 code per address
  • bind_referral(escrow_id: u64, code: Symbol) — called at escrow creation; records (escrow_id → referrer_address) on-chain; fails if escrow already has a referral; emits ReferralBound { escrow_id, referrer, code }
  • get_referrer(escrow_id: u64) -> Option<Address> — view function
  • get_code(referrer: Address) -> Option<Symbol> — view function

Backend:

  • referral_codes table: { code, referrer_user_id, created_at, total_referrals, total_earned_xlm: Decimal }
  • referral_earnings table: { id, referral_code, escrow_id, triggered_by_event: enum(release|completion), earned_xlm: Decimal, paid_out: bool, created_at }
  • On escrow release: ReferralService.calculateEarning(escrowId) — looks up on-chain referrer, computes platform_fee * referral_pct (configurable, default 20%), records in referral_earnings
  • POST /api/v1/referrals/codes — create a referral code for the authenticated user
  • GET /api/v1/referrals/my-stats — returns: code, total referrals, pending earnings (unpaid), total earned, top 5 referred users (anonymised by address prefix)
  • POST /api/v1/admin/referrals/pay-out — batch pay-out pending earnings via Stellar payment operations; marks entries as paid; requires admin auth

Frontend (/referrals page):

  • Referral code display with copy button and shareable link https://app.example.com/signup?ref={code}
  • Stats cards: Total Referrals, Pending Earnings (XLM + USD), Total Paid Out
  • Referral activity table: escrow ID (abbreviated), date, earned XLM, payout status
  • Share buttons: Twitter/X and Telegram pre-filled with a referral message

Acceptance Criteria

  • On-chain code uniqueness enforced — registering a duplicate code returns Err(CodeTaken)
  • On-chain bind_referral fails gracefully if the code is not registered (Err(UnknownCode))
  • Backend earning calculation uses the platform fee from the escrow's ledger entry (not a hardcoded value)
  • Payout batch processes at most 100 entries per invocation; remaining queued for next batch
  • Referral stats are computed from DB, not on-chain (for performance); periodic sync reconciles counts
  • Share link correctly encodes the referral code in the URL; ?ref= param pre-fills the code on the sign-up page
  • Referral activity table is paginated; default sort is newest first
  • Rust tests: code registration, duplicate rejection, bind, get_referrer; backend tests: earning calculation, payout batch

Technical notes

  • Referral code must be a valid Soroban Symbol (max 32 chars, alphanumeric + underscore)
  • Earnings percentage is stored in the backend config, not on-chain, to allow adjustment without contract upgrade

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions