clawcontract-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +229 -0
- package/dist/analyzer/fallback.d.ts +28 -0
- package/dist/analyzer/fallback.d.ts.map +1 -0
- package/dist/analyzer/fallback.js +142 -0
- package/dist/analyzer/fallback.js.map +1 -0
- package/dist/analyzer/index.d.ts +24 -0
- package/dist/analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/index.js +73 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/analyzer/slither.d.ts +36 -0
- package/dist/analyzer/slither.d.ts.map +1 -0
- package/dist/analyzer/slither.js +92 -0
- package/dist/analyzer/slither.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +7 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +74 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/create.d.ts +8 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +44 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/delete.d.ts +5 -0
- package/dist/cli/commands/delete.d.ts.map +1 -0
- package/dist/cli/commands/delete.js +48 -0
- package/dist/cli/commands/delete.js.map +1 -0
- package/dist/cli/commands/deploy.d.ts +7 -0
- package/dist/cli/commands/deploy.d.ts.map +1 -0
- package/dist/cli/commands/deploy.js +130 -0
- package/dist/cli/commands/deploy.js.map +1 -0
- package/dist/cli/commands/featured.d.ts +4 -0
- package/dist/cli/commands/featured.d.ts.map +1 -0
- package/dist/cli/commands/featured.js +47 -0
- package/dist/cli/commands/featured.js.map +1 -0
- package/dist/cli/commands/full.d.ts +14 -0
- package/dist/cli/commands/full.d.ts.map +1 -0
- package/dist/cli/commands/full.js +72 -0
- package/dist/cli/commands/full.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +10 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +71 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/info.d.ts +4 -0
- package/dist/cli/commands/info.d.ts.map +1 -0
- package/dist/cli/commands/info.js +76 -0
- package/dist/cli/commands/info.js.map +1 -0
- package/dist/cli/commands/interact.d.ts +7 -0
- package/dist/cli/commands/interact.d.ts.map +1 -0
- package/dist/cli/commands/interact.js +173 -0
- package/dist/cli/commands/interact.js.map +1 -0
- package/dist/cli/commands/list.d.ts +6 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +37 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/register.d.ts +4 -0
- package/dist/cli/commands/register.d.ts.map +1 -0
- package/dist/cli/commands/register.js +54 -0
- package/dist/cli/commands/register.js.map +1 -0
- package/dist/cli/commands/verified.d.ts +9 -0
- package/dist/cli/commands/verified.d.ts.map +1 -0
- package/dist/cli/commands/verified.js +61 -0
- package/dist/cli/commands/verified.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +9 -0
- package/dist/cli/commands/verify.d.ts.map +1 -0
- package/dist/cli/commands/verify.js +87 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +160 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils.d.ts +8 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +36 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/config/chains.d.ts +18 -0
- package/dist/config/chains.d.ts.map +1 -0
- package/dist/config/chains.js +52 -0
- package/dist/config/chains.js.map +1 -0
- package/dist/config/clawcontractbook.d.ts +3 -0
- package/dist/config/clawcontractbook.d.ts.map +1 -0
- package/dist/config/clawcontractbook.js +3 -0
- package/dist/config/clawcontractbook.js.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/constants/index.d.ts +3 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +3 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/deployer/compiler.d.ts +10 -0
- package/dist/deployer/compiler.d.ts.map +1 -0
- package/dist/deployer/compiler.js +93 -0
- package/dist/deployer/compiler.js.map +1 -0
- package/dist/deployer/deploy.d.ts +28 -0
- package/dist/deployer/deploy.d.ts.map +1 -0
- package/dist/deployer/deploy.js +60 -0
- package/dist/deployer/deploy.js.map +1 -0
- package/dist/deployer/hardhat-config-template.d.ts +2 -0
- package/dist/deployer/hardhat-config-template.d.ts.map +1 -0
- package/dist/deployer/hardhat-config-template.js +21 -0
- package/dist/deployer/hardhat-config-template.js.map +1 -0
- package/dist/deployer/index.d.ts +7 -0
- package/dist/deployer/index.d.ts.map +1 -0
- package/dist/deployer/index.js +4 -0
- package/dist/deployer/index.js.map +1 -0
- package/dist/deployer/metadata.d.ts +17 -0
- package/dist/deployer/metadata.d.ts.map +1 -0
- package/dist/deployer/metadata.js +317 -0
- package/dist/deployer/metadata.js.map +1 -0
- package/dist/deployer/wallet.d.ts +6 -0
- package/dist/deployer/wallet.d.ts.map +1 -0
- package/dist/deployer/wallet.js +15 -0
- package/dist/deployer/wallet.js.map +1 -0
- package/dist/generator/index.d.ts +2 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +2 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/llm.d.ts +15 -0
- package/dist/generator/llm.d.ts.map +1 -0
- package/dist/generator/llm.js +128 -0
- package/dist/generator/llm.js.map +1 -0
- package/dist/generator/utils.d.ts +5 -0
- package/dist/generator/utils.d.ts.map +1 -0
- package/dist/generator/utils.js +49 -0
- package/dist/generator/utils.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/clawcontractbook.d.ts +65 -0
- package/dist/lib/clawcontractbook.d.ts.map +1 -0
- package/dist/lib/clawcontractbook.js +158 -0
- package/dist/lib/clawcontractbook.js.map +1 -0
- package/dist/lib/credentials.d.ts +28 -0
- package/dist/lib/credentials.d.ts.map +1 -0
- package/dist/lib/credentials.js +73 -0
- package/dist/lib/credentials.js.map +1 -0
- package/dist/verifier/explorer-api.d.ts +21 -0
- package/dist/verifier/explorer-api.d.ts.map +1 -0
- package/dist/verifier/explorer-api.js +92 -0
- package/dist/verifier/explorer-api.js.map +1 -0
- package/dist/verifier/index.d.ts +20 -0
- package/dist/verifier/index.d.ts.map +1 -0
- package/dist/verifier/index.js +31 -0
- package/dist/verifier/index.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/deployer/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG1D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface DeploymentRecord {
|
|
2
|
+
contractAddress: string;
|
|
3
|
+
abi: readonly Record<string, unknown>[];
|
|
4
|
+
chainKey: string;
|
|
5
|
+
contractName: string;
|
|
6
|
+
sourceFile: string;
|
|
7
|
+
deployer: string;
|
|
8
|
+
transactionHash: string;
|
|
9
|
+
blockNumber: number;
|
|
10
|
+
deployedAt: string;
|
|
11
|
+
deploymentId?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function saveDeployment(record: DeploymentRecord, outputDir: string): void;
|
|
14
|
+
export declare function loadDeployment(address: string, outputDir: string): DeploymentRecord | undefined;
|
|
15
|
+
export declare function loadAllDeployments(outputDir: string): DeploymentRecord[];
|
|
16
|
+
export declare function deleteDeployment(address: string, outputDir: string): boolean;
|
|
17
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/deployer/metadata.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,GAAG,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyOD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,GAChB,IAAI,CAmEN;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,gBAAgB,GAAG,SAAS,CA4B9B;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EAAE,CA6BxE;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CA6E5E"}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Path helpers
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
const DEPLOYMENTS_DIR = '.deployments';
|
|
9
|
+
const LEGACY_FILE = '.deployments.json';
|
|
10
|
+
const LEGACY_BACKUP = '.deployments.v1.json.bak';
|
|
11
|
+
function deploymentsRoot(outputDir) {
|
|
12
|
+
return path.resolve(outputDir, DEPLOYMENTS_DIR);
|
|
13
|
+
}
|
|
14
|
+
function indexPath(outputDir) {
|
|
15
|
+
return path.join(deploymentsRoot(outputDir), 'index.json');
|
|
16
|
+
}
|
|
17
|
+
function abiFilePath(outputDir, hash) {
|
|
18
|
+
return path.join(deploymentsRoot(outputDir), 'abis', `${hash}.json`);
|
|
19
|
+
}
|
|
20
|
+
function recordFilePath(outputDir, chainKey, contractName, address) {
|
|
21
|
+
return path.join(deploymentsRoot(outputDir), 'records', chainKey, contractName, `${address}.json`);
|
|
22
|
+
}
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// ABI hashing
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
function hashAbi(abi) {
|
|
27
|
+
return crypto.createHash('sha256').update(JSON.stringify(abi)).digest('hex');
|
|
28
|
+
}
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Index helpers
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
function emptyIndex() {
|
|
33
|
+
return { version: 2, byAddress: {}, byChain: {} };
|
|
34
|
+
}
|
|
35
|
+
function readIndex(outputDir) {
|
|
36
|
+
const p = indexPath(outputDir);
|
|
37
|
+
if (!fs.existsSync(p)) {
|
|
38
|
+
return emptyIndex();
|
|
39
|
+
}
|
|
40
|
+
return JSON.parse(fs.readFileSync(p, 'utf-8'));
|
|
41
|
+
}
|
|
42
|
+
function atomicWriteJson(filePath, data) {
|
|
43
|
+
const content = JSON.stringify(data, null, 2);
|
|
44
|
+
const tmpFile = path.join(os.tmpdir(), `deploy-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
|
|
45
|
+
fs.writeFileSync(tmpFile, content, 'utf-8');
|
|
46
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
47
|
+
try {
|
|
48
|
+
fs.renameSync(tmpFile, filePath);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
fs.copyFileSync(tmpFile, filePath);
|
|
52
|
+
fs.unlinkSync(tmpFile);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Migration from v1 flat file
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
function migrateIfNeeded(outputDir) {
|
|
59
|
+
const legacyPath = path.resolve(outputDir, LEGACY_FILE);
|
|
60
|
+
const root = deploymentsRoot(outputDir);
|
|
61
|
+
if (!fs.existsSync(legacyPath) || fs.existsSync(root)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const raw = fs.readFileSync(legacyPath, 'utf-8');
|
|
65
|
+
let records;
|
|
66
|
+
try {
|
|
67
|
+
records = JSON.parse(raw);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return; // corrupted legacy file – skip migration
|
|
71
|
+
}
|
|
72
|
+
// Bootstrap empty directory structure
|
|
73
|
+
fs.mkdirSync(root, { recursive: true });
|
|
74
|
+
const index = emptyIndex();
|
|
75
|
+
for (const record of records) {
|
|
76
|
+
const abiH = hashAbi(record.abi);
|
|
77
|
+
// Write ABI file if not already present
|
|
78
|
+
const abiPath = abiFilePath(outputDir, abiH);
|
|
79
|
+
if (!fs.existsSync(abiPath)) {
|
|
80
|
+
fs.mkdirSync(path.dirname(abiPath), { recursive: true });
|
|
81
|
+
fs.writeFileSync(abiPath, JSON.stringify({ abi: record.abi }, null, 2), 'utf-8');
|
|
82
|
+
}
|
|
83
|
+
// Write record file
|
|
84
|
+
const stored = {
|
|
85
|
+
version: 2,
|
|
86
|
+
contractAddress: record.contractAddress,
|
|
87
|
+
abiHash: abiH,
|
|
88
|
+
chainKey: record.chainKey,
|
|
89
|
+
contractName: record.contractName,
|
|
90
|
+
sourceFile: record.sourceFile,
|
|
91
|
+
deployer: record.deployer,
|
|
92
|
+
transactionHash: record.transactionHash,
|
|
93
|
+
blockNumber: record.blockNumber,
|
|
94
|
+
deployedAt: record.deployedAt,
|
|
95
|
+
};
|
|
96
|
+
const recPath = recordFilePath(outputDir, record.chainKey, record.contractName, record.contractAddress);
|
|
97
|
+
fs.mkdirSync(path.dirname(recPath), { recursive: true });
|
|
98
|
+
fs.writeFileSync(recPath, JSON.stringify(stored, null, 2), 'utf-8');
|
|
99
|
+
// Update index
|
|
100
|
+
const addrLower = record.contractAddress.toLowerCase();
|
|
101
|
+
index.byAddress[addrLower] = {
|
|
102
|
+
chainKey: record.chainKey,
|
|
103
|
+
contractName: record.contractName,
|
|
104
|
+
};
|
|
105
|
+
if (!index.byChain[record.chainKey]) {
|
|
106
|
+
index.byChain[record.chainKey] = {};
|
|
107
|
+
}
|
|
108
|
+
const chainBucket = index.byChain[record.chainKey];
|
|
109
|
+
if (!chainBucket[record.contractName]) {
|
|
110
|
+
chainBucket[record.contractName] = {
|
|
111
|
+
latestAddress: record.contractAddress,
|
|
112
|
+
addresses: [],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const entry = chainBucket[record.contractName];
|
|
116
|
+
if (!entry.addresses.includes(record.contractAddress)) {
|
|
117
|
+
entry.addresses.push(record.contractAddress);
|
|
118
|
+
}
|
|
119
|
+
entry.latestAddress = record.contractAddress;
|
|
120
|
+
}
|
|
121
|
+
// Write index
|
|
122
|
+
atomicWriteJson(indexPath(outputDir), index);
|
|
123
|
+
// Rename legacy file to backup
|
|
124
|
+
const backupPath = path.resolve(outputDir, LEGACY_BACKUP);
|
|
125
|
+
try {
|
|
126
|
+
fs.renameSync(legacyPath, backupPath);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
fs.copyFileSync(legacyPath, backupPath);
|
|
130
|
+
fs.unlinkSync(legacyPath);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Reconstruct a full DeploymentRecord from stored record + ABI file
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
function hydrateRecord(stored, outputDir) {
|
|
137
|
+
const abiPath = abiFilePath(outputDir, stored.abiHash);
|
|
138
|
+
const abiData = JSON.parse(fs.readFileSync(abiPath, 'utf-8'));
|
|
139
|
+
return {
|
|
140
|
+
contractAddress: stored.contractAddress,
|
|
141
|
+
abi: abiData.abi,
|
|
142
|
+
chainKey: stored.chainKey,
|
|
143
|
+
contractName: stored.contractName,
|
|
144
|
+
sourceFile: stored.sourceFile,
|
|
145
|
+
deployer: stored.deployer,
|
|
146
|
+
transactionHash: stored.transactionHash,
|
|
147
|
+
blockNumber: stored.blockNumber,
|
|
148
|
+
deployedAt: stored.deployedAt,
|
|
149
|
+
deploymentId: stored.deploymentId,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
// Public API
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
export function saveDeployment(record, outputDir) {
|
|
156
|
+
migrateIfNeeded(outputDir);
|
|
157
|
+
const root = deploymentsRoot(outputDir);
|
|
158
|
+
fs.mkdirSync(root, { recursive: true });
|
|
159
|
+
// 1. Write ABI file (deduplicated by content hash)
|
|
160
|
+
const abiH = hashAbi(record.abi);
|
|
161
|
+
const abiPath = abiFilePath(outputDir, abiH);
|
|
162
|
+
if (!fs.existsSync(abiPath)) {
|
|
163
|
+
fs.mkdirSync(path.dirname(abiPath), { recursive: true });
|
|
164
|
+
fs.writeFileSync(abiPath, JSON.stringify({ abi: record.abi }, null, 2), 'utf-8');
|
|
165
|
+
}
|
|
166
|
+
// 2. Write record file (no ABI inline)
|
|
167
|
+
const stored = {
|
|
168
|
+
version: 2,
|
|
169
|
+
contractAddress: record.contractAddress,
|
|
170
|
+
abiHash: abiH,
|
|
171
|
+
chainKey: record.chainKey,
|
|
172
|
+
contractName: record.contractName,
|
|
173
|
+
sourceFile: record.sourceFile,
|
|
174
|
+
deployer: record.deployer,
|
|
175
|
+
transactionHash: record.transactionHash,
|
|
176
|
+
blockNumber: record.blockNumber,
|
|
177
|
+
deployedAt: record.deployedAt,
|
|
178
|
+
deploymentId: record.deploymentId,
|
|
179
|
+
};
|
|
180
|
+
const recPath = recordFilePath(outputDir, record.chainKey, record.contractName, record.contractAddress);
|
|
181
|
+
fs.mkdirSync(path.dirname(recPath), { recursive: true });
|
|
182
|
+
fs.writeFileSync(recPath, JSON.stringify(stored, null, 2), 'utf-8');
|
|
183
|
+
// 3. Update index.json (atomic write)
|
|
184
|
+
const index = readIndex(outputDir);
|
|
185
|
+
const addrLower = record.contractAddress.toLowerCase();
|
|
186
|
+
index.byAddress[addrLower] = {
|
|
187
|
+
chainKey: record.chainKey,
|
|
188
|
+
contractName: record.contractName,
|
|
189
|
+
};
|
|
190
|
+
if (!index.byChain[record.chainKey]) {
|
|
191
|
+
index.byChain[record.chainKey] = {};
|
|
192
|
+
}
|
|
193
|
+
const chainBucket = index.byChain[record.chainKey];
|
|
194
|
+
if (!chainBucket[record.contractName]) {
|
|
195
|
+
chainBucket[record.contractName] = {
|
|
196
|
+
latestAddress: record.contractAddress,
|
|
197
|
+
addresses: [],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
const entry = chainBucket[record.contractName];
|
|
201
|
+
if (!entry.addresses.includes(record.contractAddress)) {
|
|
202
|
+
entry.addresses.push(record.contractAddress);
|
|
203
|
+
}
|
|
204
|
+
entry.latestAddress = record.contractAddress;
|
|
205
|
+
atomicWriteJson(indexPath(outputDir), index);
|
|
206
|
+
}
|
|
207
|
+
export function loadDeployment(address, outputDir) {
|
|
208
|
+
migrateIfNeeded(outputDir);
|
|
209
|
+
const index = readIndex(outputDir);
|
|
210
|
+
const needle = address.toLowerCase();
|
|
211
|
+
const entry = index.byAddress[needle];
|
|
212
|
+
if (!entry) {
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
const recPath = recordFilePath(outputDir, entry.chainKey, entry.contractName,
|
|
216
|
+
// We need the original-cased address stored in the record file name.
|
|
217
|
+
// The index stores the chainKey+contractName; iterate addresses to find the
|
|
218
|
+
// matching one (case-insensitive) so we get the correct filename.
|
|
219
|
+
findOriginalAddress(index, entry.chainKey, entry.contractName, needle));
|
|
220
|
+
if (!fs.existsSync(recPath)) {
|
|
221
|
+
return undefined;
|
|
222
|
+
}
|
|
223
|
+
const stored = JSON.parse(fs.readFileSync(recPath, 'utf-8'));
|
|
224
|
+
return hydrateRecord(stored, outputDir);
|
|
225
|
+
}
|
|
226
|
+
export function loadAllDeployments(outputDir) {
|
|
227
|
+
migrateIfNeeded(outputDir);
|
|
228
|
+
const index = readIndex(outputDir);
|
|
229
|
+
const results = [];
|
|
230
|
+
for (const [addrLower, entry] of Object.entries(index.byAddress)) {
|
|
231
|
+
const originalAddr = findOriginalAddress(index, entry.chainKey, entry.contractName, addrLower);
|
|
232
|
+
const recPath = recordFilePath(outputDir, entry.chainKey, entry.contractName, originalAddr);
|
|
233
|
+
if (!fs.existsSync(recPath)) {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const stored = JSON.parse(fs.readFileSync(recPath, 'utf-8'));
|
|
237
|
+
results.push(hydrateRecord(stored, outputDir));
|
|
238
|
+
}
|
|
239
|
+
return results;
|
|
240
|
+
}
|
|
241
|
+
export function deleteDeployment(address, outputDir) {
|
|
242
|
+
migrateIfNeeded(outputDir);
|
|
243
|
+
const index = readIndex(outputDir);
|
|
244
|
+
const needle = address.toLowerCase();
|
|
245
|
+
const entry = index.byAddress[needle];
|
|
246
|
+
if (!entry) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
const { chainKey, contractName } = entry;
|
|
250
|
+
const originalAddr = findOriginalAddress(index, chainKey, contractName, needle);
|
|
251
|
+
// 1. Read record to get abiHash, then delete record file
|
|
252
|
+
const recPath = recordFilePath(outputDir, chainKey, contractName, originalAddr);
|
|
253
|
+
const stored = JSON.parse(fs.readFileSync(recPath, 'utf-8'));
|
|
254
|
+
const { abiHash } = stored;
|
|
255
|
+
fs.unlinkSync(recPath);
|
|
256
|
+
// 2. Remove from byAddress
|
|
257
|
+
delete index.byAddress[needle];
|
|
258
|
+
// 3. Update byChain
|
|
259
|
+
const chainBucket = index.byChain[chainKey];
|
|
260
|
+
if (chainBucket) {
|
|
261
|
+
const contractEntry = chainBucket[contractName];
|
|
262
|
+
if (contractEntry) {
|
|
263
|
+
contractEntry.addresses = contractEntry.addresses.filter((a) => a.toLowerCase() !== needle);
|
|
264
|
+
if (contractEntry.addresses.length === 0) {
|
|
265
|
+
delete chainBucket[contractName];
|
|
266
|
+
}
|
|
267
|
+
else if (contractEntry.latestAddress.toLowerCase() === needle) {
|
|
268
|
+
contractEntry.latestAddress =
|
|
269
|
+
contractEntry.addresses[contractEntry.addresses.length - 1];
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (Object.keys(chainBucket).length === 0) {
|
|
273
|
+
delete index.byChain[chainKey];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// 4. Garbage-collect ABI file if no remaining record references it
|
|
277
|
+
let abiStillReferenced = false;
|
|
278
|
+
for (const [remainingLower, remainingEntry] of Object.entries(index.byAddress)) {
|
|
279
|
+
const remainingOriginal = findOriginalAddress(index, remainingEntry.chainKey, remainingEntry.contractName, remainingLower);
|
|
280
|
+
const remainingRecPath = recordFilePath(outputDir, remainingEntry.chainKey, remainingEntry.contractName, remainingOriginal);
|
|
281
|
+
if (fs.existsSync(remainingRecPath)) {
|
|
282
|
+
const remainingStored = JSON.parse(fs.readFileSync(remainingRecPath, 'utf-8'));
|
|
283
|
+
if (remainingStored.abiHash === abiHash) {
|
|
284
|
+
abiStillReferenced = true;
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (!abiStillReferenced) {
|
|
290
|
+
const abiPath = abiFilePath(outputDir, abiHash);
|
|
291
|
+
if (fs.existsSync(abiPath)) {
|
|
292
|
+
fs.unlinkSync(abiPath);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// 5. Persist updated index
|
|
296
|
+
atomicWriteJson(indexPath(outputDir), index);
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
// ---------------------------------------------------------------------------
|
|
300
|
+
// Internal helper – resolve original-cased address from index
|
|
301
|
+
// ---------------------------------------------------------------------------
|
|
302
|
+
function findOriginalAddress(index, chainKey, contractName, lowerAddress) {
|
|
303
|
+
const chainBucket = index.byChain[chainKey];
|
|
304
|
+
if (chainBucket) {
|
|
305
|
+
const contractEntry = chainBucket[contractName];
|
|
306
|
+
if (contractEntry) {
|
|
307
|
+
for (const addr of contractEntry.addresses) {
|
|
308
|
+
if (addr.toLowerCase() === lowerAddress) {
|
|
309
|
+
return addr;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// Fallback – use lowercased version (shouldn't happen in a consistent store)
|
|
315
|
+
return lowerAddress;
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/deployer/metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../src/deployer/wallet.ts"],"names":[],"mappings":"AAGA,wBAAgB,iBAAiB,IAAI,MAAM,CAS1C;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAIzF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { loadCredentials } from '../lib/credentials.js';
|
|
3
|
+
export function resolvePrivateKey() {
|
|
4
|
+
const creds = loadCredentials();
|
|
5
|
+
if (creds?.privateKey?.trim()) {
|
|
6
|
+
return creds.privateKey.startsWith('0x') ? creds.privateKey : `0x${creds.privateKey}`;
|
|
7
|
+
}
|
|
8
|
+
throw new Error('No private key found. Run `clawcontract register --name MyAgent` to create credentials with a wallet.');
|
|
9
|
+
}
|
|
10
|
+
export function getWalletInfo(privateKey) {
|
|
11
|
+
const normalized = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`;
|
|
12
|
+
const wallet = new ethers.Wallet(normalized);
|
|
13
|
+
return { address: wallet.address, privateKey: normalized };
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=wallet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet.js","sourceRoot":"","sources":["../../src/deployer/wallet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,UAAU,iBAAiB;IAC/B,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC;IACxF,CAAC;IAED,MAAM,IAAI,KAAK,CACb,uGAAuG,CACxG,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,UAAkB;IAC9C,MAAM,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;IAChF,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type LLMProvider = "openrouter";
|
|
2
|
+
export interface PromptValidationResult {
|
|
3
|
+
allowed: boolean;
|
|
4
|
+
reason?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface LLMClient {
|
|
7
|
+
isAvailable(): boolean;
|
|
8
|
+
provider(): LLMProvider | null;
|
|
9
|
+
validatePrompt(description: string): Promise<PromptValidationResult>;
|
|
10
|
+
customizeContract(template: string, description: string): Promise<string>;
|
|
11
|
+
generateContract(description: string): Promise<string>;
|
|
12
|
+
suggestFixes(code: string, issues: string[]): Promise<string>;
|
|
13
|
+
}
|
|
14
|
+
export declare function createLLMClient(): LLMClient;
|
|
15
|
+
//# sourceMappingURL=llm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/generator/llm.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,YAAY,CAAC;AAEvC,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,IAAI,OAAO,CAAC;IACvB,QAAQ,IAAI,WAAW,GAAG,IAAI,CAAC;IAC/B,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACrE,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1E,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/D;AAoJD,wBAAgB,eAAe,IAAI,SAAS,CAQ3C"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
const SOLIDITY_SYSTEM_PROMPT = `You are a Solidity smart contract developer specializing in BNB Smart Chain and opBNB.
|
|
2
|
+
Follow these rules strictly:
|
|
3
|
+
- Use Solidity ^0.8.20
|
|
4
|
+
- Contracts must be fully self-contained with NO import statements
|
|
5
|
+
- Ensure compatibility with BSC and opBNB (EVM-compatible)
|
|
6
|
+
- Always include an SPDX license identifier comment at the top (e.g., // SPDX-License-Identifier: MIT)
|
|
7
|
+
- Return ONLY the Solidity source code, no markdown fences, no explanations`;
|
|
8
|
+
const OPENROUTER_MODEL = process.env.CLAWCONTRACT_OPENROUTER_MODEL || "anthropic/claude-sonnet-4-20250514";
|
|
9
|
+
const MAX_TOKENS = 4096;
|
|
10
|
+
function stripMarkdownFences(text) {
|
|
11
|
+
return text.replace(/^```(?:solidity)?\n?/m, "").replace(/\n?```\s*$/m, "").trim();
|
|
12
|
+
}
|
|
13
|
+
const VALIDATION_SYSTEM_PROMPT = `You are a smart contract request validator. Your job is to determine whether a user's request is asking to generate a token or ERC-20 / BEP-20 contract.
|
|
14
|
+
|
|
15
|
+
Reject the request if the user is asking to:
|
|
16
|
+
- Create, generate, build, or deploy an ERC-20 or BEP-20 token
|
|
17
|
+
- Create a fungible token contract
|
|
18
|
+
- Create a token with name, symbol, supply, mint, or burn functionality
|
|
19
|
+
- Any variation of creating a cryptocurrency token
|
|
20
|
+
|
|
21
|
+
Allow the request if it is about other types of smart contracts (NFTs, DAOs, staking, vesting, voting, escrow, etc.) even if they mention tokens incidentally (e.g. "staking contract that accepts token X").
|
|
22
|
+
|
|
23
|
+
Respond with ONLY a JSON object (no markdown fences):
|
|
24
|
+
{"allowed": true} if the request is acceptable
|
|
25
|
+
{"allowed": false, "reason": "<brief reason>"} if the request is a token/ERC-20 generation request`;
|
|
26
|
+
async function openRouterChatWithSystem(apiKey, systemPrompt, userMessage, maxTokens = MAX_TOKENS) {
|
|
27
|
+
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
|
|
28
|
+
method: "POST",
|
|
29
|
+
headers: {
|
|
30
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
|
+
"HTTP-Referer": "https://github.com/clawcontract",
|
|
33
|
+
"X-Title": "ClawContract",
|
|
34
|
+
},
|
|
35
|
+
body: JSON.stringify({
|
|
36
|
+
model: OPENROUTER_MODEL,
|
|
37
|
+
max_tokens: maxTokens,
|
|
38
|
+
messages: [
|
|
39
|
+
{ role: "system", content: systemPrompt },
|
|
40
|
+
{ role: "user", content: userMessage },
|
|
41
|
+
],
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
const errorText = await response.text();
|
|
46
|
+
throw new Error(`OpenRouter API error (${response.status}): ${errorText.slice(0, 200)}`);
|
|
47
|
+
}
|
|
48
|
+
const data = (await response.json());
|
|
49
|
+
if (data.error?.message) {
|
|
50
|
+
throw new Error(`OpenRouter error: ${data.error.message}`);
|
|
51
|
+
}
|
|
52
|
+
const content = data.choices?.[0]?.message?.content;
|
|
53
|
+
if (!content) {
|
|
54
|
+
throw new Error("No text response from OpenRouter");
|
|
55
|
+
}
|
|
56
|
+
return content.trim();
|
|
57
|
+
}
|
|
58
|
+
async function openRouterChat(apiKey, userMessage) {
|
|
59
|
+
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
|
|
60
|
+
method: "POST",
|
|
61
|
+
headers: {
|
|
62
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
63
|
+
"Content-Type": "application/json",
|
|
64
|
+
"HTTP-Referer": "https://github.com/clawcontract",
|
|
65
|
+
"X-Title": "ClawContract",
|
|
66
|
+
},
|
|
67
|
+
body: JSON.stringify({
|
|
68
|
+
model: OPENROUTER_MODEL,
|
|
69
|
+
max_tokens: MAX_TOKENS,
|
|
70
|
+
messages: [
|
|
71
|
+
{ role: "system", content: SOLIDITY_SYSTEM_PROMPT },
|
|
72
|
+
{ role: "user", content: userMessage },
|
|
73
|
+
],
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
const errorText = await response.text();
|
|
78
|
+
throw new Error(`OpenRouter API error (${response.status}): ${errorText.slice(0, 200)}`);
|
|
79
|
+
}
|
|
80
|
+
const data = (await response.json());
|
|
81
|
+
if (data.error?.message) {
|
|
82
|
+
throw new Error(`OpenRouter error: ${data.error.message}`);
|
|
83
|
+
}
|
|
84
|
+
const content = data.choices?.[0]?.message?.content;
|
|
85
|
+
if (!content) {
|
|
86
|
+
throw new Error("No text response from OpenRouter");
|
|
87
|
+
}
|
|
88
|
+
return stripMarkdownFences(content.trim());
|
|
89
|
+
}
|
|
90
|
+
function createOpenRouterClient(apiKey) {
|
|
91
|
+
return {
|
|
92
|
+
isAvailable: () => true,
|
|
93
|
+
provider: () => "openrouter",
|
|
94
|
+
validatePrompt: async (description) => {
|
|
95
|
+
const raw = await openRouterChatWithSystem(apiKey, VALIDATION_SYSTEM_PROMPT, description, 256);
|
|
96
|
+
try {
|
|
97
|
+
const cleaned = raw.replace(/^```(?:json)?\n?/m, "").replace(/\n?```\s*$/m, "").trim();
|
|
98
|
+
const result = JSON.parse(cleaned);
|
|
99
|
+
return { allowed: result.allowed, reason: result.reason };
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return { allowed: true };
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
customizeContract: (template, description) => openRouterChat(apiKey, `I have the following Solidity contract template:\n\n${template}\n\nUser request: "${description}"\n\nCustomize this template based on the user's request. Fill in all placeholder values (anything in {{DOUBLE_BRACES}}) with appropriate values extracted from the description. Add any additional features the user requested. Keep the contract self-contained with no imports. Return ONLY the complete Solidity source code.`),
|
|
106
|
+
generateContract: (description) => openRouterChat(apiKey, `Generate a complete Solidity smart contract based on this description:\n\n"${description}"\n\nThe contract must be:\n- Fully self-contained (no imports)\n- Compatible with BSC/opBNB\n- Using Solidity ^0.8.20\n- Well-structured with appropriate access control\n- Including relevant events and error handling\n\nReturn ONLY the Solidity source code.`),
|
|
107
|
+
suggestFixes: (code, issues) => {
|
|
108
|
+
const issueList = issues.map((i, idx) => `${idx + 1}. ${i}`).join("\n");
|
|
109
|
+
return openRouterChat(apiKey, `The following Solidity contract has security issues found by Slither:\n\nContract:\n${code}\n\nIssues:\n${issueList}\n\nFix all the listed issues and return the corrected Solidity source code. Keep the contract self-contained with no imports. Return ONLY the complete fixed Solidity source code.`);
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const NULL_CLIENT = {
|
|
114
|
+
isAvailable: () => false,
|
|
115
|
+
provider: () => null,
|
|
116
|
+
validatePrompt: async () => ({ allowed: true }),
|
|
117
|
+
customizeContract: () => { throw new Error("No LLM API key configured. Set CLAWCONTRACT_OPENROUTER_API_KEY."); },
|
|
118
|
+
generateContract: () => { throw new Error("No LLM API key configured. Set CLAWCONTRACT_OPENROUTER_API_KEY."); },
|
|
119
|
+
suggestFixes: () => { throw new Error("No LLM API key configured. Set CLAWCONTRACT_OPENROUTER_API_KEY."); },
|
|
120
|
+
};
|
|
121
|
+
export function createLLMClient() {
|
|
122
|
+
const openrouterKey = process.env.CLAWCONTRACT_OPENROUTER_API_KEY;
|
|
123
|
+
if (openrouterKey) {
|
|
124
|
+
return createOpenRouterClient(openrouterKey);
|
|
125
|
+
}
|
|
126
|
+
return NULL_CLIENT;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=llm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/generator/llm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function extractContractName(source: string): string;
|
|
2
|
+
export declare function sanitizeFileName(name: string): string;
|
|
3
|
+
export declare function writeFileUnique(dir: string, fileName: string, content: string): Promise<string>;
|
|
4
|
+
export declare function ensureOutputDir(dir: string): Promise<void>;
|
|
5
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/generator/utils.ts"],"names":[],"mappings":"AAIA,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWrD;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { mkdir } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export function extractContractName(source) {
|
|
5
|
+
const match = source.match(/contract\s+([A-Za-z_][A-Za-z0-9_]*)\s*(?:is\s|{)/);
|
|
6
|
+
if (match) {
|
|
7
|
+
return match[1];
|
|
8
|
+
}
|
|
9
|
+
return "GeneratedContract";
|
|
10
|
+
}
|
|
11
|
+
export function sanitizeFileName(name) {
|
|
12
|
+
const cleaned = name.replace(/[^a-zA-Z0-9]/g, " ");
|
|
13
|
+
const pascal = cleaned
|
|
14
|
+
.split(/\s+/)
|
|
15
|
+
.filter(Boolean)
|
|
16
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
17
|
+
.join("");
|
|
18
|
+
if (!pascal) {
|
|
19
|
+
return "Contract.sol";
|
|
20
|
+
}
|
|
21
|
+
return pascal.endsWith(".sol") ? pascal : `${pascal}.sol`;
|
|
22
|
+
}
|
|
23
|
+
export async function writeFileUnique(dir, fileName, content) {
|
|
24
|
+
const ext = path.extname(fileName);
|
|
25
|
+
const base = fileName.slice(0, -ext.length);
|
|
26
|
+
let candidate = path.resolve(dir, fileName);
|
|
27
|
+
let counter = 0;
|
|
28
|
+
const maxAttempts = 100;
|
|
29
|
+
while (counter < maxAttempts) {
|
|
30
|
+
try {
|
|
31
|
+
await writeFile(candidate, content, { encoding: "utf-8", flag: "wx" });
|
|
32
|
+
return candidate;
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
if (err.code === "EEXIST") {
|
|
36
|
+
counter++;
|
|
37
|
+
candidate = path.resolve(dir, `${base}_${counter}${ext}`);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Could not find unique filename for ${fileName} after ${maxAttempts} attempts`);
|
|
44
|
+
}
|
|
45
|
+
export async function ensureOutputDir(dir) {
|
|
46
|
+
const resolved = path.resolve(dir);
|
|
47
|
+
await mkdir(resolved, { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/generator/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;IAC/E,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,OAAO;SACnB,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SACzE,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,cAAc,CAAC;IACxB,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,MAAM,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAW,EACX,QAAgB,EAChB,OAAe;IAEf,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC5C,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,WAAW,GAAG,GAAG,CAAC;IAExB,OAAO,OAAO,GAAG,WAAW,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACvE,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrD,OAAO,EAAE,CAAC;gBACV,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,OAAO,GAAG,GAAG,EAAE,CAAC,CAAC;gBAC1D,SAAS;YACX,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,sCAAsC,QAAQ,UAAU,WAAW,WAAW,CAAC,CAAC;AAClG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAW;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC"}
|