Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
2230522
add EU flag
Sharqiewicz Mar 4, 2026
bf3d955
add COP flag
Sharqiewicz Mar 4, 2026
9c9df46
add MX flag
Sharqiewicz Mar 4, 2026
729ef9d
add USD flag
Sharqiewicz Mar 4, 2026
c36399b
remove EUR images and replace placeholder
Sharqiewicz Mar 4, 2026
c6172b1
update useGetAssetIcon to handle new currencies
Sharqiewicz Mar 4, 2026
0456a7b
update useGetAssetIcon to handle new currencies
Sharqiewicz Mar 4, 2026
f533870
add reusable Checkbox component
Sharqiewicz Mar 4, 2026
dbc188c
add business handshake svg for AlfredPay KYB
Sharqiewicz Mar 4, 2026
80a093b
create CustomerDefinitionScreen
Sharqiewicz Mar 4, 2026
14cbbef
extract DoneScreen
Sharqiewicz Mar 4, 2026
20e0e63
extract FailureKYCScreen
Sharqiewicz Mar 4, 2026
428f542
extract FailureScreen
Sharqiewicz Mar 4, 2026
eea51a2
extract FillingScreen
Sharqiewicz Mar 4, 2026
3e62563
extract LinkReadyScreen
Sharqiewicz Mar 4, 2026
8542032
extract LoadingScreen
Sharqiewicz Mar 4, 2026
5f62d89
extract OpeningLinkScreen
Sharqiewicz Mar 4, 2026
7eb4a37
extract PollingScreen
Sharqiewicz Mar 4, 2026
2499231
refactor AlfredpayKycFlow screen
Sharqiewicz Mar 4, 2026
986f2d4
move useQuote to QuoteSummary
Sharqiewicz Mar 4, 2026
43a89a6
remove unnecessary translation
Sharqiewicz Mar 4, 2026
1dca43f
fix MXN flag
Sharqiewicz Mar 4, 2026
8ce6f96
Shared: add MXN/COP tokens + isAlfredpayToken helper
Sharqiewicz Mar 9, 2026
a57cd00
add COP,MXN token mapping
Sharqiewicz Mar 10, 2026
1354ad4
new UI primitives for fiat account management
Sharqiewicz Mar 10, 2026
382e786
fiat account management constants, hooks, machine + service
Sharqiewicz Mar 10, 2026
8b4a5c3
create FiatAccountRegistration screens
Sharqiewicz Mar 10, 2026
10e4c3c
integrate AlfredpayPaymentMethodSelector into SummaryStep
Sharqiewicz Mar 10, 2026
a95d109
FiatAccountRegistration and go back navigation into widget/KYC
Sharqiewicz Mar 10, 2026
46c532d
multi-currency Alfredpay routing
Sharqiewicz Mar 10, 2026
151c614
MXN/COP token display, defaults, and URL params
Sharqiewicz Mar 10, 2026
d09ffac
chores
Sharqiewicz Mar 10, 2026
008fc2e
refactor: rename paymentMethods machine and constants to fiatAccount
Sharqiewicz Mar 11, 2026
b4ff18c
replace AlfredpayPaymentMethodSelector with FiatAccountSelector in Su…
Sharqiewicz Mar 11, 2026
33d46c1
replace MethodPickerScreen with AccountTypePickerScreen in FiatAccoun…
Sharqiewicz Mar 11, 2026
fabf1f9
add AlertBanner component and update FailureScreen
Sharqiewicz Mar 11, 2026
5c09257
disable Payment Summary confirm for alfredpay currencies if no Paymen…
Sharqiewicz Mar 11, 2026
ab53009
Add translations for Alfredpay screens
Sharqiewicz Mar 11, 2026
ebbccb2
Add selectedFiatAccountId? to RampExecutionInput
Sharqiewicz Mar 11, 2026
e96a07c
extract MaskedAccountNumber reusable component
Sharqiewicz Mar 11, 2026
5674acd
Alfredpay KYC screens: layout polish + illustrations
Sharqiewicz Mar 11, 2026
42738aa
polish Alfredpay KYC screens: illustrations, layout, spinner
Sharqiewicz Mar 11, 2026
3d5d23a
add btn-vortex-success variant and btn cursor fix
Sharqiewicz Mar 11, 2026
c63f09d
Remove trailing ellipsis from verifying translation strings
Sharqiewicz Mar 11, 2026
723a6f7
Stories / dev tooling
Sharqiewicz Mar 11, 2026
1383528
implement shared zustand store for Fiat Account Management
Sharqiewicz Mar 11, 2026
8e6e2af
improve fiat accounts store management
Sharqiewicz Mar 12, 2026
ce579f8
Remove hardcoded user ID from token verification response
ebma Mar 13, 2026
bfa40f9
Fix missing translations
ebma Mar 13, 2026
b78c079
Fix wrong symbol for MXN currency
ebma Mar 13, 2026
3c86302
Adjust text
ebma Mar 13, 2026
6019e85
Remove console logs
ebma Mar 13, 2026
0e2074e
fix(token-selection): remove conditional virtualization and correct r…
Sharqiewicz Mar 23, 2026
476e3b6
Merge branch 'feat/alfredpay-fiat-accounts' of github.com:pendulum-ch…
Sharqiewicz Mar 23, 2026
7688a17
add widget UI typography scale tokens
Sharqiewicz Mar 24, 2026
33a4013
add widget UI typography scale tokens
Sharqiewicz Mar 24, 2026
4959417
extract InfoBox from repeated border+padding pattern
Sharqiewicz Mar 24, 2026
6630034
replace hardcoded colors with semantic tokens
Sharqiewicz Mar 24, 2026
55f2453
update design tokens
Sharqiewicz Mar 24, 2026
e2aefb6
refactor: extract setInterval countdown logic into useCountdown hook
Sharqiewicz Mar 24, 2026
3660902
Code quality: cn(), SearchInput a11y, z-index scale and normalize ha…
Sharqiewicz Mar 24, 2026
3ee1f00
allow reopening verification window from VerifyingCompletion state
Sharqiewicz Mar 24, 2026
092bc59
guard repeat() against short account numbers
Sharqiewicz Mar 24, 2026
51fb635
replace malformed hyphens with em dashes in EN and PT translations
Sharqiewicz Mar 24, 2026
8d9f7fb
accessibility and touch improvements for virtual list
Sharqiewicz Mar 24, 2026
7fd7320
remove console logs from SEP-24 actors and ramp flow
Sharqiewicz Mar 24, 2026
fb31e9c
replace className string concatenation with cn() helper
Sharqiewicz Mar 24, 2026
bcf82b0
add touch-target utility; fix AssetButton hit area, CloseButton, Emai…
Sharqiewicz Mar 24, 2026
e4e71d4
optimize Fiat Accounts management
Sharqiewicz Mar 24, 2026
c9b6d16
replace hardcoded blue-700 with primary token across all components …
Sharqiewicz Mar 24, 2026
d1b8621
add .impeccable.md
Sharqiewicz Mar 24, 2026
5f64172
Merge branch 'add-alfredpay-support' into feat/alfredpay-fiat-accounts
Sharqiewicz Mar 24, 2026
d37b445
add bun.lock
Sharqiewicz Mar 24, 2026
b9e9d97
Adjust .mcp.json
ebma Mar 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"mcpServers": {
"linear-server": {
"type": "sse",
"url": "https://mcp.linear.app/sse"
},
"obsidian": {
"args": ["-y", "obsidian-mcp", "$OBSIDIAN_VAULT_PATH"],
"command": "npx"
}
}
}
27 changes: 26 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ This is a **Bun monorepo** using workspaces:

## Essential Commands

> Always use `bun`- never `npm`, `yarn`, or `pnpm`. Run `bun lint:fix` after any code change.

```bash
# Install all dependencies
bun install
Expand Down Expand Up @@ -70,7 +72,7 @@ Phase metadata and valid transitions are stored in PostgreSQL and seeded via `se
### Frontend Architecture

- **State**: Zustand stores (`stores/`) + React Context (`contexts/`)
- **Forms**: React Hook Form with Yup validation
- **Forms**: React Hook Form with Zod validation (not Yup)
- **Data Fetching**: TanStack Query
- **Routing**: TanStack Router (route tree auto-generated in `routeTree.gen.ts`)
- **State Machines**: XState machines in `machines/` for complex flows (KYC, ramp process)
Expand All @@ -95,6 +97,8 @@ Contains cross-package utilities:

**Important**: Always rebuild shared when making changes: `bun build:shared`

After ANY change to `packages/shared`, run `bun build:shared` before running frontend/api.

## Code Style Guidelines

From `.clinerules/`:
Expand All @@ -110,6 +114,11 @@ From `.clinerules/`:
- Extract complex conditional rendering into new components
- Skip useless comments; only comment race conditions, TODOs, or genuinely confusing code

### XState v5
- Use `setup({ ... }).createMachine(...)` API- not `createMachine` directly
- Actor refs from `useActor` / `useSelector` from `@xstate/react`
- Machine files live in `apps/frontend/src/machines/`

### Biome Configuration
- Line width: 128
- Indent: 2 spaces
Expand All @@ -118,6 +127,22 @@ From `.clinerules/`:
- Quote style: double
- Sorted Tailwind classes enforced via `useSortedClasses` rule

## Token Exhaustiveness

`FiatToken` currently has 6 values: `EURC`, `ARS`, `BRL`, `USD`, `MXN`, `COP`.

Any `Record<FiatToken, X>` must include ALL six. Missing entries cause TypeScript errors
when shared is rebuilt. Check: tokenAvailability, mapFiatToDestination, success page
ARRIVAL_TEXT_BY_TOKEN, sep10 tokenMapping.

## No Over-Engineering

- Don't add features, refactors, or "improvements" beyond what was asked
- Don't add docstrings/comments to code you didn't touch
- Don't create helpers/utilities for one-time operations
- Don't validate inputs that can't be invalid (internal calls, typed params)
- Three similar lines is better than a premature abstraction

## Testing

### Backend Integration Tests
Expand Down
6 changes: 0 additions & 6 deletions apps/api/src/api/controllers/alfredpay.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@ import {
AlfredpayCreateCustomerResponse,
AlfredpayCustomerType,
AlfredpayGetKybRedirectLinkResponse,
AlfredpayGetKybStatusResponse,
AlfredpayGetKycRedirectLinkRequest,
AlfredpayGetKycRedirectLinkResponse,
AlfredpayGetKycStatusRequest,
AlfredpayGetKycStatusResponse,
AlfredpayKybStatus,
AlfredpayKycRedirectFinishedRequest,
AlfredpayKycRedirectOpenedRequest,
AlfredpayKycStatus,
AlfredpayStatusRequest,
AlfredpayStatusResponse
Expand Down Expand Up @@ -258,10 +254,8 @@ export class AlfredpayController {
: await alfredpayService.getKycStatus(alfredPayCustomer.alfredPayId, lastSubmission.submissionId);

const newStatus = AlfredpayController.mapKycStatus(statusResponse.status);
console.log("newStatus", newStatus);
const updateData: Partial<AlfredPayCustomer> = {};

console.log("our status", alfredPayCustomer.status);
if (newStatus && newStatus !== alfredPayCustomer.status) {
updateData.status = newStatus;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
getNetworkId,
getOnChainTokenDetails,
getRoute,
isEvmToken,
multiplyByPowerOfTen,
Networks,
RampCurrency,
Expand Down
4 changes: 3 additions & 1 deletion apps/api/src/api/services/sep10/sep10.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ export const signSep10Challenge = async (
[FiatToken.EURC]: "EURC",
[FiatToken.ARS]: "ARS",
[FiatToken.BRL]: "BRL",
[FiatToken.USD]: "USDC" // USD maps to USDC for consistency, though not used for SEP10
[FiatToken.USD]: "USDC",
[FiatToken.MXN]: "USDC",
[FiatToken.COP]: "USDC"
};

const outToken = tokenMapping[fiatToken];
Expand Down
82 changes: 82 additions & 0 deletions apps/frontend/.impeccable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
## Design Context

### Users

**Primary:** Crypto-native DeFi users who need to move money between fiat and crypto efficiently. They understand wallets, slippage, liquidity — but still expect fast, frictionless UX.

**Integration partners:** Protocols like Pendle that embed Vortex as a ramping layer. Users arrive mid-flow from another product and need zero onboarding friction.

**High-volume P2P operators:** Businesses like IaCrypto (Brazil) processing millions in daily volume. They care about reliability, speed, and trust signals — not aesthetics. Every failure costs real money.

**Implication:** The interface must feel immediately legible to someone who has used Aave or Uniswap. No hand-holding, no consumer-app softness. Assume competence.

---

### Brand Personality

**Three words:** Reliable. Modern. Calm.

- **Reliable** — Every element should signal that this system works, is audited, and handles real money. No flashy UI that feels like a casino. When something goes wrong, error states are clear and non-panicking.
- **Modern** — On par visually with Aave, not behind it. Clean, high-contrast, purposeful use of space. No legacy fintech feel.
- **Calm** — Payments are stressful. The UI absorbs that stress. Generous whitespace, unhurried layouts, smooth transitions — not jarring or jumpy.

**Voice:** Concise, direct, confident. No filler copy. Labels describe exactly what they mean. Errors explain what happened and what to do.

---

### Aesthetic Direction

**Primary reference:** Aave — dark-capable, information-dense but not cluttered, strong typographic hierarchy, restrained use of color, data displayed with precision.

**Theme:** Light mode only (current). White cards on near-white backgrounds, blue as the single action color, pink as a secondary signal only where needed.

**Anti-references:**

- Consumer fintech (Revolut, Cash App) — too playful, too colorful, wrong audience
- Crypto degen UIs — cluttered, aggressive, no hierarchy
- Legacy banking UIs — dated, corporate, low trust with DeFi users

**Color discipline:** Blue for all primary actions. Pink accent used sparingly — not decoratively. Grays carry most of the layout weight. No rainbow, no gradients for decoration.

**Motion:** Purposeful only. Appear/slide-up transitions on mount, scale feedback on press. No looping animations, no attention-grabbing movement.

---

### Design Principles

1. **Precision over decoration** — Every pixel should communicate information or create breathing room. Remove anything that doesn't do one of those two things.
2. **Trust is the product** — Visual consistency, clear number formatting, explicit fee disclosure, and legible error states are not polish — they are the core UX. High-volume users will abandon on the first sign of confusion.
3. **Assume competence** — Skip tutorials and tooltips for basic crypto concepts. Show data at the right level of detail. Let advanced users read everything they need directly from the UI.
4. **Calm under load** — Loading states, errors, and multi-step flows should feel controlled and unhurried. Use skeletons, not spinners. Use descriptive status labels, not raw error codes.
5. **Aave-level finish** — The standard is: would this component look at home in the Aave interface? Consistent border radii, aligned grids, correct font weights, no stray margins. Ship nothing that falls below that bar.

---

### Design System

**Stack:** Tailwind CSS v4 + DaisyUI v5 + Framer Motion (`motion/react`). All color tokens in OKLCH.

**Color tokens** (defined in `apps/frontend/App.css` `:root`):
- `--color-primary` / `--color-primary-hover` — brand blue, all primary actions
- `--color-accent` — pink, secondary signal only (never decorative)
- `--color-error/success/warning` + `-hover` variants — semantic state colors
- `--color-primary-hover`, `--color-secondary-hover`, `--color-error-hover`, `--color-success-hover`, `--color-warning-hover` — darkened versions for button hover states (never invert on hover)

**Button variants** (in `App.css`):
- `.btn-vortex-primary` — blue, main CTA
- `.btn-vortex-primary-inverse` — outlined blue
- `.btn-vortex-secondary` — pink
- `.btn-vortex-accent` — gray, tertiary
- `.btn-vortex-success` / `.btn-vortex-danger` / `.btn-vortex-warning` — state variants
- All hover states darken (use `-hover` tokens), never invert to light background

**Spacing utilities:**
- `.pb-footer-offset` — `calc(var(--quote-summary-height) + 1rem)` for content above absolute footer
- `.bottom-above-quote` — positions elements above the QuoteSummary panel
- `.touch-target` — expands hit area by 8px on all sides via `::after` pseudo-element without affecting layout; use on small interactive elements instead of inflating their visual size

**Z-index scale** (named utilities, never arbitrary values):
- `.z-footer` (5) → `.z-quote` (10) → `.z-overlay` (20) → `.z-modal` (50) → `.z-toast` (100)

**Typography:** `"Red Hat Display"` only. Use `.text-widget-title`, `.text-section-title`, `.text-amount`, `.text-label`, `.text-caption` for widget UI — never raw Tailwind font sizes inside the widget.

Loading