diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml new file mode 100644 index 00000000..205b0fe2 --- /dev/null +++ b/.github/workflows/claude-code-review.yml @@ -0,0 +1,57 @@ +name: Claude Code Review + +on: + pull_request: + types: [opened, synchronize] + # Optional: Only run on specific file changes + # paths: + # - "src/**/*.ts" + # - "src/**/*.tsx" + # - "src/**/*.js" + # - "src/**/*.jsx" + +jobs: + claude-review: + # Optional: Filter by PR author + # if: | + # github.event.pull_request.user.login == 'external-contributor' || + # github.event.pull_request.user.login == 'new-developer' || + # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' + + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code Review + id: claude-review + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + prompt: | + REPO: ${{ github.repository }} + PR NUMBER: ${{ github.event.pull_request.number }} + + Please review this pull request and provide feedback on: + - Code quality and best practices + - Potential bugs or issues + - Performance considerations + - Security concerns + - Test coverage + + Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback. + + Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR. + + # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md + # or https://docs.claude.com/en/docs/claude-code/cli-reference for available options + claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"' + diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml new file mode 100644 index 00000000..412cef9e --- /dev/null +++ b/.github/workflows/claude.yml @@ -0,0 +1,50 @@ +name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + issues: + types: [opened, assigned] + pull_request_review: + types: [submitted] + +jobs: + claude: + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + actions: read # Required for Claude to read CI results on PRs + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + + # This is an optional setting that allows Claude to read CI results on PRs + additional_permissions: | + actions: read + + # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it. + # prompt: 'Update the pull request description to include a summary of changes.' + + # Optional: Add claude_args to customize behavior and configuration + # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md + # or https://docs.claude.com/en/docs/claude-code/cli-reference for available options + # claude_args: '--allowed-tools Bash(gh pr:*)' + diff --git a/.gitignore b/.gitignore index 74cf0a18..9546893d 100644 --- a/.gitignore +++ b/.gitignore @@ -17,5 +17,3 @@ buildServer.json # VSCode .vscode/ -#AI -CLAUDE.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..c90eb64c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,267 @@ +# AGENTS.md + +This file provides guidance to AI agents like Claude Code (claude.ai/code) when working with code in this repository. + +This file is symlinked for cross-agents compatibility to the following paths: +- `CLAUDE.md` + +## Project Overview + +Bitkit iOS is a native Swift implementation of a Bitcoin and Lightning Network wallet. This is a work-in-progress repository that is **NOT** the live production app. The production app uses React Native and is at github.com/synonymdev/bitkit. + +This app integrates with: +- **LDK Node** (Lightning Development Kit) for Lightning Network functionality +- **BitkitCore** (Rust-based core library) for Bitcoin operations +- **Electrum/Esplora** for blockchain data +- **Blocktank** for Lightning channel services + +## Build & Development Commands + +### Building +```bash +# Standard build - Open Bitkit.xcodeproj in Xcode and build + +# E2E test build (uses local Electrum backend) +xcodebuild -workspace Bitkit.xcodeproj/project.xcworkspace \ + -scheme Bitkit \ + -configuration Debug \ + SWIFT_ACTIVE_COMPILATION_CONDITIONS='$(inherited) E2E_BUILD' \ + build +``` + +### Code Formatting +```bash +# Install SwiftFormat +brew install swiftformat + +# Format all Swift code +swiftformat . + +# Setup git hooks for automatic formatting on commits +npm install -g git-format-staged +./scripts/setup-hooks.sh +``` + +### Localization +```bash +# Validate translations (checks for missing translations and validates translation keys) +node scripts/validate-translations.js +``` + +**Note:** Localization files are synced from Transifex using [bitkit-transifex-sync](https://github.com/synonymdev/bitkit-transifex-sync). + +### Testing +```bash +# Run tests via Xcode Test Navigator or: +# Cmd+U in Xcode +``` + +## Architecture + +### SwiftUI Patterns (CRITICAL) + +This project follows **modern SwiftUI patterns** and explicitly **AVOIDS traditional MVVM with ViewModels**. The architecture uses: + +1. **@Observable Objects for Business Logic** + - Use `@Observable class` for shared business logic instead of ViewModels + - Inject via `.environment(businessLogic)` + - Retrieve with `@Environment(BusinessLogic.self)` + - Example: `@Observable class UserManager { var users: [User] = []; func loadUsers() async { } }` + +2. **Native SwiftUI Data Flow** + - `@State` for local view state only + - `@Binding` for two-way data flow between parent/child views + - `@Observable` for shared business logic objects + - All state mutations must happen on `@MainActor` + +3. **Lifecycle Management** + - Use `.task` modifier for async operations (NOT `.onAppear`) + - `.task` automatically cancels when view disappears + - Async operations should delegate to `@Observable` business logic objects + +4. **Component Design** + - Decompose views into small, focused, single-purpose components + - Use descriptive names (e.g., `UserProfileCard` not `Card`) + - Prefer composition over deep view hierarchies + - Components should be independent and reusable with generic data types + +### Core Architecture Layers + +``` +┌─────────────────────────────────────────────────┐ +│ Views (SwiftUI) │ +│ - MainNavView, Activity, Wallet, Settings │ +│ - Small, focused components │ +└─────────────────┬───────────────────────────────┘ + │ +┌─────────────────▼───────────────────────────────┐ +│ @Observable Business Logic │ +│ - AppViewModel, WalletViewModel, etc. │ +│ - Injected via .environment() │ +└─────────────────┬───────────────────────────────┘ + │ +┌─────────────────▼───────────────────────────────┐ +│ Services │ +│ - CoreService (BitkitCore bridge) │ +│ - LightningService (LDK Node) │ +│ - TransferService, CurrencyService │ +└─────────────────┬───────────────────────────────┘ + │ +┌─────────────────▼───────────────────────────────┐ +│ External Dependencies │ +│ - BitkitCore (Rust): Bitcoin operations │ +│ - LDKNode: Lightning Network operations │ +│ - Electrum/Esplora: Blockchain data │ +└─────────────────────────────────────────────────┘ +``` + +### Key Components + +**App Entry Point:** +- `BitkitApp.swift`: Main app entry, handles AppDelegate setup, push notifications, quick actions +- `AppScene.swift`: Root scene coordinator, manages app-wide ViewModels and lifecycle +- `ContentView.swift`: Root content view + +**Services Layer:** +- `CoreService`: Bridge to BitkitCore (Rust), handles Bitcoin operations and activity storage +- `LightningService`: Manages LDK Node lifecycle, Lightning operations, channel management +- `TransferService`: Orchestrates Bitcoin/Lightning transfers (send/receive) +- `TransferStorage`: Persists pending transfer state +- `CurrencyService`: Currency conversion and exchange rates +- `ElectrumConfigService`, `RgsConfigService`: Backend configuration +- `ServiceQueue`: Queue system for background operations (`.core`, `.ldk` queues) + +**Managers:** +- `SessionManager`: User session state +- `PushNotificationManager`: Push notification handling for incoming payments +- `ScannerManager`: QR code scanning for payments +- `ToastWindowManager`: App-wide toast notifications +- `TransferTrackingManager`: Tracks pending transfers (new feature) +- `TimedSheets/`: Timed sheet management (backup reminders, high balance warnings) +- `SuggestionsManager`, `TagManager`, `LanguageManager`, `NetworkMonitor` + +**ViewModels (Legacy):** +While the project is transitioning away from traditional ViewModels, these still exist but should follow `@Observable` patterns: +- `AppViewModel`: App-wide state (toasts, errors) +- `WalletViewModel`: Wallet state, balance, node lifecycle +- `ActivityListViewModel`: Transaction/payment history +- `TransferViewModel`: Transfer flows (send/receive) +- `NavigationViewModel`, `SheetViewModel`: UI navigation state +- `BlocktankViewModel`: Lightning channel ordering via Blocktank + +**Key Directories:** +- `Components/`: Reusable UI components (buttons, sliders, widgets) +- `Views/`: Feature-specific views (Onboarding, Backup, Security, Wallets, Settings, Transfer) +- `Extensions/`: Swift extensions for utilities and mock data +- `Utilities/`: Helper utilities (Logger, Keychain, Crypto, Haptics, StateLocker) +- `Models/`: Data models (Toast, ElectrumServer, NodeLifecycleState, etc.) +- `Styles/`: Fonts and sheet styles + +### Service Queue Pattern + +Operations that interact with `CoreService` or `LightningService` must use `ServiceQueue`: + +```swift +// For BitkitCore operations +try await ServiceQueue.background(.core) { + // Core operations here +} + +// For LDK Node operations +try await ServiceQueue.background(.ldk) { + // Lightning operations here +} +``` + +### State Management Patterns + +**Node Lifecycle:** +The Lightning node has distinct lifecycle states tracked via `NodeLifecycleState`: +- `.notStarted` → `.initializing` → `.running` → `.stopped` +- Error states: `.errorStarting(String)` + +**Transfer Tracking:** +New feature (`TransferTrackingManager`) tracks pending transfers to handle edge cases where transfers are initiated but not completed. + +## Important Development Notes + +### Security & Bitcoin/Lightning + +- Use proper Bitcoin/Lightning terminology in code and naming +- All Bitcoin/Lightning operations belong in the service layer, never in views +- The app uses `StateLocker` to prevent concurrent Lightning operations (`.lightning` lock) +- Keychain is used for sensitive data (mnemonics, passphrases) + +### Network Configuration + +- The app currently runs on **regtest only** (see `LightningService.swift:92` guard) +- VSS (Versioned Storage Service) authentication is not yet implemented +- Electrum/Esplora server URLs are configurable via `Env` +- E2E builds use local Electrum backend via `E2E_BUILD` compilation flag + +### Error Handling + +- Use `do-catch` blocks for async operations +- Provide user feedback via toasts: `app.toast(type: .error, title: "...", description: "...")` +- Handle loading, error, and empty states comprehensively +- Consider using `enum LoadingState { case idle, loading, loaded(T), error(Error) }` + +### iOS Version Compatibility + +- Xcode previews only work with iOS 17 and below (due to Rust dependencies) +- Use availability checks for iOS 18/26 features: + ```swift + if #available(iOS 18.0, *) { + // Use iOS 18+ features + } else { + // Fallback + } + ``` + +### Performance + +- Avoid expensive operations in view body +- Move heavy computations to `@Observable` objects +- Use proper state granularity to minimize view updates +- Use `@ViewBuilder` for repetitive view code + +### Accessibility + +Ensure accessibility modifiers and labels are added to custom components. + +## Code Style & Conventions + +- **SwiftFormat** configuration in `.swiftformat` +- Max line width: 150 characters +- Swift version: 5.10 +- Use descriptive names: `isLoadingUsers` not `loading` +- Follow Apple's SwiftUI best practices + +## Common Workflows + +### Adding a New Feature + +1. Identify if business logic should live in an `@Observable` object or existing ViewModel +2. Create UI components in `Components/` or feature-specific views in `Views/` +3. Wire up via `.environment()` injection in `AppScene.swift` +4. Use `.task` for async initialization +5. Add error handling and user feedback (toasts) + +### Working with Lightning + +1. All Lightning operations go through `LightningService.shared` +2. Lock the Lightning state with `StateLocker.lock(.lightning)` for critical operations +3. Listen to LDK events via `wallet.addOnEvent(id:)` pattern +4. Sync activity list after Lightning events + +### Working with Bitcoin + +1. Use `CoreService` for Bitcoin operations +2. Activity tracking handles both on-chain and Lightning payments +3. RBF (Replace-By-Fee) is tracked via `ActivityService.replacementTransactions` + +### Localization Changes + +1. Update translation keys in code +2. Run `node scripts/validate-translations.js` to check for issues +3. Sync with Transifex using `bitkit-transifex-sync` tool diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 00000000..47dc3e3d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file