@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
@@ -0,0 +1,1375 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.define = define;
7
+ exports.verify = verify;
8
+ exports.load = load;
9
+ exports.verifyStateHistory = verifyStateHistory;
10
+ exports.prepareFunding = prepareFunding;
11
+ exports.verifyFunding = verifyFunding;
12
+ exports.prepareRepayment = prepareRepayment;
13
+ exports.verifyRepayment = verifyRepayment;
14
+ exports.prepareFundingClaim = prepareFundingClaim;
15
+ exports.verifyFundingClaim = verifyFundingClaim;
16
+ exports.inspectFundingClaim = inspectFundingClaim;
17
+ exports.executeFundingClaim = executeFundingClaim;
18
+ exports.prepareRepaymentClaim = prepareRepaymentClaim;
19
+ exports.verifyRepaymentClaim = verifyRepaymentClaim;
20
+ exports.inspectRepaymentClaim = inspectRepaymentClaim;
21
+ exports.executeRepaymentClaim = executeRepaymentClaim;
22
+ exports.prepareWriteOff = prepareWriteOff;
23
+ exports.verifyWriteOff = verifyWriteOff;
24
+ exports.prepareClosing = prepareClosing;
25
+ exports.verifyClosing = verifyClosing;
26
+ exports.exportEvidence = exportEvidence;
27
+ exports.exportFinalityPayload = exportFinalityPayload;
28
+ const node_fs_1 = require("node:fs");
29
+ const node_path_1 = __importDefault(require("node:path"));
30
+ const errors_1 = require("../core/errors");
31
+ const reporting_1 = require("../core/reporting");
32
+ const outputBinding_1 = require("../core/outputBinding");
33
+ const receivableValidation_1 = require("./receivableValidation");
34
+ const RECEIVABLE_VERIFICATION_REPORT_SCHEMA_VERSION = "receivable-verification-report/v1";
35
+ const RECEIVABLE_EVIDENCE_BUNDLE_SCHEMA_VERSION = "receivable-evidence-bundle/v1";
36
+ const RECEIVABLE_FINALITY_PAYLOAD_SCHEMA_VERSION = "receivable-finality-payload/v1";
37
+ function resolveReceivableDocsAsset(filename) {
38
+ const cwdCandidate = node_path_1.default.resolve(process.cwd(), "docs/definitions", filename);
39
+ if ((0, node_fs_1.existsSync)(cwdCandidate))
40
+ return cwdCandidate;
41
+ const bundledCandidate = node_path_1.default.resolve(__dirname, "../docs/definitions", filename);
42
+ if ((0, node_fs_1.existsSync)(bundledCandidate))
43
+ return bundledCandidate;
44
+ return cwdCandidate;
45
+ }
46
+ function satToBtcAmount(sat) {
47
+ return Number((sat / 1e8).toFixed(8));
48
+ }
49
+ function nowIso() {
50
+ return new Date().toISOString();
51
+ }
52
+ function resolveValueOrPath(options) {
53
+ if (options.pathValue)
54
+ return { jsonPath: options.pathValue };
55
+ if (options.objectValue !== undefined)
56
+ return { value: options.objectValue };
57
+ return {};
58
+ }
59
+ async function loadReceivableDefinitionDocument(sdk, input) {
60
+ const source = resolveValueOrPath({
61
+ pathValue: input.definitionPath,
62
+ objectValue: input.definitionValue,
63
+ });
64
+ if (!source.jsonPath && source.value === undefined) {
65
+ throw new errors_1.ValidationError("definitionPath or definitionValue is required", {
66
+ code: "RECEIVABLE_DEFINITION_REQUIRED",
67
+ });
68
+ }
69
+ const descriptor = await sdk.loadDefinition({
70
+ type: "receivable-definition",
71
+ id: "RECEIVABLE-DEFINITION",
72
+ ...source,
73
+ });
74
+ const value = (0, receivableValidation_1.validateReceivableDefinition)(JSON.parse(descriptor.canonicalJson));
75
+ return { descriptor, value, summary: (0, receivableValidation_1.summarizeReceivableDefinition)(value) };
76
+ }
77
+ async function loadReceivableStateDocument(sdk, input) {
78
+ const source = resolveValueOrPath({
79
+ pathValue: input.statePath,
80
+ objectValue: input.stateValue,
81
+ });
82
+ if (!source.jsonPath && source.value === undefined) {
83
+ throw new errors_1.ValidationError("statePath or stateValue is required", {
84
+ code: "RECEIVABLE_STATE_REQUIRED",
85
+ });
86
+ }
87
+ const descriptor = await sdk.loadStateDocument({
88
+ type: "receivable-state",
89
+ id: "RECEIVABLE-STATE",
90
+ ...source,
91
+ });
92
+ const value = (0, receivableValidation_1.validateReceivableState)(JSON.parse(descriptor.canonicalJson));
93
+ return { descriptor, value, summary: (0, receivableValidation_1.summarizeReceivableState)(value) };
94
+ }
95
+ async function loadReceivableStateHistoryDocuments(sdk, input) {
96
+ const results = [];
97
+ for (const statePath of input.stateHistoryPaths ?? []) {
98
+ const descriptor = await sdk.loadStateDocument({
99
+ type: "receivable-state",
100
+ id: "RECEIVABLE-STATE-HISTORY",
101
+ jsonPath: statePath,
102
+ });
103
+ const value = (0, receivableValidation_1.validateReceivableState)(JSON.parse(descriptor.canonicalJson));
104
+ results.push({ descriptor, value, summary: (0, receivableValidation_1.summarizeReceivableState)(value) });
105
+ }
106
+ for (const stateValue of input.stateHistoryValues ?? []) {
107
+ const value = (0, receivableValidation_1.validateReceivableState)(stateValue);
108
+ const descriptor = await sdk.loadStateDocument({
109
+ type: "receivable-state",
110
+ id: value.stateId,
111
+ value,
112
+ });
113
+ results.push({ descriptor, value, summary: (0, receivableValidation_1.summarizeReceivableState)(value) });
114
+ }
115
+ return results;
116
+ }
117
+ async function loadReceivableClosingDocument(sdk, input) {
118
+ const source = resolveValueOrPath({
119
+ pathValue: input.closingPath,
120
+ objectValue: input.closingValue,
121
+ });
122
+ if (source.jsonPath || source.value !== undefined) {
123
+ const descriptor = await sdk.loadStateDocument({
124
+ type: "receivable-closing",
125
+ id: input.closingValue?.closingId ?? input.closingId ?? "REC-CLOSE-001",
126
+ ...source,
127
+ });
128
+ const value = (0, receivableValidation_1.validateReceivableClosingDescriptor)(JSON.parse(descriptor.canonicalJson));
129
+ return { descriptor, value, summary: (0, receivableValidation_1.summarizeReceivableClosingDescriptor)(value) };
130
+ }
131
+ if (!input.latestStateValue || !input.closingId || !input.closedAt) {
132
+ throw new errors_1.ValidationError("closingPath/closingValue or latestState + closingId + closedAt is required", { code: "RECEIVABLE_CLOSING_REQUIRED" });
133
+ }
134
+ const value = (0, receivableValidation_1.buildReceivableClosingDescriptor)({
135
+ closingId: input.closingId,
136
+ latestState: input.latestStateValue,
137
+ closedAt: input.closedAt,
138
+ ...(input.closingReason ? { closingReason: input.closingReason } : {}),
139
+ });
140
+ const descriptor = await sdk.loadStateDocument({
141
+ type: "receivable-closing",
142
+ id: value.closingId,
143
+ value,
144
+ });
145
+ return { descriptor, value, summary: (0, receivableValidation_1.summarizeReceivableClosingDescriptor)(value) };
146
+ }
147
+ function assertLatestStateMatchesHistoryTip(input) {
148
+ if (!input.latestState || input.history.length === 0)
149
+ return;
150
+ const historyTip = input.history.at(-1);
151
+ if (!historyTip)
152
+ return;
153
+ if (historyTip.summary.hash !== input.latestState.summary.hash) {
154
+ throw new errors_1.ValidationError("latest receivable state must match the tip of the provided state history", {
155
+ code: "RECEIVABLE_HISTORY_TIP_MISMATCH",
156
+ });
157
+ }
158
+ }
159
+ function validateReceivablePayoutDescriptor(descriptor) {
160
+ if (!descriptor.receiverAddress || descriptor.receiverAddress.trim().length === 0) {
161
+ throw new errors_1.ValidationError("receiverAddress must be a non-empty string", {
162
+ code: "RECEIVABLE_PAYOUT_RECEIVER_REQUIRED",
163
+ });
164
+ }
165
+ if (!Number.isInteger(descriptor.amountSat) || descriptor.amountSat <= 0) {
166
+ throw new errors_1.ValidationError("amountSat must be a positive integer", {
167
+ code: "RECEIVABLE_PAYOUT_AMOUNT_INVALID",
168
+ });
169
+ }
170
+ if (!descriptor.assetId || descriptor.assetId.trim().length === 0) {
171
+ throw new errors_1.ValidationError("assetId must be a non-empty string", {
172
+ code: "RECEIVABLE_PAYOUT_ASSET_REQUIRED",
173
+ });
174
+ }
175
+ if (!Number.isInteger(descriptor.feeIndex) || descriptor.feeIndex < 0) {
176
+ throw new errors_1.ValidationError("feeIndex must be a non-negative integer", {
177
+ code: "RECEIVABLE_PAYOUT_FEE_INDEX_INVALID",
178
+ });
179
+ }
180
+ if (!Number.isInteger(descriptor.nextOutputIndex) || descriptor.nextOutputIndex < 0) {
181
+ throw new errors_1.ValidationError("nextOutputIndex must be a non-negative integer", {
182
+ code: "RECEIVABLE_PAYOUT_NEXT_OUTPUT_INDEX_INVALID",
183
+ });
184
+ }
185
+ if (!Number.isInteger(descriptor.maxFeeSat) || descriptor.maxFeeSat < 0) {
186
+ throw new errors_1.ValidationError("maxFeeSat must be a non-negative integer", {
187
+ code: "RECEIVABLE_PAYOUT_MAX_FEE_INVALID",
188
+ });
189
+ }
190
+ if (!["none", "script-bound", "descriptor-bound"].includes(descriptor.outputBindingMode)) {
191
+ throw new errors_1.ValidationError("outputBindingMode must be none, script-bound, or descriptor-bound", {
192
+ code: "RECEIVABLE_PAYOUT_BINDING_MODE_INVALID",
193
+ });
194
+ }
195
+ if (descriptor.requestedOutputBindingMode
196
+ && !["none", "script-bound", "descriptor-bound"].includes(descriptor.requestedOutputBindingMode)) {
197
+ throw new errors_1.ValidationError("requestedOutputBindingMode must be none, script-bound, or descriptor-bound", {
198
+ code: "RECEIVABLE_PAYOUT_REQUESTED_BINDING_MODE_INVALID",
199
+ });
200
+ }
201
+ if (descriptor.nextOutputHash && !/^[0-9a-f]{64}$/i.test(descriptor.nextOutputHash)) {
202
+ throw new errors_1.ValidationError("nextOutputHash must be a 64-character hex string", {
203
+ code: "RECEIVABLE_PAYOUT_OUTPUT_HASH_INVALID",
204
+ });
205
+ }
206
+ if (descriptor.nextOutputScriptHash && !/^[0-9a-f]{64}$/i.test(descriptor.nextOutputScriptHash)) {
207
+ throw new errors_1.ValidationError("nextOutputScriptHash must be a 64-character hex string", {
208
+ code: "RECEIVABLE_PAYOUT_OUTPUT_SCRIPT_HASH_INVALID",
209
+ });
210
+ }
211
+ descriptor.rawOutput = (0, outputBinding_1.normalizeOutputRawFields)(descriptor.rawOutput);
212
+ descriptor.outputForm = (0, outputBinding_1.normalizeOutputForm)(descriptor.outputForm);
213
+ descriptor.requestedOutputBindingMode = descriptor.requestedOutputBindingMode ?? descriptor.outputBindingMode;
214
+ return descriptor;
215
+ }
216
+ function buildBindingModeWitnessValue(mode) {
217
+ return mode === "descriptor-bound" ? "0x01" : mode === "script-bound" ? "0x02" : "0x03";
218
+ }
219
+ function buildReceivableClaimWitness(descriptor) {
220
+ return {
221
+ values: {
222
+ EXPECTED_PAYOUT_OUTPUT_HASH: {
223
+ type: "u256",
224
+ value: `0x${descriptor.nextOutputHash ?? "0000000000000000000000000000000000000000000000000000000000000000"}`,
225
+ },
226
+ EXPECTED_PAYOUT_OUTPUT_SCRIPT_HASH: {
227
+ type: "u256",
228
+ value: `0x${descriptor.nextOutputScriptHash ?? "0000000000000000000000000000000000000000000000000000000000000000"}`,
229
+ },
230
+ OUTPUT_BINDING_MODE: {
231
+ type: "u8",
232
+ value: buildBindingModeWitnessValue(descriptor.outputBindingMode),
233
+ },
234
+ },
235
+ };
236
+ }
237
+ async function buildReceivablePayoutDescriptor(sdk, input) {
238
+ const nextScriptPubKeyHex = await (0, outputBinding_1.getScriptPubKeyHexViaRpc)(sdk, input.receiverAddress);
239
+ const nextOutputScriptHash = (0, outputBinding_1.hashHexBytes)(nextScriptPubKeyHex);
240
+ const requestedBindingMode = input.outputBindingMode ?? "descriptor-bound";
241
+ const outputForm = (0, outputBinding_1.normalizeOutputForm)(input.outputForm);
242
+ const rawOutput = (0, outputBinding_1.normalizeOutputRawFields)(input.rawOutput);
243
+ const rawOutputAnalysis = (0, outputBinding_1.analyzeOutputRawFields)(rawOutput);
244
+ const explicitAssetHex = requestedBindingMode !== "none" && (0, outputBinding_1.isExplicitV1OutputForm)(outputForm)
245
+ ? await (0, outputBinding_1.resolveExplicitAssetHex)(sdk, input.assetId)
246
+ : undefined;
247
+ const autoDerivedNextOutputHash = requestedBindingMode === "descriptor-bound" && !input.nextOutputHash
248
+ ? rawOutputAnalysis.valid && rawOutputAnalysis.normalized
249
+ ? (0, outputBinding_1.computeRawOutputV1Hash)(rawOutputAnalysis.normalized)
250
+ : explicitAssetHex
251
+ ? (0, outputBinding_1.computeExplicitV1OutputHash)({
252
+ assetHex: explicitAssetHex,
253
+ nextAmountSat: input.amountSat,
254
+ nextOutputScriptHash,
255
+ })
256
+ : undefined
257
+ : undefined;
258
+ const nextOutputHash = input.nextOutputHash ?? autoDerivedNextOutputHash;
259
+ const bindingResolution = (0, outputBinding_1.resolveOutputBindingDecision)({
260
+ requestedBindingMode,
261
+ nextOutputHash,
262
+ nextOutputScriptHash,
263
+ autoDerivedNextOutputHash: Boolean(autoDerivedNextOutputHash && !input.nextOutputHash),
264
+ explicitAssetSupported: Boolean(explicitAssetHex),
265
+ outputForm,
266
+ rawOutput,
267
+ });
268
+ const descriptor = validateReceivablePayoutDescriptor({
269
+ receiverAddress: input.receiverAddress,
270
+ nextOutputHash: bindingResolution.outputBindingMode === "descriptor-bound" ? nextOutputHash : undefined,
271
+ nextOutputScriptHash: bindingResolution.outputBindingMode !== "none" ? nextOutputScriptHash : undefined,
272
+ amountSat: input.amountSat,
273
+ assetId: input.assetId,
274
+ requestedOutputBindingMode: requestedBindingMode,
275
+ outputForm,
276
+ rawOutput,
277
+ feeIndex: input.feeIndex ?? 1,
278
+ nextOutputIndex: input.nextOutputIndex ?? 0,
279
+ maxFeeSat: input.maxFeeSat ?? 100,
280
+ outputBindingMode: bindingResolution.outputBindingMode,
281
+ });
282
+ const bindingInputs = {
283
+ assetId: descriptor.assetId,
284
+ assetForm: descriptor.outputForm?.assetForm ?? "explicit",
285
+ amountForm: descriptor.outputForm?.amountForm ?? "explicit",
286
+ nonceForm: descriptor.outputForm?.nonceForm ?? "null",
287
+ rangeProofForm: descriptor.outputForm?.rangeProofForm ?? "empty",
288
+ nextAmountSat: descriptor.amountSat,
289
+ nextOutputIndex: descriptor.nextOutputIndex,
290
+ feeIndex: descriptor.feeIndex,
291
+ maxFeeSat: descriptor.maxFeeSat,
292
+ ...(rawOutputAnalysis.valid && rawOutputAnalysis.normalized
293
+ ? {
294
+ rawOutputComponents: {
295
+ scriptPubKey: rawOutputAnalysis.normalized.scriptComponentSource,
296
+ rangeProof: rawOutputAnalysis.normalized.rangeProofComponentSource,
297
+ },
298
+ }
299
+ : {}),
300
+ };
301
+ return {
302
+ descriptor,
303
+ supportedForm: bindingResolution.supportedForm,
304
+ autoDerivedNextOutputHash: bindingResolution.autoDerived,
305
+ reasonCode: bindingResolution.reasonCode,
306
+ fallbackReason: bindingResolution.fallbackReason,
307
+ bindingInputs,
308
+ };
309
+ }
310
+ function buildReceivableStateLineageTrust(checks) {
311
+ const identityConsistent = checks.receivableIdConsistent
312
+ && checks.originatorConsistent
313
+ && checks.debtorConsistent
314
+ && checks.currencyConsistent
315
+ && checks.controllerConsistent
316
+ && checks.faceValueConsistent;
317
+ return {
318
+ ...(0, reporting_1.buildLineageTrustBase)({
319
+ lineageKind: "state-history",
320
+ chainLength: checks.chainLength,
321
+ latestOrdinal: Math.max(0, checks.chainLength - 1),
322
+ allHashLinksVerified: checks.allPreviousStateHashMatch,
323
+ identityConsistent,
324
+ fullLineageVerified: checks.fullHistoryVerified,
325
+ }),
326
+ latestStatus: checks.latestStatus,
327
+ startsAtGenesis: checks.startsAtGenesis,
328
+ receivableIdConsistent: checks.receivableIdConsistent,
329
+ originatorConsistent: checks.originatorConsistent,
330
+ debtorConsistent: checks.debtorConsistent,
331
+ currencyConsistent: checks.currencyConsistent,
332
+ controllerConsistent: checks.controllerConsistent,
333
+ faceValueConsistent: checks.faceValueConsistent,
334
+ allPreviousStateHashMatch: checks.allPreviousStateHashMatch,
335
+ allArithmeticValid: checks.allArithmeticValid,
336
+ allStatusProgressionValid: checks.allStatusProgressionValid,
337
+ fullHistoryVerified: checks.fullHistoryVerified,
338
+ };
339
+ }
340
+ async function requireReceivableArtifact(sdk, input) {
341
+ const artifact = input.artifact ?? (input.artifactPath ? (await sdk.loadArtifact(input.artifactPath)).artifact : undefined);
342
+ if (!artifact) {
343
+ throw new errors_1.ValidationError("artifactPath or artifact is required", {
344
+ code: "RECEIVABLE_ARTIFACT_REQUIRED",
345
+ });
346
+ }
347
+ return artifact;
348
+ }
349
+ function buildReceivableClaimTrust(input) {
350
+ const bindingMode = input.payout?.descriptor.outputBindingMode ?? "none";
351
+ return {
352
+ ...input.checks,
353
+ generated: input.generated,
354
+ claimantXonlyCommitted: input.claimantXonlyCommitted,
355
+ bindingMode,
356
+ requestedMode: input.payout?.descriptor.requestedOutputBindingMode,
357
+ supportedForm: input.payout?.supportedForm ?? "unsupported",
358
+ reasonCode: input.payout?.reasonCode
359
+ ?? (bindingMode === "descriptor-bound"
360
+ ? "OK_MANUAL_HASH"
361
+ : bindingMode === "script-bound"
362
+ ? "OK_SCRIPT_BOUND"
363
+ : "OK_NONE"),
364
+ nextReceiverRuntimeCommitted: bindingMode !== "none",
365
+ nextOutputHashRuntimeBound: bindingMode === "descriptor-bound",
366
+ nextOutputScriptRuntimeBound: bindingMode !== "none",
367
+ amountRuntimeBound: bindingMode === "descriptor-bound",
368
+ autoDerived: input.payout?.autoDerivedNextOutputHash,
369
+ fallbackReason: input.payout?.fallbackReason,
370
+ bindingInputs: input.payout?.bindingInputs,
371
+ fullClaimVerified: input.checks.fullClaimVerified && input.claimantXonlyCommitted,
372
+ };
373
+ }
374
+ function buildReceivableReport(input) {
375
+ return {
376
+ schemaVersion: RECEIVABLE_VERIFICATION_REPORT_SCHEMA_VERSION,
377
+ receivableTrust: {
378
+ ...input.crossChecks,
379
+ statusValid: true,
380
+ },
381
+ ...(input.transitionTrust ? { transitionTrust: input.transitionTrust } : {}),
382
+ ...(input.closingTrust ? { closingTrust: input.closingTrust } : {}),
383
+ ...(input.fundingClaimTrust ? { fundingClaimTrust: input.fundingClaimTrust } : {}),
384
+ ...(input.repaymentClaimTrust ? { repaymentClaimTrust: input.repaymentClaimTrust } : {}),
385
+ ...(input.lineageChecks ? { stateLineageTrust: buildReceivableStateLineageTrust(input.lineageChecks) } : {}),
386
+ };
387
+ }
388
+ async function define(sdk, input) {
389
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
390
+ return {
391
+ ok: true,
392
+ definition: definition.descriptor,
393
+ definitionValue: definition.value,
394
+ summary: definition.summary,
395
+ };
396
+ }
397
+ async function verify(sdk, input) {
398
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
399
+ const state = await loadReceivableStateDocument(sdk, input);
400
+ const crossChecks = (0, receivableValidation_1.validateReceivableCrossChecks)(definition.value, state.value);
401
+ const report = buildReceivableReport({ crossChecks });
402
+ return {
403
+ verified: Object.values(crossChecks).every(Boolean),
404
+ definition: definition.descriptor,
405
+ definitionValue: definition.value,
406
+ definitionSummary: definition.summary,
407
+ state: state.descriptor,
408
+ stateValue: state.value,
409
+ stateSummary: state.summary,
410
+ crossChecks,
411
+ report,
412
+ trustSummary: (0, reporting_1.buildVerificationTrustSummary)({
413
+ bindingMode: "none",
414
+ }),
415
+ };
416
+ }
417
+ async function load(sdk, input) {
418
+ const verification = await verify(sdk, input);
419
+ return {
420
+ definition: verification.definition,
421
+ definitionValue: verification.definitionValue,
422
+ definitionSummary: verification.definitionSummary,
423
+ state: verification.state,
424
+ stateValue: verification.stateValue,
425
+ stateSummary: verification.stateSummary,
426
+ crossChecks: verification.crossChecks,
427
+ report: verification.report,
428
+ trustSummary: verification.trustSummary,
429
+ };
430
+ }
431
+ async function verifyStateHistory(sdk, input) {
432
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
433
+ const stateHistory = await loadReceivableStateHistoryDocuments(sdk, input);
434
+ const latest = stateHistory.at(-1);
435
+ if (!latest) {
436
+ throw new errors_1.ValidationError("stateHistoryPaths or stateHistoryValues must contain at least one state", {
437
+ code: "RECEIVABLE_STATE_HISTORY_REQUIRED",
438
+ });
439
+ }
440
+ const crossChecks = (0, receivableValidation_1.validateReceivableCrossChecks)(definition.value, latest.value);
441
+ const checks = (0, receivableValidation_1.verifyReceivableStateHistory)({
442
+ history: stateHistory.map((entry) => entry.value),
443
+ });
444
+ const lineageTrust = buildReceivableStateLineageTrust(checks);
445
+ const report = buildReceivableReport({
446
+ crossChecks,
447
+ lineageChecks: checks,
448
+ });
449
+ return {
450
+ verified: checks.fullHistoryVerified && Object.values(crossChecks).every(Boolean),
451
+ definition: definition.descriptor,
452
+ definitionValue: definition.value,
453
+ definitionSummary: definition.summary,
454
+ latestState: latest.descriptor,
455
+ latestStateValue: latest.value,
456
+ latestStateSummary: latest.summary,
457
+ stateHistory: stateHistory.map((entry) => entry.descriptor),
458
+ stateHistoryValues: stateHistory.map((entry) => entry.value),
459
+ stateHistorySummaries: stateHistory.map((entry) => entry.summary),
460
+ checks,
461
+ report,
462
+ trustSummary: (0, reporting_1.buildVerificationTrustSummary)({
463
+ bindingMode: "none",
464
+ lineageTrust,
465
+ }),
466
+ };
467
+ }
468
+ async function loadPreviousAndNextReceivableStates(sdk, input) {
469
+ const previous = await loadReceivableStateDocument(sdk, {
470
+ statePath: input.previousStatePath,
471
+ stateValue: input.previousStateValue,
472
+ });
473
+ const next = await loadReceivableStateDocument(sdk, {
474
+ statePath: input.nextStatePath,
475
+ stateValue: input.nextStateValue,
476
+ });
477
+ return { previous, next };
478
+ }
479
+ function buildTransitionVerificationResult(input) {
480
+ const crossChecks = (0, receivableValidation_1.validateReceivableCrossChecks)(input.definition.value, input.next.value);
481
+ const report = buildReceivableReport({
482
+ crossChecks,
483
+ transitionTrust: input.transitionTrust,
484
+ });
485
+ return {
486
+ verified: input.transitionTrust.fullTransitionVerified && Object.values(crossChecks).every(Boolean),
487
+ definition: input.definition.descriptor,
488
+ definitionValue: input.definition.value,
489
+ definitionSummary: input.definition.summary,
490
+ previousState: input.previous.descriptor,
491
+ previousStateValue: input.previous.value,
492
+ previousStateSummary: input.previous.summary,
493
+ nextState: input.next.descriptor,
494
+ nextStateValue: input.next.value,
495
+ nextStateSummary: input.next.summary,
496
+ report,
497
+ trustSummary: (0, reporting_1.buildVerificationTrustSummary)({
498
+ bindingMode: "none",
499
+ }),
500
+ };
501
+ }
502
+ async function prepareFunding(sdk, input) {
503
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
504
+ const previous = await loadReceivableStateDocument(sdk, {
505
+ statePath: input.previousStatePath,
506
+ stateValue: input.previousStateValue,
507
+ });
508
+ const next = input.nextStatePath || input.nextStateValue
509
+ ? await loadReceivableStateDocument(sdk, {
510
+ statePath: input.nextStatePath,
511
+ stateValue: input.nextStateValue,
512
+ })
513
+ : await loadReceivableStateDocument(sdk, {
514
+ stateValue: (0, receivableValidation_1.buildFundedReceivableState)({
515
+ previous: previous.value,
516
+ stateId: input.stateId ?? `${previous.value.receivableId}-FUNDED`,
517
+ holderEntityId: input.holderEntityId ?? previous.value.holderEntityId,
518
+ fundedAt: input.fundedAt ?? new Date().toISOString(),
519
+ }),
520
+ });
521
+ const transitionTrust = (0, receivableValidation_1.validateReceivableFundingTransition)(previous.value, next.value);
522
+ return buildTransitionVerificationResult({
523
+ definition,
524
+ previous,
525
+ next,
526
+ transitionTrust,
527
+ });
528
+ }
529
+ async function loadReceivableFundingClaimDocument(sdk, input) {
530
+ const source = resolveValueOrPath({
531
+ pathValue: input.fundingClaimPath,
532
+ objectValue: input.fundingClaimValue,
533
+ });
534
+ if (source.jsonPath || source.value !== undefined) {
535
+ const descriptor = await sdk.loadStateDocument({
536
+ type: "receivable-funding-claim",
537
+ id: input.fundingClaimValue?.claimId ?? input.claimId ?? "REC-FUNDING-CLAIM-001",
538
+ ...source,
539
+ });
540
+ const value = (0, receivableValidation_1.validateReceivableFundingClaimDescriptor)(JSON.parse(descriptor.canonicalJson));
541
+ return { descriptor, value, summary: (0, receivableValidation_1.summarizeReceivableFundingClaimDescriptor)(value) };
542
+ }
543
+ if (!input.currentStateValue || !input.claimId) {
544
+ throw new errors_1.ValidationError("fundingClaimPath/fundingClaimValue or currentStateValue + claimId is required", { code: "RECEIVABLE_FUNDING_CLAIM_REQUIRED" });
545
+ }
546
+ const value = (0, receivableValidation_1.buildReceivableFundingClaimDescriptor)({
547
+ claimId: input.claimId,
548
+ currentState: input.currentStateValue,
549
+ payerEntityId: input.payerEntityId,
550
+ payeeEntityId: input.payeeEntityId,
551
+ claimantXonly: input.claimantXonly,
552
+ amountSat: input.amountSat,
553
+ eventTimestamp: input.eventTimestamp,
554
+ });
555
+ const descriptor = await sdk.loadStateDocument({
556
+ type: "receivable-funding-claim",
557
+ id: value.claimId,
558
+ value,
559
+ });
560
+ return { descriptor, value, summary: (0, receivableValidation_1.summarizeReceivableFundingClaimDescriptor)(value) };
561
+ }
562
+ async function loadReceivableRepaymentClaimDocument(sdk, input) {
563
+ const source = resolveValueOrPath({
564
+ pathValue: input.repaymentClaimPath,
565
+ objectValue: input.repaymentClaimValue,
566
+ });
567
+ if (source.jsonPath || source.value !== undefined) {
568
+ const descriptor = await sdk.loadStateDocument({
569
+ type: "receivable-repayment-claim",
570
+ id: input.repaymentClaimValue?.claimId ?? input.claimId ?? "REC-REPAYMENT-CLAIM-001",
571
+ ...source,
572
+ });
573
+ const value = (0, receivableValidation_1.validateReceivableRepaymentClaimDescriptor)(JSON.parse(descriptor.canonicalJson));
574
+ return { descriptor, value, summary: (0, receivableValidation_1.summarizeReceivableRepaymentClaimDescriptor)(value) };
575
+ }
576
+ if (!input.currentStateValue || !input.claimId) {
577
+ throw new errors_1.ValidationError("repaymentClaimPath/repaymentClaimValue or currentStateValue + claimId is required", { code: "RECEIVABLE_REPAYMENT_CLAIM_REQUIRED" });
578
+ }
579
+ const value = (0, receivableValidation_1.buildReceivableRepaymentClaimDescriptor)({
580
+ claimId: input.claimId,
581
+ currentState: input.currentStateValue,
582
+ payerEntityId: input.payerEntityId,
583
+ payeeEntityId: input.payeeEntityId,
584
+ claimantXonly: input.claimantXonly,
585
+ amountSat: input.amountSat,
586
+ eventTimestamp: input.eventTimestamp,
587
+ });
588
+ const descriptor = await sdk.loadStateDocument({
589
+ type: "receivable-repayment-claim",
590
+ id: value.claimId,
591
+ value,
592
+ });
593
+ return { descriptor, value, summary: (0, receivableValidation_1.summarizeReceivableRepaymentClaimDescriptor)(value) };
594
+ }
595
+ async function compileFundingClaimContract(sdk, input) {
596
+ return sdk.compileFromFile({
597
+ simfPath: input.simfPath ?? resolveReceivableDocsAsset("receivable-funding-claim.simf"),
598
+ templateVars: {
599
+ CLAIMANT_XONLY: input.claim.claimantXonly,
600
+ },
601
+ definition: {
602
+ type: "receivable-definition",
603
+ id: input.definition.receivableId,
604
+ value: input.definition,
605
+ anchorMode: "on-chain-constant-committed",
606
+ },
607
+ state: {
608
+ type: "receivable-funding-claim",
609
+ id: input.claim.claimId,
610
+ value: input.claim,
611
+ anchorMode: "on-chain-constant-committed",
612
+ },
613
+ artifactPath: input.artifactPath,
614
+ });
615
+ }
616
+ async function compileRepaymentClaimContract(sdk, input) {
617
+ return sdk.compileFromFile({
618
+ simfPath: input.simfPath ?? resolveReceivableDocsAsset("receivable-repayment-claim.simf"),
619
+ templateVars: {
620
+ CLAIMANT_XONLY: input.claim.claimantXonly,
621
+ },
622
+ definition: {
623
+ type: "receivable-definition",
624
+ id: input.definition.receivableId,
625
+ value: input.definition,
626
+ anchorMode: "on-chain-constant-committed",
627
+ },
628
+ state: {
629
+ type: "receivable-repayment-claim",
630
+ id: input.claim.claimId,
631
+ value: input.claim,
632
+ anchorMode: "on-chain-constant-committed",
633
+ },
634
+ artifactPath: input.artifactPath,
635
+ });
636
+ }
637
+ async function verifyFunding(sdk, input) {
638
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
639
+ const { previous, next } = await loadPreviousAndNextReceivableStates(sdk, input);
640
+ const transitionTrust = (0, receivableValidation_1.validateReceivableFundingTransition)(previous.value, next.value);
641
+ return buildTransitionVerificationResult({
642
+ definition,
643
+ previous,
644
+ next,
645
+ transitionTrust,
646
+ });
647
+ }
648
+ async function prepareRepayment(sdk, input) {
649
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
650
+ const previous = await loadReceivableStateDocument(sdk, {
651
+ statePath: input.previousStatePath,
652
+ stateValue: input.previousStateValue,
653
+ });
654
+ const next = input.nextStatePath || input.nextStateValue
655
+ ? await loadReceivableStateDocument(sdk, {
656
+ statePath: input.nextStatePath,
657
+ stateValue: input.nextStateValue,
658
+ })
659
+ : await loadReceivableStateDocument(sdk, {
660
+ stateValue: (0, receivableValidation_1.applyReceivableRepayment)({
661
+ previous: previous.value,
662
+ stateId: input.stateId ?? `${previous.value.receivableId}-REPAY-${previous.value.repaidAmount + (input.amount ?? 0)}`,
663
+ amount: input.amount ?? previous.value.outstandingAmount,
664
+ repaidAt: input.repaidAt ?? new Date().toISOString(),
665
+ }),
666
+ });
667
+ const transitionTrust = (0, receivableValidation_1.validateReceivableRepaymentTransition)(previous.value, next.value);
668
+ return buildTransitionVerificationResult({
669
+ definition,
670
+ previous,
671
+ next,
672
+ transitionTrust,
673
+ });
674
+ }
675
+ async function verifyRepayment(sdk, input) {
676
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
677
+ const { previous, next } = await loadPreviousAndNextReceivableStates(sdk, input);
678
+ const transitionTrust = (0, receivableValidation_1.validateReceivableRepaymentTransition)(previous.value, next.value);
679
+ return buildTransitionVerificationResult({
680
+ definition,
681
+ previous,
682
+ next,
683
+ transitionTrust,
684
+ });
685
+ }
686
+ function buildClaimVerificationResult(input) {
687
+ return {
688
+ verified: input.verified,
689
+ artifact: input.artifact,
690
+ artifactVerification: input.artifactVerification,
691
+ definition: input.definition.descriptor,
692
+ definitionValue: input.definition.value,
693
+ definitionSummary: input.definition.summary,
694
+ currentState: input.currentState.descriptor,
695
+ currentStateValue: input.currentState.value,
696
+ currentStateSummary: input.currentState.summary,
697
+ ...(input.stateHistory && input.stateHistory.length > 0
698
+ ? {
699
+ stateHistory: input.stateHistory.map((entry) => entry.descriptor),
700
+ stateHistoryValues: input.stateHistory.map((entry) => entry.value),
701
+ stateHistorySummaries: input.stateHistory.map((entry) => entry.summary),
702
+ }
703
+ : {}),
704
+ claim: input.claim.descriptor,
705
+ claimValue: input.claim.value,
706
+ claimSummary: input.claim.summary,
707
+ report: input.report,
708
+ trustSummary: (0, reporting_1.buildVerificationTrustSummary)({
709
+ bindingMode: input.report.fundingClaimTrust?.bindingMode
710
+ ?? input.report.repaymentClaimTrust?.bindingMode
711
+ ?? "none",
712
+ ...(input.report.stateLineageTrust ? { lineageTrust: input.report.stateLineageTrust } : {}),
713
+ ...(input.artifactVerification?.definition?.trust ? { definitionTrust: input.artifactVerification.definition.trust } : {}),
714
+ ...(input.artifactVerification?.state?.trust ? { stateTrust: input.artifactVerification.state.trust } : {}),
715
+ }),
716
+ };
717
+ }
718
+ async function prepareFundingClaim(sdk, input) {
719
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
720
+ const currentState = await loadReceivableStateDocument(sdk, {
721
+ statePath: input.currentStatePath,
722
+ stateValue: input.currentStateValue,
723
+ });
724
+ const history = input.stateHistoryPaths || input.stateHistoryValues
725
+ ? await loadReceivableStateHistoryDocuments(sdk, input)
726
+ : [];
727
+ assertLatestStateMatchesHistoryTip({ latestState: currentState, history });
728
+ const claim = await loadReceivableFundingClaimDocument(sdk, {
729
+ fundingClaimPath: input.fundingClaimPath,
730
+ fundingClaimValue: input.fundingClaimValue,
731
+ currentStateValue: currentState.value,
732
+ claimId: input.claimId ?? `${currentState.value.receivableId}-FUNDING-CLAIM`,
733
+ payerEntityId: input.payerEntityId,
734
+ payeeEntityId: input.payeeEntityId,
735
+ claimantXonly: input.claimantXonly,
736
+ amountSat: input.amountSat,
737
+ eventTimestamp: input.eventTimestamp,
738
+ });
739
+ const crossChecks = (0, receivableValidation_1.validateReceivableCrossChecks)(definition.value, currentState.value);
740
+ const lineageChecks = history.length > 0
741
+ ? (0, receivableValidation_1.verifyReceivableStateHistory)({ history: history.map((entry) => entry.value) })
742
+ : undefined;
743
+ const claimChecks = (0, receivableValidation_1.validateReceivableFundingClaimAgainstState)({
744
+ currentState: currentState.value,
745
+ claim: claim.value,
746
+ });
747
+ const report = buildReceivableReport({
748
+ crossChecks,
749
+ ...(lineageChecks ? { lineageChecks } : {}),
750
+ fundingClaimTrust: buildReceivableClaimTrust({
751
+ generated: !input.fundingClaimPath && !input.fundingClaimValue,
752
+ claimantXonlyCommitted: true,
753
+ checks: claimChecks,
754
+ }),
755
+ });
756
+ const compiled = await compileFundingClaimContract(sdk, {
757
+ definition: definition.value,
758
+ claim: claim.value,
759
+ simfPath: input.simfPath,
760
+ artifactPath: input.artifactPath,
761
+ });
762
+ return {
763
+ ...buildClaimVerificationResult({
764
+ verified: report.fundingClaimTrust?.fullClaimVerified === true && Object.values(crossChecks).every(Boolean),
765
+ definition,
766
+ currentState,
767
+ stateHistory: history,
768
+ claim,
769
+ report,
770
+ }),
771
+ compiled,
772
+ };
773
+ }
774
+ async function verifyFundingClaim(sdk, input) {
775
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
776
+ const currentState = await loadReceivableStateDocument(sdk, {
777
+ statePath: input.currentStatePath,
778
+ stateValue: input.currentStateValue,
779
+ });
780
+ const history = input.stateHistoryPaths || input.stateHistoryValues
781
+ ? await loadReceivableStateHistoryDocuments(sdk, input)
782
+ : [];
783
+ assertLatestStateMatchesHistoryTip({ latestState: currentState, history });
784
+ const claim = await loadReceivableFundingClaimDocument(sdk, {
785
+ fundingClaimPath: input.fundingClaimPath,
786
+ fundingClaimValue: input.fundingClaimValue,
787
+ });
788
+ const crossChecks = (0, receivableValidation_1.validateReceivableCrossChecks)(definition.value, currentState.value);
789
+ const lineageChecks = history.length > 0
790
+ ? (0, receivableValidation_1.verifyReceivableStateHistory)({ history: history.map((entry) => entry.value) })
791
+ : undefined;
792
+ const claimChecks = (0, receivableValidation_1.validateReceivableFundingClaimAgainstState)({
793
+ currentState: currentState.value,
794
+ claim: claim.value,
795
+ });
796
+ const artifact = input.artifact ?? (input.artifactPath ? (await sdk.loadArtifact(input.artifactPath)).artifact : undefined);
797
+ const definitionVerification = artifact
798
+ ? await sdk.verifyDefinitionAgainstArtifact({
799
+ artifact,
800
+ type: "receivable-definition",
801
+ id: definition.value.receivableId,
802
+ value: definition.value,
803
+ })
804
+ : undefined;
805
+ const stateVerification = artifact
806
+ ? await sdk.verifyStateAgainstArtifact({
807
+ artifact,
808
+ type: "receivable-funding-claim",
809
+ id: claim.value.claimId,
810
+ value: claim.value,
811
+ })
812
+ : undefined;
813
+ const claimantXonlyCommitted = artifact
814
+ ? String(artifact.source.templateVars?.CLAIMANT_XONLY ?? "").toLowerCase() === claim.value.claimantXonly.toLowerCase()
815
+ : true;
816
+ const report = buildReceivableReport({
817
+ crossChecks,
818
+ ...(lineageChecks ? { lineageChecks } : {}),
819
+ fundingClaimTrust: buildReceivableClaimTrust({
820
+ generated: false,
821
+ claimantXonlyCommitted,
822
+ checks: claimChecks,
823
+ }),
824
+ });
825
+ const verified = report.fundingClaimTrust?.fullClaimVerified === true
826
+ && Object.values(crossChecks).every(Boolean)
827
+ && (!definitionVerification || definitionVerification.ok)
828
+ && (!stateVerification || stateVerification.ok);
829
+ return buildClaimVerificationResult({
830
+ verified,
831
+ definition,
832
+ currentState,
833
+ stateHistory: history,
834
+ claim,
835
+ artifact,
836
+ artifactVerification: artifact && (definitionVerification || stateVerification)
837
+ ? {
838
+ ...(definitionVerification ? { definition: definitionVerification } : {}),
839
+ ...(stateVerification ? { state: stateVerification } : {}),
840
+ }
841
+ : undefined,
842
+ report,
843
+ });
844
+ }
845
+ async function inspectFundingClaim(sdk, input) {
846
+ const verified = await verifyFundingClaim(sdk, input);
847
+ if (!verified.verified) {
848
+ throw new errors_1.ValidationError("Receivable funding claim verification failed", {
849
+ code: "RECEIVABLE_FUNDING_CLAIM_VERIFY_FAILED",
850
+ });
851
+ }
852
+ const artifact = await requireReceivableArtifact(sdk, input);
853
+ const payout = await buildReceivablePayoutDescriptor(sdk, {
854
+ receiverAddress: input.payoutAddress,
855
+ amountSat: verified.claimValue.amountSat,
856
+ assetId: verified.claimValue.currencyAssetId,
857
+ nextOutputHash: input.nextOutputHash,
858
+ outputForm: input.outputForm,
859
+ rawOutput: input.rawOutput,
860
+ outputBindingMode: input.outputBindingMode,
861
+ });
862
+ const contract = sdk.fromArtifact(artifact);
863
+ const inspect = await contract.inspectCall({
864
+ wallet: input.wallet,
865
+ toAddress: payout.descriptor.receiverAddress,
866
+ signer: input.signer,
867
+ sendAmount: satToBtcAmount(payout.descriptor.amountSat),
868
+ feeSat: input.feeSat,
869
+ utxoPolicy: input.utxoPolicy,
870
+ witness: buildReceivableClaimWitness(payout.descriptor),
871
+ });
872
+ return {
873
+ ...verified,
874
+ payoutDescriptor: payout.descriptor,
875
+ inspect,
876
+ report: buildReceivableReport({
877
+ crossChecks: verified.report.receivableTrust,
878
+ ...(verified.report.stateLineageTrust
879
+ ? {
880
+ lineageChecks: (0, receivableValidation_1.verifyReceivableStateHistory)({
881
+ history: verified.stateHistoryValues ?? [verified.currentStateValue],
882
+ }),
883
+ }
884
+ : {}),
885
+ fundingClaimTrust: buildReceivableClaimTrust({
886
+ generated: verified.report.fundingClaimTrust?.generated ?? false,
887
+ claimantXonlyCommitted: verified.report.fundingClaimTrust?.claimantXonlyCommitted ?? true,
888
+ checks: {
889
+ claimKind: verified.report.fundingClaimTrust?.claimKind ?? "FUNDING",
890
+ stateStatusEligible: verified.report.fundingClaimTrust?.stateStatusEligible ?? false,
891
+ receivableIdMatch: verified.report.fundingClaimTrust?.receivableIdMatch ?? false,
892
+ currentStateHashMatch: verified.report.fundingClaimTrust?.currentStateHashMatch ?? false,
893
+ currentStatusMatch: verified.report.fundingClaimTrust?.currentStatusMatch ?? false,
894
+ payerEntityMatch: verified.report.fundingClaimTrust?.payerEntityMatch ?? false,
895
+ payeeEntityMatch: verified.report.fundingClaimTrust?.payeeEntityMatch ?? false,
896
+ claimantXonlyMatch: verified.report.fundingClaimTrust?.claimantXonlyMatch ?? false,
897
+ currencyAssetMatch: verified.report.fundingClaimTrust?.currencyAssetMatch ?? false,
898
+ amountMatch: verified.report.fundingClaimTrust?.amountMatch ?? false,
899
+ eventTimestampMatch: verified.report.fundingClaimTrust?.eventTimestampMatch ?? false,
900
+ fullClaimVerified: verified.report.fundingClaimTrust?.fullClaimVerified ?? false,
901
+ },
902
+ payout,
903
+ }),
904
+ }),
905
+ trustSummary: (0, reporting_1.buildVerificationTrustSummary)({
906
+ bindingMode: payout.descriptor.outputBindingMode,
907
+ ...(verified.report.stateLineageTrust ? { lineageTrust: verified.report.stateLineageTrust } : {}),
908
+ ...(verified.artifactVerification?.definition?.trust ? { definitionTrust: verified.artifactVerification.definition.trust } : {}),
909
+ ...(verified.artifactVerification?.state?.trust ? { stateTrust: verified.artifactVerification.state.trust } : {}),
910
+ }),
911
+ };
912
+ }
913
+ async function executeFundingClaim(sdk, input) {
914
+ const inspected = await inspectFundingClaim(sdk, input);
915
+ const artifact = await requireReceivableArtifact(sdk, input);
916
+ const contract = sdk.fromArtifact(artifact);
917
+ const execution = await contract.execute({
918
+ wallet: input.wallet,
919
+ toAddress: inspected.payoutDescriptor.receiverAddress,
920
+ signer: input.signer,
921
+ sendAmount: satToBtcAmount(inspected.payoutDescriptor.amountSat),
922
+ feeSat: input.feeSat,
923
+ utxoPolicy: input.utxoPolicy,
924
+ broadcast: input.broadcast,
925
+ witness: buildReceivableClaimWitness(inspected.payoutDescriptor),
926
+ });
927
+ return {
928
+ ...inspected,
929
+ execution,
930
+ };
931
+ }
932
+ async function prepareRepaymentClaim(sdk, input) {
933
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
934
+ const currentState = await loadReceivableStateDocument(sdk, {
935
+ statePath: input.currentStatePath,
936
+ stateValue: input.currentStateValue,
937
+ });
938
+ const history = input.stateHistoryPaths || input.stateHistoryValues
939
+ ? await loadReceivableStateHistoryDocuments(sdk, input)
940
+ : [];
941
+ assertLatestStateMatchesHistoryTip({ latestState: currentState, history });
942
+ const claim = await loadReceivableRepaymentClaimDocument(sdk, {
943
+ repaymentClaimPath: input.repaymentClaimPath,
944
+ repaymentClaimValue: input.repaymentClaimValue,
945
+ currentStateValue: currentState.value,
946
+ claimId: input.claimId ?? `${currentState.value.receivableId}-REPAYMENT-CLAIM`,
947
+ payerEntityId: input.payerEntityId,
948
+ payeeEntityId: input.payeeEntityId,
949
+ claimantXonly: input.claimantXonly,
950
+ amountSat: input.amountSat,
951
+ eventTimestamp: input.eventTimestamp,
952
+ });
953
+ const crossChecks = (0, receivableValidation_1.validateReceivableCrossChecks)(definition.value, currentState.value);
954
+ const lineageChecks = history.length > 0
955
+ ? (0, receivableValidation_1.verifyReceivableStateHistory)({ history: history.map((entry) => entry.value) })
956
+ : undefined;
957
+ const claimChecks = (0, receivableValidation_1.validateReceivableRepaymentClaimAgainstState)({
958
+ currentState: currentState.value,
959
+ claim: claim.value,
960
+ });
961
+ const report = buildReceivableReport({
962
+ crossChecks,
963
+ ...(lineageChecks ? { lineageChecks } : {}),
964
+ repaymentClaimTrust: buildReceivableClaimTrust({
965
+ generated: !input.repaymentClaimPath && !input.repaymentClaimValue,
966
+ claimantXonlyCommitted: true,
967
+ checks: claimChecks,
968
+ }),
969
+ });
970
+ const compiled = await compileRepaymentClaimContract(sdk, {
971
+ definition: definition.value,
972
+ claim: claim.value,
973
+ simfPath: input.simfPath,
974
+ artifactPath: input.artifactPath,
975
+ });
976
+ return {
977
+ ...buildClaimVerificationResult({
978
+ verified: report.repaymentClaimTrust?.fullClaimVerified === true && Object.values(crossChecks).every(Boolean),
979
+ definition,
980
+ currentState,
981
+ stateHistory: history,
982
+ claim,
983
+ report,
984
+ }),
985
+ compiled,
986
+ };
987
+ }
988
+ async function verifyRepaymentClaim(sdk, input) {
989
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
990
+ const currentState = await loadReceivableStateDocument(sdk, {
991
+ statePath: input.currentStatePath,
992
+ stateValue: input.currentStateValue,
993
+ });
994
+ const history = input.stateHistoryPaths || input.stateHistoryValues
995
+ ? await loadReceivableStateHistoryDocuments(sdk, input)
996
+ : [];
997
+ assertLatestStateMatchesHistoryTip({ latestState: currentState, history });
998
+ const claim = await loadReceivableRepaymentClaimDocument(sdk, {
999
+ repaymentClaimPath: input.repaymentClaimPath,
1000
+ repaymentClaimValue: input.repaymentClaimValue,
1001
+ });
1002
+ const crossChecks = (0, receivableValidation_1.validateReceivableCrossChecks)(definition.value, currentState.value);
1003
+ const lineageChecks = history.length > 0
1004
+ ? (0, receivableValidation_1.verifyReceivableStateHistory)({ history: history.map((entry) => entry.value) })
1005
+ : undefined;
1006
+ const claimChecks = (0, receivableValidation_1.validateReceivableRepaymentClaimAgainstState)({
1007
+ currentState: currentState.value,
1008
+ claim: claim.value,
1009
+ });
1010
+ const artifact = input.artifact ?? (input.artifactPath ? (await sdk.loadArtifact(input.artifactPath)).artifact : undefined);
1011
+ const definitionVerification = artifact
1012
+ ? await sdk.verifyDefinitionAgainstArtifact({
1013
+ artifact,
1014
+ type: "receivable-definition",
1015
+ id: definition.value.receivableId,
1016
+ value: definition.value,
1017
+ })
1018
+ : undefined;
1019
+ const stateVerification = artifact
1020
+ ? await sdk.verifyStateAgainstArtifact({
1021
+ artifact,
1022
+ type: "receivable-repayment-claim",
1023
+ id: claim.value.claimId,
1024
+ value: claim.value,
1025
+ })
1026
+ : undefined;
1027
+ const claimantXonlyCommitted = artifact
1028
+ ? String(artifact.source.templateVars?.CLAIMANT_XONLY ?? "").toLowerCase() === claim.value.claimantXonly.toLowerCase()
1029
+ : true;
1030
+ const report = buildReceivableReport({
1031
+ crossChecks,
1032
+ ...(lineageChecks ? { lineageChecks } : {}),
1033
+ repaymentClaimTrust: buildReceivableClaimTrust({
1034
+ generated: false,
1035
+ claimantXonlyCommitted,
1036
+ checks: claimChecks,
1037
+ }),
1038
+ });
1039
+ const verified = report.repaymentClaimTrust?.fullClaimVerified === true
1040
+ && Object.values(crossChecks).every(Boolean)
1041
+ && (!definitionVerification || definitionVerification.ok)
1042
+ && (!stateVerification || stateVerification.ok);
1043
+ return buildClaimVerificationResult({
1044
+ verified,
1045
+ definition,
1046
+ currentState,
1047
+ stateHistory: history,
1048
+ claim,
1049
+ artifact,
1050
+ artifactVerification: artifact && (definitionVerification || stateVerification)
1051
+ ? {
1052
+ ...(definitionVerification ? { definition: definitionVerification } : {}),
1053
+ ...(stateVerification ? { state: stateVerification } : {}),
1054
+ }
1055
+ : undefined,
1056
+ report,
1057
+ });
1058
+ }
1059
+ async function inspectRepaymentClaim(sdk, input) {
1060
+ const verified = await verifyRepaymentClaim(sdk, input);
1061
+ if (!verified.verified) {
1062
+ throw new errors_1.ValidationError("Receivable repayment claim verification failed", {
1063
+ code: "RECEIVABLE_REPAYMENT_CLAIM_VERIFY_FAILED",
1064
+ });
1065
+ }
1066
+ const artifact = await requireReceivableArtifact(sdk, input);
1067
+ const payout = await buildReceivablePayoutDescriptor(sdk, {
1068
+ receiverAddress: input.payoutAddress,
1069
+ amountSat: verified.claimValue.amountSat,
1070
+ assetId: verified.claimValue.currencyAssetId,
1071
+ nextOutputHash: input.nextOutputHash,
1072
+ outputForm: input.outputForm,
1073
+ rawOutput: input.rawOutput,
1074
+ outputBindingMode: input.outputBindingMode,
1075
+ });
1076
+ const contract = sdk.fromArtifact(artifact);
1077
+ const inspect = await contract.inspectCall({
1078
+ wallet: input.wallet,
1079
+ toAddress: payout.descriptor.receiverAddress,
1080
+ signer: input.signer,
1081
+ sendAmount: satToBtcAmount(payout.descriptor.amountSat),
1082
+ feeSat: input.feeSat,
1083
+ utxoPolicy: input.utxoPolicy,
1084
+ witness: buildReceivableClaimWitness(payout.descriptor),
1085
+ });
1086
+ return {
1087
+ ...verified,
1088
+ payoutDescriptor: payout.descriptor,
1089
+ inspect,
1090
+ report: buildReceivableReport({
1091
+ crossChecks: verified.report.receivableTrust,
1092
+ ...(verified.report.stateLineageTrust
1093
+ ? {
1094
+ lineageChecks: (0, receivableValidation_1.verifyReceivableStateHistory)({
1095
+ history: verified.stateHistoryValues ?? [verified.currentStateValue],
1096
+ }),
1097
+ }
1098
+ : {}),
1099
+ repaymentClaimTrust: buildReceivableClaimTrust({
1100
+ generated: verified.report.repaymentClaimTrust?.generated ?? false,
1101
+ claimantXonlyCommitted: verified.report.repaymentClaimTrust?.claimantXonlyCommitted ?? true,
1102
+ checks: {
1103
+ claimKind: verified.report.repaymentClaimTrust?.claimKind ?? "REPAYMENT",
1104
+ stateStatusEligible: verified.report.repaymentClaimTrust?.stateStatusEligible ?? false,
1105
+ receivableIdMatch: verified.report.repaymentClaimTrust?.receivableIdMatch ?? false,
1106
+ currentStateHashMatch: verified.report.repaymentClaimTrust?.currentStateHashMatch ?? false,
1107
+ currentStatusMatch: verified.report.repaymentClaimTrust?.currentStatusMatch ?? false,
1108
+ payerEntityMatch: verified.report.repaymentClaimTrust?.payerEntityMatch ?? false,
1109
+ payeeEntityMatch: verified.report.repaymentClaimTrust?.payeeEntityMatch ?? false,
1110
+ claimantXonlyMatch: verified.report.repaymentClaimTrust?.claimantXonlyMatch ?? false,
1111
+ currencyAssetMatch: verified.report.repaymentClaimTrust?.currencyAssetMatch ?? false,
1112
+ amountMatch: verified.report.repaymentClaimTrust?.amountMatch ?? false,
1113
+ eventTimestampMatch: verified.report.repaymentClaimTrust?.eventTimestampMatch ?? false,
1114
+ fullClaimVerified: verified.report.repaymentClaimTrust?.fullClaimVerified ?? false,
1115
+ },
1116
+ payout,
1117
+ }),
1118
+ }),
1119
+ trustSummary: (0, reporting_1.buildVerificationTrustSummary)({
1120
+ bindingMode: payout.descriptor.outputBindingMode,
1121
+ ...(verified.report.stateLineageTrust ? { lineageTrust: verified.report.stateLineageTrust } : {}),
1122
+ ...(verified.artifactVerification?.definition?.trust ? { definitionTrust: verified.artifactVerification.definition.trust } : {}),
1123
+ ...(verified.artifactVerification?.state?.trust ? { stateTrust: verified.artifactVerification.state.trust } : {}),
1124
+ }),
1125
+ };
1126
+ }
1127
+ async function executeRepaymentClaim(sdk, input) {
1128
+ const inspected = await inspectRepaymentClaim(sdk, input);
1129
+ const artifact = await requireReceivableArtifact(sdk, input);
1130
+ const contract = sdk.fromArtifact(artifact);
1131
+ const execution = await contract.execute({
1132
+ wallet: input.wallet,
1133
+ toAddress: inspected.payoutDescriptor.receiverAddress,
1134
+ signer: input.signer,
1135
+ sendAmount: satToBtcAmount(inspected.payoutDescriptor.amountSat),
1136
+ feeSat: input.feeSat,
1137
+ utxoPolicy: input.utxoPolicy,
1138
+ broadcast: input.broadcast,
1139
+ witness: buildReceivableClaimWitness(inspected.payoutDescriptor),
1140
+ });
1141
+ return {
1142
+ ...inspected,
1143
+ execution,
1144
+ };
1145
+ }
1146
+ async function prepareWriteOff(sdk, input) {
1147
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
1148
+ const previous = await loadReceivableStateDocument(sdk, {
1149
+ statePath: input.previousStatePath,
1150
+ stateValue: input.previousStateValue,
1151
+ });
1152
+ const next = input.nextStatePath || input.nextStateValue
1153
+ ? await loadReceivableStateDocument(sdk, {
1154
+ statePath: input.nextStatePath,
1155
+ stateValue: input.nextStateValue,
1156
+ })
1157
+ : await loadReceivableStateDocument(sdk, {
1158
+ stateValue: (0, receivableValidation_1.buildDefaultedReceivableState)({
1159
+ previous: previous.value,
1160
+ stateId: input.stateId ?? `${previous.value.receivableId}-DEFAULTED`,
1161
+ defaultedAt: input.defaultedAt ?? new Date().toISOString(),
1162
+ ...(input.writeOffAmount !== undefined ? { writeOffAmount: input.writeOffAmount } : {}),
1163
+ }),
1164
+ });
1165
+ const transitionTrust = (0, receivableValidation_1.validateReceivableWriteOffTransition)(previous.value, next.value);
1166
+ return buildTransitionVerificationResult({
1167
+ definition,
1168
+ previous,
1169
+ next,
1170
+ transitionTrust,
1171
+ });
1172
+ }
1173
+ async function verifyWriteOff(sdk, input) {
1174
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
1175
+ const { previous, next } = await loadPreviousAndNextReceivableStates(sdk, input);
1176
+ const transitionTrust = (0, receivableValidation_1.validateReceivableWriteOffTransition)(previous.value, next.value);
1177
+ return buildTransitionVerificationResult({
1178
+ definition,
1179
+ previous,
1180
+ next,
1181
+ transitionTrust,
1182
+ });
1183
+ }
1184
+ async function prepareClosing(sdk, input) {
1185
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
1186
+ const latestState = await loadReceivableStateDocument(sdk, {
1187
+ statePath: input.latestStatePath,
1188
+ stateValue: input.latestStateValue,
1189
+ });
1190
+ const history = input.stateHistoryPaths || input.stateHistoryValues
1191
+ ? await loadReceivableStateHistoryDocuments(sdk, input)
1192
+ : [];
1193
+ assertLatestStateMatchesHistoryTip({ latestState, history });
1194
+ const closing = await loadReceivableClosingDocument(sdk, {
1195
+ closingPath: input.closingPath,
1196
+ closingValue: input.closingValue,
1197
+ closingId: input.closingId,
1198
+ latestStateValue: latestState.value,
1199
+ closedAt: input.closedAt,
1200
+ closingReason: input.closingReason,
1201
+ });
1202
+ const crossChecks = (0, receivableValidation_1.validateReceivableCrossChecks)(definition.value, latestState.value);
1203
+ const lineageChecks = history.length > 0
1204
+ ? (0, receivableValidation_1.verifyReceivableStateHistory)({ history: history.map((entry) => entry.value) })
1205
+ : undefined;
1206
+ const closingTrust = (0, receivableValidation_1.validateReceivableClosingAgainstState)({
1207
+ latestState: latestState.value,
1208
+ closing: closing.value,
1209
+ ...(history.length > 0 ? { history: history.map((entry) => entry.value) } : {}),
1210
+ });
1211
+ const report = buildReceivableReport({
1212
+ crossChecks,
1213
+ ...(lineageChecks ? { lineageChecks } : {}),
1214
+ closingTrust,
1215
+ });
1216
+ return {
1217
+ verified: closingTrust.fullClosingVerified
1218
+ && Object.values(crossChecks).every(Boolean)
1219
+ && (lineageChecks ? lineageChecks.fullHistoryVerified : true),
1220
+ definition: definition.descriptor,
1221
+ definitionValue: definition.value,
1222
+ definitionSummary: definition.summary,
1223
+ latestState: latestState.descriptor,
1224
+ latestStateValue: latestState.value,
1225
+ latestStateSummary: latestState.summary,
1226
+ ...(history.length > 0
1227
+ ? {
1228
+ stateHistory: history.map((entry) => entry.descriptor),
1229
+ stateHistoryValues: history.map((entry) => entry.value),
1230
+ stateHistorySummaries: history.map((entry) => entry.summary),
1231
+ }
1232
+ : {}),
1233
+ closing: closing.descriptor,
1234
+ closingValue: closing.value,
1235
+ closingSummary: closing.summary,
1236
+ report,
1237
+ trustSummary: (0, reporting_1.buildVerificationTrustSummary)({
1238
+ bindingMode: "none",
1239
+ ...(report.stateLineageTrust ? { lineageTrust: report.stateLineageTrust } : {}),
1240
+ }),
1241
+ };
1242
+ }
1243
+ async function verifyClosing(sdk, input) {
1244
+ if (!input.closingPath && !input.closingValue) {
1245
+ throw new errors_1.ValidationError("closingPath or closingValue is required", {
1246
+ code: "RECEIVABLE_CLOSING_REQUIRED",
1247
+ });
1248
+ }
1249
+ return prepareClosing(sdk, input);
1250
+ }
1251
+ async function exportEvidence(sdk, input) {
1252
+ const definition = await loadReceivableDefinitionDocument(sdk, input);
1253
+ const latestState = input.statePath || input.stateValue
1254
+ ? await loadReceivableStateDocument(sdk, input)
1255
+ : undefined;
1256
+ const history = input.stateHistoryPaths || input.stateHistoryValues
1257
+ ? await loadReceivableStateHistoryDocuments(sdk, input)
1258
+ : [];
1259
+ assertLatestStateMatchesHistoryTip({ latestState, history });
1260
+ const latest = latestState ?? history.at(-1);
1261
+ if (!latest) {
1262
+ throw new errors_1.ValidationError("statePath/stateValue or stateHistoryPaths/stateHistoryValues is required", {
1263
+ code: "RECEIVABLE_STATE_REQUIRED",
1264
+ });
1265
+ }
1266
+ const closing = input.closingPath || input.closingValue
1267
+ ? await loadReceivableClosingDocument(sdk, {
1268
+ closingPath: input.closingPath,
1269
+ closingValue: input.closingValue,
1270
+ })
1271
+ : undefined;
1272
+ const fundingClaim = input.fundingClaimPath || input.fundingClaimValue
1273
+ ? await loadReceivableFundingClaimDocument(sdk, {
1274
+ fundingClaimPath: input.fundingClaimPath,
1275
+ fundingClaimValue: input.fundingClaimValue,
1276
+ })
1277
+ : undefined;
1278
+ const repaymentClaim = input.repaymentClaimPath || input.repaymentClaimValue
1279
+ ? await loadReceivableRepaymentClaimDocument(sdk, {
1280
+ repaymentClaimPath: input.repaymentClaimPath,
1281
+ repaymentClaimValue: input.repaymentClaimValue,
1282
+ })
1283
+ : undefined;
1284
+ const lineageChecks = history.length > 0
1285
+ ? (0, receivableValidation_1.verifyReceivableStateHistory)({ history: history.map((entry) => entry.value) })
1286
+ : undefined;
1287
+ const trust = input.verificationReportValue
1288
+ ?? (lineageChecks
1289
+ ? buildReceivableReport({
1290
+ crossChecks: (0, receivableValidation_1.validateReceivableCrossChecks)(definition.value, latest.value),
1291
+ lineageChecks,
1292
+ ...(closing
1293
+ ? {
1294
+ closingTrust: (0, receivableValidation_1.validateReceivableClosingAgainstState)({
1295
+ latestState: latest.value,
1296
+ closing: closing.value,
1297
+ history: history.map((entry) => entry.value),
1298
+ }),
1299
+ }
1300
+ : {}),
1301
+ })
1302
+ : buildReceivableReport({
1303
+ crossChecks: (0, receivableValidation_1.validateReceivableCrossChecks)(definition.value, latest.value),
1304
+ ...(closing
1305
+ ? {
1306
+ closingTrust: (0, receivableValidation_1.validateReceivableClosingAgainstState)({
1307
+ latestState: latest.value,
1308
+ closing: closing.value,
1309
+ }),
1310
+ }
1311
+ : {}),
1312
+ }));
1313
+ return {
1314
+ schemaVersion: RECEIVABLE_EVIDENCE_BUNDLE_SCHEMA_VERSION,
1315
+ definition: definition.summary,
1316
+ state: latest.summary,
1317
+ ...(history.length > 1 ? { stateHistory: history.map((entry) => entry.summary) } : {}),
1318
+ ...(fundingClaim ? { fundingClaim: fundingClaim.summary } : {}),
1319
+ ...(repaymentClaim ? { repaymentClaim: repaymentClaim.summary } : {}),
1320
+ ...(closing ? { closing: closing.summary } : {}),
1321
+ trust,
1322
+ trustSummary: (0, reporting_1.buildVerificationTrustSummary)({
1323
+ bindingMode: "none",
1324
+ lineageTrust: trust.stateLineageTrust,
1325
+ }),
1326
+ };
1327
+ }
1328
+ async function exportFinalityPayload(sdk, input) {
1329
+ const evidence = await exportEvidence(sdk, input);
1330
+ const latestState = input.statePath || input.stateValue
1331
+ ? await loadReceivableStateDocument(sdk, input)
1332
+ : undefined;
1333
+ const history = input.stateHistoryPaths || input.stateHistoryValues
1334
+ ? await loadReceivableStateHistoryDocuments(sdk, input)
1335
+ : [];
1336
+ assertLatestStateMatchesHistoryTip({ latestState, history });
1337
+ const latest = latestState ?? history.at(-1);
1338
+ if (!latest) {
1339
+ throw new errors_1.ValidationError("statePath/stateValue or stateHistoryPaths/stateHistoryValues is required", {
1340
+ code: "RECEIVABLE_STATE_REQUIRED",
1341
+ });
1342
+ }
1343
+ const closing = input.closingPath || input.closingValue
1344
+ ? await loadReceivableClosingDocument(sdk, {
1345
+ closingPath: input.closingPath,
1346
+ closingValue: input.closingValue,
1347
+ })
1348
+ : undefined;
1349
+ const fundingClaim = input.fundingClaimPath || input.fundingClaimValue
1350
+ ? await loadReceivableFundingClaimDocument(sdk, {
1351
+ fundingClaimPath: input.fundingClaimPath,
1352
+ fundingClaimValue: input.fundingClaimValue,
1353
+ })
1354
+ : undefined;
1355
+ const repaymentClaim = input.repaymentClaimPath || input.repaymentClaimValue
1356
+ ? await loadReceivableRepaymentClaimDocument(sdk, {
1357
+ repaymentClaimPath: input.repaymentClaimPath,
1358
+ repaymentClaimValue: input.repaymentClaimValue,
1359
+ })
1360
+ : undefined;
1361
+ return {
1362
+ schemaVersion: RECEIVABLE_FINALITY_PAYLOAD_SCHEMA_VERSION,
1363
+ receivableId: latest.value.receivableId,
1364
+ holderEntityId: latest.value.holderEntityId,
1365
+ definitionHash: evidence.definition.hash,
1366
+ latestStateHash: evidence.state.hash,
1367
+ stateHistoryHashes: history.length > 1 ? history.map((entry) => entry.summary.hash) : null,
1368
+ fundingClaimHash: fundingClaim?.summary.hash ?? null,
1369
+ repaymentClaimHash: repaymentClaim?.summary.hash ?? null,
1370
+ closingHash: closing?.summary.hash ?? null,
1371
+ closingReason: closing?.value.closingReason ?? null,
1372
+ trust: evidence.trust,
1373
+ trustSummary: evidence.trustSummary,
1374
+ };
1375
+ }