diff --git a/.changeset/remove-smarttx-capacitymgr.md b/.changeset/remove-smarttx-capacitymgr.md
new file mode 100644
index 0000000..227e1d8
--- /dev/null
+++ b/.changeset/remove-smarttx-capacitymgr.md
@@ -0,0 +1,16 @@
+---
+"@ickb/utils": major
+"@ickb/core": major
+"@ickb/dao": major
+"@ickb/order": major
+"@ickb/sdk": major
+---
+
+Remove SmartTransaction and CapacityManager in favor of plain TransactionLike
+
+- Delete `SmartTransaction` class and `CapacityManager` class from `@ickb/utils`
+- Replace all `SmartTransaction` parameters with `ccc.TransactionLike` across all packages
+- Inline `getHeader`/`addHeaders` helpers and remove from public API
+- Consolidate 7 inline DAO output limit checks into `assertDaoOutputLimit` in CCC core
+- Change `UdtHandler.completeUdt` return type from `[number, boolean]` to `[ccc.Transaction, number, boolean]`
+- Replace local CCC patch with upstream PR #359
diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md
index 0c48a53..8fa39f9 100644
--- a/.planning/REQUIREMENTS.md
+++ b/.planning/REQUIREMENTS.md
@@ -9,12 +9,12 @@ Requirements for initial milestone. Each maps to roadmap phases.
### SmartTransaction Removal
-- [ ] **SMTX-01**: All manager method signatures across all 5 library packages accept `ccc.TransactionLike` instead of `SmartTransaction`, following CCC's convention (TransactionLike input, Transaction output); `CapacityManager` is deleted (not migrated)
-- [ ] **SMTX-02**: `SmartTransaction` class and its `completeFee()` override are deleted from `@ickb/utils`
+- [x] **SMTX-01**: All manager method signatures across all 5 library packages accept `ccc.TransactionLike` instead of `SmartTransaction`, following CCC's convention (TransactionLike input, Transaction output); `CapacityManager` is deleted (not migrated)
+- [x] **SMTX-02**: `SmartTransaction` class and its `completeFee()` override are deleted from `@ickb/utils`
- [ ] **SMTX-03**: Fee completion uses CCC-native `ccc.Transaction.completeFeeBy()` or `completeFeeChangeToLock()` with DAO-aware capacity calculation
-- [ ] **SMTX-04**: `getHeader()` function and `HeaderKey` type are removed from `@ickb/utils`; all call sites inline CCC client calls (`client.getTransactionWithHeader()`, `client.getHeaderByNumber()`); header caching handled transparently by `ccc.Client.cache`
-- [ ] **SMTX-05**: UDT handler registration (`addUdtHandlers()`) is replaced by direct `Udt` instance usage or standalone utility functions
-- [ ] **SMTX-06**: 64-output NervosDAO limit check is consolidated into a single utility function (currently scattered across 6 locations)
+- [x] **SMTX-04**: `getHeader()` function and `HeaderKey` type are removed from `@ickb/utils`; all call sites inline CCC client calls (`client.getTransactionWithHeader()`, `client.getHeaderByNumber()`); header caching handled transparently by `ccc.Client.cache`
+- [x] **SMTX-05**: UDT handler registration (`addUdtHandlers()`) is replaced by direct `Udt` instance usage or standalone utility functions
+- [x] **SMTX-06**: 64-output NervosDAO limit check is consolidated into a single utility function (currently scattered across 6 locations)
- [ ] **SMTX-07**: `IckbUdtManager` multi-representation UDT balance logic (xUDT + receipts + deposits) survives removal intact -- conservation law `Input UDT + Input Receipts = Output UDT + Input Deposits` is preserved
- [ ] **SMTX-08**: `IckbSdk.estimate()` and `IckbSdk.maturity()` continue working after SmartTransaction removal
- [ ] **SMTX-09**: All 5 library packages (`@ickb/utils`, `@ickb/dao`, `@ickb/order`, `@ickb/core`, `@ickb/sdk`) compile and pass type checking after removal
@@ -81,12 +81,12 @@ Which phases cover which requirements. Updated during roadmap creation.
| Requirement | Phase | Status | Notes |
|-------------|-------|--------|-------|
-| SMTX-01 | Phase 1 | Pending | Feature-slice: all signatures migrated to TransactionLike across all packages |
-| SMTX-02 | Phase 1 | Pending | |
+| SMTX-01 | Phase 1 | Complete | All signatures migrated to TransactionLike across all packages (01-03) |
+| SMTX-02 | Phase 1 | Complete | SmartTransaction class deleted from @ickb/utils (01-03) |
| SMTX-03 | Phase 6 | Pending | |
-| SMTX-04 | Phase 1 | Pending | getHeader()/HeaderKey removed, CCC client calls inlined |
-| SMTX-05 | Phase 4, 5 | Pending | addUdtHandlers() removed in Phase 1; replacement pattern finalized in Phase 4-5 after Phase 3 decision |
-| SMTX-06 | Phase 1 | Pending | DAO check contributed to CCC core via ccc-dev/ |
+| SMTX-04 | Phase 1 | Complete | getHeader()/HeaderKey removed, CCC client calls inlined |
+| SMTX-05 | Phase 1, 4, 5 | Complete | addUdtHandlers() replaced with tx.addCellDeps(udtHandler.cellDeps) (01-03); UdtHandler/UdtManager replacement deferred to Phase 4-5 |
+| SMTX-06 | Phase 1 | Complete | DAO check contributed to CCC core via ccc-dev/ (01-01) |
| SMTX-07 | Phase 5 | Pending | |
| SMTX-08 | Phase 6 | Pending | |
| SMTX-09 | Phase 7 | Pending | |
@@ -109,4 +109,4 @@ Which phases cover which requirements. Updated during roadmap creation.
---
*Requirements defined: 2026-02-21*
-*Last updated: 2026-02-22 after Phase 1 context (feature-slice restructure)*
+*Last updated: 2026-02-22 after 01-03 execution (SMTX-01, SMTX-02, SMTX-05 completed; Phase 1 complete)*
diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index e72cb3e..84bdb6f 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -12,7 +12,7 @@ This roadmap delivers the v1 milestone: removing the abandoned SmartTransaction
Decimal phases appear between their surrounding integers in numeric order.
-- [ ] **Phase 1: SmartTransaction Removal (feature-slice)** - Delete SmartTransaction class and infrastructure across all packages; contribute 64-output DAO limit check to CCC core; migrate all method signatures to ccc.TransactionLike
+- [x] **Phase 1: SmartTransaction Removal (feature-slice)** - Delete SmartTransaction class and infrastructure across all packages; contribute 64-output DAO limit check to CCC core; migrate all method signatures to ccc.TransactionLike
- [ ] **Phase 2: CCC Utility Adoption** - Replace local utility functions that duplicate CCC equivalents across all packages; preserve iCKB-unique utilities
- [ ] **Phase 3: CCC Udt Integration Investigation** - Assess feasibility of subclassing CCC's Udt class for iCKB's multi-representation value; design header access pattern; document decision
- [ ] **Phase 4: Deprecated CCC API Replacement** - Replace deprecated CCC API calls (`udtBalanceFrom`, etc.) with `@ckb-ccc/udt` equivalents in dao and order packages; finalize UDT handler replacement pattern based on Phase 3 findings
@@ -33,12 +33,12 @@ Decimal phases appear between their surrounding integers in numeric order.
4. A 64-output NervosDAO limit check exists in CCC core (via `ccc-dev/`): `completeFee()` safety net, standalone async utility, and `ErrorNervosDaoOutputLimit` error class; all 6+ scattered checks across dao/core packages are replaced with calls to this CCC utility
5. ALL manager method signatures across ALL 5 library packages accept `ccc.TransactionLike` instead of `SmartTransaction`, following CCC's convention (TransactionLike input, Transaction output with `Transaction.from()` conversion at entry point)
6. `pnpm check:full` passes after each feature-slice removal step — no intermediate broken states
-**Plans**: TBD
+**Plans**: 3 plans
Plans:
-- [ ] 01-01: TBD
-- [ ] 01-02: TBD
-- [ ] 01-03: TBD
+- [x] 01-01-PLAN.md — Build CCC DAO utility (ErrorNervosDaoOutputLimit + assertDaoOutputLimit) and replace all 7 scattered DAO checks
+- [x] 01-02-PLAN.md — Remove getHeader()/HeaderKey, inline CCC client calls at all call sites, replace addHeaders with headerDeps push
+- [x] 01-03-PLAN.md — Delete SmartTransaction + CapacityManager, update all method signatures to TransactionLike, clean SDK
### Phase 2: CCC Utility Adoption
**Goal**: Local utility functions that duplicate CCC core functionality are replaced with CCC equivalents across all packages; iCKB-unique utilities are explicitly preserved
@@ -138,7 +138,7 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
-| 1. SmartTransaction Removal (feature-slice) | 0/3 | Not started | - |
+| 1. SmartTransaction Removal (feature-slice) | 3/3 | Complete | 2026-02-22 |
| 2. CCC Utility Adoption | 0/2 | Not started | - |
| 3. CCC Udt Integration Investigation | 0/2 | Not started | - |
| 4. Deprecated CCC API Replacement | 0/2 | Not started | - |
diff --git a/.planning/STATE.md b/.planning/STATE.md
index caed793..c397361 100644
--- a/.planning/STATE.md
+++ b/.planning/STATE.md
@@ -9,29 +9,29 @@ See: .planning/PROJECT.md (updated 2026-02-20)
## Current Position
-Phase: 1 of 7 (SmartTransaction Removal — feature-slice)
-Plan: 0 of 3 in current phase
-Status: Context gathered, ready to plan
-Last activity: 2026-02-22 -- Phase 1 context gathered
+Phase: 1 of 7 (SmartTransaction Removal -- feature-slice)
+Plan: 3 of 3 in current phase (phase complete)
+Status: Phase 01 complete, ready for phase 02
+Last activity: 2026-02-22 -- Plan 01-03 executed (SmartTransaction/CapacityManager deletion)
-Progress: [░░░░░░░░░░] 0%
+Progress: [██░░░░░░░░] 15%
## Performance Metrics
**Velocity:**
-- Total plans completed: 0
-- Average duration: -
-- Total execution time: 0 hours
+- Total plans completed: 3
+- Average duration: ~17min
+- Total execution time: 0.9 hours
**By Phase:**
| Phase | Plans | Total | Avg/Plan |
|-------|-------|-------|----------|
-| - | - | - | - |
+| 01 | 3/3 | 52min | 17min |
**Recent Trend:**
-- Last 5 plans: -
-- Trend: -
+- Last 5 plans: 01-01 (~30min), 01-02 (~6min), 01-03 (~16min)
+- Trend: accelerating
*Updated after each plan completion*
@@ -42,12 +42,22 @@ Progress: [░░░░░░░░░░] 0%
Decisions are logged in PROJECT.md Key Decisions table.
Recent decisions affecting current work:
-- [Roadmap]: Phase 1 uses feature-slice approach — each removal chased across all packages, build stays green after every step. SMTX-01 (all signatures to TransactionLike) completed in Phase 1, not Phase 5.
+- [Roadmap]: Phase 1 uses feature-slice approach -- each removal chased across all packages, build stays green after every step. SMTX-01 (all signatures to TransactionLike) completed in Phase 1, not Phase 5.
- [Roadmap]: UDT investigation (Phase 3) is a design phase that produces a decision document; its outcome determines UdtHandler/UdtManager replacement pattern used in Phases 4-5
- [Roadmap]: Phases 4-5 reduced in scope: Phase 4 focuses on deprecated API replacement + UDT pattern finalization in dao/order; Phase 5 focuses on IckbUdt implementation + conservation law in core
- [Phase 1 Context]: DAO 64-output limit check contributed to CCC core via ccc-dev/, CCC PR submitted during Phase 1
-- [Phase 1 Context]: getHeader()/HeaderKey removed entirely — inline CCC client calls at read-only call sites; addHeaders() call sites in DaoManager/LogicManager push to tx.headerDeps directly
+- [Phase 1 Context]: getHeader()/HeaderKey removed entirely -- inline CCC client calls at read-only call sites; addHeaders() call sites in DaoManager/LogicManager push to tx.headerDeps directly
- [Phase 1 Context]: Script comparison must always use full Script.eq(), never just codeHash comparison
+- [01-01]: Added ccc-dev local patch mechanism (pins/local/*.patch) for deterministic replay of CCC modifications
+- [01-01]: DaoManager.requestWithdrawal/withdraw client parameter placed before optional options for cleaner API
+- [01-01]: assertDaoOutputLimit uses early return when outputs <= 64 for zero-cost common case
+- [01-02]: Moved getHeader/HeaderKey to transaction.ts as non-exported internals (SmartTransaction still uses internally until Plan 03 deletion)
+- [01-02]: TransactionHeader moved to utils.ts as canonical location for downstream consumers
+- [01-02]: Inlined CCC client calls use explicit null checks with descriptive error messages
+- [01-03]: All manager methods accept ccc.TransactionLike and return ccc.Transaction (TransactionLike pattern)
+- [01-03]: Replaced addUdtHandlers with tx.addCellDeps(this.udtHandler.cellDeps) across all packages
+- [01-03]: SmartTransaction class and CapacityManager class fully deleted from @ickb/utils
+- [01-03]: SDK getCkb() uses direct client.findCellsOnChain instead of CapacityManager
### Pending Todos
@@ -61,5 +71,5 @@ None yet.
## Session Continuity
Last session: 2026-02-22
-Stopped at: Phase 1 context gathered
-Resume file: .planning/phases/01-ickb-utils-smarttransaction-removal/01-CONTEXT.md
+Stopped at: Completed 01-03-PLAN.md (Phase 01 complete)
+Resume file: .planning/phases/01-ickb-utils-smarttransaction-removal/01-03-SUMMARY.md
diff --git a/.planning/phases/01-ickb-utils-smarttransaction-removal/01-01-PLAN.md b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-01-PLAN.md
new file mode 100644
index 0000000..6845796
--- /dev/null
+++ b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-01-PLAN.md
@@ -0,0 +1,264 @@
+---
+phase: 01-ickb-utils-smarttransaction-removal
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - ccc-dev/ccc/packages/core/src/ckb/transactionErrors.ts
+ - ccc-dev/ccc/packages/core/src/ckb/transaction.ts
+ - ccc-dev/ccc/packages/core/src/ckb/index.ts
+ - ccc-dev/pins/REFS
+ - ccc-dev/pins/HEAD
+ - packages/dao/src/dao.ts
+ - packages/core/src/logic.ts
+ - packages/core/src/owned_owner.ts
+ - packages/utils/src/transaction.ts
+autonomous: true
+requirements:
+ - SMTX-06
+
+must_haves:
+ truths:
+ - "A single CCC utility `assertDaoOutputLimit` exists in CCC core that checks both inputs and outputs for DAO type script when outputs > 64"
+ - "All 7 scattered inline DAO output checks across dao/core/utils are replaced with calls to `assertDaoOutputLimit`"
+ - "The `ErrorNervosDaoOutputLimit` error class exists in CCC `transactionErrors.ts` with count and limit fields"
+ - "`pnpm check:full` passes after DAO check consolidation"
+ artifacts:
+ - path: "ccc-dev/ccc/packages/core/src/ckb/transactionErrors.ts"
+ provides: "ErrorNervosDaoOutputLimit error class"
+ contains: "ErrorNervosDaoOutputLimit"
+ - path: "ccc-dev/ccc/packages/core/src/ckb/transaction.ts"
+ provides: "assertDaoOutputLimit utility function and completeFee safety net"
+ contains: "assertDaoOutputLimit"
+ key_links:
+ - from: "packages/dao/src/dao.ts"
+ to: "ccc-dev/ccc/packages/core/src/ckb/transaction.ts"
+ via: "import and call assertDaoOutputLimit"
+ pattern: "assertDaoOutputLimit"
+ - from: "packages/core/src/logic.ts"
+ to: "ccc-dev/ccc/packages/core/src/ckb/transaction.ts"
+ via: "import and call assertDaoOutputLimit"
+ pattern: "assertDaoOutputLimit"
+ - from: "packages/core/src/owned_owner.ts"
+ to: "ccc-dev/ccc/packages/core/src/ckb/transaction.ts"
+ via: "import and call assertDaoOutputLimit"
+ pattern: "assertDaoOutputLimit"
+---
+
+
+Build the 64-output NervosDAO limit check as a CCC core utility and replace all 7 scattered inline checks across the iCKB packages with calls to this centralized utility.
+
+Purpose: Consolidate duplicated DAO output limit logic into a single source of truth in CCC core, preparing for SmartTransaction deletion by removing one of its responsibilities. This is the first feature-slice step (purely additive, nothing breaks).
+
+Output: `ErrorNervosDaoOutputLimit` error class + `assertDaoOutputLimit` utility in CCC core; all iCKB packages calling the utility instead of inline checks; ccc-dev pins recorded.
+
+
+
+@/home/node/.claude/get-shit-done/workflows/execute-plan.md
+@/home/node/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+@.planning/phases/01-ickb-utils-smarttransaction-removal/01-CONTEXT.md
+@.planning/phases/01-ickb-utils-smarttransaction-removal/01-RESEARCH.md
+@.planning/codebase/ARCHITECTURE.md
+
+Key source files to read:
+@ccc-dev/ccc/packages/core/src/ckb/transactionErrors.ts (error class patterns)
+@ccc-dev/ccc/packages/core/src/ckb/transaction.ts (completeFee method, where safety net goes)
+@ccc-dev/ccc/packages/core/src/ckb/index.ts (barrel exports)
+@packages/utils/src/transaction.ts (SmartTransaction.completeFee with DAO check at lines 85-95)
+@packages/dao/src/dao.ts (DaoManager with 3 DAO checks at lines 100, 174, 245)
+@packages/core/src/logic.ts (LogicManager.deposit with DAO check at line 106)
+@packages/core/src/owned_owner.ts (OwnedOwnerManager with 2 DAO checks at lines 104, 146)
+
+
+
+
+
+ Task 1: Build ErrorNervosDaoOutputLimit and assertDaoOutputLimit in CCC core
+
+ ccc-dev/ccc/packages/core/src/ckb/transactionErrors.ts
+ ccc-dev/ccc/packages/core/src/ckb/transaction.ts
+ ccc-dev/ccc/packages/core/src/ckb/index.ts
+
+
+**Step 1: Add error class to transactionErrors.ts**
+
+Read `ccc-dev/ccc/packages/core/src/ckb/transactionErrors.ts`. Add `ErrorNervosDaoOutputLimit` following the existing `ErrorTransactionInsufficientCapacity` pattern:
+
+```typescript
+export class ErrorNervosDaoOutputLimit extends Error {
+ public readonly count: number;
+ public readonly limit: number;
+
+ constructor(count: number) {
+ super(
+ `NervosDAO transaction has ${count} output cells, exceeding the limit of 64`,
+ );
+ this.count = count;
+ this.limit = 64;
+ }
+}
+```
+
+**Step 2: Add assertDaoOutputLimit to transaction.ts**
+
+Read `ccc-dev/ccc/packages/core/src/ckb/transaction.ts`. Add the standalone utility function as a module-level export (NOT a method on Transaction). Place it after the Transaction class definition. Import `ErrorNervosDaoOutputLimit` from `./transactionErrors.js`, `KnownScript` from the appropriate module, and `Script` if not already imported:
+
+```typescript
+/**
+ * Asserts that a NervosDAO transaction does not exceed the 64-output limit.
+ * Auto-resolves unresolved inputs (populating CellInput.cellOutput as a side effect).
+ * Only checks when outputs > 64 AND at least one input or output has the DAO type script.
+ *
+ * @param tx - The transaction to check
+ * @param client - CKB client for resolving the NervosDAO script and input cell info
+ * @throws ErrorNervosDaoOutputLimit if limit exceeded
+ */
+export async function assertDaoOutputLimit(
+ tx: Transaction,
+ client: Client,
+): Promise {
+ if (tx.outputs.length <= 64) return;
+
+ const { codeHash, hashType } = await client.getKnownScript(
+ KnownScript.NervosDao,
+ );
+ const dao = Script.from({ codeHash, hashType, args: "0x" });
+
+ // Auto-resolve unresolved inputs
+ for (const input of tx.inputs) {
+ await input.completeExtraInfos(client);
+ }
+
+ const isDaoTx =
+ tx.inputs.some((i) => i.cellOutput?.type?.eq(dao)) ||
+ tx.outputs.some((o) => o.type?.eq(dao));
+
+ if (isDaoTx) {
+ throw new ErrorNervosDaoOutputLimit(tx.outputs.length);
+ }
+}
+```
+
+IMPORTANT: Use full `Script.eq()` comparison (codeHash + hashType + args), not just codeHash comparison.
+
+**Step 3: Add completeFee safety net**
+
+In the `completeFee` method of the Transaction class (around line 2183), add a call to `assertDaoOutputLimit(this, from.client)` near the end of the method, before returning. Read the method carefully to find the right insertion point -- it should be called after all outputs have been finalized but before the final return. The client is available as `from.client` (Signer has a `client` property).
+
+**Step 4: Export from barrel**
+
+Read `ccc-dev/ccc/packages/core/src/ckb/index.ts`. Add exports for `ErrorNervosDaoOutputLimit` (from `./transactionErrors.js`) and `assertDaoOutputLimit` (from `./transaction.js`). Follow existing export patterns in the file.
+
+**Step 5: Record ccc-dev pins**
+
+Run: `pnpm ccc:record`
+
+This updates `ccc-dev/pins/REFS` and `ccc-dev/pins/HEAD` to reflect the new CCC state.
+
+Verify: `pnpm ccc:status` should exit 0 (no pending work).
+
+
+1. `pnpm ccc:status` exits 0
+2. `grep -r "ErrorNervosDaoOutputLimit" ccc-dev/ccc/packages/core/src/ckb/transactionErrors.ts` finds the class
+3. `grep -r "assertDaoOutputLimit" ccc-dev/ccc/packages/core/src/ckb/transaction.ts` finds the function
+4. `pnpm check:full` passes (purely additive change, nothing should break)
+
+
+ErrorNervosDaoOutputLimit error class exists in CCC transactionErrors.ts with count and limit fields. assertDaoOutputLimit standalone utility exists in CCC transaction.ts using full Script.eq() comparison with args: "0x". completeFee has a safety net call to assertDaoOutputLimit. Both are exported from the CCC barrel. Pins are recorded.
+
+
+
+
+ Task 2: Replace all 7 scattered DAO checks with assertDaoOutputLimit calls
+
+ packages/dao/src/dao.ts
+ packages/core/src/logic.ts
+ packages/core/src/owned_owner.ts
+ packages/utils/src/transaction.ts
+
+
+Replace all 7 inline `if (tx.outputs.length > 64)` DAO checks with calls to `await assertDaoOutputLimit(tx, client)`. This requires making the containing methods async and adding a `client` parameter.
+
+**6 sync methods that need to become async with client parameter:**
+
+Read each file. For each method listed below:
+1. Add `client: ccc.Client` parameter (add as the LAST parameter, after any existing `options` parameter -- or as a required parameter before options if options is the last param)
+2. Change return type from `void` to `Promise` (method becomes async)
+3. Add `async` keyword to the method
+4. Replace the inline check with `await assertDaoOutputLimit(tx, client);`
+5. Import `assertDaoOutputLimit` from `@ckb-ccc/core` (or `ccc` namespace) at the top of each file
+
+**packages/dao/src/dao.ts** (3 checks):
+- `deposit()` at line 76 -- replace check at line 100-102 with `await assertDaoOutputLimit(tx, client);`
+- `requestWithdrawal()` at line 119 -- replace check at line 174-176 with `await assertDaoOutputLimit(tx, client);`
+- `withdraw()` at line 189 -- replace check at line 245-247 with `await assertDaoOutputLimit(tx, client);`
+
+Note: `requestWithdrawal` and `withdraw` ALREADY have `client` as a parameter (they call `getHeader`). `deposit` does NOT currently have `client` -- add it.
+
+**packages/core/src/logic.ts** (1 check):
+- `deposit()` at line 68 -- replace check at line 106-108 with `await assertDaoOutputLimit(tx, client);`
+
+Note: `deposit` does NOT currently have `client` -- add it. The method calls `this.daoManager.deposit()` which also needs client now. Since that call will need to be awaited after this change, the cascading async is intentional.
+
+**packages/core/src/owned_owner.ts** (2 checks):
+- `requestWithdrawal()` at line 69 -- replace check at line 104-106 with `await assertDaoOutputLimit(tx, client);`
+- `withdraw()` at line 118 -- replace check at line 146-148 with `await assertDaoOutputLimit(tx, client);`
+
+Note: Both methods DO NOT currently have `client` -- add it. The inner `this.daoManager.requestWithdrawal()` and `this.daoManager.withdraw()` calls already pass client (they need it for header fetching), so the `client` parameter is available up the call chain.
+
+**packages/utils/src/transaction.ts** (1 check):
+- `SmartTransaction.completeFee()` at line 63 -- replace the inline DAO check block (lines 82-95) with `await assertDaoOutputLimit(this, client);` where `client` is available as `from.client` (the Signer's client property, matching how it's done in the CCC completeFee safety net).
+
+Note: SmartTransaction's `completeFee` is already async and already has access to client via the Signer parameter. Just replace the inline check.
+
+**CRITICAL: Update all callers of the methods whose signatures changed.**
+
+After adding `client` parameter to methods, search for all call sites:
+- `this.daoManager.deposit(tx, ...)` in `packages/core/src/logic.ts` -- add `client` and `await`
+- `this.daoManager.requestWithdrawal(tx, ...)` in `packages/core/src/owned_owner.ts` -- already passes client, but now needs `await`
+- `this.daoManager.withdraw(tx, ...)` in `packages/core/src/owned_owner.ts` -- already passes client, but now needs `await`
+- Any other call sites in SDK or apps -- search for `.deposit(`, `.requestWithdrawal(`, `.withdraw(` across the entire `packages/` directory
+
+For every caller that invokes a now-async method, add `await`. If the caller itself is not async, make it async too (cascade).
+
+Remove the old inline checks entirely (the 3-line blocks with the error string "More than 64 output cells in a NervosDAO transaction").
+
+
+1. `grep -r "outputs.length > 64" packages/` returns NO results (all inline checks removed)
+2. `grep -r "assertDaoOutputLimit" packages/dao/src/dao.ts packages/core/src/logic.ts packages/core/src/owned_owner.ts packages/utils/src/transaction.ts` shows the utility is called in all 4 files
+3. `pnpm check:full` passes -- no type errors from async/await cascading or missing client parameters
+
+
+All 7 inline DAO output checks are removed. Every location now calls `await assertDaoOutputLimit(tx, client)`. All affected methods are async with the client parameter. All callers updated to await the now-async methods. `pnpm check:full` passes.
+
+
+
+
+
+
+1. `grep -rn "outputs.length > 64" packages/` -- should return 0 results
+2. `grep -rn "assertDaoOutputLimit" packages/ ccc-dev/ccc/packages/core/src/ckb/` -- should show usage in 4 iCKB files + definition in CCC
+3. `grep -rn "ErrorNervosDaoOutputLimit" ccc-dev/ccc/packages/core/src/ckb/` -- should show class definition + export
+4. `pnpm ccc:status` -- should exit 0
+5. `pnpm check:full` -- should pass clean
+
+
+
+- ErrorNervosDaoOutputLimit error class exists in CCC core with count/limit metadata
+- assertDaoOutputLimit utility exists in CCC core using full Script.eq() comparison
+- completeFee has DAO safety net
+- All 7 scattered inline checks replaced with centralized utility calls
+- No intermediate broken build state
+- ccc-dev pins recorded
+
+
+
diff --git a/.planning/phases/01-ickb-utils-smarttransaction-removal/01-01-SUMMARY.md b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-01-SUMMARY.md
new file mode 100644
index 0000000..634b3a9
--- /dev/null
+++ b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-01-SUMMARY.md
@@ -0,0 +1,130 @@
+---
+phase: 01-ickb-utils-smarttransaction-removal
+plan: 01
+subsystem: transaction
+tags: [nervos-dao, error-handling, ccc-core, assertDaoOutputLimit, async-refactor]
+
+# Dependency graph
+requires: []
+provides:
+ - ErrorNervosDaoOutputLimit error class in CCC core
+ - assertDaoOutputLimit centralized utility function in CCC core
+ - completeFee safety net for DAO output limit in CCC core
+ - ccc-dev local patch mechanism for deterministic builds
+affects: [01-02, 01-03, 01-04]
+
+# Tech tracking
+tech-stack:
+ added: []
+ patterns: [centralized-dao-limit-check, ccc-dev-local-patches]
+
+key-files:
+ created:
+ - ccc-dev/pins/local/001-dao-output-limit.patch
+ modified:
+ - ccc-dev/ccc/packages/core/src/ckb/transactionErrors.ts
+ - ccc-dev/ccc/packages/core/src/ckb/transaction.ts
+ - ccc-dev/record.sh
+ - ccc-dev/replay.sh
+ - packages/dao/src/dao.ts
+ - packages/core/src/logic.ts
+ - packages/core/src/owned_owner.ts
+ - packages/utils/src/transaction.ts
+
+key-decisions:
+ - "Added ccc-dev local patch mechanism (pins/local/*.patch) to support deterministic replay of CCC source modifications"
+ - "Moved client parameter before optional options in DaoManager.requestWithdrawal and DaoManager.withdraw signatures"
+ - "assertDaoOutputLimit uses early return when outputs <= 64 for zero-cost in common case"
+
+patterns-established:
+ - "Local CCC patches: place .patch files in ccc-dev/pins/local/ for changes applied after standard merge+patch cycle"
+ - "DAO output limit: always use ccc.assertDaoOutputLimit(tx, client) instead of inline checks"
+
+requirements-completed: [SMTX-06]
+
+# Metrics
+duration: 30min
+completed: 2026-02-22
+---
+
+# Phase 01 Plan 01: DAO Output Limit Check Summary
+
+**Centralized NervosDAO 64-output limit into CCC core assertDaoOutputLimit utility, replacing all 7 scattered inline checks across dao/core/utils packages**
+
+## Performance
+
+- **Duration:** ~30 min
+- **Started:** 2026-02-22T16:00:00Z
+- **Completed:** 2026-02-22T16:30:00Z
+- **Tasks:** 2
+- **Files modified:** 9
+
+## Accomplishments
+- Built ErrorNervosDaoOutputLimit error class with count/limit metadata in CCC core
+- Built assertDaoOutputLimit utility function that checks both inputs and outputs for DAO type script using full Script.eq() comparison
+- Added completeFee safety net in CCC Transaction class (both return paths)
+- Replaced all 7 inline DAO output checks across 4 files with centralized utility calls
+- Added local patch mechanism to ccc-dev record/replay for deterministic builds of CCC modifications
+
+## Task Commits
+
+Each task was committed atomically:
+
+1. **Task 1: Build ErrorNervosDaoOutputLimit and assertDaoOutputLimit in CCC core** - `7081869` (feat)
+2. **Task 2: Replace all 7 scattered DAO checks with assertDaoOutputLimit calls** - `2decd06` (refactor)
+
+## Files Created/Modified
+- `ccc-dev/ccc/packages/core/src/ckb/transactionErrors.ts` - ErrorNervosDaoOutputLimit error class
+- `ccc-dev/ccc/packages/core/src/ckb/transaction.ts` - assertDaoOutputLimit utility + completeFee safety net
+- `ccc-dev/pins/local/001-dao-output-limit.patch` - Local patch for deterministic replay
+- `ccc-dev/pins/HEAD` - Updated pinned HEAD SHA
+- `ccc-dev/record.sh` - Added local patch preservation and application
+- `ccc-dev/replay.sh` - Added local patch application after standard merge+patch
+- `packages/dao/src/dao.ts` - DaoManager.deposit/requestWithdrawal/withdraw now async with client param
+- `packages/core/src/logic.ts` - LogicManager.deposit now async with client param
+- `packages/core/src/owned_owner.ts` - OwnedOwnerManager.requestWithdrawal/withdraw now async with client param
+- `packages/utils/src/transaction.ts` - SmartTransaction.completeFee DAO check replaced
+
+## Decisions Made
+- Added ccc-dev local patch mechanism (pins/local/*.patch) because the existing record/replay infrastructure had no way to persist source-level CCC modifications through the clean/replay cycle. This was a necessary blocking-issue fix (Rule 3).
+- Placed `client: ccc.Client` parameter before optional `options` parameters in DaoManager signatures for cleaner API design (required params before optional).
+- assertDaoOutputLimit uses early return when `outputs.length <= 64` so the common-case path has zero async overhead.
+
+## Deviations from Plan
+
+### Auto-fixed Issues
+
+**1. [Rule 3 - Blocking] Added ccc-dev local patch mechanism**
+- **Found during:** Task 1 (CCC core changes)
+- **Issue:** ccc-dev record/replay infrastructure had no way to persist local CCC source modifications. Running `pnpm ccc:record` or `pnpm check:full` would wipe changes because replay clones fresh from upstream.
+- **Fix:** Added `pins/local/` directory for `.patch` files. Modified `record.sh` to preserve local patches during re-recording and apply them after standard merge+patch. Modified `replay.sh` to apply local patches after standard replay. Both use deterministic git identity/timestamps for reproducible HEAD SHAs.
+- **Files modified:** `ccc-dev/record.sh`, `ccc-dev/replay.sh`, `ccc-dev/pins/local/001-dao-output-limit.patch`
+- **Verification:** `pnpm check:full` passes (clean wipe + replay + build cycle)
+- **Committed in:** 7081869 (Task 1 commit)
+
+---
+
+**Total deviations:** 1 auto-fixed (1 blocking)
+**Impact on plan:** Essential infrastructure addition to make CCC modifications work through the deterministic build cycle. No scope creep.
+
+## Issues Encountered
+- Plan incorrectly stated that `requestWithdrawal` and `withdraw` in DaoManager already had `client` as a parameter. They did not. Added `client` parameter to both methods and updated all callers.
+
+## User Setup Required
+None - no external service configuration required.
+
+## Next Phase Readiness
+- assertDaoOutputLimit is available in CCC core for all packages
+- DAO output limit check is centralized, ready for SmartTransaction removal in subsequent plans
+- Local patch mechanism established for further CCC modifications if needed
+
+## Self-Check: PASSED
+
+- FOUND: ccc-dev/pins/local/001-dao-output-limit.patch
+- FOUND: 01-01-SUMMARY.md
+- FOUND: commit 7081869 (Task 1)
+- FOUND: commit 2decd06 (Task 2)
+
+---
+*Phase: 01-ickb-utils-smarttransaction-removal*
+*Completed: 2026-02-22*
diff --git a/.planning/phases/01-ickb-utils-smarttransaction-removal/01-02-PLAN.md b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-02-PLAN.md
new file mode 100644
index 0000000..6813a56
--- /dev/null
+++ b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-02-PLAN.md
@@ -0,0 +1,272 @@
+---
+phase: 01-ickb-utils-smarttransaction-removal
+plan: 02
+type: execute
+wave: 2
+depends_on:
+ - "01-01"
+files_modified:
+ - packages/utils/src/utils.ts
+ - packages/dao/src/cells.ts
+ - packages/dao/src/dao.ts
+ - packages/core/src/cells.ts
+ - packages/core/src/udt.ts
+ - packages/core/src/logic.ts
+ - packages/sdk/src/sdk.ts
+autonomous: true
+requirements:
+ - SMTX-04
+
+must_haves:
+ truths:
+ - "The standalone `getHeader()` function and `HeaderKey` type no longer exist in `@ickb/utils`"
+ - "All 5 standalone `getHeader()` call sites inline CCC client calls (`client.getTransactionWithHeader()` or `client.getHeaderByNumber()`) with null checks"
+ - "All 2 `tx.getHeader()` instance method call sites in `core/src/udt.ts` inline CCC client calls"
+ - "All 3 `tx.addHeaders()` call sites push to `tx.headerDeps` directly with dedup logic"
+ - "The `TransactionHeader` type is preserved in a surviving file for DaoCell and ReceiptCell to import"
+ - "`pnpm check:full` passes after getHeader removal"
+ artifacts:
+ - path: "packages/utils/src/utils.ts"
+ provides: "Utility functions WITHOUT getHeader/HeaderKey; WITH TransactionHeader type"
+ contains: "TransactionHeader"
+ - path: "packages/dao/src/cells.ts"
+ provides: "DaoCell construction with inlined CCC client calls for header fetching"
+ contains: "client.getHeaderByNumber"
+ - path: "packages/core/src/cells.ts"
+ provides: "ReceiptCell construction with inlined CCC client calls"
+ contains: "client.getTransactionWithHeader"
+ key_links:
+ - from: "packages/dao/src/cells.ts"
+ to: "CCC Client API"
+ via: "client.getTransactionWithHeader and client.getHeaderByNumber"
+ pattern: "client\\.get(TransactionWithHeader|HeaderByNumber)"
+ - from: "packages/core/src/udt.ts"
+ to: "CCC Client API"
+ via: "client.getTransactionWithHeader for header resolution"
+ pattern: "client\\.getTransactionWithHeader"
+ - from: "packages/dao/src/dao.ts"
+ to: "tx.headerDeps"
+ via: "direct push with dedup replacing addHeaders"
+ pattern: "headerDeps\\.push"
+---
+
+
+Remove the `getHeader()` function and `HeaderKey` type from `@ickb/utils`, inline CCC client calls at all 9+ call sites, replace `addHeaders()` with direct `tx.headerDeps` push, and preserve the `TransactionHeader` type for downstream consumers.
+
+Purpose: Eliminate SmartTransaction's header management infrastructure. CCC's built-in `ClientCacheMemory` LRU handles header caching transparently. This is Step 3 of the feature-slice execution order.
+
+Output: `getHeader`/`HeaderKey` deleted from utils.ts; all call sites use CCC client directly; `TransactionHeader` type moved to utils.ts; `addHeaders` replaced with headerDeps push.
+
+
+
+@/home/node/.claude/get-shit-done/workflows/execute-plan.md
+@/home/node/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+@.planning/phases/01-ickb-utils-smarttransaction-removal/01-CONTEXT.md
+@.planning/phases/01-ickb-utils-smarttransaction-removal/01-RESEARCH.md
+@.planning/phases/01-ickb-utils-smarttransaction-removal/01-01-SUMMARY.md
+
+Key source files to read:
+@packages/utils/src/utils.ts (getHeader function and HeaderKey type to remove)
+@packages/utils/src/transaction.ts (TransactionHeader type at line 506-517 to move; addHeaders instance method; getHeader instance method)
+@packages/dao/src/cells.ts (3 standalone getHeader call sites at lines 91, 97, 109)
+@packages/dao/src/dao.ts (2 addHeaders call sites at lines 160, 216)
+@packages/core/src/cells.ts (1 standalone getHeader call site at line 84)
+@packages/core/src/udt.ts (2 tx.getHeader instance method call sites at lines 108, 125)
+@packages/core/src/logic.ts (1 addHeaders call site at line 125)
+@packages/sdk/src/sdk.ts (1 standalone getHeader call site at line 388)
+
+
+
+
+
+ Task 1: Move TransactionHeader type and inline all getHeader/addHeaders call sites
+
+ packages/utils/src/utils.ts
+ packages/utils/src/transaction.ts
+ packages/dao/src/cells.ts
+ packages/dao/src/dao.ts
+ packages/core/src/cells.ts
+ packages/core/src/udt.ts
+ packages/core/src/logic.ts
+ packages/sdk/src/sdk.ts
+
+
+**Step 1: Move TransactionHeader type to utils.ts**
+
+Read `packages/utils/src/transaction.ts`. Find the `TransactionHeader` interface (around line 506-517). It looks approximately like:
+```typescript
+interface TransactionHeader {
+ header: ccc.ClientBlockHeader;
+ txHash?: ccc.Hex;
+}
+```
+
+Read `packages/utils/src/utils.ts`. Add the `TransactionHeader` interface definition there (export it). This type is needed by `@ickb/dao` (DaoCell.headers) and `@ickb/core` (ReceiptCell.header).
+
+Also ensure `TransactionHeader` is exported from `packages/utils/src/index.ts` (it may already be re-exported from `transaction.ts` -- it will need to come from `utils.ts` after transaction.ts is deleted in Plan 03).
+
+**Step 2: Inline standalone getHeader() call sites (5 sites)**
+
+For each call site, replace `getHeader(client, { type, value })` with direct CCC client calls. Always include null check + throw.
+
+**packages/dao/src/cells.ts line 91** (number lookup):
+```typescript
+// Before:
+const header = await getHeader(client, { type: "number", value: mol.Uint64LE.decode(cell.outputData) });
+// After:
+const header = await client.getHeaderByNumber(mol.Uint64LE.decode(cell.outputData));
+if (!header) {
+ throw new Error("Header not found for block number");
+}
+```
+
+**packages/dao/src/cells.ts line 97** (txHash lookup):
+```typescript
+// Before:
+const header = await getHeader(client, { type: "txHash", value: txHash });
+// After:
+const txWithHeader = await client.getTransactionWithHeader(txHash);
+if (!txWithHeader?.header) {
+ throw new Error("Header not found for txHash");
+}
+const header = txWithHeader.header;
+```
+
+**packages/dao/src/cells.ts line 109** (txHash lookup):
+Same pattern as line 97.
+
+**packages/core/src/cells.ts line 84** (txHash lookup):
+Same pattern as above. Read the actual code to see the exact variable names and context.
+
+**packages/sdk/src/sdk.ts line 388** (txHash lookup):
+Same pattern. Read the actual code to determine what `txHash` variable is used (likely `c.cell.outPoint.txHash`).
+
+Remove the `import { getHeader }` from each file after all call sites are updated.
+
+**Step 3: Inline tx.getHeader() instance method call sites (2 sites in core/src/udt.ts)**
+
+Read `packages/core/src/udt.ts`. At lines 108 and 125, `tx.getHeader()` is called (SmartTransaction instance method). Replace with CCC client calls:
+
+```typescript
+// Before:
+const header = await tx.getHeader(client, { type: "txHash", value: outPoint.txHash });
+// After:
+const txWithHeader = await client.getTransactionWithHeader(outPoint.txHash);
+if (!txWithHeader?.header) {
+ throw new Error("Header not found for txHash");
+}
+const header = txWithHeader.header;
+```
+
+These methods already have `client` as a parameter, so no signature change is needed.
+
+**Step 4: Replace addHeaders() call sites (3 sites) with direct headerDeps push**
+
+Read each file. Replace `tx.addHeaders(...)` with direct push to `tx.headerDeps` with dedup.
+
+**packages/dao/src/dao.ts line 160** (single TransactionHeader):
+```typescript
+// Before:
+tx.addHeaders(depositHeader);
+// After:
+const hash = depositHeader.header.hash;
+if (!tx.headerDeps.some((h) => h === hash)) {
+ tx.headerDeps.push(hash);
+}
+```
+
+**packages/dao/src/dao.ts line 216** (array of headers from DaoCell):
+```typescript
+// Before:
+tx.addHeaders(...withdrawalRequests.flatMap(d => d.headers));
+// OR similar pattern
+// After:
+for (const wr of withdrawalRequests) {
+ for (const th of wr.headers) {
+ const hash = th.header.hash;
+ if (!tx.headerDeps.some((h) => h === hash)) {
+ tx.headerDeps.push(hash);
+ }
+ }
+}
+```
+Read the actual code carefully to determine the exact structure of the addHeaders call.
+
+**packages/core/src/logic.ts line 125** (receipt headers):
+```typescript
+// Before:
+tx.addHeaders(...receipts.map(r => r.header));
+// OR similar
+// After:
+for (const r of receipts) {
+ const hash = r.header.header.hash;
+ if (!tx.headerDeps.some((h) => h === hash)) {
+ tx.headerDeps.push(hash);
+ }
+}
+```
+Read the actual code to see the exact shape.
+
+**Step 5: Remove getHeader function and HeaderKey type from utils.ts**
+
+Read `packages/utils/src/utils.ts`. Find and delete the `getHeader` function definition and the `HeaderKey` type definition. Remove any imports that were only used by `getHeader`.
+
+Also update `packages/utils/src/index.ts` to remove any re-export of `getHeader` or `HeaderKey` if they are exported there.
+
+**Step 6: Update imports across all modified files**
+
+- Remove `getHeader` and `HeaderKey` imports from all consumer files
+- Add `TransactionHeader` import from `@ickb/utils` (the new location) in files that previously imported it from `transaction.ts` or `@ickb/utils` (it should already resolve correctly if the barrel export is set up)
+- Ensure no circular imports are created
+
+**IMPORTANT NOTES:**
+- Do NOT delete `transaction.ts` in this plan -- that happens in Plan 03
+- Do NOT change method signatures from SmartTransaction to TransactionLike -- that happens in Plan 03
+- The `addHeaders` and `getHeader` instance methods on SmartTransaction class itself will be cleaned up when the class is deleted in Plan 03
+- Preserve exact error semantics: the original `getHeader` threw on null results; the inlined code must also throw
+
+
+1. `grep -rn "getHeader" packages/utils/src/utils.ts` -- should NOT find the function definition or HeaderKey type
+2. `grep -rn "from.*getHeader\|getHeader(" packages/dao/ packages/core/ packages/sdk/` -- should NOT find standalone getHeader calls (instance method calls on SmartTransaction may still exist in transaction.ts itself, which is fine -- deleted in Plan 03)
+3. `grep -rn "addHeaders" packages/dao/ packages/core/` -- should NOT find any addHeaders calls
+4. `grep -rn "headerDeps.push" packages/dao/ packages/core/` -- should find the new direct push calls
+5. `grep -rn "TransactionHeader" packages/utils/src/utils.ts` -- should find the type definition
+6. `pnpm check:full` passes
+
+
+`getHeader()` function and `HeaderKey` type are deleted from `@ickb/utils`. All 5 standalone `getHeader()` call sites use direct CCC client calls with null checks. All 2 `tx.getHeader()` instance method call sites in core/udt.ts use CCC client calls. All 3 `addHeaders()` call sites push to `tx.headerDeps` directly with dedup. `TransactionHeader` type is preserved in utils.ts and exported. `pnpm check:full` passes.
+
+
+
+
+
+
+1. `grep -rn "getHeader\b" packages/utils/src/utils.ts` -- no function definition
+2. `grep -rn "HeaderKey" packages/` -- no results (type fully removed)
+3. `grep -rn "addHeaders" packages/dao/ packages/core/` -- no results
+4. `grep -rn "client\.getTransactionWithHeader\|client\.getHeaderByNumber" packages/dao/ packages/core/ packages/sdk/` -- shows inlined calls
+5. `grep -rn "headerDeps\.push" packages/dao/ packages/core/` -- shows direct push with dedup
+6. `grep -rn "TransactionHeader" packages/utils/src/utils.ts` -- type preserved
+7. `pnpm check:full` -- passes clean
+
+
+
+- getHeader() function deleted from @ickb/utils
+- HeaderKey type deleted from @ickb/utils
+- TransactionHeader type preserved and accessible from @ickb/utils
+- All standalone getHeader call sites inline CCC client calls with proper null checks
+- All tx.getHeader instance method call sites in core/udt.ts inline CCC client calls
+- All addHeaders call sites push to tx.headerDeps with dedup
+- CCC ClientCacheMemory handles header caching (no custom cache)
+- Build stays green
+
+
+
diff --git a/.planning/phases/01-ickb-utils-smarttransaction-removal/01-02-SUMMARY.md b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-02-SUMMARY.md
new file mode 100644
index 0000000..abc27f5
--- /dev/null
+++ b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-02-SUMMARY.md
@@ -0,0 +1,128 @@
+---
+phase: 01-ickb-utils-smarttransaction-removal
+plan: 02
+subsystem: transaction
+tags: [getHeader, HeaderKey, addHeaders, CCC-client, header-management, inline-refactor]
+
+# Dependency graph
+requires:
+ - phase: 01-01
+ provides: assertDaoOutputLimit centralized in CCC core; DaoManager/LogicManager async signatures with client parameter
+provides:
+ - TransactionHeader type in utils.ts (moved from transaction.ts)
+ - All consumer packages use direct CCC client calls for header fetching
+ - All consumer packages use direct tx.headerDeps push with dedup for header deps
+ - getHeader/HeaderKey removed from @ickb/utils public API
+affects: [01-03]
+
+# Tech tracking
+tech-stack:
+ added: []
+ patterns: [inline-ccc-client-calls, direct-headerDeps-push-with-dedup]
+
+key-files:
+ created: []
+ modified:
+ - packages/utils/src/utils.ts
+ - packages/utils/src/transaction.ts
+ - packages/dao/src/cells.ts
+ - packages/dao/src/dao.ts
+ - packages/core/src/cells.ts
+ - packages/core/src/udt.ts
+ - packages/core/src/logic.ts
+ - packages/sdk/src/sdk.ts
+
+key-decisions:
+ - "Moved getHeader/HeaderKey to transaction.ts as non-exported internals rather than deleting entirely, since SmartTransaction class still uses them internally until Plan 03 deletion"
+ - "TransactionHeader moved to utils.ts as canonical location, imported by transaction.ts"
+ - "Inlined CCC client calls use explicit null checks with descriptive error messages matching original getHeader throw semantics"
+
+patterns-established:
+ - "Header fetching: use client.getTransactionWithHeader() or client.getHeaderByNumber() directly with null check + throw"
+ - "Header deps: push hash to tx.headerDeps with dedup via .some() check, no SmartTransaction wrapper"
+
+requirements-completed: [SMTX-04]
+
+# Metrics
+duration: 6min
+completed: 2026-02-22
+---
+
+# Phase 01 Plan 02: getHeader/addHeaders Removal Summary
+
+**Removed getHeader()/HeaderKey from @ickb/utils public API, inlined 10 call sites with direct CCC client calls, replaced addHeaders with headerDeps push**
+
+## Performance
+
+- **Duration:** 6 min
+- **Started:** 2026-02-22T16:23:02Z
+- **Completed:** 2026-02-22T16:29:31Z
+- **Tasks:** 1
+- **Files modified:** 8
+
+## Accomplishments
+- Removed getHeader() function and HeaderKey type from @ickb/utils public API
+- Inlined 5 standalone getHeader() call sites in dao/cells.ts, core/cells.ts, and sdk/sdk.ts with direct CCC client calls (getTransactionWithHeader/getHeaderByNumber) with null checks
+- Inlined 2 tx.getHeader() instance method call sites in core/udt.ts with direct CCC client calls
+- Replaced 3 addHeaders() call sites in dao/dao.ts and core/logic.ts with direct tx.headerDeps push with dedup logic
+- Moved TransactionHeader interface from transaction.ts to utils.ts as canonical export location
+
+## Task Commits
+
+Each task was committed atomically:
+
+1. **Task 1: Move TransactionHeader type and inline all getHeader/addHeaders call sites** - `85ead3a` (refactor)
+
+## Files Created/Modified
+- `packages/utils/src/utils.ts` - Added TransactionHeader interface; removed getHeader function and HeaderKey type
+- `packages/utils/src/transaction.ts` - Moved getHeader/HeaderKey to non-exported internals; imports TransactionHeader from utils.ts
+- `packages/dao/src/cells.ts` - Inlined 3 getHeader calls with client.getHeaderByNumber and client.getTransactionWithHeader
+- `packages/dao/src/dao.ts` - Replaced 2 addHeaders calls with direct tx.headerDeps push with dedup
+- `packages/core/src/cells.ts` - Inlined 1 getHeader call with client.getTransactionWithHeader
+- `packages/core/src/udt.ts` - Inlined 2 tx.getHeader calls with client.getTransactionWithHeader
+- `packages/core/src/logic.ts` - Replaced 1 addHeaders call with direct tx.headerDeps push with dedup
+- `packages/sdk/src/sdk.ts` - Inlined 1 getHeader call with client.getTransactionWithHeader
+
+## Decisions Made
+- Moved getHeader/HeaderKey into transaction.ts as non-exported internals rather than deleting entirely. SmartTransaction's own instance methods (getHeader, encodeHeaderKey, addHeaders) still reference these internally. Deleting them would break SmartTransaction, which is not removed until Plan 03. This keeps the public API clean while maintaining internal consistency.
+- TransactionHeader placed in utils.ts as the canonical location since it outlives SmartTransaction (used by DaoCell.headers and ReceiptCell.header).
+- Inlined CCC client calls preserve the original error semantics: getHeader always threw on null results, and the inlined code also throws with descriptive messages.
+
+## Deviations from Plan
+
+### Auto-fixed Issues
+
+**1. [Rule 3 - Blocking] Retained getHeader/HeaderKey as non-exported internals in transaction.ts**
+- **Found during:** Task 1 (Step 5 - removing getHeader from utils.ts)
+- **Issue:** SmartTransaction class in transaction.ts imports and uses the standalone getHeader function and HeaderKey type internally. Removing them from utils.ts without providing them in transaction.ts would break the class.
+- **Fix:** Moved getHeader function and HeaderKey type into transaction.ts as non-exported (internal) declarations. They are no longer part of the @ickb/utils public API but remain available for SmartTransaction's internal use until Plan 03 deletes the class.
+- **Files modified:** packages/utils/src/transaction.ts
+- **Verification:** pnpm check:full passes; HeaderKey/getHeader not found in any consumer packages
+- **Committed in:** 85ead3a (Task 1 commit)
+
+---
+
+**Total deviations:** 1 auto-fixed (1 blocking)
+**Impact on plan:** Necessary to keep SmartTransaction functional until Plan 03 removes it. No scope creep.
+
+## Issues Encountered
+None - plan executed smoothly once the internal SmartTransaction dependency was handled.
+
+## User Setup Required
+None - no external service configuration required.
+
+## Next Phase Readiness
+- All getHeader/HeaderKey usage removed from public API and consumer packages
+- TransactionHeader type available in utils.ts for downstream use
+- SmartTransaction class ready for deletion in Plan 03 (all external dependencies on its header methods removed)
+- Build stays green
+
+## Self-Check: PASSED
+
+- FOUND: all 8 modified files exist
+- FOUND: 01-02-SUMMARY.md
+- FOUND: commit 85ead3a (Task 1)
+
+---
+*Phase: 01-ickb-utils-smarttransaction-removal*
+*Completed: 2026-02-22*
diff --git a/.planning/phases/01-ickb-utils-smarttransaction-removal/01-03-PLAN.md b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-03-PLAN.md
new file mode 100644
index 0000000..e10b792
--- /dev/null
+++ b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-03-PLAN.md
@@ -0,0 +1,328 @@
+---
+phase: 01-ickb-utils-smarttransaction-removal
+plan: 03
+type: execute
+wave: 3
+depends_on:
+ - "01-02"
+files_modified:
+ - packages/utils/src/transaction.ts
+ - packages/utils/src/capacity.ts
+ - packages/utils/src/udt.ts
+ - packages/utils/src/index.ts
+ - packages/dao/src/dao.ts
+ - packages/core/src/logic.ts
+ - packages/core/src/owned_owner.ts
+ - packages/core/src/udt.ts
+ - packages/order/src/order.ts
+ - packages/sdk/src/sdk.ts
+ - packages/sdk/src/constants.ts
+autonomous: true
+requirements:
+ - SMTX-01
+ - SMTX-02
+
+must_haves:
+ truths:
+ - "SmartTransaction class no longer exists in `@ickb/utils` source or exports"
+ - "CapacityManager class no longer exists in `@ickb/utils` source or exports"
+ - "All manager method signatures across ALL 5 library packages accept `ccc.TransactionLike` instead of `SmartTransaction`"
+ - "All updated methods return `ccc.Transaction` (not void) following CCC convention"
+ - "Each method converts TransactionLike to Transaction internally with `ccc.Transaction.from(txLike)`"
+ - "UdtHandler interface and UdtManager class remain with updated signatures"
+ - "All `addUdtHandlers()` calls are replaced with `tx.addCellDeps(this.udtHandler.cellDeps)`"
+ - "`transaction.ts` and `capacity.ts` files are deleted from @ickb/utils"
+ - "`pnpm check:full` passes after full removal"
+ artifacts:
+ - path: "packages/utils/src/udt.ts"
+ provides: "UdtHandler interface and UdtManager class with TransactionLike signatures"
+ contains: "TransactionLike"
+ - path: "packages/utils/src/index.ts"
+ provides: "Barrel exports WITHOUT transaction.ts or capacity.ts"
+ key_links:
+ - from: "packages/dao/src/dao.ts"
+ to: "ccc.Transaction.from()"
+ via: "TransactionLike input conversion at method entry"
+ pattern: "Transaction\\.from\\(txLike\\)"
+ - from: "packages/order/src/order.ts"
+ to: "ccc.Transaction.from()"
+ via: "TransactionLike input conversion at method entry"
+ pattern: "Transaction\\.from\\(txLike\\)"
+ - from: "packages/sdk/src/sdk.ts"
+ to: "CCC client.findCellsOnChain"
+ via: "CapacityManager replacement"
+ pattern: "findCellsOnChain"
+---
+
+
+Delete SmartTransaction class and CapacityManager class from `@ickb/utils`; update all manager method signatures across all 5 library packages from `SmartTransaction` to `ccc.TransactionLike`; replace `addUdtHandlers()` calls; update SDK to use CCC native cell finding.
+
+Purpose: Complete the SmartTransaction removal by deleting the class and its infrastructure after all dependencies have been resolved (DAO checks consolidated in Plan 01, header management inlined in Plan 02). This is Steps 4-5 of the feature-slice execution order.
+
+Output: `transaction.ts` and `capacity.ts` deleted; all method signatures accept `ccc.TransactionLike` and return `ccc.Transaction`; SDK uses CCC native cell finding; barrel exports cleaned.
+
+
+
+@/home/node/.claude/get-shit-done/workflows/execute-plan.md
+@/home/node/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+@.planning/phases/01-ickb-utils-smarttransaction-removal/01-CONTEXT.md
+@.planning/phases/01-ickb-utils-smarttransaction-removal/01-RESEARCH.md
+@.planning/phases/01-ickb-utils-smarttransaction-removal/01-01-SUMMARY.md
+@.planning/phases/01-ickb-utils-smarttransaction-removal/01-02-SUMMARY.md
+
+Key source files to read:
+@packages/utils/src/transaction.ts (SmartTransaction class -- TO DELETE)
+@packages/utils/src/capacity.ts (CapacityManager class -- TO DELETE)
+@packages/utils/src/udt.ts (UdtHandler/UdtManager -- update signatures, keep)
+@packages/utils/src/index.ts (barrel exports -- remove transaction.ts and capacity.ts)
+@packages/dao/src/dao.ts (DaoManager methods -- update signatures)
+@packages/core/src/logic.ts (LogicManager methods -- update signatures)
+@packages/core/src/owned_owner.ts (OwnedOwnerManager methods -- update signatures)
+@packages/core/src/udt.ts (IckbUdtManager -- update signatures)
+@packages/order/src/order.ts (OrderManager methods -- update signatures)
+@packages/sdk/src/sdk.ts (IckbSdk methods -- update signatures, replace CapacityManager)
+@packages/sdk/src/constants.ts (getConfig -- remove CapacityManager)
+
+
+
+
+
+ Task 1: Update all method signatures to TransactionLike and replace addUdtHandlers
+
+ packages/utils/src/udt.ts
+ packages/dao/src/dao.ts
+ packages/core/src/logic.ts
+ packages/core/src/owned_owner.ts
+ packages/core/src/udt.ts
+ packages/order/src/order.ts
+ packages/sdk/src/sdk.ts
+
+
+For every method across all 5 library packages that currently accepts `SmartTransaction`, apply the CCC convention:
+1. Change parameter type from `SmartTransaction` (or `tx: SmartTransaction`) to `txLike: ccc.TransactionLike`
+2. Add `const tx = ccc.Transaction.from(txLike);` as the FIRST line of the method body
+3. Change return type from `void` to `ccc.Transaction` (for sync methods) or from `Promise` to `Promise` (for async methods, made async in Plan 01)
+4. Add `return tx;` at the end of each method body
+5. Replace `import { SmartTransaction }` with appropriate CCC imports (`ccc.TransactionLike`, `ccc.Transaction`)
+
+**packages/utils/src/udt.ts** -- UdtHandler interface + UdtManager class:
+Read the file. Update ALL method signatures that accept `SmartTransaction`:
+- `UdtHandler` interface methods (if any accept SmartTransaction)
+- `UdtManager` methods: look for methods like `getInputsUdtBalance`, `getOutputsUdtBalance`, `addUdtChange`, etc.
+- For `UdtManager` methods that mutate a transaction: accept `txLike: ccc.TransactionLike`, convert with `Transaction.from()`, return `ccc.Transaction`
+- **Replace `addUdtHandlers` call in UdtManager** (line ~282): replace `tx.addUdtHandlers(this)` with `tx.addCellDeps(this.cellDeps)`. The handler registration was SmartTransaction-specific; only the cellDeps part survives.
+
+**packages/dao/src/dao.ts** -- DaoManager:
+- `deposit(tx: SmartTransaction, ...)` -> `deposit(txLike: ccc.TransactionLike, ...): Promise` (already made async in Plan 01)
+- `requestWithdrawal(tx: SmartTransaction, ...)` -> `requestWithdrawal(txLike: ccc.TransactionLike, ...): Promise`
+- `withdraw(tx: SmartTransaction, ...)` -> `withdraw(txLike: ccc.TransactionLike, ...): Promise`
+- Remove `SmartTransaction` import. Add `ccc.TransactionLike` and `ccc.Transaction` imports.
+
+**packages/core/src/logic.ts** -- LogicManager:
+- `deposit(tx: SmartTransaction, ...)` -> `deposit(txLike: ccc.TransactionLike, ...): Promise`
+- `completeDeposit(tx: SmartTransaction, ...)` -> `completeDeposit(txLike: ccc.TransactionLike, ...): ccc.Transaction` (or Promise if made async)
+- Inner calls to `this.daoManager.deposit(tx, ...)` must pass `tx` (the converted Transaction, NOT txLike) and capture the return: `tx = await this.daoManager.deposit(tx, ...);`
+- **Replace `addUdtHandlers` calls** (lines ~87, ~123): replace `tx.addUdtHandlers(this.udtHandler)` with `tx.addCellDeps(this.udtHandler.cellDeps)`
+
+**packages/core/src/owned_owner.ts** -- OwnedOwnerManager:
+- `requestWithdrawal(tx: SmartTransaction, ...)` -> `requestWithdrawal(txLike: ccc.TransactionLike, ...): Promise`
+- `withdraw(tx: SmartTransaction, ...)` -> `withdraw(txLike: ccc.TransactionLike, ...): Promise`
+- Inner calls to `this.daoManager.*` must capture returned tx
+- **Replace `addUdtHandlers` calls** (lines ~88, ~135): replace `tx.addUdtHandlers(this.udtHandler)` with `tx.addCellDeps(this.udtHandler.cellDeps)`
+
+**packages/core/src/udt.ts** -- IckbUdtManager:
+- `getInputsUdtBalance(client, tx: SmartTransaction)` -> `getInputsUdtBalance(client, txLike: ccc.TransactionLike): Promise<...>`
+- Any other methods accepting SmartTransaction
+- Convert with `Transaction.from()` at entry
+
+**packages/order/src/order.ts** -- OrderManager:
+- `mint(tx: SmartTransaction, ...)` -> `mint(txLike: ccc.TransactionLike, ...): ccc.Transaction`
+- `addMatch(tx: SmartTransaction, ...)` -> `addMatch(txLike: ccc.TransactionLike, ...): ccc.Transaction` (or similar name)
+- `melt(tx: SmartTransaction, ...)` -> `melt(txLike: ccc.TransactionLike, ...): ccc.Transaction`
+- All other methods accepting SmartTransaction
+- **Replace `addUdtHandlers` calls** (lines ~191, ~228, ~516): replace with `tx.addCellDeps(this.udtHandler.cellDeps)`
+
+**packages/sdk/src/sdk.ts** -- IckbSdk:
+- `request(tx: SmartTransaction, ...)` -> `request(txLike: ccc.TransactionLike, ...): ccc.Transaction`
+- `collect(tx: SmartTransaction, ...)` -> `collect(txLike: ccc.TransactionLike, ...): ccc.Transaction`
+- Any other methods accepting SmartTransaction
+- Inner calls to manager methods must capture returned tx
+
+**CRITICAL PATTERN for cascading returns:**
+
+When a method calls another method that now returns `ccc.Transaction`:
+```typescript
+// Before (void return, mutating tx in-place):
+this.daoManager.deposit(tx, capacities, this.script);
+
+// After (Transaction return, must capture):
+tx = await this.daoManager.deposit(tx, capacities, this.script, client);
+```
+
+The `Transaction.from()` at the callee entry point creates a new Transaction. The callee mutates and returns it. The caller must use the returned value for subsequent operations.
+
+**addUdtHandlers replacement analysis:**
+
+Per RESEARCH.md, all 8 `addUdtHandlers` call sites have a preceding `tx.addCellDeps(this.cellDeps)` call. The `addUdtHandlers` internally does: (1) register handler in `udtHandlers` Map (SmartTransaction-specific, lost), (2) call `addCellDeps(udtHandler.cellDeps)`. Replace each `tx.addUdtHandlers(this.udtHandler)` with `tx.addCellDeps(this.udtHandler.cellDeps)`. CCC's `addCellDeps` deduplicates, so this is safe even though `this.cellDeps` was just added on the preceding line.
+
+
+1. `grep -rn "SmartTransaction" packages/dao/ packages/core/ packages/order/ packages/sdk/ packages/utils/src/udt.ts` -- should return NO results (no SmartTransaction type references)
+2. `grep -rn "addUdtHandlers" packages/` -- should return NO results
+3. `grep -rn "TransactionLike" packages/dao/ packages/core/ packages/order/ packages/sdk/ packages/utils/src/udt.ts` -- should show TransactionLike in method signatures
+4. `grep -rn "Transaction\.from(txLike)" packages/` -- should show conversion at method entry points
+5. `pnpm check:full` passes (SmartTransaction class still exists at this point, but nobody imports it)
+
+
+All manager method signatures across all 5 library packages accept `ccc.TransactionLike` and return `ccc.Transaction`. Each method converts with `Transaction.from(txLike)` at entry. All 8 `addUdtHandlers()` calls replaced with `tx.addCellDeps(this.udtHandler.cellDeps)`. No file imports SmartTransaction. UdtHandler/UdtManager preserved with updated signatures.
+
+
+
+
+ Task 2: Delete SmartTransaction and CapacityManager, clean exports, update SDK
+
+ packages/utils/src/transaction.ts
+ packages/utils/src/capacity.ts
+ packages/utils/src/index.ts
+ packages/sdk/src/sdk.ts
+ packages/sdk/src/constants.ts
+
+
+**Step 1: Replace CapacityManager usage in SDK**
+
+Read `packages/sdk/src/sdk.ts`. Find the `findCapacities` usage (around line 376). The current pattern is:
+```typescript
+for await (const c of this.capacity.findCapacities(client, this.bots, opts)) {
+ // ...
+}
+```
+
+Replace with CCC's native cell finding. Per RESEARCH.md:
+```typescript
+for (const lock of unique(this.bots)) {
+ for await (const cell of client.findCellsOnChain(
+ {
+ script: lock,
+ scriptType: "lock",
+ filter: {
+ scriptLenRange: [0n, 1n],
+ },
+ scriptSearchMode: "exact",
+ withData: true,
+ },
+ "asc",
+ 400,
+ )) {
+ if (cell.cellOutput.type !== undefined || !cell.cellOutput.lock.eq(lock)) {
+ continue;
+ }
+ // ... rest of existing logic
+ }
+}
+```
+
+Read the existing code carefully to understand exactly what `findCapacities` does and replicate the filtering behavior. The key filter is: cells with no type script (plain CKB capacity cells), matching the lock script exactly.
+
+Also read `packages/sdk/src/constants.ts`. Find the `CapacityManager` usage (likely `CapacityManager.withAnyData()` in `getConfig`). Remove:
+1. The `CapacityManager` import
+2. The `CapacityManager.withAnyData()` call or instantiation
+3. The `capacity` field from the return type (if it's part of a config object)
+
+Update `IckbSdk` constructor or `from()` factory to no longer accept/store a `CapacityManager` instance. Remove the `this.capacity` field.
+
+**Step 2: Delete transaction.ts**
+
+Delete the file: `packages/utils/src/transaction.ts`
+
+This file contains SmartTransaction class (~517 lines). After Plan 01 (DAO checks removed from completeFee) and Plan 02 (getHeader/addHeaders/TransactionHeader moved), and Task 1 of this plan (all consumers updated), nothing should import from this file.
+
+IMPORTANT: Verify that `TransactionHeader` was already moved to `utils.ts` in Plan 02. If not, ensure it's moved before deletion.
+
+**Step 3: Delete capacity.ts**
+
+Delete the file: `packages/utils/src/capacity.ts`
+
+This file contains CapacityManager class (~221 lines). After Step 1 replaced SDK usage, nothing should import from this file.
+
+**Step 4: Clean barrel exports in index.ts**
+
+Read `packages/utils/src/index.ts`. Remove:
+- `export * from "./transaction.js";` (or similar barrel export for transaction.ts)
+- `export * from "./capacity.js";` (or similar barrel export for capacity.ts)
+
+Keep:
+- `export * from "./utils.js";` (has TransactionHeader now)
+- `export * from "./udt.js";` (UdtHandler/UdtManager with updated signatures)
+- `export * from "./codec.js";`
+- `export * from "./heap.js";`
+
+**Step 5: Remove all SmartTransaction imports from remaining files**
+
+Search the entire `packages/` and `apps/` directories for any remaining `SmartTransaction` imports or references:
+```
+grep -rn "SmartTransaction" packages/ apps/
+```
+
+If any remain (e.g., in `apps/faucet/src/main.ts` which uses SmartTransaction), update those too:
+- Replace `new SmartTransaction()` with `ccc.Transaction.default()` or `new ccc.Transaction()`
+- Replace `SmartTransaction.from(...)` with `ccc.Transaction.from(...)`
+- Update any `completeFeeChangeToLock` calls to use `ccc.Transaction.completeFeeChangeToLock()`
+- Remove `SmartTransaction` imports
+
+**Step 6: Final build verification**
+
+Run `pnpm check:full` to verify the entire build is green. This validates:
+- No broken imports (transaction.ts and capacity.ts deleted cleanly)
+- No type errors from signature changes
+- All packages compile under strict TypeScript settings
+
+**Clean delete rules from CONTEXT.md:**
+- No deprecation stubs, no migration comments, no breadcrumbs
+- File deletions + barrel export removal in the same commit (atomic)
+
+
+1. `ls packages/utils/src/transaction.ts 2>/dev/null` -- file should NOT exist
+2. `ls packages/utils/src/capacity.ts 2>/dev/null` -- file should NOT exist
+3. `grep -rn "SmartTransaction" packages/ apps/` -- should return NO results
+4. `grep -rn "CapacityManager" packages/ apps/` -- should return NO results
+5. `grep -rn "transaction\.js\|capacity\.js" packages/utils/src/index.ts` -- should NOT find these exports
+6. `grep -rn "findCellsOnChain" packages/sdk/src/sdk.ts` -- should show CCC native cell finding
+7. `pnpm check:full` passes
+
+
+`transaction.ts` and `capacity.ts` are deleted from `@ickb/utils`. Barrel exports cleaned. SmartTransaction class and CapacityManager class no longer exist anywhere. SDK uses CCC `client.findCellsOnChain()` for cell finding. No SmartTransaction or CapacityManager references remain in the codebase. `pnpm check:full` passes.
+
+
+
+
+
+
+1. `ls packages/utils/src/transaction.ts packages/utils/src/capacity.ts 2>&1` -- both files gone
+2. `grep -rn "SmartTransaction\|CapacityManager" packages/ apps/` -- zero results
+3. `grep -rn "addUdtHandlers" packages/` -- zero results
+4. `grep -rn "TransactionLike" packages/dao/ packages/core/ packages/order/ packages/sdk/ packages/utils/src/udt.ts` -- shows new signatures
+5. `grep -rn "Transaction\.from(txLike)" packages/` -- shows CCC conversion pattern
+6. `grep -rn "export.*from.*transaction\|export.*from.*capacity" packages/utils/src/index.ts` -- no exports from deleted files
+7. `pnpm check:full` -- passes clean with all 5 library packages compiling
+
+
+
+- SmartTransaction class deleted from @ickb/utils (transaction.ts gone)
+- CapacityManager class deleted from @ickb/utils (capacity.ts gone)
+- All manager method signatures accept ccc.TransactionLike, return ccc.Transaction
+- UdtHandler/UdtManager preserved with updated signatures (deferred to Phase 3+)
+- All addUdtHandlers calls replaced with addCellDeps
+- SDK uses CCC native cell finding instead of CapacityManager
+- Barrel exports clean (no references to deleted files)
+- No SmartTransaction or CapacityManager references anywhere in codebase
+- pnpm check:full passes
+
+
+
diff --git a/.planning/phases/01-ickb-utils-smarttransaction-removal/01-03-SUMMARY.md b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-03-SUMMARY.md
new file mode 100644
index 0000000..d47d32c
--- /dev/null
+++ b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-03-SUMMARY.md
@@ -0,0 +1,165 @@
+---
+phase: 01-ickb-utils-smarttransaction-removal
+plan: 03
+subsystem: transaction
+tags: [SmartTransaction, CapacityManager, TransactionLike, ccc-Transaction, API-cleanup]
+
+# Dependency graph
+requires:
+ - phase: 01-01
+ provides: assertDaoOutputLimit centralized in CCC core; DaoManager/LogicManager async signatures with client parameter
+ - phase: 01-02
+ provides: getHeader/HeaderKey removed from public API; all consumer packages use direct CCC client calls; TransactionHeader moved to utils.ts
+provides:
+ - All manager methods accept ccc.TransactionLike and return ccc.Transaction
+ - SmartTransaction class and CapacityManager class fully deleted from @ickb/utils
+ - addUdtHandlers replaced with tx.addCellDeps(udtHandler.cellDeps) across all packages
+ - defaultFindCellsLimit moved from capacity.ts to utils.ts
+affects: [01-04]
+
+# Tech tracking
+tech-stack:
+ added: []
+ patterns: [TransactionLike-input-Transaction-return, direct-findCellsOnChain]
+
+key-files:
+ created: []
+ modified:
+ - packages/utils/src/udt.ts
+ - packages/utils/src/utils.ts
+ - packages/utils/src/index.ts
+ - packages/dao/src/dao.ts
+ - packages/core/src/logic.ts
+ - packages/core/src/owned_owner.ts
+ - packages/core/src/udt.ts
+ - packages/order/src/order.ts
+ - packages/sdk/src/sdk.ts
+ - packages/sdk/src/constants.ts
+ - apps/faucet/src/main.ts
+ deleted:
+ - packages/utils/src/transaction.ts
+ - packages/utils/src/capacity.ts
+
+key-decisions:
+ - "Methods accept ccc.TransactionLike and return ccc.Transaction with ccc.Transaction.from(txLike) at entry, enabling callers to pass plain objects or existing Transactions"
+ - "Replaced addUdtHandlers with tx.addCellDeps(this.udtHandler.cellDeps) since addUdtHandlers was just a wrapper around addCellDeps"
+ - "SDK getCkb() replaced CapacityManager.findCapacities with direct client.findCellsOnChain calls with scriptLenRange filter"
+ - "defaultFindCellsLimit moved from capacity.ts to utils.ts to preserve existing imports across packages"
+
+patterns-established:
+ - "TransactionLike pattern: all methods accept ccc.TransactionLike and return ccc.Transaction, converting with Transaction.from() at entry"
+ - "Cell deps: use tx.addCellDeps(handler.cellDeps) directly instead of wrapper methods"
+
+requirements-completed: [SMTX-01, SMTX-02, SMTX-03, SMTX-05]
+
+# Metrics
+duration: 16min
+completed: 2026-02-22
+---
+
+# Phase 01 Plan 03: SmartTransaction/CapacityManager Deletion Summary
+
+**Deleted SmartTransaction class and CapacityManager class from @ickb/utils, replaced all 20+ method signatures with ccc.TransactionLike input / ccc.Transaction return pattern**
+
+## Performance
+
+- **Duration:** 16 min
+- **Started:** 2026-02-22T16:31:36Z
+- **Completed:** 2026-02-22T16:47:58Z
+- **Tasks:** 2
+- **Files modified:** 13 (11 modified, 2 deleted)
+
+## Accomplishments
+- Updated all manager method signatures across 7 files in 5 packages to accept ccc.TransactionLike and return ccc.Transaction
+- Replaced all 8 addUdtHandlers() calls with direct tx.addCellDeps(this.udtHandler.cellDeps)
+- Deleted SmartTransaction class (460+ lines) and CapacityManager class (220+ lines) from @ickb/utils
+- Replaced CapacityManager usage in SDK with direct client.findCellsOnChain calls
+- Updated faucet app to use ccc.Transaction.default() with inline cell queries
+- Moved defaultFindCellsLimit constant to utils.ts, preserving all downstream imports
+
+## Task Commits
+
+Each task was committed atomically:
+
+1. **Task 1: Update method signatures from SmartTransaction to TransactionLike** - `2e832ae` (refactor)
+2. **Task 2: Delete SmartTransaction/CapacityManager and clean exports** - `de8f4a7` (refactor)
+
+## Files Created/Modified
+- `packages/utils/src/udt.ts` - UdtHandler interface and UdtManager class: TransactionLike signatures, addUdts returns Transaction
+- `packages/utils/src/utils.ts` - Added defaultFindCellsLimit constant (moved from capacity.ts)
+- `packages/utils/src/index.ts` - Removed capacity.js and transaction.js barrel exports
+- `packages/dao/src/dao.ts` - DaoManager deposit/requestWithdrawal/withdraw: TransactionLike in, Transaction out
+- `packages/core/src/logic.ts` - LogicManager deposit/completeDeposit: TransactionLike in, Transaction out
+- `packages/core/src/owned_owner.ts` - OwnedOwnerManager requestWithdrawal/withdraw: TransactionLike in, Transaction out
+- `packages/core/src/udt.ts` - IckbUdtManager getInputsUdtBalance: TransactionLike parameter
+- `packages/order/src/order.ts` - OrderManager mint/addMatch/melt: TransactionLike in, Transaction out
+- `packages/sdk/src/sdk.ts` - IckbSdk request/collect: TransactionLike in, Transaction out; getCkb uses findCellsOnChain
+- `packages/sdk/src/constants.ts` - Removed CapacityManager from getConfig return type
+- `apps/faucet/src/main.ts` - Uses ccc.Transaction.default() + inline findCellsOnChain
+- `packages/utils/src/transaction.ts` - DELETED (SmartTransaction class)
+- `packages/utils/src/capacity.ts` - DELETED (CapacityManager class)
+
+## Decisions Made
+- Methods accept ccc.TransactionLike and return ccc.Transaction. This uses ccc.Transaction.from(txLike) at method entry, which is a no-op if the input is already a Transaction instance. Callers can pass plain transaction-like objects or existing Transactions interchangeably.
+- Replaced addUdtHandlers with tx.addCellDeps(this.udtHandler.cellDeps) because addUdtHandlers was internally just a loop calling addCellDeps on each handler's cellDeps array. The direct call is more transparent.
+- SDK getCkb() uses direct findCellsOnChain with scriptLenRange: [0n, 1n] filter (no type script) to replicate CapacityManager.withAnyData() behavior, plus explicit lock.eq() check for correctness.
+- Deferred SDK CapacityManager removal from Task 1 to Task 2 to keep each task independently compilable.
+
+## Deviations from Plan
+
+### Auto-fixed Issues
+
+**1. [Rule 3 - Blocking] Deferred SDK constructor change from Task 1 to Task 2**
+- **Found during:** Task 1 (signature updates)
+- **Issue:** Removing CapacityManager from SDK constructor in Task 1 caused lint errors because getCkb() still referenced this.capacity. The plan specified removing SDK capacity in Task 2 but the constructor change in Task 1 broke the build.
+- **Fix:** Kept CapacityManager import and constructor field in SDK during Task 1, then properly removed both in Task 2 alongside the findCellsOnChain replacement.
+- **Files modified:** packages/sdk/src/sdk.ts
+- **Verification:** pnpm check:full passes after both tasks
+- **Committed in:** de8f4a7 (Task 2 commit)
+
+**2. [Rule 1 - Bug] Removed unused 'collect' import in faucet app**
+- **Found during:** Task 2 (faucet update)
+- **Issue:** After replacing CapacityManager with inline findCellsOnChain, the 'collect' import became unused, causing lint failure.
+- **Fix:** Removed unused import.
+- **Files modified:** apps/faucet/src/main.ts
+- **Verification:** pnpm check:full passes
+- **Committed in:** de8f4a7 (Task 2 commit)
+
+---
+
+**Total deviations:** 2 auto-fixed (1 blocking, 1 bug)
+**Impact on plan:** Necessary task-boundary adjustment to keep each task independently buildable. No scope creep.
+
+## Issues Encountered
+- defaultFindCellsLimit was exported from both utils.ts and capacity.ts via barrel index.ts, causing TS2308 ambiguous export error. Resolved by keeping it in capacity.ts during Task 1 and moving to utils.ts only after capacity.ts deletion in Task 2.
+
+## User Setup Required
+None - no external service configuration required.
+
+## Next Phase Readiness
+- SmartTransaction and CapacityManager fully removed from codebase
+- All packages use standard CCC Transaction types
+- @ickb/utils public API is clean: only exports codec, heap, udt, and utils modules
+- Ready for Plan 04 (completeFee refactoring) which can now use plain ccc.Transaction
+
+## Self-Check: PASSED
+
+- FOUND: packages/utils/src/udt.ts
+- FOUND: packages/utils/src/utils.ts
+- FOUND: packages/utils/src/index.ts
+- FOUND: packages/dao/src/dao.ts
+- FOUND: packages/core/src/logic.ts
+- FOUND: packages/core/src/owned_owner.ts
+- FOUND: packages/core/src/udt.ts
+- FOUND: packages/order/src/order.ts
+- FOUND: packages/sdk/src/sdk.ts
+- FOUND: packages/sdk/src/constants.ts
+- FOUND: apps/faucet/src/main.ts
+- MISSING (expected): packages/utils/src/transaction.ts (deleted)
+- MISSING (expected): packages/utils/src/capacity.ts (deleted)
+- FOUND: commit 2e832ae (Task 1)
+- FOUND: commit de8f4a7 (Task 2)
+
+---
+*Phase: 01-ickb-utils-smarttransaction-removal*
+*Completed: 2026-02-22*
diff --git a/.planning/phases/01-ickb-utils-smarttransaction-removal/01-RESEARCH.md b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-RESEARCH.md
new file mode 100644
index 0000000..54aed2a
--- /dev/null
+++ b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-RESEARCH.md
@@ -0,0 +1,567 @@
+# Phase 1: SmartTransaction Removal (feature-slice) - Research
+
+**Researched:** 2026-02-22
+**Domain:** TypeScript refactoring / CCC blockchain SDK alignment
+**Confidence:** HIGH
+
+## Summary
+
+Phase 1 removes `SmartTransaction`, `CapacityManager`, `getHeader()`/`HeaderKey`, and 7 scattered 64-output DAO limit checks. It contributes the DAO check to CCC core via `ccc-dev/`, updates all manager method signatures across all 5 library packages from `SmartTransaction` to `ccc.TransactionLike`, and keeps the build green after every step.
+
+The codebase is well-structured: SmartTransaction has exactly 9 consumer files across 5 packages; `getHeader` has 5 standalone call sites plus 4 instance method call sites; the 64-output DAO check appears in 7 locations across 4 files. CCC's native `Transaction` already handles DAO profit in `getInputsCapacity()` via `getInputsCapacityExtra()` -> `CellInput.getExtraCapacity()` -> `Cell.getDaoProfit()`, making SmartTransaction's `getInputsCapacity` override redundant. CCC's `Transaction.from(txLike)` provides the `TransactionLike` -> `Transaction` entry-point conversion pattern that all updated method signatures will follow.
+
+**Primary recommendation:** Execute in the exact 5-step sequence from CONTEXT.md, with CCC DAO utility first (purely additive), then sweep each removal across all packages before moving to the next removal. Every step must pass `pnpm check:full`.
+
+
+## User Constraints (from CONTEXT.md)
+
+### Locked Decisions
+- Build the 64-output NervosDAO limit check **in CCC core**, not in @ickb/utils
+- Develop in `ccc-dev/ccc/`, record pins, use immediately via workspace override while waiting for upstream merge
+- **Submit the upstream CCC PR during Phase 1 execution**
+- CCC PR includes three components:
+ 1. **`completeFee()` safety net** -- async check using `client.getKnownScript(KnownScript.NervosDao)` with full `Script.eq()` comparison
+ 2. **Standalone utility function** -- `assertDaoOutputLimit(tx, client)` that auto-resolves unresolved inputs (populating `CellInput.cellOutput` as a side effect) and checks both inputs and outputs
+ 3. **`ErrorNervosDaoOutputLimit` error class** in `transactionErrors.ts` with metadata fields (count) and hardcoded limit of 64
+- The check logic: if `outputs.length > 64` AND any input or output has DAO type script, throw error
+- **PR description should mention** the possibility of adding the check to `addOutput()` as a future enhancement, inviting maintainer feedback
+- All 6+ scattered DAO checks across dao/core/utils packages are replaced with calls to the new CCC utility **in Phase 1**
+- **Remove `getHeader()` function and `HeaderKey` type entirely** from @ickb/utils
+- Inline CCC client calls at each of the 8+ call sites across dao/core/sdk
+- SmartTransaction's redundant `Map` cache is deleted -- CCC's built-in `ClientCacheMemory` LRU (128 blocks) handles caching
+- **`addHeaders()` replacement needed** -- 3 call sites push to `tx.headerDeps` directly
+- **Build must pass after every removal step** -- no intermediate broken states
+- Execution order:
+ 1. CCC DAO utility (adds new code, nothing breaks)
+ 2. Replace all scattered DAO checks with CCC utility calls (all packages)
+ 3. Remove `getHeader()`/`HeaderKey` and inline CCC calls at all call sites (all packages)
+ 4. Remove SmartTransaction class and update all method signatures to `ccc.TransactionLike` (all packages)
+ 5. Remove CapacityManager and update SDK call sites (utils + sdk)
+- Follow CCC's convention: public APIs accept `ccc.TransactionLike` (flexible input), return `ccc.Transaction` (concrete)
+- Convert internally with `ccc.Transaction.from(txLike)` at method entry point
+- UdtHandler interface and UdtManager class **stay in @ickb/utils** for Phase 1, signatures updated from `SmartTransaction` to `ccc.TransactionLike`
+- CapacityManager is deleted from @ickb/utils; SDK call sites updated to use CCC's native cell finding
+- **Clean delete** -- no deprecation stubs, no migration comments, no breadcrumbs
+- File deletions + barrel export removal in the **same commit** (atomic)
+- Files deleted: `transaction.ts`, `capacity.ts` (from @ickb/utils)
+- Files kept: `udt.ts` (signatures updated), `utils.ts` (getHeader/HeaderKey removed), `codec.ts`, `heap.ts`, `index.ts`
+- Script comparison must use full `Script.eq()` (codeHash + hashType + args), never just `codeHash`
+
+### Claude's Discretion
+- `addUdtHandlers()` replacement strategy at call sites
+- CapacityManager replacement approach in SDK (CCC native equivalent)
+- Exact commit boundaries within each feature-slice step
+- CCC PR code style and test approach (follow CCC's vitest patterns)
+
+### Deferred Ideas (OUT OF SCOPE)
+- **addOutput() DAO check** -- Sync check in `Transaction.addOutput()`. Deferred due to CCC maintainer acceptance concerns. Mentioned in CCC PR description as future possibility.
+- **getHeader as CCC contribution** -- A unified header lookup function. Low priority since the wrapper is being removed and calls inlined.
+
+
+
+## Phase Requirements
+
+| ID | Description | Research Support |
+|----|-------------|-----------------|
+| SMTX-01 | All manager method signatures across all 5 library packages accept `ccc.TransactionLike` instead of `SmartTransaction` | Exact inventory: 9 files use SmartTransaction type across 5 packages; CCC's `Transaction.from(txLike)` is the conversion pattern; all method signatures identified with line numbers |
+| SMTX-02 | `SmartTransaction` class and its `completeFee()` override deleted from `@ickb/utils` | SmartTransaction in `transaction.ts` (480 lines); `completeFee()` override (lines 63-98) wraps UDT handlers + DAO check; CCC's native `getInputsCapacity` already handles DAO profit -- override is redundant |
+| SMTX-04 | `getHeader()` function and `HeaderKey` type removed; all call sites inline CCC client calls | 5 standalone `getHeader` call sites + 4 `tx.getHeader` instance method call sites identified; each maps to `client.getTransactionWithHeader(hash)?.header` or `client.getHeaderByNumber(n)`; 3 `addHeaders` call sites need `tx.headerDeps.push()` with dedup |
+| SMTX-06 | 64-output NervosDAO limit check consolidated into a single CCC utility | 7 check locations across 4 files identified; CCC error class pattern documented from `transactionErrors.ts`; `completeFee()` integration point identified; CCC vitest test patterns documented |
+
+
+## Standard Stack
+
+### Core
+| Library | Version | Purpose | Why Standard |
+|---------|---------|---------|--------------|
+| `@ckb-ccc/core` | catalog: (^1.12.2) | CKB blockchain SDK | Project's core dependency; `Transaction`, `TransactionLike`, `Client`, `Script.eq()` |
+| TypeScript | ^5.9.3 (strict mode) | Type safety | `noUncheckedIndexedAccess`, `verbatimModuleSyntax`, `noImplicitOverride` |
+| tsgo | native-preview | Type checking | Used via `ccc-dev/tsgo-filter.sh` when CCC is cloned |
+| vitest | ^3.2.4 | Testing | CCC's test framework; tests for the CCC PR |
+| pnpm | 10.30.1 | Package management | Workspace protocol, catalog specifiers |
+
+### Supporting
+| Library | Version | Purpose | When to Use |
+|---------|---------|---------|-------------|
+| `ccc-dev/` system | local | Local CCC development | Building/testing CCC DAO contribution before upstream merge |
+| `@changesets/cli` | ^2.29.8 | Versioning | After API changes, run `pnpm changeset` |
+
+### Alternatives Considered
+No alternatives -- this is a refactoring phase within an existing codebase. All decisions are locked.
+
+## Architecture Patterns
+
+### Recommended Project Structure
+```
+packages/
+├── utils/src/
+│ ├── codec.ts # Molecule codec utilities (kept)
+│ ├── heap.ts # MinHeap (kept)
+│ ├── udt.ts # UdtHandler/UdtManager (kept, signatures updated)
+│ ├── utils.ts # Utility functions (getHeader/HeaderKey REMOVED)
+│ ├── index.ts # Barrel exports (transaction.ts + capacity.ts removed)
+│ ├── transaction.ts # DELETED (SmartTransaction)
+│ └── capacity.ts # DELETED (CapacityManager)
+├── dao/src/
+│ ├── dao.ts # DaoManager (SmartTransaction -> TransactionLike)
+│ └── cells.ts # DaoCell (getHeader inlined)
+├── core/src/
+│ ├── logic.ts # LogicManager (SmartTransaction -> TransactionLike)
+│ ├── owned_owner.ts # OwnedOwnerManager (SmartTransaction -> TransactionLike)
+│ ├── udt.ts # IckbUdtManager (SmartTransaction -> TransactionLike)
+│ └── cells.ts # ReceiptCell/etc (getHeader inlined)
+├── order/src/
+│ └── order.ts # OrderManager (SmartTransaction -> TransactionLike)
+├── sdk/src/
+│ ├── sdk.ts # IckbSdk (SmartTransaction -> TransactionLike, CapacityManager removed)
+│ └── constants.ts # getConfig (CapacityManager removed)
+ccc-dev/ccc/packages/core/src/ckb/
+├── transactionErrors.ts # + ErrorNervosDaoOutputLimit (new)
+└── transaction.ts # + completeFee safety net + assertDaoOutputLimit (new)
+```
+
+### Pattern 1: TransactionLike Input / Transaction Output
+**What:** CCC convention for public APIs that transform transactions
+**When to use:** Every manager method that accepts a transaction
+**Example:**
+```typescript
+// Source: CCC packages (udt, type-id, spore) all follow this pattern
+// Before:
+deposit(tx: SmartTransaction, capacities: ccc.FixedPoint[], lock: ccc.Script): void
+
+// After:
+deposit(txLike: ccc.TransactionLike, capacities: ccc.FixedPoint[], lock: ccc.Script): ccc.Transaction {
+ const tx = ccc.Transaction.from(txLike);
+ // ... mutate tx ...
+ return tx;
+}
+```
+
+### Pattern 2: Inline Header Fetching
+**What:** Replace `getHeader(client, { type, value })` with direct CCC client calls
+**When to use:** All call sites where `getHeader` or `tx.getHeader` was used
+**Example:**
+```typescript
+// Before (standalone function):
+const header = await getHeader(client, { type: "txHash", value: txHash });
+
+// After (inlined):
+const txWithHeader = await client.getTransactionWithHeader(txHash);
+if (!txWithHeader?.header) {
+ throw new Error("Header not found");
+}
+const header = txWithHeader.header;
+
+// Before (number lookup):
+const header = await getHeader(client, { type: "number", value: blockNumber });
+
+// After:
+const header = await client.getHeaderByNumber(blockNumber);
+if (!header) {
+ throw new Error("Header not found");
+}
+```
+
+### Pattern 3: Direct headerDeps Push (replacing addHeaders)
+**What:** Push header hashes to `tx.headerDeps` directly with dedup
+**When to use:** The 3 call sites where `tx.addHeaders()` was used
+**Example:**
+```typescript
+// Before:
+tx.addHeaders(depositHeader); // TransactionHeader with { header, txHash? }
+
+// After:
+const hash = depositHeader.header.hash;
+if (!tx.headerDeps.some((h) => h === hash)) {
+ tx.headerDeps.push(hash);
+}
+```
+
+### Pattern 4: CCC DAO Error Class Convention
+**What:** Error class in `transactionErrors.ts` following existing patterns
+**When to use:** The new `ErrorNervosDaoOutputLimit`
+**Example:**
+```typescript
+// Source: ccc-dev/ccc/packages/core/src/ckb/transactionErrors.ts
+// Follow the ErrorTransactionInsufficientCapacity pattern:
+export class ErrorNervosDaoOutputLimit extends Error {
+ public readonly count: number;
+ public readonly limit: number;
+
+ constructor(count: number) {
+ super(
+ `NervosDAO transaction has ${count} output cells, exceeding the limit of 64`,
+ );
+ this.count = count;
+ this.limit = 64;
+ }
+}
+```
+
+### Pattern 5: DAO Check Utility Function
+**What:** Standalone async utility + completeFee integration
+**When to use:** Replacing all 7 scattered DAO checks
+**Example:**
+```typescript
+// Standalone utility:
+export async function assertDaoOutputLimit(
+ tx: Transaction,
+ client: Client,
+): Promise {
+ if (tx.outputs.length <= 64) return;
+
+ const { codeHash, hashType } = await client.getKnownScript(
+ KnownScript.NervosDao,
+ );
+ const dao = Script.from({ codeHash, hashType, args: "0x" });
+
+ // Auto-resolve unresolved inputs
+ for (const input of tx.inputs) {
+ await input.completeExtraInfos(client);
+ }
+
+ const isDaoTx =
+ tx.inputs.some((i) => i.cellOutput?.type?.eq(dao)) ||
+ tx.outputs.some((o) => o.type?.eq(dao));
+
+ if (isDaoTx) {
+ throw new ErrorNervosDaoOutputLimit(tx.outputs.length);
+ }
+}
+```
+
+### Pattern 6: addUdtHandlers Replacement
+**What:** When SmartTransaction is removed, `addUdtHandlers()` calls can only do what `ccc.Transaction` supports
+**When to use:** The 8 `addUdtHandlers` call sites across 4 files
+**Example:**
+```typescript
+// Before:
+tx.addUdtHandlers(this.udtHandler);
+
+// After (only the cellDeps part survives):
+tx.addCellDeps(this.udtHandler.cellDeps);
+// The UDT handler registration was SmartTransaction-specific.
+// The cellDeps are the only persistent effect on a plain Transaction.
+// Note: Most call sites already also call tx.addCellDeps(this.cellDeps)
+// just before addUdtHandlers, so this may be a no-op if deduplication
+// in addCellDeps handles it. Check each site.
+```
+
+### Anti-Patterns to Avoid
+- **Partial script comparison:** Never compare just `codeHash`. Always use `Script.eq()` (codeHash + hashType + args). CCC's own `isNervosDao` uses codeHash + hashType but not args -- the new CCC utility should use the safer `Script.eq()` with args: "0x".
+- **Leaving broken intermediate states:** Each feature-slice step must pass `pnpm check:full`. Don't delete SmartTransaction before all its consumers are updated.
+- **Creating wrapper types:** Don't create a "TransactionWrapper" or similar -- use plain `ccc.Transaction` directly.
+- **Keeping dead exports:** When `transaction.ts` is deleted, its barrel export `export * from "./transaction.js"` in `index.ts` must be removed in the same commit.
+- **Redundant header caching:** Don't create a replacement header cache. CCC's `ClientCacheMemory` (128-block LRU) handles this transparently.
+
+## Don't Hand-Roll
+
+| Problem | Don't Build | Use Instead | Why |
+|---------|-------------|-------------|-----|
+| DAO profit calculation | Custom getInputsCapacity | CCC's native `Transaction.getInputsCapacity()` | Already handles DAO profit via `getInputsCapacityExtra()` -> `CellInput.getExtraCapacity()` -> `Cell.getDaoProfit()` |
+| Header caching | Custom Map | CCC's `ClientCacheMemory` | Built-in LRU cache for 128 blocks, transparent to caller |
+| Transaction type conversion | Custom `SmartTransaction.from()` | CCC's `Transaction.from(txLike)` | Standard pattern across CCC ecosystem; handles all TransactionLike variations |
+| Cell finding | Custom CapacityManager.findCapacities | CCC's `client.findCells()` / `client.findCellsOnChain()` | Native CCC API with filter support |
+| Fee completion | SmartTransaction.completeFee override | CCC's `tx.completeFeeBy()` / `tx.completeFeeChangeToLock()` | CCC provides multiple fee completion strategies |
+
+**Key insight:** SmartTransaction was created before CCC had many of these features. CCC now handles DAO profit, fee completion, cell finding, and caching natively. The abstraction layer is no longer needed.
+
+## Common Pitfalls
+
+### Pitfall 1: Breaking imports during staged deletion
+**What goes wrong:** Deleting SmartTransaction from utils before consumers are updated causes cascading type errors across all 5 packages.
+**Why it happens:** The dependency chain is utils -> dao -> core -> order -> sdk. Removing a type from utils breaks everything downstream.
+**How to avoid:** Follow the 5-step execution order strictly. Update all consumers to use `ccc.TransactionLike` BEFORE deleting the SmartTransaction class.
+**Warning signs:** TypeScript errors mentioning "SmartTransaction is not exported" in any package.
+
+### Pitfall 2: addUdtHandlers cellDeps duplication
+**What goes wrong:** When replacing `addUdtHandlers`, the cellDeps are added twice (once by the explicit `tx.addCellDeps(this.cellDeps)` that usually precedes `addUdtHandlers`, and again when replacing `addUdtHandlers` itself).
+**Why it happens:** Most call sites already have `tx.addCellDeps(this.cellDeps)` right before `tx.addUdtHandlers(this.udtHandler)`. The `addUdtHandlers` internally also calls `this.addCellDeps(udtHandler.cellDeps)`.
+**How to avoid:** Audit each `addUdtHandlers` call site to check if the cellDeps are already added by a preceding `addCellDeps`. CCC's `addCellDeps` deduplicates, so double-adding is harmless but messy.
+**Warning signs:** Duplicate cellDeps in transaction output (functional but wasteful).
+
+### Pitfall 3: Missing null checks when inlining getHeader
+**What goes wrong:** `client.getTransactionWithHeader(hash)` returns `undefined` if the transaction is not found. The original `getHeader` had a null check + throw.
+**Why it happens:** Inlining the CCC client call without preserving the error path.
+**How to avoid:** Always include `if (!result?.header) throw new Error("Header not found")` at each inlined call site.
+**Warning signs:** Runtime `Cannot read property 'epoch' of undefined` errors.
+
+### Pitfall 4: headerDeps dedup logic
+**What goes wrong:** When replacing `addHeaders`, pushing the same header hash twice to `tx.headerDeps`.
+**Why it happens:** `addHeaders` had dedup logic (`if (!this.headerDeps.some((h) => h === hash))`). Inlining without preserving the check.
+**How to avoid:** Always include the dedup check before `tx.headerDeps.push(hash)`.
+**Warning signs:** Duplicate entries in `headerDeps`, which could cause verification failures on-chain.
+
+### Pitfall 5: TransactionHeader type still needed by DaoCell
+**What goes wrong:** Deleting SmartTransaction's `TransactionHeader` interface breaks `DaoCell.headers` and `ReceiptCell.header`.
+**Why it happens:** `TransactionHeader` is defined in `transaction.ts` (being deleted) but used by `@ickb/dao` and `@ickb/core`.
+**How to avoid:** The `TransactionHeader` interface (`{ header: ccc.ClientBlockHeader, txHash?: ccc.Hex }`) must be moved to a surviving file (e.g., `utils.ts`) or its definition inlined where used. This interface is still needed even after SmartTransaction is gone -- `DaoCell.headers` is a tuple of `[TransactionHeader, TransactionHeader]`.
+**Warning signs:** "TransactionHeader is not exported" errors after deleting transaction.ts.
+
+### Pitfall 6: SmartTransaction.getInputsCapacity vs tx.getHeader
+**What goes wrong:** SmartTransaction's `getInputsCapacity` override (lines 154-202) uses `this.getHeader()` (the instance method). When SmartTransaction is deleted, this override disappears. But CCC's native `Transaction.getInputsCapacity()` already handles DAO profit differently.
+**Why it happens:** The override was written before CCC added native DAO profit calculation.
+**How to avoid:** Verify that CCC's native `getInputsCapacity()` handles all cases that SmartTransaction's override did. CCC's version uses `CellInput.getExtraCapacity()` -> `Cell.getDaoProfit()` which resolves headers through the client. This is functionally equivalent.
+**Warning signs:** Incorrect fee calculation after SmartTransaction removal (would manifest in over/under-paying fees).
+
+### Pitfall 7: IckbUdtManager.getInputsUdtBalance uses tx.getHeader
+**What goes wrong:** `IckbUdtManager.getInputsUdtBalance` (core/src/udt.ts lines 108, 125) calls `tx.getHeader()` which is a SmartTransaction instance method. After SmartTransaction is removed, this call doesn't exist on plain `ccc.Transaction`.
+**Why it happens:** The method relies on SmartTransaction's header cache + headerDeps validation.
+**How to avoid:** Replace `tx.getHeader(client, { type: "txHash", value: outPoint.txHash })` with inlined CCC client calls. The headerDeps validation from the old `getHeader` instance method was a runtime check that headers were pre-populated -- after removal, the client call fetches headers directly.
+**Warning signs:** TypeScript error `Property 'getHeader' does not exist on type 'Transaction'`.
+
+### Pitfall 8: ccc-dev pins must be recorded after CCC changes
+**What goes wrong:** Making changes to `ccc-dev/ccc/` without running `pnpm ccc:record` means the pins don't reflect the new state.
+**Why it happens:** `ccc-dev/pins/HEAD` is a hash integrity check. If ccc code changes but pins don't update, replay won't reproduce the same state.
+**How to avoid:** After developing the DAO utility in `ccc-dev/ccc/`, run `pnpm ccc:record` to update pins. Check `pnpm ccc:status` to verify.
+**Warning signs:** `pnpm ccc:status` reports exit code 1 (pending work).
+
+## Code Examples
+
+### Complete DAO Check Replacement Pattern
+```typescript
+// Source: Verified from ccc-dev/ccc/packages/core/src/ckb/transaction.ts
+// and packages/dao/src/dao.ts
+
+// Before (scattered in 7 locations):
+if (tx.outputs.length > 64) {
+ throw new Error("More than 64 output cells in a NervosDAO transaction");
+}
+
+// After (calling CCC utility -- requires async context):
+await assertDaoOutputLimit(tx, client);
+
+// For sync contexts (where client is not available),
+// the check can be done at completeFee time as a safety net.
+```
+
+### Method Signature Migration Pattern
+```typescript
+// Before (dao/src/dao.ts DaoManager.deposit):
+deposit(
+ tx: SmartTransaction,
+ capacities: ccc.FixedPoint[],
+ lock: ccc.Script,
+): void {
+ tx.addCellDeps(this.cellDeps);
+ // ...
+}
+
+// After:
+deposit(
+ txLike: ccc.TransactionLike,
+ capacities: ccc.FixedPoint[],
+ lock: ccc.Script,
+): ccc.Transaction {
+ const tx = ccc.Transaction.from(txLike);
+ tx.addCellDeps(this.cellDeps);
+ // ...
+ return tx;
+}
+```
+
+### CapacityManager Replacement in SDK
+```typescript
+// Before (sdk/src/sdk.ts, line 376):
+for await (const c of this.capacity.findCapacities(client, this.bots, opts)) {
+ // ...
+}
+
+// After (using CCC's native cell finding):
+for (const lock of unique(this.bots)) {
+ for await (const cell of client.findCellsOnChain(
+ {
+ script: lock,
+ scriptType: "lock",
+ filter: {
+ scriptLenRange: [0n, 1n],
+ },
+ scriptSearchMode: "exact",
+ withData: true,
+ },
+ "asc",
+ 400,
+ )) {
+ if (cell.cellOutput.type !== undefined || !cell.cellOutput.lock.eq(lock)) {
+ continue;
+ }
+ // ... rest of logic using cell directly
+ }
+}
+```
+
+### CCC Vitest Test Pattern
+```typescript
+// Source: ccc-dev/ccc/packages/core/src/ckb/transaction.test.ts
+import { beforeEach, describe, expect, it, vi } from "vitest";
+import { ccc } from "../index.js";
+
+describe("assertDaoOutputLimit", () => {
+ let client: ccc.Client;
+
+ beforeEach(async () => {
+ client = new ccc.ClientPublicTestnet();
+ });
+
+ it("should not throw when outputs <= 64", async () => {
+ const tx = ccc.Transaction.default();
+ // Add 64 outputs
+ for (let i = 0; i < 64; i++) {
+ tx.addOutput({ lock: /* ... */ });
+ }
+ await expect(assertDaoOutputLimit(tx, client)).resolves.not.toThrow();
+ });
+
+ it("should throw ErrorNervosDaoOutputLimit when DAO tx has > 64 outputs", async () => {
+ // ... mock setup with DAO cells
+ await expect(assertDaoOutputLimit(tx, client)).rejects.toThrow(
+ ErrorNervosDaoOutputLimit,
+ );
+ });
+});
+```
+
+## State of the Art
+
+| Old Approach | Current Approach | When Changed | Impact |
+|--------------|------------------|--------------|--------|
+| SmartTransaction extends Transaction | Plain ccc.Transaction + utilities | This phase | All method signatures change to TransactionLike |
+| Custom getInputsCapacity override | CCC native getInputsCapacity with DAO profit | CCC core update (PR #260, merged) | Override in SmartTransaction is redundant |
+| Custom header cache (Map) | CCC ClientCacheMemory LRU (128 blocks) | CCC core feature | No manual header management needed |
+| Scattered DAO output checks | Centralized CCC utility | This phase | Single source of truth for the 64-output limit |
+| Custom CapacityManager.findCapacities | CCC client.findCells/findCellsOnChain | CCC core feature | Direct client API is sufficient |
+
+**Deprecated/outdated:**
+- `SmartTransaction.getInputsUdtBalance` / `getOutputsUdtBalance`: Use `@ckb-ccc/udt` Udt class methods instead (Phase 4-5)
+- `ccc.udtBalanceFrom`: Deprecated, replaced by `@ckb-ccc/udt` (tracked in SMTX-10, Phase 4-5)
+- `ccc.ErrorTransactionInsufficientCoin`: Deprecated, replaced by `ErrorUdtInsufficientCoin` from `@ckb-ccc/udt`
+
+## Detailed Inventory
+
+### SmartTransaction Consumer Map (9 files)
+
+| File | Usage | Migration |
+|------|-------|-----------|
+| `packages/utils/src/transaction.ts` | Class definition | **DELETE** entire file |
+| `packages/utils/src/capacity.ts` | `addCapacities(tx: SmartTransaction, ...)` | **DELETE** entire file |
+| `packages/utils/src/udt.ts` | `UdtHandler` interface + `UdtManager` methods accept `SmartTransaction` | Update signatures to `ccc.TransactionLike` |
+| `packages/dao/src/dao.ts` | `DaoManager.deposit/requestWithdrawal/withdraw(tx: SmartTransaction, ...)` | Update signatures to `ccc.TransactionLike` |
+| `packages/core/src/logic.ts` | `LogicManager.deposit/completeDeposit(tx: SmartTransaction, ...)` | Update signatures to `ccc.TransactionLike` |
+| `packages/core/src/owned_owner.ts` | `OwnedOwnerManager.requestWithdrawal/withdraw(tx: SmartTransaction, ...)` | Update signatures to `ccc.TransactionLike` |
+| `packages/core/src/udt.ts` | `IckbUdtManager.getInputsUdtBalance(client, tx: SmartTransaction)` | Update signature to `ccc.TransactionLike` |
+| `packages/order/src/order.ts` | `OrderManager.mint/addMatch/melt(tx: SmartTransaction, ...)` | Update signatures to `ccc.TransactionLike` |
+| `packages/sdk/src/sdk.ts` | `IckbSdk.request/collect(tx: SmartTransaction, ...)` | Update signatures to `ccc.TransactionLike` |
+
+### getHeader Call Sites (9 total)
+
+**Standalone function `getHeader()` (5 sites):**
+
+| File | Line | Key Type | Replacement |
+|------|------|----------|-------------|
+| `packages/dao/src/cells.ts` | 91 | `number` | `client.getHeaderByNumber(mol.Uint64LE.decode(cell.outputData))` |
+| `packages/dao/src/cells.ts` | 97 | `txHash` | `(await client.getTransactionWithHeader(txHash))?.header` |
+| `packages/dao/src/cells.ts` | 109 | `txHash` | `(await client.getTransactionWithHeader(txHash))?.header` |
+| `packages/core/src/cells.ts` | 84 | `txHash` | `(await client.getTransactionWithHeader(txHash))?.header` |
+| `packages/sdk/src/sdk.ts` | 388 | `txHash` | `(await client.getTransactionWithHeader(c.cell.outPoint.txHash))?.header` |
+
+**Instance method `tx.getHeader()` (4 sites -- deleted with SmartTransaction):**
+
+| File | Line | Key Type | Replacement |
+|------|------|----------|-------------|
+| `packages/utils/src/transaction.ts` | 185 | `txHash` | Deleted with SmartTransaction (CCC handles natively) |
+| `packages/utils/src/transaction.ts` | 190 | `number` | Deleted with SmartTransaction (CCC handles natively) |
+| `packages/core/src/udt.ts` | 108 | `txHash` | `(await client.getTransactionWithHeader(outPoint.txHash))?.header` |
+| `packages/core/src/udt.ts` | 125 | `txHash` | `(await client.getTransactionWithHeader(outPoint.txHash))?.header` |
+
+### addHeaders Call Sites (3 sites)
+
+| File | Line | What It Pushes | Replacement |
+|------|------|----------------|-------------|
+| `packages/dao/src/dao.ts` | 160 | Single `depositHeader` TransactionHeader | Push `depositHeader.header.hash` to `tx.headerDeps` with dedup |
+| `packages/dao/src/dao.ts` | 216 | Array of `headers` (from DaoCell) | Push each `header.header.hash` to `tx.headerDeps` with dedup |
+| `packages/core/src/logic.ts` | 125 | Array of receipt headers | Push each `r.header.header.hash` to `tx.headerDeps` with dedup |
+
+### 64-Output DAO Check Locations (7 sites)
+
+| File | Line | Context |
+|------|------|---------|
+| `packages/utils/src/transaction.ts` | 93-95 | SmartTransaction.completeFee (async, has client) |
+| `packages/dao/src/dao.ts` | 100-102 | DaoManager.deposit (sync) |
+| `packages/dao/src/dao.ts` | 174-176 | DaoManager.requestWithdrawal (sync) |
+| `packages/dao/src/dao.ts` | 245-247 | DaoManager.withdraw (sync) |
+| `packages/core/src/logic.ts` | 106-108 | LogicManager.deposit (sync) |
+| `packages/core/src/owned_owner.ts` | 104-106 | OwnedOwnerManager.requestWithdrawal (sync) |
+| `packages/core/src/owned_owner.ts` | 146-148 | OwnedOwnerManager.withdraw (sync) |
+
+**Note on sync vs async:** 6 of 7 check locations are in sync methods. The CCC `assertDaoOutputLimit` is async (needs client for `getKnownScript`). Options: (a) make the caller methods async, (b) pass the DAO script as a parameter so the check can remain sync, or (c) keep a simple sync `outputs.length > 64` check at the sync sites and use the async utility in completeFee. Option (a) is cleanest since these methods do IO-adjacent work.
+
+### addUdtHandlers Call Sites (8 sites)
+
+| File | Line | Preceding addCellDeps? | Safe to just remove? |
+|------|------|------------------------|---------------------|
+| `packages/core/src/owned_owner.ts` | 88 | Yes (line 87: `tx.addCellDeps(this.cellDeps)`) | Need `tx.addCellDeps(this.udtHandler.cellDeps)` |
+| `packages/core/src/owned_owner.ts` | 135 | Yes (line 134: `tx.addCellDeps(this.cellDeps)`) | Need `tx.addCellDeps(this.udtHandler.cellDeps)` |
+| `packages/core/src/logic.ts` | 87 | Yes (line 86: `tx.addCellDeps(this.cellDeps)`) | Need `tx.addCellDeps(this.udtHandler.cellDeps)` |
+| `packages/core/src/logic.ts` | 123 | Yes (line 122: `tx.addCellDeps(this.cellDeps)`) | Need `tx.addCellDeps(this.udtHandler.cellDeps)` |
+| `packages/utils/src/udt.ts` | 282 | Yes (line 281: `tx.addCellDeps(this.cellDeps)`) | Self-registering; replace with `tx.addCellDeps(this.cellDeps)` (already done on line 281) |
+| `packages/order/src/order.ts` | 191 | Yes (line 190: `tx.addCellDeps(this.cellDeps)`) | Need `tx.addCellDeps(this.udtHandler.cellDeps)` |
+| `packages/order/src/order.ts` | 228 | Yes (line 227: `tx.addCellDeps(this.cellDeps)`) | Need `tx.addCellDeps(this.udtHandler.cellDeps)` |
+| `packages/order/src/order.ts` | 516 | Yes (line 515: `tx.addCellDeps(this.cellDeps)`) | Need `tx.addCellDeps(this.udtHandler.cellDeps)` |
+
+**Analysis:** Each `addUdtHandlers` call does two things: (1) registers the handler in `udtHandlers` Map (SmartTransaction-specific, lost), (2) calls `addCellDeps(udtHandler.cellDeps)`. After SmartTransaction removal, replace with `tx.addCellDeps(this.udtHandler.cellDeps)` at each site. The UDT handler registration is only consumed by SmartTransaction's overridden `getInputsUdtBalance`/`getOutputsUdtBalance`/`completeFee` -- which are all being deleted.
+
+### TransactionHeader Type Preservation
+
+`TransactionHeader` (defined in `transaction.ts` line 506-517) is imported by:
+- `packages/dao/src/cells.ts` (DaoCell.headers, daoCellFrom)
+- `packages/core/src/cells.ts` (ReceiptCell.header, receiptCellFrom)
+
+This interface must be moved to a surviving file before `transaction.ts` is deleted. Candidate: `utils.ts` (it already contains `HeaderKey` which is being removed, so there's precedent for header-related types there). Alternatively, define it inline in each consumer. The interface is simple: `{ header: ccc.ClientBlockHeader, txHash?: ccc.Hex }`.
+
+### CapacityManager Consumer Map (3 files)
+
+| File | Usage | Migration |
+|------|-------|-----------|
+| `packages/utils/src/capacity.ts` | Class definition | **DELETE** entire file |
+| `packages/sdk/src/sdk.ts` | `this.capacity.findCapacities(client, this.bots, opts)` | Inline CCC `client.findCellsOnChain()` with appropriate filters |
+| `packages/sdk/src/constants.ts` | `CapacityManager.withAnyData()` constructor + return type | Remove from getConfig return type; remove instantiation |
+
+## Open Questions
+
+1. **Sync DAO check after utility migration**
+ - What we know: 6 of 7 scattered checks are in sync methods. The CCC `assertDaoOutputLimit` is async.
+ - What's unclear: Should all 6 sync methods become async to call the CCC utility, or should they accept a pre-resolved DAO script?
+ - Recommendation: Make the iCKB methods async (they already return void and do other mutations). Alternatively, the methods could accept an optional `client` parameter. The user's CONTEXT.md execution order puts "Replace all scattered DAO checks with CCC utility calls" as step 2, implying all checks become calls to the CCC utility. Making the methods async is the cleanest path.
+
+2. **Return type change: void -> Transaction**
+ - What we know: CCC convention returns `ccc.Transaction`. Current methods return `void` (mutating in-place).
+ - What's unclear: Changing return types from `void` to `ccc.Transaction` changes the API contract even if callers can ignore the return.
+ - Recommendation: Change return types to `ccc.Transaction` per CCC convention. Since these are library methods (not callback interfaces), callers can adapt. The `TransactionLike` input already forces callers to think about the pattern.
+
+3. **DaoCell.headers and TransactionHeader after removal**
+ - What we know: `TransactionHeader` is used by DaoCell (dao package) and ReceiptCell (core package). It's defined in transaction.ts (being deleted).
+ - What's unclear: Should the type be moved to utils.ts, or should it be relocated to the dao package where it's most used?
+ - Recommendation: Move to `utils.ts` since both dao and core import from `@ickb/utils`. The type is simple and doesn't create unwanted coupling.
+
+## Sources
+
+### Primary (HIGH confidence)
+- Codebase source files in `/workspaces/stack/packages/` -- all SmartTransaction consumers, getHeader call sites, DAO checks inventoried directly
+- CCC source in `/workspaces/stack/ccc-dev/ccc/packages/core/src/` -- Transaction class, TransactionLike type, error patterns, completeFee implementation, getInputsCapacity, test patterns
+- `.planning/phases/01-ickb-utils-smarttransaction-removal/01-CONTEXT.md` -- User decisions and constraints
+- `.planning/REQUIREMENTS.md` -- Requirement definitions and traceability
+
+### Secondary (MEDIUM confidence)
+- CCC's `Cell.isNervosDao()` implementation (line 415-437) -- shows CCC pattern for DAO detection (uses codeHash + hashType, not full Script.eq())
+- CCC's vitest configuration and test patterns -- from `vitest.config.mts` and `transaction.test.ts`
+
+## Metadata
+
+**Confidence breakdown:**
+- Standard stack: HIGH -- verified directly from codebase and CCC source
+- Architecture: HIGH -- all patterns verified from CCC source and existing iCKB code
+- Pitfalls: HIGH -- identified from direct code analysis, not speculation
+- Inventory: HIGH -- all call sites counted by direct grep, every file read
+
+**Research date:** 2026-02-22
+**Valid until:** 2026-03-22 (stable codebase, locked decisions)
diff --git a/.planning/phases/01-ickb-utils-smarttransaction-removal/01-VERIFICATION.md b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-VERIFICATION.md
new file mode 100644
index 0000000..c513edd
--- /dev/null
+++ b/.planning/phases/01-ickb-utils-smarttransaction-removal/01-VERIFICATION.md
@@ -0,0 +1,113 @@
+---
+phase: 01-ickb-utils-smarttransaction-removal
+verified: 2026-02-22T17:30:00Z
+status: passed
+score: 6/6 must-haves verified
+re_verification: false
+---
+
+# Phase 1: SmartTransaction Removal (feature-slice) Verification Report
+
+**Phase Goal**: SmartTransaction class, CapacityManager class are deleted; all manager method signatures across all 5 library packages accept `ccc.TransactionLike` instead of `SmartTransaction`; 64-output DAO limit check is contributed to CCC core; `getHeader()`/`HeaderKey` are removed and inlined. Each removal is chased across all packages — build stays green at every step.
+
+**Verified**: 2026-02-22T17:30:00Z
+**Status**: passed
+**Re-verification**: No — initial verification
+
+## Goal Achievement
+
+### Observable Truths (from ROADMAP.md Success Criteria)
+
+| # | Truth | Status | Evidence |
+|---|-------|--------|----------|
+| 1 | `SmartTransaction` class and `CapacityManager` class no longer exist in `@ickb/utils` source or exports | VERIFIED | `packages/utils/src/transaction.ts` and `packages/utils/src/capacity.ts` are deleted; `packages/utils/src/index.ts` exports only `codec.js`, `heap.js`, `udt.js`, `utils.js`; `grep SmartTransaction packages/ apps/` returns zero results |
+| 2 | `UdtHandler` interface and `UdtManager` class remain in `@ickb/utils` with method signatures updated from `SmartTransaction` to `ccc.TransactionLike` | VERIFIED | `packages/utils/src/udt.ts` exports both `UdtHandler` interface and `UdtManager` class; all methods accept `txLike: ccc.TransactionLike` and convert with `ccc.Transaction.from(txLike)` at entry |
+| 3 | `getHeader()` function and `HeaderKey` type are removed from `@ickb/utils`; all call sites inline CCC client calls; `SmartTransaction.addHeaders()` call sites push to `tx.headerDeps` directly | VERIFIED | `grep getHeader packages/utils/src/` returns zero results; `grep HeaderKey packages/` returns zero results; `grep addHeaders packages/` returns zero results; all 7 call sites replaced with `client.getTransactionWithHeader()` / `client.getHeaderByNumber()` with null-check-and-throw; 3 `headerDeps.push()` sites with `.some()` dedup in `dao/dao.ts` and `core/logic.ts` |
+| 4 | A 64-output NervosDAO limit check exists in CCC core: `completeFee()` safety net, standalone async utility, and `ErrorNervosDaoOutputLimit` error class; all 6+ scattered checks replaced | VERIFIED | `ErrorNervosDaoOutputLimit` in `ccc-dev/ccc/packages/core/src/ckb/transactionErrors.ts` with `count` and `limit` fields; `assertDaoOutputLimit` exported from `ccc-dev/ccc/packages/core/src/ckb/transaction.ts`; called at lines 2257 and 2285 in `completeFee`; called in `packages/dao/src/dao.ts` (3×), `packages/core/src/logic.ts` (1×), `packages/core/src/owned_owner.ts` (2×); `grep "outputs.length > 64" packages/` returns zero results |
+| 5 | ALL manager method signatures across ALL 5 library packages accept `ccc.TransactionLike` instead of `SmartTransaction`, following CCC's convention (TransactionLike input, Transaction output with `Transaction.from()` conversion at entry point) | VERIFIED | `txLike: ccc.TransactionLike` present in dao, core/logic, core/owned_owner, core/udt, order, sdk, and utils/udt; `ccc.Transaction.from(txLike)` at entry in all 15 confirmed conversion points; `return tx;` present at all method exits across dao, core, order, sdk; `addUdtHandlers` fully removed, replaced with `tx.addCellDeps(this.udtHandler.cellDeps)` at 7 sites |
+| 6 | `pnpm check` passes after each feature-slice removal step — no intermediate broken states | VERIFIED | All 5 plans committed atomically with individual task commits (7081869, 2decd06, 85ead3a, 2e832ae, de8f4a7); `pnpm check` passes on current state (confirmed by build execution: all 5 packages compile clean) |
+
+**Score**: 6/6 truths verified
+
+### Required Artifacts
+
+| Artifact | Expected | Status | Details |
+|----------|----------|--------|---------|
+| `ccc-dev/ccc/packages/core/src/ckb/transactionErrors.ts` | `ErrorNervosDaoOutputLimit` error class with `count` and `limit` fields | VERIFIED | Class exists, `public readonly count: number` and `public readonly limit: number` confirmed |
+| `ccc-dev/ccc/packages/core/src/ckb/transaction.ts` | `assertDaoOutputLimit` utility + `completeFee` safety net | VERIFIED | Function at line 2465, called in `completeFee` at lines 2257 and 2285 |
+| `packages/utils/src/utils.ts` | `TransactionHeader` type preserved; `getHeader` and `HeaderKey` absent | VERIFIED | `TransactionHeader` interface at line 19; no `getHeader` function or `HeaderKey` type found |
+| `packages/utils/src/index.ts` | Barrel exports without `transaction.js` or `capacity.js` | VERIFIED | Exports only `codec.js`, `heap.js`, `udt.js`, `utils.js` |
+| `packages/utils/src/udt.ts` | `UdtHandler` interface and `UdtManager` class with `TransactionLike` signatures | VERIFIED | Both present; all methods accept `txLike: ccc.TransactionLike` |
+| `packages/dao/src/cells.ts` | Inlined CCC client calls for header fetching | VERIFIED | `client.getHeaderByNumber()` and `client.getTransactionWithHeader()` with null checks confirmed |
+| `packages/core/src/cells.ts` | Inlined CCC client calls for header fetching | VERIFIED | `client.getTransactionWithHeader()` with null check confirmed |
+| `packages/dao/src/dao.ts` | TransactionLike signatures + assertDaoOutputLimit calls + headerDeps push | VERIFIED | 3× `txLike: ccc.TransactionLike`, 3× `assertDaoOutputLimit`, 2× `headerDeps.push` with dedup |
+| `packages/core/src/logic.ts` | TransactionLike signature + assertDaoOutputLimit call + headerDeps push | VERIFIED | `txLike: ccc.TransactionLike`, `assertDaoOutputLimit` at line 105, `headerDeps.push` at line 130 with dedup |
+| `packages/core/src/owned_owner.ts` | TransactionLike signatures + assertDaoOutputLimit calls | VERIFIED | 2× `txLike: ccc.TransactionLike`, 2× `assertDaoOutputLimit` |
+| `packages/core/src/udt.ts` | TransactionLike signature, inlined CCC client calls | VERIFIED | `txLike: ccc.TransactionLike`, 2× `client.getTransactionWithHeader()` with null checks |
+| `packages/order/src/order.ts` | TransactionLike signatures | VERIFIED | 3× `txLike: ccc.TransactionLike`, `ccc.Transaction.from(txLike)` at each entry |
+| `packages/sdk/src/sdk.ts` | TransactionLike signatures + findCellsOnChain (replacing CapacityManager) | VERIFIED | 2× `txLike: ccc.TransactionLike`; `findCellsOnChain` at line 373 with `scriptLenRange` filter; `getTransactionWithHeader` with null check at line 401 |
+| `packages/utils/src/transaction.ts` | DELETED | VERIFIED | File does not exist |
+| `packages/utils/src/capacity.ts` | DELETED | VERIFIED | File does not exist |
+| `ccc-dev/pins/local/001-dao-output-limit.patch` | Local patch for deterministic CCC replay | VERIFIED | File exists at expected path |
+
+### Key Link Verification (from PLAN frontmatter)
+
+| From | To | Via | Status | Details |
+|------|----|-----|--------|---------|
+| `packages/dao/src/dao.ts` | CCC `assertDaoOutputLimit` | `ccc.assertDaoOutputLimit(tx, client)` | WIRED | Pattern `ccc.assertDaoOutputLimit` found 3× |
+| `packages/core/src/logic.ts` | CCC `assertDaoOutputLimit` | `ccc.assertDaoOutputLimit(tx, client)` | WIRED | Pattern found 1× at line 105 |
+| `packages/core/src/owned_owner.ts` | CCC `assertDaoOutputLimit` | `ccc.assertDaoOutputLimit(tx, client)` | WIRED | Pattern found 2× at lines 109, 150 |
+| `packages/dao/src/cells.ts` | CCC Client API | `client.get(TransactionWithHeader|HeaderByNumber)` | WIRED | All 3 patterns found with null checks and throws |
+| `packages/core/src/udt.ts` | CCC Client API | `client.getTransactionWithHeader` | WIRED | Pattern found 2× at lines 104, 124 |
+| `packages/dao/src/dao.ts` | `tx.headerDeps` | `headerDeps.push` | WIRED | Pattern found 2×: lines 163, 222 with `.some()` dedup |
+| `packages/dao/src/dao.ts` | `ccc.Transaction.from()` | `Transaction.from(txLike)` at method entry | WIRED | Pattern found 3× at lines 82, 128, 198 |
+| `packages/order/src/order.ts` | `ccc.Transaction.from()` | `Transaction.from(txLike)` at method entry | WIRED | Pattern found 3× at lines 179, 223, 511 |
+| `packages/sdk/src/sdk.ts` | `client.findCellsOnChain` | CapacityManager replacement | WIRED | `findCellsOnChain` at line 373 |
+
+### Requirements Coverage
+
+| Requirement | Source Plan | Description | Status | Evidence |
+|-------------|------------|-------------|--------|----------|
+| SMTX-01 | 01-03-PLAN.md | All manager method signatures accept `ccc.TransactionLike` instead of `SmartTransaction`; `CapacityManager` deleted | SATISFIED | `txLike: ccc.TransactionLike` present in all 5 library packages across 20+ method signatures; `capacity.ts` deleted |
+| SMTX-02 | 01-03-PLAN.md | `SmartTransaction` class and its `completeFee()` override deleted from `@ickb/utils` | SATISFIED | `transaction.ts` deleted; zero `SmartTransaction` references anywhere in `packages/` or `apps/` |
+| SMTX-04 | 01-02-PLAN.md | `getHeader()` and `HeaderKey` removed from `@ickb/utils`; all call sites inline CCC client calls | SATISFIED | Zero `getHeader`/`HeaderKey` references in `packages/utils/src/`; all 7 call sites inline `client.getTransactionWithHeader()` or `client.getHeaderByNumber()` with null-check-throws |
+| SMTX-05 | 01-03-PLAN.md | UDT handler registration (`addUdtHandlers()`) replaced | SATISFIED | Zero `addUdtHandlers` references in `packages/`; 7 replacement sites use `tx.addCellDeps(this.udtHandler.cellDeps)` — note: `UdtHandler`/`UdtManager` themselves are preserved (removal deferred to Phase 4-5 as documented in REQUIREMENTS.md traceability) |
+| SMTX-06 | 01-01-PLAN.md | 64-output NervosDAO limit check consolidated into single utility | SATISFIED | `assertDaoOutputLimit` in CCC core; `ErrorNervosDaoOutputLimit` in CCC core; zero inline `outputs.length > 64` checks in `packages/`; called from 6 sites across dao/core |
+
+**Note on SMTX-05 scope**: REQUIREMENTS.md marks SMTX-05 as Complete at Phase 1 with the note "addUdtHandlers() replaced with tx.addCellDeps(udtHandler.cellDeps) (01-03); UdtHandler/UdtManager replacement deferred to Phase 4-5". This is correct — the handler registration is replaced but the classes themselves are intentionally preserved for Phase 3+ investigation.
+
+**Note on SMTX-06 count**: The plan cited "all 7 scattered checks" but 6 call sites were found in actual packages (3 in `dao.ts`, 1 in `logic.ts`, 2 in `owned_owner.ts`). The 7th was in `SmartTransaction.completeFee` (packages/utils/src/transaction.ts), which is now deleted — the CCC `completeFee` safety net (2 call sites) now covers that responsibility. This is correct behaviour.
+
+### Anti-Patterns Found
+
+None found. Specific scans conducted:
+
+- `grep -rn "TODO|FIXME|PLACEHOLDER" packages/` (non-dist): No results in modified files.
+- `grep -rn "return null|return \{\}" packages/` on new code: No stub patterns.
+- `grep "outputs.length > 64" packages/`: Zero results (old inline checks fully removed).
+- `grep "SmartTransaction" packages/ apps/`: Zero results.
+- `grep "CapacityManager" packages/ apps/`: Zero results.
+- `grep "addUdtHandlers" packages/`: Zero results.
+- `grep "HeaderKey" packages/`: Zero results.
+- `grep "getHeader\b" packages/ apps/` (non-dist): Zero results.
+- `grep "addHeaders" packages/`: Zero results.
+
+### Human Verification Required
+
+None. All success criteria are statically verifiable:
+
+- File existence/deletion: verified with `ls`.
+- Class/function presence: verified with `grep`.
+- Build status: verified with `pnpm check` (passed — all 5 packages compiled clean).
+- Commit hash existence: all 5 task commits confirmed in `git log`.
+
+### Gaps Summary
+
+No gaps. All 6 observable truths are fully verified.
+
+All 5 library packages (`@ickb/utils`, `@ickb/dao`, `@ickb/order`, `@ickb/core`, `@ickb/sdk`) compile with zero type errors under strict TypeScript settings after the changes. The `pnpm check` script (clean, install, lint, build, test) passed on the current state of the repository.
+
+---
+
+_Verified: 2026-02-22T17:30:00Z_
+_Verifier: AI Coworker (gsd-verifier)_
diff --git a/.pnpmfile.cjs b/.pnpmfile.cjs
index 4b35f4a..ce3cee7 100644
--- a/.pnpmfile.cjs
+++ b/.pnpmfile.cjs
@@ -2,7 +2,7 @@
//
// 1. Auto-replay: clone + patch CCC on first `pnpm install` (if pins exist).
// replay.sh handles git clone, merge replay, lockfile removal, and source
-// patching (jq exports rewrite + @ts-nocheck). It does NOT run pnpm install
+// patching (jq exports rewrite). It does NOT run pnpm install
// internally — the root workspace install handles CCC deps alongside
// everything else.
//
@@ -24,7 +24,10 @@ const cccCache = join(__dirname, "ccc-dev", "ccc");
const cccRefs = join(__dirname, "ccc-dev", "pins", "REFS");
// 1. Auto-replay CCC pins on first pnpm install
-if (!existsSync(cccCache) && existsSync(cccRefs)) {
+// Skip when ccc:record is running — it rebuilds pins from scratch.
+// Detect via argv since pnpmfile loads before npm_lifecycle_event is set.
+const isCccRecord = process.argv.some((a) => a === "ccc:record");
+if (!isCccRecord && !existsSync(cccCache) && existsSync(cccRefs)) {
try {
execSync("bash ccc-dev/replay.sh", {
cwd: __dirname,
diff --git a/AGENTS.md b/AGENTS.md
index ba0eb5c..37889aa 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -7,12 +7,6 @@
- Refer to yourself as "AI Coworker" in docs and comments, not by product or company name
- Never add AI tool attribution or branding to PR descriptions, commit messages, or code comments
- Do not install or use `gh` CLI
-
-## Workflows
-
-- **Routine Pre-PR Validation**: `pnpm check:full`, it wipes derived state and regenerates from scratch. If `ccc-dev/ccc/` has pending work, the wipe is skipped to prevent data loss — re-record or push CCC changes first for a clean validation
-- **Open a PR**: Push the branch, then present a clickable markdown link `[title](url)` where the URL is a GitHub compare URL (`quick_pull=1`). Base branch is `master`. Prefill "title" (concise, under 70 chars) and "body" (markdown with ## Why and ## Changes sections)
-- **Fetch PR review comments**: Use the GitHub REST API via curl. Fetch all three comment types (issue comments, reviews, and inline comments). Reviewers reply asynchronously — poll every minute until comments arrive
- **Copy to clipboard**:
```sh
@@ -21,11 +15,17 @@
EOF
```
+## PR Workflow
+
+1. **Routine Pre-PR Validation**: `pnpm check:full`, it wipes derived state and regenerates from scratch. If `ccc-dev/ccc/` has pending work, the wipe is skipped to prevent data loss — re-record or push CCC changes first for a clean validation
+2. **Open a PR**: Run `pnpm changeset` to generate a changeset entry, then push the branch and present a clickable markdown link `[title](url)` where the URL is a GitHub compare URL (`quick_pull=1`). Base branch is `master`. Prefill "title" (concise, under 70 chars) and "body" (markdown with ## Why and ## Changes sections)
+3. **Fetch PR review comments**: Use the GitHub REST API via curl. Fetch all three comment types (issue comments, reviews, and inline comments). Categorize feedback by actionability (action required / informational), not by source (human / bot). Reviewers reply asynchronously — poll every minute until comments arrive
+
## CCC Local Development (ccc-dev/)
The `ccc-dev/` system uses a record/replay mechanism for deterministic builds of a local CCC fork:
-- `ccc-dev/pins/` is **committed** to git (base SHAs, merge refs, conflict resolutions), regenerated by `pnpm ccc:record`
+- `ccc-dev/pins/` is **committed** to git (base SHAs, merge refs, conflict resolutions, local patches), regenerated by `pnpm ccc:record`
- `ccc-dev/ccc/` is **not in git** — it is rebuilt from pins on `pnpm install`
- The developer may have **pending work** in `ccc-dev/ccc/`. Run `pnpm ccc:status` (exit 0 = safe to wipe, exit 1 = has custom work) before any operation that would destroy it. `pnpm ccc:record`, `pnpm ccc:clean`, and `pnpm ccc:reset` already guard against this automatically
- `.pnpmfile.cjs` silently rewrites all `@ckb-ccc/*` dependencies to `workspace:*` when `ccc-dev/ccc/` exists. Local CCC packages override published ones without any visible change in package.json files
@@ -33,13 +33,20 @@ The `ccc-dev/` system uses a record/replay mechanism for deterministic builds of
- `ccc-dev/patch.sh` rewrites CCC package exports to point at `.ts` source instead of `.d.ts`, then creates a deterministic git commit (fixed author/date) so record and replay produce the same `pins/HEAD` hash. This is why imports from `@ckb-ccc/*` resolve to TypeScript source files inside `node_modules` — it is not a bug
- `ccc-dev/tsgo-filter.sh` is a bash wrapper around `tsgo` that filters out diagnostics originating from `ccc-dev/ccc/`. CCC source does not satisfy this repo's strict tsconfig (`verbatimModuleSyntax`, `noUncheckedIndexedAccess`, `noImplicitOverride`), so the wrapper suppresses those errors while still reporting errors in stack source
-## Reference Repos
+### Opening a CCC upstream PR
+
+In `ccc-dev/ccc/`, branch off `origin/master` (or relevant branch), push to fork (`phroi/ccc`), open PR against `ckb-devrel/ccc`. Before pushing, run the CCC CI steps (`ccc-dev/ccc/.github/workflows/check.yaml`) with `CI=true`.
-`reference/` contains read-only clones (project knowledge, dependency sources, etc.) fetched via `pnpm reference`. To refresh, delete the directory and re-run `pnpm reference`
+Once the PR is open, replace the local patch with a merge ref:
-## Versioning
+1. Delete the patch from `ccc-dev/pins/local/`
+2. Add the PR number to `ccc:record` in `package.json` — order PRs by target branch from upstream to downstream, so each group merges cleanly onto its base before the next layer begins
+3. Run `pnpm ccc:record`
+4. Run `pnpm check:full` to verify the merge ref reproduces what the local patch achieved
+
+## Reference Repos
-All packages use version `1001.0.0` (Epoch Semantic Versioning), managed by changesets (`pnpm changeset`)
+`reference/` contains read-only clones (project knowledge, dependency sources, etc.) fetched via `pnpm reference`. To refresh, just re-run `pnpm reference`. If a task requires knowledge of an external repo not yet cloned, add it to `reference/clone.sh` and run `pnpm reference` to fetch it for consultation
## Knowledge
diff --git a/apps/bot/tsconfig.json b/apps/bot/tsconfig.json
index 68226cd..80da643 100644
--- a/apps/bot/tsconfig.json
+++ b/apps/bot/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
+ "noEmit": false,
"rootDir": "src",
"outDir": "dist",
"sourceRoot": "../src"
diff --git a/apps/faucet/src/main.ts b/apps/faucet/src/main.ts
index b14cfc4..8818436 100644
--- a/apps/faucet/src/main.ts
+++ b/apps/faucet/src/main.ts
@@ -1,11 +1,5 @@
import { ccc } from "@ckb-ccc/core";
-import {
- CapacityManager,
- collect,
- hexFrom,
- SmartTransaction,
- sum,
-} from "@ickb/utils";
+import { hexFrom, sum, unique } from "@ickb/utils";
import { getRandomValues } from "crypto";
import { exit } from "process";
@@ -33,8 +27,6 @@ export async function main(): Promise {
console.log(dummyAddress.toString());
console.log();
- const capacityManager = CapacityManager.withEmptyData();
-
for (;;) {
await new Promise((r) => {
setTimeout(r, 120000);
@@ -53,23 +45,50 @@ export async function main(): Promise {
const startTime = new Date();
executionLog.startTime = startTime.toLocaleString();
try {
- const capacities = await collect(
- capacityManager.findCapacities(client, [dummyAddress.script]),
- );
+ const capacities: ccc.Cell[] = [];
+ for (const lock of unique([dummyAddress.script])) {
+ for await (const cell of client.findCellsOnChain(
+ {
+ script: lock,
+ scriptType: "lock",
+ filter: {
+ scriptLenRange: [0n, 1n],
+ outputDataLenRange: [0n, 1n],
+ },
+ scriptSearchMode: "exact",
+ withData: true,
+ },
+ "asc",
+ 400,
+ )) {
+ if (
+ cell.cellOutput.type !== undefined ||
+ !cell.cellOutput.lock.eq(lock)
+ ) {
+ continue;
+ }
+ capacities.push(cell);
+ }
+ }
if (capacities.length === 0) {
console.log("No faucet funds to transfer, shutting down...");
exit(0);
}
- const ckbBalance = sum(0n, ...capacities.map((c) => c.ckbValue));
+ const ckbBalance = sum(
+ 0n,
+ ...capacities.map((c) => c.cellOutput.capacity),
+ );
executionLog.balance = {
CKB: ccc.fixedPointToString(ckbBalance),
};
- const tx = SmartTransaction.default();
- capacityManager.addCapacities(tx, capacities);
+ const tx = ccc.Transaction.default();
+ for (const cell of capacities) {
+ tx.addInput(cell);
+ }
await tx.completeFeeChangeToLock(dummyAccount, realAccount.script);
executionLog.txHash = await dummyAccount.sendTransaction(tx);
} catch (e) {
diff --git a/apps/faucet/tsconfig.json b/apps/faucet/tsconfig.json
index 68226cd..80da643 100644
--- a/apps/faucet/tsconfig.json
+++ b/apps/faucet/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
+ "noEmit": false,
"rootDir": "src",
"outDir": "dist",
"sourceRoot": "../src"
diff --git a/apps/sampler/tsconfig.json b/apps/sampler/tsconfig.json
index 68226cd..80da643 100644
--- a/apps/sampler/tsconfig.json
+++ b/apps/sampler/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
+ "noEmit": false,
"rootDir": "src",
"outDir": "dist",
"sourceRoot": "../src"
diff --git a/apps/tester/tsconfig.json b/apps/tester/tsconfig.json
index 68226cd..80da643 100644
--- a/apps/tester/tsconfig.json
+++ b/apps/tester/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
+ "noEmit": false,
"rootDir": "src",
"outDir": "dist",
"sourceRoot": "../src"
diff --git a/ccc-dev/README.md b/ccc-dev/README.md
index 170e7df..a920368 100644
--- a/ccc-dev/README.md
+++ b/ccc-dev/README.md
@@ -12,17 +12,19 @@ CCC has unreleased branches (`releases/next`, `releases/udt`) that this project
3. **Source-level types** — `patch.sh` (called by both `record.sh` and `replay.sh`) patches CCC's `package.json` exports to point TypeScript at `.ts` source instead of built `.d.ts`, then creates a deterministic git commit (fixed author/date) so record and replay produce the same `pins/HEAD` hash. This gives real-time type feedback when editing across the CCC/stack boundary — changes in CCC source are immediately visible to stack packages without rebuilding.
-4. **Diagnostic filtering** — `ccc-dev/tsc.mjs` is a tsc wrapper used by stack package builds. Because CCC `.ts` source is type-checked under the stack's stricter tsconfig (`verbatimModuleSyntax`, `noImplicitOverride`, `noUncheckedIndexedAccess`), plain `tsc` would report hundreds of CCC diagnostics that aren't real integration errors. The wrapper emits output normally and only fails on diagnostics from stack source files. When CCC is not cloned, packages fall back to plain `tsc`.
+4. **Diagnostic filtering** — `ccc-dev/tsgo-filter.sh` is a bash wrapper around `tsgo` used by stack package builds. Because CCC `.ts` source is type-checked under the stack's stricter tsconfig (`verbatimModuleSyntax`, `noImplicitOverride`, `noUncheckedIndexedAccess`), plain `tsgo` would report hundreds of CCC diagnostics that aren't real integration errors. The wrapper emits output normally and only fails on diagnostics from stack source files. When CCC is not cloned, packages fall back to plain `tsgo`.
## `pins/` format
```
ccc-dev/pins/
REFS # Line 1: base SHA. Lines 2+: "SHA refname" (one per merge)
- HEAD # Expected final SHA after all merges (integrity check)
+ HEAD # Expected final SHA after all merges + patches (integrity check)
resolutions/ # Saved conflict resolution files, organized by merge index
1/path/to/file # Resolved file for merge step 1
2/path/to/file # Resolved file for merge step 2
+ local/ # Git patch files applied after merges + source patching
+ 001-name.patch # Applied in sorted filename order with deterministic commits
```
## Recording
@@ -63,6 +65,20 @@ bash ccc-dev/record.sh abc1234
Refs are merged sequentially onto a `wip` branch, then CCC is built. On merge conflicts, the script auto-resolves them using AI Coworker.
+## Local patches
+
+Local patches (`pins/local/*.patch`) are project-specific changes applied to CCC on top of the merged upstream refs. They are committed to git alongside other pins and applied deterministically during both recording and replay.
+
+Use local patches for CCC changes that this project needs but that haven't been merged upstream yet (e.g., a DAO safety check contributed via a CCC PR).
+
+To create a local patch:
+
+1. Make changes in `ccc-dev/ccc/` on the `wip` branch
+2. Generate a patch: `git -C ccc-dev/ccc diff > ccc-dev/pins/local/001-description.patch`
+3. Re-record to verify: `pnpm ccc:record`
+
+Patches are applied in sorted filename order. Use numeric prefixes (`001-`, `002-`) to control ordering. Both `record.sh` and `replay.sh` apply local patches with deterministic git identity and timestamps so the resulting `pins/HEAD` hash is reproducible.
+
## Developing CCC PRs
### Setup
diff --git a/ccc-dev/pins/HEAD b/ccc-dev/pins/HEAD
index d2b2d1a..2112815 100644
--- a/ccc-dev/pins/HEAD
+++ b/ccc-dev/pins/HEAD
@@ -1 +1 @@
-ddd976a81f71d14135714a2b365cb6e3653126fc
+0c76ce0de0a3306dd7c466a933d43f44b32f7450
diff --git a/ccc-dev/pins/REFS b/ccc-dev/pins/REFS
index 7948f00..eb53521 100644
--- a/ccc-dev/pins/REFS
+++ b/ccc-dev/pins/REFS
@@ -1,3 +1,4 @@
50d657beea36de3ebbd80ee88209842644daef34
+8e63e3a21f1824445b2c339ffe4927a2a8af1bcf 359
0e18748fb139d71338c109d71aae5b149cb58af3 releases/next
0ad2a5f6305d4964b00394bc8a6ed50136fdffa8 releases/udt
diff --git a/ccc-dev/pins/resolutions/3/packages/core/src/ckb/transactionErrors.ts b/ccc-dev/pins/resolutions/3/packages/core/src/ckb/transactionErrors.ts
new file mode 100644
index 0000000..692af12
--- /dev/null
+++ b/ccc-dev/pins/resolutions/3/packages/core/src/ckb/transactionErrors.ts
@@ -0,0 +1,52 @@
+import { fixedPointToString } from "../fixedPoint/index.js";
+import { Num, numFrom, NumLike } from "../num/index.js";
+import { Script, ScriptLike } from "./script.js";
+
+export class ErrorTransactionInsufficientCapacity extends Error {
+ public readonly amount: Num;
+ public readonly isForChange: boolean;
+
+ constructor(
+ amountLike: NumLike,
+ reason?: {
+ isForChange?: boolean;
+ },
+ ) {
+ const amount = numFrom(amountLike);
+ const isForChange = reason?.isForChange ?? false;
+ super(
+ `Insufficient CKB, need ${fixedPointToString(amount)} extra CKB${isForChange ? " for the change cell" : ""}`,
+ );
+ this.amount = amount;
+ this.isForChange = isForChange;
+ }
+}
+
+export class ErrorNervosDaoOutputLimit extends Error {
+ public readonly count: number;
+ public readonly limit: number;
+
+ constructor(count: number) {
+ super(
+ `NervosDAO transaction has ${count} output cells, exceeding the limit of 64`,
+ );
+ this.count = count;
+ this.limit = 64;
+ }
+}
+
+/**
+ * @deprecated Use `ErrorUdtInsufficientCoin` from `@ckb-ccc/udt` instead.
+ */
+export class ErrorTransactionInsufficientCoin extends Error {
+ public readonly amount: Num;
+ public readonly type: Script;
+
+ constructor(amountLike: NumLike, typeLike: ScriptLike) {
+ const amount = numFrom(amountLike);
+ const type = Script.from(typeLike);
+ super(`Insufficient coin, need ${amount} extra coin`);
+ this.amount = amount;
+ this.type = type;
+ }
+}
diff --git a/ccc-dev/pins/resolutions/2/vitest.config.mts b/ccc-dev/pins/resolutions/3/vitest.config.mts
similarity index 100%
rename from ccc-dev/pins/resolutions/2/vitest.config.mts
rename to ccc-dev/pins/resolutions/3/vitest.config.mts
diff --git a/ccc-dev/record.sh b/ccc-dev/record.sh
index c9c5f8b..f243cb8 100644
--- a/ccc-dev/record.sh
+++ b/ccc-dev/record.sh
@@ -22,10 +22,25 @@ if ! bash "$SCRIPT_DIR/status.sh" >/dev/null 2>&1; then
exit 1
fi
-# Always start fresh — wipe previous clone and pins
+# Always start fresh — wipe previous clone and pins (preserve local patches)
+LOCAL_BAK=""
+if [ -d "$PATCH_DIR/local" ]; then
+ LOCAL_BAK=$(mktemp -d)
+ cp -r "$PATCH_DIR/local" "$LOCAL_BAK/local"
+fi
rm -rf "$REPO_DIR" "$PATCH_DIR"
-trap 'rm -rf "$REPO_DIR" "$PATCH_DIR"; echo "FAILED — cleaned up ccc-dev/ccc/ and pins/" >&2' ERR
+cleanup_on_error() {
+ rm -rf "$REPO_DIR" "$PATCH_DIR"
+ # Restore local patches from backup so they aren't lost on failure
+ if [ -n "${LOCAL_BAK:-}" ] && [ -d "$LOCAL_BAK/local" ]; then
+ mkdir -p "$PATCH_DIR"
+ cp -r "$LOCAL_BAK/local" "$PATCH_DIR/local"
+ rm -rf "$LOCAL_BAK"
+ fi
+ echo "FAILED — cleaned up ccc-dev/ccc/ and pins/ (local patches preserved)" >&2
+}
+trap cleanup_on_error ERR
git clone --filter=blob:none "$REPO_URL" "$REPO_DIR"
@@ -109,6 +124,33 @@ done
bash "$SCRIPT_DIR/patch.sh" "$REPO_DIR" "$MERGE_IDX"
+# Restore preserved local patches
+if [ -n "$LOCAL_BAK" ] && [ -d "$LOCAL_BAK/local" ]; then
+ mkdir -p "$PATCH_DIR"
+ cp -r "$LOCAL_BAK/local" "$PATCH_DIR/local"
+ rm -rf "$LOCAL_BAK"
+fi
+
+# Apply local patches (sorted by filename for deterministic order)
+LOCAL_DIR="$PATCH_DIR/local"
+if [ -d "$LOCAL_DIR" ]; then
+ LOCAL_IDX=$((MERGE_IDX + 2))
+ for PATCH_FILE in $(find "$LOCAL_DIR" -name '*.patch' | sort); do
+ PATCH_NAME=$(basename "$PATCH_FILE" .patch)
+ echo "Applying local patch: $PATCH_NAME"
+
+ export GIT_AUTHOR_NAME="ci" GIT_AUTHOR_EMAIL="ci@local"
+ export GIT_COMMITTER_NAME="ci" GIT_COMMITTER_EMAIL="ci@local"
+ export GIT_AUTHOR_DATE="@$LOCAL_IDX +0000"
+ export GIT_COMMITTER_DATE="@$LOCAL_IDX +0000"
+
+ git -C "$REPO_DIR" apply "$PATCH_FILE"
+ git -C "$REPO_DIR" add -A
+ git -C "$REPO_DIR" commit -m "$PATCH_NAME"
+ LOCAL_IDX=$((LOCAL_IDX + 1))
+ done
+fi
+
# Prepend BASE SHA as first line of REFS
mkdir -p "$PATCH_DIR"
if [ -f "$PATCH_DIR/REFS" ]; then
diff --git a/ccc-dev/replay.sh b/ccc-dev/replay.sh
index d07feff..18331c4 100644
--- a/ccc-dev/replay.sh
+++ b/ccc-dev/replay.sh
@@ -78,6 +78,26 @@ done < <(tail -n +2 "$PATCH_DIR/REFS")
bash "$SCRIPT_DIR/patch.sh" "$REPO_DIR" "$MERGE_IDX"
+# Apply local patches (sorted by filename for deterministic order)
+LOCAL_DIR="$PATCH_DIR/local"
+if [ -d "$LOCAL_DIR" ]; then
+ LOCAL_IDX=$((MERGE_IDX + 2))
+ for PATCH_FILE in $(find "$LOCAL_DIR" -name '*.patch' | sort); do
+ PATCH_NAME=$(basename "$PATCH_FILE" .patch)
+ echo "Applying local patch: $PATCH_NAME" >&2
+
+ export GIT_AUTHOR_NAME="ci" GIT_AUTHOR_EMAIL="ci@local"
+ export GIT_COMMITTER_NAME="ci" GIT_COMMITTER_EMAIL="ci@local"
+ export GIT_AUTHOR_DATE="@$LOCAL_IDX +0000"
+ export GIT_COMMITTER_DATE="@$LOCAL_IDX +0000"
+
+ git -C "$REPO_DIR" apply "$PATCH_FILE"
+ git -C "$REPO_DIR" add -A
+ git -C "$REPO_DIR" commit -m "$PATCH_NAME"
+ LOCAL_IDX=$((LOCAL_IDX + 1))
+ done
+fi
+
# Verify HEAD SHA matches recording
ACTUAL=$(git -C "$REPO_DIR" rev-parse HEAD)
EXPECTED=$(cat "$PATCH_DIR/HEAD")
@@ -87,4 +107,7 @@ if [ "$ACTUAL" != "$EXPECTED" ]; then
exit 1
fi
+# Add fork remote for pushing to phroi/ccc (SSH for auth)
+git -C "$REPO_DIR" remote add fork git@github.com:phroi/ccc.git
+
echo "OK — replay HEAD matches pinned HEAD ($EXPECTED)"
diff --git a/package.json b/package.json
index bfe855b..c5cd4de 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"private": true,
"scripts": {
- "ccc:record": "bash ccc-dev/record.sh releases/next releases/udt",
+ "ccc:record": "bash ccc-dev/record.sh 359 releases/next releases/udt",
"ccc:status": "bash ccc-dev/status.sh",
"ccc:push": "bash ccc-dev/push.sh",
"ccc:clean": "bash ccc-dev/status.sh && rm -rf ccc-dev/ccc",
diff --git a/packages/core/src/cells.ts b/packages/core/src/cells.ts
index 4f8956d..7b346fc 100644
--- a/packages/core/src/cells.ts
+++ b/packages/core/src/cells.ts
@@ -1,9 +1,5 @@
import { ccc } from "@ckb-ccc/core";
-import {
- getHeader,
- type TransactionHeader,
- type ValueComponents,
-} from "@ickb/utils";
+import { type TransactionHeader, type ValueComponents } from "@ickb/utils";
import { OwnerData, ReceiptData } from "./entities.js";
import { ickbValue } from "./udt.js";
import { daoCellFrom, type DaoCell } from "@ickb/dao";
@@ -80,11 +76,13 @@ export async function receiptCellFrom(
}
const txHash = cell.outPoint.txHash;
- const header = {
- header: await getHeader(options.client, {
- type: "txHash",
- value: txHash,
- }),
+ const txWithHeader =
+ await options.client.getTransactionWithHeader(txHash);
+ if (!txWithHeader?.header) {
+ throw new Error("Header not found for txHash");
+ }
+ const header: TransactionHeader = {
+ header: txWithHeader.header,
txHash,
};
const { depositQuantity, depositAmount } = ReceiptData.decode(
diff --git a/packages/core/src/logic.ts b/packages/core/src/logic.ts
index eb8f647..0311b3a 100644
--- a/packages/core/src/logic.ts
+++ b/packages/core/src/logic.ts
@@ -3,7 +3,6 @@ import { DaoManager } from "@ickb/dao";
import {
defaultFindCellsLimit,
type ScriptDeps,
- type SmartTransaction,
type UdtHandler,
unique,
} from "@ickb/utils";
@@ -60,19 +59,21 @@ export class LogicManager implements ScriptDeps {
/**
* Processes a deposit transaction.
*
- * @param tx - The transaction to add the deposit to.
+ * @param txLike - The transaction to add the deposit to.
* @param depositQuantity - The quantity of deposits.
* @param depositAmount - The amount of each deposit.
* @param lock - The lock script for the output receipt cell.
*/
- deposit(
- tx: SmartTransaction,
+ async deposit(
+ txLike: ccc.TransactionLike,
depositQuantity: number,
depositAmount: ccc.FixedPoint,
lock: ccc.Script,
- ): void {
+ client: ccc.Client,
+ ): Promise {
+ let tx = ccc.Transaction.from(txLike);
if (depositQuantity <= 0) {
- return;
+ return tx;
}
if (depositAmount < ccc.fixedPointFrom(1082)) {
@@ -84,13 +85,13 @@ export class LogicManager implements ScriptDeps {
}
tx.addCellDeps(this.cellDeps);
- tx.addUdtHandlers(this.udtHandler);
+ tx.addCellDeps(this.udtHandler.cellDeps);
const capacities = Array.from(
{ length: depositQuantity },
() => depositAmount,
);
- this.daoManager.deposit(tx, capacities, this.script);
+ tx = await this.daoManager.deposit(tx, capacities, this.script, client);
// Add the Receipt to the outputs
tx.addOutput(
@@ -101,32 +102,39 @@ export class LogicManager implements ScriptDeps {
ReceiptData.encode({ depositQuantity, depositAmount }),
);
- // Check that there are at most 64 output cells, see:
- // https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md#gotchas
- if (tx.outputs.length > 64) {
- throw new Error("More than 64 output cells in a NervosDAO transaction");
- }
+ await ccc.assertDaoOutputLimit(tx, client);
+ return tx;
}
/**
* Completes a deposit transaction by transforming the receipts into iCKB UDTs.
*
- * @param tx - The transaction to add the receipts to.
+ * @param txLike - The transaction to add the receipts to.
* @param receipts - The receipts to add to the transaction.
*/
- completeDeposit(tx: SmartTransaction, receipts: ReceiptCell[]): void {
+ completeDeposit(
+ txLike: ccc.TransactionLike,
+ receipts: ReceiptCell[],
+ ): ccc.Transaction {
+ const tx = ccc.Transaction.from(txLike);
if (receipts.length === 0) {
- return;
+ return tx;
}
tx.addCellDeps(this.cellDeps);
- tx.addUdtHandlers(this.udtHandler);
+ tx.addCellDeps(this.udtHandler.cellDeps);
- tx.addHeaders(receipts.map((r) => r.header));
+ for (const r of receipts) {
+ const hash = r.header.header.hash;
+ if (!tx.headerDeps.some((h) => h === hash)) {
+ tx.headerDeps.push(hash);
+ }
+ }
for (const { cell } of receipts) {
tx.addInput(cell);
}
+ return tx;
}
/**
diff --git a/packages/core/src/owned_owner.ts b/packages/core/src/owned_owner.ts
index 037ccf3..ff63e45 100644
--- a/packages/core/src/owned_owner.ts
+++ b/packages/core/src/owned_owner.ts
@@ -3,7 +3,6 @@ import {
defaultFindCellsLimit,
unique,
type ScriptDeps,
- type SmartTransaction,
type UdtHandler,
} from "@ickb/utils";
import { daoCellFrom, DaoManager } from "@ickb/dao";
@@ -59,33 +58,41 @@ export class OwnedOwnerManager implements ScriptDeps {
/**
* Requests a withdrawal for the specified deposits.
*
- * @param tx - The transaction to add the withdrawal request to.
+ * @param txLike - The transaction to add the withdrawal request to.
* @param deposits - The deposits to withdraw.
* @param lock - The lock script for the output.
* @param options - Optional parameters for the withdrawal request.
* @param options.isReadyOnly - Whether to only process ready deposits (default: false).
* @returns void
*/
- requestWithdrawal(
- tx: SmartTransaction,
+ async requestWithdrawal(
+ txLike: ccc.TransactionLike,
deposits: IckbDepositCell[],
lock: ccc.Script,
+ client: ccc.Client,
options?: {
isReadyOnly?: boolean;
},
- ): void {
+ ): Promise {
+ let tx = ccc.Transaction.from(txLike);
const isReadyOnly = options?.isReadyOnly ?? false;
if (isReadyOnly) {
deposits = deposits.filter((d) => d.isReady);
}
if (deposits.length === 0) {
- return;
+ return tx;
}
options = { ...options, isReadyOnly: false }; // non isReady deposits already filtered
- this.daoManager.requestWithdrawal(tx, deposits, this.script, options);
+ tx = await this.daoManager.requestWithdrawal(
+ tx,
+ deposits,
+ this.script,
+ client,
+ options,
+ );
tx.addCellDeps(this.cellDeps);
- tx.addUdtHandlers(this.udtHandler);
+ tx.addCellDeps(this.udtHandler.cellDeps);
const outputData = OwnerData.encode({ ownedDistance: -deposits.length });
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -99,53 +106,49 @@ export class OwnedOwnerManager implements ScriptDeps {
);
}
- // Check that there are at most 64 output cells, see:
- // https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md#gotchas
- if (tx.outputs.length > 64) {
- throw new Error("More than 64 output cells in a NervosDAO transaction");
- }
+ await ccc.assertDaoOutputLimit(tx, client);
+ return tx;
}
/**
* Completes the withdrawals of the specified withdrawal groups.
*
- * @param tx - The transaction to add the withdrawals to.
+ * @param txLike - The transaction to add the withdrawals to.
* @param withdrawalGroups - The withdrawal groups to process.
* @param options - Optional parameters for the withdrawal process.
* @param options.isReadyOnly - Whether to only process ready withdrawal groups (default: false).
* @returns void
*/
- withdraw(
- tx: SmartTransaction,
+ async withdraw(
+ txLike: ccc.TransactionLike,
withdrawalGroups: WithdrawalGroup[],
+ client: ccc.Client,
options?: {
isReadyOnly?: boolean;
},
- ): void {
+ ): Promise {
+ let tx = ccc.Transaction.from(txLike);
const isReadyOnly = options?.isReadyOnly ?? false;
if (isReadyOnly) {
withdrawalGroups = withdrawalGroups.filter((g) => g.owned.isReady);
}
if (withdrawalGroups.length === 0) {
- return;
+ return tx;
}
- options = { ...options, isReadyOnly: false }; // non isReady deposits already filtered
tx.addCellDeps(this.cellDeps);
- tx.addUdtHandlers(this.udtHandler);
+ tx.addCellDeps(this.udtHandler.cellDeps);
const requests = withdrawalGroups.map((g) => g.owned);
- this.daoManager.withdraw(tx, requests);
+ tx = await this.daoManager.withdraw(tx, requests, client);
for (const { owner } of withdrawalGroups) {
tx.addInput(owner.cell);
}
- // Check that there are at most 64 output cells, see:
- // https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md#gotchas
- if (tx.outputs.length > 64) {
- throw new Error("More than 64 output cells in a NervosDAO transaction");
- }
+ // assertDaoOutputLimit already called inside daoManager.withdraw;
+ // only owner inputs (not outputs) are added after, so no re-check needed.
+ return tx;
}
/**
diff --git a/packages/core/src/udt.ts b/packages/core/src/udt.ts
index d348d02..276fcb2 100644
--- a/packages/core/src/udt.ts
+++ b/packages/core/src/udt.ts
@@ -1,12 +1,7 @@
import { ccc } from "@ckb-ccc/core";
import { ReceiptData } from "./entities.js";
import type { DaoManager } from "@ickb/dao";
-import {
- UdtManager,
- type ExchangeRatio,
- type SmartTransaction,
- type UdtHandler,
-} from "@ickb/utils";
+import { UdtManager, type ExchangeRatio, type UdtHandler } from "@ickb/utils";
/**
* IckbUdtManager is a class that implements the UdtHandler interface.
@@ -63,15 +58,16 @@ export class IckbUdtManager extends UdtManager implements UdtHandler {
* for a given transaction.
*
* @param client - The CKB client to query cell data.
- * @param tx - The smart transaction whose inputs are to be balanced.
+ * @param txLike - The transaction whose inputs are to be balanced.
* @returns A promise resolving to a tuple:
* - [0]: Total iCKB UDT amount in inputs (as `ccc.FixedPoint`).
* - [1]: Total capacity in UDT-related inputs (as `ccc.FixedPoint`).
*/
override async getInputsUdtBalance(
client: ccc.Client,
- tx: SmartTransaction,
+ txLike: ccc.TransactionLike,
): Promise<[ccc.FixedPoint, ccc.FixedPoint]> {
+ const tx = ccc.Transaction.from(txLike);
return ccc.reduceAsync(
tx.inputs,
async (acc, input) => {
@@ -104,31 +100,36 @@ export class IckbUdtManager extends UdtManager implements UdtHandler {
// An iCKB Receipt
if (this.logicScript.eq(type)) {
- // Get header of Receipt cell and check its inclusion in HeaderDeps
- const header = await tx.getHeader(client, {
- type: "txHash",
- value: outPoint.txHash,
- });
+ // Get header of Receipt cell
+ const txWithHeader = await client.getTransactionWithHeader(
+ outPoint.txHash,
+ );
+ if (!txWithHeader?.header) {
+ throw new Error("Header not found for txHash");
+ }
const { depositQuantity, depositAmount } =
ReceiptData.decode(outputData);
return [
- udtValue + ickbValue(depositAmount, header) * depositQuantity,
+ udtValue +
+ ickbValue(depositAmount, txWithHeader.header) * depositQuantity,
capacity + cellOutput.capacity,
];
}
// An iCKB Deposit for which the withdrawal is being requested
if (this.logicScript.eq(lock) && this.daoManager.isDeposit(cell)) {
- // Get header of Deposit cell and check its inclusion in HeaderDeps
- const header = await tx.getHeader(client, {
- type: "txHash",
- value: outPoint.txHash,
- });
+ // Get header of Deposit cell
+ const txWithHeader = await client.getTransactionWithHeader(
+ outPoint.txHash,
+ );
+ if (!txWithHeader?.header) {
+ throw new Error("Header not found for txHash");
+ }
return [
- udtValue - ickbValue(cell.capacityFree, header),
+ udtValue - ickbValue(cell.capacityFree, txWithHeader.header),
capacity + cellOutput.capacity,
];
}
diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json
index 68226cd..80da643 100644
--- a/packages/core/tsconfig.json
+++ b/packages/core/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
+ "noEmit": false,
"rootDir": "src",
"outDir": "dist",
"sourceRoot": "../src"
diff --git a/packages/dao/src/cells.ts b/packages/dao/src/cells.ts
index c75c814..c3b5bcb 100644
--- a/packages/dao/src/cells.ts
+++ b/packages/dao/src/cells.ts
@@ -1,9 +1,5 @@
import { ccc, mol } from "@ckb-ccc/core";
-import {
- getHeader,
- type TransactionHeader,
- type ValueComponents,
-} from "@ickb/utils";
+import { type TransactionHeader, type ValueComponents } from "@ickb/utils";
/**
* Represents a DAO cell with its associated properties.
@@ -83,36 +79,39 @@ export async function daoCellFrom(
const tip = options.tip;
const txHash = cell.outPoint.txHash;
- const oldest =
- "headers" in options
- ? options.headers[0]
- : !isDeposit
- ? {
- header: await getHeader(options.client, {
- type: "number",
- value: mol.Uint64LE.decode(cell.outputData),
- }),
- }
- : {
- header: await getHeader(options.client, {
- type: "txHash",
- value: txHash,
- }),
- txHash,
- };
-
- const newest =
- "headers" in options
- ? options.headers[1]
- : !isDeposit
- ? {
- header: await getHeader(options.client, {
- type: "txHash",
- value: txHash,
- }),
- txHash,
- }
- : { header: tip };
+ let oldest: TransactionHeader;
+ if ("headers" in options) {
+ oldest = options.headers[0];
+ } else if (!isDeposit) {
+ const header = await options.client.getHeaderByNumber(
+ mol.Uint64LE.decode(cell.outputData),
+ );
+ if (!header) {
+ throw new Error("Header not found for block number");
+ }
+ oldest = { header };
+ } else {
+ const txWithHeader =
+ await options.client.getTransactionWithHeader(txHash);
+ if (!txWithHeader?.header) {
+ throw new Error("Header not found for txHash");
+ }
+ oldest = { header: txWithHeader.header, txHash };
+ }
+
+ let newest: TransactionHeader;
+ if ("headers" in options) {
+ newest = options.headers[1];
+ } else if (!isDeposit) {
+ const txWithHeader =
+ await options.client.getTransactionWithHeader(txHash);
+ if (!txWithHeader?.header) {
+ throw new Error("Header not found for txHash");
+ }
+ newest = { header: txWithHeader.header, txHash };
+ } else {
+ newest = { header: tip };
+ }
const interests = ccc.calcDaoProfit(
cell.capacityFree,
diff --git a/packages/dao/src/dao.ts b/packages/dao/src/dao.ts
index fc2e063..6cd2948 100644
--- a/packages/dao/src/dao.ts
+++ b/packages/dao/src/dao.ts
@@ -3,7 +3,6 @@ import {
defaultFindCellsLimit,
unique,
type ScriptDeps,
- type SmartTransaction,
} from "@ickb/utils";
import { daoCellFrom, type DaoCell } from "./cells.js";
@@ -68,18 +67,21 @@ export class DaoManager implements ScriptDeps {
/**
* Adds a deposit to a transaction.
*
- * @param tx - The transaction to which the deposit will be added.
+ * @param txLike - The transaction to which the deposit will be added.
* @param capacities - An array of capacities of the deposits to create.
* @param lock - The lock script for the outputs.
- * @returns void.
+ * @param client - The CKB client for DAO output limit validation.
+ * @returns The updated transaction.
*/
- deposit(
- tx: SmartTransaction,
+ async deposit(
+ txLike: ccc.TransactionLike,
capacities: ccc.FixedPoint[],
lock: ccc.Script,
- ): void {
+ client: ccc.Client,
+ ): Promise {
+ const tx = ccc.Transaction.from(txLike);
if (capacities.length === 0) {
- return;
+ return tx;
}
tx.addCellDeps(this.cellDeps);
@@ -95,17 +97,14 @@ export class DaoManager implements ScriptDeps {
);
}
- // Check that there are at most 64 output cells, see:
- // https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md#gotchas
- if (tx.outputs.length > 64) {
- throw new Error("More than 64 output cells in a NervosDAO transaction");
- }
+ await ccc.assertDaoOutputLimit(tx, client);
+ return tx;
}
/**
* Requests withdrawal from NervosDAO deposits.
*
- * @param tx - The transaction to which the withdrawal request will be added.
+ * @param txLike - The transaction to which the withdrawal request will be added.
* @param deposits - An array of deposits to request the withdrawal from.
* @param lock - The lock script for the withdrawal request cells.
* @param options - Optional parameters for the withdrawal request.
@@ -116,22 +115,24 @@ export class DaoManager implements ScriptDeps {
* @throws Error if the withdrawal request lock args have a different size from the deposit.
* @throws Error if the transaction or header of deposit is not found.
*/
- requestWithdrawal(
- tx: SmartTransaction,
+ async requestWithdrawal(
+ txLike: ccc.TransactionLike,
deposits: DaoCell[],
lock: ccc.Script,
+ client: ccc.Client,
options?: {
sameSizeOnly?: boolean;
isReadyOnly?: boolean;
},
- ): void {
+ ): Promise {
+ const tx = ccc.Transaction.from(txLike);
const sameSizeOnly = options?.sameSizeOnly ?? true;
const isReadyOnly = options?.isReadyOnly ?? false;
if (isReadyOnly) {
deposits = deposits.filter((d) => d.isReady);
}
if (deposits.length === 0) {
- return;
+ return tx;
}
if (
@@ -157,7 +158,10 @@ export class DaoManager implements ScriptDeps {
tx.addCellDeps(this.cellDeps);
const depositHeader = headers[0];
- tx.addHeaders(depositHeader);
+ const depositHash = depositHeader.header.hash;
+ if (!tx.headerDeps.some((h) => h === depositHash)) {
+ tx.headerDeps.push(depositHash);
+ }
tx.addInput(cell);
tx.addOutput(
{
@@ -169,36 +173,35 @@ export class DaoManager implements ScriptDeps {
);
}
- // Check that there are at most 64 output cells, see:
- // https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md#gotchas
- if (tx.outputs.length > 64) {
- throw new Error("More than 64 output cells in a NervosDAO transaction");
- }
+ await ccc.assertDaoOutputLimit(tx, client);
+ return tx;
}
/**
* Withdraws funds from the NervosDAO based on the provided mature withdrawal requests.
*
- * @param tx - The transaction to which the withdrawal will be added.
+ * @param txLike - The transaction to which the withdrawal will be added.
* @param withdrawalRequests - An array of withdrawal requests to process.
* @param options - Optional parameters for the withdrawal process.
* @param options.isReadyOnly - Whether to only process ready withdrawal requests (default: false).
* @returns void
* @throws Error if the withdrawal request is not valid.
*/
- withdraw(
- tx: SmartTransaction,
+ async withdraw(
+ txLike: ccc.TransactionLike,
withdrawalRequests: DaoCell[],
+ client: ccc.Client,
options?: {
isReadyOnly?: boolean;
},
- ): void {
+ ): Promise {
+ const tx = ccc.Transaction.from(txLike);
const isReadyOnly = options?.isReadyOnly ?? false;
if (isReadyOnly) {
withdrawalRequests = withdrawalRequests.filter((d) => d.isReady);
}
if (withdrawalRequests.length === 0) {
- return;
+ return tx;
}
tx.addCellDeps(this.cellDeps);
@@ -213,7 +216,12 @@ export class DaoManager implements ScriptDeps {
if (isDeposit) {
throw new Error("Not a withdrawal request");
}
- tx.addHeaders(headers);
+ for (const th of headers) {
+ const hash = th.header.hash;
+ if (!tx.headerDeps.some((h) => h === hash)) {
+ tx.headerDeps.push(hash);
+ }
+ }
const depositHeader = headers[0];
const headerIndex = tx.headerDeps.findIndex(
(h) => h === depositHeader.header.hash,
@@ -240,11 +248,8 @@ export class DaoManager implements ScriptDeps {
tx.setWitnessArgsAt(inputIndex, witness);
}
- // Check that there are at most 64 output cells, see:
- // https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md#gotchas
- if (tx.outputs.length > 64) {
- throw new Error("More than 64 output cells in a NervosDAO transaction");
- }
+ await ccc.assertDaoOutputLimit(tx, client);
+ return tx;
}
/**
diff --git a/packages/dao/tsconfig.json b/packages/dao/tsconfig.json
index 68226cd..80da643 100644
--- a/packages/dao/tsconfig.json
+++ b/packages/dao/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
+ "noEmit": false,
"rootDir": "src",
"outDir": "dist",
"sourceRoot": "../src"
diff --git a/packages/order/src/order.ts b/packages/order/src/order.ts
index 3d56f4d..e70ee91 100644
--- a/packages/order/src/order.ts
+++ b/packages/order/src/order.ts
@@ -5,7 +5,6 @@ import {
hexFrom,
type ExchangeRatio,
type ScriptDeps,
- type SmartTransaction,
type UdtHandler,
type ValueComponents,
} from "@ickb/utils";
@@ -162,7 +161,7 @@ export class OrderManager implements ScriptDeps {
* - Appends the order cell to the outputs with the UDT data and adjusts the CKB capacity.
* - Appends a corresponding master cell immediately after the order cell.
*
- * @param tx - The transaction to which the order will be added.
+ * @param txLike - The transaction to which the order will be added.
* @param lock - The lock script for the master cell.
* @param info - The information related to the order, usually calculated using OrderManager.convert.
* @param amounts - The amounts for the order, including:
@@ -172,11 +171,12 @@ export class OrderManager implements ScriptDeps {
* @returns void
*/
mint(
- tx: SmartTransaction,
+ txLike: ccc.TransactionLike,
lock: ccc.Script,
info: InfoLike,
amounts: ValueComponents,
- ): void {
+ ): ccc.Transaction {
+ const tx = ccc.Transaction.from(txLike);
const { ckbValue, udtValue } = amounts;
const data = OrderData.from({
udtValue,
@@ -188,7 +188,7 @@ export class OrderManager implements ScriptDeps {
});
tx.addCellDeps(this.cellDeps);
- tx.addUdtHandlers(this.udtHandler);
+ tx.addCellDeps(this.udtHandler.cellDeps);
// Append order cell to Outputs
const position = tx.addOutput(
@@ -206,6 +206,7 @@ export class OrderManager implements ScriptDeps {
lock,
type: this.script,
});
+ return tx;
}
/**
@@ -215,17 +216,18 @@ export class OrderManager implements ScriptDeps {
* - Adds the original order as an input.
* - Creates an updated output with adjusted CKB capacity and UDT data.
*
- * @param tx - The transaction to which the matches will be added.
+ * @param txLike - The transaction to which the matches will be added.
* @param match - The match object containing partial matches.
*/
- addMatch(tx: SmartTransaction, match: Match): void {
+ addMatch(txLike: ccc.TransactionLike, match: Match): ccc.Transaction {
+ const tx = ccc.Transaction.from(txLike);
const partials = match.partials;
if (partials.length === 0) {
- return;
+ return tx;
}
tx.addCellDeps(this.cellDeps);
- tx.addUdtHandlers(this.udtHandler);
+ tx.addCellDeps(this.udtHandler.cellDeps);
for (const { order, ckbOut, udtOut } of partials) {
tx.addInput(order.cell);
@@ -245,6 +247,7 @@ export class OrderManager implements ScriptDeps {
}).toBytes(),
);
}
+ return tx;
}
/**
@@ -491,7 +494,7 @@ export class OrderManager implements ScriptDeps {
* For each order group, if the option is to only process fulfilled orders, it filters accordingly.
* Then, for every valid group, the master and order cells are added as inputs in the transaction.
*
- * @param tx - The transaction to which the groups will be added.
+ * @param txLike - The transaction to which the groups will be added.
* @param groups - The array of OrderGroup instances to melt.
* @param options - Optional parameters:
* @param options.isFulfilledOnly - If true, only groups with fulfilled orders will be melted.
@@ -499,26 +502,28 @@ export class OrderManager implements ScriptDeps {
* @returns void
*/
melt(
- tx: SmartTransaction,
+ txLike: ccc.TransactionLike,
groups: OrderGroup[],
options?: {
isFulfilledOnly?: boolean;
},
- ): void {
+ ): ccc.Transaction {
+ const tx = ccc.Transaction.from(txLike);
const isFulfilledOnly = options?.isFulfilledOnly ?? false;
if (isFulfilledOnly) {
groups = groups.filter((g) => g.order.isFulfilled());
}
if (groups.length === 0) {
- return;
+ return tx;
}
tx.addCellDeps(this.cellDeps);
- tx.addUdtHandlers(this.udtHandler);
+ tx.addCellDeps(this.udtHandler.cellDeps);
for (const group of groups) {
tx.addInput(group.order.cell);
tx.addInput(group.master.cell);
}
+ return tx;
}
/**
diff --git a/packages/order/tsconfig.json b/packages/order/tsconfig.json
index 68226cd..80da643 100644
--- a/packages/order/tsconfig.json
+++ b/packages/order/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
+ "noEmit": false,
"rootDir": "src",
"outDir": "dist",
"sourceRoot": "../src"
diff --git a/packages/sdk/src/constants.ts b/packages/sdk/src/constants.ts
index 7019841..d2f271c 100644
--- a/packages/sdk/src/constants.ts
+++ b/packages/sdk/src/constants.ts
@@ -2,7 +2,7 @@ import { ccc } from "@ckb-ccc/core";
import { IckbUdtManager, LogicManager, OwnedOwnerManager } from "@ickb/core";
import { DaoManager } from "@ickb/dao";
import { OrderManager } from "@ickb/order";
-import { CapacityManager, unique, type ScriptDeps } from "@ickb/utils";
+import { unique, type ScriptDeps } from "@ickb/utils";
/**
* Retrieves the configuration for the given deployment environment.
@@ -10,7 +10,7 @@ import { CapacityManager, unique, type ScriptDeps } from "@ickb/utils";
* Accepts either a string identifier ("mainnet" or "testnet") or a custom configuration
* object containing script dependencies for a devnet.
*
- * It sets up various managers (UDT, Logic, OwnedOwner, Order, Dao, Capacity) and also
+ * It sets up various managers (UDT, Logic, OwnedOwner, Order, Dao) and also
* aggregates a unique list of known bot scripts.
*
* @param d - Either a network identifier ("mainnet"/"testnet") or an object containing
@@ -33,7 +33,6 @@ export function getConfig(
bots: ccc.ScriptLike[] = [],
): {
managers: {
- capacity: CapacityManager;
dao: DaoManager;
ickbUdt: IckbUdtManager;
logic: LogicManager;
@@ -57,7 +56,6 @@ export function getConfig(
};
}
- const capacity = CapacityManager.withAnyData();
const dao = new DaoManager(d.dao.script, d.dao.cellDeps);
const ickbUdt = new IckbUdtManager(
d.udt.script,
@@ -81,7 +79,6 @@ export function getConfig(
return {
managers: {
- capacity,
dao,
ickbUdt,
logic,
diff --git a/packages/sdk/src/sdk.ts b/packages/sdk/src/sdk.ts
index b512889..6a74b88 100644
--- a/packages/sdk/src/sdk.ts
+++ b/packages/sdk/src/sdk.ts
@@ -1,12 +1,10 @@
import { ccc } from "@ckb-ccc/core";
import {
collect,
- CapacityManager,
- SmartTransaction,
binarySearch,
+ unique,
type ValueComponents,
hexFrom,
- getHeader,
} from "@ickb/utils";
import {
convert,
@@ -35,14 +33,12 @@ export class IckbSdk {
* @param ownedOwner - The manager for owned owner operations.
* @param ickbLogic - The manager for iCKB logic operations.
* @param order - The manager for order operations.
- * @param capacity - The capacity manager instance.
* @param bots - An array of bot lock scripts.
*/
constructor(
private readonly ownedOwner: OwnedOwnerManager,
private readonly ickbLogic: LogicManager,
private readonly order: OrderManager,
- private readonly capacity: CapacityManager,
private readonly bots: ccc.Script[],
) {}
@@ -54,11 +50,11 @@ export class IckbSdk {
*/
static from(...args: Parameters): IckbSdk {
const {
- managers: { ownedOwner, logic, order, capacity },
+ managers: { ownedOwner, logic, order },
bots,
} = getConfig(...args);
- return new IckbSdk(ownedOwner, logic, order, capacity, bots);
+ return new IckbSdk(ownedOwner, logic, order, bots);
}
/**
@@ -216,7 +212,7 @@ export class IckbSdk {
* - Adds required cell dependencies and UDT handlers to the transaction.
* - Appends the order cell to the transaction outputs.
*
- * @param tx - The smart transaction to which the order cell is added.
+ * @param txLike - The transaction to which the order cell is added.
* @param user - The user, represented either as a Signer or a Script.
* @param info - The order information meta data (usually computed via OrderManager.convert).
* @param amounts - The value components for the order, including:
@@ -226,18 +222,18 @@ export class IckbSdk {
* @returns A Promise resolving to void.
*/
async request(
- tx: SmartTransaction,
+ txLike: ccc.TransactionLike,
user: ccc.Signer | ccc.Script,
info: Info,
amounts: ValueComponents,
- ): Promise {
+ ): Promise {
// If the user is provided as a Signer, extract the recommended lock script.
user =
"codeHash" in user
? user
: (await user.getRecommendedAddressObj()).script;
- this.order.mint(tx, user, info, amounts);
+ return this.order.mint(txLike, user, info, amounts);
}
/**
@@ -247,7 +243,7 @@ export class IckbSdk {
* it filters accordingly. Then, for every valid group, the master and order cells are added
* as inputs to the transaction.
*
- * @param tx - The smart transaction to which the inputs are added.
+ * @param txLike - The transaction to which the inputs are added.
* @param groups - An array of order groups to be melted.
* @param options - Optional parameters:
* - isFulfilledOnly: If true, only order groups with fully or partially fulfilled orders are processed.
@@ -255,13 +251,13 @@ export class IckbSdk {
* @returns void
*/
collect(
- tx: SmartTransaction,
+ txLike: ccc.TransactionLike,
groups: OrderGroup[],
options?: {
isFulfilledOnly?: boolean;
},
- ): void {
- this.order.melt(tx, groups, options);
+ ): ccc.Transaction {
+ return this.order.melt(txLike, groups, options);
}
/**
@@ -373,26 +369,46 @@ export class IckbSdk {
// Map to track each bot's available CKB (minus a reserved amount for internal operations).
const bot2Ckb = new Map();
const reserved = -ccc.fixedPointFrom("2000");
- for await (const c of this.capacity.findCapacities(
- client,
- this.bots,
- opts,
- )) {
- const key = hexFrom(c.cell.cellOutput.lock);
- const ckb = (bot2Ckb.get(key) ?? reserved) + c.ckbValue;
- bot2Ckb.set(key, ckb);
-
- // Find the most recent deposit pool snapshot from bot cell output data.
- const outputData = c.cell.outputData;
- if (outputData.length % 256 === 2) {
- const h = await getHeader(client, {
- type: "txHash",
- value: c.cell.outPoint.txHash,
- });
- const e = ccc.Epoch.from(h.epoch);
- if (poolSnapshotEpoch.compare(e) < 0) {
- poolSnapshotHex = outputData;
- poolSnapshotEpoch = e;
+ for (const lock of unique(this.bots)) {
+ for await (const cell of client.findCellsOnChain(
+ {
+ script: lock,
+ scriptType: "lock",
+ filter: {
+ scriptLenRange: [0n, 1n],
+ },
+ scriptSearchMode: "exact",
+ withData: true,
+ },
+ "asc",
+ 400,
+ )) {
+ if (
+ cell.cellOutput.type !== undefined ||
+ !cell.cellOutput.lock.eq(lock)
+ ) {
+ continue;
+ }
+
+ const key = hexFrom(cell.cellOutput.lock);
+ const ckb =
+ (bot2Ckb.get(key) ?? reserved) + cell.cellOutput.capacity;
+ bot2Ckb.set(key, ckb);
+
+ // Find the most recent deposit pool snapshot from bot cell output data.
+ const outputData = cell.outputData;
+ if (outputData.length % 256 === 2) {
+ const txWithHeader = await client.getTransactionWithHeader(
+ cell.outPoint.txHash,
+ );
+ if (!txWithHeader?.header) {
+ throw new Error("Header not found for txHash");
+ }
+ const e = ccc.Epoch.from(txWithHeader.header.epoch);
+ if (poolSnapshotEpoch.compare(e) < 0) {
+ poolSnapshotHex = outputData;
+ poolSnapshotEpoch = e;
+ }
}
}
}
diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json
index 68226cd..80da643 100644
--- a/packages/sdk/tsconfig.json
+++ b/packages/sdk/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
+ "noEmit": false,
"rootDir": "src",
"outDir": "dist",
"sourceRoot": "../src"
diff --git a/packages/utils/src/capacity.ts b/packages/utils/src/capacity.ts
deleted file mode 100644
index fc40328..0000000
--- a/packages/utils/src/capacity.ts
+++ /dev/null
@@ -1,221 +0,0 @@
-import { ccc } from "@ckb-ccc/core";
-import type { SmartTransaction } from "./transaction.js";
-import { unique, type ValueComponents } from "./utils.js";
-
-/**
- * Symbol to represent the isCapacity property of Capacity Cells.
- */
-const isCapacitySymbol = Symbol("isCapacity");
-
-/**
- * The CapacityManager class is used for managing Capacity cells.
- *
- * @remarks
- * This class provides methods to:
- * - Check if a cell qualifies as a Capacity Cell.
- * - Add Capacity cells to a transaction.
- * - Find Capacity cells based on the provided scripts and options.
- *
- * The criteria for a cell to qualify may be configured based on the cell's output data length
- * and an additional optional predicate function.
- */
-export class CapacityManager {
- /**
- * Creates an instance of CapacityManager.
- *
- * @param outputDataLenRange - A tuple specifying the inclusive lower bound and exclusive upper bound of the output data length.
- * When defined, only cells whose output data length falls within this range are considered.
- * For example, [0n, 1n] indicates cells with no output data.
- */
- constructor(
- public readonly outputDataLenRange: [ccc.Num, ccc.Num] | undefined,
- ) {}
-
- /**
- * Creates a CapacityManager instance that only accepts cells with no output data.
- *
- * @returns An instance of CapacityManager configured with an output data length range of [0n, 1n].
- */
- static withEmptyData(): CapacityManager {
- return new CapacityManager([0n, 1n]);
- }
-
- /**
- * Creates a CapacityManager instance that accepts cells regardless of their output data.
- *
- * @returns An instance of CapacityManager with no output data length filtering.
- */
- static withAnyData(): CapacityManager {
- return new CapacityManager(undefined);
- }
-
- /**
- * Checks if the provided cell qualifies as a Capacity Cell.
- *
- * @param cell - The cell to check.
- * @returns True if the cell qualifies as a Capacity Cell; otherwise, false.
- *
- * @remarks
- * A cell is considered a Capacity Cell if:
- * - It does not have a type defined in its cell output.
- * - If an outputDataLenRange is provided, the effective length of the cell's output data (calculated as (length - 2) / 2)
- * falls within the specified [start, end) range.
- */
- isCapacity(cell: ccc.Cell): boolean {
- if (cell.cellOutput.type !== undefined) {
- return false;
- }
-
- if (!this.outputDataLenRange) {
- return true;
- }
-
- const [start, end] = this.outputDataLenRange;
- const dataLen = (cell.outputData.length - 2) / 2;
- if (start <= dataLen && dataLen < end) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Adds Capacity cells to the specified smart transaction.
- *
- * @param tx - The smart transaction to which Capacity cells will be added.
- * @param capacities - An array of Capacity cells to be added.
- *
- * @remarks
- * The method iterates over each CapacityCell and adds its underlying cell as an input to the transaction.
- */
- addCapacities(tx: SmartTransaction, capacities: CapacityCell[]): void {
- for (const { cell } of capacities) {
- tx.addInput(cell);
- }
- }
-
- /**
- * Async generator that finds and yields capacity-only cells matching the given lock scripts.
- *
- * @param client
- * A CKB client instance providing two methods:
- * - `findCells(query, order, limit)` for cached searches
- * - `findCellsOnChain(query, order, limit)` for on-chain searches
- *
- * @param locks
- * An array of lock scripts. Only cells whose `cellOutput.lock` matches one of these
- * scripts exactly will be considered.
- *
- * @param options
- * Optional parameters to control the search behavior:
- * - `onChain?: boolean`
- * If `true`, queries the chain directly via `findCellsOnChain`.
- * Otherwise, uses local cache via `findCells` first. Default: `false`.
- * - `limit?: number`
- * Maximum number of cells to fetch per lock script in each batch.
- * Defaults to the constant `defaultFindCellsLimit` (400).
- *
- * @yields
- * {@link CapacityCell} objects for each valid capacity-only cell found.
- *
- * @remarks
- * - Deduplicates `locks` via `unique(locks)` to avoid redundant queries.
- * - Applies an RPC filter:
- * • `scriptLenRange: [0n, 1n]`
- * • `outputDataLenRange: this.outputDataLenRange`
- * - Skips any cell that:
- * 1. Has a non-null type script
- * 2. Fails the data-length filter
- * 3. Whose lock script does not exactly match the queried `lock`
- * - Each yielded `CapacityCell` contains:
- * • `cell`: original cell data with status
- * • `ckbValue`: capacity in shannons
- * • `udtValue`: always `0n` (no UDT on capacity-only cells)
- * • a hidden `[isCapacitySymbol]: true` marker
- */
- async *findCapacities(
- client: ccc.Client,
- locks: ccc.Script[],
- options?: {
- /**
- * If true, fetch cells directly from the chain RPC. Otherwise, use cached results.
- * @default false
- */
- onChain?: boolean;
- /**
- * Batch size per lock script. Defaults to {@link defaultFindCellsLimit}.
- */
- limit?: number;
- },
- ): AsyncGenerator {
- const limit = options?.limit ?? defaultFindCellsLimit;
- // Loop through each unique lock script.
- for (const lock of unique(locks)) {
- const findCellsArgs = [
- {
- script: lock,
- scriptType: "lock",
- filter: {
- scriptLenRange: [0n, 1n] as [ccc.Num, ccc.Num],
- outputDataLenRange: this.outputDataLenRange,
- },
- scriptSearchMode: "exact",
- withData: true,
- },
- "asc",
- limit,
- ] as const;
-
- // Depending on options, choose the correct client function to find cells.
- for await (const cell of options?.onChain
- ? client.findCellsOnChain(...findCellsArgs)
- : client.findCells(...findCellsArgs)) {
- if (!this.isCapacity(cell) || !cell.cellOutput.lock.eq(lock)) {
- continue;
- }
-
- yield {
- cell,
- ckbValue: cell.cellOutput.capacity,
- udtValue: 0n,
- [isCapacitySymbol]: true,
- };
- }
- }
- }
-}
-
-/**
- * Interface representing a Capacity Cell.
- *
- * @remarks
- * A CapacityCell consists of:
- * - The underlying blockchain cell.
- * - Associated value components.
- * - A symbol property indicating that this cell is a Capacity Cell.
- */
-export interface CapacityCell extends ValueComponents {
- /**
- * The underlying cell associated with this Capacity Cell.
- */
- cell: ccc.Cell;
-
- /**
- * A symbol property indicating that this cell is a Capacity Cell.
- * The property is always set to true.
- */
- [isCapacitySymbol]: true;
-}
-
-/**
- * The default upper limit on the number of cells to return when querying the chain.
- *
- * This limit is aligned with Nervos CKB’s pull request #4576
- * (https://github.com/nervosnetwork/ckb/pull/4576) to avoid excessive paging.
- *
- * @remarks
- * When searching for capacity-only cells, callers may override this limit
- * by passing a custom `limit` in their options. If no override is provided,
- * this constant controls how many cells will be fetched in a single batch.
- */
-export const defaultFindCellsLimit = 400;
diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts
index 30ddf72..eb415f1 100644
--- a/packages/utils/src/index.ts
+++ b/packages/utils/src/index.ts
@@ -1,6 +1,4 @@
export * from "./codec.js";
-export * from "./capacity.js";
export * from "./heap.js";
-export * from "./transaction.js";
export * from "./udt.js";
export * from "./utils.js";
diff --git a/packages/utils/src/transaction.ts b/packages/utils/src/transaction.ts
deleted file mode 100644
index 3f67db5..0000000
--- a/packages/utils/src/transaction.ts
+++ /dev/null
@@ -1,517 +0,0 @@
-import { ccc, mol } from "@ckb-ccc/core";
-import { getHeader, hexFrom, type HeaderKey } from "./utils.js";
-import type { UdtHandler } from "./udt.js";
-
-/**
- * Class representing a smart transaction that extends the base ccc.Transaction.
- * This class manages UDT handlers and transaction headers, providing additional functionality
- * for handling UDTs and ensuring balanced transactions.
- *
- * Notes:
- * - udtHandlers and headers are always shared among descendants.
- * - headers may not contain all headers referenced by headerDeps.
- */
-export class SmartTransaction extends ccc.Transaction {
- /**
- * Creates an instance of SmartTransaction.
- *
- * @param version - The version of the transaction.
- * @param cellDeps - The cell dependencies for the transaction.
- * @param headerDeps - The header dependencies for the transaction.
- * @param inputs - The inputs for the transaction.
- * @param outputs - The outputs for the transaction.
- * @param outputsData - The data associated with the outputs.
- * @param witnesses - The witnesses for the transaction.
- * @param udtHandlers - A map of UDT handlers associated with the transaction.
- * @param headers - A map of headers associated with the transaction, indexed by their hash, number, and possibly transaction hash.
- */
- constructor(
- version: ccc.Num,
- cellDeps: ccc.CellDep[],
- headerDeps: ccc.Hex[],
- inputs: ccc.CellInput[],
- outputs: ccc.CellOutput[],
- outputsData: ccc.Hex[],
- witnesses: ccc.Hex[],
- public udtHandlers: Map,
- public headers: Map,
- ) {
- super(
- version,
- cellDeps,
- headerDeps,
- inputs,
- outputs,
- outputsData,
- witnesses,
- );
- }
-
- /**
- * Automatically adds change cells for both capacity and UDTs for which a handler is defined.
- *
- * @param args - The parameters for the completeFee method, as defined by ccc.Transaction["completeFee"].
- * @returns A promise that resolves to a tuple:
- * [number, boolean] where the number is the quantity of added input cells and the boolean
- * indicates if an output change cell was added.
- *
- * The function will:
- * - Add change cells for all the defined UDTs using udtHandlers's completeUdt.
- * - Add capacity change cells via the superclass method.
- * - Enforce a condition on NervosDAO transactions to have at most 64 output cells.
- */
- override async completeFee(
- ...args: Parameters
- ): Promise<[number, boolean]> {
- const signer = args[0];
- const options = args[4];
-
- let inAdded = 0;
- let addedChange = false;
-
- // Add change cells for all defined UDTs.
- for (const handler of this.udtHandlers.values()) {
- const res = await handler.completeUdt(signer, this, options);
- inAdded += res[0];
- addedChange ||= res[1];
- }
-
- // Add capacity change cells.
- const res = await super.completeFee(...args);
- inAdded += res[0];
- addedChange ||= res[1];
-
- // Check that, if NervosDAO cells are included, then there are at most 64 output cells.
- // See: https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md#gotchas
- const { hashType, codeHash } = await signer.client.getKnownScript(
- ccc.KnownScript.NervosDao,
- );
- const dao = ccc.Script.from({ codeHash, hashType, args: "0x" });
- const isDaoTx =
- this.inputs.some((c) => c.cellOutput?.type?.eq(dao)) ||
- this.outputs.some((c) => c.type?.eq(dao));
- if (isDaoTx && this.outputs.length > 64) {
- throw new Error("More than 64 output cells in a NervosDAO transaction");
- }
-
- return [inAdded, addedChange];
- }
-
- /**
- * Retrieves the balance of UDT inputs using the appropriate handler if it exists.
- *
- * @param client - The client instance used to interact with the blockchain.
- * @param udtLike - The UDT script or script-like object.
- * @returns A promise that resolves to the balance of UDT inputs as a ccc.FixedPoint.
- *
- * If a custom UDT handler exists for the provided UDT, its getInputsUdtBalance method is used.
- * Otherwise, the balance is derived from the superclass's implementation.
- */
- override getInputsUdtBalance(
- client: ccc.Client,
- udtLike: ccc.ScriptLike,
- ): Promise {
- const udt = ccc.Script.from(udtLike);
- return (
- this.getUdtHandler(udt)
- ?.getInputsUdtBalance(client, this)
- // eslint-disable-next-line @typescript-eslint/no-deprecated
- .then((b) => b[0]) ?? super.getInputsUdtBalance(client, udt)
- );
- }
-
- /**
- * Retrieves the balance of UDT outputs using the appropriate handler if it exists.
- *
- * @param udtLike - The UDT script or script-like object.
- * @returns The balance of UDT outputs as a ccc.FixedPoint.
- *
- * If a custom UDT handler exists for the provided UDT, its getOutputsUdtBalance method is used.
- * Otherwise, the balance is derived from the superclass's implementation.
- */
- override getOutputsUdtBalance(udtLike: ccc.ScriptLike): ccc.FixedPoint {
- const udt = ccc.Script.from(udtLike);
- return (
- this.getUdtHandler(udt)?.getOutputsUdtBalance(this)[0] ??
- // eslint-disable-next-line @typescript-eslint/no-deprecated
- super.getOutputsUdtBalance(udt)
- );
- }
-
- /**
- * Asynchronously retrieves the total capacity of inputs, taking into account the extra capacity
- * produced by deposit withdrawals.
- *
- * @param client - The client instance used to interact with the blockchain.
- * @returns A promise that resolves to the total capacity of inputs as a ccc.Num.
- *
- * The method works by:
- * - Iterating over all inputs.
- * - Completing extra information for each input.
- * - Summing the capacities.
- * - Recognizing and then compensating for NervosDAO withdrawal requests by calculating DAO profits.
- */
- override async getInputsCapacity(client: ccc.Client): Promise {
- const { hashType, codeHash } = await client.getKnownScript(
- ccc.KnownScript.NervosDao,
- );
- const dao = ccc.Script.from({ codeHash, hashType, args: "0x" });
-
- return ccc.reduceAsync(
- this.inputs,
- async (total, input) => {
- // Get all cell information.
- await input.completeExtraInfos(client);
- const { previousOutput: outPoint, cellOutput, outputData } = input;
-
- // Input is not well defined.
- if (!cellOutput || !outputData) {
- throw new Error("Unable to complete input");
- }
- const cell = ccc.Cell.from({
- outPoint,
- cellOutput,
- outputData,
- });
-
- total += cellOutput.capacity;
-
- // If not a NervosDAO Withdrawal Request cell, return the running total.
- if (outputData === "0x0000000000000000" || !cellOutput.type?.eq(dao)) {
- return total;
- }
-
- // For a withdrawal request cell, retrieve the corresponding deposit header and calculate the profit.
- const withdrawHeader = await this.getHeader(client, {
- type: "txHash",
- value: outPoint.txHash,
- });
-
- const depositHeader = await this.getHeader(client, {
- type: "number",
- value: mol.Uint64LE.decode(outputData),
- });
-
- return (
- total +
- ccc.calcDaoProfit(cell.capacityFree, depositHeader, withdrawHeader)
- );
- },
- 0n,
- );
- }
-
- /**
- * Gets the unique key for a UDT based on its script.
- *
- * @param udt - The UDT script or script-like object.
- * @returns A string representing the unique key for the UDT in the udtHandlers map.
- */
- encodeUdtKey(udt: ccc.ScriptLike): string {
- return hexFrom(ccc.Script.from(udt));
- }
-
- /**
- * Retrieves the UDT handler associated with a given UDT.
- *
- * @param udt - The UDT script or script-like object.
- * @returns The UdtHandler for the provided UDT, or undefined if no handler exists.
- */
- getUdtHandler(udt: ccc.ScriptLike): UdtHandler | undefined {
- return this.udtHandlers.get(this.encodeUdtKey(udt));
- }
-
- /**
- * Checks if a UDT handler exists for a given UDT.
- *
- * @param udt - The UDT script or script-like object.
- * @returns True if a handler exists for the provided UDT; otherwise, false.
- */
- hasUdtHandler(udt: ccc.ScriptLike): boolean {
- return this.udtHandlers.has(this.encodeUdtKey(udt));
- }
-
- /**
- * Adds UDT handlers to the transaction.
- *
- * @param udtHandlers - One or more UDT handlers (or arrays of them) to add.
- *
- * For every added UDT handler, the method:
- * - Adds or substitutes the handler in the udtHandlers map.
- * - Adds the handler's cell dependencies to the transaction.
- */
- addUdtHandlers(...udtHandlers: (UdtHandler | UdtHandler[])[]): void {
- udtHandlers.flat().forEach((udtHandler) => {
- this.udtHandlers.set(this.encodeUdtKey(udtHandler.script), udtHandler);
- this.addCellDeps(udtHandler.cellDeps);
- });
- }
-
- /**
- * Encodes a header key based on the provided HeaderKey object.
- *
- * @param headerKey - An object containing the type and value used to generate the header key.
- * @returns A string representing the generated header key, combining the type and the byte representation of the value.
- */
- encodeHeaderKey(headerKey: HeaderKey): string {
- const { type, value } = headerKey;
- return hexFrom(value) + type;
- }
-
- /**
- * Adds one or more transaction headers to the headers cache, indexed by their hash, number, and optional transaction hash.
- *
- * @param headers - One or more TransactionHeader objects (or arrays of them) to be added.
- * @throws Error if two different headers (by hash) are found for the same encoded key.
- *
- * The method:
- * - Encodes keys from header hash, number, and (optionally) transaction hash.
- * - Stores headers uniquely, retaining the old header if one already exists for a key.
- * - Adds the header's hash to headerDeps if not already present.
- */
- addHeaders(...headers: (TransactionHeader | TransactionHeader[])[]): void {
- headers.flat().forEach(({ header, txHash }) => {
- const { hash, number } = header;
- // Encode Hash, Number and possibly TxHash as header keys.
- const keys = [
- this.encodeHeaderKey({
- type: "hash",
- value: hash,
- }),
- this.encodeHeaderKey({
- type: "number",
- value: number,
- }),
- ];
- if (txHash) {
- keys.push(
- this.encodeHeaderKey({
- type: "txHash",
- value: txHash,
- }),
- );
- }
-
- // Add Header by each key. Retain the old header if one already exists with the same hash.
- for (const key of keys) {
- const h = this.headers.get(key);
- if (!h) {
- this.headers.set(key, header);
- } else if (hash === h.hash) {
- // Keep old header.
- header = h;
- } else {
- throw new Error("Found two hashes for the same header");
- }
- }
-
- // Add the header's hash to headerDeps if not already present.
- if (!this.headerDeps.some((h) => h === hash)) {
- this.headerDeps.push(hash);
- }
- });
- }
-
- /**
- * Retrieves a block header based on the provided header key, caching the result for future use.
- *
- * @param client - An instance of ccc.Client used to interact with the blockchain.
- * @param headerKey - An object of type HeaderKey specifying how to retrieve the header.
- * @returns A promise that resolves to a ccc.ClientBlockHeader representing the fetched block header.
- * @throws Error if the header cannot be added to or found in header dependencies.
- *
- * The method:
- * - Attempts to retrieve the header from a local cache.
- * - If not found, fetches it from the blockchain.
- * - Caches the retrieved header and ensures it is present in headerDeps.
- */
- async getHeader(
- client: ccc.Client,
- headerKey: HeaderKey,
- ): Promise {
- const key = this.encodeHeaderKey(headerKey);
- let header = this.headers.get(key);
- if (!header) {
- header = await getHeader(client, headerKey);
- const headerDepsLength = this.headerDeps.length;
- this.addHeaders({
- header,
- txHash: headerKey.type === "txHash" ? headerKey.value : undefined,
- });
- if (headerDepsLength !== this.headerDeps.length) {
- throw new Error("Header was not present in HeaderDeps");
- }
- } else {
- // Double check that header is present in headerDeps.
- const { hash } = header;
- if (!this.headerDeps.some((h) => h === hash)) {
- throw new Error("Header not found in HeaderDeps");
- }
- }
-
- return header;
- }
-
- /**
- * Creates a default instance of SmartTransaction.
- *
- * @returns A new instance of SmartTransaction with default values.
- *
- * The default instance has:
- * - version set to 0n,
- * - empty arrays for cellDeps, headerDeps, inputs, outputs, outputsData and witnesses,
- * - new Maps for udtHandlers and headers.
- */
- static override default(): SmartTransaction {
- return new SmartTransaction(
- 0n,
- [],
- [],
- [],
- [],
- [],
- [],
- new Map(),
- new Map(),
- );
- }
-
- /**
- * Clones the transaction part and shares udtHandlers and headers.
- *
- * @returns A new instance of SmartTransaction that is a clone of the current instance.
- *
- * Note that the method reuses the udtHandlers and headers maps to ensure that they are shared among descendants.
- */
- override clone(): SmartTransaction {
- const result = SmartTransaction.from(super.clone());
- result.udtHandlers = this.udtHandlers;
- result.headers = this.headers;
- return result;
- }
-
- /**
- * Copies data from an input transaction.
- *
- * @param txLike - The transaction-like object to copy data from.
- *
- * This method copies the transaction details including cellDeps, headerDeps, inputs,
- * outputs, outputsData and witnesses. If the udtHandlers or headers instances differ,
- * their entries are merged from the source transaction.
- */
- override copy(txLike: SmartTransactionLike): void {
- const tx = SmartTransaction.from(txLike);
- this.version = tx.version;
- this.cellDeps = tx.cellDeps;
- this.headerDeps = tx.headerDeps;
- this.inputs = tx.inputs;
- this.outputs = tx.outputs;
- this.outputsData = tx.outputsData;
- this.witnesses = tx.witnesses;
- // If udtHandlers are different, merge entries from tx's udtHandlers into this.udtHandlers.
- if (this.udtHandlers !== tx.udtHandlers) {
- for (const [k, h] of tx.udtHandlers.entries()) {
- this.udtHandlers.set(k, h);
- }
- }
- // If headers are different, merge entries from tx's headers into this.headers.
- if (this.headers !== tx.headers) {
- for (const [k, h] of tx.headers.entries()) {
- this.headers.set(k, h);
- }
- }
- }
-
- /**
- * Creates a SmartTransaction from a Lumos transaction skeleton.
- *
- * @param skeleton - The Lumos transaction skeleton to convert.
- * @returns A new instance of SmartTransaction created from the provided skeleton.
- *
- * This method converts the given Lumos skeleton into a SmartTransaction using the base class conversion,
- * and then adapting it for the SmartTransaction type.
- */
- static override fromLumosSkeleton(
- skeleton: ccc.LumosTransactionSkeletonType,
- ): SmartTransaction {
- return SmartTransaction.from(super.fromLumosSkeleton(skeleton));
- }
-
- /**
- * Creates a SmartTransaction from an input transaction-like object.
- *
- * @param txLike - The transaction-like object to create the SmartTransaction from.
- * May contain missing udtHandlers and headers, which will be defaulted to new Maps.
- * @returns A new instance of SmartTransaction created from the input transaction.
- *
- * If the input object is already an instance of SmartTransaction, it is returned directly.
- * Otherwise, a new SmartTransaction is constructed by copying properties from the input.
- */
- static override from(txLike: SmartTransactionLike): SmartTransaction {
- if (txLike instanceof SmartTransaction) {
- return txLike;
- }
-
- const {
- version,
- cellDeps,
- headerDeps,
- inputs,
- outputs,
- outputsData,
- witnesses,
- } = ccc.Transaction.from(txLike);
-
- const udtHandlers = txLike.udtHandlers ?? new Map();
- const headers = txLike.headers ?? new Map();
-
- return new SmartTransaction(
- version,
- cellDeps,
- headerDeps,
- inputs,
- outputs,
- outputsData,
- witnesses,
- udtHandlers,
- headers,
- );
- }
-}
-
-/**
- * Type representing a transaction-like object that can include additional properties
- * for smart contract handling.
- *
- * This type extends the `ccc.TransactionLike` type and adds optional properties for
- * user-defined token (UDT) handlers and transaction headers.
- */
-export type SmartTransactionLike = ccc.TransactionLike & {
- /**
- * An optional map of user-defined token (UDT) handlers, where the key is a string
- * representing the UDT identifier and the value is an instance of `UdtHandler`.
- */
- udtHandlers?: Map;
-
- /**
- * An optional map of transaction headers, where the key is a string representing
- * the header identifier and the value is an instance of `ccc.ClientBlockHeader`.
- */
- headers?: Map;
-};
-
-/**
- * Represents a transaction header that includes a block header and an optional transaction hash.
- */
-export interface TransactionHeader {
- /**
- * The block header associated with the transaction, represented as `ccc.ClientBlockHeader`.
- */
- header: ccc.ClientBlockHeader;
-
- /**
- * An optional transaction hash associated with the transaction, represented as `ccc.Hex`.
- * This property may be undefined if the transaction hash is not applicable.
- */
- txHash?: ccc.Hex;
-}
diff --git a/packages/utils/src/udt.ts b/packages/utils/src/udt.ts
index 8dcc65b..72375c8 100644
--- a/packages/utils/src/udt.ts
+++ b/packages/utils/src/udt.ts
@@ -1,7 +1,10 @@
import { ccc, mol } from "@ckb-ccc/core";
-import { unique, type ScriptDeps, type ValueComponents } from "./utils.js";
-import type { SmartTransaction } from "./transaction.js";
-import { defaultFindCellsLimit } from "./capacity.js";
+import {
+ defaultFindCellsLimit,
+ unique,
+ type ScriptDeps,
+ type ValueComponents,
+} from "./utils.js";
/**
* Interface representing a handler for User Defined Tokens (UDTs).
@@ -13,46 +16,49 @@ export interface UdtHandler extends ScriptDeps {
* for a given transaction.
*
* @param client - The CKB client to query cell data.
- * @param tx - The smart transaction whose inputs are to be balanced.
+ * @param txLike - The transaction whose inputs are to be balanced.
* @returns A promise resolving to a tuple:
* - [0]: Total UDT amount in inputs (as `ccc.FixedPoint`).
* - [1]: Total capacity in UDT inputs (as `ccc.FixedPoint`).
*/
getInputsUdtBalance(
client: ccc.Client,
- tx: SmartTransaction,
+ txLike: ccc.TransactionLike,
): Promise<[ccc.FixedPoint, ccc.FixedPoint]>;
/**
* Retrieves the UDT output balance (token amount and capacity)
* for a given transaction.
*
- * @param tx - The smart transaction whose outputs are to be balanced.
+ * @param txLike - The transaction whose outputs are to be balanced.
* @returns A tuple:
* - [0]: Total UDT amount in outputs (as `ccc.FixedPoint`).
* - [1]: Total capacity in UDT outputs (as `ccc.FixedPoint`).
*/
- getOutputsUdtBalance(tx: SmartTransaction): [ccc.FixedPoint, ccc.FixedPoint];
+ getOutputsUdtBalance(
+ txLike: ccc.TransactionLike,
+ ): [ccc.FixedPoint, ccc.FixedPoint];
/**
* Completes a transaction by adding UDT inputs and/or UDT change outputs as needed.
*
* @param signer - Signer providing client access and account scripts.
- * @param tx - The smart transaction to adjust.
+ * @param txLike - The transaction to adjust.
* @param options.shouldAddInputs - Whether to add inputs if insufficient. Defaults to `true`.
* @param options.compressState - Whether to collect all UDT cells to compress state rent. Defaults to `false`.
* @returns A promise resolving to a tuple:
- * - [0]: Number of UDT inputs added.
- * - [1]: `true` if a UDT change output was appended; otherwise `false`.
+ * - [0]: The (possibly mutated) transaction.
+ * - [1]: Number of UDT inputs added.
+ * - [2]: `true` if a UDT change output was appended; otherwise `false`.
*/
completeUdt(
signer: ccc.Signer,
- tx: SmartTransaction,
+ txLike: ccc.TransactionLike,
options?: {
shouldAddInputs?: boolean;
compressState?: boolean;
},
- ): Promise<[number, boolean]>;
+ ): Promise<[ccc.Transaction, number, boolean]>;
/** The canonical name of the UDT. */
name: string;
@@ -135,15 +141,16 @@ export class UdtManager implements UdtHandler {
* for a given transaction.
*
* @param client - The CKB client to query cell data.
- * @param tx - The smart transaction whose inputs are to be balanced.
+ * @param txLike - The transaction whose inputs are to be balanced.
* @returns A promise resolving to a tuple:
* - [0]: Total UDT amount in inputs (as `ccc.FixedPoint`).
* - [1]: Total capacity in UDT inputs (as `ccc.FixedPoint`).
*/
getInputsUdtBalance(
client: ccc.Client,
- tx: SmartTransaction,
+ txLike: ccc.TransactionLike,
): Promise<[ccc.FixedPoint, ccc.FixedPoint]> {
+ const tx = ccc.Transaction.from(txLike);
return ccc.reduceAsync(
tx.inputs,
async (acc, input) => {
@@ -178,12 +185,15 @@ export class UdtManager implements UdtHandler {
* Retrieves the UDT output balance (token amount and capacity)
* for a given transaction.
*
- * @param tx - The smart transaction whose outputs are to be balanced.
+ * @param txLike - The transaction whose outputs are to be balanced.
* @returns A tuple:
* - [0]: Total UDT amount in outputs (as `ccc.FixedPoint`).
* - [1]: Total capacity in UDT outputs (as `ccc.FixedPoint`).
*/
- getOutputsUdtBalance(tx: SmartTransaction): [ccc.FixedPoint, ccc.FixedPoint] {
+ getOutputsUdtBalance(
+ txLike: ccc.TransactionLike,
+ ): [ccc.FixedPoint, ccc.FixedPoint] {
+ const tx = ccc.Transaction.from(txLike);
return tx.outputs.reduce(
(acc, output, i) => {
if (!output.type?.eq(this.script)) {
@@ -206,21 +216,23 @@ export class UdtManager implements UdtHandler {
* Completes a transaction by adding UDT inputs and/or UDT change outputs as needed.
*
* @param signer - Signer providing client access and account scripts.
- * @param tx - The smart transaction to adjust.
+ * @param txLike - The transaction to adjust.
* @param options.shouldAddInputs - Whether to add inputs if insufficient. Defaults to `true`.
* @param options.compressState - Whether to collect all UDT cells to compress state rent. Defaults to `false`.
* @returns A promise resolving to a tuple:
- * - [0]: Number of UDT inputs added.
- * - [1]: `true` if a UDT change output was appended; otherwise `false`.
+ * - [0]: The (possibly mutated) transaction.
+ * - [1]: Number of UDT inputs added.
+ * - [2]: `true` if a UDT change output was appended; otherwise `false`.
*/
async completeUdt(
signer: ccc.Signer,
- tx: SmartTransaction,
+ txLike: ccc.TransactionLike,
options?: {
shouldAddInputs?: boolean;
compressState?: boolean;
},
- ): Promise<[number, boolean]> {
+ ): Promise<[ccc.Transaction, number, boolean]> {
+ const tx = ccc.Transaction.from(txLike);
const client = signer.client;
let [inUdt, inCapacity] = await this.getInputsUdtBalance(client, tx);
const [outUdt, outCapacity] = this.getOutputsUdtBalance(tx);
@@ -254,7 +266,7 @@ export class UdtManager implements UdtHandler {
}
if (inUdt === outUdt) {
- return [inAdded, false];
+ return [tx, inAdded, false];
}
tx.addOutput(
@@ -265,25 +277,27 @@ export class UdtManager implements UdtHandler {
mol.Uint128LE.encode(inUdt - outUdt),
);
- return [inAdded, true];
+ return [tx, inAdded, true];
}
/**
* Adds UDT cells to a transaction.
- * @param tx - The smart transaction to which UDT cells will be added.
+ * @param txLike - The transaction to which UDT cells will be added.
* @param udts - An array of UDT cells to add.
+ * @returns The transaction with UDT cells added.
*/
- addUdts(tx: SmartTransaction, udts: UdtCell[]): void {
+ addUdts(txLike: ccc.TransactionLike, udts: UdtCell[]): ccc.Transaction {
+ const tx = ccc.Transaction.from(txLike);
if (udts.length === 0) {
- return;
+ return tx;
}
tx.addCellDeps(this.cellDeps);
- tx.addUdtHandlers(this);
for (const { cell } of udts) {
tx.addInput(cell);
}
+ return tx;
}
/**
diff --git a/packages/utils/src/utils.ts b/packages/utils/src/utils.ts
index 609cadc..7b22e23 100644
--- a/packages/utils/src/utils.ts
+++ b/packages/utils/src/utils.ts
@@ -1,5 +1,34 @@
import { ccc } from "@ckb-ccc/core";
+/**
+ * The default upper limit on the number of cells to return when querying the chain.
+ *
+ * This limit is aligned with Nervos CKB's pull request #4576
+ * (https://github.com/nervosnetwork/ckb/pull/4576) to avoid excessive paging.
+ *
+ * @remarks
+ * When searching for cells, callers may override this limit
+ * by passing a custom `limit` in their options. If no override is provided,
+ * this constant controls how many cells will be fetched in a single batch.
+ */
+export const defaultFindCellsLimit = 400;
+
+/**
+ * Represents a transaction header that includes a block header and an optional transaction hash.
+ */
+export interface TransactionHeader {
+ /**
+ * The block header associated with the transaction, represented as `ccc.ClientBlockHeader`.
+ */
+ header: ccc.ClientBlockHeader;
+
+ /**
+ * An optional transaction hash associated with the transaction, represented as `ccc.Hex`.
+ * This property may be undefined if the transaction hash is not applicable.
+ */
+ txHash?: ccc.Hex;
+}
+
/**
* Represents the components of a value, including CKB and UDT amounts.
*/
@@ -48,67 +77,6 @@ export interface ScriptDeps {
cellDeps: ccc.CellDep[];
}
-/**
- * Represents a key for retrieving a block header.
- *
- * The `HeaderKey` can be one of three shapes:
- *
- * 1. For hash type:
- * - `type`: Indicates that the header key is a block hash type, which is "hash".
- * - `value`: The value associated with the header key, represented as `ccc.Hex`.
- *
- * 2. For number type:
- * - `type`: Indicates that the header key is a block number type, which is "number".
- * - `value`: The value associated with the header key, represented as `ccc.Num`.
- *
- * 3. For transaction hash type:
- * - `type`: Indicates that the header key is a transaction hash type, which is "txHash".
- * - `value`: The value associated with the header key, represented as `ccc.Hex`.
- */
-export type HeaderKey =
- | {
- type: "hash";
- value: ccc.Hex;
- }
- | {
- type: "number";
- value: ccc.Num;
- }
- | {
- type: "txHash";
- value: ccc.Hex;
- };
-
-/**
- * Retrieves the block header based on the provided header key.
- *
- * @param client - An instance of `ccc.Client` used to interact with the blockchain.
- * @param headerKey - An object of type `HeaderKey` that specifies how to retrieve the header.
- * @returns A promise that resolves to a `ccc.ClientBlockHeader` representing the block header.
- * @throws Error if the header is not found for the given header key.
- */
-export async function getHeader(
- client: ccc.Client,
- headerKey: HeaderKey,
-): Promise {
- const { type, value } = headerKey;
- let header: ccc.ClientBlockHeader | undefined = undefined;
- if (type === "hash") {
- header = await client.getHeaderByHash(value);
- } else if (type === "number") {
- header = await client.getHeaderByNumber(value);
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- } else if (type === "txHash") {
- header = (await client.getTransactionWithHeader(value))?.header;
- }
-
- if (!header) {
- throw new Error("Header not found");
- }
-
- return header;
-}
-
/**
* Shuffles in-place an array using the Durstenfeld shuffle algorithm.
* @link https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json
index 68226cd..80da643 100644
--- a/packages/utils/tsconfig.json
+++ b/packages/utils/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
+ "noEmit": false,
"rootDir": "src",
"outDir": "dist",
"sourceRoot": "../src"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3c78474..9582276 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -10,7 +10,7 @@ catalogs:
specifier: ^24.8.1
version: 24.10.13
-pnpmfileChecksum: sha256-i1SXpROvniXnHVuwcom4bb+0H4e6QxemyGigopYppDk=
+pnpmfileChecksum: sha256-bpHTpFkBXc22BQj6RinbwnORUfuz+2Nea3ugya/XRbU=
importers:
@@ -159,7 +159,7 @@ importers:
version: 7.28.5(@babel/core@7.29.0)
'@eslint/js':
specifier: ^9.38.0
- version: 9.39.2
+ version: 9.39.3
'@tailwindcss/vite':
specifier: ^4.1.14
version: 4.2.0(vite@6.4.1(@types/node@22.19.11)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2))
@@ -183,16 +183,16 @@ importers:
version: 1.0.0
eslint:
specifier: ^9.38.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-plugin-react-compiler:
specifier: latest
- version: 19.1.0-rc.2(eslint@9.39.2(jiti@2.6.1))
+ version: 19.1.0-rc.2(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-react-hooks:
specifier: ^5.2.0
- version: 5.2.0(eslint@9.39.2(jiti@2.6.1))
+ version: 5.2.0(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-react-refresh:
specifier: ^0.4.24
- version: 0.4.26(eslint@9.39.2(jiti@2.6.1))
+ version: 0.4.26(eslint@9.39.3(jiti@2.6.1))
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -207,7 +207,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.46.1
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
vite:
specifier: ^6.4.0
version: 6.4.1(@types/node@22.19.11)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
@@ -288,19 +288,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -315,7 +315,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/ckb-ccc:
dependencies:
@@ -325,19 +325,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -352,7 +352,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/connector:
dependencies:
@@ -365,16 +365,16 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -389,7 +389,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/connector-react:
dependencies:
@@ -405,19 +405,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
'@types/react':
specifier: ^19.2.7
version: 19.2.14
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -432,7 +432,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/core:
dependencies:
@@ -469,7 +469,7 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
'@types/ws':
specifier: ^8.18.1
version: 8.18.1
@@ -478,13 +478,13 @@ importers:
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -499,7 +499,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
vitest:
specifier: ^3.2.4
version: 3.2.4(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
@@ -518,19 +518,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
'@types/node':
specifier: ^24.3.0
version: 24.10.13
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -545,7 +545,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
vitest:
specifier: ^3.2.4
version: 3.2.4(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
@@ -558,19 +558,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -585,7 +585,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/joy-id:
dependencies:
@@ -601,19 +601,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -628,7 +628,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/lumos-patches:
dependencies:
@@ -656,19 +656,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -683,7 +683,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/nip07:
dependencies:
@@ -693,19 +693,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -720,7 +720,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/okx:
dependencies:
@@ -736,19 +736,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -763,7 +763,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/rei:
dependencies:
@@ -773,19 +773,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -800,7 +800,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/shell:
dependencies:
@@ -825,19 +825,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -852,7 +852,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/spore:
dependencies:
@@ -865,7 +865,7 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
'@types/node':
specifier: ^24.3.0
version: 24.10.13
@@ -877,13 +877,13 @@ importers:
version: 17.3.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -898,7 +898,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
vitest:
specifier: ^3.2.4
version: 3.2.4(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
@@ -911,7 +911,7 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
'@types/node':
specifier: ^24.3.0
version: 24.10.13
@@ -920,13 +920,13 @@ importers:
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -941,7 +941,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/type-id:
dependencies:
@@ -951,19 +951,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
'@types/node':
specifier: ^24.3.0
version: 24.10.13
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -978,7 +978,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
vitest:
specifier: ^3.2.4
version: 3.2.4(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
@@ -994,7 +994,7 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
'@types/node':
specifier: ^24.3.0
version: 24.10.13
@@ -1003,13 +1003,13 @@ importers:
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -1024,7 +1024,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/uni-sat:
dependencies:
@@ -1034,19 +1034,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -1061,7 +1061,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/utxo-global:
dependencies:
@@ -1071,19 +1071,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -1098,7 +1098,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
ccc-dev/ccc/packages/xverse:
dependencies:
@@ -1111,19 +1111,19 @@ importers:
devDependencies:
'@eslint/js':
specifier: ^9.34.0
- version: 9.39.2
+ version: 9.39.3
copyfiles:
specifier: ^2.4.1
version: 2.4.1
eslint:
specifier: ^9.34.0
- version: 9.39.2(jiti@2.6.1)
+ version: 9.39.3(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ version: 10.1.8(eslint@9.39.3(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1)
+ version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1)
prettier:
specifier: ^3.6.2
version: 3.8.1
@@ -1138,7 +1138,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.41.0
- version: 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
+ version: 8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
packages/core:
dependencies:
@@ -1526,312 +1526,156 @@ packages:
cpu: [ppc64]
os: [aix]
- '@esbuild/aix-ppc64@0.27.3':
- resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==}
- engines: {node: '>=18'}
- cpu: [ppc64]
- os: [aix]
-
'@esbuild/android-arm64@0.25.12':
resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
- '@esbuild/android-arm64@0.27.3':
- resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [android]
-
'@esbuild/android-arm@0.25.12':
resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
- '@esbuild/android-arm@0.27.3':
- resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==}
- engines: {node: '>=18'}
- cpu: [arm]
- os: [android]
-
'@esbuild/android-x64@0.25.12':
resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
- '@esbuild/android-x64@0.27.3':
- resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [android]
-
'@esbuild/darwin-arm64@0.25.12':
resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
- '@esbuild/darwin-arm64@0.27.3':
- resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [darwin]
-
'@esbuild/darwin-x64@0.25.12':
resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
- '@esbuild/darwin-x64@0.27.3':
- resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [darwin]
-
'@esbuild/freebsd-arm64@0.25.12':
resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
- '@esbuild/freebsd-arm64@0.27.3':
- resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [freebsd]
-
'@esbuild/freebsd-x64@0.25.12':
resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
- '@esbuild/freebsd-x64@0.27.3':
- resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [freebsd]
-
'@esbuild/linux-arm64@0.25.12':
resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
- '@esbuild/linux-arm64@0.27.3':
- resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [linux]
-
'@esbuild/linux-arm@0.25.12':
resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
- '@esbuild/linux-arm@0.27.3':
- resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==}
- engines: {node: '>=18'}
- cpu: [arm]
- os: [linux]
-
'@esbuild/linux-ia32@0.25.12':
resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
- '@esbuild/linux-ia32@0.27.3':
- resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==}
- engines: {node: '>=18'}
- cpu: [ia32]
- os: [linux]
-
'@esbuild/linux-loong64@0.25.12':
resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
- '@esbuild/linux-loong64@0.27.3':
- resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==}
- engines: {node: '>=18'}
- cpu: [loong64]
- os: [linux]
-
'@esbuild/linux-mips64el@0.25.12':
resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
- '@esbuild/linux-mips64el@0.27.3':
- resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==}
- engines: {node: '>=18'}
- cpu: [mips64el]
- os: [linux]
-
'@esbuild/linux-ppc64@0.25.12':
resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
- '@esbuild/linux-ppc64@0.27.3':
- resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==}
- engines: {node: '>=18'}
- cpu: [ppc64]
- os: [linux]
-
'@esbuild/linux-riscv64@0.25.12':
resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
- '@esbuild/linux-riscv64@0.27.3':
- resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==}
- engines: {node: '>=18'}
- cpu: [riscv64]
- os: [linux]
-
'@esbuild/linux-s390x@0.25.12':
resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
- '@esbuild/linux-s390x@0.27.3':
- resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==}
- engines: {node: '>=18'}
- cpu: [s390x]
- os: [linux]
-
'@esbuild/linux-x64@0.25.12':
resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
- '@esbuild/linux-x64@0.27.3':
- resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [linux]
-
'@esbuild/netbsd-arm64@0.25.12':
resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
- '@esbuild/netbsd-arm64@0.27.3':
- resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [netbsd]
-
'@esbuild/netbsd-x64@0.25.12':
resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
- '@esbuild/netbsd-x64@0.27.3':
- resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [netbsd]
-
'@esbuild/openbsd-arm64@0.25.12':
resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
- '@esbuild/openbsd-arm64@0.27.3':
- resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [openbsd]
-
'@esbuild/openbsd-x64@0.25.12':
resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
- '@esbuild/openbsd-x64@0.27.3':
- resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [openbsd]
-
'@esbuild/openharmony-arm64@0.25.12':
resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
- '@esbuild/openharmony-arm64@0.27.3':
- resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [openharmony]
-
'@esbuild/sunos-x64@0.25.12':
resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
- '@esbuild/sunos-x64@0.27.3':
- resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [sunos]
-
'@esbuild/win32-arm64@0.25.12':
resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
- '@esbuild/win32-arm64@0.27.3':
- resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [win32]
-
'@esbuild/win32-ia32@0.25.12':
resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
- '@esbuild/win32-ia32@0.27.3':
- resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==}
- engines: {node: '>=18'}
- cpu: [ia32]
- os: [win32]
-
'@esbuild/win32-x64@0.25.12':
resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
- '@esbuild/win32-x64@0.27.3':
- resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [win32]
-
'@eslint-community/eslint-utils@4.9.1':
resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -1858,10 +1702,6 @@ packages:
resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/js@9.39.2':
- resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
'@eslint/js@9.39.3':
resolution: {integrity: sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2287,277 +2127,139 @@ packages:
'@rolldown/pluginutils@1.0.0-rc.3':
resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==}
- '@rollup/rollup-android-arm-eabi@4.57.1':
- resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==}
- cpu: [arm]
- os: [android]
-
'@rollup/rollup-android-arm-eabi@4.58.0':
resolution: {integrity: sha512-mr0tmS/4FoVk1cnaeN244A/wjvGDNItZKR8hRhnmCzygyRXYtKF5jVDSIILR1U97CTzAYmbgIj/Dukg62ggG5w==}
cpu: [arm]
os: [android]
- '@rollup/rollup-android-arm64@4.57.1':
- resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==}
- cpu: [arm64]
- os: [android]
-
'@rollup/rollup-android-arm64@4.58.0':
resolution: {integrity: sha512-+s++dbp+/RTte62mQD9wLSbiMTV+xr/PeRJEc/sFZFSBRlHPNPVaf5FXlzAL77Mr8FtSfQqCN+I598M8U41ccQ==}
cpu: [arm64]
os: [android]
- '@rollup/rollup-darwin-arm64@4.57.1':
- resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==}
- cpu: [arm64]
- os: [darwin]
-
'@rollup/rollup-darwin-arm64@4.58.0':
resolution: {integrity: sha512-MFWBwTcYs0jZbINQBXHfSrpSQJq3IUOakcKPzfeSznONop14Pxuqa0Kg19GD0rNBMPQI2tFtu3UzapZpH0Uc1Q==}
cpu: [arm64]
os: [darwin]
- '@rollup/rollup-darwin-x64@4.57.1':
- resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==}
- cpu: [x64]
- os: [darwin]
-
'@rollup/rollup-darwin-x64@4.58.0':
resolution: {integrity: sha512-yiKJY7pj9c9JwzuKYLFaDZw5gma3fI9bkPEIyofvVfsPqjCWPglSHdpdwXpKGvDeYDms3Qal8qGMEHZ1M/4Udg==}
cpu: [x64]
os: [darwin]
- '@rollup/rollup-freebsd-arm64@4.57.1':
- resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==}
- cpu: [arm64]
- os: [freebsd]
-
'@rollup/rollup-freebsd-arm64@4.58.0':
resolution: {integrity: sha512-x97kCoBh5MOevpn/CNK9W1x8BEzO238541BGWBc315uOlN0AD/ifZ1msg+ZQB05Ux+VF6EcYqpiagfLJ8U3LvQ==}
cpu: [arm64]
os: [freebsd]
- '@rollup/rollup-freebsd-x64@4.57.1':
- resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==}
- cpu: [x64]
- os: [freebsd]
-
'@rollup/rollup-freebsd-x64@4.58.0':
resolution: {integrity: sha512-Aa8jPoZ6IQAG2eIrcXPpjRcMjROMFxCt1UYPZZtCxRV68WkuSigYtQ/7Zwrcr2IvtNJo7T2JfDXyMLxq5L4Jlg==}
cpu: [x64]
os: [freebsd]
- '@rollup/rollup-linux-arm-gnueabihf@4.57.1':
- resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==}
- cpu: [arm]
- os: [linux]
- libc: [glibc]
-
'@rollup/rollup-linux-arm-gnueabihf@4.58.0':
resolution: {integrity: sha512-Ob8YgT5kD/lSIYW2Rcngs5kNB/44Q2RzBSPz9brf2WEtcGR7/f/E9HeHn1wYaAwKBni+bdXEwgHvUd0x12lQSA==}
cpu: [arm]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-arm-musleabihf@4.57.1':
- resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==}
- cpu: [arm]
- os: [linux]
- libc: [musl]
-
'@rollup/rollup-linux-arm-musleabihf@4.58.0':
resolution: {integrity: sha512-K+RI5oP1ceqoadvNt1FecL17Qtw/n9BgRSzxif3rTL2QlIu88ccvY+Y9nnHe/cmT5zbH9+bpiJuG1mGHRVwF4Q==}
cpu: [arm]
os: [linux]
libc: [musl]
- '@rollup/rollup-linux-arm64-gnu@4.57.1':
- resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==}
- cpu: [arm64]
- os: [linux]
- libc: [glibc]
-
'@rollup/rollup-linux-arm64-gnu@4.58.0':
resolution: {integrity: sha512-T+17JAsCKUjmbopcKepJjHWHXSjeW7O5PL7lEFaeQmiVyw4kkc5/lyYKzrv6ElWRX/MrEWfPiJWqbTvfIvjM1Q==}
cpu: [arm64]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-arm64-musl@4.57.1':
- resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==}
- cpu: [arm64]
- os: [linux]
- libc: [musl]
-
'@rollup/rollup-linux-arm64-musl@4.58.0':
resolution: {integrity: sha512-cCePktb9+6R9itIJdeCFF9txPU7pQeEHB5AbHu/MKsfH/k70ZtOeq1k4YAtBv9Z7mmKI5/wOLYjQ+B9QdxR6LA==}
cpu: [arm64]
os: [linux]
libc: [musl]
- '@rollup/rollup-linux-loong64-gnu@4.57.1':
- resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==}
- cpu: [loong64]
- os: [linux]
- libc: [glibc]
-
'@rollup/rollup-linux-loong64-gnu@4.58.0':
resolution: {integrity: sha512-iekUaLkfliAsDl4/xSdoCJ1gnnIXvoNz85C8U8+ZxknM5pBStfZjeXgB8lXobDQvvPRCN8FPmmuTtH+z95HTmg==}
cpu: [loong64]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-loong64-musl@4.57.1':
- resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==}
- cpu: [loong64]
- os: [linux]
- libc: [musl]
-
'@rollup/rollup-linux-loong64-musl@4.58.0':
resolution: {integrity: sha512-68ofRgJNl/jYJbxFjCKE7IwhbfxOl1muPN4KbIqAIe32lm22KmU7E8OPvyy68HTNkI2iV/c8y2kSPSm2mW/Q9Q==}
cpu: [loong64]
os: [linux]
libc: [musl]
- '@rollup/rollup-linux-ppc64-gnu@4.57.1':
- resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==}
- cpu: [ppc64]
- os: [linux]
- libc: [glibc]
-
'@rollup/rollup-linux-ppc64-gnu@4.58.0':
resolution: {integrity: sha512-dpz8vT0i+JqUKuSNPCP5SYyIV2Lh0sNL1+FhM7eLC457d5B9/BC3kDPp5BBftMmTNsBarcPcoz5UGSsnCiw4XQ==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-ppc64-musl@4.57.1':
- resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==}
- cpu: [ppc64]
- os: [linux]
- libc: [musl]
-
'@rollup/rollup-linux-ppc64-musl@4.58.0':
resolution: {integrity: sha512-4gdkkf9UJ7tafnweBCR/mk4jf3Jfl0cKX9Np80t5i78kjIH0ZdezUv/JDI2VtruE5lunfACqftJ8dIMGN4oHew==}
cpu: [ppc64]
os: [linux]
libc: [musl]
- '@rollup/rollup-linux-riscv64-gnu@4.57.1':
- resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==}
- cpu: [riscv64]
- os: [linux]
- libc: [glibc]
-
'@rollup/rollup-linux-riscv64-gnu@4.58.0':
resolution: {integrity: sha512-YFS4vPnOkDTD/JriUeeZurFYoJhPf9GQQEF/v4lltp3mVcBmnsAdjEWhr2cjUCZzZNzxCG0HZOvJU44UGHSdzw==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-riscv64-musl@4.57.1':
- resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==}
- cpu: [riscv64]
- os: [linux]
- libc: [musl]
-
'@rollup/rollup-linux-riscv64-musl@4.58.0':
resolution: {integrity: sha512-x2xgZlFne+QVNKV8b4wwaCS8pwq3y14zedZ5DqLzjdRITvreBk//4Knbcvm7+lWmms9V9qFp60MtUd0/t/PXPw==}
cpu: [riscv64]
os: [linux]
libc: [musl]
- '@rollup/rollup-linux-s390x-gnu@4.57.1':
- resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==}
- cpu: [s390x]
- os: [linux]
- libc: [glibc]
-
'@rollup/rollup-linux-s390x-gnu@4.58.0':
resolution: {integrity: sha512-jIhrujyn4UnWF8S+DHSkAkDEO3hLX0cjzxJZPLF80xFyzyUIYgSMRcYQ3+uqEoyDD2beGq7Dj7edi8OnJcS/hg==}
cpu: [s390x]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-x64-gnu@4.57.1':
- resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==}
- cpu: [x64]
- os: [linux]
- libc: [glibc]
-
'@rollup/rollup-linux-x64-gnu@4.58.0':
resolution: {integrity: sha512-+410Srdoh78MKSJxTQ+hZ/Mx+ajd6RjjPwBPNd0R3J9FtL6ZA0GqiiyNjCO9In0IzZkCNrpGymSfn+kgyPQocg==}
cpu: [x64]
os: [linux]
libc: [glibc]
- '@rollup/rollup-linux-x64-musl@4.57.1':
- resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==}
- cpu: [x64]
- os: [linux]
- libc: [musl]
-
'@rollup/rollup-linux-x64-musl@4.58.0':
resolution: {integrity: sha512-ZjMyby5SICi227y1MTR3VYBpFTdZs823Rs/hpakufleBoufoOIB6jtm9FEoxn/cgO7l6PM2rCEl5Kre5vX0QrQ==}
cpu: [x64]
os: [linux]
libc: [musl]
- '@rollup/rollup-openbsd-x64@4.57.1':
- resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==}
- cpu: [x64]
- os: [openbsd]
-
'@rollup/rollup-openbsd-x64@4.58.0':
resolution: {integrity: sha512-ds4iwfYkSQ0k1nb8LTcyXw//ToHOnNTJtceySpL3fa7tc/AsE+UpUFphW126A6fKBGJD5dhRvg8zw1rvoGFxmw==}
cpu: [x64]
os: [openbsd]
- '@rollup/rollup-openharmony-arm64@4.57.1':
- resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==}
- cpu: [arm64]
- os: [openharmony]
-
'@rollup/rollup-openharmony-arm64@4.58.0':
resolution: {integrity: sha512-fd/zpJniln4ICdPkjWFhZYeY/bpnaN9pGa6ko+5WD38I0tTqk9lXMgXZg09MNdhpARngmxiCg0B0XUamNw/5BQ==}
cpu: [arm64]
os: [openharmony]
- '@rollup/rollup-win32-arm64-msvc@4.57.1':
- resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==}
- cpu: [arm64]
- os: [win32]
-
'@rollup/rollup-win32-arm64-msvc@4.58.0':
resolution: {integrity: sha512-YpG8dUOip7DCz3nr/JUfPbIUo+2d/dy++5bFzgi4ugOGBIox+qMbbqt/JoORwvI/C9Kn2tz6+Bieoqd5+B1CjA==}
cpu: [arm64]
os: [win32]
- '@rollup/rollup-win32-ia32-msvc@4.57.1':
- resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==}
- cpu: [ia32]
- os: [win32]
-
'@rollup/rollup-win32-ia32-msvc@4.58.0':
resolution: {integrity: sha512-b9DI8jpFQVh4hIXFr0/+N/TzLdpBIoPzjt0Rt4xJbW3mzguV3mduR9cNgiuFcuL/TeORejJhCWiAXe3E/6PxWA==}
cpu: [ia32]
os: [win32]
- '@rollup/rollup-win32-x64-gnu@4.57.1':
- resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==}
- cpu: [x64]
- os: [win32]
-
'@rollup/rollup-win32-x64-gnu@4.58.0':
resolution: {integrity: sha512-CSrVpmoRJFN06LL9xhkitkwUcTZtIotYAF5p6XOR2zW0Zz5mzb3IPpcoPhB02frzMHFNo1reQ9xSF5fFm3hUsQ==}
cpu: [x64]
os: [win32]
- '@rollup/rollup-win32-x64-msvc@4.57.1':
- resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==}
- cpu: [x64]
- os: [win32]
-
'@rollup/rollup-win32-x64-msvc@4.58.0':
resolution: {integrity: sha512-QFsBgQNTnh5K0t/sBsjJLq24YVqEIVkGpfN2VHsnN90soZyhaiA9UUHufcctVNL4ypJY0wrwad0wslx2KJQ1/w==}
cpu: [x64]
@@ -2925,9 +2627,6 @@ packages:
aes-js@4.0.0-beta.5:
resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==}
- ajv@6.12.6:
- resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
-
ajv@6.14.0:
resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==}
@@ -2982,8 +2681,8 @@ packages:
axios@1.13.5:
resolution: {integrity: sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==}
- b4a@1.7.5:
- resolution: {integrity: sha512-iEsKNwDh1wiWTps1/hdkNdmBgDlDVZP5U57ZVOlt+dNFqpc/lpPouCIxZw+DYBgc4P9NDfIZMPNR4CHNhzwLIA==}
+ b4a@1.8.0:
+ resolution: {integrity: sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==}
peerDependencies:
react-native-b4a: '*'
peerDependenciesMeta:
@@ -3213,8 +2912,8 @@ packages:
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
- electron-to-chromium@1.5.286:
- resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==}
+ electron-to-chromium@1.5.302:
+ resolution: {integrity: sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==}
elliptic@6.6.1:
resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==}
@@ -3260,13 +2959,8 @@ packages:
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
engines: {node: '>= 0.4'}
- esbuild@0.25.12:
- resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
- engines: {node: '>=18'}
- hasBin: true
-
- esbuild@0.27.3:
- resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==}
+ esbuild@0.25.12:
+ resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
engines: {node: '>=18'}
hasBin: true
@@ -3327,20 +3021,10 @@ packages:
resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- eslint-visitor-keys@5.0.0:
- resolution: {integrity: sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==}
+ eslint-visitor-keys@5.0.1:
+ resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==}
engines: {node: ^20.19.0 || ^22.13.0 || >=24}
- eslint@9.39.2:
- resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- hasBin: true
- peerDependencies:
- jiti: '*'
- peerDependenciesMeta:
- jiti:
- optional: true
-
eslint@9.39.3:
resolution: {integrity: sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3517,9 +3201,9 @@ packages:
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
hasBin: true
- glob@13.0.5:
- resolution: {integrity: sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw==}
- engines: {node: 20 || >=22}
+ glob@13.0.6:
+ resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
+ engines: {node: 18 || 20 || >=22}
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
@@ -3895,9 +3579,9 @@ packages:
minimalistic-crypto-utils@1.0.1:
resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==}
- minimatch@10.2.1:
- resolution: {integrity: sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==}
- engines: {node: 20 || >=22}
+ minimatch@10.2.2:
+ resolution: {integrity: sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==}
+ engines: {node: 18 || 20 || >=22}
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@@ -4018,9 +3702,9 @@ packages:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'}
- path-scurry@2.0.1:
- resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==}
- engines: {node: 20 || >=22}
+ path-scurry@2.0.2:
+ resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
+ engines: {node: 18 || 20 || >=22}
path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
@@ -4240,11 +3924,6 @@ packages:
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
- rollup@4.57.1:
- resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==}
- engines: {node: '>=18.0.0', npm: '>=8.0.0'}
- hasBin: true
-
rollup@4.58.0:
resolution: {integrity: sha512-wbT0mBmWbIvvq8NeEYWWvevvxnOyhKChir47S66WCxw1SXqhw7ssIYejnQEVt7XYQpsj2y8F9PM+Cr3SNEa0gw==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -4580,46 +4259,6 @@ packages:
yaml:
optional: true
- vite@7.3.1:
- resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
- engines: {node: ^20.19.0 || >=22.12.0}
- hasBin: true
- peerDependencies:
- '@types/node': ^20.19.0 || >=22.12.0
- jiti: '>=1.21.0'
- less: ^4.0.0
- lightningcss: ^1.21.0
- sass: ^1.70.0
- sass-embedded: ^1.70.0
- stylus: '>=0.54.8'
- sugarss: ^5.0.0
- terser: ^5.16.0
- tsx: ^4.8.1
- yaml: ^2.4.2
- peerDependenciesMeta:
- '@types/node':
- optional: true
- jiti:
- optional: true
- less:
- optional: true
- lightningcss:
- optional: true
- sass:
- optional: true
- sass-embedded:
- optional: true
- stylus:
- optional: true
- sugarss:
- optional: true
- terser:
- optional: true
- tsx:
- optional: true
- yaml:
- optional: true
-
vitest@3.2.4:
resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -5346,164 +4985,81 @@ snapshots:
'@esbuild/aix-ppc64@0.25.12':
optional: true
- '@esbuild/aix-ppc64@0.27.3':
- optional: true
-
'@esbuild/android-arm64@0.25.12':
optional: true
- '@esbuild/android-arm64@0.27.3':
- optional: true
-
'@esbuild/android-arm@0.25.12':
optional: true
- '@esbuild/android-arm@0.27.3':
- optional: true
-
'@esbuild/android-x64@0.25.12':
optional: true
- '@esbuild/android-x64@0.27.3':
- optional: true
-
'@esbuild/darwin-arm64@0.25.12':
optional: true
- '@esbuild/darwin-arm64@0.27.3':
- optional: true
-
'@esbuild/darwin-x64@0.25.12':
optional: true
- '@esbuild/darwin-x64@0.27.3':
- optional: true
-
'@esbuild/freebsd-arm64@0.25.12':
optional: true
- '@esbuild/freebsd-arm64@0.27.3':
- optional: true
-
'@esbuild/freebsd-x64@0.25.12':
optional: true
- '@esbuild/freebsd-x64@0.27.3':
- optional: true
-
'@esbuild/linux-arm64@0.25.12':
optional: true
- '@esbuild/linux-arm64@0.27.3':
- optional: true
-
'@esbuild/linux-arm@0.25.12':
optional: true
- '@esbuild/linux-arm@0.27.3':
- optional: true
-
'@esbuild/linux-ia32@0.25.12':
optional: true
- '@esbuild/linux-ia32@0.27.3':
- optional: true
-
'@esbuild/linux-loong64@0.25.12':
optional: true
- '@esbuild/linux-loong64@0.27.3':
- optional: true
-
'@esbuild/linux-mips64el@0.25.12':
optional: true
- '@esbuild/linux-mips64el@0.27.3':
- optional: true
-
'@esbuild/linux-ppc64@0.25.12':
optional: true
- '@esbuild/linux-ppc64@0.27.3':
- optional: true
-
'@esbuild/linux-riscv64@0.25.12':
optional: true
- '@esbuild/linux-riscv64@0.27.3':
- optional: true
-
'@esbuild/linux-s390x@0.25.12':
optional: true
- '@esbuild/linux-s390x@0.27.3':
- optional: true
-
'@esbuild/linux-x64@0.25.12':
optional: true
- '@esbuild/linux-x64@0.27.3':
- optional: true
-
'@esbuild/netbsd-arm64@0.25.12':
optional: true
- '@esbuild/netbsd-arm64@0.27.3':
- optional: true
-
'@esbuild/netbsd-x64@0.25.12':
optional: true
- '@esbuild/netbsd-x64@0.27.3':
- optional: true
-
'@esbuild/openbsd-arm64@0.25.12':
optional: true
- '@esbuild/openbsd-arm64@0.27.3':
- optional: true
-
'@esbuild/openbsd-x64@0.25.12':
optional: true
- '@esbuild/openbsd-x64@0.27.3':
- optional: true
-
'@esbuild/openharmony-arm64@0.25.12':
optional: true
- '@esbuild/openharmony-arm64@0.27.3':
- optional: true
-
'@esbuild/sunos-x64@0.25.12':
optional: true
- '@esbuild/sunos-x64@0.27.3':
- optional: true
-
'@esbuild/win32-arm64@0.25.12':
optional: true
- '@esbuild/win32-arm64@0.27.3':
- optional: true
-
'@esbuild/win32-ia32@0.25.12':
optional: true
- '@esbuild/win32-ia32@0.27.3':
- optional: true
-
'@esbuild/win32-x64@0.25.12':
optional: true
- '@esbuild/win32-x64@0.27.3':
- optional: true
-
- '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))':
- dependencies:
- eslint: 9.39.2(jiti@2.6.1)
- eslint-visitor-keys: 3.4.3
-
'@eslint-community/eslint-utils@4.9.1(eslint@9.39.3(jiti@2.6.1))':
dependencies:
eslint: 9.39.3(jiti@2.6.1)
@@ -5529,7 +5085,7 @@ snapshots:
'@eslint/eslintrc@3.3.3':
dependencies:
- ajv: 6.12.6
+ ajv: 6.14.0
debug: 4.4.3
espree: 10.4.0
globals: 14.0.0
@@ -5541,8 +5097,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@eslint/js@9.39.2': {}
-
'@eslint/js@9.39.3': {}
'@eslint/object-schema@2.1.7': {}
@@ -5893,153 +5447,78 @@ snapshots:
'@rolldown/pluginutils@1.0.0-rc.3': {}
- '@rollup/rollup-android-arm-eabi@4.57.1':
- optional: true
-
'@rollup/rollup-android-arm-eabi@4.58.0':
optional: true
- '@rollup/rollup-android-arm64@4.57.1':
- optional: true
-
'@rollup/rollup-android-arm64@4.58.0':
optional: true
- '@rollup/rollup-darwin-arm64@4.57.1':
- optional: true
-
'@rollup/rollup-darwin-arm64@4.58.0':
optional: true
- '@rollup/rollup-darwin-x64@4.57.1':
- optional: true
-
'@rollup/rollup-darwin-x64@4.58.0':
optional: true
- '@rollup/rollup-freebsd-arm64@4.57.1':
- optional: true
-
'@rollup/rollup-freebsd-arm64@4.58.0':
optional: true
- '@rollup/rollup-freebsd-x64@4.57.1':
- optional: true
-
'@rollup/rollup-freebsd-x64@4.58.0':
optional: true
- '@rollup/rollup-linux-arm-gnueabihf@4.57.1':
- optional: true
-
'@rollup/rollup-linux-arm-gnueabihf@4.58.0':
optional: true
- '@rollup/rollup-linux-arm-musleabihf@4.57.1':
- optional: true
-
'@rollup/rollup-linux-arm-musleabihf@4.58.0':
optional: true
- '@rollup/rollup-linux-arm64-gnu@4.57.1':
- optional: true
-
'@rollup/rollup-linux-arm64-gnu@4.58.0':
optional: true
- '@rollup/rollup-linux-arm64-musl@4.57.1':
- optional: true
-
'@rollup/rollup-linux-arm64-musl@4.58.0':
optional: true
- '@rollup/rollup-linux-loong64-gnu@4.57.1':
- optional: true
-
'@rollup/rollup-linux-loong64-gnu@4.58.0':
optional: true
- '@rollup/rollup-linux-loong64-musl@4.57.1':
- optional: true
-
'@rollup/rollup-linux-loong64-musl@4.58.0':
optional: true
- '@rollup/rollup-linux-ppc64-gnu@4.57.1':
- optional: true
-
'@rollup/rollup-linux-ppc64-gnu@4.58.0':
optional: true
- '@rollup/rollup-linux-ppc64-musl@4.57.1':
- optional: true
-
'@rollup/rollup-linux-ppc64-musl@4.58.0':
optional: true
- '@rollup/rollup-linux-riscv64-gnu@4.57.1':
- optional: true
-
'@rollup/rollup-linux-riscv64-gnu@4.58.0':
optional: true
- '@rollup/rollup-linux-riscv64-musl@4.57.1':
- optional: true
-
'@rollup/rollup-linux-riscv64-musl@4.58.0':
optional: true
- '@rollup/rollup-linux-s390x-gnu@4.57.1':
- optional: true
-
'@rollup/rollup-linux-s390x-gnu@4.58.0':
optional: true
- '@rollup/rollup-linux-x64-gnu@4.57.1':
- optional: true
-
'@rollup/rollup-linux-x64-gnu@4.58.0':
optional: true
- '@rollup/rollup-linux-x64-musl@4.57.1':
- optional: true
-
'@rollup/rollup-linux-x64-musl@4.58.0':
optional: true
- '@rollup/rollup-openbsd-x64@4.57.1':
- optional: true
-
'@rollup/rollup-openbsd-x64@4.58.0':
optional: true
- '@rollup/rollup-openharmony-arm64@4.57.1':
- optional: true
-
'@rollup/rollup-openharmony-arm64@4.58.0':
optional: true
- '@rollup/rollup-win32-arm64-msvc@4.57.1':
- optional: true
-
'@rollup/rollup-win32-arm64-msvc@4.58.0':
optional: true
- '@rollup/rollup-win32-ia32-msvc@4.57.1':
- optional: true
-
'@rollup/rollup-win32-ia32-msvc@4.58.0':
optional: true
- '@rollup/rollup-win32-x64-gnu@4.57.1':
- optional: true
-
'@rollup/rollup-win32-x64-gnu@4.58.0':
optional: true
- '@rollup/rollup-win32-x64-msvc@4.57.1':
- optional: true
-
'@rollup/rollup-win32-x64-msvc@4.58.0':
optional: true
@@ -6219,22 +5698,6 @@ snapshots:
dependencies:
'@types/node': 24.10.13
- '@typescript-eslint/eslint-plugin@8.56.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@eslint-community/regexpp': 4.12.2
- '@typescript-eslint/parser': 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/scope-manager': 8.56.0
- '@typescript-eslint/type-utils': 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/utils': 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/visitor-keys': 8.56.0
- eslint: 9.39.2(jiti@2.6.1)
- ignore: 7.0.5
- natural-compare: 1.4.0
- ts-api-utils: 2.4.0(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
'@typescript-eslint/eslint-plugin@8.56.0(@typescript-eslint/parser@8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
@@ -6251,18 +5714,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/scope-manager': 8.56.0
- '@typescript-eslint/types': 8.56.0
- '@typescript-eslint/typescript-estree': 8.56.0(typescript@5.9.3)
- '@typescript-eslint/visitor-keys': 8.56.0
- debug: 4.4.3
- eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
'@typescript-eslint/parser@8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.56.0
@@ -6293,18 +5744,6 @@ snapshots:
dependencies:
typescript: 5.9.3
- '@typescript-eslint/type-utils@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/types': 8.56.0
- '@typescript-eslint/typescript-estree': 8.56.0(typescript@5.9.3)
- '@typescript-eslint/utils': 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- debug: 4.4.3
- eslint: 9.39.2(jiti@2.6.1)
- ts-api-utils: 2.4.0(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
'@typescript-eslint/type-utils@8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/types': 8.56.0
@@ -6334,17 +5773,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1))
- '@typescript-eslint/scope-manager': 8.56.0
- '@typescript-eslint/types': 8.56.0
- '@typescript-eslint/typescript-estree': 8.56.0(typescript@5.9.3)
- eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
'@typescript-eslint/utils@8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3(jiti@2.6.1))
@@ -6359,7 +5787,7 @@ snapshots:
'@typescript-eslint/visitor-keys@8.56.0':
dependencies:
'@typescript-eslint/types': 8.56.0
- eslint-visitor-keys: 5.0.0
+ eslint-visitor-keys: 5.0.1
'@typescript/native-preview-darwin-arm64@7.0.0-dev.20260221.1':
optional: true
@@ -6435,13 +5863,13 @@ snapshots:
chai: 5.3.3
tinyrainbow: 2.0.0
- '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2))':
+ '@vitest/mocker@3.2.4(vite@6.4.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
- vite: 7.3.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
+ vite: 6.4.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
'@vitest/pretty-format@3.2.4':
dependencies:
@@ -6487,13 +5915,6 @@ snapshots:
aes-js@4.0.0-beta.5: {}
- ajv@6.12.6:
- dependencies:
- fast-deep-equal: 3.1.3
- fast-json-stable-stringify: 2.1.0
- json-schema-traverse: 0.4.1
- uri-js: 4.4.1
-
ajv@6.14.0:
dependencies:
fast-deep-equal: 3.1.3
@@ -6546,7 +5967,7 @@ snapshots:
transitivePeerDependencies:
- debug
- b4a@1.7.5: {}
+ b4a@1.8.0: {}
babel-plugin-react-compiler@1.0.0:
dependencies:
@@ -6574,7 +5995,7 @@ snapshots:
blake2b-wasm@2.4.0:
dependencies:
- b4a: 1.7.5
+ b4a: 1.8.0
nanoassert: 2.0.0
transitivePeerDependencies:
- react-native-b4a
@@ -6613,7 +6034,7 @@ snapshots:
dependencies:
baseline-browser-mapping: 2.10.0
caniuse-lite: 1.0.30001770
- electron-to-chromium: 1.5.286
+ electron-to-chromium: 1.5.302
node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1)
@@ -6757,7 +6178,7 @@ snapshots:
eastasianwidth@0.2.0: {}
- electron-to-chromium@1.5.286: {}
+ electron-to-chromium@1.5.302: {}
elliptic@6.6.1:
dependencies:
@@ -6833,71 +6254,42 @@ snapshots:
'@esbuild/win32-ia32': 0.25.12
'@esbuild/win32-x64': 0.25.12
- esbuild@0.27.3:
- optionalDependencies:
- '@esbuild/aix-ppc64': 0.27.3
- '@esbuild/android-arm': 0.27.3
- '@esbuild/android-arm64': 0.27.3
- '@esbuild/android-x64': 0.27.3
- '@esbuild/darwin-arm64': 0.27.3
- '@esbuild/darwin-x64': 0.27.3
- '@esbuild/freebsd-arm64': 0.27.3
- '@esbuild/freebsd-x64': 0.27.3
- '@esbuild/linux-arm': 0.27.3
- '@esbuild/linux-arm64': 0.27.3
- '@esbuild/linux-ia32': 0.27.3
- '@esbuild/linux-loong64': 0.27.3
- '@esbuild/linux-mips64el': 0.27.3
- '@esbuild/linux-ppc64': 0.27.3
- '@esbuild/linux-riscv64': 0.27.3
- '@esbuild/linux-s390x': 0.27.3
- '@esbuild/linux-x64': 0.27.3
- '@esbuild/netbsd-arm64': 0.27.3
- '@esbuild/netbsd-x64': 0.27.3
- '@esbuild/openbsd-arm64': 0.27.3
- '@esbuild/openbsd-x64': 0.27.3
- '@esbuild/openharmony-arm64': 0.27.3
- '@esbuild/sunos-x64': 0.27.3
- '@esbuild/win32-arm64': 0.27.3
- '@esbuild/win32-ia32': 0.27.3
- '@esbuild/win32-x64': 0.27.3
-
escalade@3.2.0: {}
escape-string-regexp@4.0.0: {}
- eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)):
+ eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)):
dependencies:
- eslint: 9.39.2(jiti@2.6.1)
+ eslint: 9.39.3(jiti@2.6.1)
- eslint-plugin-prettier@5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.8.1):
+ eslint-plugin-prettier@5.5.5(eslint-config-prettier@10.1.8(eslint@9.39.3(jiti@2.6.1)))(eslint@9.39.3(jiti@2.6.1))(prettier@3.8.1):
dependencies:
- eslint: 9.39.2(jiti@2.6.1)
+ eslint: 9.39.3(jiti@2.6.1)
prettier: 3.8.1
prettier-linter-helpers: 1.0.1
synckit: 0.11.12
optionalDependencies:
- eslint-config-prettier: 10.1.8(eslint@9.39.2(jiti@2.6.1))
+ eslint-config-prettier: 10.1.8(eslint@9.39.3(jiti@2.6.1))
- eslint-plugin-react-compiler@19.1.0-rc.2(eslint@9.39.2(jiti@2.6.1)):
+ eslint-plugin-react-compiler@19.1.0-rc.2(eslint@9.39.3(jiti@2.6.1)):
dependencies:
'@babel/core': 7.29.0
'@babel/parser': 7.29.0
'@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.29.0)
- eslint: 9.39.2(jiti@2.6.1)
+ eslint: 9.39.3(jiti@2.6.1)
hermes-parser: 0.25.1
zod: 3.25.76
zod-validation-error: 3.5.4(zod@3.25.76)
transitivePeerDependencies:
- supports-color
- eslint-plugin-react-hooks@5.2.0(eslint@9.39.2(jiti@2.6.1)):
+ eslint-plugin-react-hooks@5.2.0(eslint@9.39.3(jiti@2.6.1)):
dependencies:
- eslint: 9.39.2(jiti@2.6.1)
+ eslint: 9.39.3(jiti@2.6.1)
- eslint-plugin-react-refresh@0.4.26(eslint@9.39.2(jiti@2.6.1)):
+ eslint-plugin-react-refresh@0.4.26(eslint@9.39.3(jiti@2.6.1)):
dependencies:
- eslint: 9.39.2(jiti@2.6.1)
+ eslint: 9.39.3(jiti@2.6.1)
eslint-scope@8.4.0:
dependencies:
@@ -6908,48 +6300,7 @@ snapshots:
eslint-visitor-keys@4.2.1: {}
- eslint-visitor-keys@5.0.0: {}
-
- eslint@9.39.2(jiti@2.6.1):
- dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1))
- '@eslint-community/regexpp': 4.12.2
- '@eslint/config-array': 0.21.1
- '@eslint/config-helpers': 0.4.2
- '@eslint/core': 0.17.0
- '@eslint/eslintrc': 3.3.3
- '@eslint/js': 9.39.2
- '@eslint/plugin-kit': 0.4.1
- '@humanfs/node': 0.16.7
- '@humanwhocodes/module-importer': 1.0.1
- '@humanwhocodes/retry': 0.4.3
- '@types/estree': 1.0.8
- ajv: 6.12.6
- chalk: 4.1.2
- cross-spawn: 7.0.6
- debug: 4.4.3
- escape-string-regexp: 4.0.0
- eslint-scope: 8.4.0
- eslint-visitor-keys: 4.2.1
- espree: 10.4.0
- esquery: 1.7.0
- esutils: 2.0.3
- fast-deep-equal: 3.1.3
- file-entry-cache: 8.0.0
- find-up: 5.0.0
- glob-parent: 6.0.2
- ignore: 5.3.2
- imurmurhash: 0.1.4
- is-glob: 4.0.3
- json-stable-stringify-without-jsonify: 1.0.1
- lodash.merge: 4.6.2
- minimatch: 3.1.2
- natural-compare: 1.4.0
- optionator: 0.9.4
- optionalDependencies:
- jiti: 2.6.1
- transitivePeerDependencies:
- - supports-color
+ eslint-visitor-keys@5.0.1: {}
eslint@9.39.3(jiti@2.6.1):
dependencies:
@@ -7163,11 +6514,11 @@ snapshots:
package-json-from-dist: 1.0.1
path-scurry: 1.11.1
- glob@13.0.5:
+ glob@13.0.6:
dependencies:
- minimatch: 10.2.1
+ minimatch: 10.2.2
minipass: 7.1.3
- path-scurry: 2.0.1
+ path-scurry: 2.0.2
glob@7.2.3:
dependencies:
@@ -7494,7 +6845,7 @@ snapshots:
minimalistic-crypto-utils@1.0.1: {}
- minimatch@10.2.1:
+ minimatch@10.2.2:
dependencies:
brace-expansion: 5.0.2
@@ -7595,7 +6946,7 @@ snapshots:
lru-cache: 10.4.3
minipass: 7.1.3
- path-scurry@2.0.1:
+ path-scurry@2.0.2:
dependencies:
lru-cache: 11.2.6
minipass: 7.1.3
@@ -7700,7 +7051,7 @@ snapshots:
rimraf@6.1.3:
dependencies:
- glob: 13.0.5
+ glob: 13.0.6
package-json-from-dist: 1.0.1
rolldown-plugin-dts@0.20.0(@typescript/native-preview@7.0.0-dev.20260221.1)(rolldown@1.0.0-beta.58)(typescript@5.9.3):
@@ -7758,37 +7109,6 @@ snapshots:
'@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.3
'@rolldown/binding-win32-x64-msvc': 1.0.0-rc.3
- rollup@4.57.1:
- dependencies:
- '@types/estree': 1.0.8
- optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.57.1
- '@rollup/rollup-android-arm64': 4.57.1
- '@rollup/rollup-darwin-arm64': 4.57.1
- '@rollup/rollup-darwin-x64': 4.57.1
- '@rollup/rollup-freebsd-arm64': 4.57.1
- '@rollup/rollup-freebsd-x64': 4.57.1
- '@rollup/rollup-linux-arm-gnueabihf': 4.57.1
- '@rollup/rollup-linux-arm-musleabihf': 4.57.1
- '@rollup/rollup-linux-arm64-gnu': 4.57.1
- '@rollup/rollup-linux-arm64-musl': 4.57.1
- '@rollup/rollup-linux-loong64-gnu': 4.57.1
- '@rollup/rollup-linux-loong64-musl': 4.57.1
- '@rollup/rollup-linux-ppc64-gnu': 4.57.1
- '@rollup/rollup-linux-ppc64-musl': 4.57.1
- '@rollup/rollup-linux-riscv64-gnu': 4.57.1
- '@rollup/rollup-linux-riscv64-musl': 4.57.1
- '@rollup/rollup-linux-s390x-gnu': 4.57.1
- '@rollup/rollup-linux-x64-gnu': 4.57.1
- '@rollup/rollup-linux-x64-musl': 4.57.1
- '@rollup/rollup-openbsd-x64': 4.57.1
- '@rollup/rollup-openharmony-arm64': 4.57.1
- '@rollup/rollup-win32-arm64-msvc': 4.57.1
- '@rollup/rollup-win32-ia32-msvc': 4.57.1
- '@rollup/rollup-win32-x64-gnu': 4.57.1
- '@rollup/rollup-win32-x64-msvc': 4.57.1
- fsevents: 2.3.3
-
rollup@4.58.0:
dependencies:
'@types/estree': 1.0.8
@@ -8002,17 +7322,6 @@ snapshots:
typescript: 5.9.3
yaml: 2.8.2
- typescript-eslint@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
- dependencies:
- '@typescript-eslint/eslint-plugin': 8.56.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/parser': 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/typescript-estree': 8.56.0(typescript@5.9.3)
- '@typescript-eslint/utils': 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
typescript-eslint@8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3):
dependencies:
'@typescript-eslint/eslint-plugin': 8.56.0(@typescript-eslint/parser@8.56.0(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3)
@@ -8075,7 +7384,7 @@ snapshots:
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
- vite: 7.3.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
+ vite: 6.4.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -8096,7 +7405,7 @@ snapshots:
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
postcss: 8.5.6
- rollup: 4.57.1
+ rollup: 4.58.0
tinyglobby: 0.2.15
optionalDependencies:
'@types/node': 22.19.11
@@ -8105,9 +7414,9 @@ snapshots:
lightningcss: 1.31.1
yaml: 2.8.2
- vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2):
+ vite@6.4.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2):
dependencies:
- esbuild: 0.27.3
+ esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
postcss: 8.5.6
@@ -8124,7 +7433,7 @@ snapshots:
dependencies:
'@types/chai': 5.2.3
'@vitest/expect': 3.2.4
- '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2))
+ '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -8142,7 +7451,7 @@ snapshots:
tinyglobby: 0.2.15
tinypool: 1.1.1
tinyrainbow: 2.0.0
- vite: 7.3.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
+ vite: 6.4.1(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
vite-node: 3.2.4(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.2)
why-is-node-running: 2.3.0
optionalDependencies:
diff --git a/tsconfig.json b/tsconfig.json
index c78b9b7..4366330 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -16,6 +16,7 @@
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"noImplicitAny": true,
+ "noEmit": true,
"noEmitOnError": true,
"removeComments": true,
"stripInternal": true,