Skip to content

Conversation

@NeOMakinG
Copy link
Collaborator

@NeOMakinG NeOMakinG commented Nov 29, 2025

Description

Two zozio one stone:

  • Implement Cetus so we can swap from SUI to any other sui tokens and the contrary
  • Implementing SUI tokens sends + balances updates

Issue (if applicable)

Nop, follow up for sui support

Risk

Medium, behind a flag, new swapper, could be high but hey need velocity

High Risk PRs Require 2 approvals

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

Testing

  • Try to swap from X chain to SUI native asset
  • Swap from SUI native asset to another asset
  • Swap back
  • Try very well known token like USDC to USDT on sui and the contrary
  • Near seems to be supporting some swaps too, try swapping from SUI to USDC on near, and the contrary
  • All balances should be updated

Note:
Balances are not updated for the receive account if its internal account send (account 0 to 1), will be fixed by the same issue than TRON

Engineering

Operations

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

Screenshots (if applicable)

https://jam.dev/c/b082639f-b862-4b34-9509-45adc88e65ae

Summary by CodeRabbit

  • New Features

    • Cetus added as a new swapper: in-interface icon and end-to-end trade support (quotes, rates, unsigned SUI transactions, fee checks, status)
  • Configuration

    • New feature flag to enable/disable Cetus Swap (env-controlled; enabled in development)
  • Behavior

    • Cetus excluded from cross-account trades; default slippage for Cetus introduced
  • Chores

    • Network endpoints and a runtime dependency added to support Cetus integrations; state/migrations updated to include Cetus flag

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

NeOMakinG and others added 15 commits November 27, 2025 16:14
* fix: restore desktop accounts page routing

When the wallet route was removed from desktop in commit 3356c29,
the accounts page routing was also removed, causing /wallet/accounts
to redirect to /trade instead of showing account details.

This restores the accounts route for desktop while keeping other
/wallet/* routes redirecting to /trade as intended.

Fixes #11058

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

Co-Authored-By: Claude <[email protected]>

* refactor: unify accounts routing to use /accounts path

Changed from dual routing (/wallet/accounts on desktop, /accounts on mobile)
to a unified /accounts route that works on both platforms.

Changes:
- Wrapped Accounts component with Main layout and DashboardHeader
- Removed /wallet/accounts route from Desktop Dashboard
- Updated all link generators to use /accounts path
- Removed conditional basePath logic

This simplifies the codebase and provides consistent routing across platforms.

Related to #11058

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

Co-Authored-By: Claude <[email protected]>

* feat: make it better

* refactor: unify accounts routing and complete wallet route removal cleanup

This refactor addresses routing issues from PR #10923 that removed the
desktop wallet route but left incomplete cleanup.

Routing Changes:
- Unified all account routes from /wallet/accounts to /accounts
- Updated route parsing hooks (useRouteAccountId, useRouteAssetId)
- Updated all link generators to use /accounts path
- Desktop /accounts list redirects to /trade (only specific account pages work)
- Mobile /accounts list works as expected

Component Cleanup (PR #10923 missed items):
- Removed desktop wallet tabs (Overview, Wallet, DeFi, Activity)
- Removed desktop net worth display from account pages
- Deleted orphaned DashboardTab.tsx component (69 lines)
- Removed unused route props from AccountDetails, AssetAccountDetails, Asset
- Made AssetHeader consistent across all account pages

Bug Fixes:
- AccountEntryRow now routes to account pages instead of asset pages
- Fixed AccountToken redirect path
- Updated MixPanel tracking for new route structure
- Cleaned up sitemap.txt (removed 4 deprecated routes)

Fixes #11058, #11175

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

Co-Authored-By: Claude <[email protected]>

* feat: cleanup

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Jibles <[email protected]>
Bumps [node-forge](https://github.com/digitalbazaar/forge) from 1.3.1 to 1.3.2.
- [Changelog](https://github.com/digitalbazaar/forge/blob/main/CHANGELOG.md)
- [Commits](digitalbazaar/forge@v1.3.1...v1.3.2)

---
updated-dependencies:
- dependency-name: node-forge
  dependency-version: 1.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@NeOMakinG NeOMakinG requested a review from a team as a code owner November 29, 2025 22:07
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 29, 2025

Warning

Rate limit exceeded

@gomesalexandre has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 5 minutes and 33 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between c625dba and 24090e0.

📒 Files selected for processing (1)
  • src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx (2 hunks)
📝 Walkthrough

Walkthrough

Adds Cetus Sui swapper: feature flag and env entries, CSP connect-src additions, Cetus SDK dependency, new Cetus swapper implementation (quotes, rates, unsigned tx, fees), helper utilities, Sui chain-adapter changes, UI icon, state/feature gating, tests, and a migration entry.

Changes

Cohort / File(s) Change Summary
Environment & Feature Configuration
\.env`, `.env.development`, `src/config.ts`, `src/state/slices/preferencesSlice/preferencesSlice.ts`, `src/test/mocks/store.ts``
Added VITE_FEATURE_CETUS_SWAP env var (default false; true in dev), validator in config, and CetusSwap feature flag wired into preferences and test mocks.
Security & CSP
\headers/csps/chains/sui.ts``
Expanded Sui connect-src CSP array to include env.VITE_SUI_NODE_URL, https://mainnet.suiet.app/, https://api-sui.cetus.zone, and https://fullnode.mainnet.sui.io/.
Dependencies
\package.json``
Added dependency @cetusprotocol/cetus-sui-clmm-sdk version 5.4.0.
Sui Chain Adapter
\packages/chain-adapters/src/sui/SuiChainAdapter.ts``
Enhanced balance/token handling, concurrent balance fetch, per-token metadata with fallbacks, normalized assetId generation, coin-resolution token transfers using splitCoins, gasBudget/gasPrice numeric coercion, and fee fast-path for coin-type tokenIds.
Swapper Core Registration
\packages/swapper/src/constants.ts`, `packages/swapper/src/index.ts`, `packages/swapper/src/types.ts``
Added SwapperName.Cetus, SuiFeeData type, extended QuoteFeeData.chainSpecific, registered Cetus in swappers map with default slippage, and re-exported CetusSwapper.
Cetus Swapper Surface
\packages/swapper/src/swappers/CetusSwapper/CetusSwapper.ts`, `packages/swapper/src/swappers/CetusSwapper/endpoints.ts``
New cetusSwapper and cetusApi implementing Swapper/SwapperApi: trade quote, trade rate, unsigned SUI tx generation, fee retrieval, and trade status checking.
Cetus API Methods
\packages/swapper/src/swappers/CetusSwapper/swapperApi/getTradeQuote.ts`, `packages/swapper/src/swappers/CetusSwapper/swapperApi/getTradeRate.ts`**
Implemented quote and rate retrieval: input validation, pool discovery, preswap calculations, fee estimation, rate construction, and structured error handling.
Cetus Utilities
\packages/swapper/src/swappers/CetusSwapper/utils/constants.ts`, `packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts`, `packages/swapper/src/swappers/CetusSwapper/index.ts``
Added supported-chain constants, type guard, SDK lazy-loader, coin-type helpers, swap-direction, pool discovery, slippage/limit calculations, swap amount calculation utilities, and re-exported constants.
Token Namespace Support
\packages/utils/src/index.ts``
Updated isToken to treat ASSET_NAMESPACE.suiCoin as a token.
State Management & Feature Gating
\src/state/helpers.ts`, `src/state/migrations/index.ts``
Added Cetus to isCrossAccountTradeSupported (disabled), extended getEnabledSwappers to include CetusSwap gating, and appended migration entry 230.
UI Integration
\src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx`**
Added SwapperName.Cetus case returning new CetusIcon.
Testing
\packages/caip/src/adapters/coingecko/index.test.ts`**
Added Sui-mainnet USDC asset id to USD Coin test fixture.
Minor Cleanup
\src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx`**
Removed an inline comment; no behavior change.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant UI
    participant CetusAPI as CetusSwapper API
    participant Helpers as Cetus Helpers
    participant SDK as Cetus SDK
    participant ChainAdapter as SuiChainAdapter
    participant SuiNet as Sui Network

    User->>UI: choose Cetus and submit swap params
    UI->>CetusAPI: getTradeQuote(params)
    CetusAPI->>Helpers: findBestPool(sellCoinType,buyCoinType)
    Helpers->>SDK: query pools
    SDK-->>Helpers: pool list
    Helpers-->>CetusAPI: selected pool
    CetusAPI->>Helpers: calculateSwapAmounts(pool,assets,amount)
    Helpers->>SDK: preswap
    SDK-->>Helpers: estimated amounts & fee
    Helpers-->>CetusAPI: estimates
    CetusAPI->>ChainAdapter: getFeeData()
    ChainAdapter->>SuiNet: getReferenceGasPrice()
    SuiNet-->>ChainAdapter: gasPrice
    ChainAdapter-->>CetusAPI: fee data
    CetusAPI-->>UI: TradeQuote (amounts, fees)
    UI->>CetusAPI: getUnsignedSuiTransaction(quote)
    CetusAPI->>Helpers: determineSwapDirection(...)
    CetusAPI->>SDK: buildSwapPayload & tx bytes
    SDK-->>CetusAPI: intentMessageBytes, txBytes
    CetusAPI-->>UI: unsigned tx (addressNList, intentMessageBytes)
    UI->>SuiNet: broadcast signed tx
    SuiNet-->>UI: txHash
    UI->>CetusAPI: checkTradeStatus(txHash)
    CetusAPI->>ChainAdapter: checkSuiSwapStatus(txHash)
    ChainAdapter->>SuiNet: query tx status
    SuiNet-->>ChainAdapter: status
    ChainAdapter-->>CetusAPI: TradeStatus
    CetusAPI-->>UI: trade status
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing careful review:
    • packages/swapper/src/swappers/CetusSwapper/* (pool discovery, preswap, transaction bytes, error paths)
    • packages/chain-adapters/src/sui/SuiChainAdapter.ts (coin resolution, splitCoins usage, fee fast-path)
    • Feature-gating & state changes: src/state/helpers.ts and preferencesSlice
    • CSP additions and new external dependency usage (package.json)

Possibly related PRs

Suggested labels

high risk

Suggested reviewers

  • premiumjibles

Poem

🐰 I hopped to Cetus, found a pool so bright,
Swaps on Sui now sparkle in moonlight byte.
Quotes and fees, pools picked with care,
A carrot-coded trade floats on the air.
Hop on — the swap is ready, swift and fair!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: implementing Cetus swapper for SUI token swaps, which aligns with the PR objectives and file modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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 implement-sui to develop December 1, 2025 14:20
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: 7

🧹 Nitpick comments (6)
packages/chain-adapters/src/sui/SuiChainAdapter.ts (1)

464-467: Document the rationale for the hardcoded gas estimate.

The 50_000_000n (50M MIST) gas estimate is a reasonable approximation for simple token transfers, but consider adding a comment explaining this value. If actual token transfer costs vary significantly, users could experience transaction failures or overpay.

       if (tokenId && tokenId.startsWith('0x') && tokenId.includes('::')) {
+        // Pre-estimated gas for standard token transfers
+        // Based on typical Sui token transfer costs; includes 20% buffer
         const estimatedGas = 50_000_000n
         const gasBudget = ((estimatedGas * 120n) / 100n).toString()
         const txFee = estimatedGas.toString()
.env (1)

232-232: Consider reordering for consistency.

The linter suggests placing VITE_FEATURE_CETUS_SWAP before VITE_FEATURE_TRON to maintain alphabetical ordering.

Apply this diff to fix the ordering:

 VITE_FEATURE_TRON=false
+VITE_FEATURE_CETUS_SWAP=false
 VITE_SUI_NODE_URL=https://fullnode.mainnet.sui.io:443
-VITE_FEATURE_CETUS_SWAP=false
 VITE_FEATURE_MONAD=false
.env.development (1)

94-94: Consider reordering for consistency.

The linter suggests placing VITE_FEATURE_CETUS_SWAP before VITE_FEATURE_MONAD to maintain alphabetical ordering.

Apply this diff to fix the ordering:

+VITE_FEATURE_CETUS_SWAP=true
 VITE_FEATURE_TRON=true
 VITE_FEATURE_MONAD=true
-VITE_FEATURE_CETUS_SWAP=true
packages/swapper/src/swappers/CetusSwapper/swapperApi/getTradeRate.ts (1)

116-150: Simplify rates array construction.

The rates array is created empty and then a single element is pushed. Consider returning the array literal directly for clarity.

-    const protocolFees: Record<AssetId, ProtocolFee> = {}
-
-    const rates: TradeRate[] = []
-
-    const tradeRate: TradeRate = {
+    const protocolFees: Record<AssetId, ProtocolFee> = {}
+
+    const tradeRate: TradeRate = {
       id: uuid(),
       // ... rest of tradeRate
     }

-    rates.push(tradeRate)
-
-    return Ok(rates)
+    return Ok([tradeRate])
packages/swapper/src/swappers/CetusSwapper/endpoints.ts (1)

101-105: Document or extract magic bytes as constants.

The intent message prefix bytes [0, 0, 0] are SUI-specific protocol values (intent scope, version, app ID). Consider extracting these as named constants for clarity.

+const SUI_INTENT_SCOPE_TRANSACTION_DATA = 0
+const SUI_INTENT_VERSION = 0
+const SUI_INTENT_APP_ID = 0
+
     const intentMessage = new Uint8Array(3 + transactionBytes.length)
-    intentMessage[0] = 0
-    intentMessage[1] = 0
-    intentMessage[2] = 0
+    intentMessage[0] = SUI_INTENT_SCOPE_TRANSACTION_DATA
+    intentMessage[1] = SUI_INTENT_VERSION
+    intentMessage[2] = SUI_INTENT_APP_ID
     intentMessage.set(transactionBytes, 3)
packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts (1)

61-85: Function name vs. implementation mismatch.

findBestPool suggests optimal pool selection, but the implementation returns the first pool with any liquidity. Consider renaming to findPoolWithLiquidity or enhancing to select by highest liquidity.

To actually find the best pool by liquidity:

-  const poolWithLiquidity = pools.find(pool => {
-    const hasLiquidity = pool.liquidity && bnOrZero(pool.liquidity).gt(0)
-    return hasLiquidity
-  })
+  const poolsWithLiquidity = pools.filter(pool => {
+    return pool.liquidity && bnOrZero(pool.liquidity).gt(0)
+  })
+
+  if (poolsWithLiquidity.length === 0) {
+    console.warn('[Cetus] No pools with liquidity found for', sellCoinType, buyCoinType, {
+      totalPools: pools.length,
+      pools: pools.map(p => ({ id: p.poolAddress, liquidity: p.liquidity })),
+    })
+    return undefined
+  }
+
+  const poolWithLiquidity = poolsWithLiquidity.reduce((best, current) =>
+    bnOrZero(current.liquidity).gt(bnOrZero(best.liquidity)) ? current : best
+  )

gomesalexandre and others added 4 commits December 1, 2025 23:58
Reorder imports to comply with ESLint rules by moving local imports
after external dependencies.

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

Co-Authored-By: Claude <[email protected]>
Fix three critical issues in Cetus swapper implementation:

1. Decimals assignment bug (CRITICAL):
   - decimalsB was incorrectly checking coinTypeB instead of coinTypeA
   - This caused wrong decimal precision in swap calculations
   - Fixed to use correct conditional based on coinTypeA

2. Slippage calculation bug (CRITICAL):
   - amount_limit was using (1 + slippage) instead of (1 - slippage)
   - Per Cetus docs: when by_amount_in=true, amount_limit is minimum output
   - Fixed isBuyAmount parameter from false to true

3. Remove unused DEFAULT_SLIPPAGE constant:
   - Defined as 0.5 (50%) which conflicts with correct 0.005 (0.5%)
   - Constant was completely unused
   - Removed to avoid confusion

4. Fix coingecko adapter test failures:
   - Restored missing chain exports (bitcoin, ethereum, polygon, etc.)
   - Added SUI USDC to test expectations
   - All 14 tests now pass

5. Update Cetus SDK to 5.4.0:
   - Pin exact version (no caret) per CodeRabbit recommendation
   - Verified type-check passes with new version

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

Co-Authored-By: Claude <[email protected]>
Remove inaccurate comment claiming tx.splitCoins "handles merging and
splitting automatically". splitCoins only operates on a single coin
object and does not automatically merge multiple coins.

Current implementation uses first coin object only. Multi-coin merging
can be implemented later if needed.

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

Co-Authored-By: Claude <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
packages/swapper/src/swappers/CetusSwapper/endpoints.ts (1)

56-58: SDK instance mutation violates determinism and statefulness guidelines.

Setting sdk.senderAddress = from mutates the shared singleton, violating the guideline "Avoid side effects in swap logic; ensure swap methods are deterministic and stateless." This creates non-deterministic behavior where concurrent operations could interfere with each other.

Consider creating a per-transaction SDK instance or using SDK methods that accept the sender address as a parameter rather than mutating instance state.

packages/chain-adapters/src/sui/SuiChainAdapter.ts (1)

279-291: Single-coin selection for Sui tokens can fail with fragmented balances (same concern as prior review)

Both the send path and the fee-estimation path split from coins.data[0] only. If the first coin object has insufficient balance while the user has enough total balance across multiple coins of the same type, tx.splitCoins/tx.build will fail even though the account as a whole can cover value.

At minimum, it would be better to verify that the chosen coin’s balance covers value and surface a clear error when it doesn’t, instead of failing deep in transaction building. Longer term, multi-coin selection/aggregation would avoid this edge-case entirely.

A minimal improvement could look like:

-      if (tokenId) {
-        // Token transfer transaction - tokenId is the coin type (e.g., 0x...::module::Type)
-        // We need to get coin objects of this type owned by the sender
-        const coins = await this.client.getCoins({
-          owner: from,
-          coinType: tokenId,
-        })
-
-        if (!coins.data || coins.data.length === 0) {
-          throw new Error(`No coins found for type ${tokenId}`)
-        }
-
-        const [coinToSend] = tx.splitCoins(tx.object(coins.data[0].coinObjectId), [value])
-        tx.transferObjects([coinToSend], to)
-      } else {
+      if (tokenId) {
+        const coins = await this.client.getCoins({
+          owner: from,
+          coinType: tokenId,
+        })
+
+        if (!coins.data || coins.data.length === 0) {
+          throw new Error(`No coins found for type ${tokenId}`)
+        }
+
+        const primaryCoin = coins.data[0]
+
+        if (BigInt(primaryCoin.balance) < BigInt(value)) {
+          throw new Error(
+            `Insufficient balance in primary coin object for type ${tokenId}; ` +
+              `coin consolidation is not yet supported.`,
+          )
+        }
+
+        const [coinToSend] = tx.splitCoins(tx.object(primaryCoin.coinObjectId), [value])
+        tx.transferObjects([coinToSend], to)
+      } else {
         // Native SUI transfer
         const [coin] = tx.splitCoins(tx.gas, [value])
         tx.transferObjects([coin], to)
       }

and similarly in getFeeData:

-      if (tokenId) {
-        // Token transfer - get coin objects for this token type
-        const coins = await this.client.getCoins({
-          owner: from,
-          coinType: tokenId,
-        })
-
-        if (!coins.data || coins.data.length === 0) {
-          throw new Error(`No coins found for type ${tokenId}`)
-        }
-
-        const [coin] = tx.splitCoins(tx.object(coins.data[0].coinObjectId), [value])
-        tx.transferObjects([coin], to)
-      } else {
+      if (tokenId) {
+        const coins = await this.client.getCoins({
+          owner: from,
+          coinType: tokenId,
+        })
+
+        if (!coins.data || coins.data.length === 0) {
+          throw new Error(`No coins found for type ${tokenId}`)
+        }
+
+        const primaryCoin = coins.data[0]
+
+        if (BigInt(primaryCoin.balance) < BigInt(value)) {
+          throw new Error(
+            `Insufficient balance in primary coin object for type ${tokenId}; ` +
+              `coin consolidation is not yet supported.`,
+          )
+        }
+
+        const [coin] = tx.splitCoins(tx.object(primaryCoin.coinObjectId), [value])
+        tx.transferObjects([coin], to)
+      } else {
         const [coin] = tx.splitCoins(tx.gas, [value])
         tx.transferObjects([coin], to)
       }

This keeps the current “first coin only” behavior but avoids opaque failures when balances are fragmented.

Also applies to: 487-499

🧹 Nitpick comments (1)
packages/chain-adapters/src/sui/SuiChainAdapter.ts (1)

120-210: Token enumeration and Sui coin assetId generation look good; consider trimming debug logs

The new getAccount logic correctly:

  • Fetches native + all balances concurrently.
  • Filters out the native SUI coin and zero balances.
  • Normalizes coinType addresses and uses ASSET_NAMESPACE.suiCoin + toAssetId for stable Sui token assetIds.
  • Falls back cleanly when metadata is missing or fails.

The only concern is the multiple console.log/console.warn calls in this hot path, which can be noisy in production. Consider removing them or routing through the project’s structured logging utilities if ongoing visibility is needed.

Also applies to: 213-219

📜 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 27fe31d and 3b3107a.

⛔ Files ignored due to path filters (2)
  • packages/caip/src/adapters/coingecko/generated/index.ts is excluded by !**/generated/**
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (6)
  • package.json (1 hunks)
  • packages/caip/src/adapters/coingecko/index.test.ts (2 hunks)
  • packages/chain-adapters/src/sui/SuiChainAdapter.ts (4 hunks)
  • packages/swapper/src/swappers/CetusSwapper/endpoints.ts (1 hunks)
  • packages/swapper/src/swappers/CetusSwapper/utils/constants.ts (1 hunks)
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{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/CetusSwapper/utils/constants.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/swapper/src/swappers/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts
  • packages/chain-adapters/src/sui/SuiChainAdapter.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/CetusSwapper/utils/constants.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/swapper/src/swappers/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts
  • packages/chain-adapters/src/sui/SuiChainAdapter.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/CetusSwapper/utils/constants.ts
  • packages/swapper/src/swappers/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.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/CetusSwapper/utils/constants.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/swapper/src/swappers/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts
  • packages/chain-adapters/src/sui/SuiChainAdapter.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/CetusSwapper/utils/constants.ts
  • packages/swapper/src/swappers/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.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/CetusSwapper/utils/constants.ts
  • packages/swapper/src/swappers/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts
packages/swapper/src/swappers/*/utils/constants.ts

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

Define supported chain IDs for each swapper in utils/constants.ts with both 'sell' and 'buy' properties following the pattern: SupportedChainIds type

Files:

  • packages/swapper/src/swappers/CetusSwapper/utils/constants.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.test.{ts,tsx,js,jsx}: Write tests for critical business logic
Test edge cases and error conditions
Use descriptive test names that explain behavior
Keep tests isolated and independent
Mock external dependencies appropriately

Files:

  • packages/caip/src/adapters/coingecko/index.test.ts
packages/swapper/src/swappers/*/*.ts

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

packages/swapper/src/swappers/*/*.ts: All swappers must implement the Swapper interface from packages/swapper/src/types.ts
Implement filterAssetIdsBySellable method to filter assets by supported chain IDs in the sell property
Implement filterBuyAssetsBySellAssetId method to filter assets by supported chain IDs in the buy property
Reuse executeEvmTransaction utility for EVM-based swappers instead of implementing custom transaction execution

Files:

  • packages/swapper/src/swappers/CetusSwapper/endpoints.ts
packages/swapper/src/swappers/*/endpoints.ts

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

packages/swapper/src/swappers/*/endpoints.ts: All swapper API implementations must implement the SwapperApi interface from packages/swapper/src/types.ts
Reuse checkEvmSwapStatus utility for checking EVM swap status instead of implementing custom status checks

Files:

  • packages/swapper/src/swappers/CetusSwapper/endpoints.ts
🧠 Learnings (43)
📓 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: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/components/AssetSearch/components/AssetList.tsx:2-2
Timestamp: 2025-08-08T15:00:49.887Z
Learning: Project shapeshift/web: NeOMakinG prefers avoiding minor a11y/UI nitpicks (e.g., adding aria-hidden to decorative icons in empty states like src/components/AssetSearch/components/AssetList.tsx) within feature PRs; defer such suggestions to a follow-up instead of blocking the PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/ButtonWalletPredicate/ButtonWalletPredicate.tsx:7-7
Timestamp: 2025-08-27T09:47:06.275Z
Learning: In shapeshift/web project, NeOMakinG consistently prefers to defer UI/UX improvements and refactoring work (like the Drawer.Close hack fix in ButtonWalletPredicate.tsx) to follow-up PRs rather than expanding the scope of feature PRs, even when the improvements would enhance robustness.
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: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/components/Stake/components/StakeSummary.tsx:112-114
Timestamp: 2025-08-22T13:00:44.879Z
Learning: NeOMakinG prefers to keep PR changes minimal and focused on the core objectives, avoiding cosmetic or defensive code improvements that aren't directly related to the PR scope, even when they would improve robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/pages/Dashboard/components/AccountList/AccountTable.tsx:60-0
Timestamp: 2025-09-02T08:34:08.157Z
Learning: NeOMakinG prefers code review comments to focus only on actual PR changes, not pre-existing code issues, unless there are critical security or correctness concerns directly related to the new functionality.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:42-86
Timestamp: 2025-08-08T11:41:22.794Z
Learning: NeOMakinG prefers not to include refactors in move-only PRs; such suggestions should be deferred to follow-up issues instead of being applied within the same PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/Table/Table.theme.ts:177-180
Timestamp: 2025-09-02T12:38:46.940Z
Learning: NeOMakinG prefers to defer technical debt and CSS correctness issues (like improper hover selectors) to follow-up PRs when the current PR is already large and focused on major feature implementation, even when the issues are valid from a usability/technical perspective.
📚 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/CetusSwapper/utils/constants.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/swapper/src/swappers/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts
  • packages/chain-adapters/src/sui/SuiChainAdapter.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/CetusSwapper/utils/constants.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts
  • packages/chain-adapters/src/sui/SuiChainAdapter.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/CetusSwapper/utils/constants.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/chain-adapters/src/sui/SuiChainAdapter.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/CetusSwapper/utils/constants.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts
  • packages/chain-adapters/src/sui/SuiChainAdapter.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/CetusSwapper/utils/constants.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts
  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-10-23T14:27:19.073Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10857
File: src/plugins/walletConnectToDapps/eventsManager/useWalletConnectEventsHandler.ts:101-104
Timestamp: 2025-10-23T14:27:19.073Z
Learning: In WalletConnect wallet_switchEthereumChain and wallet_addEthereumChain requests, the chainId parameter is always present as per the protocol spec. Type guards checking for missing chainId in these handlers (like `if (!evmNetworkIdHex) return`) are solely for TypeScript compiler satisfaction, not real runtime edge cases.

Applied to files:

  • packages/swapper/src/swappers/CetusSwapper/utils/constants.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/constants.ts : Register new swappers in packages/swapper/src/constants.ts with an entry in the swappers registry mapping SwapperName enum to swapper implementation

Applied to files:

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

Applied to files:

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

Applied to files:

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

Applied to files:

  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/swapper/src/swappers/CetusSwapper/endpoints.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 : All swapper API implementations must implement the SwapperApi interface from packages/swapper/src/types.ts

Applied to files:

  • packages/swapper/src/swappers/CetusSwapper/endpoints.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/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.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/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.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/**/*.test.ts : Write unit tests for swapper methods and API endpoints

Applied to files:

  • packages/swapper/src/swappers/CetusSwapper/endpoints.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/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.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/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.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/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.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/swapper/src/swappers/CetusSwapper/endpoints.ts
  • packages/chain-adapters/src/sui/SuiChainAdapter.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/CetusSwapper/endpoints.ts
  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.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/CetusSwapper/endpoints.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/CetusSwapper/utils/helpers.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/CetusSwapper/utils/helpers.ts
📚 Learning: 2025-10-21T17:11:18.087Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10871
File: src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx:426-428
Timestamp: 2025-10-21T17:11:18.087Z
Learning: In src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx, within the handleInputChange function, use .toFixed() without arguments (not .toString()) when converting BigNumber amounts for input field synchronization. This avoids exponential notation in the input while preserving precision for presentational components like <Amount.Crypto /> and <Amount.Fiat /> to format appropriately.

Applied to files:

  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts
  • packages/chain-adapters/src/sui/SuiChainAdapter.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/CetusSwapper/utils/helpers.ts
📚 Learning: 2025-08-05T17:00:30.416Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10191
File: src/pages/Explore/components/AssetSearchRow.tsx:78-78
Timestamp: 2025-08-05T17:00:30.416Z
Learning: In BigNumber operations within the ShapeShift codebase, floating point literals like 0.01 should always be passed as strings like '0.01' to maintain precision. This applies to all BigNumber methods including .times(), .div(), .plus(), and .minus().

Applied to files:

  • packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts
📚 Learning: 2025-08-10T21:09:25.643Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10215
File: src/components/MultiHopTrade/hooks/useGetTradeRateInput.ts:65-67
Timestamp: 2025-08-10T21:09:25.643Z
Learning: In the MultiHopTrade components, `selectInputBuyAsset` and `selectInputSellAsset` selectors from `tradeInputSlice` always return defined values because they have default values in the initial state (BTC for buyAsset, ETH for sellAsset, with fallback to defaultAsset). Null checks for these assets are unnecessary when using these selectors.

Applied to files:

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

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.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/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-08T15:53:09.362Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10442
File: src/components/TradeAssetSearch/components/GroupedAssetList/GroupedAssetList.tsx:34-35
Timestamp: 2025-09-08T15:53:09.362Z
Learning: In DefaultAssetList.tsx, the GroupedAssetList component already receives the activeChainId prop correctly on line ~58, contrary to automated analysis that may flag it as missing.

Applied to files:

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

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-08-13T15:52:25.116Z
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.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-10-13T11:55:57.439Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10751
File: src/Routes/RoutesCommon.tsx:190-190
Timestamp: 2025-10-13T11:55:57.439Z
Learning: In the shapeshift/web codebase, there are multiple independent claim systems: Arbitrum bridge claims (removed in PR #10751), RFOX claims (in src/pages/RFOX/components/Claim/), and TCY claims (in src/pages/TCY/). Each has its own routes, components, and logic. When reviewing claim-related changes, distinguish which system is being modified and avoid suggesting changes to unrelated claim systems.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-10-01T07:42:40.195Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10596
File: src/components/Layout/Header/NavBar/WalletConnectedMenu.tsx:77-99
Timestamp: 2025-10-01T07:42:40.195Z
Learning: In WalletConnectedMenu.tsx's handleReconnectWallet handler, gomesalexandre prefers throwing an error for unsupported wallet types in the default case rather than gracefully handling with a fallback. His reasoning: "if we have a problem here, we have bigger problems" - only supported wallets (KeepKey, Ledger, MetaMask, Coinbase, Phantom) should reach the reconnect flow when disconnected/locked, so encountering an unsupported type indicates a larger architectural issue that should be surfaced explicitly rather than masked with graceful degradation.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-08-29T07:07:49.332Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10386
File: src/components/MultiHopTrade/components/VerifyAddresses/VerifyAddresses.tsx:272-294
Timestamp: 2025-08-29T07:07:49.332Z
Learning: In UTXO sell address verification flow in VerifyAddresses.tsx, the user wants address verification to be marked as "verified/complete" before starting the change address fetch, not after. The verification step and change address fetch should be treated as separate sequential operations in the UI flow.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-12T10:44:46.723Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/content/SendTransactionContent.tsx:0-0
Timestamp: 2025-09-12T10:44:46.723Z
Learning: gomesalexandre dismissed a clipboard error handling suggestion in PR #10461 for SendTransactionContent.tsx, demonstrating that the current navigator.clipboard.writeText implementation works as expected and preferring to keep it simple without additional try/catch error handling.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-11-25T21:43:10.838Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11170
File: patches/@shapeshiftoss+bitcoinjs-lib+7.0.0-shapeshift.0.patch:9-19
Timestamp: 2025-11-25T21:43:10.838Z
Learning: In shapeshift/web, gomesalexandre will not expand PR scope to fix latent bugs in unused API surface (like bitcoinjs-lib patch validation methods) when comprehensive testing proves the actual used code paths work correctly, preferring to avoid costly hdwallet/web verdaccio publish cycles and full regression testing for conceptual issues with zero runtime impact.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-10-07T03:44:27.350Z
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10760
File: src/components/ManageHiddenAssets/ManageHiddenAssetsList.tsx:78-84
Timestamp: 2025-10-07T03:44:27.350Z
Learning: In the ShapeShift web codebase, the following are stable references and do not need to be included in useCallback/useMemo dependency arrays:
- `navigate` from `useBrowserRouter()` hook
- Modal control objects (like `walletDrawer`) from `useModal()` hook (including their `isOpen`, `close`, and `open` methods)
- These are backed by stable context providers

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-08-05T22:41:35.473Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10187
File: src/pages/Assets/Asset.tsx:1-1
Timestamp: 2025-08-05T22:41:35.473Z
Learning: In the shapeshift/web codebase, component imports use direct file paths like '@/components/ComponentName/ComponentName' rather than barrel exports. The AssetAccountDetails component should be imported as '@/components/AssetAccountDetails/AssetAccountDetails', not from a directory index.

Applied to files:

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

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-12T12:08:15.823Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/WalletConnectModalManager.tsx:226-233
Timestamp: 2025-09-12T12:08:15.823Z
Learning: In WalletConnect dApps integration, EthSignTransactionCallRequest and EthSendTransactionCallRequest have identical transaction parameter structures (from, to, data, etc.) per JSON-RPC spec - only the method field differs. This makes it safe to type-cast between them when passing transaction parameters to components like EIP155TransactionConfirmation that process the underlying transaction data regardless of the originating method.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
🧬 Code graph analysis (5)
packages/swapper/src/swappers/CetusSwapper/utils/constants.ts (1)
packages/caip/src/constants.ts (1)
  • suiChainId (81-81)
packages/caip/src/adapters/coingecko/index.test.ts (2)
packages/caip/src/assetId/assetId.ts (1)
  • toAssetId (59-127)
packages/caip/src/constants.ts (2)
  • CHAIN_NAMESPACE (83-90)
  • CHAIN_REFERENCE (96-118)
packages/swapper/src/swappers/CetusSwapper/endpoints.ts (3)
packages/swapper/src/utils.ts (3)
  • isExecutableTradeQuote (308-309)
  • getExecutableTradeStep (314-324)
  • checkSuiSwapStatus (353-387)
src/lib/utils/sui.ts (1)
  • assertGetSuiChainAdapter (14-23)
packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts (5)
  • getCetusSDK (8-14)
  • getCoinType (16-26)
  • findBestPool (61-85)
  • calculateSwapAmounts (93-135)
  • determineSwapDirection (28-40)
packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts (1)
packages/caip/src/assetId/assetId.ts (1)
  • fromAssetId (140-172)
packages/chain-adapters/src/sui/SuiChainAdapter.ts (2)
packages/caip/src/assetId/assetId.ts (1)
  • toAssetId (59-127)
packages/caip/src/constants.ts (1)
  • ASSET_NAMESPACE (120-128)
🔇 Additional comments (14)
packages/swapper/src/swappers/CetusSwapper/utils/constants.ts (1)

1-10: LGTM! Clean implementation of Cetus chain support.

The constants file correctly follows the established swapper pattern with explicit types, proper imports from @shapeshiftoss/caip, and a well-formed type guard. The readonly array and type guard will enable compile-time and runtime chain validation throughout the Cetus swapper.

packages/swapper/src/swappers/CetusSwapper/endpoints.ts (4)

27-40: LGTM! Clean delegation pattern.

The getTradeQuote and getTradeRate methods correctly delegate to their respective implementations while conforming to the SwapperApi interface.


60-120: LGTM! Solid transaction construction logic.

The implementation correctly:

  • Validates and retrieves pool with appropriate error handling
  • Calculates swap amounts and determines direction
  • Applies slippage protection with correct parameters
  • Constructs the SUI transaction with proper intent message format (3-byte prefix)
  • Derives BIP44 address path appropriately

123-131: LGTM! Proper fee extraction with validation.

The method correctly validates the trade quote type, retrieves the executable step, and ensures the network fee is present before returning it.


133-147: LGTM! Proper status check implementation.

The method appropriately handles the case where no transaction hash exists by returning Unknown status, and correctly delegates to the reusable checkSuiSwapStatus utility for actual status checking.

packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts (7)

8-14: LGTM! Appropriate singleton pattern for SDK initialization.

The lazy-loaded singleton pattern with dynamic import is suitable for SDK initialization, reducing initial bundle size while ensuring a single SDK instance throughout the application lifecycle.


16-26: LGTM! Correct coin type conversion.

The function properly handles the special case of native SUI tokens (converting from slip44:784 format to Cetus's expected 0x2::sui::SUI format) while passing through other token asset references unchanged.


28-40: LGTM! Clear swap direction logic.

The function correctly determines the swap direction by checking both possible coin type orientations in the pool, with appropriate error handling when the pool doesn't match the requested pair.


42-59: LGTM! Correct slippage calculation logic.

The function properly applies slippage tolerance:

  • For buy amounts (minimum output): reduces by slippage factor (1 - slippage)
  • For sell amounts (maximum input): increases by slippage factor (1 + slippage)

Both calculations correctly protect against unfavorable price movements.


61-85: LGTM! Robust pool selection logic.

The function correctly queries for pools, filters for liquidity, and provides useful diagnostic logging when no liquid pools are found. The use of bnOrZero ensures safe numeric comparisons.


87-91: LGTM! Clean result type definition.

The type appropriately uses string fields for all amount values, which is correct for representing base unit amounts without precision loss.


93-135: LGTM! Correct swap amount calculation.

The function properly:

  • Determines swap direction and coin types
  • Correctly assigns decimals for both pool coins (lines 105-106 logic is correct: when pool.coinTypeA === sellCoinType, decimalsA gets sell precision and decimalsB gets buy precision, and vice versa)
  • Validates preswap results before returning
  • Returns undefined for invalid swap scenarios (no result or zero output)
packages/caip/src/adapters/coingecko/index.test.ts (1)

178-183: USDC on Sui mapping test looks consistent and correct

The new usdcOnSui assetId and its inclusion in the usd-coin expectations follow the existing multi-chain USDC pattern and correctly use Sui chain namespace/reference and coin namespace.

Also applies to: 192-193

packages/chain-adapters/src/sui/SuiChainAdapter.ts (1)

4-10: CAIP imports and root BIP44 params are wired correctly for Sui

Using ASSET_REFERENCE.Sui for coinType and suiChainId/suiAssetId from @shapeshiftoss/caip aligns this adapter with the shared CAIP constants and keeps chain metadata centralized.

Also applies to: 40-44

gomesalexandre and others added 3 commits December 2, 2025 00:59
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Remove all debug console.log statements from SUI chain adapter
- Change TradeQuoteError from UnknownError to InternalError for
  assertion failures (accountNumber, suiAsset)
- Revert unintended comment removal in useSendActionSubscriber

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

Co-Authored-By: Claude <[email protected]>
Fixes whitescreen issue in Edge/Chromium browsers where SVG imports
without ?url suffix fail with:
"Failed to load module script: Expected JavaScript module but the
server responded with a MIME type of 'image/svg+xml'"

Same fix as PR #11070 for orbs.svg, now applied to Jupiter and Relay
swapper icons.

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

Co-Authored-By: Claude <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/chain-adapters/src/sui/SuiChainAdapter.ts (1)

120-189: Token balance + assetId mapping is solid; normalize helper could be hoisted.

The concurrent getBalance/getAllBalances call, SUI-native filtering, CAIP-19 coin assetIds, and metadata fallbacks all look correct and robust. If you want to tighten things slightly, consider moving normalizeCoinType out of the map callback (e.g., to a private method) so it isn’t redefined per token and can be reused elsewhere if needed.

Also applies to: 192-199

📜 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 b2911b2 and c625dba.

📒 Files selected for processing (2)
  • packages/chain-adapters/src/sui/SuiChainAdapter.ts (4 hunks)
  • packages/swapper/src/swappers/CetusSwapper/swapperApi/getTradeQuote.ts (1 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/chain-adapters/src/sui/SuiChainAdapter.ts
  • packages/swapper/src/swappers/CetusSwapper/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/chain-adapters/src/sui/SuiChainAdapter.ts
  • packages/swapper/src/swappers/CetusSwapper/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/chain-adapters/src/sui/SuiChainAdapter.ts
  • packages/swapper/src/swappers/CetusSwapper/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/CetusSwapper/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/CetusSwapper/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/CetusSwapper/swapperApi/getTradeQuote.ts
🧠 Learnings (49)
📓 Common learnings
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/components/AssetSearch/components/AssetList.tsx:2-2
Timestamp: 2025-08-08T15:00:49.887Z
Learning: Project shapeshift/web: NeOMakinG prefers avoiding minor a11y/UI nitpicks (e.g., adding aria-hidden to decorative icons in empty states like src/components/AssetSearch/components/AssetList.tsx) within feature PRs; defer such suggestions to a follow-up instead of blocking the PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/ButtonWalletPredicate/ButtonWalletPredicate.tsx:7-7
Timestamp: 2025-08-27T09:47:06.275Z
Learning: In shapeshift/web project, NeOMakinG consistently prefers to defer UI/UX improvements and refactoring work (like the Drawer.Close hack fix in ButtonWalletPredicate.tsx) to follow-up PRs rather than expanding the scope of feature PRs, even when the improvements would enhance robustness.
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: 11240
File: packages/swapper/src/swappers/CetusSwapper/endpoints.ts:56-58
Timestamp: 2025-12-01T22:01:37.954Z
Learning: In packages/swapper/src/swappers/CetusSwapper/endpoints.ts, gomesalexandre is comfortable with mutating the shared Cetus SDK singleton instance (sdk.senderAddress = from) when required by the SDK API, preferring pragmatic working code over theoretical statelessness concerns.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11078
File: src/setupVitest.ts:11-15
Timestamp: 2025-11-20T12:00:45.005Z
Learning: In shapeshift/web, src/setupVitest.ts must redirect 'ethers' to 'ethers5' for shapeshiftoss/hdwallet-trezor (and -trezor-connect), same as ledger and shapeshift-multichain. Removing 'trezor' from the regex causes CI/Vitest failures due to ethers v6 vs v5 API differences.
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
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: To add a new feature flag: (1) Add to `FeatureFlags` type in `src/state/slices/preferencesSlice/preferencesSlice.ts`, (2) Add environment variable validation in `src/config.ts`, (3) Add to initial state in `preferencesSlice.ts`, (4) Add to test mock in `src/test/mocks/store.ts`, (5) Set appropriate values in `.env`, `.env.development`, and `.env.production`
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: 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
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
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/components/Stake/components/StakeSummary.tsx:112-114
Timestamp: 2025-08-22T13:00:44.879Z
Learning: NeOMakinG prefers to keep PR changes minimal and focused on the core objectives, avoiding cosmetic or defensive code improvements that aren't directly related to the PR scope, even when they would improve robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/pages/Dashboard/components/AccountList/AccountTable.tsx:60-0
Timestamp: 2025-09-02T08:34:08.157Z
Learning: NeOMakinG prefers code review comments to focus only on actual PR changes, not pre-existing code issues, unless there are critical security or correctness concerns directly related to the new functionality.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:42-86
Timestamp: 2025-08-08T11:41:22.794Z
Learning: NeOMakinG prefers not to include refactors in move-only PRs; such suggestions should be deferred to follow-up issues instead of being applied within the same PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/Table/Table.theme.ts:177-180
Timestamp: 2025-09-02T12:38:46.940Z
Learning: NeOMakinG prefers to defer technical debt and CSS correctness issues (like improper hover selectors) to follow-up PRs when the current PR is already large and focused on major feature implementation, even when the issues are valid from a usability/technical perspective.
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to **/*.{ts,tsx} : Import types from `shapeshiftoss/caip` for chain/account/asset IDs

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-11-24T21:20:57.909Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Implement filterBuyAssetsBySellAssetId method to filter assets by supported chain IDs in the buy property

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
  • packages/swapper/src/swappers/CetusSwapper/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/chain-adapters/src/sui/SuiChainAdapter.ts
  • packages/swapper/src/swappers/CetusSwapper/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 TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system

Applied to files:

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

Applied to files:

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

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.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/sui/SuiChainAdapter.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/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-08T15:53:09.362Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10442
File: src/components/TradeAssetSearch/components/GroupedAssetList/GroupedAssetList.tsx:34-35
Timestamp: 2025-09-08T15:53:09.362Z
Learning: In DefaultAssetList.tsx, the GroupedAssetList component already receives the activeChainId prop correctly on line ~58, contrary to automated analysis that may flag it as missing.

Applied to files:

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

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-08-13T15:52:25.116Z
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.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-12T10:44:46.723Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/content/SendTransactionContent.tsx:0-0
Timestamp: 2025-09-12T10:44:46.723Z
Learning: gomesalexandre dismissed a clipboard error handling suggestion in PR #10461 for SendTransactionContent.tsx, demonstrating that the current navigator.clipboard.writeText implementation works as expected and preferring to keep it simple without additional try/catch error handling.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-11-25T21:43:10.838Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11170
File: patches/@shapeshiftoss+bitcoinjs-lib+7.0.0-shapeshift.0.patch:9-19
Timestamp: 2025-11-25T21:43:10.838Z
Learning: In shapeshift/web, gomesalexandre will not expand PR scope to fix latent bugs in unused API surface (like bitcoinjs-lib patch validation methods) when comprehensive testing proves the actual used code paths work correctly, preferring to avoid costly hdwallet/web verdaccio publish cycles and full regression testing for conceptual issues with zero runtime impact.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-08-29T07:07:49.332Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10386
File: src/components/MultiHopTrade/components/VerifyAddresses/VerifyAddresses.tsx:272-294
Timestamp: 2025-08-29T07:07:49.332Z
Learning: In UTXO sell address verification flow in VerifyAddresses.tsx, the user wants address verification to be marked as "verified/complete" before starting the change address fetch, not after. The verification step and change address fetch should be treated as separate sequential operations in the UI flow.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-10-13T11:55:57.439Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10751
File: src/Routes/RoutesCommon.tsx:190-190
Timestamp: 2025-10-13T11:55:57.439Z
Learning: In the shapeshift/web codebase, there are multiple independent claim systems: Arbitrum bridge claims (removed in PR #10751), RFOX claims (in src/pages/RFOX/components/Claim/), and TCY claims (in src/pages/TCY/). Each has its own routes, components, and logic. When reviewing claim-related changes, distinguish which system is being modified and avoid suggesting changes to unrelated claim systems.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-12T11:56:19.437Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/utils/tenderly/index.ts:0-0
Timestamp: 2025-09-12T11:56:19.437Z
Learning: gomesalexandre rejected verbose try/catch error handling for address validation in Tenderly integration (PR #10461), calling the approach "ugly" but still implemented safety measures in commit ad7e424b89, preferring cleaner safety implementations over defensive programming patterns.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-10-01T07:42:40.195Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10596
File: src/components/Layout/Header/NavBar/WalletConnectedMenu.tsx:77-99
Timestamp: 2025-10-01T07:42:40.195Z
Learning: In WalletConnectedMenu.tsx's handleReconnectWallet handler, gomesalexandre prefers throwing an error for unsupported wallet types in the default case rather than gracefully handling with a fallback. His reasoning: "if we have a problem here, we have bigger problems" - only supported wallets (KeepKey, Ledger, MetaMask, Coinbase, Phantom) should reach the reconnect flow when disconnected/locked, so encountering an unsupported type indicates a larger architectural issue that should be surfaced explicitly rather than masked with graceful degradation.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-10T15:35:46.223Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/components/modals/EIP155SignTypedDataConfirmation.tsx:55-55
Timestamp: 2025-09-10T15:35:46.223Z
Learning: gomesalexandre prefers fail-fast early returns over graceful degradation when critical data is missing in WalletConnect flows (like peer metadata in EIP155SignTypedDataConfirmation.tsx). He favors "safety first, always double-wrap" approach and believes missing peer metadata indicates bigger problems that should be surfaced explicitly rather than masked with partial UI rendering.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-08-27T09:47:06.275Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/ButtonWalletPredicate/ButtonWalletPredicate.tsx:7-7
Timestamp: 2025-08-27T09:47:06.275Z
Learning: In shapeshift/web project, NeOMakinG consistently prefers to defer UI/UX improvements and refactoring work (like the Drawer.Close hack fix in ButtonWalletPredicate.tsx) to follow-up PRs rather than expanding the scope of feature PRs, even when the improvements would enhance robustness.

Applied to files:

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

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-17T22:40:30.149Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10569
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/WalletConnectModalSigningFooter.tsx:121-129
Timestamp: 2025-09-17T22:40:30.149Z
Learning: gomesalexandre maintains strict scope discipline even for style/UI PRs in shapeshift/web, declining functionally correct UX improvements (like keeping Cancel button enabled during gas simulation loading) when they fall outside the PR's stated styling objectives, demonstrating his consistent pattern of deferring valid but tangential improvements to separate efforts.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-12T13:16:27.004Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:21-24
Timestamp: 2025-09-12T13:16:27.004Z
Learning: gomesalexandre declined to add error boundaries to WalletConnect modals in PR #10461, stating "no error boundaries in this pr ser", consistent with his preference to keep PR scope focused and defer tangential improvements to separate efforts.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-13T16:45:17.166Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/StructuredMessage/StructuredMessage.tsx:0-0
Timestamp: 2025-09-13T16:45:17.166Z
Learning: gomesalexandre appreciates safety-focused suggestions for UI rendering in WalletConnect components, specifically defensive programming approaches that prevent null/undefined values from displaying as literal "null"/"undefined" strings in the user interface.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-08T22:00:48.005Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10418
File: src/plugins/walletConnectToDapps/components/header/WalletConnectToDappsHeaderButton.tsx:0-0
Timestamp: 2025-09-08T22:00:48.005Z
Learning: gomesalexandre dismissed an aria-label accessibility suggestion with "meh" in PR #10418 for WalletConnectToDappsHeaderButton.tsx, consistent with the team's pattern of deferring minor a11y improvements to follow-up PRs rather than expanding feature PR scope.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-12T12:00:33.924Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns in WalletConnect modals, including side-effects-during-render for error handling (showErrorToast + handleReject), rather than introducing isolated refactors that would make the codebase inconsistent.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-08-08T15:00:22.321Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/components/MultiHopTrade/components/TradeInput/components/HighlightedTokens.tsx:14-14
Timestamp: 2025-08-08T15:00:22.321Z
Learning: In shapeshift/web reviews for NeOMakinG, avoid nitpicks to change deep-relative imports to '@/…' alias paths within feature/non-refactor PRs; defer such style-only changes to a dedicated follow-up refactor unless they fix an issue.

Applied to files:

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

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-10-07T03:44:27.350Z
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10760
File: src/components/ManageHiddenAssets/ManageHiddenAssetsList.tsx:78-84
Timestamp: 2025-10-07T03:44:27.350Z
Learning: In the ShapeShift web codebase, the following are stable references and do not need to be included in useCallback/useMemo dependency arrays:
- `navigate` from `useBrowserRouter()` hook
- Modal control objects (like `walletDrawer`) from `useModal()` hook (including their `isOpen`, `close`, and `open` methods)
- These are backed by stable context providers

Applied to files:

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

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
  • packages/swapper/src/swappers/CetusSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-08-05T22:41:35.473Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10187
File: src/pages/Assets/Asset.tsx:1-1
Timestamp: 2025-08-05T22:41:35.473Z
Learning: In the shapeshift/web codebase, component imports use direct file paths like '@/components/ComponentName/ComponentName' rather than barrel exports. The AssetAccountDetails component should be imported as '@/components/AssetAccountDetails/AssetAccountDetails', not from a directory index.

Applied to files:

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

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-10-21T17:11:18.087Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10871
File: src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx:426-428
Timestamp: 2025-10-21T17:11:18.087Z
Learning: In src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx, within the handleInputChange function, use .toFixed() without arguments (not .toString()) when converting BigNumber amounts for input field synchronization. This avoids exponential notation in the input while preserving precision for presentational components like <Amount.Crypto /> and <Amount.Fiat /> to format appropriately.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.ts
📚 Learning: 2025-09-12T12:08:15.823Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/WalletConnectModalManager.tsx:226-233
Timestamp: 2025-09-12T12:08:15.823Z
Learning: In WalletConnect dApps integration, EthSignTransactionCallRequest and EthSendTransactionCallRequest have identical transaction parameter structures (from, to, data, etc.) per JSON-RPC spec - only the method field differs. This makes it safe to type-cast between them when passing transaction parameters to components like EIP155TransactionConfirmation that process the underlying transaction data regardless of the originating method.

Applied to files:

  • packages/chain-adapters/src/sui/SuiChainAdapter.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/CetusSwapper/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/CetusSwapper/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 : Reuse executeEvmTransaction utility for EVM-based swappers instead of implementing custom transaction execution

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/CetusSwapper/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/CetusSwapper/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/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/CetusSwapper/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/**/*.test.ts : Write unit tests for swapper methods and API endpoints

Applied to files:

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

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/CetusSwapper/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 **/*.{ts,tsx} : ALWAYS use custom error classes from `shapeshiftoss/errors` with meaningful error codes for internationalization and relevant details in error objects

Applied to files:

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

Applied to files:

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

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/CetusSwapper/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/CetusSwapper/swapperApi/getTradeQuote.ts
🧬 Code graph analysis (2)
packages/chain-adapters/src/sui/SuiChainAdapter.ts (2)
packages/caip/src/assetId/assetId.ts (1)
  • toAssetId (59-127)
packages/caip/src/constants.ts (1)
  • ASSET_NAMESPACE (120-128)
packages/swapper/src/swappers/CetusSwapper/swapperApi/getTradeQuote.ts (6)
packages/swapper/src/utils.ts (2)
  • makeSwapErrorRight (31-47)
  • getInputOutputRate (292-306)
src/state/apis/swapper/types.ts (1)
  • TradeQuoteError (39-39)
packages/swapper/src/swappers/CetusSwapper/utils/constants.ts (1)
  • isSupportedChainId (6-10)
packages/caip/src/constants.ts (1)
  • suiAssetId (23-23)
packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts (4)
  • getCetusSDK (8-14)
  • getCoinType (16-26)
  • findBestPool (61-85)
  • calculateSwapAmounts (93-135)
packages/caip/src/assetId/assetId.ts (1)
  • AssetId (17-17)
🔇 Additional comments (10)
packages/swapper/src/swappers/CetusSwapper/swapperApi/getTradeQuote.ts (7)

1-19: LGTM!

Imports are well-organized, using proper types from @shapeshiftoss/* packages and the Result pattern from @sniptt/monads as per coding guidelines.


21-35: LGTM!

Function signature follows the swapper pattern with explicit return type and proper use of Result<TradeQuote[], SwapErrorRight>.


37-75: LGTM!

Validations follow best practices with early returns, appropriate error codes (InternalError for preconditions, UnsupportedChain for chain validation), and useful error details.


77-103: LGTM!

SDK initialization, pool discovery, and swap calculation are well-structured with appropriate error codes (NoRouteFound, QueryFailed) for different failure modes.


105-128: LGTM!

Rate calculation uses the shared utility, and fee estimation properly handles missing receiveAddress with a valid SUI-format dummy address. The adapter assertion is within the try-catch block.


130-146: Verify whether protocol fees should be populated.

swapResult.estimatedFeeAmount is returned from calculateSwapAmounts but is not used here. The protocolFees record is empty, and buyAmountBeforeFeesCryptoBaseUnit equals buyAmountAfterFeesCryptoBaseUnit.

If estimatedAmountOut from Cetus already reflects fees deducted, this is correct. However, if estimatedFeeAmount represents additional protocol fees that should be displayed to users, consider populating protocolFees:

-  const protocolFees: Record<AssetId, ProtocolFee> = {}
+  const protocolFees: Record<AssetId, ProtocolFee> = swapResult.estimatedFeeAmount !== '0'
+    ? {
+        [buyAsset.assetId]: {
+          amountCryptoBaseUnit: swapResult.estimatedFeeAmount,
+          requiresBalance: false,
+          asset: buyAsset,
+        },
+      }
+    : {}

169-177: LGTM!

Error handling properly uses the Result pattern, catches all exceptions, extracts meaningful error messages, and returns an appropriate QueryFailed error code.

packages/chain-adapters/src/sui/SuiChainAdapter.ts (3)

4-10: CAIP-based Sui chain/asset wiring looks good.

Using ASSET_REFERENCE.Sui for coinType and suiChainId/suiAssetId plus toAssetId is consistent with the CAIP constants and keeps Sui BIP44/assetId derivation centralized.

Also applies to: 40-43


250-270: Token send path via getCoins + splitCoins is wired correctly.

Casting gasBudget/gasPrice to numbers and using getCoins({ owner: from, coinType: tokenId }) with splitCoins on the selected coin object matches the Sui SDK’s expectations and aligns the token send flow with the native SUI branch.


438-459: Please verify the hard-coded token gas estimate is safe across mainnet tokens.

The token getFeeData fast‑path uses a fixed estimatedGas = 50_000_000n (with a 20% buffer) and skips building/dry‑running a transaction. This is likely fine for typical transfers, but if any token transfer consistently needs more gas, users could see “insufficient gas budget” failures.

Can you confirm from Cetus/Sui mainnet testing that 50_000_000n (and the derived gasBudget) is large enough for the heaviest expected token transfers? If not, it might be worth bumping this value or extracting it to a named constant that can be tuned.

Also applies to: 466-477

Copy link
Contributor

@gomesalexandre gomesalexandre left a comment

Choose a reason for hiding this comment

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

Seems to do the thing

https://jam.dev/c/8e52508a-db43-4676-b181-ccd8ad1564a4

@NeOMakinG probably worth doing a regen before merging re:

Try very well known token like USDC to USDT on sui and the contrary

Only seeing 2 tokens on SUI, USDC and SUI as a token

Image

@NeOMakinG
Copy link
Collaborator Author

Merging, tomorrows regen will do the trick, need velocity there/sleep and I'll have another rebase if we wait

@NeOMakinG NeOMakinG merged commit c6c7323 into develop Dec 1, 2025
4 checks passed
@NeOMakinG NeOMakinG deleted the implement-cetus-sui-tokens branch December 1, 2025 23:25
gomesalexandre added a commit that referenced this pull request Dec 2, 2025
…and implementation guide

This update transforms the swapper-integration skill from basic guidance into a comprehensive, production-ready integration framework based on analysis of 3 major swapper PRs (Bebop, NEAR Intents, Cetus) and deep understanding of the swapper abstraction.

## Major Enhancements

### Phase 0: Proactive Research (NEW)
- Use WebFetch/WebSearch to research swapper APIs BEFORE asking user
- Automatically find documentation, chain support, existing integrations
- Only ask user for what can't be found online

### Expanded allowed-tools
- Added WebFetch, WebSearch for autonomous research
- Added AskUserQuestion for structured multi-question prompts
- Added gh pr:* for PR research

### Deep Swapper Categorization
- EVM Direct Transaction (Bebop, 0x, Portals)
- Deposit-to-Address (Chainflip, NEAR Intents, THORChain)
- Gasless Order-Based (CowSwap)
- Solana-Only (Jupiter)
- Chain-Specific (Cetus/Sui, Tron, etc.)

### Complete Implementation Guide
- Step-by-step file creation order (10 files)
- Full code templates for each file with actual TypeScript
- Detailed explanations of monadic error handling
- HTTP service factory with caching pattern
- Rate calculation strategies

### Swapper-Specific Metadata Deep Dive
- When to use vs when to skip
- THREE places to wire (types, quote, TWO extraction points)
- Critical: Both useTradeButtonProps AND tradeExecution.ts
- Example flows from NEAR Intents

### Registration Checklist (9 steps)
- SwapperConfig types
- Constants registration
- CSP headers with examples
- Feature flags (3 files)
- UI icon integration
- Environment variables (.env patterns)
- Test mocks

### Proactive Gotcha Prevention
- 10 critical bugs to check BEFORE testing
- Based on real issues from Bebop/NEAR Intents/Cetus PRs
- Slippage format, checksumming, hex conversion, response parsing

### Testing Framework
- Automated checks (type-check, lint, build)
- 11-point manual testing checklist
- 6-point edge case testing
- Rate vs quote delta verification

### Common Errors & Solutions
- 8 common error messages with exact fixes
- Direct mapping from error → solution
- Based on actual PR comments and fixes

## Key Insights from PR Analysis

### From Bebop PR (#11000)
- Dual routing with partial failure handling
- Affiliate fee delta issues (rate vs quote)
- Hex → decimal conversion patterns
- Address checksumming requirements

### From NEAR Intents PR (#11016)
- Deposit-to-address metadata flow
- Status polling with swap metadata
- Cross-chain EVM/UTXO/Solana handling
- OneClick SDK integration patterns

### From Cetus PR (#11240)
- Sui chain-specific adaptations
- Non-EVM transaction metadata
- Chain adapter fee estimation
- Token vs coin namespace handling

## Skill Quality Improvements

- 1500+ lines of comprehensive guidance (3x expansion)
- Code templates with actual imports and types
- File structure with exact locations
- Integration checklist (28 items)
- Three-phase workflow (Research → Implement → Test)

## Technical Depth

- Monadic Result<T, SwapErrorRight> pattern explained
- HTTP service with caching (createCache, makeSwapperAxiosServiceMonadic)
- Chain adapter usage for fee estimation
- Native token marker handling
- TradeQuote vs TradeRate differences
- accountNumber: undefined requirement for rates

## Documentation Template

- Complete INTEGRATION.md structure
- API details section
- Implementation notes with code
- Known gotchas documentation
- Testing strategies

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

Co-Authored-By: Claude <[email protected]>
gomesalexandre added a commit that referenced this pull request Dec 2, 2025
…and implementation guide

This update transforms the swapper-integration skill from basic guidance into a comprehensive, production-ready integration framework based on analysis of 3 major swapper PRs (Bebop, NEAR Intents, Cetus) and deep understanding of the swapper abstraction.

## Major Enhancements

### Phase 0: Proactive Research (NEW)
- Use WebFetch/WebSearch to research swapper APIs BEFORE asking user
- Automatically find documentation, chain support, existing integrations
- Only ask user for what can't be found online

### Expanded allowed-tools
- Added WebFetch, WebSearch for autonomous research
- Added AskUserQuestion for structured multi-question prompts
- Added gh pr:* for PR research

### Deep Swapper Categorization
- EVM Direct Transaction (Bebop, 0x, Portals)
- Deposit-to-Address (Chainflip, NEAR Intents, THORChain)
- Gasless Order-Based (CowSwap)
- Solana-Only (Jupiter)
- Chain-Specific (Cetus/Sui, Tron, etc.)

### Complete Implementation Guide
- Step-by-step file creation order (10 files)
- Full code templates for each file with actual TypeScript
- Detailed explanations of monadic error handling
- HTTP service factory with caching pattern
- Rate calculation strategies

### Swapper-Specific Metadata Deep Dive
- When to use vs when to skip
- THREE places to wire (types, quote, TWO extraction points)
- Critical: Both useTradeButtonProps AND tradeExecution.ts
- Example flows from NEAR Intents

### Registration Checklist (9 steps)
- SwapperConfig types
- Constants registration
- CSP headers with examples
- Feature flags (3 files)
- UI icon integration
- Environment variables (.env patterns)
- Test mocks

### Proactive Gotcha Prevention
- 10 critical bugs to check BEFORE testing
- Based on real issues from Bebop/NEAR Intents/Cetus PRs
- Slippage format, checksumming, hex conversion, response parsing

### Testing Framework
- Automated checks (type-check, lint, build)
- 11-point manual testing checklist
- 6-point edge case testing
- Rate vs quote delta verification

### Common Errors & Solutions
- 8 common error messages with exact fixes
- Direct mapping from error → solution
- Based on actual PR comments and fixes

## Key Insights from PR Analysis

### From Bebop PR (#11000)
- Dual routing with partial failure handling
- Affiliate fee delta issues (rate vs quote)
- Hex → decimal conversion patterns
- Address checksumming requirements

### From NEAR Intents PR (#11016)
- Deposit-to-address metadata flow
- Status polling with swap metadata
- Cross-chain EVM/UTXO/Solana handling
- OneClick SDK integration patterns

### From Cetus PR (#11240)
- Sui chain-specific adaptations
- Non-EVM transaction metadata
- Chain adapter fee estimation
- Token vs coin namespace handling

## Skill Quality Improvements

- 1500+ lines of comprehensive guidance (3x expansion)
- Code templates with actual imports and types
- File structure with exact locations
- Integration checklist (28 items)
- Three-phase workflow (Research → Implement → Test)

## Technical Depth

- Monadic Result<T, SwapErrorRight> pattern explained
- HTTP service with caching (createCache, makeSwapperAxiosServiceMonadic)
- Chain adapter usage for fee estimation
- Native token marker handling
- TradeQuote vs TradeRate differences
- accountNumber: undefined requirement for rates

## Documentation Template

- Complete INTEGRATION.md structure
- API details section
- Implementation notes with code
- Known gotchas documentation
- Testing strategies

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

Co-Authored-By: Claude <[email protected]>
0xApotheosis pushed a commit that referenced this pull request Dec 3, 2025
* feat: display current nonce in WalletConnect transaction advanced parameters

Fetches and displays the current/next nonce for the account in the advanced parameters section instead of showing "Nonce..." placeholder text. Users can now see what nonce will be automatically used if they don't set a custom one.

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

Co-Authored-By: Claude <[email protected]>

* feat: massively enhance swapper-integration skill with deep research and implementation guide

This update transforms the swapper-integration skill from basic guidance into a comprehensive, production-ready integration framework based on analysis of 3 major swapper PRs (Bebop, NEAR Intents, Cetus) and deep understanding of the swapper abstraction.

## Major Enhancements

### Phase 0: Proactive Research (NEW)
- Use WebFetch/WebSearch to research swapper APIs BEFORE asking user
- Automatically find documentation, chain support, existing integrations
- Only ask user for what can't be found online

### Expanded allowed-tools
- Added WebFetch, WebSearch for autonomous research
- Added AskUserQuestion for structured multi-question prompts
- Added gh pr:* for PR research

### Deep Swapper Categorization
- EVM Direct Transaction (Bebop, 0x, Portals)
- Deposit-to-Address (Chainflip, NEAR Intents, THORChain)
- Gasless Order-Based (CowSwap)
- Solana-Only (Jupiter)
- Chain-Specific (Cetus/Sui, Tron, etc.)

### Complete Implementation Guide
- Step-by-step file creation order (10 files)
- Full code templates for each file with actual TypeScript
- Detailed explanations of monadic error handling
- HTTP service factory with caching pattern
- Rate calculation strategies

### Swapper-Specific Metadata Deep Dive
- When to use vs when to skip
- THREE places to wire (types, quote, TWO extraction points)
- Critical: Both useTradeButtonProps AND tradeExecution.ts
- Example flows from NEAR Intents

### Registration Checklist (9 steps)
- SwapperConfig types
- Constants registration
- CSP headers with examples
- Feature flags (3 files)
- UI icon integration
- Environment variables (.env patterns)
- Test mocks

### Proactive Gotcha Prevention
- 10 critical bugs to check BEFORE testing
- Based on real issues from Bebop/NEAR Intents/Cetus PRs
- Slippage format, checksumming, hex conversion, response parsing

### Testing Framework
- Automated checks (type-check, lint, build)
- 11-point manual testing checklist
- 6-point edge case testing
- Rate vs quote delta verification

### Common Errors & Solutions
- 8 common error messages with exact fixes
- Direct mapping from error → solution
- Based on actual PR comments and fixes

## Key Insights from PR Analysis

### From Bebop PR (#11000)
- Dual routing with partial failure handling
- Affiliate fee delta issues (rate vs quote)
- Hex → decimal conversion patterns
- Address checksumming requirements

### From NEAR Intents PR (#11016)
- Deposit-to-address metadata flow
- Status polling with swap metadata
- Cross-chain EVM/UTXO/Solana handling
- OneClick SDK integration patterns

### From Cetus PR (#11240)
- Sui chain-specific adaptations
- Non-EVM transaction metadata
- Chain adapter fee estimation
- Token vs coin namespace handling

## Skill Quality Improvements

- 1500+ lines of comprehensive guidance (3x expansion)
- Code templates with actual imports and types
- File structure with exact locations
- Integration checklist (28 items)
- Three-phase workflow (Research → Implement → Test)

## Technical Depth

- Monadic Result<T, SwapErrorRight> pattern explained
- HTTP service with caching (createCache, makeSwapperAxiosServiceMonadic)
- Chain adapter usage for fee estimation
- Native token marker handling
- TradeQuote vs TradeRate differences
- accountNumber: undefined requirement for rates

## Documentation Template

- Complete INTEGRATION.md structure
- API details section
- Implementation notes with code
- Known gotchas documentation
- Testing strategies

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

Co-Authored-By: Claude <[email protected]>

* feat: reverts

* fix: remove references to missing companion files

Remove references to @reference.md, @common-gotchas.md, @examples.md
that don't exist. The skill already contains all needed information inline.

Addresses CodeRabbit review feedback.

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

Co-Authored-By: Claude <[email protected]>

* fix: remove all companion file references

Remove all references to non-existent @reference.md, @common-gotchas.md,
and @examples.md files. The skill contains all needed information inline.

Addresses CodeRabbit critical feedback.

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

Co-Authored-By: Claude <[email protected]>

* fix: address CodeRabbit feedback on swapper skill

Updates swapper integration skill to address CodeRabbit review comments:

Feature flag pattern fixes:
- Replace placeholder [SwapperName]Swap with actual example (BebopSwap)
- Update getEnabledSwappers to show direct flag destructuring pattern
- Fix isCrossAccountTradeSupported to use enum values not placeholders
- Align all examples with actual codebase implementation

Markdown formatting improvements:
- Convert 8 bold emphasis sections to proper headings (#### and ###)
- Add language specifiers to 4 code blocks (text, markdown)
- Fix heading structure for better lint compliance

These changes improve accuracy and ensure the skill matches the actual
patterns used in the ShapeShift codebase.

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

Co-Authored-By: Claude <[email protected]>

---------

Co-authored-by: Claude <[email protected]>
@coderabbitai coderabbitai bot mentioned this pull request Dec 3, 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.

4 participants