Skip to content

[READY] add Alfredpay (USD/MXN/COP/ARS) on/off-ramp support to SDK#1173

Merged
ebma merged 76 commits into
stagingfrom
1161-sdk-changes-for-alfredpay-currencies-support
Jul 5, 2026
Merged

[READY] add Alfredpay (USD/MXN/COP/ARS) on/off-ramp support to SDK#1173
ebma merged 76 commits into
stagingfrom
1161-sdk-changes-for-alfredpay-currencies-support

Conversation

@Sharqiewicz

@Sharqiewicz Sharqiewicz commented May 28, 2026

Copy link
Copy Markdown
Member

Previously the SDK only supported BRL on/off-ramps. This adds USD, MXN, COP, and ARS support in both directions — onramp and offramp — using the BRL integration as the reference pattern.

Closes #1161.

What changed

Core feature (packages/sdk)

  • New AlfredpayHandler covering onramp register, offramp register, and offramp update.
  • VortexSdk.registerRamp / updateRamp now route Alfredpay flows via isAlfredpayToken (USD/MXN/COP/ARS), checked before the existing pix/sepa branches.
  • New quote/additional-data types: AlfredpayOnrampQuote, AlfredpayOfframpQuote, AlfredpayOnrampAdditionalData, AlfredpayOfframpAdditionalData, AlfredpayOfframpUpdateAdditionalData, plus AlfredpayCurrency and discriminated ExtendedQuoteResponse / RegisterRampAdditionalData / UpdateRampAdditionalData mappings.
  • New typed errors: AlfredpayOnrampError / AlfredpayOfframpError and their Missing…ParametersError variants, wired into parseAPIError for both onramp and offramp backend messages.

@Sharqiewicz Sharqiewicz linked an issue May 28, 2026 that may be closed by this pull request
@netlify

netlify Bot commented May 28, 2026

Copy link
Copy Markdown

Deploy Preview for vortexfi ready!

Name Link
🔨 Latest commit 1415440
🔍 Latest deploy log https://app.netlify.com/projects/vortexfi/deploys/6a47f76e941eda0008e3d2f7
😎 Deploy Preview https://deploy-preview-1173--vortexfi.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented May 28, 2026

Copy link
Copy Markdown

Deploy Preview for vortex-sandbox ready!

Name Link
🔨 Latest commit 1415440
🔍 Latest deploy log https://app.netlify.com/projects/vortex-sandbox/deploys/6a47f76eab2cbc0007c33ed6
😎 Deploy Preview https://deploy-preview-1173--vortex-sandbox.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@Sharqiewicz Sharqiewicz changed the title [WIP] add Alfredpay (USD/MXN/COP) on/off-ramp support to SDK [READY] add Alfredpay (USD/MXN/COP) on/off-ramp support to SDK Jun 3, 2026
@ebma ebma requested a review from Copilot June 8, 2026 17:27
@ebma ebma self-assigned this Jun 8, 2026

@ebma ebma left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Sharqiewicz does this branch already have the latest changes from staging? I can see that it's using stellar ephemerals, from which we want to move away from. Please adjust that in the new files and fix the type issues and merge conflicts.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extends @vortexfi/sdk beyond BRL-only ramps by adding Alfredpay-based USD/MXN/COP onramp and offramp support, including SDK routing, handler implementation, new quote/additional-data types, typed errors, regression tests, and README examples.

Changes:

  • Added AlfredpayHandler and wired VortexSdk.registerRamp() / updateRamp() to route Alfredpay flows via isAlfredpayToken(...).
  • Expanded SDK type system to include Alfredpay quotes and (register/update) additional-data mappings.
  • Added Alfredpay-specific error types + API error parsing, plus a new regression test suite and README usage examples.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/sdk/test/alfredpayHandler.test.ts Adds regression tests for Alfredpay handler behavior, routing, and update semantics.
packages/sdk/src/VortexSdk.ts Routes USD/MXN/COP ramps to AlfredpayHandler for register/update flows.
packages/sdk/src/types.ts Introduces Alfredpay quote/additional-data types and updates conditional type mappings.
packages/sdk/src/handlers/AlfredpayHandler.ts Implements Alfredpay onramp/offramp register + offramp update flow (ephemerals + signing + update).
packages/sdk/src/errors.ts Adds Alfredpay-specific error classes and API error parsing hooks.
packages/sdk/README.md Documents Alfredpay onramp/offramp usage patterns for SDK consumers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/sdk/src/types.ts Outdated
Comment thread packages/sdk/src/types.ts
Comment on lines +114 to +118
export interface AlfredpayOnrampAdditionalData {
destinationAddress: string;
fiatAccountId: string;
walletAddress?: string;
sessionId?: string;
Comment thread packages/sdk/src/handlers/AlfredpayHandler.ts
Comment on lines +81 to +85
const result = await handler.registerAlfredpayOnramp("quote_1", {
destinationAddress: WALLET,
fiatAccountId: FIAT_ACCOUNT,
walletAddress: WALLET
});
Comment on lines +148 to +152
export class MissingAlfredpayOnrampParametersError extends AlfredpayOnrampError {
constructor() {
super("Parameters destinationAddress and fiatAccountId are required for Alfredpay onramp", 400);
this.name = "MissingAlfredpayOnrampParametersError";
}
Comment thread packages/sdk/README.md
Comment on lines +71 to +75
const { rampProcess } = await sdk.registerRamp(quote, {
destinationAddress: "0x1234567890123456789012345678901234567890",
fiatAccountId: "<the user's Alfredpay fiat account id>",
walletAddress: "0x1234567890123456789012345678901234567890"
});
@Sharqiewicz Sharqiewicz force-pushed the 1161-sdk-changes-for-alfredpay-currencies-support branch from ffe9b44 to e7296aa Compare June 22, 2026 12:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 7 comments.

Comment thread packages/sdk/src/eip712.ts
Comment thread packages/sdk/src/VortexSdk.ts Outdated
Comment thread packages/sdk/src/VortexSdk.ts
Comment thread packages/sdk/README.md Outdated
Comment thread packages/sdk/README.md Outdated
Comment thread packages/sdk/examples/exampleAlfredpayMexico.ts Outdated
Comment thread docs/api/pages/02-quick-start-with-the-sdk.md Outdated
ebma added 2 commits June 29, 2026 18:35
Add Mykobo invariant 23 (derive email from the effective user's profile, match
any client-supplied email, require APPROVED KYC before issuing payment
instructions), two threat-vector rows (cross-user EUR identity via body email;
unverified EUR ramp / KYC bypass), and an audit-checklist item. Generalize
quote-lifecycle invariant 15 to cover the Mykobo email alongside the BRL tax ID
and Alfredpay customer id.
The staging merge left two competing copies of the provider-identity
invariants (numbered 14–17 then 14–16 again). The incoming variant described
an Alfredpay "anonymous estimate + ANONYMOUS_ALFREDPAY_QUOTE_ID" flow that does
not exist in the code — the engines hard-reject via requireAlfredpayEffectiveUserId.
Drop the stale trio, keep the code-accurate invariants (Alfredpay quote-creation
reject; provider-identity derivation incl. Mykobo email; same-principal rule),
renumber to 15/16/17, and fix the dangling cross-references in the invariant,
threat-vector, and audit-checklist sections.
@ebma ebma force-pushed the 1161-sdk-changes-for-alfredpay-currencies-support branch from 0263b5e to 2359c2f Compare June 29, 2026 17:03
@Sharqiewicz Sharqiewicz force-pushed the 1161-sdk-changes-for-alfredpay-currencies-support branch from 8b6121f to 46e0b63 Compare July 1, 2026 14:11
Sharqiewicz and others added 23 commits July 1, 2026 16:17
… tracking customer id

User-gating Alfredpay quote creation broke the web-app funnel twice over:
the swap form requests quotes anonymously for USD/MXN/COP/ARS (all enabled),
and even logged-in users without completed Alfredpay KYC could not quote -
yet the app's KYC flow only starts after a quote is confirmed, so first-time
users could never onboard (chicken-and-egg).

Gating quotes is also unnecessary for security: Alfredpay quote requests
carry the customerId only inside the free-form tracking 'metadata' object
(staging has always sent "unknown" there for anonymous users); the
validated top-level customerId exists only on order creation. Orders are
created exclusively at ramp registration, which stays strictly KYC-gated
via resolveAlfredpayCustomerId.

Quote engines now use the non-throwing resolveAlfredpayQuoteCustomerId:
the user's real customer id when a KYC-completed customer resolves (keeps
provider-side attribution), the "anonymous" sentinel otherwise. The SDK
mirrors this split: createQuote no longer requires a secretKey (anonymous
rate discovery), while registerRamp fails fast without one since every
corridor now requires a user-linked key at registration.
…gistration

The 403 guard ('anonymous quote cannot be registered by an authenticated
caller') made anonymous quotes unregistrable by anyone, breaking the normal
web-app funnel: the frontend creates the quote before login and only
re-creates it when less than 60% of its 10-minute lifetime remains, so any
user completing login+KYC within ~4 minutes registered the original
anonymous quote and got a hard 403. quoteLocked widget flows never refresh
and failed deterministically.

Claiming an anonymous quote is not an escalation: it carries no owner, and
provider identity (taxId / alfredPayId / Mykobo email) is always derived
from the claimer's own KYC records, never from the quote or request body.
The guards that matter remain: 403 when the quote belongs to a *different*
user, 400 when no effective user resolves.

Updates the ADR and security spec to document the claiming semantics and
the registration policy of this fix series.
…eniaAccountForRamp

resolveAveniaAccountForRamp was dead code: prepareOfframpBrlTransactions
re-implemented its derive-then-compare logic inline, and the onramp path
silently ignored a client-supplied additionalData.taxId altogether. That
contradicted the documented deprecation contract ('mismatches against the
derived taxId are rejected') and left the two BRL register paths behaving
differently for no reason.

Both paths now go through resolveAveniaAccountForRamp(userId, taxId), so a
provided taxId that does not match the Avenia profile bound to the
authenticated user is rejected with 400 on onramp and offramp alike.

Also renames avena-account.ts -> avenia-account.ts (the provider is
Avenia) and aligns the BRLA security spec with the actual enforcement.
Secret-key validation narrows by keyPrefix (first 8 chars), but that prefix
is the constant sk_live_/sk_test_ for every secret key, so every auth
request bcrypt-compares (cost 10) against ALL active secret keys in the
environment. The self-serve POST /v1/api-keys endpoint made that scan
user-growable: any OTP-signup user could mint unlimited pairs and degrade
auth latency for the whole system.

createUserApiKey now rejects with 409 once a user holds
MAX_ACTIVE_KEYS_PER_USER (10) active keys (revocation frees slots), caps
expiresAt at 2 years, and creates the public/secret pair inside a single
transaction so a failed second insert cannot leave an orphaned half.

The api-keys security spec previously claimed the prefix lookup 'bounds the
cost of bcrypt comparisons' - corrected to describe the real linear-scan
behavior, the new cap, and the O(1)-lookup key-format change worth making
later.
/brla/getUser and /brla/getUserRemainingLimit now require an effective
user, but usePreRampCheck fires on the Confirm click - which happens
before the ramp machine routes to login (CheckAuth). For a logged-out
visitor the pre-check therefore hit a 400, rampWithinLimits returned
false, and every BRL submission was blocked.

The pre-check is only a UX nicety (an early limit warning); the backend
enforces limits authoritatively at ramp registration. Skip it when no
auth token is present and let the flow continue to login/KYC.
…ssages

The server no longer emits 'email must be provided for Mykobo (EUR)
offramp' (the email is now derived from the effective user's profile), and
the onramp parameter message dropped 'email' - so parseAPIError matched
dead strings and returned generic VortexSdkError for the new KYC-gate
responses.

Remove the dead mappings, match the current onramp message, and map the
three resolveMykoboCustomerForUser rejections (KYC not approved, email
mismatch, missing profile) to a typed MykoboKycRequiredError so callers
can branch on it the same way they can for Alfredpay.
Two test files were not updated when this branch changed the behavior they
cover, so they failed on the branch even before the follow-up fixes:

- brla.controller.test.ts still asserted the pre-branch contract
  (taxId required, unlinked partner keys allowed to read any taxId,
  anonymous-owned subaccount records rejected with 409). Rewritten for the
  effective-user model: anonymous and unlinked-partner lookups get 400,
  user-linked keys read their own taxId, and authenticated callers claim
  anonymous subaccount records instead of conflicting.

- ramp.service.get-ramp-status.test.ts hardcoded flowVariant 'monerium',
  so getRampStatus returned null (and every assertion failed) on any
  machine with FLOW_VARIANT=mykobo. Use config.flowVariant like the
  register-auth test does, making the test environment-independent.
Move the 'METHOD /path (status):' prefix from ApiError.message to
error.name so it still groups errors by endpoint in Sentry without
leaking into error text shown to users (e.g. the quote card).
…-support

# Conflicts:
#	apps/frontend/src/services/api/api-client.ts
@ebma ebma merged commit 1b9f0cf into staging Jul 5, 2026
7 checks passed
@ebma ebma deleted the 1161-sdk-changes-for-alfredpay-currencies-support branch July 5, 2026 07:34
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.

SDK changes for Alfredpay currencies support

4 participants