Skip to content

Commit a078424

Browse files
authored
feat: replace ckb-transaction-dumper with ccc-based implementation (#420) (#431)
* feat: replace ckb-transaction-dumper with ccc-based implementation - Rewrite src/tools/ckb-tx-dumper.ts to use ccc Client and molecule codecs - Implement dep_group unpacking using ccc.mol - Remove ckb-transaction-dumper from dependencies - Eliminates external npm dependency for transaction dumping * chore: add changeset for ckb-transaction-dumper replacement * fix: address PR review comments for ckb-tx-dumper - Remove .sisyphus/boulder.json and add to .gitignore - Fix type field serialization: emit null instead of undefined - Fix dep_type format: convert camelCase to snake_case (depGroup -> dep_group) - Fix depGroup error handling: throw error when refCell not found - Fix async race condition: make buildTxFileOptionBy and callers async * fix: fix CCC-based transaction dumper for debug command - Use cccA.JsonRpcTransformers.transactionTo() to handle snake_case input format - Convert all numeric values to hex format (since, index, version, capacity) - Add missing dep_group cell to mock_info.cell_deps before expansion - Add fs.mkdirSync to ensure output directory exists Fixes issues where debug command failed with 'undefined is not iterable', 'unprovided cell dep', or 'since is not a legal u64' errors. * fix: address Copilot PR review comments for ccc-based tx dumper - Select ClientPublicTestnet/Mainnet based on RPC URL pattern - Use proper error type checking with instanceof Error
2 parents dfe1b5f + 3da9777 commit a078424

8 files changed

Lines changed: 456 additions & 25 deletions

File tree

.changeset/wise-candies-stop.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@offckb/cli': minor
3+
---
4+
5+
Replace ckb-transaction-dumper with ccc-based implementation
6+
7+
- Rewrite transaction dumper to use ccc Client and molecule codecs
8+
- Implement dep_group unpacking using ccc.mol
9+
- Remove ckb-transaction-dumper npm dependency

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ package-lock.json
1212
# Test coverage
1313
coverage/
1414
*.lcov
15+
16+
# Sisyphus plans and sessions
17+
.sisyphus/

.sisyphus/plans/ckb-tx-dumper.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Replace ckb-transaction-dumper with ccc-based implementation
2+
3+
## TL;DR
4+
5+
> **Quick Summary**: Replace `ckb-transaction-dumper` npm package with a pure ccc-based implementation.
6+
>
7+
> **Deliverables**:
8+
>
9+
> - New `src/tools/ckb-tx-dumper.ts` (replaces old implementation)
10+
> - Removed `ckb-transaction-dumper` from package.json
11+
>
12+
> **Estimated Effort**: Medium (2-3 hours)
13+
> **Parallel Execution**: NO - sequential
14+
15+
---
16+
17+
## Context
18+
19+
### Request
20+
21+
Replace `ckb-transaction-dumper` with ccc-based implementation (no external dependencies, use ccc throughout).
22+
23+
### Current Implementation
24+
25+
- `src/tools/ckb-tx-dumper.ts` spawns `ckb-transaction-dumper` binary
26+
- Depends on npm package `ckb-transaction-dumper@0.4.2`
27+
28+
### What TransactionDumper Does
29+
30+
1. Load transaction (from file or fetch by hash)
31+
2. Resolve cell deps (handle dep_group type)
32+
3. Resolve inputs
33+
4. Output mock transaction JSON for ckb-debugger
34+
35+
### ccc Molecule Support
36+
37+
ccc provides full molecule codec:
38+
39+
- `ccc.molecule.struct()` - for OutPoint { tx_hash, index }
40+
- `ccc.molecule.vector()` - for OutPointVec
41+
- `ccc.Byte32`, `ccc.Uint32LE` - predefined codecs
42+
43+
No manual bytes parsing needed!
44+
45+
---
46+
47+
## Work Objectives
48+
49+
### Core Objective
50+
51+
Replace `ckb-transaction-dumper` with pure ccc implementation.
52+
53+
### Must Have
54+
55+
- Keep `DumpOption` interface
56+
- Keep `dumpTransaction()` signature
57+
- Same JSON output format
58+
59+
### Must NOT Have
60+
61+
- Breaking API changes
62+
- New dependencies
63+
64+
---
65+
66+
## TODOs
67+
68+
- [ ] 1. Implement ccc-based transaction dumper
69+
70+
**What to do**:
71+
72+
- Rewrite `src/tools/ckb-tx-dumper.ts`
73+
- Use ccc Client for RPC calls
74+
- Use ccc molecule codecs for dep_group unpacking
75+
76+
**Key implementation**:
77+
78+
```typescript
79+
import { ccc } from '@ckb-ccc/core';
80+
81+
// OutPoint codec for dep_group unpacking
82+
const OutPointCodec = ccc.molecule.struct({
83+
txHash: ccc.Byte32,
84+
index: ccc.Uint32LE,
85+
});
86+
87+
const OutPointVecCodec = ccc.molecule.vector(OutPointCodec);
88+
89+
// Unpack dep_group data
90+
function unpackDepGroup(data: string): ccc.OutPoint[] {
91+
return OutPointVecCodec.decode(data).map((o) =>
92+
ccc.OutPoint.from({ txHash: o.txHash, index: '0x' + o.index.toString(16) }),
93+
);
94+
}
95+
```
96+
97+
**Acceptance Criteria**:
98+
99+
- [ ] Uses ccc Client for RPC
100+
- [ ] Uses ccc molecule for dep_group
101+
- [ ] Same output format
102+
103+
**QA Scenarios**:
104+
105+
```
106+
Scenario: Compiles successfully
107+
Tool: Bash
108+
Steps: npm run typecheck
109+
Expected: No errors
110+
```
111+
112+
**Commit**: `feat: implement transaction dumper with ccc`
113+
114+
---
115+
116+
- [ ] 2. Remove ckb-transaction-dumper dependency
117+
118+
**What to do**:
119+
120+
- Remove from `package.json`
121+
- Run `pnpm install`
122+
123+
**Commit**: `chore: remove ckb-transaction-dumper`
124+
125+
---
126+
127+
## Verification
128+
129+
```bash
130+
npm run typecheck
131+
npm run lint
132+
grep -c "ckb-transaction-dumper" package.json || echo "Clean"
133+
```
134+
135+
## Key Implementation Notes
136+
137+
### Dep Group Unpacking with ccc
138+
139+
```typescript
140+
const OutPointCodec = ccc.molecule.struct({
141+
txHash: ccc.Byte32,
142+
index: ccc.Uint32LE,
143+
});
144+
const OutPointVecCodec = ccc.molecule.vector(OutPointCodec);
145+
146+
// Usage
147+
const outpoints = OutPointVecCodec.decode(cellData);
148+
```
149+
150+
### Mock Transaction Structure
151+
152+
```typescript
153+
interface MockTransaction {
154+
mock_info: {
155+
inputs: MockInput[];
156+
cell_deps: MockCellDep[];
157+
header_deps: any[];
158+
};
159+
tx: Transaction;
160+
}
161+
```
162+
163+
### Algorithm
164+
165+
1. Load tx from file
166+
2. For each cell_dep:
167+
- Fetch cell
168+
- If dep_type === 'dep_group':
169+
- Decode cell.data as OutPointVec
170+
- Fetch each referenced cell
171+
- Add to mock_info.cell_deps
172+
3. For each input:
173+
- Fetch referenced cell
174+
- Add to mock_info.inputs
175+
4. Write JSON output

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@
8686
"blessed": "0.1.81",
8787
"chalk": "4.1.2",
8888
"child_process": "^1.0.2",
89-
"ckb-transaction-dumper": "^0.4.2",
9089
"commander": "^12.0.0",
9190
"http-proxy": "^1.18.1",
9291
"https-proxy-agent": "^7.0.5",

pnpm-lock.yaml

Lines changed: 8 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cli.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ program
8181
const txHash = option.txHash;
8282
if (option.singleScript) {
8383
const { cellType, cellIndex, scriptType } = parseSingleScriptOption(option.singleScript);
84-
return debugSingleScript(txHash, cellIndex, cellType, scriptType, option.network, option.bin);
84+
return await debugSingleScript(txHash, cellIndex, cellType, scriptType, option.network, option.bin);
8585
}
86-
return debugTransaction(txHash, option.network);
86+
return await debugTransaction(txHash, option.network);
8787
});
8888

8989
program

src/cmd/debug.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import { Network } from '../type/base';
88
import { encodeBinPathForTerminal } from '../util/encoding';
99
import { logger } from '../util/logger';
1010

11-
export function debugTransaction(txHash: string, network: Network) {
12-
const txFile = buildTxFileOptionBy(txHash, network);
11+
export async function debugTransaction(txHash: string, network: Network) {
12+
const txFile = await buildTxFileOptionBy(txHash, network);
1313
const opts = buildTransactionDebugOptions(txHash, network);
1414
for (const opt of opts) {
1515
logger.section(opt.name, [], 'info');
@@ -48,15 +48,15 @@ export function buildTransactionDebugOptions(txHash: string, network: Network) {
4848
return result;
4949
}
5050

51-
export function debugSingleScript(
51+
export async function debugSingleScript(
5252
txHash: string,
5353
cellIndex: number,
5454
cellType: 'input' | 'output',
5555
scriptType: 'type' | 'lock',
5656
network: Network,
5757
bin?: string,
5858
) {
59-
const txFile = buildTxFileOptionBy(txHash, network);
59+
const txFile = await buildTxFileOptionBy(txHash, network);
6060
let opt = `--cell-index ${cellIndex} --cell-type ${cellType} --script-group-type ${scriptType}`;
6161
if (bin) {
6262
opt = opt + ` --bin ${bin}`;
@@ -81,7 +81,7 @@ export function parseSingleScriptOption(value: string) {
8181
};
8282
}
8383

84-
export function buildTxFileOptionBy(txHash: string, network: Network) {
84+
export async function buildTxFileOptionBy(txHash: string, network: Network) {
8585
const settings = readSettings();
8686
const outputFilePath = buildDebugFullTransactionFilePath(network, txHash);
8787
if (!fs.existsSync(outputFilePath)) {
@@ -90,7 +90,7 @@ export function buildTxFileOptionBy(txHash: string, network: Network) {
9090
if (!fs.existsSync(outputFilePath)) {
9191
fs.mkdirSync(path.dirname(outputFilePath), { recursive: true });
9292
}
93-
dumpTransaction({ rpc, txJsonFilePath, outputFilePath });
93+
await dumpTransaction({ rpc, txJsonFilePath, outputFilePath });
9494
}
9595
const opt = `--tx-file ${encodeBinPathForTerminal(outputFilePath)}`;
9696
return opt;

0 commit comments

Comments
 (0)