From dc9b8dd70b56e730329d7e57694512f0db559786 Mon Sep 17 00:00:00 2001 From: phroi <90913182+phroi@users.noreply.github.com> Date: Tue, 17 Feb 2026 02:38:07 +0000 Subject: [PATCH 1/3] feat: add pnpm reference command to clone contracts and whitepaper repos Enables Claude to read the on-chain Rust contracts and protocol whitepaper on demand for better context about the iCKB protocol. Co-Authored-By: Claude Opus 4.6 --- .gitignore | 4 ++++ README.md | 13 +++++++++++++ package.json | 7 +++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4a7cfe9..022d076 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,7 @@ # Artifacts **/dist/ + +# Reference repos +contracts/ +whitepaper/ diff --git a/README.md b/README.md index e25a496..b0ea18b 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,19 @@ To redo the setup from scratch: `rm -rf ccc-dev/ccc && pnpm install`. See [ccc-dev/README.md](ccc-dev/README.md) for recording new pins, developing CCC PRs, and the full workflow. +## Reference + +Clone the on-chain contracts and whitepaper repos locally for AI context: + +```bash +pnpm reference +``` + +This clones two repos into the project root (both are git-ignored and made read-only): + +- **[contracts](https://github.com/ickb/contracts)** — Rust L1 scripts deployed on Nervos CKB +- **[whitepaper](https://github.com/ickb/whitepaper)** — iCKB protocol design and specification + ## Developer Scripts | Command | Description | diff --git a/package.json b/package.json index 36f9f98..c5df51e 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,10 @@ "docs": "typedoc", "pr": "bash scripts/pr.sh", "review": "bash scripts/review.sh", - "claude": "claude --dangerously-skip-permissions" + "claude": "claude --dangerously-skip-permissions", + "reference": "pnpm reference:contracts; pnpm reference:whitepaper", + "reference:contracts": "[ -d contracts ] || (git clone https://github.com/ickb/contracts.git && chmod -R a-w contracts)", + "reference:whitepaper": "[ -d whitepaper ] || (git clone https://github.com/ickb/whitepaper.git && chmod -R a-w whitepaper)" }, "engines": { "node": ">=24" @@ -43,4 +46,4 @@ "vitest": "^3.2.4" }, "packageManager": "pnpm@10.29.3+sha512.498e1fb4cca5aa06c1dcf2611e6fafc50972ffe7189998c409e90de74566444298ffe43e6cd2acdc775ba1aa7cc5e092a8b7054c811ba8c5770f84693d33d2dc" -} +} \ No newline at end of file From 7856961b2d66c2f0f655aa177efdb8414ea40066 Mon Sep 17 00:00:00 2001 From: phroi <90913182+phroi@users.noreply.github.com> Date: Tue, 17 Feb 2026 02:38:15 +0000 Subject: [PATCH 2/3] docs: enrich planning docs with contract and whitepaper context Add protocol design, on-chain contract architecture, validation rules, error codes, Molecule schemas, and TS-Rust alignment concerns derived from the contracts and whitepaper reference repos. Co-Authored-By: Claude Opus 4.6 --- .planning/codebase/ARCHITECTURE.md | 438 +++++++++++++++++++------- .planning/codebase/CONCERNS.md | 54 +++- .planning/codebase/CONVENTIONS.md | 15 +- .planning/codebase/INTEGRATIONS.md | 78 ++++- .planning/codebase/STACK.md | 9 +- .planning/codebase/STRUCTURE.md | 486 ++++++++++++++++++----------- .planning/codebase/TESTING.md | 28 +- 7 files changed, 777 insertions(+), 331 deletions(-) diff --git a/.planning/codebase/ARCHITECTURE.md b/.planning/codebase/ARCHITECTURE.md index bfda91d..aa02cce 100644 --- a/.planning/codebase/ARCHITECTURE.md +++ b/.planning/codebase/ARCHITECTURE.md @@ -1,171 +1,385 @@ # Architecture -**Analysis Date:** 2026-02-14 +**Analysis Date:** 2026-02-17 ## Pattern Overview -**Overall:** Layered monorepo architecture with blockchain-first design +**Overall:** Layered monorepo with blockchain-centric manager composition pattern **Key Characteristics:** -- Monorepo structure with `packages/` (NEW CCC-based libraries) and `apps/` (applications) -- CCC (`@ckb-ccc/core`) as foundation for CKB blockchain interactions (replacing deprecated Lumos) -- Manager-based pattern for handling domain entities (DAO, Orders, Logic, Capacity) -- Local CCC dev build override via `ccc-dev/record.sh` + `ccc-dev/replay.sh` + `.pnpmfile.cjs` (NOT a git submodule) -- Transaction-centric abstraction with SmartTransaction extending ccc.Transaction +- Modular library packages (`packages/`) composed into high-level SDK +- Manager-based pattern encapsulating script operations with uniform `ScriptDeps` interface +- Async-first cell discovery via generator functions with lazy evaluation +- TypeScript ESM modules with strict null checks and type safety +- SmartTransaction builder for automatic fee/change calculation +- Cell wrapper abstractions extending raw blockchain data with domain logic **Migration Status:** - `packages/` contain the NEW replacement libraries built on CCC - `@ickb/lumos-utils@1.4.2` and `@ickb/v1-core@1.4.2` are LEGACY & DEPRECATED (this monorepo builds their replacements) - All `@ckb-lumos/*` packages are DEPRECATED (CCC is the replacement) - Apps split: `faucet` and `sampler` already use new packages; `bot`, `tester`, `interface` still on legacy Lumos -- CCC PRs for UDT and Epoch support have been MERGED upstream -- some local code may now overlap with CCC features +- CCC PRs for UDT and Epoch support have been MERGED upstream -- local Epoch class has been deleted (replaced by `ccc.Epoch`); some local UDT handling may still overlap with CCC's `@ckb-ccc/udt` +- Custom `mol.union` codec and deprecated `mol.*` APIs have been replaced with CCC's `mol.union`, `ccc.Entity.Base`, and `@ccc.codec` decorator - SmartTransaction was ABANDONED as an ecosystem-wide concept (no adoption), but the class itself remains used locally; headers are now cached in CCC Client Cache -## Layers +## Protocol Design (from whitepaper) -**Core Blockchain Foundation (CCC):** -- Purpose: Abstract CKB protocol operations and provide type-safe wrappers -- Source: `@ckb-ccc/core` (npm) or local clone at `ccc-dev/ccc/` (via `ccc-dev/record.sh`) -- Contains: CKB RPC clients, transaction builders, signer implementations, Molecule codec, UDT support, Epoch handling -- Depends on: CKB network services -- Used by: All new packages and migrated apps -- Note: CCC now includes UDT and Epoch features contributed by this project's maintainer +The iCKB protocol solves NervosDAO illiquidity by pooling DAO deposits and issuing a liquid iCKB token. Key design principles: -**Utility Layer:** -- Purpose: Provide reusable blockchain primitives and transaction helpers -- Location: `packages/utils/` -- Contains: SmartTransaction, CapacityManager, epoch handling, codec helpers, UDT handlers -- Depends on: @ckb-ccc/core -- Used by: All domain packages and applications - -**Domain Packages:** -- Purpose: Implement specific protocol/business logic -- Location: `packages/{core,dao,order,sdk}` -- Core (`packages/core/`): iCKB core logic, deposit/receipt management via LogicManager -- DAO (`packages/dao/`): Nervos DAO interactions via DaoManager -- Order (`packages/order/`): Limit order cell management via OrderManager -- SDK (`packages/sdk/`): High-level IckbSdk composing all domain managers - -**Application Layer:** -- Purpose: Run specific operational tasks -- Location: `apps/{bot,faucet,sampler,tester,interface}` -- Bot: Continuously matches and fulfills limit orders (**LEGACY** -- still on Lumos + @ickb/v1-core) -- Faucet: Distributes testnet CKB from deposit cells (**MIGRATED** -- uses new @ickb/utils + CCC) -- Sampler: Samples blockchain state and outputs exchange rate CSV (**MIGRATED** -- uses new @ickb/core + CCC) -- Tester: Simulates limit order creation scenarios (**LEGACY** -- still on Lumos + @ickb/v1-core) -- Interface: React web UI for user interactions (**LEGACY** -- still on Lumos + @ickb/v1-core) +**Core Concept:** CKB deposited into NervosDAO is locked for ~30 days (180 epochs). iCKB tokenizes these deposits so users can trade the locked value immediately while still accruing DAO interest. -## Data Flow +**Exchange Rate:** `iCKB_value = unoccupied_capacity * AR_0 / AR_m` where `AR_0 = 10^16` (genesis accumulated rate) and `AR_m` is the accumulated rate at the deposit block. CKB is inflationary; iCKB is not -- 1 iCKB represents an ever-increasing amount of CKB over time. + +**Deposit (2-Phase):** +1. Phase 1: User deposits CKB into NervosDAO -> receives a Receipt cell (cannot calculate iCKB value yet because the block's accumulated rate isn't available during validation). +2. Phase 2: Receipt cell is converted to iCKB xUDT tokens using the now-available accumulated rate from the deposit block header. + +**Withdrawal (2-Phase):** +1. Phase 1: User burns iCKB tokens -> creates a NervosDAO withdrawal request (using any mature deposit from the pool, not necessarily the user's original deposit). +2. Phase 2: Standard NervosDAO withdrawal after 180-epoch maturity. + +**Soft Cap Penalty:** Deposits exceeding 100,000 iCKB-equivalent incur a 10% discount on the excess amount. This incentivizes standard-size deposits (~100k CKB) and prevents DoS via fragmentation. Formula: `final = amount - (amount - 100000) / 10` when `amount > 100000`. + +**Pooled Deposits:** Unlike dCKB (predecessor), deposits are protocol-owned, not user-specific. Any mature deposit can satisfy any withdrawal request. This eliminates the "original depositor only" restriction. + +**Non-Upgradable:** All scripts are deployed with zero-args locks (unlockable), making the protocol immutable and trustless. No governance, no oracles, no admin keys. + +## On-Chain Contracts (Rust) + +Three production smart contracts (in `contracts/` reference repo) implement the protocol on CKB L1. Each TS package in `packages/` corresponds to contract logic: + +| Contract | Script Type | TS Package | Purpose | +|---|---|---|---| +| `ickb_logic` | Type script | `@ickb/core` (LogicManager) | Controls iCKB minting/burning, validates deposits and receipts, enforces conservation law | +| `limit_order` | Lock script | `@ickb/order` (OrderManager) | Enables peer-to-peer limit order matching for CKB/UDT trading | +| `owned_owner` | Lock script | `@ickb/core` (OwnedOwnerManager) | Manages owner-owned cell pairing for DAO withdrawal delegation | +| (shared `utils`) | Library | `@ickb/utils`, `@ickb/dao` | DAO helpers, safe math (C256), MetaPoint, cell type classification | + +**Key Contract Invariant (ickb_logic):** +``` +Input UDT + Input Receipts = Output UDT + Input Deposits +``` +Receipts convert to UDT; deposits stay as deposits or convert to UDT. No iCKB can be created or destroyed outside this conservation law. -**Order Fulfillment Flow (Bot):** +**Limit Order Lifecycle:** Mint (create order + master cell) -> Match (partial/full fill preserving value) -> Melt (destroy fulfilled order). Value conservation: `in_ckb * ckb_mul + in_udt * udt_mul <= out_ckb * ckb_mul + out_udt * udt_mul`. -1. Bot queries L1 state via IckbSdk.getL1State() -2. Retrieves all order cells, available/maturing CKB, exchange ratio -3. Filters matchable orders at midpoint ratio -4. Builds transaction using OrderManager.satisfy() for matched orders -5. Adds order inputs/outputs and witnesses -6. Completes transaction fee via SmartTransaction.completeFee() -7. Signs and broadcasts transaction +**Owned Owner Pairing:** 1:1 relationship between "owned" cells (DAO withdrawal requests) and "owner" cells (authorization). Connected via relative `owned_distance: i32` offset. Solves NervosDAO's constraint that deposit lock and withdrawal lock must have equal size. -**User Conversion Flow (Interface):** +## Layers + +**Foundation: CCC Framework** +- Purpose: Provide blockchain primitives and client interface +- Location: `@ckb-ccc/core` (npm or local `ccc-dev/ccc/`) +- Contains: CKB RPC clients, transaction builders, signers, Molecule codec, UDT support, Epoch handling +- Used by: All packages and applications +- Note: CCC now includes UDT and Epoch features contributed by this project's maintainer + +**Utilities Layer (`packages/utils/src/`)** +- Purpose: Reusable blockchain primitives and transaction helpers +- Key exports: `SmartTransaction`, `CapacityManager`, codec/heap/epoch utilities, UDT handlers +- Key files: + - `transaction.ts` (517 lines): SmartTransaction builder with fee completion and UDT balancing + - `capacity.ts` (221 lines): CapacityManager for cell discovery and collection + - `udt.ts` (393 lines): UDT token value calculations and handlers + - `utils.ts` (458 lines): General utilities (binary search, collectors, script helpers) +- Depends on: `@ckb-ccc/core` +- Used by: All domain packages + +**Domain Layer - DAO (`packages/dao/src/`)** +- Purpose: Abstract Nervos DAO operations (deposit, withdraw, requestWithdrawal) +- Key abstractions: + - `DaoManager`: Implements ScriptDeps, manages deposit/withdrawal transactions + - `DaoCell`: Wraps blockchain cell with maturity and interest calculations + - Methods: `isDeposit()`, `isWithdrawalRequest()`, async generators `findDeposits()` and `findWithdrawalRequests()` +- Key files: + - `dao.ts` (412 lines): DaoManager implementation + - `cells.ts` (180 lines): DaoCell construction and type checking +- Depends on: Utilities layer +- Used by: Core and applications + +**Domain Layer - Order (`packages/order/src/`)** +- Purpose: Limit order cell management and matching logic +- Key abstractions: + - `OrderManager`: Implements ScriptDeps, mint/satisfy/melt operations + - `OrderCell`, `MasterCell`, `OrderGroup`: Order representation and grouping + - `Info`, `Ratio`: Order metadata and exchange ratio types + - Conversion logic with fee calculations (default 0.001% fee) +- Key files: + - `order.ts` (988 lines): OrderManager with convert/mint/satisfy/melt/find methods + - `entities.ts` (754 lines): Info/Ratio/OrderData types and comparisons + - `cells.ts` (396 lines): Cell wrappers for orders, groups, masters +- Depends on: Utilities layer +- Used by: Core and SDK + +**Domain Layer - Core iCKB Logic (`packages/core/src/`)** +- Purpose: iCKB protocol-specific operations (deposits, receipts, ownership) +- Key abstractions: + - `LogicManager`: Deposit/receipt management (implements ScriptDeps) + - `OwnedOwnerManager`: Ownership and withdrawal group management (implements ScriptDeps) + - `IckbDepositCell`: DAO cell marked as iCKB deposit + - `ReceiptCell`, `WithdrawalGroup`, `OwnerCell`: Domain-specific cell types +- Key files: + - `logic.ts` (269 lines): LogicManager for deposits and receipts + - `owned_owner.ts` (239 lines): OwnedOwnerManager for withdrawal operations + - `cells.ts` (175 lines): Cell wrappers and type constructors + - `udt.ts` (213 lines): iCKB UDT calculations +- Depends on: DAO + Utilities layers +- Used by: SDK + +**SDK Composition Layer (`packages/sdk/src/`)** +- Purpose: High-level interface composing all domain managers +- Key abstractions: + - `IckbSdk`: Factory and orchestrator class + - `SystemState`: Immutable snapshot of blockchain state (fee rate, tip, exchange ratio, orders, available/maturing CKB) + - `CkbCumulative`: Maturing CKB entries with cumulative amounts +- Key methods: + - Static `estimate()`: Conversion preview with optional fee + - Static `maturity()`: Estimated order fulfillment timestamp + - Instance `request()`: Create order cell + - Instance `collect()`: Cancel order groups + - Instance `getL1State()`: Fetch complete system state + - Instance `getCkb()` (private): Maturing CKB calculation from deposits and bot withdrawals +- Key files: + - `sdk.ts` (512 lines): IckbSdk implementation + - `constants.ts` (205 lines): Script configurations + - `codec.ts` (138 lines): Pool snapshot encoding/decoding +- Depends on: All domain + utils layers +- Used by: Applications + +**Application Layer (`apps/*/src/`)** +- Purpose: Domain-specific operational services + + **Faucet (Migrated to CCC + New Packages):** + - Location: `apps/faucet/src/main.ts` (86 lines) + - Entry: `main()` async function + - Pattern: Infinite loop with 2-minute poll interval + - Uses: CCC client, CapacityManager, SmartTransaction + - Flow: Discover faucet funds → transfer to user account → log JSON results + + **Sampler (Migrated to CCC):** + - Location: `apps/sampler/src/index.ts` (192 lines) + - Entry: Direct execution + - Pattern: Periodic blockchain observation + - Uses: CCC primitives + + **Bot (Legacy - Lumos):** + - Location: `apps/bot/src/index.ts` (897 lines) + - Entry: `main()` async function + - Pattern: Infinite loop with configurable sleep interval + - Uses: `@ickb/v1-core`, `@ckb-lumos/*`, TransactionSkeleton + - Flow: Query orders → match at midpoint → build transaction → sign/broadcast + - Note: Status quo legacy implementation; NOT yet migrated + + **Interface (Legacy - Lumos + React):** + - Location: `apps/interface/src/` (total 1,158 lines) + - Entry: `startApp(wallet_chain)` in `main.tsx` (68 lines) + - Pattern: React component hierarchy with React Query state management + - Uses: `@ickb/v1-core`, `@ckb-lumos/*`, React, TanStack Query + - Component tree: + - `Connector.tsx` (104 lines): Wallet connection setup + - `App.tsx` (93 lines): Main state/conversion logic + - `Form.tsx` (144 lines): Input form + - `Action.tsx` (174 lines): Transaction execution + - `Dashboard.tsx` (36 lines): Balance display + - `Progress.tsx` (42 lines): Loading indicator + - Queries/Utils: `queries.ts` (395 lines), `transaction.ts` (291 lines), `utils.ts` (160 lines) + - Note: Status quo legacy implementation; NOT yet migrated + + **Tester (Legacy - Lumos):** + - Location: `apps/tester/src/index.ts` (469 lines) + - Entry: `main()` async function + - Pattern: Simulation of order creation scenarios + - Uses: `@ickb/v1-core`, `@ckb-lumos/*` + +## Data Flow -1. User selects conversion direction (CKB↔UDT) and amount -2. Interface fetches L1State (cached via react-query) -3. Estimates conversion using IckbSdk.estimate() with fee rate -4. Displays maturity estimate via IckbSdk.maturity() -5. If user requests, builds transaction via transaction builders -6. SmartTransaction completes fee and adds UDT/capacity changes -7. Signer signs transaction (JoyId connector) -8. Transaction submitted to CKB network +**Order Creation and Matching (Primary Flow):** + +1. User calls `IckbSdk.request(tx, user, info, amounts)` via app +2. `OrderManager.mint()` creates order cell with `Info` metadata (ratio, direction, fee info) +3. `SmartTransaction` adds cell deps, outputs, UDT handlers +4. User signs and broadcasts transaction + +**Order Discovery and Matching (Bot Flow):** + +1. Bot calls `IckbSdk.getL1State(client, locks)` +2. Parallel fetch: tip header, fee rate, order cells, bot capacities +3. Calculate exchange ratio from tip: `Ratio.from(ickbExchangeRatio(tip))` +4. Fetch deposits and withdrawal requests to calculate maturing CKB +5. Filter orders: separate user orders from system-matchable orders (ratio within 0.1% of midpoint) +6. Estimate maturity for each user order based on pool liquidity +7. Returns `SystemState { feeRate, tip, exchangeRatio, orderPool, ckbAvailable, ckbMaturing }` +8. Bot identifies orders where CKB/UDT supply exists for matching +9. Calls `OrderManager.satisfy()` to process matched orders +10. Builds transaction with satisfied order cells and input/output witnesses +11. Completes fees via `SmartTransaction.completeFeeChangeToLock()` +12. Signs and broadcasts + +**Maturity Estimation (Supporting Calculation):** + +1. `IckbSdk.maturity(order, system)` computes estimated fulfillment timestamp +2. For dual-ratio orders: returns undefined (no fixed maturity) +3. For single-direction orders: + - Scans order pool to calculate available opposite liquidity + - Applies exchange ratio conversion to matching depth + - If sufficient liquidity exists: maturity = 10 minutes + (amount / capacity scaling factor) + - If insufficient: finds earliest bin in `ckbMaturing` cumulative array that covers shortfall +4. Returns Unix timestamp (milliseconds) or undefined + +**Conversion Preview (UI Flow):** + +1. User calls `IckbSdk.estimate(isCkb2Udt, amounts, system, options?)` +2. Applies 0.001% default fee (or custom fee/feeBase) +3. Calls `OrderManager.convert()` with adjusted ratio +4. Returns `{ convertedAmount, ckbFee, info, maturity? }` +5. UI displays converted amount and estimated maturity if applicable **Deposit Lifecycle:** -1. User calls LogicManager.deposit() to lock CKB in Nervos DAO +1. User calls `LogicManager.deposit()` to lock CKB in Nervos DAO 2. Receipt cell minted containing deposit metadata -3. Bot fetches deposits via LogicManager.findDeposits() -4. After maturity, bot calls LogicManager.withdraw() to extract funds +3. Bot fetches deposits via `LogicManager.findDeposits()` +4. After maturity, bot calls `LogicManager.withdraw()` to extract funds 5. Change cells automatically added by SmartTransaction **State Management:** - L1 state: Immutable snapshots fetched per query with configurable refresh intervals -- Transaction state: Built incrementally via SmartTransaction.add* methods -- UDT balances: Tracked per UDT handler in SmartTransaction.udtHandlers map +- Transaction state: Built incrementally via `SmartTransaction.add*` methods +- UDT balances: Tracked per UDT handler in `SmartTransaction.udtHandlers` map - Maturing CKB: Cumulative array sorted by maturity timestamp ## Key Abstractions -**IckbSdk:** -- Purpose: Unified interface for all iCKB operations -- Examples: `packages/sdk/src/sdk.ts` -- Pattern: Factory pattern (static `from()` method) + composition of managers -- Exposes: estimate(), maturity(), request(), collect(), getL1State() - -**Manager Classes:** -- Purpose: Encapsulate entity-specific logic and cell finding -- Examples: LogicManager, OrderManager, DaoManager, CapacityManager -- Pattern: Implements ScriptDeps interface where applicable -- Provide: Cell discovery, transaction mutations, entity serialization - -**SmartTransaction:** -- Purpose: Extend CCC Transaction with automatic UDT/capacity balancing -- Location: `packages/utils/src/transaction.ts` -- Pattern: Inheritance from ccc.Transaction with additional state maps -- Manages: UDT handlers, block headers, fee completion +**ScriptDeps Interface (Contracts):** +- Implemented by: DaoManager, OrderManager, LogicManager, OwnedOwnerManager +- Contract: `{ script: ccc.Script; cellDeps: ccc.CellDep[] }` +- Purpose: Uniform interface for adding script dependencies to transactions +- Pattern: Enables composability and type-safe manager stacking + +**Manager Classes (Pattern):** +- Purpose: Encapsulate entity-specific operations +- Pattern: Stateless managers with methods that operate on SmartTransaction +- Examples: + - `DaoManager.deposit(tx, capacities, lock)`: Add DAO deposit cells + - `OrderManager.mint(tx, user, info, amounts)`: Create order cell + - `LogicManager.deposit(tx, user, info, amounts)`: Create iCKB deposit with receipt +- Type checkers: `isDeposit()`, `isOrder()`, `isMaster()` methods for cell filtering + +**Cell Wrappers (Abstraction):** +- Purpose: Extend raw blockchain cells with domain calculations +- Pattern: Factory functions return wrapped interfaces with computed properties +- Examples: + - `DaoCell`: Adds maturity, interests, isReady properties + - `IckbDepositCell`: Extends DaoCell with [isIckbDepositSymbol] marker + - `ReceiptCell`: Wraps receipt data with header reference + - `WithdrawalGroup`: Pairs owned (withdrawal request) + owner cell with value aggregation +- Construction: Async factories via `daoCellFrom()`, `ickbDepositCellFrom()`, `receiptCellFrom()` + +**SmartTransaction (Builder):** +- Purpose: Extends ccc.Transaction with UDT-aware balancing +- Pattern: Incremental builder with state accumulation +- Key state: `inputs`, `outputs`, `outputsData`, `cellDeps`, `headerDeps`, `witnesses`, `udtHandlers` map +- Automatic operations: + - `completeFeeChangeToLock()`: Calculate and add change cells for CKB + - `addUdtChange()`: Add change cells for each tracked UDT + - `addCellDeps()`: Deduplicate and append cell dependencies +- Used by: All managers to build transactions atomically - Note: The "SmartTransaction" ecosystem concept was ABANDONED (no CKB ecosystem adoption). However, this class is still actively used throughout all new packages. The name is a vestige. Header caching has moved to CCC's Client Cache. -**Cell Finding Pattern:** -- Purpose: Lazy async iteration over blockchain cells matching criteria -- Pattern: Async generator functions (e.g., findCapacities, findOrders) -- Supports: Filtering, pagination, onChain snapshots -- Usage: Collected via `collect()` helper into arrays +**Value Types (Domain Models):** +- `ValueComponents`: `{ ckbValue: ccc.FixedPoint; udtValue: ccc.FixedPoint }` +- `Info`: Order metadata with ratio bounds, direction, fee tier +- `Ratio`: Exchange rate as scaled numerator/denominator +- `OrderCell`: Extends ValueComponents with order-specific properties +- `OrderGroup`: Wrapper for order cells grouped by master cell +- `SystemState`: Immutable snapshot with fee rate, exchange ratio, order pool, available/maturing CKB + +**Async Generator Pattern (Cell Finding):** +- Signature: `async *find*(client, locks, options?) : AsyncGenerator` +- Examples: `DaoManager.findDeposits()`, `OrderManager.findOrders()` +- Usage: Lazy evaluation with batching via `defaultFindCellsLimit` (400 cells) +- Filtering: Applied after fetch via type checkers and lock script matching +- Collection: Wrapped via `collect()` helper to realize as array ## Entry Points -**IckbSdk Factory:** -- Location: `packages/sdk/src/sdk.ts` - `IckbSdk.from()` -- Triggers: Called by all applications to initialize SDK -- Responsibilities: Instantiates managers, loads script configs, prepares bot scripts +**CLI Entry Points:** -**Bot Main Loop:** -- Location: `apps/bot/src/index.ts` - `main()` -- Triggers: Scheduled execution (configurable interval from env) -- Responsibilities: Query state, match orders, build/sign/broadcast transactions +**Faucet:** +- Location: `apps/faucet/src/main.ts` - `main()` function +- Invocation: Run via `index.ts` or direct execution +- Environment: ADDRESS env variable (recipient CKB address) +- Behavior: Polls every 2 minutes for accumulated CKB, transfers to recipient account -**Interface Startup:** -- Location: `apps/interface/src/main.tsx` - `startApp()` -- Triggers: Browser navigation to specific chain -- Responsibilities: Initialize chain config, setup query client, render React app +**Sampler:** +- Location: `apps/sampler/src/index.ts` +- Invocation: Direct execution +- Behavior: Periodic blockchain observation and data sampling -**Faucet Main Loop:** -- Location: `apps/faucet/src/index.ts` - `main0()` -- Triggers: Continuous loop with 2-minute intervals -- Responsibilities: Transfer accumulated CKB from temporary account to real account +**Bot:** +- Location: `apps/bot/src/index.ts` - `main()` function +- Invocation: CLI execution +- Environment: CHAIN, RPC_URL, BOT_PRIVATE_KEY, BOT_SLEEP_INTERVAL env variables +- Behavior: Infinite loop matching orders at configurable interval + +**Web Application Entry:** + +**Interface:** +- Location: `apps/interface/src/main.tsx` - `startApp(wallet_chain: string)` function +- Invocation: Called with parameter `"_"` (e.g., `"JoyId_mainnet"`) +- Behavior: Initializes chain config, creates query client, renders React app +- Sets up: CCC client (ClientPublicTestnet or ClientPublicMainnet), JoyId wallet signers, React Query cache + +**SDK Entry:** +- Location: `packages/sdk/src/sdk.ts` - `IckbSdk.from(...args)` static factory +- Invocation: Called by applications during setup +- Behavior: Instantiates all managers from script config, returns fully-composed SDK ## Error Handling -**Strategy:** Try-catch with execution logging and graceful degradation +**Strategy:** Contract validation with descriptive errors; graceful degradation in apps **Patterns:** -- Bot/Faucet/Sampler: Log errors to stdout JSON format for monitoring -- Interface: React error boundaries + query retry logic with exponential backoff -- Validation: Throw errors with descriptive messages (e.g., "iCKB deposit minimum is 1082 CKB") -- Network errors: Query-level retry mechanism in react-query with refetchInterval +- **Validation**: Throw errors for invalid state (e.g., "Not a deposit", "Transaction have different inputs and outputs lengths") +- **Cell not found**: Throw in constructors (`receiptCellFrom()`), return empty generators in finders +- **Configuration**: Throw on missing or invalid environment variables with helpful messages +- **Transaction constraints**: Check limits (e.g., max 64 output cells in DAO transactions) +- **App-level**: Try-catch with JSON error logging including stack traces for monitoring + +**Examples:** +- Bot/Faucet: Log execution JSON with error field containing full stack trace +- Interface: React Query retry logic with exponential backoff +- Managers: Pre-condition checks before transaction mutations (throw early) ## Cross-Cutting Concerns **Logging:** -- Bot/Faucet: JSON structured logs with timestamps and operation results -- Interface: Console.log for debugging, suppressed in production +- Apps: Structured JSON logs with timestamps, success/error status, operation results +- Pattern: Log at operation boundaries (start, end) for monitoring +- Format: `{ startTime, balance?, txHash?, error?, elapsedSeconds }` **Validation:** -- Constructor validation (e.g., minimum amounts, non-empty env vars) -- Pre-transaction checks (deposit minimums, fee calculations) +- Script matching: `script.eq()` calls for type/lock verification +- Cell type checking: Manager predicates (isDeposit, isOrder, isMaster) +- Amount validation: Zero/minimum checks before operations **Authentication:** -- Bot/Faucet/Sampler: Environment variable secrets (BOT_PRIVATE_KEY, ADDRESS) -- Interface: JoyId wallet connector for transaction signing +- Apps: Private key from environment variables (BOT_PRIVATE_KEY) +- Interface: JoyId wallet connector for signing +- Pattern: CCC signers abstract wallet implementation + +**Capacity & Fee Management:** +- `CapacityManager`: Discovers and collects cells for capacity +- `SmartTransaction`: Auto-calculates fees from transaction size +- Pattern: Add-then-complete flow (add inputs/outputs, then complete fee) + +**UDT Handling:** +- `UdtHandler`: Encapsulates token script + type script pair +- Pattern: Managers create handlers; SmartTransaction tracks per-UDT changes +- Automatic change: `SmartTransaction.addUdtChange()` for balancing --- -*Architecture analysis: 2026-02-14* +*Architecture analysis: 2026-02-17* diff --git a/.planning/codebase/CONCERNS.md b/.planning/codebase/CONCERNS.md index 39bb567..f7e17f1 100644 --- a/.planning/codebase/CONCERNS.md +++ b/.planning/codebase/CONCERNS.md @@ -1,6 +1,6 @@ # Codebase Concerns -**Analysis Date:** 2026-02-14 +**Analysis Date:** 2026-02-17 ## Tech Debt @@ -31,23 +31,19 @@ - Impact: Lumos is deprecated upstream and will eventually stop receiving updates. Security patches and CKB protocol changes will only be reflected in CCC. - Fix approach: This is resolved by the app migration above. The new `packages/` libraries already use CCC exclusively via `@ckb-ccc/core`. -### Local Epoch Class Partially Duplicates CCC Upstream (Medium) +### ~~Local Epoch Class Partially Duplicates CCC Upstream~~ (RESOLVED) -- Issue: `packages/utils/src/epoch.ts` defines a custom `Epoch` class (258 lines) that duplicates functionality now available in CCC's `ccc.Epoch`. CCC's `Epoch` class (in `ccc-dev/ccc/packages/core/src/ckb/epoch.ts`, 490 lines) provides `from()`, `add()`, `sub()`, `compare()`, `toUnix()`, `normalizeCanonical()`, `toPackedHex()`, and convenience comparison methods (`lt`, `le`, `eq`, `ge`, `gt`). The local `Epoch` class provides nearly identical functionality but uses different property naming (`number/index/length` vs. CCC's `integer/numerator/denominator`). -- Files: - - `packages/utils/src/epoch.ts` - local `Epoch` class - - `ccc-dev/ccc/packages/core/src/ckb/epoch.ts` - CCC upstream `Epoch` class -- Impact: Maintaining a parallel Epoch implementation means bugs fixed upstream are not automatically inherited. The local class already wraps CCC functions (`ccc.epochFromHex` at line 101, `ccc.epochToHex` at line 111) and accepts `ccc.Epoch` instances (via `deStruct()` at line 240), showing partial integration but also added complexity. -- Fix approach: Replace local `Epoch` with `ccc.Epoch` throughout `packages/`. Both classes provide `from()`, `add()`, `sub()`, `compare()`, and `toUnix()`. The main migration friction is the naming difference. CCC provides deprecated array-style accessors `[0]`, `[1]`, `[2]` for backwards compatibility, easing the transition for code that uses tuple-style access. +- **Resolved in:** commit ae8b5af (`refactor: replace ickb Epoch with ccc.Epoch`) +- Local `packages/utils/src/epoch.ts` (244 lines) was deleted. All packages now use `ccc.Epoch` directly. ### Local UDT Handling May Overlap CCC Upstream (Medium) -- Issue: CCC now has a dedicated `@ckb-ccc/udt` package (at `ccc-dev/ccc/packages/udt/`). The local `packages/utils/src/udt.ts` and `packages/core/src/udt.ts` implement custom UDT handling (`UdtHandler` interface, `IckbUdtManager` class). While the local UDT handling is iCKB-specific (custom balance calculation accounting for DAO deposits), the generic UDT operations like `ccc.udtBalanceFrom()` are already being used from CCC upstream in five locations. +- Issue: CCC now has a dedicated `@ckb-ccc/udt` package (at `ccc-dev/ccc/packages/udt/`). The local `packages/utils/src/udt.ts` and `packages/core/src/udt.ts` implement custom UDT handling (`UdtHandler` interface, `IckbUdtManager` class). While the local UDT handling is iCKB-specific (custom balance calculation accounting for DAO deposits), the generic UDT operations like `ccc.udtBalanceFrom()` are still being used from CCC upstream in `packages/utils/src/udt.ts` (4 locations). - Files: - `packages/utils/src/udt.ts` - `UdtHandler` interface, `UdtManager` class (~370 lines) - `packages/core/src/udt.ts` - `IckbUdtManager` extending UDT handling for iCKB-specific logic - `ccc-dev/ccc/packages/udt/src/` - CCC upstream UDT package - - Usage of `ccc.udtBalanceFrom()`: `packages/core/src/udt.ts` line 100, `packages/utils/src/udt.ts` lines 166, 193, 319, 363 + - Usage of `ccc.udtBalanceFrom()`: `packages/utils/src/udt.ts` lines 169, 197, 323, 368 - Impact: There may be duplicated utility code for standard UDT operations (finding cells, calculating balances). The iCKB-specific extensions (e.g., `IckbUdtManager` which modifies balance calculations based on DAO deposit/withdrawal state) are domain-specific and unlikely to be in CCC. - Fix approach: Audit the CCC `@ckb-ccc/udt` package to identify which local utilities can be replaced. Keep iCKB-specific extensions but delegate standard UDT operations (cell finding, basic balance) to CCC where possible. @@ -220,12 +216,36 @@ - Files: All files under `packages/` and `apps/` - Risk: The financial logic in `packages/sdk/src/sdk.ts` (order matching, maturity estimation, CKB/UDT conversion), `packages/order/src/order.ts` (order matching algorithm with complex bigint arithmetic), and `packages/dao/src/cells.ts` (DAO interest calculation, maturity computation) handle real cryptocurrency operations. Bugs in these areas could lead to financial loss. - Priority: High. At minimum, the following should have unit tests: - 1. `packages/utils/src/epoch.ts` - Epoch arithmetic (add, sub, compare, toUnix) - 2. `packages/order/src/entities.ts` - `Ratio.applyFee()`, `Ratio.convert()`, `Info.validate()` - 3. `packages/order/src/order.ts` - `OrderMatcher.match()`, `OrderMatcher.nonDecreasing()`, `OrderManager.bestMatch()` - 4. `packages/sdk/src/codec.ts` - `PoolSnapshot` encode/decode roundtrip - 5. `packages/dao/src/cells.ts` - `daoCellFrom()` maturity/interest calculations - 6. `packages/core/src/logic.ts` - iCKB exchange ratio and conversion logic + 1. `packages/utils/src/utils.ts` - `binarySearch`, `asyncBinarySearch`, `gcd`, `min`, `max`, `sum`, `hexFrom`, `isHex`, `shuffle` + 2. `packages/utils/src/codec.ts` - `CheckedInt32LE` encode/decode + 3. `packages/order/src/entities.ts` - `Ratio.applyFee()`, `Ratio.convert()`, `Info.validate()` + 4. `packages/order/src/order.ts` - `OrderMatcher.match()`, `OrderMatcher.nonDecreasing()`, `OrderManager.bestMatch()` + 5. `packages/sdk/src/codec.ts` - `PoolSnapshot` encode/decode roundtrip + 6. `packages/dao/src/cells.ts` - `daoCellFrom()` maturity/interest calculations + 7. `packages/core/src/logic.ts` - iCKB exchange ratio and conversion logic + +### TS Exchange Rate Must Match Rust Contract Logic + +- What's not tested: The TypeScript exchange rate calculation (`packages/core/src/udt.ts`) must produce identical results to the Rust contract's `deposit_to_ickb()` function (`contracts/scripts/contracts/ickb_logic/src/entry.rs`). Any discrepancy would cause transactions to be rejected on-chain. +- Key formula: `iCKB = capacity * AR_0 / AR_m` with soft cap penalty `amount - (amount - 100000) / 10` when `amount > ICKB_SOFT_CAP_PER_DEPOSIT` +- Contract constants that TS must match: + - `CKB_MINIMUM_UNOCCUPIED_CAPACITY_PER_DEPOSIT = 1,000 * 100_000_000` (1,000 CKB) + - `CKB_MAXIMUM_UNOCCUPIED_CAPACITY_PER_DEPOSIT = 1,000,000 * 100_000_000` (1,000,000 CKB) + - `ICKB_SOFT_CAP_PER_DEPOSIT = 100,000 * 100_000_000` (100,000 iCKB) + - `GENESIS_ACCUMULATED_RATE = 10_000_000_000_000_000` (10^16) +- Reference: `contracts/scripts/contracts/ickb_logic/src/entry.rs` function `deposit_to_ickb()` +- Fix approach: Add cross-validation tests with known inputs/outputs derived from the Rust contract logic + +### TS Molecule Codecs Must Match Contract Schemas + +- What's not tested: The TypeScript Molecule codec definitions (`@ccc.codec` decorators in `packages/order/src/entities.ts`, `packages/core/src/entities.ts`) must produce byte-identical encodings to the Molecule schema at `contracts/schemas/encoding.mol`. Field order, sizes, and endianness must match exactly. +- Key schemas: + - `ReceiptData { deposit_quantity: Uint32, deposit_amount: Uint64 }` = 12 bytes + - `OwnedOwnerData { owned_distance: Int32 }` = 4 bytes + - `Ratio { ckb_multiplier: Uint64, udt_multiplier: Uint64 }` = 16 bytes + - `OrderInfo { ckb_to_udt: Ratio, udt_to_ckb: Ratio, ckb_min_match_log: Uint8 }` = 33 bytes + - Order cell data: `[UDT amount (16)] [Action (4)] [TX hash/padding (32)] [Index/distance (4)] [OrderInfo (33)] = 89 bytes` +- Fix approach: Add codec roundtrip tests using known byte vectors from the Rust contract tests or manually constructed from the Molecule schema ## Dead Code @@ -252,4 +272,4 @@ --- -*Concerns audit: 2026-02-14* +*Concerns audit: 2026-02-17* diff --git a/.planning/codebase/CONVENTIONS.md b/.planning/codebase/CONVENTIONS.md index 3142032..2a9e1f9 100644 --- a/.planning/codebase/CONVENTIONS.md +++ b/.planning/codebase/CONVENTIONS.md @@ -1,6 +1,6 @@ # Coding Conventions -**Analysis Date:** 2026-02-14 +**Analysis Date:** 2026-02-17 ## Important Context @@ -18,7 +18,7 @@ **Files:** - Use `snake_case` for multi-word source files: `owned_owner.ts` -- Use single lowercase words when possible: `cells.ts`, `entities.ts`, `logic.ts`, `codec.ts`, `utils.ts`, `epoch.ts`, `heap.ts`, `udt.ts` +- Use single lowercase words when possible: `cells.ts`, `entities.ts`, `logic.ts`, `codec.ts`, `utils.ts`, `heap.ts`, `udt.ts` - Every package has an `index.ts` barrel file that re-exports everything - Config files at root use dot-prefix convention: `prettier.config.cjs`, `eslint.config.mjs`, `vitest.config.mts` @@ -270,16 +270,18 @@ export * from "./utils.js"; ## Molecule / Codec Patterns -**Entity classes** use CCC's `mol.Entity.Base` with decorator-based codec definition: +**TS codecs must match the Molecule schema** at `contracts/schemas/encoding.mol`. The on-chain contracts use Molecule for serialization; the TS packages must produce byte-identical encodings. + +**Entity classes** use CCC's `ccc.Entity.Base` with decorator-based codec definition: ```typescript // packages/order/src/entities.ts -@mol.codec( +@ccc.codec( mol.struct({ ckbScale: mol.Uint64, udtScale: mol.Uint64, }), ) -export class Ratio extends mol.Entity.Base() { +export class Ratio extends ccc.Entity.Base() { constructor( public ckbScale: ccc.Num, public udtScale: ccc.Num, @@ -324,7 +326,6 @@ let origins: readonly I8Cell[] = Object.freeze([]); ``` - Use `readonly` on class fields and interface members where appropriate - Use `Readonly` wrapper type for maps and objects: `Readonly>` -- Private constructors for controlled instantiation: `Epoch` in `packages/utils/src/epoch.ts` uses `private constructor` ## Async Generator Pattern @@ -369,4 +370,4 @@ process.exit(0); --- -*Convention analysis: 2026-02-14* +*Convention analysis: 2026-02-17* diff --git a/.planning/codebase/INTEGRATIONS.md b/.planning/codebase/INTEGRATIONS.md index 77c65de..e93fd06 100644 --- a/.planning/codebase/INTEGRATIONS.md +++ b/.planning/codebase/INTEGRATIONS.md @@ -1,6 +1,6 @@ # External Integrations -**Analysis Date:** 2026-02-14 +**Analysis Date:** 2026-02-17 ## APIs & External Services @@ -104,42 +104,104 @@ All interaction with the Nervos CKB Layer 1 blockchain happens via JSON-RPC 2.0. ## Smart Contracts (On-Chain Scripts) -The project interacts with several on-chain CKB scripts defined in `packages/sdk/src/constants.ts`: +The project interacts with several on-chain CKB scripts defined in `packages/sdk/src/constants.ts`. The Rust source code is available in the `contracts/` reference repo (clone via `pnpm reference`). Protocol design is documented in the `whitepaper/` reference repo. **NervosDAO:** - Code hash: `0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e` - Hash type: `type` - Purpose: Deposit/withdraw CKB with interest (Nervos DAO) - Managed by: `DaoManager` in `packages/dao/src/dao.ts` +- Constants: `DAO_DEPOSIT_DATA = [0,0,0,0,0,0,0,0]` (8 zero bytes = deposit; non-zero = withdrawal request) +- DAO accumulated rate: extracted from block header at offset 168, size 8 bytes +- Genesis accumulated rate: `AR_0 = 10^16` (used as baseline for iCKB exchange rate) -**iCKB UDT (User Defined Token):** +**iCKB UDT (xUDT Token):** - Code hash: `0x50bd8d6680b8b9cf98b73f3c08faf8b2a21914311954118ad6609be6e78a1b95` - Hash type: `data1` -- Purpose: The iCKB token type script +- Args: `[iCKB_Logic_Hash, 0x00000080]` (0x80000000 = owner mode by input type) +- Token script hash: `0xd485c2271949c232e3f5d46128336c716f90bcbf3cb278696083689fbbcd407a` +- Amount storage: 16 bytes (u128 LE) in cell data +- Purpose: The iCKB token type script (xUDT standard) - Managed by: `IckbUdtManager` in `packages/core/src/udt.ts` **iCKB Logic:** - Code hash: `0x2a8100ab5990fa055ab1b50891702e1e895c7bd1df6322cd725c1a6115873bd3` - Hash type: `data1` -- Purpose: Core iCKB deposit/receipt logic +- Purpose: Core iCKB deposit/receipt logic (type script) - Managed by: `LogicManager` in `packages/core/src/logic.ts` +- Contract source: `contracts/scripts/contracts/ickb_logic/` +- Validation rules: + - Empty args required (prevents reuse with different configurations) + - Cell classification: Deposit (iCKB lock + DAO type), Receipt (any lock + iCKB type), UDT (any lock + xUDT type) + - Conservation law: `input_udt + input_receipts = output_udt + input_deposits` + - Deposit size: min 1,000 CKB, max 1,000,000 CKB (unoccupied capacity) + - Soft cap: 100,000 iCKB per deposit; 10% penalty on excess + - Receipt-deposit matching: for each unique deposit amount, deposit count must equal receipt count +- Receipt data format: `[deposit_quantity: u32 LE (4 bytes), deposit_amount: u64 LE (8 bytes)]` = 12 bytes total +- Exchange rate: `iCKB = capacity * AR_0 / AR_m` where AR_m = accumulated rate at deposit block +- Error codes: NotEmptyArgs(5), ScriptMisuse(6), DepositTooSmall(7), DepositTooBig(8), EmptyReceipt(9), ReceiptMismatch(10), AmountMismatch(11), AmountUnreasonablyBig(12) **Owned Owner:** - Code hash: `0xacc79e07d107831feef4c70c9e683dac5644d5993b9cb106dca6e74baa381bd0` - Hash type: `data1` -- Purpose: Withdrawal ownership tracking +- Purpose: Withdrawal ownership tracking (lock script) - Managed by: `OwnedOwnerManager` in `packages/core/src/owned_owner.ts` +- Contract source: `contracts/scripts/contracts/owned_owner/` +- Design: Solves NervosDAO constraint that deposit lock and withdrawal lock must have equal size +- Mechanism: Owner cell (type=owned_owner) contains `owned_distance: i32 LE` (4 bytes) pointing to its paired owned cell (lock=owned_owner) +- Validation rules: + - Empty args required + - Owned cells must be DAO withdrawal requests (not deposits) + - 1:1 pairing enforced: exactly 1 owner and 1 owned per MetaPoint, in both inputs and outputs + - Cannot be both lock and type simultaneously +- Error codes: NotEmptyArgs(5), NotWithdrawalRequest(6), ScriptMisuse(7), Mismatch(8) **Order (Limit Order):** - Code hash: `0x49dfb6afee5cc8ac4225aeea8cb8928b150caf3cd92fea33750683c74b13254a` - Hash type: `data1` -- Purpose: On-chain limit orders for CKB/iCKB exchange +- Purpose: On-chain limit orders for CKB/UDT exchange (lock script) - Managed by: `OrderManager` in `packages/order/src/order.ts` +- Contract source: `contracts/scripts/contracts/limit_order/` +- Lifecycle: Mint (create order + master cell) -> Match (partial/full fill) -> Melt (destroy fulfilled order) +- Order cell data layout (88-89 bytes): + - `[0:16]` UDT amount (u128 LE) + - `[16:20]` Action (u32 LE): 0=Mint, 1=Match + - `[20:52]` TX hash (Mint: all zeros padding) or master outpoint hash (Match) + - `[52:56]` Master distance (Mint: i32 relative offset) or master index (Match: u32 absolute) + - `[56:64]` CKB->UDT ckb_multiplier (u64 LE) + - `[64:72]` CKB->UDT udt_multiplier (u64 LE) + - `[72:80]` UDT->CKB ckb_multiplier (u64 LE) + - `[80:88]` UDT->CKB udt_multiplier (u64 LE) + - `[88:89]` ckb_min_match_log (u8): minimum match = `1 << n`, range 0..=64 +- Validation rules: + - Empty args required + - Mint: output has order + master; padding must be all zeros + - Match: value conservation `in_ckb * ckb_mul + in_udt * udt_mul <= out_ckb * ckb_mul + out_udt * udt_mul` + - Melt: input has order + master; no output + - Concavity check: `c2u.ckb_mul * u2c.udt_mul >= c2u.udt_mul * u2c.ckb_mul` (round-trip cannot lose value) + - DOS prevention: partial matches must meet minimum threshold (`1 << ckb_min_match_log`) + - Order info (ratios, min match, UDT hash) must be immutable across matches + - Cannot modify already-fulfilled orders +- Error codes: NotEmptyArgs(5), DuplicatedMaster(6), InvalidAction(7), NonZeroPadding(8), InvalidRatio(9), InvalidCkbMinMatchLog(10), ConcaveRatio(11), BothRatioNull(12), MissingUdtType(13), SameMaster(14), ScriptMisuse(15), DifferentInfo(16), InvalidMatch(17), DecreasingValue(18), AttemptToChangeFulfilled(19), InsufficientMatch(20), InvalidConfiguration(21) + +**Molecule Schema (`contracts/schemas/encoding.mol`):** +```molecule +struct ReceiptData { deposit_quantity: Uint32, deposit_amount: Uint64 } +struct OwnedOwnerData { owned_distance: Int32 } +struct Ratio { ckb_multiplier: Uint64, udt_multiplier: Uint64 } +struct OrderInfo { ckb_to_udt: Ratio, udt_to_ckb: Ratio, ckb_min_match_log: Uint8 } +struct MintOrderData { padding: Byte32, master_distance: Int32, order_info: OrderInfo } +struct MatchOrderData { master_outpoint: OutPoint, order_info: OrderInfo } +union PartialOrderData { MintOrderData, MatchOrderData } +``` **Deployment Groups (Cell Dependencies):** - Mainnet dep group: TX `0x621a6f38de3b9f453016780edac3b26bfcbfa3e2ecb47c2da275471a5d3ed165` index 0 - Testnet dep group: TX `0xf7ece4fb33d8378344cab11fcd6a4c6f382fd4207ac921cf5821f30712dcd311` index 0 - Known bot scripts: one mainnet bot, one testnet bot (lock scripts in `packages/sdk/src/constants.ts`) +- Deployment TX (mainnet): `0xd7309191381f5a8a2904b8a79958a9be2752dbba6871fa193dab6aeb29dc8f44` +- All scripts deployed with zero lock (immutable, non-upgradable) +- Security audit: Scalebit (2024-09-11), no critical vulnerabilities **Network configuration:** `IckbSdk.from("mainnet" | "testnet")` in `packages/sdk/src/sdk.ts` selects the appropriate script hashes and dep groups. @@ -218,4 +280,4 @@ CCC (`@ckb-ccc/core`) is the most critical external dependency. Key capabilities --- -*Integration audit: 2026-02-14* +*Integration audit: 2026-02-17* diff --git a/.planning/codebase/STACK.md b/.planning/codebase/STACK.md index 6761aaa..301548a 100644 --- a/.planning/codebase/STACK.md +++ b/.planning/codebase/STACK.md @@ -1,12 +1,15 @@ # Technology Stack -**Analysis Date:** 2026-02-14 +**Analysis Date:** 2026-02-17 ## Languages **Primary:** - TypeScript 5.9.3 - All source code across packages and apps +**On-Chain (reference):** +- Rust 2021 edition - On-chain CKB smart contracts in `contracts/` reference repo (3 contracts + shared utils, ~1,163 lines). Built with Capsule v0.10.5, `no_std` + alloc-only runtime, targeting RISC-V. Uses `ckb-std 0.15.3` and `primitive_types` crate for C256 safe math. + **Secondary:** - Bash - `ccc-dev/record.sh`, `ccc-dev/replay.sh` for local CCC dev build setup - JavaScript (CJS) - `.pnpmfile.cjs` for pnpm hook overrides, `prettier.config.cjs` @@ -110,7 +113,7 @@ The repo supports using a local development build of CCC for testing unpublished - Applies to `dependencies`, `devDependencies`, and `optionalDependencies` - Effect: all workspace packages transparently use the local CCC build instead of npm versions -**CCC upstream contributions:** The maintainer contributed UDT and Epoch support to CCC upstream (now merged). Some local code in `packages/utils/src/epoch.ts` and `packages/utils/src/udt.ts` may overlap with features now available natively in CCC. +**CCC upstream contributions:** The maintainer contributed UDT and Epoch support to CCC upstream (now merged). The local Epoch class has been deleted (replaced by `ccc.Epoch`). Some local UDT handling in `packages/utils/src/udt.ts` may still overlap with features now available in CCC's `@ckb-ccc/udt` package. ## Configuration @@ -181,4 +184,4 @@ The repo supports using a local development build of CCC for testing unpublished --- -*Stack analysis: 2026-02-14* +*Stack analysis: 2026-02-17* diff --git a/.planning/codebase/STRUCTURE.md b/.planning/codebase/STRUCTURE.md index 1eb844b..1cb8c7b 100644 --- a/.planning/codebase/STRUCTURE.md +++ b/.planning/codebase/STRUCTURE.md @@ -1,250 +1,388 @@ # Codebase Structure -**Analysis Date:** 2026-02-14 +**Analysis Date:** 2026-02-17 ## Directory Layout ``` /workspaces/stack/ -├── packages/ # NEW CCC-based libraries (replacing deprecated @ickb/lumos-utils, @ickb/v1-core) -│ ├── core/ # iCKB core logic and entities -│ ├── dao/ # Nervos DAO wrapper -│ ├── order/ # Limit order cell logic -│ ├── sdk/ # High-level SDK composing all packages -│ └── utils/ # Blockchain primitives and transaction helpers -├── apps/ # Applications -│ ├── bot/ # Order fulfillment bot (LEGACY - Lumos) -│ ├── faucet/ # Testnet CKB distribution (MIGRATED - CCC) -│ ├── sampler/ # Blockchain state sampling (MIGRATED - CCC) -│ ├── tester/ # Order creation simulator (LEGACY - Lumos) -│ └── interface/ # React web UI (LEGACY - Lumos) -├── scripts/ # Dev scripts (setup-ccc.sh) -├── ccc-dev/ # Local CCC development (record/replay system for unpublished changes) -├── .pnpmfile.cjs # pnpm hook to override @ckb-ccc/* with local ccc-dev/ builds -├── .planning/ # GSD planning documents -├── .github/ # GitHub workflows and configuration -├── .devcontainer/ # Dev container config -├── pnpm-workspace.yaml # Monorepo workspace definition -├── package.json # Root package manifest -├── tsconfig.json # TypeScript configuration -├── vitest.config.mts # Vitest configuration -├── eslint.config.mjs # ESLint configuration -└── README.md # Project documentation +├── packages/ # NEW CCC-based libraries (replacing Lumos) +│ ├── core/ # iCKB protocol logic (deposits, receipts, ownership) +│ │ └── src/ +│ │ ├── index.ts # Barrel export: cells, entities, logic, owned_owner, udt +│ │ ├── logic.ts # LogicManager class (269 lines) +│ │ ├── owned_owner.ts # OwnedOwnerManager class (239 lines) +│ │ ├── cells.ts # Cell type wrappers (175 lines) +│ │ ├── entities.ts # OwnerData, ReceiptData codec (113 lines) +│ │ └── udt.ts # iCKB UDT value calculations (213 lines) +│ ├── dao/ # Nervos DAO abstraction layer +│ │ └── src/ +│ │ ├── index.ts # Barrel export: cells, dao +│ │ ├── dao.ts # DaoManager class (412 lines) +│ │ └── cells.ts # DaoCell types (180 lines) +│ ├── order/ # Limit order management +│ │ └── src/ +│ │ ├── index.ts # Barrel export: cells, entities, order +│ │ ├── order.ts # OrderManager class (988 lines) +│ │ ├── entities.ts # Info, Ratio, OrderData types (754 lines) +│ │ └── cells.ts # OrderCell, MasterCell, OrderGroup (396 lines) +│ ├── sdk/ # High-level SDK composition +│ │ └── src/ +│ │ ├── index.ts # Barrel export: codec, constants, sdk +│ │ ├── sdk.ts # IckbSdk class (512 lines) +│ │ ├── constants.ts # Script config factory (205 lines) +│ │ └── codec.ts # PoolSnapshot codec (138 lines) +│ └── utils/ # Shared blockchain utilities +│ └── src/ +│ ├── index.ts # Barrel export: codec, capacity, heap, transaction, udt, utils│ ├── transaction.ts # SmartTransaction class (517 lines) +│ ├── capacity.ts # CapacityManager class (221 lines) +│ ├── udt.ts # UDT calculations and handlers (393 lines) +│ ├── utils.ts # Binary search, collectors, etc. (458 lines) +│ ├── codec.ts # CheckedInt32LE codec (21 lines) +│ └── heap.ts # Heap implementation (175 lines) +├── apps/ # Applications +│ ├── bot/ # Order matching daemon (LEGACY - Lumos) +│ │ └── src/ +│ │ └── index.ts # main() entry with order matching loop (897 lines) +│ ├── faucet/ # Testnet CKB distribution (MIGRATED to CCC) +│ │ └── src/ +│ │ ├── index.ts # Export main() +│ │ └── main.ts # main() entry with distribution loop (86 lines) +│ ├── sampler/ # Blockchain state sampling (MIGRATED to CCC) +│ │ └── src/ +│ │ └── index.ts # Direct execution entry (192 lines) +│ ├── tester/ # Order creation simulator (LEGACY - Lumos) +│ │ └── src/ +│ │ └── index.ts # main() entry with test scenarios (469 lines) +│ └── interface/ # React web UI (LEGACY - Lumos) +│ ├── src/ +│ │ ├── main.tsx # startApp(wallet_chain) entry (68 lines) +│ │ ├── App.tsx # Root component with conversion logic (93 lines) +│ │ ├── Connector.tsx # Wallet connection setup (104 lines) +│ │ ├── Form.tsx # User input form (144 lines) +│ │ ├── Action.tsx # Transaction execution (174 lines) +│ │ ├── Dashboard.tsx # Balance display (36 lines) +│ │ ├── Progress.tsx # Loading indicator (42 lines) +│ │ ├── queries.ts # React Query options and state (395 lines) +│ │ ├── transaction.ts # Transaction builders (291 lines) +│ │ ├── utils.ts # Helper utilities (160 lines) +│ │ └── vite-env.d.ts # Vite type definitions +│ └── public/ # Static assets +├── ccc-dev/ # Local CCC development (record/replay system) +│ ├── pins/ # Committed: pinned SHAs and conflict resolutions +│ │ ├── REFS # Pinned branch HEADs +│ │ └── resolutions/ # Merge conflict resolutions +│ ├── ccc/ # Gitignored: ephemeral CCC clone (auto-generated) +│ ├── record.sh # Records new pins with Claude conflict resolution +│ ├── replay.sh # Deterministically rebuilds ccc/ from pins +│ └── tsc.mjs # TypeScript compilation script override +├── contracts/ # Reference: Rust on-chain contracts (git-ignored, clone via `pnpm reference`) +│ └── scripts/contracts/ +│ ├── ickb_logic/ # Type script: iCKB UDT minting/validation +│ ├── limit_order/ # Lock script: peer-to-peer limit orders +│ ├── owned_owner/ # Lock script: DAO withdrawal delegation +│ └── utils/ # Shared: DAO helpers, C256 safe math, MetaPoint +├── whitepaper/ # Reference: iCKB protocol design (git-ignored, clone via `pnpm reference`) +│ ├── README.md # Complete protocol specification (~49KB) +│ └── 2024_overview.md # Project overview and timeline +├── .planning/ # GSD analysis documents +│ └── codebase/ +│ ├── ARCHITECTURE.md # Architecture and data flows +│ ├── STRUCTURE.md # Directory layout and file locations +│ ├── CONVENTIONS.md # Code style and naming conventions +│ ├── TESTING.md # Testing patterns and frameworks +│ ├── CONCERNS.md # Technical debt and issues +│ ├── STACK.md # Technology stack +│ └── INTEGRATIONS.md # External services and APIs +├── scripts/ # Developer scripts +│ ├── pr.sh # Open GitHub PR creation page +│ └── review.sh # Fetch PR review comments +├── .github/ # GitHub configuration +│ └── workflows/ # CI/CD pipeline definitions +├── .devcontainer/ # Dev container configuration +├── node_modules/ # Installed dependencies (gitignored) +├── .pnpm-store/ # pnpm package cache (gitignored) +├── pnpm-workspace.yaml # Monorepo workspace and catalog definitions +├── package.json # Root workspace scripts and metadata +├── pnpm-lock.yaml # Deterministic lock file (committed) +├── tsconfig.json # Root TypeScript configuration +├── vitest.config.mts # Test framework configuration +├── eslint.config.mjs # ESLint configuration +├── prettier.config.cjs # Code formatter configuration +├── .gitignore # Git exclusions +├── LICENSE # MIT License +├── README.md # Project overview +└── CONTRIBUTING.md # Contribution guidelines ``` ## Directory Purposes -**packages/core:** +**packages/core/src/:** - Purpose: Core iCKB protocol implementation -- Contains: Deposit/receipt cell types, LogicManager, entity encoders, owned owner script logic -- Key files: `logic.ts` (LogicManager), `entities.ts` (ReceiptData), `cells.ts` (cell types) -- Exports: All via `index.ts` barrel export +- Exports: LogicManager, OwnedOwnerManager, IckbDepositCell, ReceiptCell, WithdrawalGroup, OwnerCell - Dependencies: @ckb-ccc/core, @ickb/dao, @ickb/utils -**packages/dao:** +**packages/dao/src/:** - Purpose: Nervos DAO abstraction layer -- Contains: DaoManager for DAO cell operations, cell type wrappers -- Key files: `dao.ts` (DaoManager), `cells.ts` (DAO cell types) -- Exports: All via `index.ts` barrel export -- Dependencies: @ckb-ccc/core +- Exports: DaoManager, DaoCell factory +- Key class: `DaoManager` implements ScriptDeps interface +- Methods: `deposit()`, `requestWithdrawal()`, `withdraw()`, `findDeposits()`, `findWithdrawalRequests()` +- Dependencies: @ckb-ccc/core, @ickb/utils -**packages/order:** -- Purpose: Limit order cell management -- Contains: OrderManager, order cell types, order entities -- Key files: `order.ts` (OrderManager), `entities.ts` (order data structures), `cells.ts` (cell types) -- Exports: All via `index.ts` barrel export +**packages/order/src/:** +- Purpose: Limit order cell management and matching +- Exports: OrderManager, OrderCell, MasterCell, OrderGroup, Info, Ratio, OrderData +- Key class: `OrderManager` implements ScriptDeps interface +- Methods: `convert()`, `mint()`, `satisfy()`, `melt()`, `findOrders()` +- Key types: `Info` (order metadata), `Ratio` (exchange rate) - Dependencies: @ckb-ccc/core, @ickb/utils -**packages/sdk:** -- Purpose: High-level unified SDK -- Contains: IckbSdk class (main entry point), codec definitions, constants -- Key files: `sdk.ts` (IckbSdk), `codec.ts` (PoolSnapshot codec), `constants.ts` (script configs) -- Exports: All via `index.ts` barrel export +**packages/sdk/src/:** +- Purpose: High-level unified SDK for iCKB operations +- Exports: IckbSdk, SystemState, CkbCumulative, PoolSnapshot codec +- Key class: `IckbSdk` with static factory `from()` and instance methods +- Primary methods: `estimate()`, `maturity()`, `request()`, `collect()`, `getL1State()` - Dependencies: @ckb-ccc/core, @ickb/core, @ickb/dao, @ickb/order, @ickb/utils -**packages/utils:** +**packages/utils/src/:** - Purpose: Shared blockchain utilities and primitives -- Contains: SmartTransaction, CapacityManager, epoch helpers, UDT handlers, codec utilities -- Key files: `transaction.ts` (SmartTransaction), `capacity.ts` (CapacityManager), `epoch.ts`, `udt.ts` -- Exports: All via `index.ts` barrel export +- Exports: SmartTransaction, CapacityManager, UdtHandler, CheckedInt32LE, codecs +- Key classes: `SmartTransaction` (transaction builder), `CapacityManager` (cell management) +- Key helpers: `collect()`, `unique()`, `binarySearch()`, `hexFrom()`, `getHeader()` - Dependencies: @ckb-ccc/core -**apps/bot:** -- Purpose: Automated order fulfillment service -- **Status: LEGACY** -- still uses `@ickb/lumos-utils`, `@ickb/v1-core`, `@ckb-lumos/*` (all deprecated) -- Contains: Main loop logic for matching and executing limit orders -- Key files: `src/index.ts` (main entry point with bot loop) -- Environment: Requires CHAIN, RPC_URL, BOT_PRIVATE_KEY, BOT_SLEEP_INTERVAL -- Execution: `pnpm start` runs with specified chain environment +**apps/bot/src/:** +- Purpose: Automated order matching service +- Status: LEGACY (uses @ickb/v1-core, @ckb-lumos/*, deprecated) +- Entry: `main()` function with infinite loop +- Key operations: State query → order matching → transaction building → signing → broadcast +- Environment variables: CHAIN, RPC_URL, BOT_PRIVATE_KEY, BOT_SLEEP_INTERVAL -**apps/faucet:** +**apps/faucet/src/:** - Purpose: Testnet CKB distribution from deposit cells -- **Status: MIGRATED** -- uses new `@ickb/utils` + CCC -- Contains: Account management, transaction building for fund transfers -- Key files: `src/index.ts` (main0 function with distribution loop) -- Environment: Requires ADDRESS (target account) -- Execution: `pnpm start` with ADDRESS env variable - -**apps/sampler:** -- Purpose: Blockchain state monitoring and iCKB exchange rate sampling -- **Status: MIGRATED** -- uses new `@ickb/core`, `@ickb/utils` + CCC -- Contains: State snapshot collection, rate calculation -- Key files: `src/index.ts` (main entry point) -- Output: CSV format to stdout via rate.csv -- Execution: `pnpm start` - -**apps/tester:** +- Status: MIGRATED (uses new packages + CCC) +- Entry: `main.ts` with `main()` function and 2-minute poll loop +- Key operations: Discover faucet funds → build transfer transaction → sign and broadcast +- Environment variables: ADDRESS (recipient address) + +**apps/sampler/src/:** +- Purpose: Blockchain state monitoring and exchange rate sampling +- Status: MIGRATED (uses new packages + CCC) +- Entry: Direct execution from `index.ts` +- Key operations: Periodic state snapshot collection, rate calculation +- Output: CSV format data via rate.csv + +**apps/tester/src/:** - Purpose: Order creation simulation and testing -- **Status: LEGACY** -- still uses `@ickb/lumos-utils`, `@ickb/v1-core`, `@ckb-lumos/*` (all deprecated) -- Contains: Order scenario execution, response validation -- Key files: `src/index.ts` (main entry point) -- Environment: Requires CHAIN environment variable -- Execution: `pnpm start` with CHAIN environment - -**apps/interface:** -- Purpose: Web UI for iCKB operations -- **Status: LEGACY** -- still uses `@ickb/lumos-utils`, `@ickb/v1-core`, `@ckb-lumos/*` (all deprecated) -- Contains: React components, transaction building, state queries -- Key files: `main.tsx` (app bootstrap), `App.tsx` (root component), `queries.ts` (data fetching) -- Components: Dashboard, Form, Action, Progress, Connector -- Dependencies: React 19, TailwindCSS, react-query, CCC, Lumos +- Status: LEGACY (uses @ickb/v1-core, @ckb-lumos/*, deprecated) +- Entry: `main()` function with test scenarios +- Key operations: Simulate user order creation, validate responses + +**apps/interface/src/:** +- Purpose: Web UI for iCKB operations (React application) +- Status: LEGACY (uses @ickb/v1-core, @ckb-lumos/*, deprecated) +- Entry: `main.tsx` with `startApp(wallet_chain)` function +- Component tree: Connector → App → Form/Dashboard/Action +- Data flow: React Query for L1 state, SmartTransaction for TX building +- Styling: TailwindCSS with inline classes **ccc-dev/:** - Purpose: Local CCC clone for development against unpublished upstream changes -- Uses record/replay system: `record.sh` captures pinned SHAs + conflict resolutions, `replay.sh` deterministically rebuilds -- `ccc-dev/pins/` is committed (pinned SHAs and resolutions), `ccc-dev/ccc/` is gitignored (ephemeral clone) -- `.pnpmfile.cjs` auto-triggers replay on `pnpm install` and overrides all `@ckb-ccc/*` deps to `workspace:*` -- Recording: `pnpm ccc:record` (requires Claude CLI for conflict resolution) +- System: Record/replay mechanism for deterministic builds +- `pins/`: Committed directory with pinned SHAs (REFS, HEAD) and conflict resolutions +- `ccc/`: Gitignored, ephemeral clone auto-generated by `replay.sh` +- Activation: `.pnpmfile.cjs` auto-triggers replay on `pnpm install` and redirects @ckb-ccc/* deps **.planning/codebase/:** - Purpose: GSD codebase analysis documents -- Contains: ARCHITECTURE.md, STRUCTURE.md, CONVENTIONS.md, TESTING.md, CONCERNS.md, STACK.md, INTEGRATIONS.md -- Usage: Referenced by GSD orchestrator for phase planning +- Contents: ARCHITECTURE.md, STRUCTURE.md, CONVENTIONS.md, TESTING.md, CONCERNS.md, STACK.md, INTEGRATIONS.md +- Usage: Read by GSD orchestrator for phase planning and code generation ## Key File Locations **Entry Points:** -- `packages/sdk/src/sdk.ts` - IckbSdk.from() factory -- `apps/bot/src/index.ts` - Bot main() function -- `apps/faucet/src/index.ts` - Faucet main0() function -- `apps/sampler/src/index.ts` - Sampler main() function -- `apps/tester/src/index.ts` - Tester main() function -- `apps/interface/src/main.tsx` - Interface startApp() function - -**Configuration:** -- `pnpm-workspace.yaml` - Monorepo packages and catalog definitions -- `package.json` - Root scripts and CCC override configuration -- `tsconfig.json` - TypeScript compiler options (ES2020 target, strict mode) -- `vitest.config.mts` - Vitest test discovery and coverage configuration - -**Core Logic:** -- `packages/core/src/logic.ts` - LogicManager (deposit/receipt operations) -- `packages/order/src/order.ts` - OrderManager (order cell operations) -- `packages/utils/src/transaction.ts` - SmartTransaction (fee completion, UDT balancing) -- `packages/utils/src/capacity.ts` - CapacityManager (cell collection and change management) - -**Testing:** -- `vitest.config.mts` - Test configuration at root -- `packages/*/vitest.config.mts` - Per-package test configs (if present) -- No test files currently in packages/ or apps/ +- SDK: `packages/sdk/src/sdk.ts` → `IckbSdk` class with static `from()` factory +- Faucet app: `apps/faucet/src/main.ts` → `main()` async function +- Bot app: `apps/bot/src/index.ts` → `main()` async function +- Interface app: `apps/interface/src/main.tsx` → `startApp(wallet_chain: string)` function +- Sampler app: `apps/sampler/src/index.ts` → Direct execution entry +- Tester app: `apps/tester/src/index.ts` → `main()` async function + +**Configuration Files:** +- Monorepo: `pnpm-workspace.yaml` (workspace definition + catalog) +- Root scripts: `package.json` (build/test/lint/dev commands) +- TypeScript: `tsconfig.json` (ES2020 target, strict mode) +- Tests: `vitest.config.mts` (test discovery and coverage) +- Linting: `eslint.config.mjs` (ESLint rules) +- Formatting: `prettier.config.cjs` (code style) + +**Core Domain Logic:** +- Deposits: `packages/core/src/logic.ts` → `LogicManager` class (269 lines) +- Orders: `packages/order/src/order.ts` → `OrderManager` class (988 lines) +- DAO: `packages/dao/src/dao.ts` → `DaoManager` class (412 lines) +- Transactions: `packages/utils/src/transaction.ts` → `SmartTransaction` class (517 lines) +- Capacity: `packages/utils/src/capacity.ts` → `CapacityManager` class (221 lines) + +**Type Definitions:** +- Order entities: `packages/order/src/entities.ts` (Info, Ratio, OrderData) — 754 lines +- Core entities: `packages/core/src/entities.ts` (OwnerData, ReceiptData) — 113 lines +- Cell wrappers: `packages/{core,dao,order}/src/cells.ts` (DaoCell, IckbDepositCell, etc.) ## Naming Conventions **Files:** -- Sources: `*.ts` for TypeScript, `*.tsx` for React components -- Compiled output: `dist/` directory (gitignored) -- Type definitions: Automatic from `*.ts` files via `declaration: true` in tsconfig +- Source: `*.ts` for TypeScript, `*.tsx` for React components +- Compiled: `dist/` directory (generated, gitignored) +- Type definitions: Auto-generated from source via `declaration: true` +- Tests: Not currently present; would use `*.test.ts` or `*.spec.ts` pattern **Directories:** -- Package directories: kebab-case (e.g., `packages/order`, `apps/interface`) -- Source directories: Always `src/` for packages and apps -- Output directory: Always `dist/` after compilation +- Packages: kebab-case (`core`, `dao`, `order`, `sdk`, `utils`) +- Apps: kebab-case (`bot`, `faucet`, `sampler`, `tester`, `interface`) +- Source: Always `src/` for both packages and apps +- Output: Always `dist/` after compilation **Exports:** -- Barrel exports: `index.ts` re-exports all public types and functions +- Barrel files: `index.ts` re-exports all public symbols - Pattern: `export * from "./module.js"` (using `.js` extension for ESM) -- No default exports in index files +- No default exports; all named exports +- Types and functions exported at package level via index -**Functions and Classes:** -- Class names: PascalCase (e.g., `IckbSdk`, `LogicManager`, `SmartTransaction`) -- Function names: camelCase (e.g., `main`, `deposit`, `completeFee`) -- Manager classes: Consistently named with Manager suffix (LogicManager, OrderManager, DaoManager, CapacityManager) +**Classes and Functions:** +- Classes: PascalCase (e.g., `IckbSdk`, `LogicManager`, `SmartTransaction`, `DaoManager`) +- Manager suffix: Consistently applied to manager classes +- Instance methods: camelCase (e.g., `deposit()`, `mint()`, `getL1State()`) +- Static methods: camelCase on class (e.g., `IckbSdk.from()`, `IckbSdk.estimate()`) +- Private methods: camelCase prefixed with underscore (e.g., `_getCkb()`) **Interfaces and Types:** -- Interfaces: PascalCase, often end with -Like for permissive input types (e.g., `OwnerDataLike`, `ReceiptDataLike`) -- Type unions: PascalCase (e.g., `SystemState`, `OrderCell`, `L1StateType`) -- Type aliases: Match the entity they represent +- Interfaces: PascalCase (e.g., `DaoCell`, `OrderCell`, `ValueComponents`) +- Input-like types: Suffix with -Like (e.g., `InfoLike`, `OwnerDataLike`) +- Readonly types: No prefix; immutability expressed via readonly properties +- Type unions: PascalCase (e.g., `SystemState`, `OrderGroup`, `L1StateType`) ## Where to Add New Code -**New Feature (e.g., new protocol operation):** -- Primary code: Create in `packages/{appropriate-package}/src/{feature}.ts` - - If cross-domain: Add to `packages/sdk/src/` and compose with existing managers - - If specific to domain: Add to domain package (core, dao, order) -- Tests: Create `packages/{package}/src/{feature}.test.ts` (when testing is set up) -- Export: Add to `packages/{package}/src/index.ts` barrel file - -**New Component/Module (e.g., new UI page):** -- Implementation: `apps/interface/src/{ComponentName}.tsx` -- Styles: Inline with TailwindCSS classes or tailwind.config.js -- Data fetching: Add query options in `apps/interface/src/queries.ts` -- Transaction helpers: Add to `apps/interface/src/transaction.ts` if needed - -**New Application (e.g., new CLI tool):** -- Create: New directory in `apps/{app-name}/` -- Copy structure: Use existing app (e.g., faucet or sampler) as template -- Files needed: - - `package.json` - With appropriate scripts and dependencies - - `src/index.ts` - Main entry point - - `env/{CHAIN}/.env` - If environment-specific (for bot, tester) -- Register: Add to `pnpm-workspace.yaml` packages list if not auto-detected - -**Utilities (e.g., new helper functions):** -- Shared helpers: `packages/utils/src/{category}.ts` -- Import pattern: `export * from "./{category}.js"` in `packages/utils/src/index.ts` -- Domain-specific: Place in appropriate domain package +**New Blockchain Operation (e.g., new order type):** +- Domain package location: `packages/{appropriate-domain}/src/{feature}.ts` + - Order-related: `packages/order/src/` + - DAO-related: `packages/dao/src/` + - iCKB-specific: `packages/core/src/` +- Manager method: Add to appropriate Manager class +- Type export: Add to barrel export in `packages/{package}/src/index.ts` +- SDK integration: If cross-domain, add to `IckbSdk` in `packages/sdk/src/sdk.ts` + +**New React Component (e.g., new UI page):** +- Location: `apps/interface/src/{ComponentName}.tsx` +- Pattern: Functional component with React hooks +- Data fetching: Add query factory to `apps/interface/src/queries.ts` +- Styling: TailwindCSS classes inline; no separate CSS files +- State: Use React hooks + React Query for async state + +**New CLI App (e.g., new service daemon):** +- Structure: Create `apps/{app-name}/` directory +- Template: Copy structure from existing app (faucet or sampler) +- Required files: + - `package.json` with scripts and dependencies + - `src/index.ts` as entry point (export main function if needed) + - `src/main.ts` if index.ts re-exports + - `env/{CHAIN}/.env` if environment-specific config needed +- Registration: Auto-detected by pnpm-workspace.yaml pattern matching + +**New Utility Function:** +- Shared/generic: `packages/utils/src/{category}.ts` +- Domain-specific: Place in appropriate domain package `src/{category}.ts` +- Export: Add to barrel in `src/index.ts` with `export * from "./{category}.js"` +- Import pattern: Use `.js` extensions in ESM exports for compatibility + +**New Manager Class:** +- Location: `packages/{domain}/src/{manager-name}.ts` +- Pattern: Implement `ScriptDeps` interface if handling scripts: + ```typescript + export class FeatureManager implements ScriptDeps { + constructor( + public readonly script: ccc.Script, + public readonly cellDeps: ccc.CellDep[], + ) {} + // ... methods + } + ``` +- Transaction methods: Accept `SmartTransaction`, call `.addCellDeps()`, `.addInput()`, `.addOutput()` +- Finding methods: Use async generators for lazy cell discovery +- Type checkers: Implement `isFoo(cell)` methods for type verification **Dependencies:** -- Internal: Use workspace protocol: `"@ickb/package": "workspace:*"` -- External: Run `pnpm add @package/name` from workspace root -- Catalog versions: Use `"@package/name": "catalog:"` if defined in pnpm-workspace.yaml +- Internal package: `"@ickb/package": "workspace:*"` in package.json +- Internal CCC (local dev): Automatic via `.pnpmfile.cjs` override when `ccc-dev/ccc/` exists +- External package: `pnpm add @vendor/package` from workspace root +- Catalog versions: Reference via `"@vendor/package": "catalog:"` in pnpm-workspace.yaml + +**contracts/ (reference repo):** +- Purpose: Rust on-chain smart contracts for the iCKB protocol (3 production contracts + shared utils) +- Cloned via: `pnpm reference` (git-ignored, read-only reference) +- Key paths: + - `scripts/contracts/ickb_logic/` - Type script: iCKB UDT minting, deposit/receipt validation, conservation law + - `scripts/contracts/limit_order/` - Lock script: peer-to-peer limit order matching (mint/match/melt lifecycle) + - `scripts/contracts/owned_owner/` - Lock script: owner-owned cell pairing for DAO withdrawal delegation + - `scripts/contracts/utils/` - Shared: DAO helpers, C256 safe math, MetaPoint, cell type classification + - `schemas/encoding.mol` - Molecule schema definitions (canonical data format that TS codecs must match) + - `scripts/deployment/` - Network configs (devnet/testnet/mainnet) +- Build: Capsule v0.10.5, Rust 2021, `no_std` + alloc-only, RISC-V target +- Audit: Scalebit (2024-09-11) + +**whitepaper/ (reference repo):** +- Purpose: iCKB protocol design specification +- Cloned via: `pnpm reference` (git-ignored, read-only reference) +- Key files: + - `README.md` (~49KB) - Complete protocol specification: deposit/withdrawal phases, exchange rate mechanics, soft cap penalty, pooled deposit model, ancillary scripts (owned owner, limit order), deployment details, attack mitigations + - `2024_overview.md` - Project timeline and milestones +- Key concepts: 2-phase deposit/withdrawal, `iCKB = capacity * AR_0 / AR_m`, 100k iCKB soft cap with 10% excess penalty, non-upgradable deployment, NervosDAO illiquidity solution ## Special Directories **ccc-dev/:** -- Purpose: Local CCC clone for development against unpublished upstream changes -- `ccc-dev/pins/`: Committed — pinned SHAs (`REFS`, `HEAD`) and conflict resolutions -- `ccc-dev/ccc/`: Gitignored — ephemeral CCC clone (auto-generated by replay) -- Override: `.pnpmfile.cjs` auto-triggers replay and redirects `@ckb-ccc/*` deps to local builds -- Scripts: `pnpm ccc:record` (record new pins), `pnpm install` (auto-replay) +- Purpose: Local development environment for CCC upstream PRs +- System: Record/replay mechanism for deterministic, conflict-free builds +- `pins/`: Committed directory containing: + - `REFS`: Pinned branch HEADs for merging + - `resolutions/`: Serialized conflict resolutions with Claude aid +- `ccc/`: Generated from pins; auto-deleted and rebuilt on `pnpm install` +- Activation: `.pnpmfile.cjs` hook triggers `replay.sh` and overrides package resolution +- Commands: + - Record: `pnpm ccc:record releases/next releases/udt` (requires Claude CLI) + - Rebuild: `pnpm install` (automatic) + - Clean: `pnpm ccc:nuke && pnpm install` **scripts/:** -- Purpose: Dev tooling scripts +- Purpose: Developer convenience scripts +- Files: `pr.sh` (GitHub PR creation), `review.sh` (fetch PR comments) +- Execution: Via `pnpm pr` and `pnpm review` shortcuts - Committed: Yes **node_modules/:** -- Purpose: Installed dependencies via pnpm -- Generated: Yes (via `pnpm install`) +- Purpose: Installed npm/pnpm dependencies +- Auto-generated: Yes (via `pnpm install`) - Committed: No (in .gitignore) -- Management: Use pnpm-lock.yaml for lock file +- Management: pnpm handles with pnpm-lock.yaml **dist/:** - Purpose: Compiled TypeScript output -- Generated: Yes (via `pnpm build`) +- Auto-generated: Yes (via `pnpm build`) - Committed: No (in .gitignore) -- Structure: Mirrors src/ with .js, .d.ts, and .map files +- Structure: Mirrors src/ with `.js`, `.d.ts`, and `.map` files +- Cleanup: `pnpm clean` removes all dist/ directories **.github/workflows/:** -- Purpose: CI/CD pipeline definitions +- Purpose: GitHub Actions CI/CD pipelines - Committed: Yes -- Contains: Automated tests, build, and publish workflows +- Workflows: Build, test, and publish on push/PR **.planning/codebase/:** -- Purpose: GSD analysis documents -- Generated: By gsd:map-codebase command +- Purpose: GSD analysis documents for orchestrator reference +- Generated: Yes (by `gsd:map-codebase` command) - Committed: Yes -- Usage: Read by gsd:plan-phase for implementation guidance +- Usage: `gsd:plan-phase` loads relevant docs for code generation guidance --- -*Structure analysis: 2026-02-14* +*Structure analysis: 2026-02-17* diff --git a/.planning/codebase/TESTING.md b/.planning/codebase/TESTING.md index 96f43e0..651b59f 100644 --- a/.planning/codebase/TESTING.md +++ b/.planning/codebase/TESTING.md @@ -1,6 +1,6 @@ # Testing Patterns -**Analysis Date:** 2026-02-14 +**Analysis Date:** 2026-02-17 ## Important Context @@ -84,7 +84,7 @@ export default defineConfig({ **Naming:** - Use `.test.ts` suffix (not `.spec.ts`) -- Name should match the source file: `epoch.ts` -> `epoch.test.ts`, `codec.ts` -> `codec.test.ts` +- Name should match the source file: `codec.ts` -> `codec.test.ts`, `heap.ts` -> `heap.test.ts` **Expected structure when adding tests:** ``` @@ -94,14 +94,12 @@ packages/utils/ │ ├── capacity.test.ts # <-- tests go here │ ├── codec.ts │ ├── codec.test.ts # <-- tests go here -│ ├── epoch.ts -│ ├── epoch.test.ts # <-- tests go here │ ├── heap.ts │ ├── heap.test.ts # <-- tests go here │ ├── index.ts │ ├── transaction.ts │ ├── udt.ts -│ └── utils.ts +│ ├── utils.ts │ └── utils.test.ts # <-- tests go here └── vitest.config.mts ``` @@ -244,10 +242,9 @@ pnpm test:cov # Generates V8 coverage report - Scope: Individual classes, functions, pure logic - Location: `packages/*/src/*.test.ts` - Priority targets for new tests: - 1. `packages/utils/src/epoch.ts` - Epoch arithmetic, normalization, comparison, hex conversion - 2. `packages/utils/src/utils.ts` - `binarySearch`, `asyncBinarySearch`, `gcd`, `min`, `max`, `sum`, `hexFrom`, `isHex`, `shuffle` - 3. `packages/utils/src/codec.ts` - `CheckedInt32LE` encode/decode, `union` codec - 4. `packages/utils/src/heap.ts` - `MinHeap` operations (push, pop, remove, fix) + 1. `packages/utils/src/utils.ts` - `binarySearch`, `asyncBinarySearch`, `gcd`, `min`, `max`, `sum`, `hexFrom`, `isHex`, `shuffle` + 2. `packages/utils/src/codec.ts` - `CheckedInt32LE` encode/decode + 3. `packages/utils/src/heap.ts` - `MinHeap` operations (push, pop, remove, fix) 5. `packages/order/src/entities.ts` - `Ratio`, `Info`, `Relative`, `OrderData` encode/decode/validate 6. `packages/order/src/cells.ts` - `OrderCell.mustFrom`, `OrderCell.tryFrom`, `OrderGroup` 7. `packages/dao/src/dao.ts` - `DaoManager.isDeposit`, `isWithdrawalRequest` @@ -258,6 +255,17 @@ pnpm test:cov # Generates V8 coverage report - Example: `LogicManager.deposit()` combining DaoManager + UdtHandler - Example: `IckbSdk.estimate()` combining exchange ratios with order info +**Contract-Alignment Tests (critical):** +- Scope: Verify TS logic produces identical results to Rust contract validation +- Priority targets: + 1. Exchange rate: `iCKB = capacity * AR_0 / AR_m` with soft cap penalty -- must match `contracts/scripts/contracts/ickb_logic/src/entry.rs` `deposit_to_ickb()` + 2. Molecule encoding: `ReceiptData`, `OwnedOwnerData`, `Ratio`, `OrderInfo`, `MintOrderData`, `MatchOrderData` -- must match `contracts/schemas/encoding.mol` + 3. Order value conservation: `in_ckb * ckb_mul + in_udt * udt_mul <= out_ckb * ckb_mul + out_udt * udt_mul` -- must match `contracts/scripts/contracts/limit_order/src/entry.rs` `validate()` + 4. Concavity check: `c2u.ckb_mul * u2c.udt_mul >= c2u.udt_mul * u2c.ckb_mul` -- must match limit_order contract + 5. Deposit size bounds: min 1,000 CKB, max 1,000,000 CKB unoccupied capacity + 6. Owned owner distance calculation: TS MetaPoint arithmetic must match contract's `extract_owned_metapoint()` +- Approach: Use known input/output vectors derived from the Rust contract logic or construct test cases from the Molecule schema + **E2E Tests:** - Not applicable -- apps interact with live blockchain nodes - Integration testing of apps happens via manual testing against devnet/testnet @@ -369,4 +377,4 @@ The test step is **commented out**. Once tests are written, uncomment to enable: --- -*Testing analysis: 2026-02-14* +*Testing analysis: 2026-02-17* From 6bd3aa1595d2a9d1437b1120c1363d5a12b8ea38 Mon Sep 17 00:00:00 2001 From: phroi <90913182+phroi@users.noreply.github.com> Date: Tue, 17 Feb 2026 02:44:29 +0000 Subject: [PATCH 3/3] docs: note that gh CLI is unavailable, use pnpm pr/review instead Co-Authored-By: Claude Opus 4.6 --- .planning/codebase/CONVENTIONS.md | 3 +++ README.md | 2 ++ 2 files changed, 5 insertions(+) diff --git a/.planning/codebase/CONVENTIONS.md b/.planning/codebase/CONVENTIONS.md index 2a9e1f9..09159be 100644 --- a/.planning/codebase/CONVENTIONS.md +++ b/.planning/codebase/CONVENTIONS.md @@ -4,6 +4,9 @@ ## Important Context +**Tooling:** +- `gh` CLI is NOT available and must NOT be installed. Use `pnpm pr` to open PRs and `pnpm review` to fetch PR comments. + **Legacy vs. New code:** - `@ickb/lumos-utils@1.4.2` and `@ickb/v1-core@1.4.2` are **LEGACY and DEPRECATED** npm packages. The apps (`apps/bot`, `apps/tester`, `apps/interface`) still depend on them. - The `packages/` directory contains the **NEW replacement libraries** built on CCC (ckb-ccc), which will eventually replace the legacy packages in the apps. diff --git a/README.md b/README.md index b0ea18b..6eab3d9 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,8 @@ This clones two repos into the project root (both are git-ignored and made read- | `pnpm pr` | Open a GitHub PR creation page for the current branch. Uses Claude to auto-generate title and body when available, falls back to branch name and commit log. | | `pnpm review` | Fetch and display PR review comments from GitHub for the current branch (or `pnpm review -- --pr ` for a specific PR). | +> **Note:** `gh` CLI is not available in this environment. Use `pnpm pr` and `pnpm review` instead. + ## Epoch Semantic Versioning This repository follows [Epoch Semantic Versioning](https://antfu.me/posts/epoch-semver). In short ESV aims to provide a more nuanced and effective way to communicate software changes, allowing for better user understanding and smoother upgrades.