Skip to content

[READY] Feature: Alfredpay Fiat Accounts#1088

Open
Sharqiewicz wants to merge 52 commits intoadd-alfredpay-supportfrom
feat/alfredpay-fiat-accounts
Open

[READY] Feature: Alfredpay Fiat Accounts#1088
Sharqiewicz wants to merge 52 commits intoadd-alfredpay-supportfrom
feat/alfredpay-fiat-accounts

Conversation

@Sharqiewicz
Copy link
Member

@Sharqiewicz Sharqiewicz commented Mar 4, 2026

What this PR does

This PR extends the Vortex app with full fiat account management support for the Alfredpay payment provider, enabling users to register and select fiat accounts when transacting in USD, MXN (Mexican Peso) and COP (Colombian Peso).


Key changes

New currencies & token support

  • Added MXN and COP as FiatToken values in packages/shared, including token config, token mapping, and an isAlfredpayToken helper
  • Added flag/coin icons for MXN, COP, USD, and EU; refreshed EUR/EURC assets
  • Updated useGetAssetIcon to handle the new currencies
  • MXN/COP available via URL params and token defaults

Fiat Account Registration flow (new page)

  • Full registration UI in pages/alfredpay/FiatAccountRegistration/, including: AccountTypePickerScreen, RegisterFiatAccountScreen, RegisteredAccountsList, AccountCardDeck, AccountCardSkeleton, CardHeader, KycRequiredBanner, RemoveAccountControls
  • Driven by a new XState machine (fiatAccount.machine.ts) with associated hooks (useFiatAccounts) and service (alfredpay.service.ts)
  • FiatAccountMachineContext provides machine state to the UI

Summary Step integration

  • New FiatAccountSelector component surfaces registered fiat accounts in the payment SummaryStep
  • Confirm button is disabled for Alfredpay currencies until a payment method is selected
  • selectedFiatAccountId wired into RampExecutionInput

KYC flow refactor

  • AlfredpayKycFlow decomposed into discrete screen components: CustomerDefinitionScreen, DoneScreen, FailureKycScreen, FailureScreen, FillingScreen, LinkReadyScreen, LoadingScreen, OpeningLinkScreen, PollingScreen
  • Layout polish, new illustrations (business handshake SVG, document ready/verified SVGs), spinner improvements

New reusable components

  • Checkbox — general-purpose checkbox primitive
  • AlertBanner — contextual alert display (with Storybook story)
  • MaskedAccountNumber — masked display of account numbers (with Storybook story)
  • AnimatedRemoveFiatAccountLabel — animated label for account removal

UI & styling

  • New btn-vortex-success button variant (green)
  • Button cursor fix (cursor: pointer !important)
  • Hover color tweaks for btn-vortex-primary and btn-vortex-danger
  • Modal scroll behavior fix

Translations

  • New strings added to en.json and pt.json for all Alfredpay screens

Minor backend fixes

  • auth.controller.ts: removed stale hardcoded mock return
  • sep10.service.ts: added MXN and COP to the token mapping (marked as not used for SEP10)
  • Removed unused isEvmToken import from final-settlement-subsidy.ts

Docs / tooling

  • CLAUDE.md updated with XState v5 patterns, token exhaustiveness requirements, and "no over-engineering" guidelines
  • Storybook stories added for AlertBanner and MaskedAccountNumber
  • radix-ui added as a frontend dependency

@netlify
Copy link

netlify bot commented Mar 4, 2026

Deploy Preview for vortex-sandbox ready!

Name Link
🔨 Latest commit 6019e85
🔍 Latest deploy log https://app.netlify.com/projects/vortex-sandbox/deploys/69b3ea597b3b150008355faf
😎 Deploy Preview https://deploy-preview-1088--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.

@netlify
Copy link

netlify bot commented Mar 4, 2026

Deploy Preview for vortexfi ready!

Name Link
🔨 Latest commit 43a89a6
🔍 Latest deploy log https://app.netlify.com/projects/vortexfi/deploys/69a8638c2004d00008772348
😎 Deploy Preview https://deploy-preview-1088--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.

@Sharqiewicz Sharqiewicz changed the base branch from staging to add-alfredpay-support March 4, 2026 16:54
@Sharqiewicz Sharqiewicz requested review from ebma and gianfra-t and removed request for gianfra-t March 11, 2026 15:26
@Sharqiewicz Sharqiewicz changed the title [DRAFT] Feature: Alfredpay Fiat Accounts [READY] Feature: Alfredpay Fiat Accounts Mar 11, 2026
Copy link
Contributor

Copilot AI left a comment

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 adds Alfredpay-specific fiat account management and expands fiat token support (USD/MXN/COP), wiring the selected fiat account into the ramp execution flow and updating UI flows (Summary/KYC) accordingly.

Changes:

  • Extend shared token + payment method definitions to include MXN/COP and Alfredpay fiat account types/endpoints.
  • Add a new frontend fiat-account registration + selection UX (XState machine, hooks, API service, SummaryStep integration).
  • Refactor Alfredpay KYC UI into composable screens and introduce new UI primitives (AlertBanner, Checkbox, MaskedAccountNumber, Select, etc.) plus styling/translation updates.

Reviewed changes

Copilot reviewed 82 out of 95 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
packages/shared/src/tokens/types/base.ts Adds MXN/COP to FiatToken enum.
packages/shared/src/tokens/freeTokens/config.ts Updates USD decimals; adds free-token configs for MXN/COP.
packages/shared/src/services/alfredpay/types.ts Adds fiat account types + isAlfredpayToken helper.
packages/shared/src/helpers/payment-method-mapper.ts Adds shared mapFiatToDestination mapping for fiat tokens.
packages/shared/src/endpoints/payment-methods.endpoints.ts Adds SPEI/WIRE payment methods.
packages/shared/src/endpoints/alfredpay.endpoints.ts Adds Alfredpay fiat accounts + requirements endpoint request/response types.
apps/frontend/src/types/phases.ts Adds selectedFiatAccountId to RampExecutionInput.
apps/frontend/src/translations/pt.json Updates existing strings; adds Alfredpay fiat-account strings in PT.
apps/frontend/src/translations/en.json Updates existing strings; adds Alfredpay fiat-account strings in EN.
apps/frontend/src/stories/providers/MockProviders.tsx Wraps Storybook stories with a TanStack Router provider.
apps/frontend/src/stories/MaskedAccountNumber.stories.tsx Adds Storybook coverage for MaskedAccountNumber.
apps/frontend/src/stories/AlertBanner.stories.tsx Adds Storybook coverage for AlertBanner.
apps/frontend/src/stores/quote/useQuoteStore.ts Removes local mapFiatToDestination in favor of shared helper import.
apps/frontend/src/stores/quote/useQuoteFormStore.ts Adds default amounts for USD/MXN/COP.
apps/frontend/src/services/api/alfredpay.service.ts Adds API methods for fiat accounts CRUD + requirements + listing.
apps/frontend/src/sections/business/WhyVortexApi/index.tsx Updates video asset path.
apps/frontend/src/pages/widget/index.tsx Adds FiatAccountMachineContext.Provider + conditional fiat account registration routing.
apps/frontend/src/pages/success/index.tsx Adds MXN/COP success arrival-text mapping.
apps/frontend/src/pages/alfredpay/FiatAccountRegistration/index.tsx Introduces the Alfredpay fiat account registration page/controller component.
apps/frontend/src/pages/alfredpay/FiatAccountRegistration/RemoveAccountControls.tsx Adds hold-to-remove UX for deleting a fiat account.
apps/frontend/src/pages/alfredpay/FiatAccountRegistration/RegisteredAccountsList.tsx Adds list view for registered accounts, skeleton, and KYC gating.
apps/frontend/src/pages/alfredpay/FiatAccountRegistration/RegisterFiatAccountScreen.tsx Adds dynamic RHF+Zod registration form and submission logic.
apps/frontend/src/pages/alfredpay/FiatAccountRegistration/KycRequiredBanner.tsx Adds banner prompting KYC completion before adding accounts.
apps/frontend/src/pages/alfredpay/FiatAccountRegistration/CardHeader.tsx Adds reusable card header for account cards.
apps/frontend/src/pages/alfredpay/FiatAccountRegistration/AccountTypePickerScreen.tsx Adds payment-method picker UI for account type.
apps/frontend/src/pages/alfredpay/FiatAccountRegistration/AccountCardSkeleton.tsx Adds skeleton loader for the account card deck.
apps/frontend/src/pages/alfredpay/FiatAccountRegistration/AccountCardDeck.tsx Adds animated stacked card deck for account selection/removal.
apps/frontend/src/machines/ramp.machine.ts Carries selectedFiatAccountId into executionInput on proceed-to-registration.
apps/frontend/src/machines/fiatAccount.machine.ts Adds new XState v5 machine for fiat account selection/registration navigation.
apps/frontend/src/machines/alfredpayKyc.machine.ts Adjusts Alfredpay KYC machine to add a VerificationDone step.
apps/frontend/src/machines/actors/validateKyc.actor.ts Uses isAlfredpayToken to decide when KYC is needed.
apps/frontend/src/machines/actors/register.actor.ts Sends fiatAccountId for Alfredpay registrations via selectedFiatAccountId.
apps/frontend/src/hooks/useStepper.ts Marks stepper steps as error when Alfredpay KYC subflow is in failure state.
apps/frontend/src/hooks/useStepBackNavigation.ts Adds “back” handling for the fiat account registration subflow.
apps/frontend/src/hooks/useRampUrlParams.ts Uses shared mapFiatToDestination (removes local copy).
apps/frontend/src/hooks/useOnchainTokenBalances.ts Minor comment/punctuation tweak.
apps/frontend/src/hooks/useGetAssetIcon.tsx Adds icon mapping for COP/MXN/USD; updates EUR asset import.
apps/frontend/src/hooks/alfredpay/useFiatAccounts.ts Adds React Query hooks for listing/adding/deleting fiat accounts.
apps/frontend/src/contexts/FiatAccountMachineContext.tsx Adds actor context wiring for the fiat account machine.
apps/frontend/src/constants/fiatAccountMethods.ts Defines country/method configs and mapping helpers for fiat account methods.
apps/frontend/src/constants/fiatAccountForms.ts Defines dynamic form field schemas per payment method.
apps/frontend/src/constants/cache.ts Adds fiatAccounts cache key.
apps/frontend/src/config/tokenAvailability.ts Adds MXN/COP token availability flags.
apps/frontend/src/components/widget-steps/SummaryStep/index.tsx Adds FiatAccountSelector and replaces inline warnings with AlertBanner.
apps/frontend/src/components/widget-steps/SummaryStep/TransactionTokensDisplay.tsx Adds Alfredpay homepage link resolution.
apps/frontend/src/components/widget-steps/SummaryStep/FiatAccountSelector.tsx Adds dropdown selector to choose/manage registered fiat accounts.
apps/frontend/src/components/widget-steps/DetailsStep/index.tsx Updates StepFooter usage after StepFooter API change.
apps/frontend/src/components/widget-steps/AveniaLivenessStep/index.tsx Updates StepFooter usage after StepFooter API change.
apps/frontend/src/components/widget-steps/AuthOTPStep/index.tsx Removes local quote plumbing; relies on store-backed QuoteSummary.
apps/frontend/src/components/widget-steps/AuthEmailStep/index.tsx Removes local quote plumbing; relies on store-backed QuoteSummary.
apps/frontend/src/components/ui/select.tsx Adds a Select component wrapper around Radix primitives.
apps/frontend/src/components/ui/DropdownSelector.tsx Adds custom dropdown selector component (used for fiat account selection).
apps/frontend/src/components/StepFooter/index.tsx Refactors StepFooter to read quote from store and add hideQuoteSummary.
apps/frontend/src/components/Spinner/index.tsx Updates spinner “dark” theme border class.
apps/frontend/src/components/RampSubmitButton/RampSubmitButton.tsx Requires selected fiat account for Alfredpay in KycComplete; passes account id into machine event.
apps/frontend/src/components/QuoteSummary/index.tsx Refactors QuoteSummary to read quote from store and render null when absent.
apps/frontend/src/components/MaskedAccountNumber/index.tsx Adds masked/revealable account number display component.
apps/frontend/src/components/ContactForm/ContactInfo.tsx Minor Tailwind class ordering tweak.
apps/frontend/src/components/Checkbox/index.tsx Adds reusable checkbox primitive.
apps/frontend/src/components/Avenia/DocumentUpload/index.tsx Updates StepFooter usage after StepFooter API change.
apps/frontend/src/components/Avenia/AveniaVerificationForm/index.tsx Updates StepFooter usage after StepFooter API change.
apps/frontend/src/components/Avenia/AveniaKYCForm.tsx Removes local quote plumbing; relies on store-backed QuoteSummary.
apps/frontend/src/components/Avenia/AveniaKYBForm.tsx Removes local quote plumbing; relies on store-backed QuoteSummary.
apps/frontend/src/components/Avenia/AveniaKYBFlow/AveniaKYBVerifyStep.tsx Updates StepFooter usage after StepFooter API change.
apps/frontend/src/components/AnimatedRemoveFiatAccountLabel/index.tsx Adds animated label component used in account removal controls.
apps/frontend/src/components/Alfredpay/PollingScreen.tsx Adds Alfredpay KYC polling screen component.
apps/frontend/src/components/Alfredpay/OpeningLinkScreen.tsx Adds Alfredpay “opening link” screen component.
apps/frontend/src/components/Alfredpay/LoadingScreen.tsx Adds Alfredpay loading screen component.
apps/frontend/src/components/Alfredpay/LinkReadyScreen.tsx Adds Alfredpay “link ready” screen component.
apps/frontend/src/components/Alfredpay/FillingScreen.tsx Adds Alfredpay “complete in new window” screen component.
apps/frontend/src/components/Alfredpay/FailureScreen.tsx Adds Alfredpay failure screen component.
apps/frontend/src/components/Alfredpay/FailureKycScreen.tsx Adds Alfredpay KYC failure screen component.
apps/frontend/src/components/Alfredpay/DoneScreen.tsx Adds Alfredpay done/verified screen component.
apps/frontend/src/components/Alfredpay/CustomerDefinitionScreen.tsx Adds customer type selection/confirmation screen component.
apps/frontend/src/components/Alfredpay/AlfredpayKycFlow.tsx Refactors flow to use new screen components and callbacks.
apps/frontend/src/components/AlertBanner/index.tsx Adds reusable alert banner component.
apps/frontend/src/assets/exclamation_mark_error.svg Adds error illustration asset.
apps/frontend/src/assets/document_verified.svg Adds “verified” illustration asset.
apps/frontend/src/assets/document_ready.svg Adds “document ready” illustration asset.
apps/frontend/src/assets/coins/placeholder.svg Updates placeholder coin SVG asset.
apps/frontend/src/assets/coins/USD.png Adds USD icon asset.
apps/frontend/src/assets/business-handshake.svg Adds business handshake illustration asset.
apps/frontend/src/assets/coins/EUR.svg Removes old EUR svg asset (replaced by EU.png in code).
apps/frontend/package.json Adds radix-ui dependency.
apps/frontend/App.css Adds success button variant and various button/modal style tweaks.
apps/api/src/api/services/sep10/sep10.service.ts Extends token mapping to include MXN/COP (mapped to USDC).
apps/api/src/api/services/phases/handlers/final-settlement-subsidy.ts Removes unused import.
apps/api/src/api/controllers/auth.controller.ts Modifies token verification endpoint (currently hardcoded).
CLAUDE.md Updates repo guidelines (Bun usage, XState v5 patterns, token exhaustiveness notes).

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

Comment on lines +138 to +139
return { user_id: "4f1cf68e-831a-4314-b156-0d5c0fa93d67", valid: true };

Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

verifyToken returns a hardcoded { user_id, valid } object before any validation logic and without sending an HTTP response via res.json(...). This effectively bypasses auth verification (and may leave requests hanging depending on the framework wiring). Remove the early return and restore proper token verification + response handling.

Suggested change
return { user_id: "4f1cf68e-831a-4314-b156-0d5c0fa93d67", valid: true };

Copilot uses AI. Check for mistakes.
Comment on lines 23 to 34
[FiatToken.USD]: {
disabledReasonTranslationKey: "pages.swap.error.USD_tokenUnavailable",
enabled: true
},
[FiatToken.MXN]: {
disabledReasonTranslationKey: "pages.swap.error.MXN_tokenUnavailable",
enabled: false
},
[FiatToken.COP]: {
disabledReasonTranslationKey: "pages.swap.error.COP_tokenUnavailable",
enabled: false
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

MXN/COP are introduced as part of this Alfredpay fiat accounts feature, but they are marked enabled: false here. This conflicts with the PR description (“enabling users… when transacting in USD, MXN and COP”) and will keep them unavailable in the UI. Either enable them or clarify/gate the rollout elsewhere and update the PR description accordingly.

Copilot uses AI. Check for mistakes.
Comment on lines +291 to 292
"noNewslettersNoSpam": "No newsletters, no spam- just your honest thoughts.",
"submit": "Submit",
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

These strings replaced an em dash with a hyphen but missed spacing ("spam- just"). This reads like a typo; use either an em dash (—) or add spaces around the hyphen for proper punctuation.

Copilot uses AI. Check for mistakes.
"cnpjUserDoesntExist": "Please contact our support team at support@vortexfinance.co to get onboarded as a business user.",
"kycInvalid": "Your KYC level is invalid. Please contact support.",
"maintenance": "Temporary maintenance in progress please check back later."
"maintenance": "Temporary maintenance in progress- please check back later."
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

This string replaced an em dash with a hyphen but missed spacing ("progress- please"). This reads like a typo; use either an em dash (—) or add spaces around the hyphen for proper punctuation.

Copilot uses AI. Check for mistakes.
"error": "Erro ao salvar seu e-mail. Por favor, tente novamente.",
"loading": "Carregando...",
"noNewslettersNoSpam": "Sem newsletters, sem spam apenas suas opiniões sinceras.",
"noNewslettersNoSpam": "Sem newsletters, sem spam- apenas suas opiniões sinceras.",
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

This string replaced an em dash with a hyphen but missed spacing ("spam- apenas"). This reads like a punctuation typo; use either an em dash (—) or add a space after the hyphen.

Copilot uses AI. Check for mistakes.
Comment on lines +338 to +340
const ALFREDPAY_FIAT_TOKEN_SET = new Set<FiatToken>([FiatToken.USD, FiatToken.MXN, FiatToken.COP]);

export const isAlfredpayToken = (token: FiatToken): boolean => ALFREDPAY_FIAT_TOKEN_SET.has(token);
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

isAlfredpayToken includes FiatToken.COP, but the frontend Alfredpay country/method config currently only covers USD (US) and MXN (MX). This can cause COP flows to require Alfredpay KYC / fiat-account selection without having a supported country/method mapping. Either add full COP support (country config + payment method mapping + UI) or remove COP from the Alfredpay token set until it’s supported end-to-end.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +30
export const ALFREDPAY_COUNTRY_METHODS: CountryFiatAccountConfig[] = [
{
country: "US",
countryName: "United States",
currency: "USD",
offramp: ["ACH", "WIRE"],
onramp: ["ACH", "WIRE"]
},
{
country: "MX",
countryName: "Mexico",
currency: "MXN",
offramp: ["SPEI"],
onramp: ["SPEI"]
}
];
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

FiatToken.COP is treated as an Alfredpay token elsewhere (e.g. isAlfredpayToken), but there is no corresponding country config here, so ALFREDPAY_FIAT_TOKEN_TO_COUNTRY will never map COP to a country. That means the fiat account selector/registration flow can’t work for COP. Add a Colombia entry (and supported methods) or remove COP from the Alfredpay token set until it’s fully supported end-to-end.

Copilot uses AI. Check for mistakes.
Comment on lines +68 to +75
export const mapFiatToDestination = (fiatToken: FiatToken): DestinationType => {
const destinationMap: Record<FiatToken, DestinationType> = {
ARS: EPaymentMethod.CBU,
BRL: EPaymentMethod.PIX,
COP: EPaymentMethod.SPEI,
EUR: EPaymentMethod.SEPA,
MXN: EPaymentMethod.SPEI,
USD: EPaymentMethod.ACH
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

mapFiatToDestination maps COP to SPEI, which is a Mexico payment rail. Given COP isn’t configured in ALFREDPAY_COUNTRY_METHODS, this mapping is likely incorrect and will route COP quotes to the wrong destination type. Please confirm the correct payment method for COP and update this mapping (or avoid mapping COP until supported).

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +38
<>
{"•"
.repeat(accountNumber.length - 4)
.split("")
.map((_, i) => (
<span className="inline-block w-[1ch] text-center" key={i}>
</span>
))}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

"•".repeat(accountNumber.length - 4) will throw a RangeError if accountNumber is shorter than 4 characters. Since AlfredpayFiatAccountFields.accountNumber is just a string (no length guarantees at the type level), this can crash the UI for unexpected provider data. Guard the repeat count with Math.max(0, accountNumber.length - 4) (and consider a sensible fallback display for very short values).

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +9
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
import { Select as SelectPrimitive } from "radix-ui";
import * as React from "react";

import { cn } from "../../helpers/cn";

function Select({ ...props }: React.ComponentProps<typeof SelectPrimitive.Root>) {
return <SelectPrimitive.Root data-slot="select" {...props} />;
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

The Select primitive is imported as a single named export (Select as SelectPrimitive) but then used as a namespace (SelectPrimitive.Root, SelectPrimitive.Trigger, etc.). Unless the library explicitly exports an object with these members, this will be undefined at runtime. Use a namespace import that matches Radix Select’s API surface (and ensure the dependency matches the import path).

Copilot uses AI. Check for mistakes.
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.

3 participants