Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ jobs:
- name: Run tests
run: pnpm test

- name: Build project
run: pnpm build

- name: Integration test - Start node and test RPC
shell: bash
run: bash scripts/starting-node-test.sh
Expand Down
41 changes: 32 additions & 9 deletions scripts/create-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,25 @@ fi
# Install offckb since create test need it
echo ""
echo "Installing offckb CLI tool..."
npm install -g @offckb/cli
echo "✓ offckb installed"
# Use the local build but install it globally for better compatibility
OFFCKB_CLI_PATH="$(pwd)/build/index.js"
if [ ! -f "$OFFCKB_CLI_PATH" ]; then
echo "✗ Local build not found at $OFFCKB_CLI_PATH"
echo "Please run 'pnpm build' first"
exit 1
fi

# Pack and install the local build globally
echo "Packing local build..."
PACKAGE_FILE=$(pnpm pack --pack-destination /tmp 2>&1 | tail -1)
if [ ! -f "$PACKAGE_FILE" ]; then
echo "✗ Failed to pack local build. Output: $PACKAGE_FILE"
exit 1
fi
echo "Installing local package globally: $PACKAGE_FILE"
npm install -g "$PACKAGE_FILE"

echo "✓ Local offckb CLI installed globally"

# Create test project with non-interactive mode
echo ""
Expand All @@ -82,12 +99,13 @@ echo "Creating test project with offckb create..."
# - --no-install: Skip automatic dependency installation (we'll do it explicitly)
# - -l typescript: Use TypeScript language
# - -c hello-world: Name the first contract 'hello-world'
pnpm start create "$TEST_PROJECT_DIR" \
CONTRACT_NAME="hello-world"
offckb create "$TEST_PROJECT_DIR" \
--no-interactive \
--no-git \
--no-install \
-l typescript \
-c hello-world
-c "$CONTRACT_NAME"

# Check if project was created
if [ ! -d "$TEST_PROJECT_DIR" ]; then
Expand Down Expand Up @@ -162,10 +180,10 @@ echo "✓ Project built successfully"
echo ""
echo "Deploying the project..."
cd "$TEST_PROJECT_DIR"
pnpm run deploy
pnpm run deploy -- --network devnet --yes

# Check if deployment artifacts were created
if [ ! -f "$TEST_PROJECT_DIR/deployment/devnet.json" ]; then
if [ ! -f "$TEST_PROJECT_DIR/deployment/scripts.json" ]; then
echo "✗ Deploy failed - deployment record not created"
exit 1
fi
Expand All @@ -175,10 +193,15 @@ echo "✓ Project deployed successfully"
# Verify deployment record contains expected data
echo ""
echo "Verifying deployment record..."
DEPLOY_RECORD=$(cat "$TEST_PROJECT_DIR/deployment/devnet.json")
DEPLOY_RECORD=$(cat "$TEST_PROJECT_DIR/deployment/scripts.json")

if ! echo "$DEPLOY_RECORD" | grep -q '"devnet"'; then
echo "✗ Deployment record is missing devnet section"
exit 1
fi

if ! echo "$DEPLOY_RECORD" | grep -q '"contractName"'; then
echo "✗ Deployment record is missing contractName"
if ! echo "$DEPLOY_RECORD" | grep -q "\"${CONTRACT_NAME}.bc\""; then
echo "✗ Deployment record is missing ${CONTRACT_NAME}.bc contract"
exit 1
fi

Expand Down
9 changes: 6 additions & 3 deletions src/templates/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ export const PACKAGE_JSON_CONFIG: PackageJsonConfig = {
'build:contract:debug': 'node scripts/build-contract.js --debug',
build: 'node scripts/build-all.js',
'build:debug': 'node scripts/build-all.js --debug',
deploy: 'node scripts/build-all.js && node scripts/deploy.js',
'deploy:debug': 'node scripts/build-all.js --debug && node scripts/deploy.js',
test: 'node scripts/build-all.js && jest',
deploy: 'node scripts/deploy.js',
'deploy:build': 'run-s build deploy',
'deploy:debug': 'run-s build:debug deploy',
test: 'run-s build test:only',
'test:only': 'jest',
'add-contract': 'node scripts/add-contract.js',
clean: 'rimraf dist',
format: 'prettier --write .',
Expand All @@ -36,6 +38,7 @@ export const PACKAGE_JSON_CONFIG: PackageJsonConfig = {
'@ckb-ccc/core': '1.12.2', // lock to version compatible with ckb-testtool
esbuild: '~0.25.8',
jest: '~29.7.0',
'npm-run-all': '^4.1.5',
prettier: '^3.5.3',
rimraf: '^6.0.1',
},
Expand Down
3 changes: 2 additions & 1 deletion templates/v4/base-template/scripts/build-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ function buildAllContracts(isDebug = false) {
for (const contractName of contracts) {
console.log(`\n📦 Building contract: ${contractName}`);
try {
execSync(`node scripts/build-contract.js ${contractName} ${isDebug ? '--debug' : ''}`, { stdio: 'inherit' });
const buildScriptPath = path.join('scripts', 'build-contract.js');
execSync(`node "${buildScriptPath}" ${contractName} ${isDebug ? '--debug' : ''}`, { stdio: 'inherit' });
console.log(`✅ Successfully built: ${contractName} with ${isDebug ? 'debug' : 'release'} version`);
} catch (error) {
console.error(`❌ Failed to build: ${contractName}`);
Expand Down
18 changes: 11 additions & 7 deletions templates/v4/base-template/scripts/build-contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ function buildContract(contractName, isDebug = false) {
// Step 1: TypeScript type checking (if TypeScript file) - temporarily disabled due to @ckb-ccc/core version conflicts
// if (srcFile.endsWith('.ts')) {
// console.log(' 🔍 Type checking...');
// execSync(`./node_modules/.bin/tsc --noEmit --project .`, { stdio: 'pipe' });
// const tscPath = path.join('node_modules', '.bin', 'tsc');
// execSync(`"${tscPath}" --noEmit --project .`, { stdio: 'pipe' });
// }

// Step 2: Bundle with esbuild
Expand All @@ -60,28 +61,31 @@ function buildContract(contractName, isDebug = false) {
'--loader:.map=json',
];
const releaseParams = ['--minify'];
const esbuildPath = path.join('node_modules', '.bin', 'esbuild');
const esbuildCmd = [
'./node_modules/.bin/esbuild',
`"${esbuildPath}"`,
'--platform=neutral',
'--bundle',
'--external:@ckb-js-std/bindings',
'--target=es2022',
...(isDebug ? debugParams : releaseParams),
srcFile,
`--outfile=${outputJsFile}`,
`"${srcFile}"`,
`--outfile="${outputJsFile}"`,
].join(' ');

execSync(esbuildCmd, { stdio: 'pipe' });

// Step 3: Compile to bytecode with ckb-debugger
console.log(' 🔧 Compiling to bytecode...');
const ckbJsVmPath = path.join('node_modules', 'ckb-testtool', 'src', 'unittest', 'defaultScript', 'ckb-js-vm');
const debuggerCmd = [
'ckb-debugger',
`--read-file ${outputJsFile}`,
'--bin node_modules/ckb-testtool/src/unittest/defaultScript/ckb-js-vm',
`--read-file "${outputJsFile}"`,
'--bin',
`"${ckbJsVmPath}"`,
'--',
'-c',
outputBcFile,
`"${outputBcFile}"`,
].join(' ');

execSync(debuggerCmd, { stdio: 'pipe' });
Expand Down
46 changes: 36 additions & 10 deletions templates/v4/base-template/scripts/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,34 @@
* - --network: Network to deploy to (devnet, testnet, mainnet) - defaults to devnet
* - --privkey: Private key for deployment - defaults to offckb's deployer account
* - --type-id: Whether to use upgradable type id - defaults to false
* - --yes, -y: Skip confirmation prompt and deploy immediately - defaults to false
*
* Usage:
* pnpm run deploy
* pnpm run deploy --network testnet
* pnpm run deploy --network testnet --privkey 0x...
* pnpm run deploy --network testnet --type-id
* pnpm run deploy --yes
*/

import { spawn } from 'child_process';
import fs from 'fs';
import { fileURLToPath } from 'url';
import path from 'path';

function parseArgs() {
const args = process.argv.slice(2);
let args = process.argv.slice(2);

// Skip the first argument if it's "--" (npm/pnpm script separator)
if (args.length > 0 && args[0] === '--') {
args = args.slice(1);
}

const parsed = {
network: 'devnet',
privkey: null,
typeId: false,
yes: false,
};

for (let i = 0; i < args.length; i++) {
Expand All @@ -43,6 +54,8 @@ function parseArgs() {
i++; // Skip next argument since we consumed it
} else if (arg === '--type-id' || arg === '-t') {
parsed.typeId = true;
} else if (arg === '--yes' || arg === '-y') {
parsed.yes = true;
}
}

Expand All @@ -59,6 +72,7 @@ function main() {
const NETWORK = options.network;
const PRIVKEY = options.privkey;
const TYPE_ID = options.typeId;
const YES = options.yes;

// Validate that dist directory exists
if (!fs.existsSync(TARGET)) {
Expand Down Expand Up @@ -100,12 +114,16 @@ function main() {
args.push('--privkey', PRIVKEY);
}

// Try to find offckb binary
if (YES) {
args.push('--yes');
}

// Use offckb command - should be available in PATH
const offckbCmd = 'offckb';

// For now, use 'offckb' directly - users should have it installed
console.log(`� Deploying contracts...`);
console.log(`�💻 Running: ${offckbCmd} ${args.join(' ')}`);
console.log(`🚀 Deploying contracts...`);
console.log(`💻 Running: ${offckbCmd} ${args.join(' ')}`);
console.log(`🖥️ Platform: ${process.platform}`);
console.log('');

// Execute the deploy command
Expand All @@ -115,6 +133,7 @@ function main() {
});

deployProcess.on('close', (code) => {
console.log(`Deploy process exited with code: ${code}`);
if (code === 0) {
console.log('');
console.log('✅ Successfully deployed all contracts!');
Expand All @@ -124,6 +143,7 @@ function main() {
console.log('💡 Next steps:');
console.log(' - Check the deployment artifacts in the deployment/ folder');
console.log(' - Run your tests to use the deployed contract scripts');
process.exit(0);
} else {
console.error('');
console.error('❌ Deployment failed.');
Expand All @@ -134,16 +154,22 @@ function main() {

deployProcess.on('error', (error) => {
console.error('❌ Error running deploy command:', error.message);
console.error(`💻 Command: ${offckbCmd} ${args.join(' ')}`);
console.error('');
console.error('💡 Make sure offckb is installed:');
console.error(' npm install -g offckb-cli');
console.error(' # or');
console.error(' pnpm add -g offckb-cli');
console.error('💡 Troubleshooting:');
console.error(' 1. Make sure offckb is installed:');
console.error(' npm install -g @offckb/cli');
console.error(' # or');
console.error(' pnpm add -g @offckb/cli');
console.error(' 2. Check if offckb is in your PATH');
console.error(' 3. Try running the command manually to see the exact error');
process.exit(1);
});
}

// Run main function if this script is executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
// Use URL comparison for cross-platform compatibility (Windows uses backslashes in process.argv)
const __filename = fileURLToPath(import.meta.url);
if (path.resolve(process.argv[1]) === path.resolve(__filename)) {
main();
}
Loading