Skip to content

feat: tron parseTx() handle transfers#11449

Merged
NeOMakinG merged 3 commits intodevelopfrom
feat_tron_tx_parsing
Dec 18, 2025
Merged

feat: tron parseTx() handle transfers#11449
NeOMakinG merged 3 commits intodevelopfrom
feat_tron_tx_parsing

Conversation

@gomesalexandre
Copy link
Contributor

@gomesalexandre gomesalexandre commented Dec 17, 2025

Description

Same dance as #11447 / #11426, better parsing including transfers, which allows us to get proper actual buy amount. Note, this one does handle internal transfers too.

Issue (if applicable)

closes #11428

Risk

Low risk - isolated to TRON transaction parsing. Only affects how TRON transactions are parsed and displayed, doesn't modify on-chain transaction building or signing.

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

TRON swaps and sends will now show complete transfer information including internal TRX transfers from DEX swaps.

Testing

Engineering

  • Try a few TRON (TRX / tokens) swaps
  • Ensure actual buy amount looks good

Operations

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

Try TRON swaps:

  • TRX → USDT (should show both transfers)
  • USDT → TRX (should show USDT send and TRX receive including internal transfer)
  • Verify actual buy amount displays correctly in swap cards

Screenshots (if applicable)

N/A

Summary by CodeRabbit

  • New Features

    • Look up and parse TRON transactions by hash.
    • Consolidated view of native TRX transfers, TRC20 token transfers, and internal TRX transfers.
    • Exposes fee details and richer transaction metadata (logs/internal transfers) for clearer transaction results.
    • Improved error reporting when parsing fails.
  • Refactor

    • Modularized parsing flow to better aggregate multiple transfer types.

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

Add comprehensive transaction parsing for TRON including:
- Native TRX transfers (direct and internal)
- TRC20 token transfers from event logs
- Internal transaction parsing for DEX swaps

Enables accurate actual buy amount detection for TRON swaps.

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

Co-Authored-By: Claude <[email protected]>
@gomesalexandre gomesalexandre requested a review from a team as a code owner December 17, 2025 13:48
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 17, 2025

📝 Walkthrough

Walkthrough

Refactors TRON transaction parsing to a modular private-helpers approach, adds TRC20 and internal TRX transfer extraction, makes parseTx accept either a tx hash or tx object (fetching when given a hash), and extends unchained-client Tron types+api to expose logs and internal_transactions for parsing.

Changes

Cohort / File(s) Change Summary
TRON Chain Adapter Parsing Logic
packages/chain-adapters/src/tron/TronChainAdapter.ts
Removed TransactionParser field; introduced private parse(tx, pubkey), parseTRC20Transfers, and parseInternalTrxTransfers; updated parseTx to accept a hash or tx object and fetch when needed; aggregate native, TRC20, and internal transfers; updated imports to type-only unchained and added TransferType/TxStatus.
TRON Unchained-Client API
packages/unchained-client/src/tron/api.ts
getTransaction now collects and returns log and internal_transactions from the provider response and includes them on the returned TronTx.
TRON Unchained-Client Types
packages/unchained-client/src/tron/types.ts
Added TronTxLog and TronInternalTransaction interfaces; extended exported TronTx with optional log?: TronTxLog[] and internal_transactions?: TronInternalTransaction[].

Sequence Diagram

sequenceDiagram
    participant Caller
    participant TronChainAdapter
    participant HTTPProvider
    participant ParserHelpers

    Caller->>TronChainAdapter: parseTx(txHashOrTx, pubkey)
    alt Input is tx hash
        TronChainAdapter->>HTTPProvider: fetchTransaction(hash)
        HTTPProvider-->>TronChainAdapter: TronTx (includes log & internal_transactions)
    else Input is tx object
        Note over TronChainAdapter: use provided TronTx
    end
    TronChainAdapter->>ParserHelpers: parse(tx, pubkey)
    par extract transfers
        ParserHelpers->>ParserHelpers: extract native TRX transfer(s)
        ParserHelpers->>ParserHelpers: parseTRC20Transfers(tx, pubkey)
        ParserHelpers->>ParserHelpers: parseInternalTrxTransfers(tx, pubkey)
    end
    ParserHelpers->>TronChainAdapter: aggregated Transaction (transfers, fee, block metadata)
    TronChainAdapter-->>Caller: Transaction / Promise
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing extra attention:
    • All call sites for parseTx to ensure compatibility with the new hash-or-object signature and behavior.
    • Correctness and deduplication when merging native, TRC20, and internal transfers.
    • Decoding of TRC20 events/logs (address decoding and contractAddress→assetId mapping).
    • Proper population of fee and block metadata in both fetch and direct-parse flows.
    • New types in unchained-client (ensure consumers compile against updated interfaces).

Possibly related PRs

Suggested reviewers

  • NeOMakinG
  • 0xApotheosis

Poem

🐰 I nibble logs and hop through hashes,

decode TRC20s in joyful sashes.
Native hops and internal bounds,
I stitch transfers into tidy rounds.
Hooray — parsed coins, no loose ends found! 🎉

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 'feat: tron parseTx() handle transfers' directly and specifically describes the main change: enhancing TRON transaction parsing to handle transfer information.
Linked Issues check ✅ Passed The PR successfully implements TRON transaction parsing improvements (#11428) by adding TRC20 and internal transfer parsing, enabling visibility of transfers needed for execution price calculation.
Out of Scope Changes check ✅ Passed All changes are tightly scoped to TRON transaction parsing: type definitions, API data collection, and parser refactoring; no unrelated modifications detected.
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_tron_tx_parsing

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: 1

🧹 Nitpick comments (5)
packages/unchained-client/src/tron/api.ts (1)

144-152: Inline types duplicate definitions from types.ts.

These inline type annotations duplicate TronTxLog and TronInternalTransaction interfaces already defined in ./types.ts. Import and use those types directly for consistency and to avoid type drift.

+import type { TronAccount, TronBlock, TronTx, TronTxLog, TronInternalTransaction } from './types'
+
-    let log: { address: string; topics: string[]; data: string }[] = []
-    let internal_transactions: {
-      hash: string
-      caller_address: string
-      transferTo_address: string
-      callValueInfo: { callValue?: number; tokenId?: string }[]
-      note: string
-      rejected?: boolean
-    }[] = []
+    let log: TronTxLog[] = []
+    let internal_transactions: TronInternalTransaction[] = []
packages/chain-adapters/src/tron/TronChainAdapter.ts (4)

580-582: Unsafe type assertion without runtime validation.

Casting txHashOrTx to TronTx without validation could cause runtime errors if the caller passes an incompatible object. Consider adding a type guard to verify the object has required TronTx properties before parsing.

+  private isTronTx(obj: unknown): obj is unchained.tron.TronTx {
+    return (
+      typeof obj === 'object' &&
+      obj !== null &&
+      'txid' in obj &&
+      'raw_data' in obj
+    )
+  }
+
   async parseTx(txHashOrTx: unknown, pubkey: string): Promise<Transaction> {
     try {
       let tx: unchained.tron.TronTx

       if (typeof txHashOrTx === 'string') {
         const fetchedTx = await this.providers.http.getTransaction({ txid: txHashOrTx })
         if (!fetchedTx) {
           throw new Error(`Transaction not found: ${txHashOrTx}`)
         }
         tx = fetchedTx
+      } else if (this.isTronTx(txHashOrTx)) {
+        tx = txHashOrTx
       } else {
-        tx = txHashOrTx as unchained.tron.TronTx
+        throw new Error('Invalid transaction input: expected string txid or TronTx object')
       }

623-623: Inefficient: TronWeb instance created on each call.

A new TronWeb instance is created every time parseTRC20Transfers is called. Consider reusing the instance from this.getTronWeb() pattern used elsewhere, or create a private accessor similar to the api.ts approach.

-    const tronWeb = new TronWeb({ fullHost: this.rpcUrl })
+    const tronWeb = this.getTronWeb()

You'll need to add a private method if not already present:

private getTronWeb(): TronWeb {
  if (!this.tronWeb) {
    this.tronWeb = new TronWeb({ fullHost: this.rpcUrl })
  }
  return this.tronWeb
}

665-667: Silent error swallowing in log parsing.

The empty catch block silently discards parsing errors. Consider logging at debug level to aid troubleshooting without breaking the flow.

Based on learnings, gomesalexandre prefers console.error for debugging, so:

       } catch (error) {
+        console.error('Failed to parse TRC20 transfer log:', error)
         continue
       }

739-741: Silent error swallowing in internal transaction parsing.

Same issue as in parseTRC20Transfers - consider logging errors for debuggability.

       } catch (error) {
+        console.error('Failed to parse internal TRX transfer:', error)
         continue
       }
📜 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 a4da536.

📒 Files selected for processing (3)
  • packages/chain-adapters/src/tron/TronChainAdapter.ts (2 hunks)
  • packages/unchained-client/src/tron/api.ts (2 hunks)
  • packages/unchained-client/src/tron/types.ts (2 hunks)
🧰 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/unchained-client/src/tron/types.ts
  • packages/unchained-client/src/tron/api.ts
  • packages/chain-adapters/src/tron/TronChainAdapter.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/unchained-client/src/tron/types.ts
  • packages/unchained-client/src/tron/api.ts
  • packages/chain-adapters/src/tron/TronChainAdapter.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/unchained-client/src/tron/types.ts
  • packages/unchained-client/src/tron/api.ts
  • packages/chain-adapters/src/tron/TronChainAdapter.ts
🧠 Learnings (12)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11261
File: src/components/MultiHopTrade/components/TradeConfirm/hooks/useAllowanceApproval.tsx:117-172
Timestamp: 2025-12-03T23:16:28.342Z
Learning: In TRON transaction confirmation polling (e.g., approval flows in useAllowanceApproval.tsx), gomesalexandre is comfortable with optimistic completion when polling times out after the configured duration (e.g., 60 seconds). He considers the timeout a "paranoia" safety net for unlikely scenarios, expecting normal transactions to complete much faster. He prefers to defer more sophisticated timeout/failure handling as a separate follow-up concern rather than expanding PR scope.
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: 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-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/unchained-client/src/tron/types.ts
  • packages/chain-adapters/src/tron/TronChainAdapter.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/tron/TronChainAdapter.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/tron/TronChainAdapter.ts
📚 Learning: 2025-11-28T13:07:32.395Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11171
File: src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx:295-296
Timestamp: 2025-11-28T13:07:32.395Z
Learning: Tron is not supported on GridPlus, Trezor, or Ledger hardware wallets. Therefore, skipDeviceDerivation optimization (which only applies to these wallet types) is not needed in Tron adapter code paths.

Applied to files:

  • packages/chain-adapters/src/tron/TronChainAdapter.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/chain-adapters/src/tron/TronChainAdapter.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/tron/TronChainAdapter.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/chain-adapters/src/tron/TronChainAdapter.ts
📚 Learning: 2025-10-01T07:42:40.195Z
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.

Applied to files:

  • packages/chain-adapters/src/tron/TronChainAdapter.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/tron/TronChainAdapter.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/tron/TronChainAdapter.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/tron/TronChainAdapter.ts
🧬 Code graph analysis (1)
packages/chain-adapters/src/tron/TronChainAdapter.ts (5)
packages/unchained-client/src/tron/types.ts (1)
  • TronTx (19-53)
packages/chain-adapters/src/types.ts (2)
  • Transaction (141-145)
  • TransferType (133-133)
packages/swapper/src/swappers/RelaySwapper/utils/types.ts (1)
  • Transaction (45-50)
packages/caip/src/adapters/coingecko/generated/index.ts (1)
  • tron (47-47)
packages/utils/src/assetData/baseAssets.ts (1)
  • tron (391-405)
🔇 Additional comments (6)
packages/unchained-client/src/tron/api.ts (1)

159-173: LGTM!

The log and internal_transactions fields are correctly populated from the transaction info response and included in the returned TronTx object.

packages/unchained-client/src/tron/types.ts (2)

1-17: LGTM!

The new TronTxLog and TronInternalTransaction interfaces are well-defined with appropriate field types. The snake_case property names correctly match the TRON API response structure.


51-52: LGTM!

The optional log and internal_transactions fields are correctly added to TronTx, extending the interface to support transfer parsing.

packages/chain-adapters/src/tron/TronChainAdapter.ts (3)

7-8: LGTM!

Correct use of type-only import for the unchained module (only used for type annotations) and value imports for TransferType/TxStatus (used at runtime).


511-568: Overall implementation approach looks good.

The modular decomposition into parse(), parseTRC20Transfers(), and parseInternalTrxTransfers() is clean. The parsing logic correctly:

  • Identifies native TRX transfers from contract data
  • Parses TRC20 Transfer events from logs using the standard event signature
  • Extracts internal TRX transfers from DEX swap operations
  • Filters rejected/failed transactions appropriately

Also applies to: 598-671, 673-745


531-549: Self-transfer creates duplicate transfer entries.

When owner_address === to_address === pubkey (user sends to themselves), both a Send and Receive transfer are added to the nativeTransfers array. This pattern exists identically in other adapters (e.g., EVM), suggesting it may be intentional for capturing both perspectives. However, without test coverage or documentation confirming this design, the risk of double-counting transfer values in downstream consumers remains unclear.

TRON's callValueInfo is a repeated field (array) that can contain multiple
TRX/TRC10 value transfers in a single internal transaction. The previous
code only processed callValueInfo[0], silently ignoring additional entries.

This fix iterates all callValueInfo entries, matching the pattern used for:
- Bitcoin: iterates all vout entries
- TRON TRC20: iterates all log entries

Impact:
- Fixes missing TRX transfers in complex DEX swaps
- Improves swap detection accuracy for actual buy amounts
- Ensures complete transaction history display
- Aligns with TRON protocol specification

While multiple entries are uncommon, they are valid and explicitly
supported by the protocol. Missing transfers could affect swap detection
for second-class chain TRON swaps.

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

Co-Authored-By: Claude <[email protected]>
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: 1

🧹 Nitpick comments (2)
packages/chain-adapters/src/tron/TronChainAdapter.ts (2)

598-671: Consider logging errors for debugging visibility.

The Transfer event parsing logic is correct. However, the catch block at lines 665-667 silently swallows errors, which could make debugging parsing failures difficult. Consider adding at least a console.error to aid troubleshooting while maintaining the optimistic continue behavior.

Example:

       } catch (error) {
+        console.error('Failed to parse TRC20 transfer from log:', error)
         continue
       }

673-745: Good fix on callValueInfo iteration; consider adding debug logging.

The iteration over all callValueInfo entries (line 701) correctly implements the fix from the previous review. Similar to parseTRC20Transfers, consider adding console.error in the catch block at lines 739-741 to aid debugging while maintaining optimistic parsing.

Example:

       } catch (error) {
+        console.error('Failed to parse internal TRX transfer:', error)
         continue
       }
📜 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 a4da536 and fd32507.

📒 Files selected for processing (1)
  • packages/chain-adapters/src/tron/TronChainAdapter.ts (2 hunks)
🧰 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/tron/TronChainAdapter.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/tron/TronChainAdapter.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/tron/TronChainAdapter.ts
🧠 Learnings (13)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11261
File: src/components/MultiHopTrade/components/TradeConfirm/hooks/useAllowanceApproval.tsx:117-172
Timestamp: 2025-12-03T23:16:28.342Z
Learning: In TRON transaction confirmation polling (e.g., approval flows in useAllowanceApproval.tsx), gomesalexandre is comfortable with optimistic completion when polling times out after the configured duration (e.g., 60 seconds). He considers the timeout a "paranoia" safety net for unlikely scenarios, expecting normal transactions to complete much faster. He prefers to defer more sophisticated timeout/failure handling as a separate follow-up concern rather than expanding PR scope.
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-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/tron/TronChainAdapter.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/chain-adapters/src/tron/TronChainAdapter.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/tron/TronChainAdapter.ts
📚 Learning: 2025-07-28T10:36:26.897Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10121
File: src/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsx:65-66
Timestamp: 2025-07-28T10:36:26.897Z
Learning: In ShapeShift web app transaction processing, prefer parallel async execution over sequential processing to avoid blocking when handling multiple transactions. Use forEach for concurrent operations rather than for...of loops to prevent slower transactions from blocking faster ones.

Applied to files:

  • packages/chain-adapters/src/tron/TronChainAdapter.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/tron/TronChainAdapter.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/tron/TronChainAdapter.ts
📚 Learning: 2025-11-28T13:07:32.395Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11171
File: src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx:295-296
Timestamp: 2025-11-28T13:07:32.395Z
Learning: Tron is not supported on GridPlus, Trezor, or Ledger hardware wallets. Therefore, skipDeviceDerivation optimization (which only applies to these wallet types) is not needed in Tron adapter code paths.

Applied to files:

  • packages/chain-adapters/src/tron/TronChainAdapter.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/chain-adapters/src/tron/TronChainAdapter.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/tron/TronChainAdapter.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/chain-adapters/src/tron/TronChainAdapter.ts
📚 Learning: 2025-10-01T07:42:40.195Z
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.

Applied to files:

  • packages/chain-adapters/src/tron/TronChainAdapter.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/tron/TronChainAdapter.ts
🧬 Code graph analysis (1)
packages/chain-adapters/src/tron/TronChainAdapter.ts (4)
packages/unchained-client/src/tron/types.ts (1)
  • TronTx (19-53)
packages/chain-adapters/src/types.ts (2)
  • Transaction (141-145)
  • TransferType (133-133)
packages/caip/src/assetId/assetId.ts (1)
  • AssetId (17-17)
packages/utils/src/assetData/baseAssets.ts (1)
  • tron (391-405)
⏰ 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 (2)
packages/chain-adapters/src/tron/TronChainAdapter.ts (2)

7-8: LGTM!

Type-only import for the unchained namespace and explicit TransferType/TxStatus imports are properly structured.


511-568: LGTM!

The base parsing logic correctly handles native TRX transfers, properly distinguishing send vs receive, and appropriately attaches fees only to outgoing transactions.

Copy link
Collaborator

@NeOMakinG NeOMakinG left a comment

Choose a reason for hiding this comment

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

@NeOMakinG NeOMakinG enabled auto-merge (squash) December 18, 2025 12:01
@NeOMakinG NeOMakinG merged commit 9d6f25f into develop Dec 18, 2025
4 checks passed
@NeOMakinG NeOMakinG deleted the feat_tron_tx_parsing branch December 18, 2025 12:09
@coderabbitai coderabbitai bot mentioned this pull request Jan 21, 2026
1 task
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.

Tron - Tx parsing

2 participants