@hazbase/simplicity 0.0.5 → 0.2.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.
Files changed (61) hide show
  1. package/README.md +140 -1038
  2. package/dist/cli.js +3341 -269
  3. package/dist/client/SimplicityClient.d.ts +91 -290
  4. package/dist/client/SimplicityClient.js +93 -23
  5. package/dist/core/executor.js +67 -92
  6. package/dist/core/lineage.d.ts +18 -0
  7. package/dist/core/lineage.js +30 -0
  8. package/dist/core/outputBinding.d.ts +61 -0
  9. package/dist/core/outputBinding.js +552 -0
  10. package/dist/core/reporting.d.ts +22 -0
  11. package/dist/core/reporting.js +40 -0
  12. package/dist/core/schnorr.d.ts +5 -0
  13. package/dist/core/schnorr.js +46 -0
  14. package/dist/core/types.d.ts +799 -1
  15. package/dist/docs/definitions/bond-anchor.simf +19 -0
  16. package/dist/docs/definitions/bond-definition.json +10 -0
  17. package/dist/docs/definitions/bond-descriptor-bound-settlement-machine.simf +144 -0
  18. package/dist/docs/definitions/bond-issuance-anchor.simf +26 -0
  19. package/dist/docs/definitions/bond-issuance-state-partial-redemption.json +18 -0
  20. package/dist/docs/definitions/bond-issuance-state-redeemed.json +18 -0
  21. package/dist/docs/definitions/bond-issuance-state.json +12 -0
  22. package/dist/docs/definitions/bond-redemption-state-machine.simf +118 -0
  23. package/dist/docs/definitions/bond-redemption-transition.simf +41 -0
  24. package/dist/docs/definitions/bond-script-bound-settlement-machine.simf +142 -0
  25. package/dist/docs/definitions/fund-capital-call-open.simf +82 -0
  26. package/dist/docs/definitions/fund-capital-call-refund-only.simf +67 -0
  27. package/dist/docs/definitions/fund-capital-call-state.json +11 -0
  28. package/dist/docs/definitions/fund-definition.json +8 -0
  29. package/dist/docs/definitions/fund-distribution-claim.simf +57 -0
  30. package/dist/docs/definitions/receivable-definition.json +9 -0
  31. package/dist/docs/definitions/receivable-funding-claim.json +13 -0
  32. package/dist/docs/definitions/receivable-funding-claim.simf +58 -0
  33. package/dist/docs/definitions/receivable-repayment-claim.json +13 -0
  34. package/dist/docs/definitions/receivable-repayment-claim.simf +59 -0
  35. package/dist/docs/definitions/receivable-state-funded.json +20 -0
  36. package/dist/docs/definitions/receivable-state-originated.json +19 -0
  37. package/dist/docs/definitions/receivable-state-repaid.json +20 -0
  38. package/dist/docs/definitions/recursive-delay-direct-next.simf +60 -0
  39. package/dist/docs/definitions/recursive-delay-optional.simf +88 -0
  40. package/dist/docs/definitions/recursive-delay-required.simf +72 -0
  41. package/dist/docs/definitions/recursive-delay.simf +83 -0
  42. package/dist/docs/definitions/recursive-policy-transfer-machine.simf +65 -0
  43. package/dist/domain/bond.d.ts +8649 -720
  44. package/dist/domain/bond.js +1398 -8
  45. package/dist/domain/bondSettlementValidation.d.ts +2 -0
  46. package/dist/domain/bondSettlementValidation.js +28 -0
  47. package/dist/domain/bondValidation.d.ts +37 -1
  48. package/dist/domain/bondValidation.js +137 -11
  49. package/dist/domain/fund.d.ts +2452 -0
  50. package/dist/domain/fund.js +1756 -0
  51. package/dist/domain/fundValidation.d.ts +152 -0
  52. package/dist/domain/fundValidation.js +767 -0
  53. package/dist/domain/policies.d.ts +1064 -0
  54. package/dist/domain/policies.js +1625 -0
  55. package/dist/domain/receivable.d.ts +824 -0
  56. package/dist/domain/receivable.js +1375 -0
  57. package/dist/domain/receivableValidation.d.ts +147 -0
  58. package/dist/domain/receivableValidation.js +831 -0
  59. package/dist/index.d.ts +8 -2
  60. package/dist/index.js +137 -21
  61. package/package.json +20 -2
@@ -40,27 +40,77 @@ exports.defineBond = defineBond;
40
40
  exports.verifyBond = verifyBond;
41
41
  exports.loadBond = loadBond;
42
42
  exports.buildBondPayload = buildBondPayload;
43
+ exports.verifyIssuanceHistory = verifyIssuanceHistory;
44
+ exports.summarizeExpectedOutputDescriptor = summarizeExpectedOutputDescriptor;
45
+ exports.validateExpectedOutputDescriptor = validateExpectedOutputDescriptor;
46
+ exports.buildExpectedOutputDescriptor = buildExpectedOutputDescriptor;
47
+ exports.verifyExpectedOutputDescriptor = verifyExpectedOutputDescriptor;
43
48
  exports.redeemBond = redeemBond;
44
49
  exports.buildBondTransitionPayload = buildBondTransitionPayload;
45
50
  exports.buildBondSettlementDescriptor = buildBondSettlementDescriptor;
46
51
  exports.verifyBondSettlementDescriptor = verifyBondSettlementDescriptor;
47
52
  exports.buildBondSettlementPayload = buildBondSettlementPayload;
53
+ exports.buildBondClosing = buildBondClosing;
54
+ exports.verifyBondClosing = verifyBondClosing;
55
+ exports.buildEvidenceBundle = buildEvidenceBundle;
56
+ exports.verifyEvidenceBundle = verifyEvidenceBundle;
57
+ exports.issueBond = issueBond;
58
+ exports.prepareRedemption = prepareRedemption;
59
+ exports.finalizeRedemption = finalizeRedemption;
60
+ exports.prepareClosing = prepareClosing;
61
+ exports.exportFinalityPayload = exportFinalityPayload;
62
+ exports.define = define;
63
+ exports.verify = verify;
64
+ exports.load = load;
65
+ exports.issue = issue;
66
+ exports.buildSettlement = buildSettlement;
67
+ exports.verifySettlement = verifySettlement;
68
+ exports.inspectRedemption = inspectRedemption;
69
+ exports.executeRedemption = executeRedemption;
70
+ exports.verifyRedemption = verifyRedemption;
71
+ exports.inspectClosing = inspectClosing;
72
+ exports.executeClosing = executeClosing;
73
+ exports.verifyClosing = verifyClosing;
74
+ exports.exportEvidence = exportEvidence;
48
75
  exports.compileBondTransition = compileBondTransition;
49
76
  exports.verifyBondRedemptionMachineArtifact = verifyBondRedemptionMachineArtifact;
50
77
  exports.compileBondRedemptionMachine = compileBondRedemptionMachine;
78
+ exports.compileBondScriptBoundSettlementMachine = compileBondScriptBoundSettlementMachine;
79
+ exports.verifyBondScriptBoundSettlementMachineArtifact = verifyBondScriptBoundSettlementMachineArtifact;
80
+ exports.compileBondDescriptorBoundSettlementMachine = compileBondDescriptorBoundSettlementMachine;
81
+ exports.verifyBondDescriptorBoundSettlementMachineArtifact = verifyBondDescriptorBoundSettlementMachineArtifact;
82
+ exports.compileBondClosingMachine = compileBondClosingMachine;
51
83
  exports.buildBondRedemption = buildBondRedemption;
52
84
  exports.verifyBondTransition = verifyBondTransition;
53
85
  exports.buildBondRolloverPlan = buildBondRolloverPlan;
54
86
  exports.buildBondMachineRolloverPlan = buildBondMachineRolloverPlan;
87
+ exports.buildBondScriptBoundMachineRolloverPlan = buildBondScriptBoundMachineRolloverPlan;
88
+ exports.buildBondDescriptorBoundMachineRolloverPlan = buildBondDescriptorBoundMachineRolloverPlan;
55
89
  exports.buildBondMachineSettlementPlan = buildBondMachineSettlementPlan;
90
+ exports.buildBondScriptBoundMachineSettlementPlan = buildBondScriptBoundMachineSettlementPlan;
91
+ exports.buildBondDescriptorBoundMachineSettlementPlan = buildBondDescriptorBoundMachineSettlementPlan;
56
92
  exports.inspectBondStateRollover = inspectBondStateRollover;
57
93
  exports.inspectBondMachineRollover = inspectBondMachineRollover;
94
+ exports.inspectBondScriptBoundMachineRollover = inspectBondScriptBoundMachineRollover;
95
+ exports.inspectBondDescriptorBoundMachineRollover = inspectBondDescriptorBoundMachineRollover;
58
96
  exports.inspectBondMachineSettlement = inspectBondMachineSettlement;
97
+ exports.inspectBondScriptBoundMachineSettlement = inspectBondScriptBoundMachineSettlement;
98
+ exports.inspectBondDescriptorBoundMachineSettlement = inspectBondDescriptorBoundMachineSettlement;
99
+ exports.buildBondClosingPlan = buildBondClosingPlan;
59
100
  exports.executeBondStateRollover = executeBondStateRollover;
60
101
  exports.executeBondMachineRollover = executeBondMachineRollover;
102
+ exports.executeBondScriptBoundMachineRollover = executeBondScriptBoundMachineRollover;
103
+ exports.executeBondDescriptorBoundMachineRollover = executeBondDescriptorBoundMachineRollover;
61
104
  exports.executeBondMachineSettlement = executeBondMachineSettlement;
105
+ exports.executeBondScriptBoundMachineSettlement = executeBondScriptBoundMachineSettlement;
106
+ exports.executeBondDescriptorBoundMachineSettlement = executeBondDescriptorBoundMachineSettlement;
107
+ exports.inspectBondClosing = inspectBondClosing;
108
+ exports.executeBondClosing = executeBondClosing;
109
+ const node_fs_1 = require("node:fs");
62
110
  const node_path_1 = __importDefault(require("node:path"));
111
+ const reporting_1 = require("../core/reporting");
63
112
  const summary_1 = require("../core/summary");
113
+ const outputBinding_1 = require("../core/outputBinding");
64
114
  const bondSettlementValidation_1 = require("./bondSettlementValidation");
65
115
  const bondValidation_1 = require("./bondValidation");
66
116
  function resolveValueOrPath(options) {
@@ -70,6 +120,106 @@ function resolveValueOrPath(options) {
70
120
  return { value: options.objectValue };
71
121
  return {};
72
122
  }
123
+ function resolveBondDocsAsset(filename) {
124
+ const cwdCandidate = node_path_1.default.resolve(process.cwd(), "docs/definitions", filename);
125
+ if ((0, node_fs_1.existsSync)(cwdCandidate)) {
126
+ return cwdCandidate;
127
+ }
128
+ // In published packages we copy bond example contracts into dist/docs/definitions.
129
+ const bundledCandidate = node_path_1.default.resolve(__dirname, "../docs/definitions", filename);
130
+ if ((0, node_fs_1.existsSync)(bundledCandidate)) {
131
+ return bundledCandidate;
132
+ }
133
+ return cwdCandidate;
134
+ }
135
+ async function loadIssuanceHistoryDocuments(sdk, input) {
136
+ const results = [];
137
+ for (const issuancePath of input.issuanceHistoryPaths ?? []) {
138
+ const state = await sdk.loadStateDocument({
139
+ type: "bond-issuance",
140
+ id: "BOND-ISSUANCE-HISTORY",
141
+ jsonPath: issuancePath,
142
+ });
143
+ const value = (0, bondValidation_1.validateBondIssuanceState)(JSON.parse(state.canonicalJson));
144
+ results.push({
145
+ state,
146
+ value,
147
+ summary: (0, bondValidation_1.summarizeBondIssuanceState)(value),
148
+ });
149
+ }
150
+ for (const issuanceValue of input.issuanceHistoryValues ?? []) {
151
+ const value = (0, bondValidation_1.validateBondIssuanceState)(issuanceValue);
152
+ const state = await sdk.loadStateDocument({
153
+ type: "bond-issuance",
154
+ id: value.issuanceId,
155
+ value,
156
+ });
157
+ results.push({
158
+ state,
159
+ value,
160
+ summary: (0, bondValidation_1.summarizeBondIssuanceState)(value),
161
+ });
162
+ }
163
+ return results;
164
+ }
165
+ function buildBondIssuanceLineageTrust(checks) {
166
+ const identityConsistent = checks.issuanceIdConsistent
167
+ && checks.bondIdConsistent
168
+ && checks.currencyConsistent
169
+ && checks.controllerConsistent
170
+ && checks.issuerEntityConsistent
171
+ && checks.issuedPrincipalConsistent
172
+ && checks.allTransitionIdentitiesMatch;
173
+ return {
174
+ ...(0, reporting_1.buildLineageTrustBase)({
175
+ lineageKind: "state-history",
176
+ chainLength: checks.chainLength,
177
+ latestOrdinal: Math.max(0, checks.chainLength - 1),
178
+ allHashLinksVerified: checks.previousStateHashLinked && checks.allPreviousStateHashMatch,
179
+ identityConsistent,
180
+ fullLineageVerified: checks.fullHistoryVerified,
181
+ }),
182
+ latestStatus: checks.latestStatus,
183
+ startsAtGenesis: checks.startsAtGenesis,
184
+ previousStateHashLinked: checks.previousStateHashLinked,
185
+ issuanceIdConsistent: checks.issuanceIdConsistent,
186
+ bondIdConsistent: checks.bondIdConsistent,
187
+ currencyConsistent: checks.currencyConsistent,
188
+ controllerConsistent: checks.controllerConsistent,
189
+ issuerEntityConsistent: checks.issuerEntityConsistent,
190
+ issuedPrincipalConsistent: checks.issuedPrincipalConsistent,
191
+ allPreviousStateHashMatch: checks.allPreviousStateHashMatch,
192
+ allRedemptionArithmeticValid: checks.allRedemptionArithmeticValid,
193
+ allStatusProgressionValid: checks.allStatusProgressionValid,
194
+ allTransitionIdentitiesMatch: checks.allTransitionIdentitiesMatch,
195
+ fullHistoryVerified: checks.fullHistoryVerified,
196
+ };
197
+ }
198
+ function buildEmptyBondDefinitionTrust() {
199
+ return {
200
+ artifactMatch: false,
201
+ onChainAnchorPresent: false,
202
+ onChainAnchorVerified: false,
203
+ effectiveMode: "none",
204
+ };
205
+ }
206
+ function buildEmptyBondStateTrust() {
207
+ return {
208
+ artifactMatch: false,
209
+ onChainAnchorPresent: false,
210
+ onChainAnchorVerified: false,
211
+ effectiveMode: "none",
212
+ };
213
+ }
214
+ function buildBaseBondReport(input) {
215
+ return (0, reporting_1.buildVerificationTrustSections)({
216
+ definitionTrust: input?.definitionTrust,
217
+ stateTrust: input?.stateTrust,
218
+ requireArtifactTrust: input?.requireArtifactTrust,
219
+ emptyDefinitionTrust: buildEmptyBondDefinitionTrust(),
220
+ emptyStateTrust: buildEmptyBondStateTrust(),
221
+ });
222
+ }
73
223
  async function defineBond(sdk, input) {
74
224
  const definitionSource = resolveValueOrPath({
75
225
  pathValue: input.definitionPath,
@@ -102,7 +252,7 @@ async function defineBond(sdk, input) {
102
252
  ...(issuanceSource.jsonPath ? { jsonPath: issuanceSource.jsonPath } : { value: issuance }),
103
253
  });
104
254
  (0, bondValidation_1.validateBondCrossChecks)(definition, issuance);
105
- const simfPath = input.simfPath ?? node_path_1.default.resolve(process.cwd(), "docs/definitions/bond-issuance-anchor.simf");
255
+ const simfPath = input.simfPath ?? resolveBondDocsAsset("bond-issuance-anchor.simf");
106
256
  return sdk.compileFromFile({
107
257
  simfPath,
108
258
  templateVars: {
@@ -186,6 +336,15 @@ async function buildBondPayload(sdk, input) {
186
336
  const definitionValue = (0, bondValidation_1.validateBondDefinition)(JSON.parse(verification.definition.definition.canonicalJson));
187
337
  const issuanceValue = (0, bondValidation_1.validateBondIssuanceState)(JSON.parse(verification.issuance.state.canonicalJson));
188
338
  const issuanceSummary = (0, bondValidation_1.summarizeBondIssuanceState)(issuanceValue);
339
+ const issuanceHistory = input.issuanceHistoryPaths || input.issuanceHistoryValues
340
+ ? await loadIssuanceHistoryDocuments(sdk, {
341
+ issuanceHistoryPaths: input.issuanceHistoryPaths,
342
+ issuanceHistoryValues: input.issuanceHistoryValues,
343
+ })
344
+ : [];
345
+ const lineageChecks = issuanceHistory.length > 0
346
+ ? (0, bondValidation_1.verifyBondIssuanceHistory)({ history: issuanceHistory.map((entry) => entry.value) })
347
+ : undefined;
189
348
  return {
190
349
  artifact: verification.artifact,
191
350
  payload: {
@@ -218,6 +377,45 @@ async function buildBondPayload(sdk, input) {
218
377
  trust: {
219
378
  definitionTrust: verification.definition.trust,
220
379
  issuanceTrust: verification.issuance.trust,
380
+ issuanceLineageTrust: lineageChecks ? buildBondIssuanceLineageTrust(lineageChecks) : undefined,
381
+ },
382
+ ...(issuanceHistory.length > 0
383
+ ? {
384
+ issuanceHistory: issuanceHistory.map((entry) => entry.state),
385
+ issuanceHistoryValues: issuanceHistory.map((entry) => entry.value),
386
+ issuanceHistorySummaries: issuanceHistory.map((entry) => entry.summary),
387
+ }
388
+ : {}),
389
+ };
390
+ }
391
+ async function verifyIssuanceHistory(sdk, input) {
392
+ const definitionSource = resolveValueOrPath({
393
+ pathValue: input.definitionPath,
394
+ objectValue: input.definitionValue,
395
+ });
396
+ const definition = input.definitionPath || input.definitionValue
397
+ ? await sdk.loadDefinition({
398
+ type: "bond",
399
+ id: input.definitionValue?.bondId ?? "BOND-2026-001",
400
+ ...definitionSource,
401
+ })
402
+ : undefined;
403
+ const definitionValue = definition ? (0, bondValidation_1.validateBondDefinition)(JSON.parse(definition.canonicalJson)) : undefined;
404
+ const issuanceHistory = await loadIssuanceHistoryDocuments(sdk, input);
405
+ const checks = (0, bondValidation_1.verifyBondIssuanceHistory)({ history: issuanceHistory.map((entry) => entry.value) });
406
+ if (definitionValue) {
407
+ (0, bondValidation_1.validateBondCrossChecks)(definitionValue, issuanceHistory.at(-1).value);
408
+ }
409
+ return {
410
+ verified: checks.fullHistoryVerified,
411
+ ...(definition ? { definition, definitionValue } : {}),
412
+ issuanceHistory: issuanceHistory.map((entry) => entry.state),
413
+ issuanceHistoryValues: issuanceHistory.map((entry) => entry.value),
414
+ issuanceHistorySummaries: issuanceHistory.map((entry) => entry.summary),
415
+ checks,
416
+ report: {
417
+ ...buildBaseBondReport({ requireArtifactTrust: true }),
418
+ issuanceLineageTrust: buildBondIssuanceLineageTrust(checks),
221
419
  },
222
420
  };
223
421
  }
@@ -263,12 +461,223 @@ function bondStatusToCode(status) {
263
461
  return 2;
264
462
  case "REDEEMED":
265
463
  return 3;
464
+ case "CLOSED":
465
+ return 4;
266
466
  default: {
267
467
  const exhaustiveCheck = status;
268
468
  throw new Error(`Unsupported bond status: ${exhaustiveCheck}`);
269
469
  }
270
470
  }
271
471
  }
472
+ function closingReasonToCode(reason) {
473
+ switch (reason) {
474
+ case "REDEEMED":
475
+ return 1;
476
+ case "CANCELLED":
477
+ return 2;
478
+ case "MATURED_OUT":
479
+ return 3;
480
+ default: {
481
+ const exhaustiveCheck = reason;
482
+ throw new Error(`Unsupported closing reason: ${exhaustiveCheck}`);
483
+ }
484
+ }
485
+ }
486
+ function summarizeExpectedOutputDescriptor(descriptor) {
487
+ const canonicalJson = (0, summary_1.stableStringify)({
488
+ assetId: descriptor.assetId,
489
+ feeIndex: descriptor.feeIndex,
490
+ maxFeeSat: descriptor.maxFeeSat,
491
+ nextAmountSat: descriptor.nextAmountSat,
492
+ nextContractAddress: descriptor.nextContractAddress,
493
+ nextOutputHash: descriptor.nextOutputHash ?? null,
494
+ nextOutputScriptHash: descriptor.nextOutputScriptHash ?? null,
495
+ nextOutputIndex: descriptor.nextOutputIndex,
496
+ requestedOutputBindingMode: descriptor.requestedOutputBindingMode ?? descriptor.outputBindingMode ?? "none",
497
+ outputForm: descriptor.outputForm ?? (0, outputBinding_1.normalizeOutputForm)(),
498
+ rawOutput: (0, outputBinding_1.normalizeOutputRawFields)(descriptor.rawOutput) ?? null,
499
+ outputBindingMode: descriptor.outputBindingMode ?? "none",
500
+ });
501
+ return { canonicalJson, hash: (0, summary_1.sha256HexUtf8)(canonicalJson) };
502
+ }
503
+ function validateExpectedOutputDescriptor(descriptor) {
504
+ if (!descriptor.nextContractAddress || descriptor.nextContractAddress.trim().length === 0) {
505
+ throw new Error("nextContractAddress must be a non-empty string");
506
+ }
507
+ if (!descriptor.assetId || descriptor.assetId.trim().length === 0) {
508
+ throw new Error("assetId must be a non-empty string");
509
+ }
510
+ if (descriptor.nextOutputScriptHash !== undefined && descriptor.nextOutputScriptHash !== null) {
511
+ if (!/^[0-9a-f]{64}$/i.test(descriptor.nextOutputScriptHash)) {
512
+ throw new Error("nextOutputScriptHash must be a 64-character hex string");
513
+ }
514
+ }
515
+ if (descriptor.nextOutputHash !== undefined && descriptor.nextOutputHash !== null) {
516
+ if (!/^[0-9a-f]{64}$/i.test(descriptor.nextOutputHash)) {
517
+ throw new Error("nextOutputHash must be a 64-character hex string");
518
+ }
519
+ }
520
+ if (!Number.isInteger(descriptor.nextAmountSat) || descriptor.nextAmountSat <= 0) {
521
+ throw new Error("nextAmountSat must be a positive integer");
522
+ }
523
+ if (!Number.isInteger(descriptor.maxFeeSat) || descriptor.maxFeeSat < 0) {
524
+ throw new Error("maxFeeSat must be a non-negative integer");
525
+ }
526
+ if (!Number.isInteger(descriptor.nextOutputIndex) || descriptor.nextOutputIndex < 0) {
527
+ throw new Error("nextOutputIndex must be a non-negative integer");
528
+ }
529
+ if (!Number.isInteger(descriptor.feeIndex) || descriptor.feeIndex < 0) {
530
+ throw new Error("feeIndex must be a non-negative integer");
531
+ }
532
+ if (descriptor.requestedOutputBindingMode
533
+ && descriptor.requestedOutputBindingMode !== "none"
534
+ && descriptor.requestedOutputBindingMode !== "script-bound"
535
+ && descriptor.requestedOutputBindingMode !== "descriptor-bound") {
536
+ throw new Error("requestedOutputBindingMode must be none, script-bound, or descriptor-bound");
537
+ }
538
+ if (descriptor.outputBindingMode !== "none"
539
+ && descriptor.outputBindingMode !== "script-bound"
540
+ && descriptor.outputBindingMode !== "descriptor-bound") {
541
+ throw new Error("outputBindingMode must be none, script-bound, or descriptor-bound");
542
+ }
543
+ descriptor.rawOutput = (0, outputBinding_1.normalizeOutputRawFields)(descriptor.rawOutput);
544
+ descriptor.outputForm = (0, outputBinding_1.normalizeOutputForm)(descriptor.outputForm);
545
+ descriptor.requestedOutputBindingMode = descriptor.requestedOutputBindingMode ?? descriptor.outputBindingMode ?? "none";
546
+ return descriptor;
547
+ }
548
+ async function buildExpectedOutputDescriptor(sdk, input) {
549
+ const definitionSource = resolveValueOrPath({
550
+ pathValue: input.definitionPath,
551
+ objectValue: input.definitionValue,
552
+ });
553
+ const nextSource = resolveValueOrPath({
554
+ pathValue: input.nextIssuancePath,
555
+ objectValue: input.nextIssuanceValue,
556
+ });
557
+ const definitionDescriptor = await sdk.loadDefinition({
558
+ type: "bond",
559
+ id: input.definitionValue?.bondId ?? "BOND-2026-001",
560
+ ...definitionSource,
561
+ });
562
+ const nextDescriptor = await sdk.loadStateDocument({
563
+ type: "bond-issuance",
564
+ id: input.nextIssuanceValue?.issuanceId ?? "BOND-2026-001-ISSUE-1",
565
+ ...nextSource,
566
+ });
567
+ const definition = (0, bondValidation_1.validateBondDefinition)(JSON.parse(definitionDescriptor.canonicalJson));
568
+ const next = (0, bondValidation_1.validateBondIssuanceState)(JSON.parse(nextDescriptor.canonicalJson));
569
+ (0, bondValidation_1.validateBondCrossChecks)(definition, next);
570
+ const nextStateCompiled = await defineBond(sdk, {
571
+ definitionValue: definition,
572
+ issuanceValue: next,
573
+ simfPath: input.nextStateSimfPath,
574
+ });
575
+ const nextScriptPubKeyHex = await (0, outputBinding_1.getScriptPubKeyHexViaRpc)(sdk, nextStateCompiled.deployment().contractAddress);
576
+ const nextOutputScriptHash = (0, outputBinding_1.hashHexBytes)(nextScriptPubKeyHex);
577
+ const requestedBindingMode = input.outputBindingMode ?? "script-bound";
578
+ const outputForm = (0, outputBinding_1.normalizeOutputForm)(input.outputForm);
579
+ const rawOutput = (0, outputBinding_1.normalizeOutputRawFields)(input.rawOutput);
580
+ const rawOutputAnalysis = (0, outputBinding_1.analyzeOutputRawFields)(rawOutput);
581
+ const explicitAssetHex = requestedBindingMode !== "none" && (0, outputBinding_1.isExplicitV1OutputForm)(outputForm)
582
+ ? await (0, outputBinding_1.resolveExplicitAssetHex)(sdk, definition.currencyAssetId)
583
+ : undefined;
584
+ const autoDerivedNextOutputHash = requestedBindingMode === "descriptor-bound" && !input.nextOutputHash
585
+ ? rawOutputAnalysis.valid && rawOutputAnalysis.normalized
586
+ ? (0, outputBinding_1.computeRawOutputV1Hash)(rawOutputAnalysis.normalized)
587
+ : explicitAssetHex
588
+ ? (0, outputBinding_1.computeExplicitV1OutputHash)({
589
+ assetHex: explicitAssetHex,
590
+ nextAmountSat: input.nextAmountSat,
591
+ nextOutputScriptHash,
592
+ })
593
+ : undefined
594
+ : undefined;
595
+ const nextOutputHash = input.nextOutputHash ?? autoDerivedNextOutputHash;
596
+ const bindingDecision = (0, outputBinding_1.resolveOutputBindingDecision)({
597
+ requestedBindingMode,
598
+ nextOutputHash,
599
+ nextOutputScriptHash,
600
+ autoDerivedNextOutputHash: Boolean(autoDerivedNextOutputHash && !input.nextOutputHash),
601
+ explicitAssetSupported: Boolean(explicitAssetHex),
602
+ outputForm,
603
+ rawOutput,
604
+ });
605
+ const descriptor = validateExpectedOutputDescriptor({
606
+ nextContractAddress: nextStateCompiled.deployment().contractAddress,
607
+ nextOutputHash: bindingDecision.outputBindingMode === "descriptor-bound" ? nextOutputHash : undefined,
608
+ nextOutputScriptHash: bindingDecision.outputBindingMode !== "none" ? nextOutputScriptHash : undefined,
609
+ nextAmountSat: input.nextAmountSat,
610
+ assetId: definition.currencyAssetId,
611
+ requestedOutputBindingMode: requestedBindingMode,
612
+ outputForm,
613
+ rawOutput,
614
+ feeIndex: input.feeIndex ?? 1,
615
+ nextOutputIndex: input.nextOutputIndex ?? 0,
616
+ maxFeeSat: input.maxFeeSat ?? 100,
617
+ outputBindingMode: bindingDecision.outputBindingMode,
618
+ });
619
+ const summary = summarizeExpectedOutputDescriptor(descriptor);
620
+ return {
621
+ descriptor,
622
+ canonicalJson: summary.canonicalJson,
623
+ hash: summary.hash,
624
+ supportedForm: bindingDecision.supportedForm,
625
+ reasonCode: bindingDecision.reasonCode,
626
+ autoDerivedNextOutputHash: bindingDecision.autoDerived,
627
+ fallbackReason: bindingDecision.fallbackReason,
628
+ bindingInputs: {
629
+ assetId: descriptor.assetId,
630
+ assetForm: descriptor.outputForm?.assetForm ?? "explicit",
631
+ amountForm: descriptor.outputForm?.amountForm ?? "explicit",
632
+ nonceForm: descriptor.outputForm?.nonceForm ?? "null",
633
+ rangeProofForm: descriptor.outputForm?.rangeProofForm ?? "empty",
634
+ nextAmountSat: descriptor.nextAmountSat,
635
+ nextOutputIndex: descriptor.nextOutputIndex,
636
+ feeIndex: descriptor.feeIndex,
637
+ maxFeeSat: descriptor.maxFeeSat,
638
+ ...(rawOutputAnalysis.valid && rawOutputAnalysis.normalized
639
+ ? {
640
+ rawOutputComponents: {
641
+ scriptPubKey: rawOutputAnalysis.normalized.scriptComponentSource,
642
+ rangeProof: rawOutputAnalysis.normalized.rangeProofComponentSource,
643
+ },
644
+ }
645
+ : {}),
646
+ },
647
+ };
648
+ }
649
+ async function verifyExpectedOutputDescriptor(sdk, input) {
650
+ const actual = validateExpectedOutputDescriptor(input.descriptorValue);
651
+ const expected = await buildExpectedOutputDescriptor(sdk, {
652
+ definitionPath: input.definitionPath,
653
+ definitionValue: input.definitionValue,
654
+ nextIssuancePath: input.nextIssuancePath,
655
+ nextIssuanceValue: input.nextIssuanceValue,
656
+ nextStateSimfPath: input.nextStateSimfPath,
657
+ nextAmountSat: input.nextAmountSat ?? actual.nextAmountSat,
658
+ maxFeeSat: input.maxFeeSat ?? actual.maxFeeSat,
659
+ nextOutputIndex: input.nextOutputIndex ?? actual.nextOutputIndex,
660
+ feeIndex: input.feeIndex ?? actual.feeIndex,
661
+ nextOutputHash: input.nextOutputHash ?? actual.nextOutputHash,
662
+ outputForm: input.outputForm ?? actual.outputForm,
663
+ rawOutput: input.rawOutput ?? actual.rawOutput,
664
+ outputBindingMode: input.outputBindingMode ?? actual.outputBindingMode,
665
+ });
666
+ const actualSummary = summarizeExpectedOutputDescriptor(actual);
667
+ return {
668
+ ok: actualSummary.hash === expected.hash,
669
+ reason: actualSummary.hash === expected.hash ? undefined : "Expected output descriptor hash mismatch",
670
+ descriptor: actual,
671
+ expected: expected.descriptor,
672
+ hash: actualSummary.hash,
673
+ expectedHash: expected.hash,
674
+ supportedForm: expected.supportedForm,
675
+ reasonCode: expected.reasonCode,
676
+ autoDerivedNextOutputHash: expected.autoDerivedNextOutputHash,
677
+ fallbackReason: expected.fallbackReason,
678
+ bindingInputs: expected.bindingInputs,
679
+ };
680
+ }
272
681
  async function redeemBond(sdk, input) {
273
682
  const definitionSource = resolveValueOrPath({
274
683
  pathValue: input.definitionPath,
@@ -307,7 +716,7 @@ async function redeemBond(sdk, input) {
307
716
  id: nextIssuance.issuanceId,
308
717
  value: nextIssuance,
309
718
  });
310
- const simfPath = input.simfPath ?? node_path_1.default.resolve(process.cwd(), "docs/definitions/bond-issuance-anchor.simf");
719
+ const simfPath = input.simfPath ?? resolveBondDocsAsset("bond-issuance-anchor.simf");
311
720
  return sdk.compileFromFile({
312
721
  simfPath,
313
722
  templateVars: {
@@ -413,6 +822,17 @@ async function buildBondSettlementDescriptor(sdk, input) {
413
822
  issuanceValue: transition.next,
414
823
  simfPath: input.nextStateSimfPath,
415
824
  });
825
+ const expectedOutputDescriptor = await buildExpectedOutputDescriptor(sdk, {
826
+ definitionValue: transition.definition,
827
+ nextIssuanceValue: transition.next,
828
+ nextStateSimfPath: input.nextStateSimfPath,
829
+ nextAmountSat: input.nextAmountSat,
830
+ maxFeeSat: input.maxFeeSat ?? 100,
831
+ nextOutputHash: input.nextOutputHash,
832
+ outputForm: input.outputForm,
833
+ rawOutput: input.rawOutput,
834
+ outputBindingMode: input.outputBindingMode,
835
+ });
416
836
  const nextContractAddress = nextStateCompiled.deployment().contractAddress;
417
837
  const descriptor = (0, bondSettlementValidation_1.validateBondSettlementDescriptor)({
418
838
  settlementId: `${transition.previous.issuanceId}-SETTLEMENT-${transition.payload.nextStatus}`,
@@ -430,6 +850,8 @@ async function buildBondSettlementDescriptor(sdk, input) {
430
850
  nextContractAddress,
431
851
  nextAmountSat: input.nextAmountSat,
432
852
  maxFeeSat: input.maxFeeSat ?? 100,
853
+ expectedOutputDescriptorHash: expectedOutputDescriptor.hash,
854
+ outputBindingMode: expectedOutputDescriptor.descriptor.outputBindingMode ?? "none",
433
855
  principal: {
434
856
  issued: transition.payload.principal.issued,
435
857
  previousOutstanding: transition.payload.principal.previousOutstanding,
@@ -446,6 +868,13 @@ async function buildBondSettlementDescriptor(sdk, input) {
446
868
  transition: transition.payload.crossChecks.transition,
447
869
  nextContractAddress,
448
870
  descriptor,
871
+ expectedOutputDescriptor: expectedOutputDescriptor.descriptor,
872
+ expectedOutputDescriptorHash: expectedOutputDescriptor.hash,
873
+ expectedOutputBindingSupportedForm: expectedOutputDescriptor.supportedForm,
874
+ expectedOutputBindingReasonCode: expectedOutputDescriptor.reasonCode,
875
+ expectedOutputBindingAutoDerived: expectedOutputDescriptor.autoDerivedNextOutputHash,
876
+ expectedOutputBindingFallbackReason: expectedOutputDescriptor.fallbackReason,
877
+ expectedOutputBindingInputs: expectedOutputDescriptor.bindingInputs,
449
878
  canonicalJson: summary.canonicalJson,
450
879
  hash: summary.hash,
451
880
  };
@@ -468,6 +897,10 @@ async function verifyBondSettlementDescriptor(sdk, input) {
468
897
  nextStateSimfPath: input.nextStateSimfPath,
469
898
  nextAmountSat: input.nextAmountSat ?? descriptor.nextAmountSat,
470
899
  maxFeeSat: input.maxFeeSat ?? descriptor.maxFeeSat,
900
+ nextOutputHash: input.nextOutputHash,
901
+ outputForm: input.outputForm,
902
+ rawOutput: input.rawOutput,
903
+ outputBindingMode: descriptor.outputBindingMode,
471
904
  });
472
905
  const actualSummary = (0, bondSettlementValidation_1.summarizeBondSettlementDescriptor)(descriptor);
473
906
  const matches = (0, bondSettlementValidation_1.validateBondSettlementMatchesExpected)(descriptor, expected.descriptor);
@@ -479,6 +912,11 @@ async function verifyBondSettlementDescriptor(sdk, input) {
479
912
  hash: actualSummary.hash,
480
913
  expectedHash: expected.hash,
481
914
  matches,
915
+ supportedForm: expected.expectedOutputBindingSupportedForm,
916
+ reasonCode: expected.expectedOutputBindingReasonCode,
917
+ autoDerivedNextOutputHash: expected.expectedOutputBindingAutoDerived,
918
+ fallbackReason: expected.expectedOutputBindingFallbackReason,
919
+ bindingInputs: expected.expectedOutputBindingInputs,
482
920
  };
483
921
  }
484
922
  async function buildBondSettlementPayload(sdk, input) {
@@ -486,6 +924,13 @@ async function buildBondSettlementPayload(sdk, input) {
486
924
  return {
487
925
  descriptor: result.descriptor,
488
926
  descriptorHash: result.hash,
927
+ expectedOutputDescriptor: result.expectedOutputDescriptor,
928
+ expectedOutputDescriptorHash: result.expectedOutputDescriptorHash,
929
+ supportedForm: result.expectedOutputBindingSupportedForm,
930
+ reasonCode: result.expectedOutputBindingReasonCode,
931
+ autoDerivedNextOutputHash: result.expectedOutputBindingAutoDerived,
932
+ fallbackReason: result.expectedOutputBindingFallbackReason,
933
+ bindingInputs: result.expectedOutputBindingInputs,
489
934
  previousStateHash: result.descriptor.previousStateHash,
490
935
  nextStateHash: result.descriptor.nextStateHash,
491
936
  nextContractAddress: result.descriptor.nextContractAddress,
@@ -493,6 +938,440 @@ async function buildBondSettlementPayload(sdk, input) {
493
938
  maxFeeSat: result.descriptor.maxFeeSat,
494
939
  };
495
940
  }
941
+ async function buildBondClosing(sdk, input) {
942
+ const definitionSource = resolveValueOrPath({
943
+ pathValue: input.definitionPath,
944
+ objectValue: input.definitionValue,
945
+ });
946
+ const issuanceSource = resolveValueOrPath({
947
+ pathValue: input.redeemedIssuancePath,
948
+ objectValue: input.redeemedIssuanceValue,
949
+ });
950
+ const definitionDescriptor = await sdk.loadDefinition({
951
+ type: "bond",
952
+ id: input.definitionValue?.bondId ?? "BOND-2026-001",
953
+ ...definitionSource,
954
+ });
955
+ const issuanceDescriptor = await sdk.loadStateDocument({
956
+ type: "bond-issuance",
957
+ id: input.redeemedIssuanceValue?.issuanceId ?? "BOND-2026-001-ISSUE-1",
958
+ ...issuanceSource,
959
+ });
960
+ const definition = (0, bondValidation_1.validateBondDefinition)(JSON.parse(definitionDescriptor.canonicalJson));
961
+ const redeemed = (0, bondValidation_1.validateBondIssuanceState)(JSON.parse(issuanceDescriptor.canonicalJson));
962
+ (0, bondValidation_1.validateBondCrossChecks)(definition, redeemed);
963
+ const settlementVerification = await verifyBondSettlementDescriptor(sdk, {
964
+ descriptorPath: input.settlementDescriptorPath,
965
+ descriptorValue: input.settlementDescriptorValue,
966
+ definitionValue: definition,
967
+ previousIssuanceValue: undefined,
968
+ nextIssuanceValue: redeemed,
969
+ nextAmountSat: input.settlementDescriptorValue?.nextAmountSat,
970
+ maxFeeSat: input.settlementDescriptorValue?.maxFeeSat,
971
+ }).catch(() => undefined);
972
+ const finalSettlementDescriptorHash = settlementVerification?.hash
973
+ ?? (input.settlementDescriptorValue
974
+ ? (0, bondSettlementValidation_1.summarizeBondSettlementDescriptor)(input.settlementDescriptorValue).hash
975
+ : undefined);
976
+ if (!finalSettlementDescriptorHash) {
977
+ throw new Error("A valid settlement descriptor is required to build a closing state");
978
+ }
979
+ const closed = (0, bondValidation_1.buildClosedBondIssuanceState)({
980
+ previous: redeemed,
981
+ closedAt: input.closedAt,
982
+ closingReason: input.closingReason ?? "REDEEMED",
983
+ finalSettlementDescriptorHash,
984
+ });
985
+ const closing = {
986
+ closingId: `${closed.issuanceId}-CLOSE`,
987
+ bondId: definition.bondId,
988
+ issuanceId: closed.issuanceId,
989
+ finalStatus: "CLOSED",
990
+ definitionHash: definitionDescriptor.hash,
991
+ previousStateHash: (0, bondValidation_1.summarizeBondIssuanceState)(redeemed).hash,
992
+ closedStateHash: (0, bondValidation_1.summarizeBondIssuanceState)(closed).hash,
993
+ stateHash: (0, bondValidation_1.summarizeBondIssuanceState)(closed).hash,
994
+ closedAt: input.closedAt,
995
+ closingReason: input.closingReason ?? "REDEEMED",
996
+ finalSettlementDescriptorHash,
997
+ };
998
+ return {
999
+ definition,
1000
+ previous: redeemed,
1001
+ closed,
1002
+ closing,
1003
+ closingHash: (0, summary_1.sha256HexUtf8)((0, summary_1.stableStringify)(closing)),
1004
+ };
1005
+ }
1006
+ async function verifyBondClosing(sdk, input) {
1007
+ const definitionSource = resolveValueOrPath({
1008
+ pathValue: input.definitionPath,
1009
+ objectValue: input.definitionValue,
1010
+ });
1011
+ const redeemedSource = resolveValueOrPath({
1012
+ pathValue: input.redeemedIssuancePath,
1013
+ objectValue: input.redeemedIssuanceValue,
1014
+ });
1015
+ const closedSource = resolveValueOrPath({
1016
+ pathValue: input.closedIssuancePath,
1017
+ objectValue: input.closedIssuanceValue,
1018
+ });
1019
+ const definitionDescriptor = await sdk.loadDefinition({
1020
+ type: "bond",
1021
+ id: input.definitionValue?.bondId ?? "BOND-2026-001",
1022
+ ...definitionSource,
1023
+ });
1024
+ const redeemedDescriptor = await sdk.loadStateDocument({
1025
+ type: "bond-issuance",
1026
+ id: input.redeemedIssuanceValue?.issuanceId ?? "BOND-2026-001-ISSUE-1",
1027
+ ...redeemedSource,
1028
+ });
1029
+ const closedDescriptor = await sdk.loadStateDocument({
1030
+ type: "bond-issuance",
1031
+ id: input.closedIssuanceValue?.issuanceId ?? "BOND-2026-001-ISSUE-1",
1032
+ ...closedSource,
1033
+ });
1034
+ const definition = (0, bondValidation_1.validateBondDefinition)(JSON.parse(definitionDescriptor.canonicalJson));
1035
+ const redeemed = (0, bondValidation_1.validateBondIssuanceState)(JSON.parse(redeemedDescriptor.canonicalJson));
1036
+ const closed = (0, bondValidation_1.validateBondIssuanceState)(JSON.parse(closedDescriptor.canonicalJson));
1037
+ (0, bondValidation_1.validateBondCrossChecks)(definition, redeemed);
1038
+ (0, bondValidation_1.validateBondCrossChecks)(definition, closed);
1039
+ const settlementHash = input.settlementDescriptorValue
1040
+ ? (0, bondSettlementValidation_1.summarizeBondSettlementDescriptor)(input.settlementDescriptorValue).hash
1041
+ : input.settlementDescriptorPath
1042
+ ? (0, bondSettlementValidation_1.summarizeBondSettlementDescriptor)(JSON.parse(await Promise.resolve().then(() => __importStar(require("node:fs/promises"))).then((fs) => fs.readFile(input.settlementDescriptorPath, "utf8")))).hash
1043
+ : "";
1044
+ const checks = {
1045
+ redeemedStateMatch: redeemed.status === "REDEEMED",
1046
+ closedStateMatch: closed.status === "CLOSED",
1047
+ previousStateHashMatch: closed.previousStateHash === (0, bondValidation_1.summarizeBondIssuanceState)(redeemed).hash,
1048
+ finalSettlementDescriptorHashMatch: closed.finalSettlementDescriptorHash === settlementHash,
1049
+ closingReasonPresent: !!closed.closingReason,
1050
+ closedAtPresent: !!closed.closedAt,
1051
+ };
1052
+ return {
1053
+ definition,
1054
+ redeemed,
1055
+ closed,
1056
+ checks,
1057
+ verified: Object.values(checks).every(Boolean),
1058
+ };
1059
+ }
1060
+ async function buildEvidenceBundle(sdk, input) {
1061
+ const artifact = input.artifact ?? (input.artifactPath ? (await sdk.loadArtifact(input.artifactPath)).artifact : undefined);
1062
+ if (!artifact)
1063
+ throw new Error("artifactPath or artifact is required");
1064
+ const verification = await verifyBond(sdk, {
1065
+ artifact,
1066
+ definitionPath: input.definitionPath,
1067
+ definitionValue: input.definitionValue,
1068
+ issuancePath: input.issuancePath,
1069
+ issuanceValue: input.issuanceValue,
1070
+ });
1071
+ const definition = verification.definition.definition;
1072
+ const issuance = verification.issuance.state;
1073
+ const issuanceHistory = input.issuanceHistoryPaths || input.issuanceHistoryValues
1074
+ ? await loadIssuanceHistoryDocuments(sdk, {
1075
+ issuanceHistoryPaths: input.issuanceHistoryPaths,
1076
+ issuanceHistoryValues: input.issuanceHistoryValues,
1077
+ })
1078
+ : [];
1079
+ const lineageChecks = issuanceHistory.length > 0
1080
+ ? (0, bondValidation_1.verifyBondIssuanceHistory)({ history: issuanceHistory.map((entry) => entry.value) })
1081
+ : undefined;
1082
+ const settlementCanonicalJson = input.settlementDescriptorValue
1083
+ ? (0, bondSettlementValidation_1.summarizeBondSettlementDescriptor)(input.settlementDescriptorValue).canonicalJson
1084
+ : null;
1085
+ const settlementHash = input.settlementDescriptorValue
1086
+ ? (0, bondSettlementValidation_1.summarizeBondSettlementDescriptor)(input.settlementDescriptorValue).hash
1087
+ : null;
1088
+ const closingCanonicalJson = input.closingDescriptorValue
1089
+ ? (0, summary_1.stableStringify)(input.closingDescriptorValue)
1090
+ : null;
1091
+ const closingHash = closingCanonicalJson
1092
+ ? (0, summary_1.sha256HexUtf8)(closingCanonicalJson)
1093
+ : null;
1094
+ const sourcePath = artifact.source.mode === "file" ? artifact.source.simfPath : undefined;
1095
+ const renderedSourceHash = sourcePath && (0, node_fs_1.existsSync)(sourcePath)
1096
+ ? (0, summary_1.sha256HexUtf8)(await Promise.resolve().then(() => __importStar(require("node:fs/promises"))).then((fs) => fs.readFile(sourcePath, "utf8")))
1097
+ : null;
1098
+ return {
1099
+ artifact,
1100
+ definition: {
1101
+ canonicalJson: definition.canonicalJson,
1102
+ hash: definition.hash,
1103
+ },
1104
+ issuance: {
1105
+ canonicalJson: issuance.canonicalJson,
1106
+ hash: issuance.hash,
1107
+ },
1108
+ transition: input.transitionValue
1109
+ ? {
1110
+ canonicalJson: (0, summary_1.stableStringify)(input.transitionValue),
1111
+ hash: (0, summary_1.sha256HexUtf8)((0, summary_1.stableStringify)(input.transitionValue)),
1112
+ }
1113
+ : undefined,
1114
+ settlement: settlementCanonicalJson && settlementHash
1115
+ ? {
1116
+ canonicalJson: settlementCanonicalJson,
1117
+ hash: settlementHash,
1118
+ }
1119
+ : undefined,
1120
+ closing: closingCanonicalJson && closingHash
1121
+ ? {
1122
+ canonicalJson: closingCanonicalJson,
1123
+ hash: closingHash,
1124
+ }
1125
+ : undefined,
1126
+ trust: {
1127
+ ...buildBaseBondReport({
1128
+ definitionTrust: verification.definition.trust,
1129
+ stateTrust: verification.issuance.trust,
1130
+ }),
1131
+ issuanceLineageTrust: lineageChecks ? buildBondIssuanceLineageTrust(lineageChecks) : undefined,
1132
+ settlementTrust: input.settlementDescriptorValue
1133
+ ? {
1134
+ descriptorHashMatch: true,
1135
+ outputBindingMode: input.settlementDescriptorValue.outputBindingMode ?? "none",
1136
+ }
1137
+ : undefined,
1138
+ },
1139
+ trustSummary: (0, reporting_1.buildVerificationTrustSummary)({
1140
+ definitionTrust: verification.definition.trust,
1141
+ stateTrust: verification.issuance.trust,
1142
+ bindingMode: input.settlementDescriptorValue?.outputBindingMode ?? "none",
1143
+ lineageTrust: lineageChecks ? buildBondIssuanceLineageTrust(lineageChecks) : undefined,
1144
+ }),
1145
+ renderedSourceHash: renderedSourceHash ?? undefined,
1146
+ sourceVerificationMode: renderedSourceHash ? "source-reloaded" : "artifact-only",
1147
+ compiled: {
1148
+ program: artifact.compiled.program,
1149
+ cmr: artifact.compiled.cmr,
1150
+ contractAddress: artifact.compiled.contractAddress,
1151
+ },
1152
+ };
1153
+ }
1154
+ async function verifyEvidenceBundle(sdk, input) {
1155
+ const expected = await buildEvidenceBundle(sdk, {
1156
+ artifact: input.bundleValue.artifact,
1157
+ definitionPath: input.definitionPath,
1158
+ issuancePath: input.issuancePath,
1159
+ settlementDescriptorValue: input.settlementDescriptorValue,
1160
+ closingDescriptorValue: input.closingDescriptorValue,
1161
+ });
1162
+ const checks = {
1163
+ definitionHashMatch: input.bundleValue.definition.hash === expected.definition.hash,
1164
+ issuanceHashMatch: input.bundleValue.issuance.hash === expected.issuance.hash,
1165
+ settlementHashMatch: (input.bundleValue.settlement?.hash ?? null) === (expected.settlement?.hash ?? null),
1166
+ closingHashMatch: (input.bundleValue.closing?.hash ?? null) === (expected.closing?.hash ?? null),
1167
+ renderedSourceHashMatch: input.bundleValue.renderedSourceHash === expected.renderedSourceHash,
1168
+ cmrMatch: input.bundleValue.compiled.cmr === expected.compiled.cmr,
1169
+ contractAddressMatch: input.bundleValue.compiled.contractAddress === expected.compiled.contractAddress,
1170
+ };
1171
+ return {
1172
+ expected,
1173
+ checks,
1174
+ verified: Object.values(checks).every(Boolean),
1175
+ };
1176
+ }
1177
+ async function issueBond(sdk, input) {
1178
+ return defineBond(sdk, input);
1179
+ }
1180
+ async function prepareRedemption(sdk, input) {
1181
+ const preview = await buildBondRedemption(sdk, {
1182
+ definitionPath: input.definitionPath,
1183
+ definitionValue: input.definitionValue,
1184
+ previousIssuancePath: input.previousIssuancePath,
1185
+ previousIssuanceValue: input.previousIssuanceValue,
1186
+ amount: input.amount,
1187
+ redeemedAt: input.redeemedAt,
1188
+ });
1189
+ const settlement = await buildBondSettlementPayload(sdk, {
1190
+ definitionValue: preview.definition,
1191
+ previousIssuanceValue: preview.previous,
1192
+ nextIssuanceValue: preview.next,
1193
+ nextStateSimfPath: input.nextStateSimfPath,
1194
+ nextAmountSat: input.nextAmountSat,
1195
+ maxFeeSat: input.maxFeeSat,
1196
+ nextOutputHash: input.nextOutputHash,
1197
+ rawOutput: input.rawOutput,
1198
+ outputBindingMode: input.outputBindingMode,
1199
+ });
1200
+ return { preview, settlement };
1201
+ }
1202
+ async function finalizeRedemption(sdk, input) {
1203
+ return buildBondMachineSettlementPlan(sdk, input);
1204
+ }
1205
+ async function prepareClosing(sdk, input) {
1206
+ return buildBondClosing(sdk, input);
1207
+ }
1208
+ async function exportFinalityPayload(sdk, input) {
1209
+ const bondPayload = await buildBondPayload(sdk, input);
1210
+ const evidence = await buildEvidenceBundle(sdk, input);
1211
+ return {
1212
+ payload: bondPayload.payload,
1213
+ bindingMode: input.settlementDescriptorValue?.outputBindingMode ?? "none",
1214
+ trust: bondPayload.trust,
1215
+ trustSummary: evidence.trustSummary,
1216
+ evidenceSummary: {
1217
+ definitionHash: evidence.definition.hash,
1218
+ issuanceHash: evidence.issuance.hash,
1219
+ settlementHash: evidence.settlement?.hash ?? null,
1220
+ closingHash: evidence.closing?.hash ?? null,
1221
+ renderedSourceHash: evidence.renderedSourceHash,
1222
+ sourceVerificationMode: evidence.sourceVerificationMode,
1223
+ },
1224
+ };
1225
+ }
1226
+ async function define(sdk, input) {
1227
+ return defineBond(sdk, input);
1228
+ }
1229
+ async function verify(sdk, input) {
1230
+ return verifyBond(sdk, input);
1231
+ }
1232
+ async function load(sdk, input) {
1233
+ return loadBond(sdk, input);
1234
+ }
1235
+ async function issue(sdk, input) {
1236
+ return issueBond(sdk, input);
1237
+ }
1238
+ async function buildSettlement(sdk, input) {
1239
+ return buildBondSettlementPayload(sdk, input);
1240
+ }
1241
+ async function verifySettlement(sdk, input) {
1242
+ return verifyBondSettlementDescriptor(sdk, input);
1243
+ }
1244
+ function resolveRedemptionBindingMode(settlement) {
1245
+ return settlement.descriptor?.outputBindingMode ?? "none";
1246
+ }
1247
+ async function inspectRedemption(sdk, input) {
1248
+ const settlement = await buildBondSettlementPayload(sdk, {
1249
+ definitionPath: input.definitionPath,
1250
+ definitionValue: input.definitionValue,
1251
+ previousIssuancePath: input.previousIssuancePath,
1252
+ previousIssuanceValue: input.previousIssuanceValue,
1253
+ nextIssuancePath: input.nextIssuancePath,
1254
+ nextIssuanceValue: input.nextIssuanceValue,
1255
+ nextStateSimfPath: input.nextStateSimfPath,
1256
+ nextAmountSat: input.nextAmountSat ?? 1900,
1257
+ maxFeeSat: input.maxFeeSat,
1258
+ nextOutputHash: input.nextOutputHash,
1259
+ outputForm: input.outputForm,
1260
+ rawOutput: input.rawOutput,
1261
+ outputBindingMode: input.outputBindingMode,
1262
+ });
1263
+ const mode = resolveRedemptionBindingMode(settlement);
1264
+ if (mode === "descriptor-bound") {
1265
+ const result = await inspectBondDescriptorBoundMachineRollover(sdk, {
1266
+ ...input,
1267
+ nextAmountSat: input.nextAmountSat,
1268
+ maxFeeSat: input.maxFeeSat,
1269
+ nextOutputHash: input.nextOutputHash,
1270
+ });
1271
+ return { mode, settlement, ...result };
1272
+ }
1273
+ if (mode === "script-bound") {
1274
+ const result = await inspectBondScriptBoundMachineRollover(sdk, {
1275
+ ...input,
1276
+ nextAmountSat: input.nextAmountSat,
1277
+ maxFeeSat: input.maxFeeSat,
1278
+ });
1279
+ return { mode, settlement, ...result };
1280
+ }
1281
+ const result = await inspectBondMachineRollover(sdk, input);
1282
+ return { mode, settlement, ...result };
1283
+ }
1284
+ async function executeRedemption(sdk, input) {
1285
+ const settlement = await buildBondSettlementPayload(sdk, {
1286
+ definitionPath: input.definitionPath,
1287
+ definitionValue: input.definitionValue,
1288
+ previousIssuancePath: input.previousIssuancePath,
1289
+ previousIssuanceValue: input.previousIssuanceValue,
1290
+ nextIssuancePath: input.nextIssuancePath,
1291
+ nextIssuanceValue: input.nextIssuanceValue,
1292
+ nextStateSimfPath: input.nextStateSimfPath,
1293
+ nextAmountSat: input.nextAmountSat ?? 1900,
1294
+ maxFeeSat: input.maxFeeSat,
1295
+ nextOutputHash: input.nextOutputHash,
1296
+ outputForm: input.outputForm,
1297
+ rawOutput: input.rawOutput,
1298
+ outputBindingMode: input.outputBindingMode,
1299
+ });
1300
+ const mode = resolveRedemptionBindingMode(settlement);
1301
+ if (mode === "descriptor-bound") {
1302
+ const result = await executeBondDescriptorBoundMachineRollover(sdk, {
1303
+ ...input,
1304
+ nextAmountSat: input.nextAmountSat,
1305
+ maxFeeSat: input.maxFeeSat,
1306
+ nextOutputHash: input.nextOutputHash,
1307
+ });
1308
+ return { mode, settlement, ...result };
1309
+ }
1310
+ if (mode === "script-bound") {
1311
+ const result = await executeBondScriptBoundMachineRollover(sdk, {
1312
+ ...input,
1313
+ nextAmountSat: input.nextAmountSat,
1314
+ maxFeeSat: input.maxFeeSat,
1315
+ });
1316
+ return { mode, settlement, ...result };
1317
+ }
1318
+ const result = await executeBondMachineRollover(sdk, input);
1319
+ return { mode, settlement, ...result };
1320
+ }
1321
+ async function verifyRedemption(sdk, input) {
1322
+ const settlement = await buildBondSettlementPayload(sdk, {
1323
+ definitionPath: input.definitionPath,
1324
+ definitionValue: input.definitionValue,
1325
+ previousIssuancePath: input.previousIssuancePath,
1326
+ previousIssuanceValue: input.previousIssuanceValue,
1327
+ nextIssuancePath: input.nextIssuancePath,
1328
+ nextIssuanceValue: input.nextIssuanceValue,
1329
+ nextStateSimfPath: input.nextStateSimfPath,
1330
+ nextAmountSat: input.nextAmountSat ?? 1900,
1331
+ maxFeeSat: input.maxFeeSat,
1332
+ nextOutputHash: input.nextOutputHash,
1333
+ outputForm: input.outputForm,
1334
+ rawOutput: input.rawOutput,
1335
+ outputBindingMode: input.outputBindingMode,
1336
+ });
1337
+ const mode = resolveRedemptionBindingMode(settlement);
1338
+ if (mode === "descriptor-bound") {
1339
+ const result = await verifyBondDescriptorBoundSettlementMachineArtifact(sdk, {
1340
+ ...input,
1341
+ nextAmountSat: input.nextAmountSat,
1342
+ maxFeeSat: input.maxFeeSat,
1343
+ nextOutputHash: input.nextOutputHash,
1344
+ outputForm: input.outputForm,
1345
+ });
1346
+ return { mode, settlement, ...result };
1347
+ }
1348
+ if (mode === "script-bound") {
1349
+ const result = await verifyBondScriptBoundSettlementMachineArtifact(sdk, {
1350
+ ...input,
1351
+ nextAmountSat: input.nextAmountSat,
1352
+ maxFeeSat: input.maxFeeSat,
1353
+ outputForm: input.outputForm,
1354
+ });
1355
+ return { mode, settlement, ...result };
1356
+ }
1357
+ const result = await verifyBondRedemptionMachineArtifact(sdk, {
1358
+ ...input,
1359
+ outputForm: input.outputForm,
1360
+ });
1361
+ return { mode, settlement, ...result };
1362
+ }
1363
+ async function inspectClosing(sdk, input) {
1364
+ return inspectBondClosing(sdk, input);
1365
+ }
1366
+ async function executeClosing(sdk, input) {
1367
+ return executeBondClosing(sdk, input);
1368
+ }
1369
+ async function verifyClosing(sdk, input) {
1370
+ return verifyBondClosing(sdk, input);
1371
+ }
1372
+ async function exportEvidence(sdk, input) {
1373
+ return buildEvidenceBundle(sdk, input);
1374
+ }
496
1375
  async function compileBondTransition(sdk, input) {
497
1376
  const transitionPayload = await buildBondTransitionPayload(sdk, {
498
1377
  definitionPath: input.definitionPath,
@@ -520,7 +1399,7 @@ async function compileBondTransition(sdk, input) {
520
1399
  id: transitionPayload.next.issuanceId,
521
1400
  ...nextSource,
522
1401
  });
523
- const simfPath = input.simfPath ?? node_path_1.default.resolve(process.cwd(), "docs/definitions/bond-redemption-transition.simf");
1402
+ const simfPath = input.simfPath ?? resolveBondDocsAsset("bond-redemption-transition.simf");
524
1403
  const rawSource = await Promise.resolve().then(() => __importStar(require("node:fs/promises"))).then((fs) => fs.readFile(simfPath, "utf8"));
525
1404
  const previousAnchor = detectPreviousStateAnchor(rawSource);
526
1405
  if (!previousAnchor.sourceVerified) {
@@ -605,6 +1484,10 @@ async function verifyBondRedemptionMachineArtifact(sdk, input) {
605
1484
  nextStateSimfPath: input.nextStateSimfPath,
606
1485
  nextAmountSat: input.nextAmountSat ?? 1900,
607
1486
  maxFeeSat: input.maxFeeSat ?? 100,
1487
+ nextOutputHash: input.nextOutputHash,
1488
+ outputForm: input.outputForm,
1489
+ rawOutput: input.rawOutput,
1490
+ outputBindingMode: input.outputBindingMode,
608
1491
  });
609
1492
  const templateVars = artifact.source.templateVars ?? {};
610
1493
  const committed = {
@@ -619,7 +1502,10 @@ async function verifyBondRedemptionMachineArtifact(sdk, input) {
619
1502
  nextOutstanding32: String(templateVars.NEXT_OUTSTANDING_32 ?? ""),
620
1503
  nextRedeemed32: String(templateVars.NEXT_REDEEMED_32 ?? ""),
621
1504
  nextContractAddressHash256: String(templateVars.NEXT_CONTRACT_ADDRESS_HASH_256 ?? ""),
1505
+ expectedNextOutputHash256: String(templateVars.EXPECTED_NEXT_OUTPUT_HASH_256 ?? ""),
1506
+ expectedNextOutputScriptHash256: String(templateVars.EXPECTED_NEXT_OUTPUT_SCRIPT_HASH_256 ?? ""),
622
1507
  settlementDescriptorHash256: String(templateVars.SETTLEMENT_DESCRIPTOR_HASH ?? ""),
1508
+ expectedOutputDescriptorHash256: String(templateVars.EXPECTED_OUTPUT_DESCRIPTOR_HASH ?? ""),
623
1509
  };
624
1510
  const checks = {
625
1511
  previousStateHashCommitted: committed.previousStateHash === expected.payload.previousStateHash,
@@ -633,7 +1519,14 @@ async function verifyBondRedemptionMachineArtifact(sdk, input) {
633
1519
  && committed.nextOutstanding32 === toUint32Hex(expected.payload.principal.nextOutstanding)
634
1520
  && committed.nextRedeemed32 === toUint32Hex(expected.payload.principal.nextRedeemed),
635
1521
  nextContractAddressCommitted: committed.nextContractAddressHash256 === expectedNextContractAddressHash,
1522
+ nextOutputHashCommitted: !expectedSettlement.expectedOutputDescriptor?.nextOutputHash
1523
+ || committed.expectedNextOutputHash256 === expectedSettlement.expectedOutputDescriptor.nextOutputHash,
1524
+ nextOutputScriptCommitted: !expectedSettlement.expectedOutputDescriptor?.nextOutputScriptHash
1525
+ || committed.expectedNextOutputScriptHash256
1526
+ === expectedSettlement.expectedOutputDescriptor.nextOutputScriptHash,
636
1527
  settlementDescriptorCommitted: committed.settlementDescriptorHash256 === expectedSettlement.hash,
1528
+ expectedOutputDescriptorCommitted: !expectedSettlement.expectedOutputDescriptorHash
1529
+ || committed.expectedOutputDescriptorHash256 === expectedSettlement.expectedOutputDescriptorHash,
637
1530
  };
638
1531
  const allChecks = Object.values(checks).every(Boolean);
639
1532
  return {
@@ -647,6 +1540,16 @@ async function verifyBondRedemptionMachineArtifact(sdk, input) {
647
1540
  },
648
1541
  expectedSettlementDescriptor: expectedSettlement.descriptor,
649
1542
  expectedSettlementDescriptorHash: expectedSettlement.hash,
1543
+ outputBindingMetadata: {
1544
+ requestedMode: expectedSettlement.expectedOutputDescriptor?.requestedOutputBindingMode
1545
+ ?? expectedSettlement.descriptor.outputBindingMode
1546
+ ?? "none",
1547
+ supportedForm: expectedSettlement.expectedOutputBindingSupportedForm,
1548
+ reasonCode: expectedSettlement.expectedOutputBindingReasonCode,
1549
+ autoDerived: expectedSettlement.expectedOutputBindingAutoDerived,
1550
+ fallbackReason: expectedSettlement.expectedOutputBindingFallbackReason,
1551
+ bindingInputs: expectedSettlement.expectedOutputBindingInputs,
1552
+ },
650
1553
  expectedNextContractAddress,
651
1554
  expectedNextContractAddressHash,
652
1555
  committed,
@@ -705,8 +1608,12 @@ async function compileBondRedemptionMachine(sdk, input) {
705
1608
  nextStateSimfPath: input.nextStateSimfPath,
706
1609
  nextAmountSat: input.nextAmountSat ?? 1900,
707
1610
  maxFeeSat: input.maxFeeSat ?? 100,
1611
+ nextOutputHash: input.nextOutputHash,
1612
+ outputForm: input.outputForm,
1613
+ rawOutput: input.rawOutput,
1614
+ outputBindingMode: input.outputBindingMode,
708
1615
  });
709
- const simfPath = input.simfPath ?? node_path_1.default.resolve(process.cwd(), "docs/definitions/bond-redemption-state-machine.simf");
1616
+ const simfPath = input.simfPath ?? resolveBondDocsAsset("bond-redemption-state-machine.simf");
710
1617
  const compiled = await sdk.compileFromFile({
711
1618
  simfPath,
712
1619
  templateVars: {
@@ -724,6 +1631,15 @@ async function compileBondRedemptionMachine(sdk, input) {
724
1631
  NEXT_REDEEMED_32: toUint32Hex(transitionResult.payload.principal.nextRedeemed),
725
1632
  NEXT_CONTRACT_ADDRESS_HASH_256: nextStateContractAddressHash,
726
1633
  SETTLEMENT_DESCRIPTOR_HASH: settlementDescriptor.hash,
1634
+ ...(input.expectedOutputDescriptorHash
1635
+ ? { EXPECTED_OUTPUT_DESCRIPTOR_HASH: input.expectedOutputDescriptorHash }
1636
+ : {}),
1637
+ ...(settlementDescriptor.expectedOutputDescriptor?.nextOutputHash
1638
+ ? { EXPECTED_NEXT_OUTPUT_HASH_256: settlementDescriptor.expectedOutputDescriptor.nextOutputHash }
1639
+ : {}),
1640
+ ...(settlementDescriptor.expectedOutputDescriptor?.nextOutputScriptHash
1641
+ ? { EXPECTED_NEXT_OUTPUT_SCRIPT_HASH_256: settlementDescriptor.expectedOutputDescriptor.nextOutputScriptHash }
1642
+ : {}),
727
1643
  },
728
1644
  definition: {
729
1645
  type: definitionDescriptor.definitionType,
@@ -768,13 +1684,147 @@ async function compileBondRedemptionMachine(sdk, input) {
768
1684
  nextStateContractAddressHash,
769
1685
  settlementDescriptor: settlementDescriptor.descriptor,
770
1686
  settlementDescriptorHash: settlementDescriptor.hash,
1687
+ outputBindingMode: settlementDescriptor.descriptor.outputBindingMode ?? "none",
771
1688
  },
772
1689
  };
773
1690
  }
774
- async function buildBondRedemption(sdk, input) {
775
- const definitionSource = resolveValueOrPath({
776
- pathValue: input.definitionPath,
777
- objectValue: input.definitionValue,
1691
+ async function compileBondScriptBoundSettlementMachine(sdk, input) {
1692
+ const settlement = await buildBondSettlementDescriptor(sdk, {
1693
+ definitionPath: input.definitionPath,
1694
+ definitionValue: input.definitionValue,
1695
+ previousIssuancePath: input.previousIssuancePath,
1696
+ previousIssuanceValue: input.previousIssuanceValue,
1697
+ nextIssuancePath: input.nextIssuancePath,
1698
+ nextIssuanceValue: input.nextIssuanceValue,
1699
+ nextStateSimfPath: input.nextStateSimfPath,
1700
+ nextAmountSat: input.nextAmountSat ?? 1900,
1701
+ maxFeeSat: input.maxFeeSat ?? 100,
1702
+ rawOutput: input.rawOutput,
1703
+ outputBindingMode: "script-bound",
1704
+ });
1705
+ const base = await compileBondRedemptionMachine(sdk, {
1706
+ ...input,
1707
+ outputBindingMode: "script-bound",
1708
+ expectedOutputDescriptorHash: settlement.expectedOutputDescriptorHash,
1709
+ simfPath: input.simfPath ?? resolveBondDocsAsset("bond-script-bound-settlement-machine.simf"),
1710
+ });
1711
+ return {
1712
+ ...base,
1713
+ expectedOutputDescriptor: settlement.expectedOutputDescriptor,
1714
+ expectedOutputDescriptorHash: settlement.expectedOutputDescriptorHash,
1715
+ outputBindingMode: "script-bound",
1716
+ };
1717
+ }
1718
+ async function verifyBondScriptBoundSettlementMachineArtifact(sdk, input) {
1719
+ const base = await verifyBondRedemptionMachineArtifact(sdk, {
1720
+ ...input,
1721
+ outputBindingMode: "script-bound",
1722
+ });
1723
+ return {
1724
+ ...base,
1725
+ outputBindingTrust: {
1726
+ mode: "script-bound",
1727
+ requestedMode: base.outputBindingMetadata.requestedMode,
1728
+ supportedForm: base.outputBindingMetadata.supportedForm,
1729
+ outputCountRuntimeBound: true,
1730
+ feeIndexRuntimeBound: true,
1731
+ settlementDescriptorCommitted: base.checks.settlementDescriptorCommitted,
1732
+ nextContractAddressCommitted: base.checks.nextContractAddressCommitted,
1733
+ nextOutputHashRuntimeBound: false,
1734
+ nextOutputScriptRuntimeBound: true,
1735
+ amountRuntimeBound: false,
1736
+ reasonCode: base.outputBindingMetadata.reasonCode,
1737
+ autoDerived: base.outputBindingMetadata.autoDerived,
1738
+ fallbackReason: base.outputBindingMetadata.fallbackReason,
1739
+ bindingInputs: base.outputBindingMetadata.bindingInputs,
1740
+ },
1741
+ };
1742
+ }
1743
+ async function compileBondDescriptorBoundSettlementMachine(sdk, input) {
1744
+ const settlement = await buildBondSettlementDescriptor(sdk, {
1745
+ definitionPath: input.definitionPath,
1746
+ definitionValue: input.definitionValue,
1747
+ previousIssuancePath: input.previousIssuancePath,
1748
+ previousIssuanceValue: input.previousIssuanceValue,
1749
+ nextIssuancePath: input.nextIssuancePath,
1750
+ nextIssuanceValue: input.nextIssuanceValue,
1751
+ nextStateSimfPath: input.nextStateSimfPath,
1752
+ nextAmountSat: input.nextAmountSat ?? 1900,
1753
+ maxFeeSat: input.maxFeeSat ?? 100,
1754
+ nextOutputHash: input.nextOutputHash,
1755
+ rawOutput: input.rawOutput,
1756
+ outputBindingMode: "descriptor-bound",
1757
+ });
1758
+ if (settlement.descriptor.outputBindingMode !== "descriptor-bound") {
1759
+ const fallback = await compileBondScriptBoundSettlementMachine(sdk, input);
1760
+ return {
1761
+ ...fallback,
1762
+ requestedOutputBindingMode: "descriptor-bound",
1763
+ outputBindingMode: fallback.outputBindingMode,
1764
+ };
1765
+ }
1766
+ const base = await compileBondRedemptionMachine(sdk, {
1767
+ ...input,
1768
+ nextOutputHash: settlement.expectedOutputDescriptor?.nextOutputHash,
1769
+ outputBindingMode: "descriptor-bound",
1770
+ expectedOutputDescriptorHash: settlement.expectedOutputDescriptorHash,
1771
+ simfPath: input.simfPath ?? resolveBondDocsAsset("bond-descriptor-bound-settlement-machine.simf"),
1772
+ });
1773
+ return {
1774
+ ...base,
1775
+ expectedOutputDescriptor: settlement.expectedOutputDescriptor,
1776
+ expectedOutputDescriptorHash: settlement.expectedOutputDescriptorHash,
1777
+ requestedOutputBindingMode: "descriptor-bound",
1778
+ outputBindingMode: "descriptor-bound",
1779
+ };
1780
+ }
1781
+ async function verifyBondDescriptorBoundSettlementMachineArtifact(sdk, input) {
1782
+ const base = await verifyBondRedemptionMachineArtifact(sdk, {
1783
+ ...input,
1784
+ outputBindingMode: "descriptor-bound",
1785
+ });
1786
+ const mode = base.expectedSettlementDescriptor.outputBindingMode === "descriptor-bound" && base.checks.nextOutputHashCommitted
1787
+ ? "descriptor-bound"
1788
+ : "script-bound";
1789
+ return {
1790
+ ...base,
1791
+ outputBindingTrust: {
1792
+ mode,
1793
+ requestedMode: base.outputBindingMetadata.requestedMode,
1794
+ supportedForm: base.outputBindingMetadata.supportedForm,
1795
+ outputCountRuntimeBound: true,
1796
+ feeIndexRuntimeBound: true,
1797
+ settlementDescriptorCommitted: base.checks.settlementDescriptorCommitted,
1798
+ nextContractAddressCommitted: base.checks.nextContractAddressCommitted,
1799
+ nextOutputHashRuntimeBound: mode === "descriptor-bound",
1800
+ nextOutputScriptRuntimeBound: mode !== "descriptor-bound",
1801
+ amountRuntimeBound: false,
1802
+ reasonCode: base.outputBindingMetadata.reasonCode,
1803
+ autoDerived: base.outputBindingMetadata.autoDerived,
1804
+ fallbackReason: base.outputBindingMetadata.fallbackReason,
1805
+ bindingInputs: base.outputBindingMetadata.bindingInputs,
1806
+ },
1807
+ };
1808
+ }
1809
+ async function compileBondClosingMachine(sdk, input) {
1810
+ const closing = await buildBondClosing(sdk, input);
1811
+ const result = await defineBond(sdk, {
1812
+ definitionValue: closing.definition,
1813
+ issuanceValue: closing.closed,
1814
+ simfPath: input.simfPath ?? resolveBondDocsAsset("bond-issuance-anchor.simf"),
1815
+ artifactPath: input.artifactPath,
1816
+ });
1817
+ return {
1818
+ compiled: result,
1819
+ closing: closing.closing,
1820
+ closingHash: closing.closingHash,
1821
+ closedState: closing.closed,
1822
+ };
1823
+ }
1824
+ async function buildBondRedemption(sdk, input) {
1825
+ const definitionSource = resolveValueOrPath({
1826
+ pathValue: input.definitionPath,
1827
+ objectValue: input.definitionValue,
778
1828
  });
779
1829
  const previousSource = resolveValueOrPath({
780
1830
  pathValue: input.previousIssuancePath,
@@ -931,6 +1981,102 @@ async function buildBondMachineRolloverPlan(sdk, input) {
931
1981
  transitionPayload: machineCompiled.payload,
932
1982
  };
933
1983
  }
1984
+ async function buildBondScriptBoundMachineRolloverPlan(sdk, input) {
1985
+ const currentArtifact = input.currentArtifact
1986
+ ?? (input.currentArtifactPath ? (await sdk.loadArtifact(input.currentArtifactPath)).artifact : undefined);
1987
+ if (!currentArtifact) {
1988
+ throw new Error("currentArtifactPath or currentArtifact is required");
1989
+ }
1990
+ const currentVerification = await verifyBond(sdk, {
1991
+ artifact: currentArtifact,
1992
+ definitionPath: input.definitionPath,
1993
+ definitionValue: input.definitionValue,
1994
+ issuancePath: input.previousIssuancePath,
1995
+ issuanceValue: input.previousIssuanceValue,
1996
+ });
1997
+ const machineCompiled = await compileBondScriptBoundSettlementMachine(sdk, {
1998
+ definitionPath: input.definitionPath,
1999
+ definitionValue: input.definitionValue,
2000
+ previousIssuancePath: input.previousIssuancePath,
2001
+ previousIssuanceValue: input.previousIssuanceValue,
2002
+ nextIssuancePath: input.nextIssuancePath,
2003
+ nextIssuanceValue: input.nextIssuanceValue,
2004
+ nextStateSimfPath: input.nextStateSimfPath,
2005
+ nextAmountSat: input.nextAmountSat,
2006
+ maxFeeSat: input.maxFeeSat,
2007
+ simfPath: input.machineSimfPath,
2008
+ artifactPath: input.machineArtifactPath,
2009
+ });
2010
+ const machineVerification = await verifyBondScriptBoundSettlementMachineArtifact(sdk, {
2011
+ artifact: machineCompiled.compiled.artifact,
2012
+ definitionPath: input.definitionPath,
2013
+ definitionValue: input.definitionValue,
2014
+ previousIssuancePath: input.previousIssuancePath,
2015
+ previousIssuanceValue: input.previousIssuanceValue,
2016
+ nextIssuancePath: input.nextIssuancePath,
2017
+ nextIssuanceValue: input.nextIssuanceValue,
2018
+ nextStateSimfPath: input.nextStateSimfPath,
2019
+ nextAmountSat: input.nextAmountSat,
2020
+ maxFeeSat: input.maxFeeSat,
2021
+ });
2022
+ return {
2023
+ currentArtifact,
2024
+ currentVerification,
2025
+ machineCompiled,
2026
+ machineVerification,
2027
+ nextContractAddress: machineCompiled.compiled.deployment().contractAddress,
2028
+ transitionPayload: machineCompiled.payload,
2029
+ };
2030
+ }
2031
+ async function buildBondDescriptorBoundMachineRolloverPlan(sdk, input) {
2032
+ const currentArtifact = input.currentArtifact
2033
+ ?? (input.currentArtifactPath ? (await sdk.loadArtifact(input.currentArtifactPath)).artifact : undefined);
2034
+ if (!currentArtifact) {
2035
+ throw new Error("currentArtifactPath or currentArtifact is required");
2036
+ }
2037
+ const currentVerification = await verifyBond(sdk, {
2038
+ artifact: currentArtifact,
2039
+ definitionPath: input.definitionPath,
2040
+ definitionValue: input.definitionValue,
2041
+ issuancePath: input.previousIssuancePath,
2042
+ issuanceValue: input.previousIssuanceValue,
2043
+ });
2044
+ const machineCompiled = await compileBondDescriptorBoundSettlementMachine(sdk, {
2045
+ definitionPath: input.definitionPath,
2046
+ definitionValue: input.definitionValue,
2047
+ previousIssuancePath: input.previousIssuancePath,
2048
+ previousIssuanceValue: input.previousIssuanceValue,
2049
+ nextIssuancePath: input.nextIssuancePath,
2050
+ nextIssuanceValue: input.nextIssuanceValue,
2051
+ nextStateSimfPath: input.nextStateSimfPath,
2052
+ nextAmountSat: input.nextAmountSat,
2053
+ maxFeeSat: input.maxFeeSat,
2054
+ nextOutputHash: input.nextOutputHash,
2055
+ simfPath: input.machineSimfPath,
2056
+ artifactPath: input.machineArtifactPath,
2057
+ });
2058
+ const machineVerification = await verifyBondDescriptorBoundSettlementMachineArtifact(sdk, {
2059
+ artifact: machineCompiled.compiled.artifact,
2060
+ definitionPath: input.definitionPath,
2061
+ definitionValue: input.definitionValue,
2062
+ previousIssuancePath: input.previousIssuancePath,
2063
+ previousIssuanceValue: input.previousIssuanceValue,
2064
+ nextIssuancePath: input.nextIssuancePath,
2065
+ nextIssuanceValue: input.nextIssuanceValue,
2066
+ nextStateSimfPath: input.nextStateSimfPath,
2067
+ nextAmountSat: input.nextAmountSat,
2068
+ maxFeeSat: input.maxFeeSat,
2069
+ nextOutputHash: input.nextOutputHash,
2070
+ });
2071
+ return {
2072
+ currentArtifact,
2073
+ currentVerification,
2074
+ machineCompiled,
2075
+ machineVerification,
2076
+ nextContractAddress: machineCompiled.compiled.deployment().contractAddress,
2077
+ transitionPayload: machineCompiled.payload,
2078
+ };
2079
+ }
934
2080
  async function buildBondMachineSettlementPlan(sdk, input) {
935
2081
  const currentMachineArtifact = input.currentMachineArtifact
936
2082
  ?? (input.currentMachineArtifactPath ? (await sdk.loadArtifact(input.currentMachineArtifactPath)).artifact : undefined);
@@ -965,6 +2111,79 @@ async function buildBondMachineSettlementPlan(sdk, input) {
965
2111
  nextContractAddressMatchesMachineCommitment: nextCompiled.deployment().contractAddress === machineVerification.expectedNextContractAddress,
966
2112
  };
967
2113
  }
2114
+ async function buildBondScriptBoundMachineSettlementPlan(sdk, input) {
2115
+ const currentMachineArtifact = input.currentMachineArtifact
2116
+ ?? (input.currentMachineArtifactPath ? (await sdk.loadArtifact(input.currentMachineArtifactPath)).artifact : undefined);
2117
+ if (!currentMachineArtifact) {
2118
+ throw new Error("currentMachineArtifactPath or currentMachineArtifact is required");
2119
+ }
2120
+ const machineVerification = await verifyBondScriptBoundSettlementMachineArtifact(sdk, {
2121
+ artifact: currentMachineArtifact,
2122
+ definitionPath: input.definitionPath,
2123
+ definitionValue: input.definitionValue,
2124
+ previousIssuancePath: input.previousIssuancePath,
2125
+ previousIssuanceValue: input.previousIssuanceValue,
2126
+ nextIssuancePath: input.nextIssuancePath,
2127
+ nextIssuanceValue: input.nextIssuanceValue,
2128
+ nextStateSimfPath: input.nextSimfPath,
2129
+ nextAmountSat: input.nextAmountSat,
2130
+ maxFeeSat: input.maxFeeSat,
2131
+ });
2132
+ const definitionValue = (0, bondValidation_1.validateBondDefinition)(JSON.parse(machineVerification.definition.definition.canonicalJson));
2133
+ const nextStateValue = (0, bondValidation_1.validateBondIssuanceState)(JSON.parse(machineVerification.issuance.state.canonicalJson));
2134
+ const nextCompiled = await defineBond(sdk, {
2135
+ definitionPath: input.definitionPath,
2136
+ definitionValue,
2137
+ issuanceValue: nextStateValue,
2138
+ simfPath: input.nextSimfPath,
2139
+ artifactPath: input.nextArtifactPath,
2140
+ });
2141
+ return {
2142
+ currentMachineArtifact,
2143
+ machineVerification,
2144
+ nextCompiled,
2145
+ nextContractAddress: nextCompiled.deployment().contractAddress,
2146
+ transitionPayload: machineVerification.expectedPayload,
2147
+ nextContractAddressMatchesMachineCommitment: nextCompiled.deployment().contractAddress === machineVerification.expectedNextContractAddress,
2148
+ };
2149
+ }
2150
+ async function buildBondDescriptorBoundMachineSettlementPlan(sdk, input) {
2151
+ const currentMachineArtifact = input.currentMachineArtifact
2152
+ ?? (input.currentMachineArtifactPath ? (await sdk.loadArtifact(input.currentMachineArtifactPath)).artifact : undefined);
2153
+ if (!currentMachineArtifact) {
2154
+ throw new Error("currentMachineArtifactPath or currentMachineArtifact is required");
2155
+ }
2156
+ const machineVerification = await verifyBondDescriptorBoundSettlementMachineArtifact(sdk, {
2157
+ artifact: currentMachineArtifact,
2158
+ definitionPath: input.definitionPath,
2159
+ definitionValue: input.definitionValue,
2160
+ previousIssuancePath: input.previousIssuancePath,
2161
+ previousIssuanceValue: input.previousIssuanceValue,
2162
+ nextIssuancePath: input.nextIssuancePath,
2163
+ nextIssuanceValue: input.nextIssuanceValue,
2164
+ nextStateSimfPath: input.nextSimfPath,
2165
+ nextAmountSat: input.nextAmountSat,
2166
+ maxFeeSat: input.maxFeeSat,
2167
+ nextOutputHash: input.nextOutputHash,
2168
+ });
2169
+ const definitionValue = (0, bondValidation_1.validateBondDefinition)(JSON.parse(machineVerification.definition.definition.canonicalJson));
2170
+ const nextStateValue = (0, bondValidation_1.validateBondIssuanceState)(JSON.parse(machineVerification.issuance.state.canonicalJson));
2171
+ const nextCompiled = await defineBond(sdk, {
2172
+ definitionPath: input.definitionPath,
2173
+ definitionValue,
2174
+ issuanceValue: nextStateValue,
2175
+ simfPath: input.nextSimfPath,
2176
+ artifactPath: input.nextArtifactPath,
2177
+ });
2178
+ return {
2179
+ currentMachineArtifact,
2180
+ machineVerification,
2181
+ nextCompiled,
2182
+ nextContractAddress: nextCompiled.deployment().contractAddress,
2183
+ transitionPayload: machineVerification.expectedPayload,
2184
+ nextContractAddressMatchesMachineCommitment: nextCompiled.deployment().contractAddress === machineVerification.expectedNextContractAddress,
2185
+ };
2186
+ }
968
2187
  async function inspectBondStateRollover(sdk, input) {
969
2188
  const plan = await buildBondRolloverPlan(sdk, input);
970
2189
  const contract = sdk.fromArtifact(plan.currentArtifact);
@@ -989,6 +2208,30 @@ async function inspectBondMachineRollover(sdk, input) {
989
2208
  });
990
2209
  return { plan, inspect };
991
2210
  }
2211
+ async function inspectBondScriptBoundMachineRollover(sdk, input) {
2212
+ const plan = await buildBondScriptBoundMachineRolloverPlan(sdk, input);
2213
+ const contract = sdk.fromArtifact(plan.currentArtifact);
2214
+ const inspect = await contract.inspectCall({
2215
+ wallet: input.wallet,
2216
+ toAddress: plan.nextContractAddress,
2217
+ signer: input.signer,
2218
+ feeSat: input.feeSat,
2219
+ utxoPolicy: input.utxoPolicy,
2220
+ });
2221
+ return { plan, inspect };
2222
+ }
2223
+ async function inspectBondDescriptorBoundMachineRollover(sdk, input) {
2224
+ const plan = await buildBondDescriptorBoundMachineRolloverPlan(sdk, input);
2225
+ const contract = sdk.fromArtifact(plan.currentArtifact);
2226
+ const inspect = await contract.inspectCall({
2227
+ wallet: input.wallet,
2228
+ toAddress: plan.nextContractAddress,
2229
+ signer: input.signer,
2230
+ feeSat: input.feeSat,
2231
+ utxoPolicy: input.utxoPolicy,
2232
+ });
2233
+ return { plan, inspect };
2234
+ }
992
2235
  async function inspectBondMachineSettlement(sdk, input) {
993
2236
  const plan = await buildBondMachineSettlementPlan(sdk, input);
994
2237
  const contract = sdk.fromArtifact(plan.currentMachineArtifact);
@@ -1001,6 +2244,76 @@ async function inspectBondMachineSettlement(sdk, input) {
1001
2244
  });
1002
2245
  return { plan, inspect };
1003
2246
  }
2247
+ async function inspectBondScriptBoundMachineSettlement(sdk, input) {
2248
+ const plan = await buildBondScriptBoundMachineSettlementPlan(sdk, input);
2249
+ const contract = sdk.fromArtifact(plan.currentMachineArtifact);
2250
+ const inspect = await contract.inspectCall({
2251
+ wallet: input.wallet,
2252
+ toAddress: plan.nextContractAddress,
2253
+ signer: input.signer,
2254
+ feeSat: input.feeSat,
2255
+ utxoPolicy: input.utxoPolicy,
2256
+ });
2257
+ return { plan, inspect };
2258
+ }
2259
+ async function inspectBondDescriptorBoundMachineSettlement(sdk, input) {
2260
+ const plan = await buildBondDescriptorBoundMachineSettlementPlan(sdk, input);
2261
+ const contract = sdk.fromArtifact(plan.currentMachineArtifact);
2262
+ const inspect = await contract.inspectCall({
2263
+ wallet: input.wallet,
2264
+ toAddress: plan.nextContractAddress,
2265
+ signer: input.signer,
2266
+ feeSat: input.feeSat,
2267
+ utxoPolicy: input.utxoPolicy,
2268
+ });
2269
+ return { plan, inspect };
2270
+ }
2271
+ async function buildBondClosingPlan(sdk, input) {
2272
+ const currentArtifact = input.currentArtifact
2273
+ ?? (input.currentArtifactPath ? (await sdk.loadArtifact(input.currentArtifactPath)).artifact : undefined);
2274
+ if (!currentArtifact) {
2275
+ throw new Error("currentArtifactPath or currentArtifact is required");
2276
+ }
2277
+ const currentVerification = await verifyBond(sdk, {
2278
+ artifact: currentArtifact,
2279
+ definitionPath: input.definitionPath,
2280
+ definitionValue: input.definitionValue,
2281
+ issuancePath: input.redeemedIssuancePath,
2282
+ issuanceValue: input.redeemedIssuanceValue,
2283
+ });
2284
+ const closingCompiled = await compileBondClosingMachine(sdk, {
2285
+ definitionPath: input.definitionPath,
2286
+ definitionValue: input.definitionValue,
2287
+ redeemedIssuancePath: input.redeemedIssuancePath,
2288
+ redeemedIssuanceValue: input.redeemedIssuanceValue,
2289
+ settlementDescriptorPath: input.settlementDescriptorPath,
2290
+ settlementDescriptorValue: input.settlementDescriptorValue,
2291
+ closedAt: input.closedAt,
2292
+ closingReason: input.closingReason,
2293
+ simfPath: input.closedIssuanceSimfPath,
2294
+ artifactPath: input.closingArtifactPath,
2295
+ });
2296
+ const closingVerification = await verifyBondClosing(sdk, {
2297
+ definitionPath: input.definitionPath,
2298
+ definitionValue: input.definitionValue,
2299
+ redeemedIssuancePath: input.redeemedIssuancePath,
2300
+ redeemedIssuanceValue: input.redeemedIssuanceValue,
2301
+ closedIssuanceValue: closingCompiled.closedState,
2302
+ settlementDescriptorPath: input.settlementDescriptorPath,
2303
+ settlementDescriptorValue: input.settlementDescriptorValue,
2304
+ closingDescriptorValue: closingCompiled.closing,
2305
+ });
2306
+ return {
2307
+ currentArtifact,
2308
+ currentVerification,
2309
+ closingCompiled,
2310
+ closingVerification,
2311
+ nextContractAddress: closingCompiled.compiled.deployment().contractAddress,
2312
+ closingDescriptor: closingCompiled.closing,
2313
+ closingHash: closingCompiled.closingHash,
2314
+ closedState: closingCompiled.closedState,
2315
+ };
2316
+ }
1004
2317
  async function executeBondStateRollover(sdk, input) {
1005
2318
  const plan = await buildBondRolloverPlan(sdk, input);
1006
2319
  const contract = sdk.fromArtifact(plan.currentArtifact);
@@ -1027,6 +2340,32 @@ async function executeBondMachineRollover(sdk, input) {
1027
2340
  });
1028
2341
  return { plan, execution };
1029
2342
  }
2343
+ async function executeBondScriptBoundMachineRollover(sdk, input) {
2344
+ const plan = await buildBondScriptBoundMachineRolloverPlan(sdk, input);
2345
+ const contract = sdk.fromArtifact(plan.currentArtifact);
2346
+ const execution = await contract.execute({
2347
+ wallet: input.wallet,
2348
+ toAddress: plan.nextContractAddress,
2349
+ signer: input.signer,
2350
+ feeSat: input.feeSat,
2351
+ utxoPolicy: input.utxoPolicy,
2352
+ broadcast: input.broadcast,
2353
+ });
2354
+ return { plan, execution };
2355
+ }
2356
+ async function executeBondDescriptorBoundMachineRollover(sdk, input) {
2357
+ const plan = await buildBondDescriptorBoundMachineRolloverPlan(sdk, input);
2358
+ const contract = sdk.fromArtifact(plan.currentArtifact);
2359
+ const execution = await contract.execute({
2360
+ wallet: input.wallet,
2361
+ toAddress: plan.nextContractAddress,
2362
+ signer: input.signer,
2363
+ feeSat: input.feeSat,
2364
+ utxoPolicy: input.utxoPolicy,
2365
+ broadcast: input.broadcast,
2366
+ });
2367
+ return { plan, execution };
2368
+ }
1030
2369
  async function executeBondMachineSettlement(sdk, input) {
1031
2370
  const plan = await buildBondMachineSettlementPlan(sdk, input);
1032
2371
  const contract = sdk.fromArtifact(plan.currentMachineArtifact);
@@ -1040,3 +2379,54 @@ async function executeBondMachineSettlement(sdk, input) {
1040
2379
  });
1041
2380
  return { plan, execution };
1042
2381
  }
2382
+ async function executeBondScriptBoundMachineSettlement(sdk, input) {
2383
+ const plan = await buildBondScriptBoundMachineSettlementPlan(sdk, input);
2384
+ const contract = sdk.fromArtifact(plan.currentMachineArtifact);
2385
+ const execution = await contract.execute({
2386
+ wallet: input.wallet,
2387
+ toAddress: plan.nextContractAddress,
2388
+ signer: input.signer,
2389
+ feeSat: input.feeSat,
2390
+ utxoPolicy: input.utxoPolicy,
2391
+ broadcast: input.broadcast,
2392
+ });
2393
+ return { plan, execution };
2394
+ }
2395
+ async function executeBondDescriptorBoundMachineSettlement(sdk, input) {
2396
+ const plan = await buildBondDescriptorBoundMachineSettlementPlan(sdk, input);
2397
+ const contract = sdk.fromArtifact(plan.currentMachineArtifact);
2398
+ const execution = await contract.execute({
2399
+ wallet: input.wallet,
2400
+ toAddress: plan.nextContractAddress,
2401
+ signer: input.signer,
2402
+ feeSat: input.feeSat,
2403
+ utxoPolicy: input.utxoPolicy,
2404
+ broadcast: input.broadcast,
2405
+ });
2406
+ return { plan, execution };
2407
+ }
2408
+ async function inspectBondClosing(sdk, input) {
2409
+ const plan = await buildBondClosingPlan(sdk, input);
2410
+ const contract = sdk.fromArtifact(plan.currentArtifact);
2411
+ const inspect = await contract.inspectCall({
2412
+ wallet: input.wallet,
2413
+ toAddress: plan.nextContractAddress,
2414
+ signer: input.signer,
2415
+ feeSat: input.feeSat,
2416
+ utxoPolicy: input.utxoPolicy,
2417
+ });
2418
+ return { plan, inspect };
2419
+ }
2420
+ async function executeBondClosing(sdk, input) {
2421
+ const plan = await buildBondClosingPlan(sdk, input);
2422
+ const contract = sdk.fromArtifact(plan.currentArtifact);
2423
+ const execution = await contract.execute({
2424
+ wallet: input.wallet,
2425
+ toAddress: plan.nextContractAddress,
2426
+ signer: input.signer,
2427
+ feeSat: input.feeSat,
2428
+ utxoPolicy: input.utxoPolicy,
2429
+ broadcast: input.broadcast,
2430
+ });
2431
+ return { plan, execution };
2432
+ }