Skip to content

Gw/kalshi poc - #11278

Open
georgeweiler wants to merge 4 commits into
mainfrom
gw/kalshi-poc
Open

georgeweiler wants to merge 4 commits into
mainfrom
gw/kalshi-poc

Conversation

@georgeweiler

@georgeweiler georgeweiler commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Explanation

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

High Risk
Breaking changes to persisted KYC state and many controller/service APIs that orchestrate identity sessions, disclaimers, and SumSub flows; ramps onboarding now depends on the new decision API.

Overview
Breaking refactor of @metamask/kyc-controller from a single active session to sessions keyed by identity vendor (moonpay, iron, kalshi). Per-vendor entries hold session status, provider flow, residence country, disclaimer acceptance, and consent state; clearState / reset wipe all vendors and stop each vendor’s polling loop.

Session APIs now require { vendor } (read/refresh/poll status, disclaimers, provider flow, etc.). startSession no longer throws on vendor/country/email mismatches and only needs a verified email when creating a session. KycService.fetchVendorDisclaimers and createUkycSession require an explicit vendor (no MoonPay default).

Vendor terms flow: new acceptVendorDisclaimers stores local acceptance before a session exists; recordVendorDisclaimers({ vendor }) submits that stored acceptance once a session exists. hasCompletedVendorDisclaimers only counts submitted acceptance against the catalog for the entry’s residenceCountry.

New surface: getSessionDecision({ vendor }) (and exported getKycSessionDecision) maps a vendor entry to none | new | pending | approved | rejected | retry. Selectors are now selectKycSession(state, vendor) and selectKycSessionStatus(state, vendor). Removed public KycPhase, KycProduct, and related disclaimer types. launchProviderFlow returns failed without mutating state if another vendor’s SumSub UI is already open.

Kalshi / relay-registered vendors: adds kalshi, VENDORS_REGISTERED_BY_RELAY, optional email on session creation, KycService.postOnboardingStep, and controller messenger actions for vendor email/SMS OTP steps.

@metamask/ramps-controller adopts the new KYC actions (vendor-scoped calls + KycController:getSessionDecision) so hydrateVbaOnboarding derives kycStatus from the decision instead of inline session parsing. Clients must migrate persisted KYC state to the new shape.

Reviewed by Cursor Bugbot for commit 49beb9f. Bugbot is set up for automated code reviews on this repo. Configure here.

georgeweiler and others added 4 commits November 3, 2026 15:56
Replace the single-session KycController state with `sessions`, keyed by
vendor, so a second vendor (e.g. Kalshi) can hold its own session next to
Iron. Every session method takes `{ vendor }`; there is no active vendor.

- Add getSessionDecision (none/new/pending/approved/rejected/retry), moved
  from RampsController's resolveVbaKycStatus
- Add acceptVendorDisclaimers so vendor terms accepted before a session
  exists are stored on the controller, then submitted by
  recordVendorDisclaimers({ vendor })
- Drop the stored email/vendor/geoCountry and their 'different X' guards;
  email is only required when creating a session
- One SumSub flow on screen at a time; per-vendor polling loops
- Make vendor required on KycService.fetchVendorDisclaimers and
  createUkycSession
- Remove dead KycPhase / KycProduct types
- RampsController passes vendor 'iron' and reads getSessionDecision

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ions

Also require a session id in the controller's session lookup, stop
recordVendorDisclaimers recreating an entry cleared mid-request, and update
ARCHITECTURE.md's state and selectors sections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- KycVendor gains kalshi; startSession registers relay-registered
  vendors with a caller-supplied email and skips the partner identity
  token and vendor customer call
- KycService.postOnboardingStep and KycController verify/resend email
  code, send/verify phone code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@georgeweiler
georgeweiler requested review from a team as code owners November 4, 2026 02:51
@georgeweiler
georgeweiler deployed to default-branch November 4, 2026 02:52 — with GitHub Actions Active

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 49beb9f. Configure here.

session = await this.messenger.call(
'KycController:fetchSessionStatusOnce',
session.id,
vendorParams,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VBA clear wipes every vendor

High Severity

hydrateVbaOnboarding still calls KycController:clearState when the Iron session 404s. That action now deletes every vendor entry, so a missing VBA session also drops Kalshi or MoonPay progress the user already completed.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 49beb9f. Configure here.


this.update((state) => {
state.email = email;
state.vendor = params.vendor;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Session create drops terms country

Medium Severity

startSession overwrites residenceCountry with geo when it creates a session, but leaves any vendorDisclaimersAccepted from acceptVendorDisclaimers in place. recordVendorDisclaimers can then submit terms for a different country than the session, and later catalog checks use the new country.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 49beb9f. Configure here.

This branch was successfully deployed

1 active deployment
default-branch — 49beb9ff Deployed Nov 4, 2026 by georgeweiler via Determine whether this PR is a release PR #6447
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.

1 participant