Skip to content

fix: second-class EVM chains internal Tx parsing - #11447

Merged
gomesalexandre merged 3 commits into
developfrom
capy/cap-6-aae98542
Dec 18, 2025
Merged

fix: second-class EVM chains internal Tx parsing#11447
gomesalexandre merged 3 commits into
developfrom
capy/cap-6-aae98542

Conversation

@gomesalexandre

@gomesalexandre gomesalexandre commented Dec 17, 2025

Copy link
Copy Markdown
Contributor

Description

Adds internal Tx parsing for Monad/Plasma (not HyperEVM as their endpoint doesn't support trace, and Tenderly doesn't support HyperEVM either)

Issue (if applicable)

Risk

High Risk PRs Require 2 approvals

Low

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

Monad and Plasma swaps - will now correctly parse internal transactions for accurate execution prices

Testing

Engineering

  • Swap TO Monad via Relay - verify execution price is accurate with internal tx parsing
  • Swap TO Plasma via Relay - verify execution price is accurate with internal tx parsing
  • Swap TO HyperEVM - verify it's still happy

Operations

  • Actual buy amount for Monad/Plasma should be sane against actual

Screenshots (if applicable)

https://jam.dev/c/eb11c5c2-4ef9-4777-8c3f-6e358cf885f0

Summary by CodeRabbit

Release Notes

  • New Features
    • Enhanced transaction parsing to detect and capture internal transactions that occur during smart contract execution.
    • Transaction records now include internal value transfers within contracts for more complete transaction visibility.

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

gomesalexandre and others added 2 commits December 17, 2025 12:18
Co-authored-by: Capy <capy@capy.ai>

- Add support for parsing internal transactions using debug_traceTransaction JSON-RPC

- Use debug_traceTransaction for chains that support it (Plasma)

- Exclude Monad and HyperEVM (no debug_traceTransaction support)

- Add constants DEBUG_TRACE_SUPPORTED_CHAINS and DEBUG_TRACE_UNSUPPORTED_CHAINS

- Extract fetchInternalTransactionsViaDebug as utility function

- Parse internal transfers for accurate execution price calculation

This enables proper execution price calculation for swaps on second-class EVM chains

where native token transfers occur via internal transactions.

Fixes #11429
…action exclusion

Monad and Plasma support debug_traceTransaction, but HyperEVM doesn't.
The original implementation incorrectly excluded Monad instead of HyperEVM.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@gomesalexandre
gomesalexandre requested a review from a team as a code owner December 17, 2025 13:15
@coderabbitai

coderabbitai Bot commented Dec 17, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR adds internal transaction parsing to second-class EVM chains by introducing methods to fetch internal transactions via debug_traceTransaction and Tenderly API, then integrating these transactions into the parsing logic. Internal transfers are extracted and augmented into parsed transaction output, with special handling to skip HyperEVM chains.

Changes

Cohort / File(s) Summary
EVM Adapter Internal Transaction Fetching
packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts
Added private fetchInternalTransactions() method to fetch internal transactions via debug_traceTransaction (skipped for HyperEVM). Extended parseTx() to concurrently fetch and include internal transactions. Modified parsed transaction result to include internalTxs array when present, and augmented native transfers extraction to include Send/Receive transfers from internal transactions.
Tenderly Internal Transaction Types
packages/swapper/src/utils/tenderly/types.ts
Added two new public types: TenderlyInternalTransaction (with from, to, value fields) and TenderlyTransactionResponse (wrapping a transaction object containing hash, block number, transaction details, and optional internal_transactions array).
Tenderly API Utilities
packages/swapper/src/utils/tenderly/simulate.ts
Added fetchInternalTransactions() method to fetch internal transactions from Tenderly API by chainId and txHash, deriving the EVM network ID and returning an array of TenderlyInternalTransaction. Returns empty array on error. Updated type imports to include new Tenderly types.

Sequence Diagram

sequenceDiagram
    participant Client
    participant SecondClassEvmAdapter
    participant EVMNode as EVM Node/<br/>Tenderly API
    participant Parser as Transaction Parser

    Client->>SecondClassEvmAdapter: parseTx(txHash, address)
    
    rect rgb(200, 220, 255)
    Note over SecondClassEvmAdapter: Standard TX parsing
    SecondClassEvmAdapter->>EVMNode: fetch standard transaction data
    EVMNode-->>SecondClassEvmAdapter: transaction object
    end
    
    alt Is HyperEVM Chain
        SecondClassEvmAdapter->>SecondClassEvmAdapter: skip internal txs (return [])
    else Other Second-Class Chains
        rect rgb(220, 200, 255)
        Note over SecondClassEvmAdapter: Fetch Internal Transactions
        SecondClassEvmAdapter->>EVMNode: debug_traceTransaction<br/>or Tenderly API
        EVMNode-->>SecondClassEvmAdapter: internal transactions array
        end
    end
    
    rect rgb(200, 255, 220)
    Note over Parser: Extract Transfers
    SecondClassEvmAdapter->>Parser: parse token transfers +<br/>internal transfers
    Parser-->>SecondClassEvmAdapter: parsed transaction with<br/>internalTxs and transfers
    end
    
    SecondClassEvmAdapter-->>Client: parsed transaction<br/>(includes internal transfers)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • SecondClassEvmAdapter.ts: Review the new fetchInternalTransactions() logic for correct error handling and recursion; verify the integration into parseTx() and transfer extraction logic works correctly with the conditional HyperEVM check.
  • tenderly/simulate.ts: Verify the fetchInternalTransactions() implementation correctly handles chainId-to-evmNetworkId mapping and error cases.
  • tenderly/types.ts: Type definitions are straightforward but ensure they align with actual Tenderly API response structure.

Possibly related PRs

Suggested reviewers

  • NeOMakinG

Poem

🐰 A rabbit hops through transactions deep,
Internal flows no longer sleep,
Debug traces and Tenderly's call,
Parsing transfers, we catch them all,
Save HyperEVM from the debug brigade,
Internal transfers have come to parade!

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR implements the acceptance criteria from issue #11429: internal transaction parsing via debug_traceTransaction for Monad and Plasma, with HyperEVM properly excluded, enabling accurate execution price calculations.
Out of Scope Changes check ✅ Passed All changes are scoped to internal transaction parsing: new Tenderly types and fetch method, chain adapter integration, and debug_traceTransaction exclusion logic for HyperEVM as specified in issue #11429.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title directly references the main change: internal transaction parsing for second-class EVM chains, which is the core objective of this PR.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ 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 capy/cap-6-aae98542

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.

@gomesalexandre gomesalexandre changed the title fix: correct debug_traceTransaction chain exclusion for internal tx parsing fix: second-class EVM chains internal Tx parsing Dec 17, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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/evm/SecondClassEvmAdapter.ts (1)

357-371: Consider adding a type for the call tracer response.

The call parameter is typed as any, which violates the coding guidelines. Consider defining a type for the call tracer response structure:

+type CallTracerResult = {
+  from: string
+  to: string
+  value?: string
+  calls?: CallTracerResult[]
+}
+
-      const extractCalls = (call: any) => {
+      const extractCalls = (call: CallTracerResult) => {
📜 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 4f2dd78 and ad0ff5f.

📒 Files selected for processing (3)
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts (5 hunks)
  • packages/swapper/src/utils/tenderly/simulate.ts (2 hunks)
  • packages/swapper/src/utils/tenderly/types.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{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/swapper/src/utils/tenderly/simulate.ts
  • packages/swapper/src/utils/tenderly/types.ts
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.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/swapper/src/utils/tenderly/simulate.ts
  • packages/swapper/src/utils/tenderly/types.ts
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts
**/swapper{s,}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)

ALWAYS use makeSwapErrorRight for swapper errors with TradeQuoteError enum for error codes and provide detailed error information

Files:

  • packages/swapper/src/utils/tenderly/simulate.ts
  • packages/swapper/src/utils/tenderly/types.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/swapper/src/utils/tenderly/simulate.ts
  • packages/swapper/src/utils/tenderly/types.ts
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts
packages/swapper/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/swapper.mdc)

packages/swapper/**/*.ts: Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system
Use camelCase for variable and function names in the Swapper system
Use PascalCase for types, interfaces, and enums in the Swapper system
Use kebab-case for filenames in the Swapper system

Files:

  • packages/swapper/src/utils/tenderly/simulate.ts
  • packages/swapper/src/utils/tenderly/types.ts
🧠 Learnings (24)
📓 Common learnings
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: 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: 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: 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-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/swapper/src/utils/tenderly/simulate.ts
  • packages/swapper/src/utils/tenderly/types.ts
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.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 : Implement filterBuyAssetsBySellAssetId method to filter assets by supported chain IDs in the buy property

Applied to files:

  • packages/swapper/src/utils/tenderly/simulate.ts
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.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 : Implement filterAssetIdsBySellable method to filter assets by supported chain IDs in the sell property

Applied to files:

  • packages/swapper/src/utils/tenderly/simulate.ts
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.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/*/utils/constants.ts : Define supported chain IDs for each swapper in utils/constants.ts with both 'sell' and 'buy' properties following the pattern: SupportedChainIds type

Applied to files:

  • packages/swapper/src/utils/tenderly/simulate.ts
  • packages/swapper/src/utils/tenderly/types.ts
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.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/**/*.ts : Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system

Applied to files:

  • packages/swapper/src/utils/tenderly/simulate.ts
  • packages/swapper/src/utils/tenderly/types.ts
📚 Learning: 2025-12-04T11:05:01.146Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11281
File: packages/swapper/src/swappers/PortalsSwapper/utils/fetchSquidStatus.ts:98-106
Timestamp: 2025-12-04T11:05:01.146Z
Learning: In packages/swapper/src/swappers/PortalsSwapper/utils/fetchSquidStatus.ts, getSquidTrackingLink should return blockchain explorer links (using Asset.explorerTxLink) rather than API endpoints. For non-GMP Squid swaps: return source chain explorer link with sourceTxHash when pending/failed, and destination chain explorer link with destinationTxHash when confirmed.

Applied to files:

  • packages/swapper/src/utils/tenderly/simulate.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/**/*.ts : Use PascalCase for types, interfaces, and enums in the Swapper system

Applied to files:

  • packages/swapper/src/utils/tenderly/types.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/index.ts : Export unique functions and types from packages/swapper/src/index.ts only if needed for external consumption

Applied to files:

  • packages/swapper/src/utils/tenderly/types.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/swapper/src/utils/tenderly/types.ts
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts
📚 Learning: 2025-12-09T21:07:22.474Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11335
File: packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts:3-3
Timestamp: 2025-12-09T21:07:22.474Z
Learning: In packages/swapper/src/swappers/CetusSwapper, mysten/sui types (SuiClient, Transaction) must be imported from the nested path within cetusprotocol/aggregator-sdk (e.g., 'cetusprotocol/aggregator-sdk/node_modules/mysten/sui/client') because the aggregator SDK bundles its own version of mysten/sui. Direct imports from 'mysten/sui' break at runtime even when specified in package.json.

Applied to files:

  • packages/swapper/src/utils/tenderly/types.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 : Avoid side effects in swap logic; ensure swap methods are deterministic and stateless

Applied to files:

  • packages/swapper/src/utils/tenderly/types.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/swapper/src/utils/tenderly/types.ts
📚 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/SecondClassEvmAdapter.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/SecondClassEvmAdapter.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/SecondClassEvmAdapter.ts
📚 Learning: 2025-11-20T12:00:45.005Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11078
File: src/setupVitest.ts:11-15
Timestamp: 2025-11-20T12:00:45.005Z
Learning: In shapeshift/web, src/setupVitest.ts must redirect 'ethers' to 'ethers5' for shapeshiftoss/hdwallet-trezor (and -trezor-connect), same as ledger and shapeshift-multichain. Removing 'trezor' from the regex causes CI/Vitest failures due to ethers v6 vs v5 API differences.

Applied to files:

  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts
📚 Learning: 2025-08-05T23:36:13.214Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10187
File: src/state/slices/preferencesSlice/selectors.ts:21-25
Timestamp: 2025-08-05T23:36:13.214Z
Learning: The AssetId type from 'shapeshiftoss/caip' package is a string type alias, so it can be used directly as a return type for cache key resolvers in re-reselect selectors without needing explicit string conversion.

Applied to files:

  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.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/chain-adapters/src/evm/SecondClassEvmAdapter.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/SecondClassEvmAdapter.ts
📚 Learning: 2025-12-12T16:20:33.904Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11377
File: src/lib/referral/api.ts:30-57
Timestamp: 2025-12-12T16:20:33.904Z
Learning: In shapeshift/web referral feature, the backend expects an EVM address (0x… viem Address) as the owner identifier, not a CAIP AccountId. Update useReferral to derive the first connected EVM address via fromAccountId + getAddress, and do not URL-encode it in the API path.

Applied to files:

  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.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/chain-adapters/src/evm/SecondClassEvmAdapter.ts
📚 Learning: 2025-08-29T18:09:45.982Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10376
File: vite.config.mts:136-137
Timestamp: 2025-08-29T18:09:45.982Z
Learning: In the ShapeShift web repository vite.config.mts, the commonjsOptions.exclude configuration using bare package name strings like ['shapeshiftoss/caip', 'shapeshiftoss/types'] works correctly for excluding specific packages from CommonJS transformation, despite theoretical concerns about module ID matching patterns.

Applied to files:

  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.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/evm/SecondClassEvmAdapter.ts
🧬 Code graph analysis (2)
packages/swapper/src/utils/tenderly/simulate.ts (1)
packages/swapper/src/utils/tenderly/types.ts (3)
  • TenderlyConfig (57-61)
  • TenderlyInternalTransaction (63-67)
  • TenderlyTransactionResponse (69-84)
packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts (2)
packages/caip/src/constants.ts (1)
  • hyperEvmChainId (77-77)
packages/chain-adapters/src/types.ts (1)
  • TransferType (133-133)
⏰ 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 (5)
packages/swapper/src/utils/tenderly/simulate.ts (1)

118-144: LGTM - Clean implementation for fetching internal transactions from Tenderly.

The function correctly derives the network ID from chainId and returns an empty array on failure, which is appropriate for optional data enrichment. The implementation follows the same patterns used elsewhere in this file.

One consideration: the silent error handling (returning []) may make debugging difficult if Tenderly API issues occur. Consider adding a console.error for visibility, consistent with how errors are handled elsewhere in the codebase.

packages/swapper/src/utils/tenderly/types.ts (1)

63-84: LGTM - Well-defined types for Tenderly transaction response.

The types are properly structured with appropriate use of Address from viem for type safety, string for value fields (correct for handling large numbers), and optional internal_transactions array. The separation from TenderlySimulationResponse is appropriate as they represent different API endpoints.

packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts (3)

343-381: Correct implementation for HyperEVM exclusion and internal transaction fetching.

The early return for hyperEvmChainId correctly addresses the PR objective (HyperEVM doesn't support debug_traceTransaction). The recursive extraction of nested calls is well-implemented.


392-396: Good use of parallel fetching for internal transactions.

Fetching internal transactions concurrently with the transaction and receipt is efficient. The conditional assignment on line 458 (internalTxs.length > 0 ? internalTxs : undefined) correctly avoids adding empty arrays to the parsed transaction.

Also applies to: 458-458


496-523: Correct internal transfer parsing logic.

The logic properly:

  • Skips zero-value transfers
  • Normalizes addresses with getAddress before comparison
  • Creates Send transfers when user is the sender
  • Creates Receive transfers when user is the recipient

This ensures execution prices are accurate by including internal native transfers.

@0xApotheosis 0xApotheosis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Swap TO Monad via Relay - verify execution price is accurate with internal tx parsing

Image

❓ Swap TO Plasma via Relay - verify execution price is accurate with internal tx parsing

Could not get a quote on Relay, the quote endpoint returned 400 with the below response for all assets I tried into Plasma:

{
    "message": "Invalid input or output currency",
    "errorCode": "INVALID_INPUT_CURRENCY"
}

✅ Swap TO HyperEVM - verify it's still happy

@gomesalexandre

Copy link
Copy Markdown
Contributor Author

Could not get a quote on Relay, the quote endpoint returned 400 with the below response for all assets I tried into Plasma:

@coderabbitai this time around you able to create a GitHub issue for this boi? pls senpai UwU

@coderabbitai

coderabbitai Bot commented Dec 18, 2025

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the PR details including body and comments to find the full context of the Relay 400 error
gh pr view 11447 --repo shapeshift/web --json body,comments --jq '.body, .comments[].body'

Length of output: 17576


🏁 Script executed:

#!/bin/bash
# Search for existing issues about Relay and Plasma to avoid duplicates
gh issue list --repo shapeshift/web --search "Relay Plasma" --state all --limit 10 --json number,title,state

Length of output: 99


🏁 Script executed:

#!/bin/bash
# Get review comments and review threads to find the full error message
gh pr view 11447 --repo shapeshift/web --json reviews,comments --jq '.reviews[].body, .comments[].body' | grep -A 20 "Could not get a quote on Relay"

Length of output: 1038


🏁 Script executed:

#!/bin/bash
# Also check the latest comments more thoroughly
gh api repos/shapeshift/web/pulls/11447/comments --jq '.[] | select(.body | contains("Relay")) | {user: .user.login, body: .body}'

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Create GitHub issue for Relay/Plasma quote endpoint problem
gh issue create --repo shapeshift/web \
  --title "Relay quote endpoint returns 400 error for Plasma swaps" \
  --body "## Description

During testing of PR #11447, it was discovered that the Relay quote endpoint returns \`400\` errors when attempting to get quotes for swaps into Plasma chain.

## Error Details

The quote endpoint returns the following error for all assets tried into Plasma:

\`\`\`json
{
    \"message\": \"Invalid input or output currency\",
    \"errorCode\": \"INVALID_INPUT_CURRENCY\"
}
\`\`\`

## Context

- Discovered during testing in PR #11447
- Affects all assets when swapping TO Plasma via Relay
- The error suggests Relay may not support Plasma as a destination chain

## Expected Behavior

Users should be able to get quotes from Relay for swaps into Plasma chain.

## Actual Behavior

Relay quote endpoint returns 400 error indicating invalid input or output currency.

## Related

- PR: #11447
- Reported by: @gomesalexandre" \
  --assignee gomesalexandre

Length of output: 46


@gomesalexandre Done! ✨ I've created issue #11473 for the Relay quote endpoint 400 error when swapping to Plasma. The issue includes the error details, context from this PR, and has been assigned to you.

You can view it here: #11473


🧠 Learnings used
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.

@gomesalexandre
gomesalexandre enabled auto-merge (squash) December 18, 2025 08:42
@gomesalexandre

Copy link
Copy Markdown
Contributor Author

@0xApotheosis yeeting, considering this comment as a stamp as Tx parsing is unrelated to quotes shenanigans and Mr Rabbit authored an issue.

@gomesalexandre
gomesalexandre merged commit ed6b691 into develop Dec 18, 2025
4 checks passed
@gomesalexandre
gomesalexandre deleted the capy/cap-6-aae98542 branch December 18, 2025 10:08

Copy link
Copy Markdown
Member

I'm all for yeeting at your discretion ser @gomes

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.

Second-class EVM chains - Internal transactions parsing

2 participants