Skip to content

Conversation

@fghdotio
Copy link
Contributor

No description provided.

@changeset-bot
Copy link

changeset-bot bot commented Dec 30, 2025

⚠️ No Changeset found

Latest commit: 531e392

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@netlify
Copy link

netlify bot commented Dec 30, 2025

Deploy Preview for appccc ready!

Name Link
🔨 Latest commit 531e392
🔍 Latest deploy log https://app.netlify.com/projects/appccc/deploys/69543770a10b2c0008ae0fa1
😎 Deploy Preview https://deploy-preview-338--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: 71 (🔴 down 6 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
Copy link

netlify bot commented Dec 30, 2025

Deploy Preview for apiccc ready!

Name Link
🔨 Latest commit 531e392
🔍 Latest deploy log https://app.netlify.com/projects/apiccc/deploys/69543770300aa70008d23b2d
😎 Deploy Preview https://deploy-preview-338--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: 69 (🔴 down 29 from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 94 (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
Copy link

netlify bot commented Dec 30, 2025

Deploy Preview for liveccc ready!

Name Link
🔨 Latest commit 531e392
🔍 Latest deploy log https://app.netlify.com/projects/liveccc/deploys/69543770a0bd4100086f46d1
😎 Deploy Preview https://deploy-preview-338--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: 42 (🟢 up 8 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.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @fghdotio, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly expands the project's capabilities by introducing a dedicated package for the RGB++ protocol. The changes enable the integration of Bitcoin-based User Defined Tokens (UDTs) with the CKB blockchain, providing necessary script definitions, utility functions for Bitcoin interactions, and a client for managing UDT issuance. This lays the groundwork for advanced cross-chain asset management between Bitcoin and CKB.

Highlights

  • New RGB++ Package Introduction: A new package, @ckb-ccc/rgbpp, has been added to the repository. This package is dedicated to providing core functionalities for integrating the RGB++ protocol with CKB, specifically focusing on User Defined Tokens (UDTs).
  • CKB Script Integration: The core CKB client configurations (clientPublicMainnet.advanced.ts and clientPublicTestnet.advanced.ts) have been updated to include new RgbppLock and BtcTimeLock script definitions. These new script types are also added to the KnownScript enum, making them recognizable within the CKB ecosystem.
  • Comprehensive Bitcoin Utilities: The new rgbpp package includes extensive utilities for Bitcoin-related operations, such as address decoding, transaction input/output handling, script manipulation (e.g., OP_RETURN), and type definitions for various Bitcoin network and transaction components.
  • RGB++ Specific Data Structures and Logic: New data structures and Mol.js codecs (ExtraCommitmentDataCCC, RgbppUnlock, BtcTimeLock, BtcTimeUnlock) have been introduced to handle RGB++ specific transaction data. This includes logic for building RGB++ lock arguments, calculating transaction commitments, and managing BTC RGB++ outputs.
  • UDT Issuance Client: A RgbppUdtClient class has been implemented to facilitate the issuance of UDTs on CKB via the RGB++ protocol. This client provides methods for building RGB++ and BTC time lock scripts, managing script information, and creating CKB partial transactions for UDT issuance.
  • Development Tooling Configuration: The new rgbpp package comes with its own set of development tooling configurations, including .prettierignore, .prettierrc, eslint.config.mjs, and tsconfig files, ensuring consistent code style and quality within the new module.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@netlify
Copy link

netlify bot commented Dec 30, 2025

Deploy Preview for docsccc ready!

Name Link
🔨 Latest commit 531e392
🔍 Latest deploy log https://app.netlify.com/projects/docsccc/deploys/69543770a10b2c0008ae0fa3
😎 Deploy Preview https://deploy-preview-338--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: 76 (🟢 up 13 from production)
Accessibility: 88 (no change from production)
Best Practices: 92 (no change from production)
SEO: 92 (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.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new package @ckb-ccc/rgbpp with UDT (User Defined Token) functionality for RGB++. It adds new script definitions for mainnet and testnet, and a lot of new logic for handling RGB++ UDTs, including building CKB transactions, calculating commitments, and interacting with Bitcoin transactions. The code is well-structured, but I've found a few issues, including a critical bug in transaction construction, potential runtime errors from unsafe array access, and some project configuration problems like duplicate dependencies and risky ESLint rules. I've provided suggestions to fix these issues.

Comment on lines 29 to 30
"@ckb-lumos/base": "^0.22.2",
"@ckb-lumos/codec": "^0.22.2",
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

There are duplicate @ckb-lumos/base and @ckb-lumos/codec packages defined in devDependencies and dependencies. The versions are also different (^0.22.2 vs ^0.23.0). This can lead to version conflicts and unpredictable behavior. Since they are required at runtime, they should only be in dependencies. Please remove them from devDependencies.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

type: ccc.Script.from({
codeHash: params.udtScriptInfo.codeHash,
hashType: params.udtScriptInfo.hashType,
args: params.rgbppLiveCells[0].cellOutput.lock.hash(), // unique ID of udt token
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

There is a bug here. params.rgbppLiveCells is used to get the first cell, but this array might contain duplicates and have a different order than rgpbbLiveCells, which is the deduplicated and correctly ordered list of cells used for creating transaction inputs. You should use rgpbbLiveCells[0] to ensure you're using a cell that is actually part of the transaction inputs and to make the UDT's unique ID deterministic.

Suggested change
args: params.rgbppLiveCells[0].cellOutput.lock.hash(), // unique ID of udt token
args: rgpbbLiveCells[0].cellOutput.lock.hash(), // unique ID of udt token

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

},
],
"@typescript-eslint/unbound-method": ["error", { ignoreStatic: true }],
"@typescript-eslint/no-unsafe-member-access": "off",
Copy link
Contributor

Choose a reason for hiding this comment

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

high

Disabling @typescript-eslint/no-unsafe-member-access is highly discouraged as it can hide potential runtime errors by allowing member access on any types without checks. This undermines the benefits of TypeScript's type safety. It's better to handle any types explicitly (e.g., with type guards or assertions) or, if necessary, disable the rule on a case-by-case basis with an inline comment explaining why it's safe. Consider re-enabling this rule or setting it to "warn" to avoid introducing bugs.

Suggested change
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-member-access": "warn",

Comment on lines +1 to +11
/**
* @see https://prettier.io/docs/configuration
* @type {import("prettier").Config}
*/
const config = {
singleQuote: false,
trailingComma: "all",
plugins: [require.resolve("prettier-plugin-organize-imports")],
};

module.exports = config;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This Prettier configuration file (prettier.config.cjs) seems redundant because a .prettierrc file with similar settings already exists in the same directory. Having multiple configuration files for the same tool can be confusing and lead to inconsistencies. It's recommended to consolidate into a single configuration file. Please consider removing this file and keeping only .prettierrc.

}

if (rgbppCells.length !== 0) {
console.log("Using existing RGB++ cell");
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Using console.log for logging (here and on lines 132 and 144) in a library package is generally not recommended. It can pollute the console of the consuming application and isn't configurable (e.g., to control log levels or redirect output). Consider using a dedicated, configurable logging library (like debug or pino) or passing in an optional logger instance to the client.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

Comment on lines +212 to +215
tx.addCellDeps(
params.udtScriptInfo.cellDeps[0].cellDep,
uniqueTypeInfo.cellDeps[0].cellDep,
);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Accessing cellDeps[0] directly without checking if the cellDeps array is empty can lead to a runtime error if a script happens to have no cell dependencies defined. It's safer to add a check to ensure the dependencies exist before accessing them.

    if (!params.udtScriptInfo.cellDeps[0] || !uniqueTypeInfo.cellDeps[0]) {
      throw new Error("Missing cell dependencies for UDT or UniqueType script");
    }
    tx.addCellDeps(
      params.udtScriptInfo.cellDeps[0].cellDep,
      uniqueTypeInfo.cellDeps[0].cellDep,
    );

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@fghdotio
Copy link
Contributor Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new package @ckb-ccc/rgbpp to handle RGB++ related logic, including UDT issuance. It adds new script definitions for mainnet and testnet, and a comprehensive set of types, utilities, and a client for RGB++. The overall structure is well-designed and the implementation covers many aspects of the RGB++ protocol. I've found a few issues, mainly in utility functions, related to incorrect length checks and handling of hex strings, which could lead to bugs. I've also pointed out a magic number that should be replaced by a constant. The suggested changes will improve the correctness and maintainability of the new package.

Comment on lines +41 to +49
export function getTxIdFromScriptArgs(args: ccc.Hex): string {
if (args.length < 32 * 2) {
throw new Error("Lock args length is invalid");
}

return trimHexPrefix(
reverseHexByteOrder(args.substring(args.length - 32 * 2) as ccc.Hex),
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This function has two issues:

  1. The length check args.length < 32 * 2 is incorrect because args is a ccc.Hex string which includes the 0x prefix. The check should be on the length of the hex characters, so it should be args.length < 32 * 2 + 2.
  2. The implementation is inconsistent with updateScriptArgsWithTxId which operates on a trimmed hex string. It's better to be consistent.

Here is a suggested fix that addresses both points.

export function getTxIdFromScriptArgs(args: ccc.Hex): string {
  const trimmed = trimHexPrefix(args);
  if (trimmed.length < 32 * 2) {
    throw new Error("Lock args length is invalid");
  }

  return trimHexPrefix(
    reverseHexByteOrder(
      prependHexPrefix(trimmed.substring(trimmed.length - 32 * 2)),
    ),
  );
}

Comment on lines +51 to +60
export function getTxIndexFromScriptArgs(args: ccc.Hex): number {
if (args.length < 32 * 2) {
throw new Error("Lock args length is invalid");
}

return parseInt(
reverseHexByteOrder(trimHexPrefix(args.substring(0, 8)) as ccc.Hex),
16,
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This function has two issues, likely from copy-pasting getTxIdFromScriptArgs:

  1. The length check args.length < 32 * 2 is incorrect. It should check for the presence of a 4-byte index, not a 32-byte txId. The check should be trimHexPrefix(args).length < 4 * 2.
  2. args.substring(0, 8) is incorrect because args includes the 0x prefix. This will slice part of the prefix and part of the hex. It should operate on the trimmed hex string.

Here is a suggested fix that addresses both points.

export function getTxIndexFromScriptArgs(args: ccc.Hex): number {
  const trimmed = trimHexPrefix(args);
  if (trimmed.length < 4 * 2) {
    throw new Error("Lock args length is invalid");
  }

  return parseInt(
    reverseHexByteOrder(prependHexPrefix(trimmed.substring(0, 8))),
    16,
  );
}

throw new Error("Unsupported output");
}

const minUtxoSatoshi = 546;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The value 546 for minUtxoSatoshi is a magic number. To improve readability and maintainability, please import and use the DEFAULT_DUST_LIMIT constant, which is already defined in ../configs/scripts/index.js.

You'll need to add this import at the top of the file:

import { DEFAULT_DUST_LIMIT } from "../configs/scripts/index.js";
Suggested change
const minUtxoSatoshi = 546;
const minUtxoSatoshi = DEFAULT_DUST_LIMIT;

Comment on lines +31 to +33
if (argsLength < (32 + 2) * 2) {
throw new Error("Lock args length is invalid");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The length check argsLength < (32 + 2) * 2 is likely incorrect. The value (32 + 2) * 2 evaluates to 68. A 32-byte hex string is 64 characters long. The purpose of this check is probably to ensure the args string is long enough to contain a 32-byte txId. A more accurate check would be argsLength < 32 * 2.

Suggested change
if (argsLength < (32 + 2) * 2) {
throw new Error("Lock args length is invalid");
}
if (argsLength < 32 * 2) {
throw new Error("Lock args length is invalid");
}

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.

1 participant