Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/mean-yaks-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@ckb-ccc/spore": minor
---

Migrate dob-render-sdk directly into spore module

3 changes: 2 additions & 1 deletion packages/ccc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
"@ckb-ccc/shell": "workspace:*",
"@ckb-ccc/uni-sat": "workspace:*",
"@ckb-ccc/utxo-global": "workspace:*",
"@ckb-ccc/xverse": "workspace:*"
"@ckb-ccc/xverse": "workspace:*",
"@ckb-ccc/dob-render": "workspace:*"
},
"packageManager": "[email protected]"
}
1 change: 1 addition & 0 deletions packages/ccc/src/barrel.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "@ckb-ccc/dob-render";
export * from "@ckb-ccc/eip6963";
export * from "@ckb-ccc/joy-id";
export * from "@ckb-ccc/nip07";
Expand Down
42 changes: 42 additions & 0 deletions packages/dob-render/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# @ckb-ccc/render
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 package name in the README title is @ckb-ccc/render, but the actual package name is @ckb-ccc/dob-render. This should be corrected to avoid confusion.

Suggested change
# @ckb-ccc/render
# @ckb-ccc/dob-render

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 package name in the main heading is @ckb-ccc/render, but the actual package name is @ckb-ccc/dob-render. This should be corrected for consistency and to avoid confusion for developers.

Suggested change
# @ckb-ccc/render
# @ckb-ccc/dob-render


CCC - CKBer's Codebase. Common Chains Connector's render SDK for DOB protocol.

This package provides rendering capabilities for DOB (Decentralized Object) protocol, allowing you to render DOB tokens as SVG images.

## Installation

```bash
npm install @ckb-ccc/dob-render
```

## Usage

```typescript
import {
renderByTokenKey,
renderByDobDecodeResponse,
} from "@ckb-ccc/dob-render";

// Render by token key
const svg = await renderByTokenKey("your-token-key");

// Render by DOB decode response
const svg = renderByDobDecodeResponse(renderOutput);
```

## API

### `renderByTokenKey(tokenKey: string, options?: RenderOptions)`

Renders a DOB token by its key.

### `renderByDobDecodeResponse(renderOutput: RenderOutput | string, props?: RenderProps)`
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 function signature for renderByDobDecodeResponse in the API documentation is incorrect. The renderOutput parameter is typed as RenderOutput | string, but the implementation only accepts RenderOutput. The | string part should be removed to accurately reflect the function's signature.

Suggested change
### `renderByDobDecodeResponse(renderOutput: RenderOutput | string, props?: RenderProps)`
### `renderByDobDecodeResponse(renderOutput: RenderOutput, props?: RenderProps)`


Renders a DOB token from a decoded response.

## Dependencies

- `satori` - SVG to image conversion
- `svgson` - SVG parsing
- `axios` - HTTP client for API calls
62 changes: 62 additions & 0 deletions packages/dob-render/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -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,
];
58 changes: 58 additions & 0 deletions packages/dob-render/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "@ckb-ccc/dob-render",
"version": "1.0.1",
"description": "CCC - CKBer's Codebase. Common Chains Connector's render SDK for DOB protocol",
"author": "ashuralyk <[email protected]>",
"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",
"lint": "eslint ./src",
"format": "prettier --write . && eslint --fix ./src"
},
"devDependencies": {
"@eslint/js": "^9.34.0",
"@types/node": "^24.3.0",
"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/spore": "workspace:*",
"axios": "^1.11.0",
"satori": "^0.10.13",
"svgson": "^5.3.1"
},
"peerDependencies": {
"satori": "^0.10.13"
},
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

satori is listed as both a direct dependency and a peer dependency. This is generally not recommended. If it's a peer dependency, the consumer of this package is responsible for providing it, and it shouldn't be included as a direct dependency to avoid potential version conflicts. Please clarify the intention and remove it from either dependencies or peerDependencies.

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 satori package is listed as both a dependency and a peerDependency. A package should typically be one or the other. If users of @ckb-ccc/dob-render are expected to provide their own version of satori, it should only be a peerDependency and removed from dependencies. If it's a direct dependency required by the package, it should be removed from peerDependencies. Please clarify the intention and remove the redundant entry to avoid confusion and potential dependency issues.

"packageManager": "[email protected]"
}
11 changes: 11 additions & 0 deletions packages/dob-render/prettier.config.cjs
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 2 additions & 0 deletions packages/dob-render/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./renderDobDecode.js";
export * from "./renderToken.js";
37 changes: 37 additions & 0 deletions packages/dob-render/src/api/renderDobDecode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Key } from "../config/constants.js";
import { renderTextParamsParser } from "../core/parsers/textParamsParser.js";
import { traitsParser } from "../core/parsers/traitsParser.js";
import { renderDob1Svg } from "../core/renderers/dob1Render.js";
import { renderImageSvg } from "../core/renderers/imageRender.js";
import { renderTextSvg } from "../core/renderers/textRender.js";
import type { RenderOutput } from "../types/external.js";
import type { RenderOptions } from "../types/query.js";
import {
defaultQueryBtcFsFn,
defaultQueryCkbFsFn,
defaultQueryIpfsFn,
defaultQueryUrlFn,
} from "../types/query.js";

export function renderByDobDecodeResponse(
renderOutput: RenderOutput,
props?: RenderOptions,
) {
const { traits, indexVarRegister } = traitsParser(renderOutput);
for (const trait of traits) {
if (trait.name === String(Key.Type) && trait.value === "image") {
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 String() wrapper around Key.Type is redundant because TypeScript enum members with string initializers are already strings. You can compare trait.name directly with Key.Type. This improves code clarity and removes an unnecessary function call.

Suggested change
if (trait.name === String(Key.Type) && trait.value === "image") {
if (trait.name === Key.Type && trait.value === "image") {

return renderImageSvg(traits, {
queryBtcFsFn: props?.queryBtcFsFn || defaultQueryBtcFsFn,
queryIpfsFn: props?.queryIpfsFn || defaultQueryIpfsFn,
queryCkbFsFn: props?.queryCkbFsFn || defaultQueryCkbFsFn,
queryUrlFn: props?.queryUrlFn || defaultQueryUrlFn,
});
}
// TODO: multiple images
if (trait.name === String(Key.Image) && trait.value instanceof Promise) {
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Similar to the comment on line 22, the String() wrapper around Key.Image is redundant and can be removed for cleaner code.

Suggested change
if (trait.name === String(Key.Image) && trait.value instanceof Promise) {
if (trait.name === Key.Image && trait.value instanceof Promise) {

return renderDob1Svg(trait.value);
}
}
const renderOptions = renderTextParamsParser(traits, indexVarRegister);
return renderTextSvg({ ...renderOptions, font: props?.font });
}
14 changes: 14 additions & 0 deletions packages/dob-render/src/api/renderToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { dob } from "@ckb-ccc/spore";
import type { RenderOptions } from "../types/query.js";
import { renderByDobDecodeResponse } from "./renderDobDecode.js";

export async function renderByTokenKey(
tokenKey: string,
options?: RenderOptions & { dobDecodeServerURL?: string },
) {
const serverURL =
options?.dobDecodeServerURL || "https://dob-decoder.ckbccc.com";
const renderOutput = await dob.decodeDobBySporeId(tokenKey, serverURL);

return renderByDobDecodeResponse(renderOutput, options);
}
5 changes: 5 additions & 0 deletions packages/dob-render/src/barrel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from "./api/index.js";
export * from "./config/index.js";
export * from "./core/index.js";
export * from "./types/index.js";
export * from "./utils/index.js";
12 changes: 12 additions & 0 deletions packages/dob-render/src/config/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export enum Key {
Bg = "prev.bg",
Type = "prev.type",
BgColor = "prev.bgcolor",
Prev = "prev",
Image = "IMAGE",
}

export const ARRAY_REG = /\(%(.*?)\):(\[.*?\])/;
export const ARRAY_INDEX_REG = /(\d+)<_>$/;
export const GLOBAL_TEMPLATE_REG = /^prev<(.*?)>/;
export const TEMPLATE_REG = /^(.*?)<(.*?)>/;
9 changes: 9 additions & 0 deletions packages/dob-render/src/config/fonts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import SpaceGroteskBoldBase64 from "../fonts/spaceGroteskBold.base64.js";
import TurretRoadBoldBase64 from "../fonts/turretRoadBold.base64.js";
import TurretRoadMediumBase64 from "../fonts/turretRoadMedium.base64.js";

export const FONTS = {
SpaceGroteskBold: SpaceGroteskBoldBase64,
TurretRoadBold: TurretRoadBoldBase64,
TurretRoadMedium: TurretRoadMediumBase64,
} as const;
2 changes: 2 additions & 0 deletions packages/dob-render/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./constants.js";
export * from "./fonts.js";
2 changes: 2 additions & 0 deletions packages/dob-render/src/core/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./parsers/index.js";
export * from "./renderers/index.js";
29 changes: 29 additions & 0 deletions packages/dob-render/src/core/parsers/backgroundColorParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Key } from "../../config/constants.js";
import type { ParsedTrait } from "../../types/core.js";

export function getBackgroundColorByTraits(
traits: ParsedTrait[],
): ParsedTrait | undefined {
return traits.find((trait) => trait.name === String(Key.BgColor));
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 String() wrapper around Key.BgColor is redundant, as enum members are already strings. You can compare trait.name directly with Key.BgColor for better readability.

Suggested change
return traits.find((trait) => trait.name === String(Key.BgColor));
return traits.find((trait) => trait.name === Key.BgColor);

}

export function backgroundColorParser(
traits: ParsedTrait[],
options?: {
defaultColor?: string;
},
): string {
const bgColorTrait = getBackgroundColorByTraits(traits);
if (bgColorTrait) {
if (typeof bgColorTrait.value === "string") {
if (
bgColorTrait.value.startsWith("#(") &&
bgColorTrait.value.endsWith(")")
) {
return bgColorTrait.value.replace("#(", "linear-gradient(");
}
return bgColorTrait.value;
}
}
return options?.defaultColor || "#000";
}
4 changes: 4 additions & 0 deletions packages/dob-render/src/core/parsers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./backgroundColorParser.js";
export * from "./styleParser.js";
export * from "./textParamsParser.js";
export * from "./traitsParser.js";
Loading