Skip to content

feat: migrate addressable over to hypelabs - #11420

Merged
premiumjibles merged 3 commits into
developfrom
11181_addressable_to_hypelabs
Dec 17, 2025
Merged

premiumjibles merged 3 commits into
developfrom
11181_addressable_to_hypelabs

Conversation

@premiumjibles

@premiumjibles premiumjibles commented Dec 15, 2025 •

Copy link
Copy Markdown
Contributor

Description

Replaces Addressable Pixel with HypeLabs Pixel as per marketing request

Sister PR in website-frontend: shapeshift/website-frontend#87

Issue (if applicable)

closes #11181

Risk

Low risk, marketing tracking change so unlikely to break anything in the app

High Risk PRs Require 2 approvals

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

Testing

Engineering

  • Turn off any adblock
  • Enable VITE_ENABLE_HYPELAB on local env
  • Make sure you don't see any errors in the console for ha-sdk or api.hypelab
  • Check that window.HypeLabAnalytics is defined
  • Try running window.HypeLabAnalytics.logEvent('test_event') in the console and see if the event appears in window.__hype_analytics
  • Connect a new wallet. You should see the wallet connect event in window.__hype_analytics

Operations

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

Screenshots (if applicable)

image

Summary by CodeRabbit

  • New Features

    • Integrated HypeLab analytics to track wallet connections and trade events; added safe initialization and event tracking.
  • Chores

    • Replaced the previous analytics integration with HypeLab and introduced new environment feature flags and config entries.
    • Updated content security and script loading behavior to align with the HypeLab integration.

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

@premiumjibles
premiumjibles requested a review from a team as a code owner December 15, 2025 23:59
@coderabbitai

coderabbitai Bot commented Dec 16, 2025 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR replaces the Addressable pixel integration with a HypeLab pixel across the app: env vars, CSP, config, pixels, window typings, a HypeLab wrapper, and telemetry hooks (wallet connect, trade confirm, trade success) are updated to use HypeLab.

Changes

Cohort / File(s) Summary
Environment & Config
​.env, ​.env.production, src/config.ts, src/vite-env.d.ts
Replace VITE_ENABLE_ADDRESSABLE/VITE_ADDRESSABLE_TID with VITE_ENABLE_HYPELAB/VITE_HYPELAB_PROPERTY_SLUG; update validators/defaults and .env entries.
CSP Headers
headers/csps/hypelab.ts, headers/csps/index.ts
Swap Addressable → HypeLab CSP: use https://api.hypelab.com for script/connect-src, drop img-src when enabled, and replace addressable import with hypelab.
Window Type Definitions
src/window.d.ts
Remove __adrsbl; add HypeLabAnalytics?, __hype_analytics?, and __hype_wids? globals and corresponding typings.
Pixel Implementation
src/pixels/addressable.ts, src/pixels/hypelab.ts
Remove Addressable initializer; add HypeLab initializer that injects https://api.hypelab.com/v1/scripts/ha-sdk.js, exposes window API, configures client, and handles load/error.
HypeLab Integration Layer
src/lib/hypelab/hypelabSingleton.ts
New module: HypeLabEvent enum, getHypeLab() accessor, and trackHypeLabEvent() safe dispatcher (no-ops if disabled/not present).
Telemetry Hooks
src/index.tsx, src/components/.../useTradeExecution.tsx, src/state/slices/portfolioSlice/portfolioSlice.ts
Replace Addressable import with HypeLab; emit HypeLab events at wallet connect (WalletConnected), trade confirm (first hop), and trade success (final hop) alongside existing Mixpanel calls.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant App as App (UI / Hooks)
participant HypeSingleton as HypeLab Singleton
participant WindowSDK as window.HypeLabAnalytics (SDK)
participant Mixpanel as Mixpanel
Note over App,HypeSingleton: User actions (wallet connect, trade confirm, trade success)
App->>Mixpanel: emit Mixpanel event
App->>HypeSingleton: call trackHypeLabEvent(Event)
HypeSingleton->>WindowSDK: call logEvent(event) [if enabled & SDK present]
alt SDK missing or feature disabled
HypeSingleton-->>App: no-op (safe return)
end

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • src/pixels/hypelab.ts: script injection, Client initialization, and runtime assumptions about window API.
    • src/lib/hypelab/hypelabSingleton.ts: gating logic around env flag and window SDK presence.
    • Telemetry call sites (useTradeExecution.tsx, portfolioSlice.ts): correct event conditions (first hop vs final hop) and ensure no behavioral regressions alongside Mixpanel.
    • CSP change (headers/csps/hypelab.ts): confirm domains and removed img-src are acceptable.

Possibly related PRs

Suggested reviewers

  • gomesalexandre
  • 0xApotheosis

Poem

🐰 I hopped from tag to shiny new script,

adrsbl tucked away in my crypt.
HypeLab hums and logs the trail,
wallet, confirm, success — all without fail.
🎉 carrots for metrics, a celebratory skip!

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change: migrating from Addressable to HypeLabs for marketing tracking pixel functionality.
Linked Issues check ✅ Passed All coding requirements from issue #11181 are met: HypeLabs pixel implemented with custom slug, fires on wallet connect, tracks trade confirm and trade success events for funnel tracking.
Out of Scope Changes check ✅ Passed All changes are in scope: environment configurations, CSP headers, pixel implementations, event tracking, and window type definitions all directly support the Addressable-to-HypeLabs migration.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 11181_addressable_to_hypelabs

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
src/pixels/hypelab.ts (2)

2-6: Simplify boolean normalization and validate propertySlug.

Line 5 uses String(enabledRaw).toLowerCase() which is unnecessarily defensive since environment variables are already strings. Additionally, line 6 exits if propertySlug is missing but doesn't validate its format. Per the PR objectives, the slug should be 4793fe16ca.

Apply this diff to simplify and add validation:

-  const enabledRaw = import.meta.env.VITE_ENABLE_HYPELAB
-  const propertySlug = import.meta.env.VITE_HYPELAB_PROPERTY_SLUG
-
-  const enabled = String(enabledRaw).toLowerCase() === 'true'
-  if (!enabled || !propertySlug) return
+  const enabled = import.meta.env.VITE_ENABLE_HYPELAB === 'true'
+  const propertySlug = import.meta.env.VITE_HYPELAB_PROPERTY_SLUG
+
+  if (!enabled || !propertySlug) return

Optionally, add a console warning for invalid slug:

  if (propertySlug !== '4793fe16ca') {
    console.warn(`Unexpected HypeLab property slug: ${propertySlug}`)
  }

37-44: Simplify script insertion logic.

The multiple fallback paths (insertBefore → head.appendChild → documentElement.appendChild) are overly defensive. Modern browsers always have document.head available, and the standard approach is to simply append to the head.

Apply this diff to simplify:

-  const firstScript = document.getElementsByTagName('script')[0]
-  if (firstScript && firstScript.parentNode) {
-    firstScript.parentNode.insertBefore(script, firstScript)
-  } else if (document.head) {
-    document.head.appendChild(script)
-  } else {
-    document.documentElement.appendChild(script)
-  }
+  document.head.appendChild(script)
src/lib/hypelab/hypelabSingleton.ts (1)

7-16: LGTM with a minor suggestion.

The validation logic properly guards against missing HypeLab integration. The duplicate feature flag check (also in src/pixels/hypelab.ts line 5) is acceptable for safety.

Consider extracting the return type to a shared type definition to ensure consistency with window.d.ts:

export type HypeLabAnalytics = {
  logEvent: (event: string) => void
}

export const getHypeLab = (): HypeLabAnalytics | undefined => {
  // ...
}
📜 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 f78aae0 and f2a2e6a.

📒 Files selected for processing (13)
  • .env (1 hunks)
  • .env.production (1 hunks)
  • headers/csps/hypelab.ts (1 hunks)
  • headers/csps/index.ts (2 hunks)
  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx (3 hunks)
  • src/config.ts (1 hunks)
  • src/index.tsx (1 hunks)
  • src/lib/hypelab/hypelabSingleton.ts (1 hunks)
  • src/pixels/addressable.ts (0 hunks)
  • src/pixels/hypelab.ts (1 hunks)
  • src/state/slices/portfolioSlice/portfolioSlice.ts (2 hunks)
  • src/vite-env.d.ts (2 hunks)
  • src/window.d.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • src/pixels/addressable.ts
🧰 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:

  • src/vite-env.d.ts
  • src/index.tsx
  • src/state/slices/portfolioSlice/portfolioSlice.ts
  • src/pixels/hypelab.ts
  • headers/csps/hypelab.ts
  • headers/csps/index.ts
  • src/config.ts
  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
  • src/lib/hypelab/hypelabSingleton.ts
  • src/window.d.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:

  • src/vite-env.d.ts
  • src/index.tsx
  • src/state/slices/portfolioSlice/portfolioSlice.ts
  • src/pixels/hypelab.ts
  • headers/csps/hypelab.ts
  • headers/csps/index.ts
  • src/config.ts
  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
  • src/lib/hypelab/hypelabSingleton.ts
  • src/window.d.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:

  • src/vite-env.d.ts
  • src/index.tsx
  • src/state/slices/portfolioSlice/portfolioSlice.ts
  • src/pixels/hypelab.ts
  • headers/csps/hypelab.ts
  • headers/csps/index.ts
  • src/config.ts
  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
  • src/lib/hypelab/hypelabSingleton.ts
  • src/window.d.ts
**/*.{tsx,jsx}

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

**/*.{tsx,jsx}: ALWAYS wrap React components in error boundaries and provide user-friendly fallback components with error logging
ALWAYS use useErrorToast hook for displaying errors with translated error messages and handle different error types appropriately

Use PascalCase for React component names and match the component name to the file name

Files:

  • src/index.tsx
  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)

**/*.{jsx,tsx}: ALWAYS use useMemo for expensive computations, object/array creations, and filtered data
ALWAYS use useMemo for derived values and computed properties
ALWAYS use useMemo for conditional values and simple transformations
ALWAYS use useCallback for event handlers and functions passed as props
ALWAYS use useCallback for any function that could be passed as a prop or dependency
ALWAYS include all dependencies in useEffect, useMemo, useCallback dependency arrays
NEVER use // eslint-disable-next-line react-hooks/exhaustive-deps unless absolutely necessary, and ALWAYS explain why dependencies are excluded if using eslint disable
ALWAYS use named exports for components; NEVER use default exports for components
KEEP component files under 200 lines when possible; BREAK DOWN large components into smaller, reusable pieces
EXTRACT complex logic into custom hooks
ALWAYS wrap components in error boundaries for production
ALWAYS handle async errors properly in async operations
ALWAYS provide user-friendly error messages in error handling
ALWAYS use virtualization for lists with 100+ items
ALWAYS implement proper key props for list items
ALWAYS lazy load heavy components using React.lazy for code splitting
ALWAYS use Suspense wrapper for lazy loaded components
USE local state for component-level state; LIFT state up when needed across multiple components; USE Context for avoiding prop drilling; USE Redux only for global state shared across multiple places
Wrap components receiving props with memo for performance optimization

Files:

  • src/index.tsx
  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)

Ensure TypeScript types are explicit and proper; avoid use of any type

Files:

  • src/index.tsx
  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
src/state/slices/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/state/slices/**/*.ts: Migrations are required when changing persisted state structure (see src/state/migrations/)
Export selectors from slice using inline selectors property

Files:

  • src/state/slices/portfolioSlice/portfolioSlice.ts
src/state/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

src/state/**/*.{ts,tsx}: Use createDeepEqualOutputSelector from @/state/selector-utils for deep equality checks
Use createCachedSelector from re-reselect for parameterized selectors

Files:

  • src/state/slices/portfolioSlice/portfolioSlice.ts
{.env.development,.env.production}

📄 CodeRabbit inference engine (CLAUDE.md)

Use .env.development for dev-only features and .env.production for prod settings

Files:

  • .env.production
src/config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Default values always come from environment variables prefixed with VITE_FEATURE_

Files:

  • src/config.ts
🧠 Learnings (25)
📚 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 src/config.ts : Default values always come from environment variables prefixed with `VITE_FEATURE_`

Applied to files:

  • .env
  • src/vite-env.d.ts
  • headers/csps/hypelab.ts
  • .env.production
  • src/config.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: 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`

Applied to files:

  • .env
  • .env.production
📚 Learning: 2025-12-03T23:19:39.158Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11275
File: headers/csps/chains/plasma.ts:1-10
Timestamp: 2025-12-03T23:19:39.158Z
Learning: For CSP files in headers/csps/chains/, gomesalexandre prefers using Vite's loadEnv() pattern directly to load environment variables (e.g., VITE_PLASMA_NODE_URL, VITE_MONAD_NODE_URL) for consistency with existing second-class chain CSP files, rather than using getConfig() from src/config.ts, even though other parts of the codebase use validated config values.

Applied to files:

  • .env
  • src/vite-env.d.ts
  • headers/csps/hypelab.ts
  • .env.production
  • headers/csps/index.ts
  • src/config.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:

  • src/vite-env.d.ts
  • src/config.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:

  • src/index.tsx
  • headers/csps/index.ts
📚 Learning: 2025-11-24T21:20:30.085Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-11-24T21:20:30.085Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use descriptive import names and avoid renaming imports unless necessary

Applied to files:

  • src/index.tsx
📚 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:

  • src/index.tsx
📚 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} : Use Chakra UI components and conventions

Applied to files:

  • src/index.tsx
📚 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:

  • src/index.tsx
📚 Learning: 2025-11-24T21:20:30.085Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-11-24T21:20:30.085Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use named exports for components, functions, and utilities instead of default exports

Applied to files:

  • src/index.tsx
📚 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:

  • src/state/slices/portfolioSlice/portfolioSlice.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 src/state/slices/**/*.ts : Migrations are required when changing persisted state structure (see `src/state/migrations/`)

Applied to files:

  • src/state/slices/portfolioSlice/portfolioSlice.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:

  • src/state/slices/portfolioSlice/portfolioSlice.ts
📚 Learning: 2025-09-22T14:28:23.109Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10566
File: src/hooks/useLedgerConnectionState.ts:71-95
Timestamp: 2025-09-22T14:28:23.109Z
Learning: gomesalexandre designed useLedgerConnectionState to distinguish between USB device connection state and wallet pairing state. When pairing fails but USB is connected, connectionState should remain 'idle' to allow retries, while 'failed' is reserved for when the USB device is physically disconnected.

Applied to files:

  • src/state/slices/portfolioSlice/portfolioSlice.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: Each wallet has unique `walletId` (e.g., `metamask:0x123`, `ledger:ABC`)

Applied to files:

  • src/state/slices/portfolioSlice/portfolioSlice.ts
📚 Learning: 2025-08-22T13:03:36.919Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/Explore/Explore.tsx:110-113
Timestamp: 2025-08-22T13:03:36.919Z
Learning: In src/Routes/RoutesCommon.tsx, the /fox-ecosystem route is already properly gated using disable: !getConfig().VITE_FEATURE_RFOX_FOX_ECOSYSTEM_PAGE, which prevents direct navigation when the VITE_FEATURE_RFOX_FOX_ECOSYSTEM_PAGE flag is false.

Applied to files:

  • headers/csps/hypelab.ts
📚 Learning: 2025-09-16T13:17:02.938Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.

Applied to files:

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

Applied to files:

  • headers/csps/index.ts
📚 Learning: 2025-08-07T11:20:44.614Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.

Applied to files:

  • src/config.ts
📚 Learning: 2025-08-08T11:40:55.734Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx:41-41
Timestamp: 2025-08-08T11:40:55.734Z
Learning: In MultiHopTrade confirm flow (src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx and related hooks), there is only one active trade per flow. Because of this, persistent (module/Redux) dedupe for QuotesReceived in useTrackTradeQuotes is not necessary; the existing ref-based dedupe is acceptable.

Applied to files:

  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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:

  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 Learning: 2025-08-08T11:41:36.971Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:88-109
Timestamp: 2025-08-08T11:41:36.971Z
Learning: In MultiHopTrade Confirm flow (src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx), the Confirm route does not remount; navigating away goes to the swapper input page. Therefore, persistent deduplication across remounts for quote tracking is unnecessary; a ref-based single-mount dedupe is sufficient.

Applied to files:

  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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:

  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useErrorToast` hook for displaying errors with translated error messages and handle different error types appropriately

Applied to files:

  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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:

  • src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
🧬 Code graph analysis (3)
src/state/slices/portfolioSlice/portfolioSlice.ts (2)
src/lib/mixpanel/mixPanelSingleton.ts (1)
  • getMixPanel (9-41)
src/lib/hypelab/hypelabSingleton.ts (1)
  • trackHypeLabEvent (18-23)
headers/csps/hypelab.ts (1)
headers/types.ts (1)
  • Csp (2-2)
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx (1)
src/lib/hypelab/hypelabSingleton.ts (1)
  • trackHypeLabEvent (18-23)
🪛 dotenv-linter (4.0.0)
.env

[warning] 274-274: [UnorderedKey] The VITE_ENABLE_HYPELAB key should go before the VITE_HYPELAB_PROPERTY_SLUG key

(UnorderedKey)

.env.production

[warning] 3-3: [UnorderedKey] The VITE_ENABLE_HYPELAB key should go before the VITE_FEATURE_MIXPANEL key

(UnorderedKey)


[warning] 4-4: [UnorderedKey] The VITE_FEATURE_ADDRESS_BOOK key should go before the VITE_FEATURE_MIXPANEL key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Call / Static
🔇 Additional comments (3)
headers/csps/hypelab.ts (1)

1-15: LGTM!

The CSP configuration correctly uses the loadEnv pattern (consistent with other CSP files), checks the appropriate feature flag, and points to the correct HypeLab domain for both script and connection sources.

src/lib/hypelab/hypelabSingleton.ts (2)

18-23: LGTM!

The function properly handles the optional nature of HypeLab analytics by silently failing when unavailable. The use of the HypeLabEvent enum provides good type safety.


1-5: The enum is well-implemented with descriptive naming and proper string values. However, verification that these event names align with HypeLab's expected event schema requires access to HypeLab's SDK documentation, which is not available in this repository. The integration relies on the external HypeLab Analytics API at https://api.hypelab.com, so confirming the event names match their expected schema would require consulting HypeLab's documentation directly.

Comment thread src/pixels/hypelab.ts
Comment thread src/pixels/hypelab.ts
Comment thread src/window.d.ts

@NeOMakinG NeOMakinG left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

image

Tested with yarn preview:prod and seems to work as intended

Comment thread src/pixels/hypelab.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.env (1)

272-274: Reorder the HypeLab environment variables to match dotenv-linter expectations.

The static analysis tool flags an unordered key issue: VITE_ENABLE_HYPELAB should precede VITE_HYPELAB_PROPERTY_SLUG in the file.

Apply this diff to correct the order:

-# HypeLab
-VITE_HYPELAB_PROPERTY_SLUG=4793fe16ca
 VITE_ENABLE_HYPELAB=false
+VITE_HYPELAB_PROPERTY_SLUG=4793fe16ca
📜 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 f2a2e6a and aff48dc.

📒 Files selected for processing (1)
  • .env (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 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 src/config.ts : Default values always come from environment variables prefixed with `VITE_FEATURE_`

Applied to files:

  • .env
📚 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: 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`

Applied to files:

  • .env
📚 Learning: 2025-12-03T23:19:39.158Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11275
File: headers/csps/chains/plasma.ts:1-10
Timestamp: 2025-12-03T23:19:39.158Z
Learning: For CSP files in headers/csps/chains/, gomesalexandre prefers using Vite's loadEnv() pattern directly to load environment variables (e.g., VITE_PLASMA_NODE_URL, VITE_MONAD_NODE_URL) for consistency with existing second-class chain CSP files, rather than using getConfig() from src/config.ts, even though other parts of the codebase use validated config values.

Applied to files:

  • .env
🪛 dotenv-linter (4.0.0)
.env

[warning] 274-274: [UnorderedKey] The VITE_ENABLE_HYPELAB key should go before the VITE_HYPELAB_PROPERTY_SLUG key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install and Cache

Comment thread .env
@premiumjibles
premiumjibles enabled auto-merge (squash) December 17, 2025 03:49
@premiumjibles
premiumjibles merged commit 4f2dd78 into develop Dec 17, 2025
4 checks passed
@premiumjibles
premiumjibles deleted the 11181_addressable_to_hypelabs branch December 17, 2025 03:56
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.

Replace Addressable Pixel with HypeLabs Pixel

2 participants