@hazbase/simplicity 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +143 -1531
  2. package/dist/cli.js +1128 -1
  3. package/dist/client/SimplicityClient.d.ts +30 -3
  4. package/dist/client/SimplicityClient.js +28 -0
  5. package/dist/core/lineage.d.ts +18 -0
  6. package/dist/core/lineage.js +30 -0
  7. package/dist/core/reporting.d.ts +22 -0
  8. package/dist/core/reporting.js +40 -0
  9. package/dist/core/schnorr.d.ts +3 -3
  10. package/dist/core/schnorr.js +19 -7
  11. package/dist/core/types.d.ts +256 -5
  12. package/dist/docs/definitions/fund-capital-call-refund-only.simf +36 -2
  13. package/dist/docs/definitions/receivable-definition.json +10 -0
  14. package/dist/docs/definitions/receivable-funding-claim.json +13 -0
  15. package/dist/docs/definitions/receivable-funding-claim.simf +58 -0
  16. package/dist/docs/definitions/receivable-repayment-claim-partial.json +13 -0
  17. package/dist/docs/definitions/receivable-repayment-claim.json +13 -0
  18. package/dist/docs/definitions/receivable-repayment-claim.simf +59 -0
  19. package/dist/docs/definitions/receivable-state-funded.json +21 -0
  20. package/dist/docs/definitions/receivable-state-originated.json +20 -0
  21. package/dist/docs/definitions/receivable-state-partially-repaid.json +21 -0
  22. package/dist/docs/definitions/receivable-state-repaid.json +21 -0
  23. package/dist/domain/bond.d.ts +82 -15
  24. package/dist/domain/bond.js +159 -10
  25. package/dist/domain/bondValidation.d.ts +31 -1
  26. package/dist/domain/bondValidation.js +73 -9
  27. package/dist/domain/fund.d.ts +451 -68
  28. package/dist/domain/fund.js +460 -88
  29. package/dist/domain/fundValidation.d.ts +33 -3
  30. package/dist/domain/fundValidation.js +137 -5
  31. package/dist/domain/policies.d.ts +13 -0
  32. package/dist/domain/policies.js +50 -30
  33. package/dist/domain/receivable.d.ts +825 -0
  34. package/dist/domain/receivable.js +1385 -0
  35. package/dist/domain/receivableValidation.d.ts +150 -0
  36. package/dist/domain/receivableValidation.js +874 -0
  37. package/dist/index.d.ts +5 -3
  38. package/dist/index.js +55 -3
  39. package/package.json +6 -1
@@ -10,6 +10,7 @@ exports.prepareCapitalCall = prepareCapitalCall;
10
10
  exports.verifyCapitalCall = verifyCapitalCall;
11
11
  exports.signPositionReceipt = signPositionReceipt;
12
12
  exports.verifyPositionReceipt = verifyPositionReceipt;
13
+ exports.verifyPositionReceiptChain = verifyPositionReceiptChain;
13
14
  exports.inspectCapitalCallClaim = inspectCapitalCallClaim;
14
15
  exports.executeCapitalCallClaim = executeCapitalCallClaim;
15
16
  exports.inspectCapitalCallRollover = inspectCapitalCallRollover;
@@ -31,6 +32,7 @@ const node_path_1 = __importDefault(require("node:path"));
31
32
  const errors_1 = require("../core/errors");
32
33
  const summary_1 = require("../core/summary");
33
34
  const outputBinding_1 = require("../core/outputBinding");
35
+ const reporting_1 = require("../core/reporting");
34
36
  const fundValidation_1 = require("./fundValidation");
35
37
  const FUND_VERIFICATION_REPORT_SCHEMA_VERSION = "fund-verification-report/v1";
36
38
  const FUND_EVIDENCE_BUNDLE_SCHEMA_VERSION = "fund-evidence-bundle/v1";
@@ -305,8 +307,23 @@ function buildRolloverWitness() {
305
307
  },
306
308
  };
307
309
  }
308
- function buildRefundWitness() {
309
- return { values: {} };
310
+ function buildRefundWitness(descriptor) {
311
+ return {
312
+ values: {
313
+ EXPECTED_PAYOUT_OUTPUT_HASH: {
314
+ type: "u256",
315
+ value: `0x${descriptor.nextOutputHash ?? "0000000000000000000000000000000000000000000000000000000000000000"}`,
316
+ },
317
+ EXPECTED_PAYOUT_OUTPUT_SCRIPT_HASH: {
318
+ type: "u256",
319
+ value: `0x${descriptor.nextOutputScriptHash ?? "0000000000000000000000000000000000000000000000000000000000000000"}`,
320
+ },
321
+ OUTPUT_BINDING_MODE: {
322
+ type: "u8",
323
+ value: buildBindingModeWitnessValue(descriptor.outputBindingMode),
324
+ },
325
+ },
326
+ };
310
327
  }
311
328
  function buildDistributionWitness(descriptor) {
312
329
  return {
@@ -391,6 +408,18 @@ async function loadPositionReceiptEnvelopeDocument(sdk, input) {
391
408
  envelopeSummary: (0, fundValidation_1.summarizeLPPositionReceiptEnvelope)(value),
392
409
  };
393
410
  }
411
+ async function loadPositionReceiptEnvelopeChainDocuments(sdk, input) {
412
+ const combinedPaths = [...(input.positionReceiptChainPaths ?? [])];
413
+ const combinedValues = [...(input.positionReceiptChainValues ?? [])];
414
+ const results = [];
415
+ for (const positionReceiptPath of combinedPaths) {
416
+ results.push(await loadPositionReceiptEnvelopeDocument(sdk, { positionReceiptPath }));
417
+ }
418
+ for (const positionReceiptValue of combinedValues) {
419
+ results.push(await loadPositionReceiptEnvelopeDocument(sdk, { positionReceiptValue }));
420
+ }
421
+ return results;
422
+ }
394
423
  async function loadDistributionDocument(sdk, input) {
395
424
  const source = resolveValueOrPath({ pathValue: input.distributionPath, objectValue: input.distributionValue });
396
425
  let value;
@@ -461,8 +490,33 @@ async function loadClosingDocument(sdk, input) {
461
490
  });
462
491
  return { descriptor, value, summary: (0, fundValidation_1.summarizeFundClosingDescriptor)(value) };
463
492
  }
464
- function buildBaseFundReport() {
465
- return { schemaVersion: FUND_VERIFICATION_REPORT_SCHEMA_VERSION };
493
+ function buildEmptyFundDefinitionTrust() {
494
+ return {
495
+ artifactMatch: false,
496
+ onChainAnchorPresent: false,
497
+ onChainAnchorVerified: false,
498
+ effectiveMode: "none",
499
+ };
500
+ }
501
+ function buildEmptyFundStateTrust() {
502
+ return {
503
+ artifactMatch: false,
504
+ onChainAnchorPresent: false,
505
+ onChainAnchorVerified: false,
506
+ effectiveMode: "none",
507
+ };
508
+ }
509
+ function buildBaseFundReport(input) {
510
+ return {
511
+ schemaVersion: FUND_VERIFICATION_REPORT_SCHEMA_VERSION,
512
+ ...(0, reporting_1.buildVerificationTrustSections)({
513
+ definitionTrust: input?.definitionTrust,
514
+ stateTrust: input?.stateTrust,
515
+ requireArtifactTrust: input?.requireArtifactTrust,
516
+ emptyDefinitionTrust: buildEmptyFundDefinitionTrust(),
517
+ emptyStateTrust: buildEmptyFundStateTrust(),
518
+ }),
519
+ };
466
520
  }
467
521
  async function compileOpenCapitalCallContract(sdk, input) {
468
522
  return sdk.compileFromFile({
@@ -549,10 +603,28 @@ async function requireRefundOnlyArtifact(sdk, input) {
549
603
  }
550
604
  return artifact;
551
605
  }
552
- function ensureVerifiedEnvelope(definition, envelope) {
553
- const checks = (0, fundValidation_1.verifyLPPositionReceiptEnvelope)({
606
+ async function ensureVerifiedEnvelope(definition, envelope) {
607
+ const checks = await (0, fundValidation_1.verifyLPPositionReceiptEnvelope)({
608
+ envelope,
609
+ expectedManagerXonly: definition.managerXonly,
610
+ });
611
+ if (!checks.positionReceiptHashMatch
612
+ || !checks.sequenceMatch
613
+ || !checks.sequenceMonotonic
614
+ || !checks.attestingSignerMatch
615
+ || !checks.attestationVerified) {
616
+ throw new errors_1.ValidationError("Position receipt envelope must be attested and internally consistent", {
617
+ code: "FUND_POSITION_ENVELOPE_VERIFY_FAILED",
618
+ checks,
619
+ });
620
+ }
621
+ return checks;
622
+ }
623
+ async function ensureVerifiedEnvelopeContinuity(definition, envelope, previousEnvelope) {
624
+ const checks = await (0, fundValidation_1.verifyLPPositionReceiptEnvelope)({
554
625
  envelope,
555
626
  expectedManagerXonly: definition.managerXonly,
627
+ previousEnvelope,
556
628
  });
557
629
  if (!checks.positionReceiptHashMatch
558
630
  || !checks.sequenceMatch
@@ -564,6 +636,20 @@ function ensureVerifiedEnvelope(definition, envelope) {
564
636
  checks,
565
637
  });
566
638
  }
639
+ if (envelope.receipt.sequence > 0) {
640
+ if (!previousEnvelope) {
641
+ throw new errors_1.ValidationError("sequence>0 receipts require the immediate previous receipt envelope", {
642
+ code: "FUND_PREVIOUS_POSITION_ENVELOPE_REQUIRED",
643
+ checks,
644
+ });
645
+ }
646
+ if (!checks.continuityVerified) {
647
+ throw new errors_1.ValidationError("Position receipt envelope continuity must match the immediate previous envelope", {
648
+ code: "FUND_POSITION_ENVELOPE_CONTINUITY_VERIFY_FAILED",
649
+ checks,
650
+ });
651
+ }
652
+ }
567
653
  return checks;
568
654
  }
569
655
  function buildReceiptTrust(input) {
@@ -576,6 +662,79 @@ function buildReceiptTrust(input) {
576
662
  sequence: input.envelope.receipt.sequence,
577
663
  sequenceMonotonic: input.checks.sequenceMonotonic && input.checks.sequenceMatch,
578
664
  attestingSignerMatch: input.checks.attestingSignerMatch,
665
+ previousEnvelopeProvided: input.checks.previousEnvelopeProvided,
666
+ previousReceiptHashMatch: input.checks.previousReceiptHashMatch,
667
+ previousSequenceMatch: input.checks.previousSequenceMatch,
668
+ continuityVerified: input.checks.continuityVerified,
669
+ };
670
+ }
671
+ function buildReceiptChainTrust(input) {
672
+ const identityConsistent = input.fundConsistent
673
+ && input.positionConsistent
674
+ && input.lpConsistent
675
+ && input.callConsistent
676
+ && input.currencyConsistent
677
+ && input.lpXonlyConsistent
678
+ && input.attestingSignerConsistent;
679
+ return {
680
+ ...(0, reporting_1.buildLineageTrustBase)({
681
+ lineageKind: "receipt-chain",
682
+ chainLength: input.chainLength,
683
+ latestOrdinal: input.latestSequence ?? Math.max(0, input.chainLength - 1),
684
+ allHashLinksVerified: input.allContinuityVerified && input.allPositionReceiptHashMatch,
685
+ identityConsistent,
686
+ fullLineageVerified: input.fullChainVerified,
687
+ }),
688
+ latestSequence: input.latestSequence,
689
+ startsAtGenesis: input.startsAtGenesis,
690
+ latestSequenceCovered: input.latestSequenceCovered,
691
+ sequenceContiguous: input.sequenceContiguous,
692
+ fundConsistent: input.fundConsistent,
693
+ positionConsistent: input.positionConsistent,
694
+ lpConsistent: input.lpConsistent,
695
+ callConsistent: input.callConsistent,
696
+ currencyConsistent: input.currencyConsistent,
697
+ lpXonlyConsistent: input.lpXonlyConsistent,
698
+ attestingSignerConsistent: input.attestingSignerConsistent,
699
+ allPositionReceiptHashMatch: input.allPositionReceiptHashMatch,
700
+ allSequenceMatch: input.allSequenceMatch,
701
+ allSequenceMonotonic: input.allSequenceMonotonic,
702
+ allAttestingSignerMatch: input.allAttestingSignerMatch,
703
+ allAttestationVerified: input.allAttestationVerified,
704
+ allContinuityVerified: input.allContinuityVerified,
705
+ fullChainVerified: input.fullChainVerified,
706
+ };
707
+ }
708
+ function resolveReceiptChainContext(input) {
709
+ const chainEntries = input.chainEntries && input.chainEntries.length > 0
710
+ ? input.chainEntries
711
+ : input.receipt
712
+ ? [
713
+ ...(input.previousEnvelope ? [input.previousEnvelope] : []),
714
+ input.receipt,
715
+ ]
716
+ : [];
717
+ const receipt = input.receipt ?? chainEntries.at(-1);
718
+ if (!receipt) {
719
+ throw new errors_1.ValidationError("position receipt envelope is required", {
720
+ code: "FUND_POSITION_RECEIPT_REQUIRED",
721
+ });
722
+ }
723
+ const latestChainEntry = chainEntries.at(-1);
724
+ if (latestChainEntry && latestChainEntry.envelopeSummary.hash !== receipt.envelopeSummary.hash) {
725
+ throw new errors_1.ValidationError("position receipt chain must end with the provided latest envelope", {
726
+ code: "FUND_POSITION_CHAIN_LATEST_MISMATCH",
727
+ latestEnvelopeHash: receipt.envelopeSummary.hash,
728
+ chainLatestEnvelopeHash: latestChainEntry.envelopeSummary.hash,
729
+ });
730
+ }
731
+ const previousEnvelope = chainEntries.length > 1
732
+ ? chainEntries[chainEntries.length - 2]
733
+ : input.previousEnvelope;
734
+ return {
735
+ receipt,
736
+ previousEnvelope,
737
+ chainEntries,
579
738
  };
580
739
  }
581
740
  async function define(sdk, input) {
@@ -713,16 +872,10 @@ async function verifyCapitalCall(sdk, input) {
713
872
  ? { definition: definitionVerification, state: stateVerification }
714
873
  : undefined,
715
874
  report: {
716
- ...buildBaseFundReport(),
717
- ...(definitionVerification && stateVerification
718
- ? {
719
- artifactTrust: {
720
- definition: definitionVerification.trust,
721
- state: stateVerification.trust,
722
- },
723
- stateTrust: stateVerification.trust,
724
- }
725
- : {}),
875
+ ...buildBaseFundReport({
876
+ definitionTrust: definitionVerification?.trust,
877
+ stateTrust: stateVerification?.trust,
878
+ }),
726
879
  capitalCallTrust: {
727
880
  capitalCallStage: deriveCapitalCallStage(capitalCall.value),
728
881
  cutoffMode: "rollover-window",
@@ -742,7 +895,7 @@ async function verifyCapitalCall(sdk, input) {
742
895
  async function signPositionReceipt(sdk, input) {
743
896
  const definition = await loadFundDefinitionDocument(sdk, input);
744
897
  const receipt = await loadBarePositionReceiptDocument(sdk, input);
745
- const positionReceiptEnvelope = (0, fundValidation_1.signLPPositionReceipt)({
898
+ const positionReceiptEnvelope = await (0, fundValidation_1.signLPPositionReceipt)({
746
899
  receipt: receipt.value,
747
900
  managerXonly: definition.value.managerXonly,
748
901
  signer: input.signer,
@@ -761,21 +914,101 @@ async function signPositionReceipt(sdk, input) {
761
914
  }
762
915
  async function verifyPositionReceipt(sdk, input) {
763
916
  const definition = await loadFundDefinitionDocument(sdk, input);
764
- const envelope = await loadPositionReceiptEnvelopeDocument(sdk, input);
765
- const receiptChecks = ensureVerifiedEnvelope(definition.value, envelope.value);
917
+ const envelope = input.positionReceiptPath || input.positionReceiptValue
918
+ ? await loadPositionReceiptEnvelopeDocument(sdk, input)
919
+ : undefined;
920
+ const previousEnvelope = input.previousPositionReceiptPath || input.previousPositionReceiptValue
921
+ ? await loadPositionReceiptEnvelopeDocument(sdk, {
922
+ positionReceiptPath: input.previousPositionReceiptPath,
923
+ positionReceiptValue: input.previousPositionReceiptValue,
924
+ })
925
+ : undefined;
926
+ const chainEntries = input.positionReceiptChainPaths || input.positionReceiptChainValues
927
+ ? await loadPositionReceiptEnvelopeChainDocuments(sdk, {
928
+ positionReceiptChainPaths: input.positionReceiptChainPaths,
929
+ positionReceiptChainValues: input.positionReceiptChainValues,
930
+ })
931
+ : [];
932
+ const context = resolveReceiptChainContext({
933
+ receipt: envelope,
934
+ previousEnvelope,
935
+ chainEntries,
936
+ });
937
+ const receiptChecks = await ensureVerifiedEnvelopeContinuity(definition.value, context.receipt.value, context.previousEnvelope?.value);
938
+ const chainChecks = await (0, fundValidation_1.verifyLPPositionReceiptEnvelopeChain)({
939
+ envelopes: context.chainEntries.map((entry) => entry.value),
940
+ expectedManagerXonly: definition.value.managerXonly,
941
+ });
766
942
  return {
767
943
  verified: true,
768
944
  definition: definition.descriptor,
769
945
  definitionValue: definition.value,
770
946
  definitionSummary: definition.summary,
771
- positionReceipt: envelope.descriptor,
772
- positionReceiptValue: envelope.value,
773
- positionReceiptSummary: envelope.receiptSummary,
774
- positionReceiptEnvelopeSummary: envelope.envelopeSummary,
947
+ positionReceipt: context.receipt.descriptor,
948
+ positionReceiptValue: context.receipt.value,
949
+ positionReceiptSummary: context.receipt.receiptSummary,
950
+ positionReceiptEnvelopeSummary: context.receipt.envelopeSummary,
951
+ ...(context.previousEnvelope
952
+ ? {
953
+ previousPositionReceipt: context.previousEnvelope.descriptor,
954
+ previousPositionReceiptValue: context.previousEnvelope.value,
955
+ previousPositionReceiptSummary: context.previousEnvelope.receiptSummary,
956
+ previousPositionReceiptEnvelopeSummary: context.previousEnvelope.envelopeSummary,
957
+ }
958
+ : {}),
959
+ ...(context.chainEntries.length > 0
960
+ ? {
961
+ positionReceiptChain: context.chainEntries.map((entry) => entry.descriptor),
962
+ positionReceiptChainValues: context.chainEntries.map((entry) => entry.value),
963
+ positionReceiptChainSummaries: context.chainEntries.map((entry) => entry.receiptSummary),
964
+ positionReceiptEnvelopeChainSummaries: context.chainEntries.map((entry) => entry.envelopeSummary),
965
+ }
966
+ : {}),
967
+ receiptChecks,
968
+ receiptChainChecks: chainChecks,
969
+ report: {
970
+ ...buildBaseFundReport(),
971
+ receiptTrust: buildReceiptTrust({ generated: false, envelope: context.receipt.value, checks: receiptChecks }),
972
+ receiptChainTrust: buildReceiptChainTrust(chainChecks),
973
+ },
974
+ };
975
+ }
976
+ async function verifyPositionReceiptChain(sdk, input) {
977
+ const definition = await loadFundDefinitionDocument(sdk, input);
978
+ const chainEntries = await loadPositionReceiptEnvelopeChainDocuments(sdk, input);
979
+ const context = resolveReceiptChainContext({ chainEntries });
980
+ const receiptChecks = await ensureVerifiedEnvelopeContinuity(definition.value, context.receipt.value, context.previousEnvelope?.value);
981
+ const chainChecks = await (0, fundValidation_1.verifyLPPositionReceiptEnvelopeChain)({
982
+ envelopes: context.chainEntries.map((entry) => entry.value),
983
+ expectedManagerXonly: definition.value.managerXonly,
984
+ });
985
+ return {
986
+ verified: chainChecks.fullChainVerified,
987
+ definition: definition.descriptor,
988
+ definitionValue: definition.value,
989
+ definitionSummary: definition.summary,
990
+ positionReceipt: context.receipt.descriptor,
991
+ positionReceiptValue: context.receipt.value,
992
+ positionReceiptSummary: context.receipt.receiptSummary,
993
+ positionReceiptEnvelopeSummary: context.receipt.envelopeSummary,
994
+ ...(context.previousEnvelope
995
+ ? {
996
+ previousPositionReceipt: context.previousEnvelope.descriptor,
997
+ previousPositionReceiptValue: context.previousEnvelope.value,
998
+ previousPositionReceiptSummary: context.previousEnvelope.receiptSummary,
999
+ previousPositionReceiptEnvelopeSummary: context.previousEnvelope.envelopeSummary,
1000
+ }
1001
+ : {}),
1002
+ positionReceiptChain: context.chainEntries.map((entry) => entry.descriptor),
1003
+ positionReceiptChainValues: context.chainEntries.map((entry) => entry.value),
1004
+ positionReceiptChainSummaries: context.chainEntries.map((entry) => entry.receiptSummary),
1005
+ positionReceiptEnvelopeChainSummaries: context.chainEntries.map((entry) => entry.envelopeSummary),
775
1006
  receiptChecks,
1007
+ receiptChainChecks: chainChecks,
776
1008
  report: {
777
1009
  ...buildBaseFundReport(),
778
- receiptTrust: buildReceiptTrust({ generated: false, envelope: envelope.value, checks: receiptChecks }),
1010
+ receiptTrust: buildReceiptTrust({ generated: false, envelope: context.receipt.value, checks: receiptChecks }),
1011
+ receiptChainTrust: buildReceiptChainTrust(chainChecks),
779
1012
  },
780
1013
  };
781
1014
  }
@@ -805,13 +1038,13 @@ async function inspectCapitalCallClaim(sdk, input) {
805
1038
  capitalCall: verified.capitalCallValue,
806
1039
  effectiveAt: claimedAt,
807
1040
  });
808
- const positionReceiptEnvelope = (0, fundValidation_1.signLPPositionReceipt)({
1041
+ const positionReceiptEnvelope = await (0, fundValidation_1.signLPPositionReceipt)({
809
1042
  receipt: positionReceipt,
810
1043
  managerXonly: definition.value.managerXonly,
811
1044
  signer: input.signer,
812
1045
  signedAt: claimedAt,
813
1046
  });
814
- const receiptChecks = ensureVerifiedEnvelope(definition.value, positionReceiptEnvelope);
1047
+ const receiptChecks = await ensureVerifiedEnvelope(definition.value, positionReceiptEnvelope);
815
1048
  const contract = sdk.fromArtifact(artifact);
816
1049
  const inspect = await contract.inspectCall({
817
1050
  wallet: input.wallet,
@@ -940,22 +1173,43 @@ async function inspectCapitalCallRefund(sdk, input) {
940
1173
  },
941
1174
  });
942
1175
  }
1176
+ const payout = await buildFundPayoutDescriptor(sdk, {
1177
+ receiverAddress: input.refundAddress,
1178
+ amountSat: refundAmountSat,
1179
+ assetId: verified.capitalCallValue.currencyAssetId,
1180
+ nextOutputHash: input.nextOutputHash,
1181
+ outputForm: input.outputForm,
1182
+ rawOutput: input.rawOutput,
1183
+ outputBindingMode: input.outputBindingMode,
1184
+ });
943
1185
  const contract = sdk.fromArtifact(artifact);
944
1186
  const inspect = await contract.inspectCall({
945
1187
  wallet: input.wallet,
946
- toAddress: input.refundAddress,
1188
+ toAddress: payout.descriptor.receiverAddress,
947
1189
  signer: input.signer,
948
- sendAmount: satToBtcAmount(refundAmountSat),
1190
+ sendAmount: satToBtcAmount(payout.descriptor.amountSat),
949
1191
  feeSat,
950
1192
  utxoPolicy: input.utxoPolicy,
951
- witness: buildRefundWitness(),
1193
+ witness: buildRefundWitness(payout.descriptor),
952
1194
  });
953
1195
  return {
954
1196
  mode: "refund",
955
1197
  verified,
1198
+ payoutDescriptor: payout.descriptor,
1199
+ payoutSummary: payout.summary,
956
1200
  refundedCapitalCall,
957
1201
  inspect,
958
- report: verified.report,
1202
+ report: {
1203
+ ...verified.report,
1204
+ outputBindingTrust: buildFundOutputBindingReport({
1205
+ descriptor: payout.descriptor,
1206
+ supportedForm: payout.supportedForm,
1207
+ reasonCode: payout.reasonCode,
1208
+ autoDerived: payout.autoDerivedNextOutputHash,
1209
+ fallbackReason: payout.fallbackReason,
1210
+ bindingInputs: payout.bindingInputs,
1211
+ }),
1212
+ },
959
1213
  };
960
1214
  }
961
1215
  async function executeCapitalCallRefund(sdk, input) {
@@ -963,16 +1217,15 @@ async function executeCapitalCallRefund(sdk, input) {
963
1217
  const artifact = await requireFundArtifact(sdk, input);
964
1218
  const contract = sdk.fromArtifact(artifact);
965
1219
  const feeSat = input.feeSat ?? 100;
966
- const refundAmountSat = inspected.verified.capitalCallValue.amount - feeSat;
967
1220
  const execution = await contract.execute({
968
1221
  wallet: input.wallet,
969
- toAddress: input.refundAddress,
1222
+ toAddress: inspected.payoutDescriptor.receiverAddress,
970
1223
  signer: input.signer,
971
- sendAmount: satToBtcAmount(refundAmountSat),
1224
+ sendAmount: satToBtcAmount(inspected.payoutDescriptor.amountSat),
972
1225
  feeSat,
973
1226
  utxoPolicy: input.utxoPolicy,
974
1227
  broadcast: input.broadcast,
975
- witness: buildRefundWitness(),
1228
+ witness: buildRefundWitness(inspected.payoutDescriptor),
976
1229
  });
977
1230
  return {
978
1231
  ...inspected,
@@ -983,7 +1236,7 @@ async function executeCapitalCallRefund(sdk, input) {
983
1236
  async function prepareDistribution(sdk, input) {
984
1237
  const definition = await loadFundDefinitionDocument(sdk, input);
985
1238
  const receipt = await loadPositionReceiptEnvelopeDocument(sdk, input);
986
- const receiptChecks = ensureVerifiedEnvelope(definition.value, receipt.value);
1239
+ const receiptChecks = await ensureVerifiedEnvelope(definition.value, receipt.value);
987
1240
  const distribution = await loadDistributionDocument(sdk, {
988
1241
  distributionPath: input.distributionPath,
989
1242
  distributionValue: input.distributionValue,
@@ -1024,13 +1277,13 @@ async function prepareDistribution(sdk, input) {
1024
1277
  async function reconcilePosition(sdk, input) {
1025
1278
  const definition = await loadFundDefinitionDocument(sdk, input);
1026
1279
  const receipt = await loadPositionReceiptEnvelopeDocument(sdk, input);
1027
- ensureVerifiedEnvelope(definition.value, receipt.value);
1280
+ await ensureVerifiedEnvelope(definition.value, receipt.value);
1028
1281
  const distributions = await loadDistributionDocuments(sdk, input);
1029
1282
  const reconciledReceiptValue = (0, fundValidation_1.reconcileLPPositionReceipt)({
1030
1283
  previousEnvelope: receipt.value,
1031
1284
  distributions: distributions.map((entry) => entry.value),
1032
1285
  });
1033
- const reconciledReceiptEnvelope = (0, fundValidation_1.signLPPositionReceipt)({
1286
+ const reconciledReceiptEnvelope = await (0, fundValidation_1.signLPPositionReceipt)({
1034
1287
  receipt: reconciledReceiptValue,
1035
1288
  managerXonly: definition.value.managerXonly,
1036
1289
  signer: input.signer,
@@ -1058,7 +1311,7 @@ async function reconcilePosition(sdk, input) {
1058
1311
  async function verifyDistribution(sdk, input) {
1059
1312
  const definition = await loadFundDefinitionDocument(sdk, input);
1060
1313
  const receipt = await loadPositionReceiptEnvelopeDocument(sdk, input);
1061
- const receiptChecks = ensureVerifiedEnvelope(definition.value, receipt.value);
1314
+ const receiptChecks = await ensureVerifiedEnvelope(definition.value, receipt.value);
1062
1315
  const distribution = await loadDistributionDocument(sdk, {
1063
1316
  distributionPath: input.distributionPath,
1064
1317
  distributionValue: input.distributionValue,
@@ -1111,16 +1364,10 @@ async function verifyDistribution(sdk, input) {
1111
1364
  ? { definition: definitionVerification, state: stateVerification }
1112
1365
  : undefined,
1113
1366
  report: {
1114
- ...buildBaseFundReport(),
1115
- ...(definitionVerification && stateVerification
1116
- ? {
1117
- artifactTrust: {
1118
- definition: definitionVerification.trust,
1119
- state: stateVerification.trust,
1120
- },
1121
- stateTrust: stateVerification.trust,
1122
- }
1123
- : {}),
1367
+ ...buildBaseFundReport({
1368
+ definitionTrust: definitionVerification?.trust,
1369
+ stateTrust: stateVerification?.trust,
1370
+ }),
1124
1371
  distributionTrust: {
1125
1372
  ...crossChecks,
1126
1373
  positionStatusEligible: crossChecks.positionStatusEligible && lpCommitted,
@@ -1196,26 +1443,63 @@ async function executeDistributionClaim(sdk, input) {
1196
1443
  };
1197
1444
  }
1198
1445
  async function prepareClosing(sdk, input) {
1199
- const definition = input.definitionPath || input.definitionValue
1200
- ? await loadFundDefinitionDocument(sdk, input)
1446
+ const definition = await loadFundDefinitionDocument(sdk, input);
1447
+ const receipt = input.positionReceiptPath || input.positionReceiptValue
1448
+ ? await loadPositionReceiptEnvelopeDocument(sdk, input)
1201
1449
  : undefined;
1202
- const receipt = await loadPositionReceiptEnvelopeDocument(sdk, input);
1203
- const receiptChecks = definition ? ensureVerifiedEnvelope(definition.value, receipt.value) : (0, fundValidation_1.verifyLPPositionReceiptEnvelope)({ envelope: receipt.value });
1450
+ const previousEnvelope = input.previousPositionReceiptPath || input.previousPositionReceiptValue
1451
+ ? await loadPositionReceiptEnvelopeDocument(sdk, {
1452
+ positionReceiptPath: input.previousPositionReceiptPath,
1453
+ positionReceiptValue: input.previousPositionReceiptValue,
1454
+ })
1455
+ : undefined;
1456
+ const chainEntries = input.positionReceiptChainPaths || input.positionReceiptChainValues
1457
+ ? await loadPositionReceiptEnvelopeChainDocuments(sdk, {
1458
+ positionReceiptChainPaths: input.positionReceiptChainPaths,
1459
+ positionReceiptChainValues: input.positionReceiptChainValues,
1460
+ })
1461
+ : [];
1462
+ const context = resolveReceiptChainContext({
1463
+ receipt,
1464
+ previousEnvelope,
1465
+ chainEntries,
1466
+ });
1467
+ const receiptChecks = await ensureVerifiedEnvelopeContinuity(definition.value, context.receipt.value, context.previousEnvelope?.value);
1468
+ const chainChecks = await (0, fundValidation_1.verifyLPPositionReceiptEnvelopeChain)({
1469
+ envelopes: context.chainEntries.map((entry) => entry.value),
1470
+ expectedManagerXonly: definition.value.managerXonly,
1471
+ });
1204
1472
  const closing = await loadClosingDocument(sdk, {
1205
1473
  closingPath: input.closingPath,
1206
1474
  closingValue: input.closingValue,
1207
- positionReceipt: receipt.value.receipt,
1475
+ positionReceipt: context.receipt.value.receipt,
1208
1476
  closingId: input.closingId,
1209
1477
  finalDistributionHashes: input.finalDistributionHashes,
1210
1478
  closedAt: input.closedAt,
1211
1479
  closingReason: input.closingReason,
1212
1480
  });
1213
- const checks = (0, fundValidation_1.validateClosingAgainstReceipt)(receipt.value.receipt, closing.value);
1481
+ const checks = (0, fundValidation_1.validateClosingAgainstReceipt)(context.receipt.value.receipt, closing.value);
1214
1482
  return {
1215
- positionReceipt: receipt.descriptor,
1216
- positionReceiptValue: receipt.value,
1217
- positionReceiptSummary: receipt.receiptSummary,
1218
- positionReceiptEnvelopeSummary: receipt.envelopeSummary,
1483
+ positionReceipt: context.receipt.descriptor,
1484
+ positionReceiptValue: context.receipt.value,
1485
+ positionReceiptSummary: context.receipt.receiptSummary,
1486
+ positionReceiptEnvelopeSummary: context.receipt.envelopeSummary,
1487
+ ...(context.previousEnvelope
1488
+ ? {
1489
+ previousPositionReceipt: context.previousEnvelope.descriptor,
1490
+ previousPositionReceiptValue: context.previousEnvelope.value,
1491
+ previousPositionReceiptSummary: context.previousEnvelope.receiptSummary,
1492
+ previousPositionReceiptEnvelopeSummary: context.previousEnvelope.envelopeSummary,
1493
+ }
1494
+ : {}),
1495
+ ...(context.chainEntries.length > 0
1496
+ ? {
1497
+ positionReceiptChain: context.chainEntries.map((entry) => entry.descriptor),
1498
+ positionReceiptChainValues: context.chainEntries.map((entry) => entry.value),
1499
+ positionReceiptChainSummaries: context.chainEntries.map((entry) => entry.receiptSummary),
1500
+ positionReceiptEnvelopeChainSummaries: context.chainEntries.map((entry) => entry.envelopeSummary),
1501
+ }
1502
+ : {}),
1219
1503
  closing: closing.descriptor,
1220
1504
  closingValue: closing.value,
1221
1505
  closingSummary: closing.summary,
@@ -1226,26 +1510,67 @@ async function prepareClosing(sdk, input) {
1226
1510
  closingTrust: checks,
1227
1511
  receiptTrust: buildReceiptTrust({
1228
1512
  generated: false,
1229
- envelope: receipt.value,
1513
+ envelope: context.receipt.value,
1230
1514
  checks: receiptChecks,
1231
1515
  }),
1516
+ receiptChainTrust: buildReceiptChainTrust(chainChecks),
1232
1517
  },
1233
1518
  };
1234
1519
  }
1235
1520
  async function verifyClosing(sdk, input) {
1236
- const definition = input.definitionPath || input.definitionValue
1237
- ? await loadFundDefinitionDocument(sdk, input)
1521
+ const definition = await loadFundDefinitionDocument(sdk, input);
1522
+ const receipt = input.positionReceiptPath || input.positionReceiptValue
1523
+ ? await loadPositionReceiptEnvelopeDocument(sdk, input)
1238
1524
  : undefined;
1239
- const receipt = await loadPositionReceiptEnvelopeDocument(sdk, input);
1240
- const receiptChecks = definition ? ensureVerifiedEnvelope(definition.value, receipt.value) : (0, fundValidation_1.verifyLPPositionReceiptEnvelope)({ envelope: receipt.value });
1525
+ const previousEnvelope = input.previousPositionReceiptPath || input.previousPositionReceiptValue
1526
+ ? await loadPositionReceiptEnvelopeDocument(sdk, {
1527
+ positionReceiptPath: input.previousPositionReceiptPath,
1528
+ positionReceiptValue: input.previousPositionReceiptValue,
1529
+ })
1530
+ : undefined;
1531
+ const chainEntries = input.positionReceiptChainPaths || input.positionReceiptChainValues
1532
+ ? await loadPositionReceiptEnvelopeChainDocuments(sdk, {
1533
+ positionReceiptChainPaths: input.positionReceiptChainPaths,
1534
+ positionReceiptChainValues: input.positionReceiptChainValues,
1535
+ })
1536
+ : [];
1537
+ const context = resolveReceiptChainContext({
1538
+ receipt,
1539
+ previousEnvelope,
1540
+ chainEntries,
1541
+ });
1542
+ const receiptChecks = await ensureVerifiedEnvelopeContinuity(definition.value, context.receipt.value, context.previousEnvelope?.value);
1543
+ const chainChecks = await (0, fundValidation_1.verifyLPPositionReceiptEnvelopeChain)({
1544
+ envelopes: context.chainEntries.map((entry) => entry.value),
1545
+ expectedManagerXonly: definition.value.managerXonly,
1546
+ });
1241
1547
  const closing = await loadClosingDocument(sdk, { closingPath: input.closingPath, closingValue: input.closingValue });
1242
- const checks = (0, fundValidation_1.validateClosingAgainstReceipt)(receipt.value.receipt, closing.value);
1548
+ const checks = (0, fundValidation_1.validateClosingAgainstReceipt)(context.receipt.value.receipt, closing.value);
1243
1549
  return {
1244
1550
  verified: true,
1245
- positionReceipt: receipt.descriptor,
1246
- positionReceiptValue: receipt.value,
1247
- positionReceiptSummary: receipt.receiptSummary,
1248
- positionReceiptEnvelopeSummary: receipt.envelopeSummary,
1551
+ definition: definition.descriptor,
1552
+ definitionValue: definition.value,
1553
+ definitionSummary: definition.summary,
1554
+ positionReceipt: context.receipt.descriptor,
1555
+ positionReceiptValue: context.receipt.value,
1556
+ positionReceiptSummary: context.receipt.receiptSummary,
1557
+ positionReceiptEnvelopeSummary: context.receipt.envelopeSummary,
1558
+ ...(context.previousEnvelope
1559
+ ? {
1560
+ previousPositionReceipt: context.previousEnvelope.descriptor,
1561
+ previousPositionReceiptValue: context.previousEnvelope.value,
1562
+ previousPositionReceiptSummary: context.previousEnvelope.receiptSummary,
1563
+ previousPositionReceiptEnvelopeSummary: context.previousEnvelope.envelopeSummary,
1564
+ }
1565
+ : {}),
1566
+ ...(context.chainEntries.length > 0
1567
+ ? {
1568
+ positionReceiptChain: context.chainEntries.map((entry) => entry.descriptor),
1569
+ positionReceiptChainValues: context.chainEntries.map((entry) => entry.value),
1570
+ positionReceiptChainSummaries: context.chainEntries.map((entry) => entry.receiptSummary),
1571
+ positionReceiptEnvelopeChainSummaries: context.chainEntries.map((entry) => entry.envelopeSummary),
1572
+ }
1573
+ : {}),
1249
1574
  closing: closing.descriptor,
1250
1575
  closingValue: closing.value,
1251
1576
  closingSummary: closing.summary,
@@ -1253,7 +1578,8 @@ async function verifyClosing(sdk, input) {
1253
1578
  report: {
1254
1579
  ...buildBaseFundReport(),
1255
1580
  closingTrust: checks,
1256
- receiptTrust: buildReceiptTrust({ generated: false, envelope: receipt.value, checks: receiptChecks }),
1581
+ receiptTrust: buildReceiptTrust({ generated: false, envelope: context.receipt.value, checks: receiptChecks }),
1582
+ receiptChainTrust: buildReceiptChainTrust(chainChecks),
1257
1583
  },
1258
1584
  };
1259
1585
  }
@@ -1263,6 +1589,25 @@ async function exportEvidence(sdk, input) {
1263
1589
  const receipt = input.positionReceiptPath || input.positionReceiptValue
1264
1590
  ? await loadPositionReceiptEnvelopeDocument(sdk, input)
1265
1591
  : undefined;
1592
+ const previousEnvelope = input.previousPositionReceiptPath || input.previousPositionReceiptValue
1593
+ ? await loadPositionReceiptEnvelopeDocument(sdk, {
1594
+ positionReceiptPath: input.previousPositionReceiptPath,
1595
+ positionReceiptValue: input.previousPositionReceiptValue,
1596
+ })
1597
+ : undefined;
1598
+ const chainEntries = input.positionReceiptChainPaths || input.positionReceiptChainValues
1599
+ ? await loadPositionReceiptEnvelopeChainDocuments(sdk, {
1600
+ positionReceiptChainPaths: input.positionReceiptChainPaths,
1601
+ positionReceiptChainValues: input.positionReceiptChainValues,
1602
+ })
1603
+ : [];
1604
+ const receiptContext = receipt || chainEntries.length > 0
1605
+ ? resolveReceiptChainContext({
1606
+ receipt,
1607
+ previousEnvelope,
1608
+ chainEntries,
1609
+ })
1610
+ : undefined;
1266
1611
  const distributions = input.distributionPath || input.distributionValue || input.distributionPaths || input.distributionValues
1267
1612
  ? await loadDistributionDocuments(sdk, {
1268
1613
  distributionPath: input.distributionPath,
@@ -1277,11 +1622,11 @@ async function exportEvidence(sdk, input) {
1277
1622
  : undefined;
1278
1623
  const artifact = input.artifact ?? (input.artifactPath ? (await sdk.loadArtifact(input.artifactPath)).artifact : undefined);
1279
1624
  const trust = input.verificationReportValue
1280
- ?? (distribution && receipt && artifact
1625
+ ?? (distribution && receiptContext?.receipt && artifact
1281
1626
  ? (await verifyDistribution(sdk, {
1282
1627
  artifact,
1283
1628
  definitionValue: definition.value,
1284
- positionReceiptValue: receipt.value,
1629
+ positionReceiptValue: receiptContext.receipt.value,
1285
1630
  distributionValue: distribution.value,
1286
1631
  })).report
1287
1632
  : capitalCall && artifact
@@ -1290,16 +1635,20 @@ async function exportEvidence(sdk, input) {
1290
1635
  definitionValue: definition.value,
1291
1636
  capitalCallValue: capitalCall.value,
1292
1637
  })).report
1293
- : closing && receipt
1638
+ : closing && receiptContext?.receipt
1294
1639
  ? (await verifyClosing(sdk, {
1295
1640
  definitionValue: definition.value,
1296
- positionReceiptValue: receipt.value,
1641
+ positionReceiptValue: receiptContext.receipt.value,
1642
+ previousPositionReceiptValue: receiptContext.previousEnvelope?.value,
1643
+ positionReceiptChainValues: receiptContext.chainEntries.map((entry) => entry.value),
1297
1644
  closingValue: closing.value,
1298
1645
  })).report
1299
- : receipt
1646
+ : receiptContext?.receipt
1300
1647
  ? (await verifyPositionReceipt(sdk, {
1301
1648
  definitionValue: definition.value,
1302
- positionReceiptValue: receipt.value,
1649
+ positionReceiptValue: receiptContext.receipt.value,
1650
+ previousPositionReceiptValue: receiptContext.previousEnvelope?.value,
1651
+ positionReceiptChainValues: receiptContext.chainEntries.map((entry) => entry.value),
1303
1652
  })).report
1304
1653
  : buildBaseFundReport());
1305
1654
  const renderedSourceHash = artifact?.source.simfPath && (0, node_fs_1.existsSync)(artifact.source.simfPath)
@@ -1310,16 +1659,22 @@ async function exportEvidence(sdk, input) {
1310
1659
  ...(artifact ? { artifact } : {}),
1311
1660
  definition: definition.summary,
1312
1661
  ...(capitalCall ? { capitalCall: capitalCall.summary } : {}),
1313
- ...(receipt
1662
+ ...(receiptContext?.receipt
1314
1663
  ? {
1315
- positionReceipt: receipt.receiptSummary,
1316
- positionReceiptEnvelope: receipt.envelopeSummary,
1664
+ positionReceipt: receiptContext.receipt.receiptSummary,
1665
+ positionReceiptEnvelope: receiptContext.receipt.envelopeSummary,
1317
1666
  }
1318
1667
  : {}),
1319
1668
  ...(distribution ? { distribution: distribution.summary } : {}),
1320
1669
  ...(distributions.length > 1 ? { distributions: distributions.map((entry) => entry.summary) } : {}),
1321
1670
  ...(closing ? { closing: closing.summary } : {}),
1322
1671
  trust,
1672
+ trustSummary: (0, reporting_1.buildVerificationTrustSummary)({
1673
+ definitionTrust: trust.artifactTrust?.definition,
1674
+ stateTrust: trust.stateTrust,
1675
+ bindingMode: trust.outputBindingTrust?.mode ?? "none",
1676
+ lineageTrust: trust.receiptChainTrust,
1677
+ }),
1323
1678
  renderedSourceHash,
1324
1679
  sourceVerificationMode: renderedSourceHash ? "source-reloaded" : "artifact-only",
1325
1680
  ...(artifact
@@ -1340,6 +1695,25 @@ async function exportFinalityPayload(sdk, input) {
1340
1695
  const receipt = input.positionReceiptPath || input.positionReceiptValue
1341
1696
  ? await loadPositionReceiptEnvelopeDocument(sdk, input)
1342
1697
  : undefined;
1698
+ const previousEnvelope = input.previousPositionReceiptPath || input.previousPositionReceiptValue
1699
+ ? await loadPositionReceiptEnvelopeDocument(sdk, {
1700
+ positionReceiptPath: input.previousPositionReceiptPath,
1701
+ positionReceiptValue: input.previousPositionReceiptValue,
1702
+ })
1703
+ : undefined;
1704
+ const chainEntries = input.positionReceiptChainPaths || input.positionReceiptChainValues
1705
+ ? await loadPositionReceiptEnvelopeChainDocuments(sdk, {
1706
+ positionReceiptChainPaths: input.positionReceiptChainPaths,
1707
+ positionReceiptChainValues: input.positionReceiptChainValues,
1708
+ })
1709
+ : [];
1710
+ const receiptContext = receipt || chainEntries.length > 0
1711
+ ? resolveReceiptChainContext({
1712
+ receipt,
1713
+ previousEnvelope,
1714
+ chainEntries,
1715
+ })
1716
+ : undefined;
1343
1717
  const distributions = input.distributionPath || input.distributionValue || input.distributionPaths || input.distributionValues
1344
1718
  ? await loadDistributionDocuments(sdk, {
1345
1719
  distributionPath: input.distributionPath,
@@ -1352,7 +1726,7 @@ async function exportFinalityPayload(sdk, input) {
1352
1726
  const closing = input.closingPath || input.closingValue
1353
1727
  ? await loadClosingDocument(sdk, { closingPath: input.closingPath, closingValue: input.closingValue })
1354
1728
  : undefined;
1355
- const lpId = closing?.value.lpId ?? distribution?.value.lpId ?? receipt?.value.receipt.lpId ?? capitalCall?.value.lpId;
1729
+ const lpId = closing?.value.lpId ?? distribution?.value.lpId ?? receiptContext?.receipt.value.receipt.lpId ?? capitalCall?.value.lpId;
1356
1730
  if (!lpId) {
1357
1731
  throw new errors_1.ValidationError("Finality payload requires at least one LP-linked document", {
1358
1732
  code: "FUND_FINALITY_LP_ID_REQUIRED",
@@ -1363,22 +1737,20 @@ async function exportFinalityPayload(sdk, input) {
1363
1737
  fundId: definition.value.fundId,
1364
1738
  lpId,
1365
1739
  ...(capitalCall?.value.callId ? { callId: capitalCall.value.callId } : {}),
1366
- ...(receipt?.value.receipt.positionId ?? distribution?.value.positionId ?? closing?.value.positionId
1367
- ? { positionId: receipt?.value.receipt.positionId ?? distribution?.value.positionId ?? closing?.value.positionId }
1740
+ ...(receiptContext?.receipt.value.receipt.positionId ?? distribution?.value.positionId ?? closing?.value.positionId
1741
+ ? {
1742
+ positionId: receiptContext?.receipt.value.receipt.positionId ?? distribution?.value.positionId ?? closing?.value.positionId,
1743
+ }
1368
1744
  : {}),
1369
1745
  definitionHash: definition.summary.hash,
1370
1746
  capitalCallStateHash: capitalCall?.summary.hash ?? null,
1371
- positionReceiptHash: receipt?.receiptSummary.hash ?? null,
1372
- positionReceiptEnvelopeHash: receipt?.envelopeSummary.hash ?? null,
1747
+ positionReceiptHash: receiptContext?.receipt.receiptSummary.hash ?? null,
1748
+ positionReceiptEnvelopeHash: receiptContext?.receipt.envelopeSummary.hash ?? null,
1373
1749
  distributionHash: distribution?.summary.hash ?? null,
1374
1750
  distributionHashes: distributions.length > 0 ? distributions.map((entry) => entry.summary.hash) : null,
1375
1751
  closingHash: closing?.summary.hash ?? null,
1376
1752
  bindingMode: evidence.trust.outputBindingTrust?.mode ?? "none",
1377
1753
  trust: evidence.trust,
1378
- trustSummary: {
1379
- definition: evidence.trust.artifactTrust?.definition,
1380
- state: evidence.trust.stateTrust,
1381
- bindingMode: evidence.trust.outputBindingTrust?.mode ?? "none",
1382
- },
1754
+ trustSummary: evidence.trustSummary,
1383
1755
  };
1384
1756
  }