Skip to content

feat: prediction fraud signals, dispute SLA timers, referral tracking… - #1482

Merged
Olowodarey merged 2 commits into
Arena1X:mainfrom
Immex171:feature/backend-issues-1389-1390-1394-contract-1359
Jul 27, 2026
Merged

feat: prediction fraud signals, dispute SLA timers, referral tracking…#1482
Olowodarey merged 2 commits into
Arena1X:mainfrom
Immex171:feature/backend-issues-1389-1390-1394-contract-1359

Conversation

@Immex171

Copy link
Copy Markdown
Contributor

Summary

Implements four independent tasks:

[Backend] Prediction Pattern Fraud Signals

Closes #1389

  • Computes per-user timing-clustering and counterparty-concentration signals over prediction behavior.
  • Flags accounts exceeding configurable thresholds (env-configurable) as advisory PredictionFraudFlag records — never auto-enforced.
  • Exposes flags to admins via GET /admin/predictions/fraud-flags (filterable by status/signal_type/user).
  • Files: backend/src/predictions/predictions.service.ts, backend/src/predictions/entities/prediction-fraud-flag.entity.ts, backend/src/admin/admin.service.ts, backend/src/admin/admin.controller.ts.

[Backend] Dispute SLA Timers and Escalation

Closes #1394

  • Each dispute now tracks an SLA deadline per stage (initial_reviewescalated).
  • An hourly scheduler (DisputesService.runSlaCheck) detects approaching/breached SLAs, notifies the assigned arbiter and all admins, and escalates breached disputes into a second SLA window per configurable policy.
  • New PATCH /admin/disputes/:id/assign-arbiter endpoint to assign an admin/moderator as the dispute's arbiter.
  • Files: backend/src/disputes/disputes.service.ts, backend/src/disputes/entities/dispute.entity.ts, backend/src/notifications/notification-generator.service.ts.

[Backend] Referral Tracking API

Closes #1390

  • Records referrer→referred relationships via POST /users/me/referrals/claim (a user's own ID doubles as their shareable referral code).
  • Rejects self-referral and duplicate attribution (unique constraint on the referred side).
  • GET /users/me/referrals reports counts and per-referral status.
  • A referred user's first prediction submission advances their referral from pending to qualified.
  • Files: backend/src/users/users.service.ts, backend/src/users/users.controller.ts, backend/src/users/entities/user-referral.entity.ts, backend/src/users/dto/referral.dto.ts.

[Contract] Weighted Arbiter Quorum Voting with Slashing

Closes #1359

  • Admins assign a panel of arbiters to a pending dispute (assign_arbiters); each arbiter's voting weight (staked bond × reputation multiplier) is snapshotted at assignment, immune to later stake/reputation changes.
  • finalize_arbiter_vote requires assigned weight meeting a configurable quorum (Config::arbiter_quorum_bps) and the voting deadline to have passed.
  • Non-voting arbiters are slashed by Config::arbiter_slash_bps; the slashed amount is redistributed to voters exactly (verified in tests).
  • Ties resolve to reject, preserving the original market resolution as the safe default.
  • get_arbiter_tally exposes a read-only tally, quorum progress, and per-arbiter participation.
  • Files: contracts/open-market/src/dispute.rs, contracts/open-market/src/storage_types.rs, contracts/open-market/src/config.rs.
  • Note: both DataKey and InsightArenaError are already at their 50-variant XDR cap, so this reuses the existing raw-tuple-key pattern (see reputation::trusted_creator_key) for arbiter stake storage, and documents each reused error variant inline.

Test plan

  • cd backend && npm test — unit tests added/updated in predictions.service.spec.ts, disputes.service.spec.ts, users.service.spec.ts, admin.service.spec.ts.
  • cd contracts/open-market && cargo test — new tests/arbiter_vote_tests.rs covers staking, weight snapshotting, quorum gating, tie resolution, and exact slash/redistribution accounting.
  • Run new migrations against a local Postgres instance.
  • Manually exercise POST /users/me/referrals/claim and GET /admin/predictions/fraud-flags against a running backend.

…, weighted arbiter voting

Implements four independent features:

- Prediction fraud signals (Arena1X#1389): computes timing-clustering and
  counterparty-concentration signals per user, raises advisory
  PredictionFraudFlag records against configurable thresholds, and
  exposes them via GET /admin/predictions/fraud-flags. No automatic
  enforcement is taken from flags alone.

- Dispute SLA timers and escalation (Arena1X#1394): attaches an SLA deadline
  to each dispute's stage (initial review -> escalated), runs an
  hourly sweep that detects approaching/breached deadlines, notifies
  assigned arbiters and admins, and escalates breached disputes to a
  second SLA window per configurable policy.

- Referral tracking API (Arena1X#1390): records referrer -> referred
  relationships via POST /users/me/referrals/claim (self-referral and
  duplicate attribution rejected), reports counts/statuses via GET
  /users/me/referrals, and advances a referral to "qualified" when the
  referred user completes their first prediction.

- Weighted arbiter quorum voting with slashing (Arena1X#1359, contract):
  admins assign a panel of arbiters to a dispute with per-arbiter
  weight (stake x reputation multiplier) snapshotted at assignment;
  finalization requires assigned weight meeting a configurable quorum
  and slashes non-voters, redistributing the slashed stake to voters
  exactly. Ties resolve to reject, preserving the original resolution.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
insight-arena-4rll Ready Ready Preview, Comment Jul 26, 2026 9:31pm

@drips-wave

drips-wave Bot commented Jul 26, 2026

Copy link
Copy Markdown

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

- disputes.service.ts: compare arbiter.role against string literals
  instead of the Role enum (User.role is typed as string, so the enum
  comparison tripped @typescript-eslint/no-unsafe-enum-comparison).
- bulk-import-markets.spec.ts: add the missing PredictionsService
  provider now required by AdminService's constructor.
- disputes.service.spec.ts: stop reusing the shared, mutable
  mockDispute fixture in two assignArbiter tests - earlier specs in
  the file mutate its status in place via the service, making those
  tests order-dependent. Clone it with status explicitly set instead.

Verified with the exact CI-pinned toolchain (pnpm install
--frozen-lockfile): lint is 0 errors, and all 85 suites / 1032 tests
pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@Olowodarey
Olowodarey merged commit cf5bbde into Arena1X:main Jul 27, 2026
7 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

2 participants