Skip to content

fix(samples/frontend): floor default quote amount to corridor minimum#605

Merged
pengying merged 1 commit into
mainfrom
06-18-fix_samples_frontend_floor_default_quote_amount_to_corridor_minimum
Jun 26, 2026
Merged

fix(samples/frontend): floor default quote amount to corridor minimum#605
pengying merged 1 commit into
mainfrom
06-18-fix_samples_frontend_floor_default_quote_amount_to_corridor_minimum

Conversation

@pengying

Copy link
Copy Markdown
Contributor

Corridor minimums vary widely (e.g. USD->EUR ~$23, USD->BRL ~$12, USD->MXN
~$1), so a fixed default still failed with AMOUNT_OUT_OF_RANGE on higher-min
corridors. The quote step now looks up the corridor's minSendingAmount via
the exchange-rates endpoint and floors the default amount to it (+5% buffer
for FX drift). maxSendingAmount is intentionally not used as it is unreliable
for some corridors in this environment.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

@vercel

vercel Bot commented Jun 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
grid-flow-builder Ignored Ignored Preview Jun 26, 2026 12:27am
grid-wallet-demo Ignored Ignored Preview Jun 26, 2026 12:27am

Request Review

@greptile-apps

greptile-apps Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes AMOUNT_OUT_OF_RANGE errors in the sample frontend's quote step by fetching the corridor's minSendingAmount via the exchange-rates API before building the request body, then flooring the default amount to that minimum plus a 5% FX-drift buffer.

  • A new useEffect fires on sourceCurrency/destCurrency change, calls /api/exchange-rates with a probe amount, and stores the max minSendingAmount across all returned exchange-rate records.
  • The body-building useEffect now takes minSendingAmount as a dependency and raises lockedCurrencyAmount to Math.max(defaultAmount, Math.ceil(minSendingAmount * 1.05)) when the corridor minimum exceeds the fixed default.
  • Cancellation via a cancelled flag is handled correctly for in-flight fetches on rapid corridor switches.

Confidence Score: 5/5

Safe to merge — the change is confined to the sample frontend's quote step and only affects how the default body amount is pre-populated; users can still edit the value manually before submitting.

The new exchange-rates prefetch is well-scoped: cancellation is handled correctly, the two-effect sequencing is idiomatic React, and Math.max over corridor minimums is the safe choice. The silent-failure path was already flagged in the previous review thread and is a known trade-off in this demo context. No data is persisted or mutated by this component.

No files require special attention beyond what was already discussed in the earlier review thread about the catch handler.

Important Files Changed

Filename Overview
samples/frontend/src/steps/CreateQuote.tsx Adds a preflight exchange-rates fetch to discover the corridor's minSendingAmount and floors the default quote amount to it (+ 5% buffer). Logic is correct for the happy path; the previously-flagged silent-failure case (catch resets to null, body falls back to un-floored default) remains unaddressed in this revision.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant U as User
    participant C as CreateQuote
    participant ER as /api/exchange-rates
    participant Q as /api/quotes

    U->>C: Change sourceCurrency / destCurrency (or mount)
    C->>C: setMinSendingAmount(null)
    C->>C: "body useEffect → lockedCurrencyAmount = defaultAmount (un-floored)"
    C->>ER: "GET /api/exchange-rates?sourceCurrency=...&destinationCurrency=...&sendingAmount=probe"
    alt Success
        ER-->>C: "{ data: [{ minSendingAmount }] }"
        C->>C: setMinSendingAmount(max of all mins)
        C->>C: "body useEffect → lockedCurrencyAmount = max(defaultAmount, ceil(min * 1.05))"
    else Failure (network / API error)
        ER-->>C: error
        C->>C: catch → setMinSendingAmount(null)
        C->>C: "body useEffect → lockedCurrencyAmount = defaultAmount (still un-floored)"
    end
    U->>C: Click Create Quote
    C->>Q: "POST /api/quotes { lockedCurrencyAmount, ... }"
    Q-->>C: Quote response
    C->>U: Display result
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant U as User
    participant C as CreateQuote
    participant ER as /api/exchange-rates
    participant Q as /api/quotes

    U->>C: Change sourceCurrency / destCurrency (or mount)
    C->>C: setMinSendingAmount(null)
    C->>C: "body useEffect → lockedCurrencyAmount = defaultAmount (un-floored)"
    C->>ER: "GET /api/exchange-rates?sourceCurrency=...&destinationCurrency=...&sendingAmount=probe"
    alt Success
        ER-->>C: "{ data: [{ minSendingAmount }] }"
        C->>C: setMinSendingAmount(max of all mins)
        C->>C: "body useEffect → lockedCurrencyAmount = max(defaultAmount, ceil(min * 1.05))"
    else Failure (network / API error)
        ER-->>C: error
        C->>C: catch → setMinSendingAmount(null)
        C->>C: "body useEffect → lockedCurrencyAmount = defaultAmount (still un-floored)"
    end
    U->>C: Click Create Quote
    C->>Q: "POST /api/quotes { lockedCurrencyAmount, ... }"
    Q-->>C: Quote response
    C->>U: Display result
Loading

Reviews (2): Last reviewed commit: "fix(samples/frontend): floor default quo..." | Re-trigger Greptile

const mins = (res.data ?? []).map((r) => r.minSendingAmount ?? 0)
setMinSendingAmount(mins.length ? Math.max(...mins) : null)
})
.catch(() => { if (!cancelled) setMinSendingAmount(null) })

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.

P2 Silent min-fetch failure leaves body at the un-floored default

When the exchange-rates request fails (transient network error, API error, non-ok response), the .catch() handler silently resets minSendingAmount to null. The body useEffect then fires with flooredToMin = 0, so lockedCurrencyAmount falls back to defaultAmount — potentially below the corridor minimum. There is no in-UI indication of this, so a developer would only discover the fallback by seeing the AMOUNT_OUT_OF_RANGE error after submitting the quote. Surfacing the error (e.g. via setError) or at least displaying a warning in the form header would make the failure visible before submission.

Prompt To Fix With AI
This is a comment left during a code review.
Path: samples/frontend/src/steps/CreateQuote.tsx
Line: 53

Comment:
**Silent min-fetch failure leaves body at the un-floored default**

When the exchange-rates request fails (transient network error, API error, non-`ok` response), the `.catch()` handler silently resets `minSendingAmount` to `null`. The body `useEffect` then fires with `flooredToMin = 0`, so `lockedCurrencyAmount` falls back to `defaultAmount` — potentially below the corridor minimum. There is no in-UI indication of this, so a developer would only discover the fallback by seeing the `AMOUNT_OUT_OF_RANGE` error after submitting the quote. Surfacing the error (e.g. via `setError`) or at least displaying a warning in the form header would make the failure visible before submission.

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

shreyav
shreyav previously approved these changes Jun 26, 2026

pengying commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Merge activity

  • Jun 26, 12:16 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 26, 12:28 AM UTC: Graphite rebased this pull request as part of a merge.
  • Jun 26, 12:28 AM UTC: @pengying merged this pull request with Graphite.

@pengying pengying changed the base branch from 06-18-fix_samples_frontend_scale_default_quote_amount_by_source_currency_decimals to graphite-base/605 June 26, 2026 00:25
@pengying pengying changed the base branch from graphite-base/605 to main June 26, 2026 00:26
@pengying pengying dismissed shreyav’s stale review June 26, 2026 00:26

The base branch was changed.

Corridor minimums vary widely (e.g. USD->EUR ~$23, USD->BRL ~$12, USD->MXN
~$1), so a fixed default still failed with AMOUNT_OUT_OF_RANGE on higher-min
corridors. The quote step now looks up the corridor's minSendingAmount via
the exchange-rates endpoint and floors the default amount to it (+5% buffer
for FX drift). maxSendingAmount is intentionally not used as it is unreliable
for some corridors in this environment.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@pengying pengying force-pushed the 06-18-fix_samples_frontend_floor_default_quote_amount_to_corridor_minimum branch from cd77ced to 8ec790d Compare June 26, 2026 00:27

@restamp-bot restamp-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

8ec790d is a pure rebase onto c310a47. Approving based on @shreyav's previous approval of cd77ced.

@pengying pengying merged commit da959ea into main Jun 26, 2026
9 checks passed
@pengying pengying deleted the 06-18-fix_samples_frontend_floor_default_quote_amount_to_corridor_minimum branch June 26, 2026 00:28
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.

2 participants