Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis PR significantly refactors the swap options infrastructure by shifting logic from client-side utilities to server-side subgraph queries. It removes swap path and options builders, replaces an API endpoint with a subgraph query, and updates the SDK to expose payment option metadata including token names and symbols. UI components are updated to use the new data flow and formatting utilities. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Frontend<br/>(useSwapOptions)
participant SDK as SDK<br/>(swapRouteRequest)
participant Subgraph as Subgraph API
participant Convert as convertSwapRoute<br/>ToOptions
Client->>SDK: swapRouteRequest(coinAddress, chainId)
SDK->>SDK: Validate address
SDK->>Subgraph: Query SwapRoute(coinAddress)
Subgraph-->>SDK: SwapRouteFragment<br/>(paymentOptions, mainPath, coinInfo)
SDK-->>Client: SwapRouteFragment
Client->>Convert: convertSwapRouteToOptions<br/>(swapRoute, isBuying, chainId)
Convert->>Convert: normalizeHopsForTradeDirection<br/>convertCoinType<br/>sanitizeHopRange
Convert->>Convert: Build TokenInfo from<br/>payment options metadata
Convert->>Convert: Construct SwapPath<br/>with hops
Convert->>Convert: Generate ETH/WETH<br/>options
Convert-->>Client: SwapOption[]<br/>(with tokenName, tokenSymbol)
Client->>Client: Render swap UI<br/>with formatted amounts
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 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 |
dd29796 to
639d9c2
Compare
639d9c2 to
3644c8e
Compare
a763d47 to
5b8a989
Compare
5b8a989 to
7170be8
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
packages/hooks/src/useSwapOptions.ts (1)
4-4: Useimport typefor type-only imports from@buildeross/swap.
CoinInfo,SwapOption, andSwapPathare used exclusively as type annotations and assertions (lines 9, 12, 81, 118, 129, 141, 146, 183, 189, 194, 210). They are all exported as type-only constructs (export typeorexport interface). Usingimport typeclarifies intent and ensures better tree-shaking behavior.🔧 Proposed fix
-import { CoinInfo, SwapOption as SwapOptionType, SwapPath } from '@buildeross/swap' +import type { CoinInfo, SwapOption as SwapOptionType, SwapPath } from '@buildeross/swap'🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/hooks/src/useSwapOptions.ts` at line 4, The import currently brings in CoinInfo, SwapOption (aliased SwapOptionType), and SwapPath as runtime imports; change that to a type-only import by using "import type { CoinInfo, SwapOption as SwapOptionType, SwapPath } from '@buildeross/swap'". This clarifies they are only used as types (e.g., in uses inside useSwapOptions.ts such as CoinInfo, SwapOptionType, and SwapPath at lines referenced) and enables better tree-shaking without altering any runtime behavior.packages/sdk/src/subgraph/sdk.generated.ts (1)
9464-9469: Add explicit ordering forpaymentOptionsinSwapRoutefragmentLine 9467 currently fetches
paymentOptionswithout ordering. Downstream code inpackages/hooks/src/useSwapOptions.tsiterates through this array to build swap options without defensive sorting, making the order directly impact the UI presentation. SincemainPathis explicitly ordered byhopIndex, adding explicit ordering topaymentOptions(for example bystartHopIndex) ensures deterministic ordering across updates.Suggested source-level change (apply in
packages/sdk/src/subgraph/fragments/SwapRoute.graphql, then regenerate)- paymentOptions { + paymentOptions(orderBy: startHopIndex, orderDirection: asc) { ...PaymentOption }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/sdk/src/subgraph/sdk.generated.ts` around lines 9464 - 9469, The SwapRoute fragment fetches paymentOptions without an explicit order which makes UI ordering non-deterministic; update the SwapRoute GraphQL fragment (the fragment used to generate packages/sdk/src/subgraph/sdk.generated.ts) to add an orderBy clause for paymentOptions (for example orderBy: startHopIndex, orderDirection: asc) so paymentOptions is consistently ordered like mainPath (orderBy: hopIndex), then regenerate the SDK so the generated file and downstream useSwapOptions.ts consume the ordered array deterministically.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/subgraph/src/utils/swapPath.ts`:
- Around line 244-252: The code currently defaults
tokenType/tokenName/tokenSymbol to CoinType.WETH/'Wrapped Ether'/'WETH' when
loadCoinInfo(tokenBytes) returns null, which can corrupt PaymentOption metadata;
instead, stop using WETH as a silent fallback: call loadCoinInfo(tokenBytes) and
if it returns null, set tokenType/tokenName/tokenSymbol to null/undefined (or a
clear sentinel like 'UNKNOWN') and add a guard so you do not persist a
PaymentOption with incorrect WETH metadata (or skip creating the PaymentOption
entirely); update the same logic used around the other occurrence (the similar
block at lines ~260-261) to follow the same non-WETH-fallback behavior and
ensure downstream code that writes PaymentOption handles null/sentinel values
safely.
In `@packages/hooks/src/useSwapOptions.ts`:
- Around line 121-125: The code uses subgraph-provided indices
(paymentOption.startHopIndex, paymentOption.endHopIndex) to slice
swapRoute.mainPath without checks; validate and sanitize these indices before
slicing in useSwapOptions.ts (the loop building relevantHops and the similar
logic at lines ~162-165). Ensure startHopIndex and endHopIndex are integers,
clamp them to the range [0, swapRoute.mainPath.length - 1], and enforce start <=
end (skip or mark the payment option invalid if not). Add a small guard around
the slice (or skip the paymentOption) and optionally log/warn when indices were
out-of-bounds to make issues detectable.
- Around line 57-69: The convertCoinType function currently maps unknown
coinType values to 'weth', which silently mislabels unsupported tokens; change
convertCoinType to either return a narrower union plus undefined (e.g.,
'eth'|'weth'|'zora-coin'|'clanker-token'|undefined) or throw a descriptive Error
on unknown inputs, update its signature accordingly, and adjust all call sites
in this module (the other token-mapping occurrence in the same file) to
explicitly handle undefined/throw (skip the option or surface the error) instead
of assuming 'weth'; ensure the function name convertCoinType and every place
that consumes its result performs explicit validation before building swap
options.
In `@packages/swap/src/types.ts`:
- Around line 256-259: SwapOption.token is declared as CoinInfo but the mapper
in useSwapOptions.ts only supplies address/name/symbol/type and currently casts,
making the type contract unsound; define a narrower type (e.g., TokenInfo or
MinimalCoinInfo) containing only the fields actually provided (address, name,
symbol, type), change SwapOption.token to that new type, and update the mapper
in useSwapOptions.ts to construct and return that TokenInfo without casting to
CoinInfo so the public type matches actual runtime shape (leave CoinInfo for
places that truly need full pool metadata).
---
Nitpick comments:
In `@packages/hooks/src/useSwapOptions.ts`:
- Line 4: The import currently brings in CoinInfo, SwapOption (aliased
SwapOptionType), and SwapPath as runtime imports; change that to a type-only
import by using "import type { CoinInfo, SwapOption as SwapOptionType, SwapPath
} from '@buildeross/swap'". This clarifies they are only used as types (e.g., in
uses inside useSwapOptions.ts such as CoinInfo, SwapOptionType, and SwapPath at
lines referenced) and enables better tree-shaking without altering any runtime
behavior.
In `@packages/sdk/src/subgraph/sdk.generated.ts`:
- Around line 9464-9469: The SwapRoute fragment fetches paymentOptions without
an explicit order which makes UI ordering non-deterministic; update the
SwapRoute GraphQL fragment (the fragment used to generate
packages/sdk/src/subgraph/sdk.generated.ts) to add an orderBy clause for
paymentOptions (for example orderBy: startHopIndex, orderDirection: asc) so
paymentOptions is consistently ordered like mainPath (orderBy: hopIndex), then
regenerate the SDK so the generated file and downstream useSwapOptions.ts
consume the ordered array deterministically.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 884575c6-ca53-41dc-9a49-fd25e8d25605
📒 Files selected for processing (23)
apps/subgraph/schema.graphqlapps/subgraph/src/utils/coinInfo.tsapps/subgraph/src/utils/swapPath.tsapps/web/src/pages/api/coins/swap-options.tspackages/dao-ui/src/components/Cards/Cards.css.tspackages/hooks/src/index.tspackages/hooks/src/useSwapOptions.tspackages/hooks/src/useSwapPath.tspackages/sdk/codegen.ymlpackages/sdk/src/subgraph/fragments/PaymentOption.graphqlpackages/sdk/src/subgraph/fragments/SwapHop.graphqlpackages/sdk/src/subgraph/fragments/SwapRoute.graphqlpackages/sdk/src/subgraph/index.tspackages/sdk/src/subgraph/queries/swapRoute.graphqlpackages/sdk/src/subgraph/requests/swapRouteQuery.tspackages/sdk/src/subgraph/sdk.generated.tspackages/swap/src/buildSwapOptions.tspackages/swap/src/buildSwapPath.tspackages/swap/src/getCoinInfo.tspackages/swap/src/index.tspackages/swap/src/types.tspackages/ui/src/LikeButton/LikeButton.tsxpackages/ui/src/SwapWidget/SwapWidget.tsx
💤 Files with no reviewable changes (7)
- packages/hooks/src/index.ts
- packages/hooks/src/useSwapPath.ts
- packages/swap/src/getCoinInfo.ts
- packages/swap/src/index.ts
- apps/web/src/pages/api/coins/swap-options.ts
- packages/swap/src/buildSwapPath.ts
- packages/swap/src/buildSwapOptions.ts
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/hooks/src/useSwapOptions.ts`:
- Around line 36-43: The mapped hop construction in useSwapOptions.ts returns
hop.hooks possibly as null which violates the SwapPathHop contract expecting an
optional Address (undefined, not null); update the mapping in the
relevantHops.map (and the similar block at lines ~47-54) to normalize nullable
hooks to undefined (e.g., replace the direct cast hop.hooks as AddressType |
undefined with an explicit conversion that yields undefined when hop.hooks is
null) so downstream consumers receive undefined instead of null while keeping
other fields as-is.
In `@packages/utils/src/numbers.ts`:
- Around line 109-116: formatTokenAmount currently truncates tiny non-zero
values to "0.00"; update formatTokenAmount to detect when the numeric input is
non-zero but the formatted string equals the minimum-zero representation (from
formatDecimalValue with minDecimals:2 and mode:'truncate') and instead return a
small-nonzero indicator such as "<0.01"; implement this by converting the input
(BigNumber/BigNumberish/string) to a high-precision numeric check (e.g., compare
>0 and < 10^-minDecimals) before/after calling formatDecimalValue and return
"<0.01" (or the computed threshold string) when that condition is met. Ensure
changes are made inside formatTokenAmount and reference formatDecimalValue
usage.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 69c67d72-db97-4405-8699-6140ac3b2e2b
📒 Files selected for processing (8)
apps/subgraph/schema.graphqlapps/subgraph/src/utils/coinInfo.tsapps/subgraph/src/utils/swapPath.tspackages/hooks/src/useSwapOptions.tspackages/swap/src/types.tspackages/ui/src/SwapWidget/SwapWidget.css.tspackages/ui/src/SwapWidget/SwapWidget.tsxpackages/utils/src/numbers.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/subgraph/schema.graphql
| export function formatTokenAmount(value: BigNumber | BigNumberish | string): string { | ||
| return formatDecimalValue(value, { | ||
| minDecimals: 2, | ||
| maxDecimals: 10, | ||
| mode: 'truncate', | ||
| useGrouping: false, | ||
| }) | ||
| } |
There was a problem hiding this comment.
Very small non-zero token amounts can be displayed as 0.00.
formatTokenAmount currently truncates to 10 decimals with a 2-decimal floor, so dust balances (e.g. 1 wei) render as zero. That can mislead users in balance displays.
💡 Proposed fix
export function formatTokenAmount(value: BigNumber | BigNumberish | string): string {
- return formatDecimalValue(value, {
+ const parsed = new BigNumber(typeof value === 'string' ? value : value?.toString())
+ if (!parsed.isFinite()) return '0'
+
+ const minVisible = new BigNumber(1).shiftedBy(-10) // 0.0000000001
+ if (!parsed.isZero() && parsed.abs().isLessThan(minVisible)) {
+ return `<${minVisible.toFixed(10)}`
+ }
+
+ return formatDecimalValue(parsed, {
minDecimals: 2,
maxDecimals: 10,
mode: 'truncate',
useGrouping: false,
})
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function formatTokenAmount(value: BigNumber | BigNumberish | string): string { | |
| return formatDecimalValue(value, { | |
| minDecimals: 2, | |
| maxDecimals: 10, | |
| mode: 'truncate', | |
| useGrouping: false, | |
| }) | |
| } | |
| export function formatTokenAmount(value: BigNumber | BigNumberish | string): string { | |
| const parsed = new BigNumber(typeof value === 'string' ? value : value?.toString()) | |
| if (!parsed.isFinite()) return '0' | |
| const minVisible = new BigNumber(1).shiftedBy(-10) // 0.0000000001 | |
| if (!parsed.isZero() && parsed.abs().isLessThan(minVisible)) { | |
| return `<${minVisible.toFixed(10)}` | |
| } | |
| return formatDecimalValue(parsed, { | |
| minDecimals: 2, | |
| maxDecimals: 10, | |
| mode: 'truncate', | |
| useGrouping: false, | |
| }) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/utils/src/numbers.ts` around lines 109 - 116, formatTokenAmount
currently truncates tiny non-zero values to "0.00"; update formatTokenAmount to
detect when the numeric input is non-zero but the formatted string equals the
minimum-zero representation (from formatDecimalValue with minDecimals:2 and
mode:'truncate') and instead return a small-nonzero indicator such as "<0.01";
implement this by converting the input (BigNumber/BigNumberish/string) to a
high-precision numeric check (e.g., compare >0 and < 10^-minDecimals)
before/after calling formatDecimalValue and return "<0.01" (or the computed
threshold string) when that condition is met. Ensure changes are made inside
formatTokenAmount and reference formatDecimalValue usage.
6fed9be to
2254dc4
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
packages/utils/src/numbers.ts (1)
126-128: KeepzeroFormattedtied to the configured decimals.At Line 127,
minDecimalsis hardcoded to2even though Line 110 already definesminDecimals. Reusing the variable avoids silent drift later.Refactor patch
const zeroFormatted = formatDecimalValue(0, { - minDecimals: 2, + minDecimals, maxDecimals, mode, useGrouping, })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/utils/src/numbers.ts` around lines 126 - 128, zeroFormatted is being created with a hardcoded minDecimals of 2 even though a minDecimals variable is defined earlier; update the call to formatDecimalValue (the zeroFormatted initialization) to use the existing minDecimals variable instead of the literal 2 so zeroFormatted respects the configured minDecimals and stays in sync with maxDecimals.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/hooks/src/useSwapOptions.ts`:
- Around line 40-41: The current truthy check `hop.fee ? BigInt(hop.fee) :
undefined` drops legitimate zero fees; change it to a nullish check so zero is
preserved by using `hop.fee != null ? BigInt(hop.fee) : undefined` in the
mapping where `hop` is handled (replace both occurrences around the fee
assignment at the two hop mappings in useSwapOptions.ts); leave the `hooks` cast
as-is.
In `@packages/ui/src/SwapWidget/SwapWidget.tsx`:
- Line 341: Add a decimals: number field to the TokenInfo type and ensure it is
populated from the token metadata at initialization (e.g., when loading token
info for swaps), then replace all uses of formatEther(...) with formatUnits(...,
token.decimals) so amounts render per-token decimals; specifically update the
TokenInfo type (TokenInfo) to include decimals, ensure consumers that build
token objects supply decimals, and change formatting calls in SwapWidget (the
return message and the other flagged amount displays that currently call
formatEther) to use formatUnits(amount, token.decimals).
---
Nitpick comments:
In `@packages/utils/src/numbers.ts`:
- Around line 126-128: zeroFormatted is being created with a hardcoded
minDecimals of 2 even though a minDecimals variable is defined earlier; update
the call to formatDecimalValue (the zeroFormatted initialization) to use the
existing minDecimals variable instead of the literal 2 so zeroFormatted respects
the configured minDecimals and stays in sync with maxDecimals.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 15f5baf7-35bf-47e6-9993-430ae9b60b5d
📒 Files selected for processing (4)
packages/hooks/src/useSwapOptions.tspackages/ui/src/SwapWidget/SwapWidget.tsxpackages/utils/src/numbers.test.tspackages/utils/src/numbers.ts
packages/hooks/src/useSwapOptions.ts
Outdated
| fee: hop.fee ? BigInt(hop.fee) : undefined, | ||
| hooks: hop.hooks ? (hop.hooks as AddressType) : undefined, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n packages/hooks/src/useSwapOptions.ts | head -80Repository: BuilderOSS/nouns-builder
Length of output: 2950
🏁 Script executed:
# Check the exact lines mentioned
sed -n '35,55p' packages/hooks/src/useSwapOptions.tsRepository: BuilderOSS/nouns-builder
Length of output: 837
🏁 Script executed:
# Find type definitions for Hop and hop.fee
rg "type Hop|interface Hop" packages/hooks/src -A 10Repository: BuilderOSS/nouns-builder
Length of output: 697
🏁 Script executed:
# Check SwapPathHop in the types
rg "SwapPathHop|fee\?:" packages/swap/src/types.ts -A 5 -B 2Repository: BuilderOSS/nouns-builder
Length of output: 667
🏁 Script executed:
# Check subgraph type definitions for fee
rg "fee.*:" packages/sdk/src/subgraph -A 2 -B 2 -t ts | head -100Repository: BuilderOSS/nouns-builder
Length of output: 5158
Fix fee coercion to preserve zero-fee hops at lines 40–41 and 51–52.
The truthy check hop.fee ? BigInt(hop.fee) : undefined converts fee: 0 to undefined, losing zero-fee pool information. Use nullish coalescing instead:
Proposed fix
- fee: hop.fee ? BigInt(hop.fee) : undefined,
+ fee: hop.fee != null ? BigInt(hop.fee) : undefined,(Apply to both lines 40 and 51)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fee: hop.fee ? BigInt(hop.fee) : undefined, | |
| hooks: hop.hooks ? (hop.hooks as AddressType) : undefined, | |
| fee: hop.fee != null ? BigInt(hop.fee) : undefined, | |
| hooks: hop.hooks ? (hop.hooks as AddressType) : undefined, |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/hooks/src/useSwapOptions.ts` around lines 40 - 41, The current
truthy check `hop.fee ? BigInt(hop.fee) : undefined` drops legitimate zero fees;
change it to a nullish check so zero is preserved by using `hop.fee != null ?
BigInt(hop.fee) : undefined` in the mapping where `hop` is handled (replace both
occurrences around the fee assignment at the two hop mappings in
useSwapOptions.ts); leave the `hooks` cast as-is.
| )?.token.symbol || 'ETH' | ||
| : symbol | ||
| return `Amount exceeds pool limit (max: ${parseFloat(formatEther(poolMaxAmount!)).toFixed(4)} ${tokenSymbol})` | ||
| return `Amount exceeds pool limit (max: ${formatTokenAmount(formatEther(poolMaxAmount!))} ${tokenSymbol})` |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== SwapWidget.tsx file length and formatEther usage ==="
wc -l packages/ui/src/SwapWidget/SwapWidget.tsx
echo ""
echo "=== formatEther calls in SwapWidget.tsx ==="
rg -n 'formatEther' packages/ui/src/SwapWidget/SwapWidget.tsx | head -20Repository: BuilderOSS/nouns-builder
Length of output: 1036
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== SwapOption/Token interface definitions ==="
rg -n -B2 -A10 'interface.*SwapOption|type.*SwapOption|interface.*Token' packages --type=ts --type=tsx | head -100
echo "=== Token decimals field in SwapOption or related types ==="
rg -n 'decimals' packages --type=ts --type=tsx | grep -i 'swap\|token' | head -30Repository: BuilderOSS/nouns-builder
Length of output: 159
🏁 Script executed:
#!/bin/bash
set -euoelpipefail
echo "=== Examine specific lines around formatEther calls in SwapWidget.tsx ==="
sed -n '335,350p' packages/ui/src/SwapWidget/SwapWidget.tsx
echo "---"
sed -n '490,500p' packages/ui/src/SwapWidget/SwapWidget.tsx
echo "---"
sed -n '575,590p' packages/ui/src/SwapWidget/SwapWidget.tsxRepository: BuilderOSS/nouns-builder
Length of output: 742
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== SwapOption/Token interface definitions ==="
rg -n 'interface.*SwapOption|type.*SwapOption' packages --type ts | head -20
echo ""
echo "=== Check for decimals in token-related types ==="
rg -n 'decimals' packages --type ts | head -30Repository: BuilderOSS/nouns-builder
Length of output: 3102
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Context around line 341 formatEther usage ==="
sed -n '335,350p' packages/ui/src/SwapWidget/SwapWidget.tsx
echo ""
echo "=== Context around line 494 formatEther usage ==="
sed -n '488,502p' packages/ui/src/SwapWidget/SwapWidget.tsx
echo ""
echo "=== Context around line 581 formatEther usage ==="
sed -n '575,590p' packages/ui/src/SwapWidget/SwapWidget.tsxRepository: BuilderOSS/nouns-builder
Length of output: 1887
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== SwapWidget.tsx imports section ==="
head -40 packages/ui/src/SwapWidget/SwapWidget.tsx
echo ""
echo "=== Check if formatUnits is used elsewhere in the file ==="
rg -n 'formatUnits' packages/ui/src/SwapWidget/SwapWidget.tsxRepository: BuilderOSS/nouns-builder
Length of output: 1411
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== SwapOption interface definition ==="
sed -n '266,290p' packages/swap/src/types.ts
echo ""
echo "=== TokenInfo interface definition (referenced in useSwapOptions.ts) ==="
rg -n -A15 'export interface TokenInfo|export type TokenInfo' packages/swap/src/types.tsRepository: BuilderOSS/nouns-builder
Length of output: 749
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Token field types in SwapOption ==="
rg -n -B5 -A20 'export interface SwapOption' packages/swap/src/types.ts
echo ""
echo "=== Check SwapPath and related types ==="
rg -n -A10 'export interface SwapPath|export type.*Token' packages/swap/src/types.ts | head -80Repository: BuilderOSS/nouns-builder
Length of output: 858
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== How token is used in SwapWidget.tsx context ==="
sed -n '480,510p' packages/ui/src/SwapWidget/SwapWidget.tsx
echo ""
echo "=== Token access patterns ==="
rg -n 'token\.' packages/ui/src/SwapWidget/SwapWidget.tsx | head -20Repository: BuilderOSS/nouns-builder
Length of output: 2546
Add token decimals to TokenInfo and use token-specific formatting.
Token balances at lines 341, 494, 581, 624, 646, and 651 are formatted with formatEther, which assumes 18 decimals. The TokenInfo type includes address, symbol, name, and type—but no decimals field. This means non-18-decimal tokens (USDC, USDT, etc.) will display incorrect amounts by orders of magnitude (e.g., 1 USDC with 6 decimals would render as 0.000000000001).
Required changes:
- Add
decimals: numberfield to theTokenInfotype inpackages/swap/src/types.ts - Populate decimals from on-chain ERC20 metadata or swap initialization
- Replace
formatEther(amount)withformatUnits(amount, decimals)at all flagged lines
Also applies to: 494–495, 581–582, 624–625, 646–652
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/ui/src/SwapWidget/SwapWidget.tsx` at line 341, Add a decimals:
number field to the TokenInfo type and ensure it is populated from the token
metadata at initialization (e.g., when loading token info for swaps), then
replace all uses of formatEther(...) with formatUnits(..., token.decimals) so
amounts render per-token decimals; specifically update the TokenInfo type
(TokenInfo) to include decimals, ensure consumers that build token objects
supply decimals, and change formatting calls in SwapWidget (the return message
and the other flagged amount displays that currently call formatEther) to use
formatUnits(amount, token.decimals).
2254dc4 to
0f7c994
Compare
Summary by CodeRabbit
Release Notes
New Features
Style & UX
Refactor