Skip to content

fix: updating samples and components for schema updates#241

Open
pengying wants to merge 2 commits intomainfrom
03-02-fix_updating_samples_and_components_for_schema_updates
Open

fix: updating samples and components for schema updates#241
pengying wants to merge 2 commits intomainfrom
03-02-fix_updating_samples_and_components_for_schema_updates

Conversation

@pengying
Copy link
Contributor

@pengying pengying commented Mar 3, 2026

Updating the kotlin sample and grid visualizer component for the latest api changes

Copy link
Contributor Author

pengying commented Mar 3, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@pengying pengying marked this pull request as ready for review March 3, 2026 04:39
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 3, 2026

Greptile Summary

This PR updates the Kotlin sample app and Grid Visualizer component to align with the latest API schema changes: account type renames (e.g. US_ACCOUNTUSD_ACCOUNT, IBANEUR_ACCOUNT), the beneficiary moving inside accountInfo, paymentRails becoming an explicit field, and purposeOfPayment being added to quotes. The frontend samples, TypeScript data files, and Kotlin route handlers are all updated together.

Key changes:

  • Account type renames across account-types.ts, currencies.ts, CreateExternalAccount.tsx, and the Kotlin routes — old generic keys replaced with currency-prefixed names.
  • paymentRails added as a first-class field in AccountTypeSpec and propagated into the code generator and API request bodies.
  • ExternalAccounts.kt refactored from a single UsAccountInfo-only builder to a dispatcher (buildAccountInfo) with typed per-currency beneficiary builders.
  • Webhook signature verification added via WebhookUtils.verifyWebhookSignature, though the result is currently not enforced (see inline comment).
  • SDK bumped from 0.5.0 to 0.9.0 and credentials renamed from GRID_API_TOKEN_ID/GRID_API_CLIENT_SECRET to GRID_CLIENT_ID/GRID_CLIENT_SECRET.

Confidence Score: 3/5

  • Safe to merge with caveats — two logic bugs in the Kotlin sample should be addressed before this is used as a reference implementation.
  • The TypeScript/frontend changes are clean and correct. The Kotlin sample has two notable issues: (1) webhook signature verification is implemented but the result is never checked, so all webhooks are accepted regardless of validity; (2) buildAccountInfo() only handles 5 of the ~20 account types now advertised in account-types.ts, causing unhandled exceptions for all others. Since this is a sample app these won't break production, but they undermine the correctness of the reference implementation.
  • samples/kotlin/src/main/kotlin/com/grid/sample/routes/Webhooks.kt and samples/kotlin/src/main/kotlin/com/grid/sample/routes/ExternalAccounts.kt need attention.

Important Files Changed

Filename Overview
components/grid-visualizer/src/data/account-types.ts Renames account type keys (US_ACCOUNT→USD_ACCOUNT, IBAN→EUR_ACCOUNT, PIX→BRL_ACCOUNT, etc.), adds optional paymentRails field to AccountTypeSpec, adds many new account types, and removes the generic fallback spread; changes look correct and consistent with schema updates.
components/grid-visualizer/src/data/currencies.ts Updates accountType references to match renamed enum values and normalises payment rail strings to uppercase enum style (e.g. FEDNOW, SEPA_INSTANT, FASTER_PAYMENTS); adds DKK, RWF, TZS, ZMW, ZAR currencies and removes several unsupported ones.
samples/kotlin/src/main/kotlin/com/grid/sample/routes/Webhooks.kt Adds WebhookUtils.verifyWebhookSignature call, but the isValid result is only logged and never used to reject invalid requests — webhooks are processed unconditionally regardless of signature validity, which is a security logic bug.
samples/kotlin/src/main/kotlin/com/grid/sample/routes/ExternalAccounts.kt Major refactor to typed per-currency account builders with paymentRails support, but buildAccountInfo() only handles 5 of the ~20 account types now defined in account-types.ts; the else branch throws an uncaught exception for all new types.
samples/kotlin/src/main/kotlin/com/grid/sample/routes/Quotes.kt Adds purposeOfPayment support and updates QuoteSourceOneOf to QuoteCreateParams.Source with updated factory method names; clean migration to new SDK types.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[POST /api/customers/:id/external-accounts] --> B{accountType?}
    B -- missing --> C[400 Bad Request]
    B -- present --> D{buildAccountInfo switch}
    D -- USD_ACCOUNT --> E[UsdExternalAccountInfo + UsdBeneficiary]
    D -- INR_ACCOUNT --> F[InrExternalAccountInfo + InrBeneficiary]
    D -- BRL_ACCOUNT --> G[BrlExternalAccountInfo + BrlBeneficiary]
    D -- MXN_ACCOUNT --> H[MxnExternalAccountInfo + MxnBeneficiary]
    D -- GBP_ACCOUNT --> I[GbpExternalAccountInfo + GbpBeneficiary]
    D -- EUR/DKK/NGN/SGD/etc --> J[⚠️ IllegalArgumentException → 500]
    E & F & G & H & I --> K[ExternalAccountCreate.builder]
    K --> L[client.customers.externalAccounts.create]
    L --> M[201 Created]

    N[POST /api/webhooks] --> O[ensurePublicKey]
    O --> P[verifyWebhookSignature]
    P --> Q[Log result only ⚠️ not enforced]
    Q --> R[webhooks.unwrap — always runs]
    R --> S[WebhookStream.addEvent]
Loading

Last reviewed commit: b267999

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

15 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 27 to +33
Log.webhook(rawBody)

try {
ensurePublicKey()
val signature = call.request.header("X-Grid-Signature") ?: ""
val isValid = WebhookUtils.verifyWebhookSignature(rawBody, signature)
Log.webhookSignatureResult(isValid)
Copy link
Contributor

Choose a reason for hiding this comment

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

Webhook signature result is ignored

isValid is logged but never acted upon — the webhook is parsed and processed even when signature verification fails. This defeats the purpose of the verification entirely. An invalid signature should reject the request immediately.

Suggested change
Log.webhook(rawBody)
try {
ensurePublicKey()
val signature = call.request.header("X-Grid-Signature") ?: ""
val isValid = WebhookUtils.verifyWebhookSignature(rawBody, signature)
Log.webhookSignatureResult(isValid)
ensurePublicKey()
val signature = call.request.header("X-Grid-Signature") ?: ""
val isValid = WebhookUtils.verifyWebhookSignature(rawBody, signature)
Log.webhookSignatureResult(isValid)
if (!isValid) {
call.respondText("""{"error": "Invalid webhook signature"}""", ContentType.Application.Json, HttpStatusCode.Unauthorized)
return@post
}
val event = GridClientBuilder.client.webhooks().unwrap(rawBody)
val eventJson = JsonUtils.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(event)
Prompt To Fix With AI
This is a comment left during a code review.
Path: samples/kotlin/src/main/kotlin/com/grid/sample/routes/Webhooks.kt
Line: 27-33

Comment:
**Webhook signature result is ignored**

`isValid` is logged but never acted upon — the webhook is parsed and processed even when signature verification fails. This defeats the purpose of the verification entirely. An invalid signature should reject the request immediately.

```suggestion
                ensurePublicKey()
                val signature = call.request.header("X-Grid-Signature") ?: ""
                val isValid = WebhookUtils.verifyWebhookSignature(rawBody, signature)
                Log.webhookSignatureResult(isValid)
                if (!isValid) {
                    call.respondText("""{"error": "Invalid webhook signature"}""", ContentType.Application.Json, HttpStatusCode.Unauthorized)
                    return@post
                }

                val event = GridClientBuilder.client.webhooks().unwrap(rawBody)
                val eventJson = JsonUtils.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(event)
```

How can I resolve this? If you propose a fix, please make it concise.

@@ -110,5 +78,190 @@ fun Route.externalAccountRoutes() {
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Many new account types unhandled — will throw unhandled exception

buildAccountInfo() only handles USD_ACCOUNT, INR_ACCOUNT, BRL_ACCOUNT, MXN_ACCOUNT, and GBP_ACCOUNT. The account types added in this PR (EUR_ACCOUNT, DKK_ACCOUNT, NGN_ACCOUNT, CAD_ACCOUNT, PHP_ACCOUNT, SGD_ACCOUNT, HKD_ACCOUNT, IDR_ACCOUNT, KES_ACCOUNT, MYR_ACCOUNT, RWF_ACCOUNT, THB_ACCOUNT, TZS_ACCOUNT, VND_ACCOUNT, ZAR_ACCOUNT, ZMW_ACCOUNT) all fall through to the else -> throw IllegalArgumentException(...) branch. This will surface as a 500 error to callers instead of a meaningful 400. Even as a sample app, the new account types listed in account-types.ts should either have corresponding builders here or the else branch should return a proper HTTP 400 response before the exception propagates.

Prompt To Fix With AI
This is a comment left during a code review.
Path: samples/kotlin/src/main/kotlin/com/grid/sample/routes/ExternalAccounts.kt
Line: 78

Comment:
**Many new account types unhandled — will throw unhandled exception**

`buildAccountInfo()` only handles `USD_ACCOUNT`, `INR_ACCOUNT`, `BRL_ACCOUNT`, `MXN_ACCOUNT`, and `GBP_ACCOUNT`. The account types added in this PR (`EUR_ACCOUNT`, `DKK_ACCOUNT`, `NGN_ACCOUNT`, `CAD_ACCOUNT`, `PHP_ACCOUNT`, `SGD_ACCOUNT`, `HKD_ACCOUNT`, `IDR_ACCOUNT`, `KES_ACCOUNT`, `MYR_ACCOUNT`, `RWF_ACCOUNT`, `THB_ACCOUNT`, `TZS_ACCOUNT`, `VND_ACCOUNT`, `ZAR_ACCOUNT`, `ZMW_ACCOUNT`) all fall through to the `else -> throw IllegalArgumentException(...)` branch. This will surface as a 500 error to callers instead of a meaningful 400. Even as a sample app, the new account types listed in `account-types.ts` should either have corresponding builders here or the `else` branch should return a proper HTTP 400 response before the exception propagates.

How can I resolve this? If you propose a fix, please make it concise.

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