Skip to content

Conversation

@kaladinlight
Copy link
Contributor

@kaladinlight kaladinlight commented Jan 13, 2026

Description

Add shared broadcast transaction error handling which improves handling by cloning the response object to avoid Failed to execute 'json' on 'Response': body stream already read errors, along with handling both json and text errors. This will also properly display timeout response errors with the associated unchained update here: shapeshift/unchained#1256

Issue (if applicable)

closes #11357

Risk

High Risk PRs Require 2 approvals

Low

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

Testing

The actual reported issue was transient and I wasn't able to reproduce it directly. I have attached screenshots showing error handling of basic errors from malformed payloads and the evm timeout. This issue should be raised again if anyone sees the body stream already read error.

Engineering

☝️

Operations

☝️

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

Screenshots (if applicable)

image image image image

Summary by CodeRabbit

  • Refactor
    • Standardized error handling mechanisms across blockchain chain adapters to improve consistency in transaction broadcast error reporting.

✏️ Tip: You can customize this high-level summary in your review settings.

@kaladinlight kaladinlight requested a review from a team as a code owner January 13, 2026 19:54
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 13, 2026

📝 Walkthrough

Walkthrough

The PR centralizes broadcast transaction error handling by introducing a handleBroadcastTransactionError helper function in ErrorHandler, replacing repetitive error-handling logic across multiple chain adapters (Cosmos, EVM, Solana, UTXO) with delegated calls. ResponseError is also exported from the unchained-client package.

Changes

Cohort / File(s) Summary
Error Handler Centralization
packages/chain-adapters/src/error/ErrorHandler.ts
Introduces handleBroadcastTransactionError() function with new isResponseError() type guard; handles ResponseError responses by cloning/parsing JSON, accepts optional customMessage callback, and provides fallback error handling.
Chain Adapter Refactoring
packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts, packages/chain-adapters/src/evm/EvmBaseAdapter.ts, packages/chain-adapters/src/solana/SolanaChainAdapter.ts, packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
Imports and delegates to handleBroadcastTransactionError() in broadcastTransaction catch blocks, replacing inline manual error parsing and ErrorHandler construction.
Public API Export
packages/unchained-client/src/index.ts
Re-exports ResponseError from generated ethereum runtime, expanding public surface.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • NeOMakinG

Poem

🐰 Hops through handlers with bundled care,
No more error-catching everywhere!
One rabbit path, so clean and neat,
Makes broadcast troubles obsolete! 🎯✨

🚥 Pre-merge checks | ✅ 5
✅ 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: a refactoring to centralize and improve broadcast transaction error handling across multiple adapters.
Linked Issues check ✅ Passed The PR addresses issue #11357 by cloning the Response object before reading to prevent 'body stream already read' errors, handling both JSON and text responses, and improving error messaging for timeout scenarios.
Out of Scope Changes check ✅ Passed All changes are directly related to centralizing broadcast transaction error handling; no unrelated modifications were introduced.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 response-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/chain-adapters/src/error/ErrorHandler.ts (1)

38-66: The .clone() call correctly addresses the "body stream already read" issue.

A few optional improvements:

  1. Variable shadowing (line 61): The inner catch (err) shadows the outer err parameter, which can be confusing during debugging. Consider renaming.

  2. Type safety (line 40): The customMessage callback uses any for the response parameter. Consider defining a more specific type.

♻️ Suggested improvements
+type BroadcastErrorResponse = {
+  message?: string
+  [key: string]: unknown
+}
+
 export const handleBroadcastTransactionError = async (
   err: unknown,
-  customMessage?: (response: any) => string,
+  customMessage?: (response: BroadcastErrorResponse) => string,
 ) => {
   try {
     if (!isResponseError(err)) throw err

     const response = await err.response.clone().json()

     const message = (() => {
       if (customMessage) return customMessage(response)

       try {
         return JSON.parse(response.message).message
       } catch {
         return response.message
       }
     })()

     return ErrorHandler(JSON.stringify(response), {
       translation: 'chainAdapters.errors.broadcastTransactionWithMessage',
       options: { message },
     })
-  } catch (err) {
-    return ErrorHandler(err, {
+  } catch (innerErr) {
+    return ErrorHandler(innerErr, {
       translation: 'chainAdapters.errors.broadcastTransaction',
     })
   }
 }
📜 Review details

Configuration used: Organization 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 04681c1 and 50ee5b9.

📒 Files selected for processing (6)
  • packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts
  • packages/chain-adapters/src/error/ErrorHandler.ts
  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/unchained-client/src/index.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Never assume a library is available - always check imports/package.json first
Prefer composition over inheritance
Write self-documenting code with clear variable and function names
Keep functions small and focused on a single responsibility
Avoid deep nesting - use early returns instead
Prefer procedural and easy to understand code
Never expose, log, or commit secrets, API keys, or credentials
Validate all inputs, especially user inputs
Handle errors gracefully with meaningful messages
Don't silently catch and ignore exceptions
Log errors appropriately for debugging
Provide fallback behavior when possible
Use appropriate data structures for the task
Never add code comments unless explicitly requested
When modifying code, do not add comments that reference previous implementations or explain what changed. Comments should only describe the current logic and functionality.
Use meaningful names for branches, variables, and functions
Always run yarn lint --fix and yarn type-check after making changes
Avoid let variable assignments - prefer const with inline IIFE switch statements or extract to functions for conditional logic

Files:

  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/unchained-client/src/index.ts
  • packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts
  • packages/chain-adapters/src/error/ErrorHandler.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Avoid useEffect where practical - use it only when necessary and following best practices
Avoid 'any' types - use specific type annotations instead
For default values with user overrides, use computed values (useMemo) instead of useEffect - pattern: userSelected ?? smartDefault ?? fallback
When function parameters are unused due to interface requirements, refactor the interface or implementation to remove them rather than prefixing with underscore
Sanitize data before displaying to prevent XSS
Memoize aggressively - wrap component variables in useMemo and callbacks in useCallback where possible
For static JSX icon elements (e.g., <TbCopy />) that don't depend on state/props, define them as constants outside the component to avoid re-renders instead of using useMemo
Account for light/dark mode using useColorModeValue hook
Account for responsive mobile designs in all UI components
When applying styles, use the existing standards and conventions of the codebase
Use Chakra UI components and conventions
All copy/text must use translation keys - never hardcode strings
Use the translation hook: useTranslate() from react-polyglot
Use useFeatureFlag('FlagName') hook to access feature flag values in components
Prefer type over interface for type definitions
Use strict typing - avoid any
Use Nominal types for domain identifiers (e.g., WalletId, AccountId)
Import types from @shapeshiftoss/caip for chain/account/asset IDs
Use useAppSelector for Redux state
Use useAppDispatch for Redux actions
Memoize expensive computations with useMemo
Memoize callbacks with useCallback

**/*.{ts,tsx}: Use Result<T, E> pattern for error handling in swappers and APIs; ALWAYS use Ok() and Err() from @sniptt/monads; AVOID throwing within swapper API implementations
ALWAYS use custom error classes from @shapeshiftoss/errors with meaningful error codes for internationalization and relevant details in error objects
ALWAYS wrap async op...

Files:

  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/unchained-client/src/index.ts
  • packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts
  • packages/chain-adapters/src/error/ErrorHandler.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/naming-conventions.mdc)

**/*.{js,jsx,ts,tsx}: Use camelCase for variables, functions, and methods with descriptive names that explain the purpose
Use verb prefixes for functions that perform actions (e.g., fetch, validate, execute, update, calculate)
Use UPPER_SNAKE_CASE for constants and configuration values with descriptive names
Use handle prefix for event handlers with descriptive names in camelCase
Use descriptive boolean variable names with is, has, can, should prefixes
Use named exports for components, functions, and utilities instead of default exports
Use descriptive import names and avoid renaming imports unless necessary
Avoid non-descriptive variable names like data, item, obj, and single-letter variable names except in loops
Avoid abbreviations in names unless they are widely understood
Avoid generic function names like fn, func, or callback

Files:

  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/unchained-client/src/index.ts
  • packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts
  • packages/chain-adapters/src/error/ErrorHandler.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
🧠 Learnings (20)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10074
File: src/features/defi/providers/fox-farming/components/FoxFarmingManager/Withdraw/components/Confirm.tsx:192-194
Timestamp: 2025-07-24T10:07:54.919Z
Learning: For fox farming withdrawals in the ShapeShift web app, the architectural preference is to either not handle errors with old-style toast notifications or handle broadcast on-chain errors holistically through the action center system. On-chain errors are considered rare and not a major concern worth individual toast handling.
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsx:105-111
Timestamp: 2025-08-22T14:59:04.889Z
Learning: In the ShapeShift web Base chain handling, the await pattern inside forEach in useGenericTransactionSubscriber is intentional to delay the entire action completion flow (not just fetchBasePortfolio) for Base chain transactions. The user kaladinlight wants everything below the Base portfolio refresh - including dispatch, query invalidation, and toast notifications - to also be delayed by ~10 seconds to accommodate Base's degraded node state.
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10361
File: src/pages/Markets/components/CardWithSparkline.tsx:83-92
Timestamp: 2025-08-25T23:32:13.876Z
Learning: In shapeshift/web PR #10361, premiumjibles considered the nested button accessibility issue (ChartErrorFallback retry Button inside Card rendered as Button in CardWithSparkline.tsx) out of scope for the error boundaries feature PR, consistent with deferring minor a11y improvements to follow-up PRs.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/content/SendTransactionContent.tsx:0-0
Timestamp: 2025-09-12T10:44:46.723Z
Learning: gomesalexandre dismissed a clipboard error handling suggestion in PR #10461 for SendTransactionContent.tsx, demonstrating that the current navigator.clipboard.writeText implementation works as expected and preferring to keep it simple without additional try/catch error handling.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11170
File: patches/@shapeshiftoss+bitcoinjs-lib+7.0.0-shapeshift.0.patch:9-19
Timestamp: 2025-11-25T21:43:10.838Z
Learning: In shapeshift/web, gomesalexandre will not expand PR scope to fix latent bugs in unused API surface (like bitcoinjs-lib patch validation methods) when comprehensive testing proves the actual used code paths work correctly, preferring to avoid costly hdwallet/web verdaccio publish cycles and full regression testing for conceptual issues with zero runtime impact.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/hooks/useSimulateEvmTransaction.ts:0-0
Timestamp: 2025-09-12T13:44:17.019Z
Learning: gomesalexandre prefers letting chain adapter errors throw naturally in useSimulateEvmTransaction rather than adding explicit error handling for missing adapters, consistent with his fail-fast approach and dismissal of defensive validation as "stale" in WalletConnect transaction simulation flows.
📚 Learning: 2025-09-12T13:44:17.019Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/hooks/useSimulateEvmTransaction.ts:0-0
Timestamp: 2025-09-12T13:44:17.019Z
Learning: gomesalexandre prefers letting chain adapter errors throw naturally in useSimulateEvmTransaction rather than adding explicit error handling for missing adapters, consistent with his fail-fast approach and dismissal of defensive validation as "stale" in WalletConnect transaction simulation flows.

Applied to files:

  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts
  • packages/chain-adapters/src/error/ErrorHandler.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
📚 Learning: 2026-01-05T23:24:54.841Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11569
File: packages/chain-adapters/src/evm/katana/KatanaChainAdapter.ts:44-46
Timestamp: 2026-01-05T23:24:54.841Z
Learning: In packages/chain-adapters/src/evm/**/[chain]ChainAdapter.ts files, second-class EVM chain adapters (those extending SecondClassEvmAdapter, such as Monad, Plasma, HyperEVM, and Katana) use hardcoded strings in their getName() method (e.g., `return 'Monad'`), NOT the enum reverse-lookup pattern. The enum reverse-lookup pattern (`Object.values(ChainAdapterDisplayName).indexOf(...)`) only applies to first-class chain adapters.

Applied to files:

  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
📚 Learning: 2025-11-24T21:20:57.909Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Reuse executeEvmTransaction utility for EVM-based swappers instead of implementing custom transaction execution

Applied to files:

  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
📚 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/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts
  • packages/chain-adapters/src/error/ErrorHandler.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.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/chain-adapters/src/evm/EvmBaseAdapter.ts
📚 Learning: 2025-12-17T14:50:01.629Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11449
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:570-596
Timestamp: 2025-12-17T14:50:01.629Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, the parseTx method uses `unknown` type for the txHashOrTx parameter intentionally. TRON is a "second-class chain" that works differently from other chains - it accepts either a string hash (to fetch TronTx via unchained client) or a TronTx object directly. The base chain-adapter interface is strongly typed and doesn't accommodate this flexible signature, so `unknown` is used as an appropriate escape hatch rather than a type safety issue.

Applied to files:

  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts
  • packages/chain-adapters/src/error/ErrorHandler.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
📚 Learning: 2025-12-04T22:57:50.850Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 11290
File: packages/chain-adapters/src/utxo/zcash/ZcashChainAdapter.ts:48-51
Timestamp: 2025-12-04T22:57:50.850Z
Learning: In packages/chain-adapters/src/**/*ChainAdapter.ts files, the getName() method uses the pattern `const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.XXX); return Object.keys(ChainAdapterDisplayName)[enumIndex]` to reverse-lookup the enum key from its value. This is the established pattern used consistently across almost all chain adapters (Bitcoin, Ethereum, Litecoin, Dogecoin, Polygon, Arbitrum, Cosmos, etc.) and should be preserved for consistency when adding new chain adapters.

Applied to files:

  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to **/*.{ts,tsx} : Import types from `shapeshiftoss/caip` for chain/account/asset IDs

Applied to files:

  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/error/ErrorHandler.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/chain-adapters/src/evm/EvmBaseAdapter.ts
📚 Learning: 2025-11-19T16:59:50.569Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11012
File: src/context/WalletProvider/Vultisig/components/Connect.tsx:24-59
Timestamp: 2025-11-19T16:59:50.569Z
Learning: In src/context/WalletProvider/*/components/Connect.tsx files across the ShapeShift web codebase, the established pattern for handling null/undefined adapter from getAdapter() is to simply check `if (adapter) { ... }` without an else clause. All wallet Connect components (Coinbase, Keplr, Phantom, Ledger, MetaMask, WalletConnectV2, KeepKey, Vultisig) follow this pattern—they reset loading state after the if block but do not show error messages when adapter is null. This is an intentional design decision and should be maintained for consistency.

Applied to files:

  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useErrorToast` hook for displaying errors with translated error messages and handle different error types appropriately

Applied to files:

  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts
  • packages/chain-adapters/src/error/ErrorHandler.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
📚 Learning: 2025-12-09T21:06:15.748Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11335
File: packages/swapper/src/swappers/CetusSwapper/endpoints.ts:66-68
Timestamp: 2025-12-09T21:06:15.748Z
Learning: In packages/swapper/src/swappers/CetusSwapper/endpoints.ts, gomesalexandre is comfortable with throwing errors directly in getUnsignedSuiTransaction and similar transaction preparation methods, rather than using the Result pattern. The Result pattern with makeSwapErrorRight/TradeQuoteError is primarily for the main swapper API methods (getTradeQuote, getTradeRate), while helper/preparation methods can use throws.

Applied to files:

  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/swapper{s,}/**/*.{ts,tsx} : ALWAYS use `makeSwapErrorRight` for swapper errors with `TradeQuoteError` enum for error codes and provide detailed error information

Applied to files:

  • packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use custom error classes from `shapeshiftoss/errors` with meaningful error codes for internationalization and relevant details in error objects

Applied to files:

  • packages/unchained-client/src/index.ts
  • packages/chain-adapters/src/error/ErrorHandler.ts
📚 Learning: 2025-08-22T12:58:26.590Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/GenericTransactionActionCard.tsx:108-111
Timestamp: 2025-08-22T12:58:26.590Z
Learning: In the RFOX GenericTransactionDisplayType flow in src/components/Layout/Header/ActionCenter/components/GenericTransactionActionCard.tsx, the txHash is always guaranteed to be present according to NeOMakinG, so defensive null checks for txLink are not needed in this context.

Applied to files:

  • packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Handle errors gracefully with meaningful messages

Applied to files:

  • packages/chain-adapters/src/error/ErrorHandler.ts
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.{jsx,tsx} : ALWAYS handle async errors properly in async operations

Applied to files:

  • packages/chain-adapters/src/error/ErrorHandler.ts
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.{jsx,tsx} : ALWAYS provide user-friendly error messages in error handling

Applied to files:

  • packages/chain-adapters/src/error/ErrorHandler.ts
📚 Learning: 2025-12-03T23:21:16.985Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11261
File: src/lib/utils/tron/getAllowance.ts:14-59
Timestamp: 2025-12-03T23:21:16.985Z
Learning: In src/lib/utils/tron/getAllowance.ts, gomesalexandre is not concerned about adding comprehensive error handling (try-catch blocks, custom error classes) for the getTrc20Allowance utility function, because it is used close to the view layer. He prefers simpler error handling for view-layer utilities, letting errors propagate naturally rather than adding defensive guards.

Applied to files:

  • packages/chain-adapters/src/solana/SolanaChainAdapter.ts
🧬 Code graph analysis (4)
packages/chain-adapters/src/evm/EvmBaseAdapter.ts (1)
packages/chain-adapters/src/error/ErrorHandler.ts (1)
  • handleBroadcastTransactionError (38-66)
packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts (1)
packages/chain-adapters/src/error/ErrorHandler.ts (1)
  • handleBroadcastTransactionError (38-66)
packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts (1)
packages/chain-adapters/src/error/ErrorHandler.ts (1)
  • handleBroadcastTransactionError (38-66)
packages/chain-adapters/src/solana/SolanaChainAdapter.ts (1)
packages/chain-adapters/src/error/ErrorHandler.ts (1)
  • handleBroadcastTransactionError (38-66)
⏰ 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: Call / Static
🔇 Additional comments (11)
packages/unchained-client/src/index.ts (1)

3-4: LGTM!

The export of ResponseError from the ethereum runtime enables the new centralized broadcast error handling pattern across chain adapters.

packages/chain-adapters/src/error/ErrorHandler.ts (2)

10-17: LGTM!

The type guard is well-structured with proper checks for Error instance, name, and the presence of a valid Response object.


103-106: LGTM!

Using the isResponseError type guard and .clone() before reading the response body ensures consistent error handling and prevents the "body stream already read" issue.

packages/chain-adapters/src/solana/SolanaChainAdapter.ts (2)

46-50: LGTM!

Import correctly includes handleBroadcastTransactionError alongside existing error handling utilities.


417-419: LGTM!

The error handling is now centralized through handleBroadcastTransactionError, consistent with other chain adapters and aligning with the PR objective to prevent "body stream already read" errors.

packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts (2)

21-25: LGTM!

Import correctly includes handleBroadcastTransactionError alongside existing error handling utilities.


597-599: LGTM!

The error handling is centralized through handleBroadcastTransactionError, properly catching errors from both the unchained API and the Zcash Blockchair fallback.

packages/chain-adapters/src/evm/EvmBaseAdapter.ts (2)

33-37: LGTM!

Import correctly includes handleBroadcastTransactionError alongside existing error handling utilities.


529-531: LGTM!

The error handling is centralized through handleBroadcastTransactionError, which properly clones the response before reading to prevent the "body stream already read" error that was causing false failure reports.

packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts (2)

15-15: LGTM!

Import correctly expanded to include the new shared error handler.


385-388: LGTM! Centralizes error handling and fixes response body consumption issue.

This correctly delegates to the shared helper which clones the response before reading JSON, preventing the "body stream already read" error. The custom message callback appropriately extracts Cosmos SDK error descriptions with a sensible fallback.

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.

Transaction saying its failing but actually goes through

2 participants