@caatinga/core 3.1.2 → 3.3.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/index.cjs CHANGED
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  BINDING_MARKER_FILENAME: () => BINDING_MARKER_FILENAME,
34
34
  BindingMarkerSchema: () => BindingMarkerSchema,
35
35
  CAATINGA_CORE_VERSION: () => CAATINGA_CORE_VERSION,
36
+ CURRENT_ARTIFACTS_SCHEMA_VERSION: () => CURRENT_ARTIFACTS_SCHEMA_VERSION,
36
37
  CaatingaArtifactsSchema: () => CaatingaArtifactsSchema,
37
38
  CaatingaConfigSchema: () => CaatingaConfigSchema,
38
39
  CaatingaError: () => CaatingaError,
@@ -40,6 +41,8 @@ __export(index_exports, {
40
41
  READ_CALL_FAILURE_REGEX: () => READ_CALL_FAILURE_REGEX,
41
42
  STELLAR_CLI_LAST_TESTED_VERSION: () => STELLAR_CLI_LAST_TESTED_VERSION,
42
43
  STELLAR_CLI_MIN_VERSION: () => STELLAR_CLI_MIN_VERSION,
44
+ STELLAR_SDK_LAST_TESTED_VERSION: () => STELLAR_SDK_LAST_TESTED_VERSION,
45
+ STELLAR_SDK_MIN_VERSION: () => STELLAR_SDK_MIN_VERSION,
43
46
  TemplateManifestSchema: () => TemplateManifestSchema,
44
47
  WELL_KNOWN_NETWORKS: () => WELL_KNOWN_NETWORKS,
45
48
  buildContract: () => buildContract,
@@ -47,6 +50,7 @@ __export(index_exports, {
47
50
  buildReadCallHint: () => buildReadCallHint,
48
51
  checkBinary: () => checkBinary,
49
52
  checkStellarCliVersion: () => checkStellarCliVersion,
53
+ checkStellarSdkVersion: () => checkStellarSdkVersion,
50
54
  collectProjectStatus: () => collectProjectStatus,
51
55
  createInitialArtifacts: () => createInitialArtifacts,
52
56
  createMinimalProject: () => createMinimalProject,
@@ -55,20 +59,26 @@ __export(index_exports, {
55
59
  defineConfig: () => defineConfig,
56
60
  deployContract: () => deployContract,
57
61
  deployContractGraph: () => deployContractGraph,
62
+ estimateDeployCost: () => estimateDeployCost,
58
63
  evaluateBindingFreshness: () => evaluateBindingFreshness,
59
64
  evaluateBindingsFreshness: () => evaluateBindingsFreshness,
60
65
  evaluateStellarCliCompatibility: () => evaluateStellarCliCompatibility,
66
+ evaluateStellarSdkCompatibility: () => evaluateStellarSdkCompatibility,
61
67
  formatCaatingaError: () => formatCaatingaError,
62
68
  generateBindings: () => generateBindings,
63
69
  generateBindingsGraph: () => generateBindingsGraph,
70
+ inspectContract: () => inspectContract,
64
71
  invokeContract: () => invokeContract,
65
72
  isCargoBinMissingFromPath: () => isCargoBinMissingFromPath,
66
73
  isReadCallFailure: () => isReadCallFailure,
67
74
  isTransientTestnetSmokeFailure: () => isTransientTestnetSmokeFailure,
68
75
  loadConfig: () => loadConfig,
76
+ migrateArtifactsFile: () => migrateArtifactsFile,
77
+ migrateArtifactsToV2: () => migrateArtifactsToV2,
69
78
  parseContractId: () => parseContractId,
70
79
  parseInvokeTarget: () => parseInvokeTarget,
71
80
  parseStellarCliVersion: () => parseStellarCliVersion,
81
+ parseStellarSdkVersion: () => parseStellarSdkVersion,
72
82
  readArtifacts: () => readArtifacts,
73
83
  readBindingMarker: () => readBindingMarker,
74
84
  readContract: () => readContract,
@@ -78,6 +88,8 @@ __export(index_exports, {
78
88
  resolveDeployOrder: () => resolveDeployOrder,
79
89
  resolveNetwork: () => resolveNetwork,
80
90
  resolveSubprocessEnv: () => resolveSubprocessEnv,
91
+ restoreArtifactFromHistory: () => restoreArtifactFromHistory,
92
+ rollbackContractArtifact: () => rollbackContractArtifact,
81
93
  runCommand: () => runCommand,
82
94
  toCaatingaError: () => toCaatingaError,
83
95
  updateArtifact: () => updateArtifact,
@@ -97,6 +109,8 @@ var CaatingaErrorCode = {
97
109
  STELLAR_CLI_NOT_FOUND: "CAATINGA_STELLAR_CLI_NOT_FOUND",
98
110
  STELLAR_CLI_VERSION_PARSE_FAILED: "CAATINGA_STELLAR_CLI_VERSION_PARSE_FAILED",
99
111
  UNSUPPORTED_CLI_VERSION: "CAATINGA_UNSUPPORTED_CLI_VERSION",
112
+ STELLAR_SDK_VERSION_PARSE_FAILED: "CAATINGA_STELLAR_SDK_VERSION_PARSE_FAILED",
113
+ UNSUPPORTED_SDK_VERSION: "CAATINGA_UNSUPPORTED_SDK_VERSION",
100
114
  RUST_NOT_FOUND: "CAATINGA_RUST_NOT_FOUND",
101
115
  RUST_TARGET_NOT_FOUND: "CAATINGA_RUST_TARGET_NOT_FOUND",
102
116
  DEPLOY_FAILED: "CAATINGA_DEPLOY_FAILED",
@@ -137,7 +151,10 @@ var CaatingaErrorCode = {
137
151
  TEMPLATE_MANIFEST_NOT_FOUND: "CAATINGA_TEMPLATE_MANIFEST_NOT_FOUND",
138
152
  TEMPLATE_INCOMPATIBLE: "CAATINGA_TEMPLATE_INCOMPATIBLE",
139
153
  ZK_VERIFICATION_FAILED: "CAATINGA_ZK_VERIFICATION_FAILED",
154
+ ZK_DEV_CEREMONY_BLOCKED: "CAATINGA_ZK_DEV_CEREMONY_BLOCKED",
140
155
  DOCTOR_PARTIAL_DEPLOY: "CAATINGA_DOCTOR_PARTIAL_DEPLOY",
156
+ ROLLBACK_TARGET_NOT_FOUND: "CAATINGA_ROLLBACK_TARGET_NOT_FOUND",
157
+ ESTIMATE_FAILED: "CAATINGA_ESTIMATE_FAILED",
141
158
  MULTI_AUTH_REQUIRED: "CAATINGA_MULTI_AUTH_REQUIRED"
142
159
  };
143
160
 
@@ -155,7 +172,8 @@ var CaatingaError = class extends Error {
155
172
  cause;
156
173
  };
157
174
  var ZK_ERROR_CODE_MAP = {
158
- ZK_VERIFY_FAILED: CaatingaErrorCode.ZK_VERIFICATION_FAILED
175
+ ZK_VERIFY_FAILED: CaatingaErrorCode.ZK_VERIFICATION_FAILED,
176
+ ZK_DEV_CEREMONY_BLOCKED: CaatingaErrorCode.ZK_DEV_CEREMONY_BLOCKED
159
177
  };
160
178
  function toCaatingaError(error) {
161
179
  if (error instanceof CaatingaError) {
@@ -248,7 +266,7 @@ var CaatingaConfigSchema = import_zod.z.object({
248
266
  "At least one network must be configured."
249
267
  ),
250
268
  frontend: import_zod.z.object({
251
- framework: import_zod.z.enum(["vite-react", "next", "astro"]).default("vite-react"),
269
+ framework: import_zod.z.literal("vite-react").default("vite-react"),
252
270
  bindingsOutput: import_zod.z.string().min(1)
253
271
  }).optional(),
254
272
  zk: ZkConfigSchema
@@ -325,6 +343,14 @@ async function loadConfig(options = {}) {
325
343
 
326
344
  // src/artifacts/artifact.schema.ts
327
345
  var import_zod3 = require("zod");
346
+ var ArtifactSupersedeReasonSchema = import_zod3.z.enum(["upgrade", "rollback", "force-redeploy"]);
347
+ var ContractArtifactHistoryEntrySchema = import_zod3.z.object({
348
+ contractId: import_zod3.z.string().min(1),
349
+ wasmHash: import_zod3.z.string().min(1),
350
+ deployedAt: import_zod3.z.string().datetime(),
351
+ supersededAt: import_zod3.z.string().datetime(),
352
+ reason: ArtifactSupersedeReasonSchema.optional()
353
+ });
328
354
  var ContractArtifactSchema = import_zod3.z.object({
329
355
  contractId: import_zod3.z.string().min(1),
330
356
  wasmHash: import_zod3.z.string().min(1),
@@ -332,17 +358,28 @@ var ContractArtifactSchema = import_zod3.z.object({
332
358
  sourcePath: import_zod3.z.string().min(1),
333
359
  wasmPath: import_zod3.z.string().min(1),
334
360
  dependencies: import_zod3.z.array(import_zod3.z.string().min(1)).default([]),
335
- resolvedDeployArgs: import_zod3.z.record(import_zod3.z.string().min(1), import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number(), import_zod3.z.boolean()])).default({})
361
+ resolvedDeployArgs: import_zod3.z.record(import_zod3.z.string().min(1), import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number(), import_zod3.z.boolean()])).default({}),
362
+ history: import_zod3.z.array(ContractArtifactHistoryEntrySchema).optional()
336
363
  });
337
364
  var NetworkArtifactsSchema = import_zod3.z.object({
338
365
  contracts: import_zod3.z.record(import_zod3.z.string().min(1), ContractArtifactSchema).default({}),
339
366
  dependencyGraph: import_zod3.z.record(import_zod3.z.string().min(1), import_zod3.z.array(import_zod3.z.string().min(1))).default({})
340
367
  });
341
- var CaatingaArtifactsSchema = import_zod3.z.object({
368
+ var CaatingaArtifactsBaseSchema = import_zod3.z.object({
342
369
  project: import_zod3.z.string().min(1),
343
- version: import_zod3.z.literal(1),
344
370
  networks: import_zod3.z.record(import_zod3.z.string().min(1), NetworkArtifactsSchema).default({})
345
371
  });
372
+ var CaatingaArtifactsV1Schema = CaatingaArtifactsBaseSchema.extend({
373
+ version: import_zod3.z.literal(1)
374
+ });
375
+ var CaatingaArtifactsV2Schema = CaatingaArtifactsBaseSchema.extend({
376
+ version: import_zod3.z.literal(2)
377
+ });
378
+ var CaatingaArtifactsSchema = import_zod3.z.union([
379
+ CaatingaArtifactsV1Schema,
380
+ CaatingaArtifactsV2Schema
381
+ ]);
382
+ var CURRENT_ARTIFACTS_SCHEMA_VERSION = 2;
346
383
 
347
384
  // src/artifacts/read-artifacts.ts
348
385
  var import_promises2 = require("fs/promises");
@@ -394,29 +431,139 @@ function createInitialArtifacts(project, options = {}) {
394
431
  );
395
432
  return {
396
433
  project,
397
- version: 1,
434
+ version: 2,
398
435
  networks
399
436
  };
400
437
  }
401
438
 
402
439
  // src/artifacts/update-artifact.ts
403
- function updateArtifact(artifacts, networkName, contractName, contractArtifact, networkExtras) {
440
+ function appendHistory(existing, reason) {
441
+ if (!existing || !reason) {
442
+ return existing?.history;
443
+ }
444
+ const supersededAt = (/* @__PURE__ */ new Date()).toISOString();
445
+ const entry = {
446
+ contractId: existing.contractId,
447
+ wasmHash: existing.wasmHash,
448
+ deployedAt: existing.deployedAt,
449
+ supersededAt,
450
+ reason
451
+ };
452
+ return [...existing.history ?? [], entry];
453
+ }
454
+ function updateArtifact(artifacts, networkName, contractName, contractArtifact, options = {}) {
404
455
  const existingNetwork = artifacts.networks[networkName] ?? { contracts: {}, dependencyGraph: {} };
456
+ const existingContract = existingNetwork.contracts[contractName];
457
+ const history = appendHistory(existingContract, options.supersedeReason);
458
+ const nextVersion = artifacts.version === 1 && options.supersedeReason ? 2 : artifacts.version;
405
459
  return {
406
460
  ...artifacts,
461
+ version: nextVersion,
407
462
  networks: {
408
463
  ...artifacts.networks,
409
464
  [networkName]: {
410
465
  ...existingNetwork,
411
- dependencyGraph: networkExtras?.dependencyGraph ?? existingNetwork.dependencyGraph ?? {},
466
+ dependencyGraph: options.dependencyGraph ?? existingNetwork.dependencyGraph ?? {},
412
467
  contracts: {
413
468
  ...existingNetwork.contracts,
414
- [contractName]: contractArtifact
469
+ [contractName]: {
470
+ ...contractArtifact,
471
+ history: history ?? contractArtifact.history
472
+ }
415
473
  }
416
474
  }
417
475
  }
418
476
  };
419
477
  }
478
+ function restoreArtifactFromHistory(input) {
479
+ const network = input.artifacts.networks[input.networkName];
480
+ const current = network?.contracts[input.contractName];
481
+ if (!current) {
482
+ throw new CaatingaError(
483
+ `No artifact for "${input.contractName}" on "${input.networkName}".`,
484
+ CaatingaErrorCode.ARTIFACT_NOT_FOUND,
485
+ "Deploy the contract before attempting rollback."
486
+ );
487
+ }
488
+ if (current.contractId === input.contractId) {
489
+ return input.artifacts;
490
+ }
491
+ const fromHistory = (current.history ?? []).find(
492
+ (entry) => entry.contractId === input.contractId
493
+ );
494
+ if (!fromHistory) {
495
+ throw new CaatingaError(
496
+ `Rollback target "${input.contractId}" was not found in artifact history for "${input.contractName}".`,
497
+ CaatingaErrorCode.ROLLBACK_TARGET_NOT_FOUND,
498
+ "Use caatinga inspect to list prior contract IDs, or redeploy manually."
499
+ );
500
+ }
501
+ const supersededAt = (/* @__PURE__ */ new Date()).toISOString();
502
+ const restoredArtifact = {
503
+ contractId: fromHistory.contractId,
504
+ wasmHash: fromHistory.wasmHash,
505
+ deployedAt: fromHistory.deployedAt,
506
+ sourcePath: current.sourcePath,
507
+ wasmPath: current.wasmPath,
508
+ dependencies: current.dependencies,
509
+ resolvedDeployArgs: current.resolvedDeployArgs,
510
+ history: [
511
+ ...current.history ?? [],
512
+ {
513
+ contractId: current.contractId,
514
+ wasmHash: current.wasmHash,
515
+ deployedAt: current.deployedAt,
516
+ supersededAt,
517
+ reason: "rollback"
518
+ }
519
+ ]
520
+ };
521
+ return {
522
+ ...updateArtifact(input.artifacts, input.networkName, input.contractName, restoredArtifact),
523
+ version: 2
524
+ };
525
+ }
526
+
527
+ // src/artifacts/migrate-artifacts.ts
528
+ function migrateArtifactsToV2(artifacts) {
529
+ if (artifacts.version === CURRENT_ARTIFACTS_SCHEMA_VERSION) {
530
+ return {
531
+ artifacts,
532
+ migrated: false
533
+ };
534
+ }
535
+ const v1 = artifacts;
536
+ return {
537
+ artifacts: {
538
+ project: v1.project,
539
+ version: CURRENT_ARTIFACTS_SCHEMA_VERSION,
540
+ networks: v1.networks
541
+ },
542
+ migrated: true
543
+ };
544
+ }
545
+
546
+ // src/artifacts/migrate-artifacts-file.ts
547
+ async function migrateArtifactsFile(cwd = process.cwd()) {
548
+ const artifacts = await readArtifacts(cwd);
549
+ const { artifacts: migrated, migrated: changed } = migrateArtifactsToV2(artifacts);
550
+ const path17 = await writeArtifacts(migrated, cwd);
551
+ return { path: path17, migrated: changed, artifacts: migrated };
552
+ }
553
+
554
+ // src/artifacts/rollback-artifact.ts
555
+ async function rollbackContractArtifact(input) {
556
+ const cwd = input.cwd ?? process.cwd();
557
+ const artifacts = await readArtifacts(cwd);
558
+ const next = restoreArtifactFromHistory({
559
+ artifacts,
560
+ networkName: input.networkName,
561
+ contractName: input.contractName,
562
+ contractId: input.contractId
563
+ });
564
+ const path17 = await writeArtifacts(next, cwd);
565
+ return { path: path17, artifacts: next };
566
+ }
420
567
 
421
568
  // src/networks/resolve-network.ts
422
569
  function resolveNetwork(config, networkName) {
@@ -683,6 +830,35 @@ function evaluateStellarCliCompatibility(input) {
683
830
  };
684
831
  }
685
832
 
833
+ // src/stellar-cli/probe-stellar-cli-features.ts
834
+ var import_semver3 = __toESM(require("semver"), 1);
835
+ var STELLAR_CLI_REQUIRED_FEATURES = [
836
+ "contract-build",
837
+ "contract-deploy",
838
+ "contract-invoke-sign"
839
+ ];
840
+ var FEATURE_COMMANDS = {
841
+ "contract-build": ["contract", "build", "--help"],
842
+ "contract-deploy": ["contract", "deploy", "--help"],
843
+ "contract-invoke-sign": ["contract", "invoke", "--help"]
844
+ };
845
+ async function probeMissingStellarCliFeatures(version) {
846
+ const missing = [];
847
+ if (import_semver3.default.valid(version) && import_semver3.default.lt(version, STELLAR_CLI_MIN_VERSION)) {
848
+ return ["contract-invoke-sign"];
849
+ }
850
+ for (const feature of STELLAR_CLI_REQUIRED_FEATURES) {
851
+ try {
852
+ await runCommand("stellar", FEATURE_COMMANDS[feature], {
853
+ skipStellarVersionCheck: true
854
+ });
855
+ } catch {
856
+ missing.push(feature);
857
+ }
858
+ }
859
+ return missing;
860
+ }
861
+
686
862
  // src/stellar-cli/check-stellar-cli-version.ts
687
863
  async function checkStellarCliVersion(input = {}) {
688
864
  let rawOutput;
@@ -702,9 +878,12 @@ async function checkStellarCliVersion(input = {}) {
702
878
  }
703
879
  throw error;
704
880
  }
881
+ const version = parseStellarCliVersion(rawOutput);
882
+ const probedMissing = input.probeFeatures === false ? [] : await probeMissingStellarCliFeatures(version);
883
+ const missingFeatures = [...input.features ?? [], ...probedMissing];
705
884
  const report = evaluateStellarCliCompatibility({
706
- version: parseStellarCliVersion(rawOutput),
707
- features: input.features,
885
+ version,
886
+ features: missingFeatures.length > 0 ? missingFeatures : void 0,
708
887
  lastTestedVersion: input.lastTestedVersion
709
888
  });
710
889
  for (const warning of report.warnings) {
@@ -850,6 +1029,122 @@ function parseContractId(output) {
850
1029
  return match[0];
851
1030
  }
852
1031
 
1032
+ // src/stellar-sdk/check-stellar-sdk-version.ts
1033
+ var import_promises6 = require("fs/promises");
1034
+ var import_node_path7 = __toESM(require("path"), 1);
1035
+
1036
+ // src/stellar-sdk/compat.ts
1037
+ var import_semver4 = __toESM(require("semver"), 1);
1038
+
1039
+ // src/stellar-sdk/version.ts
1040
+ var STELLAR_SDK_MIN_VERSION = "16.0.1";
1041
+ var STELLAR_SDK_LAST_TESTED_VERSION = "16.0.1";
1042
+
1043
+ // src/stellar-sdk/compat.ts
1044
+ function evaluateStellarSdkCompatibility(input) {
1045
+ const parsed = import_semver4.default.parse(input.version);
1046
+ if (!parsed || !import_semver4.default.valid(input.version)) {
1047
+ throw new CaatingaError(
1048
+ "Could not parse @stellar/stellar-sdk version.",
1049
+ CaatingaErrorCode.STELLAR_SDK_VERSION_PARSE_FAILED,
1050
+ "Use a semantic version such as 16.0.1."
1051
+ );
1052
+ }
1053
+ const lastTestedVersion = import_semver4.default.valid(input.lastTestedVersion ?? STELLAR_SDK_LAST_TESTED_VERSION) ?? STELLAR_SDK_LAST_TESTED_VERSION;
1054
+ const warnings = [];
1055
+ let status = "supported";
1056
+ if (import_semver4.default.lt(parsed, STELLAR_SDK_MIN_VERSION)) {
1057
+ throw new CaatingaError(
1058
+ `@stellar/stellar-sdk ${input.version} is below the supported minimum ${STELLAR_SDK_MIN_VERSION}.`,
1059
+ CaatingaErrorCode.UNSUPPORTED_SDK_VERSION,
1060
+ `Install @stellar/stellar-sdk ${STELLAR_SDK_MIN_VERSION} or newer.`
1061
+ );
1062
+ }
1063
+ if (import_semver4.default.gt(parsed, lastTestedVersion)) {
1064
+ status = "untested";
1065
+ warnings.push({
1066
+ code: "STELLAR_SDK_UNTESTED_VERSION",
1067
+ message: `@stellar/stellar-sdk ${input.version} is newer than the last-tested ${lastTestedVersion}; binding output may differ.`,
1068
+ remediation: "Pin @stellar/stellar-sdk to the last-tested version in package.json, or update Caatinga fixtures after validating generate output."
1069
+ });
1070
+ }
1071
+ return {
1072
+ version: input.version,
1073
+ status,
1074
+ minVersion: STELLAR_SDK_MIN_VERSION,
1075
+ lastTestedVersion,
1076
+ warnings
1077
+ };
1078
+ }
1079
+ function parseStellarSdkVersion(raw) {
1080
+ const trimmed = raw.trim();
1081
+ const match = trimmed.match(/(\d+\.\d+\.\d+(?:[-+][\w.-]+)?)/);
1082
+ if (!match) {
1083
+ throw new CaatingaError(
1084
+ "Could not parse @stellar/stellar-sdk version.",
1085
+ CaatingaErrorCode.STELLAR_SDK_VERSION_PARSE_FAILED,
1086
+ "Expected output like 16.0.1."
1087
+ );
1088
+ }
1089
+ return match[1];
1090
+ }
1091
+
1092
+ // src/stellar-sdk/check-stellar-sdk-version.ts
1093
+ async function readInstalledSdkVersion(cwd) {
1094
+ try {
1095
+ const pkgPath = import_node_path7.default.join(cwd, "node_modules", "@stellar", "stellar-sdk", "package.json");
1096
+ const raw = await (0, import_promises6.readFile)(pkgPath, "utf8");
1097
+ const pkg = JSON.parse(raw);
1098
+ return typeof pkg.version === "string" ? pkg.version : void 0;
1099
+ } catch {
1100
+ return void 0;
1101
+ }
1102
+ }
1103
+ async function resolveRegistrySdkVersion() {
1104
+ const result = await runCommand("npm", ["view", "@stellar/stellar-sdk", "version"], {
1105
+ skipStellarVersionCheck: true
1106
+ });
1107
+ return parseStellarSdkVersion(result.stdout || result.all);
1108
+ }
1109
+ async function checkStellarSdkVersion(input = {}) {
1110
+ const cwd = input.cwd ?? process.cwd();
1111
+ let version;
1112
+ try {
1113
+ const installed = await readInstalledSdkVersion(cwd);
1114
+ version = installed ?? await resolveRegistrySdkVersion();
1115
+ } catch (error) {
1116
+ if (error instanceof CaatingaError) {
1117
+ throw error;
1118
+ }
1119
+ throw new CaatingaError(
1120
+ "Could not resolve @stellar/stellar-sdk version.",
1121
+ CaatingaErrorCode.STELLAR_SDK_VERSION_PARSE_FAILED,
1122
+ "Install @stellar/stellar-sdk in your project or ensure npm registry access.",
1123
+ error
1124
+ );
1125
+ }
1126
+ const report = evaluateStellarSdkCompatibility({
1127
+ version,
1128
+ lastTestedVersion: input.lastTestedVersion
1129
+ });
1130
+ for (const warning of report.warnings) {
1131
+ if (input.onWarning) {
1132
+ input.onWarning(warning);
1133
+ } else {
1134
+ defaultEmitWarning2(warning);
1135
+ }
1136
+ }
1137
+ return report;
1138
+ }
1139
+ function defaultEmitWarning2(warning) {
1140
+ const lines = [
1141
+ `Warning: ${warning.message}`,
1142
+ warning.remediation ? ` ${warning.remediation}` : void 0
1143
+ ].filter((line) => Boolean(line));
1144
+ process.stderr.write(`${lines.join("\n")}
1145
+ `);
1146
+ }
1147
+
853
1148
  // src/stellar-cli/build-stellar-network-args.ts
854
1149
  function matchesWellKnownNetwork(name, config) {
855
1150
  const known = WELL_KNOWN_NETWORKS[name];
@@ -988,7 +1283,7 @@ function validateSourceShape(source) {
988
1283
  }
989
1284
 
990
1285
  // src/contracts/resolve-contract.ts
991
- var import_node_path7 = __toESM(require("path"), 1);
1286
+ var import_node_path8 = __toESM(require("path"), 1);
992
1287
  function resolveContract(config, contractName, cwd = process.cwd()) {
993
1288
  const contract = config.contracts[contractName];
994
1289
  if (!contract) {
@@ -1001,8 +1296,8 @@ function resolveContract(config, contractName, cwd = process.cwd()) {
1001
1296
  return {
1002
1297
  name: contractName,
1003
1298
  config: contract,
1004
- sourcePath: import_node_path7.default.resolve(cwd, contract.path),
1005
- wasmPath: import_node_path7.default.resolve(cwd, contract.wasm)
1299
+ sourcePath: import_node_path8.default.resolve(cwd, contract.path),
1300
+ wasmPath: import_node_path8.default.resolve(cwd, contract.wasm)
1006
1301
  };
1007
1302
  }
1008
1303
 
@@ -1021,8 +1316,8 @@ function resolveDefaultContractName(config) {
1021
1316
 
1022
1317
  // src/contracts/wasm.ts
1023
1318
  var import_node_crypto = require("crypto");
1024
- var import_promises6 = require("fs/promises");
1025
- var import_node_path8 = __toESM(require("path"), 1);
1319
+ var import_promises7 = require("fs/promises");
1320
+ var import_node_path9 = __toESM(require("path"), 1);
1026
1321
  var LEGACY_RUST_WASM_TARGET = "wasm32-unknown-unknown";
1027
1322
  var CURRENT_RUST_WASM_TARGET = "wasm32v1-none";
1028
1323
  function toCurrentWasmTargetPath(wasmPath) {
@@ -1053,18 +1348,18 @@ function wasmNotFoundError(configuredWasmPath, options) {
1053
1348
  );
1054
1349
  }
1055
1350
  function toConfigRelativeWasmPath(absoluteWasmPath) {
1056
- const relative = import_node_path8.default.relative(process.cwd(), absoluteWasmPath);
1057
- return relative.startsWith("..") ? absoluteWasmPath : `./${relative.split(import_node_path8.default.sep).join("/")}`;
1351
+ const relative = import_node_path9.default.relative(process.cwd(), absoluteWasmPath);
1352
+ return relative.startsWith("..") ? absoluteWasmPath : `./${relative.split(import_node_path9.default.sep).join("/")}`;
1058
1353
  }
1059
1354
  function wasmFileName(configuredWasmPath) {
1060
- return import_node_path8.default.basename(configuredWasmPath);
1355
+ return import_node_path9.default.basename(configuredWasmPath);
1061
1356
  }
1062
1357
  function buildAlternateWasmCandidates(configuredWasmPath, options) {
1063
1358
  const fileName = wasmFileName(configuredWasmPath);
1064
1359
  const candidates = [];
1065
1360
  const seen = /* @__PURE__ */ new Set();
1066
1361
  function addCandidate(candidate) {
1067
- const resolved = import_node_path8.default.resolve(candidate);
1362
+ const resolved = import_node_path9.default.resolve(candidate);
1068
1363
  if (seen.has(resolved)) {
1069
1364
  return;
1070
1365
  }
@@ -1073,15 +1368,15 @@ function buildAlternateWasmCandidates(configuredWasmPath, options) {
1073
1368
  }
1074
1369
  const cargoTargetDir = process.env.CARGO_TARGET_DIR;
1075
1370
  if (cargoTargetDir) {
1076
- addCandidate(import_node_path8.default.join(cargoTargetDir, CURRENT_RUST_WASM_TARGET, "release", fileName));
1077
- addCandidate(import_node_path8.default.join(cargoTargetDir, LEGACY_RUST_WASM_TARGET, "release", fileName));
1371
+ addCandidate(import_node_path9.default.join(cargoTargetDir, CURRENT_RUST_WASM_TARGET, "release", fileName));
1372
+ addCandidate(import_node_path9.default.join(cargoTargetDir, LEGACY_RUST_WASM_TARGET, "release", fileName));
1078
1373
  }
1079
1374
  if (options?.sourcePath) {
1080
1375
  addCandidate(
1081
- import_node_path8.default.join(options.sourcePath, "target", CURRENT_RUST_WASM_TARGET, "release", fileName)
1376
+ import_node_path9.default.join(options.sourcePath, "target", CURRENT_RUST_WASM_TARGET, "release", fileName)
1082
1377
  );
1083
1378
  addCandidate(
1084
- import_node_path8.default.join(options.sourcePath, "target", LEGACY_RUST_WASM_TARGET, "release", fileName)
1379
+ import_node_path9.default.join(options.sourcePath, "target", LEGACY_RUST_WASM_TARGET, "release", fileName)
1085
1380
  );
1086
1381
  }
1087
1382
  return candidates;
@@ -1089,7 +1384,7 @@ function buildAlternateWasmCandidates(configuredWasmPath, options) {
1089
1384
  async function firstExistingPath(paths) {
1090
1385
  for (const candidate of paths) {
1091
1386
  try {
1092
- await (0, import_promises6.access)(candidate);
1387
+ await (0, import_promises7.access)(candidate);
1093
1388
  return candidate;
1094
1389
  } catch {
1095
1390
  continue;
@@ -1098,9 +1393,9 @@ async function firstExistingPath(paths) {
1098
1393
  return void 0;
1099
1394
  }
1100
1395
  async function resolveWasmArtifactPath(configuredWasmPath, options) {
1101
- const resolvedConfiguredPath = import_node_path8.default.resolve(configuredWasmPath);
1396
+ const resolvedConfiguredPath = import_node_path9.default.resolve(configuredWasmPath);
1102
1397
  try {
1103
- await (0, import_promises6.access)(resolvedConfiguredPath);
1398
+ await (0, import_promises7.access)(resolvedConfiguredPath);
1104
1399
  return resolvedConfiguredPath;
1105
1400
  } catch {
1106
1401
  const currentTargetPath = toCurrentWasmTargetPath(resolvedConfiguredPath);
@@ -1122,20 +1417,20 @@ async function resolveWasmArtifactPath(configuredWasmPath, options) {
1122
1417
  }
1123
1418
  }
1124
1419
  async function hashWasm(wasmPath) {
1125
- const bytes = await (0, import_promises6.readFile)(wasmPath);
1420
+ const bytes = await (0, import_promises7.readFile)(wasmPath);
1126
1421
  return (0, import_node_crypto.createHash)("sha256").update(bytes).digest("hex");
1127
1422
  }
1128
1423
  async function getNewestMtimeInDirectory(directory) {
1129
1424
  try {
1130
- await (0, import_promises6.access)(directory);
1425
+ await (0, import_promises7.access)(directory);
1131
1426
  } catch {
1132
1427
  return void 0;
1133
1428
  }
1134
1429
  let newest = 0;
1135
1430
  async function walk(dir) {
1136
- const entries = await (0, import_promises6.readdir)(dir, { withFileTypes: true });
1431
+ const entries = await (0, import_promises7.readdir)(dir, { withFileTypes: true });
1137
1432
  for (const entry of entries) {
1138
- const entryPath = import_node_path8.default.join(dir, entry.name);
1433
+ const entryPath = import_node_path9.default.join(dir, entry.name);
1139
1434
  if (entry.isDirectory()) {
1140
1435
  await walk(entryPath);
1141
1436
  continue;
@@ -1143,7 +1438,7 @@ async function getNewestMtimeInDirectory(directory) {
1143
1438
  if (!entry.isFile()) {
1144
1439
  continue;
1145
1440
  }
1146
- const fileStat = await (0, import_promises6.stat)(entryPath);
1441
+ const fileStat = await (0, import_promises7.stat)(entryPath);
1147
1442
  newest = Math.max(newest, fileStat.mtimeMs);
1148
1443
  }
1149
1444
  }
@@ -1151,14 +1446,14 @@ async function getNewestMtimeInDirectory(directory) {
1151
1446
  return newest > 0 ? newest : void 0;
1152
1447
  }
1153
1448
  async function isWasmOlderThanSources(input) {
1154
- const srcDir = import_node_path8.default.join(input.contractPath, "src");
1449
+ const srcDir = import_node_path9.default.join(input.contractPath, "src");
1155
1450
  const newestSourceMtime = await getNewestMtimeInDirectory(srcDir);
1156
1451
  if (newestSourceMtime === void 0) {
1157
1452
  return false;
1158
1453
  }
1159
1454
  let wasmStat;
1160
1455
  try {
1161
- wasmStat = await (0, import_promises6.stat)(input.wasmPath);
1456
+ wasmStat = await (0, import_promises7.stat)(input.wasmPath);
1162
1457
  } catch {
1163
1458
  return false;
1164
1459
  }
@@ -1226,7 +1521,38 @@ async function buildContract(options) {
1226
1521
  }
1227
1522
 
1228
1523
  // src/contracts/deploy-contract.ts
1229
- var import_node_path9 = __toESM(require("path"), 1);
1524
+ var import_node_path10 = __toESM(require("path"), 1);
1525
+
1526
+ // src/shell/is-transient-command-failure.ts
1527
+ var NO_RETRY_CAATINGA_SUBSTRINGS = [
1528
+ "CAATINGA_UNSUPPORTED_CLI_VERSION",
1529
+ "CAATINGA_STELLAR_CLI_VERSION_PARSE_FAILED",
1530
+ "CAATINGA_STELLAR_CLI_NOT_FOUND",
1531
+ "CAATINGA_INVALID_CONFIG",
1532
+ "CAATINGA_CONFIG_NOT_FOUND"
1533
+ ];
1534
+ var TRANSIENT_COMMAND_FAILURE_PATTERN = /timeout|i\/o timeout|econnreset|connection reset|503|502|429|rate limit|temporar|bad gateway|fetch failed|network error|unavailable/i;
1535
+ function isTransientCommandFailure(logText) {
1536
+ if (!logText.trim()) {
1537
+ return false;
1538
+ }
1539
+ for (const marker of NO_RETRY_CAATINGA_SUBSTRINGS) {
1540
+ if (logText.includes(marker)) {
1541
+ return false;
1542
+ }
1543
+ }
1544
+ return TRANSIENT_COMMAND_FAILURE_PATTERN.test(logText);
1545
+ }
1546
+
1547
+ // src/contracts/is-transient-deploy-failure.ts
1548
+ function isTransientDeployFailure(error) {
1549
+ if (!(error instanceof CaatingaError) || error.code !== CaatingaErrorCode.DEPLOY_FAILED) {
1550
+ return false;
1551
+ }
1552
+ const logText = `${error.message}
1553
+ ${error.hint ?? ""}`;
1554
+ return isTransientCommandFailure(logText);
1555
+ }
1230
1556
 
1231
1557
  // src/contracts/dependency-graph.ts
1232
1558
  function buildDependencyGraph(contracts) {
@@ -1288,6 +1614,12 @@ function resolveCliSource(explicit) {
1288
1614
  }
1289
1615
 
1290
1616
  // src/contracts/deploy-contract.ts
1617
+ var DEFAULT_DEPLOY_RETRY_DELAYS_MS = [2e3, 5e3];
1618
+ function sleep(ms) {
1619
+ return new Promise((resolve) => {
1620
+ setTimeout(resolve, ms);
1621
+ });
1622
+ }
1291
1623
  function toSnakeCaseFlag(key) {
1292
1624
  return key.replace(/([A-Z])/g, "_$1").replace(/^_/, "").toLowerCase();
1293
1625
  }
@@ -1332,7 +1664,7 @@ async function deployContract(options) {
1332
1664
  contract: contractWithWasm,
1333
1665
  network,
1334
1666
  contractId: existing.contractId,
1335
- artifactsPath: import_node_path9.default.resolve(cwd, "caatinga.artifacts.json"),
1667
+ artifactsPath: import_node_path10.default.resolve(cwd, "caatinga.artifacts.json"),
1336
1668
  output: "",
1337
1669
  skipped: true,
1338
1670
  staleWasmWarning
@@ -1372,40 +1704,69 @@ async function deployContract(options) {
1372
1704
  ...buildStellarNetworkArgs(network),
1373
1705
  ...constructorArgs
1374
1706
  ];
1375
- let output = "";
1376
- let contractId;
1377
- try {
1378
- const result = await runCommand("stellar", stellarArgs, {
1379
- cwd,
1380
- failureCode: CaatingaErrorCode.DEPLOY_FAILED
1381
- });
1382
- output = result.all || `${result.stdout}
1707
+ let deployOutcome;
1708
+ const retryDelaysMs = options.deployRetryDelaysMs ?? DEFAULT_DEPLOY_RETRY_DELAYS_MS;
1709
+ const maxDeployAttempts = retryDelaysMs.length + 1;
1710
+ for (let attempt = 0; attempt < maxDeployAttempts; attempt++) {
1711
+ try {
1712
+ const result = await runCommand("stellar", stellarArgs, {
1713
+ cwd,
1714
+ failureCode: CaatingaErrorCode.DEPLOY_FAILED
1715
+ });
1716
+ const output2 = result.all || `${result.stdout}
1383
1717
  ${result.stderr}`;
1384
- contractId = parseContractId(output);
1385
- } catch (error) {
1386
- if (!(error instanceof CaatingaError) || error.code !== CaatingaErrorCode.DEPLOY_FAILED) {
1387
- throw error;
1388
- }
1389
- const recoveredContractId = await tryRecoverContractIdFromDeployFailure({
1390
- output: `${error.message}
1718
+ deployOutcome = {
1719
+ output: output2,
1720
+ contractId: parseContractId(output2)
1721
+ };
1722
+ break;
1723
+ } catch (error) {
1724
+ if (!(error instanceof CaatingaError) || error.code !== CaatingaErrorCode.DEPLOY_FAILED) {
1725
+ throw error;
1726
+ }
1727
+ const recoveredContractId = await tryRecoverContractIdFromDeployFailure({
1728
+ output: `${error.message}
1391
1729
  ${error.hint ?? ""}`,
1392
- source,
1393
- network: network.config,
1394
- cwd
1395
- });
1396
- if (!recoveredContractId) {
1397
- throw error;
1730
+ source,
1731
+ network: network.config,
1732
+ cwd
1733
+ });
1734
+ if (recoveredContractId) {
1735
+ deployOutcome = {
1736
+ output: [
1737
+ error.hint ?? "",
1738
+ "Caatinga recovered the contract ID from the on-chain deploy transaction.",
1739
+ `Contract ID: ${recoveredContractId}`
1740
+ ].filter(Boolean).join("\n"),
1741
+ contractId: recoveredContractId
1742
+ };
1743
+ break;
1744
+ }
1745
+ const isLastAttempt = attempt === maxDeployAttempts - 1;
1746
+ if (!isTransientDeployFailure(error) || isLastAttempt) {
1747
+ throw error;
1748
+ }
1749
+ const delayMs = retryDelaysMs[attempt] ?? retryDelaysMs[retryDelaysMs.length - 1] ?? 0;
1750
+ options.onTransientDeployRetry?.({
1751
+ attempt: attempt + 1,
1752
+ maxAttempts: maxDeployAttempts,
1753
+ delayMs
1754
+ });
1755
+ await sleep(delayMs);
1398
1756
  }
1399
- contractId = recoveredContractId;
1400
- output = [
1401
- error.hint ?? "",
1402
- "Caatinga recovered the contract ID from the on-chain deploy transaction.",
1403
- `Contract ID: ${contractId}`
1404
- ].filter(Boolean).join("\n");
1405
1757
  }
1758
+ if (!deployOutcome) {
1759
+ throw new CaatingaError(
1760
+ "Deploy failed without a contract ID.",
1761
+ CaatingaErrorCode.DEPLOY_FAILED,
1762
+ "Re-run the deploy command with the underlying Stellar CLI for full diagnostics."
1763
+ );
1764
+ }
1765
+ const { output, contractId } = deployOutcome;
1406
1766
  const wasmHash = await hashWasm(wasmPath);
1407
1767
  const dependencyGraph = buildDependencyGraph(options.config.contracts);
1408
1768
  const dependencies = options.dependencies ?? contract.config.dependsOn;
1769
+ const supersedeReason = existing?.contractId && options.force ? options.upgrade ? "upgrade" : "force-redeploy" : void 0;
1409
1770
  const nextArtifacts = updateArtifact(
1410
1771
  artifactsBefore,
1411
1772
  network.name,
@@ -1419,7 +1780,7 @@ ${error.hint ?? ""}`,
1419
1780
  dependencies,
1420
1781
  resolvedDeployArgs
1421
1782
  },
1422
- { dependencyGraph }
1783
+ { dependencyGraph, supersedeReason }
1423
1784
  );
1424
1785
  const artifactsPath = await writeArtifacts(nextArtifacts, cwd);
1425
1786
  return {
@@ -1583,9 +1944,11 @@ async function deployContractGraph(options) {
1583
1944
  source: options.source,
1584
1945
  cwd,
1585
1946
  force: options.force,
1947
+ upgrade: options.upgrade,
1586
1948
  checkStaleWasm: options.checkStaleWasm,
1587
1949
  resolvedDeployArgs,
1588
- dependencies: contractConfig.dependsOn
1950
+ dependencies: contractConfig.dependsOn,
1951
+ onTransientDeployRetry: options.onTransientDeployRetry
1589
1952
  });
1590
1953
  if (result.staleWasmWarning) {
1591
1954
  staleWasmWarnings.push({
@@ -1608,12 +1971,12 @@ async function deployContractGraph(options) {
1608
1971
  }
1609
1972
 
1610
1973
  // src/contracts/generate-bindings.ts
1611
- var import_promises8 = require("fs/promises");
1612
- var import_node_path11 = __toESM(require("path"), 1);
1974
+ var import_promises9 = require("fs/promises");
1975
+ var import_node_path12 = __toESM(require("path"), 1);
1613
1976
 
1614
1977
  // src/bindings/patch-generated-binding-package.ts
1615
- var import_promises7 = require("fs/promises");
1616
- var import_node_path10 = __toESM(require("path"), 1);
1978
+ var import_promises8 = require("fs/promises");
1979
+ var import_node_path11 = __toESM(require("path"), 1);
1617
1980
  var BUNDLER_ENTRY = "./src/index.ts";
1618
1981
  var ROOT_BINDING_INDEX_CONTENT = 'export * from "./src/index.js";\n';
1619
1982
  function resolveExportEntry(exportsField) {
@@ -1648,22 +2011,22 @@ function shouldPatchPackageJson(packageJson) {
1648
2011
  return pointsToDist(packageJson.main) || pointsToDist(packageJson.types) || !pointsToBundlerSource(exportEntry);
1649
2012
  }
1650
2013
  async function ensureRootBindingIndex(outputDir) {
1651
- const rootIndexPath = import_node_path10.default.join(outputDir, "index.ts");
2014
+ const rootIndexPath = import_node_path11.default.join(outputDir, "index.ts");
1652
2015
  try {
1653
- const existing = await (0, import_promises7.readFile)(rootIndexPath, "utf8");
2016
+ const existing = await (0, import_promises8.readFile)(rootIndexPath, "utf8");
1654
2017
  if (existing === ROOT_BINDING_INDEX_CONTENT) {
1655
2018
  return;
1656
2019
  }
1657
2020
  return;
1658
2021
  } catch {
1659
- await (0, import_promises7.writeFile)(rootIndexPath, ROOT_BINDING_INDEX_CONTENT, "utf8");
2022
+ await (0, import_promises8.writeFile)(rootIndexPath, ROOT_BINDING_INDEX_CONTENT, "utf8");
1660
2023
  }
1661
2024
  }
1662
2025
  async function patchGeneratedBindingPackage(outputDir) {
1663
- const packageJsonPath = import_node_path10.default.join(outputDir, "package.json");
1664
- const entryPath = import_node_path10.default.join(outputDir, "src", "index.ts");
2026
+ const packageJsonPath = import_node_path11.default.join(outputDir, "package.json");
2027
+ const entryPath = import_node_path11.default.join(outputDir, "src", "index.ts");
1665
2028
  try {
1666
- await (0, import_promises7.access)(entryPath);
2029
+ await (0, import_promises8.access)(entryPath);
1667
2030
  } catch {
1668
2031
  throw new CaatingaError(
1669
2032
  "Generated binding package is missing src/index.ts.",
@@ -1673,7 +2036,7 @@ async function patchGeneratedBindingPackage(outputDir) {
1673
2036
  }
1674
2037
  let raw;
1675
2038
  try {
1676
- raw = await (0, import_promises7.readFile)(packageJsonPath, "utf8");
2039
+ raw = await (0, import_promises8.readFile)(packageJsonPath, "utf8");
1677
2040
  } catch {
1678
2041
  throw new CaatingaError(
1679
2042
  "Generated binding package is missing package.json.",
@@ -1698,7 +2061,7 @@ async function patchGeneratedBindingPackage(outputDir) {
1698
2061
  ...typeof packageJson.exports === "object" && packageJson.exports !== null && !Array.isArray(packageJson.exports) ? packageJson.exports : {},
1699
2062
  ".": BUNDLER_ENTRY
1700
2063
  };
1701
- await (0, import_promises7.writeFile)(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
2064
+ await (0, import_promises8.writeFile)(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
1702
2065
  `, "utf8");
1703
2066
  }
1704
2067
  await ensureRootBindingIndex(outputDir);
@@ -1714,14 +2077,14 @@ function buildGenerateNetworkArgs(network) {
1714
2077
 
1715
2078
  // src/contracts/generate-bindings.ts
1716
2079
  function toBindingImportPath(bindingsOutput, contractName) {
1717
- const normalized = bindingsOutput.replace(/^\.\//, "").split(import_node_path11.default.sep).join("/");
1718
- return `./${import_node_path11.default.posix.join(normalized, contractName)}`;
2080
+ const normalized = bindingsOutput.replace(/^\.\//, "").split(import_node_path12.default.sep).join("/");
2081
+ return `./${import_node_path12.default.posix.join(normalized, contractName)}`;
1719
2082
  }
1720
2083
  async function removeLegacyBindingStub(cwd, bindingsOutput, contractName) {
1721
- const legacyPath = import_node_path11.default.resolve(cwd, bindingsOutput, `${contractName}.ts`);
2084
+ const legacyPath = import_node_path12.default.resolve(cwd, bindingsOutput, `${contractName}.ts`);
1722
2085
  try {
1723
- await (0, import_promises8.access)(legacyPath);
1724
- await (0, import_promises8.unlink)(legacyPath);
2086
+ await (0, import_promises9.access)(legacyPath);
2087
+ await (0, import_promises9.unlink)(legacyPath);
1725
2088
  return true;
1726
2089
  } catch {
1727
2090
  return false;
@@ -1746,8 +2109,9 @@ async function generateBindings(options) {
1746
2109
  "Run caatinga deploy for this contract and network before generating bindings."
1747
2110
  );
1748
2111
  }
1749
- const outputDir = import_node_path11.default.resolve(cwd, options.config.frontend.bindingsOutput, options.contractName);
1750
- await (0, import_promises8.mkdir)(outputDir, { recursive: true });
2112
+ const outputDir = import_node_path12.default.resolve(cwd, options.config.frontend.bindingsOutput, options.contractName);
2113
+ await (0, import_promises9.mkdir)(outputDir, { recursive: true });
2114
+ await checkStellarSdkVersion({ cwd });
1751
2115
  const result = await runCommand(
1752
2116
  "npx",
1753
2117
  [
@@ -1972,14 +2336,172 @@ async function readContract(options) {
1972
2336
  };
1973
2337
  }
1974
2338
 
2339
+ // src/contracts/estimate-deploy-cost.ts
2340
+ var import_node_path13 = __toESM(require("path"), 1);
2341
+ function toSnakeCaseFlag2(key) {
2342
+ return key.replace(/([A-Z])/g, "_$1").replace(/^_/, "").toLowerCase();
2343
+ }
2344
+ function formatConstructorCliArgs2(resolved) {
2345
+ const entries = Object.entries(resolved);
2346
+ if (entries.length === 0) {
2347
+ return [];
2348
+ }
2349
+ const tail = ["--"];
2350
+ for (const [key, value] of entries) {
2351
+ tail.push(`--${toSnakeCaseFlag2(key)}`, String(value));
2352
+ }
2353
+ return tail;
2354
+ }
2355
+ function parseFeeStroops(output) {
2356
+ const inclusionMatch = output.match(/inclusion[_\s-]*fee[:\s]+(\d+)/i);
2357
+ const resourceMatch = output.match(/resource[_\s-]*fee[:\s]+(\d+)/i);
2358
+ const totalMatch = output.match(/total[_\s-]*fee[:\s]+(\d+)/i);
2359
+ return {
2360
+ inclusion: inclusionMatch ? Number(inclusionMatch[1]) : void 0,
2361
+ resource: resourceMatch ? Number(resourceMatch[1]) : void 0,
2362
+ ...totalMatch && !resourceMatch ? { resource: Number(totalMatch[1]) } : {}
2363
+ };
2364
+ }
2365
+ async function estimateDeployCost(options) {
2366
+ const cwd = options.cwd ?? process.cwd();
2367
+ const contract = resolveContract(options.config, options.contractName, cwd);
2368
+ const network = resolveNetwork(options.config, options.networkName);
2369
+ const source = assertSafeSourceAccount(options.source);
2370
+ await checkBinary("stellar", "Install Stellar CLI before running caatinga estimate.");
2371
+ const wasmPath = await resolveWasmArtifactPath(contract.wasmPath, {
2372
+ sourcePath: contract.sourcePath
2373
+ });
2374
+ const artifacts = await readArtifacts(cwd);
2375
+ const rawDeployArgs = contract.config.deployArgs;
2376
+ const resolvedDeployArgs = Object.keys(rawDeployArgs).length > 0 ? resolveDeployArgs({
2377
+ deployArgs: rawDeployArgs,
2378
+ artifacts,
2379
+ network: network.name
2380
+ }) : {};
2381
+ const constructorArgs = formatConstructorCliArgs2(resolvedDeployArgs);
2382
+ const deployArgs = [
2383
+ "contract",
2384
+ "deploy",
2385
+ "--wasm",
2386
+ wasmPath,
2387
+ "--source-account",
2388
+ source,
2389
+ "--build-only",
2390
+ ...buildStellarNetworkArgs(network),
2391
+ ...constructorArgs
2392
+ ];
2393
+ let buildOutput;
2394
+ try {
2395
+ const buildResult = await runCommand("stellar", deployArgs, {
2396
+ cwd,
2397
+ failureCode: CaatingaErrorCode.ESTIMATE_FAILED
2398
+ });
2399
+ buildOutput = (buildResult.stdout || buildResult.all).trim();
2400
+ } catch (error) {
2401
+ if (error instanceof CaatingaError) {
2402
+ throw new CaatingaError(
2403
+ `Deploy cost estimate failed for "${contract.name}".`,
2404
+ CaatingaErrorCode.ESTIMATE_FAILED,
2405
+ error.hint ?? "Ensure WASM is built and deploy args resolve correctly.",
2406
+ error.cause
2407
+ );
2408
+ }
2409
+ throw error;
2410
+ }
2411
+ const simulateArgs = ["tx", "simulate", "--source-account", source, buildOutput];
2412
+ let simulateOutput = "";
2413
+ try {
2414
+ const simulateResult = await runCommand("stellar", simulateArgs, {
2415
+ cwd,
2416
+ failureCode: CaatingaErrorCode.ESTIMATE_FAILED
2417
+ });
2418
+ simulateOutput = simulateResult.all || `${simulateResult.stdout}
2419
+ ${simulateResult.stderr}`;
2420
+ } catch {
2421
+ simulateOutput = "";
2422
+ }
2423
+ const parsed = parseFeeStroops(simulateOutput);
2424
+ const inclusionFeeStroops = parsed.inclusion ?? 100;
2425
+ const resourceFeeStroops = parsed.resource;
2426
+ const totalFeeStroops = inclusionFeeStroops + (resourceFeeStroops ?? 0);
2427
+ return {
2428
+ contractName: contract.name,
2429
+ network: network.name,
2430
+ wasmPath: import_node_path13.default.relative(cwd, wasmPath) || wasmPath,
2431
+ inclusionFeeStroops,
2432
+ resourceFeeStroops,
2433
+ totalFeeStroops,
2434
+ advisory: "Advisory estimate only \u2014 actual fees may differ under network congestion or contract complexity.",
2435
+ rawOutput: simulateOutput || buildOutput
2436
+ };
2437
+ }
2438
+
2439
+ // src/contracts/inspect-contract.ts
2440
+ async function inspectContract(options) {
2441
+ const cwd = options.cwd ?? process.cwd();
2442
+ const contract = resolveContract(options.config, options.contractName, cwd);
2443
+ const network = resolveNetwork(options.config, options.networkName);
2444
+ const artifacts = await readArtifacts(cwd);
2445
+ const artifact = artifacts.networks[network.name]?.contracts[contract.name];
2446
+ if (!artifact) {
2447
+ throw new CaatingaError(
2448
+ `No deployed artifact found for "${contract.name}" on "${network.name}".`,
2449
+ CaatingaErrorCode.ARTIFACT_NOT_FOUND,
2450
+ "Run caatinga deploy before inspect."
2451
+ );
2452
+ }
2453
+ await checkBinary("stellar", "Install Stellar CLI before running caatinga inspect.");
2454
+ let reachable = false;
2455
+ let detail;
2456
+ try {
2457
+ await verifyDependencyContract({
2458
+ dependencyName: contract.name,
2459
+ contractId: artifact.contractId,
2460
+ network,
2461
+ cwd
2462
+ });
2463
+ reachable = true;
2464
+ detail = "Contract interface reachable on network.";
2465
+ } catch (error) {
2466
+ reachable = false;
2467
+ detail = error instanceof CaatingaError ? error.message : "Contract not reachable on network.";
2468
+ }
2469
+ let localHash;
2470
+ try {
2471
+ const wasmPath = await resolveWasmArtifactPath(contract.wasmPath, {
2472
+ sourcePath: contract.sourcePath
2473
+ });
2474
+ localHash = await hashWasm(wasmPath);
2475
+ } catch {
2476
+ localHash = void 0;
2477
+ }
2478
+ return {
2479
+ contractName: contract.name,
2480
+ network: network.name,
2481
+ artifact: {
2482
+ contractId: artifact.contractId,
2483
+ wasmHash: artifact.wasmHash,
2484
+ deployedAt: artifact.deployedAt,
2485
+ historyCount: artifact.history?.length ?? 0
2486
+ },
2487
+ onChain: { reachable, detail },
2488
+ localWasm: {
2489
+ path: contract.config.wasm,
2490
+ hash: localHash,
2491
+ matchesArtifact: Boolean(localHash && localHash === artifact.wasmHash)
2492
+ },
2493
+ dependencies: artifact.dependencies ?? contract.config.dependsOn ?? []
2494
+ };
2495
+ }
2496
+
1975
2497
  // src/templates/create-project-from-template.ts
1976
- var import_promises9 = require("fs/promises");
1977
- var import_node_path12 = __toESM(require("path"), 1);
2498
+ var import_promises10 = require("fs/promises");
2499
+ var import_node_path14 = __toESM(require("path"), 1);
1978
2500
  var import_zod7 = require("zod");
1979
2501
 
1980
2502
  // src/templates/template-manifest.schema.ts
1981
2503
  var import_zod6 = require("zod");
1982
- var import_semver3 = __toESM(require("semver"), 1);
2504
+ var import_semver5 = __toESM(require("semver"), 1);
1983
2505
  var CURRENT_TEMPLATE_VERSION = 1;
1984
2506
  var TemplateManifestSchema = import_zod6.z.object({
1985
2507
  name: import_zod6.z.string().min(1),
@@ -1990,7 +2512,7 @@ var TemplateManifestSchema = import_zod6.z.object({
1990
2512
  templateVersion: import_zod6.z.number().int().positive()
1991
2513
  }),
1992
2514
  frontend: import_zod6.z.object({
1993
- framework: import_zod6.z.enum(["vite-react", "next", "astro"]),
2515
+ framework: import_zod6.z.literal("vite-react"),
1994
2516
  packageManager: import_zod6.z.enum(["npm", "pnpm", "yarn", "bun"]).default("npm")
1995
2517
  }),
1996
2518
  contracts: import_zod6.z.object({
@@ -2003,14 +2525,14 @@ var TemplateManifestSchema = import_zod6.z.object({
2003
2525
  })
2004
2526
  });
2005
2527
  function defaultCompatibleCoreRange(coreVersion = CAATINGA_CORE_VERSION) {
2006
- const version = import_semver3.default.valid(import_semver3.default.coerce(coreVersion));
2528
+ const version = import_semver5.default.valid(import_semver5.default.coerce(coreVersion));
2007
2529
  if (!version) {
2008
2530
  throw new Error(`Invalid core version: ${coreVersion}`);
2009
2531
  }
2010
2532
  return `^${version}`;
2011
2533
  }
2012
2534
  function isCoreVersionCompatible(range, coreVersion = CAATINGA_CORE_VERSION) {
2013
- return import_semver3.default.satisfies(coreVersion, range);
2535
+ return import_semver5.default.satisfies(coreVersion, range);
2014
2536
  }
2015
2537
  function getTemplateCompatibilityIssue(manifest, coreVersion = CAATINGA_CORE_VERSION) {
2016
2538
  if (manifest.caatinga.templateVersion !== CURRENT_TEMPLATE_VERSION) {
@@ -2045,10 +2567,10 @@ function formatTemplateCompatibilityHint(issue) {
2045
2567
  // src/templates/create-project-from-template.ts
2046
2568
  var TEMPLATE_COPY_EXCLUDED_DIRS = /* @__PURE__ */ new Set(["target", "test_snapshots", "node_modules", ".git"]);
2047
2569
  async function createProjectFromTemplate(options) {
2048
- const targetDir = import_node_path12.default.resolve(options.targetDir);
2049
- const templateDir = import_node_path12.default.resolve(options.templateDir);
2570
+ const targetDir = import_node_path14.default.resolve(options.targetDir);
2571
+ const templateDir = import_node_path14.default.resolve(options.templateDir);
2050
2572
  try {
2051
- await (0, import_promises9.stat)(templateDir);
2573
+ await (0, import_promises10.stat)(templateDir);
2052
2574
  } catch {
2053
2575
  throw new CaatingaError(
2054
2576
  `Template directory was not found: ${templateDir}`,
@@ -2058,8 +2580,8 @@ async function createProjectFromTemplate(options) {
2058
2580
  }
2059
2581
  const manifest = await readTemplateManifest(templateDir);
2060
2582
  const mergeIntoExisting = Boolean(options.filter);
2061
- await (0, import_promises9.mkdir)(targetDir, { recursive: true });
2062
- await (0, import_promises9.cp)(templateDir, targetDir, {
2583
+ await (0, import_promises10.mkdir)(targetDir, { recursive: true });
2584
+ await (0, import_promises10.cp)(templateDir, targetDir, {
2063
2585
  recursive: true,
2064
2586
  force: true,
2065
2587
  errorOnExist: false,
@@ -2087,9 +2609,9 @@ async function ensureArtifacts(targetDir, projectName) {
2087
2609
  }
2088
2610
  }
2089
2611
  async function readTemplateManifest(templateDir) {
2090
- const manifestPath = import_node_path12.default.join(templateDir, "caatinga.template.json");
2612
+ const manifestPath = import_node_path14.default.join(templateDir, "caatinga.template.json");
2091
2613
  try {
2092
- const rawManifest = await (0, import_promises9.readFile)(manifestPath, "utf8");
2614
+ const rawManifest = await (0, import_promises10.readFile)(manifestPath, "utf8");
2093
2615
  const manifest = TemplateManifestSchema.parse(JSON.parse(rawManifest));
2094
2616
  const compatibilityIssue = getTemplateCompatibilityIssue(manifest);
2095
2617
  if (compatibilityIssue) {
@@ -2122,11 +2644,11 @@ async function readTemplateManifest(templateDir) {
2122
2644
  }
2123
2645
  }
2124
2646
  async function replaceTemplateVariables(dir, projectName) {
2125
- const entries = await (0, import_promises9.readdir)(dir);
2647
+ const entries = await (0, import_promises10.readdir)(dir);
2126
2648
  await Promise.all(
2127
2649
  entries.map(async (entry) => {
2128
- const entryPath = import_node_path12.default.join(dir, entry);
2129
- const entryStat = await (0, import_promises9.stat)(entryPath);
2650
+ const entryPath = import_node_path14.default.join(dir, entry);
2651
+ const entryStat = await (0, import_promises10.stat)(entryPath);
2130
2652
  if (entryStat.isDirectory()) {
2131
2653
  await replaceTemplateVariables(entryPath, projectName);
2132
2654
  return;
@@ -2134,39 +2656,39 @@ async function replaceTemplateVariables(dir, projectName) {
2134
2656
  if (!isTextTemplateFile(entryPath)) {
2135
2657
  return;
2136
2658
  }
2137
- const content = await (0, import_promises9.readFile)(entryPath, "utf8");
2138
- await (0, import_promises9.writeFile)(entryPath, content.replaceAll("__PROJECT_NAME__", projectName), "utf8");
2659
+ const content = await (0, import_promises10.readFile)(entryPath, "utf8");
2660
+ await (0, import_promises10.writeFile)(entryPath, content.replaceAll("__PROJECT_NAME__", projectName), "utf8");
2139
2661
  })
2140
2662
  );
2141
2663
  }
2142
2664
  function shouldCopyTemplateEntry(templateDir, source, userFilter) {
2143
- const relativePath = import_node_path12.default.relative(templateDir, source);
2665
+ const relativePath = import_node_path14.default.relative(templateDir, source);
2144
2666
  if (!relativePath || relativePath === ".") {
2145
2667
  return true;
2146
2668
  }
2147
- const normalizedPath = relativePath.split(import_node_path12.default.sep).join("/");
2669
+ const normalizedPath = relativePath.split(import_node_path14.default.sep).join("/");
2148
2670
  if (userFilter && !userFilter(normalizedPath)) {
2149
2671
  return false;
2150
2672
  }
2151
- return !relativePath.split(import_node_path12.default.sep).some((segment) => TEMPLATE_COPY_EXCLUDED_DIRS.has(segment));
2673
+ return !relativePath.split(import_node_path14.default.sep).some((segment) => TEMPLATE_COPY_EXCLUDED_DIRS.has(segment));
2152
2674
  }
2153
2675
  function isTextTemplateFile(filePath) {
2154
2676
  return [".json", ".md", ".rs", ".toml", ".ts", ".tsx", ".css", ".html"].includes(
2155
- import_node_path12.default.extname(filePath)
2677
+ import_node_path14.default.extname(filePath)
2156
2678
  );
2157
2679
  }
2158
2680
 
2159
2681
  // src/scaffold/create-zk-project.ts
2160
- var import_promises10 = require("fs/promises");
2682
+ var import_promises11 = require("fs/promises");
2161
2683
  var import_node_fs2 = require("fs");
2162
- var import_node_path13 = __toESM(require("path"), 1);
2684
+ var import_node_path15 = __toESM(require("path"), 1);
2163
2685
  var import_node_url = require("url");
2164
2686
  var import_meta3 = {};
2165
- var moduleDir = typeof __dirname === "string" ? __dirname : import_node_path13.default.dirname((0, import_node_url.fileURLToPath)(import_meta3.url));
2687
+ var moduleDir = typeof __dirname === "string" ? __dirname : import_node_path15.default.dirname((0, import_node_url.fileURLToPath)(import_meta3.url));
2166
2688
  function scaffoldRoot() {
2167
2689
  const candidates = [
2168
- import_node_path13.default.resolve(moduleDir, "../../scaffolds"),
2169
- import_node_path13.default.resolve(moduleDir, "../scaffolds")
2690
+ import_node_path15.default.resolve(moduleDir, "../../scaffolds"),
2691
+ import_node_path15.default.resolve(moduleDir, "../scaffolds")
2170
2692
  ];
2171
2693
  const found = candidates.find((candidate) => (0, import_node_fs2.existsSync)(candidate));
2172
2694
  return found ?? candidates[0];
@@ -2257,39 +2779,39 @@ Replace \`circuits/main.circom\` with your circuit. Keep the entry point named \
2257
2779
  `;
2258
2780
  }
2259
2781
  async function createZkProject(options) {
2260
- const targetDir = import_node_path13.default.resolve(options.targetDir);
2782
+ const targetDir = import_node_path15.default.resolve(options.targetDir);
2261
2783
  const force = options.force ?? false;
2262
2784
  const projectFiles = options.projectFiles ?? true;
2263
- await (0, import_promises10.mkdir)(targetDir, { recursive: true });
2785
+ await (0, import_promises11.mkdir)(targetDir, { recursive: true });
2264
2786
  if (projectFiles) {
2265
2787
  await Promise.all([
2266
- (0, import_promises10.writeFile)(import_node_path13.default.join(targetDir, "caatinga.config.ts"), configSource(options.projectName), {
2788
+ (0, import_promises11.writeFile)(import_node_path15.default.join(targetDir, "caatinga.config.ts"), configSource(options.projectName), {
2267
2789
  encoding: "utf8",
2268
2790
  flag: force ? "w" : "wx"
2269
2791
  }),
2270
- (0, import_promises10.writeFile)(import_node_path13.default.join(targetDir, "package.json"), packageJsonSource(options.projectName), {
2792
+ (0, import_promises11.writeFile)(import_node_path15.default.join(targetDir, "package.json"), packageJsonSource(options.projectName), {
2271
2793
  encoding: "utf8",
2272
2794
  flag: force ? "w" : "wx"
2273
2795
  }),
2274
- (0, import_promises10.writeFile)(import_node_path13.default.join(targetDir, ".gitignore"), "node_modules\n.artifacts\ntarget\n", {
2796
+ (0, import_promises11.writeFile)(import_node_path15.default.join(targetDir, ".gitignore"), "node_modules\n.artifacts\ntarget\n", {
2275
2797
  encoding: "utf8",
2276
2798
  flag: force ? "w" : "wx"
2277
2799
  }),
2278
- (0, import_promises10.writeFile)(import_node_path13.default.join(targetDir, "README.md"), readmeSource(options.projectName), {
2800
+ (0, import_promises11.writeFile)(import_node_path15.default.join(targetDir, "README.md"), readmeSource(options.projectName), {
2279
2801
  encoding: "utf8",
2280
2802
  flag: force ? "w" : "wx"
2281
2803
  })
2282
2804
  ]);
2283
2805
  }
2284
- await (0, import_promises10.mkdir)(import_node_path13.default.join(targetDir, "contracts"), { recursive: true });
2285
- await (0, import_promises10.cp)(import_node_path13.default.join(scaffoldRoot(), "zk-circuit-stub"), import_node_path13.default.join(targetDir, "circuits"), {
2806
+ await (0, import_promises11.mkdir)(import_node_path15.default.join(targetDir, "contracts"), { recursive: true });
2807
+ await (0, import_promises11.cp)(import_node_path15.default.join(scaffoldRoot(), "zk-circuit-stub"), import_node_path15.default.join(targetDir, "circuits"), {
2286
2808
  recursive: true,
2287
2809
  force,
2288
2810
  errorOnExist: !force
2289
2811
  });
2290
- await (0, import_promises10.cp)(
2291
- import_node_path13.default.join(scaffoldRoot(), "zk-verifier"),
2292
- import_node_path13.default.join(targetDir, "contracts", "verifier"),
2812
+ await (0, import_promises11.cp)(
2813
+ import_node_path15.default.join(scaffoldRoot(), "zk-verifier"),
2814
+ import_node_path15.default.join(targetDir, "contracts", "verifier"),
2293
2815
  {
2294
2816
  recursive: true,
2295
2817
  force,
@@ -2306,16 +2828,16 @@ async function createZkProject(options) {
2306
2828
  }
2307
2829
 
2308
2830
  // src/scaffold/create-minimal-project.ts
2309
- var import_promises11 = require("fs/promises");
2831
+ var import_promises12 = require("fs/promises");
2310
2832
  var import_node_fs3 = require("fs");
2311
- var import_node_path14 = __toESM(require("path"), 1);
2833
+ var import_node_path16 = __toESM(require("path"), 1);
2312
2834
  var import_node_url2 = require("url");
2313
2835
  var import_meta4 = {};
2314
- var moduleDir2 = typeof __dirname === "string" ? __dirname : import_node_path14.default.dirname((0, import_node_url2.fileURLToPath)(import_meta4.url));
2836
+ var moduleDir2 = typeof __dirname === "string" ? __dirname : import_node_path16.default.dirname((0, import_node_url2.fileURLToPath)(import_meta4.url));
2315
2837
  function scaffoldRoot2() {
2316
2838
  const candidates = [
2317
- import_node_path14.default.resolve(moduleDir2, "../../scaffolds"),
2318
- import_node_path14.default.resolve(moduleDir2, "../scaffolds")
2839
+ import_node_path16.default.resolve(moduleDir2, "../../scaffolds"),
2840
+ import_node_path16.default.resolve(moduleDir2, "../scaffolds")
2319
2841
  ];
2320
2842
  const found = candidates.find((candidate) => (0, import_node_fs3.existsSync)(candidate));
2321
2843
  return found ?? candidates[0];
@@ -2406,31 +2928,31 @@ Edit \`contracts/app/src/lib.rs\` to customize the contract. Add a frontend late
2406
2928
  `;
2407
2929
  }
2408
2930
  async function createMinimalProject(options) {
2409
- const targetDir = import_node_path14.default.resolve(options.targetDir);
2931
+ const targetDir = import_node_path16.default.resolve(options.targetDir);
2410
2932
  const force = options.force ?? false;
2411
- await (0, import_promises11.mkdir)(targetDir, { recursive: true });
2933
+ await (0, import_promises12.mkdir)(targetDir, { recursive: true });
2412
2934
  await Promise.all([
2413
- (0, import_promises11.writeFile)(import_node_path14.default.join(targetDir, "caatinga.config.ts"), configSource2(options.projectName), {
2935
+ (0, import_promises12.writeFile)(import_node_path16.default.join(targetDir, "caatinga.config.ts"), configSource2(options.projectName), {
2414
2936
  encoding: "utf8",
2415
2937
  flag: force ? "w" : "wx"
2416
2938
  }),
2417
- (0, import_promises11.writeFile)(import_node_path14.default.join(targetDir, "package.json"), packageJsonSource2(options.projectName), {
2939
+ (0, import_promises12.writeFile)(import_node_path16.default.join(targetDir, "package.json"), packageJsonSource2(options.projectName), {
2418
2940
  encoding: "utf8",
2419
2941
  flag: force ? "w" : "wx"
2420
2942
  }),
2421
- (0, import_promises11.writeFile)(import_node_path14.default.join(targetDir, ".gitignore"), "node_modules\n.artifacts\ntarget\n", {
2943
+ (0, import_promises12.writeFile)(import_node_path16.default.join(targetDir, ".gitignore"), "node_modules\n.artifacts\ntarget\n", {
2422
2944
  encoding: "utf8",
2423
2945
  flag: force ? "w" : "wx"
2424
2946
  }),
2425
- (0, import_promises11.writeFile)(import_node_path14.default.join(targetDir, "README.md"), readmeSource2(options.projectName), {
2947
+ (0, import_promises12.writeFile)(import_node_path16.default.join(targetDir, "README.md"), readmeSource2(options.projectName), {
2426
2948
  encoding: "utf8",
2427
2949
  flag: force ? "w" : "wx"
2428
2950
  })
2429
2951
  ]);
2430
- await (0, import_promises11.mkdir)(import_node_path14.default.join(targetDir, "contracts"), { recursive: true });
2431
- await (0, import_promises11.cp)(
2432
- import_node_path14.default.join(scaffoldRoot2(), "soroban-contract-stub"),
2433
- import_node_path14.default.join(targetDir, "contracts", "app"),
2952
+ await (0, import_promises12.mkdir)(import_node_path16.default.join(targetDir, "contracts"), { recursive: true });
2953
+ await (0, import_promises12.cp)(
2954
+ import_node_path16.default.join(scaffoldRoot2(), "soroban-contract-stub"),
2955
+ import_node_path16.default.join(targetDir, "contracts", "app"),
2434
2956
  {
2435
2957
  recursive: true,
2436
2958
  force,
@@ -2445,30 +2967,15 @@ async function createMinimalProject(options) {
2445
2967
  }
2446
2968
 
2447
2969
  // src/ci/is-transient-testnet-smoke-failure.ts
2448
- var NO_RETRY_CAATINGA_SUBSTRINGS = [
2449
- "CAATINGA_UNSUPPORTED_CLI_VERSION",
2450
- "CAATINGA_STELLAR_CLI_VERSION_PARSE_FAILED",
2451
- "CAATINGA_STELLAR_CLI_NOT_FOUND",
2452
- "CAATINGA_INVALID_CONFIG",
2453
- "CAATINGA_CONFIG_NOT_FOUND"
2454
- ];
2455
- var TRANSIENT_PATTERN = /timeout|i\/o timeout|econnreset|connection reset|503|502|429|rate limit|temporar|bad gateway|fetch failed|network error|unavailable/i;
2456
2970
  function isTransientTestnetSmokeFailure(logText) {
2457
- if (!logText.trim()) {
2458
- return false;
2459
- }
2460
- for (const marker of NO_RETRY_CAATINGA_SUBSTRINGS) {
2461
- if (logText.includes(marker)) {
2462
- return false;
2463
- }
2464
- }
2465
- return TRANSIENT_PATTERN.test(logText);
2971
+ return isTransientCommandFailure(logText);
2466
2972
  }
2467
2973
  // Annotate the CommonJS export names for ESM import in node:
2468
2974
  0 && (module.exports = {
2469
2975
  BINDING_MARKER_FILENAME,
2470
2976
  BindingMarkerSchema,
2471
2977
  CAATINGA_CORE_VERSION,
2978
+ CURRENT_ARTIFACTS_SCHEMA_VERSION,
2472
2979
  CaatingaArtifactsSchema,
2473
2980
  CaatingaConfigSchema,
2474
2981
  CaatingaError,
@@ -2476,6 +2983,8 @@ function isTransientTestnetSmokeFailure(logText) {
2476
2983
  READ_CALL_FAILURE_REGEX,
2477
2984
  STELLAR_CLI_LAST_TESTED_VERSION,
2478
2985
  STELLAR_CLI_MIN_VERSION,
2986
+ STELLAR_SDK_LAST_TESTED_VERSION,
2987
+ STELLAR_SDK_MIN_VERSION,
2479
2988
  TemplateManifestSchema,
2480
2989
  WELL_KNOWN_NETWORKS,
2481
2990
  buildContract,
@@ -2483,6 +2992,7 @@ function isTransientTestnetSmokeFailure(logText) {
2483
2992
  buildReadCallHint,
2484
2993
  checkBinary,
2485
2994
  checkStellarCliVersion,
2995
+ checkStellarSdkVersion,
2486
2996
  collectProjectStatus,
2487
2997
  createInitialArtifacts,
2488
2998
  createMinimalProject,
@@ -2491,20 +3001,26 @@ function isTransientTestnetSmokeFailure(logText) {
2491
3001
  defineConfig,
2492
3002
  deployContract,
2493
3003
  deployContractGraph,
3004
+ estimateDeployCost,
2494
3005
  evaluateBindingFreshness,
2495
3006
  evaluateBindingsFreshness,
2496
3007
  evaluateStellarCliCompatibility,
3008
+ evaluateStellarSdkCompatibility,
2497
3009
  formatCaatingaError,
2498
3010
  generateBindings,
2499
3011
  generateBindingsGraph,
3012
+ inspectContract,
2500
3013
  invokeContract,
2501
3014
  isCargoBinMissingFromPath,
2502
3015
  isReadCallFailure,
2503
3016
  isTransientTestnetSmokeFailure,
2504
3017
  loadConfig,
3018
+ migrateArtifactsFile,
3019
+ migrateArtifactsToV2,
2505
3020
  parseContractId,
2506
3021
  parseInvokeTarget,
2507
3022
  parseStellarCliVersion,
3023
+ parseStellarSdkVersion,
2508
3024
  readArtifacts,
2509
3025
  readBindingMarker,
2510
3026
  readContract,
@@ -2514,6 +3030,8 @@ function isTransientTestnetSmokeFailure(logText) {
2514
3030
  resolveDeployOrder,
2515
3031
  resolveNetwork,
2516
3032
  resolveSubprocessEnv,
3033
+ restoreArtifactFromHistory,
3034
+ rollbackContractArtifact,
2517
3035
  runCommand,
2518
3036
  toCaatingaError,
2519
3037
  updateArtifact,