Skip to content

Commit

Permalink
feat: support multiple templates for init cmd (ckb-devrel#22)
Browse files Browse the repository at this point in the history
* feat: support multiple templates for init cmd

* chore: fmt

* fix: ts-config

* fix: rm package-lock

* fix: update yarn.lock

* chore: ignore .vscode

* refactor: init cmd with common files and different templates

* fix: genKey code hash

* refactor: rm the update-config-json.ts on the template

* fix: templates typo in package.json

* docs: update development and readme
  • Loading branch information
RetricSu authored Feb 29, 2024
1 parent ca6e240 commit 274fb21
Show file tree
Hide file tree
Showing 30 changed files with 3,289 additions and 388 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ ckb/devnet/data/
.DS_Store
data/
dist/
.vscode
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,23 @@ npm install -g @offckb/cli

```sh
offckb node // start the devnet of CKB
offckb init <project-name> // init a typescript boilerplate with lumos to get started with to build CKB DAPP,think 'hardhat init'
offckb init <project-name> // init a CKB Dapp typescript boilerplate with multiple templates
offckb accounts // list 20 accounts info with prefund CKB tokens
offckb list-hashes // list scripts hashes, equals `ckb list-hashes`
offckb list-hashes // list built-in scripts hashes, equals `ckb list-hashes`
```

### Get started

```sh
offckb init my-awesome-ckb-dapp

## select the template for your boilerplate
? Select a dapp template (Use arrow keys)
❯ Transfer CKB
Issue Coin With XUDT scripts
a simple dapp to check CKB balance and transfer CKB from address to address

## start running
cd my-awesome-ckb-dapp
yarn && yarn start

Expand Down Expand Up @@ -62,9 +70,4 @@ detail informations about each account are recorded in the `account/account.json

## Development

update built-in scripts:

update submodule inside `ckb` and then run
```sh
make all
```
check [development doc](/docs/develop.md)
2 changes: 1 addition & 1 deletion ckb/devnet/specs/dev.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name = "ckb_dev"
name = "offckb"

[genesis]
version = 0
Expand Down
26 changes: 26 additions & 0 deletions docs/develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## Development

### Update built-in scripts

update submodule inside `ckb` and then run
```sh
make all
```

### Update chain config

edit the things in `ckb/devnet`

whenever the devnet genesis block's tx hashes changed, you need to update the devnet lumos config file, which is `templates/config.json`.

first start the node:

```sh
yarn start node
```

second, generate lumos config file:

```sh
NODE_ENV=development yarn start build-lumos-config
```
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"dist",
"account",
"ckb",
"template"
"templates"
],
"private": false,
"publishConfig": {
Expand All @@ -26,17 +26,17 @@
"build": "tsc",
"start": "ts-node-dev --transpile-only src/cli.ts",
"clean": "rm -rf ./target",
"lint": "eslint \"{src,template}/**/*.ts\" \"{src,template}/**/*.tsx\" --ignore-pattern 'node_modules/'",
"lint:fix": "eslint \"{src,template}/**/*.ts\" \"{src,template}/**/*.tsx\" --ignore-pattern 'node_modules/' --fix",
"fmt": "prettier --write '{src,template,account}/**/*.{js,jsx,ts,tsx,md,json}'"
"lint": "eslint \"{src,templates}/**/*.ts\" \"{src,templates}/**/*.tsx\" --ignore-pattern 'node_modules/'",
"lint:fix": "eslint \"{src,templates}/**/*.ts\" \"{src,templates}/**/*.tsx\" --ignore-pattern 'node_modules/' --fix",
"fmt": "prettier --write '{src,templates,account}/**/*.{js,jsx,ts,tsx,md,json}'"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"{src,template,account}/**/*.{js,jsx,ts,tsx,md,json}": "prettier --ignore-unknown --write"
"{src,templates,account}/**/*.{js,jsx,ts,tsx,md,json}": "prettier --ignore-unknown --write"
},
"eslintConfig": {
"extends": [
Expand All @@ -59,6 +59,7 @@
},
"dependencies": {
"@ckb-lumos/lumos": "0.21.1",
"@inquirer/prompts": "^4.1.0",
"adm-zip": "^0.5.10",
"axios": "^1.6.7",
"child_process": "^1.0.2",
Expand Down
2 changes: 1 addition & 1 deletion src/cfg/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const currentExecPath = process.cwd();
export const packageSrcPath = path.dirname(require.main!.filename);
export const packageRootPath = path.resolve(packageSrcPath, '../');

export const dappTemplatePath = path.resolve(packageRootPath, './template');
export const dappTemplatePath = path.resolve(packageRootPath, './templates');
export const targetEnvironmentPath = path.resolve(packageRootPath, './target');

export const devnetSourcePath = path.resolve(packageRootPath, './ckb/devnet');
Expand Down
21 changes: 21 additions & 0 deletions src/cfg/select.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import select from '@inquirer/select';

export async function selectTemplate() {
const answer = await select({
message: 'Select a dapp template',
choices: [
{
name: 'Transfer CKB',
value: 'transfer',
description: 'a simple dapp to check CKB balance and transfer CKB from address to address',
},
{
name: 'Issue Coin With XUDT scripts',
value: 'xudt',
description: 'a simple dapp to issue your own token with XUDT scripts',
},
],
});

return answer;
}
11 changes: 6 additions & 5 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { initChainIfNeeded } from './cmd/init-chain';
import { buildLumosConfig } from './cmd/build-lumos-config';
import { init } from './cmd/init';
import { accounts } from './cmd/accounts';
import { selectTemplate } from './cfg/select';
const version = require('../package.json').version;

const program = new Command();
Expand All @@ -18,12 +19,12 @@ program
.version(version);

program
.command('init')
.command('init [string]')
.description('init dapp project with lumos')
.argument('<string>', 'name of the dapp')
.action((str) => {
const name = str ?? 'offckb-dapp';
return init(name);
.action(async (str) => {
const name = str ?? 'my-awesome-ckb-dapp';
const template = await selectTemplate();
return init(name, template);
});

program.command('node').description('Use the CKB to start devnet').action(node);
Expand Down
154 changes: 82 additions & 72 deletions src/cmd/build-lumos-config.ts
Original file line number Diff line number Diff line change
@@ -1,79 +1,89 @@
import fs from 'fs';
import path from 'path';
import { dappTemplatePath } from '../cfg/const';
import { RPC } from '@ckb-lumos/lumos';

const genesisTxHash = '0x920bb4250dc6216c08ee0713f86b3fcb01bf444027b08b7d92db0ed1c0fb9214';
const depGroupTxHash = '0x37f2b7799b199491f4732c572c086afdace0bf92992faf0b90bae44cdd119f9e';

export const devnetConfig = {
PREFIX: 'ckt',
SCRIPTS: {
SECP256K1_BLAKE160: {
CODE_HASH: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
HASH_TYPE: 'type',
TX_HASH: depGroupTxHash,
INDEX: '0x0',
DEP_TYPE: 'depGroup',
SHORT_ID: 1,
},
SECP256K1_BLAKE160_MULTISIG: {
CODE_HASH: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8',
HASH_TYPE: 'type',
TX_HASH: depGroupTxHash,
INDEX: '0x1',
DEP_TYPE: 'depGroup',
},
DAO: {
CODE_HASH: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',
HASH_TYPE: 'type',
TX_HASH: genesisTxHash,
INDEX: '0x2',
DEP_TYPE: 'code',
SHORT_ID: 2,
},
SUDT: {
CODE_HASH: '0x6283a479a3cf5d4276cd93594de9f1827ab9b55c7b05b3d28e4c2e0a696cfefd',
HASH_TYPE: 'type',
TX_HASH: genesisTxHash,
INDEX: '0x5',
DEP_TYPE: 'code',
},
XUDT: {
CODE_HASH: '0x1a1e4fef34f5982906f745b048fe7b1089647e82346074e0f32c2ece26cf6b1e',
HASH_TYPE: 'type',
TX_HASH: genesisTxHash,
INDEX: '0x6',
DEP_TYPE: 'code',
export function devnetLumosConfigTemplate(cellBaseTxHashInGenesisBlock: string, secondTxHashInGenesisBlock: string) {
const devnetConfig = {
PREFIX: 'ckt',
SCRIPTS: {
SECP256K1_BLAKE160: {
CODE_HASH: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
HASH_TYPE: 'type',
TX_HASH: secondTxHashInGenesisBlock,
INDEX: '0x0',
DEP_TYPE: 'depGroup',
SHORT_ID: 1,
},
SECP256K1_BLAKE160_MULTISIG: {
CODE_HASH: '0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8',
HASH_TYPE: 'type',
TX_HASH: secondTxHashInGenesisBlock,
INDEX: '0x1',
DEP_TYPE: 'depGroup',
},
DAO: {
CODE_HASH: '0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e',
HASH_TYPE: 'type',
TX_HASH: cellBaseTxHashInGenesisBlock,
INDEX: '0x2',
DEP_TYPE: 'code',
SHORT_ID: 2,
},
SUDT: {
CODE_HASH: '0x6283a479a3cf5d4276cd93594de9f1827ab9b55c7b05b3d28e4c2e0a696cfefd',
HASH_TYPE: 'type',
TX_HASH: cellBaseTxHashInGenesisBlock,
INDEX: '0x5',
DEP_TYPE: 'code',
},
XUDT: {
CODE_HASH: '0x1a1e4fef34f5982906f745b048fe7b1089647e82346074e0f32c2ece26cf6b1e',
HASH_TYPE: 'type',
TX_HASH: cellBaseTxHashInGenesisBlock,
INDEX: '0x6',
DEP_TYPE: 'code',
},
OMNILOCK: {
CODE_HASH: '0x9c6933d977360f115a3e9cd5a2e0e475853681b80d775d93ad0f8969da343e56',
HASH_TYPE: 'type',
TX_HASH: cellBaseTxHashInGenesisBlock,
INDEX: '0x7',
DEP_TYPE: 'code',
},
ANYONE_CAN_PAY: {
CODE_HASH: '0xe09352af0066f3162287763ce4ddba9af6bfaeab198dc7ab37f8c71c9e68bb5b',
HASH_TYPE: 'type',
TX_HASH: cellBaseTxHashInGenesisBlock,
INDEX: '0x8',
DEP_TYPE: 'code',
},
ALWAYS_SUCCESS: {
CODE_HASH: '0xbb4469004225b39e983929db71fe2253cba1d49a76223e9e1d212cdca1f79f28',
HASH_TYPE: 'type',
TX_HASH: cellBaseTxHashInGenesisBlock,
INDEX: '0x9',
DEP_TYPE: 'code',
},
},
OMNILOCK: {
CODE_HASH: '0x9c6933d977360f115a3e9cd5a2e0e475853681b80d775d93ad0f8969da343e56',
HASH_TYPE: 'type',
TX_HASH: genesisTxHash,
INDEX: '0x7',
DEP_TYPE: 'code',
},
ANYONE_CAN_PAY: {
CODE_HASH: '0xe09352af0066f3162287763ce4ddba9af6bfaeab198dc7ab37f8c71c9e68bb5b',
HASH_TYPE: 'type',
TX_HASH: genesisTxHash,
INDEX: '0x8',
DEP_TYPE: 'code',
},
ALWAYS_SUCCESS: {
CODE_HASH: '0xbb4469004225b39e983929db71fe2253cba1d49a76223e9e1d212cdca1f79f28',
HASH_TYPE: 'type',
TX_HASH: genesisTxHash,
INDEX: '0x9',
DEP_TYPE: 'code',
},
},
};
};
return devnetConfig;
}

export function buildLumosConfig() {
const filePath = path.resolve(dappTemplatePath, 'config.json');
fs.writeFile(filePath, JSON.stringify(devnetConfig, null, 2), 'utf8', (err) => {
if (err) {
return console.error('Error writing file:', err);
}
});
export async function buildLumosConfig() {
const rpcUrl = 'http://127.0.0.1:8114';
const rpc = new RPC(rpcUrl);
const chainInfo = await rpc.getBlockchainInfo();
const genesisBlock = await rpc.getBlockByNumber('0x0');
const cellBaseTxHashInGenesisBlock = genesisBlock.transactions[0].hash;
const secondTxHashInGenesisBlock = genesisBlock.transactions[1].hash;
if (chainInfo.chain === 'offckb') {
const config = devnetLumosConfigTemplate(cellBaseTxHashInGenesisBlock, secondTxHashInGenesisBlock);
const filePath = path.resolve(dappTemplatePath, 'config.json');
fs.writeFile(filePath, JSON.stringify(config, null, 2), 'utf8', (err) => {
if (err) {
return console.error('Error writing file:', err);
}
});
}
}
12 changes: 4 additions & 8 deletions src/cmd/genkey.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import * as fs from 'fs';
import * as path from 'path';
import { accountTargetDir } from '../cfg/const';
import { Address, HashType, HexString, Script, config, hd, helpers } from '@ckb-lumos/lumos';
import { Address, HashType, HexString, Script, hd, helpers } from '@ckb-lumos/lumos';
import * as readline from 'readline';
import { devnetConfig } from './build-lumos-config';

interface Account {
privkey: HexString;
Expand Down Expand Up @@ -73,15 +72,12 @@ export async function buildAccounts() {
export function genAccount(privkey: HexString): Account {
const pubkey = hd.key.privateToPublic(privkey);
const args = hd.key.publicKeyToBlake160(pubkey);
const template = devnetConfig.SCRIPTS['SECP256K1_BLAKE160']!;
const lockScript: Script = {
codeHash: template.CODE_HASH,
hashType: template.HASH_TYPE as HashType,
codeHash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
hashType: 'type' as HashType,
args: args,
};
const address = helpers.encodeToAddress(lockScript, {
config: devnetConfig as config.Config,
});
const address = helpers.encodeToAddress(lockScript);
return {
privkey,
pubkey,
Expand Down
16 changes: 12 additions & 4 deletions src/cmd/init.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { currentExecPath, dappTemplatePath } from '../cfg/const';
import path from 'path';
import { copyFolderSync } from '../util';
import { copyFileSync, copyFolderSync } from '../util';

export function init(name: string) {
export function init(name: string, template: string) {
const targetPath = path.resolve(currentExecPath, name);
copyFolderSync(dappTemplatePath, targetPath);
console.log(`init CKB dapp project with lumos: ${targetPath}`);
const sourcePath = path.resolve(dappTemplatePath, template);
copyFolderSync(sourcePath, targetPath);

// add some common code files
const ckbDotTs = path.resolve(dappTemplatePath, 'ckb.ts');
const configJson = path.resolve(dappTemplatePath, 'config.json');
copyFileSync(ckbDotTs, targetPath);
copyFileSync(configJson, targetPath);

console.log(`init CKB dapp project: ${targetPath}`);
}
Loading

0 comments on commit 274fb21

Please sign in to comment.