Sync Grid Visualizer with PaymentRail enum - #351
Conversation
Update currencies.ts to use SCREAMING_SNAKE_CASE payment rail values that match the PaymentRail enum in the OpenAPI spec (e.g., FEDNOW, FASTER_PAYMENTS, SEPA_INSTANT, BANK_TRANSFER, MOBILE_MONEY). Add paymentRails field to generated external account creation requests in code-generator.ts to match documented workflow examples. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR syncs the Grid Visualizer with the new Confidence Score: 4/5The currencies.ts enum update is safe, but code-generator.ts injects a response-only field into create request bodies which would produce incorrect example code. One P1 finding: paymentRails is injected into accountInfo for external account creation requests, but the field is absent from all create-request schemas (*AccountInfoBase). This generates misleading or broken example API calls, which is the core purpose of this visualizer. The P2 (enum values in prose) is minor. Score is 4 until the P1 is resolved. components/grid-visualizer/src/lib/code-generator.ts — paymentRails field placement in buildAccountInfoBody
|
| Filename | Overview |
|---|---|
| components/grid-visualizer/src/data/currencies.ts | Rail values updated to SCREAMING_SNAKE_CASE matching the PaymentRail enum; all new values (FEDNOW, WIRE, SEPA_INSTANT, FASTER_PAYMENTS, BANK_TRANSFER, MOBILE_MONEY, PAYNOW) are valid enum members. |
| components/grid-visualizer/src/lib/code-generator.ts | Adds paymentRails to accountInfo in external account create requests, but this field exists only in response schemas (*AccountInfo), not create request schemas (*AccountInfoBase) — the generated example code would send an undocumented field to the API. |
Sequence Diagram
sequenceDiagram
participant UI as Grid Visualizer UI
participant CG as code-generator.ts
participant CUR as currencies.ts (PaymentRail enum)
participant API as Grid API
UI->>CG: generateSteps(source, destination)
CG->>CUR: find(c => c.code === sel.code)
CUR-->>CG: fiat.allRails (SCREAMING_SNAKE_CASE)
CG->>CG: buildAccountInfoBody() sets info.paymentRails = allRails
CG-->>UI: ApiStep with accountInfo.paymentRails
UI->>API: POST /customers/external-accounts { accountInfo: { ..., paymentRails: [...] } }
Note over API: paymentRails not in create schema, only in response schema
Comments Outside Diff (1)
-
components/grid-visualizer/src/lib/code-generator.ts, line 309 (link)Raw enum values in user-facing note text
getJitPaymentMethod()now returns strings like"FEDNOW transfer"or"SEPA_INSTANT transfer"fromfiat.instantRails[0], which appear directly in the step note shown to the user: "Trigger the payment by sending a SEPA_INSTANT transfer to the deposit address...". The previous human-readable names (FedNow,SEPA Instant) were better suited for this prose context.Consider either keeping a separate display-name map for prose use or adding a formatting helper that converts
SEPA_INSTANT→SEPA Instantfor the note text.Prompt To Fix With AI
This is a comment left during a code review. Path: components/grid-visualizer/src/lib/code-generator.ts Line: 309 Comment: **Raw enum values in user-facing note text** `getJitPaymentMethod()` now returns strings like `"FEDNOW transfer"` or `"SEPA_INSTANT transfer"` from `fiat.instantRails[0]`, which appear directly in the step note shown to the user: *"Trigger the payment by sending a SEPA_INSTANT transfer to the deposit address..."*. The previous human-readable names (`FedNow`, `SEPA Instant`) were better suited for this prose context. Consider either keeping a separate display-name map for prose use or adding a formatting helper that converts `SEPA_INSTANT` → `SEPA Instant` for the note text. How can I resolve this? If you propose a fix, please make it concise.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix All With AI
This is a comment left during a code review.
Path: components/grid-visualizer/src/lib/code-generator.ts
Line: 51-57
Comment:
**`paymentRails` is a response-only field**
`paymentRails` is not part of the external account creation request schema. Every `*ExternalAccountCreateInfo` schema (e.g. `UsdExternalAccountCreateInfo`) extends `*AccountInfoBase`, and none of those base schemas include `paymentRails`. The field only appears in the response-side `*AccountInfo` schemas (e.g. `UsdAccountInfo`) that the API returns after creation.
Sending `paymentRails` inside `accountInfo` will either cause a 400 validation error or be silently ignored — either way it generates misleading example code for developers using this visualizer as a reference. The OpenAPI spec examples in `customers_external_accounts.yaml` also omit it from create request bodies.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: components/grid-visualizer/src/lib/code-generator.ts
Line: 309
Comment:
**Raw enum values in user-facing note text**
`getJitPaymentMethod()` now returns strings like `"FEDNOW transfer"` or `"SEPA_INSTANT transfer"` from `fiat.instantRails[0]`, which appear directly in the step note shown to the user: *"Trigger the payment by sending a SEPA_INSTANT transfer to the deposit address..."*. The previous human-readable names (`FedNow`, `SEPA Instant`) were better suited for this prose context.
Consider either keeping a separate display-name map for prose use or adding a formatting helper that converts `SEPA_INSTANT` → `SEPA Instant` for the note text.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "Sync Grid Visualizer with PaymentRail en..." | Re-trigger Greptile
| // Add paymentRails for fiat currencies | ||
| if (sel.type === 'fiat') { | ||
| const fiat = currencies.find((c) => c.code === sel.code); | ||
| if (fiat && fiat.allRails.length > 0) { | ||
| info.paymentRails = fiat.allRails; | ||
| } | ||
| } |
There was a problem hiding this comment.
paymentRails is a response-only field
paymentRails is not part of the external account creation request schema. Every *ExternalAccountCreateInfo schema (e.g. UsdExternalAccountCreateInfo) extends *AccountInfoBase, and none of those base schemas include paymentRails. The field only appears in the response-side *AccountInfo schemas (e.g. UsdAccountInfo) that the API returns after creation.
Sending paymentRails inside accountInfo will either cause a 400 validation error or be silently ignored — either way it generates misleading example code for developers using this visualizer as a reference. The OpenAPI spec examples in customers_external_accounts.yaml also omit it from create request bodies.
Prompt To Fix With AI
This is a comment left during a code review.
Path: components/grid-visualizer/src/lib/code-generator.ts
Line: 51-57
Comment:
**`paymentRails` is a response-only field**
`paymentRails` is not part of the external account creation request schema. Every `*ExternalAccountCreateInfo` schema (e.g. `UsdExternalAccountCreateInfo`) extends `*AccountInfoBase`, and none of those base schemas include `paymentRails`. The field only appears in the response-side `*AccountInfo` schemas (e.g. `UsdAccountInfo`) that the API returns after creation.
Sending `paymentRails` inside `accountInfo` will either cause a 400 validation error or be silently ignored — either way it generates misleading example code for developers using this visualizer as a reference. The OpenAPI spec examples in `customers_external_accounts.yaml` also omit it from create request bodies.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Fixed in e3191b4 — the paymentRails injection is removed, and code-generator.ts is now byte-identical to the base commit.
Confirmed the finding against current main before removing it. UsdExternalAccountCreateInfo and UsdAccountInfo both extend the same UsdAccountInfoBase; paymentRails is added only in the response wrapper:
# UsdAccountInfo.yaml (response)
allOf:
- $ref: ./UsdAccountInfoBase.yaml
- required: [paymentRails] # ← only here
# UsdExternalAccountCreateInfo.yaml (create request)
allOf:
- $ref: ./BaseExternalAccountInfo.yaml
- $ref: ../common/UsdAccountInfoBase.yaml
- required: [beneficiary] # ← no paymentRailsWorth noting the PR description justified this hunk by citing workflows.md. That reference no longer says so — main now states the opposite in two places, so there's nothing left to fix upstream:
.claude/skills/grid-api/SKILL.md: "Do not sendpaymentRails— Grid selects the rail and returns it on the created account.".claude/skills/grid-api/references/account-types.md: "The rail is chosen by Grid and returned on the created account (the responsepaymentRailsfield) — it is not a request input."
The currencies.ts half is unaffected and still needed: main continues to carry 'FedNow' / 'SEPA Instant' / 'Bank Transfer' while the spec has the PaymentRail enum. I checked every value in the diff against PaymentRail.yaml — ACH, WIRE, RTP, FEDNOW, SEPA, SEPA_INSTANT, FASTER_PAYMENTS, BANK_TRANSFER, MOBILE_MONEY, PAYNOW, FAST are all valid members.
Generated by Claude Code
The visualizer was injecting paymentRails into the body of
POST /customers/external-accounts. That field is response-only:
*ExternalAccountCreateInfo and *AccountInfo both extend the same
*AccountInfoBase, and paymentRails is added only in the response
wrapper. Generated example calls therefore sent a field the create
endpoint does not accept.
The skill reference now states this explicitly ("Do not send
paymentRails - Grid selects the rail and returns it on the created
account"), so the workflow examples this change was originally
justified by no longer say what it claimed.
Also add railDisplayName() for rendering rails as prose. Moving
currencies.ts to PaymentRail enum values is correct for the data, but
those values reach the UI in four places - the JIT payment note, the
currency picker rail list, the rail dropdown, and the flow-path
captions - which would otherwise read "SEPA_INSTANT transfer". The
enum value stays the data; the display name is presentation only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMnjJ8yWJsui7jLqqrDrL4
|
Also addressed the P2 from the Greptile summary (raw enum values in prose), which had no review thread to reply to. The scope was slightly wider than the original comment described.
Took the display-map approach suggested in the comment: The enum value remains the data everywhere; One thing I could not verify locally: Generated by Claude Code |
|
no longer relevant -- rail is not specified on create anymore |
## What Makes the Grid Visualizer's payment-rail selection functional. Today the rail is decorative — the user picks one from a dropdown and it only changes UI captions. This threads the choice into the generated `POST /quotes` request as `destination.paymentRail`. **Supersedes #351.** ## Why the `currencies.ts` rename is a prerequisite, not a cosmetic change `instantRails` / `allRails` currently hold human-readable strings (`'FedNow'`, `'SEPA Instant'`, `'Bank Transfer'`, …). Those are not values the API accepts, so **no rail could be sent at all** while the data held display strings. Converting them to `PaymentRail` enum members (`FEDNOW`, `SEPA_INSTANT`, `BANK_TRANSFER`, …) is what makes the feature possible. Because the enum values would otherwise render as `SEPA_INSTANT` at users, this adds an exported `railDisplayName()` covering all 23 enum members (with an underscores-to-spaces fallback) and applies it at the four sites that surface a rail: 1. `code-generator.ts` — `getJitPaymentMethod()`, the "sending a FedNow transfer" prose note 2. `CurrencyPicker.tsx` — `getRailsText()` and the `keywords` array in `buildFiatItem` (keywords keep **both** enum and display forms, so search still matches either) 3. `InputCard.tsx` — dropdown button label, dropdown menu items, static `fiatRail` row 4. `flow-path.ts` — the "Funds in via X" / "Funds out via X" captions **The enum value is the data; `railDisplayName()` is presentation only.** No display string reaches a request body or `onSelect`/state. The rename + display map is carried over from the closing PR on `docs/sync-20260418` (`e3191b4`). Two currencies added to `main` since that branch (El Salvador `SLV_ACCOUNT`, `CNY_ACCOUNT`) were converted here as well. ## `paymentRail` vs `paymentRails` — the distinction #351 got wrong | | | |---|---| | **`paymentRail`** (singular) | **Request** field, on quote destinations only (`quotes/AccountDestination.yaml`). Optional — omitted, Grid selects a default. | | **`paymentRails`** (plural) | **Response**-only. Lives in `*AccountInfo.yaml` wrappers, reporting what an account supports. Absent from `*ExternalAccountCreateInfo` / `*AccountInfoBase`. | #351 injected the plural into `POST /customers/external-accounts` bodies — a field that endpoint does not accept. This PR introduces **no** `paymentRails` anywhere (`grep -rn paymentRails src/` in the visualizer returns nothing), and `buildAccountInfoBody` has no rail logic at all. A short WHY comment at the emission site records the distinction. ## The source/destination asymmetry The spec puts `paymentRail` on the **destination**, but the visualizer's only rail selector was on the **Source** card. So this adds a destination-side selection rather than reusing the source's: - `useFlowBuilder.ts`: `destRail` state, `SET_DEST_RAIL` action, `setDestRail` callback — mirroring `sourceRail` exactly. Defaults via the existing `getDefaultRail()` on `SET_RECEIVE`, and recomputed on `SWAP` (matching how `sourceRail` already behaves there). - `page.tsx`: Destination `InputCard` now gets `rail` / `onRailChange`. `InputCard` already supported these generically, so no component changes were needed beyond the display-name calls. - Options stay constrained to the currency's `allRails` via the existing `getFiatRailOptions`, per "must be one of the rails supported by the destination account." The existing source rail is untouched and keeps its display purposes. `flow-path.ts`'s "Funds out via X" caption now uses the selected destination rail instead of always defaulting to `instantRails[0]` — same user choice, so it should reflect it. ## Judgment call worth a second opinion **`paymentRail` is emitted only for external destinations**, in addition to the "fiat and a rail selected" conditions. Funds credited to a Grid internal balance never traverse an external payment rail, so sending one there would generate an example the API would likely reject. This also matches how `flow-path.ts` already treats rails (the "Funds out via" caption only renders for `!next.isInternal`). A destination can become internal via **Swap**. Happy to drop the gate if reviewers disagree. Note the UI still shows a Rail row on an internal fiat destination card even though it no longer affects the body — consistent with how the Source card already behaves for internal sources. Hiding it felt like scope creep; flagging rather than fixing. ## Verification — please read **I could not run the real build.** `npm ci` in `components/grid-visualizer` fails because `@central-icons-react` requires a `CENTRAL_LICENSE_KEY` env var that is not available in this environment. **The Vercel preview build on this PR is the real check** — `next build` / `next lint` and all `.tsx` typechecking are unverified here. What I *was* able to verify locally: - **Strict typecheck of every dependency-free module** — `code-generator.ts`, `flow-path.ts`, `currencies.ts`, `settlement-rails.ts`, `account-types.ts`, `crypto.ts` under `strict: true` with the `@/*` path mapping: clean. The `.tsx` files could not be checked (missing `react` / `next` / icon types). - **Behavioral smoke test** of the compiled pure logic: - `paymentRail` appears in the quote body with the enum value, and changing the selection changes it (`SEPA_INSTANT` → `SEPA`) - key **omitted entirely** (not null/undefined) when no rail is selected, when the destination is crypto, and when the destination is internal - across every rail of every currency, no non-enum-looking value is ever emitted - "Funds out via" follows the selection, falls back to the default, and renders display names - all 23 `PaymentRail` members are covered by the display map, and every rail value in `currencies.ts` is a valid enum member - **Spec claims re-verified** against `openapi/components/schemas/quotes/AccountDestination.yaml`, `common/PaymentRail.yaml`, and the `*AccountInfo` / `*ExternalAccountCreateInfo` split. There is no test suite in `grid-visualizer` (no `test` script, no test files), so no tests were added or updated. Not verified: actual rendering, dropdown interaction, and that `CodePanel`'s `stepsKey` remount behaves as intended in the browser (`destRail` was added to both the memo deps and the key, so stale code should be impossible, but this is untested at runtime). ## Files changed - `src/data/currencies.ts` — enum rename + `railDisplayName()` - `src/hooks/useFlowBuilder.ts` — `destRail` state/action/setter - `src/lib/code-generator.ts` — `destRail` param, `paymentRail` emission, display names in the JIT note - `src/lib/flow-path.ts` — `destRail` param, "Funds out via" uses it, display names - `src/app/page.tsx` — wires `destRail` to the Destination card and both panels - `src/components/CodePanel/CodePanel.tsx` — `destRail` prop, memo deps, `stepsKey` - `src/components/FlowPanel/FlowPanel.tsx` — `destRail` prop, memo deps - `src/components/InputCard/InputCard.tsx` — display names - `src/components/CurrencyPicker/CurrencyPicker.tsx` — display names --- _Generated by [Claude Code](https://claude.ai/code/session_01MMnjJ8yWJsui7jLqqrDrL4)_ Co-authored-by: Claude <noreply@anthropic.com>
Rebased onto main. INR_ACCOUNT still only exposed vpa in the visualizer and UPI in the docs, while InrAccountInfoBase documents NEFT and RTGS alongside it, with accountNumber, ifsc, rail and bankName. - account-types.ts: adds the four NEFT/RTGS fields and marks which rail each belongs to - currencies.ts: allRails gains NEFT and RTGS, both PaymentRail members - country-support.mdx: India lists all three rails - external-accounts.mdx: splits the India tab into UPI and NEFT/RTGS examples - Kotlin sample: vpa was required, so a NEFT payload could not be built. All five fields are now optional, matching the pattern already used for GBP and SGD in the same file. The GTQ and JMD changes from the original revision are dropped: both landed on main through later syncs, and account-types.ts already carries them. Also dropped "paymentRails" from the two request examples. That field is response-only - InrExternalAccountCreateInfo composes InrAccountInfoBase, which does not define it, while InrAccountInfo does. Sending it is the same mistake #351 made. Note this is distinct from "rail", which is a genuine request field on the base schema. The Note now says so explicitly, since having both names in one payload invites exactly this confusion. New curl blocks use -u rather than -H 'Authorization: Basic ...', which does not survive copy-paste. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MMnjJ8yWJsui7jLqqrDrL4
## Summary `InrAccountInfoBase` documents three rails for India — UPI, NEFT and RTGS — but the visualizer exposed only `vpa` and the docs only UPI. This syncs both, plus the Kotlin sample. Rebased onto current `main` (`a1cd310`); the conflict is resolved and the branch is a single commit. | File | Change | |---|---| | `account-types.ts` | `INR_ACCOUNT` gains `accountNumber`, `ifsc`, `rail`, `bankName`, each marked with the rail it belongs to | | `currencies.ts` | `allRails` gains `NEFT` and `RTGS`; label becomes `UPI / Bank Account` | | `country-support.mdx` | India row lists all three rails | | `external-accounts.mdx` | India tab split into UPI and NEFT/RTGS examples | | `samples/kotlin/.../ExternalAccounts.kt` | all five fields optional, so a NEFT payload can be built | ## What changed in the rebase **GTQ and JMD are dropped.** The original revision fixed `GTQ_ACCOUNT` fields and added `bankName` to `JMD_ACCOUNT`. Both landed on `main` through later syncs — `account-types.ts` already carries them — so those hunks are gone and this is INR-only. The title has been narrowed to match. **`paymentRails` removed from both request examples.** The original added `"paymentRails": ["UPI"]` and `["NEFT"]` to the create bodies. That field is **response-only**: `InrExternalAccountCreateInfo` composes `BaseExternalAccountInfo` + `InrAccountInfoBase` + `beneficiary`, and none of those define it, while `InrAccountInfo` (the response wrapper) does. Sending it is the same mistake #351 made. This is worth care because **`rail` and `paymentRails` are different things** and both are in play here. `rail` is a genuine request field on `InrAccountInfoBase` — singular, the rail you want to route over. `paymentRails` is the plural array Grid returns. Having both names in one payload is exactly how the earlier confusion happened, so the `<Note>` now states it outright. **New curl blocks use `-u`.** The original used `-H 'Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET'`, which fails on copy-paste twice over — single quotes block variable expansion, and Basic auth needs `base64(user:pass)` rather than the raw pair. #793 is fixing the other 85 instances of this repo-wide. ## Verification - Both India JSON payloads parse - MDX component tags and code fences balance - `UPI`, `NEFT`, `RTGS` all confirmed as `PaymentRail` enum members - `account-types.ts` and `currencies.ts` typecheck clean under `--strict` - No `paymentRails` remains anywhere in `external-accounts.mdx` - GTQ and JMD entries verified byte-unchanged from `main` **Not verified — needs a reviewer who can build:** - **The Kotlin sample does not compile here.** `.accountNumber()`, `.ifsc()`, `.rail()` and `.bankName()` need to exist on `InrExternalAccountCreateInfo.Builder` in the pinned Grid SDK version. The `optText(...)?.let { }` pattern itself matches what the same file already does for GBP and SGD, and `optText` is imported, but whether the SDK exposes those four setters is unconfirmed. **If the SDK predates the INR schema change, this hunk will not build** — worth checking before merge. - No visual render check. `npm ci` fails in this environment (`@central-icons-react` needs `CENTRAL_LICENSE_KEY`), and `make lint` is broken on `main` regardless (`npx spectral lint` resolves to a stub `spectral@0.0.0`). The Mintlify and Vercel previews are the real checks. ## Possible conflict #793 rewrites 26 auth lines in `external-accounts.mdx`. Whichever of these merges second may need a trivial rebase; the overlap is auth lines only, not the India tab. Co-authored-by: Claude <noreply@anthropic.com>
## Summary `external-accounts.mdx` documented **21 of the 45** account types in `ExternalAccountType`. Because the page reads as an enumeration — a tab per country or rail — a developer scanning it would reasonably conclude the other 24 aren't supported. This documents all of them. Docs-only, one file, +927 lines. Generated bundles untouched. **Coverage is now 45/45**, verified by diffing the `accountType` values in the page against `account-types.ts`. | Added | Types | |---|---| | 18 fiat tabs | `AED` `BDT` `BWP` `CNY` `DKK` `EGP` `GHS` `GTQ` `HKD` `HTG` `IDR` `JMD` `MYR` `PKR` `SGD` `THB` `VND` `XAF` | | Cryptocurrency tab | Ethereum L1, Base, Polygon, Solana, Tron, Plasma, Lightning — it previously showed Spark alone | ## Scope grew during the work — worth knowing I started from a list of 17 missing types. A mechanical diff against `account-types.ts` found **24**: `DKK`, `HKD`, `IDR`, `MYR`, `SGD`, `THB`, `VND` and `LIGHTNING` weren't on my list. Stopping at 17 would have reproduced the same partial-coverage problem in a PR whose entire purpose is fixing it, so all 24 are here. ## Where the content comes from Nothing is inferred from existing examples — each type was read from its schema: - **Fields and required/optional split** — `<Ccy>AccountInfoBase.yaml` - **Beneficiary shape** — `<Ccy>Beneficiary.yaml`, which is where the real variation lives. Most need only `fullName`, but **AED** and **JMD** also require an `address`, **GTQ** requires `countryOfResidence` and `phoneNumber`, and **JMD** requires `phoneNumber`. Those are easy to miss and produce confusing validation failures. - **Per-chain asset support** — each `Payment<Chain>WalletInfo.yaml`. Ethereum carries `USDC` and `USDT`; Base and Polygon are USDC-only. Stated per chain rather than assumed uniform. - **Dual-rail currencies** (BDT, CNY, EGP, GHS, PKR) get separate bank-transfer and mobile-money examples, following the existing Colombia and El Salvador tabs. **No example sends `paymentRails`.** It's response-only, and three separate PRs (#351, #661, and the original #359 lineage) got that wrong. The single occurrence of it in this file remains where it belongs — the `GET` **response** example. Example people match the entries added to `currencies.ts` in #791, so the docs and the visualizer describe the same fictional customers. ## Verification - **All 54 curl payloads in the file parse as JSON** — not just the new ones - **Every `accountType` used is a valid `ExternalAccountType` member** - **Coverage diff is empty**: no type in `account-types.ts` is undocumented - MDX component tags and code fences balance - All new curl examples use `-u`, consistent with #793 - `openapi.yaml` and `mintlify/openapi.yaml` byte-identical to `main` **Not verified:** no visual render. This is 927 lines of new tabs, so the **Mintlify preview is the meaningful review** — worth checking that the tab strip doesn't overflow badly now that it holds 32 tabs. `make lint` was not run; it fails on `main` regardless (`npx spectral lint` resolves to a stub `spectral@0.0.0`). ## One thing this surfaces `SWIFT_ACCOUNT` is documented here but **absent from `account-types.ts`**, so the visualizer still can't produce it. That's the known gap from closed #775 — the entry was correct but unreachable without widening `FiatCurrency` past a single `accountType`. Unchanged by this PR, but the asymmetry is now visible: the docs describe a type the visualizer can't build. ## Left out deliberately I had also listed adding SWIFT to `account-model.mdx`. **That item doesn't hold up.** My earlier check used the wrong path — the file is at `platform-overview/core-concepts/account-model.mdx`, not `snippets/`. Looking at the real file, it's an explicitly illustrative page showing 8 representative types, not an enumeration. Singling out SWIFT there would recreate the curated-list problem rather than fix one. Left alone. --- _Generated by [Claude Code](https://claude.ai/code/session_01MMnjJ8yWJsui7jLqqrDrL4)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary
Syncs the Grid Visualizer with the new PaymentRail enum added in #347:
FEDNOWinstead ofFedNow,FASTER_PAYMENTSinstead ofFaster Payments,SEPA_INSTANTinstead ofSEPA Instant,BANK_TRANSFERinstead ofBank Transfer,MOBILE_MONEYinstead ofMobile Money)paymentRailsarray to generated external account creation requests, matching the documented workflow examples in.claude/skills/grid-api/references/workflows.mdTrigger
OpenAPI schema changes in commit 4d89702:
openapi/components/schemas/common/PaymentRail.yaml(new enum)openapi/components/schemas/exchange_rates/ExchangeRate.yaml(addeddestinationPaymentRail)openapi/components/schemas/quotes/AccountDestination.yaml(added optionalpaymentRail)Test plan
paymentRailsin request body🤖 Generated with Claude Code