@sip-protocol/sdk 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.js CHANGED
@@ -32,11 +32,15 @@ var browser_exports = {};
32
32
  __export(browser_exports, {
33
33
  ATTESTATION_VERSION: () => ATTESTATION_VERSION,
34
34
  AptosStealthService: () => AptosStealthService,
35
+ AuditorKeyDerivation: () => AuditorKeyDerivation,
36
+ AuditorType: () => AuditorType,
35
37
  BaseWalletAdapter: () => BaseWalletAdapter,
36
38
  BrowserNoirProvider: () => BrowserNoirProvider,
37
39
  CHAIN_NUMERIC_IDS: () => CHAIN_NUMERIC_IDS,
38
40
  COSMOS_CHAIN_PREFIXES: () => CHAIN_PREFIXES,
39
41
  ComplianceManager: () => ComplianceManager,
42
+ ComplianceReporter: () => ComplianceReporter,
43
+ ConditionalDisclosure: () => ConditionalDisclosure,
40
44
  CosmosStealthService: () => CosmosStealthService,
41
45
  CryptoError: () => CryptoError,
42
46
  DEFAULT_THRESHOLD: () => DEFAULT_THRESHOLD,
@@ -89,6 +93,7 @@ __export(browser_exports, {
89
93
  SmartRouter: () => SmartRouter,
90
94
  SolanaWalletAdapter: () => SolanaWalletAdapter,
91
95
  SwapStatus: () => SwapStatus,
96
+ ThresholdViewingKey: () => ThresholdViewingKey,
92
97
  Treasury: () => Treasury,
93
98
  TrezorWalletAdapter: () => TrezorWalletAdapter,
94
99
  ValidationError: () => ValidationError,
@@ -177,6 +182,7 @@ __export(browser_exports, {
177
182
  generateEd25519StealthAddress: () => generateEd25519StealthAddress,
178
183
  generateEd25519StealthMetaAddress: () => generateEd25519StealthMetaAddress,
179
184
  generateIntentId: () => generateIntentId,
185
+ generatePdfReport: () => generatePdfReport,
180
186
  generateRandomBytes: () => generateRandomBytes,
181
187
  generateStealthAddress: () => generateStealthAddress,
182
188
  generateStealthMetaAddress: () => generateStealthMetaAddress,
@@ -316,6 +322,14 @@ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
316
322
  ErrorCode2["SIGNATURE_FAILED"] = "SIP_3005";
317
323
  ErrorCode2["INVALID_CURVE_POINT"] = "SIP_3006";
318
324
  ErrorCode2["INVALID_SCALAR"] = "SIP_3007";
325
+ ErrorCode2["INVALID_KEY_SIZE"] = "SIP_3008";
326
+ ErrorCode2["INVALID_ENCRYPTED_DATA"] = "SIP_3009";
327
+ ErrorCode2["INVALID_COMMITMENT"] = "SIP_3010";
328
+ ErrorCode2["INVALID_TIME_LOCK"] = "SIP_3011";
329
+ ErrorCode2["INVALID_SHARE"] = "SIP_3012";
330
+ ErrorCode2["INVALID_THRESHOLD"] = "SIP_3013";
331
+ ErrorCode2["CRYPTO_OPERATION_FAILED"] = "SIP_3014";
332
+ ErrorCode2["INVALID_FORMAT"] = "SIP_3015";
319
333
  ErrorCode2["PROOF_FAILED"] = "SIP_4000";
320
334
  ErrorCode2["PROOF_GENERATION_FAILED"] = "SIP_4001";
321
335
  ErrorCode2["PROOF_VERIFICATION_FAILED"] = "SIP_4002";
@@ -9239,6 +9253,79 @@ var ComplianceManager = class _ComplianceManager {
9239
9253
  getAllReports() {
9240
9254
  return Array.from(this.reports.values());
9241
9255
  }
9256
+ // ─── Dashboard Data API ──────────────────────────────────────────────────────
9257
+ /**
9258
+ * Get list of auditors for dashboard UI
9259
+ *
9260
+ * Returns a simplified view of auditors with essential info.
9261
+ * Alias for getAllAuditors() but returns AuditorRegistration directly.
9262
+ *
9263
+ * @returns Array of auditor registrations
9264
+ */
9265
+ getAuditorList() {
9266
+ return this.getAllAuditors();
9267
+ }
9268
+ /**
9269
+ * Get pending disclosure requests for dashboard
9270
+ *
9271
+ * Returns disclosure requests waiting for approval/denial.
9272
+ * This is for disclosure REQUESTS, not disclosed transactions.
9273
+ *
9274
+ * @returns Array of pending disclosure requests
9275
+ */
9276
+ getPendingDisclosures() {
9277
+ return this.getPendingRequests();
9278
+ }
9279
+ /**
9280
+ * Get disclosure history for a specific auditor
9281
+ *
9282
+ * Returns all disclosed transactions that were shared with this auditor,
9283
+ * sorted by disclosure date (most recent first).
9284
+ *
9285
+ * @param auditorId - Auditor ID to get history for
9286
+ * @returns Array of disclosed transactions for this auditor
9287
+ */
9288
+ getDisclosureHistory(auditorId) {
9289
+ return this.getDisclosedTransactions(auditorId).sort((a, b) => b.disclosedAt - a.disclosedAt);
9290
+ }
9291
+ /**
9292
+ * Get compliance metrics for dashboard
9293
+ *
9294
+ * Calculates key compliance metrics including:
9295
+ * - Total auditors (active + inactive)
9296
+ * - Total disclosures made
9297
+ * - Pending disclosure requests
9298
+ * - Approval rate (approved / total resolved requests)
9299
+ * - Average processing time for disclosure requests
9300
+ *
9301
+ * @returns Compliance metrics object
9302
+ */
9303
+ getComplianceMetrics() {
9304
+ const allAuditors = this.getAllAuditors();
9305
+ const allDisclosures = this.getDisclosedTransactions();
9306
+ const pendingRequests = this.getPendingRequests();
9307
+ const allRequests = Array.from(this.disclosureRequests.values());
9308
+ const resolvedRequests = allRequests.filter((r) => r.status !== "pending");
9309
+ const approvedRequests = resolvedRequests.filter((r) => r.status === "approved");
9310
+ const approvalRate = resolvedRequests.length > 0 ? approvedRequests.length / resolvedRequests.length : 0;
9311
+ let averageProcessingTime;
9312
+ if (resolvedRequests.length > 0) {
9313
+ const totalProcessingTime = resolvedRequests.reduce((sum, req) => {
9314
+ if (req.resolvedAt) {
9315
+ return sum + (req.resolvedAt - req.requestedAt);
9316
+ }
9317
+ return sum;
9318
+ }, 0);
9319
+ averageProcessingTime = totalProcessingTime / resolvedRequests.length;
9320
+ }
9321
+ return {
9322
+ totalAuditors: allAuditors.length,
9323
+ totalDisclosures: allDisclosures.length,
9324
+ pendingDisclosures: pendingRequests.length,
9325
+ approvalRate,
9326
+ averageProcessingTime
9327
+ };
9328
+ }
9242
9329
  // ─── Audit Log ───────────────────────────────────────────────────────────────
9243
9330
  /**
9244
9331
  * Get audit log entries
@@ -9437,147 +9524,1767 @@ var ComplianceManager = class _ComplianceManager {
9437
9524
  highRisk,
9438
9525
  flaggedTransactions: flagged
9439
9526
  }
9440
- };
9441
- if (includeTransactions) {
9442
- data.transactions = transactions;
9527
+ };
9528
+ if (includeTransactions) {
9529
+ data.transactions = transactions;
9530
+ }
9531
+ return data;
9532
+ }
9533
+ generateCSV(transactions) {
9534
+ const headers = [
9535
+ "Transaction ID",
9536
+ "Disclosure ID",
9537
+ "Type",
9538
+ "Direction",
9539
+ "Token",
9540
+ "Amount",
9541
+ "Sender",
9542
+ "Recipient",
9543
+ "Chain",
9544
+ "Privacy Level",
9545
+ "Timestamp",
9546
+ "TX Hash",
9547
+ "Block",
9548
+ "Risk Score",
9549
+ "Purpose",
9550
+ "Memo"
9551
+ ];
9552
+ const rows = transactions.map((tx) => [
9553
+ tx.transactionId,
9554
+ tx.disclosureId,
9555
+ tx.type,
9556
+ tx.direction,
9557
+ tx.token.symbol,
9558
+ tx.amount.toString(),
9559
+ tx.sender,
9560
+ tx.recipient,
9561
+ tx.chain,
9562
+ tx.privacyLevel,
9563
+ new Date(tx.timestamp * 1e3).toISOString(),
9564
+ tx.txHash,
9565
+ tx.blockNumber.toString(),
9566
+ tx.riskScore?.toString() ?? "",
9567
+ tx.purpose ?? "",
9568
+ tx.memo ?? ""
9569
+ ]);
9570
+ const escapeForCSV = (val) => {
9571
+ let escaped = val;
9572
+ if (/^[=+\-@|\t]/.test(escaped)) {
9573
+ escaped = `'${escaped}`;
9574
+ }
9575
+ return `"${escaped.replace(/"/g, '""')}"`;
9576
+ };
9577
+ const csvRows = [headers, ...rows].map((row) => row.map(escapeForCSV).join(","));
9578
+ return csvRows.join("\n");
9579
+ }
9580
+ };
9581
+ function generateId(prefix) {
9582
+ return `${prefix}_${(0, import_utils20.bytesToHex)((0, import_utils20.randomBytes)(12))}`;
9583
+ }
9584
+ function validateRegisterAuditorParams(params) {
9585
+ if (!params.organization?.trim()) {
9586
+ throw new ValidationError(
9587
+ "organization is required",
9588
+ "organization",
9589
+ void 0,
9590
+ "SIP_2008" /* MISSING_REQUIRED */
9591
+ );
9592
+ }
9593
+ if (!params.contactName?.trim()) {
9594
+ throw new ValidationError(
9595
+ "contact name is required",
9596
+ "contactName",
9597
+ void 0,
9598
+ "SIP_2008" /* MISSING_REQUIRED */
9599
+ );
9600
+ }
9601
+ if (!params.contactEmail?.trim()) {
9602
+ throw new ValidationError(
9603
+ "contact email is required",
9604
+ "contactEmail",
9605
+ void 0,
9606
+ "SIP_2008" /* MISSING_REQUIRED */
9607
+ );
9608
+ }
9609
+ if (!params.publicKey?.trim()) {
9610
+ throw new ValidationError(
9611
+ "public key is required",
9612
+ "publicKey",
9613
+ void 0,
9614
+ "SIP_2008" /* MISSING_REQUIRED */
9615
+ );
9616
+ }
9617
+ if (!params.scope) {
9618
+ throw new ValidationError(
9619
+ "audit scope is required",
9620
+ "scope",
9621
+ void 0,
9622
+ "SIP_2008" /* MISSING_REQUIRED */
9623
+ );
9624
+ }
9625
+ }
9626
+ function validateReportParams(params) {
9627
+ if (!params.title?.trim()) {
9628
+ throw new ValidationError(
9629
+ "report title is required",
9630
+ "title",
9631
+ void 0,
9632
+ "SIP_2008" /* MISSING_REQUIRED */
9633
+ );
9634
+ }
9635
+ if (!params.type) {
9636
+ throw new ValidationError(
9637
+ "report type is required",
9638
+ "type",
9639
+ void 0,
9640
+ "SIP_2008" /* MISSING_REQUIRED */
9641
+ );
9642
+ }
9643
+ if (!params.format) {
9644
+ throw new ValidationError(
9645
+ "report format is required",
9646
+ "format",
9647
+ void 0,
9648
+ "SIP_2008" /* MISSING_REQUIRED */
9649
+ );
9650
+ }
9651
+ if (params.startDate === void 0 || params.startDate === null || params.endDate === void 0 || params.endDate === null) {
9652
+ throw new ValidationError(
9653
+ "date range is required",
9654
+ "dateRange",
9655
+ void 0,
9656
+ "SIP_2008" /* MISSING_REQUIRED */
9657
+ );
9658
+ }
9659
+ if (params.startDate >= params.endDate) {
9660
+ throw new ValidationError(
9661
+ "start date must be before end date",
9662
+ "dateRange",
9663
+ void 0,
9664
+ "SIP_2001" /* INVALID_INPUT */
9665
+ );
9666
+ }
9667
+ }
9668
+
9669
+ // src/compliance/reports.ts
9670
+ var import_sha25615 = require("@noble/hashes/sha256");
9671
+ var import_utils21 = require("@noble/hashes/utils");
9672
+
9673
+ // src/compliance/pdf.ts
9674
+ function generatePdfReport(report, options = {}) {
9675
+ const {
9676
+ title = "SIP Protocol Audit Report",
9677
+ organization = "",
9678
+ includeTransactions = true,
9679
+ maxTransactions = 100
9680
+ } = options;
9681
+ const content = buildPdfContent(report, {
9682
+ title,
9683
+ organization,
9684
+ includeTransactions,
9685
+ maxTransactions
9686
+ });
9687
+ return generatePdfBinary(content, title);
9688
+ }
9689
+ function buildPdfContent(report, options) {
9690
+ const lines = [];
9691
+ lines.push(options.title);
9692
+ if (options.organization && options.organization.trim() !== "") {
9693
+ lines.push(`Organization: ${options.organization}`);
9694
+ }
9695
+ lines.push(`Report ID: ${report.reportId}`);
9696
+ lines.push(
9697
+ `Generated: ${report.generatedAt.toISOString().replace("T", " ").slice(0, 19)} UTC`
9698
+ );
9699
+ lines.push("");
9700
+ lines.push("Report Period");
9701
+ lines.push(` Start: ${formatDate(report.period.start)}`);
9702
+ lines.push(` End: ${formatDate(report.period.end)}`);
9703
+ lines.push("");
9704
+ lines.push("Summary Statistics");
9705
+ lines.push(` Total Transactions: ${report.summary.transactionCount}`);
9706
+ lines.push(
9707
+ ` Total Volume: ${formatBigInt(report.summary.totalVolume)}`
9708
+ );
9709
+ lines.push(
9710
+ ` Unique Counterparties: ${report.summary.uniqueCounterparties}`
9711
+ );
9712
+ lines.push("");
9713
+ if (options.includeTransactions && report.transactions.length > 0) {
9714
+ lines.push("Transaction Details");
9715
+ lines.push("");
9716
+ const txToShow = Math.min(
9717
+ report.transactions.length,
9718
+ options.maxTransactions
9719
+ );
9720
+ for (let i = 0; i < txToShow; i++) {
9721
+ const tx = report.transactions[i];
9722
+ lines.push(`Transaction ${i + 1}/${report.transactions.length}`);
9723
+ lines.push(` ID: ${tx.id}`);
9724
+ lines.push(` Sender: ${truncateAddress(tx.sender)}`);
9725
+ lines.push(` Recipient: ${truncateAddress(tx.recipient)}`);
9726
+ lines.push(` Amount: ${formatAmount(tx.amount)}`);
9727
+ lines.push(
9728
+ ` Timestamp: ${formatTimestamp(tx.timestamp)}`
9729
+ );
9730
+ if (tx.txHash) {
9731
+ lines.push(` Tx Hash: ${truncateHash(tx.txHash)}`);
9732
+ }
9733
+ if (tx.metadata && Object.keys(tx.metadata).length > 0) {
9734
+ lines.push(` Metadata: ${JSON.stringify(tx.metadata)}`);
9735
+ }
9736
+ lines.push("");
9737
+ }
9738
+ if (report.transactions.length > options.maxTransactions) {
9739
+ lines.push(
9740
+ `... and ${report.transactions.length - options.maxTransactions} more transactions`
9741
+ );
9742
+ lines.push("");
9743
+ }
9744
+ }
9745
+ lines.push("---");
9746
+ lines.push(
9747
+ "This report was generated by SIP Protocol compliance tools."
9748
+ );
9749
+ lines.push("For verification, please contact your compliance officer.");
9750
+ return lines.join("\n");
9751
+ }
9752
+ function generatePdfBinary(content, title) {
9753
+ const objects = [];
9754
+ objects.push(
9755
+ "1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj"
9756
+ );
9757
+ objects.push(
9758
+ "2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj"
9759
+ );
9760
+ objects.push(
9761
+ "3 0 obj\n<< /Type /Page /Parent 2 0 R /Resources 4 0 R /MediaBox [0 0 612 792] /Contents 5 0 R >>\nendobj"
9762
+ );
9763
+ objects.push(
9764
+ "4 0 obj\n<< /Font << /F1 << /Type /Font /Subtype /Type1 /BaseFont /Courier >> >> >>\nendobj"
9765
+ );
9766
+ const contentStream = buildContentStream(content);
9767
+ objects.push(
9768
+ `5 0 obj
9769
+ << /Length ${contentStream.length} >>
9770
+ stream
9771
+ ${contentStream}
9772
+ endstream
9773
+ endobj`
9774
+ );
9775
+ const now = /* @__PURE__ */ new Date();
9776
+ const pdfDate = formatPdfDate(now);
9777
+ objects.push(
9778
+ `6 0 obj
9779
+ << /Title (${title}) /Author (SIP Protocol) /Creator (SIP SDK) /CreationDate (${pdfDate}) >>
9780
+ endobj`
9781
+ );
9782
+ const pdfParts = [];
9783
+ pdfParts.push("%PDF-1.4\n%\xE2\xE3\xCF\xD3\n");
9784
+ const xrefOffsets = [0];
9785
+ let currentOffset = pdfParts.join("").length;
9786
+ for (const obj of objects) {
9787
+ xrefOffsets.push(currentOffset);
9788
+ pdfParts.push(obj + "\n");
9789
+ currentOffset = pdfParts.join("").length;
9790
+ }
9791
+ const xrefStart = currentOffset;
9792
+ pdfParts.push("xref\n");
9793
+ pdfParts.push(`0 ${xrefOffsets.length}
9794
+ `);
9795
+ for (let i = 0; i < xrefOffsets.length; i++) {
9796
+ if (i === 0) {
9797
+ pdfParts.push("0000000000 65535 f \n");
9798
+ } else {
9799
+ const offset = String(xrefOffsets[i]).padStart(10, "0");
9800
+ pdfParts.push(`${offset} 00000 n
9801
+ `);
9802
+ }
9803
+ }
9804
+ pdfParts.push("trailer\n");
9805
+ pdfParts.push(
9806
+ `<< /Size ${xrefOffsets.length} /Root 1 0 R /Info 6 0 R >>
9807
+ `
9808
+ );
9809
+ pdfParts.push("startxref\n");
9810
+ pdfParts.push(`${xrefStart}
9811
+ `);
9812
+ pdfParts.push("%%EOF");
9813
+ const pdfString = pdfParts.join("");
9814
+ const encoder = new TextEncoder();
9815
+ return encoder.encode(pdfString);
9816
+ }
9817
+ function buildContentStream(text) {
9818
+ const lines = text.split("\n");
9819
+ const commands = [];
9820
+ commands.push("BT");
9821
+ commands.push("/F1 10 Tf");
9822
+ commands.push("12 TL");
9823
+ let y = 742;
9824
+ for (const line of lines) {
9825
+ commands.push(`50 ${y} Td`);
9826
+ const escaped = escapePdfString(line);
9827
+ commands.push(`(${escaped}) Tj`);
9828
+ y -= 12;
9829
+ if (y < 50) {
9830
+ break;
9831
+ }
9832
+ }
9833
+ commands.push("ET");
9834
+ return commands.join("\n");
9835
+ }
9836
+ function escapePdfString(str) {
9837
+ return str.replace(/\\/g, "\\\\").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/\r/g, "\\r").replace(/\n/g, "\\n");
9838
+ }
9839
+ function formatPdfDate(date) {
9840
+ const year = date.getUTCFullYear();
9841
+ const month = String(date.getUTCMonth() + 1).padStart(2, "0");
9842
+ const day = String(date.getUTCDate()).padStart(2, "0");
9843
+ const hour = String(date.getUTCHours()).padStart(2, "0");
9844
+ const minute = String(date.getUTCMinutes()).padStart(2, "0");
9845
+ const second = String(date.getUTCSeconds()).padStart(2, "0");
9846
+ return `D:${year}${month}${day}${hour}${minute}${second}Z`;
9847
+ }
9848
+ function formatDate(date) {
9849
+ return date.toISOString().split("T")[0];
9850
+ }
9851
+ function formatBigInt(value) {
9852
+ return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
9853
+ }
9854
+ function formatAmount(amount) {
9855
+ try {
9856
+ const num = BigInt(amount);
9857
+ return formatBigInt(num);
9858
+ } catch {
9859
+ return amount;
9860
+ }
9861
+ }
9862
+ function formatTimestamp(timestamp) {
9863
+ const date = new Date(timestamp * 1e3);
9864
+ return date.toISOString().replace("T", " ").slice(0, 19) + " UTC";
9865
+ }
9866
+ function truncateAddress(address) {
9867
+ if (address.length <= 12) {
9868
+ return address;
9869
+ }
9870
+ return `${address.slice(0, 6)}...${address.slice(-4)}`;
9871
+ }
9872
+ function truncateHash(hash2) {
9873
+ if (hash2.length <= 16) {
9874
+ return hash2;
9875
+ }
9876
+ return `${hash2.slice(0, 8)}...${hash2.slice(-8)}`;
9877
+ }
9878
+
9879
+ // src/compliance/reports.ts
9880
+ var ComplianceReporter = class {
9881
+ /**
9882
+ * Generate an audit report from encrypted transactions
9883
+ *
9884
+ * Decrypts transactions using the provided viewing key, filters by date range,
9885
+ * and generates a comprehensive report with summary statistics.
9886
+ *
9887
+ * @param params - Report generation parameters
9888
+ * @returns Audit report with decrypted transactions and statistics
9889
+ * @throws {ValidationError} If parameters are invalid
9890
+ * @throws {CryptoError} If decryption fails
9891
+ */
9892
+ async generateAuditReport(params) {
9893
+ this.validateParams(params);
9894
+ const viewingKey = this.normalizeViewingKey(params.viewingKey);
9895
+ const decryptedTransactions = this.decryptTransactions(
9896
+ params.transactions,
9897
+ viewingKey,
9898
+ params.startDate,
9899
+ params.endDate
9900
+ );
9901
+ const summary = this.calculateSummary(decryptedTransactions);
9902
+ const period = this.determinePeriod(
9903
+ decryptedTransactions,
9904
+ params.startDate,
9905
+ params.endDate
9906
+ );
9907
+ const reportId = `audit_${generateRandomBytes(16).slice(2)}`;
9908
+ return {
9909
+ reportId,
9910
+ generatedAt: /* @__PURE__ */ new Date(),
9911
+ period,
9912
+ transactions: decryptedTransactions,
9913
+ summary
9914
+ };
9915
+ }
9916
+ /**
9917
+ * Validate report generation parameters
9918
+ */
9919
+ validateParams(params) {
9920
+ if (!params.viewingKey) {
9921
+ throw new ValidationError(
9922
+ "viewingKey is required",
9923
+ "viewingKey",
9924
+ void 0,
9925
+ "SIP_2008" /* MISSING_REQUIRED */
9926
+ );
9927
+ }
9928
+ if (!params.transactions) {
9929
+ throw new ValidationError(
9930
+ "transactions array is required",
9931
+ "transactions",
9932
+ void 0,
9933
+ "SIP_2008" /* MISSING_REQUIRED */
9934
+ );
9935
+ }
9936
+ if (!Array.isArray(params.transactions)) {
9937
+ throw new ValidationError(
9938
+ "transactions must be an array",
9939
+ "transactions",
9940
+ { received: typeof params.transactions },
9941
+ "SIP_2001" /* INVALID_INPUT */
9942
+ );
9943
+ }
9944
+ if (params.format !== "json" && params.format !== "pdf") {
9945
+ throw new ValidationError(
9946
+ "only JSON and PDF formats are supported",
9947
+ "format",
9948
+ { received: params.format },
9949
+ "SIP_2001" /* INVALID_INPUT */
9950
+ );
9951
+ }
9952
+ if (params.startDate && params.endDate) {
9953
+ if (params.startDate > params.endDate) {
9954
+ throw new ValidationError(
9955
+ "startDate must be before endDate",
9956
+ "startDate",
9957
+ {
9958
+ startDate: params.startDate.toISOString(),
9959
+ endDate: params.endDate.toISOString()
9960
+ },
9961
+ "SIP_2001" /* INVALID_INPUT */
9962
+ );
9963
+ }
9964
+ }
9965
+ }
9966
+ /**
9967
+ * Normalize viewing key to ViewingKey object
9968
+ */
9969
+ normalizeViewingKey(viewingKey) {
9970
+ if (typeof viewingKey === "string") {
9971
+ const keyHex = viewingKey.startsWith("0x") ? viewingKey.slice(2) : viewingKey;
9972
+ const keyBytes = (0, import_utils21.hexToBytes)(keyHex);
9973
+ const hashBytes = (0, import_sha25615.sha256)(keyBytes);
9974
+ return {
9975
+ key: `0x${keyHex}`,
9976
+ path: "m/0",
9977
+ hash: `0x${(0, import_utils21.bytesToHex)(hashBytes)}`
9978
+ };
9979
+ }
9980
+ return viewingKey;
9981
+ }
9982
+ /**
9983
+ * Decrypt transactions and filter by date range
9984
+ */
9985
+ decryptTransactions(encrypted, viewingKey, startDate, endDate) {
9986
+ const decrypted = [];
9987
+ const errors = [];
9988
+ for (let i = 0; i < encrypted.length; i++) {
9989
+ try {
9990
+ const txData = decryptWithViewing(encrypted[i], viewingKey);
9991
+ if (startDate || endDate) {
9992
+ const txDate = new Date(txData.timestamp * 1e3);
9993
+ if (startDate && txDate < startDate) {
9994
+ continue;
9995
+ }
9996
+ if (endDate && txDate > endDate) {
9997
+ continue;
9998
+ }
9999
+ }
10000
+ decrypted.push({
10001
+ id: `tx_${i}`,
10002
+ sender: txData.sender,
10003
+ recipient: txData.recipient,
10004
+ amount: txData.amount,
10005
+ timestamp: txData.timestamp
10006
+ });
10007
+ } catch (error) {
10008
+ errors.push({ index: i, error });
10009
+ }
10010
+ }
10011
+ if (decrypted.length === 0 && encrypted.length > 0) {
10012
+ throw new CryptoError(
10013
+ `Failed to decrypt any transactions. First error: ${errors[0]?.error.message}`,
10014
+ "SIP_3002" /* DECRYPTION_FAILED */,
10015
+ {
10016
+ context: {
10017
+ totalTransactions: encrypted.length,
10018
+ failedCount: errors.length
10019
+ }
10020
+ }
10021
+ );
10022
+ }
10023
+ return decrypted;
10024
+ }
10025
+ /**
10026
+ * Calculate summary statistics
10027
+ */
10028
+ calculateSummary(transactions) {
10029
+ let totalVolume = 0n;
10030
+ const counterparties = /* @__PURE__ */ new Set();
10031
+ for (const tx of transactions) {
10032
+ try {
10033
+ const amount = BigInt(tx.amount);
10034
+ totalVolume += amount;
10035
+ } catch (error) {
10036
+ console.warn(`Skipping invalid amount in transaction ${tx.id}: ${tx.amount}`);
10037
+ }
10038
+ counterparties.add(tx.sender);
10039
+ counterparties.add(tx.recipient);
10040
+ }
10041
+ return {
10042
+ totalVolume,
10043
+ transactionCount: transactions.length,
10044
+ uniqueCounterparties: counterparties.size
10045
+ };
10046
+ }
10047
+ /**
10048
+ * Determine report period from transactions and params
10049
+ */
10050
+ determinePeriod(transactions, startDate, endDate) {
10051
+ if (startDate && endDate) {
10052
+ return { start: startDate, end: endDate };
10053
+ }
10054
+ if (transactions.length === 0) {
10055
+ const now = /* @__PURE__ */ new Date();
10056
+ return { start: now, end: now };
10057
+ }
10058
+ let minTimestamp = transactions[0].timestamp;
10059
+ let maxTimestamp = transactions[0].timestamp;
10060
+ for (const tx of transactions) {
10061
+ if (tx.timestamp < minTimestamp) {
10062
+ minTimestamp = tx.timestamp;
10063
+ }
10064
+ if (tx.timestamp > maxTimestamp) {
10065
+ maxTimestamp = tx.timestamp;
10066
+ }
10067
+ }
10068
+ return {
10069
+ start: startDate || new Date(minTimestamp * 1e3),
10070
+ end: endDate || new Date(maxTimestamp * 1e3)
10071
+ };
10072
+ }
10073
+ /**
10074
+ * Export audit report to PDF format
10075
+ *
10076
+ * Generates a professionally formatted PDF document from an audit report.
10077
+ * Works in both Node.js and browser environments.
10078
+ *
10079
+ * @param report - The audit report to export
10080
+ * @param options - PDF export options
10081
+ * @returns PDF document as Uint8Array
10082
+ *
10083
+ * @example
10084
+ * ```typescript
10085
+ * const reporter = new ComplianceReporter()
10086
+ * const report = await reporter.generateAuditReport({...})
10087
+ *
10088
+ * const pdfBytes = reporter.exportToPdf(report, {
10089
+ * title: 'Q1 2025 Audit Report',
10090
+ * organization: 'ACME Corp',
10091
+ * })
10092
+ *
10093
+ * // Save to file (Node.js)
10094
+ * fs.writeFileSync('report.pdf', pdfBytes)
10095
+ * ```
10096
+ */
10097
+ exportToPdf(report, options) {
10098
+ return generatePdfReport(report, options);
10099
+ }
10100
+ /**
10101
+ * Export transactions to regulatory compliance formats
10102
+ *
10103
+ * Decrypts and exports transactions in formats required by regulators:
10104
+ * - FATF: Financial Action Task Force Travel Rule format
10105
+ * - FINCEN: FinCEN Suspicious Activity Report (SAR) format
10106
+ * - CSV: Generic comma-separated values format
10107
+ *
10108
+ * @param params - Export parameters
10109
+ * @returns Regulatory export in the specified format
10110
+ * @throws {ValidationError} If parameters are invalid
10111
+ * @throws {CryptoError} If decryption fails
10112
+ *
10113
+ * @example
10114
+ * ```typescript
10115
+ * const reporter = new ComplianceReporter()
10116
+ *
10117
+ * // FATF Travel Rule export
10118
+ * const fatfExport = await reporter.exportForRegulator({
10119
+ * viewingKey: myViewingKey,
10120
+ * transactions: encryptedTxs,
10121
+ * jurisdiction: 'EU',
10122
+ * format: 'FATF',
10123
+ * currency: 'EUR',
10124
+ * })
10125
+ *
10126
+ * // FINCEN SAR export (US only)
10127
+ * const fincenExport = await reporter.exportForRegulator({
10128
+ * viewingKey: myViewingKey,
10129
+ * transactions: suspiciousTxs,
10130
+ * jurisdiction: 'US',
10131
+ * format: 'FINCEN',
10132
+ * })
10133
+ *
10134
+ * // CSV export
10135
+ * const csvExport = await reporter.exportForRegulator({
10136
+ * viewingKey: myViewingKey,
10137
+ * transactions: encryptedTxs,
10138
+ * jurisdiction: 'SG',
10139
+ * format: 'CSV',
10140
+ * })
10141
+ * ```
10142
+ */
10143
+ async exportForRegulator(params) {
10144
+ this.validateRegulatoryParams(params);
10145
+ const viewingKey = this.normalizeViewingKey(params.viewingKey);
10146
+ const decryptedTransactions = this.decryptTransactions(
10147
+ params.transactions,
10148
+ viewingKey,
10149
+ params.startDate,
10150
+ params.endDate
10151
+ );
10152
+ const reportId = `reg_${generateRandomBytes(16).slice(2)}`;
10153
+ switch (params.format) {
10154
+ case "FATF":
10155
+ return this.exportToFATF(
10156
+ reportId,
10157
+ decryptedTransactions,
10158
+ params.jurisdiction,
10159
+ params.currency || "USD"
10160
+ );
10161
+ case "FINCEN":
10162
+ return this.exportToFINCEN(
10163
+ reportId,
10164
+ decryptedTransactions,
10165
+ params.startDate,
10166
+ params.endDate,
10167
+ params.currency || "USD"
10168
+ );
10169
+ case "CSV":
10170
+ return this.exportToCSV(
10171
+ reportId,
10172
+ decryptedTransactions,
10173
+ params.jurisdiction,
10174
+ params.currency || "USD"
10175
+ );
10176
+ default:
10177
+ throw new ValidationError(
10178
+ `unsupported format: ${params.format}`,
10179
+ "format",
10180
+ { received: params.format },
10181
+ "SIP_2001" /* INVALID_INPUT */
10182
+ );
10183
+ }
10184
+ }
10185
+ /**
10186
+ * Validate regulatory export parameters
10187
+ */
10188
+ validateRegulatoryParams(params) {
10189
+ if (!params.viewingKey) {
10190
+ throw new ValidationError(
10191
+ "viewingKey is required",
10192
+ "viewingKey",
10193
+ void 0,
10194
+ "SIP_2008" /* MISSING_REQUIRED */
10195
+ );
10196
+ }
10197
+ if (!params.transactions) {
10198
+ throw new ValidationError(
10199
+ "transactions array is required",
10200
+ "transactions",
10201
+ void 0,
10202
+ "SIP_2008" /* MISSING_REQUIRED */
10203
+ );
10204
+ }
10205
+ if (!Array.isArray(params.transactions)) {
10206
+ throw new ValidationError(
10207
+ "transactions must be an array",
10208
+ "transactions",
10209
+ { received: typeof params.transactions },
10210
+ "SIP_2001" /* INVALID_INPUT */
10211
+ );
10212
+ }
10213
+ if (!params.jurisdiction) {
10214
+ throw new ValidationError(
10215
+ "jurisdiction is required",
10216
+ "jurisdiction",
10217
+ void 0,
10218
+ "SIP_2008" /* MISSING_REQUIRED */
10219
+ );
10220
+ }
10221
+ const validJurisdictions = ["US", "EU", "UK", "SG"];
10222
+ if (!validJurisdictions.includes(params.jurisdiction)) {
10223
+ throw new ValidationError(
10224
+ `invalid jurisdiction. Must be one of: ${validJurisdictions.join(", ")}`,
10225
+ "jurisdiction",
10226
+ { received: params.jurisdiction },
10227
+ "SIP_2001" /* INVALID_INPUT */
10228
+ );
10229
+ }
10230
+ if (!params.format) {
10231
+ throw new ValidationError(
10232
+ "format is required",
10233
+ "format",
10234
+ void 0,
10235
+ "SIP_2008" /* MISSING_REQUIRED */
10236
+ );
10237
+ }
10238
+ const validFormats = ["FATF", "FINCEN", "CSV"];
10239
+ if (!validFormats.includes(params.format)) {
10240
+ throw new ValidationError(
10241
+ `invalid format. Must be one of: ${validFormats.join(", ")}`,
10242
+ "format",
10243
+ { received: params.format },
10244
+ "SIP_2001" /* INVALID_INPUT */
10245
+ );
10246
+ }
10247
+ if (params.format === "FINCEN" && params.jurisdiction !== "US") {
10248
+ throw new ValidationError(
10249
+ "FINCEN format is only available for US jurisdiction",
10250
+ "format",
10251
+ { jurisdiction: params.jurisdiction, format: params.format },
10252
+ "SIP_2001" /* INVALID_INPUT */
10253
+ );
10254
+ }
10255
+ if (params.startDate && params.endDate) {
10256
+ if (params.startDate > params.endDate) {
10257
+ throw new ValidationError(
10258
+ "startDate must be before endDate",
10259
+ "startDate",
10260
+ {
10261
+ startDate: params.startDate.toISOString(),
10262
+ endDate: params.endDate.toISOString()
10263
+ },
10264
+ "SIP_2001" /* INVALID_INPUT */
10265
+ );
10266
+ }
10267
+ }
10268
+ }
10269
+ /**
10270
+ * Export to FATF Travel Rule format
10271
+ */
10272
+ exportToFATF(reportId, transactions, jurisdiction, currency) {
10273
+ const fatfTransactions = transactions.map((tx) => ({
10274
+ originatorAccount: tx.sender,
10275
+ beneficiaryAccount: tx.recipient,
10276
+ amount: tx.amount,
10277
+ currency,
10278
+ transactionRef: tx.id,
10279
+ timestamp: new Date(tx.timestamp * 1e3).toISOString()
10280
+ }));
10281
+ return {
10282
+ reportId,
10283
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
10284
+ jurisdiction,
10285
+ transactions: fatfTransactions
10286
+ };
10287
+ }
10288
+ /**
10289
+ * Export to FINCEN SAR format
10290
+ */
10291
+ exportToFINCEN(reportId, transactions, startDate, endDate, currency = "USD") {
10292
+ let totalAmount = 0n;
10293
+ for (const tx of transactions) {
10294
+ try {
10295
+ totalAmount += BigInt(tx.amount);
10296
+ } catch (error) {
10297
+ }
10298
+ }
10299
+ const period = this.determinePeriod(transactions, startDate, endDate);
10300
+ const fincenTransactions = transactions.map((tx) => ({
10301
+ transactionDate: new Date(tx.timestamp * 1e3).toISOString(),
10302
+ amount: tx.amount,
10303
+ currency,
10304
+ narrativeSummary: `Transfer from ${tx.sender} to ${tx.recipient}`,
10305
+ transactionRef: tx.id,
10306
+ parties: {
10307
+ sender: tx.sender,
10308
+ recipient: tx.recipient
10309
+ }
10310
+ }));
10311
+ return {
10312
+ reportId,
10313
+ filingType: "SAR",
10314
+ reportDate: (/* @__PURE__ */ new Date()).toISOString(),
10315
+ jurisdiction: "US",
10316
+ summary: {
10317
+ transactionCount: transactions.length,
10318
+ totalAmount: totalAmount.toString(),
10319
+ period: {
10320
+ start: period.start.toISOString(),
10321
+ end: period.end.toISOString()
10322
+ }
10323
+ },
10324
+ transactions: fincenTransactions
10325
+ };
10326
+ }
10327
+ /**
10328
+ * Export to CSV format
10329
+ */
10330
+ exportToCSV(reportId, transactions, jurisdiction, currency) {
10331
+ const headers = [
10332
+ "Transaction ID",
10333
+ "Timestamp",
10334
+ "Sender",
10335
+ "Recipient",
10336
+ "Amount",
10337
+ "Currency"
10338
+ ];
10339
+ const rows = transactions.map((tx) => [
10340
+ tx.id,
10341
+ new Date(tx.timestamp * 1e3).toISOString(),
10342
+ tx.sender,
10343
+ tx.recipient,
10344
+ tx.amount,
10345
+ currency
10346
+ ]);
10347
+ return {
10348
+ reportId,
10349
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
10350
+ jurisdiction,
10351
+ headers,
10352
+ rows
10353
+ };
10354
+ }
10355
+ };
10356
+
10357
+ // src/compliance/conditional.ts
10358
+ var import_sha25616 = require("@noble/hashes/sha256");
10359
+ var import_utils22 = require("@noble/hashes/utils");
10360
+ var import_chacha3 = require("@noble/ciphers/chacha.js");
10361
+ var ConditionalDisclosure = class {
10362
+ /**
10363
+ * Create a time-locked disclosure
10364
+ *
10365
+ * Encrypts the viewing key with a deterministic key derived from
10366
+ * the commitment and reveal time. The key can only be reconstructed
10367
+ * after the specified time/block height.
10368
+ *
10369
+ * @param params - Time-lock parameters
10370
+ * @returns Time-lock result with encrypted key
10371
+ * @throws {ValidationError} If parameters are invalid
10372
+ * @throws {CryptoError} If encryption fails
10373
+ */
10374
+ createTimeLocked(params) {
10375
+ if (!params.viewingKey || !params.viewingKey.startsWith("0x")) {
10376
+ throw new ValidationError(
10377
+ "Invalid viewing key format",
10378
+ "viewingKey",
10379
+ { viewingKey: params.viewingKey },
10380
+ "SIP_2006" /* INVALID_KEY */
10381
+ );
10382
+ }
10383
+ if (!params.commitment || !params.commitment.startsWith("0x")) {
10384
+ throw new ValidationError(
10385
+ "Invalid commitment format",
10386
+ "commitment",
10387
+ { commitment: params.commitment },
10388
+ "SIP_3010" /* INVALID_COMMITMENT */
10389
+ );
10390
+ }
10391
+ let revealAfterSeconds;
10392
+ let type;
10393
+ if (params.revealAfter instanceof Date) {
10394
+ revealAfterSeconds = Math.floor(params.revealAfter.getTime() / 1e3);
10395
+ type = "timestamp";
10396
+ } else if (typeof params.revealAfter === "number") {
10397
+ if (params.revealAfter > 1e10) {
10398
+ revealAfterSeconds = Math.floor(params.revealAfter / 1e3);
10399
+ type = "timestamp";
10400
+ } else {
10401
+ revealAfterSeconds = params.revealAfter;
10402
+ type = "blockheight";
10403
+ }
10404
+ if (revealAfterSeconds <= 0) {
10405
+ throw new ValidationError(
10406
+ "Reveal time/block height must be positive",
10407
+ "revealAfter",
10408
+ { revealAfter: revealAfterSeconds },
10409
+ "SIP_3011" /* INVALID_TIME_LOCK */
10410
+ );
10411
+ }
10412
+ } else {
10413
+ throw new ValidationError(
10414
+ "Invalid revealAfter type (must be Date or number)",
10415
+ "revealAfter",
10416
+ { revealAfter: params.revealAfter },
10417
+ "SIP_3011" /* INVALID_TIME_LOCK */
10418
+ );
10419
+ }
10420
+ try {
10421
+ const encryptionKey = this._deriveEncryptionKey(
10422
+ params.commitment,
10423
+ revealAfterSeconds
10424
+ );
10425
+ const nonce = (0, import_utils22.randomBytes)(24);
10426
+ const viewingKeyBytes = (0, import_utils22.hexToBytes)(params.viewingKey.slice(2));
10427
+ const cipher = (0, import_chacha3.xchacha20poly1305)(encryptionKey, nonce);
10428
+ const encryptedKey = cipher.encrypt(viewingKeyBytes);
10429
+ const commitmentData = new Uint8Array([
10430
+ ...viewingKeyBytes,
10431
+ ...this._numberToBytes(revealAfterSeconds)
10432
+ ]);
10433
+ const commitmentHash = (0, import_sha25616.sha256)(commitmentData);
10434
+ return {
10435
+ encryptedKey: "0x" + (0, import_utils22.bytesToHex)(encryptedKey),
10436
+ nonce: "0x" + (0, import_utils22.bytesToHex)(nonce),
10437
+ revealAfter: revealAfterSeconds,
10438
+ verificationCommitment: "0x" + (0, import_utils22.bytesToHex)(commitmentHash),
10439
+ encryptionCommitment: params.commitment,
10440
+ type
10441
+ };
10442
+ } catch (error) {
10443
+ if (error instanceof ValidationError) {
10444
+ throw error;
10445
+ }
10446
+ throw new CryptoError(
10447
+ "Failed to create time-locked disclosure",
10448
+ "SIP_3001" /* ENCRYPTION_FAILED */,
10449
+ {
10450
+ cause: error instanceof Error ? error : void 0,
10451
+ operation: "createTimeLocked"
10452
+ }
10453
+ );
10454
+ }
10455
+ }
10456
+ /**
10457
+ * Check if a time-lock is unlocked and retrieve the viewing key
10458
+ *
10459
+ * @param timeLock - Time-lock result to check
10460
+ * @param currentTimeOrBlock - Current time (Date/number) or block height (number)
10461
+ * @returns Unlock result with viewing key if unlocked
10462
+ * @throws {ValidationError} If time-lock format is invalid
10463
+ * @throws {CryptoError} If decryption fails
10464
+ */
10465
+ checkUnlocked(timeLock, currentTimeOrBlock) {
10466
+ if (!timeLock.encryptedKey || !timeLock.encryptedKey.startsWith("0x")) {
10467
+ throw new ValidationError(
10468
+ "Invalid encrypted key format",
10469
+ "encryptedKey",
10470
+ { encryptedKey: timeLock.encryptedKey },
10471
+ "SIP_3009" /* INVALID_ENCRYPTED_DATA */
10472
+ );
10473
+ }
10474
+ if (!timeLock.nonce || !timeLock.nonce.startsWith("0x")) {
10475
+ throw new ValidationError(
10476
+ "Invalid nonce format",
10477
+ "nonce",
10478
+ { nonce: timeLock.nonce },
10479
+ "SIP_3009" /* INVALID_ENCRYPTED_DATA */
10480
+ );
10481
+ }
10482
+ if (!timeLock.verificationCommitment || !timeLock.verificationCommitment.startsWith("0x")) {
10483
+ throw new ValidationError(
10484
+ "Invalid verification commitment format",
10485
+ "verificationCommitment",
10486
+ { commitment: timeLock.verificationCommitment },
10487
+ "SIP_3010" /* INVALID_COMMITMENT */
10488
+ );
10489
+ }
10490
+ if (!timeLock.encryptionCommitment || !timeLock.encryptionCommitment.startsWith("0x")) {
10491
+ throw new ValidationError(
10492
+ "Invalid encryption commitment format",
10493
+ "encryptionCommitment",
10494
+ { commitment: timeLock.encryptionCommitment },
10495
+ "SIP_3010" /* INVALID_COMMITMENT */
10496
+ );
10497
+ }
10498
+ let currentValue;
10499
+ if (currentTimeOrBlock instanceof Date) {
10500
+ currentValue = Math.floor(currentTimeOrBlock.getTime() / 1e3);
10501
+ } else if (typeof currentTimeOrBlock === "number") {
10502
+ currentValue = currentTimeOrBlock;
10503
+ } else {
10504
+ currentValue = Math.floor(Date.now() / 1e3);
10505
+ }
10506
+ const unlocked = currentValue >= timeLock.revealAfter;
10507
+ if (!unlocked) {
10508
+ return { unlocked: false };
10509
+ }
10510
+ try {
10511
+ const encryptionKey = this._deriveEncryptionKey(
10512
+ timeLock.encryptionCommitment,
10513
+ timeLock.revealAfter
10514
+ );
10515
+ const nonce = (0, import_utils22.hexToBytes)(timeLock.nonce.slice(2));
10516
+ const encryptedData = (0, import_utils22.hexToBytes)(timeLock.encryptedKey.slice(2));
10517
+ const cipher = (0, import_chacha3.xchacha20poly1305)(encryptionKey, nonce);
10518
+ const decryptedBytes = cipher.decrypt(encryptedData);
10519
+ const viewingKey = "0x" + (0, import_utils22.bytesToHex)(decryptedBytes);
10520
+ return {
10521
+ unlocked: true,
10522
+ viewingKey
10523
+ };
10524
+ } catch (error) {
10525
+ if (error instanceof ValidationError || error instanceof CryptoError) {
10526
+ throw error;
10527
+ }
10528
+ throw new CryptoError(
10529
+ "Failed to decrypt time-locked viewing key",
10530
+ "SIP_3002" /* DECRYPTION_FAILED */,
10531
+ {
10532
+ cause: error instanceof Error ? error : void 0,
10533
+ operation: "checkUnlocked"
10534
+ }
10535
+ );
10536
+ }
10537
+ }
10538
+ /**
10539
+ * Verify a time-lock commitment
10540
+ *
10541
+ * Verifies that the verification commitment in the time-lock matches the hash
10542
+ * of the provided viewing key and reveal time.
10543
+ *
10544
+ * @param timeLock - Time-lock to verify
10545
+ * @param viewingKey - Viewing key to verify against
10546
+ * @returns True if commitment is valid
10547
+ */
10548
+ verifyCommitment(timeLock, viewingKey) {
10549
+ try {
10550
+ const viewingKeyBytes = (0, import_utils22.hexToBytes)(viewingKey.slice(2));
10551
+ const commitmentData = new Uint8Array([
10552
+ ...viewingKeyBytes,
10553
+ ...this._numberToBytes(timeLock.revealAfter)
10554
+ ]);
10555
+ const expectedCommitment = (0, import_sha25616.sha256)(commitmentData);
10556
+ const actualCommitment = (0, import_utils22.hexToBytes)(timeLock.verificationCommitment.slice(2));
10557
+ if (expectedCommitment.length !== actualCommitment.length) {
10558
+ return false;
10559
+ }
10560
+ let diff = 0;
10561
+ for (let i = 0; i < expectedCommitment.length; i++) {
10562
+ diff |= expectedCommitment[i] ^ actualCommitment[i];
10563
+ }
10564
+ return diff === 0;
10565
+ } catch {
10566
+ return false;
10567
+ }
10568
+ }
10569
+ /**
10570
+ * Derive deterministic encryption key from commitment and reveal time
10571
+ *
10572
+ * @private
10573
+ */
10574
+ _deriveEncryptionKey(commitment, revealAfter) {
10575
+ const commitmentBytes = (0, import_utils22.hexToBytes)(commitment.slice(2));
10576
+ const timeBytes = this._numberToBytes(revealAfter);
10577
+ const combined = new Uint8Array([...commitmentBytes, ...timeBytes]);
10578
+ const key = (0, import_sha25616.sha256)(combined);
10579
+ if (key.length !== 32) {
10580
+ throw new CryptoError(
10581
+ "Derived key must be 32 bytes",
10582
+ "SIP_3008" /* INVALID_KEY_SIZE */,
10583
+ {
10584
+ context: { actualSize: key.length, expectedSize: 32 },
10585
+ operation: "_deriveEncryptionKey"
10586
+ }
10587
+ );
10588
+ }
10589
+ return key;
10590
+ }
10591
+ /**
10592
+ * Convert number to 8-byte big-endian representation
10593
+ *
10594
+ * @private
10595
+ */
10596
+ _numberToBytes(num) {
10597
+ const bytes = new Uint8Array(8);
10598
+ const view = new DataView(bytes.buffer);
10599
+ view.setBigUint64(0, BigInt(Math.floor(num)), false);
10600
+ return bytes;
10601
+ }
10602
+ };
10603
+
10604
+ // src/compliance/conditional-threshold.ts
10605
+ var import_secp256k17 = require("@noble/curves/secp256k1");
10606
+ var import_sha25617 = require("@noble/hashes/sha256");
10607
+ var import_utils23 = require("@noble/hashes/utils");
10608
+ var CURVE_ORDER2 = import_secp256k17.secp256k1.CURVE.n;
10609
+
10610
+ // src/compliance/threshold.ts
10611
+ var import_sha25618 = require("@noble/hashes/sha256");
10612
+ var import_utils24 = require("@noble/hashes/utils");
10613
+ var FIELD_PRIME = 2n ** 256n - 189n;
10614
+ var ThresholdViewingKey = class {
10615
+ /**
10616
+ * Create threshold shares from a viewing key
10617
+ *
10618
+ * @param params - Configuration parameters
10619
+ * @returns Threshold shares with commitment
10620
+ * @throws ValidationError if parameters are invalid
10621
+ *
10622
+ * @example
10623
+ * ```typescript
10624
+ * const threshold = ThresholdViewingKey.create({
10625
+ * threshold: 3,
10626
+ * totalShares: 5,
10627
+ * viewingKey: '0xabc123...',
10628
+ * })
10629
+ * ```
10630
+ */
10631
+ static create(params) {
10632
+ this.validateParams(params.threshold, params.totalShares);
10633
+ this.validateViewingKey(params.viewingKey);
10634
+ const secret = this.viewingKeyToSecret(params.viewingKey);
10635
+ const keyLength = params.viewingKey.slice(2).length;
10636
+ const coefficients = this.generateCoefficients(params.threshold, secret);
10637
+ const commitment = this.createCommitment(secret, coefficients);
10638
+ const shares = [];
10639
+ for (let i = 1; i <= params.totalShares; i++) {
10640
+ const x = BigInt(i);
10641
+ const y = this.evaluatePolynomial(coefficients, x);
10642
+ shares.push(this.encodeShare(x, y, keyLength, commitment));
10643
+ }
10644
+ return {
10645
+ shares,
10646
+ commitment,
10647
+ threshold: params.threshold,
10648
+ totalShares: params.totalShares
10649
+ };
10650
+ }
10651
+ /**
10652
+ * Reconstruct viewing key from threshold shares
10653
+ *
10654
+ * @param shares - Array of encoded shares (must be >= threshold)
10655
+ * @returns Reconstructed viewing key
10656
+ * @throws ValidationError if insufficient or invalid shares
10657
+ *
10658
+ * @example
10659
+ * ```typescript
10660
+ * const viewingKey = ThresholdViewingKey.reconstruct([
10661
+ * 'share1',
10662
+ * 'share2',
10663
+ * 'share3',
10664
+ * ])
10665
+ * ```
10666
+ */
10667
+ static reconstruct(shares) {
10668
+ if (!shares || shares.length === 0) {
10669
+ throw new ValidationError(
10670
+ "at least one share is required",
10671
+ "shares",
10672
+ { received: shares },
10673
+ "SIP_2008" /* MISSING_REQUIRED */
10674
+ );
10675
+ }
10676
+ const decodedShares = shares.map((s) => this.decodeShare(s));
10677
+ const commitment = decodedShares[0].commitment;
10678
+ const keyLength = decodedShares[0].keyLength;
10679
+ for (const share of decodedShares) {
10680
+ if (share.commitment !== commitment) {
10681
+ throw new ValidationError(
10682
+ "shares must all have the same commitment",
10683
+ "shares",
10684
+ { commitment },
10685
+ "SIP_3012" /* INVALID_SHARE */
10686
+ );
10687
+ }
10688
+ if (share.keyLength !== keyLength) {
10689
+ throw new ValidationError(
10690
+ "shares must all have the same key length",
10691
+ "shares",
10692
+ { keyLength },
10693
+ "SIP_3012" /* INVALID_SHARE */
10694
+ );
10695
+ }
10696
+ }
10697
+ const xCoords = new Set(decodedShares.map((s) => s.x.toString()));
10698
+ if (xCoords.size !== decodedShares.length) {
10699
+ throw new ValidationError(
10700
+ "shares must have unique x-coordinates",
10701
+ "shares",
10702
+ void 0,
10703
+ "SIP_3012" /* INVALID_SHARE */
10704
+ );
10705
+ }
10706
+ const secret = this.lagrangeInterpolate(decodedShares);
10707
+ return this.secretToViewingKey(secret, keyLength);
10708
+ }
10709
+ /**
10710
+ * Verify a share without revealing the viewing key
10711
+ *
10712
+ * @param share - Encoded share to verify
10713
+ * @param expectedCommitment - Expected commitment hash
10714
+ * @returns True if share is valid
10715
+ *
10716
+ * @example
10717
+ * ```typescript
10718
+ * const isValid = ThresholdViewingKey.verifyShare(
10719
+ * 'share1',
10720
+ * 'commitment_hash'
10721
+ * )
10722
+ * ```
10723
+ */
10724
+ static verifyShare(share, expectedCommitment) {
10725
+ try {
10726
+ const decoded = this.decodeShare(share);
10727
+ return decoded.commitment === expectedCommitment;
10728
+ } catch {
10729
+ return false;
10730
+ }
10731
+ }
10732
+ // ─── Private Helper Methods ─────────────────────────────────────────────────
10733
+ /**
10734
+ * Validate threshold and total shares parameters
10735
+ */
10736
+ static validateParams(threshold, totalShares) {
10737
+ if (!Number.isInteger(threshold) || threshold < 2) {
10738
+ throw new ValidationError(
10739
+ "threshold must be an integer >= 2",
10740
+ "threshold",
10741
+ { received: threshold },
10742
+ "SIP_3013" /* INVALID_THRESHOLD */
10743
+ );
10744
+ }
10745
+ if (!Number.isInteger(totalShares) || totalShares < threshold) {
10746
+ throw new ValidationError(
10747
+ "totalShares must be an integer >= threshold",
10748
+ "totalShares",
10749
+ { received: totalShares, threshold },
10750
+ "SIP_3013" /* INVALID_THRESHOLD */
10751
+ );
10752
+ }
10753
+ if (totalShares > 255) {
10754
+ throw new ValidationError(
10755
+ "totalShares must be <= 255",
10756
+ "totalShares",
10757
+ { received: totalShares },
10758
+ "SIP_3013" /* INVALID_THRESHOLD */
10759
+ );
10760
+ }
10761
+ }
10762
+ /**
10763
+ * Validate viewing key format
10764
+ */
10765
+ static validateViewingKey(viewingKey) {
10766
+ if (!viewingKey || typeof viewingKey !== "string") {
10767
+ throw new ValidationError(
10768
+ "viewingKey is required",
10769
+ "viewingKey",
10770
+ { received: viewingKey },
10771
+ "SIP_2008" /* MISSING_REQUIRED */
10772
+ );
10773
+ }
10774
+ if (!viewingKey.startsWith("0x")) {
10775
+ throw new ValidationError(
10776
+ "viewingKey must be hex-encoded (start with 0x)",
10777
+ "viewingKey",
10778
+ { received: viewingKey },
10779
+ "SIP_3015" /* INVALID_FORMAT */
10780
+ );
10781
+ }
10782
+ if (viewingKey.length < 66) {
10783
+ throw new ValidationError(
10784
+ "viewingKey must be at least 32 bytes",
10785
+ "viewingKey",
10786
+ { received: viewingKey.length },
10787
+ "SIP_3015" /* INVALID_FORMAT */
10788
+ );
10789
+ }
10790
+ }
10791
+ /**
10792
+ * Convert viewing key to secret (bigint)
10793
+ */
10794
+ static viewingKeyToSecret(viewingKey) {
10795
+ const bytes = (0, import_utils24.hexToBytes)(viewingKey.slice(2));
10796
+ let secret = 0n;
10797
+ for (let i = 0; i < bytes.length; i++) {
10798
+ secret = secret << 8n | BigInt(bytes[i]);
10799
+ }
10800
+ return this.mod(secret, FIELD_PRIME);
10801
+ }
10802
+ /**
10803
+ * Convert secret (bigint) back to viewing key
10804
+ * @param secret - The secret as bigint
10805
+ * @param hexLength - Length of the hex string (without 0x prefix)
10806
+ */
10807
+ static secretToViewingKey(secret, hexLength) {
10808
+ let hex = secret.toString(16);
10809
+ hex = hex.padStart(hexLength, "0");
10810
+ return `0x${hex}`;
10811
+ }
10812
+ /**
10813
+ * Generate random polynomial coefficients
10814
+ * Polynomial: f(x) = a₀ + a₁x + a₂x² + ... + aₙ₋₁xⁿ⁻¹
10815
+ * where a₀ = secret
10816
+ */
10817
+ static generateCoefficients(threshold, secret) {
10818
+ const coefficients = [secret];
10819
+ for (let i = 1; i < threshold; i++) {
10820
+ const randomCoeff = this.randomFieldElement();
10821
+ coefficients.push(randomCoeff);
10822
+ }
10823
+ return coefficients;
10824
+ }
10825
+ /**
10826
+ * Generate a random field element
10827
+ */
10828
+ static randomFieldElement() {
10829
+ const bytes = (0, import_utils24.randomBytes)(32);
10830
+ let value = 0n;
10831
+ for (let i = 0; i < bytes.length; i++) {
10832
+ value = value << 8n | BigInt(bytes[i]);
10833
+ }
10834
+ return this.mod(value, FIELD_PRIME);
10835
+ }
10836
+ /**
10837
+ * Evaluate polynomial at point x
10838
+ * f(x) = a₀ + a₁x + a₂x² + ... + aₙ₋₁xⁿ⁻¹
10839
+ */
10840
+ static evaluatePolynomial(coefficients, x) {
10841
+ let result = 0n;
10842
+ let xPower = 1n;
10843
+ for (const coeff of coefficients) {
10844
+ result = this.mod(result + this.mod(coeff * xPower, FIELD_PRIME), FIELD_PRIME);
10845
+ xPower = this.mod(xPower * x, FIELD_PRIME);
10846
+ }
10847
+ return result;
10848
+ }
10849
+ /**
10850
+ * Create commitment hash from secret and coefficients
10851
+ */
10852
+ static createCommitment(secret, coefficients) {
10853
+ const data = [secret, ...coefficients].map((c) => c.toString(16).padStart(64, "0")).join("");
10854
+ const hash2 = (0, import_sha25618.sha256)((0, import_utils24.hexToBytes)(data));
10855
+ return (0, import_utils24.bytesToHex)(hash2);
10856
+ }
10857
+ /**
10858
+ * Encode share as string: "x:y:len:commitment"
10859
+ */
10860
+ static encodeShare(x, y, keyLength, commitment) {
10861
+ const xHex = x.toString(16).padStart(2, "0");
10862
+ const yHex = y.toString(16).padStart(64, "0");
10863
+ const lenHex = keyLength.toString(16).padStart(4, "0");
10864
+ return `${xHex}:${yHex}:${lenHex}:${commitment}`;
10865
+ }
10866
+ /**
10867
+ * Decode share from string
10868
+ */
10869
+ static decodeShare(share) {
10870
+ if (!share || typeof share !== "string") {
10871
+ throw new ValidationError(
10872
+ "share must be a non-empty string",
10873
+ "share",
10874
+ { received: share },
10875
+ "SIP_3012" /* INVALID_SHARE */
10876
+ );
10877
+ }
10878
+ const parts = share.split(":");
10879
+ if (parts.length !== 4) {
10880
+ throw new ValidationError(
10881
+ 'share must have format "x:y:len:commitment"',
10882
+ "share",
10883
+ { received: share },
10884
+ "SIP_3012" /* INVALID_SHARE */
10885
+ );
10886
+ }
10887
+ const [xHex, yHex, lenHex, commitment] = parts;
10888
+ try {
10889
+ const x = BigInt(`0x${xHex}`);
10890
+ const y = BigInt(`0x${yHex}`);
10891
+ const keyLength = parseInt(lenHex, 16);
10892
+ if (x <= 0n) {
10893
+ throw new ValidationError(
10894
+ "share x-coordinate must be positive",
10895
+ "share",
10896
+ { x },
10897
+ "SIP_3012" /* INVALID_SHARE */
10898
+ );
10899
+ }
10900
+ if (keyLength < 64) {
10901
+ throw new ValidationError(
10902
+ "key length must be at least 64 (32 bytes)",
10903
+ "share",
10904
+ { keyLength },
10905
+ "SIP_3012" /* INVALID_SHARE */
10906
+ );
10907
+ }
10908
+ return { x, y, keyLength, commitment };
10909
+ } catch (error) {
10910
+ throw new ValidationError(
10911
+ "failed to decode share",
10912
+ "share",
10913
+ { error: error.message },
10914
+ "SIP_3012" /* INVALID_SHARE */
10915
+ );
9443
10916
  }
9444
- return data;
9445
10917
  }
9446
- generateCSV(transactions) {
9447
- const headers = [
9448
- "Transaction ID",
9449
- "Disclosure ID",
9450
- "Type",
9451
- "Direction",
9452
- "Token",
9453
- "Amount",
9454
- "Sender",
9455
- "Recipient",
9456
- "Chain",
9457
- "Privacy Level",
9458
- "Timestamp",
9459
- "TX Hash",
9460
- "Block",
9461
- "Risk Score",
9462
- "Purpose",
9463
- "Memo"
9464
- ];
9465
- const rows = transactions.map((tx) => [
9466
- tx.transactionId,
9467
- tx.disclosureId,
9468
- tx.type,
9469
- tx.direction,
9470
- tx.token.symbol,
9471
- tx.amount.toString(),
9472
- tx.sender,
9473
- tx.recipient,
9474
- tx.chain,
9475
- tx.privacyLevel,
9476
- new Date(tx.timestamp * 1e3).toISOString(),
9477
- tx.txHash,
9478
- tx.blockNumber.toString(),
9479
- tx.riskScore?.toString() ?? "",
9480
- tx.purpose ?? "",
9481
- tx.memo ?? ""
9482
- ]);
9483
- const escapeForCSV = (val) => {
9484
- let escaped = val;
9485
- if (/^[=+\-@|\t]/.test(escaped)) {
9486
- escaped = `'${escaped}`;
10918
+ /**
10919
+ * Lagrange interpolation to reconstruct secret
10920
+ * Evaluates polynomial at x=0 to get f(0) = secret
10921
+ */
10922
+ static lagrangeInterpolate(shares) {
10923
+ let secret = 0n;
10924
+ for (let i = 0; i < shares.length; i++) {
10925
+ const xi = shares[i].x;
10926
+ const yi = shares[i].y;
10927
+ let numerator = 1n;
10928
+ let denominator = 1n;
10929
+ for (let j = 0; j < shares.length; j++) {
10930
+ if (i === j) continue;
10931
+ const xj = shares[j].x;
10932
+ numerator = this.mod(numerator * this.mod(-xj, FIELD_PRIME), FIELD_PRIME);
10933
+ denominator = this.mod(denominator * this.mod(xi - xj, FIELD_PRIME), FIELD_PRIME);
9487
10934
  }
9488
- return `"${escaped.replace(/"/g, '""')}"`;
9489
- };
9490
- const csvRows = [headers, ...rows].map((row) => row.map(escapeForCSV).join(","));
9491
- return csvRows.join("\n");
10935
+ const coeff = this.mod(numerator * this.modInverse(denominator, FIELD_PRIME), FIELD_PRIME);
10936
+ secret = this.mod(secret + this.mod(yi * coeff, FIELD_PRIME), FIELD_PRIME);
10937
+ }
10938
+ return secret;
9492
10939
  }
9493
- };
9494
- function generateId(prefix) {
9495
- return `${prefix}_${(0, import_utils20.bytesToHex)((0, import_utils20.randomBytes)(12))}`;
9496
- }
9497
- function validateRegisterAuditorParams(params) {
9498
- if (!params.organization?.trim()) {
9499
- throw new ValidationError(
9500
- "organization is required",
9501
- "organization",
9502
- void 0,
9503
- "SIP_2008" /* MISSING_REQUIRED */
9504
- );
10940
+ /**
10941
+ * Modular arithmetic: a mod m
10942
+ */
10943
+ static mod(a, m) {
10944
+ return (a % m + m) % m;
9505
10945
  }
9506
- if (!params.contactName?.trim()) {
9507
- throw new ValidationError(
9508
- "contact name is required",
9509
- "contactName",
9510
- void 0,
9511
- "SIP_2008" /* MISSING_REQUIRED */
9512
- );
10946
+ /**
10947
+ * Modular multiplicative inverse using Extended Euclidean Algorithm
10948
+ * Returns x such that (a * x) mod m = 1
10949
+ */
10950
+ static modInverse(a, m) {
10951
+ const a0 = this.mod(a, m);
10952
+ if (a0 === 0n) {
10953
+ throw new CryptoError(
10954
+ "modular inverse does not exist (a = 0)",
10955
+ "SIP_3014" /* CRYPTO_OPERATION_FAILED */,
10956
+ { operation: "modInverse" }
10957
+ );
10958
+ }
10959
+ let [old_r, r] = [a0, m];
10960
+ let [old_s, s] = [1n, 0n];
10961
+ while (r !== 0n) {
10962
+ const quotient = old_r / r;
10963
+ [old_r, r] = [r, old_r - quotient * r];
10964
+ [old_s, s] = [s, old_s - quotient * s];
10965
+ }
10966
+ if (old_r !== 1n) {
10967
+ throw new CryptoError(
10968
+ "modular inverse does not exist (gcd != 1)",
10969
+ "SIP_3014" /* CRYPTO_OPERATION_FAILED */,
10970
+ { operation: "modInverse" }
10971
+ );
10972
+ }
10973
+ return this.mod(old_s, m);
9513
10974
  }
9514
- if (!params.contactEmail?.trim()) {
9515
- throw new ValidationError(
9516
- "contact email is required",
9517
- "contactEmail",
9518
- void 0,
9519
- "SIP_2008" /* MISSING_REQUIRED */
9520
- );
10975
+ };
10976
+
10977
+ // src/compliance/derivation.ts
10978
+ var import_sha25619 = require("@noble/hashes/sha256");
10979
+ var import_sha5123 = require("@noble/hashes/sha512");
10980
+ var import_hmac2 = require("@noble/hashes/hmac");
10981
+ var import_utils25 = require("@noble/hashes/utils");
10982
+ var AuditorType = /* @__PURE__ */ ((AuditorType2) => {
10983
+ AuditorType2[AuditorType2["PRIMARY"] = 0] = "PRIMARY";
10984
+ AuditorType2[AuditorType2["REGULATORY"] = 1] = "REGULATORY";
10985
+ AuditorType2[AuditorType2["INTERNAL"] = 2] = "INTERNAL";
10986
+ AuditorType2[AuditorType2["TAX"] = 3] = "TAX";
10987
+ return AuditorType2;
10988
+ })(AuditorType || {});
10989
+ var AuditorKeyDerivation = class {
10990
+ /**
10991
+ * SIP Protocol coin type (BIP-44 registered)
10992
+ *
10993
+ * Note: This is a placeholder. In production, register with SLIP-44:
10994
+ * https://github.com/satoshilabs/slips/blob/master/slip-0044.md
10995
+ */
10996
+ static COIN_TYPE = 1234;
10997
+ /**
10998
+ * BIP-44 purpose field
10999
+ */
11000
+ static PURPOSE = 44;
11001
+ /**
11002
+ * Hardened derivation flag (2^31)
11003
+ */
11004
+ static HARDENED = 2147483648;
11005
+ /**
11006
+ * Generate BIP-44 derivation path
11007
+ *
11008
+ * @param auditorType - Type of auditor key
11009
+ * @param account - Account index (default: 0)
11010
+ * @returns BIP-44 style path string
11011
+ *
11012
+ * @example
11013
+ * ```typescript
11014
+ * AuditorKeyDerivation.derivePath(AuditorType.REGULATORY)
11015
+ * // Returns: "m/44'/1234'/0'/1"
11016
+ *
11017
+ * AuditorKeyDerivation.derivePath(AuditorType.TAX, 5)
11018
+ * // Returns: "m/44'/1234'/5'/3"
11019
+ * ```
11020
+ */
11021
+ static derivePath(auditorType, account = 0) {
11022
+ this.validateAuditorType(auditorType);
11023
+ this.validateAccount(account);
11024
+ return `m/${this.PURPOSE}'/${this.COIN_TYPE}'/${account}'/${auditorType}`;
9521
11025
  }
9522
- if (!params.publicKey?.trim()) {
9523
- throw new ValidationError(
9524
- "public key is required",
9525
- "publicKey",
9526
- void 0,
9527
- "SIP_2008" /* MISSING_REQUIRED */
9528
- );
11026
+ /**
11027
+ * Derive a viewing key for an auditor
11028
+ *
11029
+ * Uses BIP-32 style hierarchical deterministic key derivation:
11030
+ * 1. Derive master key from seed
11031
+ * 2. Harden purpose (44')
11032
+ * 3. Harden coin type (1234')
11033
+ * 4. Harden account index
11034
+ * 5. Derive auditor type (non-hardened)
11035
+ *
11036
+ * @param params - Derivation parameters
11037
+ * @returns Derived viewing key with metadata
11038
+ *
11039
+ * @throws {ValidationError} If parameters are invalid
11040
+ *
11041
+ * @example
11042
+ * ```typescript
11043
+ * const regulatoryKey = AuditorKeyDerivation.deriveViewingKey({
11044
+ * masterSeed: randomBytes(32),
11045
+ * auditorType: AuditorType.REGULATORY,
11046
+ * })
11047
+ *
11048
+ * console.log(regulatoryKey.path) // "m/44'/1234'/0'/1"
11049
+ * console.log(regulatoryKey.viewingKey.key) // "0x..."
11050
+ * ```
11051
+ */
11052
+ static deriveViewingKey(params) {
11053
+ const { masterSeed, auditorType, account = 0 } = params;
11054
+ this.validateMasterSeed(masterSeed);
11055
+ this.validateAuditorType(auditorType);
11056
+ this.validateAccount(account);
11057
+ const path = this.derivePath(auditorType, account);
11058
+ const indices = [
11059
+ this.PURPOSE | this.HARDENED,
11060
+ // 44' (hardened)
11061
+ this.COIN_TYPE | this.HARDENED,
11062
+ // 1234' (hardened)
11063
+ account | this.HARDENED,
11064
+ // account' (hardened)
11065
+ auditorType
11066
+ // auditorType (non-hardened)
11067
+ ];
11068
+ const masterData = (0, import_hmac2.hmac)(import_sha5123.sha512, (0, import_utils25.utf8ToBytes)("SIP-MASTER-SEED"), masterSeed);
11069
+ let currentKey = new Uint8Array(masterData.slice(0, 32));
11070
+ let chainCode = new Uint8Array(masterData.slice(32, 64));
11071
+ try {
11072
+ for (let i = 0; i < indices.length; i++) {
11073
+ const index = indices[i];
11074
+ const derived = this.deriveChildKey(currentKey, chainCode, index);
11075
+ if (i > 0) {
11076
+ secureWipe(currentKey);
11077
+ }
11078
+ currentKey = new Uint8Array(derived.key);
11079
+ chainCode = new Uint8Array(derived.chainCode);
11080
+ }
11081
+ const keyHex = `0x${(0, import_utils25.bytesToHex)(currentKey)}`;
11082
+ const hashBytes = (0, import_sha25619.sha256)(currentKey);
11083
+ const hash2 = `0x${(0, import_utils25.bytesToHex)(hashBytes)}`;
11084
+ const viewingKey = {
11085
+ key: keyHex,
11086
+ path,
11087
+ hash: hash2
11088
+ };
11089
+ return {
11090
+ path,
11091
+ viewingKey,
11092
+ auditorType,
11093
+ account
11094
+ };
11095
+ } finally {
11096
+ secureWipe(currentKey);
11097
+ secureWipe(chainCode);
11098
+ }
9529
11099
  }
9530
- if (!params.scope) {
9531
- throw new ValidationError(
9532
- "audit scope is required",
9533
- "scope",
9534
- void 0,
9535
- "SIP_2008" /* MISSING_REQUIRED */
9536
- );
11100
+ /**
11101
+ * Derive multiple viewing keys at once
11102
+ *
11103
+ * Efficiently derives keys for multiple auditor types from the same
11104
+ * master seed. This is more efficient than calling deriveViewingKey
11105
+ * multiple times as it reuses intermediate derivations.
11106
+ *
11107
+ * @param params - Derivation parameters
11108
+ * @returns Array of derived viewing keys
11109
+ *
11110
+ * @example
11111
+ * ```typescript
11112
+ * const keys = AuditorKeyDerivation.deriveMultiple({
11113
+ * masterSeed: randomBytes(32),
11114
+ * auditorTypes: [
11115
+ * AuditorType.PRIMARY,
11116
+ * AuditorType.REGULATORY,
11117
+ * AuditorType.INTERNAL,
11118
+ * ],
11119
+ * })
11120
+ *
11121
+ * // keys[0] -> PRIMARY key (m/44'/1234'/0'/0)
11122
+ * // keys[1] -> REGULATORY key (m/44'/1234'/0'/1)
11123
+ * // keys[2] -> INTERNAL key (m/44'/1234'/0'/2)
11124
+ * ```
11125
+ */
11126
+ static deriveMultiple(params) {
11127
+ const { masterSeed, auditorTypes, account = 0 } = params;
11128
+ this.validateMasterSeed(masterSeed);
11129
+ this.validateAccount(account);
11130
+ if (!auditorTypes || auditorTypes.length === 0) {
11131
+ throw new ValidationError(
11132
+ "at least one auditor type is required",
11133
+ "auditorTypes",
11134
+ { received: auditorTypes },
11135
+ "SIP_2008" /* MISSING_REQUIRED */
11136
+ );
11137
+ }
11138
+ for (const type of auditorTypes) {
11139
+ this.validateAuditorType(type);
11140
+ }
11141
+ const uniqueTypes = Array.from(new Set(auditorTypes));
11142
+ const commonIndices = [
11143
+ this.PURPOSE | this.HARDENED,
11144
+ // 44' (hardened)
11145
+ this.COIN_TYPE | this.HARDENED,
11146
+ // 1234' (hardened)
11147
+ account | this.HARDENED
11148
+ // account' (hardened)
11149
+ ];
11150
+ const masterData = (0, import_hmac2.hmac)(import_sha5123.sha512, (0, import_utils25.utf8ToBytes)("SIP-MASTER-SEED"), masterSeed);
11151
+ let commonKey = new Uint8Array(masterData.slice(0, 32));
11152
+ let commonChainCode = new Uint8Array(masterData.slice(32, 64));
11153
+ try {
11154
+ for (let i = 0; i < commonIndices.length; i++) {
11155
+ const index = commonIndices[i];
11156
+ const derived = this.deriveChildKey(commonKey, commonChainCode, index);
11157
+ if (i > 0) {
11158
+ secureWipe(commonKey);
11159
+ }
11160
+ commonKey = new Uint8Array(derived.key);
11161
+ commonChainCode = new Uint8Array(derived.chainCode);
11162
+ }
11163
+ const results = [];
11164
+ for (const auditorType of uniqueTypes) {
11165
+ const derived = this.deriveChildKey(commonKey, commonChainCode, auditorType);
11166
+ try {
11167
+ const keyHex = `0x${(0, import_utils25.bytesToHex)(derived.key)}`;
11168
+ const hashBytes = (0, import_sha25619.sha256)(derived.key);
11169
+ const hash2 = `0x${(0, import_utils25.bytesToHex)(hashBytes)}`;
11170
+ const path = this.derivePath(auditorType, account);
11171
+ const viewingKey = {
11172
+ key: keyHex,
11173
+ path,
11174
+ hash: hash2
11175
+ };
11176
+ results.push({
11177
+ path,
11178
+ viewingKey,
11179
+ auditorType,
11180
+ account
11181
+ });
11182
+ } finally {
11183
+ secureWipe(derived.key);
11184
+ secureWipe(derived.chainCode);
11185
+ }
11186
+ }
11187
+ return results;
11188
+ } finally {
11189
+ secureWipe(commonKey);
11190
+ secureWipe(commonChainCode);
11191
+ }
9537
11192
  }
9538
- }
9539
- function validateReportParams(params) {
9540
- if (!params.title?.trim()) {
9541
- throw new ValidationError(
9542
- "report title is required",
9543
- "title",
9544
- void 0,
9545
- "SIP_2008" /* MISSING_REQUIRED */
9546
- );
11193
+ /**
11194
+ * Get human-readable name for auditor type
11195
+ *
11196
+ * @param auditorType - Auditor type enum value
11197
+ * @returns Friendly name string
11198
+ */
11199
+ static getAuditorTypeName(auditorType) {
11200
+ switch (auditorType) {
11201
+ case 0 /* PRIMARY */:
11202
+ return "Primary";
11203
+ case 1 /* REGULATORY */:
11204
+ return "Regulatory";
11205
+ case 2 /* INTERNAL */:
11206
+ return "Internal";
11207
+ case 3 /* TAX */:
11208
+ return "Tax Authority";
11209
+ default:
11210
+ return `Unknown (${auditorType})`;
11211
+ }
9547
11212
  }
9548
- if (!params.type) {
9549
- throw new ValidationError(
9550
- "report type is required",
9551
- "type",
9552
- void 0,
9553
- "SIP_2008" /* MISSING_REQUIRED */
9554
- );
11213
+ // ─── Private Helpers ─────────────────────────────────────────────────────────
11214
+ /**
11215
+ * Derive a child key using BIP-32 HMAC-SHA512 derivation
11216
+ *
11217
+ * @param parentKey - Parent key bytes (32 bytes)
11218
+ * @param chainCode - Parent chain code (32 bytes)
11219
+ * @param index - Child index (use | HARDENED for hardened derivation)
11220
+ * @returns Derived key and chain code
11221
+ */
11222
+ static deriveChildKey(parentKey, chainCode, index) {
11223
+ const isHardened = (index & this.HARDENED) !== 0;
11224
+ const data = new Uint8Array(37);
11225
+ if (isHardened) {
11226
+ data[0] = 0;
11227
+ data.set(parentKey, 1);
11228
+ } else {
11229
+ data[0] = 1;
11230
+ data.set(parentKey, 1);
11231
+ }
11232
+ const indexView = new DataView(data.buffer, 33, 4);
11233
+ indexView.setUint32(0, index, false);
11234
+ const hmacResult = (0, import_hmac2.hmac)(import_sha5123.sha512, chainCode, data);
11235
+ const childKey = new Uint8Array(hmacResult.slice(0, 32));
11236
+ const childChainCode = new Uint8Array(hmacResult.slice(32, 64));
11237
+ return {
11238
+ key: childKey,
11239
+ chainCode: childChainCode
11240
+ };
9555
11241
  }
9556
- if (!params.format) {
9557
- throw new ValidationError(
9558
- "report format is required",
9559
- "format",
9560
- void 0,
9561
- "SIP_2008" /* MISSING_REQUIRED */
9562
- );
11242
+ /**
11243
+ * Validate master seed
11244
+ */
11245
+ static validateMasterSeed(seed) {
11246
+ if (!seed || seed.length < 32) {
11247
+ throw new ValidationError(
11248
+ "master seed must be at least 32 bytes",
11249
+ "masterSeed",
11250
+ { received: seed?.length ?? 0 },
11251
+ "SIP_2001" /* INVALID_INPUT */
11252
+ );
11253
+ }
9563
11254
  }
9564
- if (params.startDate === void 0 || params.startDate === null || params.endDate === void 0 || params.endDate === null) {
9565
- throw new ValidationError(
9566
- "date range is required",
9567
- "dateRange",
9568
- void 0,
9569
- "SIP_2008" /* MISSING_REQUIRED */
9570
- );
11255
+ /**
11256
+ * Validate auditor type
11257
+ */
11258
+ static validateAuditorType(type) {
11259
+ const validTypes = [
11260
+ 0 /* PRIMARY */,
11261
+ 1 /* REGULATORY */,
11262
+ 2 /* INTERNAL */,
11263
+ 3 /* TAX */
11264
+ ];
11265
+ if (!validTypes.includes(type)) {
11266
+ throw new ValidationError(
11267
+ `invalid auditor type: ${type}`,
11268
+ "auditorType",
11269
+ { received: type, valid: validTypes },
11270
+ "SIP_2001" /* INVALID_INPUT */
11271
+ );
11272
+ }
9571
11273
  }
9572
- if (params.startDate >= params.endDate) {
9573
- throw new ValidationError(
9574
- "start date must be before end date",
9575
- "dateRange",
9576
- void 0,
9577
- "SIP_2001" /* INVALID_INPUT */
9578
- );
11274
+ /**
11275
+ * Validate account index
11276
+ */
11277
+ static validateAccount(account) {
11278
+ if (!Number.isInteger(account) || account < 0 || account >= this.HARDENED) {
11279
+ throw new ValidationError(
11280
+ `account must be a non-negative integer less than ${this.HARDENED}`,
11281
+ "account",
11282
+ { received: account },
11283
+ "SIP_2001" /* INVALID_INPUT */
11284
+ );
11285
+ }
9579
11286
  }
9580
- }
11287
+ };
9581
11288
 
9582
11289
  // src/wallet/errors.ts
9583
11290
  var import_types18 = require("@sip-protocol/types");
@@ -12726,7 +14433,7 @@ function createTrezorAdapter(config) {
12726
14433
 
12727
14434
  // src/wallet/hardware/mock.ts
12728
14435
  var import_types51 = require("@sip-protocol/types");
12729
- var import_utils21 = require("@noble/hashes/utils");
14436
+ var import_utils26 = require("@noble/hashes/utils");
12730
14437
  var MockLedgerAdapter = class extends BaseWalletAdapter {
12731
14438
  chain;
12732
14439
  name = "mock-ledger";
@@ -12971,15 +14678,15 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
12971
14678
  }
12972
14679
  }
12973
14680
  generateMockAddress(index) {
12974
- const bytes = (0, import_utils21.randomBytes)(20);
14681
+ const bytes = (0, import_utils26.randomBytes)(20);
12975
14682
  bytes[0] = index;
12976
- return `0x${(0, import_utils21.bytesToHex)(bytes)}`;
14683
+ return `0x${(0, import_utils26.bytesToHex)(bytes)}`;
12977
14684
  }
12978
14685
  generateMockPublicKey(index) {
12979
- const bytes = (0, import_utils21.randomBytes)(33);
14686
+ const bytes = (0, import_utils26.randomBytes)(33);
12980
14687
  bytes[0] = 2;
12981
14688
  bytes[1] = index;
12982
- return `0x${(0, import_utils21.bytesToHex)(bytes)}`;
14689
+ return `0x${(0, import_utils26.bytesToHex)(bytes)}`;
12983
14690
  }
12984
14691
  generateMockSignature(data) {
12985
14692
  const sig = new Uint8Array(65);
@@ -12988,7 +14695,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
12988
14695
  sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 11;
12989
14696
  }
12990
14697
  sig[64] = 27;
12991
- return `0x${(0, import_utils21.bytesToHex)(sig)}`;
14698
+ return `0x${(0, import_utils26.bytesToHex)(sig)}`;
12992
14699
  }
12993
14700
  delay(ms) {
12994
14701
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -13177,15 +14884,15 @@ var MockTrezorAdapter = class extends BaseWalletAdapter {
13177
14884
  }
13178
14885
  }
13179
14886
  generateMockAddress(index) {
13180
- const bytes = (0, import_utils21.randomBytes)(20);
14887
+ const bytes = (0, import_utils26.randomBytes)(20);
13181
14888
  bytes[0] = index + 100;
13182
- return `0x${(0, import_utils21.bytesToHex)(bytes)}`;
14889
+ return `0x${(0, import_utils26.bytesToHex)(bytes)}`;
13183
14890
  }
13184
14891
  generateMockPublicKey(index) {
13185
- const bytes = (0, import_utils21.randomBytes)(33);
14892
+ const bytes = (0, import_utils26.randomBytes)(33);
13186
14893
  bytes[0] = 3;
13187
14894
  bytes[1] = index + 100;
13188
- return `0x${(0, import_utils21.bytesToHex)(bytes)}`;
14895
+ return `0x${(0, import_utils26.bytesToHex)(bytes)}`;
13189
14896
  }
13190
14897
  generateMockSignature(data) {
13191
14898
  const sig = new Uint8Array(65);
@@ -13194,7 +14901,7 @@ var MockTrezorAdapter = class extends BaseWalletAdapter {
13194
14901
  sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 17;
13195
14902
  }
13196
14903
  sig[64] = 28;
13197
- return `0x${(0, import_utils21.bytesToHex)(sig)}`;
14904
+ return `0x${(0, import_utils26.bytesToHex)(sig)}`;
13198
14905
  }
13199
14906
  delay(ms) {
13200
14907
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -13213,7 +14920,7 @@ var import_types54 = require("@sip-protocol/types");
13213
14920
  // src/proofs/browser.ts
13214
14921
  var import_noir_js = require("@noir-lang/noir_js");
13215
14922
  var import_bb = require("@aztec/bb.js");
13216
- var import_secp256k17 = require("@noble/curves/secp256k1");
14923
+ var import_secp256k18 = require("@noble/curves/secp256k1");
13217
14924
 
13218
14925
  // src/proofs/circuits/funding_proof.json
13219
14926
  var funding_proof_default = { noir_version: "1.0.0-beta.15+83245db91dcf63420ef4bcbbd85b98f397fee663", hash: "3859649086066977477", abi: { parameters: [{ name: "minimum_required", type: { kind: "integer", sign: "unsigned", width: 64 }, visibility: "public" }, { name: "asset_id", type: { kind: "field" }, visibility: "public" }, { name: "balance", type: { kind: "integer", sign: "unsigned", width: 64 }, visibility: "private" }, { name: "blinding", type: { kind: "field" }, visibility: "private" }], return_type: { abi_type: { kind: "array", length: 32, type: { kind: "integer", sign: "unsigned", width: 8 } }, visibility: "public" }, error_types: { "2900908756532713827": { error_kind: "string", string: "Insufficient balance" }, "15764276373176857197": { error_kind: "string", string: "Stack too deep" }, "15835548349546956319": { error_kind: "string", string: "Field failed to decompose into specified 32 limbs" } } }, bytecode: "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", debug_symbols: "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", file_map: { "17": { source: `use crate::field::field_less_than;
@@ -14226,7 +15933,7 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
14226
15933
  * Derive secp256k1 public key coordinates from a private key
14227
15934
  */
14228
15935
  static derivePublicKey(privateKey) {
14229
- const uncompressedPubKey = import_secp256k17.secp256k1.getPublicKey(privateKey, false);
15936
+ const uncompressedPubKey = import_secp256k18.secp256k1.getPublicKey(privateKey, false);
14230
15937
  const x = Array.from(uncompressedPubKey.slice(1, 33));
14231
15938
  const y = Array.from(uncompressedPubKey.slice(33, 65));
14232
15939
  return { x, y };
@@ -14732,14 +16439,14 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
14732
16439
  }
14733
16440
  async computeCommitmentHash(balance, blindingFactor, assetId) {
14734
16441
  const blindingField = this.bytesToField(blindingFactor);
14735
- const { sha256: sha25615 } = await import("@noble/hashes/sha256");
16442
+ const { sha256: sha25620 } = await import("@noble/hashes/sha256");
14736
16443
  const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
14737
16444
  const preimage = new Uint8Array([
14738
16445
  ...this.bigintToBytes(balance, 8),
14739
16446
  ...blindingFactor.slice(0, 32),
14740
16447
  ...hexToBytes9(this.assetIdToField(assetId))
14741
16448
  ]);
14742
- const hash2 = sha25615(preimage);
16449
+ const hash2 = sha25620(preimage);
14743
16450
  const commitmentHash = nobleToHex(hash2);
14744
16451
  return { commitmentHash, blindingField };
14745
16452
  }
@@ -14785,46 +16492,46 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
14785
16492
  return bytes;
14786
16493
  }
14787
16494
  async computeSenderCommitment(senderAddressField, senderBlindingField) {
14788
- const { sha256: sha25615 } = await import("@noble/hashes/sha256");
16495
+ const { sha256: sha25620 } = await import("@noble/hashes/sha256");
14789
16496
  const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
14790
16497
  const addressBytes = hexToBytes9(senderAddressField);
14791
16498
  const blindingBytes = hexToBytes9(senderBlindingField.padStart(64, "0"));
14792
16499
  const preimage = new Uint8Array([...addressBytes, ...blindingBytes]);
14793
- const hash2 = sha25615(preimage);
16500
+ const hash2 = sha25620(preimage);
14794
16501
  const commitmentX = nobleToHex(hash2.slice(0, 16)).padStart(64, "0");
14795
16502
  const commitmentY = nobleToHex(hash2.slice(16, 32)).padStart(64, "0");
14796
16503
  return { commitmentX, commitmentY };
14797
16504
  }
14798
16505
  async computeNullifier(senderSecretField, intentHashField, nonceField) {
14799
- const { sha256: sha25615 } = await import("@noble/hashes/sha256");
16506
+ const { sha256: sha25620 } = await import("@noble/hashes/sha256");
14800
16507
  const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
14801
16508
  const secretBytes = hexToBytes9(senderSecretField.padStart(64, "0"));
14802
16509
  const intentBytes = hexToBytes9(intentHashField);
14803
16510
  const nonceBytes = hexToBytes9(nonceField.padStart(64, "0"));
14804
16511
  const preimage = new Uint8Array([...secretBytes, ...intentBytes, ...nonceBytes]);
14805
- const hash2 = sha25615(preimage);
16512
+ const hash2 = sha25620(preimage);
14806
16513
  return nobleToHex(hash2);
14807
16514
  }
14808
16515
  async computeOutputCommitment(outputAmount, outputBlinding) {
14809
- const { sha256: sha25615 } = await import("@noble/hashes/sha256");
16516
+ const { sha256: sha25620 } = await import("@noble/hashes/sha256");
14810
16517
  const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
14811
16518
  const amountBytes = this.bigintToBytes(outputAmount, 8);
14812
16519
  const blindingBytes = outputBlinding.slice(0, 32);
14813
16520
  const preimage = new Uint8Array([...amountBytes, ...blindingBytes]);
14814
- const hash2 = sha25615(preimage);
16521
+ const hash2 = sha25620(preimage);
14815
16522
  const commitmentX = nobleToHex(hash2.slice(0, 16)).padStart(64, "0");
14816
16523
  const commitmentY = nobleToHex(hash2.slice(16, 32)).padStart(64, "0");
14817
16524
  return { commitmentX, commitmentY };
14818
16525
  }
14819
16526
  async computeSolverId(solverSecretField) {
14820
- const { sha256: sha25615 } = await import("@noble/hashes/sha256");
16527
+ const { sha256: sha25620 } = await import("@noble/hashes/sha256");
14821
16528
  const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
14822
16529
  const secretBytes = hexToBytes9(solverSecretField.padStart(64, "0"));
14823
- const hash2 = sha25615(secretBytes);
16530
+ const hash2 = sha25620(secretBytes);
14824
16531
  return nobleToHex(hash2);
14825
16532
  }
14826
16533
  async computeOracleMessageHash(recipient, amount, txHash, blockNumber) {
14827
- const { sha256: sha25615 } = await import("@noble/hashes/sha256");
16534
+ const { sha256: sha25620 } = await import("@noble/hashes/sha256");
14828
16535
  const recipientBytes = hexToBytes9(this.hexToField(recipient));
14829
16536
  const amountBytes = this.bigintToBytes(amount, 8);
14830
16537
  const txHashBytes = hexToBytes9(this.hexToField(txHash));
@@ -14835,11 +16542,11 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
14835
16542
  ...txHashBytes,
14836
16543
  ...blockBytes
14837
16544
  ]);
14838
- const hash2 = sha25615(preimage);
16545
+ const hash2 = sha25620(preimage);
14839
16546
  return Array.from(hash2);
14840
16547
  }
14841
16548
  getPublicKeyCoordinates(privateKey) {
14842
- const uncompressedPubKey = import_secp256k17.secp256k1.getPublicKey(privateKey, false);
16549
+ const uncompressedPubKey = import_secp256k18.secp256k1.getPublicKey(privateKey, false);
14843
16550
  const x = Array.from(uncompressedPubKey.slice(1, 33));
14844
16551
  const y = Array.from(uncompressedPubKey.slice(33, 65));
14845
16552
  return { x, y };
@@ -15393,11 +17100,15 @@ var ProofWorker = class _ProofWorker {
15393
17100
  0 && (module.exports = {
15394
17101
  ATTESTATION_VERSION,
15395
17102
  AptosStealthService,
17103
+ AuditorKeyDerivation,
17104
+ AuditorType,
15396
17105
  BaseWalletAdapter,
15397
17106
  BrowserNoirProvider,
15398
17107
  CHAIN_NUMERIC_IDS,
15399
17108
  COSMOS_CHAIN_PREFIXES,
15400
17109
  ComplianceManager,
17110
+ ComplianceReporter,
17111
+ ConditionalDisclosure,
15401
17112
  CosmosStealthService,
15402
17113
  CryptoError,
15403
17114
  DEFAULT_THRESHOLD,
@@ -15450,6 +17161,7 @@ var ProofWorker = class _ProofWorker {
15450
17161
  SmartRouter,
15451
17162
  SolanaWalletAdapter,
15452
17163
  SwapStatus,
17164
+ ThresholdViewingKey,
15453
17165
  Treasury,
15454
17166
  TrezorWalletAdapter,
15455
17167
  ValidationError,
@@ -15538,6 +17250,7 @@ var ProofWorker = class _ProofWorker {
15538
17250
  generateEd25519StealthAddress,
15539
17251
  generateEd25519StealthMetaAddress,
15540
17252
  generateIntentId,
17253
+ generatePdfReport,
15541
17254
  generateRandomBytes,
15542
17255
  generateStealthAddress,
15543
17256
  generateStealthMetaAddress,