@eliseev_s/tolk-tlb-transpiler
Version:
Transpile Tolk structs to TLB definitions and generate TypeScript wrappers for TON blockchain smart contracts
181 lines ⢠8.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const commander_1 = require("commander");
const fs_1 = require("fs");
const path_1 = require("path");
const tlb_codegen_1 = require("@ton-community/tlb-codegen");
const handlers_1 = require("../src/handlers");
const package_json_1 = __importDefault(require("../package.json"));
const { version } = package_json_1.default;
const commonTLB = `// Common TLB definitions
bool_false$0 = Bool;
bool_true$1 = Bool;
nothing$0 {X:Type} = Maybe X;
just$1 {X:Type} value:X = Maybe X;
left$0 {X:Type} {Y:Type} value:X = Either X Y;
right$1 {X:Type} {Y:Type} value:Y = Either X Y;
pair$_ {X:Type} {Y:Type} first:X second:Y = Both X Y;
`;
const program = new commander_1.Command();
program
.name('tolk-tlb')
.description('Transpile Tolk structs to TLB (Type Language Binary) definitions')
.version(version);
// Original transpile command
program
.command('transpile')
.description('Transpile Tolk structs to TLB definitions')
.argument('<input>', 'Input Tolk file path')
.option('-o, --output <path>', 'Output directory (default: same as input directory)')
.option('-n, --name <name>', 'Output file name (default: based on input file name)')
.option('--no-ts', 'Skip TypeScript code generation', true)
.option('-v, --verbose', 'Verbose output')
.action(async (input, options) => {
try {
await transpileCommand(input, options);
}
catch (error) {
console.error('ā Error:', error instanceof Error ? error.message : error);
process.exit(1);
}
});
// New wrapper generation command
program
.command('wrapper')
.description('Generate TypeScript wrapper for smart contract')
.argument('<structures>', 'Tolk file with struct definitions')
.argument('<get-methods>', 'Tolk file with get method definitions')
.argument('<contract-name>', 'Contract name (e.g., "Minter")')
.option('-o, --output <path>', 'Output directory (default: same as structures directory)')
.option('-n, --name <name>', 'Output file name (default: based on contract name)')
.option('-v, --verbose', 'Verbose output')
.action(async (structures, getMethods, contractName, options) => {
try {
await wrapperCommand(structures, getMethods, contractName, options);
}
catch (error) {
console.error('ā Error:', error instanceof Error ? error.message : error);
process.exit(1);
}
});
async function wrapperCommand(structuresPath, getMethodsPath, contractName, options) {
const verbose = options.verbose;
if (verbose) {
console.log('š Smart Contract Wrapper Generator');
console.log('===================================\n');
}
const resolvedStructures = (0, path_1.resolve)(structuresPath);
const resolvedGetMethods = (0, path_1.resolve)(getMethodsPath);
if (!(0, fs_1.existsSync)(resolvedStructures)) {
throw new Error(`Structures file not found: ${structuresPath}`);
}
if (!(0, fs_1.existsSync)(resolvedGetMethods)) {
throw new Error(`Get methods file not found: ${getMethodsPath}`);
}
const structuresDir = (0, path_1.dirname)(resolvedStructures);
const outputDir = options.output ? (0, path_1.resolve)(options.output) : structuresDir;
const outputName = options.name || contractName;
if (!(0, fs_1.existsSync)(outputDir)) {
(0, fs_1.mkdirSync)(outputDir, { recursive: true });
}
if (verbose) {
console.log(`š Reading structures from ${structuresPath}...`);
console.log(`š Reading get methods from ${getMethodsPath}...`);
}
const structuresCode = (0, fs_1.readFileSync)(resolvedStructures, 'utf-8');
const getMethodsCode = (0, fs_1.readFileSync)(resolvedGetMethods, 'utf-8');
if (verbose) {
console.log(`ā
Read ${structuresCode.length} characters from structures file`);
console.log(`ā
Read ${getMethodsCode.length} characters from get methods file\n`);
console.log('š§ Generating wrapper...');
}
const result = await (0, handlers_1.generateContractWrapper)(structuresCode, getMethodsCode, contractName);
const tlbPath = (0, path_1.join)(outputDir, `${outputName}.tlb`);
(0, fs_1.writeFileSync)(tlbPath, result.tlbString);
console.log(`š¾ TLB definitions written to: ${tlbPath}`);
const tsPath = (0, path_1.join)(outputDir, `${outputName}.ts`);
(0, fs_1.writeFileSync)(tsPath, result.fullCode);
console.log(`š¾ TypeScript wrapper written to: ${tsPath}`);
if (verbose) {
const stats = (0, handlers_1.getTlbStats)(result.tlbDefinitions);
console.log('\nš Summary:');
console.log('===========');
console.log(`Contract: ${contractName}`);
console.log(`Structures: ${structuresPath} (${structuresCode.length} chars)`);
console.log(`Get methods: ${getMethodsPath} (${getMethodsCode.length} chars)`);
console.log(`Output directory: ${outputDir}`);
console.log(`Generated ${stats.totalDefinitions} TLB definitions`);
console.log(`Total constructors: ${stats.totalConstructors}`);
console.log('š Wrapper generation completed successfully!');
}
}
async function transpileCommand(inputPath, options) {
const verbose = options.verbose;
if (verbose) {
console.log('š Tolk-to-TLB Transpiler');
console.log('========================\n');
}
const resolvedInput = (0, path_1.resolve)(inputPath);
if (!(0, fs_1.existsSync)(resolvedInput)) {
throw new Error(`Input file not found: ${inputPath}`);
}
const inputDir = (0, path_1.dirname)(resolvedInput);
const inputBaseName = (0, path_1.join)(inputPath).replace((0, path_1.extname)(inputPath), '');
const outputDir = options.output ? (0, path_1.resolve)(options.output) : inputDir;
const outputName = options.name || (0, path_1.join)(inputBaseName).split('/').pop();
if (!(0, fs_1.existsSync)(outputDir)) {
(0, fs_1.mkdirSync)(outputDir, { recursive: true });
}
if (verbose) {
console.log(`š Reading ${inputPath}...`);
}
const tolkCode = (0, fs_1.readFileSync)(resolvedInput, 'utf-8');
if (verbose) {
console.log(`ā
Read ${tolkCode.length} characters\n`);
console.log('š§ Initializing transpiler...');
}
const tlbDefinitions = await (0, handlers_1.transpileTolkToTlbDefinitions)(tolkCode);
if (verbose) {
console.log(`ā
Generated ${tlbDefinitions.length} TLB definitions\n`);
}
const tlbHeader = `TLB Schema Generated from ${(0, path_1.join)(inputPath)}`;
const outputContent = (0, handlers_1.formatTlbDefinitions)(tlbDefinitions, tlbHeader);
const tlbPath = (0, path_1.join)(outputDir, `${outputName}.tlb`);
(0, fs_1.writeFileSync)(tlbPath, outputContent);
console.log(`š¾ TLB definitions written to: ${tlbPath}`);
if (options.ts) {
try {
const tsPath = (0, path_1.join)(outputDir, `${outputName}.ts`);
const tsCode = await (0, tlb_codegen_1.generateCodeFromData)(commonTLB + outputContent, 'typescript');
(0, fs_1.writeFileSync)(tsPath, tsCode);
console.log(`š¾ TypeScript code written to: ${tsPath}`);
}
catch (error) {
console.warn('ā ļø TypeScript generation failed:', error instanceof Error ? error.message : error);
}
}
if (verbose) {
const stats = (0, handlers_1.getTlbStats)(tlbDefinitions);
console.log('\nš Summary:');
console.log('===========');
console.log(`Input: ${inputPath} (${tolkCode.length} chars)`);
console.log(`Output directory: ${outputDir}`);
console.log(`Generated ${stats.totalDefinitions} TLB definitions`);
console.log(`Total constructors: ${stats.totalConstructors}`);
console.log('š Transpilation completed successfully!');
}
}
process.on('uncaughtException', (error) => {
console.error('ā Uncaught exception:', error.message);
process.exit(1);
});
process.on('unhandledRejection', (reason) => {
console.error('ā Unhandled rejection:', reason);
process.exit(1);
});
program.parse();
//# sourceMappingURL=cli.js.map