Skip to content
Merged
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
48 changes: 25 additions & 23 deletions .claude/rules/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,47 @@

OpenScan follows a layered architecture with clear separation between data fetching, transformation, and presentation:

### 1. RPC Layer (`RPCClient.ts`)
Handles JSON-RPC communication with blockchain nodes:
- Supports two strategies: `fallback` (sequential with automatic failover) and `parallel` (query all providers simultaneously)
- Strategy is configurable via user settings (`useDataService` hook applies strategy)
- Parallel mode enables provider comparison and inconsistency detection

### 2. Fetcher Layer (`services/EVM/*/fetchers/`)
Makes raw RPC calls for specific data types:
- Network-specific implementations: `L1/`, `Arbitrum/`, `Optimism/`
- Each fetcher handles one domain (blocks, transactions, addresses, network stats)

### 3. Adapter Layer (`services/EVM/*/adapters/`)
Transforms raw RPC responses into typed domain objects:
- Normalizes network-specific fields (e.g., Arbitrum's `l1BlockNumber`, Optimism's L1 fee data)
- Ensures consistent type structure across networks

### 4. Service Layer (`DataService.ts`)
### 1. Client Layer (`@openscan/network-connectors`)
Typed RPC clients for blockchain communication:
- `EthereumClient` - Standard JSON-RPC for EVM chains
- `HardhatClient` - Extended client with Hardhat-specific methods (`hardhat_*`, `evm_*`, `debug_*`)
- `BitcoinClient` - Bitcoin JSON-RPC (`getblock`, `getrawtransaction`, etc.)
- Supports `fallback`, `parallel`, and `race` strategies

### 2. Adapter Layer (`services/adapters/`)
Abstract `NetworkAdapter` base class with chain-specific implementations:
- `EVMAdapter` - Default EVM adapter (Ethereum, BSC, Polygon, Sepolia)
- `ArbitrumAdapter` - Adds `l1BlockNumber`, `sendCount`, `sendRoot`
- `OptimismAdapter` / `BaseAdapter` - Adds L1 fee breakdown (`l1Fee`, `l1GasPrice`, `l1GasUsed`)
- `HardhatAdapter` - Localhost (31337) with trace support via struct log conversion
- `BitcoinAdapter` - Bitcoin networks with UTXO model, mempool, and block explorer
- Each adapter implements: `getBlock`, `getTransaction`, `getAddress`, `getNetworkStats`, trace methods
- `AdapterFactory` routes chain ID to the correct adapter

### 3. Service Layer (`DataService.ts`)
Orchestrates data fetching with caching and metadata:
- Instantiates network-specific fetchers/adapters based on chain ID
- Instantiates the correct adapter via `AdapterFactory` based on chain ID
- Returns `DataWithMetadata<T>` when using parallel strategy
- 30-second in-memory cache keyed by `networkId:type:identifier`
- Supports trace operations for Hardhat (31337) and localhost networks

### 5. Hook Layer (`hooks/`)
### 4. Hook Layer (`hooks/`)
React integration:
- `useDataService(networkId)`: Creates DataService instance with strategy from settings
- `useProviderSelection`: Manages user's selected RPC provider in parallel mode
- `useSelectedData`: Extracts data from specific provider based on user selection

### 6. Context Layer (`context/`)
### 5. Context Layer (`context/`)
Global state management:
- `AppContext`: RPC URLs configuration
- `SettingsContext`: User settings including `rpcStrategy` ('fallback' | 'parallel')
- `SettingsContext`: User settings including `rpcStrategy` ('fallback' | 'parallel' | 'race')

## Network-Specific Handling

Chain ID detection in `DataService` constructor determines which adapters/fetchers to use:
Chain ID detection in `AdapterFactory` determines which adapter to instantiate:

- **Arbitrum** (42161): `ArbitrumAdapter` - adds `l1BlockNumber`, `sendCount`, `requestId`
- **Arbitrum** (42161): `ArbitrumAdapter` - adds `l1BlockNumber`, `sendCount`, `sendRoot`
- **Bitcoin** (bip122:*): `BitcoinAdapter` - UTXO model, mempool transactions, block rewards
- **OP Stack** (10, 8453): `OptimismAdapter` (10), `BaseAdapter` (8453) - adds L1 fee breakdown (`l1Fee`, `l1GasPrice`, `l1GasUsed`)
- **Hardhat** (31337): `HardhatAdapter` - uses `HardhatClient` from `@openscan/network-connectors`; trace support via struct log conversion (`buildCallTreeFromStructLogs`, `buildPrestateFromStructLogs` in `src/utils/structLogConverter.ts`) since Hardhat v3 does not support `callTracer`/`prestateTracer`
- **Default**: `EVMAdapter` for Ethereum (1), BSC (56, 97), Polygon (137), Sepolia (11155111), Avalanche (43114)
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/code-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ npm run typecheck

# 4. Verify i18n compliance
# - Ensure no hardcoded user-facing strings
# - Test in both English and Spanish if you added translations
# - Test in multiple languages if you added translations (en, es, ja, pt-BR, zh)

# 5. Run tests (if applicable)
npm run test:run
Expand Down
13 changes: 7 additions & 6 deletions .claude/rules/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
- **Library**: react-i18next (v16.5.4) with i18next (v25.8.0)
- **Configuration**: `src/i18n.ts`
- **Type Definitions**: `src/i18next.d.ts` (provides TypeScript autocomplete)
- **Supported Languages**: English (en), Spanish (es)
- **Supported Languages**: English (en), Spanish (es), Japanese (ja), Portuguese-BR (pt-BR), Chinese (zh)
- **Language Detection**: Auto-detects from browser or localStorage (`openScan_language`)

## When to Use i18n
Expand Down Expand Up @@ -49,6 +49,7 @@ Choose the appropriate namespace based on the component location:
8. **devtools** - Developer tools page
9. **errors** - Error messages (if not in common)
10. **tokenDetails** - Token detail pages (ERC20, ERC721, ERC1155)
11. **tooltips** - Helper tooltip content for blockchain data fields (used by FieldLabel/HelperTooltip)

## Basic Usage

Expand Down Expand Up @@ -153,9 +154,9 @@ const currentLang = i18n.language; // "en" or "es"

1. **Identify the appropriate namespace** based on component location
2. **Add key to English file** (`src/locales/en/{namespace}.json`)
3. **Add same key to Spanish file** (`src/locales/es/{namespace}.json`)
3. **Add same key to all other locale files** (`src/locales/{es,ja,pt-BR,zh}/{namespace}.json`)
4. **Use TypeScript autocomplete** to verify the key exists
5. **Test in both languages** by switching in Settings
5. **Test in multiple languages** by switching in Settings

### Example

Expand Down Expand Up @@ -325,9 +326,9 @@ When adding or modifying components, ensure:

- [ ] No hardcoded user-facing strings remain
- [ ] All text uses `t()` function from useTranslation
- [ ] Translation keys exist in **both** en/ and es/ directories
- [ ] Translation keys exist in **all** locale directories (en, es, ja, pt-BR, zh)
- [ ] TypeScript compilation passes (`npm run typecheck`)
- [ ] Tested in both English and Spanish (switch in Settings)
- [ ] Tested in multiple languages (switch in Settings)

## Checklist for Code Review

Expand All @@ -337,5 +338,5 @@ When reviewing code, verify:
- [ ] Appropriate namespace is selected
- [ ] Translation keys follow existing naming patterns
- [ ] Interpolation variables are properly typed
- [ ] Translations exist in all supported languages
- [ ] Translations exist in all 5 supported languages (en, es, ja, pt-BR, zh)
- [ ] No typos in translation keys (TypeScript should catch these)
19 changes: 10 additions & 9 deletions .claude/rules/patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

## When Modifying Data Fetching

- Always maintain the adapter pattern: Fetcher → Adapter → Service
- Always maintain the adapter pattern: Client → Adapter → Service
- All adapters extend the abstract `NetworkAdapter` class (`services/adapters/NetworkAdapter.ts`)
- If adding parallel strategy support, ensure complete objects are built for each provider
- Test both `fallback` and `parallel` strategies
- Test `fallback`, `parallel`, and `race` strategies
- Update TypeScript types in `src/types/index.ts` if adding new fields

## When Adding L2-Specific Features

- Check if network is OP Stack-based (Optimism, Base) or Arbitrum
- Add network-specific types (e.g., `TransactionOptimism extends Transaction`)
- Create adapters that inherit base behavior and add L2 fields
- Update `DataService` conditional logic in constructor and relevant methods
- Create a new adapter extending `NetworkAdapter` in `services/adapters/[Network]/`
- Register the adapter in `AdapterFactory` (`services/adapters/adaptersFactory.ts`)

## When Working with Cache

Expand All @@ -32,10 +33,10 @@

1. Add chain ID to `src/types/index.ts` if creating new domain types
2. Add default RPC endpoints to `src/config/rpcConfig.ts`
3. Determine if network needs a custom adapter (L1, Arbitrum-like, OP Stack-like, Hardhat-like)
4. If custom: create `src/services/adapters/[Network]Adapter/[Network]Adapter.ts`
5. Register the adapter in `src/services/adapters/adaptersFactory.ts` with its chain ID
6. Add network config to `src/config/networks.json`
3. Determine if network needs a custom adapter (L1, Arbitrum-like, OP Stack-like, Bitcoin, Hardhat-like)
4. If custom: create `src/services/adapters/[Network]/[Network]Adapter.ts` extending `NetworkAdapter`
5. Register the adapter in `AdapterFactory` (`src/services/adapters/adaptersFactory.ts`)
6. Add network config to `ALL_NETWORKS` in `src/config/networks.ts`
7. Add network logo to `public/` and update `logoType` in network config

## Testing with Local Networks
Expand All @@ -51,7 +52,7 @@ OpenScan includes special support for localhost development:

### Address Page Components
- Use display components for different address types: `AccountDisplay`, `ContractDisplay`, `ERC20Display`, `ERC721Display`, `ERC1155Display`
- Shared components in `src/components/pages/address/shared/`
- Shared components in `src/components/pages/evm/address/shared/`
- Card-based layout with Overview and More Info sections

### Theming
Expand Down
107 changes: 69 additions & 38 deletions .claude/rules/workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,76 +2,107 @@

## Branch Strategy

The project follows a structured branching workflow:
The project uses two workflows depending on the scope of changes:

### Patch Releases (default workflow)

For incremental work (bug fixes, small features, improvements) that goes into the next patch version:

```
feature/fix/refactor branches → release branch (vX.Y.Z) → dev (staging/QA) → main (production)
feature/fix/refactor branches → dev (release candidate) → main (production)
```

### Branch Types
1. **Dev Branch**: Always holds the next release candidate (patch increment)
- Feature/fix PRs are created directly against `dev`
- Used for QA/staging before production
- Always represents the next patch version (e.g., if main is v1.2.0, dev is the v1.2.1 candidate)

1. **Feature/Fix/Refactor Branches**: Created from the **release branch** for specific changes
2. **Feature/Fix/Refactor Branches**: Created from `dev`
- Naming: `feat/<description>`, `fix/<description>`, `refactor/<description>`
- Example: `feat/token-holdings`, `fix/light-theme-colors`, `refactor/address-layout`
- PRs are created against the release branch

2. **Release Branches**: Created for each release cycle
- Naming: `release/vX.Y.Z` (e.g., `release/v1.1.1`)
- All feature branches are merged here
- When features are complete, merged to `dev` for QA/staging
- PRs are created against `dev`

3. **Dev Branch**: Staging/QA environment
- Receives merges from release branches
- Used for QA testing before production
- If fixes are needed during QA, PRs can be created directly against `dev`

4. **Main Branch**: Production-ready code
3. **Main Branch**: Production-ready code
- Only receives merges from `dev` after QA approval
- Always stable and deployable
- Tagged with the version on merge

### Workflow Steps
#### Patch Workflow Steps

1. Create or checkout the release branch:
1. Create feature branch from `dev`:
```bash
git checkout release/v1.1.1
git pull origin release/v1.1.1
git checkout dev
git pull origin dev
git checkout -b feat/my-feature
```

2. Create feature branch from the release branch:
2. Work on feature, commit changes following conventional commits

3. Push and create PR to `dev`:
```bash
git checkout -b feat/my-feature
git push -u origin feat/my-feature
gh pr create --base dev
```

3. Work on feature, commit changes following conventional commits
4. After PR approval and merge to `dev`, delete feature branch

4. Push and create PR to the **release branch**:
5. After QA approval, merge `dev` to `main`:
```bash
git push -u origin feat/my-feature
gh pr create --base release/v1.1.1
git checkout main
git merge dev
git tag v1.2.1
git push origin main --tags
```

5. After PR approval and merge to release branch, delete feature branch
### Minor/Major Releases (release branch workflow)

For larger milestones with multiple coordinated changes (new features, breaking changes):

6. When release is ready for QA, merge release branch to `dev`:
```
feature/fix/refactor branches → release branch (vX.Y.Z) → dev → main
```

1. **Release Branches**: Created from `dev` for each release cycle
- Naming: `release/vX.Y.Z` (e.g., `release/v1.3.0`)
- Feature branches are created from and merged into the release branch
- When features are complete, merged to `dev` for QA/staging

2. **Feature Branches**: Created from the **release branch**
- PRs are created against the release branch

#### Release Branch Workflow Steps

1. Create the release branch from `dev`:
```bash
git checkout dev
git merge release/v1.1.1
git push origin dev
git checkout -b release/v1.3.0
git push -u origin release/v1.3.0
```

2. Create feature branches from the release branch:
```bash
git checkout release/v1.3.0
git checkout -b feat/my-feature
```

7. **QA/Staging fixes**: If issues are found during QA, create PRs directly against `dev`:
3. Push and create PR to the **release branch**:
```bash
git push -u origin feat/my-feature
gh pr create --base release/v1.3.0
```

4. When all features are merged, merge release branch to `dev` for QA:
```bash
git checkout dev
git checkout -b fix/qa-issue
# ... fix the issue ...
gh pr create --base dev
git merge release/v1.3.0
git push origin dev
```

8. After QA approval, merge `dev` to `main`:
5. QA fixes go directly against `dev`

6. After QA approval, merge `dev` to `main`:
```bash
git checkout main
git merge dev
git tag v1.1.1
git tag v1.3.0
git push origin main --tags
```

Expand Down
Loading