@caatinga/core 3.2.0 → 3.3.1
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/artifact.schema-CIDkTrL3.d.cts +580 -0
- package/dist/artifact.schema-CIDkTrL3.d.ts +580 -0
- package/dist/browser.cjs +4 -0
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +4 -0
- package/dist/index.cjs +708 -171
- package/dist/index.d.cts +210 -9
- package/dist/index.d.ts +210 -9
- package/dist/index.js +670 -147
- package/dist/runtime/requirements.cjs +4 -0
- package/dist/runtime/requirements.js +4 -0
- package/package.json +1 -1
- package/dist/artifact.schema-DZC05uy_.d.cts +0 -186
- package/dist/artifact.schema-DZC05uy_.d.ts +0 -186
package/dist/index.js
CHANGED
|
@@ -8,6 +8,8 @@ var CaatingaErrorCode = {
|
|
|
8
8
|
STELLAR_CLI_NOT_FOUND: "CAATINGA_STELLAR_CLI_NOT_FOUND",
|
|
9
9
|
STELLAR_CLI_VERSION_PARSE_FAILED: "CAATINGA_STELLAR_CLI_VERSION_PARSE_FAILED",
|
|
10
10
|
UNSUPPORTED_CLI_VERSION: "CAATINGA_UNSUPPORTED_CLI_VERSION",
|
|
11
|
+
STELLAR_SDK_VERSION_PARSE_FAILED: "CAATINGA_STELLAR_SDK_VERSION_PARSE_FAILED",
|
|
12
|
+
UNSUPPORTED_SDK_VERSION: "CAATINGA_UNSUPPORTED_SDK_VERSION",
|
|
11
13
|
RUST_NOT_FOUND: "CAATINGA_RUST_NOT_FOUND",
|
|
12
14
|
RUST_TARGET_NOT_FOUND: "CAATINGA_RUST_TARGET_NOT_FOUND",
|
|
13
15
|
DEPLOY_FAILED: "CAATINGA_DEPLOY_FAILED",
|
|
@@ -50,6 +52,8 @@ var CaatingaErrorCode = {
|
|
|
50
52
|
ZK_VERIFICATION_FAILED: "CAATINGA_ZK_VERIFICATION_FAILED",
|
|
51
53
|
ZK_DEV_CEREMONY_BLOCKED: "CAATINGA_ZK_DEV_CEREMONY_BLOCKED",
|
|
52
54
|
DOCTOR_PARTIAL_DEPLOY: "CAATINGA_DOCTOR_PARTIAL_DEPLOY",
|
|
55
|
+
ROLLBACK_TARGET_NOT_FOUND: "CAATINGA_ROLLBACK_TARGET_NOT_FOUND",
|
|
56
|
+
ESTIMATE_FAILED: "CAATINGA_ESTIMATE_FAILED",
|
|
53
57
|
MULTI_AUTH_REQUIRED: "CAATINGA_MULTI_AUTH_REQUIRED"
|
|
54
58
|
};
|
|
55
59
|
|
|
@@ -236,6 +240,14 @@ async function loadConfig(options = {}) {
|
|
|
236
240
|
|
|
237
241
|
// src/artifacts/artifact.schema.ts
|
|
238
242
|
import { z as z3 } from "zod";
|
|
243
|
+
var ArtifactSupersedeReasonSchema = z3.enum(["upgrade", "rollback", "force-redeploy"]);
|
|
244
|
+
var ContractArtifactHistoryEntrySchema = z3.object({
|
|
245
|
+
contractId: z3.string().min(1),
|
|
246
|
+
wasmHash: z3.string().min(1),
|
|
247
|
+
deployedAt: z3.string().datetime(),
|
|
248
|
+
supersededAt: z3.string().datetime(),
|
|
249
|
+
reason: ArtifactSupersedeReasonSchema.optional()
|
|
250
|
+
});
|
|
239
251
|
var ContractArtifactSchema = z3.object({
|
|
240
252
|
contractId: z3.string().min(1),
|
|
241
253
|
wasmHash: z3.string().min(1),
|
|
@@ -243,17 +255,28 @@ var ContractArtifactSchema = z3.object({
|
|
|
243
255
|
sourcePath: z3.string().min(1),
|
|
244
256
|
wasmPath: z3.string().min(1),
|
|
245
257
|
dependencies: z3.array(z3.string().min(1)).default([]),
|
|
246
|
-
resolvedDeployArgs: z3.record(z3.string().min(1), z3.union([z3.string(), z3.number(), z3.boolean()])).default({})
|
|
258
|
+
resolvedDeployArgs: z3.record(z3.string().min(1), z3.union([z3.string(), z3.number(), z3.boolean()])).default({}),
|
|
259
|
+
history: z3.array(ContractArtifactHistoryEntrySchema).optional()
|
|
247
260
|
});
|
|
248
261
|
var NetworkArtifactsSchema = z3.object({
|
|
249
262
|
contracts: z3.record(z3.string().min(1), ContractArtifactSchema).default({}),
|
|
250
263
|
dependencyGraph: z3.record(z3.string().min(1), z3.array(z3.string().min(1))).default({})
|
|
251
264
|
});
|
|
252
|
-
var
|
|
265
|
+
var CaatingaArtifactsBaseSchema = z3.object({
|
|
253
266
|
project: z3.string().min(1),
|
|
254
|
-
version: z3.literal(1),
|
|
255
267
|
networks: z3.record(z3.string().min(1), NetworkArtifactsSchema).default({})
|
|
256
268
|
});
|
|
269
|
+
var CaatingaArtifactsV1Schema = CaatingaArtifactsBaseSchema.extend({
|
|
270
|
+
version: z3.literal(1)
|
|
271
|
+
});
|
|
272
|
+
var CaatingaArtifactsV2Schema = CaatingaArtifactsBaseSchema.extend({
|
|
273
|
+
version: z3.literal(2)
|
|
274
|
+
});
|
|
275
|
+
var CaatingaArtifactsSchema = z3.union([
|
|
276
|
+
CaatingaArtifactsV1Schema,
|
|
277
|
+
CaatingaArtifactsV2Schema
|
|
278
|
+
]);
|
|
279
|
+
var CURRENT_ARTIFACTS_SCHEMA_VERSION = 2;
|
|
257
280
|
|
|
258
281
|
// src/artifacts/read-artifacts.ts
|
|
259
282
|
import { readFile } from "fs/promises";
|
|
@@ -305,29 +328,139 @@ function createInitialArtifacts(project, options = {}) {
|
|
|
305
328
|
);
|
|
306
329
|
return {
|
|
307
330
|
project,
|
|
308
|
-
version:
|
|
331
|
+
version: 2,
|
|
309
332
|
networks
|
|
310
333
|
};
|
|
311
334
|
}
|
|
312
335
|
|
|
313
336
|
// src/artifacts/update-artifact.ts
|
|
314
|
-
function
|
|
337
|
+
function appendHistory(existing, reason) {
|
|
338
|
+
if (!existing || !reason) {
|
|
339
|
+
return existing?.history;
|
|
340
|
+
}
|
|
341
|
+
const supersededAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
342
|
+
const entry = {
|
|
343
|
+
contractId: existing.contractId,
|
|
344
|
+
wasmHash: existing.wasmHash,
|
|
345
|
+
deployedAt: existing.deployedAt,
|
|
346
|
+
supersededAt,
|
|
347
|
+
reason
|
|
348
|
+
};
|
|
349
|
+
return [...existing.history ?? [], entry];
|
|
350
|
+
}
|
|
351
|
+
function updateArtifact(artifacts, networkName, contractName, contractArtifact, options = {}) {
|
|
315
352
|
const existingNetwork = artifacts.networks[networkName] ?? { contracts: {}, dependencyGraph: {} };
|
|
353
|
+
const existingContract = existingNetwork.contracts[contractName];
|
|
354
|
+
const history = appendHistory(existingContract, options.supersedeReason);
|
|
355
|
+
const nextVersion = artifacts.version === 1 && options.supersedeReason ? 2 : artifacts.version;
|
|
316
356
|
return {
|
|
317
357
|
...artifacts,
|
|
358
|
+
version: nextVersion,
|
|
318
359
|
networks: {
|
|
319
360
|
...artifacts.networks,
|
|
320
361
|
[networkName]: {
|
|
321
362
|
...existingNetwork,
|
|
322
|
-
dependencyGraph:
|
|
363
|
+
dependencyGraph: options.dependencyGraph ?? existingNetwork.dependencyGraph ?? {},
|
|
323
364
|
contracts: {
|
|
324
365
|
...existingNetwork.contracts,
|
|
325
|
-
[contractName]:
|
|
366
|
+
[contractName]: {
|
|
367
|
+
...contractArtifact,
|
|
368
|
+
history: history ?? contractArtifact.history
|
|
369
|
+
}
|
|
326
370
|
}
|
|
327
371
|
}
|
|
328
372
|
}
|
|
329
373
|
};
|
|
330
374
|
}
|
|
375
|
+
function restoreArtifactFromHistory(input) {
|
|
376
|
+
const network = input.artifacts.networks[input.networkName];
|
|
377
|
+
const current = network?.contracts[input.contractName];
|
|
378
|
+
if (!current) {
|
|
379
|
+
throw new CaatingaError(
|
|
380
|
+
`No artifact for "${input.contractName}" on "${input.networkName}".`,
|
|
381
|
+
CaatingaErrorCode.ARTIFACT_NOT_FOUND,
|
|
382
|
+
"Deploy the contract before attempting rollback."
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
if (current.contractId === input.contractId) {
|
|
386
|
+
return input.artifacts;
|
|
387
|
+
}
|
|
388
|
+
const fromHistory = (current.history ?? []).find(
|
|
389
|
+
(entry) => entry.contractId === input.contractId
|
|
390
|
+
);
|
|
391
|
+
if (!fromHistory) {
|
|
392
|
+
throw new CaatingaError(
|
|
393
|
+
`Rollback target "${input.contractId}" was not found in artifact history for "${input.contractName}".`,
|
|
394
|
+
CaatingaErrorCode.ROLLBACK_TARGET_NOT_FOUND,
|
|
395
|
+
"Use caatinga inspect to list prior contract IDs, or redeploy manually."
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
const supersededAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
399
|
+
const restoredArtifact = {
|
|
400
|
+
contractId: fromHistory.contractId,
|
|
401
|
+
wasmHash: fromHistory.wasmHash,
|
|
402
|
+
deployedAt: fromHistory.deployedAt,
|
|
403
|
+
sourcePath: current.sourcePath,
|
|
404
|
+
wasmPath: current.wasmPath,
|
|
405
|
+
dependencies: current.dependencies,
|
|
406
|
+
resolvedDeployArgs: current.resolvedDeployArgs,
|
|
407
|
+
history: [
|
|
408
|
+
...current.history ?? [],
|
|
409
|
+
{
|
|
410
|
+
contractId: current.contractId,
|
|
411
|
+
wasmHash: current.wasmHash,
|
|
412
|
+
deployedAt: current.deployedAt,
|
|
413
|
+
supersededAt,
|
|
414
|
+
reason: "rollback"
|
|
415
|
+
}
|
|
416
|
+
]
|
|
417
|
+
};
|
|
418
|
+
return {
|
|
419
|
+
...updateArtifact(input.artifacts, input.networkName, input.contractName, restoredArtifact),
|
|
420
|
+
version: 2
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// src/artifacts/migrate-artifacts.ts
|
|
425
|
+
function migrateArtifactsToV2(artifacts) {
|
|
426
|
+
if (artifacts.version === CURRENT_ARTIFACTS_SCHEMA_VERSION) {
|
|
427
|
+
return {
|
|
428
|
+
artifacts,
|
|
429
|
+
migrated: false
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
const v1 = artifacts;
|
|
433
|
+
return {
|
|
434
|
+
artifacts: {
|
|
435
|
+
project: v1.project,
|
|
436
|
+
version: CURRENT_ARTIFACTS_SCHEMA_VERSION,
|
|
437
|
+
networks: v1.networks
|
|
438
|
+
},
|
|
439
|
+
migrated: true
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// src/artifacts/migrate-artifacts-file.ts
|
|
444
|
+
async function migrateArtifactsFile(cwd = process.cwd()) {
|
|
445
|
+
const artifacts = await readArtifacts(cwd);
|
|
446
|
+
const { artifacts: migrated, migrated: changed } = migrateArtifactsToV2(artifacts);
|
|
447
|
+
const path17 = await writeArtifacts(migrated, cwd);
|
|
448
|
+
return { path: path17, migrated: changed, artifacts: migrated };
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// src/artifacts/rollback-artifact.ts
|
|
452
|
+
async function rollbackContractArtifact(input) {
|
|
453
|
+
const cwd = input.cwd ?? process.cwd();
|
|
454
|
+
const artifacts = await readArtifacts(cwd);
|
|
455
|
+
const next = restoreArtifactFromHistory({
|
|
456
|
+
artifacts,
|
|
457
|
+
networkName: input.networkName,
|
|
458
|
+
contractName: input.contractName,
|
|
459
|
+
contractId: input.contractId
|
|
460
|
+
});
|
|
461
|
+
const path17 = await writeArtifacts(next, cwd);
|
|
462
|
+
return { path: path17, artifacts: next };
|
|
463
|
+
}
|
|
331
464
|
|
|
332
465
|
// src/networks/resolve-network.ts
|
|
333
466
|
function resolveNetwork(config, networkName) {
|
|
@@ -594,6 +727,35 @@ function evaluateStellarCliCompatibility(input) {
|
|
|
594
727
|
};
|
|
595
728
|
}
|
|
596
729
|
|
|
730
|
+
// src/stellar-cli/probe-stellar-cli-features.ts
|
|
731
|
+
import semver3 from "semver";
|
|
732
|
+
var STELLAR_CLI_REQUIRED_FEATURES = [
|
|
733
|
+
"contract-build",
|
|
734
|
+
"contract-deploy",
|
|
735
|
+
"contract-invoke-sign"
|
|
736
|
+
];
|
|
737
|
+
var FEATURE_COMMANDS = {
|
|
738
|
+
"contract-build": ["contract", "build", "--help"],
|
|
739
|
+
"contract-deploy": ["contract", "deploy", "--help"],
|
|
740
|
+
"contract-invoke-sign": ["contract", "invoke", "--help"]
|
|
741
|
+
};
|
|
742
|
+
async function probeMissingStellarCliFeatures(version) {
|
|
743
|
+
const missing = [];
|
|
744
|
+
if (semver3.valid(version) && semver3.lt(version, STELLAR_CLI_MIN_VERSION)) {
|
|
745
|
+
return ["contract-invoke-sign"];
|
|
746
|
+
}
|
|
747
|
+
for (const feature of STELLAR_CLI_REQUIRED_FEATURES) {
|
|
748
|
+
try {
|
|
749
|
+
await runCommand("stellar", FEATURE_COMMANDS[feature], {
|
|
750
|
+
skipStellarVersionCheck: true
|
|
751
|
+
});
|
|
752
|
+
} catch {
|
|
753
|
+
missing.push(feature);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
return missing;
|
|
757
|
+
}
|
|
758
|
+
|
|
597
759
|
// src/stellar-cli/check-stellar-cli-version.ts
|
|
598
760
|
async function checkStellarCliVersion(input = {}) {
|
|
599
761
|
let rawOutput;
|
|
@@ -613,9 +775,12 @@ async function checkStellarCliVersion(input = {}) {
|
|
|
613
775
|
}
|
|
614
776
|
throw error;
|
|
615
777
|
}
|
|
778
|
+
const version = parseStellarCliVersion(rawOutput);
|
|
779
|
+
const probedMissing = input.probeFeatures === false ? [] : await probeMissingStellarCliFeatures(version);
|
|
780
|
+
const missingFeatures = [...input.features ?? [], ...probedMissing];
|
|
616
781
|
const report = evaluateStellarCliCompatibility({
|
|
617
|
-
version
|
|
618
|
-
features:
|
|
782
|
+
version,
|
|
783
|
+
features: missingFeatures.length > 0 ? missingFeatures : void 0,
|
|
619
784
|
lastTestedVersion: input.lastTestedVersion
|
|
620
785
|
});
|
|
621
786
|
for (const warning of report.warnings) {
|
|
@@ -761,6 +926,122 @@ function parseContractId(output) {
|
|
|
761
926
|
return match[0];
|
|
762
927
|
}
|
|
763
928
|
|
|
929
|
+
// src/stellar-sdk/check-stellar-sdk-version.ts
|
|
930
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
931
|
+
import path7 from "path";
|
|
932
|
+
|
|
933
|
+
// src/stellar-sdk/compat.ts
|
|
934
|
+
import semver4 from "semver";
|
|
935
|
+
|
|
936
|
+
// src/stellar-sdk/version.ts
|
|
937
|
+
var STELLAR_SDK_MIN_VERSION = "16.0.1";
|
|
938
|
+
var STELLAR_SDK_LAST_TESTED_VERSION = "16.0.1";
|
|
939
|
+
|
|
940
|
+
// src/stellar-sdk/compat.ts
|
|
941
|
+
function evaluateStellarSdkCompatibility(input) {
|
|
942
|
+
const parsed = semver4.parse(input.version);
|
|
943
|
+
if (!parsed || !semver4.valid(input.version)) {
|
|
944
|
+
throw new CaatingaError(
|
|
945
|
+
"Could not parse @stellar/stellar-sdk version.",
|
|
946
|
+
CaatingaErrorCode.STELLAR_SDK_VERSION_PARSE_FAILED,
|
|
947
|
+
"Use a semantic version such as 16.0.1."
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
const lastTestedVersion = semver4.valid(input.lastTestedVersion ?? STELLAR_SDK_LAST_TESTED_VERSION) ?? STELLAR_SDK_LAST_TESTED_VERSION;
|
|
951
|
+
const warnings = [];
|
|
952
|
+
let status = "supported";
|
|
953
|
+
if (semver4.lt(parsed, STELLAR_SDK_MIN_VERSION)) {
|
|
954
|
+
throw new CaatingaError(
|
|
955
|
+
`@stellar/stellar-sdk ${input.version} is below the supported minimum ${STELLAR_SDK_MIN_VERSION}.`,
|
|
956
|
+
CaatingaErrorCode.UNSUPPORTED_SDK_VERSION,
|
|
957
|
+
`Install @stellar/stellar-sdk ${STELLAR_SDK_MIN_VERSION} or newer.`
|
|
958
|
+
);
|
|
959
|
+
}
|
|
960
|
+
if (semver4.gt(parsed, lastTestedVersion)) {
|
|
961
|
+
status = "untested";
|
|
962
|
+
warnings.push({
|
|
963
|
+
code: "STELLAR_SDK_UNTESTED_VERSION",
|
|
964
|
+
message: `@stellar/stellar-sdk ${input.version} is newer than the last-tested ${lastTestedVersion}; binding output may differ.`,
|
|
965
|
+
remediation: "Pin @stellar/stellar-sdk to the last-tested version in package.json, or update Caatinga fixtures after validating generate output."
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
return {
|
|
969
|
+
version: input.version,
|
|
970
|
+
status,
|
|
971
|
+
minVersion: STELLAR_SDK_MIN_VERSION,
|
|
972
|
+
lastTestedVersion,
|
|
973
|
+
warnings
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
function parseStellarSdkVersion(raw) {
|
|
977
|
+
const trimmed = raw.trim();
|
|
978
|
+
const match = trimmed.match(/(\d+\.\d+\.\d+(?:[-+][\w.-]+)?)/);
|
|
979
|
+
if (!match) {
|
|
980
|
+
throw new CaatingaError(
|
|
981
|
+
"Could not parse @stellar/stellar-sdk version.",
|
|
982
|
+
CaatingaErrorCode.STELLAR_SDK_VERSION_PARSE_FAILED,
|
|
983
|
+
"Expected output like 16.0.1."
|
|
984
|
+
);
|
|
985
|
+
}
|
|
986
|
+
return match[1];
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// src/stellar-sdk/check-stellar-sdk-version.ts
|
|
990
|
+
async function readInstalledSdkVersion(cwd) {
|
|
991
|
+
try {
|
|
992
|
+
const pkgPath = path7.join(cwd, "node_modules", "@stellar", "stellar-sdk", "package.json");
|
|
993
|
+
const raw = await readFile3(pkgPath, "utf8");
|
|
994
|
+
const pkg = JSON.parse(raw);
|
|
995
|
+
return typeof pkg.version === "string" ? pkg.version : void 0;
|
|
996
|
+
} catch {
|
|
997
|
+
return void 0;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
async function resolveRegistrySdkVersion() {
|
|
1001
|
+
const result = await runCommand("npm", ["view", "@stellar/stellar-sdk", "version"], {
|
|
1002
|
+
skipStellarVersionCheck: true
|
|
1003
|
+
});
|
|
1004
|
+
return parseStellarSdkVersion(result.stdout || result.all);
|
|
1005
|
+
}
|
|
1006
|
+
async function checkStellarSdkVersion(input = {}) {
|
|
1007
|
+
const cwd = input.cwd ?? process.cwd();
|
|
1008
|
+
let version;
|
|
1009
|
+
try {
|
|
1010
|
+
const installed = await readInstalledSdkVersion(cwd);
|
|
1011
|
+
version = installed ?? await resolveRegistrySdkVersion();
|
|
1012
|
+
} catch (error) {
|
|
1013
|
+
if (error instanceof CaatingaError) {
|
|
1014
|
+
throw error;
|
|
1015
|
+
}
|
|
1016
|
+
throw new CaatingaError(
|
|
1017
|
+
"Could not resolve @stellar/stellar-sdk version.",
|
|
1018
|
+
CaatingaErrorCode.STELLAR_SDK_VERSION_PARSE_FAILED,
|
|
1019
|
+
"Install @stellar/stellar-sdk in your project or ensure npm registry access.",
|
|
1020
|
+
error
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
const report = evaluateStellarSdkCompatibility({
|
|
1024
|
+
version,
|
|
1025
|
+
lastTestedVersion: input.lastTestedVersion
|
|
1026
|
+
});
|
|
1027
|
+
for (const warning of report.warnings) {
|
|
1028
|
+
if (input.onWarning) {
|
|
1029
|
+
input.onWarning(warning);
|
|
1030
|
+
} else {
|
|
1031
|
+
defaultEmitWarning2(warning);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
return report;
|
|
1035
|
+
}
|
|
1036
|
+
function defaultEmitWarning2(warning) {
|
|
1037
|
+
const lines = [
|
|
1038
|
+
`Warning: ${warning.message}`,
|
|
1039
|
+
warning.remediation ? ` ${warning.remediation}` : void 0
|
|
1040
|
+
].filter((line) => Boolean(line));
|
|
1041
|
+
process.stderr.write(`${lines.join("\n")}
|
|
1042
|
+
`);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
764
1045
|
// src/stellar-cli/build-stellar-network-args.ts
|
|
765
1046
|
function matchesWellKnownNetwork(name, config) {
|
|
766
1047
|
const known = WELL_KNOWN_NETWORKS[name];
|
|
@@ -898,8 +1179,38 @@ function validateSourceShape(source) {
|
|
|
898
1179
|
return void 0;
|
|
899
1180
|
}
|
|
900
1181
|
|
|
1182
|
+
// src/contracts/source-account.ts
|
|
1183
|
+
function assertSafeSourceAccount(source) {
|
|
1184
|
+
if (!source) {
|
|
1185
|
+
throw new CaatingaError(
|
|
1186
|
+
"A source account or Stellar CLI identity is required.",
|
|
1187
|
+
CaatingaErrorCode.SOURCE_ACCOUNT_REQUIRED,
|
|
1188
|
+
"Pass a Stellar CLI identity alias, for example: --source alice"
|
|
1189
|
+
);
|
|
1190
|
+
}
|
|
1191
|
+
const unsafeSource = validateSourceShape(source);
|
|
1192
|
+
if (unsafeSource) {
|
|
1193
|
+
throw unsafeSource;
|
|
1194
|
+
}
|
|
1195
|
+
return source;
|
|
1196
|
+
}
|
|
1197
|
+
var DEFAULT_CLI_SOURCE = "alice";
|
|
1198
|
+
function describeCliSource(explicit) {
|
|
1199
|
+
if (explicit) {
|
|
1200
|
+
return { source: assertSafeSourceAccount(explicit), origin: "explicit" };
|
|
1201
|
+
}
|
|
1202
|
+
const fromEnv = process.env.CAATINGA_SOURCE;
|
|
1203
|
+
if (fromEnv) {
|
|
1204
|
+
return { source: assertSafeSourceAccount(fromEnv), origin: "env" };
|
|
1205
|
+
}
|
|
1206
|
+
return { source: assertSafeSourceAccount(DEFAULT_CLI_SOURCE), origin: "default" };
|
|
1207
|
+
}
|
|
1208
|
+
function resolveCliSource(explicit) {
|
|
1209
|
+
return describeCliSource(explicit).source;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
901
1212
|
// src/contracts/resolve-contract.ts
|
|
902
|
-
import
|
|
1213
|
+
import path8 from "path";
|
|
903
1214
|
function resolveContract(config, contractName, cwd = process.cwd()) {
|
|
904
1215
|
const contract = config.contracts[contractName];
|
|
905
1216
|
if (!contract) {
|
|
@@ -912,8 +1223,8 @@ function resolveContract(config, contractName, cwd = process.cwd()) {
|
|
|
912
1223
|
return {
|
|
913
1224
|
name: contractName,
|
|
914
1225
|
config: contract,
|
|
915
|
-
sourcePath:
|
|
916
|
-
wasmPath:
|
|
1226
|
+
sourcePath: path8.resolve(cwd, contract.path),
|
|
1227
|
+
wasmPath: path8.resolve(cwd, contract.wasm)
|
|
917
1228
|
};
|
|
918
1229
|
}
|
|
919
1230
|
|
|
@@ -932,8 +1243,8 @@ function resolveDefaultContractName(config) {
|
|
|
932
1243
|
|
|
933
1244
|
// src/contracts/wasm.ts
|
|
934
1245
|
import { createHash } from "crypto";
|
|
935
|
-
import { access as access2, readdir as readdir2, readFile as
|
|
936
|
-
import
|
|
1246
|
+
import { access as access2, readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
|
|
1247
|
+
import path9 from "path";
|
|
937
1248
|
var LEGACY_RUST_WASM_TARGET = "wasm32-unknown-unknown";
|
|
938
1249
|
var CURRENT_RUST_WASM_TARGET = "wasm32v1-none";
|
|
939
1250
|
function toCurrentWasmTargetPath(wasmPath) {
|
|
@@ -964,18 +1275,18 @@ function wasmNotFoundError(configuredWasmPath, options) {
|
|
|
964
1275
|
);
|
|
965
1276
|
}
|
|
966
1277
|
function toConfigRelativeWasmPath(absoluteWasmPath) {
|
|
967
|
-
const relative =
|
|
968
|
-
return relative.startsWith("..") ? absoluteWasmPath : `./${relative.split(
|
|
1278
|
+
const relative = path9.relative(process.cwd(), absoluteWasmPath);
|
|
1279
|
+
return relative.startsWith("..") ? absoluteWasmPath : `./${relative.split(path9.sep).join("/")}`;
|
|
969
1280
|
}
|
|
970
1281
|
function wasmFileName(configuredWasmPath) {
|
|
971
|
-
return
|
|
1282
|
+
return path9.basename(configuredWasmPath);
|
|
972
1283
|
}
|
|
973
1284
|
function buildAlternateWasmCandidates(configuredWasmPath, options) {
|
|
974
1285
|
const fileName = wasmFileName(configuredWasmPath);
|
|
975
1286
|
const candidates = [];
|
|
976
1287
|
const seen = /* @__PURE__ */ new Set();
|
|
977
1288
|
function addCandidate(candidate) {
|
|
978
|
-
const resolved =
|
|
1289
|
+
const resolved = path9.resolve(candidate);
|
|
979
1290
|
if (seen.has(resolved)) {
|
|
980
1291
|
return;
|
|
981
1292
|
}
|
|
@@ -984,15 +1295,15 @@ function buildAlternateWasmCandidates(configuredWasmPath, options) {
|
|
|
984
1295
|
}
|
|
985
1296
|
const cargoTargetDir = process.env.CARGO_TARGET_DIR;
|
|
986
1297
|
if (cargoTargetDir) {
|
|
987
|
-
addCandidate(
|
|
988
|
-
addCandidate(
|
|
1298
|
+
addCandidate(path9.join(cargoTargetDir, CURRENT_RUST_WASM_TARGET, "release", fileName));
|
|
1299
|
+
addCandidate(path9.join(cargoTargetDir, LEGACY_RUST_WASM_TARGET, "release", fileName));
|
|
989
1300
|
}
|
|
990
1301
|
if (options?.sourcePath) {
|
|
991
1302
|
addCandidate(
|
|
992
|
-
|
|
1303
|
+
path9.join(options.sourcePath, "target", CURRENT_RUST_WASM_TARGET, "release", fileName)
|
|
993
1304
|
);
|
|
994
1305
|
addCandidate(
|
|
995
|
-
|
|
1306
|
+
path9.join(options.sourcePath, "target", LEGACY_RUST_WASM_TARGET, "release", fileName)
|
|
996
1307
|
);
|
|
997
1308
|
}
|
|
998
1309
|
return candidates;
|
|
@@ -1009,7 +1320,7 @@ async function firstExistingPath(paths) {
|
|
|
1009
1320
|
return void 0;
|
|
1010
1321
|
}
|
|
1011
1322
|
async function resolveWasmArtifactPath(configuredWasmPath, options) {
|
|
1012
|
-
const resolvedConfiguredPath =
|
|
1323
|
+
const resolvedConfiguredPath = path9.resolve(configuredWasmPath);
|
|
1013
1324
|
try {
|
|
1014
1325
|
await access2(resolvedConfiguredPath);
|
|
1015
1326
|
return resolvedConfiguredPath;
|
|
@@ -1033,7 +1344,7 @@ async function resolveWasmArtifactPath(configuredWasmPath, options) {
|
|
|
1033
1344
|
}
|
|
1034
1345
|
}
|
|
1035
1346
|
async function hashWasm(wasmPath) {
|
|
1036
|
-
const bytes = await
|
|
1347
|
+
const bytes = await readFile4(wasmPath);
|
|
1037
1348
|
return createHash("sha256").update(bytes).digest("hex");
|
|
1038
1349
|
}
|
|
1039
1350
|
async function getNewestMtimeInDirectory(directory) {
|
|
@@ -1046,7 +1357,7 @@ async function getNewestMtimeInDirectory(directory) {
|
|
|
1046
1357
|
async function walk(dir) {
|
|
1047
1358
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
1048
1359
|
for (const entry of entries) {
|
|
1049
|
-
const entryPath =
|
|
1360
|
+
const entryPath = path9.join(dir, entry.name);
|
|
1050
1361
|
if (entry.isDirectory()) {
|
|
1051
1362
|
await walk(entryPath);
|
|
1052
1363
|
continue;
|
|
@@ -1062,7 +1373,7 @@ async function getNewestMtimeInDirectory(directory) {
|
|
|
1062
1373
|
return newest > 0 ? newest : void 0;
|
|
1063
1374
|
}
|
|
1064
1375
|
async function isWasmOlderThanSources(input) {
|
|
1065
|
-
const srcDir =
|
|
1376
|
+
const srcDir = path9.join(input.contractPath, "src");
|
|
1066
1377
|
const newestSourceMtime = await getNewestMtimeInDirectory(srcDir);
|
|
1067
1378
|
if (newestSourceMtime === void 0) {
|
|
1068
1379
|
return false;
|
|
@@ -1137,7 +1448,38 @@ async function buildContract(options) {
|
|
|
1137
1448
|
}
|
|
1138
1449
|
|
|
1139
1450
|
// src/contracts/deploy-contract.ts
|
|
1140
|
-
import
|
|
1451
|
+
import path10 from "path";
|
|
1452
|
+
|
|
1453
|
+
// src/shell/is-transient-command-failure.ts
|
|
1454
|
+
var NO_RETRY_CAATINGA_SUBSTRINGS = [
|
|
1455
|
+
"CAATINGA_UNSUPPORTED_CLI_VERSION",
|
|
1456
|
+
"CAATINGA_STELLAR_CLI_VERSION_PARSE_FAILED",
|
|
1457
|
+
"CAATINGA_STELLAR_CLI_NOT_FOUND",
|
|
1458
|
+
"CAATINGA_INVALID_CONFIG",
|
|
1459
|
+
"CAATINGA_CONFIG_NOT_FOUND"
|
|
1460
|
+
];
|
|
1461
|
+
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;
|
|
1462
|
+
function isTransientCommandFailure(logText) {
|
|
1463
|
+
if (!logText.trim()) {
|
|
1464
|
+
return false;
|
|
1465
|
+
}
|
|
1466
|
+
for (const marker of NO_RETRY_CAATINGA_SUBSTRINGS) {
|
|
1467
|
+
if (logText.includes(marker)) {
|
|
1468
|
+
return false;
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
return TRANSIENT_COMMAND_FAILURE_PATTERN.test(logText);
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
// src/contracts/is-transient-deploy-failure.ts
|
|
1475
|
+
function isTransientDeployFailure(error) {
|
|
1476
|
+
if (!(error instanceof CaatingaError) || error.code !== CaatingaErrorCode.DEPLOY_FAILED) {
|
|
1477
|
+
return false;
|
|
1478
|
+
}
|
|
1479
|
+
const logText = `${error.message}
|
|
1480
|
+
${error.hint ?? ""}`;
|
|
1481
|
+
return isTransientCommandFailure(logText);
|
|
1482
|
+
}
|
|
1141
1483
|
|
|
1142
1484
|
// src/contracts/dependency-graph.ts
|
|
1143
1485
|
function buildDependencyGraph(contracts) {
|
|
@@ -1179,26 +1521,13 @@ function resolveDeployArgs(input) {
|
|
|
1179
1521
|
return resolved;
|
|
1180
1522
|
}
|
|
1181
1523
|
|
|
1182
|
-
// src/contracts/source-account.ts
|
|
1183
|
-
function assertSafeSourceAccount(source) {
|
|
1184
|
-
if (!source) {
|
|
1185
|
-
throw new CaatingaError(
|
|
1186
|
-
"A source account or Stellar CLI identity is required.",
|
|
1187
|
-
CaatingaErrorCode.SOURCE_ACCOUNT_REQUIRED,
|
|
1188
|
-
"Pass a Stellar CLI identity alias, for example: --source alice"
|
|
1189
|
-
);
|
|
1190
|
-
}
|
|
1191
|
-
const unsafeSource = validateSourceShape(source);
|
|
1192
|
-
if (unsafeSource) {
|
|
1193
|
-
throw unsafeSource;
|
|
1194
|
-
}
|
|
1195
|
-
return source;
|
|
1196
|
-
}
|
|
1197
|
-
function resolveCliSource(explicit) {
|
|
1198
|
-
return assertSafeSourceAccount(explicit ?? process.env.CAATINGA_SOURCE ?? "alice");
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
1524
|
// src/contracts/deploy-contract.ts
|
|
1525
|
+
var DEFAULT_DEPLOY_RETRY_DELAYS_MS = [2e3, 5e3];
|
|
1526
|
+
function sleep(ms) {
|
|
1527
|
+
return new Promise((resolve) => {
|
|
1528
|
+
setTimeout(resolve, ms);
|
|
1529
|
+
});
|
|
1530
|
+
}
|
|
1202
1531
|
function toSnakeCaseFlag(key) {
|
|
1203
1532
|
return key.replace(/([A-Z])/g, "_$1").replace(/^_/, "").toLowerCase();
|
|
1204
1533
|
}
|
|
@@ -1243,7 +1572,7 @@ async function deployContract(options) {
|
|
|
1243
1572
|
contract: contractWithWasm,
|
|
1244
1573
|
network,
|
|
1245
1574
|
contractId: existing.contractId,
|
|
1246
|
-
artifactsPath:
|
|
1575
|
+
artifactsPath: path10.resolve(cwd, "caatinga.artifacts.json"),
|
|
1247
1576
|
output: "",
|
|
1248
1577
|
skipped: true,
|
|
1249
1578
|
staleWasmWarning
|
|
@@ -1283,40 +1612,69 @@ async function deployContract(options) {
|
|
|
1283
1612
|
...buildStellarNetworkArgs(network),
|
|
1284
1613
|
...constructorArgs
|
|
1285
1614
|
];
|
|
1286
|
-
let
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1615
|
+
let deployOutcome;
|
|
1616
|
+
const retryDelaysMs = options.deployRetryDelaysMs ?? DEFAULT_DEPLOY_RETRY_DELAYS_MS;
|
|
1617
|
+
const maxDeployAttempts = retryDelaysMs.length + 1;
|
|
1618
|
+
for (let attempt = 0; attempt < maxDeployAttempts; attempt++) {
|
|
1619
|
+
try {
|
|
1620
|
+
const result = await runCommand("stellar", stellarArgs, {
|
|
1621
|
+
cwd,
|
|
1622
|
+
failureCode: CaatingaErrorCode.DEPLOY_FAILED
|
|
1623
|
+
});
|
|
1624
|
+
const output2 = result.all || `${result.stdout}
|
|
1294
1625
|
${result.stderr}`;
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1626
|
+
deployOutcome = {
|
|
1627
|
+
output: output2,
|
|
1628
|
+
contractId: parseContractId(output2)
|
|
1629
|
+
};
|
|
1630
|
+
break;
|
|
1631
|
+
} catch (error) {
|
|
1632
|
+
if (!(error instanceof CaatingaError) || error.code !== CaatingaErrorCode.DEPLOY_FAILED) {
|
|
1633
|
+
throw error;
|
|
1634
|
+
}
|
|
1635
|
+
const recoveredContractId = await tryRecoverContractIdFromDeployFailure({
|
|
1636
|
+
output: `${error.message}
|
|
1302
1637
|
${error.hint ?? ""}`,
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1638
|
+
source,
|
|
1639
|
+
network: network.config,
|
|
1640
|
+
cwd
|
|
1641
|
+
});
|
|
1642
|
+
if (recoveredContractId) {
|
|
1643
|
+
deployOutcome = {
|
|
1644
|
+
output: [
|
|
1645
|
+
error.hint ?? "",
|
|
1646
|
+
"Caatinga recovered the contract ID from the on-chain deploy transaction.",
|
|
1647
|
+
`Contract ID: ${recoveredContractId}`
|
|
1648
|
+
].filter(Boolean).join("\n"),
|
|
1649
|
+
contractId: recoveredContractId
|
|
1650
|
+
};
|
|
1651
|
+
break;
|
|
1652
|
+
}
|
|
1653
|
+
const isLastAttempt = attempt === maxDeployAttempts - 1;
|
|
1654
|
+
if (!isTransientDeployFailure(error) || isLastAttempt) {
|
|
1655
|
+
throw error;
|
|
1656
|
+
}
|
|
1657
|
+
const delayMs = retryDelaysMs[attempt] ?? retryDelaysMs[retryDelaysMs.length - 1] ?? 0;
|
|
1658
|
+
options.onTransientDeployRetry?.({
|
|
1659
|
+
attempt: attempt + 1,
|
|
1660
|
+
maxAttempts: maxDeployAttempts,
|
|
1661
|
+
delayMs
|
|
1662
|
+
});
|
|
1663
|
+
await sleep(delayMs);
|
|
1309
1664
|
}
|
|
1310
|
-
contractId = recoveredContractId;
|
|
1311
|
-
output = [
|
|
1312
|
-
error.hint ?? "",
|
|
1313
|
-
"Caatinga recovered the contract ID from the on-chain deploy transaction.",
|
|
1314
|
-
`Contract ID: ${contractId}`
|
|
1315
|
-
].filter(Boolean).join("\n");
|
|
1316
1665
|
}
|
|
1666
|
+
if (!deployOutcome) {
|
|
1667
|
+
throw new CaatingaError(
|
|
1668
|
+
"Deploy failed without a contract ID.",
|
|
1669
|
+
CaatingaErrorCode.DEPLOY_FAILED,
|
|
1670
|
+
"Re-run the deploy command with the underlying Stellar CLI for full diagnostics."
|
|
1671
|
+
);
|
|
1672
|
+
}
|
|
1673
|
+
const { output, contractId } = deployOutcome;
|
|
1317
1674
|
const wasmHash = await hashWasm(wasmPath);
|
|
1318
1675
|
const dependencyGraph = buildDependencyGraph(options.config.contracts);
|
|
1319
1676
|
const dependencies = options.dependencies ?? contract.config.dependsOn;
|
|
1677
|
+
const supersedeReason = existing?.contractId && options.force ? options.upgrade ? "upgrade" : "force-redeploy" : void 0;
|
|
1320
1678
|
const nextArtifacts = updateArtifact(
|
|
1321
1679
|
artifactsBefore,
|
|
1322
1680
|
network.name,
|
|
@@ -1330,7 +1688,7 @@ ${error.hint ?? ""}`,
|
|
|
1330
1688
|
dependencies,
|
|
1331
1689
|
resolvedDeployArgs
|
|
1332
1690
|
},
|
|
1333
|
-
{ dependencyGraph }
|
|
1691
|
+
{ dependencyGraph, supersedeReason }
|
|
1334
1692
|
);
|
|
1335
1693
|
const artifactsPath = await writeArtifacts(nextArtifacts, cwd);
|
|
1336
1694
|
return {
|
|
@@ -1494,9 +1852,11 @@ async function deployContractGraph(options) {
|
|
|
1494
1852
|
source: options.source,
|
|
1495
1853
|
cwd,
|
|
1496
1854
|
force: options.force,
|
|
1855
|
+
upgrade: options.upgrade,
|
|
1497
1856
|
checkStaleWasm: options.checkStaleWasm,
|
|
1498
1857
|
resolvedDeployArgs,
|
|
1499
|
-
dependencies: contractConfig.dependsOn
|
|
1858
|
+
dependencies: contractConfig.dependsOn,
|
|
1859
|
+
onTransientDeployRetry: options.onTransientDeployRetry
|
|
1500
1860
|
});
|
|
1501
1861
|
if (result.staleWasmWarning) {
|
|
1502
1862
|
staleWasmWarnings.push({
|
|
@@ -1520,11 +1880,11 @@ async function deployContractGraph(options) {
|
|
|
1520
1880
|
|
|
1521
1881
|
// src/contracts/generate-bindings.ts
|
|
1522
1882
|
import { access as access4, mkdir as mkdir2, unlink } from "fs/promises";
|
|
1523
|
-
import
|
|
1883
|
+
import path12 from "path";
|
|
1524
1884
|
|
|
1525
1885
|
// src/bindings/patch-generated-binding-package.ts
|
|
1526
|
-
import { access as access3, readFile as
|
|
1527
|
-
import
|
|
1886
|
+
import { access as access3, readFile as readFile5, writeFile as writeFile3 } from "fs/promises";
|
|
1887
|
+
import path11 from "path";
|
|
1528
1888
|
var BUNDLER_ENTRY = "./src/index.ts";
|
|
1529
1889
|
var ROOT_BINDING_INDEX_CONTENT = 'export * from "./src/index.js";\n';
|
|
1530
1890
|
function resolveExportEntry(exportsField) {
|
|
@@ -1559,9 +1919,9 @@ function shouldPatchPackageJson(packageJson) {
|
|
|
1559
1919
|
return pointsToDist(packageJson.main) || pointsToDist(packageJson.types) || !pointsToBundlerSource(exportEntry);
|
|
1560
1920
|
}
|
|
1561
1921
|
async function ensureRootBindingIndex(outputDir) {
|
|
1562
|
-
const rootIndexPath =
|
|
1922
|
+
const rootIndexPath = path11.join(outputDir, "index.ts");
|
|
1563
1923
|
try {
|
|
1564
|
-
const existing = await
|
|
1924
|
+
const existing = await readFile5(rootIndexPath, "utf8");
|
|
1565
1925
|
if (existing === ROOT_BINDING_INDEX_CONTENT) {
|
|
1566
1926
|
return;
|
|
1567
1927
|
}
|
|
@@ -1571,8 +1931,8 @@ async function ensureRootBindingIndex(outputDir) {
|
|
|
1571
1931
|
}
|
|
1572
1932
|
}
|
|
1573
1933
|
async function patchGeneratedBindingPackage(outputDir) {
|
|
1574
|
-
const packageJsonPath =
|
|
1575
|
-
const entryPath =
|
|
1934
|
+
const packageJsonPath = path11.join(outputDir, "package.json");
|
|
1935
|
+
const entryPath = path11.join(outputDir, "src", "index.ts");
|
|
1576
1936
|
try {
|
|
1577
1937
|
await access3(entryPath);
|
|
1578
1938
|
} catch {
|
|
@@ -1584,7 +1944,7 @@ async function patchGeneratedBindingPackage(outputDir) {
|
|
|
1584
1944
|
}
|
|
1585
1945
|
let raw;
|
|
1586
1946
|
try {
|
|
1587
|
-
raw = await
|
|
1947
|
+
raw = await readFile5(packageJsonPath, "utf8");
|
|
1588
1948
|
} catch {
|
|
1589
1949
|
throw new CaatingaError(
|
|
1590
1950
|
"Generated binding package is missing package.json.",
|
|
@@ -1625,11 +1985,11 @@ function buildGenerateNetworkArgs(network) {
|
|
|
1625
1985
|
|
|
1626
1986
|
// src/contracts/generate-bindings.ts
|
|
1627
1987
|
function toBindingImportPath(bindingsOutput, contractName) {
|
|
1628
|
-
const normalized = bindingsOutput.replace(/^\.\//, "").split(
|
|
1629
|
-
return `./${
|
|
1988
|
+
const normalized = bindingsOutput.replace(/^\.\//, "").split(path12.sep).join("/");
|
|
1989
|
+
return `./${path12.posix.join(normalized, contractName)}`;
|
|
1630
1990
|
}
|
|
1631
1991
|
async function removeLegacyBindingStub(cwd, bindingsOutput, contractName) {
|
|
1632
|
-
const legacyPath =
|
|
1992
|
+
const legacyPath = path12.resolve(cwd, bindingsOutput, `${contractName}.ts`);
|
|
1633
1993
|
try {
|
|
1634
1994
|
await access4(legacyPath);
|
|
1635
1995
|
await unlink(legacyPath);
|
|
@@ -1657,8 +2017,9 @@ async function generateBindings(options) {
|
|
|
1657
2017
|
"Run caatinga deploy for this contract and network before generating bindings."
|
|
1658
2018
|
);
|
|
1659
2019
|
}
|
|
1660
|
-
const outputDir =
|
|
2020
|
+
const outputDir = path12.resolve(cwd, options.config.frontend.bindingsOutput, options.contractName);
|
|
1661
2021
|
await mkdir2(outputDir, { recursive: true });
|
|
2022
|
+
await checkStellarSdkVersion({ cwd });
|
|
1662
2023
|
const result = await runCommand(
|
|
1663
2024
|
"npx",
|
|
1664
2025
|
[
|
|
@@ -1883,14 +2244,172 @@ async function readContract(options) {
|
|
|
1883
2244
|
};
|
|
1884
2245
|
}
|
|
1885
2246
|
|
|
2247
|
+
// src/contracts/estimate-deploy-cost.ts
|
|
2248
|
+
import path13 from "path";
|
|
2249
|
+
function toSnakeCaseFlag2(key) {
|
|
2250
|
+
return key.replace(/([A-Z])/g, "_$1").replace(/^_/, "").toLowerCase();
|
|
2251
|
+
}
|
|
2252
|
+
function formatConstructorCliArgs2(resolved) {
|
|
2253
|
+
const entries = Object.entries(resolved);
|
|
2254
|
+
if (entries.length === 0) {
|
|
2255
|
+
return [];
|
|
2256
|
+
}
|
|
2257
|
+
const tail = ["--"];
|
|
2258
|
+
for (const [key, value] of entries) {
|
|
2259
|
+
tail.push(`--${toSnakeCaseFlag2(key)}`, String(value));
|
|
2260
|
+
}
|
|
2261
|
+
return tail;
|
|
2262
|
+
}
|
|
2263
|
+
function parseFeeStroops(output) {
|
|
2264
|
+
const inclusionMatch = output.match(/inclusion[_\s-]*fee[:\s]+(\d+)/i);
|
|
2265
|
+
const resourceMatch = output.match(/resource[_\s-]*fee[:\s]+(\d+)/i);
|
|
2266
|
+
const totalMatch = output.match(/total[_\s-]*fee[:\s]+(\d+)/i);
|
|
2267
|
+
return {
|
|
2268
|
+
inclusion: inclusionMatch ? Number(inclusionMatch[1]) : void 0,
|
|
2269
|
+
resource: resourceMatch ? Number(resourceMatch[1]) : void 0,
|
|
2270
|
+
...totalMatch && !resourceMatch ? { resource: Number(totalMatch[1]) } : {}
|
|
2271
|
+
};
|
|
2272
|
+
}
|
|
2273
|
+
async function estimateDeployCost(options) {
|
|
2274
|
+
const cwd = options.cwd ?? process.cwd();
|
|
2275
|
+
const contract = resolveContract(options.config, options.contractName, cwd);
|
|
2276
|
+
const network = resolveNetwork(options.config, options.networkName);
|
|
2277
|
+
const source = assertSafeSourceAccount(options.source);
|
|
2278
|
+
await checkBinary("stellar", "Install Stellar CLI before running caatinga estimate.");
|
|
2279
|
+
const wasmPath = await resolveWasmArtifactPath(contract.wasmPath, {
|
|
2280
|
+
sourcePath: contract.sourcePath
|
|
2281
|
+
});
|
|
2282
|
+
const artifacts = await readArtifacts(cwd);
|
|
2283
|
+
const rawDeployArgs = contract.config.deployArgs;
|
|
2284
|
+
const resolvedDeployArgs = Object.keys(rawDeployArgs).length > 0 ? resolveDeployArgs({
|
|
2285
|
+
deployArgs: rawDeployArgs,
|
|
2286
|
+
artifacts,
|
|
2287
|
+
network: network.name
|
|
2288
|
+
}) : {};
|
|
2289
|
+
const constructorArgs = formatConstructorCliArgs2(resolvedDeployArgs);
|
|
2290
|
+
const deployArgs = [
|
|
2291
|
+
"contract",
|
|
2292
|
+
"deploy",
|
|
2293
|
+
"--wasm",
|
|
2294
|
+
wasmPath,
|
|
2295
|
+
"--source-account",
|
|
2296
|
+
source,
|
|
2297
|
+
"--build-only",
|
|
2298
|
+
...buildStellarNetworkArgs(network),
|
|
2299
|
+
...constructorArgs
|
|
2300
|
+
];
|
|
2301
|
+
let buildOutput;
|
|
2302
|
+
try {
|
|
2303
|
+
const buildResult = await runCommand("stellar", deployArgs, {
|
|
2304
|
+
cwd,
|
|
2305
|
+
failureCode: CaatingaErrorCode.ESTIMATE_FAILED
|
|
2306
|
+
});
|
|
2307
|
+
buildOutput = (buildResult.stdout || buildResult.all).trim();
|
|
2308
|
+
} catch (error) {
|
|
2309
|
+
if (error instanceof CaatingaError) {
|
|
2310
|
+
throw new CaatingaError(
|
|
2311
|
+
`Deploy cost estimate failed for "${contract.name}".`,
|
|
2312
|
+
CaatingaErrorCode.ESTIMATE_FAILED,
|
|
2313
|
+
error.hint ?? "Ensure WASM is built and deploy args resolve correctly.",
|
|
2314
|
+
error.cause
|
|
2315
|
+
);
|
|
2316
|
+
}
|
|
2317
|
+
throw error;
|
|
2318
|
+
}
|
|
2319
|
+
const simulateArgs = ["tx", "simulate", "--source-account", source, buildOutput];
|
|
2320
|
+
let simulateOutput = "";
|
|
2321
|
+
try {
|
|
2322
|
+
const simulateResult = await runCommand("stellar", simulateArgs, {
|
|
2323
|
+
cwd,
|
|
2324
|
+
failureCode: CaatingaErrorCode.ESTIMATE_FAILED
|
|
2325
|
+
});
|
|
2326
|
+
simulateOutput = simulateResult.all || `${simulateResult.stdout}
|
|
2327
|
+
${simulateResult.stderr}`;
|
|
2328
|
+
} catch {
|
|
2329
|
+
simulateOutput = "";
|
|
2330
|
+
}
|
|
2331
|
+
const parsed = parseFeeStroops(simulateOutput);
|
|
2332
|
+
const inclusionFeeStroops = parsed.inclusion ?? 100;
|
|
2333
|
+
const resourceFeeStroops = parsed.resource;
|
|
2334
|
+
const totalFeeStroops = inclusionFeeStroops + (resourceFeeStroops ?? 0);
|
|
2335
|
+
return {
|
|
2336
|
+
contractName: contract.name,
|
|
2337
|
+
network: network.name,
|
|
2338
|
+
wasmPath: path13.relative(cwd, wasmPath) || wasmPath,
|
|
2339
|
+
inclusionFeeStroops,
|
|
2340
|
+
resourceFeeStroops,
|
|
2341
|
+
totalFeeStroops,
|
|
2342
|
+
advisory: "Advisory estimate only \u2014 actual fees may differ under network congestion or contract complexity.",
|
|
2343
|
+
rawOutput: simulateOutput || buildOutput
|
|
2344
|
+
};
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2347
|
+
// src/contracts/inspect-contract.ts
|
|
2348
|
+
async function inspectContract(options) {
|
|
2349
|
+
const cwd = options.cwd ?? process.cwd();
|
|
2350
|
+
const contract = resolveContract(options.config, options.contractName, cwd);
|
|
2351
|
+
const network = resolveNetwork(options.config, options.networkName);
|
|
2352
|
+
const artifacts = await readArtifacts(cwd);
|
|
2353
|
+
const artifact = artifacts.networks[network.name]?.contracts[contract.name];
|
|
2354
|
+
if (!artifact) {
|
|
2355
|
+
throw new CaatingaError(
|
|
2356
|
+
`No deployed artifact found for "${contract.name}" on "${network.name}".`,
|
|
2357
|
+
CaatingaErrorCode.ARTIFACT_NOT_FOUND,
|
|
2358
|
+
"Run caatinga deploy before inspect."
|
|
2359
|
+
);
|
|
2360
|
+
}
|
|
2361
|
+
await checkBinary("stellar", "Install Stellar CLI before running caatinga inspect.");
|
|
2362
|
+
let reachable = false;
|
|
2363
|
+
let detail;
|
|
2364
|
+
try {
|
|
2365
|
+
await verifyDependencyContract({
|
|
2366
|
+
dependencyName: contract.name,
|
|
2367
|
+
contractId: artifact.contractId,
|
|
2368
|
+
network,
|
|
2369
|
+
cwd
|
|
2370
|
+
});
|
|
2371
|
+
reachable = true;
|
|
2372
|
+
detail = "Contract interface reachable on network.";
|
|
2373
|
+
} catch (error) {
|
|
2374
|
+
reachable = false;
|
|
2375
|
+
detail = error instanceof CaatingaError ? error.message : "Contract not reachable on network.";
|
|
2376
|
+
}
|
|
2377
|
+
let localHash;
|
|
2378
|
+
try {
|
|
2379
|
+
const wasmPath = await resolveWasmArtifactPath(contract.wasmPath, {
|
|
2380
|
+
sourcePath: contract.sourcePath
|
|
2381
|
+
});
|
|
2382
|
+
localHash = await hashWasm(wasmPath);
|
|
2383
|
+
} catch {
|
|
2384
|
+
localHash = void 0;
|
|
2385
|
+
}
|
|
2386
|
+
return {
|
|
2387
|
+
contractName: contract.name,
|
|
2388
|
+
network: network.name,
|
|
2389
|
+
artifact: {
|
|
2390
|
+
contractId: artifact.contractId,
|
|
2391
|
+
wasmHash: artifact.wasmHash,
|
|
2392
|
+
deployedAt: artifact.deployedAt,
|
|
2393
|
+
historyCount: artifact.history?.length ?? 0
|
|
2394
|
+
},
|
|
2395
|
+
onChain: { reachable, detail },
|
|
2396
|
+
localWasm: {
|
|
2397
|
+
path: contract.config.wasm,
|
|
2398
|
+
hash: localHash,
|
|
2399
|
+
matchesArtifact: Boolean(localHash && localHash === artifact.wasmHash)
|
|
2400
|
+
},
|
|
2401
|
+
dependencies: artifact.dependencies ?? contract.config.dependsOn ?? []
|
|
2402
|
+
};
|
|
2403
|
+
}
|
|
2404
|
+
|
|
1886
2405
|
// src/templates/create-project-from-template.ts
|
|
1887
|
-
import { cp, mkdir as mkdir3, readFile as
|
|
1888
|
-
import
|
|
2406
|
+
import { cp, lstat, mkdir as mkdir3, readFile as readFile6, readdir as readdir3, stat as stat2, writeFile as writeFile4 } from "fs/promises";
|
|
2407
|
+
import path14 from "path";
|
|
1889
2408
|
import { z as z7 } from "zod";
|
|
1890
2409
|
|
|
1891
2410
|
// src/templates/template-manifest.schema.ts
|
|
1892
2411
|
import { z as z6 } from "zod";
|
|
1893
|
-
import
|
|
2412
|
+
import semver5 from "semver";
|
|
1894
2413
|
var CURRENT_TEMPLATE_VERSION = 1;
|
|
1895
2414
|
var TemplateManifestSchema = z6.object({
|
|
1896
2415
|
name: z6.string().min(1),
|
|
@@ -1914,14 +2433,14 @@ var TemplateManifestSchema = z6.object({
|
|
|
1914
2433
|
})
|
|
1915
2434
|
});
|
|
1916
2435
|
function defaultCompatibleCoreRange(coreVersion = CAATINGA_CORE_VERSION) {
|
|
1917
|
-
const version =
|
|
2436
|
+
const version = semver5.valid(semver5.coerce(coreVersion));
|
|
1918
2437
|
if (!version) {
|
|
1919
2438
|
throw new Error(`Invalid core version: ${coreVersion}`);
|
|
1920
2439
|
}
|
|
1921
2440
|
return `^${version}`;
|
|
1922
2441
|
}
|
|
1923
2442
|
function isCoreVersionCompatible(range, coreVersion = CAATINGA_CORE_VERSION) {
|
|
1924
|
-
return
|
|
2443
|
+
return semver5.satisfies(coreVersion, range);
|
|
1925
2444
|
}
|
|
1926
2445
|
function getTemplateCompatibilityIssue(manifest, coreVersion = CAATINGA_CORE_VERSION) {
|
|
1927
2446
|
if (manifest.caatinga.templateVersion !== CURRENT_TEMPLATE_VERSION) {
|
|
@@ -1956,8 +2475,8 @@ function formatTemplateCompatibilityHint(issue) {
|
|
|
1956
2475
|
// src/templates/create-project-from-template.ts
|
|
1957
2476
|
var TEMPLATE_COPY_EXCLUDED_DIRS = /* @__PURE__ */ new Set(["target", "test_snapshots", "node_modules", ".git"]);
|
|
1958
2477
|
async function createProjectFromTemplate(options) {
|
|
1959
|
-
const targetDir =
|
|
1960
|
-
const templateDir =
|
|
2478
|
+
const targetDir = path14.resolve(options.targetDir);
|
|
2479
|
+
const templateDir = path14.resolve(options.templateDir);
|
|
1961
2480
|
try {
|
|
1962
2481
|
await stat2(templateDir);
|
|
1963
2482
|
} catch {
|
|
@@ -1998,9 +2517,9 @@ async function ensureArtifacts(targetDir, projectName) {
|
|
|
1998
2517
|
}
|
|
1999
2518
|
}
|
|
2000
2519
|
async function readTemplateManifest(templateDir) {
|
|
2001
|
-
const manifestPath =
|
|
2520
|
+
const manifestPath = path14.join(templateDir, "caatinga.template.json");
|
|
2002
2521
|
try {
|
|
2003
|
-
const rawManifest = await
|
|
2522
|
+
const rawManifest = await readFile6(manifestPath, "utf8");
|
|
2004
2523
|
const manifest = TemplateManifestSchema.parse(JSON.parse(rawManifest));
|
|
2005
2524
|
const compatibilityIssue = getTemplateCompatibilityIssue(manifest);
|
|
2006
2525
|
if (compatibilityIssue) {
|
|
@@ -2036,47 +2555,53 @@ async function replaceTemplateVariables(dir, projectName) {
|
|
|
2036
2555
|
const entries = await readdir3(dir);
|
|
2037
2556
|
await Promise.all(
|
|
2038
2557
|
entries.map(async (entry) => {
|
|
2039
|
-
|
|
2040
|
-
|
|
2558
|
+
if (TEMPLATE_COPY_EXCLUDED_DIRS.has(entry)) {
|
|
2559
|
+
return;
|
|
2560
|
+
}
|
|
2561
|
+
const entryPath = path14.join(dir, entry);
|
|
2562
|
+
const entryStat = await lstat(entryPath);
|
|
2563
|
+
if (entryStat.isSymbolicLink()) {
|
|
2564
|
+
return;
|
|
2565
|
+
}
|
|
2041
2566
|
if (entryStat.isDirectory()) {
|
|
2042
2567
|
await replaceTemplateVariables(entryPath, projectName);
|
|
2043
2568
|
return;
|
|
2044
2569
|
}
|
|
2045
|
-
if (!isTextTemplateFile(entryPath)) {
|
|
2570
|
+
if (!entryStat.isFile() || !isTextTemplateFile(entryPath)) {
|
|
2046
2571
|
return;
|
|
2047
2572
|
}
|
|
2048
|
-
const content = await
|
|
2573
|
+
const content = await readFile6(entryPath, "utf8");
|
|
2049
2574
|
await writeFile4(entryPath, content.replaceAll("__PROJECT_NAME__", projectName), "utf8");
|
|
2050
2575
|
})
|
|
2051
2576
|
);
|
|
2052
2577
|
}
|
|
2053
2578
|
function shouldCopyTemplateEntry(templateDir, source, userFilter) {
|
|
2054
|
-
const relativePath =
|
|
2579
|
+
const relativePath = path14.relative(templateDir, source);
|
|
2055
2580
|
if (!relativePath || relativePath === ".") {
|
|
2056
2581
|
return true;
|
|
2057
2582
|
}
|
|
2058
|
-
const normalizedPath = relativePath.split(
|
|
2583
|
+
const normalizedPath = relativePath.split(path14.sep).join("/");
|
|
2059
2584
|
if (userFilter && !userFilter(normalizedPath)) {
|
|
2060
2585
|
return false;
|
|
2061
2586
|
}
|
|
2062
|
-
return !relativePath.split(
|
|
2587
|
+
return !relativePath.split(path14.sep).some((segment) => TEMPLATE_COPY_EXCLUDED_DIRS.has(segment));
|
|
2063
2588
|
}
|
|
2064
2589
|
function isTextTemplateFile(filePath) {
|
|
2065
2590
|
return [".json", ".md", ".rs", ".toml", ".ts", ".tsx", ".css", ".html"].includes(
|
|
2066
|
-
|
|
2591
|
+
path14.extname(filePath)
|
|
2067
2592
|
);
|
|
2068
2593
|
}
|
|
2069
2594
|
|
|
2070
2595
|
// src/scaffold/create-zk-project.ts
|
|
2071
2596
|
import { cp as cp2, mkdir as mkdir4, writeFile as writeFile5 } from "fs/promises";
|
|
2072
2597
|
import { existsSync as existsSync2 } from "fs";
|
|
2073
|
-
import
|
|
2598
|
+
import path15 from "path";
|
|
2074
2599
|
import { fileURLToPath } from "url";
|
|
2075
|
-
var moduleDir = typeof __dirname === "string" ? __dirname :
|
|
2600
|
+
var moduleDir = typeof __dirname === "string" ? __dirname : path15.dirname(fileURLToPath(import.meta.url));
|
|
2076
2601
|
function scaffoldRoot() {
|
|
2077
2602
|
const candidates = [
|
|
2078
|
-
|
|
2079
|
-
|
|
2603
|
+
path15.resolve(moduleDir, "../../scaffolds"),
|
|
2604
|
+
path15.resolve(moduleDir, "../scaffolds")
|
|
2080
2605
|
];
|
|
2081
2606
|
const found = candidates.find((candidate) => existsSync2(candidate));
|
|
2082
2607
|
return found ?? candidates[0];
|
|
@@ -2167,39 +2692,39 @@ Replace \`circuits/main.circom\` with your circuit. Keep the entry point named \
|
|
|
2167
2692
|
`;
|
|
2168
2693
|
}
|
|
2169
2694
|
async function createZkProject(options) {
|
|
2170
|
-
const targetDir =
|
|
2695
|
+
const targetDir = path15.resolve(options.targetDir);
|
|
2171
2696
|
const force = options.force ?? false;
|
|
2172
2697
|
const projectFiles = options.projectFiles ?? true;
|
|
2173
2698
|
await mkdir4(targetDir, { recursive: true });
|
|
2174
2699
|
if (projectFiles) {
|
|
2175
2700
|
await Promise.all([
|
|
2176
|
-
writeFile5(
|
|
2701
|
+
writeFile5(path15.join(targetDir, "caatinga.config.ts"), configSource(options.projectName), {
|
|
2177
2702
|
encoding: "utf8",
|
|
2178
2703
|
flag: force ? "w" : "wx"
|
|
2179
2704
|
}),
|
|
2180
|
-
writeFile5(
|
|
2705
|
+
writeFile5(path15.join(targetDir, "package.json"), packageJsonSource(options.projectName), {
|
|
2181
2706
|
encoding: "utf8",
|
|
2182
2707
|
flag: force ? "w" : "wx"
|
|
2183
2708
|
}),
|
|
2184
|
-
writeFile5(
|
|
2709
|
+
writeFile5(path15.join(targetDir, ".gitignore"), "node_modules\n.artifacts\ntarget\n", {
|
|
2185
2710
|
encoding: "utf8",
|
|
2186
2711
|
flag: force ? "w" : "wx"
|
|
2187
2712
|
}),
|
|
2188
|
-
writeFile5(
|
|
2713
|
+
writeFile5(path15.join(targetDir, "README.md"), readmeSource(options.projectName), {
|
|
2189
2714
|
encoding: "utf8",
|
|
2190
2715
|
flag: force ? "w" : "wx"
|
|
2191
2716
|
})
|
|
2192
2717
|
]);
|
|
2193
2718
|
}
|
|
2194
|
-
await mkdir4(
|
|
2195
|
-
await cp2(
|
|
2719
|
+
await mkdir4(path15.join(targetDir, "contracts"), { recursive: true });
|
|
2720
|
+
await cp2(path15.join(scaffoldRoot(), "zk-circuit-stub"), path15.join(targetDir, "circuits"), {
|
|
2196
2721
|
recursive: true,
|
|
2197
2722
|
force,
|
|
2198
2723
|
errorOnExist: !force
|
|
2199
2724
|
});
|
|
2200
2725
|
await cp2(
|
|
2201
|
-
|
|
2202
|
-
|
|
2726
|
+
path15.join(scaffoldRoot(), "zk-verifier"),
|
|
2727
|
+
path15.join(targetDir, "contracts", "verifier"),
|
|
2203
2728
|
{
|
|
2204
2729
|
recursive: true,
|
|
2205
2730
|
force,
|
|
@@ -2218,13 +2743,13 @@ async function createZkProject(options) {
|
|
|
2218
2743
|
// src/scaffold/create-minimal-project.ts
|
|
2219
2744
|
import { cp as cp3, mkdir as mkdir5, writeFile as writeFile6 } from "fs/promises";
|
|
2220
2745
|
import { existsSync as existsSync3 } from "fs";
|
|
2221
|
-
import
|
|
2746
|
+
import path16 from "path";
|
|
2222
2747
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2223
|
-
var moduleDir2 = typeof __dirname === "string" ? __dirname :
|
|
2748
|
+
var moduleDir2 = typeof __dirname === "string" ? __dirname : path16.dirname(fileURLToPath2(import.meta.url));
|
|
2224
2749
|
function scaffoldRoot2() {
|
|
2225
2750
|
const candidates = [
|
|
2226
|
-
|
|
2227
|
-
|
|
2751
|
+
path16.resolve(moduleDir2, "../../scaffolds"),
|
|
2752
|
+
path16.resolve(moduleDir2, "../scaffolds")
|
|
2228
2753
|
];
|
|
2229
2754
|
const found = candidates.find((candidate) => existsSync3(candidate));
|
|
2230
2755
|
return found ?? candidates[0];
|
|
@@ -2315,31 +2840,31 @@ Edit \`contracts/app/src/lib.rs\` to customize the contract. Add a frontend late
|
|
|
2315
2840
|
`;
|
|
2316
2841
|
}
|
|
2317
2842
|
async function createMinimalProject(options) {
|
|
2318
|
-
const targetDir =
|
|
2843
|
+
const targetDir = path16.resolve(options.targetDir);
|
|
2319
2844
|
const force = options.force ?? false;
|
|
2320
2845
|
await mkdir5(targetDir, { recursive: true });
|
|
2321
2846
|
await Promise.all([
|
|
2322
|
-
writeFile6(
|
|
2847
|
+
writeFile6(path16.join(targetDir, "caatinga.config.ts"), configSource2(options.projectName), {
|
|
2323
2848
|
encoding: "utf8",
|
|
2324
2849
|
flag: force ? "w" : "wx"
|
|
2325
2850
|
}),
|
|
2326
|
-
writeFile6(
|
|
2851
|
+
writeFile6(path16.join(targetDir, "package.json"), packageJsonSource2(options.projectName), {
|
|
2327
2852
|
encoding: "utf8",
|
|
2328
2853
|
flag: force ? "w" : "wx"
|
|
2329
2854
|
}),
|
|
2330
|
-
writeFile6(
|
|
2855
|
+
writeFile6(path16.join(targetDir, ".gitignore"), "node_modules\n.artifacts\ntarget\n", {
|
|
2331
2856
|
encoding: "utf8",
|
|
2332
2857
|
flag: force ? "w" : "wx"
|
|
2333
2858
|
}),
|
|
2334
|
-
writeFile6(
|
|
2859
|
+
writeFile6(path16.join(targetDir, "README.md"), readmeSource2(options.projectName), {
|
|
2335
2860
|
encoding: "utf8",
|
|
2336
2861
|
flag: force ? "w" : "wx"
|
|
2337
2862
|
})
|
|
2338
2863
|
]);
|
|
2339
|
-
await mkdir5(
|
|
2864
|
+
await mkdir5(path16.join(targetDir, "contracts"), { recursive: true });
|
|
2340
2865
|
await cp3(
|
|
2341
|
-
|
|
2342
|
-
|
|
2866
|
+
path16.join(scaffoldRoot2(), "soroban-contract-stub"),
|
|
2867
|
+
path16.join(targetDir, "contracts", "app"),
|
|
2343
2868
|
{
|
|
2344
2869
|
recursive: true,
|
|
2345
2870
|
force,
|
|
@@ -2354,36 +2879,24 @@ async function createMinimalProject(options) {
|
|
|
2354
2879
|
}
|
|
2355
2880
|
|
|
2356
2881
|
// src/ci/is-transient-testnet-smoke-failure.ts
|
|
2357
|
-
var NO_RETRY_CAATINGA_SUBSTRINGS = [
|
|
2358
|
-
"CAATINGA_UNSUPPORTED_CLI_VERSION",
|
|
2359
|
-
"CAATINGA_STELLAR_CLI_VERSION_PARSE_FAILED",
|
|
2360
|
-
"CAATINGA_STELLAR_CLI_NOT_FOUND",
|
|
2361
|
-
"CAATINGA_INVALID_CONFIG",
|
|
2362
|
-
"CAATINGA_CONFIG_NOT_FOUND"
|
|
2363
|
-
];
|
|
2364
|
-
var TRANSIENT_PATTERN = /timeout|i\/o timeout|econnreset|connection reset|503|502|429|rate limit|temporar|bad gateway|fetch failed|network error|unavailable/i;
|
|
2365
2882
|
function isTransientTestnetSmokeFailure(logText) {
|
|
2366
|
-
|
|
2367
|
-
return false;
|
|
2368
|
-
}
|
|
2369
|
-
for (const marker of NO_RETRY_CAATINGA_SUBSTRINGS) {
|
|
2370
|
-
if (logText.includes(marker)) {
|
|
2371
|
-
return false;
|
|
2372
|
-
}
|
|
2373
|
-
}
|
|
2374
|
-
return TRANSIENT_PATTERN.test(logText);
|
|
2883
|
+
return isTransientCommandFailure(logText);
|
|
2375
2884
|
}
|
|
2376
2885
|
export {
|
|
2377
2886
|
BINDING_MARKER_FILENAME,
|
|
2378
2887
|
BindingMarkerSchema,
|
|
2379
2888
|
CAATINGA_CORE_VERSION,
|
|
2889
|
+
CURRENT_ARTIFACTS_SCHEMA_VERSION,
|
|
2380
2890
|
CaatingaArtifactsSchema,
|
|
2381
2891
|
CaatingaConfigSchema,
|
|
2382
2892
|
CaatingaError,
|
|
2383
2893
|
CaatingaErrorCode,
|
|
2894
|
+
DEFAULT_CLI_SOURCE,
|
|
2384
2895
|
READ_CALL_FAILURE_REGEX,
|
|
2385
2896
|
STELLAR_CLI_LAST_TESTED_VERSION,
|
|
2386
2897
|
STELLAR_CLI_MIN_VERSION,
|
|
2898
|
+
STELLAR_SDK_LAST_TESTED_VERSION,
|
|
2899
|
+
STELLAR_SDK_MIN_VERSION,
|
|
2387
2900
|
TemplateManifestSchema,
|
|
2388
2901
|
WELL_KNOWN_NETWORKS,
|
|
2389
2902
|
buildContract,
|
|
@@ -2391,6 +2904,7 @@ export {
|
|
|
2391
2904
|
buildReadCallHint,
|
|
2392
2905
|
checkBinary,
|
|
2393
2906
|
checkStellarCliVersion,
|
|
2907
|
+
checkStellarSdkVersion,
|
|
2394
2908
|
collectProjectStatus,
|
|
2395
2909
|
createInitialArtifacts,
|
|
2396
2910
|
createMinimalProject,
|
|
@@ -2399,20 +2913,27 @@ export {
|
|
|
2399
2913
|
defineConfig,
|
|
2400
2914
|
deployContract,
|
|
2401
2915
|
deployContractGraph,
|
|
2916
|
+
describeCliSource,
|
|
2917
|
+
estimateDeployCost,
|
|
2402
2918
|
evaluateBindingFreshness,
|
|
2403
2919
|
evaluateBindingsFreshness,
|
|
2404
2920
|
evaluateStellarCliCompatibility,
|
|
2921
|
+
evaluateStellarSdkCompatibility,
|
|
2405
2922
|
formatCaatingaError,
|
|
2406
2923
|
generateBindings,
|
|
2407
2924
|
generateBindingsGraph,
|
|
2925
|
+
inspectContract,
|
|
2408
2926
|
invokeContract,
|
|
2409
2927
|
isCargoBinMissingFromPath,
|
|
2410
2928
|
isReadCallFailure,
|
|
2411
2929
|
isTransientTestnetSmokeFailure,
|
|
2412
2930
|
loadConfig,
|
|
2931
|
+
migrateArtifactsFile,
|
|
2932
|
+
migrateArtifactsToV2,
|
|
2413
2933
|
parseContractId,
|
|
2414
2934
|
parseInvokeTarget,
|
|
2415
2935
|
parseStellarCliVersion,
|
|
2936
|
+
parseStellarSdkVersion,
|
|
2416
2937
|
readArtifacts,
|
|
2417
2938
|
readBindingMarker,
|
|
2418
2939
|
readContract,
|
|
@@ -2422,6 +2943,8 @@ export {
|
|
|
2422
2943
|
resolveDeployOrder,
|
|
2423
2944
|
resolveNetwork,
|
|
2424
2945
|
resolveSubprocessEnv,
|
|
2946
|
+
restoreArtifactFromHistory,
|
|
2947
|
+
rollbackContractArtifact,
|
|
2425
2948
|
runCommand,
|
|
2426
2949
|
toCaatingaError,
|
|
2427
2950
|
updateArtifact,
|