Skip to content
Open
Show file tree
Hide file tree
Changes from all 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

7 changes: 7 additions & 0 deletions .changeset/tall-parrots-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@ckb-ccc/dob-render": patch
"@ckb-ccc/spore": patch
---

Fix decoder responsed value type mismatch and migrate dob-render-sdk to ccc

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/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, 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,
];
55 changes: 55 additions & 0 deletions packages/dob-render/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"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"
},
"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 { dob } from "@ckb-ccc/spore";
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 { RenderOptions } from "../types/query.js";
import {
defaultQueryBtcFsFn,
defaultQueryCkbFsFn,
defaultQueryIpfsFn,
defaultQueryUrlFn,
} from "../types/query.js";

export function renderByDobDecodeResponse(
renderOutput: dob.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