Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ VITE_ARBITRUM_NOVA_NODE_URL=https://api.arbitrum-nova.shapeshift.com/api/v1/json
VITE_BASE_NODE_URL=https://api.base.shapeshift.com/api/v1/jsonrpc
VITE_MONAD_NODE_URL=https://rpc.monad.xyz
VITE_PLASMA_NODE_URL=https://rpc.plasma.to
VITE_MEGAETH_NODE_URL=https://mainnet.megaeth.com/rpc
VITE_THORCHAIN_NODE_URL=https://api.thorchain.shapeshift.com/lcd
VITE_MAYACHAIN_NODE_URL=https://api.mayachain.shapeshift.com/lcd
VITE_SOLANA_NODE_URL=https://api.solana.shapeshift.com/api/v1/jsonrpc
Expand Down Expand Up @@ -303,4 +304,5 @@ VITE_FEATURE_MONAD=true
VITE_FEATURE_PLASMA=true
VITE_HYPEREVM_NODE_URL=https://rpc.hyperliquid.xyz/evm
VITE_FEATURE_HYPEREVM=true
VITE_FEATURE_MEGAETH=false
VITE_FEATURE_NEAR=false
2 changes: 2 additions & 0 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ VITE_BASE_NODE_URL=https://dev-api.base.shapeshift.com/api/v1/jsonrpc
VITE_MONAD_NODE_URL=https://rpc.monad.xyz
VITE_PLASMA_NODE_URL=https://rpc.plasma.to
VITE_HYPEREVM_NODE_URL=https://rpc.hyperliquid.xyz/evm
VITE_MEGAETH_NODE_URL=https://mainnet.megaeth.com/rpc
# Swap me back to 9R as-needed
# VITE_THORCHAIN_NODE_URL=https://thornode.ninerealms.com
VITE_THORCHAIN_NODE_URL=https://dev-api.thorchain.shapeshift.com/lcd
Expand Down Expand Up @@ -92,4 +93,5 @@ VITE_FEATURE_NOTIFICATIONS_WEBSERVICES=true

VITE_FEATURE_WC_DIRECT_CONNECTION=true
VITE_FEATURE_CETUS_SWAP=true
VITE_FEATURE_MEGAETH=true
VITE_FEATURE_NEAR=true
2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ nodeLinker: node-modules

npmAuthToken: "${NPM_AUTH-fallback}"

npmRegistryServer: "https://registry.npmjs.org"
npmRegistryServer: "http://127.0.0.1:4873"

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
Expand Down
36 changes: 36 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Global Programming Rules

### Code Quality & Style

- Look for opportunities to use existing code rather than creating new code
- Follow existing code conventions in each file/project
- Use existing libraries and utilities already present in the codebase
Expand All @@ -19,6 +20,7 @@
- When function parameters are unused due to interface requirements, refactor the interface or implementation to remove them rather than prefixing with underscore

### Security & Best Practices

- Never expose, log, or commit secrets, API keys, or credentials
- Validate all inputs, especially user inputs
- Use parameterized queries to prevent SQL injection
Expand All @@ -27,34 +29,39 @@
- Use HTTPS and secure communication protocols

### Error Handling

- Handle errors gracefully with meaningful messages
- Don't silently catch and ignore exceptions
- Log errors appropriately for debugging
- Provide fallback behavior when possible
- Use proper HTTP status codes in APIs

### Performance

- Avoid premature optimization, but be mindful of performance
- Use appropriate data structures for the task
- Minimize database queries and API calls
- Implement proper caching strategies
- Optimize images and assets for web delivery

### Testing

- 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

### Documentation & Communication

- 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.
- Write clear commit messages explaining the "why"
- Use meaningful names for branches, variables, and functions
- Keep README files updated with setup and usage instructions

### Rule Management

- When user says "add that to the project rules": take previous guidance, form a rule, add to project-specific section in CLAUDE.md
- When user says "add that to the global rules": take previous guidance, form a rule, add to global rules section in CLAUDE.md

Expand All @@ -63,13 +70,15 @@
## Project-Specific Rules: ShapeShift

### Project Overview

- **Project**: Decentralized crypto exchange platform
- **Main branch**: `develop` (not main/master)
- **Package manager**: yarn
- **State management**: Redux Toolkit with redux-persist
- **Architecture**: Plugin-based for blockchain support

### Code Quality & Standards

- Always run `yarn lint --fix` and `yarn type-check` after making changes
- Keep changes surgical where possible - minimize changes to make code reviews easier
- Make targeted, focused modifications rather than broad refactors unless specifically requested
Expand All @@ -79,42 +88,65 @@
- Avoid `let` variable assignments - prefer `const` with inline IIFE switch statements or extract to functions for conditional logic
- 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

### Code Style & Formatting

**Prettier/ESLint formatting rules (follow these to avoid lint changes):**

- Use **single quotes** for strings (both JS and JSX)
- **No semicolons** at end of statements
- 100 character line width
- Trailing commas everywhere
- Arrow functions: avoid parens for single parameter (`x => x` not `(x) => x`)
- Use `===` not `==` (eqeqeq rule)
- Object shorthand (`{ foo }` not `{ foo: foo }`)
- No default exports (use named exports: `export const Foo` not `export default Foo`)
- Exception: Allowed in `*.stories.*` and test mock data files
- Type imports: Use `import type` for types (`import type { Foo } from './foo'`)
- Prefer top-level type imports over inline type imports

### Git & Version Control

- Never commit changes unless explicitly requested
- When creating commits, follow the Git Safety Protocol (see session notes)
- Main branch is `develop` - use this for PRs
- Branch naming: Use descriptive names (e.g., `feat_gridplus`, `fix_wallet_connect`)

### UI/UX Standards

- 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

### Internationalization (i18n)

- All copy/text must use translation keys - never hardcode strings
- Add English copy to `src/assets/translations/en/main.json` (find appropriate section)
- Ignore other language translation files - only update English
- Use the translation hook: `useTranslate()` from `react-polyglot`

### Feature Flags

- Feature flags are stored in Redux state under `preferences.featureFlags`
- Feature flags are NOT persisted between sessions (blacklisted in redux-persist)
- Default values always come from environment variables prefixed with `VITE_FEATURE_`

**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` (e.g., `VITE_FEATURE_MY_FLAG: bool({ default: false })`)
3. Add to initial state in `preferencesSlice.ts` (e.g., `MyFlag: getConfig().VITE_FEATURE_MY_FLAG`)
4. Add to test mock in `src/test/mocks/store.ts`
5. Set appropriate values in `.env`, `.env.development`, and `.env.production`

**Usage:**

- Use `useFeatureFlag('FlagName')` hook to access feature flag values in components
- The `/flags` route provides a hidden UI for toggling feature flags at runtime (click settings modal header 5 times)
- Use `.env.development` for dev-only features and `.env.production` for prod settings

### Redux State Management

- Uses Redux Toolkit with createSlice
- State is persisted with redux-persist (localforage)
- Migrations are required when changing persisted state structure (see `src/state/migrations/`)
Expand All @@ -126,6 +158,7 @@
5. Export selectors from slice using `selectors` property

### Type Definitions

- Prefer `type` over `interface` for type definitions
- Use strict typing - avoid `any`
- Use `Nominal` types for domain identifiers (e.g., `WalletId`, `AccountId`)
Expand All @@ -134,17 +167,20 @@
### Common Patterns

**Selectors:**

- Use `createDeepEqualOutputSelector` from `@/state/selector-utils` for deep equality checks
- Use `createCachedSelector` from `re-reselect` for parameterized selectors
- Export selectors from slice using inline `selectors` property

**Components:**

- Use `useAppSelector` for Redux state
- Use `useAppDispatch` for Redux actions
- Memoize expensive computations with `useMemo`
- Memoize callbacks with `useCallback`

**Wallet Integration:**

- Wallets are managed via `WalletProvider` context
- Each wallet has unique `walletId` (e.g., `metamask:0x123`, `ledger:ABC`)
- Portfolio state is filtered by active `walletId`
Expand Down
10 changes: 10 additions & 0 deletions headers/csps/chains/megaeth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { loadEnv } from 'vite'

import type { Csp } from '../../types'

const mode = process.env.MODE ?? process.env.NODE_ENV ?? 'development'
const env = loadEnv(mode, process.cwd(), '')

export const csp: Csp = {
'connect-src': [env.VITE_MEGAETH_NODE_URL],
}
2 changes: 2 additions & 0 deletions headers/csps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { csp as gnosis } from './chains/gnosis'
import { csp as hyperevm } from './chains/hyperevm'
import { csp as litecoin } from './chains/litecoin'
import { csp as mayachain } from './chains/mayachain'
import { csp as megaeth } from './chains/megaeth'
import { csp as monad } from './chains/monad'
import { csp as near } from './chains/near'
import { csp as optimism } from './chains/optimism'
Expand Down Expand Up @@ -106,6 +107,7 @@ export const csps = [
gnosis,
hyperevm,
litecoin,
megaeth,
optimism,
polygon,
solana,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@
"use-long-press": "^3.3.0",
"uuid": "^9.0.0",
"vaul": "^1.1.2",
"viem": "2.40.3",
"viem": "2.43.5",
"wagmi": "^2.9.2",
"web-vitals": "^2.1.4",
"wouter": "^3.6.0"
Expand Down
6 changes: 6 additions & 0 deletions packages/caip/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const baseAssetId: AssetId = 'eip155:8453/slip44:60'
export const monadAssetId: AssetId = 'eip155:143/slip44:60'
export const hyperEvmAssetId: AssetId = 'eip155:999/slip44:60'
export const plasmaAssetId: AssetId = 'eip155:9745/slip44:60'
export const megaethAssetId: AssetId = 'eip155:4326/slip44:60' // TODO: MegaETH Mainnet - Switch from testnet when whitelisted
export const solAssetId: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501'
export const wrappedSolAssetId: AssetId =
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:So11111111111111111111111111111111111111112'
Expand Down Expand Up @@ -78,6 +79,7 @@ export const baseChainId: ChainId = 'eip155:8453'
export const monadChainId: ChainId = 'eip155:143'
export const hyperEvmChainId: ChainId = 'eip155:999'
export const plasmaChainId: ChainId = 'eip155:9745'
export const megaethChainId: ChainId = 'eip155:4326' // TODO: MegaETH Mainnet (Frontier) - Switch from testnet when whitelisted

export const cosmosChainId: ChainId = 'cosmos:cosmoshub-4'
export const thorchainChainId: ChainId = 'cosmos:thorchain-1'
Expand Down Expand Up @@ -127,6 +129,7 @@ export const CHAIN_REFERENCE = {
MonadMainnet: '143', // https://docs.monad.xyz/developer-essentials/network-information
HyperEvmMainnet: '999', // https://chainlist.org/chain/999
PlasmaMainnet: '9745', // https://chainlist.org/chain/9745
MegaEthMainnet: '4326', // https://docs.megaeth.com/frontier - TODO: Switch from testnet when whitelisted
SolanaMainnet: '5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', // https://namespaces.chainagnostic.org/solana/caip2
TronMainnet: '0x2b6653dc', // https://developers.tron.network/docs/networks
SuiMainnet: '35834a8a', // First 8 chars of SUI mainnet genesis hash
Expand Down Expand Up @@ -169,6 +172,7 @@ export const ASSET_REFERENCE = {
Monad: '60', // evm chain which uses ethereum derivation path as common practice
HyperEvm: '60', // evm chain which uses ethereum derivation path as common practice
Plasma: '60', // evm chain which uses ethereum derivation path as common practice
MegaEth: '60', // evm chain which uses ethereum derivation path as common practice
Solana: '501',
Tron: '195',
Sui: '784',
Expand Down Expand Up @@ -197,6 +201,7 @@ export const VALID_CHAIN_IDS: ValidChainMap = Object.freeze({
CHAIN_REFERENCE.MonadMainnet,
CHAIN_REFERENCE.HyperEvmMainnet,
CHAIN_REFERENCE.PlasmaMainnet,
CHAIN_REFERENCE.MegaEthMainnet,
],
[CHAIN_NAMESPACE.CosmosSdk]: [
CHAIN_REFERENCE.CosmosHubMainnet,
Expand Down Expand Up @@ -250,6 +255,7 @@ export const FEE_ASSET_IDS = [
arbitrumNovaAssetId,
baseAssetId,
monadAssetId,
megaethAssetId,
solAssetId,
tronAssetId,
suiAssetId,
Expand Down
2 changes: 1 addition & 1 deletion packages/chain-adapters/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"multicoin-address-validator": "^0.5.12",
"node-polyglot": "^2.4.0",
"p-queue": "^8.0.1",
"viem": "^2.40.3"
"viem": "2.43.5"
},
"devDependencies": {
"@types/bs58check": "^2.1.0",
Expand Down
21 changes: 19 additions & 2 deletions packages/chain-adapters/src/evm/EvmBaseAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
supportsETH,
supportsGnosis,
supportsHyperEvm,
supportsMegaEth,
supportsMonad,
supportsOptimism,
supportsPlasma,
Expand Down Expand Up @@ -82,6 +83,7 @@ export const evmChainIds = [
KnownChainIds.MonadMainnet,
KnownChainIds.HyperEvmMainnet,
KnownChainIds.PlasmaMainnet,
KnownChainIds.MegaEthMainnet,
] as const

export type EvmChainAdapter = EvmBaseAdapter<EvmChainId>
Expand Down Expand Up @@ -151,7 +153,12 @@ export abstract class EvmBaseAdapter<T extends EvmChainId> implements IChainAdap

getBip44Params({ accountNumber }: GetBip44ParamsInput): Bip44Params {
if (accountNumber < 0) throw new Error('accountNumber must be >= 0')
return { ...this.rootBip44Params, accountNumber, isChange: false, addressIndex: 0 }
return {
...this.rootBip44Params,
accountNumber,
isChange: false,
addressIndex: 0,
}
}

protected assertSupportsChain(
Expand Down Expand Up @@ -184,6 +191,8 @@ export abstract class EvmBaseAdapter<T extends EvmChainId> implements IChainAdap
return supportsHyperEvm(wallet)
case Number(fromChainId(KnownChainIds.PlasmaMainnet).chainReference):
return supportsPlasma(wallet)
case Number(fromChainId(KnownChainIds.MegaEthMainnet).chainReference):
return supportsMegaEth(wallet)
default:
return false
}
Expand Down Expand Up @@ -276,6 +285,11 @@ export abstract class EvmBaseAdapter<T extends EvmChainId> implements IChainAdap
symbol: 'XPL',
explorer: 'https://plasmascan.to',
},
[KnownChainIds.MegaEthMainnet]: {
name: 'Ether',
symbol: 'ETH',
explorer: 'https://megaeth.blockscout.com',
},
}[this.chainId]

try {
Expand Down Expand Up @@ -665,7 +679,10 @@ export abstract class EvmBaseAdapter<T extends EvmChainId> implements IChainAdap
const bip44Params = this.getBip44Params({ accountNumber })
const subscriptionId = toRootDerivationPath(bip44Params)

this.providers.ws.unsubscribeTxs(subscriptionId, { topic: 'txs', addresses: [] })
this.providers.ws.unsubscribeTxs(subscriptionId, {
topic: 'txs',
addresses: [],
})
}

closeTxs(): void {
Expand Down
1 change: 1 addition & 0 deletions packages/chain-adapters/src/evm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ export * as base from './base'
export * as monad from './monad'
export * as hyperevm from './hyperevm'
export * as plasma from './plasma'
export * as megaeth from './megaeth'
Loading
Loading