{"id":18275518,"url":"https://github.com/ckb-js/kuai","last_synced_at":"2025-04-05T03:31:00.525Z","repository":{"id":61930842,"uuid":"547787398","full_name":"ckb-js/kuai","owner":"ckb-js","description":"A protocol and framework for building universal dapps on Nervos CKB","archived":false,"fork":false,"pushed_at":"2025-03-31T19:32:40.000Z","size":13384,"stargazers_count":23,"open_issues_count":40,"forks_count":11,"subscribers_count":6,"default_branch":"develop","last_synced_at":"2025-04-04T10:52:15.915Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ckb-js.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-08T09:39:49.000Z","updated_at":"2025-01-05T05:49:05.000Z","dependencies_parsed_at":"2024-02-26T21:27:11.834Z","dependency_job_id":"265f850f-4538-40aa-9508-c8368c406534","html_url":"https://github.com/ckb-js/kuai","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckb-js%2Fkuai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckb-js%2Fkuai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckb-js%2Fkuai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckb-js%2Fkuai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ckb-js","download_url":"https://codeload.github.com/ckb-js/kuai/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247284911,"owners_count":20913691,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T12:13:11.093Z","updated_at":"2025-04-05T03:30:55.481Z","avatar_url":"https://github.com/ckb-js.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/ckb-js/kuai/assets/7271329/f128229c-950d-45e8-85f5-c937c04aee9b\" alt=\"Kuai Logo\" width=\"120\" /\u003e\n\u003c/p\u003e\n\n# Overview\n\n**Kuai** is an application development **philosophy** and all-in-one development **framework** designed specifically for Nervos CKB. It encompasses generic application development **patterns**, convenient development **scaffolding**, plug-and-play application **architecture**, and development **manuals** to facilitate development processes.\n\n# Design Philosophy\n\nThe cell model of CKB is a generalization of Bitcoin's [UTXO model](https://en.wikipedia.org/wiki/Unspent_transaction_output) and naturally has the ability to execute in parallel. Inspired by the [Actor model](https://en.wikipedia.org/wiki/Actor_model), the Kuai project abstracts a group of cells into an actor based on patterns. Actors communicate with each other through message passing, which enables efficient parallel execution of multiple actors and improves the interoperability from module level to application level. This design facilitates the development of highly concurrent and scalable applications.\n\nRead [Kuai Proposal](https://github.com/ckb-js/topics/blob/add-draft-of-kuai-proposal/README.md) for more details on the design.\n\n# Modules\n\n## [@kuai/cli](https://github.com/ckb-js/kuai/tree/develop/packages/cli)\n\nkuai-cli maps kuai's task system to a unix command-line interface and executes it, providing additional commands such as help\n\n### how to use this module\n\nbuild or download kuai-cli\n\n- Build locally\n\n```bash\n$ git clone git@github.com:ckb-js/kuai.git\n$ npm i\n$ npx lerna run build\n$ npx link ./packages/cli\n```\n\n### Built-in commands list\n\n- kuai test\n\n```bash\n# kuai test [options]\n\n# Options:\n#   --projectRootPath [path]    The Root of testing project (default: \"\")\n#   -h, --help                  display help for command\n```\n\n- kuai node\n\n```bash\n# start\n# kuai node [options] start\n\n# Options:\n#   --port [number]            port number (default: 8114)\n#   --detached                 run in backend (default: false)\n#   --genesisArgs [string...]  The genesis args\n#   -h, --help                 display help for command\n```\n\n```bash\n# close\n$ kuai node close\n```\n\n- kuai init\n\n```bash\n# kuai init [options]\n\n# Options:\n#   -h, --help                 display help for command\n```\n\n- kuai build\n\n```bash\n# Usage: kuai build [options] [command]\n\n# build the dapp\n\n# Options:\n#   --server    Build Server (default: true)\n#   -h, --help  display help for command\n\n# Commands:\n#   dev         build server side application in dev mode\n#   server      build server side application\n```\n\n- Kuai contract\n  [TODO]\n- kuai contract deploy\n\n```bash\n# Usage: kuai contract deploy [options]\n\n# Options:\n#   --name [string]      name of the contract to be deployed (default: \"\")\n#   --bin-path [path]    path of contract bin file (default: \"\")\n#   --from \u003cstring...\u003e   address or multisig config of the contract deployer (default: \"\")\n#   --signer [string]    signer provider [default: ckb-cli] [possible values: ckb-cli, ckb-cli-multisig]\n#                        (default: \"\")\n#   --fee-rate [number]  per transaction's fee, deployment may involve more than one transaction. default:\n#                        [1000] shannons/Byte (default: 1000)\n#   --export [path]      export transaction to file (default: \"\")\n#   --send               send transaction directly (default: false)\n#   --no-type-id         not use type id deploy\n#   -h, --help           display help for command\n```\n\n- kuai contract sign-message\n\n```bash\n# Usage: kuai contract sign-message [options]\n\n# Options:\n#   --message \u003cstring\u003e  message to be signed (default: \"\")\n#   --address \u003cstring\u003e  the address of message signer (default: \"\")\n#   --prefix [string]   the prefix of signature (default: \"\")\n#   --signer [string]   signer provider [default: ckb-cli] [possible values: ckb-cli, ckb-cli-multisig]\n#                       (default: \"ckb-cli\")\n#   -h, --help          display help for command\n```\n\n- kuai contract build\n\n```bash\n# Usage: kuai contract build [options]\n\n# Options:\n#   --name [string]  contract name (default: \"\")\n#   --release        build contracts in release mode (default: false)\n#   -h, --help       display help for command\n```\n\n- kuai contract new\n\n```bash\n# Usage: kuai contract new [options]\n\n# Options:\n#   --name \u003cstring\u003e      The name of new contract\n#   --template [string]  language template  [default: rust]  [possible values: rust, c, c-sharedlib]\n#                        (default: \"rust\")\n#   -h, --help           display help for command\n```\n\n- Kuai signer\n  [built-in signer]\n- kuai signer account-list\n\n```bash\n# Usage: kuai signer account-list [options]\n\n# list accounts of built-in signer\n\n# Options:\n#   --console   console output (default: false)\n#   -h, --help  display help for command\n```\n\n- kuai signer account-new\n\n```bash\n# Usage: kuai signer account-new [options]\n\n# create new account for built-in signer\n\n# Options:\n#   --password \u003cstring\u003e  The password of account\n#   --console            console output (default: false)\n#   -h, --help           display help for command\n```\n\n- kuai signer account-import\n\n```bash\n# Usage: kuai signer account-import [options]\n\n# import an unencrypted private key from \u003cprivkey-path\u003e and create a new account.\n\n# Options:\n#   --privkey-path \u003cstring\u003e           The privkey is assumed to contain an unencrypted private key in\n                                    hexadecimal format. (only read first line)\n#   --password [string]               The Password to lock your account (default: \"\")\n#   --extended-privkey-path \u003cstring\u003e  Extended private key path (include master private key and chain\n                                    code)\n#   --console                         console output (default: false)\n#   -h, --help                        display help for command\n```\n\n- kuai signer account-export\n\n```bash\n# Usage: kuai signer account-export [options]\n\n# export master private key and chain code as hex plain text (USE WITH YOUR OWN RISK)\n\n# Options:\n#   --lock-arg \u003cstring\u003e               Lock argument (account identifier, blake2b(pubkey)[0..20])\n#   --password [string]               The Password for unlock your account (default: \"\")\n#   --extended-privkey-path \u003cstring\u003e   Output extended private key path (PrivKey + ChainCode)\n#   --console                         console output (default: false)\n#   -h, --help                        display help for command\n```\n\n## [@kuai/common](https://github.com/ckb-js/kuai/tree/develop/packages/common)\n\nThe common module provides a set of common utility functions and helpers that are used throughout the Kuai repository.\n**[what is this module]** @zhengjianhui\n**[how to use this module]** @zhengjianhui\n\n## [@kuai/core](https://github.com/ckb-js/kuai/tree/develop/packages/core)\n\nThe core module exposes the core functionalities for building decentralized applications on Nervos CKB. It includes tasks to create projects in generic development patterns and a universal architecture, to launch a local devnet chain, to run tests in a general manner, to deploy applications smoothly.\n\n### how to use this module\n\n1. define built-in kuai project templates at https://github.com/ckb-js/kuai/tree/develop/packages/core/sample-projects, these templates are used to initialize a DApp;\n2. define tasks at https://github.com/ckb-js/kuai/tree/develop/packages/core/src/builtin-tasks to enhance [kuai-cli](https://github.com/ckb-js/kuai/tree/develop/packages/cli), it includes basic steps to build a DApp, e.g. `build for various modes`, `develop\u0026deploy a contract`, `start devnet locally`, `run tests in a generalized manner`;\n3. export base class of ContractDeployer at https://github.com/ckb-js/kuai/blob/develop/packages/core/src/contract.ts for extension;\n4. define scripts metadata of devnet at https://github.com/ckb-js/kuai/blob/develop/packages/core/src/util/chain.ts, `dao`, `secp256k1_blake160`, and `secp256k1_blake160_multisig` are set by default;\n5. wrap [ckb-cli](https://github.com/nervosnetwork/ckb-cli) at https://github.com/ckb-js/kuai/blob/develop/packages/core/src/ckb-cli.ts to provide a universal development experience(DX);\n6. define default networks at https://github.com/ckb-js/kuai/blob/develop/packages/core/src/constants.ts;\n\n## [@kuai/docker-node](https://github.com/ckb-js/kuai/tree/develop/packages/docker-node)\n\nThe docker-node module provides a Docker image for running a Nervos CKB node in a containerized environment. It includes all the necessary dependencies and configuration files.\n\n### how to use this module\n\n```ts\nimport { CkbDockerNetwork } from '@ckb-js/kuai-docker-node'\n\nconst ckbDockerNetwork = new CkbDockerNetwork()\n\n// start ckb-node\nawait ckbDockerNetwork.start({\n  port: 3000, //\n  detached: true, //  Whether to run in the background\n  genesisAccountArgs: ['0x0000000000000000000000000000000000000000', '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'], // Initial account on the chain\n})\n\n// stop ckb-node\nawait ckbDockerNetwork.stop()\n```\n\n## [@kuai/io](https://github.com/ckb-js/kuai/tree/develop/packages/io)\n\nThe IO module defines interfaces of applications for various use cases. It includes functions to encode/decode input and output data.\n\nThe IO module contains several parts\n\n- cor is a chain of responsibility implementation with two methods, `use` and `dispatch`\n  using `use` adds middleware to `cor`, and when using `dispacth`, the incoming arguments are processed through each middleware\n\n- router\n  `Router` is a `cor` middle built into `kuai/io` that provides the ability to find and execute a specific middleware based on a path, and is often used to implement restful interfaces\n\n- adapter\n  Adapter is `kuai/io` built-in and other http framework compatible adapter, currently supports `koaAdapter`\n\n- listener\n  Listener is used to periodically rotate the data on the chain and return a `rxjs` Observable\n\n## how to use this module\n\n- cor\n\n```ts\nimport { CoR } from '@ckb-js/kuai-io'\n\nconst cor = new CoR()\n\nconst mockFn = console.log('mockFn')\nconst mockFn1 = console.log('mockFn1')\nconst mockFn2 = console.log('mockFn2')\n\ncor.use(async (_, next) =\u003e {\n  mockFn()\n  await next()\n})\n\ncor.use(async (ctx) =\u003e {\n  mockFn1()\n  ctx.ok('ok')\n})\n\ncor.use(async (_, next) =\u003e {\n  mockFn2()\n  await next()\n})\n\nawait cor.dispatch({})\n// print\n// mockFn\n// mockFn2\n```\n\n- router\n\n```ts\nimport { CoR, KuaiRouter } from '@ckb-js/kuai-io'\n\nconst cor = new CoR()\nconst kuaiRouter = new KuaiRouter()\nkuaiRouter.get('/', async (ctx) =\u003e {\n  ctx.ok('hello root')\n})\n\nkuaiRouter.get('/parent', async (ctx) =\u003e {\n  ctx.ok('hello parent')\n})\n\nkuaiRouter.get('/parent/children', async (ctx) =\u003e {\n  ctx.ok('hello children')\n})\n\ncor.use(kuaiRouter.middleware())\n\nconst rootResult = await cor.dispatch({ method: 'GET', path: '/' })\n// hello root\n\nconst parentResult = await cor.dispatch({ method: 'GET', path: '/parent' })\n// hello parent\n\nconst childrenResult = await cor.dispatch({ method: 'GET', path: '/parent/children' })\n// hello children\n```\n\n- adapter\n\n```ts\nimport { CoR, KuaiRouter } from '@ckb-js/kuai-io'\n\nconst koaServer = new Koa()\nkoaServer.use(koaBody())\n\nconst cor = new CoR()\nconst kuaiRouter = new KuaiRouter()\nkuaiRouter.get('/', async (ctx) =\u003e {\n  ctx.ok('hello root')\n})\n\nkuaiRouter.get('/parent', async (ctx) =\u003e {\n  ctx.ok('hello parent')\n})\n\nkuaiRouter.get('/parent/children', async (ctx) =\u003e {\n  ctx.ok('hello children')\n})\n\ncor.use(kuaiRouter.middleware())\nconst koaRouterAdapter = new KoaRouterAdapter(cor)\nkoaServer.use(koaRouterAdapter.routes())\nconst server = koaServer.listen(4004)\n\nconst res = await fetch('http://localhost:4004/', { method: 'GET' })\nconsole.log(res.status) // 200\nconst body = await res.text()\nconsole.log(body) // hello root\n\nconst res = await fetch('http://localhost:4004/parent', { method: 'GET' })\nconsole.log(res.status) // 200\nconst body = await res.text()\nconsole.log(body) // hello parent\n\nconst res = await fetch('http://localhost:4004/parent/children', { method: 'GET' })\nconsole.log(res.status) // 200\nconst body = await res.text()\nconsole.log(body) // hello children\n```\n\n## [@kuai/models](https://github.com/ckb-js/kuai/tree/develop/packages/models)\n\nThis codebase provides a set of data models for working with the Nervos CKB blockchain. It includes models for blocks, transactions, and cells, among others.\n\n### [resource-binding](https://github.com/ckb-js/kuai/tree/develop/packages/models/src/resource-binding)\n\nResource binding is a built-in module that serves the purpose of connecting on-chain data with off-chain data. Once the DApp is launched, resource binding synchronizes the data based on pre-defined rules. Whenever there is a change in on-chain data, resource binding promptly updates the off-chain model.\n\n### How to use the resource binding?\n\n#### Initiate the resource binding when bootstrap\n\nFirst, the resource binding module is a pluggable module that can be utilized by declaring it in the entry file. We provide a function which can help to initialize the resource binding as follow.\n\n```typescript\nimport {initiateResourceBindingManager } from '@ckb-js/kuai-models'\nimport { TipHeaderListener, NervosChainSource } from '@ckb-js/kuai-io'\n\nasync function bootstrap() {\n  ...\n  const dataSource = new NervosChainSource(kuaiEnv.config.ckbChain.rpcUrl)\n  initiateResourceBindingManager(dataSource, new TipHeaderListener(dataSource))\n  ...\n}\n```\n\nFor this, we provider the default `listener` and the default `data source` in `kuai-io` module, you can find the import as above.\n\n#### Define `store` with decorators\n\nWe provider several decorators to help to register the `store` to resource binding, here is one example to use these decorators as below.\n\n```typescript\nimport { ActorProvider, DataFilter, LockFilter, Omnilock } from '@ckb-js/kuai-models'\n\n@ActorProvider({ ref: { name: 'omnilock', path: `/:args/` } })\n@LockFilter()\n@DataFilter('0x')\n@Omnilock()\nclass OmnilockModel extends JSONStore\u003cRecord\u003cstring, never\u003e\u003e {\n  constructor() {\n    @Param('args') args: string,\n    ...\n  }\n\n  ...\n}\n```\n\n##### Register\n\n`kuai` should know which `store` should be connected to the chain, so the `store` should be registered to the `kuai`. We provider a decorator `ActorProcider` to achieve this. The `name` defined in `ref` is to register to the `Registry` with the `store`, and the parameters in `path` is used to inject to the `constructor` as defined in `Param` decorator.\n\n##### Lock\n\nAs in nervos network, each cell has its own `lock script`, so the `lock script` should be defined in `store`. We provide two default lock decorators, the `Omnilock` and the `Secp256k1Lock`, to use to define the most used `lock script`s in nervos network, and if you are using other `lock script`s in system, the `DefaultScript` could be used. Also we provide the `Lock` decorator for you to define your custom `lock script`.\n\nThe Lock decorators we provided as below.\n\n- `Lock`\n- `DefaultScript`\n- `Omnilock`\n- `Secp256k1Lock`\n\n##### Filter\n\n`kuai` should know which cell should be connected to the `store`, filter data of them from chain. We provide several decorator for you to do this.\n\n- `LockFilter`: Filter the lock to equal to the `lockscript` of `store` defined.\n- `DataFilter`: It has one parameter means data, filter the data in cell to equal to the parameter.\n- `DataPrefixFilter`: It has one parameter means data prefix, filter the data to start with the parameter.\n\n### [store](https://github.com/ckb-js/kuai/tree/develop/packages/models/src/store)\n\nThe store extends from Actor, uses to subscribe data on the ckb chain and transform it to locally structured data, then change them and submit to the ckb chain.\n\nSupported storage location: data, witness, lock.args, type.args.\n\nSupported transform methods: JSON and molecule\n\nSupported types for JSON Store: string, array, object, reference[ packages/models/src/store/json-storage.ts](https://github.com/ckb-js/kuai/blob/5586346f21b677dcc3ddc4d24948a17d6ea9cb33/packages/models/src/store/json-storage.ts#L5-L11)\n\nSupported types for molecule store: string, number, [BI](https://github.com/ckb-js/lumos/tree/develop/packages/bi), array, object, Supported molecule types: array, struct, vec, table, option, union. reference [molecule-storage](https://github.com/ckb-js/kuai/blob/4558a98f7188769830e62e14ecbbce9a2d8dbdde/packages/models/src/store/molecule-storage.ts#L55-L62C1)\n\n### How to use this module\n\nDefined JSONStore and MoleculeStore to handle JSON data or molecule data.\n\n- Create a new `Store`:\n\n  - For JSON with `JSONStore`:\n\n  ```typescript\n  type Data = {\n    field1: string\n    field2: string\n    field3: string\n  }\n  export class NewJSONStore extends JSONStore\u003c{ data: Data }\u003e {\n    constructor(\n      _schemaOption?: { data: true },\n      params?: {\n        states?: Record\u003cOutPointString, { data: Data }\u003e\n        chainData?: Record\u003cOutPointString, UpdateStorageValue\u003e\n        cellPattern?: CellPattern\n        schemaPattern?: SchemaPattern\n      },\n    ) {\n      super({ data: true }, params)\n    }\n  }\n  ```\n\n  - For molecule with `MoleculeStore`:\n\n  ```typescript\n  const data = {\n    type: 'table',\n    value: { field1: 'string', field2: 'Uint8' },\n  } as const\n  type Data = typeof data\n\n  export class NewMoleculeStore extends MoleculeStore\u003c{ data: Data }\u003e {\n    constructor(\n      _schemaOption?: { data: true },\n      params?: {\n        states?: Record\u003cOutPointString, GetStorageStruct\u003cGetMoleculeStorageStruct\u003c{ data: Data }\u003e\u003e\u003e\n        chainData?: Record\u003cOutPointString, UpdateStorageValue\u003e\n        cellPattern?: CellPattern\n        schemaPattern?: SchemaPattern\n      },\n    ) {\n      super(\n        { data: true },\n        {\n          ...params,\n          options: { data },\n        },\n      )\n    }\n  }\n  ```\n\n- Use new `Store` to transform locally structured data to chain data\n\n  - New JSONStore\n    ```ts\n    new JSONStore.initOnChain({\n      data: {\n        field1: 'a',\n        field2: 'a',\n        field3: 'b',\n      },\n    })\n    ```\n\n  ````\n   - New MoleculeStore\n    ```typescript\n       new MoleculeStore.initOnChain({\n             data: {\n                 field1: 'a',\n                 field2: 10\n             }\n       })\n  ````\n\n- Register with resource binding\n\n  [TODO]\n\n- Update the data\n  ```typescript\n  // Update from the root\n  store.set(['data'], { field1: 'a1', field2: 'a1', field3: 'b1' })\n  // update a field\n  store.set(['data', 'field1'], 'a1')\n  ```\n- Get the data\n\n  ```typescript\n  // get from the root\n  store.get(['data'])\n  // get a filed value with key path\n  store.set(['data', 'field1'])\n  ```\n\n# Tutorials \u0026 Demos\n\n- [MVP DApp](./packages/samples/mvp-dapp)\n  This is a sample Minimum Viable Product (MVP) decentralized application(dAppp) built using Kuai framework. It aims to demonstrate how easy and fast it is to build a simple dApp specific to cell model, and showcase the abstract ability to easily read and write data to cells.\n\n- [Development Guide](./docs/tutorials/mvp-dapp.md)\n  This is a comprehensive guide that lists the fundamental steps to build the [MVP DApp](./packages/samples/mvp-dapp);\n\n# Quick start\n\n## Environment\n\n    node \u003e= 18\n\n## Kuai Installation\n\nFirst, install `kuai` globally by `npm link`:\n\n```bash\n$ git clone git@github.com:ckb-js/kuai.git\n\n$ cd kuai\n\n$ npm install\n\n$ npm run build\n\n$ cd packages/cli\n\n$ npm link\n```\n\n#### Create a template project using the command.\n\n```bash\nkuai init\n```\n\n#### Running\n\n`kuai` has `dev` and `prod` modes\n\ndev\n\n```bash\nnpm run dev\n```\n\nprod\n\n```bash\nnpm run build\nnpm run start:prod\n```\n\n#### Others commands\n\nrun test\n\n```bash\nnpm run test\n```\n\nbuild docs\n\nThe docs is build by [typedoc](https://typedoc.org/), `typedoc.json` is the build configuration.\n\n```bash\nnpm run doc\n```\n\n# Kuai Roadmap\n\n    - M1 ~ M2\n      - [x] Construct a build system similar to https://nx.dev/, only for project structure, basic tasks, and plugins\n      - [x] Design storage paradigm\n      - [ ] Design action paradigm\n      - [ ] Design workflow with base contracts/scripts\n    - M3 ~ M4\n      - [ ] Implements SDK following the designed paradigm and workflow with base contracts/scripts\n      - [x] Design generally used tasks and plugins\n      - [ ] Cycle reporter\n      - [ ] Script sizer\n      - [ ] Test-coverage\n      - [x] Document\n      - [ ] Debugger remover\n      - [ ] Typechain: https://github.com/dethcrypto/TypeChain/\n      - [ ] Storage layout: https://www.npmjs.com/package/hardhat-storage-layout, when to use on-chain/off-chain data\n      - [x] Design local network debug/test/deploy tools\n    - M5\n      - [x] Implement tasks/plugins\n      - [x] Implement local network\n      - [x] Implement debug/test/deploy tools\n    - M6\n      - [x] Use the project to deliver a simple .bit dapp\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fckb-js%2Fkuai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fckb-js%2Fkuai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fckb-js%2Fkuai/lists"}