Skip to content

feat: add TRON gas estimates for all swappers#11288

Merged
NeOMakinG merged 42 commits intodevelopfrom
feat_tron_all_swapper_estimates
Dec 5, 2025
Merged

feat: add TRON gas estimates for all swappers#11288
NeOMakinG merged 42 commits intodevelopfrom
feat_tron_all_swapper_estimates

Conversation

@gomesalexandre
Copy link
Contributor

@gomesalexandre gomesalexandre commented Dec 4, 2025

Description

This PR adds fee estimation for TRON transactions across all swappers:

  • Relay: Uses estimates straight from Relay API (quote.fees.gas.amount)
  • Sun.io: Simulated contract call estimation (2k energy + 1100 bytes bandwidth)
  • Near Intents: Simple sends, simulated using chain adapter

While at it, also fixes missing Relay quotes for USDT (the only supported Relay token) by adding RelayQuoteTronItemData type guard.

Key Changes

Near Intents

  • Pass contractAddress and from in chainSpecific to properly detect TRC-20 vs native TRX
  • Enables accurate gas estimation for both token types

Sun.io

  • Add fee estimation for both quotes AND rates (when wallet connected)
  • Fix native TRX swaps: Account for contract call costs (not simple transfers)
  • Use 2k energy estimate (Sun.io contract provides ~117k-217k, user pays ~2k)
  • Use 1100 bytes bandwidth for contract calls
  • Include 1 TRX account activation fee when recipient is new

Relay

  • Add RelayQuoteTronItemData type and isRelayQuoteTronItemData type guard
  • Fixes "Relay quote step contains no data" error for TRON swaps
  • Uses Relay API gas estimates (quote.fees.gas.amount)

TronChainAdapter Improvements

  • Include 1 TRX account activation fee in getFeeData for new recipients
  • Use actual sender address for bandwidth estimation (not recipient)
  • Better fallback values for estimation failures

Issue (if applicable)

Risk

Low risk - Only affects TRON gas estimation display and calculation. Does not modify core transaction building logic.

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

TRON swaps through Relay, Sun.io, and Near Intents swappers. Technically, THOR too.

Testing

Ensure TRX and TRC-20 transactions work correctly for all three swappers mentionned above:

  • Gas estimates are displayed for Relay, Near Intents, and Sun.io
  • Estimates are reasonably close to actual transaction costs (usually ~1-1.5 TRX for swaps, with caveats e.g Near Intents, which is a send to a fresh address)
  • Transactions execute successfully without "insufficient balance" errors

Engineering

  • ☝🏽

Operations

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

  • ☝🏽

Screenshots (if applicable)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added broader Tron support across swappers (quoting/execution) and Relay transaction metadata handling.
    • Introduced account activation fee estimation for Tron recipients.
  • Bug Fixes

    • Improved Tron fee estimation accuracy with clearer API error surfacing and safer fallbacks.
    • Enforced receive address requirement for quotes and stabilized estimation behavior when recipient checks fail.

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

gomesalexandre and others added 30 commits December 3, 2025 01:04
- Add executeTronTransaction method to ThorchainSwapper for transaction execution
- Implement proper TRON fee estimation using real-time network prices:
  * TRC20: triggerConstantContract for energy calculation (~27 TRX)
  * TRX: actual bandwidth calculation with memo overhead (~0.3-0.5 TRX)
- Add VITE_TRON_NODE_URL to SwapperConfig
- Set networkFeeCryptoBaseUnit to undefined for rate quotes (calculated at execution time)

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Reuse single TronWeb instance for transaction building
- Remove manual fee_limit restoration (addUpdateData preserves it)
- Clean up transaction flow

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

Co-Authored-By: Claude <noreply@anthropic.com>
…t address extraction

- Increase feeLimit to 150 TRX for TRC20 transfers with memo (covers energy + bandwidth)
- Use contractAddressOrUndefined utility consistently across tron utils
- Research shows feeLimit only covers energy, bandwidth is burned separately

Note: TRC20 transfers require ~64k-130k energy + ~345 bandwidth
With memo, bandwidth increases. Account needs TRX to burn for bandwidth if
free daily bandwidth (600 units) is exhausted.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Critical fix for TRC20 bandwidth error:
- Add txLocal: true to addUpdateData() call
- This preserves fee_limit field (150 TRX for TRC20 with memo)
- Without txLocal, addUpdateData calls wallet/getsignweight API which
  returns transaction WITHOUT fee_limit, causing "Account resource insufficient" error

Root cause: TronWeb's addUpdateData() loses fee_limit when using remote API.
Solution: txLocal: true forces local transaction recreation that preserves all fields.

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

Co-Authored-By: Claude <noreply@anthropic.com>
…sues

Testing theory: txLocal: true might cause transaction validation issues.
Successful Thorchain TRC20 txs on-chain have both fee_limit and memo preserved,
suggesting addUpdateData() works correctly without txLocal option.

On-chain evidence:
- TX 78055EA7: fee_limit 100 TRX, has memo, SUCCESS
- TX BD77F95E: fee_limit 15.6 TRX, has memo, SUCCESS

If this doesn't work, need to investigate wallet balance or other issues.

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

Co-Authored-By: Claude <noreply@anthropic.com>
After analyzing SwapKit's TRON implementation and successful Thorchain TRC20 txs:
- Standard feeLimit is 100 TRX (not 150)
- addUpdateData() without txLocal is correct
- Transaction structure matches working implementations

Root cause of BANDWIDTH_ERROR confirmed:
- Account has 0.25 TRX liquid (frozen TRX cannot pay fees)
- Transaction needs ~7-8 TRX liquid for energy + memo fee
- Error is misleading - it's insufficient liquid TRX, not bandwidth

Code is correct. Issue is account balance.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Created TRON_FEE_ESTIMATION_ISSUES.md documenting critical problems:
- getFeeData() returns fixed 0.268 TRX for ALL transactions
- TRC20 transfers actually cost 6-15 TRX (24-56x underestimate)
- Causes misleading UI fees and on-chain transaction failures
- Users lose TRX in partial execution before OUT_OF_ENERGY errors

Added TODO comments in TronChainAdapter.getFeeData() with:
- Detect TRC20 vs TRX using contractAddress
- Use existing estimateTRC20TransferFee() method
- Account for memo overhead (1 TRX memo fee + bandwidth)
- Build actual transaction for accurate size estimation

Evidence includes failed txs and cost analysis.
Priority: HIGH - users losing funds on failed transactions.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Created THORCHAIN_TRON_INTEGRATION.md covering:
- Architecture (UTXO-style pattern, not EVM)
- Implementation details for all components
- Memo handling via addUpdateData()
- Cost breakdown (energy, bandwidth, memo fee)
- Successful on-chain transaction examples
- Common issues and solutions
- Testing checklist
- Comparison with SwapKit implementation

Documents that implementation is correct and matches working integrations.
Main issue is inherited getFeeData() returning wrong fees for TRC20.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed getTronTransactionFees to estimate from user's perspective:
- Use args.from instead of vault for triggerConstantContract issuerAddress
- Use args.from instead of vault for sendTrx from parameter
- Remove unnecessary Number() conversion (TronWeb accepts strings)

Why this matters:
- triggerConstantContract simulates execution from caller's perspective
- Using vault address estimated "vault→vault" cost, not "user→vault"
- Energy costs may vary based on sender's account state

Credit: coderabbitai review feedback

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

Co-Authored-By: Claude <noreply@anthropic.com>
CodeRabbit was incorrect about sendTrx accepting strings.
TronWeb's TypeScript definition requires number for amount parameter:
  sendTrx(to: string, amount?: number, from?: string)

While implementation accepts strings internally, the type definition
enforces number, causing TS2345 error.

Kept the important fix: using args.from instead of vault for sender.

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

Co-Authored-By: Claude <noreply@anthropic.com>
More consistent with codebase patterns and safer for edge cases.
bnOrZero handles invalid inputs gracefully vs raw Number() cast.

Note: TronWeb's TypeScript definition requires number type for sendTrx amount,
so string is not an option (contrary to CodeRabbit's suggestion).

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

Co-Authored-By: Claude <noreply@anthropic.com>
CRITICAL: Fixes 24-50x fee underestimation causing OUT_OF_ENERGY failures

Previously returned fixed 0.268 TRX for all transactions.
Now returns accurate estimates validated against real transactions:
- TRC20 transfers: 6.7-13.3 TRX (without memo)
- TRC20 with memo: 7.8-14.4 TRX
- TRX transfers: 0.198 TRX (without memo)
- TRX with memo: 1.231 TRX

Validation Results (Real Thorchain USDT swaps + User transaction):
- User tx: 6.77 TRX actual, 9.92 TRX estimated (1.46x = conservative ✅)
- Thor tx 1: 7.84 TRX actual, 10.92 TRX estimated (1.39x = conservative ✅)
- Thor tx 2: 7.82 TRX actual, 10.92 TRX estimated (1.40x = conservative ✅)
- Old estimate: 0.268 TRX (0.034x actual = 29x underestimate ❌)
- Improvement: 41x more accurate

Implementation:
- Detects TRC20 vs TRX via contractAddress in chainSpecific
- Calls estimateTRC20TransferFee() with actual recipient address
- Applies 1.5x safety margin for dynamic energy spikes (max 3.4x)
- Builds real transactions to measure bandwidth accurately
- Adds 1 TRX memo fee when present (network parameter #68)
- Thor/TRON rates now show fees when wallet connected
- Send modal now passes contractAddress for TRC20 detection

Files Modified:
- TronChainAdapter.ts: Rewritten getFeeData() (85 lines)
- getL1RateOrQuote.ts: Thor rates with fee calculation (68 lines)
- api.ts: Realistic fallback (31→13 TRX)
- tron/types.ts: Added GetFeeDataInput type
- types.ts: Added TRON to ChainSpecificGetFeeDataInput
- Send/utils.ts: Pass contractAddress and memo to getFeeData
- NearIntentsSwapper: Added chainSpecific for TRON calls

Technical Details:
- Uses triggerConstantContract (estimateEnergy not available on TronGrid)
- SSTORE cost varies 2x based on recipient balance (20k vs 5k energy)
- Dynamic energy can spike up to 3.4x during congestion
- Memo fee confirmed via getChainParameters(): 1,000,000 SUN
- Energy price: 100 SUN/unit (mainnet), 210 SUN/unit (Shasta)
- Validated against NETTS article: 65k/131k energy for USDT

Fixes #11270

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

Co-Authored-By: Claude <noreply@anthropic.com>
The 19.776 TRX estimate was caused by using fallback (130k energy)
because triggerConstantContract didn't have a valid sender address.

Changes:
- Added 'from' (sender) to TRON GetFeeDataInput type
- Send modal now extracts and passes sender address from accountId
- estimateTRC20TransferFee uses actual sender for accurate estimation

This fixes the recipient balance detection:
- Recipient HAS USDT: ~64k energy → 9.6 TRX estimate
- Recipient NO USDT: ~130k energy → 19.5 TRX estimate

Previously always used fallback 130k energy (19.5 TRX) because
sender address was missing. Now estimates accurately based on
actual sender calling triggerConstantContract.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Added user-facing documentation explaining TRON fee structure:
- Why USDT transfers cost $1-3 (normal and expected)
- How energy and bandwidth fees work
- Real transaction examples with breakdowns
- Dynamic energy model explanation
- Fee reduction strategies
- Links to TRON docs, explorers, and resources

This helps users understand why fees changed from $0.05 to $2
(the old $0.05 was a bug, $1-2 is the real cost).

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove documentation files (not needed in codebase)
- Remove console.warn from getL1RateOrQuote.ts
- Keep only essential code changes

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove debug console.log with fee estimation info
- Remove console.debug in error catch block

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

Co-Authored-By: Claude <noreply@anthropic.com>
Resolve merge conflicts after PR #11266 was squash merged. The original
PR had basic/placeholder Tron fee estimation, while this branch contains
the improved fee estimation logic. Kept the improvements from HEAD.

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

Co-Authored-By: Claude <noreply@anthropic.com>
…h calculation

After the mergefix, the Tron GetFeeDataInput type now requires chainSpecific
parameter with from, contractAddress, and memo fields. Updated all callers:

- SunioSwapper: Pass from, contractAddress to estimate swap fees correctly
- useApprovalFees: Pass from, contractAddress for approval tx estimation
- Fixed memo fee calculation to scale with memo byte length instead of flat 1 TRX

Also addressed CodeRabbit feedback: Memo data adds to transaction bandwidth
proportionally to byte length, not as a separate flat fee. Removed the
redundant 1 TRX memo fee and properly calculate bandwidth based on actual
memo size in both chain adapter and swapper code.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Pass contractAddress and from address in chainSpecific to properly detect
TRC-20 tokens vs native TRX transfers. This enables accurate gas estimation
for both token types, following the same pattern as the send modal.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Remove the .svg?url import and isFirefox ternary that was causing
"Expected a JavaScript module script but server responded with MIME type
image/svg+xml" error. Use static PNG for all browsers.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Add logging to track down "balance is not sufficient" error:

- Near Intents getTradeQuote: Log getFeeData inputs/outputs and final quote
- getUnsignedTronTransaction: Log buildSendApiTransaction parameters
- TronChainAdapter.getFeeData: Log inputs, chain params, and calculated fees
- TronChainAdapter.buildSendApiTransaction: Log transaction building and API responses

This will help identify if the issue is in:
- Fee estimation (too high)
- Transaction value calculation
- Balance checking logic

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

Co-Authored-By: Claude <noreply@anthropic.com>
Query /wallet/getaccount before building transaction to see:
- Actual available balance
- Frozen/staked balance
- Free bandwidth used/limit
- Whether balance is sufficient for send amount

This will help debug the "balance is not sufficient" error by showing
what TronGrid actually sees vs what we're trying to send.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Convert all console.log objects to JSON.stringify for easier copy/paste.
This makes debugging much easier since logs don't need to be manually expanded.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Previously used recipient as sender for bandwidth estimation, which could
create different transaction sizes. Now uses actual from address when available.

Also added detailed bandwidth calculation logging to debug fee estimation.

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

Co-Authored-By: Claude <noreply@anthropic.com>
TRON charges 1 TRX to activate new accounts. Check if recipient exists
and log the activation cost, as this could explain balance insufficient errors.

Formula: total_cost = send_amount + bandwidth_fee + activation_fee (if new)

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

Co-Authored-By: Claude <noreply@anthropic.com>
gomesalexandre and others added 9 commits December 4, 2025 20:54
TRON charges 1 TRX to activate new accounts. Check if recipient exists
in getFeeData and include activation cost in total fee estimate.

This fixes "balance is not sufficient" errors when sending to new addresses,
as the UI will now show the correct total cost including activation.

Formula: totalFee = energyFee + bandwidthFee + accountActivationFee

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

Co-Authored-By: Claude <noreply@anthropic.com>
Add fee estimation for both quotes and rates (when wallet connected):
- Estimate fees for rates when receiveAddress exists
- Fix value parameter: use sellAmount for TRX, '0' for TRC-20
- Add try-catch with fallback to '0' for rates (not quotes)
- Follow Near Intents pattern for consistency

This enables Sun.io to show accurate TRON gas estimates for both
rate quotes (no wallet) and actual quotes (wallet connected).

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

Co-Authored-By: Claude <noreply@anthropic.com>
Add RelayQuoteTronItemData type and isRelayQuoteTronItemData type guard
to handle TRON quote step data validation. This fixes the "Relay quote
step contains no data" error when swapping with TRON via Relay.

TRON uses TriggerSmartContract type with parameter fields:
- owner_address: sender address
- contract_address: TRC-20 contract or destination
- data: encoded transaction data

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

Co-Authored-By: Claude <noreply@anthropic.com>
Sun.io TRX swaps go through smart router contract, not peer-to-peer.
Previous estimation treated it as simple transfer (199 bytes bandwidth),
but actual cost is ~1 TRX (120k energy + 950 bytes bandwidth).

Changes:
- Use triggerConstantContract to estimate actual energy for swap
- Build swap parameters with route data for accurate estimation
- Estimate ~950 bytes bandwidth for contract calls (not 199)
- Apply 1.5x safety margin to energy estimate
- Include account activation check (1 TRX if recipient is new)

Fallback: If estimation fails, use conservative 120k energy estimate

Fixes underestimation: 0.199 TRX → ~1.0 TRX (matches actual costs)

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

Co-Authored-By: Claude <noreply@anthropic.com>
Sun.io contract owner provides ~117k energy, users only pay ~2k.
Previous estimate used full 120k energy with 1.5x multiplier = 18 TRX ($5+)
New estimate uses 2k energy without multiplier = 0.2 TRX

Math:
- Energy: 2000 * 100 = 0.2 TRX
- Bandwidth: 950 * 1000 = 0.95 TRX
- Total: ~1.15 TRX (matches actual ~1.05 TRX observed)

Removed triggerConstantContract call since it returns total energy needed,
not what user actually pays after contract owner's energy contribution.

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

Co-Authored-By: Claude <noreply@anthropic.com>
TRC-20 swaps through Sun.io router also benefit from contract owner energy.
Previous: Used standard TRC-20 estimation (130k energy * 1.5x = ~19 TRX)
Actual: Sun.io provides ~217k energy, user pays ~2k = ~1.1 TRX

Now both TRX and TRC-20 swaps use same estimate:
- Energy: 2000 * 100 = 0.2 TRX
- Bandwidth: 950 * 1000 = 0.95 TRX
- Total: ~1.15 TRX

Matches observed costs: 1.143 TRX actual vs 1.15 TRX estimated

Code cleanup:
- Move TronWeb import to top-level
- Use bn().plus() instead of + operator
- Remove unused adapter reference

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

Co-Authored-By: Claude <noreply@anthropic.com>
Actual transactions were failing with "Account resource insufficient error"
(BANDWIDTH_ERROR) despite 950 byte estimate being close to actual 928 bytes.

Increase from 950 to 1100 bytes to add ~15% safety buffer for:
- Transaction size variations
- Different swap routes
- Edge cases with larger parameter sets

New estimate:
- Energy: 2000 * 100 = 0.2 TRX
- Bandwidth: 1100 * 1000 = 1.1 TRX
- Total: ~1.3 TRX (was 1.15 TRX)

Still accurate: 1.3 TRX estimate vs ~1.05-1.15 TRX actual

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

Co-Authored-By: Claude <noreply@anthropic.com>
Remove all console.log/console.error statements added during development:
- Near Intents getTradeQuote TRON logs
- getUnsignedTronTransaction logs
- TronChainAdapter getFeeData input/output logs
- TronChainAdapter buildSendApiTransaction logs
- Account balance check logs (debug-only, not used in logic)

The activation cost check in getFeeData is preserved (used in fee calculation).
The activation check in buildSendApiTransaction was debug-only and removed.

🤖 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 4, 2025 19:36
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 4, 2025

📝 Walkthrough

Walkthrough

Adds TRON fee-estimation and recipient-activation checks across multiple swappers; updates TronChainAdapter transaction/error handling and TRX estimation behavior; expands swapper callers to pass from and contractAddress; introduces Relay TRON types and Sun.io/Relay/NEAR swaps now include TRON network fee calculations.

Changes

Cohort / File(s) Summary
TRON Chain Adapter Core
packages/chain-adapters/src/tron/TronChainAdapter.ts
Updated getFeeData to use `estimationFrom = from
NEAR Intents Swapper (TRON branch)
packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts,
packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts
Pass chainSpecific: { from: sendAddress, contractAddress } for TRON paths so fee estimation receives from and contractAddress (previously empty).
Relay Swapper TRON support
packages/swapper/src/swappers/RelaySwapper/utils/types.ts,
packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts
Added RelayQuoteTronItemData type and isRelayQuoteTronItemData guard; extended RelayQuoteItem.data union; added TRON branch in getTrade returning relayTransactionMetadata with relayId and to set to TRON contract address.
Sun.io Swapper TRON fee estimation
packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
Replaced adapter-based fee retrieval with TronWeb-based estimation for quotes/rates; enforce receiveAddress for quotes; estimate energy/bandwidth and optionally account activation fee (recipient existence check); apply fallback estimates and different error behavior for quote vs. rate paths.

Sequence Diagram(s)

sequenceDiagram
    participant Swapper
    participant TronChainAdapter
    participant TronWeb
    participant TronNode as TRON_Node_API

    Swapper->>TronChainAdapter: getFeeData(chainSpecific { from?, contractAddress? })
    alt TRX transfer
        TronChainAdapter->>TronWeb: transactionBuilder.sendTrx(estimationFrom, to, amount)
        TronWeb-->>TronChainAdapter: transaction (energy/bandwidth estimates)
    else TRC20 transfer
        TronChainAdapter->>TronWeb: transactionBuilder.triggerSmartContract(...contractAddress...)
        TronWeb-->>TronChainAdapter: transaction (energy/bandwidth estimates)
    end
    TronChainAdapter->>TronNode: GET /wallet/getaccount?address=to
    TronNode-->>TronChainAdapter: account exists / not found / error
    alt Account not found
        TronChainAdapter->>TronChainAdapter: accountActivationFee = 1,000,000 sun
    else Account exists or check error
        TronChainAdapter->>TronChainAdapter: accountActivationFee = 0
    end
    TronChainAdapter->>TronChainAdapter: totalFee = energyFee + bandwidthFee + accountActivationFee
    TronChainAdapter-->>Swapper: return fee components and networkFeeCryptoBaseUnit
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to: TronChainAdapter.ts fee aggregation and error swallowing behavior for account check, getQuoteOrRate.ts changes enforcing receiveAddress and new TronWeb estimation/fallback paths, and the new Relay type guards to ensure exhaustive narrowing.

Possibly related PRs

Suggested reviewers

  • NeOMakinG
  • premiumjibles

Poem

🐰 Hoppity hop, fees we now seek,

Energy, bandwidth, and activation tweak.
From senders to contracts the numbers align,
TRON’s path is clearer — one carrot at a time. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add TRON gas estimates for all swappers' clearly and concisely summarizes the main objective—adding gas/fee estimation across all TRON-supporting swappers.
Linked Issues check ✅ Passed The PR successfully implements all objectives from #11285: adds gas estimates for Sun.io, Relay, and Near Intents swappers; integrates estimates into quote/rate flows; TronChainAdapter improvements support all three swappers.
Out of Scope Changes check ✅ Passed All changes directly support TRON gas estimation requirements; improvements to TronChainAdapter fee calculation, new type guards, and chainSpecific data passing are all necessary and in-scope for the stated objectives.
✨ 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_all_swapper_estimates

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • TRC-20: Entity not found: Issue - Could not find referenced Issue.

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.

Base automatically changed from fix_tron_estimates to develop December 5, 2025 11:47
Resolved conflicts from squash-merged PR #11274 (Sun.io integration):
- TronChainAdapter.ts: kept improved fee estimation with from parameter and account activation
- SunioSwapper/getQuoteOrRate.ts: kept detailed TronWeb-based fee estimation (this PR's feature)
- NearIntents files: kept proper chainSpecific params with from and contractAddress

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

Co-Authored-By: Claude <noreply@anthropic.com>
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 (4)
packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts (1)

220-233: Tron fee estimation wiring looks correct; optional consistency tweak

The Tron branch now passes contractAddress and from in chainSpecific, which should let TronChainAdapter.getFeeData correctly distinguish native TRX vs TRC‑20 and estimate fees from the actual sender, aligning with the PR’s intent for accurate TRON gas estimates.

Very minor nit: you already compute const from = sendAddress at Line 77, so you could use from here instead of sendAddress for consistency with the other chain branches:

-        case CHAIN_NAMESPACE.Tron: {
-          const sellAdapter = deps.assertGetTronChainAdapter(sellAsset.chainId)
-          const contractAddress = contractAddressOrUndefined(sellAsset.assetId)
-          const feeData = await sellAdapter.getFeeData({
-            to: depositAddress,
-            value: sellAmount,
-            chainSpecific: {
-              from: sendAddress,
-              contractAddress,
-            },
-          })
+        case CHAIN_NAMESPACE.Tron: {
+          const sellAdapter = deps.assertGetTronChainAdapter(sellAsset.chainId)
+          const contractAddress = contractAddressOrUndefined(sellAsset.assetId)
+          const feeData = await sellAdapter.getFeeData({
+            to: depositAddress,
+            value: sellAmount,
+            chainSpecific: {
+              from,
+              contractAddress,
+            },
+          })

Functionally this is equivalent, so feel free to keep as-is if you prefer.

packages/swapper/src/swappers/RelaySwapper/utils/types.ts (1)

185-193: Type guard follows established patterns.

The isRelayQuoteTronItemData guard correctly uses the in operator to discriminate Tron data from other union members. The check for both type and parameter keys provides sufficient discrimination, consistent with the isRelayQuoteEvmItemData pattern.

For additional robustness, consider validating that parameter is an object:

 export const isRelayQuoteTronItemData = (
   item:
     | RelayQuoteUtxoItemData
     | RelayQuoteEvmItemData
     | RelayQuoteSolanaItemData
     | RelayQuoteTronItemData,
 ): item is RelayQuoteTronItemData => {
-  return 'type' in item && 'parameter' in item
+  return 'type' in item && 'parameter' in item && typeof item.parameter === 'object'
 }

This would prevent matching malformed data where parameter exists but isn't an object, though the current implementation is consistent with existing guards.

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

222-239: Improve HTTP error handling when creating TRX transactions

Refactoring to a requestBody object and checking txData.Error makes failures from the node more explicit, which is good. You might also want to check response.ok before response.json() to distinguish transport/HTTP errors from protocol-level Error payloads and surface a clearer error in those cases, instead of relying on JSON parse failures to flow through ErrorHandler.

packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts (1)

107-115: Receive address requirement for quotes is reasonable; consider a more specific error code

Requiring receiveAddress for Sun.io quotes makes sense now that you depend on it for TRON fee estimation. If TradeQuoteError exposes a more specific validation-oriented code for missing/invalid receive addresses, it may be preferable to use that instead of InternalError so callers can distinguish user input issues from genuine internal failures.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6f6b9cd and bdf495c.

📒 Files selected for processing (6)
  • packages/chain-adapters/src/tron/TronChainAdapter.ts (3 hunks)
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts (1 hunks)
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts (1 hunks)
  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts (2 hunks)
  • packages/swapper/src/swappers/RelaySwapper/utils/types.ts (2 hunks)
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{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/swappers/RelaySwapper/utils/types.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts
  • packages/chain-adapters/src/tron/TronChainAdapter.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.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/swappers/RelaySwapper/utils/types.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts
  • packages/chain-adapters/src/tron/TronChainAdapter.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.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/swappers/RelaySwapper/utils/types.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.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/swappers/RelaySwapper/utils/types.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts
  • packages/chain-adapters/src/tron/TronChainAdapter.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.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/swappers/RelaySwapper/utils/types.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
packages/swapper/src/swappers/**/*.ts

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

packages/swapper/src/swappers/**/*.ts: Adhere to the Swapper directory structure: each swapper resides in packages/swapper/src/swappers// with required files (SwapperName.ts, endpoints.ts, types.ts, utils/constants.ts, utils/helpers.ts)
Validate inputs and log errors for debugging in Swapper system implementations
Swapper files must be located in packages/swapper/src/swappers/ directory structure and not placed outside this location
Avoid side effects in swap logic; ensure swap methods are deterministic and stateless

Files:

  • packages/swapper/src/swappers/RelaySwapper/utils/types.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
🧠 Learnings (28)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.
Learnt from: 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
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/*/endpoints.ts : Reuse checkEvmSwapStatus utility for checking EVM swap status instead of implementing custom status checks
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/swapper/src/swappers/RelaySwapper/utils/types.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts
  • packages/chain-adapters/src/tron/TronChainAdapter.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/swapper{s,}/**/*.{ts,tsx} : ALWAYS use `makeSwapErrorRight` for swapper errors with `TradeQuoteError` enum for error codes and provide detailed error information

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/RelaySwapper/utils/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/swappers/RelaySwapper/utils/types.ts
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.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/swapper/src/swappers/RelaySwapper/utils/types.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts
  • packages/chain-adapters/src/tron/TronChainAdapter.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.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 : All swappers must implement the Swapper interface from packages/swapper/src/types.ts

Applied to files:

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

Applied to files:

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

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
  • packages/chain-adapters/src/tron/TronChainAdapter.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.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/*/endpoints.ts : Reuse checkEvmSwapStatus utility for checking EVM swap status instead of implementing custom status checks

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts
📚 Learning: 2025-11-18T09:52:51.368Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10334
File: src/lib/user/api.ts:46-105
Timestamp: 2025-11-18T09:52:51.368Z
Learning: In the shapeshift/web repository, monadic error-handling with Result types (Ok/Err from sniptt/monads) is specific to the swapper domain and is not used anywhere else in the codebase. API helpers outside the swapper domain (e.g., user API, notification services) should use traditional throw/catch error handling patterns instead of Result monads.

Applied to files:

  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/*.{ts,tsx} : 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

Applied to files:

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

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts
📚 Learning: 2025-12-04T22:57:50.839Z
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.839Z
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-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/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-08-26T19:04:38.672Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10369
File: packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts:167-176
Timestamp: 2025-08-26T19:04:38.672Z
Learning: In packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts, when processing assets from data.assets.reduce(), the team prefers using empty catch blocks to gracefully skip any assets that fail processing, rather than specific error type handling, to avoid useless noise and ensure robust asset filtering.

Applied to files:

  • packages/chain-adapters/src/tron/TronChainAdapter.ts
🧬 Code graph analysis (3)
packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts (1)
packages/utils/src/index.ts (1)
  • contractAddressOrUndefined (46-47)
packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts (3)
packages/swapper/src/utils.ts (1)
  • makeSwapErrorRight (31-47)
src/state/apis/swapper/types.ts (1)
  • TradeQuoteError (39-39)
packages/utils/src/index.ts (1)
  • contractAddressOrUndefined (46-47)
packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts (1)
packages/utils/src/index.ts (1)
  • contractAddressOrUndefined (46-47)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install and Cache
🔇 Additional comments (6)
packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts (1)

224-235: Tron chainSpecific wiring for fee estimation looks correct

Passing contractAddress = contractAddressOrUndefined(sellAsset.assetId) plus from: sendAddress into assertGetTronChainAdapter(...).getFeeData should give the adapter enough context to distinguish TRC‑20 vs native TRX and to use the real sender for bandwidth/account-activation estimation when a wallet is connected, while still allowing adapter-side fallbacks when sendAddress is undefined. This is consistent with how other chain branches enrich chainSpecific and aligns with the PR’s TRON fee‑estimation objectives; no changes requested here.

packages/swapper/src/swappers/RelaySwapper/utils/types.ts (3)

136-141: LGTM! Union properly extended.

The RelayQuoteItem.data union correctly includes RelayQuoteTronItemData, enabling type-safe handling of Tron quotes alongside existing chain types.


155-183: Required updates for proper type narrowing.

The parameter unions for isRelayQuoteUtxoItemData, isRelayQuoteEvmItemData, and isRelayQuoteSolanaItemData correctly include RelayQuoteTronItemData. This is necessary for TypeScript's discriminated union type narrowing to work properly when these guards are called on RelayQuoteItem.data.


126-133: Type guard and type definition are inconsistent.

The isRelayQuoteTronItemData type guard checks for the presence of type and parameter properties, but the RelayQuoteTronItemData type definition marks both as optional. This creates a type safety gap: after the type guard passes, TypeScript doesn't properly narrow the type, yet the code still uses optional chaining (parameter?.contract_address).

Either make type and parameter required fields in the type definition (matching the type guard expectations like RelayQuoteSolanaItemData does), or update the type guard to only check for the fields that are actually guaranteed after it passes.

⛔ Skipped due to learnings
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:21:12.774Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS make properties optional with `?` when they might not be present in TypeScript type definitions
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10272
File: src/context/WalletProvider/MobileWallet/mobileMessageHandlers.ts:61-0
Timestamp: 2025-08-13T15:52:25.116Z
Learning: In the ShapeShift web codebase, specifically in src/context/WalletProvider/MobileWallet/mobileMessageHandlers.ts, message variants in the Message union type do not include inline comments documenting their expected return types. The codebase follows a pattern of keeping these type definitions clean without such documentation comments.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP155SignTypedDataConfirmation.tsx:14-15
Timestamp: 2025-09-12T09:58:50.671Z
Learning: In EIP155SignTypedDataConfirmation.tsx, gomesalexandre is comfortable with null returns for missing message data as TypeScript type safety guards, viewing them as compile-time protections rather than runtime scenarios that need explicit error handling and user feedback. He considers these TypeScript-level safeguards sufficient and prefers not to add defensive runtime error handling for what should be type-guaranteed scenarios.
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.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10181
File: packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeQuote.ts:0-0
Timestamp: 2025-08-04T09:33:49.191Z
Learning: In Solana web3.js VersionedTransaction.message.addressTableLookups, the addressTableLookups property is typed as always defined (not optional), so optional chaining operators are unnecessary when accessing this property.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10181
File: packages/swapper/src/swappers/ButterSwap/swapperApi/getTradeQuote.ts:0-0
Timestamp: 2025-08-04T09:33:49.191Z
Learning: In Solana web3.js VersionedTransaction.message.addressTableLookups, the addressTableLookups property is typed as always defined (not optional), so optional chaining operators are unnecessary when accessing this property.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10810
File: src/plugins/walletConnectToDapps/utils/tenderly/index.ts:212-0
Timestamp: 2025-10-15T15:57:39.956Z
Learning: gomesalexandre uses discriminated union patterns (e.g., `isEIP1559 ? { max_fee_per_gas, max_priority_fee_per_gas } : { gas_price }`) in WalletConnect flows without additional validation guards, trusting that the runtime data structure ensures mutual exclusivity between EIP-1559 and legacy gas pricing fields.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/state/slices/actionSlice/types.ts:91-94
Timestamp: 2025-08-13T17:10:05.685Z
Learning: In the ActionGenericTransactionMetadata type in src/state/slices/actionSlice/types.ts, the thorMemo field is typed as `string | null` (rather than the more common `string | undefined` pattern) because it receives its value from the memo field returned by useSendThorTx(), which is also typed as `string | null`. This maintains type consistency across the data flow.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/state/slices/actionSlice/types.ts:91-94
Timestamp: 2025-08-13T17:10:05.685Z
Learning: In the ActionGenericTransactionMetadata type in src/state/slices/actionSlice/types.ts, the thorMemo field is typed as `string | null` (rather than the more common `string | undefined` pattern) because it receives its value from the memo field returned by useSendThorTx(), which is also typed as `string | null`. This maintains type consistency across the data flow.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10139
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx:109-115
Timestamp: 2025-07-29T15:04:28.083Z
Learning: In src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx, the component is used under an umbrella that 100% of the time contains the quote, making the type assertion `activeTradeQuote?.steps[currentHopIndex] as TradeQuoteStep` safe. Adding conditional returns before hooks would violate React's Rules of Hooks.
packages/swapper/src/swappers/RelaySwapper/utils/getTrade.ts (1)

629-638: LGTM! Tron handling follows established patterns.

The implementation correctly extracts the contract address from Tron-specific quote data and follows the same pattern as existing BTC, EVM, and Solana handlers. The optional to field in relayTransactionMetadata is appropriately typed to accept the optional contract_address from the Relay API response. Minimal metadata (relayId and contract address) is appropriate if Relay handles Tron transaction construction internally.

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

409-455: TRX bandwidth estimation and account-activation fee integration look sound

Using estimationFrom = from || to for sendTrx makes the bandwidth estimate better match real transactions that originate from the sender, while still having a safe fallback when from is absent. The new /wallet/getaccount probe and accountActivationFee addition for non-contract (native TRX) transfers also align with the intent to cover 1 TRX activation costs without making fee estimation brittle since errors are swallowed.

Account activation (1 TRX) occurs when ANY transaction is sent to a
new address, not just when selling native TRX. Previously, the
activation check was only in the TRX sell path, causing swaps like
USDT → TRX to new addresses to underestimate fees by 1 TRX.

Moved activation check outside the sell-type conditional so it applies
to all swaps (TRC-20 and native TRX).

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

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts (1)

48-48: Remove unused dependency reference.

The _assertGetTronChainAdapter variable is destructured but never used in the function. Since fee estimation now uses TronWeb directly (line 126), this dependency reference can be removed.

Apply this diff:

-    const { assertGetTronChainAdapter: _assertGetTronChainAdapter } = deps
+    // Fee estimation uses TronWeb directly, no chain adapter needed
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bdf495c and 6d24430.

📒 Files selected for processing (1)
  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{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/swappers/SunioSwapper/utils/getQuoteOrRate.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/swappers/SunioSwapper/utils/getQuoteOrRate.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/swappers/SunioSwapper/utils/getQuoteOrRate.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/swappers/SunioSwapper/utils/getQuoteOrRate.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/swappers/SunioSwapper/utils/getQuoteOrRate.ts
packages/swapper/src/swappers/**/*.ts

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

packages/swapper/src/swappers/**/*.ts: Adhere to the Swapper directory structure: each swapper resides in packages/swapper/src/swappers// with required files (SwapperName.ts, endpoints.ts, types.ts, utils/constants.ts, utils/helpers.ts)
Validate inputs and log errors for debugging in Swapper system implementations
Swapper files must be located in packages/swapper/src/swappers/ directory structure and not placed outside this location
Avoid side effects in swap logic; ensure swap methods are deterministic and stateless

Files:

  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
🧠 Learnings (24)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/utils/EIP155RequestHandlerUtil.ts:94-103
Timestamp: 2025-09-12T13:43:19.770Z
Learning: gomesalexandre has implemented a reliable gasLimit flow in WalletConnect dApps where Tenderly simulation provides gas estimates that get written to the form via setValue in GasSelectionMenu.tsx, making customTransactionData.gasLimit the primary reliable source. The sendTransaction.gasLimit fallback is kept as "paranoia" but may rarely be hit in practice due to this simulation-based architecture.
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
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/*/endpoints.ts : Reuse checkEvmSwapStatus utility for checking EVM swap status instead of implementing custom status checks
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-03T22:31:30.786Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10985
File: packages/swapper/src/swappers/PortalsSwapper/getPortalsTradeQuote/getPortalsTradeQuote.ts:0-0
Timestamp: 2025-11-03T22:31:30.786Z
Learning: In packages/swapper/src/swappers/PortalsSwapper, the rate and quote files intentionally use different approaches for calculating buyAmountBeforeSlippageCryptoBaseUnit: getPortalsTradeRate.tsx uses minOutputAmount / (1 - buffer) for conservative estimates, while getPortalsTradeQuote.ts uses outputAmount / (1 - buffer) for final quote display. This difference is validated by on-chain simulation testing and is intentional.

Applied to files:

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

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.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/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.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/*/endpoints.ts : Reuse checkEvmSwapStatus utility for checking EVM swap status instead of implementing custom status checks

Applied to files:

  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.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/swappers/SunioSwapper/utils/getQuoteOrRate.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/swappers/SunioSwapper/utils/getQuoteOrRate.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/swappers/SunioSwapper/utils/getQuoteOrRate.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/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.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 : Validate inputs and log errors for debugging in Swapper system implementations

Applied to files:

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

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
📚 Learning: 2025-08-04T16:02:27.360Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10171
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandedStepperSteps.tsx:458-458
Timestamp: 2025-08-04T16:02:27.360Z
Learning: In multi-hop swap transactions, last hop sell transactions might not be detected by the swapper (unlike buy transactions which are always known immediately). The conditional stepSource logic for last hop buy transactions (`isLastHopSellTxSeen ? stepSource : undefined`) serves as defensive programming for future multi-hop support with intermediate chains, even though multi-hop functionality is not currently supported in production.

Applied to files:

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

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
📚 Learning: 2025-11-18T09:52:51.368Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10334
File: src/lib/user/api.ts:46-105
Timestamp: 2025-11-18T09:52:51.368Z
Learning: In the shapeshift/web repository, monadic error-handling with Result types (Ok/Err from sniptt/monads) is specific to the swapper domain and is not used anywhere else in the codebase. API helpers outside the swapper domain (e.g., user API, notification services) should use traditional throw/catch error handling patterns instead of Result monads.

Applied to files:

  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/*.{ts,tsx} : 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

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.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/swappers/SunioSwapper/utils/getQuoteOrRate.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/swappers/SunioSwapper/utils/getQuoteOrRate.ts
🧬 Code graph analysis (1)
packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts (3)
packages/swapper/src/utils.ts (1)
  • makeSwapErrorRight (31-47)
src/state/apis/swapper/types.ts (1)
  • TradeQuoteError (39-39)
packages/utils/src/index.ts (1)
  • contractAddressOrUndefined (46-47)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install and Cache
🔇 Additional comments (1)
packages/swapper/src/swappers/SunioSwapper/utils/getQuoteOrRate.ts (1)

121-199: Fee estimation logic is correct - clarifying previous review concern.

The network fee estimation implementation is sound. The activation fee check (lines 134-151) correctly occurs before the isSellingNativeTrx branch (line 155) and applies to all swaps regardless of asset type. Both the native TRX path (lines 165-168) and TRC-20 path (lines 185-188) include accountActivationFee.

The use of isSellingNativeTrx (line 124) to determine the fee estimation path is correct because contract call fees depend on the input asset type (what you're sending to the contract), not the output. The activation fee correctly applies to both paths when sending to a new address.

The previous review comment suggesting activation should depend on buyAsset appears to have misread the code structure—the activation check is not conditional on the branch.

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.

https://jam.dev/c/c372cb09-8ec6-4e61-8d6f-e3ba27f03aec

Seems way better now, finally TRON is usable 😆

We should be close to be able to send to production now

@NeOMakinG NeOMakinG enabled auto-merge (squash) December 5, 2025 12:34
@NeOMakinG NeOMakinG disabled auto-merge December 5, 2025 12:46
@NeOMakinG NeOMakinG merged commit df842b9 into develop Dec 5, 2025
4 checks passed
@NeOMakinG NeOMakinG deleted the feat_tron_all_swapper_estimates branch December 5, 2025 12:46
@coderabbitai coderabbitai bot mentioned this pull request Dec 8, 2025
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 - ensure all swappers have gas estimates

2 participants