Skip to content

Conversation

@gomesalexandre
Copy link
Contributor

@gomesalexandre gomesalexandre commented Nov 14, 2025

Description

Does what it says on the box - adds proper error handling for unsupported pairs.

Issue (if applicable)

closes #11071

Risk

High Risk PRs Require 2 approvals

What protocols, transaction types, wallets or contract interactions might be affected by this PR?

Testing

Engineering

  • Still able to get rates for supported NEAR Intents tokens (see https://1click.chaindefuser.com/v0/tokens)
  • Unsupported tokens (see support tokens here) now are properly handled with "Unsupported Trade Pair" on both buy/sell side

Operations

  • 🏁 My feature is behind a flag and doesn't require operations testing (yet)

Screenshots (if applicable)

https://jam.dev/c/3051fdeb-143e-4354-8ab8-af7118cc3a0f

Summary by CodeRabbit

  • Bug Fixes
    • Added early validation of asset pairs to detect unsupported combinations before processing swap requests
    • Improved error messages when assets cannot be resolved, providing clearer feedback to users
    • Enhanced error handling in swap operations with more specific identification of invalid asset configurations
    • Strengthened input validation across trade rate and quote request flows

@gomesalexandre gomesalexandre requested a review from a team as a code owner November 14, 2025 15:34
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 14, 2025

📝 Walkthrough

Walkthrough

Modified NEAR Intents swapper to improve error handling for unsupported asset pairs. Changes include early validation of asset resolution, catching and mapping specific API errors to UnsupportedTradePair errors, updating the assetToNearIntentsAsset helper to return null instead of throwing, and exporting ApiError for use across the module.

Changes

Cohort / File(s) Summary
Error handling and validation
packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts, packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
Added ApiError import and enhanced error handling to catch ApiError exceptions with messages 'tokenIn is not valid' or 'tokenOut is not valid', mapping them to UnsupportedTradePair errors. Introduced early validation to return UnsupportedTradePair if originAsset or destinationAsset cannot be resolved.
Module exports
packages/swapper/src/swappers/NearIntentsSwapper/utils/oneClickService.ts
Added ApiError to module exports alongside OneClickService.
Helper function signature
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
Updated assetToNearIntentsAsset return type from Promise<string> to `Promise<string

Sequence Diagram

sequenceDiagram
    participant Caller
    participant getTradeRate as getTradeRate/Quote
    participant assetToNearIntents as assetToNearIntentsAsset
    participant oneClickSDK as One-Click SDK
    
    Caller->>getTradeRate: request with assets
    getTradeRate->>assetToNearIntents: resolve originAsset
    alt asset resolved
        assetToNearIntents-->>getTradeRate: NEAR Intents asset (string)
    else asset not found
        assetToNearIntents-->>getTradeRate: null
        getTradeRate-->>Caller: UnsupportedTradePair ✗
    end
    
    getTradeRate->>assetToNearIntents: resolve destinationAsset
    alt asset resolved
        assetToNearIntents-->>getTradeRate: NEAR Intents asset (string)
    else asset not found
        assetToNearIntents-->>getTradeRate: null
        getTradeRate-->>Caller: UnsupportedTradePair ✗
    end
    
    getTradeRate->>oneClickSDK: request quote/rate
    alt success
        oneClickSDK-->>getTradeRate: result ✓
        getTradeRate-->>Caller: trade data
    else ApiError (invalid tokens)
        oneClickSDK-->>getTradeRate: ApiError
        getTradeRate-->>Caller: UnsupportedTradePair ✗
    else other error
        oneClickSDK-->>getTradeRate: error
        getTradeRate-->>Caller: QueryFailed ✗
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • File helpers.ts: Review the impact of changing return type to Promise<string | null> and verify all callers properly handle null results
  • Files getTradeRate.ts and getTradeQuote.ts: Verify error mapping logic correctly distinguishes between invalid token pairs (mapped to UnsupportedTradePair) and other API errors (mapped to QueryFailed)
  • Cross-file integration: Ensure the new early validation flow and null-handling work cohesively across the error handling layers

Possibly related PRs

  • PR #11016: Directly modifies the same oneClickService and error handling in getTradeRate/getTradeQuote, introducing ApiError export and mapping specific API error messages to UnsupportedTradePair
  • PR #11043: Modifies asset resolution logic in assetToNearIntentsAsset helper and how unsupported NEAR asset mappings are handled, directly related to the null-return and early validation introduced here

Suggested reviewers

  • premiumjibles
  • 0xApotheosis

Poem

🐰 A swapper most NEAR brought errors so dear,
Now ApiErrors map with precision and cheer,
When assets unsupported dare show their face,
Null returns flow gracefully through every place! 🌟

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding error handling for unsupported trade pairs in NEAR Intents, which is the core focus of all file modifications.
Linked Issues check ✅ Passed The PR successfully addresses both failure scenarios from issue #11071: token validation errors via early null checks and API quote errors via ApiError mapping, both returning UnsupportedTradePair errors consistent with expected behavior.
Out of Scope Changes check ✅ Passed All changes directly support the PR objectives: ApiError export addition, early validation checks, and error mapping are all focused on handling unsupported trade pairs with no unrelated modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat_near_better_error_handling

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (1)
packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts (1)

72-83: Early null guard cleanly surfaces unsupported NEAR Intents pairs

The originAsset/destinationAsset null check is a good defensive layer and correctly maps unsupported assets to TradeQuoteError.UnsupportedTradePair, preventing unnecessary quote calls and aligning with the PR’s goal of clearer unsupported‑pair messaging. If you want to exactly mirror the UI copy (“Unsupported Trade Pair”), consider updating the message string here, but that’s optional.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c808de6 and 43ba8f5.

📒 Files selected for processing (3)
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts (3 hunks)
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts (3 hunks)
  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:21-24
Timestamp: 2025-09-12T13:16:27.004Z
Learning: gomesalexandre declined to add error boundaries to WalletConnect modals in PR #10461, stating "no error boundaries in this pr ser", consistent with his preference to keep PR scope focused and defer tangential improvements to separate efforts.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/content/TransactionContent.tsx:40-140
Timestamp: 2025-09-12T12:04:24.562Z
Learning: gomesalexandre prefers to defer error handling improvements in new/preparatory code until real-world error cases are encountered, rather than implementing speculative error handling without concrete failure scenarios to test against. This aligns with keeping PR scope focused and evidence-based development practices.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/utils/tenderly/index.ts:0-0
Timestamp: 2025-09-12T11:56:19.437Z
Learning: gomesalexandre rejected verbose try/catch error handling for address validation in Tenderly integration (PR #10461), calling the approach "ugly" but still implemented safety measures in commit ad7e424b89, preferring cleaner safety implementations over defensive programming patterns.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10596
File: src/components/Layout/Header/NavBar/WalletConnectedMenu.tsx:77-99
Timestamp: 2025-10-01T07:42:40.195Z
Learning: In WalletConnectedMenu.tsx's handleReconnectWallet handler, gomesalexandre prefers throwing an error for unsupported wallet types in the default case rather than gracefully handling with a fallback. His reasoning: "if we have a problem here, we have bigger problems" - only supported wallets (KeepKey, Ledger, MetaMask, Coinbase, Phantom) should reach the reconnect flow when disconnected/locked, so encountering an unsupported type indicates a larger architectural issue that should be surfaced explicitly rather than masked with graceful degradation.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10569
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/WalletConnectModalSigningFooter.tsx:121-129
Timestamp: 2025-09-17T22:40:30.149Z
Learning: gomesalexandre maintains strict scope discipline even for style/UI PRs in shapeshift/web, declining functionally correct UX improvements (like keeping Cancel button enabled during gas simulation loading) when they fall outside the PR's stated styling objectives, demonstrating his consistent pattern of deferring valid but tangential improvements to separate efforts.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.
📚 Learning: 2025-08-26T19:04:38.672Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10369
File: packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts:167-176
Timestamp: 2025-08-26T19:04:38.672Z
Learning: In packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts, when processing assets from data.assets.reduce(), the team prefers using empty catch blocks to gracefully skip any assets that fail processing, rather than specific error type handling, to avoid useless noise and ensure robust asset filtering.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-09-04T13:22:35.399Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/state/slices/assetsSlice/selectors.ts:45-51
Timestamp: 2025-09-04T13:22:35.399Z
Learning: In shapeshift/web, the isPrimaryAsset function in src/lib/utils/asset.ts is intentionally designed to only treat null relatedAssetKey as primary (not undefined). The asset generation process specifically sets relatedAssetKey to null for primary assets, while undefined means the asset doesn't participate in grouping and should not be considered primary. Only assets with null relatedAssetKey or where relatedAssetKey === assetId are primary assets.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-11-12T12:18:00.863Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-08-11T09:45:51.174Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10219
File: src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx:175-180
Timestamp: 2025-08-11T09:45:51.174Z
Learning: gomesalexandre prefers truthy checks over explicit boolean comparisons (e.g., `walletSupportsSellAssetChain` instead of `walletSupportsSellAssetChain === true`) when dealing with tri-state values (boolean | null) in TypeScript, as the falsy behavior for null/undefined is intentional and acceptable.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-08-08T15:00:49.887Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/components/AssetSearch/components/AssetList.tsx:2-2
Timestamp: 2025-08-08T15:00:49.887Z
Learning: Project shapeshift/web: NeOMakinG prefers avoiding minor a11y/UI nitpicks (e.g., adding aria-hidden to decorative icons in empty states like src/components/AssetSearch/components/AssetList.tsx) within feature PRs; defer such suggestions to a follow-up instead of blocking the PR.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-08-17T21:53:03.806Z
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10290
File: scripts/generateAssetData/color-map.json:41-47
Timestamp: 2025-08-17T21:53:03.806Z
Learning: In the ShapeShift web codebase, native assets (using CAIP-19 slip44 namespace like eip155:1/slip44:60, bip122:.../slip44:..., cosmos:.../slip44:...) are manually hardcoded and not generated via the automated asset generation script. Only ERC20/BEP20 tokens go through the asset generation process. The validation scripts should only validate generated assets, not manually added native assets.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-11-12T12:49:17.895Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-125
Timestamp: 2025-11-12T12:49:17.895Z
Learning: In packages/chain-adapters/src/evm/utils.ts, the getErc20Data function already includes a guard that returns an empty string when contractAddress is undefined (line 8: `if (!contractAddress) return ''`). This built-in handling means callers don't need to conditionally invoke getErc20Data—it safely handles both ERC20 tokens and native assets.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-09-04T17:29:59.479Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx:28-33
Timestamp: 2025-09-04T17:29:59.479Z
Learning: In shapeshift/web, the useGetPopularAssetsQuery function in src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx intentionally uses primaryAssets[assetId] instead of falling back to assets[assetId]. The design distributes primary assets across chains by iterating through their related assets and adding the primary asset to each related asset's chain. This ensures primary assets appear in all chains where they have related assets, supporting the grouped asset system.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-10-23T14:27:19.073Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10857
File: src/plugins/walletConnectToDapps/eventsManager/useWalletConnectEventsHandler.ts:101-104
Timestamp: 2025-10-23T14:27:19.073Z
Learning: In WalletConnect wallet_switchEthereumChain and wallet_addEthereumChain requests, the chainId parameter is always present as per the protocol spec. Type guards checking for missing chainId in these handlers (like `if (!evmNetworkIdHex) return`) are solely for TypeScript compiler satisfaction, not real runtime edge cases.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-09-04T17:35:57.584Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/state/slices/common-selectors.ts:164-178
Timestamp: 2025-09-04T17:35:57.584Z
Learning: In shapeshift/web, while the Asset type allows relatedAssetKey to be AssetId | null | undefined, the actual asset generation and processing system ensures relatedAssetKey is never undefined in practice. All asset creation utilities explicitly set it to either a specific AssetId (for grouped assets) or null (for primary/unique assets). The only undefined assignments occur during intermediate processing phases and get resolved during the final asset generation step.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-09-04T17:35:57.584Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/state/slices/common-selectors.ts:164-178
Timestamp: 2025-09-04T17:35:57.584Z
Learning: In shapeshift/web, while the Asset type allows relatedAssetKey to be AssetId | null | undefined, the actual asset generation and processing system ensures relatedAssetKey is never undefined in practice. All asset creation utilities explicitly set it to either a specific AssetId (for grouped assets) or null (for primary/unique assets). The only exception is temporary undefined assignment during portal asset processing, which gets resolved later in the pipeline.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-11-03T22:31:30.786Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10985
File: packages/swapper/src/swappers/PortalsSwapper/getPortalsTradeQuote/getPortalsTradeQuote.ts:0-0
Timestamp: 2025-11-03T22:31:30.786Z
Learning: In packages/swapper/src/swappers/PortalsSwapper, the rate and quote files intentionally use different approaches for calculating buyAmountBeforeSlippageCryptoBaseUnit: getPortalsTradeRate.tsx uses minOutputAmount / (1 - buffer) for conservative estimates, while getPortalsTradeQuote.ts uses outputAmount / (1 - buffer) for final quote display. This difference is validated by on-chain simulation testing and is intentional.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-11-03T05:46:24.190Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10985
File: packages/swapper/src/swappers/PortalsSwapper/getPortalsTradeRate/getPortalsTradeRate.tsx:130-141
Timestamp: 2025-11-03T05:46:24.190Z
Learning: In packages/swapper/src/swappers/PortalsSwapper/getPortalsTradeRate/getPortalsTradeRate.tsx, gomesalexandre prefers "let it crash" approach when Portals returns zero outputAmount or 100% buffer causing division by zero, rather than adding defensive guards to surface zero quotes. He wants to fail fast with exceptions that bubble up to the try/catch wrapper, surfacing upstream data issues rather than masking them with defensive programming.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-11-12T13:01:06.086Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts:25-38
Timestamp: 2025-11-12T13:01:06.086Z
Learning: In the swapper architecture (packages/swapper), input validation for sell amounts (e.g., checking sellAmount > 0) is handled by the application layer before reaching individual swapper implementations. Swapper methods like getTradeRate and getTradeQuote can assume inputs have already been validated upstream, so defensive guards for basic input validation (amount > 0, valid addresses, etc.) are unnecessary at the swapper layer.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-07-31T03:51:48.479Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10154
File: src/state/apis/swapper/helpers/swapperApiHelpers.ts:57-60
Timestamp: 2025-07-31T03:51:48.479Z
Learning: In src/state/apis/swapper/helpers/swapperApiHelpers.ts, the getState parameter in processQuoteResultWithRatios uses `() => unknown` type instead of `() => ReduxState` to avoid type compatibility issues elsewhere in the codebase.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-08-11T09:46:41.060Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10219
File: src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx:167-172
Timestamp: 2025-08-11T09:46:41.060Z
Learning: In the shapeshift/web repository, the display cache logic for trade quotes (using `selectUserAvailableTradeQuotes` and `selectUserUnavailableTradeQuotes`) is intentionally kept the same between `TradeInput.tsx` and `TradeQuotes.tsx` components. The `hasQuotes` computation in `TradeInput.tsx` uses these display cache selectors by design, matching the pattern used in `TradeQuotes.tsx`.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-07-29T15:04:28.083Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10139
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx:109-115
Timestamp: 2025-07-29T15:04:28.083Z
Learning: In src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx, the component is used under an umbrella that 100% of the time contains the quote, making the type assertion `activeTradeQuote?.steps[currentHopIndex] as TradeQuoteStep` safe. Adding conditional returns before hooks would violate React's Rules of Hooks.

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
🧬 Code graph analysis (2)
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts (1)
packages/swapper/src/swappers/NearIntentsSwapper/types.ts (1)
  • chainIdToNearIntentsChain (25-37)
packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts (3)
packages/swapper/src/utils.ts (1)
  • makeSwapErrorRight (28-44)
src/state/apis/swapper/types.ts (1)
  • TradeQuoteError (39-39)
packages/swapper/src/swappers/NearIntentsSwapper/utils/oneClickService.ts (1)
  • ApiError (17-17)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install and Cache
🔇 Additional comments (2)
packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts (1)

23-23: ApiError handling for invalid tokenIn/tokenOut is correctly classified

Importing ApiError and mapping tokenIn is not valid / tokenOut is not valid responses to TradeQuoteError.UnsupportedTradePair is the right move and neatly covers the “quote endpoint failing due to unsupported assets” scenario without changing other error behavior. Please just double‑check during testing that these message strings exactly match what the 1Click API currently returns so we don’t silently misclassify future errors if the API wording changes.

Also applies to: 239-252

packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts (1)

44-79: assetToNearIntentsAsset nullability aligns with unsupported‑pair handling

Changing assetToNearIntentsAsset to return string | null for “no NEAR Intents mapping” (missing chain mapping or token lookup miss) is a solid improvement and lines up with the new UnsupportedTradePair handling in the swapper. This keeps helpers focused on resolution while letting callers decide how to surface unsupported assets, without over‑using exceptions for normal “not supported” cases.

@gomesalexandre gomesalexandre merged commit 744f42a into develop Nov 17, 2025
4 checks passed
@gomesalexandre gomesalexandre deleted the feat_near_better_error_handling branch November 17, 2025 18:33
@coderabbitai coderabbitai bot mentioned this pull request Jan 16, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Near Intents- Better error messaging for unsupported assets

3 participants