Skip to content

feat(coin): new coin package#415

Open
Hanssen0 wants to merge 2 commits into
ckb-devrel:next-majorfrom
Hanssen0:feat/coin
Open

feat(coin): new coin package#415
Hanssen0 wants to merge 2 commits into
ckb-devrel:next-majorfrom
Hanssen0:feat/coin

Conversation

@Hanssen0

Copy link
Copy Markdown
Member

@changeset-bot

changeset-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 627b291

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@ckb-ccc/shell Minor
@ckb-ccc/coin Minor
@ckb-ccc/ccc Patch
ckb-ccc Patch
@ckb-ccc/connector Patch
@ckb-ccc/connector-react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify

netlify Bot commented Jun 30, 2026

Copy link
Copy Markdown

Deploy Preview for apiccc ready!

Name Link
🔨 Latest commit 627b291
🔍 Latest deploy log https://app.netlify.com/projects/apiccc/deploys/6a63c15c5e169700086b6e22
😎 Deploy Preview https://deploy-preview-415--apiccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 86 (🔴 down 8 from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 95 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Jun 30, 2026

Copy link
Copy Markdown

Deploy Preview for appccc ready!

Name Link
🔨 Latest commit 627b291
🔍 Latest deploy log https://app.netlify.com/projects/appccc/deploys/6a63c15ca32b350008e93339
😎 Deploy Preview https://deploy-preview-415--appccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 69 (🔴 down 15 from production)
Accessibility: 89 (🟢 up 1 from production)
Best Practices: 92 (🔴 down 8 from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Jun 30, 2026

Copy link
Copy Markdown

Deploy Preview for liveccc ready!

Name Link
🔨 Latest commit 627b291
🔍 Latest deploy log https://app.netlify.com/projects/liveccc/deploys/6a63c15c5faee70008fabf8f
😎 Deploy Preview https://deploy-preview-415--liveccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 30 (🔴 down 11 from production)
Accessibility: 88 (no change from production)
Best Practices: 92 (🔴 down 8 from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Jun 30, 2026

Copy link
Copy Markdown

Deploy Preview for docsccc ready!

Name Link
🔨 Latest commit 627b291
🔍 Latest deploy log https://app.netlify.com/projects/docsccc/deploys/6a63c15ce9c5fe0008474cb3
😎 Deploy Preview https://deploy-preview-415--docsccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 78 (🔴 down 10 from production)
Accessibility: 95 (no change from production)
Best Practices: 92 (🔴 down 8 from production)
SEO: 75 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new @ckb-ccc/coin workspace package that provides a generic fungible-token (Coin) helper built on @ckb-ccc/core, and wires it into the monorepo’s testing/docs tooling and the @ckb-ccc/shell re-export surface.

Changes:

  • Added new packages/coin package (Coin implementation, tests, build/lint/test/tooling config, docs).
  • Updated root Vitest + TypeDoc configs to include packages/coin.
  • Updated @ckb-ccc/shell to depend on and re-export @ckb-ccc/coin; updated lockfile accordingly.

Reviewed changes

Copilot reviewed 21 out of 23 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
vitest.config.mts Adds packages/coin to the monorepo Vitest projects list.
typedoc.config.mjs Adds packages/coin to TypeDoc workspace entry points.
pnpm-lock.yaml Adds the packages/coin importer and updates resolved dependency snapshots.
packages/shell/src/barrel.ts Re-exports the coin namespace from @ckb-ccc/coin.
packages/shell/package.json Adds @ckb-ccc/coin as a workspace dependency.
packages/coin/vitest.config.ts Adds package-local Vitest configuration for tests and coverage.
packages/coin/typedoc.json Adds package-local TypeDoc configuration for API generation.
packages/coin/tsdown.config.mts Adds tsdown build configuration for ESM+CJS outputs and copy-basedirs.
packages/coin/tsconfig.json Adds TypeScript build configuration for the coin package.
packages/coin/src/index.ts Exposes barrel exports and a coin namespace export.
packages/coin/src/coin/index.ts Implements the Coin class (balance/info helpers and transaction completion helpers).
packages/coin/src/coin/index.test.ts Adds Vitest coverage for Coin behaviors (inputs completion, change handling, balance/info helpers).
packages/coin/src/coin/error.ts Adds ErrorCoinInsufficient error type for insufficient Coin balance conditions.
packages/coin/src/coin/coinInfo.ts Adds CoinInfo aggregation helper used by the Coin implementation.
packages/coin/src/barrel.ts Re-exports the coin module surface from src/coin.
packages/coin/README.md Adds package documentation and usage examples.
packages/coin/prettier.config.cjs Adds package-local Prettier configuration.
packages/coin/package.json Defines the new @ckb-ccc/coin package metadata, exports, and scripts.
packages/coin/misc/basedirs/dist/package.json Ensures emitted ESM dist is treated as "type": "module".
packages/coin/misc/basedirs/dist.commonjs/package.json Ensures emitted CJS dist is treated as "type": "commonjs".
packages/coin/eslint.config.mjs Adds package-local ESLint + typescript-eslint configuration.
packages/coin/.prettierignore Adds package-local Prettier ignore rules.
packages/coin/.npmignore Adds package-local npm publish ignore rules.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/coin/src/coin/index.ts Outdated
Comment thread packages/coin/typedoc.json
@Hanssen0
Hanssen0 force-pushed the feat/coin branch 5 times, most recently from 9481017 to 982850a Compare June 30, 2026 08:04
@Hanssen0
Hanssen0 requested a review from Copilot June 30, 2026 08:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 23 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread packages/coin/src/coin/index.ts Outdated
Comment thread packages/coin/src/coin/index.ts Outdated
Comment thread packages/coin/src/coin/index.ts Outdated
@Hanssen0
Hanssen0 force-pushed the feat/coin branch 6 times, most recently from 0c73462 to 497132a Compare July 4, 2026 07:55
@Hanssen0
Hanssen0 changed the base branch from dev to next-major July 4, 2026 07:55
@Hanssen0
Hanssen0 requested a review from Copilot July 4, 2026 09:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 26 changed files in this pull request and generated 6 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread packages/coin/README.md
Comment thread packages/coin/README.md
Comment thread packages/coin/README.md
Comment thread packages/coin/src/coin/coin.ts
Comment thread packages/coin/src/coin/coin.ts
Comment thread packages/coin/src/coin/coin.ts
@Hanssen0
Hanssen0 force-pushed the feat/coin branch 3 times, most recently from b32dcb5 to 7c07413 Compare July 4, 2026 09:46
@Hanssen0
Hanssen0 marked this pull request as ready for review July 4, 2026 13:26
@Hanssen0
Hanssen0 requested a review from Copilot July 13, 2026 17:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 30 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread packages/coin/src/xUdt/args.ts
@Hanssen0

Copy link
Copy Markdown
Member Author

/canary

@github-actions

Copy link
Copy Markdown
Contributor

❌ Canary version deployment failed. View workflow run

@Hanssen0

Copy link
Copy Markdown
Member Author

/canary

@github-actions

Copy link
Copy Markdown
Contributor

❌ Canary version deployment failed. View workflow run

@Hanssen0

Copy link
Copy Markdown
Member Author

/canary

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Canary version published successfully! View workflow run

The following packages have been published to npm:

  • @ckb-ccc/ccc@0.0.0-canary-20260713182150
  • ckb-ccc@0.0.0-canary-20260713182150
  • @ckb-ccc/co-build@0.0.0-canary-20260713182150
  • @ckb-ccc/coin@0.0.0-canary-20260713182150
  • @ckb-ccc/connector@0.0.0-canary-20260713182150
  • @ckb-ccc/connector-react@0.0.0-canary-20260713182150
  • @ckb-ccc/core@0.0.0-canary-20260713182150
  • @ckb-ccc/did-ckb@0.0.0-canary-20260713182150
  • @ckb-ccc/eip6963@0.0.0-canary-20260713182150
  • @ckb-ccc/joy-id@0.0.0-canary-20260713182150
  • @ckb-ccc/lumos-patches@0.0.0-canary-20260713182150
  • @ckb-ccc/nip07@0.0.0-canary-20260713182150
  • @ckb-ccc/okx@0.0.0-canary-20260713182150
  • @ckb-ccc/rei@0.0.0-canary-20260713182150
  • @ckb-ccc/shell@0.0.0-canary-20260713182150
  • @ckb-ccc/spore@0.0.0-canary-20260713182150
  • @ckb-ccc/ssri@0.0.0-canary-20260713182150
  • @ckb-ccc/type-id@0.0.0-canary-20260713182150
  • @ckb-ccc/udt@0.0.0-canary-20260713182150
  • @ckb-ccc/uni-sat@0.0.0-canary-20260713182150
  • @ckb-ccc/utxo-global@0.0.0-canary-20260713182150
  • @ckb-ccc/xverse@0.0.0-canary-20260713182150

@Hanssen0

Copy link
Copy Markdown
Member Author

/canary

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Canary version published successfully! View workflow run

The following packages have been published to npm:

  • @ckb-ccc/ccc@0.0.0-canary-20260713204024
  • ckb-ccc@0.0.0-canary-20260713204024
  • @ckb-ccc/co-build@0.0.0-canary-20260713204024
  • @ckb-ccc/coin@0.0.0-canary-20260713204024
  • @ckb-ccc/connector@0.0.0-canary-20260713204024
  • @ckb-ccc/connector-react@0.0.0-canary-20260713204024
  • @ckb-ccc/core@0.0.0-canary-20260713204024
  • @ckb-ccc/did-ckb@0.0.0-canary-20260713204024
  • @ckb-ccc/eip6963@0.0.0-canary-20260713204024
  • @ckb-ccc/joy-id@0.0.0-canary-20260713204024
  • @ckb-ccc/lumos-patches@0.0.0-canary-20260713204024
  • @ckb-ccc/nip07@0.0.0-canary-20260713204024
  • @ckb-ccc/okx@0.0.0-canary-20260713204024
  • @ckb-ccc/rei@0.0.0-canary-20260713204024
  • @ckb-ccc/shell@0.0.0-canary-20260713204024
  • @ckb-ccc/spore@0.0.0-canary-20260713204024
  • @ckb-ccc/ssri@0.0.0-canary-20260713204024
  • @ckb-ccc/type-id@0.0.0-canary-20260713204024
  • @ckb-ccc/udt@0.0.0-canary-20260713204024
  • @ckb-ccc/uni-sat@0.0.0-canary-20260713204024
  • @ckb-ccc/utxo-global@0.0.0-canary-20260713204024
  • @ckb-ccc/xverse@0.0.0-canary-20260713204024

@Hanssen0
Hanssen0 force-pushed the feat/coin branch 2 times, most recently from ce82cc8 to 1b32769 Compare July 14, 2026 06:55
@Hanssen0

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added the Coin package for querying balances and building fungible-token transfers, mints, burns, and change outputs.
    • Added xUDT support, including structured argument handling, extensions, and owner-mode options.
    • Exposed Coin functionality through the shell package.
  • Documentation
    • Added comprehensive Coin and xUDT usage documentation, API references, and quick-start examples.
  • Bug Fixes
    • Improved transaction completion and capacity handling for Coin outputs and transformed output data.

Walkthrough

This change introduces the @ckb-ccc/coin package with Coin transaction utilities, CoBuild actions, xUDT support, tests, build tooling, documentation, and public exports through @ckb-ccc/shell.

Changes

Coin package

Layer / File(s) Summary
Package foundation
packages/coin/*, typedoc.config.mjs, vitest.config.mts, packages/shell/package.json
Adds package metadata, ESM/CommonJS builds, TypeScript, linting, formatting, testing, publishing configuration, and workspace wiring.
Coin contracts and public exports
packages/coin/src/coBuild.ts, packages/coin/src/coin/*, packages/coin/src/index.ts, packages/coin/src/barrel.ts
Defines Coin action entities, CoinInfo, insufficient-coin errors, and public barrel exports.
Coin discovery and transaction completion
packages/coin/src/coin/coin.ts, packages/coin/src/coin/coin.test.ts
Implements Coin balance inspection, input selection, change completion, transfers, minting, burning, capacity handling, and CoBuild integration with tests.
xUDT arguments and CoinXUdt
packages/coin/src/xUdt/*
Adds extension-aware owner-mode argument codecs, normalized xUDT construction, known-script resolution, and xUDT tests.
Documentation and release exposure
packages/coin/README.md, .changeset/early-oranges-lick.md, packages/shell/src/barrel.ts
Documents Coin and CoinXUdt usage, records minor package releases, and re-exports the coin namespace from the shell package.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Coin
  participant Client
  participant Transaction
  participant CoBuild
  Caller->>Coin: create transfer or complete transaction
  Coin->>Client: query matching cells
  Client-->>Coin: return Coin cells and cell dependencies
  Coin->>Transaction: add inputs and change output
  Coin->>CoBuild: record transfer, mint, or burn action
  CoBuild-->>Coin: return action witness index
  Coin-->>Caller: return completed transaction
Loading

Suggested labels: dependencies, javascript

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding a new coin package.
Description check ✅ Passed The description matches the template and includes the required contributing guidelines acknowledgment.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/coin/vitest.config.ts

Parsing error: "parserOptions.project" has been provided for @typescript-eslint/parser.
The file was not found in any of the provided project(s): vitest.config.ts


Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/coin/README.md`:
- Around line 123-128: Update the “Change to a specific address” README example
so it is self-contained by defining tx, or explicitly label the snippet as
continuing from the preceding Send example and add that clarification in the
code block. Preserve the existing signer.getRecommendedAddressObj and
coin.completeChangeToLock calls.

In `@packages/coin/src/coin/coin.test.ts`:
- Around line 1538-1555: Update the test around completeInputsByAmount so it
passes the negative amountTweak value of -100 when invoking the method. Preserve
the existing transaction setup and addedCount expectation, ensuring the test
specifically verifies that the negative tweak cancels the output requirement.

In `@packages/coin/src/coin/coinInfo.ts`:
- Around line 49-52: Update CoinInfo.from so that when infoLike is already a
CoinInfo, it returns infoLike.clone() rather than the original reference.
Preserve the existing conversion behavior for other CoinInfoLike inputs and
maintain the documented guarantee that from always returns a new instance.

In `@packages/coin/src/xUdt/args.ts`:
- Around line 42-60: Update CoinXUdtArgsCodec and CoinXUdtArgs so xUDT extension
payloads are preserved during decode and re-encode, modeling extensionData
explicitly if supported; otherwise validate flags and encoded lengths and reject
unsupported extension data instead of silently emitting only the owner hash and
four flag bytes.

In `@packages/coin/src/xUdt/coinXUdt.ts`:
- Around line 99-115: Update the CoinXUdt constructor’s argument handling around
CoinXUdtArgs.fromBytes so extended bytes from options.script.args are preserved
when rebuilding the script, rather than always replacing them with
args.toBytes(). Keep canonical serialization for options.xUdtArgs while
retaining the original script argument bytes for the script-derived path, and
add a regression test using the extended arguments covered in xUdt.test.ts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b179b27b-6b93-41c2-8a16-7fa1df39ce82

📥 Commits

Reviewing files that changed from the base of the PR and between 8076f62 and 1b32769.

⛔ Files ignored due to path filters (2)
  • packages/coin/misc/basedirs/dist/package.json is excluded by !**/dist/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (28)
  • .changeset/early-oranges-lick.md
  • packages/coin/.npmignore
  • packages/coin/.prettierignore
  • packages/coin/README.md
  • packages/coin/eslint.config.mjs
  • packages/coin/misc/basedirs/dist.commonjs/package.json
  • packages/coin/package.json
  • packages/coin/prettier.config.cjs
  • packages/coin/src/barrel.ts
  • packages/coin/src/coBuild.ts
  • packages/coin/src/coin/coin.test.ts
  • packages/coin/src/coin/coin.ts
  • packages/coin/src/coin/coinInfo.ts
  • packages/coin/src/coin/error.ts
  • packages/coin/src/coin/index.ts
  • packages/coin/src/index.ts
  • packages/coin/src/xUdt/args.ts
  • packages/coin/src/xUdt/coinXUdt.ts
  • packages/coin/src/xUdt/index.ts
  • packages/coin/src/xUdt/xUdt.test.ts
  • packages/coin/tsconfig.json
  • packages/coin/tsdown.config.mts
  • packages/coin/typedoc.json
  • packages/coin/vitest.config.ts
  • packages/shell/package.json
  • packages/shell/src/barrel.ts
  • typedoc.config.mjs
  • vitest.config.mts

Comment thread packages/coin/README.md
Comment on lines +123 to +128
### Change to a specific address

```ts
const { script: changeLock } = await signer.getRecommendedAddressObj();
const { tx: completedTx } = await coin.completeChangeToLock(tx, changeLock);
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the change-address example self-contained or explicitly mark it as a continuation.

This snippet uses tx without defining it in the same example. Readers who copy only this section will encounter an undefined identifier; either include the transaction construction or label the section as continuing from the previous example.

Suggested clarification
-### Change to a specific address
+### Change to a specific address (using the `tx` from the Send example above)

 ```ts
+// `tx` is created in the Send example above.
 const { script: changeLock } = await signer.getRecommendedAddressObj();
 const { tx: completedTx } = await coin.completeChangeToLock(tx, changeLock);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### Change to a specific address
```ts
const { script: changeLock } = await signer.getRecommendedAddressObj();
const { tx: completedTx } = await coin.completeChangeToLock(tx, changeLock);
```
### Change to a specific address (using the `tx` from the Send example above)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/coin/README.md` around lines 123 - 128, Update the “Change to a
specific address” README example so it is self-contained by defining tx, or
explicitly label the snippet as continuing from the preceding Send example and
add that clarification in the code block. Preserve the existing
signer.getRecommendedAddressObj and coin.completeChangeToLock calls.

Comment on lines +1538 to +1555
it("should add no inputs when amountTweak exactly cancels the output requirement", async () => {
// Output needs 100, but amountTweak is -100 (negative tweak zeroing requirement)
const tx = ccc.Transaction.from({
inputs: [
{
previousOutput: {
txHash: `0x${"c".repeat(63)}0`,
index: 0,
},
},
],
outputs: [{ lock, type }],
outputsData: [ccc.numLeToBytes(100, 16)],
});

// Already have 1 input (amount 100) matching output exactly → no more needed
const { addedCount } = await coin.completeInputsByAmount(tx);
expect(addedCount).toBe(0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Actually exercise the negative amountTweak.

The existing input already balances the output, and the call omits -100, so this test passes without covering its stated edge case.

Proposed fix
 const tx = ccc.Transaction.from({
-  inputs: [
-    {
-      previousOutput: {
-        txHash: `0x${"c".repeat(63)}0`,
-        index: 0,
-      },
-    },
-  ],
   outputs: [{ lock, type }],
   outputsData: [ccc.numLeToBytes(100, 16)],
 });

-const { addedCount } = await coin.completeInputsByAmount(tx);
+const { addedCount } = await coin.completeInputsByAmount(tx, -100);
 expect(addedCount).toBe(0);
+expect(tx.inputs).toHaveLength(0);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it("should add no inputs when amountTweak exactly cancels the output requirement", async () => {
// Output needs 100, but amountTweak is -100 (negative tweak zeroing requirement)
const tx = ccc.Transaction.from({
inputs: [
{
previousOutput: {
txHash: `0x${"c".repeat(63)}0`,
index: 0,
},
},
],
outputs: [{ lock, type }],
outputsData: [ccc.numLeToBytes(100, 16)],
});
// Already have 1 input (amount 100) matching output exactly → no more needed
const { addedCount } = await coin.completeInputsByAmount(tx);
expect(addedCount).toBe(0);
it("should add no inputs when amountTweak exactly cancels the output requirement", async () => {
// Output needs 100, but amountTweak is -100 (negative tweak zeroing requirement)
const tx = ccc.Transaction.from({
outputs: [{ lock, type }],
outputsData: [ccc.numLeToBytes(100, 16)],
});
// Already have 1 input (amount 100) matching output exactly → no more needed
const { addedCount } = await coin.completeInputsByAmount(tx, -100);
expect(addedCount).toBe(0);
expect(tx.inputs).toHaveLength(0);
🧰 Tools
🪛 ESLint

[error] 1540-1551: Unsafe assignment of an error typed value.

(@typescript-eslint/no-unsafe-assignment)


[error] 1540-1540: Unsafe call of a type that could not be resolved.

(@typescript-eslint/no-unsafe-call)


[error] 1549-1549: Unsafe assignment of an error typed value.

(@typescript-eslint/no-unsafe-assignment)


[error] 1549-1549: Unsafe assignment of an error typed value.

(@typescript-eslint/no-unsafe-assignment)


[error] 1550-1550: Unsafe call of a type that could not be resolved.

(@typescript-eslint/no-unsafe-call)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/coin/src/coin/coin.test.ts` around lines 1538 - 1555, Update the
test around completeInputsByAmount so it passes the negative amountTweak value
of -100 when invoking the method. Preserve the existing transaction setup and
addedCount expectation, ensuring the test specifically verifies that the
negative tweak cancels the output requirement.

Comment on lines +49 to +52
static from(infoLike?: CoinInfoLike) {
if (infoLike instanceof CoinInfo) {
return infoLike;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Avoid aliasing the input from CoinInfo.from.

Line 50 returns an existing CoinInfo by reference, despite the documentation promising a new instance. CoinInfo.from(existing).addAssign(...) can therefore mutate the caller’s object. Return infoLike.clone() or explicitly document and test the identity-preserving behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/coin/src/coin/coinInfo.ts` around lines 49 - 52, Update
CoinInfo.from so that when infoLike is already a CoinInfo, it returns
infoLike.clone() rather than the original reference. Preserve the existing
conversion behavior for other CoinInfoLike inputs and maintain the documented
guarantee that from always returns a new instance.

Comment thread packages/coin/src/xUdt/args.ts Outdated
Comment thread packages/coin/src/xUdt/coinXUdt.ts
@Hanssen0
Hanssen0 force-pushed the feat/coin branch 3 times, most recently from b48efaf to ebd5a39 Compare July 21, 2026 23:26

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
packages/coin/src/coin/coin.ts (2)

791-893: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

transfer and mint are byte-for-byte identical except the action type.

Extract the shared output-building + action-append flow into a private helper parameterized by "Transfer" | "Mint" to keep the two paths from drifting.

♻️ Sketch
+  private async addCoinOutputs(
+    type: "Transfer" | "Mint",
+    items: { to: ccc.ScriptLike; amount: ccc.NumLike }[],
+    txLike?: ccc.TransactionLike | null,
+  ): Promise<{
+    tx: ccc.Transaction;
+    outputIndexes: number[];
+    witnessIndex: number;
+  }> {
+    const tx = ccc.Transaction.from(txLike ?? {});
+    const outputIndexes: number[] = [];
+
+    for (const { to, amount } of items) {
+      outputIndexes.push(
+        tx.addOutput(
+          await this.setAmount(
+            { cellOutput: { lock: to, type: await this.script } },
+            amount,
+          ),
+        ) - 1,
+      );
+    }
+
+    return {
+      ...(await (
+        await this.coBuild
+      ).appendActions(
+        tx,
+        items.map((value) => CoinAction.from({ type, value })),
+      )),
+      outputIndexes,
+    };
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/coin/src/coin/coin.ts` around lines 791 - 893, Extract the
duplicated transaction output-building and CoBuild action-appending logic from
transfer and mint into a private helper parameterized by the action type
"Transfer" | "Mint". Have transfer and mint delegate to this helper while
preserving their existing inputs, outputIndexes, transaction handling, and
CoinAction behavior.

377-395: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Silently swallowing every decode error hides malformed actions.

A CoBuild action that fails to decode is treated as "no mint/burn intent", so completion accounting silently diverges from what the script will enforce on-chain. Consider narrowing the swallow to decode failures and surfacing them (log/warn), so callers can diagnose a tx that later fails verification.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/coin/src/coin/coin.ts` around lines 377 - 395, Update
getIntendedAmountBurned so CoinAction decoding failures are not silently
ignored: catch only the expected decode error type, surface it through the
established logging or warning mechanism, and let unexpected errors propagate.
Preserve the existing zero contribution for successfully decoded non-mint/burn
actions.
packages/coin/src/coin/coin.test.ts (1)

1012-1017: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

mockImplementationOnce is fragile here — completion sources inputs in two phases.

completeChangeToOutput invokes completeInputsByAmount twice and resolves each input cell via client.getCell, so the second and later calls silently fall back to the describe-level mocks, which don't know highCapCoin. Prefer a persistent mockImplementation that resolves highCapCoin by out point.

♻️ Proposed change
-      vi.spyOn(signer, "findCells").mockImplementationOnce(async function* () {
-        yield highCapCoin;
-      });
-      vi.spyOn(client, "getCell").mockImplementationOnce(
-        async () => highCapCoin,
-      );
+      vi.spyOn(signer, "findCells").mockImplementation(async function* () {
+        yield highCapCoin;
+      });
+      vi.spyOn(client, "getCell").mockImplementation(async (outPoint) =>
+        ccc.OutPoint.from(outPoint).eq(highCapCoin.outPoint)
+          ? highCapCoin
+          : undefined,
+      );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/coin/src/coin/coin.test.ts` around lines 1012 - 1017, Update the
test mocks around completeChangeToOutput to use persistent mockImplementation
calls instead of mockImplementationOnce for signer.findCells and client.getCell.
Ensure client.getCell resolves highCapCoin by its out point on every invocation,
so both completeInputsByAmount phases use the intended fixture rather than
falling back to describe-level mocks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/coin/src/coin/coin.test.ts`:
- Around line 1700-1707: Update the test setup in “should add outputs correctly”
so recipientLock1 and recipientLock2 are distinct scripts, using a separate
signer or address source for the second recipient. Keep the existing transfer
and recipient-pairing assertions unchanged so they can detect swapped or
incorrect output destinations.
- Around line 720-727: Clone completedTx.outputs[1] before passing it to
CellOutput.from when computing minCapacity, ensuring the capacity baseline is
independent of the output being validated. Apply the same
clone-before-comparison pattern to the other two related assertions in
coin.test.ts.

In `@packages/coin/src/coin/coin.ts`:
- Around line 145-184: Update the constructor promise fan-out around resolved,
script, cellDeps, filter, and coBuild so a single initialization failure is
shared through one guarded promise rather than producing independently unhandled
branch rejections. Ensure callers can still await each exposed promise while
handling getKnownScript or getCellDeps failures does not terminate the process
through unobserved sibling promises.

---

Nitpick comments:
In `@packages/coin/src/coin/coin.test.ts`:
- Around line 1012-1017: Update the test mocks around completeChangeToOutput to
use persistent mockImplementation calls instead of mockImplementationOnce for
signer.findCells and client.getCell. Ensure client.getCell resolves highCapCoin
by its out point on every invocation, so both completeInputsByAmount phases use
the intended fixture rather than falling back to describe-level mocks.

In `@packages/coin/src/coin/coin.ts`:
- Around line 791-893: Extract the duplicated transaction output-building and
CoBuild action-appending logic from transfer and mint into a private helper
parameterized by the action type "Transfer" | "Mint". Have transfer and mint
delegate to this helper while preserving their existing inputs, outputIndexes,
transaction handling, and CoinAction behavior.
- Around line 377-395: Update getIntendedAmountBurned so CoinAction decoding
failures are not silently ignored: catch only the expected decode error type,
surface it through the established logging or warning mechanism, and let
unexpected errors propagate. Preserve the existing zero contribution for
successfully decoded non-mint/burn actions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 243b1e87-efc2-487f-9007-58ca5a786248

📥 Commits

Reviewing files that changed from the base of the PR and between ebd5a39 and 627b291.

⛔ Files ignored due to path filters (2)
  • packages/coin/misc/basedirs/dist/package.json is excluded by !**/dist/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (28)
  • .changeset/early-oranges-lick.md
  • packages/coin/.npmignore
  • packages/coin/.prettierignore
  • packages/coin/README.md
  • packages/coin/eslint.config.mjs
  • packages/coin/misc/basedirs/dist.commonjs/package.json
  • packages/coin/package.json
  • packages/coin/prettier.config.cjs
  • packages/coin/src/barrel.ts
  • packages/coin/src/coBuild.ts
  • packages/coin/src/coin/coin.test.ts
  • packages/coin/src/coin/coin.ts
  • packages/coin/src/coin/coinInfo.ts
  • packages/coin/src/coin/error.ts
  • packages/coin/src/coin/index.ts
  • packages/coin/src/index.ts
  • packages/coin/src/xUdt/args.ts
  • packages/coin/src/xUdt/coinXUdt.ts
  • packages/coin/src/xUdt/index.ts
  • packages/coin/src/xUdt/xUdt.test.ts
  • packages/coin/tsconfig.json
  • packages/coin/tsdown.config.mts
  • packages/coin/typedoc.json
  • packages/coin/vitest.config.ts
  • packages/shell/package.json
  • packages/shell/src/barrel.ts
  • typedoc.config.mjs
  • vitest.config.mts
🚧 Files skipped from review as they are similar to previous changes (22)
  • packages/coin/misc/basedirs/dist.commonjs/package.json
  • packages/coin/typedoc.json
  • vitest.config.mts
  • packages/shell/src/barrel.ts
  • packages/coin/.prettierignore
  • packages/coin/src/xUdt/index.ts
  • packages/coin/src/coin/error.ts
  • packages/coin/src/coin/index.ts
  • packages/coin/README.md
  • packages/coin/prettier.config.cjs
  • typedoc.config.mjs
  • .changeset/early-oranges-lick.md
  • packages/coin/src/barrel.ts
  • packages/coin/src/index.ts
  • packages/coin/tsdown.config.mts
  • packages/coin/tsconfig.json
  • packages/coin/vitest.config.ts
  • packages/shell/package.json
  • packages/coin/eslint.config.mjs
  • packages/coin/src/coBuild.ts
  • packages/coin/package.json
  • packages/coin/src/coin/coinInfo.ts

Comment on lines +720 to +727
// capacity must be enough to cover the enlarged data
const minCapacity = ccc.CellOutput.from(
completedTx.outputs[1],
completedTx.outputsData[1],
).capacity;
expect(completedTx.outputs[1].capacity).toBeGreaterThanOrEqual(
minCapacity,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm whether CellOutput.from mutates the instance it is given
ast-grep run --pattern 'class CellOutput $$$' --lang typescript packages/core/src/ckb/transaction.ts 2>/dev/null | head -40
rg -nP -A 25 'static from\(\s*cellOutput' packages/core/src/ckb/transaction.ts | head -60

Repository: ckb-devrel/ccc

Length of output: 152


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- transaction.ts outline ---'
ast-grep outline packages/core/src/ckb/transaction.ts --view expanded | sed -n '1,220p'

echo
echo '--- from/clone/search in transaction.ts ---'
rg -n -A 40 -B 10 'static from\(|clone\(' packages/core/src/ckb/transaction.ts

echo
echo '--- coin.test.ts around cited lines ---'
sed -n '700,740p' packages/coin/src/coin/coin.test.ts
echo
sed -n '1040,1115p' packages/coin/src/coin/coin.test.ts

Repository: ckb-devrel/ccc

Length of output: 34229


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- file presence ---\n'
git ls-files 'packages/core/src/ckb/transaction.ts' 'packages/coin/src/coin/coin.test.ts'

printf '\n--- line counts ---\n'
wc -l packages/core/src/ckb/transaction.ts packages/coin/src/coin/coin.test.ts

printf '\n--- transaction.ts relevant declarations ---\n'
rg -n -A 30 -B 8 'from\(|clone\(|class CellOutput|interface CellOutput|type CellOutput' packages/core/src/ckb/transaction.ts

printf '\n--- coin.test.ts target ranges ---\n'
sed -n '712,732p' packages/coin/src/coin/coin.test.ts
printf '\n---\n'
sed -n '1048,1060p' packages/coin/src/coin/coin.test.ts
printf '\n---\n'
sed -n '1094,1106p' packages/coin/src/coin/coin.test.ts

Repository: ckb-devrel/ccc

Length of output: 243


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- all CellOutput.from call sites ---'
rg -n 'CellOutput\.from\(' packages | sed -n '1,200p'

echo
echo '--- search for clone usage near CellOutput ---'
rg -n -A 2 -B 2 'clone\(\)' packages/core packages/coin | sed -n '1,240p'

Repository: ckb-devrel/ccc

Length of output: 50373


🌐 Web query:

"ccc CellOutput.from mutates CellOutput.from(output, data) clone capacity ccc"

💡 Result:

In the CCC (CKB Common Collection) library, the CellOutput.from method is a factory function used to create a CellOutput instance [1][2]. It does not mutate the inputs provided to it; instead, it returns a new, properly initialized object based on the provided CellOutputLike configuration and optional output data [3][4]. A key feature of CellOutput.from is its ability to automatically calculate and set the cell's capacity if it is not provided or set to 0 [3][4]. When creating a cell, the capacity is calculated based on the cell's occupied size (which includes the lock script, type script, and the length of the provided output data) [3][4]. It ensures the resulting cell meets the minimum capacity requirements [3][4]. The method does not involve a manual clone operation by the user; rather, it handles the construction and necessary sizing logic internally [3][4]. If you need to produce a copy of an existing script or component (such as a type script) to pass into the factory, you should use the.clone method explicitly on that specific object before passing it into CellOutput.from if you wish to avoid shared references [5][6].

Citations:


Use a clone before computing minCapacity. CellOutput.from(completedTx.outputs[1], completedTx.outputsData[1]) reuses the passed CellOutput instance here, so minCapacity can be read after the output has already been raised and the check becomes self-comparing. Clone the output first; the same pattern appears in the other two assertions in this file.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/coin/src/coin/coin.test.ts` around lines 720 - 727, Clone
completedTx.outputs[1] before passing it to CellOutput.from when computing
minCapacity, ensuring the capacity baseline is independent of the output being
validated. Apply the same clone-before-comparison pattern to the other two
related assertions in coin.test.ts.

Comment on lines +1700 to +1707
it("should add outputs correctly", async () => {
const recipientLock1 = (await signer.getRecommendedAddressObj()).script;
const recipientLock2 = (await signer.getRecommendedAddressObj()).script;

const { tx, outputIndexes } = await coin.transfer([
{ to: recipientLock1, amount: 100n },
{ to: recipientLock2, amount: 200n },
]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Both "recipients" are the same lock, so recipient-pairing assertions can't fail.

recipientLock1 and recipientLock2 both come from signer.getRecommendedAddressObj(), making the checks at Lines 1734/1736 insensitive to a swapped or wrong to. Use a distinct second script.

💚 Proposed fix
       const recipientLock1 = (await signer.getRecommendedAddressObj()).script;
-      const recipientLock2 = (await signer.getRecommendedAddressObj()).script;
+      const recipientLock2 = ccc.Script.from({
+        codeHash: "0x" + "9".repeat(64),
+        hashType: "type",
+        args: "0xdeadbeef",
+      });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it("should add outputs correctly", async () => {
const recipientLock1 = (await signer.getRecommendedAddressObj()).script;
const recipientLock2 = (await signer.getRecommendedAddressObj()).script;
const { tx, outputIndexes } = await coin.transfer([
{ to: recipientLock1, amount: 100n },
{ to: recipientLock2, amount: 200n },
]);
it("should add outputs correctly", async () => {
const recipientLock1 = (await signer.getRecommendedAddressObj()).script;
const recipientLock2 = ccc.Script.from({
codeHash: "0x" + "9".repeat(64),
hashType: "type",
args: "0xdeadbeef",
});
const { tx, outputIndexes } = await coin.transfer([
{ to: recipientLock1, amount: 100n },
{ to: recipientLock2, amount: 200n },
]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/coin/src/coin/coin.test.ts` around lines 1700 - 1707, Update the
test setup in “should add outputs correctly” so recipientLock1 and
recipientLock2 are distinct scripts, using a separate signer or address source
for the second recipient. Keep the existing transfer and recipient-pairing
assertions unchanged so they can detect swapped or incorrect output
destinations.

Comment on lines +145 to +184
const resolved = (async (): Promise<
[ccc.ScriptLike, ccc.CellDepLike[]]
> => {
if (script.codeHash != null && script.hashType != null) {
return [script as ccc.ScriptLike, cellDeps ?? []];
}

const scriptInfo = await client.getKnownScript(
knownScript as ccc.KnownScript,
);
return [
{
codeHash: scriptInfo.codeHash,
hashType: scriptInfo.hashType,
args: script.args,
},
(await client.getCellDeps(scriptInfo.cellDeps)).concat(
cellDeps?.map(ccc.CellDep.from) ?? [],
),
];
})();

this.script = resolved.then(([script]) => ccc.Script.from(script));
this.cellDeps = resolved.then(([_, cellDeps]) =>
cellDeps.map(ccc.CellDep.from),
);

const scriptRes = this.script;
this.filter = (async () => {
return ccc.ClientIndexerSearchKeyFilter.from(
options.filter ?? {
script: await scriptRes,
outputDataLenRange: [16, "0xffffffff"],
},
);
})();

this.coBuild = Promise.all([this.script]).then(
([script]) => new coBuild.CoBuild(script, options.scriptInfo),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Constructor promise fan-out can surface unhandled rejections.

resolved fans out into four independently-derived promises (script, cellDeps, filter, coBuild). If client.getKnownScript / getCellDeps rejects, every branch a caller does not await stays unhandled — under Node's default --unhandled-rejections=throw that terminates the process even though the caller may have handled the one promise it awaited.

🛡️ Proposed guard
     this.coBuild = Promise.all([this.script]).then(
       ([script]) => new coBuild.CoBuild(script, options.scriptInfo),
     );
+
+    // Every field is independently awaitable; mark each branch as handled so an
+    // early resolution failure cannot escape as an unhandled rejection.
+    for (const p of [this.script, this.cellDeps, this.filter, this.coBuild]) {
+      void p.catch(() => {});
+    }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const resolved = (async (): Promise<
[ccc.ScriptLike, ccc.CellDepLike[]]
> => {
if (script.codeHash != null && script.hashType != null) {
return [script as ccc.ScriptLike, cellDeps ?? []];
}
const scriptInfo = await client.getKnownScript(
knownScript as ccc.KnownScript,
);
return [
{
codeHash: scriptInfo.codeHash,
hashType: scriptInfo.hashType,
args: script.args,
},
(await client.getCellDeps(scriptInfo.cellDeps)).concat(
cellDeps?.map(ccc.CellDep.from) ?? [],
),
];
})();
this.script = resolved.then(([script]) => ccc.Script.from(script));
this.cellDeps = resolved.then(([_, cellDeps]) =>
cellDeps.map(ccc.CellDep.from),
);
const scriptRes = this.script;
this.filter = (async () => {
return ccc.ClientIndexerSearchKeyFilter.from(
options.filter ?? {
script: await scriptRes,
outputDataLenRange: [16, "0xffffffff"],
},
);
})();
this.coBuild = Promise.all([this.script]).then(
([script]) => new coBuild.CoBuild(script, options.scriptInfo),
);
const resolved = (async (): Promise<
[ccc.ScriptLike, ccc.CellDepLike[]]
> => {
if (script.codeHash != null && script.hashType != null) {
return [script as ccc.ScriptLike, cellDeps ?? []];
}
const scriptInfo = await client.getKnownScript(
knownScript as ccc.KnownScript,
);
return [
{
codeHash: scriptInfo.codeHash,
hashType: scriptInfo.hashType,
args: script.args,
},
(await client.getCellDeps(scriptInfo.cellDeps)).concat(
cellDeps?.map(ccc.CellDep.from) ?? [],
),
];
})();
this.script = resolved.then(([script]) => ccc.Script.from(script));
this.cellDeps = resolved.then(([_, cellDeps]) =>
cellDeps.map(ccc.CellDep.from),
);
const scriptRes = this.script;
this.filter = (async () => {
return ccc.ClientIndexerSearchKeyFilter.from(
options.filter ?? {
script: await scriptRes,
outputDataLenRange: [16, "0xffffffff"],
},
);
})();
this.coBuild = Promise.all([this.script]).then(
([script]) => new coBuild.CoBuild(script, options.scriptInfo),
);
// Every field is independently awaitable; mark each branch as handled so an
// early resolution failure cannot escape as an unhandled rejection.
for (const p of [this.script, this.cellDeps, this.filter, this.coBuild]) {
void p.catch(() => {});
}
🧰 Tools
🪛 ESLint

[error] 183-183: Unsafe construction of a type that could not be resolved.

(@typescript-eslint/no-unsafe-call)


[error] 183-183: Unsafe return of a value of type error.

(@typescript-eslint/no-unsafe-return)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/coin/src/coin/coin.ts` around lines 145 - 184, Update the
constructor promise fan-out around resolved, script, cellDeps, filter, and
coBuild so a single initialization failure is shared through one guarded promise
rather than producing independently unhandled branch rejections. Ensure callers
can still await each exposed promise while handling getKnownScript or
getCellDeps failures does not terminate the process through unobserved sibling
promises.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 30 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment on lines +239 to +246
cell.outputData = ccc.hexFrom(
ccc.bytesConcat(
ccc.numLeToBytes(normalizedAmount, 16),
ccc.bytesFrom(cell.outputData).slice(16),
),
);

return this.transformOutput(cell);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants