Conversation
🦋 Changeset detectedLatest commit: 7b8decb The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughAdds Mantéca fiat on‑ramp: new add‑funds routes and thin route exports; multiple UI screens/components (KYC, Onboard, Ramp, Status, AddFiatButton, MantecaDisclaimer); persona Mantéca KYC flow; server ramp/KYC helpers; currency utilities; onboarding orchestrator; Spanish translations and minor UI tweaks. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant UI as AddFunds UI
participant KYC as KYC Component
participant Persona as Persona Client
participant Server as Server API
participant Onboard as Onboard Component
participant Ramp as Ramp Component
participant Status as Status Component
User->>UI: select fiat deposit (currency)
UI->>KYC: navigate /add-funds/kyc?currency=...
User->>KYC: initiate verification
KYC->>Persona: startMantecaKYC()
Persona-->>KYC: MantecaKYCResult {status}
alt status == "complete"
KYC->>Server: startRampOnboarding({provider:"manteca"})
KYC->>Server: getKYCStatus("manteca") → countryCode
KYC->>Server: getRampProviders(countryCode)
alt provider.status == "ACTIVE"
KYC->>Ramp: navigate /add-funds/ramp?currency=...
Ramp->>Server: getRampQuote(...)
Ramp->>User: show deposit details
else provider.status == "ONBOARDING"
KYC->>Onboard: navigate /add-funds/onboard?currency=...
else
KYC->>Status: navigate /add-funds/status?status=error
end
else status == "cancel" or "error"
KYC->>Status: navigate /add-funds/status?status=error
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @franm91, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a significant new feature: the Manteca fiat on-ramp. It provides a comprehensive flow for users to add funds by converting fiat currencies into on-chain USDC. The changes encompass new UI screens for onboarding, KYC verification, status tracking, and the ramp details, along with the necessary backend integrations to support these operations. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new fiat on-ramp feature using 'Manteca' as a provider. This includes new screens for onboarding, KYC, and displaying ramp details, along with the necessary components, assets, and API utility functions. The changes are well-structured, but there are a few areas that could be improved for clarity, maintainability, and robustness. Specifically, the Persona KYC initiation logic is duplicated, some useQuery data flow is indirect, and depositInfo extraction could be cleaner.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #704 +/- ##
==========================================
- Coverage 68.21% 67.68% -0.53%
==========================================
Files 206 206
Lines 6827 7056 +229
Branches 2139 2217 +78
==========================================
+ Hits 4657 4776 +119
- Misses 1988 2093 +105
- Partials 182 187 +5
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 20
🤖 Fix all issues with AI agents
In `@src/components/add-funds/AddFiatButton.tsx`:
- Around line 10-13: The AddFiatButtonProperties type declares currency as a
plain string which weakens type safety against currencyMap keys; import the
Currency type from ../../utils/currencies and change the property signature in
AddFiatButtonProperties from currency: string to currency: Currency so the
component's currency prop is strongly typed to the known currency keys (update
any usages of AddFiatButtonProperties/AddFiatButton to satisfy the new type if
necessary).
In `@src/components/add-funds/AddFunds.tsx`:
- Line 113: In AddFunds.tsx replace the hardcoded gap={16} on the YStack with
the appropriate design token (e.g., the app's spacing token such as
spacing.medium or $4) used across the codebase; update the YStack prop to use
that token (and import the token if needed) so styling relies on predefined
design tokens rather than a raw number, then run the linter/formatter to ensure
the prop type matches the token format.
- Around line 107-111: In the AddFunds component JSX where the fiat options are
rendered (the block using countryCode and isPending to decide between the
Skeleton and options), change the condition from countryCode && isPending to
show the skeleton when either the providers are loading or the country code is
not yet available (e.g., use isPending || !countryCode or !countryCode ||
isPending) so the loading skeleton is displayed while countryCode is being
fetched as well as while providers are loading.
In `@src/components/add-funds/Kyc.tsx`:
- Around line 99-101: The FaceId SVG is receiving string percentages for
dimensions which don't work in React Native SVG; update the FaceId usage in
Kyc.tsx (the View + FaceId block) to pass numeric width/height props (e.g.,
width={200} height={200} or width={iconSize} height={iconSize}) or remove those
props and control sizing via the parent View/style (flex or explicit numeric
size computed with Dimensions) so the FaceId component gets numeric literals
rather than "100%".
- Around line 79-80: The two JSX View elements are using hardcoded gap={20};
replace those with the project design token for that spacing (e.g.,
gap={tokens.spacing.md} or gap={tokens.space[20]}) by importing the
tokens/spacing object from your design tokens module and using the appropriate
token value (ensure the token name matches the project's token API and types),
updating both occurrences of gap={20} on the View components.
- Around line 54-66: The code assumes providers.providers.manteca exists and
reads its status directly; add a defensive null/undefined check for
providers.providers.manteca (after the queryClient.fetchQuery/getRampProviders
call) before accessing manteca.status and set newStatus to a safe fallback
(e.g., "error" or "UNAVAILABLE") when manteca is missing, then call
router.replace accordingly (ensure logic around newStatus, router.replace, and
the existing branches for "ACTIVE"/"ONBOARDING" handle the fallback case).
In `@src/components/add-funds/Onboard.tsx`:
- Around line 26-96: The Onboard component contains routing, mutations and
server-state logic (useMutation with mutationFn, getKYCStatus handling,
completeOnboarding, queryClient calls, router.push/replace) and must be
refactored into a smart screen in src/app/**; extract all side-effect logic
(handleOnboarding mutation, completeOnboarding function,
queryClient.fetch/invalidate, getKYCStatus, startRampOnboarding, router
navigation and error handling) into a container/screen component and convert
this file into a pure presentational component that accepts props like currency,
validCurrency, CurrencyImage, isPending, onContinue (callback) and onNavigate
(or expose status callbacks). Keep only UI rendering and call props.onContinue
from handleContinue; remove any direct use of router, queryClient, useMutation,
and reportError from this component. Ensure function names referenced (Onboard,
completeOnboarding, handleOnboarding, handleContinue) are implemented/used in
the new smart screen and the UI component only receives data and callbacks via
props.
- Around line 34-57: The inline multi-line mutationFn passed to useMutation
(alias handleOnboarding) contains complex logic (calls to getKYCStatus,
router.push/replace and completeOnboarding) and should be extracted into a named
async function (e.g., async function performRampOnboarding(currency) { ... })
declared outside the inline prop so the handler is stable and testable; replace
mutationFn: async () => { ... } with mutationFn: performRampOnboarding (or () =>
performRampOnboarding(currency)) and move the existing logic (including the
APIError catch, kycCode calculation, router.push/replace and completeOnboarding
calls) into that function. Do the same refactor for the other multi-line
callbacks noted (the handler around completeOnboarding / status flow referenced
later) so they become named functions instead of inline multi-line arrow
functions.
- Around line 1-24: The React default import is only used for the React.FC type
in the currencyImages declaration; change the import to a type-only import and
update the type usage to use a type import (e.g., import type { FC } from
"react") and then type currencyImages as Record<string, FC<{ height: string;
width: string }>> so the runtime bundle does not include React unnecessarily;
update the top import line accordingly and remove the unused default React
import.
- Around line 100-123: Replace hardcoded numeric spacing and longhand padding
with Tamagui design tokens and shorthand props: change gap={20} and gap={10} to
token-based values (e.g. gap="$s6" or "$s2" as appropriate) on the View and
inner row, replace padding="$s4" longhand on YStack with the shorthand p="$s4",
and prefer shorthands like px, py, m, mt, etc., on components such as View,
ScrollView, YStack, Pressable and the container wrapping CurrencyImage; keep
existing behavior for router.back()/router.replace() and retain the
ArrowLeft/Pressable structure while only updating spacing props to use the
tokens from tamagui.config.ts.
- Around line 30-72: Move the top-level countryCode read into the
completeOnboarding function to avoid pinning an empty-string cache key; remove
the module-scope const countryCode and instead call
queryClient.getQueryData<string>(["user","country"]) (or similar) inside
completeOnboarding before you call queryClient.fetchQuery({ queryKey:
["ramp","providers", countryCode], ... }) so the providers query is only keyed
with the actual country value (and not a default ""), and apply the same change
to the analogous code in Kyc.tsx.
In `@src/components/add-funds/Ramp.tsx`:
- Around line 181-183: The X icon inside Button.Icon is missing an explicit size
prop and should match the other icons in this component for visual consistency;
update the X component in the Button.Icon block (the X element) to include the
same size prop used by the other icons in this file (e.g., size=16 or the
project's standard icon size) so all icons in the Ramp/Add-funds component
render at the same dimensions.
- Around line 90-91: Replace hardcoded numeric gaps in the Ramp component's JSX
(the View elements using gap={20}) with the app's design tokens: locate the View
elements in Ramp.tsx (props gap={20}) and change them to use the shared spacing
token (e.g., spacing.X or tokens.space.xxx — whatever the project's spacing
token export is) so all gap props reference the token constant; update both
occurrences mentioned and any other hardcoded gap values in this file to use the
same token import.
- Around line 107-109: The Info Pressable in Ramp.tsx is missing an onPress
handler, so either remove the Pressable or add an onPress that mirrors the
behavior used elsewhere (e.g., the help/article opener in AddFunds.tsx); locate
the Pressable wrapping the Info icon and implement an onPress prop that opens
the appropriate help modal or navigator route (or call the same helper function
used by AddFunds), and keep hitSlop={15} if retaining the button for consistent
touch target.
- Around line 104-106: Replace the hardcoded style props on the Text component
(currently fontSize={15} and fontWeight="bold") with the design-system token
props used elsewhere (e.g., use the Text variant/size prop like subHeadline and
the emphasis prop like emphasized or the component's weight token) so styling
comes from predefined tokens; update the Text invocation in the Ramp component
to remove fontSize/fontWeight and pass the appropriate predefined props
(subHeadline and emphasized) to match the design system.
In `@src/components/add-funds/Status.tsx`:
- Around line 43-45: The SVG components FaceId and Denied are being passed
percentage strings for width/height which SVG in React Native doesn't support;
update the JSX in the View that renders these icons (the conditional using
isOnboarding) to pass numeric width and height values (e.g., width={...}
height={...}) or compute numbers from the container/screen dimensions before
passing them; ensure the values are numeric literals or variables (not strings)
so FaceId and Denied receive valid numeric props.
- Around line 38-40: Replace the hardcoded gap={20} uses in the Status
component's View elements with the appropriate spacing design token from
tamagui.config.ts (e.g., the spacing token equivalent like "$4" or "space-4");
update both the outer View (the fullScreen padded container) and the inner View
(the child with gap) to use that token and, if required by your setup,
import/consume the token or theme so the component uses the predefined spacing
value rather than a raw number.
In `@src/utils/persona.ts`:
- Around line 117-205: startMantecaKYC duplicates large portions of startKYC
(pagehide listener, abort handling, Persona client/inquiry setup); extract
shared behavior into small helpers to remove duplication. Create a helper like
setupPagehideAbort(controller) that installs/removes the pagehide listener and
re-use it in both startMantecaKYC and startKYC; extract a common
attachAbortHandler(controller.signal, onAbort) pattern and a factory that wires
Persona callbacks (for Client and Inquiry) to shared onComplete/onCancel/onError
logic (referencing Client, Inquiry, onAbort, controller.signal,
queryClient.invalidateQueries and reportError) so both functions call the shared
helpers and only implement the KYC-specific return/resolve logic.
In `@src/utils/server.ts`:
- Around line 170-171: The error parsing uses a TypeScript type assertion
((await response.json()) as { code: string }) which bypasses runtime validation;
define a valibot schema (e.g., APIErrorResponse = object({ code: string() }))
and replace the assertions by calling parse(APIErrorResponse, await
response.json()) and destructuring the returned { code } before throwing
APIError; import object, string, and parse from valibot and apply this change
consistently for the locations that construct APIError (the occurrences around
the current response handling code and the other mentioned spots).
- Line 176: Remove the redundant type redeclaration that shadows the imported
RampProvider: delete the line exporting "export type RampProvider = (typeof
RampProvider)[number];" so the imported RampProvider from
`@exactly/server/utils/ramps/shared` is used; if you intended to also re-export a
runtime value, instead export the imported symbol (e.g., export { RampProvider
}) rather than redefining its type.
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/add-funds/AddFunds.tsx (1)
57-58: 🧹 Nitpick | 🔵 TrivialUse design tokens for gap values.
gap={20}should use a design token instead of a hardcoded number.As per coding guidelines: "All styling must use predefined design tokens."
♻️ Suggested fix
- <View gap={20} fullScreen padded> - <YStack gap={20}> + <View gap="$s5" fullScreen padded> + <YStack gap="$s5">
🤖 Fix all issues with AI agents
In `@src/components/add-funds/AddFunds.tsx`:
- Around line 38-46: The current useQuery implementation relies on getKYCStatus
as a side-effect to populate queryClient and then reads back via
queryClient.getQueryData, which is indirect and returns "" on failure (truthy)
so downstream providers query can enable incorrectly; change the query to return
the country code directly (have queryFn call an API that returns country or call
getKYCStatus and return its country value) or use the useQuery `select` option
to extract the country from the getKYCStatus response instead of reading
queryClient; also ensure the queryFn returns undefined (not empty string) when
the country is absent or getKYCStatus throws so the providers query remains
disabled.
In `@src/components/add-funds/Kyc.tsx`:
- Around line 23-71: The Kyc component currently contains routing, mutations and
cache reads (useMutation handling via handleContinue, completeOnboarding,
startMantecaKYC, startRampOnboarding, queryClient and router usage) and must be
converted to a dumb presentational component; extract all side-effect and
stateful logic into a new screen/container (e.g., KycContainer) which owns the
mutation (mutationKey ["kyc","complete","manteca"]), completeOnboarding flow,
queryClient interactions (invalidateQueries/fetchQuery), router.replace calls
and error reporting (reportError), and pass only props into the Kyc UI component
(e.g., isPending, onContinue callback, validCurrency, currency, countryCode) so
src/components/Kyc.tsx becomes purely presentational and receives callbacks/data
via props.
- Around line 30-43: The inline multi-line mutationFn passed to useMutation and
the multi-line Pressable onPress handler should be moved into named function
declarations for stability and readability: extract the async mutation body into
a function like function handleMantecaKyc() that calls startMantecaKYC(), checks
result.status ("cancel" / "error") and calls router.replace or
completeOnboarding() as currently implemented, then pass that function as
mutationFn to useMutation; likewise extract the Pressable handler into a named
function (e.g., function onPressContinue()) and reference it in the Pressable.
Ensure you keep existing symbols (startMantecaKYC, completeOnboarding,
router.replace, mutateAsync/handleContinue) and behavior unchanged while
replacing inline arrow bodies with these function declarations.
In `@src/components/add-funds/Onboard.tsx`:
- Line 24: The currencyImages map currently types SVG components as React.FC<{
height: string; width: string }> and the ARS, BRL, USD components are being
passed string percentages like "100%"; change the prop type to React.FC<{
height: number; width: number }>, update any usages of
currencyImages/ARS/BRL/USD to compute and pass numeric pixel values (e.g.,
containerHeight or parsed values) instead of "100%", and adjust places
referenced around the same usage (lines ~120-121) to pass numbers so the SVG
components receive numeric dimensions.
In `@src/components/add-funds/Ramp.tsx`:
- Line 92: Replace the hardcoded numeric gap value on the JSX View inside the
Ramp component: locate the View element with props flexDirection="row" gap={10}
justifyContent="space-between" alignItems="center" and change gap to use the
design token (for example gap="$s3") so all styling uses predefined design
tokens instead of raw numbers.
In `@src/utils/currencies.ts`:
- Around line 1-12: Replace the manual Currency type and import with valibot's
InferInput: import InferInput from valibot and derive Currency from the already
defined CurrencySchema (e.g., type Currency = InferInput<typeof CurrencySchema>)
instead of using keyof typeof currencyMap; keep currencyMap and CurrencySchema
(picklist) as-is so the schema is the single source of truth and the derived
Currency type stays in sync with CurrencySchema and currencyMap.
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In `@src/components/add-funds/AddFunds.tsx`:
- Around line 93-95: The onPress handler currently calls router.push with a raw
string ("/add-funds/bridge"); replace this with the Expo Router typed route
constant/function (e.g., use the generated Routes enum/const for the add-funds
bridge route) so navigation is type-safe. Update the onPress in AddFunds.tsx to
call router.push with the typed route (reference the existing useRouter()
instance) and add the import for the generated route identifiers (the Routes or
route helper used across the project) so the route is not constructed as a raw
string.
In `@src/components/add-funds/Kyc.tsx`:
- Line 27: The component reads countryCode at render time which can become
stale; move the queryClient.getQueryData<string>(["user","country"]) call into
the completeOnboarding function so the mutation always reads the latest cache
value. Update the code to remove the top-level countryCode constant and instead
call queryClient.getQueryData inside completeOnboarding (referencing the same
query key), then use that local countryCode variable in the existing mutation
payload/logic.
In `@src/components/add-funds/Onboard.tsx`:
- Around line 70-76: The code assumes providers.providers.manteca always exists
and then reads its status into newStatus, which can throw if manteca is missing;
update the logic around the fetchQuery result (the providers variable returned
by queryClient.fetchQuery / getRampProviders) to null-check or use optional
chaining for providers.providers.manteca before accessing .status and provide a
safe fallback (e.g., undefined or a default status) and handle that fallback
where newStatus is used so missing manteca entries won't cause a runtime error.
In `@src/components/add-funds/Status.tsx`:
- Around line 30-34: The code uses raw path strings in Redirect and
router.replace (see Redirect and handleClose/router.replace) which breaks the
typed-route convention; replace the string routes with the app's typed route
helpers (use the generated typed routes or route constants) so Redirect gets a
typed route prop and handleClose calls router.replace with the corresponding
typed route value instead of "/add-funds" or "/(main)/(home)"; update the
imports to pull the typed routes (or route helper functions) and use those
symbols wherever validCurrency gating currently returns or navigates.
In `@src/utils/server.ts`:
- Around line 302-314: The onboardingData parameter of startRampOnboarding is
overly restrictive (typed as { provider: "manteca" }); change its type to accept
the broader RampProvider (or a union that includes "manteca" and future
providers) so the function signature becomes something like
startRampOnboarding(onboardingData: { provider: RampProvider }) and update any
callers to pass a RampProvider value; keep the body (auth(), api.ramp.$post,
error handling and return response.json()) unchanged but ensure
imports/reference to RampProvider are added where startRampOnboarding is
defined.
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/utils/server.ts (1)
178-190: 🧹 Nitpick | 🔵 Trivial
createMantecaKYCduplicatesgetKYCTokenslogic.
createMantecaKYCis nearly identical to callinggetKYCTokens("manteca", redirectURI). Consider reusing the existing function to reduce duplication.♻️ Suggested consolidation
export async function createMantecaKYC(redirectURI?: string) { - await auth(); - const response = await api.kyc.$post({ json: { scope: "manteca", redirectURI } }); - if (!response.ok) { - const { code } = (await response.json()) as { code: string }; - throw new APIError(response.status, code); - } - return response.json(); + return getKYCTokens("manteca", redirectURI); }
🤖 Fix all issues with AI agents
In `@src/components/add-funds/AddFiatButton.tsx`:
- Around line 25-46: The router.push calls in handlePress should use compact
single-line object literals; update each case (NOT_STARTED, ONBOARDING, ACTIVE)
so their router.push invocation passes a single-line object (e.g., router.push({
pathname: "/add-funds/onboard", params: { currency } })) rather than multi-line
blocks—locate handlePress and replace the multi-line objects passed to
router.push with single-line equivalents to satisfy the compact-style rule.
In `@src/components/add-funds/Onboard.tsx`:
- Line 60: CurrencyImage is being computed before the validCurrency check,
causing an undefined or invalid currency to temporarily resolve to ARS; move the
CurrencyImage resolution so it only runs after validation (i.e., compute
CurrencyImage after the validCurrency check or guard with validCurrency) by
updating the code around the CurrencyImage assignment (reference symbols:
CurrencyImage, currency, currencyImages, ARS, validCurrency) so that an
invalid/missing currency does not momentarily pick ARS before the redirect.
In `@src/components/add-funds/Ramp.tsx`:
- Line 67: The current assignment const depositInfo = data?.depositInfo[0] can
yield undefined when depositInfo is an empty array; change it to explicitly
handle empty arrays by using either data?.depositInfo?.at(0) or a length check
(e.g., data?.depositInfo?.length ? data.depositInfo[0] : undefined) so
depositInfo is deterministically undefined only when there is no element, and
update any downstream usage that assumes an element exists to handle the
explicit undefined from depositInfo in the Ramp component.
- Around line 57-63: The query currently casts currency with `currency as
Currency` even though `validCurrency` already guarantees validity; instead,
narrow the value before calling useQuery to avoid inline casts: compute a typed
variable (e.g., const typedCurrency = validCurrency ? currency as Currency :
undefined), set useQuery enabled to !!typedCurrency, and pass typedCurrency into
the queryFn for getRampQuote; reference symbols: useQuery, getRampQuote,
validCurrency, currency, and queryFn. This ensures the type is asserted once
outside the query and removes the unsafe cast inside the queryFn.
In `@src/i18n/es.json`:
- Around line 540-560: The new add-funds i18n keys were appended to the end of
es.json; move them into the existing onboarding/fiat section (or insert in
sorted order) so related strings are grouped—locate keys like "Turn {{currency}}
transfers to onchain USDC", "Transfer from accounts in your name and
automatically receive USDC in your Exa account.", "Copy and share your account
details to turn {{currency}} transfers into USDC.", "Account details",
"Beneficiary name", and "Continue verification" and insert them near the other
onboarding/fiat strings (or alphabetically among nearby keys) rather than
leaving them at the end of the file.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/components/add-funds/AddFunds.tsx`:
- Around line 114-121: Rename the variable providerData to a more concrete noun
(e.g., provider) in the map over Object.entries(providers.providers) so the
callback signature becomes ([providerKey, provider]) and update all references
inside that callback (currencies = provider.onramp.currencies,
status={provider.status}) to use the new name; ensure the key construction
(key={`${providerKey}-${currency}`}) and the AddFiatButton usage remain
unchanged.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/components/add-funds/Ramp.tsx`:
- Around line 124-142: The onCopy callbacks passed to DetailRow (for DetailRow
props in Ramp.tsx) call copyToClipboard with variables of type string |
undefined (beneficiaryName, depositAddress, depositAlias) using
short-circuiting, which doesn't narrow types inside the callback; update each
onCopy to perform an explicit runtime type check (e.g., if (typeof
beneficiaryName === "string") copyToClipboard(beneficiaryName)) for
beneficiaryName, depositAddress and depositAlias so only a string is passed to
copyToClipboard and TypeScript type errors are resolved.
1a28ba6 to
c71e562
Compare
There was a problem hiding this comment.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/utils/server.ts (1)
183-191: 🛠️ Refactor suggestion | 🟠 Major
createMantecaKYCduplicatesgetKYCTokens("manteca", redirectURI).Both functions call
api.kyc.$post({ json: { scope: "manteca", redirectURI } })with identical error handling and return. This can be a simple delegation.♻️ Proposed fix
export async function createMantecaKYC(redirectURI?: string) { - await auth(); - const response = await api.kyc.$post({ json: { scope: "manteca", redirectURI } }); - if (!response.ok) { - const { code } = await response.json(); - throw new APIError(response.status, code); - } - return response.json(); + return getKYCTokens("manteca", redirectURI); }
🤖 Fix all issues with AI agents
In `@src/components/add-funds/Ramp.tsx`:
- Around line 90-91: The code accesses providers.providers.manteca directly
which can throw if manteca is missing; update the guard so you only read onramp
and limits when manteca exists (e.g., check providers?.providers?.manteca before
using its onramp), then derive limits and limitCurrency from that safe reference
(adjust the affected variables: limits and limitCurrency in Ramp.tsx) so
optional chaining or an explicit existence check prevents a runtime crash.
In `@src/i18n/es.json`:
- Line 558: The i18n key in src/i18n/es.json currently embeds a newline ("We
need more\ninformation about you"), coupling layout to the lookup; replace that
key with a plain identifier (e.g., "We need more information about you" or a
named key like "need_more_information") and update all usages to reference the
new key, then move any line-break or wrapping logic into the component/template
(split the string into two <span> or insert a <br/>/CSS-controlled wrap) so
presentation is handled in the UI rather than in the translation key.
In `@src/utils/completeOnboarding.ts`:
- Around line 17-23: Remove the redundant call to
queryClient.invalidateQueries(["ramp","providers"]) before calling
queryClient.fetchQuery with staleTime: 0 since fetchQuery({ queryKey:
["ramp","providers", countryCode], queryFn: getRampProviders, staleTime: 0 })
already forces a fresh network request; either delete the invalidateQueries line
or, if you actually need to mark other provider queries stale, replace it with a
narrower invalidateQueries call that targets specific keys (e.g., include
countryCode) to avoid unnecessary broader invalidation.
- Around line 25-32: The code unguards access to providers.providers.manteca
which can be undefined; update the logic in completeOnboarding to safely read
the status (e.g., via optional chaining or a checked variable) before using it:
compute something like const newStatus = providers?.providers?.manteca?.status
|| "UNKNOWN" (or handle missing provider explicitly), then branch on newStatus
and call router.replace with appropriate params (use "error" or a dedicated
"unsupported" status when manteca is missing) so no TypeError is thrown when
providers.providers.manteca is absent; ensure this change touches the block that
sets newStatus and the subsequent router.replace calls.
- Around line 11-15: The countryCode variable in completeOnboarding.ts can end
up as an empty string and then passed to getRampProviders, causing
countryCode="" to appear in the query; after calling getKYCStatus("basic", true)
and re-reading queryClient.getQueryData<string>(["user","country"]) (or
otherwise obtaining countryCode), normalize it so that empty string becomes
undefined before calling getRampProviders — i.e., replace the current fallback
assignment (countryCode = ... ?? "") with logic that sets countryCode to
undefined when the cached value is missing or an empty string; reference the
countryCode variable, getKYCStatus, and the call site for getRampProviders to
locate and update the code.
In `@src/utils/currencies.ts`:
- Around line 3-7: Update the BRL entry in the currencyMap so the currency name
uses the correct plural form; change the BRL object (in currencyMap) from name:
"Brazilian Real" to name: "Brazilian Reais" so it matches the pluralization
style used by ARS and USD.
In `@src/utils/persona.ts`:
- Line 16: The MantecaKYCResult type is currently not exported but
startMantecaKYC returns Promise<MantecaKYCResult); export the type so consumers
can annotate and reuse it. Locate the type alias MantecaKYCResult in persona.ts
and add an export modifier (export type MantecaKYCResult = ...) so the symbol is
publicly available; ensure any existing imports/exports remain consistent with
startMantecaKYC's signature.
- Around line 147-151: The environment cast in the Client construction inside
startMantecaKYC is missing the matching TODO comment present in startKYC; update
the code so both places are consistent by either adding the same "// TODO
implement environmentId" comment next to the environment as "production" |
"sandbox" cast in startMantecaKYC or remove that TODO from startKYC, then run
tests/lint; look for the Client instantiation in startMantecaKYC and startKYC to
make the change.
In `@src/utils/server.ts`:
- Around line 286-296: In getRampQuote, remove the two unnecessary blank lines
inside the function body so the response assignment, error check, and return
flow are contiguous and consistent with the file's style; update the block
around api.ramp.quote.$get, the if (!response.ok) { ... throw new APIError(...)
} check, and the final return response.json() so there are no extra blank lines
between those statements.
- Around line 298-310: The $post call in startRampOnboarding is split across
multiple lines; collapse the object argument to a single line to match the
compact code style: change the api.ramp.$post invocation (in function
startRampOnboarding) to pass { json: onboarding } on one line (i.e.,
api.ramp.$post({ json: onboarding })) while keeping the surrounding await
auth(), response handling, and error logic (APIError creation and returning
response.json()) unchanged.
baf220a to
1ee2b04
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/utils/server.ts (1)
183-191: 🛠️ Refactor suggestion | 🟠 Major
createMantecaKYCduplicatesgetKYCTokens("manteca", redirectURI).This function's body is identical to calling
getKYCTokenswithscope: "manteca". Consider delegating to avoid duplicating the auth + post + error-handling logic.♻️ Proposed simplification
export async function createMantecaKYC(redirectURI?: string) { - await auth(); - const response = await api.kyc.$post({ json: { scope: "manteca", redirectURI } }); - if (!response.ok) { - const { code } = await response.json(); - throw new APIError(response.status, code); - } - return response.json(); + return getKYCTokens("manteca", redirectURI); }
🤖 Fix all issues with AI agents
In `@src/components/add-funds/Ramp.tsx`:
- Around line 42-44: The Copy icon inside the Pressable (component names:
Pressable, Copy) doesn't change appearance when disabled; update the icon color
to a dimmed/disabled token when the Pressable is disabled by using the same
disabled condition (isLoading || !value) to choose the color (e.g.,
neutral/disabled token vs $interactiveBaseBrandDefault) so the Copy icon
visually indicates it is inactive; apply this conditional color logic where Copy
is rendered and keep the existing onCopy handler and disabled prop on Pressable.
In `@src/utils/currencies.ts`:
- Around line 3-7: Rename the exported constant currencyMap to currencies and
update all references/imports accordingly (e.g., in AddFiatButton.tsx and any
other consumers) to use the new name; ensure the export remains "export const
currencies = { ... } as const" so types are preserved and update any
destructuring or property access that referenced currencyMap to reference
currencies instead.
In `@src/utils/server.ts`:
- Around line 274-284: Remove the gratuitous blank line inside getRampProviders
so it matches the compact style of other helpers: place the api.ramp.$get({
query }) call immediately after the query = { countryCode, redirectURL }
assignment; ensure the function (getRampProviders) retains the same logic around
auth(), response error handling (response.ok check, extracting code, throwing
APIError) and returning response.json(), only removing the extra empty line
between the query variable and the fetch.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/i18n/es.json`:
- Line 565: The JSON entry for "The bank account must be in your name" is the
final property in src/i18n/es.json and is missing the required trailing comma;
update that line (the key "The bank account must be in your name") to include a
trailing comma after the value so the file follows the "trailing commas
everywhere" guideline and stays consistent with the project's JSON formatting
rules.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/utils/server.ts (1)
183-191: 🛠️ Refactor suggestion | 🟠 Major
createMantecaKYCduplicatesgetKYCTokens("manteca", redirectURI).Both functions call
api.kyc.$post({ json: { scope: "manteca", redirectURI } })with identical error handling and return. Consider delegating to reduce duplication:Proposed fix
export async function createMantecaKYC(redirectURI?: string) { - await auth(); - const response = await api.kyc.$post({ json: { scope: "manteca", redirectURI } }); - if (!response.ok) { - const { code } = await response.json(); - throw new APIError(response.status, code); - } - return response.json(); + return getKYCTokens("manteca", redirectURI); }
🤖 Fix all issues with AI agents
In `@src/components/add-funds/Ramp.tsx`:
- Around line 213-217: Prettier is failing on the JSX ternary that renders the
estimatedProcessingTime in Ramp component; open the JSX block around
depositInfo.estimatedProcessingTime in the AddFunds Ramp.tsx (the ternary using
Number.isFinite(Number(depositInfo.estimatedProcessingTime))) and reformat it to
valid/prettier-compliant JSX: ensure the ternary’s true branch is properly
indented and closed, the t(...) call’s object argument and closing
braces/parentheses are on their own lines consistently, and all commas/braces
are correctly placed so the JSX parses (locate the depositInfo variable and the
JSX fragment in the Ramp component to apply the change).
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@cspell.json`:
- Line 141: The cspell.json entry "sixalime" appears unused in the codebase;
either add a short comment in the repo or project docs explaining its purpose
(e.g., it's a username, brand, or external identifier) or remove the entry from
cspell.json to avoid clutter; update the "sixalime" entry in cspell.json (or
delete it) and, if kept, document where/why it is allowed so future reviewers
understand its intent.
In `@src/components/add-funds/KYC.tsx`:
- Around line 36-39: The router.replace call is split across multiple lines;
inline the argument object so it stays compact on a single line
(router.replace({ pathname: "/add-funds/status", params: { status: "error",
currency } })), keeping the properties pathname and params with nested status
and currency together to follow the compact style rule used elsewhere.
In `@src/components/add-funds/Onboard.tsx`:
- Around line 58-61: The router.replace call is formatted across multiple lines;
collapse the object literal into a single line to follow the compact style
rule—update the call to router.replace({ pathname: "/add-funds/status", params:
{ status: "error", currency } }) so the entire argument object (keys pathname
and params and nested status/currency) is on one line while leaving behavior
unchanged; locate the usage of router.replace in the Onboard component,
referencing router.replace, pathname, params, status and currency to make the
single-line change.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@src/components/add-funds/AddFunds.tsx`:
- Around line 112-121: The code iterates directly over the top-level `providers`
object but the API response shape is { providers: { manteca, bridge } }, so
update the traversal in AddFunds.tsx to use the nested `providers.providers`
object (or explicitly access `providers.providers.manteca` and
`providers.providers.bridge`) when building AddFiatButton components; ensure you
read currencies from `provider.onramp.currencies` and status from
`provider.status` as before and guard for missing `providers.providers` before
mapping.
In `@src/components/add-funds/Ramp.tsx`:
- Around line 90-91: The code reads nested provider data from the wrong object —
change accesses to read from providers.providers so you use the actual nested
payload (e.g., replace uses of providers?.manteca with
providers?.providers?.manteca and likewise for providers?.bridge), and update
the lines that set limits and limitCurrency (symbols: limits, limitCurrency) to
use optional chaining against providers?.providers?.manteca.onramp.limits and
providers?.providers?.manteca.onramp.limits?.monthly?.symbol (and similarly
reference providers?.providers?.bridge where applicable) so you safely read the
nested manteca/bridge keys returned by the API.
In `@src/utils/completeOnboarding.ts`:
- Around line 23-24: In completeOnboarding, the code reads providers.manteca
which will throw when the API returns { providers: { ... } }; update access to
use the nested object (e.g., providers.providers.manteca and
providers.providers.bridge), add safe checks (optional chaining or presence
checks) before accessing .status, and ensure you handle missing keys by failing
gracefully or using a sensible fallback; modify the references to newStatus and
any bridge lookups to use providers.providers and include null/undefined guards
in the completeOnboarding function.
closes #470
Summary by CodeRabbit