Skip to content

Commit

Permalink
feat(node): abstract the ckb node interface (#319)
Browse files Browse the repository at this point in the history
Co-authored-by: Chen Yu <keithwhisper@gmail.com>
  • Loading branch information
Daryl-L and Keith-CY authored Jul 12, 2023
1 parent 7701193 commit 386fe3e
Show file tree
Hide file tree
Showing 22 changed files with 725 additions and 354 deletions.
7 changes: 4 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

247 changes: 174 additions & 73 deletions packages/cli/__tests__/index.ts
Original file line number Diff line number Diff line change
@@ -1,101 +1,202 @@
import { describe, expect, test, beforeAll, afterAll } from '@jest/globals'
import { execSync } from 'node:child_process'
import { execSync, exec } from 'node:child_process'
/* eslint-disable-next-line @typescript-eslint/no-var-requires */
const { scheduler } = require('node:timers/promises')
const CONFIG_PATH = './__tests__/__fixtures__/kuai-config-case/kuai.config.ts'

describe('kuai cli', () => {
beforeAll(async () => {
beforeAll(() => {
execSync('npm link')
execSync(
'npx kuai node --port 9002 --detached --genesisArgs 0x0000000000000000000000000000000000000000 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
)
await scheduler.wait(10000)
}, 50000)
})

afterAll(() => {
execSync('npx kuai node stop')
execSync('npm unlink -g @ckb-js/kuai-cli')
})

test('ckb node listening port', async () => {
const res = await fetch('http://localhost:9002/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
id: 0,
jsonrpc: '2.0',
method: 'get_tip_header',
params: [],
}),
})

expect(res.status).toEqual(200)

const data = await res.json()
expect(typeof data.result.number).toEqual('string')
expect(typeof data.result.hash).toEqual('string')
})
describe('docker node', () => {
beforeAll(async () => {
execSync(
'npx kuai node --port 9002 --detached --genesisArgs 0x0000000000000000000000000000000000000000 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
)
await scheduler.wait(10000)
}, 50000)

afterAll(() => {
execSync('npx kuai node stop')
})

test('ckb node accept genesis accounts', async () => {
const res = await fetch('http://localhost:9002/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify([
{
test('ckb node listening port', async () => {
const res = await fetch('http://localhost:9002/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
id: 0,
jsonrpc: '2.0',
method: 'get_cells',
params: [
{
script: {
code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
hash_type: 'type',
args: '0x0000000000000000000000000000000000000000',
method: 'get_tip_header',
params: [],
}),
})

expect(res.status).toEqual(200)

const data = await res.json()
expect(typeof data.result.number).toEqual('string')
expect(typeof data.result.hash).toEqual('string')
})

test('ckb node accept genesis accounts', async () => {
const res = await fetch('http://localhost:9002/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify([
{
id: 0,
jsonrpc: '2.0',
method: 'get_cells',
params: [
{
script: {
code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
hash_type: 'type',
args: '0x0000000000000000000000000000000000000000',
},
script_type: 'lock',
},
script_type: 'lock',
},
'asc',
'0x64',
],
'asc',
'0x64',
],
},
{
id: 0,
jsonrpc: '2.0',
method: 'get_cells',
params: [
{
script: {
code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
hash_type: 'type',
args: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
},
script_type: 'lock',
},
'asc',
'0x64',
],
},
]),
})

expect(res.status).toEqual(200)

const rpcResponses = await res.json()

expect(rpcResponses.length).toEqual(2)

expect(rpcResponses[0].result.objects.length).toEqual(1)
expect(rpcResponses[0].result.objects.length).toEqual(1)
expect(rpcResponses[0].result.objects[0].output.capacity).toEqual('0x1bc16d674ec80000')

expect(rpcResponses[1].result.objects.length).toEqual(1)
expect(rpcResponses[1].result.objects.length).toEqual(1)
expect(rpcResponses[1].result.objects[0].output.capacity).toEqual('0x1bc16d674ec80000')
})
})

describe('bin node', () => {
beforeAll(async () => {
exec(
'npx kuai --network bin-node node --detached --genesisArgs 0x0000000000000000000000000000000000000001 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef',
)
await scheduler.wait(10000)
}, 50000)

afterAll(() => {
execSync('npx kuai --network bin-node node stop --clear')
})

test('ckb node listening port', async () => {
const res = await fetch('http://127.0.0.1:8114/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
{
body: JSON.stringify({
id: 0,
jsonrpc: '2.0',
method: 'get_cells',
params: [
{
script: {
code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
hash_type: 'type',
args: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
},
script_type: 'lock',
},
'asc',
'0x64',
],
},
]),
method: 'get_tip_header',
params: [],
}),
})

expect(res.status).toEqual(200)

const data = await res.json()
expect(typeof data.result.number).toEqual('string')
expect(typeof data.result.hash).toEqual('string')
})

expect(res.status).toEqual(200)
test('ckb node accept genesis accounts', async () => {
const res = await fetch('http://127.0.0.1:8114/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify([
{
id: 0,
jsonrpc: '2.0',
method: 'get_cells',
params: [
{
script: {
code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
hash_type: 'type',
args: '0x0000000000000000000000000000000000000001',
},
script_type: 'lock',
},
'asc',
'0x64',
],
},
{
id: 0,
jsonrpc: '2.0',
method: 'get_cells',
params: [
{
script: {
code_hash: '0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8',
hash_type: 'type',
args: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef',
},
script_type: 'lock',
},
'asc',
'0x64',
],
},
]),
})

expect(res.status).toEqual(200)

const rpcResponses = await res.json()
const rpcResponses = await res.json()

expect(rpcResponses.length).toEqual(2)
expect(rpcResponses.length).toEqual(2)

expect(rpcResponses[0].result.objects.length).toEqual(1)
expect(rpcResponses[0].result.objects.length).toEqual(1)
expect(rpcResponses[0].result.objects[0].output.capacity).toEqual('0x1bc16d674ec80000')
expect(rpcResponses[0].result.objects.length).toEqual(1)
expect(rpcResponses[0].result.objects.length).toEqual(1)
expect(rpcResponses[0].result.objects[0].output.capacity).toEqual('0x1bc16d674ec80000')

expect(rpcResponses[1].result.objects.length).toEqual(1)
expect(rpcResponses[1].result.objects.length).toEqual(1)
expect(rpcResponses[1].result.objects[0].output.capacity).toEqual('0x1bc16d674ec80000')
expect(rpcResponses[1].result.objects.length).toEqual(1)
expect(rpcResponses[1].result.objects.length).toEqual(1)
expect(rpcResponses[1].result.objects[0].output.capacity).toEqual('0x1bc16d674ec80000')
})
})

test('Unsupported network', async () => {
Expand Down
3 changes: 2 additions & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"test": "jest"
},
"dependencies": {
"@ckb-lumos/lumos": "0.19.0"
"@ckb-lumos/lumos": "0.19.0",
"undici": "5.22.1"
}
}
3 changes: 3 additions & 0 deletions packages/common/src/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import envPaths from 'env-paths'

export const PATH = envPaths('kuai')
1 change: 1 addition & 0 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './errors'
export * from './util'
export * from './constant'
27 changes: 27 additions & 0 deletions packages/common/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import type { TransactionWithStatus } from '@ckb-lumos/base'
import type { RPC } from '@ckb-lumos/lumos'
import type { URL, UrlObject } from 'node:url'
import { scheduler } from 'node:timers/promises'
import path from 'node:path'
import fs from 'node:fs'
import { PATH } from './constant'
import undici from 'undici'
import { pipeline } from 'node:stream/promises'

const MAX_REDIRECTS = 5

export const waitUntilCommitted = async (rpc: RPC, txHash: string, timeout = 120): Promise<TransactionWithStatus> => {
let waitTime = 0
Expand All @@ -21,3 +29,22 @@ export const waitUntilCommitted = async (rpc: RPC, txHash: string, timeout = 120
await scheduler.wait(1000)
}
}

export const createPath = (path: string) => {
if (!fs.existsSync(path)) {
fs.mkdirSync(path, { recursive: true })
}
return path
}

export const cachePath = (...paths: string[]) => createPath(path.resolve(PATH.cache, ...paths))

export const configPath = (...paths: string[]) => createPath(path.resolve(PATH.config, ...paths))

export const downloadFile = async (url: string | URL | UrlObject, filePath: string) =>
await pipeline(
await undici.request(url, { method: 'GET', maxRedirections: MAX_REDIRECTS }).then((res) => res.body),
fs.createWriteStream(filePath),
).catch((e) => {
console.error('Error downloading file:', e)
})
Loading

0 comments on commit 386fe3e

Please sign in to comment.