-
Notifications
You must be signed in to change notification settings - Fork 13
[TASK-11579] feat: add cross-chain action card #919
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TASK-11579] feat: add cross-chain action card #919
Conversation
Use coral through squid to get the cross-chain route for the different flows. This enables xchain withdraw for peanut wallet
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Caution Review failedThe pull request is closed. WalkthroughThis update introduces cross-chain route expiry timers, approval transaction handling, and enhanced fee and error management for both payment and withdrawal flows. It adds new UI components for route expiry, updates the swap service to handle ERC-20 approvals, and refactors hooks and views to support minimum received amounts, cross-chain awareness, and improved transaction preparation logic. Changes
Possibly related PRs
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (5)
✨ Finishing Touches
🧪 Generate Unit Tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (2)
src/components/Global/RouteExpiryTimer/index.tsx (1)
117-125
: Consider making the total duration configurable.The progress calculation assumes a fixed 1-minute duration, but route expiry times might vary. Consider making this configurable or calculating it dynamically.
+ const totalDurationMs = expiry ? (parseInt(expiry) * 1000) - (new Date().getTime() - timeRemaining.totalMs) : 60000 - const totalDurationMs = 1 * 60 * 1000 // 1 minutesOr add it as a prop:
interface RouteExpiryTimerProps { expiry?: string + totalDurationMs?: number // Allow customization of total duration // ... other props }
src/hooks/usePaymentInitiator.ts (1)
221-225
: Remove commented code or document the transition plan.The commented-out validation code suggests this refactor is incomplete. Either remove the commented code if it's no longer needed, or document when it will be cleaned up.
- /* - if (!txData?.unsignedTxs) { - throw new Error('Failed to prepare cross-chain transaction') - } - */
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
src/app/(mobile-ui)/withdraw/crypto/page.tsx
(6 hunks)src/app/[...recipient]/client.tsx
(1 hunks)src/app/actions/tokens.ts
(3 hunks)src/components/Global/PeanutActionDetailsCard/index.tsx
(4 hunks)src/components/Global/RouteExpiryTimer/index.tsx
(1 hunks)src/components/Payment/Views/Confirm.payment.view.tsx
(11 hunks)src/components/Withdraw/views/Confirm.withdraw.view.tsx
(6 hunks)src/components/Withdraw/views/Initial.withdraw.view.tsx
(2 hunks)src/hooks/usePaymentInitiator.ts
(13 hunks)src/services/swap.ts
(8 hunks)src/utils/index.ts
(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/components/Withdraw/views/Initial.withdraw.view.tsx (2)
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#413
File: src/context/tokenSelector.context.tsx:118-123
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In the `TokenContextProvider` component within `src/context/tokenSelector.context.tsx`, in the TypeScript React application, when data changes and before calling `fetchAndSetTokenPrice`, it is necessary to reset `selectedTokenData`, `selectedTokenPrice`, `selectedTokenDecimals`, and `inputDenomination` to discard stale data.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
🧬 Code Graph Analysis (1)
src/app/actions/tokens.ts (3)
src/utils/general.utils.ts (2)
isStableCoin
(1108-1110)estimateIfIsStableCoinFromPrice
(748-755)src/app/actions/clients.ts (2)
getPublicClient
(20-35)ChainId
(11-11)src/utils/token.utils.ts (1)
NATIVE_TOKEN_ADDRESS
(27-27)
🔇 Additional comments (34)
src/utils/index.ts (1)
6-6
: LGTM! Clean utility export addition.The export follows the established pattern and extends the available utility functions from the token.utils module.
src/app/[...recipient]/client.tsx (1)
396-396
: LGTM! Consistent flow-based prop passing.The
isDirectPay
prop correctly derives from the flow comparison and maintains consistency with the component's flow-handling pattern.src/components/Withdraw/views/Initial.withdraw.view.tsx (1)
16-16
: LGTM! TokenSelector properly integrated.The TokenSelector import and usage are correctly implemented, allowing users to select their preferred token for withdrawal.
Also applies to: 90-90
src/app/actions/tokens.ts (2)
7-9
: LGTM! Necessary imports for enhanced functionality.The new imports support the enhanced stablecoin detection and transaction cost estimation features.
90-90
: LGTM! Enhanced stablecoin detection.Adding symbol-based stablecoin detection alongside price-based detection provides more robust stablecoin identification.
src/components/Global/RouteExpiryTimer/index.tsx (4)
35-58
: LGTM! Robust time calculation with proper validation.The
calculateTimeRemaining
function properly handles edge cases:
- Validates expiry input
- Handles invalid timestamps
- Correctly converts Unix timestamp to milliseconds
- Returns null for invalid inputs
60-109
: LGTM! Proper cleanup and state management.The useEffect properly:
- Cleans up intervals to prevent memory leaks
- Resets state when conditions change
- Handles callback triggers with proper guards
- Updates timer at appropriate intervals
140-144
: LGTM! Smart pulse logic for user feedback.The pulse animation appropriately triggers during loading and near expiry states, providing good visual feedback to users.
155-187
: LGTM! Well-structured render with proper styling.The component renders with:
- Clear status text with appropriate colors
- Animated progress bar with color coding
- Proper conditional styling using twMerge
- Good accessibility through color and text indicators
src/components/Global/PeanutActionDetailsCard/index.tsx (2)
24-31
: Well-structured timer props interface.The timer-related props are clearly defined with appropriate types and optional flags. The naming convention is consistent and the props cover all necessary timer functionality.
135-144
: Clean timer integration.The conditional rendering of
RouteExpiryTimer
is well-implemented, passing through all necessary props while maintaining the existing card layout.src/app/(mobile-ui)/withdraw/crypto/page.tsx (4)
217-233
: Solid cross-chain detection logic.The cross-chain detection correctly compares source and destination chain IDs, with proper handling of Peanut Wallet context. The logging provides good debugging information.
236-245
: Appropriate route type restrictions.The route type error checking correctly restricts "swap" routes for Peanut Wallet users, providing a clear error message. This aligns with the business logic requirements.
202-207
: Clean route refresh implementation.The route refresh handler properly calls
prepareTransactionDetails
with current charge details and amount. The logging helps with debugging route expiry scenarios.
252-257
: Robust network fee calculation.The network fee calculation provides appropriate fallbacks and formatting, handling both cross-chain routes and default scenarios properly.
src/components/Payment/Views/Confirm.payment.view.tsx (3)
75-83
: Improved network fee calculation.The network fee memo handles multiple scenarios properly: Peanut Wallet sponsorship, fee estimation errors, and small amounts with appropriate formatting.
298-307
: Consistent route type restrictions.The route type error logic matches the withdrawal flow implementation, maintaining consistency across payment and withdrawal experiences.
334-342
: Effective timer integration.The timer props are properly passed to
PeanutActionDetailsCard
, enabling cross-chain route expiry handling in the payment flow.src/components/Withdraw/views/Confirm.withdraw.view.tsx (3)
68-76
: Well-integrated timer functionality.The timer props are properly integrated, providing expiry handling and loading states for cross-chain withdrawals.
128-137
: Improved error handling logic.The enhanced error handling correctly differentiates between route type errors (triggering refresh) and other errors (triggering retry), providing better user experience.
67-67
: Let’s broaden the search to include both.ts
and.tsx
files without relying on ripgrep types:#!/bin/bash # Search for hardcoded USDC tokenSymbol across TS and TSX files rg 'tokenSymbol\s*=\s*"USDC"' -A3 -B3 --glob '*.ts' --glob '*.tsx'src/services/swap.ts (6)
177-193
: Secure allowance checking implementation.The
checkTokenAllowance
function properly uses the ERC-20 standard interface and handles the blockchain interaction correctly.
198-214
: Clean approval transaction creation.The
createApproveTransaction
function correctly encodes the ERC-20 approve function call with proper parameter handling.
274-277
: Excellent performance optimization.The concurrent fetching of token prices using
Promise.all
significantly improves performance by avoiding sequential API calls.
290-306
: Thoughtful tolerance adjustments.The dynamic tolerance ranges based on USD amounts show careful consideration of slippage effects across different transaction sizes, with more granular control for smaller amounts.
482-524
: Robust approval handling logic.The approval logic correctly:
- Checks current allowance before creating approval transactions
- Only adds approval when insufficient allowance exists
- Includes approval costs in total fee calculation
- Handles errors gracefully without breaking the flow
This is a solid implementation of ERC-20 approval handling.
527-537
: Well-structured transaction array.The transaction preparation properly sequences approval (if needed) followed by the main swap transaction, with consistent fee options for both transaction types.
src/hooks/usePaymentInitiator.ts (7)
26-35
: LGTM: Import updates align with new cross-chain functionality.The new imports properly support the architectural shift to using the swap service for cross-chain routing and fee estimation.
95-95
: LGTM: Added state for cross-chain route data.The new
xChainRoute
state variable properly stores the comprehensive route information from the swap service.
172-173
: LGTM: Function signature improvements for withdrawal flow.The parameter changes from
isAddMoneyFlowContext
toisWithdrawFlow
and the addition ofusdAmount
provide better clarity and support for USD-based routing.
254-263
: LGTM: Improved fee estimation for same-chain transactions.The integration with
estimateTransactionCostUsd
provides more accurate fee estimation compared to the previous approach.
207-219
: LGTM: Comprehensive cross-chain route integration.The new
getRoute
integration properly handles both USD-based and token amount-based routing, providing a more flexible and powerful cross-chain solution.
746-746
: LGTM: Return object updated with cross-chain route data.Adding
xChainRoute
to the return object enables components to access route expiry timers and other cross-chain metadata as mentioned in the PR objectives.
447-504
: Verify hardcoded chain/token values match transaction preparation.The function now uses hardcoded
PEANUT_WALLET_CHAIN
andPEANUT_WALLET_TOKEN
values when creating payment records, but the actual transactions might use different chains/tokens based on the cross-chain route. This could cause inconsistencies in payment tracking.#!/bin/bash # Description: Check if PEANUT_WALLET_CHAIN and PEANUT_WALLET_TOKEN are consistently used across transaction preparation and payment creation # Search for usage of these constants in cross-chain transaction preparation rg -A 5 -B 5 "PEANUT_WALLET_CHAIN|PEANUT_WALLET_TOKEN" --type ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
squid 99.5 WIP
const networkFee = useCallback(() => { | ||
if (xChainRoute?.feeCostsUsd) { | ||
return xChainRoute.feeCostsUsd < 0.01 ? '$ <0.01' : `$ ${xChainRoute.feeCostsUsd.toFixed(2)}` | ||
} | ||
return '$ 0.00' | ||
}, [xChainRoute]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue, non-blocking: I dislike this. We have a lot of money flows
withdraw, add, pay a request, send money etc
In all of them we have fees. We should handle that in a centralized place (probably 2: one for calculation, the other for formatting). Having it like this increases code complexity and surface for bugs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For xChain the calculation is centralized (we use the one informed by squid), formatting I actually prefer it to be near of where we show the value. We have two confirm pages right now. The withdraw one and the payment one that is used in all other flows
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i disagree. We've had so much back and forth on fees - tons of discussions and edge case bugs and so on. I really think centralizing would save us a lot of time longterm. Happy to disagree and commit on this one, but lets revisit it next time we have a bug on fees
currency, | ||
currencyAmount, | ||
isAddMoneyFlow, | ||
isDirectPay = false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Readability: directPay var is not clear. Why does it matter? Would a dev reading this for the first time be able to understand why the variables are needed and what they represent without having to deeply understand prepareTransaction and other fns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: for functions, always add a quick docstring. IMO almost always it helps readability. It is extremely rare that we are too verbose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jjramirezn this isnt resolved
async function estimateApprovalCostUsd( | ||
tokenAddress: Address, | ||
spenderAddress: Address, | ||
amount: bigint, | ||
fromAddress: Address, | ||
chainId: string | ||
): Promise<number> { | ||
const estimateCost = await estimateTransactionCostUsd( | ||
fromAddress, | ||
tokenAddress, | ||
encodeFunctionData({ | ||
abi: erc20Abi, | ||
functionName: 'approve', | ||
args: [spenderAddress, amount], | ||
}), | ||
chainId | ||
) | ||
return estimateCost | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this seems like an unnecessary fn. A generic estimateTxnCostUsd is better and always usable imo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my brother in christ, this function uses the generic estimateTxCostUsd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes exactly! estimateApprovalCostUsd seems superfluous!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (3)
src/app/actions/tokens.ts (1)
148-210
: Review the gas estimation assumptions and error handling.The function implementation looks solid but has some areas for improvement:
Gas decimals assumption: Line 201 uses
nativeTokenPrice.decimals
but this may not represent the native token's actual decimals. Native tokens often have different decimal configurations than what's returned from price APIs.Scientific notation handling: Based on the PR objectives, there's a known issue with scientific notation in
parseUnits
that could affect this code path.Conservative fallback: The 0.01 USD fallback might be too low for high-gas networks like Ethereum mainnet.
Consider these improvements:
// Get native token decimals dynamically - const estimatedCostUsd = nativeTokenPrice ? Number(formatUnits(gasCostWei, nativeTokenPrice.decimals)) * nativeTokenPrice.price : 0.01 + const nativeTokenDetails = await fetchTokenDetails(NATIVE_TOKEN_ADDRESS, chainId) + const decimals = nativeTokenDetails?.decimals ?? 18 + const estimatedCostUsd = nativeTokenPrice ? Number(formatUnits(gasCostWei, decimals)) * nativeTokenPrice.price : 0.01Also consider making the fallback amount configurable based on the chain:
- return 0.01 + // Higher fallback for mainnet, lower for testnets/L2s + const fallbackAmount = Number(chainId) === 1 ? 0.05 : 0.01 + return fallbackAmountsrc/components/Payment/Views/Confirm.payment.view.tsx (1)
323-326
: Add error handling for deep property access.The minimum received calculation accesses deeply nested properties (
xChainRoute.rawResponse.route.estimate.toAmountMin
) without null checks, which could throw runtime errors if the API response structure changes.Add defensive programming:
const minReceived = useMemo<string | null>(() => { - if (!xChainRoute || !chargeDetails?.tokenDecimals) return null - return formatUnits(BigInt(xChainRoute.rawResponse.route.estimate.toAmountMin), chargeDetails.tokenDecimals) + if (!xChainRoute || !chargeDetails?.tokenDecimals) return null + + try { + const toAmountMin = xChainRoute.rawResponse?.route?.estimate?.toAmountMin + if (!toAmountMin) return null + return formatUnits(BigInt(toAmountMin), chargeDetails.tokenDecimals) + } catch (error) { + console.warn('Failed to calculate minimum received amount:', error) + return null + } }, [xChainRoute, chargeDetails?.tokenDecimals])src/hooks/usePaymentInitiator.ts (1)
238-238
: Fix potentially incorrect slippage calculation.The slippage calculation appears to be comparing amounts rather than prices, which would not give a meaningful slippage percentage. Slippage should typically be calculated based on price impact or expected vs actual exchange rates.
Verify this calculation is correct, or consider:
- const slippagePercentage = Number(xChainRoute.fromAmount) / Number(chargeDetails.tokenAmount) - 1 + // Calculate slippage based on route's price impact if available + const slippagePercentage = xChainRoute.slippage ?? 0
🧹 Nitpick comments (1)
src/hooks/usePaymentInitiator.ts (1)
232-236
: Remove commented-out code.This commented code block should be removed to maintain code cleanliness.
- /* - if (!txData?.unsignedTxs) { - throw new Error('Failed to prepare cross-chain transaction') - } - */
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
src/app/(mobile-ui)/withdraw/crypto/page.tsx
(11 hunks)src/app/actions/tokens.ts
(3 hunks)src/components/Payment/Views/Confirm.payment.view.tsx
(11 hunks)src/hooks/usePaymentInitiator.ts
(13 hunks)src/services/swap.ts
(10 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/app/(mobile-ui)/withdraw/crypto/page.tsx
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#919
File: src/components/Withdraw/views/Initial.withdraw.view.tsx:87-87
Timestamp: 2025-06-18T19:56:55.443Z
Learning: In withdraw flows for Peanut Wallet, the PeanutActionDetailsCard should always display "USDC" as the token symbol because it shows the amount being withdrawn from the Peanut Wallet (which holds USDC), regardless of the destination token/chain selected by the user. The TokenSelector is used for choosing the withdrawal destination, not the source display.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#535
File: src/components/Claim/Claim.tsx:142-146
Timestamp: 2024-11-18T21:36:11.486Z
Learning: In `src/components/Claim/Claim.tsx`, external calls like token price fetching and cross-chain details retrieval are already encapsulated within existing `try...catch` blocks, so additional error handling may be unnecessary.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:103-111
Timestamp: 2024-10-08T20:13:42.967Z
Learning: When the token price cannot be fetched in `src/components/Request/Pay/Pay.tsx` within the `PayRequestLink` component, set `tokenPriceData.price` to 0 to ensure the UI remains functional. Since Squid uses their own price engine for x-chain fulfillment transactions, this approach will not affect the transaction computation.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:103-111
Timestamp: 2024-10-07T13:42:00.443Z
Learning: When the token price cannot be fetched in `src/components/Request/Pay/Pay.tsx` within the `PayRequestLink` component, set `tokenPriceData.price` to 0 to ensure the UI remains functional. Since Squid uses their own price engine for x-chain fulfillment transactions, this approach will not affect the transaction computation.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:28:25.280Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(estimatedGasCost, 3)` return strings, ensuring consistent return types for `calculatedFee`.
src/app/actions/tokens.ts (16)
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:28:25.280Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(estimatedGasCost, 3)` return strings, ensuring consistent return types for `calculatedFee`.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:25:45.170Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(...)` return strings, ensuring that `calculatedFee` consistently returns a string without the need for additional type conversion.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:103-111
Timestamp: 2024-10-08T20:13:42.967Z
Learning: When the token price cannot be fetched in `src/components/Request/Pay/Pay.tsx` within the `PayRequestLink` component, set `tokenPriceData.price` to 0 to ensure the UI remains functional. Since Squid uses their own price engine for x-chain fulfillment transactions, this approach will not affect the transaction computation.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:103-111
Timestamp: 2024-10-07T13:42:00.443Z
Learning: When the token price cannot be fetched in `src/components/Request/Pay/Pay.tsx` within the `PayRequestLink` component, set `tokenPriceData.price` to 0 to ensure the UI remains functional. Since Squid uses their own price engine for x-chain fulfillment transactions, this approach will not affect the transaction computation.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#535
File: src/components/Claim/Claim.tsx:142-146
Timestamp: 2024-11-18T21:36:11.486Z
Learning: In `src/components/Claim/Claim.tsx`, external calls like token price fetching and cross-chain details retrieval are already encapsulated within existing `try...catch` blocks, so additional error handling may be unnecessary.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#413
File: src/context/tokenSelector.context.tsx:118-123
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In the `TokenContextProvider` component within `src/context/tokenSelector.context.tsx`, in the TypeScript React application, when data changes and before calling `fetchAndSetTokenPrice`, it is necessary to reset `selectedTokenData`, `selectedTokenPrice`, `selectedTokenDecimals`, and `inputDenomination` to discard stale data.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#847
File: src/app/actions/clients.ts:48-68
Timestamp: 2025-05-13T16:26:58.336Z
Learning: In viem v2.21.48, the `stateOverride` parameter for `estimateGas` and related functions expects an array-based format: `[{ address: tokenAddress, stateDiff: [{ slot: calculatedSlot, value: hexValue }] }]` rather than an object-based format.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#868
File: src/components/Payment/PaymentForm/index.tsx:284-293
Timestamp: 2025-05-19T19:40:43.138Z
Learning: When converting between USD and token amounts, always check if the token price (divisor) is valid and non-zero before performing the division to prevent Infinity, NaN, or errors. Implementing validation like `if (!tokenPrice || isNaN(tokenPrice) || tokenPrice === 0)` before division operations is crucial for handling cases where price data might be unavailable.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/context/walletContext/walletContext.tsx:87-88
Timestamp: 2024-12-02T17:21:45.515Z
Learning: When converting `totalBalance` (in USD) to a `BigInt` balance in `src/context/walletContext/walletContext.tsx`, multiplying by `1e6` is intentional to maintain compatibility with USDC's 6 decimal places. The application displays only 2 decimal places, so this level of precision is sufficient.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#404
File: src/context/tokenSelector.context.tsx:121-121
Timestamp: 2024-10-03T09:57:43.885Z
Learning: In `TokenContextProvider` within `tokenSelector.context.tsx`, when token data is loaded from preferences, it's acceptable to set `isTokenPriceFetchingComplete` to `true` because the token data is already available.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#495
File: src/components/Cashout/Components/Initial.view.tsx:194-198
Timestamp: 2024-10-29T14:44:08.745Z
Learning: Using a fixed 6 decimal places for `floorFixed` is acceptable for token amounts in this codebase, even if tokens have varying decimal places.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#424
File: src/components/Global/TokenSelector/TokenSelector.tsx:197-211
Timestamp: 2024-10-11T01:14:15.489Z
Learning: In `src/components/Global/TokenSelector/TokenSelector.tsx`, when the calculation within functions like `byChainAndText` is not computationally expensive, it's acceptable to avoid using `useCallback` for memoization.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#443
File: src/components/Request/Pay/Views/Initial.view.tsx:293-297
Timestamp: 2024-10-16T11:37:07.647Z
Learning: Routes obtained from `createXChainUnsignedTx` are only valid for 20 seconds, so caching them for reuse is not effective.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.consts.ts:34-34
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In `src/components/Request/Pay` components, the `tokenPrice` property in the `IPayScreenProps` interface is only relevant to these views. Other components using `IPayScreenProps` do not need to handle `tokenPriceData` when it's updated in these components.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.consts.ts:34-34
Timestamp: 2024-10-07T15:50:29.173Z
Learning: In `src/components/Request/Pay` components, the `tokenPrice` property in the `IPayScreenProps` interface is only relevant to these views. Other components using `IPayScreenProps` do not need to handle `tokenPriceData` when it's updated in these components.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#478
File: src/components/Dashboard/useDashboard.tsx:134-134
Timestamp: 2024-10-24T12:36:40.508Z
Learning: In the file `src/components/Dashboard/useDashboard.tsx`, memoization of the `getTokenSymbol` function is not necessary because it is lightweight and does not involve complex computations or network calls.
src/components/Payment/Views/Confirm.payment.view.tsx (26)
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.consts.ts:34-34
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In `src/components/Request/Pay` components, the `tokenPrice` property in the `IPayScreenProps` interface is only relevant to these views. Other components using `IPayScreenProps` do not need to handle `tokenPriceData` when it's updated in these components.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.consts.ts:34-34
Timestamp: 2024-10-07T15:50:29.173Z
Learning: In `src/components/Request/Pay` components, the `tokenPrice` property in the `IPayScreenProps` interface is only relevant to these views. Other components using `IPayScreenProps` do not need to handle `tokenPriceData` when it's updated in these components.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:28:25.280Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(estimatedGasCost, 3)` return strings, ensuring consistent return types for `calculatedFee`.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:25:45.170Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(...)` return strings, ensuring that `calculatedFee` consistently returns a string without the need for additional type conversion.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#413
File: src/components/Request/Pay/Views/Initial.view.tsx:71-72
Timestamp: 2024-10-04T13:10:49.199Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, it's acceptable to use the `!` operator in TypeScript to assert that `selectedTokenData` is not `null` or `undefined`, and potential runtime errors from accessing its properties without checks can be disregarded.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#413
File: src/components/Request/Pay/Views/Initial.view.tsx:71-72
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, it's acceptable to use the `!` operator in TypeScript to assert that `selectedTokenData` is not `null` or `undefined`, and potential runtime errors from accessing its properties without checks can be disregarded.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#564
File: src/components/Request/Pay/Views/Initial.view.tsx:430-430
Timestamp: 2024-12-11T10:13:22.806Z
Learning: In the React TypeScript file `src/components/Request/Pay/Views/Initial.view.tsx`, when reviewing the `InitialView` component, do not flag potential issues with using non-null assertion `!` on the `slippagePercentage` variable, as handling undefined values in this context is considered out of scope.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#458
File: src/components/Offramp/Confirm.view.tsx:141-141
Timestamp: 2024-10-18T01:51:35.247Z
Learning: The `handleConfirm` function in `src/components/Create/Link/Confirm.view.tsx` is separate from the one in `src/components/Offramp/Confirm.view.tsx` and does not need to be renamed when refactoring `handleConfirm` in `src/components/Offramp/Confirm.view.tsx`.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#458
File: src/components/Offramp/Confirm.view.tsx:96-96
Timestamp: 2024-10-18T08:54:22.142Z
Learning: In the `src/components/Offramp/Confirm.view.tsx` file, it's acceptable to include crass or informal language in code comments.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#469
File: src/app/request/pay/page.tsx:32-64
Timestamp: 2024-10-23T09:38:04.446Z
Learning: Within `src/app/request/pay/page.tsx`, extracting the `getBaseUrl` function does not add significant readability, and the host URL construction code is expected to change soon.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#535
File: src/components/Claim/Claim.tsx:142-146
Timestamp: 2024-11-18T21:36:11.486Z
Learning: In `src/components/Claim/Claim.tsx`, external calls like token price fetching and cross-chain details retrieval are already encapsulated within existing `try...catch` blocks, so additional error handling may be unnecessary.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:103-111
Timestamp: 2024-10-07T13:42:00.443Z
Learning: When the token price cannot be fetched in `src/components/Request/Pay/Pay.tsx` within the `PayRequestLink` component, set `tokenPriceData.price` to 0 to ensure the UI remains functional. Since Squid uses their own price engine for x-chain fulfillment transactions, this approach will not affect the transaction computation.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:103-111
Timestamp: 2024-10-08T20:13:42.967Z
Learning: When the token price cannot be fetched in `src/components/Request/Pay/Pay.tsx` within the `PayRequestLink` component, set `tokenPriceData.price` to 0 to ensure the UI remains functional. Since Squid uses their own price engine for x-chain fulfillment transactions, this approach will not affect the transaction computation.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:113-123
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In the `PayRequestLink` component (`src/components/Request/Pay/Pay.tsx`), when resolving ENS names, handle errors by displaying an appropriate error message to the user if the ENS cannot be resolved.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#469
File: src/app/request/pay/page.tsx:25-25
Timestamp: 2024-10-22T18:10:56.955Z
Learning: In the `src/app/request/pay/page.tsx` file, the `PreviewType` enum values are strings, so when adding `previewType` to `URLSearchParams`, there's no need to convert them to strings.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#469
File: src/app/request/pay/page.tsx:32-64
Timestamp: 2024-10-23T09:38:27.670Z
Learning: In `src/app/request/pay/page.tsx`, if `linkRes` is not OK in the `generateMetadata` function, the desired behavior is to use the standard title and preview image without throwing an error.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#469
File: src/app/request/pay/page.tsx:32-49
Timestamp: 2024-10-22T18:11:36.864Z
Learning: In `src/app/request/pay/page.tsx`, the `id` parameter is accessed via `searchParams.id` in the `generateMetadata` function.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:113-123
Timestamp: 2024-10-07T13:42:07.299Z
Learning: In the `PayRequestLink` component (`src/components/Request/Pay/Pay.tsx`), when resolving ENS names, handle errors by displaying an appropriate error message to the user if the ENS cannot be resolved.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#404
File: src/context/tokenSelector.context.tsx:121-121
Timestamp: 2024-10-03T09:57:43.885Z
Learning: In `TokenContextProvider` within `tokenSelector.context.tsx`, when token data is loaded from preferences, it's acceptable to set `isTokenPriceFetchingComplete` to `true` because the token data is already available.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#413
File: src/context/tokenSelector.context.tsx:118-123
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In the `TokenContextProvider` component within `src/context/tokenSelector.context.tsx`, in the TypeScript React application, when data changes and before calling `fetchAndSetTokenPrice`, it is necessary to reset `selectedTokenData`, `selectedTokenPrice`, `selectedTokenDecimals`, and `inputDenomination` to discard stale data.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#631
File: src/components/Create/Create.tsx:108-112
Timestamp: 2025-01-16T13:14:40.363Z
Learning: In the Peanut UI codebase, the `resetTokenContextProvider` function from `tokenSelectorContext` is a stable function reference that doesn't change, so it doesn't need to be included in useEffect dependencies.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#424
File: src/components/Global/TokenSelector/TokenSelector.tsx:197-211
Timestamp: 2024-10-11T01:14:15.489Z
Learning: In `src/components/Global/TokenSelector/TokenSelector.tsx`, when the calculation within functions like `byChainAndText` is not computationally expensive, it's acceptable to avoid using `useCallback` for memoization.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#478
File: src/components/Request/Create/Views/Initial.view.tsx:48-128
Timestamp: 2024-10-24T12:40:15.006Z
Learning: When `handleOnNext` is deliberately refactored to avoid dependencies that change, it's acceptable to have an empty dependency array in `useCallback`.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#420
File: src/components/Offramp/Offramp.consts.ts:27-28
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In `src/components/Offramp/Offramp.consts.ts`, the `MIN_CASHOUT_LIMIT` is set to $10 because smaller amounts are impractical due to approximately $1 fee per cashout.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#919
File: src/components/Withdraw/views/Initial.withdraw.view.tsx:87-87
Timestamp: 2025-06-18T19:56:55.443Z
Learning: In withdraw flows for Peanut Wallet, the PeanutActionDetailsCard should always display "USDC" as the token symbol because it shows the amount being withdrawn from the Peanut Wallet (which holds USDC), regardless of the destination token/chain selected by the user. The TokenSelector is used for choosing the withdrawal destination, not the source display.
src/services/swap.ts (17)
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#535
File: src/components/Claim/Claim.tsx:142-146
Timestamp: 2024-11-18T21:36:11.486Z
Learning: In `src/components/Claim/Claim.tsx`, external calls like token price fetching and cross-chain details retrieval are already encapsulated within existing `try...catch` blocks, so additional error handling may be unnecessary.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:103-111
Timestamp: 2024-10-08T20:13:42.967Z
Learning: When the token price cannot be fetched in `src/components/Request/Pay/Pay.tsx` within the `PayRequestLink` component, set `tokenPriceData.price` to 0 to ensure the UI remains functional. Since Squid uses their own price engine for x-chain fulfillment transactions, this approach will not affect the transaction computation.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:103-111
Timestamp: 2024-10-07T13:42:00.443Z
Learning: When the token price cannot be fetched in `src/components/Request/Pay/Pay.tsx` within the `PayRequestLink` component, set `tokenPriceData.price` to 0 to ensure the UI remains functional. Since Squid uses their own price engine for x-chain fulfillment transactions, this approach will not affect the transaction computation.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:28:25.280Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(estimatedGasCost, 3)` return strings, ensuring consistent return types for `calculatedFee`.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:25:45.170Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(...)` return strings, ensuring that `calculatedFee` consistently returns a string without the need for additional type conversion.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#847
File: src/app/actions/clients.ts:48-68
Timestamp: 2025-05-13T16:26:58.336Z
Learning: In viem v2.21.48, the `stateOverride` parameter for `estimateGas` and related functions expects an array-based format: `[{ address: tokenAddress, stateDiff: [{ slot: calculatedSlot, value: hexValue }] }]` rather than an object-based format.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#413
File: src/context/tokenSelector.context.tsx:118-123
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In the `TokenContextProvider` component within `src/context/tokenSelector.context.tsx`, in the TypeScript React application, when data changes and before calling `fetchAndSetTokenPrice`, it is necessary to reset `selectedTokenData`, `selectedTokenPrice`, `selectedTokenDecimals`, and `inputDenomination` to discard stale data.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.consts.ts:34-34
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In `src/components/Request/Pay` components, the `tokenPrice` property in the `IPayScreenProps` interface is only relevant to these views. Other components using `IPayScreenProps` do not need to handle `tokenPriceData` when it's updated in these components.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.consts.ts:34-34
Timestamp: 2024-10-07T15:50:29.173Z
Learning: In `src/components/Request/Pay` components, the `tokenPrice` property in the `IPayScreenProps` interface is only relevant to these views. Other components using `IPayScreenProps` do not need to handle `tokenPriceData` when it's updated in these components.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#431
File: src/components/Create/Link/Success.view.tsx:89-89
Timestamp: 2024-10-08T20:28:39.527Z
Learning: The remaining uses of `shortenAddressLong` are for transaction hashes and do not need to be replaced.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/context/walletContext/walletContext.tsx:87-88
Timestamp: 2024-12-02T17:21:45.515Z
Learning: When converting `totalBalance` (in USD) to a `BigInt` balance in `src/context/walletContext/walletContext.tsx`, multiplying by `1e6` is intentional to maintain compatibility with USDC's 6 decimal places. The application displays only 2 decimal places, so this level of precision is sufficient.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#404
File: src/context/tokenSelector.context.tsx:121-121
Timestamp: 2024-10-03T09:57:43.885Z
Learning: In `TokenContextProvider` within `tokenSelector.context.tsx`, when token data is loaded from preferences, it's acceptable to set `isTokenPriceFetchingComplete` to `true` because the token data is already available.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#424
File: src/components/Global/TokenSelector/TokenSelector.tsx:197-211
Timestamp: 2024-10-11T01:14:15.489Z
Learning: In `src/components/Global/TokenSelector/TokenSelector.tsx`, when the calculation within functions like `byChainAndText` is not computationally expensive, it's acceptable to avoid using `useCallback` for memoization.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#478
File: src/components/Request/Create/Views/Initial.view.tsx:81-89
Timestamp: 2024-10-24T12:38:32.793Z
Learning: In `src/components/Request/Create/Views/Initial.view.tsx`, the function `getTokenDetails` is a simple function that does not fetch from the network or perform asynchronous operations.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#868
File: src/components/Payment/PaymentForm/index.tsx:284-293
Timestamp: 2025-05-19T19:40:43.138Z
Learning: When converting between USD and token amounts, always check if the token price (divisor) is valid and non-zero before performing the division to prevent Infinity, NaN, or errors. Implementing validation like `if (!tokenPrice || isNaN(tokenPrice) || tokenPrice === 0)` before division operations is crucial for handling cases where price data might be unavailable.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#443
File: src/components/Request/Pay/Views/Initial.view.tsx:293-297
Timestamp: 2024-10-16T11:37:07.647Z
Learning: Routes obtained from `createXChainUnsignedTx` are only valid for 20 seconds, so caching them for reuse is not effective.
src/hooks/usePaymentInitiator.ts (29)
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:28:25.280Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(estimatedGasCost, 3)` return strings, ensuring consistent return types for `calculatedFee`.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:25:45.170Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(...)` return strings, ensuring that `calculatedFee` consistently returns a string without the need for additional type conversion.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#495
File: src/components/Create/useCreateLink.tsx:647-657
Timestamp: 2024-10-29T16:06:38.812Z
Learning: In the React code for `useCreateLink` in `src/components/Create/useCreateLink.tsx`, the `switchNetwork` function used within `useCallback` hooks is stable and does not need to be included in the dependency arrays.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:103-111
Timestamp: 2024-10-08T20:13:42.967Z
Learning: When the token price cannot be fetched in `src/components/Request/Pay/Pay.tsx` within the `PayRequestLink` component, set `tokenPriceData.price` to 0 to ensure the UI remains functional. Since Squid uses their own price engine for x-chain fulfillment transactions, this approach will not affect the transaction computation.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:103-111
Timestamp: 2024-10-07T13:42:00.443Z
Learning: When the token price cannot be fetched in `src/components/Request/Pay/Pay.tsx` within the `PayRequestLink` component, set `tokenPriceData.price` to 0 to ensure the UI remains functional. Since Squid uses their own price engine for x-chain fulfillment transactions, this approach will not affect the transaction computation.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#564
File: src/components/Request/Pay/Views/Initial.view.tsx:430-430
Timestamp: 2024-12-11T10:13:22.806Z
Learning: In the React TypeScript file `src/components/Request/Pay/Views/Initial.view.tsx`, when reviewing the `InitialView` component, do not flag potential issues with using non-null assertion `!` on the `slippagePercentage` variable, as handling undefined values in this context is considered out of scope.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#535
File: src/components/Claim/Claim.tsx:142-146
Timestamp: 2024-11-18T21:36:11.486Z
Learning: In `src/components/Claim/Claim.tsx`, external calls like token price fetching and cross-chain details retrieval are already encapsulated within existing `try...catch` blocks, so additional error handling may be unnecessary.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.consts.ts:34-34
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In `src/components/Request/Pay` components, the `tokenPrice` property in the `IPayScreenProps` interface is only relevant to these views. Other components using `IPayScreenProps` do not need to handle `tokenPriceData` when it's updated in these components.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.consts.ts:34-34
Timestamp: 2024-10-07T15:50:29.173Z
Learning: In `src/components/Request/Pay` components, the `tokenPrice` property in the `IPayScreenProps` interface is only relevant to these views. Other components using `IPayScreenProps` do not need to handle `tokenPriceData` when it's updated in these components.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#413
File: src/components/Request/Pay/Views/Initial.view.tsx:71-72
Timestamp: 2024-10-04T13:10:49.199Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, it's acceptable to use the `!` operator in TypeScript to assert that `selectedTokenData` is not `null` or `undefined`, and potential runtime errors from accessing its properties without checks can be disregarded.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#413
File: src/components/Request/Pay/Views/Initial.view.tsx:71-72
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, it's acceptable to use the `!` operator in TypeScript to assert that `selectedTokenData` is not `null` or `undefined`, and potential runtime errors from accessing its properties without checks can be disregarded.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#868
File: src/components/Payment/PaymentForm/index.tsx:284-293
Timestamp: 2025-05-19T19:40:43.138Z
Learning: When converting between USD and token amounts, always check if the token price (divisor) is valid and non-zero before performing the division to prevent Infinity, NaN, or errors. Implementing validation like `if (!tokenPrice || isNaN(tokenPrice) || tokenPrice === 0)` before division operations is crucial for handling cases where price data might be unavailable.
Learnt from: kushagrasarathe
PR: peanutprotocol/peanut-ui#869
File: src/app/(mobile-ui)/withdraw/page.tsx:82-88
Timestamp: 2025-05-22T15:38:48.586Z
Learning: The country-specific withdrawal route exists at src/app/(mobile-ui)/withdraw/[...country]/page.tsx and renders the AddWithdrawCountriesList component with flow="withdraw".
Learnt from: kushagrasarathe
PR: peanutprotocol/peanut-ui#869
File: src/app/(mobile-ui)/withdraw/page.tsx:82-88
Timestamp: 2025-05-22T15:38:48.586Z
Learning: The country-specific withdrawal route exists at src/app/(mobile-ui)/withdraw/[...country]/page.tsx and renders the AddWithdrawCountriesList component with flow="withdraw".
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#919
File: src/components/Withdraw/views/Initial.withdraw.view.tsx:87-87
Timestamp: 2025-06-18T19:56:55.443Z
Learning: In withdraw flows for Peanut Wallet, the PeanutActionDetailsCard should always display "USDC" as the token symbol because it shows the amount being withdrawn from the Peanut Wallet (which holds USDC), regardless of the destination token/chain selected by the user. The TokenSelector is used for choosing the withdrawal destination, not the source display.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#431
File: src/components/Create/Link/Success.view.tsx:89-89
Timestamp: 2024-10-08T20:28:39.527Z
Learning: The remaining uses of `shortenAddressLong` are for transaction hashes and do not need to be replaced.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#478
File: src/components/Request/Create/Views/Initial.view.tsx:93-94
Timestamp: 2024-10-24T12:39:09.318Z
Learning: In `src/components/Request/Create/Views/Initial.view.tsx`, the `inputValue` variable passed to `peanut.createRequestLink` is expected to be a string.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#827
File: src/components/Claim/Link/Initial.view.tsx:120-126
Timestamp: 2025-04-30T21:31:27.790Z
Learning: The `sendLinksApi.claim` function in the Peanut Protocol UI accepts both username and wallet address as the first parameter.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#420
File: src/components/Offramp/Offramp.consts.ts:27-28
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In `src/components/Offramp/Offramp.consts.ts`, the `MIN_CASHOUT_LIMIT` is set to $10 because smaller amounts are impractical due to approximately $1 fee per cashout.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#631
File: src/components/Create/Create.tsx:108-112
Timestamp: 2025-01-16T13:14:40.363Z
Learning: In the Peanut UI codebase, the `resetTokenContextProvider` function from `tokenSelectorContext` is a stable function reference that doesn't change, so it doesn't need to be included in useEffect dependencies.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#413
File: src/context/tokenSelector.context.tsx:118-123
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In the `TokenContextProvider` component within `src/context/tokenSelector.context.tsx`, in the TypeScript React application, when data changes and before calling `fetchAndSetTokenPrice`, it is necessary to reset `selectedTokenData`, `selectedTokenPrice`, `selectedTokenDecimals`, and `inputDenomination` to discard stale data.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#404
File: src/context/tokenSelector.context.tsx:121-121
Timestamp: 2024-10-03T09:57:43.885Z
Learning: In `TokenContextProvider` within `tokenSelector.context.tsx`, when token data is loaded from preferences, it's acceptable to set `isTokenPriceFetchingComplete` to `true` because the token data is already available.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:113-123
Timestamp: 2024-10-07T13:42:07.299Z
Learning: In the `PayRequestLink` component (`src/components/Request/Pay/Pay.tsx`), when resolving ENS names, handle errors by displaying an appropriate error message to the user if the ENS cannot be resolved.
Learnt from: Hugo0
PR: peanutprotocol/peanut-ui#422
File: src/components/Request/Pay/Pay.tsx:113-123
Timestamp: 2024-10-08T20:13:42.967Z
Learning: In the `PayRequestLink` component (`src/components/Request/Pay/Pay.tsx`), when resolving ENS names, handle errors by displaying an appropriate error message to the user if the ENS cannot be resolved.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#424
File: src/components/Global/TokenSelector/TokenSelector.tsx:197-211
Timestamp: 2024-10-11T01:14:15.489Z
Learning: In `src/components/Global/TokenSelector/TokenSelector.tsx`, when the calculation within functions like `byChainAndText` is not computationally expensive, it's acceptable to avoid using `useCallback` for memoization.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#484
File: src/components/Cashout/Components/Initial.view.tsx:273-274
Timestamp: 2024-10-25T11:33:46.776Z
Learning: In the `InitialCashoutView` component (`src/components/Cashout/Components/Initial.view.tsx`), linked bank accounts should not generate error states, and the `ValidatedInput` component will clear any error messages if needed. Therefore, it's unnecessary to manually clear the error state when selecting or clearing linked bank accounts.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#443
File: src/components/Request/Pay/Views/Initial.view.tsx:293-297
Timestamp: 2024-10-16T11:37:07.647Z
Learning: Routes obtained from `createXChainUnsignedTx` are only valid for 20 seconds, so caching them for reuse is not effective.
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#830
File: src/components/Global/ListItemView/index.tsx:186-191
Timestamp: 2025-05-05T20:43:40.198Z
Learning: In the Peanut UI codebase, chainId is stored as a numeric or hex ID in the HistoryEntry object, not as a human-readable name string. When using it with explorer links, it should be passed directly to getExplorerUrl() as a number, rather than comparing it against chain.name in the supportedPeanutChains array.
🧬 Code Graph Analysis (1)
src/app/actions/tokens.ts (4)
src/utils/general.utils.ts (2)
isStableCoin
(1108-1110)estimateIfIsStableCoinFromPrice
(748-755)src/utils/__mocks__/next-cache.ts (1)
unstable_cache
(1-1)src/app/actions/clients.ts (2)
getPublicClient
(20-29)ChainId
(11-11)src/utils/token.utils.ts (1)
NATIVE_TOKEN_ADDRESS
(27-27)
🔇 Additional comments (27)
src/app/actions/tokens.ts (2)
7-9
: LGTM!The new imports are correctly structured and will support the enhanced token price checking and gas estimation functionality.
90-90
: Enhanced stablecoin detection is a good improvement.The dual approach using both symbol-based checking and price-based estimation provides better coverage for stablecoin identification.
src/components/Payment/Views/Confirm.payment.view.tsx (7)
41-41
: LGTM!The new
isDirectPay
prop correctly supports conditional transaction preparation for direct USD payments.
75-83
: Well-implemented fee display logic.The
networkFee
memo correctly handles different wallet types, error states, and formatting edge cases for small amounts.
140-146
: Good conditional transaction preparation logic.The direct pay flow correctly passes the currency amount when paying in USD, which aligns with the intended functionality.
159-163
: Excellent route refresh handling.The callback properly refreshes transaction details on route expiry, ensuring users get updated routing information.
312-321
: Strong route type validation for Peanut Wallet.The logic correctly prevents unsupported swap routes for Peanut Wallet users, enforcing the RFQ-only requirement.
353-362
: Excellent route expiry timer integration.The timer implementation with callbacks for near expiry and expiry events provides a great user experience for time-sensitive cross-chain routes.
366-372
: Good addition of minimum received information.The conditional display of minimum received amount helps users understand potential slippage in cross-chain transactions.
src/services/swap.ts (10)
3-8
: LGTM!The new imports properly support ERC-20 approval handling and enhanced transaction cost estimation.
177-193
: Well-implemented allowance checking.The function correctly uses the ERC-20 standard allowance function and provides a clean interface for checking current approvals.
198-214
: Good approval transaction creation.The function properly encodes the ERC-20 approve function call with correct parameters and return structure.
219-237
: Solid approval cost estimation.The function leverages the existing transaction cost estimation infrastructure to provide accurate gas cost estimates for approval transactions.
274-283
: Excellent concurrent price fetching optimization.The parallel fetching of token prices significantly improves performance compared to sequential API calls.
290-309
: Enhanced granularity for small amounts is well-designed.The refined tolerances and range multipliers for small USD amounts (< 0.3 and < 1) provide better handling of micro-transactions and testing scenarios.
412-413
: Verify number formatting to prevent scientific notation issues.Based on the PR objectives, there's a known issue with scientific notation numbers not being accepted by
parseUnits
. The division here could produce scientific notation for very small amounts.Add validation to ensure the number is in proper decimal format:
- const tokenAmount = Number(amount.fromUsd) / fromTokenPrice.price - fromAmount = parseUnits(tokenAmount.toFixed(fromTokenPrice.decimals), fromTokenPrice.decimals).toString() + const tokenAmount = Number(amount.fromUsd) / fromTokenPrice.price + const tokenAmountString = tokenAmount.toFixed(fromTokenPrice.decimals) + // Ensure no scientific notation + if (tokenAmountString.includes('e') || tokenAmountString.includes('E')) { + throw new Error(`Token amount calculation resulted in scientific notation: ${tokenAmountString}`) + } + fromAmount = parseUnits(tokenAmountString, fromTokenPrice.decimals).toString()
482-524
: Comprehensive approval handling implementation.The approval logic is well-structured with proper error handling:
- Smart allowance checking: Only creates approval transactions when needed
- Graceful error handling: Continues with swap if allowance check fails
- Cost integration: Properly adds approval costs to total fees
- Transaction ordering: Correctly places approval before the main swap
This implementation significantly enhances the cross-chain swap experience.
527-537
: Good transaction structure standardization.The consistent transaction format with fee options provides a clean interface for transaction execution across different transaction types.
548-550
: Helpful debugging information.The detailed logging provides valuable insights for troubleshooting route creation and expiry handling.
src/hooks/usePaymentInitiator.ts (8)
26-36
: LGTM! Import updates align with the refactoring.The import changes properly support the transition from internal fee calculation to the external routing service approach.
95-95
: LGTM! State addition supports new routing approach.Adding
xChainRoute
state properly supports the new cross-chain routing functionality.
172-180
: LGTM! Function signature enhancement with good defaults.The optional parameters with sensible defaults maintain backward compatibility while enabling more flexible usage.
207-231
: LGTM! Cross-chain preparation refactoring is well-structured.The refactoring to use
getRoute
service properly centralizes cross-chain logic and handles both USD amount and token amount scenarios appropriately.
265-274
: LGTM! Gas estimation refactoring is appropriate.The transition to using
estimateTransactionCostUsd
centralizes gas estimation logic and properly handles the async calculation.
458-515
: LGTM! Peanut Wallet payment handling properly updated.The removal of the payload parameter and use of prepared transactions from state aligns well with the new transaction preparation approach. The hardcoded constants for Peanut Wallet are appropriate for this specific payment flow.
690-690
: LGTM! Function call updated correctly.The removal of the payload parameter aligns with the updated function signature.
749-757
: LGTM! Return object properly reflects state changes.The replacement of
feeCalculations
withestimatedGasCost
and addition ofxChainRoute
correctly exposes the new state structure to consumers.
// Run all API calls in parallel since they're independent | ||
const [gasEstimate, gasPrice, nativeTokenPrice] = await Promise.all([ | ||
getCachedGasEstimate(fromAddress, contractAddress, data, chainId), | ||
getCachedGasPrice(chainId), | ||
fetchTokenPrice(NATIVE_TOKEN_ADDRESS, chainId), | ||
]) | ||
|
||
// Calculate gas cost in native token | ||
const gasCostWei = gasEstimate * gasPrice | ||
|
||
const estimatedCostUsd = nativeTokenPrice | ||
? Number(formatUnits(gasCostWei, nativeTokenPrice.decimals)) * nativeTokenPrice.price | ||
: 0.01 | ||
|
||
return estimatedCostUsd | ||
} catch (error) { | ||
console.error('Error estimating transaction cost:', error) | ||
// Return a conservative estimate if we can't calculate exact cost | ||
return 0.01 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yay
also, its insane to me that 1 cents is a conservative cost estimate. thats insane. we've come so far in crypto
Use coral through squid to get the cross-chain route for the different
flows. This enables xchain withdraw for peanut wallet
contributes to TASK-11580