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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 10 additions & 0 deletions packages/delegation-abis/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@
"default": "./dist/index.mjs"
}
},
"./bytecode": {
"require": {
"types": "./dist/bytecode.d.cts",
"default": "./dist/bytecode.cjs"
},
"import": {
"types": "./dist/bytecode.d.ts",
"default": "./dist/bytecode.mjs"
}
},
"./package.json": "./package.json"
},
"engines": {
Expand Down
97 changes: 97 additions & 0 deletions packages/delegation-abis/scripts/fixExtensionsPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// From https://github.com/aymericzip/esbuild-fix-imports-plugin/blob/main/src/fixExtensionsPlugin.ts, included here to avoid adding a dependency
import type { Plugin } from 'esbuild';
import { readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
import { join, extname } from 'node:path';

const CJS_RELATIVE_IMPORT_EXP = /require\s*\(\s*["'](\..+?)["']\s*\)(;?)/g;
const ESM_RELATIVE_IMPORT_EXP = /from\s*(["'])(\.[^"']+)\1([^;]*;?)/g;
const hasJSExtensionRegex = /\.(?:js)$/i;
const hasNonJSExtensionRegex =
/\.(?:png|svg|css|scss|csv|tsv|xml|toml|ini|jpe?g|json|md|mdx|yaml|gif|webp|ico|mp4|webm|ogg|wav|mp3|m4a|aac|webm|woff2?|eot|ttf|otf|wasm)$/i;

function modifyEsmImports(contents: string, outExt: string) {
return contents.replace(ESM_RELATIVE_IMPORT_EXP, (_m, quote, importPath, rest = '') => {
if (importPath.endsWith('.') || importPath.endsWith('/')) {
return `from ${quote}${importPath}/index${outExt}${quote}${rest}`;
}
if (importPath.endsWith(outExt)) {
return `from ${quote}${importPath}${quote}${rest}`;
}
if (hasJSExtensionRegex.test(importPath) && outExt !== '.js') {
return `from ${quote}${importPath.replace(hasJSExtensionRegex, outExt)}${quote}${rest}`;
}
if (hasNonJSExtensionRegex.test(importPath)) {
return `from ${quote}${importPath}${quote}${rest}`;
}
return `from ${quote}${importPath}${outExt}${quote}${rest}`;
});
}

function modifyCjsImports(contents: string, outExt: string) {
return contents.replace(CJS_RELATIVE_IMPORT_EXP, (_m, importPath, maybeSemi = '') => {
if (importPath.endsWith('.') || importPath.endsWith('/')) {
return `require('${importPath}/index${outExt}')${maybeSemi}`;
}
if (hasJSExtensionRegex.test(importPath) && outExt !== '.js') {
return `require('${importPath.replace(hasJSExtensionRegex, outExt)}')${maybeSemi}`;
}
if (importPath.endsWith(outExt) || hasNonJSExtensionRegex.test(importPath)) {
return `require('${importPath}')${maybeSemi}`;
}
return `require('${importPath}${outExt}')${maybeSemi}`;
});
}

function modifyRelativeImports(contents: string, isEsm: boolean, outExt: string) {
return isEsm ? modifyEsmImports(contents, outExt) : modifyCjsImports(contents, outExt);
}

// Fallback if esbuild doesn't provide outputFiles (write: true)
function processOutdirFiles(outdir: string, isEsm: boolean, outExt: string) {
const stack = [outdir];
while (stack.length) {
const dir = stack.pop()!;
for (const entry of readdirSync(dir)) {
const p = join(dir, entry);
if (statSync(p).isDirectory()) {
stack.push(p);
continue;
}
const ext = extname(p);
if (ext !== outExt) {
continue;
}
if (ext === '.mjs' || ext === '.cjs' || ext === '.js') {
const original = readFileSync(p, 'utf8');
const updated = modifyRelativeImports(original, isEsm || ext === '.mjs', outExt);
if (updated !== original) {
writeFileSync(p, updated);
}
}
}
}
}

export const fixExtensionsPlugin = (): Plugin => ({
name: 'fixExtensionsPlugin',
setup(build) {
const isEsm = build.initialOptions.format === 'esm';
const outExt = build.initialOptions.outExtension?.['.js'] ?? (isEsm ? '.mjs' : '.cjs');
const outdir = build.initialOptions.outdir;

build.onEnd((result) => {
if (result.errors.length > 0) return;

if (result.outputFiles && result.outputFiles.length > 0) {
for (const ofile of result.outputFiles) {
if (!ofile.path.endsWith(outExt)) continue;
const next = modifyRelativeImports(ofile.text, isEsm, outExt);
ofile.contents = Buffer.from(next);
}
} else if (outdir) {
processOutdirFiles(outdir, isEsm, outExt);
}
});
},
});

155 changes: 100 additions & 55 deletions packages/delegation-abis/scripts/format-abis.js
Original file line number Diff line number Diff line change
@@ -1,88 +1,133 @@
const fs = require('fs');
const path = require('path');
import fs from 'node:fs';
import path from 'node:path';

// Directory containing the JSON ABI files
const inputDir = './src/raw';
// Output directory for the TypeScript files
const outputDir = './src/formatted';
const inputDir = './src/artifacts';
const abiDir = './src/abis';
const bytecodeModulesDir = './src/bytecode';
const INDEX_FILE = './src/index.ts';
const BYTECODE_FILE = './src/bytecode.ts';

// Ensure the output directory exists
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
if (!fs.existsSync(abiDir)) {
fs.mkdirSync(abiDir, { recursive: true });
}
if (!fs.existsSync(bytecodeModulesDir)) {
fs.mkdirSync(bytecodeModulesDir, { recursive: true });
}

// Export ts in an index file
function addExportToIndexFile(fileName) {
const indexStream = fs.createWriteStream('./src/index.ts', {
flags: 'a',
});
// Initialize index files (truncate)
fs.writeFileSync(INDEX_FILE, '');
fs.writeFileSync(BYTECODE_FILE, '');

indexStream.write(`export * as ${fileName} from './formatted/${fileName}'\n`);
// Write exports to index and bytecode files in sorted order
function writeIndexFiles(exportNames) {
const sortedNames = exportNames
.slice()
.sort((a, b) => a.localeCompare(b));
const indexContents = sortedNames
.map((fileName) => `export { abi as ${fileName} } from './abis/${fileName}';`)
.join('\n');
const bytecodeContents = sortedNames
.map(
(fileName) => `export { bytecode as ${fileName} } from './bytecode/${fileName}';`,
)
.join('\n');

indexStream.end();
fs.writeFileSync(INDEX_FILE, `${indexContents}\n`);
fs.writeFileSync(BYTECODE_FILE, `${bytecodeContents}\n`);
}

// Recursive function to process files and directories
function processDirectory(directory) {
fs.readdir(directory, { withFileTypes: true }, (err, entries) => {
if (err) {
console.error('Error reading directory:', err);
return;
}
const exportNames = [];
let entries;
try {
entries = fs.readdirSync(directory, { withFileTypes: true });
} catch (err) {
console.error('Error reading directory:', err);
return exportNames;
}

const ignoreList = ['utils', 'build-info'];
entries.forEach((entry) => {
const ignoreList = ['utils', 'build-info'];
entries
.slice()
.sort((a, b) => a.name.localeCompare(b.name))
.forEach((entry) => {
if (!ignoreList.includes(path.basename(directory))) {
const fullPath = path.join(directory, entry.name);
if (entry.isDirectory()) {
// Recurse into subdirectories
processDirectory(fullPath);
exportNames.push(...processDirectory(fullPath));
} else if (path.extname(entry.name) === '.json') {
// Process JSON files
processFile(fullPath, entry.name);
const exportName = processFile(fullPath, entry.name);
if (exportName) {
exportNames.push(exportName);
}
}
}
});
});

return exportNames;
}

// Function to process each JSON file
function processFile(filePath, fileName) {
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
console.error(`Error reading file ${fileName}:`, err);
return;
}
let data;
try {
data = fs.readFileSync(filePath, 'utf8');
} catch (err) {
console.error(`Error reading file ${fileName}:`, err);
return null;
}

try {
const abi = JSON.parse(data);
const tsContent = `export const abi = ${JSON.stringify(
abi.abi,
null,
2,
)} as const;\n
try {
const parsed = JSON.parse(data);
const abi = parsed.abi;
const bytecode = parsed.bytecode?.object ?? '';
const abiOnlyContent = `export const abi = ${JSON.stringify(
abi,
null,
2,
)} as const;\n`;
const bytecodeOnlyContent = `export const bytecode = '${bytecode}' as const;`;
const abiOnlyPath = path.join(
abiDir,
`${path.basename(fileName, '.json')}.ts`,
);
const bytecodeOnlyPath = path.join(
bytecodeModulesDir,
`${path.basename(fileName, '.json')}.ts`,
);

export const bytecode = \"${abi.bytecode.object}\" as const;`;
const outputFilePath = path.join(
outputDir,
`${path.basename(fileName, '.json')}.ts`,
// Write abi-only and bytecode-only modules
const exportName = path.basename(fileName, '.json');
try {
fs.writeFileSync(abiOnlyPath, abiOnlyContent);
console.log(
`ABI-only file generated for ${fileName}: ${abiOnlyPath}`,
);
} catch (err) {
console.error(`Error writing ABI-only file for ${fileName}:`, err);
return null;
}

fs.writeFile(outputFilePath, tsContent, (err) => {
if (err) {
console.error(`Error writing TypeScript file for ${fileName}:`, err);
} else {
console.log(
`TypeScript file generated for ${fileName}: ${outputFilePath}`,
);
addExportToIndexFile(path.basename(fileName, '.json'));
}
});
} catch (parseError) {
console.error(`Error parsing JSON from ${fileName}:`, parseError);
try {
fs.writeFileSync(bytecodeOnlyPath, bytecodeOnlyContent);
console.log(
`Bytecode-only file generated for ${fileName}: ${bytecodeOnlyPath}`,
);
} catch (err) {
console.error(`Error writing bytecode-only file for ${fileName}:`, err);
return null;
}
});
return exportName;
} catch (parseError) {
console.error(`Error parsing JSON from ${fileName}:`, parseError);
return null;
}
}

// Start processing from the input directory
processDirectory(inputDir);
const exportNames = processDirectory(inputDir);
writeIndexFiles(exportNames);
6 changes: 3 additions & 3 deletions packages/delegation-abis/scripts/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ cd ../..
# Synchronize files
cd packages/delegation-abis

rsync -r ../../abisTemp1/ src/raw/
rsync -r --ignore-existing ../../abisTemp2/ src/raw/
rsync -r --ignore-existing ../../abisTemp3/ src/raw/
rsync -r ../../abisTemp1/ src/artifacts/
rsync -r --ignore-existing ../../abisTemp2/ src/artifacts/
rsync -r --ignore-existing ../../abisTemp3/ src/artifacts/
rm -r ../../abisTemp1
rm -r ../../abisTemp2
rm -r ../../abisTemp3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,3 @@ export const abi = [
"inputs": []
}
] as const;


export const bytecode = "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212204a050c4fa34153d3fae9d282b8c08f593842bb7e1d0caa440348574559167b6a64736f6c63430008170033" as const;
Loading
Loading