@caatinga/core 2.3.1 → 2.4.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/dist/{browser-Cq4ZofIq.d.cts → artifact.schema-BH5K-IiZ.d.cts} +2 -1
- package/dist/{browser-Cq4ZofIq.d.ts → artifact.schema-BH5K-IiZ.d.ts} +2 -1
- package/dist/browser.cjs +20 -0
- package/dist/browser.d.cts +5 -1
- package/dist/browser.d.ts +5 -1
- package/dist/browser.js +19 -0
- package/dist/index.cjs +322 -42
- package/dist/index.d.cts +35 -5
- package/dist/index.d.ts +35 -5
- package/dist/index.js +314 -42
- package/package.json +1 -1
- package/scaffolds/soroban-contract-stub/Cargo.toml +24 -0
- package/scaffolds/soroban-contract-stub/src/lib.rs +42 -0
package/dist/index.cjs
CHANGED
|
@@ -37,16 +37,19 @@ __export(index_exports, {
|
|
|
37
37
|
CaatingaConfigSchema: () => CaatingaConfigSchema,
|
|
38
38
|
CaatingaError: () => CaatingaError,
|
|
39
39
|
CaatingaErrorCode: () => CaatingaErrorCode,
|
|
40
|
+
READ_CALL_FAILURE_REGEX: () => READ_CALL_FAILURE_REGEX,
|
|
40
41
|
STELLAR_CLI_LAST_TESTED_VERSION: () => STELLAR_CLI_LAST_TESTED_VERSION,
|
|
41
42
|
STELLAR_CLI_MIN_VERSION: () => STELLAR_CLI_MIN_VERSION,
|
|
42
43
|
TemplateManifestSchema: () => TemplateManifestSchema,
|
|
43
44
|
WELL_KNOWN_NETWORKS: () => WELL_KNOWN_NETWORKS,
|
|
44
45
|
buildContract: () => buildContract,
|
|
45
46
|
buildDependencyGraph: () => buildDependencyGraph,
|
|
47
|
+
buildReadCallHint: () => buildReadCallHint,
|
|
46
48
|
checkBinary: () => checkBinary,
|
|
47
49
|
checkStellarCliVersion: () => checkStellarCliVersion,
|
|
48
50
|
collectProjectStatus: () => collectProjectStatus,
|
|
49
51
|
createInitialArtifacts: () => createInitialArtifacts,
|
|
52
|
+
createMinimalProject: () => createMinimalProject,
|
|
50
53
|
createProjectFromTemplate: () => createProjectFromTemplate,
|
|
51
54
|
createZkProject: () => createZkProject,
|
|
52
55
|
defineConfig: () => defineConfig,
|
|
@@ -59,6 +62,8 @@ __export(index_exports, {
|
|
|
59
62
|
generateBindings: () => generateBindings,
|
|
60
63
|
generateBindingsGraph: () => generateBindingsGraph,
|
|
61
64
|
invokeContract: () => invokeContract,
|
|
65
|
+
isCargoBinMissingFromPath: () => isCargoBinMissingFromPath,
|
|
66
|
+
isReadCallFailure: () => isReadCallFailure,
|
|
62
67
|
isTransientTestnetSmokeFailure: () => isTransientTestnetSmokeFailure,
|
|
63
68
|
loadConfig: () => loadConfig,
|
|
64
69
|
parseContractId: () => parseContractId,
|
|
@@ -66,11 +71,13 @@ __export(index_exports, {
|
|
|
66
71
|
parseStellarCliVersion: () => parseStellarCliVersion,
|
|
67
72
|
readArtifacts: () => readArtifacts,
|
|
68
73
|
readBindingMarker: () => readBindingMarker,
|
|
74
|
+
readContract: () => readContract,
|
|
69
75
|
resolveContract: () => resolveContract,
|
|
70
76
|
resolveDefaultContractName: () => resolveDefaultContractName,
|
|
71
77
|
resolveDeployArgs: () => resolveDeployArgs,
|
|
72
78
|
resolveDeployOrder: () => resolveDeployOrder,
|
|
73
79
|
resolveNetwork: () => resolveNetwork,
|
|
80
|
+
resolveSubprocessEnv: () => resolveSubprocessEnv,
|
|
74
81
|
runCommand: () => runCommand,
|
|
75
82
|
toCaatingaError: () => toCaatingaError,
|
|
76
83
|
updateArtifact: () => updateArtifact,
|
|
@@ -83,6 +90,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
83
90
|
// src/errors/CaatingaErrorCode.ts
|
|
84
91
|
var CaatingaErrorCode = {
|
|
85
92
|
CONFIG_NOT_FOUND: "CAATINGA_CONFIG_NOT_FOUND",
|
|
93
|
+
DEPENDENCIES_NOT_INSTALLED: "CAATINGA_DEPENDENCIES_NOT_INSTALLED",
|
|
86
94
|
INVALID_CONFIG: "CAATINGA_INVALID_CONFIG",
|
|
87
95
|
COMMAND_FAILED: "CAATINGA_COMMAND_FAILED",
|
|
88
96
|
UNEXPECTED_ERROR: "CAATINGA_UNEXPECTED_ERROR",
|
|
@@ -187,7 +195,7 @@ function formatCause(cause) {
|
|
|
187
195
|
}
|
|
188
196
|
|
|
189
197
|
// src/version.ts
|
|
190
|
-
var CAATINGA_CORE_VERSION = "2.
|
|
198
|
+
var CAATINGA_CORE_VERSION = "2.4.0";
|
|
191
199
|
|
|
192
200
|
// src/config/config.schema.ts
|
|
193
201
|
var import_zod = require("zod");
|
|
@@ -239,6 +247,28 @@ var import_promises = require("fs/promises");
|
|
|
239
247
|
var import_node_path = __toESM(require("path"), 1);
|
|
240
248
|
var import_jiti = require("jiti");
|
|
241
249
|
var import_zod2 = require("zod");
|
|
250
|
+
|
|
251
|
+
// src/config/is-dependencies-not-installed-error.ts
|
|
252
|
+
function isDependenciesNotInstalledError(error) {
|
|
253
|
+
if (!error || typeof error !== "object") {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
const candidate = error;
|
|
257
|
+
const code = candidate.code;
|
|
258
|
+
const message = String(candidate.message ?? error);
|
|
259
|
+
if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") {
|
|
260
|
+
return /@caatinga\/core/.test(message);
|
|
261
|
+
}
|
|
262
|
+
if (/Cannot find (module|package).+@caatinga\/core/i.test(message)) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
if (candidate.cause !== void 0) {
|
|
266
|
+
return isDependenciesNotInstalledError(candidate.cause);
|
|
267
|
+
}
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// src/config/load-config.ts
|
|
242
272
|
var import_meta = {};
|
|
243
273
|
async function loadConfig(options = {}) {
|
|
244
274
|
const cwd = options.cwd ?? process.cwd();
|
|
@@ -264,6 +294,14 @@ async function loadConfig(options = {}) {
|
|
|
264
294
|
error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ")
|
|
265
295
|
);
|
|
266
296
|
}
|
|
297
|
+
if (isDependenciesNotInstalledError(error)) {
|
|
298
|
+
throw new CaatingaError(
|
|
299
|
+
"Project dependencies are not installed.",
|
|
300
|
+
CaatingaErrorCode.DEPENDENCIES_NOT_INSTALLED,
|
|
301
|
+
"Run npm install (or pnpm install) in the project root, then retry.",
|
|
302
|
+
error
|
|
303
|
+
);
|
|
304
|
+
}
|
|
267
305
|
throw error;
|
|
268
306
|
}
|
|
269
307
|
}
|
|
@@ -670,6 +708,64 @@ function defaultEmitWarning(warning) {
|
|
|
670
708
|
`);
|
|
671
709
|
}
|
|
672
710
|
|
|
711
|
+
// src/shell/resolve-subprocess-env.ts
|
|
712
|
+
var import_node_fs = require("fs");
|
|
713
|
+
var import_node_os = __toESM(require("os"), 1);
|
|
714
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
715
|
+
function uniquePaths(entries) {
|
|
716
|
+
const seen = /* @__PURE__ */ new Set();
|
|
717
|
+
const ordered = [];
|
|
718
|
+
for (const entry of entries) {
|
|
719
|
+
if (!entry || seen.has(entry)) {
|
|
720
|
+
continue;
|
|
721
|
+
}
|
|
722
|
+
seen.add(entry);
|
|
723
|
+
ordered.push(entry);
|
|
724
|
+
}
|
|
725
|
+
return ordered;
|
|
726
|
+
}
|
|
727
|
+
function hasExecutable(binDir, name) {
|
|
728
|
+
return (0, import_node_fs.existsSync)(import_node_path6.default.join(binDir, name));
|
|
729
|
+
}
|
|
730
|
+
function toolchainBinDirs(home, env) {
|
|
731
|
+
const candidates = [
|
|
732
|
+
import_node_path6.default.join(home, ".cargo", "bin"),
|
|
733
|
+
env.CARGO_HOME ? import_node_path6.default.join(env.CARGO_HOME, "bin") : void 0
|
|
734
|
+
];
|
|
735
|
+
return candidates.filter((entry) => Boolean(entry && (0, import_node_fs.existsSync)(entry)));
|
|
736
|
+
}
|
|
737
|
+
function buildToolchainPrepend(existingPath, toolchainBins, executableExists = hasExecutable) {
|
|
738
|
+
const prepend = [];
|
|
739
|
+
for (const binDir of toolchainBins) {
|
|
740
|
+
const externalStellarDir = existingPath.find(
|
|
741
|
+
(entry) => entry !== binDir && executableExists(entry, "stellar")
|
|
742
|
+
);
|
|
743
|
+
if (externalStellarDir && executableExists(binDir, "stellar")) {
|
|
744
|
+
prepend.push(externalStellarDir);
|
|
745
|
+
}
|
|
746
|
+
prepend.push(binDir);
|
|
747
|
+
}
|
|
748
|
+
return prepend;
|
|
749
|
+
}
|
|
750
|
+
function resolveSubprocessEnv(overrides = {}) {
|
|
751
|
+
const env = { ...process.env, ...overrides };
|
|
752
|
+
const home = env.HOME ?? import_node_os.default.homedir();
|
|
753
|
+
const existingPath = (env.PATH ?? "").split(import_node_path6.default.delimiter).filter(Boolean);
|
|
754
|
+
const toolchainBins = toolchainBinDirs(home, env);
|
|
755
|
+
const prepend = buildToolchainPrepend(existingPath, toolchainBins);
|
|
756
|
+
env.PATH = uniquePaths([...prepend, ...existingPath]).join(import_node_path6.default.delimiter);
|
|
757
|
+
return env;
|
|
758
|
+
}
|
|
759
|
+
function isCargoBinMissingFromPath(baseEnv = process.env) {
|
|
760
|
+
const home = baseEnv.HOME ?? import_node_os.default.homedir();
|
|
761
|
+
const cargoBin = import_node_path6.default.join(home, ".cargo", "bin", "cargo");
|
|
762
|
+
if (!(0, import_node_fs.existsSync)(cargoBin)) {
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
const pathEntries = (baseEnv.PATH ?? "").split(import_node_path6.default.delimiter);
|
|
766
|
+
return !pathEntries.some((entry) => entry === import_node_path6.default.join(home, ".cargo", "bin"));
|
|
767
|
+
}
|
|
768
|
+
|
|
673
769
|
// src/shell/run-command.ts
|
|
674
770
|
async function runCommand(command, args, options = {}) {
|
|
675
771
|
try {
|
|
@@ -678,7 +774,7 @@ async function runCommand(command, args, options = {}) {
|
|
|
678
774
|
}
|
|
679
775
|
const result = await (0, import_execa.execa)(command, args, {
|
|
680
776
|
cwd: options.cwd,
|
|
681
|
-
env: options.env,
|
|
777
|
+
env: resolveSubprocessEnv(options.env ?? {}),
|
|
682
778
|
input: options.input,
|
|
683
779
|
all: true,
|
|
684
780
|
reject: true
|
|
@@ -876,7 +972,7 @@ function validateSourceShape(source) {
|
|
|
876
972
|
}
|
|
877
973
|
|
|
878
974
|
// src/contracts/resolve-contract.ts
|
|
879
|
-
var
|
|
975
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
880
976
|
function resolveContract(config, contractName, cwd = process.cwd()) {
|
|
881
977
|
const contract = config.contracts[contractName];
|
|
882
978
|
if (!contract) {
|
|
@@ -889,8 +985,8 @@ function resolveContract(config, contractName, cwd = process.cwd()) {
|
|
|
889
985
|
return {
|
|
890
986
|
name: contractName,
|
|
891
987
|
config: contract,
|
|
892
|
-
sourcePath:
|
|
893
|
-
wasmPath:
|
|
988
|
+
sourcePath: import_node_path7.default.resolve(cwd, contract.path),
|
|
989
|
+
wasmPath: import_node_path7.default.resolve(cwd, contract.wasm)
|
|
894
990
|
};
|
|
895
991
|
}
|
|
896
992
|
|
|
@@ -910,7 +1006,7 @@ function resolveDefaultContractName(config) {
|
|
|
910
1006
|
// src/contracts/wasm.ts
|
|
911
1007
|
var import_node_crypto = require("crypto");
|
|
912
1008
|
var import_promises6 = require("fs/promises");
|
|
913
|
-
var
|
|
1009
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
914
1010
|
var LEGACY_RUST_WASM_TARGET = "wasm32-unknown-unknown";
|
|
915
1011
|
var CURRENT_RUST_WASM_TARGET = "wasm32v1-none";
|
|
916
1012
|
function toCurrentWasmTargetPath(wasmPath) {
|
|
@@ -933,8 +1029,8 @@ function wasmNotFoundError(configuredWasmPath, options) {
|
|
|
933
1029
|
);
|
|
934
1030
|
}
|
|
935
1031
|
function toConfigRelativeWasmPath(absoluteWasmPath) {
|
|
936
|
-
const relative =
|
|
937
|
-
return relative.startsWith("..") ? absoluteWasmPath : `./${relative.split(
|
|
1032
|
+
const relative = import_node_path8.default.relative(process.cwd(), absoluteWasmPath);
|
|
1033
|
+
return relative.startsWith("..") ? absoluteWasmPath : `./${relative.split(import_node_path8.default.sep).join("/")}`;
|
|
938
1034
|
}
|
|
939
1035
|
async function resolveWasmArtifactPath(configuredWasmPath) {
|
|
940
1036
|
try {
|
|
@@ -967,7 +1063,7 @@ async function getNewestMtimeInDirectory(directory) {
|
|
|
967
1063
|
async function walk(dir) {
|
|
968
1064
|
const entries = await (0, import_promises6.readdir)(dir, { withFileTypes: true });
|
|
969
1065
|
for (const entry of entries) {
|
|
970
|
-
const entryPath =
|
|
1066
|
+
const entryPath = import_node_path8.default.join(dir, entry.name);
|
|
971
1067
|
if (entry.isDirectory()) {
|
|
972
1068
|
await walk(entryPath);
|
|
973
1069
|
continue;
|
|
@@ -983,7 +1079,7 @@ async function getNewestMtimeInDirectory(directory) {
|
|
|
983
1079
|
return newest > 0 ? newest : void 0;
|
|
984
1080
|
}
|
|
985
1081
|
async function isWasmOlderThanSources(input) {
|
|
986
|
-
const srcDir =
|
|
1082
|
+
const srcDir = import_node_path8.default.join(input.contractPath, "src");
|
|
987
1083
|
const newestSourceMtime = await getNewestMtimeInDirectory(srcDir);
|
|
988
1084
|
if (newestSourceMtime === void 0) {
|
|
989
1085
|
return false;
|
|
@@ -1056,7 +1152,7 @@ async function buildContract(options) {
|
|
|
1056
1152
|
}
|
|
1057
1153
|
|
|
1058
1154
|
// src/contracts/deploy-contract.ts
|
|
1059
|
-
var
|
|
1155
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
1060
1156
|
|
|
1061
1157
|
// src/contracts/dependency-graph.ts
|
|
1062
1158
|
function buildDependencyGraph(contracts) {
|
|
@@ -1113,6 +1209,9 @@ function assertSafeSourceAccount(source) {
|
|
|
1113
1209
|
}
|
|
1114
1210
|
return source;
|
|
1115
1211
|
}
|
|
1212
|
+
function resolveCliSource(explicit) {
|
|
1213
|
+
return assertSafeSourceAccount(explicit ?? process.env.CAATINGA_SOURCE ?? "alice");
|
|
1214
|
+
}
|
|
1116
1215
|
|
|
1117
1216
|
// src/contracts/deploy-contract.ts
|
|
1118
1217
|
function toSnakeCaseFlag(key) {
|
|
@@ -1157,7 +1256,7 @@ async function deployContract(options) {
|
|
|
1157
1256
|
contract: contractWithWasm,
|
|
1158
1257
|
network,
|
|
1159
1258
|
contractId: existing.contractId,
|
|
1160
|
-
artifactsPath:
|
|
1259
|
+
artifactsPath: import_node_path9.default.resolve(cwd, "caatinga.artifacts.json"),
|
|
1161
1260
|
output: "",
|
|
1162
1261
|
skipped: true,
|
|
1163
1262
|
staleWasmWarning
|
|
@@ -1434,13 +1533,13 @@ async function deployContractGraph(options) {
|
|
|
1434
1533
|
|
|
1435
1534
|
// src/contracts/generate-bindings.ts
|
|
1436
1535
|
var import_promises7 = require("fs/promises");
|
|
1437
|
-
var
|
|
1536
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
1438
1537
|
function toBindingImportPath(bindingsOutput, contractName) {
|
|
1439
|
-
const normalized = bindingsOutput.replace(/^\.\//, "").split(
|
|
1440
|
-
return `./${
|
|
1538
|
+
const normalized = bindingsOutput.replace(/^\.\//, "").split(import_node_path10.default.sep).join("/");
|
|
1539
|
+
return `./${import_node_path10.default.posix.join(normalized, contractName, "src", "index.js")}`;
|
|
1441
1540
|
}
|
|
1442
1541
|
async function removeLegacyBindingStub(cwd, bindingsOutput, contractName) {
|
|
1443
|
-
const legacyPath =
|
|
1542
|
+
const legacyPath = import_node_path10.default.resolve(cwd, bindingsOutput, `${contractName}.ts`);
|
|
1444
1543
|
try {
|
|
1445
1544
|
await (0, import_promises7.access)(legacyPath);
|
|
1446
1545
|
await (0, import_promises7.unlink)(legacyPath);
|
|
@@ -1469,7 +1568,7 @@ async function generateBindings(options) {
|
|
|
1469
1568
|
);
|
|
1470
1569
|
}
|
|
1471
1570
|
await checkBinary("stellar", "Install Stellar CLI before running caatinga generate.");
|
|
1472
|
-
const outputDir =
|
|
1571
|
+
const outputDir = import_node_path10.default.resolve(cwd, options.config.frontend.bindingsOutput, options.contractName);
|
|
1473
1572
|
await (0, import_promises7.mkdir)(outputDir, { recursive: true });
|
|
1474
1573
|
const result = await runCommand("stellar", [
|
|
1475
1574
|
"contract",
|
|
@@ -1543,8 +1642,8 @@ async function generateBindingsGraph(options) {
|
|
|
1543
1642
|
return { network, results };
|
|
1544
1643
|
}
|
|
1545
1644
|
|
|
1546
|
-
// src/contracts/invoke-
|
|
1547
|
-
var
|
|
1645
|
+
// src/contracts/invoke-target.ts
|
|
1646
|
+
var READ_CALL_FAILURE_REGEX = /this is a read call|read-only/i;
|
|
1548
1647
|
function parseInvokeTarget(target) {
|
|
1549
1648
|
const [contractName, method, extra] = target.split(".");
|
|
1550
1649
|
if (!contractName || !method || extra) {
|
|
@@ -1556,6 +1655,29 @@ function parseInvokeTarget(target) {
|
|
|
1556
1655
|
}
|
|
1557
1656
|
return { contractName, method };
|
|
1558
1657
|
}
|
|
1658
|
+
function buildReadCallHint(target, networkName) {
|
|
1659
|
+
return [
|
|
1660
|
+
`"${target.contractName}.${target.method}" is a read-only contract method.`,
|
|
1661
|
+
"Simulate without signing instead:",
|
|
1662
|
+
` npx caatinga read ${target.contractName}.${target.method} --network ${networkName}`,
|
|
1663
|
+
" (--source is optional; Caatinga resolves CAATINGA_SOURCE or defaults to alice)",
|
|
1664
|
+
"In browser code, use:",
|
|
1665
|
+
` client.contract("${target.contractName}").read("${target.method}")`,
|
|
1666
|
+
` client.contract("${target.contractName}").simulate("${target.method}")`,
|
|
1667
|
+
"Pass method args as the second argument to read() when the contract method takes parameters.",
|
|
1668
|
+
"Only pass Stellar CLI --force when you intentionally need a signed read simulation."
|
|
1669
|
+
].join("\n");
|
|
1670
|
+
}
|
|
1671
|
+
function isReadCallFailure(error) {
|
|
1672
|
+
if (!(error instanceof CaatingaError) || error.code !== CaatingaErrorCode.INVOKE_FAILED) {
|
|
1673
|
+
return false;
|
|
1674
|
+
}
|
|
1675
|
+
return READ_CALL_FAILURE_REGEX.test(`${error.message}
|
|
1676
|
+
${error.hint ?? ""}`);
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
// src/contracts/invoke-contract.ts
|
|
1680
|
+
var INVOKE_SIGNING_FAILURE_REGEX = /xdr processing error: xdr value invalid/i;
|
|
1559
1681
|
async function invokeContract(options) {
|
|
1560
1682
|
const cwd = options.cwd ?? process.cwd();
|
|
1561
1683
|
const network = resolveNetwork(options.config, options.networkName);
|
|
@@ -1589,6 +1711,14 @@ async function invokeContract(options) {
|
|
|
1589
1711
|
failureCode: CaatingaErrorCode.INVOKE_FAILED
|
|
1590
1712
|
});
|
|
1591
1713
|
} catch (error) {
|
|
1714
|
+
if (error instanceof CaatingaError && error.code === CaatingaErrorCode.INVOKE_FAILED && isReadCallFailure(error)) {
|
|
1715
|
+
throw new CaatingaError(
|
|
1716
|
+
error.message,
|
|
1717
|
+
error.code,
|
|
1718
|
+
buildReadCallHint(target, network.name),
|
|
1719
|
+
error
|
|
1720
|
+
);
|
|
1721
|
+
}
|
|
1592
1722
|
if (error instanceof CaatingaError && error.code === CaatingaErrorCode.INVOKE_FAILED && INVOKE_SIGNING_FAILURE_REGEX.test(`${error.message}
|
|
1593
1723
|
${error.hint ?? ""}`)) {
|
|
1594
1724
|
throw new CaatingaError(
|
|
@@ -1614,9 +1744,48 @@ ${error.hint ?? ""}`)) {
|
|
|
1614
1744
|
};
|
|
1615
1745
|
}
|
|
1616
1746
|
|
|
1747
|
+
// src/contracts/read-contract.ts
|
|
1748
|
+
async function readContract(options) {
|
|
1749
|
+
const cwd = options.cwd ?? process.cwd();
|
|
1750
|
+
const network = resolveNetwork(options.config, options.networkName);
|
|
1751
|
+
const target = parseInvokeTarget(options.target);
|
|
1752
|
+
const artifacts = await readArtifacts(cwd);
|
|
1753
|
+
const contractArtifact = artifacts.networks[network.name]?.contracts[target.contractName];
|
|
1754
|
+
if (!contractArtifact) {
|
|
1755
|
+
throw new CaatingaError(
|
|
1756
|
+
`No deployed artifact found for "${target.contractName}" on "${network.name}".`,
|
|
1757
|
+
CaatingaErrorCode.ARTIFACT_NOT_FOUND,
|
|
1758
|
+
"Run caatinga deploy for this contract and network before reading it."
|
|
1759
|
+
);
|
|
1760
|
+
}
|
|
1761
|
+
await checkBinary("stellar", "Install Stellar CLI before running caatinga read.");
|
|
1762
|
+
const stellarArgs = [
|
|
1763
|
+
"contract",
|
|
1764
|
+
"invoke",
|
|
1765
|
+
"--id",
|
|
1766
|
+
contractArtifact.contractId,
|
|
1767
|
+
"--source-account",
|
|
1768
|
+
resolveCliSource(options.source),
|
|
1769
|
+
"--send=no",
|
|
1770
|
+
...buildStellarNetworkArgs(network),
|
|
1771
|
+
"--",
|
|
1772
|
+
target.method,
|
|
1773
|
+
...options.args ?? []
|
|
1774
|
+
];
|
|
1775
|
+
const result = await runCommand("stellar", stellarArgs, {
|
|
1776
|
+
cwd,
|
|
1777
|
+
failureCode: CaatingaErrorCode.INVOKE_FAILED
|
|
1778
|
+
});
|
|
1779
|
+
return {
|
|
1780
|
+
target,
|
|
1781
|
+
network,
|
|
1782
|
+
result: result.stdout || result.all
|
|
1783
|
+
};
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1617
1786
|
// src/templates/create-project-from-template.ts
|
|
1618
1787
|
var import_promises8 = require("fs/promises");
|
|
1619
|
-
var
|
|
1788
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
1620
1789
|
var import_zod7 = require("zod");
|
|
1621
1790
|
|
|
1622
1791
|
// src/templates/template-manifest.schema.ts
|
|
@@ -1692,8 +1861,8 @@ var TEMPLATE_COPY_EXCLUDED_DIRS = /* @__PURE__ */ new Set([
|
|
|
1692
1861
|
".git"
|
|
1693
1862
|
]);
|
|
1694
1863
|
async function createProjectFromTemplate(options) {
|
|
1695
|
-
const targetDir =
|
|
1696
|
-
const templateDir =
|
|
1864
|
+
const targetDir = import_node_path11.default.resolve(options.targetDir);
|
|
1865
|
+
const templateDir = import_node_path11.default.resolve(options.templateDir);
|
|
1697
1866
|
try {
|
|
1698
1867
|
await (0, import_promises8.stat)(templateDir);
|
|
1699
1868
|
} catch {
|
|
@@ -1731,7 +1900,7 @@ async function ensureArtifacts(targetDir, projectName) {
|
|
|
1731
1900
|
}
|
|
1732
1901
|
}
|
|
1733
1902
|
async function readTemplateManifest(templateDir) {
|
|
1734
|
-
const manifestPath =
|
|
1903
|
+
const manifestPath = import_node_path11.default.join(templateDir, "caatinga.template.json");
|
|
1735
1904
|
try {
|
|
1736
1905
|
const rawManifest = await (0, import_promises8.readFile)(manifestPath, "utf8");
|
|
1737
1906
|
const manifest = TemplateManifestSchema.parse(JSON.parse(rawManifest));
|
|
@@ -1768,7 +1937,7 @@ async function readTemplateManifest(templateDir) {
|
|
|
1768
1937
|
async function replaceTemplateVariables(dir, projectName) {
|
|
1769
1938
|
const entries = await (0, import_promises8.readdir)(dir);
|
|
1770
1939
|
await Promise.all(entries.map(async (entry) => {
|
|
1771
|
-
const entryPath =
|
|
1940
|
+
const entryPath = import_node_path11.default.join(dir, entry);
|
|
1772
1941
|
const entryStat = await (0, import_promises8.stat)(entryPath);
|
|
1773
1942
|
if (entryStat.isDirectory()) {
|
|
1774
1943
|
await replaceTemplateVariables(entryPath, projectName);
|
|
@@ -1782,15 +1951,15 @@ async function replaceTemplateVariables(dir, projectName) {
|
|
|
1782
1951
|
}));
|
|
1783
1952
|
}
|
|
1784
1953
|
function shouldCopyTemplateEntry(templateDir, source, userFilter) {
|
|
1785
|
-
const relativePath =
|
|
1954
|
+
const relativePath = import_node_path11.default.relative(templateDir, source);
|
|
1786
1955
|
if (!relativePath || relativePath === ".") {
|
|
1787
1956
|
return true;
|
|
1788
1957
|
}
|
|
1789
|
-
const normalizedPath = relativePath.split(
|
|
1958
|
+
const normalizedPath = relativePath.split(import_node_path11.default.sep).join("/");
|
|
1790
1959
|
if (userFilter && !userFilter(normalizedPath)) {
|
|
1791
1960
|
return false;
|
|
1792
1961
|
}
|
|
1793
|
-
return !relativePath.split(
|
|
1962
|
+
return !relativePath.split(import_node_path11.default.sep).some((segment) => TEMPLATE_COPY_EXCLUDED_DIRS.has(segment));
|
|
1794
1963
|
}
|
|
1795
1964
|
function isTextTemplateFile(filePath) {
|
|
1796
1965
|
return [
|
|
@@ -1802,22 +1971,22 @@ function isTextTemplateFile(filePath) {
|
|
|
1802
1971
|
".tsx",
|
|
1803
1972
|
".css",
|
|
1804
1973
|
".html"
|
|
1805
|
-
].includes(
|
|
1974
|
+
].includes(import_node_path11.default.extname(filePath));
|
|
1806
1975
|
}
|
|
1807
1976
|
|
|
1808
1977
|
// src/scaffold/create-zk-project.ts
|
|
1809
1978
|
var import_promises9 = require("fs/promises");
|
|
1810
|
-
var
|
|
1811
|
-
var
|
|
1979
|
+
var import_node_fs2 = require("fs");
|
|
1980
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
1812
1981
|
var import_node_url = require("url");
|
|
1813
1982
|
var import_meta2 = {};
|
|
1814
|
-
var moduleDir = typeof __dirname === "string" ? __dirname :
|
|
1983
|
+
var moduleDir = typeof __dirname === "string" ? __dirname : import_node_path12.default.dirname((0, import_node_url.fileURLToPath)(import_meta2.url));
|
|
1815
1984
|
function scaffoldRoot() {
|
|
1816
1985
|
const candidates = [
|
|
1817
|
-
|
|
1818
|
-
|
|
1986
|
+
import_node_path12.default.resolve(moduleDir, "../../scaffolds"),
|
|
1987
|
+
import_node_path12.default.resolve(moduleDir, "../scaffolds")
|
|
1819
1988
|
];
|
|
1820
|
-
const found = candidates.find((candidate) => (0,
|
|
1989
|
+
const found = candidates.find((candidate) => (0, import_node_fs2.existsSync)(candidate));
|
|
1821
1990
|
return found ?? candidates[0];
|
|
1822
1991
|
}
|
|
1823
1992
|
function configSource(projectName) {
|
|
@@ -1889,25 +2058,25 @@ Replace \`circuits/main.circom\` with your circuit. Keep the entry point named \
|
|
|
1889
2058
|
`;
|
|
1890
2059
|
}
|
|
1891
2060
|
async function createZkProject(options) {
|
|
1892
|
-
const targetDir =
|
|
2061
|
+
const targetDir = import_node_path12.default.resolve(options.targetDir);
|
|
1893
2062
|
const force = options.force ?? false;
|
|
1894
2063
|
const projectFiles = options.projectFiles ?? true;
|
|
1895
2064
|
await (0, import_promises9.mkdir)(targetDir, { recursive: true });
|
|
1896
2065
|
if (projectFiles) {
|
|
1897
2066
|
await Promise.all([
|
|
1898
|
-
(0, import_promises9.writeFile)(
|
|
1899
|
-
(0, import_promises9.writeFile)(
|
|
1900
|
-
(0, import_promises9.writeFile)(
|
|
1901
|
-
(0, import_promises9.writeFile)(
|
|
2067
|
+
(0, import_promises9.writeFile)(import_node_path12.default.join(targetDir, "caatinga.config.ts"), configSource(options.projectName), { encoding: "utf8", flag: force ? "w" : "wx" }),
|
|
2068
|
+
(0, import_promises9.writeFile)(import_node_path12.default.join(targetDir, "package.json"), packageJsonSource(options.projectName), { encoding: "utf8", flag: force ? "w" : "wx" }),
|
|
2069
|
+
(0, import_promises9.writeFile)(import_node_path12.default.join(targetDir, ".gitignore"), "node_modules\n.artifacts\ntarget\n", { encoding: "utf8", flag: force ? "w" : "wx" }),
|
|
2070
|
+
(0, import_promises9.writeFile)(import_node_path12.default.join(targetDir, "README.md"), readmeSource(options.projectName), { encoding: "utf8", flag: force ? "w" : "wx" })
|
|
1902
2071
|
]);
|
|
1903
2072
|
}
|
|
1904
|
-
await (0, import_promises9.mkdir)(
|
|
1905
|
-
await (0, import_promises9.cp)(
|
|
2073
|
+
await (0, import_promises9.mkdir)(import_node_path12.default.join(targetDir, "contracts"), { recursive: true });
|
|
2074
|
+
await (0, import_promises9.cp)(import_node_path12.default.join(scaffoldRoot(), "zk-circuit-stub"), import_node_path12.default.join(targetDir, "circuits"), {
|
|
1906
2075
|
recursive: true,
|
|
1907
2076
|
force,
|
|
1908
2077
|
errorOnExist: !force
|
|
1909
2078
|
});
|
|
1910
|
-
await (0, import_promises9.cp)(
|
|
2079
|
+
await (0, import_promises9.cp)(import_node_path12.default.join(scaffoldRoot(), "zk-verifier"), import_node_path12.default.join(targetDir, "contracts", "verifier"), {
|
|
1911
2080
|
recursive: true,
|
|
1912
2081
|
force,
|
|
1913
2082
|
errorOnExist: !force
|
|
@@ -1918,6 +2087,110 @@ async function createZkProject(options) {
|
|
|
1918
2087
|
return { targetDir };
|
|
1919
2088
|
}
|
|
1920
2089
|
|
|
2090
|
+
// src/scaffold/create-minimal-project.ts
|
|
2091
|
+
var import_promises10 = require("fs/promises");
|
|
2092
|
+
var import_node_fs3 = require("fs");
|
|
2093
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
2094
|
+
var import_node_url2 = require("url");
|
|
2095
|
+
var import_meta3 = {};
|
|
2096
|
+
var moduleDir2 = typeof __dirname === "string" ? __dirname : import_node_path13.default.dirname((0, import_node_url2.fileURLToPath)(import_meta3.url));
|
|
2097
|
+
function scaffoldRoot2() {
|
|
2098
|
+
const candidates = [
|
|
2099
|
+
import_node_path13.default.resolve(moduleDir2, "../../scaffolds"),
|
|
2100
|
+
import_node_path13.default.resolve(moduleDir2, "../scaffolds")
|
|
2101
|
+
];
|
|
2102
|
+
const found = candidates.find((candidate) => (0, import_node_fs3.existsSync)(candidate));
|
|
2103
|
+
return found ?? candidates[0];
|
|
2104
|
+
}
|
|
2105
|
+
function configSource2(projectName) {
|
|
2106
|
+
return `import { defineConfig } from "@caatinga/core";
|
|
2107
|
+
|
|
2108
|
+
export default defineConfig({
|
|
2109
|
+
project: "${projectName}",
|
|
2110
|
+
defaultNetwork: "testnet",
|
|
2111
|
+
contracts: {
|
|
2112
|
+
app: {
|
|
2113
|
+
path: "./contracts/app",
|
|
2114
|
+
wasm: "./contracts/app/target/wasm32v1-none/release/app.wasm"
|
|
2115
|
+
}
|
|
2116
|
+
},
|
|
2117
|
+
networks: {
|
|
2118
|
+
testnet: {
|
|
2119
|
+
rpcUrl: "https://soroban-testnet.stellar.org",
|
|
2120
|
+
networkPassphrase: "Test SDF Network ; September 2015"
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
});
|
|
2124
|
+
`;
|
|
2125
|
+
}
|
|
2126
|
+
function packageJsonSource2(projectName) {
|
|
2127
|
+
return `${JSON.stringify({
|
|
2128
|
+
name: projectName,
|
|
2129
|
+
version: "0.1.0",
|
|
2130
|
+
private: true,
|
|
2131
|
+
type: "module",
|
|
2132
|
+
scripts: {
|
|
2133
|
+
build: "caatinga build app",
|
|
2134
|
+
deploy: "caatinga deploy app --network testnet --source ${CAATINGA_SOURCE:-alice}",
|
|
2135
|
+
doctor: "caatinga doctor",
|
|
2136
|
+
"read:hello": "caatinga read app.hello --network testnet --source ${CAATINGA_SOURCE:-alice}",
|
|
2137
|
+
"read:version": "caatinga read app.version --network testnet --source ${CAATINGA_SOURCE:-alice}"
|
|
2138
|
+
},
|
|
2139
|
+
devDependencies: {
|
|
2140
|
+
"@caatinga/cli": `^${CAATINGA_CORE_VERSION}`,
|
|
2141
|
+
"@caatinga/core": `^${CAATINGA_CORE_VERSION}`
|
|
2142
|
+
}
|
|
2143
|
+
}, null, 2)}
|
|
2144
|
+
`;
|
|
2145
|
+
}
|
|
2146
|
+
function readmeSource2(projectName) {
|
|
2147
|
+
return `# ${projectName}
|
|
2148
|
+
|
|
2149
|
+
Minimal Caatinga project with a Soroban contract stub (no frontend template).
|
|
2150
|
+
|
|
2151
|
+
## Workflow
|
|
2152
|
+
|
|
2153
|
+
\`\`\`bash
|
|
2154
|
+
npm install
|
|
2155
|
+
npx caatinga doctor
|
|
2156
|
+
npx caatinga build app
|
|
2157
|
+
npx caatinga deploy app --network testnet --source <identity>
|
|
2158
|
+
npx caatinga read app.version --network testnet
|
|
2159
|
+
npx caatinga read app.hello --network testnet
|
|
2160
|
+
\`\`\`
|
|
2161
|
+
|
|
2162
|
+
## Contract
|
|
2163
|
+
|
|
2164
|
+
- \`hello()\` \u2014 read-only; returns Soroban Symbol \`hello\`
|
|
2165
|
+
- \`version()\` \u2014 read-only; returns \`1\`
|
|
2166
|
+
|
|
2167
|
+
Use \`caatinga read\` for read-only methods. Use \`caatinga invoke\` only after you add state-changing methods to the contract.
|
|
2168
|
+
|
|
2169
|
+
Soroban \`Symbol\` parameters are generated as TypeScript \`string\` values with host-specific restrictions \u2014 see the Caatinga docs on [Soroban types](https://github.com/caatinga/caatinga/blob/main/docs/soroban-types.md).
|
|
2170
|
+
|
|
2171
|
+
Edit \`contracts/app/src/lib.rs\` to customize the contract. Add a frontend later with \`@caatinga/client\` and your chosen UI stack.
|
|
2172
|
+
`;
|
|
2173
|
+
}
|
|
2174
|
+
async function createMinimalProject(options) {
|
|
2175
|
+
const targetDir = import_node_path13.default.resolve(options.targetDir);
|
|
2176
|
+
const force = options.force ?? false;
|
|
2177
|
+
await (0, import_promises10.mkdir)(targetDir, { recursive: true });
|
|
2178
|
+
await Promise.all([
|
|
2179
|
+
(0, import_promises10.writeFile)(import_node_path13.default.join(targetDir, "caatinga.config.ts"), configSource2(options.projectName), { encoding: "utf8", flag: force ? "w" : "wx" }),
|
|
2180
|
+
(0, import_promises10.writeFile)(import_node_path13.default.join(targetDir, "package.json"), packageJsonSource2(options.projectName), { encoding: "utf8", flag: force ? "w" : "wx" }),
|
|
2181
|
+
(0, import_promises10.writeFile)(import_node_path13.default.join(targetDir, ".gitignore"), "node_modules\n.artifacts\ntarget\n", { encoding: "utf8", flag: force ? "w" : "wx" }),
|
|
2182
|
+
(0, import_promises10.writeFile)(import_node_path13.default.join(targetDir, "README.md"), readmeSource2(options.projectName), { encoding: "utf8", flag: force ? "w" : "wx" })
|
|
2183
|
+
]);
|
|
2184
|
+
await (0, import_promises10.mkdir)(import_node_path13.default.join(targetDir, "contracts"), { recursive: true });
|
|
2185
|
+
await (0, import_promises10.cp)(import_node_path13.default.join(scaffoldRoot2(), "soroban-contract-stub"), import_node_path13.default.join(targetDir, "contracts", "app"), {
|
|
2186
|
+
recursive: true,
|
|
2187
|
+
force,
|
|
2188
|
+
errorOnExist: !force
|
|
2189
|
+
});
|
|
2190
|
+
await writeArtifacts(createInitialArtifacts(options.projectName, { networks: ["testnet"] }), targetDir);
|
|
2191
|
+
return { targetDir };
|
|
2192
|
+
}
|
|
2193
|
+
|
|
1921
2194
|
// src/ci/is-transient-testnet-smoke-failure.ts
|
|
1922
2195
|
var NO_RETRY_CAATINGA_SUBSTRINGS = [
|
|
1923
2196
|
"CAATINGA_UNSUPPORTED_CLI_VERSION",
|
|
@@ -1947,16 +2220,19 @@ function isTransientTestnetSmokeFailure(logText) {
|
|
|
1947
2220
|
CaatingaConfigSchema,
|
|
1948
2221
|
CaatingaError,
|
|
1949
2222
|
CaatingaErrorCode,
|
|
2223
|
+
READ_CALL_FAILURE_REGEX,
|
|
1950
2224
|
STELLAR_CLI_LAST_TESTED_VERSION,
|
|
1951
2225
|
STELLAR_CLI_MIN_VERSION,
|
|
1952
2226
|
TemplateManifestSchema,
|
|
1953
2227
|
WELL_KNOWN_NETWORKS,
|
|
1954
2228
|
buildContract,
|
|
1955
2229
|
buildDependencyGraph,
|
|
2230
|
+
buildReadCallHint,
|
|
1956
2231
|
checkBinary,
|
|
1957
2232
|
checkStellarCliVersion,
|
|
1958
2233
|
collectProjectStatus,
|
|
1959
2234
|
createInitialArtifacts,
|
|
2235
|
+
createMinimalProject,
|
|
1960
2236
|
createProjectFromTemplate,
|
|
1961
2237
|
createZkProject,
|
|
1962
2238
|
defineConfig,
|
|
@@ -1969,6 +2245,8 @@ function isTransientTestnetSmokeFailure(logText) {
|
|
|
1969
2245
|
generateBindings,
|
|
1970
2246
|
generateBindingsGraph,
|
|
1971
2247
|
invokeContract,
|
|
2248
|
+
isCargoBinMissingFromPath,
|
|
2249
|
+
isReadCallFailure,
|
|
1972
2250
|
isTransientTestnetSmokeFailure,
|
|
1973
2251
|
loadConfig,
|
|
1974
2252
|
parseContractId,
|
|
@@ -1976,11 +2254,13 @@ function isTransientTestnetSmokeFailure(logText) {
|
|
|
1976
2254
|
parseStellarCliVersion,
|
|
1977
2255
|
readArtifacts,
|
|
1978
2256
|
readBindingMarker,
|
|
2257
|
+
readContract,
|
|
1979
2258
|
resolveContract,
|
|
1980
2259
|
resolveDefaultContractName,
|
|
1981
2260
|
resolveDeployArgs,
|
|
1982
2261
|
resolveDeployOrder,
|
|
1983
2262
|
resolveNetwork,
|
|
2263
|
+
resolveSubprocessEnv,
|
|
1984
2264
|
runCommand,
|
|
1985
2265
|
toCaatingaError,
|
|
1986
2266
|
updateArtifact,
|