diff --git a/packages/ccc/package.json b/packages/ccc/package.json
index 61219eb9e..e4750d899 100644
--- a/packages/ccc/package.json
+++ b/packages/ccc/package.json
@@ -62,6 +62,7 @@
"@ckb-ccc/okx": "workspace:*",
"@ckb-ccc/rei": "workspace:*",
"@ckb-ccc/shell": "workspace:*",
+ "@ckb-ccc/superise": "workspace:*",
"@ckb-ccc/uni-sat": "workspace:*",
"@ckb-ccc/utxo-global": "workspace:*",
"@ckb-ccc/xverse": "workspace:*"
diff --git a/packages/ccc/src/assets/superise.svg.ts b/packages/ccc/src/assets/superise.svg.ts
new file mode 100644
index 000000000..3d6f493d6
--- /dev/null
+++ b/packages/ccc/src/assets/superise.svg.ts
@@ -0,0 +1,85 @@
+import { encodeSvgToImgSrc } from "./utils.js";
+
+export const SUPERISE_SVG = encodeSvgToImgSrc(`
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`);
diff --git a/packages/ccc/src/barrel.ts b/packages/ccc/src/barrel.ts
index 8b46c112d..a47eae2df 100644
--- a/packages/ccc/src/barrel.ts
+++ b/packages/ccc/src/barrel.ts
@@ -4,6 +4,7 @@ export * from "@ckb-ccc/nip07";
export * from "@ckb-ccc/okx";
export * from "@ckb-ccc/rei";
export * from "@ckb-ccc/shell/barrel";
+export * from "@ckb-ccc/superise";
export * from "@ckb-ccc/uni-sat";
export * from "@ckb-ccc/utxo-global";
export * from "@ckb-ccc/xverse";
diff --git a/packages/ccc/src/signersController.ts b/packages/ccc/src/signersController.ts
index 05e58deaa..b92b17161 100644
--- a/packages/ccc/src/signersController.ts
+++ b/packages/ccc/src/signersController.ts
@@ -4,6 +4,7 @@ import { Nip07 } from "@ckb-ccc/nip07";
import { Okx } from "@ckb-ccc/okx";
import { Rei } from "@ckb-ccc/rei";
import { ccc } from "@ckb-ccc/shell";
+import { SupeRISE } from "@ckb-ccc/superise";
import { UniSat } from "@ckb-ccc/uni-sat";
import { UtxoGlobal } from "@ckb-ccc/utxo-global";
import { Xverse } from "@ckb-ccc/xverse";
@@ -13,6 +14,7 @@ import { METAMASK_SVG } from "./assets/metamask.svg.js";
import { NOSTR_SVG } from "./assets/nostr.svg.js";
import { OKX_SVG } from "./assets/okx.svg.js";
import { REI_SVG } from "./assets/rei.svg.js";
+import { SUPERISE_SVG } from "./assets/superise.svg.js";
import { UNI_SAT_SVG } from "./assets/uni-sat.svg.js";
import { UTXO_GLOBAL_SVG } from "./assets/utxo-global.svg.js";
@@ -124,6 +126,14 @@ export class SignersController {
async addRealSigners(context: SignersControllerRefreshContext) {
const { appName, appIcon, client, preferredNetworks } = context;
+
+ await this.addSigners(
+ "SupeRISE",
+ SUPERISE_SVG,
+ SupeRISE.getSupeRISESigners(client, preferredNetworks),
+ context,
+ );
+
await this.addSigners(
"UTXO Global Wallet",
UTXO_GLOBAL_SVG,
diff --git a/packages/core/src/signer/ckb/verifySuperise.ts b/packages/core/src/signer/ckb/verifySuperise.ts
new file mode 100644
index 000000000..46e726187
--- /dev/null
+++ b/packages/core/src/signer/ckb/verifySuperise.ts
@@ -0,0 +1,40 @@
+import { secp256k1 } from "@noble/curves/secp256k1";
+import { BytesLike, bytesFrom } from "../../bytes/index.js";
+import { hashCkb } from "../../hasher/index.js";
+import { Hex, hexFrom } from "../../hex/index.js";
+import { numFrom } from "../../num/index.js";
+
+const SUPERISE_MESSAGE_PREFIX = "\x19SupeRISE Message:\n";
+
+/**
+ * @public
+ */
+function messageHashCkbSuperise(message: string | BytesLike): Hex {
+ const msg = typeof message === "string" ? message : hexFrom(message);
+ const buffer = bytesFrom(
+ `${SUPERISE_MESSAGE_PREFIX}${msg.length}${msg}`,
+ "utf8",
+ );
+ return hashCkb(buffer);
+}
+
+/**
+ * @public
+ */
+export function verifyMessageSuperise(
+ message: string | BytesLike,
+ signature: string,
+ publicKey: string,
+): boolean {
+ const signatureBytes = bytesFrom(signature);
+ return secp256k1.verify(
+ new secp256k1.Signature(
+ numFrom(signatureBytes.slice(0, 32)),
+ numFrom(signatureBytes.slice(32, 64)),
+ )
+ .addRecoveryBit(Number(numFrom(signatureBytes.slice(64, 65))))
+ .toBytes(),
+ bytesFrom(messageHashCkbSuperise(message)),
+ bytesFrom(publicKey),
+ );
+}
diff --git a/packages/core/src/signer/signer/index.ts b/packages/core/src/signer/signer/index.ts
index 1522b3353..e985a2684 100644
--- a/packages/core/src/signer/signer/index.ts
+++ b/packages/core/src/signer/signer/index.ts
@@ -13,6 +13,7 @@ import { Num } from "../../num/index.js";
import { verifyMessageBtcEcdsa } from "../btc/index.js";
import { verifyMessageCkbSecp256k1 } from "../ckb/verifyCkbSecp256k1.js";
import { verifyMessageJoyId } from "../ckb/verifyJoyId.js";
+import { verifyMessageSuperise } from "../ckb/verifySuperise.js";
import { verifyMessageDogeEcdsa } from "../doge/verify.js";
import { verifyMessageEvmPersonal } from "../evm/verify.js";
import { verifyMessageNostrEvent } from "../nostr/verify.js";
@@ -28,6 +29,7 @@ export enum SignerSignType {
NostrEvent = "NostrEvent",
CkbSecp256k1 = "CkbSecp256k1",
DogeEcdsa = "DogeEcdsa",
+ SupeRISE = "SupeRISE",
}
/**
@@ -152,6 +154,12 @@ export abstract class Signer {
signature.signature,
signature.identity,
);
+ case SignerSignType.SupeRISE:
+ return verifyMessageSuperise(
+ message,
+ signature.signature,
+ signature.identity,
+ );
case SignerSignType.Unknown:
throw new Error("Unknown signer sign type");
}
diff --git a/packages/superise/.npmignore b/packages/superise/.npmignore
new file mode 100644
index 000000000..7a88408aa
--- /dev/null
+++ b/packages/superise/.npmignore
@@ -0,0 +1,21 @@
+node_modules/
+misc/
+
+*test.js
+*test.ts
+*test.d.ts
+*test.d.ts.map
+*spec.js
+*spec.ts
+*spec.d.ts
+*spec.d.ts.map
+
+tsconfig.json
+tsconfig.*.json
+eslint.config.mjs
+.prettierrc
+.prettierignore
+
+tsconfig.tsbuildinfo
+tsconfig.*.tsbuildinfo
+.github/
diff --git a/packages/superise/.prettierignore b/packages/superise/.prettierignore
new file mode 100644
index 000000000..aef5d239c
--- /dev/null
+++ b/packages/superise/.prettierignore
@@ -0,0 +1,15 @@
+node_modules/
+
+dist/
+dist.commonjs/
+
+.npmignore
+.prettierrc
+tsconfig.json
+eslint.config.mjs
+prettier.config.*
+
+tsconfig.tsbuildinfo
+.github/
+
+CHANGELOG.md
diff --git a/packages/superise/README.md b/packages/superise/README.md
new file mode 100644
index 000000000..d4fb74223
--- /dev/null
+++ b/packages/superise/README.md
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+ CCC's support for SupeRISE
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CCC - CKBers' Codebase is a one-stop solution for your CKB JS/TS ecosystem development.
+
+ Empower yourself with CCC to discover the unlimited potential of CKB.
+
+ Interoperate with wallets from different chain ecosystems.
+
+ Fully enabling CKB's Turing completeness and cryptographic freedom power.
+
+
+
diff --git a/packages/superise/eslint.config.mjs b/packages/superise/eslint.config.mjs
new file mode 100644
index 000000000..b6132c277
--- /dev/null
+++ b/packages/superise/eslint.config.mjs
@@ -0,0 +1,62 @@
+// @ts-check
+
+import eslint from "@eslint/js";
+import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
+import tseslint from "typescript-eslint";
+
+import { dirname } from "path";
+import { fileURLToPath } from "url";
+
+export default [
+ ...tseslint.config({
+ files: ["**/*.ts"],
+ extends: [
+ eslint.configs.recommended,
+ ...tseslint.configs.recommendedTypeChecked,
+ ],
+ rules: {
+ "@typescript-eslint/no-unused-vars": [
+ "error",
+ {
+ args: "all",
+ argsIgnorePattern: "^_",
+ caughtErrors: "all",
+ caughtErrorsIgnorePattern: "^_",
+ destructuredArrayIgnorePattern: "^_",
+ varsIgnorePattern: "^_",
+ ignoreRestSiblings: true,
+ },
+ ],
+ "@typescript-eslint/unbound-method": ["error", { ignoreStatic: true }],
+ "@typescript-eslint/no-unsafe-member-access": "off",
+ "@typescript-eslint/require-await": "off",
+ "@typescript-eslint/only-throw-error": [
+ "error",
+ {
+ allowThrowingAny: true,
+ allowThrowingUnknown: true,
+ allowRethrowing: true,
+ },
+ ],
+ "@typescript-eslint/prefer-promise-reject-errors": [
+ "error",
+ {
+ allowThrowingAny: true,
+ allowThrowingUnknown: true,
+ },
+ ],
+ "no-empty": "off",
+ "prefer-const": [
+ "error",
+ { ignoreReadBeforeAssign: true, destructuring: "all" },
+ ],
+ },
+ languageOptions: {
+ parserOptions: {
+ project: true,
+ tsconfigRootDir: dirname(fileURLToPath(import.meta.url)),
+ },
+ },
+ }),
+ eslintPluginPrettierRecommended,
+];
diff --git a/packages/superise/misc/basedirs/dist.commonjs/package.json b/packages/superise/misc/basedirs/dist.commonjs/package.json
new file mode 100644
index 000000000..5bbefffba
--- /dev/null
+++ b/packages/superise/misc/basedirs/dist.commonjs/package.json
@@ -0,0 +1,3 @@
+{
+ "type": "commonjs"
+}
diff --git a/packages/superise/misc/basedirs/dist/package.json b/packages/superise/misc/basedirs/dist/package.json
new file mode 100644
index 000000000..aead43de3
--- /dev/null
+++ b/packages/superise/misc/basedirs/dist/package.json
@@ -0,0 +1,3 @@
+{
+ "type": "module"
+}
\ No newline at end of file
diff --git a/packages/superise/package.json b/packages/superise/package.json
new file mode 100644
index 000000000..df6492def
--- /dev/null
+++ b/packages/superise/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "@ckb-ccc/superise",
+ "version": "1.0.29",
+ "description": "Common Chains Connector's support for SupeRISE",
+ "author": "rivjc",
+ "license": "MIT",
+ "private": false,
+ "homepage": "https://github.com/ckb-devrel/ccc",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/ckb-devrel/ccc.git"
+ },
+ "sideEffects": false,
+ "main": "dist.commonjs/index.js",
+ "module": "dist/index.js",
+ "exports": {
+ ".": {
+ "import": "./dist/index.js",
+ "require": "./dist.commonjs/index.js",
+ "default": "./dist.commonjs/index.js"
+ },
+ "./barrel": {
+ "import": "./dist/barrel.js",
+ "require": "./dist.commonjs/barrel.js",
+ "default": "./dist.commonjs/barrel.js"
+ }
+ },
+ "scripts": {
+ "build": "rimraf ./dist && rimraf ./dist.commonjs && tsc && tsc --project tsconfig.commonjs.json && copyfiles -u 2 misc/basedirs/**/* .",
+ "lint": "eslint ./src",
+ "format": "prettier --write . && eslint --fix ./src"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.34.0",
+ "copyfiles": "^2.4.1",
+ "eslint": "^9.34.0",
+ "eslint-config-prettier": "^10.1.8",
+ "eslint-plugin-prettier": "^5.5.4",
+ "prettier": "^3.6.2",
+ "prettier-plugin-organize-imports": "^4.2.0",
+ "rimraf": "^6.0.1",
+ "typescript": "^5.9.2",
+ "typescript-eslint": "^8.41.0"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "dependencies": {
+ "@ckb-ccc/core": "workspace:*"
+ },
+ "packageManager": "pnpm@10.8.1"
+}
diff --git a/packages/superise/prettier.config.cjs b/packages/superise/prettier.config.cjs
new file mode 100644
index 000000000..5e1810363
--- /dev/null
+++ b/packages/superise/prettier.config.cjs
@@ -0,0 +1,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;
diff --git a/packages/superise/src/advanced.ts b/packages/superise/src/advanced.ts
new file mode 100644
index 000000000..5bf9d080e
--- /dev/null
+++ b/packages/superise/src/advanced.ts
@@ -0,0 +1 @@
+export * as SupeRISEA from "./advancedBarrel.js";
diff --git a/packages/superise/src/advancedBarrel.ts b/packages/superise/src/advancedBarrel.ts
new file mode 100644
index 000000000..300bc39b4
--- /dev/null
+++ b/packages/superise/src/advancedBarrel.ts
@@ -0,0 +1,17 @@
+export interface CkbConnection {
+ publicKey: string;
+ address: string;
+}
+
+export interface Bridge {
+ version: string;
+
+ connectCkb: () => Promise;
+
+ signCkbMessage: (message: string) => Promise<{ signature: string }>;
+
+ signCkbTransaction: (
+ transaction: string,
+ witnessIndexes: number[],
+ ) => Promise<{ signedTransaction: string }>;
+}
diff --git a/packages/superise/src/barrel.ts b/packages/superise/src/barrel.ts
new file mode 100644
index 000000000..b60ec7b8e
--- /dev/null
+++ b/packages/superise/src/barrel.ts
@@ -0,0 +1,2 @@
+export * from "./ckb/index.js";
+export * from "./signersFactory.js";
diff --git a/packages/superise/src/ckb/index.ts b/packages/superise/src/ckb/index.ts
new file mode 100644
index 000000000..858ef3ae5
--- /dev/null
+++ b/packages/superise/src/ckb/index.ts
@@ -0,0 +1,176 @@
+import { ccc } from "@ckb-ccc/core";
+import type { Bridge, CkbConnection } from "../advancedBarrel";
+
+export class CkbSigner extends ccc.Signer {
+ get type() {
+ return ccc.SignerType.CKB;
+ }
+
+ get signType() {
+ return ccc.SignerSignType.CkbSecp256k1;
+ }
+
+ private connectionStorageKey = "superise-ckb-connection";
+
+ private connection?: CkbConnection;
+
+ constructor(
+ private readonly bridge: Bridge,
+ client: ccc.Client,
+ ) {
+ super(client);
+ }
+
+ private saveConnection() {
+ localStorage.setItem(
+ this.connectionStorageKey,
+ JSON.stringify(this.connection),
+ );
+ }
+
+ private restoreConnection() {
+ const connection = localStorage.getItem(this.connectionStorageKey);
+ if (!connection) return;
+ try {
+ this.connection = JSON.parse(connection) as CkbConnection;
+ } catch (error) {
+ console.error("Failed to restore superise connection:", error);
+ }
+ }
+
+ private async getConnection() {
+ if (!this.connection) this.restoreConnection();
+ if (!this.connection) throw new Error("Not connected");
+
+ return this.connection;
+ }
+
+ async connect() {
+ this.connection = await this.bridge.connectCkb();
+ this.saveConnection();
+ }
+
+ async isConnected() {
+ if (this.connection) return true;
+
+ this.restoreConnection();
+ return !!this.connection;
+ }
+
+ override async disconnect() {
+ this.connection = undefined;
+ localStorage.removeItem(this.connectionStorageKey);
+ }
+
+ override async getInternalAddress() {
+ return (await this.getConnection()).address;
+ }
+
+ override async getIdentity() {
+ return (await this.getConnection()).publicKey;
+ }
+
+ async getAddressObj() {
+ return await ccc.Address.fromString(
+ await this.getInternalAddress(),
+ this.client,
+ );
+ }
+
+ override async getAddressObjs() {
+ return [await this.getAddressObj()];
+ }
+
+ override async signMessageRaw(message: string) {
+ const sign = await this.bridge.signCkbMessage(message);
+ return ccc.hexFrom(sign.signature);
+ }
+
+ async getRelatedScripts(
+ txLike: ccc.TransactionLike,
+ ): Promise<{ script: ccc.Script; cellDeps: ccc.CellDepInfo[] }[]> {
+ const tx = ccc.Transaction.from(txLike);
+
+ const addressObj = await this.getAddressObj();
+ const acp = await ccc.Script.fromKnownScript(
+ this.client,
+ ccc.KnownScript.AnyoneCanPay,
+ addressObj.script.args,
+ );
+
+ const scripts: { script: ccc.Script; cellDeps: ccc.CellDepInfo[] }[] = [];
+ for (const input of tx.inputs) {
+ const {
+ cellOutput: { lock },
+ } = await input.getCell(this.client);
+
+ if (scripts.some(({ script }) => script.eq(lock))) {
+ continue;
+ }
+
+ if (lock.eq(addressObj.script)) {
+ scripts.push({
+ script: lock,
+ cellDeps: (
+ await this.client.getKnownScript(ccc.KnownScript.Secp256k1Blake160)
+ ).cellDeps,
+ });
+ } else if (
+ lock.codeHash === acp.codeHash &&
+ lock.hashType === acp.hashType &&
+ lock.args.startsWith(acp.args)
+ ) {
+ scripts.push({
+ script: lock,
+ cellDeps: (
+ await this.client.getKnownScript(ccc.KnownScript.AnyoneCanPay)
+ ).cellDeps,
+ });
+ }
+ }
+
+ return scripts;
+ }
+
+ override async prepareTransaction(txLike: ccc.TransactionLike) {
+ const tx = ccc.Transaction.from(txLike);
+
+ const scripts = await this.getRelatedScripts(tx);
+
+ await Promise.all(
+ scripts.map(async ({ script, cellDeps }) => {
+ await tx.prepareSighashAllWitness(script, 65, this.client);
+ await tx.addCellDepInfos(this.client, cellDeps);
+ }),
+ );
+
+ return tx;
+ }
+
+ override async signOnlyTransaction(txLike: ccc.TransactionLike) {
+ const tx = ccc.Transaction.from(txLike);
+
+ const witnessIndexes = await ccc.reduceAsync(
+ await this.getRelatedScripts(tx),
+ async (indexes, scriptInfo) => {
+ const index = await tx.findInputIndexByLock(
+ scriptInfo.script,
+ this.client,
+ );
+ if (typeof index !== "number") return;
+
+ indexes.push(index);
+ },
+ [] as number[],
+ );
+
+ const result = await this.bridge.signCkbTransaction(
+ ccc.stringify(tx),
+ witnessIndexes,
+ );
+ const signedTx = JSON.parse(
+ result.signedTransaction,
+ ) as ccc.TransactionLike;
+ return ccc.Transaction.from(signedTx);
+ }
+}
diff --git a/packages/superise/src/index.ts b/packages/superise/src/index.ts
new file mode 100644
index 000000000..46a02e3c3
--- /dev/null
+++ b/packages/superise/src/index.ts
@@ -0,0 +1 @@
+export * as SupeRISE from "./barrel.js";
diff --git a/packages/superise/src/signersFactory.ts b/packages/superise/src/signersFactory.ts
new file mode 100644
index 000000000..dc16a5436
--- /dev/null
+++ b/packages/superise/src/signersFactory.ts
@@ -0,0 +1,26 @@
+import { ccc } from "@ckb-ccc/core";
+import type { Bridge } from "./advancedBarrel";
+import { CkbSigner } from "./ckb/index.js";
+
+/**
+ * @public
+ */
+export function getSupeRISESigners(
+ client: ccc.Client,
+ _preferredNetworks?: ccc.NetworkPreference[],
+): ccc.SignerInfo[] {
+ const windowRef = window as {
+ superise?: Bridge;
+ };
+
+ if (typeof windowRef.superise === "undefined") {
+ return [];
+ }
+
+ return [
+ {
+ name: "CKB",
+ signer: new CkbSigner(windowRef.superise, client),
+ },
+ ];
+}
diff --git a/packages/superise/tsconfig.base.json b/packages/superise/tsconfig.base.json
new file mode 100644
index 000000000..7e5ac952b
--- /dev/null
+++ b/packages/superise/tsconfig.base.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "target": "es2020",
+ "incremental": true,
+ "allowJs": true,
+ "importHelpers": false,
+ "declaration": true,
+ "declarationMap": true,
+ "experimentalDecorators": true,
+ "useDefineForClassFields": false,
+ "esModuleInterop": true,
+ "strict": true,
+ "noImplicitAny": true,
+ "strictBindCallApply": true,
+ "strictNullChecks": true,
+ "alwaysStrict": true,
+ "noFallthroughCasesInSwitch": true,
+ "forceConsistentCasingInFileNames": true,
+ "skipLibCheck": true
+ },
+ "include": ["src/**/*"]
+}
diff --git a/packages/superise/tsconfig.commonjs.json b/packages/superise/tsconfig.commonjs.json
new file mode 100644
index 000000000..76a25e98b
--- /dev/null
+++ b/packages/superise/tsconfig.commonjs.json
@@ -0,0 +1,8 @@
+{
+ "extends": "./tsconfig.base.json",
+ "compilerOptions": {
+ "module": "NodeNext",
+ "moduleResolution": "NodeNext",
+ "outDir": "./dist.commonjs"
+ }
+}
diff --git a/packages/superise/tsconfig.json b/packages/superise/tsconfig.json
new file mode 100644
index 000000000..df22faeca
--- /dev/null
+++ b/packages/superise/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "./tsconfig.base.json",
+ "compilerOptions": {
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "outDir": "./dist",
+ }
+}
diff --git a/packages/superise/typedoc.json b/packages/superise/typedoc.json
new file mode 100644
index 000000000..b663440e9
--- /dev/null
+++ b/packages/superise/typedoc.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "https://typedoc.org/schema.json",
+ "entryPoints": ["./src/index.ts", "./src/advanced.ts"],
+ "extends": ["../../typedoc.base.json"],
+ "name": "@ckb-ccc superise"
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 78369fd1c..3d01d660c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -70,6 +70,9 @@ importers:
'@ckb-ccc/shell':
specifier: workspace:*
version: link:../shell
+ '@ckb-ccc/superise':
+ specifier: workspace:*
+ version: link:../superise
'@ckb-ccc/uni-sat':
specifier: workspace:*
version: link:../uni-sat
@@ -1083,6 +1086,43 @@ importers:
specifier: ^8.41.0
version: 8.41.0(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2)
+ packages/superise:
+ dependencies:
+ '@ckb-ccc/core':
+ specifier: workspace:*
+ version: link:../core
+ devDependencies:
+ '@eslint/js':
+ specifier: ^9.34.0
+ version: 9.34.0
+ copyfiles:
+ specifier: ^2.4.1
+ version: 2.4.1
+ eslint:
+ specifier: ^9.34.0
+ version: 9.34.0(jiti@2.5.1)
+ eslint-config-prettier:
+ specifier: ^10.1.8
+ version: 10.1.8(eslint@9.34.0(jiti@2.5.1))
+ eslint-plugin-prettier:
+ specifier: ^5.5.4
+ version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.34.0(jiti@2.5.1)))(eslint@9.34.0(jiti@2.5.1))(prettier@3.6.2)
+ prettier:
+ specifier: ^3.6.2
+ version: 3.6.2
+ prettier-plugin-organize-imports:
+ specifier: ^4.2.0
+ version: 4.2.0(prettier@3.6.2)(typescript@5.9.2)
+ rimraf:
+ specifier: ^6.0.1
+ version: 6.0.1
+ typescript:
+ specifier: ^5.9.2
+ version: 5.9.2
+ typescript-eslint:
+ specifier: ^8.41.0
+ version: 8.41.0(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2)
+
packages/tests:
devDependencies:
'@ckb-ccc/ccc':