@sip-protocol/sdk 0.7.1 → 0.7.3

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 (50) hide show
  1. package/dist/browser.d.mts +1 -1
  2. package/dist/browser.d.ts +1 -1
  3. package/dist/browser.js +2926 -341
  4. package/dist/browser.mjs +48 -2
  5. package/dist/chunk-2XIVXWHA.mjs +1930 -0
  6. package/dist/chunk-3M3HNQCW.mjs +18253 -0
  7. package/dist/chunk-7RFRWDCW.mjs +1504 -0
  8. package/dist/chunk-F6F73W35.mjs +16166 -0
  9. package/dist/chunk-OFDBEIEK.mjs +16166 -0
  10. package/dist/chunk-SF7YSLF5.mjs +1515 -0
  11. package/dist/chunk-WWUSGOXE.mjs +17129 -0
  12. package/dist/index-8MQz13eJ.d.mts +13746 -0
  13. package/dist/index-B71aXVzk.d.ts +13264 -0
  14. package/dist/index-DIBZHOOQ.d.ts +13746 -0
  15. package/dist/index-pOIIuwfV.d.mts +13264 -0
  16. package/dist/index.d.mts +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.js +2911 -326
  19. package/dist/index.mjs +48 -2
  20. package/dist/solana-4O4K45VU.mjs +46 -0
  21. package/dist/solana-NDABAZ6P.mjs +56 -0
  22. package/dist/solana-ZYO63LY5.mjs +46 -0
  23. package/package.json +3 -3
  24. package/src/chains/solana/index.ts +24 -0
  25. package/src/chains/solana/providers/generic.ts +160 -0
  26. package/src/chains/solana/providers/helius.ts +249 -0
  27. package/src/chains/solana/providers/index.ts +54 -0
  28. package/src/chains/solana/providers/interface.ts +178 -0
  29. package/src/chains/solana/providers/webhook.ts +519 -0
  30. package/src/chains/solana/scan.ts +88 -8
  31. package/src/chains/solana/types.ts +20 -1
  32. package/src/compliance/index.ts +14 -0
  33. package/src/compliance/range-sas.ts +591 -0
  34. package/src/index.ts +99 -0
  35. package/src/privacy-backends/index.ts +86 -0
  36. package/src/privacy-backends/interface.ts +263 -0
  37. package/src/privacy-backends/privacycash-types.ts +278 -0
  38. package/src/privacy-backends/privacycash.ts +460 -0
  39. package/src/privacy-backends/registry.ts +278 -0
  40. package/src/privacy-backends/router.ts +346 -0
  41. package/src/privacy-backends/sip-native.ts +253 -0
  42. package/src/proofs/noir.ts +1 -1
  43. package/src/surveillance/algorithms/address-reuse.ts +143 -0
  44. package/src/surveillance/algorithms/cluster.ts +247 -0
  45. package/src/surveillance/algorithms/exchange.ts +295 -0
  46. package/src/surveillance/algorithms/temporal.ts +337 -0
  47. package/src/surveillance/analyzer.ts +442 -0
  48. package/src/surveillance/index.ts +64 -0
  49. package/src/surveillance/scoring.ts +372 -0
  50. package/src/surveillance/types.ts +264 -0
package/dist/index.js CHANGED
@@ -1552,7 +1552,8 @@ async function scanForPayments(params) {
1552
1552
  spendingPublicKey,
1553
1553
  fromSlot,
1554
1554
  toSlot,
1555
- limit = 100
1555
+ limit = 100,
1556
+ provider
1556
1557
  } = params;
1557
1558
  const results = [];
1558
1559
  const memoProgram = new import_web32.PublicKey(MEMO_PROGRAM_ID);
@@ -1596,12 +1597,26 @@ async function scanForPayments(params) {
1596
1597
  if (isOurs) {
1597
1598
  const transferInfo = parseTokenTransfer(tx);
1598
1599
  if (transferInfo) {
1600
+ let amount = transferInfo.amount;
1601
+ const tokenSymbol = getTokenSymbol(transferInfo.mint);
1602
+ if (provider && announcement.stealthAddress) {
1603
+ try {
1604
+ const balance = await provider.getTokenBalance(
1605
+ announcement.stealthAddress,
1606
+ transferInfo.mint
1607
+ );
1608
+ if (balance > 0n) {
1609
+ amount = balance;
1610
+ }
1611
+ } catch {
1612
+ }
1613
+ }
1599
1614
  results.push({
1600
1615
  stealthAddress: announcement.stealthAddress || "",
1601
1616
  ephemeralPublicKey: announcement.ephemeralPublicKey,
1602
- amount: transferInfo.amount,
1617
+ amount,
1603
1618
  mint: transferInfo.mint,
1604
- tokenSymbol: getTokenSymbol(transferInfo.mint),
1619
+ tokenSymbol,
1605
1620
  txSignature: sigInfo.signature,
1606
1621
  slot: sigInfo.slot,
1607
1622
  timestamp: sigInfo.blockTime || 0
@@ -1644,8 +1659,19 @@ async function claimStealthPayment(params) {
1644
1659
  );
1645
1660
  const stealthPrivKeyBytes = (0, import_utils9.hexToBytes)(recovery.privateKey.slice(2));
1646
1661
  const stealthPubkey = new import_web32.PublicKey(stealthAddress);
1662
+ const expectedPubKeyBytes = stealthPubkey.toBytes();
1663
+ const scalarBigInt = bytesToBigIntLE2(stealthPrivKeyBytes);
1664
+ const ED25519_ORDER2 = 2n ** 252n + 27742317777372353535851937790883648493n;
1665
+ let validScalar = scalarBigInt % ED25519_ORDER2;
1666
+ if (validScalar === 0n) validScalar = 1n;
1667
+ const derivedPubKeyBytes = import_ed255192.ed25519.ExtendedPoint.BASE.multiply(validScalar).toRawBytes();
1668
+ if (!derivedPubKeyBytes.every((b, i) => b === expectedPubKeyBytes[i])) {
1669
+ throw new Error(
1670
+ "Stealth key derivation failed: derived private key does not produce expected public key. This may indicate incorrect spending/viewing keys or corrupted announcement data."
1671
+ );
1672
+ }
1647
1673
  const stealthKeypair = import_web32.Keypair.fromSecretKey(
1648
- new Uint8Array([...stealthPrivKeyBytes, ...stealthPubkey.toBytes()])
1674
+ new Uint8Array([...stealthPrivKeyBytes, ...expectedPubKeyBytes])
1649
1675
  );
1650
1676
  const stealthATA = await (0, import_spl_token2.getAssociatedTokenAddress)(
1651
1677
  mint,
@@ -1696,7 +1722,13 @@ async function claimStealthPayment(params) {
1696
1722
  explorerUrl: getExplorerUrl(txSignature, cluster)
1697
1723
  };
1698
1724
  }
1699
- async function getStealthBalance(connection, stealthAddress, mint) {
1725
+ async function getStealthBalance(connection, stealthAddress, mint, provider) {
1726
+ if (provider) {
1727
+ try {
1728
+ return await provider.getTokenBalance(stealthAddress, mint.toBase58());
1729
+ } catch {
1730
+ }
1731
+ }
1700
1732
  try {
1701
1733
  const stealthPubkey = new import_web32.PublicKey(stealthAddress);
1702
1734
  const ata = await (0, import_spl_token2.getAssociatedTokenAddress)(mint, stealthPubkey, true);
@@ -1746,7 +1778,14 @@ function detectCluster2(endpoint) {
1746
1778
  }
1747
1779
  return "mainnet-beta";
1748
1780
  }
1749
- var import_web32, import_spl_token2, import_utils9;
1781
+ function bytesToBigIntLE2(bytes) {
1782
+ let result = 0n;
1783
+ for (let i = bytes.length - 1; i >= 0; i--) {
1784
+ result = result << 8n | BigInt(bytes[i]);
1785
+ }
1786
+ return result;
1787
+ }
1788
+ var import_web32, import_spl_token2, import_utils9, import_ed255192;
1750
1789
  var init_scan = __esm({
1751
1790
  "src/chains/solana/scan.ts"() {
1752
1791
  "use strict";
@@ -1756,6 +1795,428 @@ var init_scan = __esm({
1756
1795
  init_types();
1757
1796
  init_constants();
1758
1797
  import_utils9 = require("@noble/hashes/utils");
1798
+ import_ed255192 = require("@noble/curves/ed25519");
1799
+ }
1800
+ });
1801
+
1802
+ // src/chains/solana/providers/helius.ts
1803
+ var HeliusProvider;
1804
+ var init_helius = __esm({
1805
+ "src/chains/solana/providers/helius.ts"() {
1806
+ "use strict";
1807
+ HeliusProvider = class {
1808
+ name = "helius";
1809
+ apiKey;
1810
+ cluster;
1811
+ rpcUrl;
1812
+ restUrl;
1813
+ constructor(config) {
1814
+ if (!config.apiKey) {
1815
+ throw new Error("Helius API key is required. Get one at https://dev.helius.xyz");
1816
+ }
1817
+ this.apiKey = config.apiKey;
1818
+ this.cluster = config.cluster ?? "mainnet-beta";
1819
+ this.rpcUrl = this.cluster === "devnet" ? `https://devnet.helius-rpc.com/?api-key=${this.apiKey}` : `https://mainnet.helius-rpc.com/?api-key=${this.apiKey}`;
1820
+ this.restUrl = this.cluster === "devnet" ? `https://api-devnet.helius.xyz/v0` : `https://api.helius.xyz/v0`;
1821
+ }
1822
+ /**
1823
+ * Get all token assets owned by an address using DAS API
1824
+ *
1825
+ * Uses getAssetsByOwner for comprehensive asset information including
1826
+ * NFTs and fungible tokens with metadata.
1827
+ */
1828
+ async getAssetsByOwner(owner) {
1829
+ const assets = [];
1830
+ let page = 1;
1831
+ const limit = 1e3;
1832
+ let hasMore = true;
1833
+ while (hasMore) {
1834
+ const response = await fetch(this.rpcUrl, {
1835
+ method: "POST",
1836
+ headers: { "Content-Type": "application/json" },
1837
+ body: JSON.stringify({
1838
+ jsonrpc: "2.0",
1839
+ id: `sip-${Date.now()}`,
1840
+ method: "getAssetsByOwner",
1841
+ params: {
1842
+ ownerAddress: owner,
1843
+ page,
1844
+ limit,
1845
+ displayOptions: {
1846
+ showFungible: true,
1847
+ showNativeBalance: false
1848
+ }
1849
+ }
1850
+ })
1851
+ });
1852
+ if (!response.ok) {
1853
+ throw new Error(`Helius API error: ${response.status} ${response.statusText}`);
1854
+ }
1855
+ const data = await response.json();
1856
+ if (data.error) {
1857
+ throw new Error(`Helius RPC error: ${data.error.message} (code: ${data.error.code})`);
1858
+ }
1859
+ if (data.result?.items) {
1860
+ for (const item of data.result.items) {
1861
+ if (item.interface !== "FungibleToken" && item.interface !== "FungibleAsset") {
1862
+ continue;
1863
+ }
1864
+ const tokenInfo = item.token_info;
1865
+ if (!tokenInfo?.balance) continue;
1866
+ const balanceValue = typeof tokenInfo.balance === "string" ? BigInt(tokenInfo.balance) : BigInt(Math.floor(tokenInfo.balance));
1867
+ assets.push({
1868
+ mint: item.id,
1869
+ amount: balanceValue,
1870
+ decimals: tokenInfo.decimals ?? 0,
1871
+ symbol: tokenInfo.symbol ?? item.content?.metadata?.symbol,
1872
+ name: item.content?.metadata?.name,
1873
+ logoUri: item.content?.links?.image
1874
+ });
1875
+ }
1876
+ }
1877
+ hasMore = data.result?.items?.length === limit;
1878
+ page++;
1879
+ if (page > 100) {
1880
+ console.warn("[HeliusProvider] Reached page limit (100), stopping pagination");
1881
+ break;
1882
+ }
1883
+ }
1884
+ return assets;
1885
+ }
1886
+ /**
1887
+ * Get token balance for a specific mint using Balances API
1888
+ *
1889
+ * More efficient than getAssetsByOwner when you only need one token's balance.
1890
+ */
1891
+ async getTokenBalance(owner, mint) {
1892
+ try {
1893
+ const url = `${this.restUrl}/addresses/${owner}/balances?api-key=${this.apiKey}`;
1894
+ const response = await fetch(url);
1895
+ if (!response.ok) {
1896
+ const assets = await this.getAssetsByOwner(owner);
1897
+ const asset = assets.find((a) => a.mint === mint);
1898
+ return asset?.amount ?? 0n;
1899
+ }
1900
+ const data = await response.json();
1901
+ const token = data.tokens?.find((t) => t.mint === mint);
1902
+ return token ? BigInt(token.amount) : 0n;
1903
+ } catch (error) {
1904
+ console.warn("[HeliusProvider] getTokenBalance error, falling back to DAS:", error);
1905
+ const assets = await this.getAssetsByOwner(owner);
1906
+ const asset = assets.find((a) => a.mint === mint);
1907
+ return asset?.amount ?? 0n;
1908
+ }
1909
+ }
1910
+ /**
1911
+ * Check if provider supports real-time subscriptions
1912
+ *
1913
+ * Helius supports webhooks for real-time notifications,
1914
+ * but that requires server-side setup. Client-side subscriptions
1915
+ * are not directly supported.
1916
+ */
1917
+ supportsSubscriptions() {
1918
+ return false;
1919
+ }
1920
+ };
1921
+ }
1922
+ });
1923
+
1924
+ // src/chains/solana/providers/generic.ts
1925
+ function validateSolanaAddress(address, paramName) {
1926
+ try {
1927
+ return new import_web33.PublicKey(address);
1928
+ } catch {
1929
+ throw new Error(`Invalid Solana address for ${paramName}: ${address}`);
1930
+ }
1931
+ }
1932
+ var import_web33, import_spl_token3, CLUSTER_ENDPOINTS, GenericProvider;
1933
+ var init_generic = __esm({
1934
+ "src/chains/solana/providers/generic.ts"() {
1935
+ "use strict";
1936
+ import_web33 = require("@solana/web3.js");
1937
+ import_spl_token3 = require("@solana/spl-token");
1938
+ CLUSTER_ENDPOINTS = {
1939
+ "mainnet-beta": "https://api.mainnet-beta.solana.com",
1940
+ devnet: "https://api.devnet.solana.com",
1941
+ testnet: "https://api.testnet.solana.com"
1942
+ };
1943
+ GenericProvider = class {
1944
+ name = "generic";
1945
+ connection;
1946
+ constructor(config) {
1947
+ if (config.connection) {
1948
+ this.connection = config.connection;
1949
+ } else {
1950
+ const endpoint = config.endpoint ?? CLUSTER_ENDPOINTS[config.cluster ?? "mainnet-beta"];
1951
+ this.connection = new import_web33.Connection(endpoint, "confirmed");
1952
+ }
1953
+ }
1954
+ /**
1955
+ * Get all token assets owned by an address using getParsedTokenAccountsByOwner
1956
+ *
1957
+ * Note: This is less efficient than Helius DAS API for large wallets,
1958
+ * but works with any RPC endpoint.
1959
+ */
1960
+ async getAssetsByOwner(owner) {
1961
+ const ownerPubkey = validateSolanaAddress(owner, "owner");
1962
+ const accounts = await this.connection.getParsedTokenAccountsByOwner(
1963
+ ownerPubkey,
1964
+ { programId: import_spl_token3.TOKEN_PROGRAM_ID }
1965
+ );
1966
+ const assets = [];
1967
+ for (const { account } of accounts.value) {
1968
+ const parsed = account.data.parsed;
1969
+ if (parsed.type !== "account") continue;
1970
+ const info = parsed.info;
1971
+ const amount = BigInt(info.tokenAmount.amount);
1972
+ if (amount === 0n) continue;
1973
+ assets.push({
1974
+ mint: info.mint,
1975
+ amount,
1976
+ decimals: info.tokenAmount.decimals,
1977
+ // Generic RPC doesn't provide symbol/name, those need metadata lookup
1978
+ symbol: void 0,
1979
+ name: void 0,
1980
+ logoUri: void 0
1981
+ });
1982
+ }
1983
+ return assets;
1984
+ }
1985
+ /**
1986
+ * Get token balance for a specific mint
1987
+ *
1988
+ * Uses getAccount on the associated token address.
1989
+ */
1990
+ async getTokenBalance(owner, mint) {
1991
+ const ownerPubkey = validateSolanaAddress(owner, "owner");
1992
+ const mintPubkey = validateSolanaAddress(mint, "mint");
1993
+ try {
1994
+ const ata = await (0, import_spl_token3.getAssociatedTokenAddress)(
1995
+ mintPubkey,
1996
+ ownerPubkey,
1997
+ true
1998
+ // allowOwnerOffCurve for PDAs
1999
+ );
2000
+ const account = await (0, import_spl_token3.getAccount)(this.connection, ata);
2001
+ return account.amount;
2002
+ } catch {
2003
+ return 0n;
2004
+ }
2005
+ }
2006
+ /**
2007
+ * Check if provider supports real-time subscriptions
2008
+ *
2009
+ * Generic RPC supports WebSocket subscriptions but they're not
2010
+ * efficient for monitoring token transfers. Returns false.
2011
+ */
2012
+ supportsSubscriptions() {
2013
+ return false;
2014
+ }
2015
+ /**
2016
+ * Get the underlying Connection object
2017
+ *
2018
+ * Useful for advanced operations that need direct RPC access.
2019
+ */
2020
+ getConnection() {
2021
+ return this.connection;
2022
+ }
2023
+ };
2024
+ }
2025
+ });
2026
+
2027
+ // src/chains/solana/providers/interface.ts
2028
+ function createProvider(type, config) {
2029
+ switch (type) {
2030
+ case "helius":
2031
+ return new HeliusProvider(config);
2032
+ case "generic":
2033
+ return new GenericProvider(config);
2034
+ case "quicknode":
2035
+ case "triton":
2036
+ throw new Error(
2037
+ `Provider '${type}' is not yet implemented. Use 'helius' or 'generic' for now. See https://github.com/sip-protocol/sip-protocol/issues/${type === "quicknode" ? "494" : "495"}`
2038
+ );
2039
+ default:
2040
+ throw new Error(`Unknown provider type: ${type}`);
2041
+ }
2042
+ }
2043
+ var init_interface = __esm({
2044
+ "src/chains/solana/providers/interface.ts"() {
2045
+ "use strict";
2046
+ init_helius();
2047
+ init_generic();
2048
+ }
2049
+ });
2050
+
2051
+ // src/chains/solana/providers/webhook.ts
2052
+ function createWebhookHandler(config) {
2053
+ const { viewingPrivateKey, spendingPublicKey, onPaymentFound, onError } = config;
2054
+ if (!viewingPrivateKey || !viewingPrivateKey.startsWith("0x")) {
2055
+ throw new ValidationError("viewingPrivateKey must be a valid hex string starting with 0x", "viewingPrivateKey");
2056
+ }
2057
+ if (!spendingPublicKey || !spendingPublicKey.startsWith("0x")) {
2058
+ throw new ValidationError("spendingPublicKey must be a valid hex string starting with 0x", "spendingPublicKey");
2059
+ }
2060
+ if (typeof onPaymentFound !== "function") {
2061
+ throw new ValidationError("onPaymentFound callback is required", "onPaymentFound");
2062
+ }
2063
+ return async (payload) => {
2064
+ const transactions = Array.isArray(payload) ? payload : [payload];
2065
+ const results = [];
2066
+ for (const tx of transactions) {
2067
+ try {
2068
+ if (isRawTransaction(tx)) {
2069
+ const result = await processRawTransaction(
2070
+ tx,
2071
+ viewingPrivateKey,
2072
+ spendingPublicKey,
2073
+ onPaymentFound
2074
+ );
2075
+ results.push(result);
2076
+ } else {
2077
+ results.push({
2078
+ found: false,
2079
+ signature: tx.signature
2080
+ });
2081
+ }
2082
+ } catch (error) {
2083
+ onError?.(error, isRawTransaction(tx) ? tx : void 0);
2084
+ results.push({
2085
+ found: false,
2086
+ signature: getSignature(tx)
2087
+ });
2088
+ }
2089
+ }
2090
+ return results;
2091
+ };
2092
+ }
2093
+ async function processRawTransaction(tx, viewingPrivateKey, spendingPublicKey, onPaymentFound) {
2094
+ const signature = tx.transaction?.signatures?.[0] ?? "unknown";
2095
+ if (tx.meta?.err) {
2096
+ return { found: false, signature };
2097
+ }
2098
+ if (!tx.meta?.logMessages) {
2099
+ return { found: false, signature };
2100
+ }
2101
+ for (const log2 of tx.meta.logMessages) {
2102
+ if (!log2.includes(SIP_MEMO_PREFIX)) continue;
2103
+ const memoMatch = log2.match(/Program log: (.+)/);
2104
+ if (!memoMatch) continue;
2105
+ const memoContent = memoMatch[1];
2106
+ const announcement = parseAnnouncement(memoContent);
2107
+ if (!announcement) continue;
2108
+ const ephemeralPubKeyHex = solanaAddressToEd25519PublicKey(
2109
+ announcement.ephemeralPublicKey
2110
+ );
2111
+ const viewTagNumber = parseInt(announcement.viewTag, 16);
2112
+ if (!Number.isFinite(viewTagNumber) || viewTagNumber < 0 || viewTagNumber > 255) {
2113
+ continue;
2114
+ }
2115
+ const stealthAddressToCheck = {
2116
+ address: announcement.stealthAddress ? solanaAddressToEd25519PublicKey(announcement.stealthAddress) : "0x" + "00".repeat(32),
2117
+ ephemeralPublicKey: ephemeralPubKeyHex,
2118
+ viewTag: viewTagNumber
2119
+ };
2120
+ let isOurs = false;
2121
+ try {
2122
+ isOurs = checkEd25519StealthAddress(
2123
+ stealthAddressToCheck,
2124
+ viewingPrivateKey,
2125
+ spendingPublicKey
2126
+ );
2127
+ } catch {
2128
+ continue;
2129
+ }
2130
+ if (isOurs) {
2131
+ const transferInfo = parseTokenTransferFromWebhook(tx);
2132
+ const payment = {
2133
+ stealthAddress: announcement.stealthAddress || "",
2134
+ ephemeralPublicKey: announcement.ephemeralPublicKey,
2135
+ amount: transferInfo?.amount ?? 0n,
2136
+ mint: transferInfo?.mint ?? "",
2137
+ tokenSymbol: transferInfo?.mint ? getTokenSymbol2(transferInfo.mint) : void 0,
2138
+ txSignature: signature,
2139
+ slot: tx.slot,
2140
+ timestamp: tx.blockTime
2141
+ };
2142
+ try {
2143
+ await onPaymentFound(payment);
2144
+ } catch {
2145
+ }
2146
+ return { found: true, payment, signature };
2147
+ }
2148
+ }
2149
+ return { found: false, signature };
2150
+ }
2151
+ function parseTokenTransferFromWebhook(tx) {
2152
+ const { preTokenBalances, postTokenBalances } = tx.meta;
2153
+ if (!postTokenBalances || !preTokenBalances) {
2154
+ return null;
2155
+ }
2156
+ for (const post of postTokenBalances) {
2157
+ const pre = preTokenBalances.find(
2158
+ (p) => p.accountIndex === post.accountIndex
2159
+ );
2160
+ const postAmount = BigInt(post.uiTokenAmount.amount);
2161
+ const preAmount = pre ? BigInt(pre.uiTokenAmount.amount) : 0n;
2162
+ if (postAmount > preAmount) {
2163
+ return {
2164
+ mint: post.mint,
2165
+ amount: postAmount - preAmount
2166
+ };
2167
+ }
2168
+ }
2169
+ return null;
2170
+ }
2171
+ function getTokenSymbol2(mint) {
2172
+ for (const [symbol, address] of Object.entries(SOLANA_TOKEN_MINTS)) {
2173
+ if (address === mint) {
2174
+ return symbol;
2175
+ }
2176
+ }
2177
+ return void 0;
2178
+ }
2179
+ function isRawTransaction(tx) {
2180
+ return typeof tx === "object" && tx !== null && "meta" in tx && "transaction" in tx && Array.isArray(tx.transaction?.signatures);
2181
+ }
2182
+ function getSignature(tx) {
2183
+ if ("signature" in tx && typeof tx.signature === "string") {
2184
+ return tx.signature;
2185
+ }
2186
+ if (isRawTransaction(tx)) {
2187
+ return tx.transaction?.signatures?.[0] ?? "unknown";
2188
+ }
2189
+ return "unknown";
2190
+ }
2191
+ async function processWebhookTransaction(transaction, viewingPrivateKey, spendingPublicKey) {
2192
+ const result = await processRawTransaction(
2193
+ transaction,
2194
+ viewingPrivateKey,
2195
+ spendingPublicKey,
2196
+ () => {
2197
+ }
2198
+ // No-op callback
2199
+ );
2200
+ return result.found ? result.payment ?? null : null;
2201
+ }
2202
+ var init_webhook = __esm({
2203
+ "src/chains/solana/providers/webhook.ts"() {
2204
+ "use strict";
2205
+ init_stealth();
2206
+ init_types();
2207
+ init_constants();
2208
+ init_errors();
2209
+ }
2210
+ });
2211
+
2212
+ // src/chains/solana/providers/index.ts
2213
+ var init_providers = __esm({
2214
+ "src/chains/solana/providers/index.ts"() {
2215
+ "use strict";
2216
+ init_interface();
2217
+ init_helius();
2218
+ init_generic();
2219
+ init_webhook();
1759
2220
  }
1760
2221
  });
1761
2222
 
@@ -1764,6 +2225,8 @@ var solana_exports = {};
1764
2225
  __export(solana_exports, {
1765
2226
  ATA_RENT_LAMPORTS: () => ATA_RENT_LAMPORTS,
1766
2227
  ESTIMATED_TX_FEE_LAMPORTS: () => ESTIMATED_TX_FEE_LAMPORTS,
2228
+ GenericProvider: () => GenericProvider,
2229
+ HeliusProvider: () => HeliusProvider,
1767
2230
  MEMO_PROGRAM_ID: () => MEMO_PROGRAM_ID,
1768
2231
  SIP_MEMO_PREFIX: () => SIP_MEMO_PREFIX,
1769
2232
  SOLANA_EXPLORER_URLS: () => SOLANA_EXPLORER_URLS,
@@ -1772,6 +2235,8 @@ __export(solana_exports, {
1772
2235
  SOLANA_TOKEN_MINTS: () => SOLANA_TOKEN_MINTS,
1773
2236
  claimStealthPayment: () => claimStealthPayment,
1774
2237
  createAnnouncementMemo: () => createAnnouncementMemo,
2238
+ createProvider: () => createProvider,
2239
+ createWebhookHandler: () => createWebhookHandler,
1775
2240
  estimatePrivateTransferFee: () => estimatePrivateTransferFee,
1776
2241
  getExplorerUrl: () => getExplorerUrl,
1777
2242
  getStealthBalance: () => getStealthBalance,
@@ -1779,6 +2244,7 @@ __export(solana_exports, {
1779
2244
  getTokenMint: () => getTokenMint,
1780
2245
  hasTokenAccount: () => hasTokenAccount,
1781
2246
  parseAnnouncement: () => parseAnnouncement,
2247
+ processWebhookTransaction: () => processWebhookTransaction,
1782
2248
  scanForPayments: () => scanForPayments,
1783
2249
  sendPrivateSPLTransfer: () => sendPrivateSPLTransfer
1784
2250
  });
@@ -1789,6 +2255,8 @@ var init_solana = __esm({
1789
2255
  init_types();
1790
2256
  init_transfer();
1791
2257
  init_scan();
2258
+ init_providers();
2259
+ init_providers();
1792
2260
  }
1793
2261
  });
1794
2262
 
@@ -4947,6 +5415,8 @@ var index_exports = {};
4947
5415
  __export(index_exports, {
4948
5416
  ATTESTATION_VERSION: () => ATTESTATION_VERSION,
4949
5417
  AptosStealthService: () => AptosStealthService,
5418
+ AttestationGatedDisclosure: () => AttestationGatedDisclosure,
5419
+ AttestationSchema: () => AttestationSchema,
4950
5420
  AuditorKeyDerivation: () => AuditorKeyDerivation,
4951
5421
  AuditorType: () => AuditorType,
4952
5422
  BaseWalletAdapter: () => BaseWalletAdapter,
@@ -4964,11 +5434,14 @@ __export(index_exports, {
4964
5434
  ErrorCode: () => ErrorCode,
4965
5435
  EthereumChainId: () => EthereumChainId,
4966
5436
  EthereumWalletAdapter: () => EthereumWalletAdapter,
5437
+ GenericProvider: () => GenericProvider,
4967
5438
  HardwareErrorCode: () => HardwareErrorCode,
4968
5439
  HardwareWalletError: () => HardwareWalletError,
5440
+ HeliusProvider: () => HeliusProvider,
4969
5441
  IntentBuilder: () => IntentBuilder,
4970
5442
  IntentError: () => IntentError,
4971
- IntentStatus: () => import_types58.IntentStatus,
5443
+ IntentStatus: () => import_types59.IntentStatus,
5444
+ KNOWN_EXCHANGES: () => KNOWN_EXCHANGES,
4972
5445
  LedgerWalletAdapter: () => LedgerWalletAdapter,
4973
5446
  MEMO_PROGRAM_ID: () => MEMO_PROGRAM_ID,
4974
5447
  MockEthereumAdapter: () => MockEthereumAdapter,
@@ -4978,30 +5451,33 @@ __export(index_exports, {
4978
5451
  MockSolver: () => MockSolver,
4979
5452
  MockTrezorAdapter: () => MockTrezorAdapter,
4980
5453
  MockWalletAdapter: () => MockWalletAdapter,
4981
- NATIVE_TOKENS: () => import_types58.NATIVE_TOKENS,
5454
+ NATIVE_TOKENS: () => import_types59.NATIVE_TOKENS,
4982
5455
  NEARIntentsAdapter: () => NEARIntentsAdapter,
4983
5456
  NEARIntentsBackend: () => NEARIntentsBackend,
4984
5457
  NetworkError: () => NetworkError,
4985
5458
  ORACLE_DOMAIN: () => ORACLE_DOMAIN,
4986
5459
  OneClickClient: () => OneClickClient,
4987
- OneClickDepositMode: () => import_types62.OneClickDepositMode,
4988
- OneClickErrorCode: () => import_types62.OneClickErrorCode,
4989
- OneClickSwapStatus: () => import_types62.OneClickSwapStatus,
4990
- OneClickSwapType: () => import_types62.OneClickSwapType,
5460
+ OneClickDepositMode: () => import_types63.OneClickDepositMode,
5461
+ OneClickErrorCode: () => import_types63.OneClickErrorCode,
5462
+ OneClickSwapStatus: () => import_types63.OneClickSwapStatus,
5463
+ OneClickSwapType: () => import_types63.OneClickSwapType,
4991
5464
  PaymentBuilder: () => PaymentBuilder,
4992
- PaymentStatus: () => import_types59.PaymentStatus,
4993
- PrivacyLevel: () => import_types58.PrivacyLevel,
5465
+ PaymentStatus: () => import_types60.PaymentStatus,
5466
+ PrivacyBackendRegistry: () => PrivacyBackendRegistry,
5467
+ PrivacyLevel: () => import_types59.PrivacyLevel,
5468
+ PrivacySmartRouter: () => SmartRouter2,
4994
5469
  PrivateNFT: () => PrivateNFT,
4995
5470
  PrivateVoting: () => PrivateVoting,
4996
5471
  ProofError: () => ProofError,
4997
5472
  ProofGenerationError: () => ProofGenerationError,
4998
5473
  ProofNotImplementedError: () => ProofNotImplementedError,
4999
- ProposalStatus: () => import_types60.ProposalStatus,
5000
- ReportStatus: () => import_types61.ReportStatus,
5474
+ ProposalStatus: () => import_types61.ProposalStatus,
5475
+ ReportStatus: () => import_types62.ReportStatus,
5001
5476
  SIP: () => SIP,
5002
5477
  SIPError: () => SIPError,
5478
+ SIPNativeBackend: () => SIPNativeBackend,
5003
5479
  SIP_MEMO_PREFIX: () => SIP_MEMO_PREFIX,
5004
- SIP_VERSION: () => import_types58.SIP_VERSION,
5480
+ SIP_VERSION: () => import_types59.SIP_VERSION,
5005
5481
  SOLANA_EXPLORER_URLS: () => SOLANA_EXPLORER_URLS,
5006
5482
  SOLANA_RPC_ENDPOINTS: () => SOLANA_RPC_ENDPOINTS,
5007
5483
  SOLANA_TOKEN_DECIMALS: () => SOLANA_TOKEN_DECIMALS,
@@ -5016,14 +5492,15 @@ __export(index_exports, {
5016
5492
  SolanaSameChainExecutor: () => SolanaSameChainExecutor,
5017
5493
  SolanaWalletAdapter: () => SolanaWalletAdapter,
5018
5494
  SuiStealthService: () => SuiStealthService,
5495
+ SurveillanceAnalyzer: () => SurveillanceAnalyzer,
5019
5496
  SwapStatus: () => SwapStatus,
5020
5497
  ThresholdViewingKey: () => ThresholdViewingKey,
5021
5498
  Treasury: () => Treasury,
5022
5499
  TrezorWalletAdapter: () => TrezorWalletAdapter,
5023
5500
  ValidationError: () => ValidationError,
5024
5501
  WalletError: () => WalletError,
5025
- WalletErrorCode: () => import_types57.WalletErrorCode,
5026
- ZcashErrorCode: () => import_types63.ZcashErrorCode,
5502
+ WalletErrorCode: () => import_types58.WalletErrorCode,
5503
+ ZcashErrorCode: () => import_types64.ZcashErrorCode,
5027
5504
  ZcashNativeBackend: () => ZcashNativeBackend,
5028
5505
  ZcashRPCClient: () => ZcashRPCClient,
5029
5506
  ZcashRPCError: () => ZcashRPCError,
@@ -5032,11 +5509,15 @@ __export(index_exports, {
5032
5509
  addBlindings: () => addBlindings,
5033
5510
  addCommitments: () => addCommitments,
5034
5511
  addOracle: () => addOracle,
5512
+ analyzeAddressReuse: () => analyzeAddressReuse,
5513
+ analyzeTemporalPatterns: () => analyzeTemporalPatterns,
5035
5514
  aptosAddressToAuthKey: () => aptosAddressToAuthKey,
5036
5515
  attachProofs: () => attachProofs,
5037
5516
  base58ToHex: () => base58ToHex,
5038
- browserBytesToHex: () => bytesToHex12,
5517
+ browserBytesToHex: () => bytesToHex11,
5039
5518
  browserHexToBytes: () => hexToBytes10,
5519
+ calculatePrivacyScore: () => calculatePrivacyScore,
5520
+ calculateSIPComparison: () => calculateSIPComparison,
5040
5521
  checkAptosStealthAddress: () => checkAptosStealthAddress,
5041
5522
  checkEd25519StealthAddress: () => checkEd25519StealthAddress,
5042
5523
  checkStealthAddress: () => checkStealthAddress,
@@ -5051,6 +5532,7 @@ __export(index_exports, {
5051
5532
  createEthereumAdapter: () => createEthereumAdapter,
5052
5533
  createKeySpendOnlyOutput: () => createKeySpendOnlyOutput,
5053
5534
  createLedgerAdapter: () => createLedgerAdapter,
5535
+ createMockAttestation: () => createMockAttestation,
5054
5536
  createMockEthereumAdapter: () => createMockEthereumAdapter,
5055
5537
  createMockEthereumProvider: () => createMockEthereumProvider,
5056
5538
  createMockLedgerAdapter: () => createMockLedgerAdapter,
@@ -5065,6 +5547,7 @@ __export(index_exports, {
5065
5547
  createPrivateOwnership: () => createPrivateOwnership,
5066
5548
  createPrivateVoting: () => createPrivateVoting,
5067
5549
  createProductionSIP: () => createProductionSIP,
5550
+ createProvider: () => createProvider,
5068
5551
  createSIP: () => createSIP,
5069
5552
  createSameChainExecutor: () => createSameChainExecutor,
5070
5553
  createSealedBidAuction: () => createSealedBidAuction,
@@ -5072,9 +5555,11 @@ __export(index_exports, {
5072
5555
  createShieldedPayment: () => createShieldedPayment,
5073
5556
  createSmartRouter: () => createSmartRouter,
5074
5557
  createSolanaAdapter: () => createSolanaAdapter,
5558
+ createSurveillanceAnalyzer: () => createSurveillanceAnalyzer,
5075
5559
  createTaprootOutput: () => createTaprootOutput,
5076
5560
  createTrezorAdapter: () => createTrezorAdapter,
5077
5561
  createWalletFactory: () => createWalletFactory,
5562
+ createWebhookHandler: () => createWebhookHandler,
5078
5563
  createZcashClient: () => createZcashClient,
5079
5564
  createZcashNativeBackend: () => createZcashNativeBackend,
5080
5565
  createZcashShieldedService: () => createZcashShieldedService,
@@ -5083,6 +5568,7 @@ __export(index_exports, {
5083
5568
  decodeTaprootAddress: () => decodeTaprootAddress,
5084
5569
  decryptMemo: () => decryptMemo,
5085
5570
  decryptWithViewing: () => decryptWithViewing,
5571
+ defaultRegistry: () => defaultRegistry,
5086
5572
  deriveAptosStealthPrivateKey: () => deriveAptosStealthPrivateKey,
5087
5573
  deriveEd25519StealthPrivateKey: () => deriveEd25519StealthPrivateKey,
5088
5574
  deriveOracleId: () => deriveOracleId,
@@ -5092,7 +5578,9 @@ __export(index_exports, {
5092
5578
  deserializeAttestationMessage: () => deserializeAttestationMessage,
5093
5579
  deserializeIntent: () => deserializeIntent,
5094
5580
  deserializePayment: () => deserializePayment,
5581
+ detectClusters: () => detectClusters,
5095
5582
  detectEthereumWallets: () => detectEthereumWallets,
5583
+ detectExchangeExposure: () => detectExchangeExposure,
5096
5584
  detectSolanaWallets: () => detectSolanaWallets,
5097
5585
  ed25519PublicKeyToAptosAddress: () => ed25519PublicKeyToAptosAddress,
5098
5586
  ed25519PublicKeyToNearAddress: () => ed25519PublicKeyToNearAddress,
@@ -5102,6 +5590,7 @@ __export(index_exports, {
5102
5590
  encryptForViewing: () => encryptForViewing,
5103
5591
  estimatePrivateTransferFee: () => estimatePrivateTransferFee,
5104
5592
  featureNotSupportedError: () => featureNotSupportedError,
5593
+ fetchAttestation: () => fetchAttestation,
5105
5594
  formatStablecoinAmount: () => formatStablecoinAmount,
5106
5595
  fromHex: () => fromHex,
5107
5596
  fromStablecoinUnits: () => fromStablecoinUnits,
@@ -5157,7 +5646,7 @@ __export(index_exports, {
5157
5646
  isExpired: () => isExpired,
5158
5647
  isNonNegativeAmount: () => isNonNegativeAmount,
5159
5648
  isPaymentExpired: () => isPaymentExpired,
5160
- isPrivate: () => import_types58.isPrivate,
5649
+ isPrivate: () => import_types59.isPrivate,
5161
5650
  isPrivateWalletAdapter: () => isPrivateWalletAdapter,
5162
5651
  isSIPError: () => isSIPError,
5163
5652
  isSameChainSupported: () => isSameChainSupported,
@@ -5186,6 +5675,7 @@ __export(index_exports, {
5186
5675
  normalizeSuiAddress: () => normalizeSuiAddress,
5187
5676
  notConnectedError: () => notConnectedError,
5188
5677
  parseAnnouncement: () => parseAnnouncement,
5678
+ processWebhookTransaction: () => processWebhookTransaction,
5189
5679
  proveOwnership: () => proveOwnership,
5190
5680
  publicKeyToEthAddress: () => publicKeyToEthAddress,
5191
5681
  registerWallet: () => registerWallet,
@@ -5208,7 +5698,7 @@ __export(index_exports, {
5208
5698
  subtractBlindings: () => subtractBlindings,
5209
5699
  subtractCommitments: () => subtractCommitments,
5210
5700
  supportsSharedArrayBuffer: () => supportsSharedArrayBuffer,
5211
- supportsViewingKey: () => import_types58.supportsViewingKey,
5701
+ supportsViewingKey: () => import_types59.supportsViewingKey,
5212
5702
  supportsWebBluetooth: () => supportsWebBluetooth,
5213
5703
  supportsWebHID: () => supportsWebHID,
5214
5704
  supportsWebUSB: () => supportsWebUSB,
@@ -5226,6 +5716,7 @@ __export(index_exports, {
5226
5716
  validateScalar: () => validateScalar,
5227
5717
  validateViewingKey: () => validateViewingKey,
5228
5718
  verifyAttestation: () => verifyAttestation,
5719
+ verifyAttestationSignature: () => verifyAttestationSignature,
5229
5720
  verifyCommitment: () => verifyCommitment,
5230
5721
  verifyOpening: () => verifyOpening,
5231
5722
  verifyOracleSignature: () => verifyOracleSignature,
@@ -5239,7 +5730,7 @@ module.exports = __toCommonJS(index_exports);
5239
5730
  init_errors();
5240
5731
 
5241
5732
  // src/sip.ts
5242
- var import_types7 = require("@sip-protocol/types");
5733
+ var import_types8 = require("@sip-protocol/types");
5243
5734
 
5244
5735
  // src/intent.ts
5245
5736
  var import_types = require("@sip-protocol/types");
@@ -7158,7 +7649,7 @@ var SIP = class {
7158
7649
  this.config = {
7159
7650
  ...config,
7160
7651
  mode: config.mode ?? "demo",
7161
- defaultPrivacy: config.defaultPrivacy ?? import_types7.PrivacyLevel.SHIELDED
7652
+ defaultPrivacy: config.defaultPrivacy ?? import_types8.PrivacyLevel.SHIELDED
7162
7653
  };
7163
7654
  this.proofProvider = config.proofProvider;
7164
7655
  if (config.intentsAdapter) {
@@ -7363,8 +7854,8 @@ var SIP = class {
7363
7854
  "intentsAdapter"
7364
7855
  );
7365
7856
  }
7366
- const metaAddr = recipientMetaAddress ?? (params.privacy !== import_types7.PrivacyLevel.TRANSPARENT ? this.stealthKeys?.metaAddress : void 0);
7367
- if (params.privacy !== import_types7.PrivacyLevel.TRANSPARENT && !metaAddr) {
7857
+ const metaAddr = recipientMetaAddress ?? (params.privacy !== import_types8.PrivacyLevel.TRANSPARENT ? this.stealthKeys?.metaAddress : void 0);
7858
+ if (params.privacy !== import_types8.PrivacyLevel.TRANSPARENT && !metaAddr) {
7368
7859
  throw new ValidationError(
7369
7860
  "Stealth meta-address required for privacy modes. Call generateStealthKeys() or provide recipientMetaAddress.",
7370
7861
  "recipientMetaAddress"
@@ -7455,10 +7946,10 @@ var SIP = class {
7455
7946
  }
7456
7947
  );
7457
7948
  this.pendingSwaps.delete(quote.intentId);
7458
- const isSuccess = finalStatus.status === import_types7.OneClickSwapStatus.SUCCESS;
7949
+ const isSuccess = finalStatus.status === import_types8.OneClickSwapStatus.SUCCESS;
7459
7950
  return {
7460
7951
  intentId: intent.intentId,
7461
- status: isSuccess ? import_types7.IntentStatus.FULFILLED : import_types7.IntentStatus.FAILED,
7952
+ status: isSuccess ? import_types8.IntentStatus.FULFILLED : import_types8.IntentStatus.FAILED,
7462
7953
  outputAmount: quote.outputAmount,
7463
7954
  txHash: finalStatus.settlementTxHash ?? depositTxHash,
7464
7955
  fulfilledAt: Math.floor(Date.now() / 1e3),
@@ -7525,9 +8016,9 @@ var SIP = class {
7525
8016
  await new Promise((resolve) => setTimeout(resolve, 2e3));
7526
8017
  return {
7527
8018
  intentId: intent.intentId,
7528
- status: import_types7.IntentStatus.FULFILLED,
8019
+ status: import_types8.IntentStatus.FULFILLED,
7529
8020
  outputAmount: quote.outputAmount,
7530
- txHash: intent.privacyLevel === import_types7.PrivacyLevel.TRANSPARENT ? `0x${Date.now().toString(16)}` : void 0,
8021
+ txHash: intent.privacyLevel === import_types8.PrivacyLevel.TRANSPARENT ? `0x${Date.now().toString(16)}` : void 0,
7531
8022
  fulfilledAt: Math.floor(Date.now() / 1e3)
7532
8023
  };
7533
8024
  }
@@ -7569,7 +8060,7 @@ var SIP = class {
7569
8060
  }
7570
8061
  const { sendPrivateSPLTransfer: sendPrivateSPLTransfer2 } = await Promise.resolve().then(() => (init_solana(), solana_exports));
7571
8062
  const { PublicKey: SolanaPublicKey } = await import("@solana/web3.js");
7572
- const { getAssociatedTokenAddress: getAssociatedTokenAddress3 } = await import("@solana/spl-token");
8063
+ const { getAssociatedTokenAddress: getAssociatedTokenAddress4 } = await import("@solana/spl-token");
7573
8064
  const { SOLANA_TOKEN_MINTS: SOLANA_TOKEN_MINTS2 } = await Promise.resolve().then(() => (init_constants(), constants_exports));
7574
8065
  let mint;
7575
8066
  if (params.token in SOLANA_TOKEN_MINTS2) {
@@ -7577,7 +8068,7 @@ var SIP = class {
7577
8068
  } else {
7578
8069
  mint = new SolanaPublicKey(params.token);
7579
8070
  }
7580
- const senderTokenAccount = await getAssociatedTokenAddress3(
8071
+ const senderTokenAccount = await getAssociatedTokenAddress4(
7581
8072
  mint,
7582
8073
  params.sender
7583
8074
  );
@@ -8140,7 +8631,7 @@ function hexToBytes10(hex) {
8140
8631
  }
8141
8632
  return bytes;
8142
8633
  }
8143
- function bytesToHex12(bytes) {
8634
+ function bytesToHex11(bytes) {
8144
8635
  return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
8145
8636
  }
8146
8637
  function isBrowser() {
@@ -8203,7 +8694,7 @@ var CHAIN_NUMERIC_IDS = {
8203
8694
  };
8204
8695
 
8205
8696
  // src/oracle/verification.ts
8206
- var import_ed255192 = require("@noble/curves/ed25519");
8697
+ var import_ed255193 = require("@noble/curves/ed25519");
8207
8698
  var import_sha25610 = require("@noble/hashes/sha256");
8208
8699
  var import_utils14 = require("@noble/hashes/utils");
8209
8700
 
@@ -8369,7 +8860,7 @@ function verifyAttestation(attestation, registry) {
8369
8860
  const signatureBytes = (0, import_utils14.hexToBytes)(
8370
8861
  sig.signature.startsWith("0x") ? sig.signature.slice(2) : sig.signature
8371
8862
  );
8372
- const isValid = import_ed255192.ed25519.verify(signatureBytes, messageHash, publicKeyBytes);
8863
+ const isValid = import_ed255193.ed25519.verify(signatureBytes, messageHash, publicKeyBytes);
8373
8864
  if (isValid) {
8374
8865
  validCount++;
8375
8866
  validOracles.push(sig.oracleId);
@@ -8397,14 +8888,14 @@ function verifyOracleSignature(signature, messageHash, oracle) {
8397
8888
  const signatureBytes = (0, import_utils14.hexToBytes)(
8398
8889
  signature.signature.startsWith("0x") ? signature.signature.slice(2) : signature.signature
8399
8890
  );
8400
- return import_ed255192.ed25519.verify(signatureBytes, messageHash, publicKeyBytes);
8891
+ return import_ed255193.ed25519.verify(signatureBytes, messageHash, publicKeyBytes);
8401
8892
  } catch {
8402
8893
  return false;
8403
8894
  }
8404
8895
  }
8405
8896
  function signAttestationMessage(messageHash, privateKey) {
8406
- const signature = import_ed255192.ed25519.sign(messageHash, privateKey);
8407
- const publicKey = import_ed255192.ed25519.getPublicKey(privateKey);
8897
+ const signature = import_ed255193.ed25519.sign(messageHash, privateKey);
8898
+ const publicKey = import_ed255193.ed25519.getPublicKey(privateKey);
8408
8899
  const oracleId = deriveOracleId(publicKey);
8409
8900
  return {
8410
8901
  oracleId,
@@ -8460,13 +8951,13 @@ function hasEnoughOracles(registry) {
8460
8951
  }
8461
8952
 
8462
8953
  // src/index.ts
8463
- var import_types58 = require("@sip-protocol/types");
8464
8954
  var import_types59 = require("@sip-protocol/types");
8465
8955
  var import_types60 = require("@sip-protocol/types");
8466
8956
  var import_types61 = require("@sip-protocol/types");
8957
+ var import_types62 = require("@sip-protocol/types");
8467
8958
 
8468
8959
  // src/solver/mock-solver.ts
8469
- var import_types10 = require("@sip-protocol/types");
8960
+ var import_types11 = require("@sip-protocol/types");
8470
8961
  var import_utils15 = require("@noble/hashes/utils");
8471
8962
  var MockSolver = class {
8472
8963
  info;
@@ -8592,7 +9083,7 @@ var MockSolver = class {
8592
9083
  status.error = "Simulated failure for testing";
8593
9084
  return {
8594
9085
  intentId: intent.intentId,
8595
- status: import_types10.IntentStatus.FAILED,
9086
+ status: import_types11.IntentStatus.FAILED,
8596
9087
  fulfilledAt: Math.floor(Date.now() / 1e3),
8597
9088
  error: status.error
8598
9089
  };
@@ -8602,7 +9093,7 @@ var MockSolver = class {
8602
9093
  status.txHash = txHash;
8603
9094
  return {
8604
9095
  intentId: intent.intentId,
8605
- status: import_types10.IntentStatus.FULFILLED,
9096
+ status: import_types11.IntentStatus.FULFILLED,
8606
9097
  outputAmount: quote.outputAmount,
8607
9098
  txHash: intent.privacyLevel === "transparent" ? txHash : void 0,
8608
9099
  fulfillmentProof: {
@@ -8648,7 +9139,7 @@ function createMockSolver(config) {
8648
9139
  }
8649
9140
 
8650
9141
  // src/index.ts
8651
- var import_types62 = require("@sip-protocol/types");
9142
+ var import_types63 = require("@sip-protocol/types");
8652
9143
 
8653
9144
  // src/settlement/interface.ts
8654
9145
  var SwapStatus = /* @__PURE__ */ ((SwapStatus2) => {
@@ -9055,21 +9546,21 @@ function createSmartRouter(registry) {
9055
9546
  }
9056
9547
 
9057
9548
  // src/settlement/backends/near-intents.ts
9058
- var import_types11 = require("@sip-protocol/types");
9549
+ var import_types12 = require("@sip-protocol/types");
9059
9550
  init_errors();
9060
9551
  function mapOneClickStatus(status) {
9061
9552
  switch (status) {
9062
- case import_types11.OneClickSwapStatus.PENDING_DEPOSIT:
9553
+ case import_types12.OneClickSwapStatus.PENDING_DEPOSIT:
9063
9554
  return "pending_deposit" /* PENDING_DEPOSIT */;
9064
- case import_types11.OneClickSwapStatus.PROCESSING:
9555
+ case import_types12.OneClickSwapStatus.PROCESSING:
9065
9556
  return "in_progress" /* IN_PROGRESS */;
9066
- case import_types11.OneClickSwapStatus.SUCCESS:
9557
+ case import_types12.OneClickSwapStatus.SUCCESS:
9067
9558
  return "success" /* SUCCESS */;
9068
- case import_types11.OneClickSwapStatus.FAILED:
9559
+ case import_types12.OneClickSwapStatus.FAILED:
9069
9560
  return "failed" /* FAILED */;
9070
- case import_types11.OneClickSwapStatus.INCOMPLETE_DEPOSIT:
9561
+ case import_types12.OneClickSwapStatus.INCOMPLETE_DEPOSIT:
9071
9562
  return "failed" /* FAILED */;
9072
- case import_types11.OneClickSwapStatus.REFUNDED:
9563
+ case import_types12.OneClickSwapStatus.REFUNDED:
9073
9564
  return "refunded" /* REFUNDED */;
9074
9565
  default:
9075
9566
  return "pending_deposit" /* PENDING_DEPOSIT */;
@@ -9107,9 +9598,9 @@ var NEARIntentsBackend = class {
9107
9598
  "zcash"
9108
9599
  ],
9109
9600
  supportedPrivacyLevels: [
9110
- import_types11.PrivacyLevel.TRANSPARENT,
9111
- import_types11.PrivacyLevel.SHIELDED,
9112
- import_types11.PrivacyLevel.COMPLIANT
9601
+ import_types12.PrivacyLevel.TRANSPARENT,
9602
+ import_types12.PrivacyLevel.SHIELDED,
9603
+ import_types12.PrivacyLevel.COMPLIANT
9113
9604
  ],
9114
9605
  supportsCancellation: false,
9115
9606
  supportsRefunds: true,
@@ -9366,13 +9857,13 @@ var NEARIntentsBackend = class {
9366
9857
  if (!params.privacyLevel) {
9367
9858
  throw new ValidationError("privacyLevel is required", "privacyLevel");
9368
9859
  }
9369
- if (params.privacyLevel !== import_types11.PrivacyLevel.TRANSPARENT && !params.recipientMetaAddress) {
9860
+ if (params.privacyLevel !== import_types12.PrivacyLevel.TRANSPARENT && !params.recipientMetaAddress) {
9370
9861
  throw new ValidationError(
9371
9862
  "recipientMetaAddress is required for shielded/compliant privacy modes",
9372
9863
  "recipientMetaAddress"
9373
9864
  );
9374
9865
  }
9375
- if (params.privacyLevel === import_types11.PrivacyLevel.TRANSPARENT && !params.senderAddress) {
9866
+ if (params.privacyLevel === import_types12.PrivacyLevel.TRANSPARENT && !params.senderAddress) {
9376
9867
  throw new ValidationError(
9377
9868
  "senderAddress is required for transparent mode",
9378
9869
  "senderAddress"
@@ -9411,7 +9902,7 @@ function createNEARIntentsBackend(config) {
9411
9902
  }
9412
9903
 
9413
9904
  // src/settlement/backends/zcash-native.ts
9414
- var import_types12 = require("@sip-protocol/types");
9905
+ var import_types13 = require("@sip-protocol/types");
9415
9906
  init_errors();
9416
9907
  var ZcashNativeBackend = class {
9417
9908
  name = "zcash-native";
@@ -9430,9 +9921,9 @@ var ZcashNativeBackend = class {
9430
9921
  supportedSourceChains: ["zcash"],
9431
9922
  supportedDestinationChains: ["zcash"],
9432
9923
  supportedPrivacyLevels: [
9433
- import_types12.PrivacyLevel.TRANSPARENT,
9434
- import_types12.PrivacyLevel.SHIELDED,
9435
- import_types12.PrivacyLevel.COMPLIANT
9924
+ import_types13.PrivacyLevel.TRANSPARENT,
9925
+ import_types13.PrivacyLevel.SHIELDED,
9926
+ import_types13.PrivacyLevel.COMPLIANT
9436
9927
  ],
9437
9928
  supportsCancellation: false,
9438
9929
  supportsRefunds: false,
@@ -9471,7 +9962,7 @@ var ZcashNativeBackend = class {
9471
9962
  const minAmountOut = amountOut * BigInt(99) / BigInt(100);
9472
9963
  let depositAddress;
9473
9964
  let recipientAddress;
9474
- if (privacyLevel === import_types12.PrivacyLevel.SHIELDED || privacyLevel === import_types12.PrivacyLevel.COMPLIANT) {
9965
+ if (privacyLevel === import_types13.PrivacyLevel.SHIELDED || privacyLevel === import_types13.PrivacyLevel.COMPLIANT) {
9475
9966
  if (typeof recipientMetaAddress === "string") {
9476
9967
  recipientAddress = recipientMetaAddress;
9477
9968
  } else if (recipientMetaAddress) {
@@ -9756,7 +10247,7 @@ function createZcashNativeBackend(config) {
9756
10247
  }
9757
10248
 
9758
10249
  // src/settlement/backends/direct-chain.ts
9759
- var import_types13 = require("@sip-protocol/types");
10250
+ var import_types14 = require("@sip-protocol/types");
9760
10251
  init_stealth();
9761
10252
  init_errors();
9762
10253
  var import_utils16 = require("@noble/hashes/utils");
@@ -9798,7 +10289,7 @@ var DEFAULT_GAS_FEES = {
9798
10289
  };
9799
10290
 
9800
10291
  // src/zcash/rpc-client.ts
9801
- var import_types14 = require("@sip-protocol/types");
10292
+ var import_types15 = require("@sip-protocol/types");
9802
10293
  init_errors();
9803
10294
  var DEFAULT_CONFIG = {
9804
10295
  host: "127.0.0.1",
@@ -9819,19 +10310,19 @@ var ZcashRPCError = class extends Error {
9819
10310
  * Check if error is due to insufficient funds
9820
10311
  */
9821
10312
  isInsufficientFunds() {
9822
- return this.code === import_types14.ZcashErrorCode.WALLET_INSUFFICIENT_FUNDS;
10313
+ return this.code === import_types15.ZcashErrorCode.WALLET_INSUFFICIENT_FUNDS;
9823
10314
  }
9824
10315
  /**
9825
10316
  * Check if error is due to invalid address
9826
10317
  */
9827
10318
  isInvalidAddress() {
9828
- return this.code === import_types14.ZcashErrorCode.INVALID_ADDRESS_OR_KEY;
10319
+ return this.code === import_types15.ZcashErrorCode.INVALID_ADDRESS_OR_KEY;
9829
10320
  }
9830
10321
  /**
9831
10322
  * Check if error is due to wallet being locked
9832
10323
  */
9833
10324
  isWalletLocked() {
9834
- return this.code === import_types14.ZcashErrorCode.WALLET_UNLOCK_NEEDED;
10325
+ return this.code === import_types15.ZcashErrorCode.WALLET_UNLOCK_NEEDED;
9835
10326
  }
9836
10327
  };
9837
10328
  var ZcashRPCClient = class {
@@ -10218,7 +10709,7 @@ function createZcashClient(config) {
10218
10709
  }
10219
10710
 
10220
10711
  // src/zcash/shielded-service.ts
10221
- var import_types15 = require("@sip-protocol/types");
10712
+ var import_types16 = require("@sip-protocol/types");
10222
10713
  init_errors();
10223
10714
  var ZcashShieldedService = class _ZcashShieldedService {
10224
10715
  client;
@@ -10405,7 +10896,7 @@ var ZcashShieldedService = class _ZcashShieldedService {
10405
10896
  * Higher-level method that handles privacy level mapping.
10406
10897
  */
10407
10898
  async sendWithPrivacy(to, amount, privacyLevel, memo) {
10408
- if (privacyLevel === import_types15.PrivacyLevel.TRANSPARENT) {
10899
+ if (privacyLevel === import_types16.PrivacyLevel.TRANSPARENT) {
10409
10900
  throw new ValidationError(
10410
10901
  "Transparent mode not supported for Zcash shielded service. Use standard RPC client.",
10411
10902
  "privacyLevel",
@@ -10499,7 +10990,7 @@ var ZcashShieldedService = class _ZcashShieldedService {
10499
10990
  const viewingKey = await this.exportViewingKey();
10500
10991
  return {
10501
10992
  viewingKey,
10502
- privacyLevel: import_types15.PrivacyLevel.COMPLIANT,
10993
+ privacyLevel: import_types16.PrivacyLevel.COMPLIANT,
10503
10994
  disclaimer: "This viewing key provides read-only access to transaction history. It cannot be used to spend funds. Share only with authorized auditors."
10504
10995
  };
10505
10996
  }
@@ -10585,11 +11076,11 @@ var ZcashShieldedService = class _ZcashShieldedService {
10585
11076
  */
10586
11077
  mapPrivacyLevelToPolicy(level) {
10587
11078
  switch (level) {
10588
- case import_types15.PrivacyLevel.TRANSPARENT:
11079
+ case import_types16.PrivacyLevel.TRANSPARENT:
10589
11080
  return "NoPrivacy";
10590
- case import_types15.PrivacyLevel.SHIELDED:
11081
+ case import_types16.PrivacyLevel.SHIELDED:
10591
11082
  return "FullPrivacy";
10592
- case import_types15.PrivacyLevel.COMPLIANT:
11083
+ case import_types16.PrivacyLevel.COMPLIANT:
10593
11084
  return "FullPrivacy";
10594
11085
  default:
10595
11086
  return "FullPrivacy";
@@ -10642,7 +11133,7 @@ function createZcashShieldedService(config) {
10642
11133
  }
10643
11134
 
10644
11135
  // src/zcash/swap-service.ts
10645
- var import_types16 = require("@sip-protocol/types");
11136
+ var import_types17 = require("@sip-protocol/types");
10646
11137
  init_errors();
10647
11138
  var MOCK_PRICES = {
10648
11139
  ETH: 2500,
@@ -10756,7 +11247,7 @@ var ZcashSwapService = class {
10756
11247
  validUntil,
10757
11248
  depositAddress: this.generateMockDepositAddress(sourceChain),
10758
11249
  estimatedTime: this.getEstimatedTime(sourceChain),
10759
- privacyLevel: import_types16.PrivacyLevel.SHIELDED
11250
+ privacyLevel: import_types17.PrivacyLevel.SHIELDED
10760
11251
  };
10761
11252
  this.quotes.set(quoteId, quote);
10762
11253
  return quote;
@@ -10799,7 +11290,7 @@ var ZcashSwapService = class {
10799
11290
  depositAddress: "",
10800
11291
  // Will be set by bridge
10801
11292
  estimatedTime: this.getEstimatedTime(params.sourceChain),
10802
- privacyLevel: import_types16.PrivacyLevel.SHIELDED
11293
+ privacyLevel: import_types17.PrivacyLevel.SHIELDED
10803
11294
  };
10804
11295
  this.quotes.set(quote.quoteId, quote);
10805
11296
  return quote;
@@ -11082,10 +11573,10 @@ function createZcashSwapService(config) {
11082
11573
  init_errors();
11083
11574
 
11084
11575
  // src/zcash/index.ts
11085
- var import_types17 = require("@sip-protocol/types");
11576
+ var import_types18 = require("@sip-protocol/types");
11086
11577
 
11087
11578
  // src/index.ts
11088
- var import_types63 = require("@sip-protocol/types");
11579
+ var import_types64 = require("@sip-protocol/types");
11089
11580
 
11090
11581
  // src/bitcoin/taproot.ts
11091
11582
  var import_secp256k14 = require("@noble/curves/secp256k1");
@@ -11380,7 +11871,7 @@ init_errors();
11380
11871
  init_validation();
11381
11872
 
11382
11873
  // src/payment/payment.ts
11383
- var import_types18 = require("@sip-protocol/types");
11874
+ var import_types19 = require("@sip-protocol/types");
11384
11875
  var import_sha25613 = require("@noble/hashes/sha256");
11385
11876
  var import_utils19 = require("@noble/hashes/utils");
11386
11877
  var import_chacha2 = require("@noble/ciphers/chacha.js");
@@ -11571,7 +12062,7 @@ var PaymentBuilder = class {
11571
12062
  _amount;
11572
12063
  _recipientMetaAddress;
11573
12064
  _recipientAddress;
11574
- _privacy = import_types18.PrivacyLevel.SHIELDED;
12065
+ _privacy = import_types19.PrivacyLevel.SHIELDED;
11575
12066
  _viewingKey;
11576
12067
  _sourceChain;
11577
12068
  _destinationChain;
@@ -11854,7 +12345,7 @@ async function createShieldedPayment(params, options) {
11854
12345
  } else {
11855
12346
  resolvedToken = token;
11856
12347
  }
11857
- if (privacy !== import_types18.PrivacyLevel.TRANSPARENT && !recipientMetaAddress) {
12348
+ if (privacy !== import_types19.PrivacyLevel.TRANSPARENT && !recipientMetaAddress) {
11858
12349
  throw new ValidationError(
11859
12350
  "recipientMetaAddress is required for shielded/compliant privacy modes",
11860
12351
  "recipientMetaAddress",
@@ -11862,7 +12353,7 @@ async function createShieldedPayment(params, options) {
11862
12353
  "SIP_2008" /* MISSING_REQUIRED */
11863
12354
  );
11864
12355
  }
11865
- if (privacy === import_types18.PrivacyLevel.TRANSPARENT && !recipientAddress) {
12356
+ if (privacy === import_types19.PrivacyLevel.TRANSPARENT && !recipientAddress) {
11866
12357
  throw new ValidationError(
11867
12358
  "recipientAddress is required for transparent mode",
11868
12359
  "recipientAddress",
@@ -11870,7 +12361,7 @@ async function createShieldedPayment(params, options) {
11870
12361
  "SIP_2008" /* MISSING_REQUIRED */
11871
12362
  );
11872
12363
  }
11873
- if (privacy === import_types18.PrivacyLevel.COMPLIANT && !viewingKey) {
12364
+ if (privacy === import_types19.PrivacyLevel.COMPLIANT && !viewingKey) {
11874
12365
  throw new ValidationError(
11875
12366
  "viewingKey is required for compliant mode",
11876
12367
  "viewingKey",
@@ -11892,7 +12383,7 @@ async function createShieldedPayment(params, options) {
11892
12383
  const now = Math.floor(Date.now() / 1e3);
11893
12384
  const payment = {
11894
12385
  paymentId,
11895
- version: import_types18.SIP_VERSION,
12386
+ version: import_types19.SIP_VERSION,
11896
12387
  privacyLevel: privacy,
11897
12388
  createdAt: now,
11898
12389
  expiry: now + ttl,
@@ -11903,7 +12394,7 @@ async function createShieldedPayment(params, options) {
11903
12394
  purpose,
11904
12395
  viewingKeyHash
11905
12396
  };
11906
- if (privacy !== import_types18.PrivacyLevel.TRANSPARENT && recipientMetaAddress) {
12397
+ if (privacy !== import_types19.PrivacyLevel.TRANSPARENT && recipientMetaAddress) {
11907
12398
  const metaAddress = decodeStealthMetaAddress(recipientMetaAddress);
11908
12399
  const { stealthAddress } = generateStealthAddress(metaAddress);
11909
12400
  payment.recipientStealth = stealthAddress;
@@ -11920,7 +12411,7 @@ async function createShieldedPayment(params, options) {
11920
12411
  payment.recipientAddress = recipientAddress;
11921
12412
  payment.memo = memo;
11922
12413
  }
11923
- if (privacy !== import_types18.PrivacyLevel.TRANSPARENT && proofProvider?.isReady) {
12414
+ if (privacy !== import_types19.PrivacyLevel.TRANSPARENT && proofProvider?.isReady) {
11924
12415
  const hexToUint8 = (hex) => {
11925
12416
  const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
11926
12417
  return (0, import_utils19.hexToBytes)(cleanHex);
@@ -11986,7 +12477,7 @@ function decryptMemo(encryptedMemo, viewingKey) {
11986
12477
  function trackPayment(payment) {
11987
12478
  return {
11988
12479
  ...payment,
11989
- status: import_types18.PaymentStatus.DRAFT
12480
+ status: import_types19.PaymentStatus.DRAFT
11990
12481
  };
11991
12482
  }
11992
12483
  function isPaymentExpired(payment) {
@@ -12019,7 +12510,7 @@ function getPaymentSummary(payment) {
12019
12510
  }
12020
12511
 
12021
12512
  // src/treasury/treasury.ts
12022
- var import_types19 = require("@sip-protocol/types");
12513
+ var import_types20 = require("@sip-protocol/types");
12023
12514
  var import_secp256k16 = require("@noble/curves/secp256k1");
12024
12515
  var import_sha25614 = require("@noble/hashes/sha256");
12025
12516
  var import_utils20 = require("@noble/hashes/utils");
@@ -12055,7 +12546,7 @@ var Treasury = class _Treasury {
12055
12546
  ...m,
12056
12547
  addedAt: now
12057
12548
  })),
12058
- defaultPrivacy: params.defaultPrivacy ?? import_types19.PrivacyLevel.SHIELDED,
12549
+ defaultPrivacy: params.defaultPrivacy ?? import_types20.PrivacyLevel.SHIELDED,
12059
12550
  masterViewingKey,
12060
12551
  dailyLimit: params.dailyLimit,
12061
12552
  transactionLimit: params.transactionLimit,
@@ -12134,7 +12625,7 @@ var Treasury = class _Treasury {
12134
12625
  proposalId,
12135
12626
  treasuryId: this.config.treasuryId,
12136
12627
  type: "payment",
12137
- status: import_types19.ProposalStatus.PENDING,
12628
+ status: import_types20.ProposalStatus.PENDING,
12138
12629
  proposer: "",
12139
12630
  // Should be set by caller
12140
12631
  title: params.title,
@@ -12167,7 +12658,7 @@ var Treasury = class _Treasury {
12167
12658
  proposalId,
12168
12659
  treasuryId: this.config.treasuryId,
12169
12660
  type: "batch_payment",
12170
- status: import_types19.ProposalStatus.PENDING,
12661
+ status: import_types20.ProposalStatus.PENDING,
12171
12662
  proposer: "",
12172
12663
  title: params.title,
12173
12664
  description: params.description,
@@ -12201,7 +12692,7 @@ var Treasury = class _Treasury {
12201
12692
  * Get pending proposals
12202
12693
  */
12203
12694
  getPendingProposals() {
12204
- return this.getAllProposals().filter((p) => p.status === import_types19.ProposalStatus.PENDING);
12695
+ return this.getAllProposals().filter((p) => p.status === import_types20.ProposalStatus.PENDING);
12205
12696
  }
12206
12697
  /**
12207
12698
  * Sign a proposal
@@ -12232,7 +12723,7 @@ var Treasury = class _Treasury {
12232
12723
  "SIP_2001" /* INVALID_INPUT */
12233
12724
  );
12234
12725
  }
12235
- if (proposal.status !== import_types19.ProposalStatus.PENDING) {
12726
+ if (proposal.status !== import_types20.ProposalStatus.PENDING) {
12236
12727
  throw new ValidationError(
12237
12728
  `proposal is not pending: ${proposal.status}`,
12238
12729
  "proposalId",
@@ -12242,7 +12733,7 @@ var Treasury = class _Treasury {
12242
12733
  }
12243
12734
  const now = Math.floor(Date.now() / 1e3);
12244
12735
  if (now > proposal.expiresAt) {
12245
- proposal.status = import_types19.ProposalStatus.EXPIRED;
12736
+ proposal.status = import_types20.ProposalStatus.EXPIRED;
12246
12737
  throw new ValidationError(
12247
12738
  "proposal has expired",
12248
12739
  "proposalId",
@@ -12274,9 +12765,9 @@ var Treasury = class _Treasury {
12274
12765
  const approvals = proposal.signatures.filter((s) => s.approved).length;
12275
12766
  const rejections = proposal.signatures.filter((s) => !s.approved).length;
12276
12767
  if (approvals >= proposal.requiredSignatures) {
12277
- proposal.status = import_types19.ProposalStatus.APPROVED;
12768
+ proposal.status = import_types20.ProposalStatus.APPROVED;
12278
12769
  } else if (rejections > this.config.totalSigners - proposal.requiredSignatures) {
12279
- proposal.status = import_types19.ProposalStatus.REJECTED;
12770
+ proposal.status = import_types20.ProposalStatus.REJECTED;
12280
12771
  }
12281
12772
  return proposal;
12282
12773
  }
@@ -12293,7 +12784,7 @@ var Treasury = class _Treasury {
12293
12784
  "SIP_2001" /* INVALID_INPUT */
12294
12785
  );
12295
12786
  }
12296
- if (proposal.status !== import_types19.ProposalStatus.APPROVED) {
12787
+ if (proposal.status !== import_types20.ProposalStatus.APPROVED) {
12297
12788
  throw new ValidationError(
12298
12789
  `proposal is not approved: ${proposal.status}`,
12299
12790
  "proposalId",
@@ -12306,8 +12797,8 @@ var Treasury = class _Treasury {
12306
12797
  const payment = await createShieldedPayment({
12307
12798
  token: proposal.payment.token,
12308
12799
  amount: proposal.payment.amount,
12309
- recipientMetaAddress: proposal.payment.privacy !== import_types19.PrivacyLevel.TRANSPARENT ? proposal.payment.recipient : void 0,
12310
- recipientAddress: proposal.payment.privacy === import_types19.PrivacyLevel.TRANSPARENT ? proposal.payment.recipient : void 0,
12800
+ recipientMetaAddress: proposal.payment.privacy !== import_types20.PrivacyLevel.TRANSPARENT ? proposal.payment.recipient : void 0,
12801
+ recipientAddress: proposal.payment.privacy === import_types20.PrivacyLevel.TRANSPARENT ? proposal.payment.recipient : void 0,
12311
12802
  privacy: proposal.payment.privacy,
12312
12803
  viewingKey: this.config.masterViewingKey?.key,
12313
12804
  sourceChain: this.config.chain,
@@ -12320,8 +12811,8 @@ var Treasury = class _Treasury {
12320
12811
  const payment = await createShieldedPayment({
12321
12812
  token: proposal.batchPayment.token,
12322
12813
  amount: recipient.amount,
12323
- recipientMetaAddress: proposal.batchPayment.privacy !== import_types19.PrivacyLevel.TRANSPARENT ? recipient.address : void 0,
12324
- recipientAddress: proposal.batchPayment.privacy === import_types19.PrivacyLevel.TRANSPARENT ? recipient.address : void 0,
12814
+ recipientMetaAddress: proposal.batchPayment.privacy !== import_types20.PrivacyLevel.TRANSPARENT ? recipient.address : void 0,
12815
+ recipientAddress: proposal.batchPayment.privacy === import_types20.PrivacyLevel.TRANSPARENT ? recipient.address : void 0,
12325
12816
  privacy: proposal.batchPayment.privacy,
12326
12817
  viewingKey: this.config.masterViewingKey?.key,
12327
12818
  sourceChain: this.config.chain,
@@ -12331,7 +12822,7 @@ var Treasury = class _Treasury {
12331
12822
  payments.push(payment);
12332
12823
  }
12333
12824
  }
12334
- proposal.status = import_types19.ProposalStatus.EXECUTED;
12825
+ proposal.status = import_types20.ProposalStatus.EXECUTED;
12335
12826
  proposal.executedAt = Math.floor(Date.now() / 1e3);
12336
12827
  proposal.resultPayments = payments;
12337
12828
  return payments;
@@ -12360,7 +12851,7 @@ var Treasury = class _Treasury {
12360
12851
  "SIP_2001" /* INVALID_INPUT */
12361
12852
  );
12362
12853
  }
12363
- if (proposal.status !== import_types19.ProposalStatus.PENDING) {
12854
+ if (proposal.status !== import_types20.ProposalStatus.PENDING) {
12364
12855
  throw new ValidationError(
12365
12856
  `proposal is not pending: ${proposal.status}`,
12366
12857
  "proposalId",
@@ -12368,7 +12859,7 @@ var Treasury = class _Treasury {
12368
12859
  "SIP_2001" /* INVALID_INPUT */
12369
12860
  );
12370
12861
  }
12371
- proposal.status = import_types19.ProposalStatus.CANCELLED;
12862
+ proposal.status = import_types20.ProposalStatus.CANCELLED;
12372
12863
  return proposal;
12373
12864
  }
12374
12865
  // ─── Auditor Access ──────────────────────────────────────────────────────────
@@ -12465,7 +12956,7 @@ var Treasury = class _Treasury {
12465
12956
  getCommittedAmount(token) {
12466
12957
  let committed = 0n;
12467
12958
  for (const proposal of this.proposals.values()) {
12468
- if (proposal.status !== import_types19.ProposalStatus.PENDING) continue;
12959
+ if (proposal.status !== import_types20.ProposalStatus.PENDING) continue;
12469
12960
  if (proposal.type === "payment" && proposal.payment) {
12470
12961
  if (proposal.payment.token.symbol === token.symbol && proposal.payment.token.chain === token.chain) {
12471
12962
  committed += proposal.payment.amount;
@@ -12708,7 +13199,7 @@ function validateBatchProposalParams(params, config) {
12708
13199
  }
12709
13200
 
12710
13201
  // src/compliance/compliance-manager.ts
12711
- var import_types20 = require("@sip-protocol/types");
13202
+ var import_types21 = require("@sip-protocol/types");
12712
13203
  var import_utils21 = require("@noble/hashes/utils");
12713
13204
  init_errors();
12714
13205
  var DEFAULTS2 = {
@@ -13077,7 +13568,7 @@ var ComplianceManager = class _ComplianceManager {
13077
13568
  title: params.title,
13078
13569
  description: params.description,
13079
13570
  format: params.format,
13080
- status: import_types20.ReportStatus.GENERATING,
13571
+ status: import_types21.ReportStatus.GENERATING,
13081
13572
  requestedBy,
13082
13573
  requestedAt: now,
13083
13574
  startDate: params.startDate,
@@ -13106,10 +13597,10 @@ var ComplianceManager = class _ComplianceManager {
13106
13597
  } else if (params.format === "csv") {
13107
13598
  report.content = this.generateCSV(transactions);
13108
13599
  }
13109
- report.status = import_types20.ReportStatus.COMPLETED;
13600
+ report.status = import_types21.ReportStatus.COMPLETED;
13110
13601
  report.generatedAt = Math.floor(Date.now() / 1e3);
13111
13602
  } catch (error) {
13112
- report.status = import_types20.ReportStatus.FAILED;
13603
+ report.status = import_types21.ReportStatus.FAILED;
13113
13604
  report.error = error instanceof Error ? error.message : "Unknown error";
13114
13605
  }
13115
13606
  this.addAuditLog(requestedBy, "report_generated", {
@@ -15180,54 +15671,359 @@ var AuditorKeyDerivation = class {
15180
15671
  }
15181
15672
  };
15182
15673
 
15183
- // src/auction/sealed-bid.ts
15674
+ // src/compliance/range-sas.ts
15675
+ var import_sha25620 = require("@noble/hashes/sha256");
15676
+ var import_hmac3 = require("@noble/hashes/hmac");
15677
+ var import_sha5124 = require("@noble/hashes/sha512");
15184
15678
  var import_utils27 = require("@noble/hashes/utils");
15185
15679
  init_errors();
15186
- var SealedBidAuction = class {
15680
+ init_secure_memory();
15681
+ var AttestationSchema = /* @__PURE__ */ ((AttestationSchema2) => {
15682
+ AttestationSchema2["RANGE_KYC_V1"] = "range-kyc-v1";
15683
+ AttestationSchema2["RANGE_ACCREDITED_INVESTOR"] = "range-accredited-investor";
15684
+ AttestationSchema2["RANGE_INSTITUTIONAL"] = "range-institutional";
15685
+ AttestationSchema2["RANGE_REGULATOR"] = "range-regulator";
15686
+ AttestationSchema2["CUSTOM"] = "custom";
15687
+ return AttestationSchema2;
15688
+ })(AttestationSchema || {});
15689
+ var DEFAULT_MAX_CACHE_SIZE = 1e3;
15690
+ var AttestationGatedDisclosure = class {
15691
+ config;
15692
+ derivedKeys = /* @__PURE__ */ new Map();
15693
+ cacheOrder = [];
15694
+ // LRU tracking
15187
15695
  /**
15188
- * Create a sealed bid for an auction
15189
- *
15190
- * Generates a cryptographically binding commitment to a bid amount.
15191
- * The commitment can be published publicly without revealing the bid.
15696
+ * Create a new attestation-gated disclosure manager
15192
15697
  *
15193
- * **Important:** Keep the returned `BidReceipt` secret! It contains the bid
15194
- * amount and salt needed to reveal the bid later. Only publish the commitment.
15698
+ * @param config - Configuration options
15699
+ */
15700
+ constructor(config) {
15701
+ if (!config.masterViewingKey) {
15702
+ throw new ValidationError(
15703
+ "masterViewingKey is required",
15704
+ "masterViewingKey",
15705
+ void 0,
15706
+ "SIP_2008" /* MISSING_REQUIRED */
15707
+ );
15708
+ }
15709
+ this.config = {
15710
+ masterViewingKey: config.masterViewingKey,
15711
+ allowedSchemas: config.allowedSchemas ?? [],
15712
+ allowedIssuers: config.allowedIssuers ?? [],
15713
+ verifyOnChain: config.verifyOnChain ?? false,
15714
+ rangeApiEndpoint: config.rangeApiEndpoint ?? "https://api.range.org/v1",
15715
+ minAttestationAge: config.minAttestationAge ?? 0,
15716
+ maxAttestationAge: config.maxAttestationAge ?? 0,
15717
+ // 0 = no limit
15718
+ maxCacheSize: config.maxCacheSize ?? DEFAULT_MAX_CACHE_SIZE,
15719
+ customVerifier: config.customVerifier ?? (async () => true)
15720
+ };
15721
+ }
15722
+ /**
15723
+ * Derive a viewing key for a verified auditor
15195
15724
  *
15196
- * @param params - Bid creation parameters
15197
- * @returns Complete bid receipt (keep secret!) and sealed bid (publish this)
15198
- * @throws {ValidationError} If auctionId is empty, amount is non-positive, or salt is invalid
15725
+ * @param attestation - The auditor's Range SAS attestation
15726
+ * @param scope - Optional scope restrictions for the viewing key
15727
+ * @returns Derivation result with viewing key if granted
15199
15728
  *
15200
15729
  * @example
15201
15730
  * ```typescript
15202
- * const auction = new SealedBidAuction()
15203
- *
15204
- * // Create a bid for 50 ETH
15205
- * const receipt = auction.createBid({
15206
- * auctionId: 'auction-xyz',
15207
- * amount: 50n * 10n**18n,
15208
- * })
15209
- *
15210
- * // Public data (safe to publish)
15211
- * console.log({
15212
- * auctionId: receipt.auctionId,
15213
- * commitment: receipt.commitment,
15214
- * timestamp: receipt.timestamp,
15731
+ * const result = await disclosure.deriveViewingKeyForAuditor(attestation, {
15732
+ * startTime: Date.now() / 1000 - 30 * 24 * 60 * 60, // Last 30 days
15733
+ * endTime: Date.now() / 1000,
15215
15734
  * })
15216
15735
  *
15217
- * // Secret data (store securely, needed for reveal)
15218
- * secureStorage.save({
15219
- * amount: receipt.amount,
15220
- * salt: receipt.salt,
15221
- * })
15736
+ * if (result.granted) {
15737
+ * // Share result.viewingKey with auditor
15738
+ * }
15222
15739
  * ```
15223
15740
  */
15224
- createBid(params) {
15225
- if (typeof params.auctionId !== "string" || params.auctionId.length === 0) {
15226
- throw new ValidationError(
15227
- "auctionId must be a non-empty string",
15228
- "auctionId",
15229
- { received: params.auctionId }
15230
- );
15741
+ async deriveViewingKeyForAuditor(attestation, scope) {
15742
+ const verification = await this.verifyAttestation(attestation);
15743
+ if (!verification.valid) {
15744
+ return {
15745
+ granted: false,
15746
+ reason: verification.errors.join("; ")
15747
+ };
15748
+ }
15749
+ const cacheKey = this.getCacheKey(attestation);
15750
+ const cached = this.derivedKeys.get(cacheKey);
15751
+ if (cached) {
15752
+ this.updateCacheOrder(cacheKey);
15753
+ return {
15754
+ granted: true,
15755
+ viewingKey: cached,
15756
+ scope,
15757
+ expiresAt: attestation.expiresAt
15758
+ // 0 = never expires, undefined = not set
15759
+ };
15760
+ }
15761
+ const viewingKey = this.deriveKeyFromAttestation(attestation);
15762
+ this.cacheKey(cacheKey, viewingKey);
15763
+ return {
15764
+ granted: true,
15765
+ viewingKey,
15766
+ scope,
15767
+ expiresAt: attestation.expiresAt
15768
+ // 0 = never expires, undefined = not set
15769
+ };
15770
+ }
15771
+ /**
15772
+ * Verify a Range SAS attestation
15773
+ *
15774
+ * @param attestation - The attestation to verify
15775
+ * @returns Verification result
15776
+ */
15777
+ async verifyAttestation(attestation) {
15778
+ const errors = [];
15779
+ if (!attestation || typeof attestation !== "object") {
15780
+ return {
15781
+ valid: false,
15782
+ errors: ["Attestation must be an object"]
15783
+ };
15784
+ }
15785
+ if (!attestation.uid || typeof attestation.uid !== "string" || attestation.uid.trim() === "") {
15786
+ errors.push("Attestation uid is required and must be a non-empty string");
15787
+ }
15788
+ if (!attestation.subject || typeof attestation.subject !== "string" || attestation.subject.trim() === "") {
15789
+ errors.push("Attestation subject is required and must be a non-empty string");
15790
+ }
15791
+ if (!attestation.schema || typeof attestation.schema !== "string" || attestation.schema.trim() === "") {
15792
+ errors.push("Attestation schema is required and must be a non-empty string");
15793
+ }
15794
+ if (!attestation.issuer || typeof attestation.issuer !== "string" || attestation.issuer.trim() === "") {
15795
+ errors.push("Attestation issuer is required and must be a non-empty string");
15796
+ }
15797
+ if (errors.length > 0) {
15798
+ return { valid: false, errors };
15799
+ }
15800
+ if (attestation.revoked) {
15801
+ errors.push("Attestation has been revoked");
15802
+ }
15803
+ const now = Date.now() / 1e3;
15804
+ if (attestation.expiresAt > 0 && attestation.expiresAt < now) {
15805
+ errors.push("Attestation has expired");
15806
+ }
15807
+ const age = now - attestation.timestamp;
15808
+ if (age < this.config.minAttestationAge) {
15809
+ errors.push(`Attestation too new (age: ${age}s, required: ${this.config.minAttestationAge}s)`);
15810
+ }
15811
+ if (this.config.maxAttestationAge > 0 && age > this.config.maxAttestationAge) {
15812
+ errors.push(`Attestation too old (age: ${Math.floor(age)}s, max: ${this.config.maxAttestationAge}s)`);
15813
+ }
15814
+ if (this.config.allowedSchemas.length > 0) {
15815
+ if (!this.config.allowedSchemas.includes(attestation.schema)) {
15816
+ errors.push(`Schema '${attestation.schema}' not in allowed list`);
15817
+ }
15818
+ }
15819
+ if (this.config.allowedIssuers.length > 0) {
15820
+ if (!this.config.allowedIssuers.includes(attestation.issuer)) {
15821
+ errors.push(`Issuer '${attestation.issuer}' not in allowed list`);
15822
+ }
15823
+ }
15824
+ if (errors.length === 0 && this.config.customVerifier) {
15825
+ try {
15826
+ const customValid = await this.config.customVerifier(attestation);
15827
+ if (!customValid) {
15828
+ errors.push("Custom verification failed");
15829
+ }
15830
+ } catch (e) {
15831
+ errors.push(`Custom verification error: ${e instanceof Error ? e.message : "unknown"}`);
15832
+ }
15833
+ }
15834
+ return {
15835
+ valid: errors.length === 0,
15836
+ errors,
15837
+ metadata: {
15838
+ verificationMethod: this.config.verifyOnChain ? "on-chain" : "api",
15839
+ schemaVersion: attestation.schema
15840
+ }
15841
+ };
15842
+ }
15843
+ /**
15844
+ * Revoke a previously derived viewing key
15845
+ *
15846
+ * @param attestation - The attestation whose key should be revoked
15847
+ * @returns Whether revocation was successful
15848
+ */
15849
+ revokeViewingKey(attestation) {
15850
+ const key = this.getCacheKey(attestation);
15851
+ const deleted = this.derivedKeys.delete(key);
15852
+ if (deleted) {
15853
+ const index = this.cacheOrder.indexOf(key);
15854
+ if (index !== -1) {
15855
+ this.cacheOrder.splice(index, 1);
15856
+ }
15857
+ }
15858
+ return deleted;
15859
+ }
15860
+ /**
15861
+ * Check if a viewing key has been derived for an attestation
15862
+ *
15863
+ * @param attestation - The attestation to check
15864
+ * @returns Whether a key exists
15865
+ */
15866
+ hasViewingKey(attestation) {
15867
+ const key = this.getCacheKey(attestation);
15868
+ return this.derivedKeys.has(key);
15869
+ }
15870
+ /**
15871
+ * Get the current cache size
15872
+ *
15873
+ * @returns Number of cached viewing keys
15874
+ */
15875
+ getCacheSize() {
15876
+ return this.derivedKeys.size;
15877
+ }
15878
+ /**
15879
+ * Clear all cached viewing keys
15880
+ */
15881
+ clearCache() {
15882
+ this.derivedKeys.clear();
15883
+ this.cacheOrder.length = 0;
15884
+ }
15885
+ // ─── Private Methods ────────────────────────────────────────────────────────
15886
+ /**
15887
+ * Add a key to cache with LRU eviction
15888
+ */
15889
+ cacheKey(key, viewingKey) {
15890
+ while (this.derivedKeys.size >= this.config.maxCacheSize && this.cacheOrder.length > 0) {
15891
+ const oldest = this.cacheOrder.shift();
15892
+ if (oldest) {
15893
+ this.derivedKeys.delete(oldest);
15894
+ }
15895
+ }
15896
+ this.derivedKeys.set(key, viewingKey);
15897
+ this.cacheOrder.push(key);
15898
+ }
15899
+ /**
15900
+ * Update LRU order for a cache key (move to end)
15901
+ */
15902
+ updateCacheOrder(key) {
15903
+ const index = this.cacheOrder.indexOf(key);
15904
+ if (index !== -1) {
15905
+ this.cacheOrder.splice(index, 1);
15906
+ this.cacheOrder.push(key);
15907
+ }
15908
+ }
15909
+ /**
15910
+ * Derive a viewing key from an attestation
15911
+ */
15912
+ deriveKeyFromAttestation(attestation) {
15913
+ const masterKeyHex = this.config.masterViewingKey.key.startsWith("0x") ? this.config.masterViewingKey.key.slice(2) : this.config.masterViewingKey.key;
15914
+ const masterKeyBytes = (0, import_utils27.hexToBytes)(masterKeyHex);
15915
+ const derivationData = (0, import_utils27.utf8ToBytes)(
15916
+ `SIP-RANGE-SAS:${attestation.uid}:${attestation.subject}:${attestation.schema}:${attestation.signature}`
15917
+ );
15918
+ const derived = (0, import_hmac3.hmac)(import_sha5124.sha512, masterKeyBytes, derivationData);
15919
+ const keyBytes = derived.slice(0, 32);
15920
+ try {
15921
+ const key = `0x${(0, import_utils27.bytesToHex)(keyBytes)}`;
15922
+ const hashBytes = (0, import_sha25620.sha256)(keyBytes);
15923
+ const hash2 = `0x${(0, import_utils27.bytesToHex)(hashBytes)}`;
15924
+ return {
15925
+ key,
15926
+ path: `${this.config.masterViewingKey.path}/sas/${attestation.uid.slice(0, 8)}`,
15927
+ hash: hash2
15928
+ };
15929
+ } finally {
15930
+ secureWipe(masterKeyBytes);
15931
+ secureWipe(derived);
15932
+ secureWipe(keyBytes);
15933
+ }
15934
+ }
15935
+ /**
15936
+ * Get cache key for an attestation
15937
+ *
15938
+ * Includes schema and issuer to prevent cache poisoning attacks where
15939
+ * an attacker could evict legitimate cache entries with same uid:subject.
15940
+ */
15941
+ getCacheKey(attestation) {
15942
+ return `${attestation.uid}:${attestation.subject}:${attestation.schema}:${attestation.issuer}`;
15943
+ }
15944
+ };
15945
+ function createMockAttestation(overrides = {}) {
15946
+ const now = Math.floor(Date.now() / 1e3);
15947
+ return {
15948
+ uid: `sas_${Math.random().toString(36).slice(2, 10)}`,
15949
+ schema: "range-kyc-v1" /* RANGE_KYC_V1 */,
15950
+ issuer: "range-protocol",
15951
+ subject: "11111111111111111111111111111112",
15952
+ // System program (placeholder)
15953
+ data: {
15954
+ level: "institutional",
15955
+ jurisdiction: "US",
15956
+ verifiedAt: now
15957
+ },
15958
+ timestamp: now,
15959
+ expiresAt: now + 365 * 24 * 60 * 60,
15960
+ // 1 year
15961
+ signature: "0x" + "00".repeat(64),
15962
+ revoked: false,
15963
+ ...overrides
15964
+ };
15965
+ }
15966
+ async function verifyAttestationSignature(_attestation) {
15967
+ console.warn(
15968
+ "[Range SAS] verifyAttestationSignature is a STUB - always returns true. Implement real Ed25519 signature verification before production use."
15969
+ );
15970
+ return true;
15971
+ }
15972
+ async function fetchAttestation(uid, apiEndpoint = "https://api.range.org/v1") {
15973
+ console.warn(
15974
+ `[Range SAS] fetchAttestation is a STUB - returning null for ${uid}. Would fetch from ${apiEndpoint}. Implement Range API integration before production use.`
15975
+ );
15976
+ return null;
15977
+ }
15978
+
15979
+ // src/auction/sealed-bid.ts
15980
+ var import_utils28 = require("@noble/hashes/utils");
15981
+ init_errors();
15982
+ var SealedBidAuction = class {
15983
+ /**
15984
+ * Create a sealed bid for an auction
15985
+ *
15986
+ * Generates a cryptographically binding commitment to a bid amount.
15987
+ * The commitment can be published publicly without revealing the bid.
15988
+ *
15989
+ * **Important:** Keep the returned `BidReceipt` secret! It contains the bid
15990
+ * amount and salt needed to reveal the bid later. Only publish the commitment.
15991
+ *
15992
+ * @param params - Bid creation parameters
15993
+ * @returns Complete bid receipt (keep secret!) and sealed bid (publish this)
15994
+ * @throws {ValidationError} If auctionId is empty, amount is non-positive, or salt is invalid
15995
+ *
15996
+ * @example
15997
+ * ```typescript
15998
+ * const auction = new SealedBidAuction()
15999
+ *
16000
+ * // Create a bid for 50 ETH
16001
+ * const receipt = auction.createBid({
16002
+ * auctionId: 'auction-xyz',
16003
+ * amount: 50n * 10n**18n,
16004
+ * })
16005
+ *
16006
+ * // Public data (safe to publish)
16007
+ * console.log({
16008
+ * auctionId: receipt.auctionId,
16009
+ * commitment: receipt.commitment,
16010
+ * timestamp: receipt.timestamp,
16011
+ * })
16012
+ *
16013
+ * // Secret data (store securely, needed for reveal)
16014
+ * secureStorage.save({
16015
+ * amount: receipt.amount,
16016
+ * salt: receipt.salt,
16017
+ * })
16018
+ * ```
16019
+ */
16020
+ createBid(params) {
16021
+ if (typeof params.auctionId !== "string" || params.auctionId.length === 0) {
16022
+ throw new ValidationError(
16023
+ "auctionId must be a non-empty string",
16024
+ "auctionId",
16025
+ { received: params.auctionId }
16026
+ );
15231
16027
  }
15232
16028
  if (typeof params.amount !== "bigint") {
15233
16029
  throw new ValidationError(
@@ -15259,7 +16055,7 @@ var SealedBidAuction = class {
15259
16055
  );
15260
16056
  }
15261
16057
  }
15262
- const salt = params.salt ?? (0, import_utils27.randomBytes)(32);
16058
+ const salt = params.salt ?? (0, import_utils28.randomBytes)(32);
15263
16059
  const { commitment, blinding } = commit(params.amount, salt);
15264
16060
  const sealedBid = {
15265
16061
  auctionId: params.auctionId,
@@ -15403,7 +16199,7 @@ var SealedBidAuction = class {
15403
16199
  * ```
15404
16200
  */
15405
16201
  revealBid(bid, amount, salt) {
15406
- const saltHex = `0x${(0, import_utils27.bytesToHex)(salt)}`;
16202
+ const saltHex = `0x${(0, import_utils28.bytesToHex)(salt)}`;
15407
16203
  const isValid = this.verifyBid({
15408
16204
  commitment: bid.commitment,
15409
16205
  amount,
@@ -15888,9 +16684,9 @@ function createSealedBidAuction() {
15888
16684
  }
15889
16685
 
15890
16686
  // src/governance/private-vote.ts
15891
- var import_sha25620 = require("@noble/hashes/sha256");
16687
+ var import_sha25621 = require("@noble/hashes/sha256");
15892
16688
  var import_hkdf3 = require("@noble/hashes/hkdf");
15893
- var import_utils28 = require("@noble/hashes/utils");
16689
+ var import_utils29 = require("@noble/hashes/utils");
15894
16690
  var import_chacha4 = require("@noble/ciphers/chacha.js");
15895
16691
  init_errors();
15896
16692
  init_secure_memory();
@@ -15930,7 +16726,7 @@ var PrivateVoting = class {
15930
16726
  const { proposalId, choice, weight, encryptionKey, voter = "anonymous" } = params;
15931
16727
  const derivedKey = this.deriveEncryptionKey(encryptionKey, proposalId);
15932
16728
  try {
15933
- const nonce = (0, import_utils28.randomBytes)(NONCE_SIZE2);
16729
+ const nonce = (0, import_utils29.randomBytes)(NONCE_SIZE2);
15934
16730
  const voteData = {
15935
16731
  proposalId,
15936
16732
  choice,
@@ -15938,14 +16734,14 @@ var PrivateVoting = class {
15938
16734
  voter,
15939
16735
  timestamp: Date.now()
15940
16736
  };
15941
- const plaintext = (0, import_utils28.utf8ToBytes)(JSON.stringify(voteData));
16737
+ const plaintext = (0, import_utils29.utf8ToBytes)(JSON.stringify(voteData));
15942
16738
  const cipher = (0, import_chacha4.xchacha20poly1305)(derivedKey, nonce);
15943
16739
  const ciphertext = cipher.encrypt(plaintext);
15944
- const keyHash = (0, import_sha25620.sha256)((0, import_utils28.hexToBytes)(encryptionKey.slice(2)));
16740
+ const keyHash = (0, import_sha25621.sha256)((0, import_utils29.hexToBytes)(encryptionKey.slice(2)));
15945
16741
  return {
15946
- ciphertext: `0x${(0, import_utils28.bytesToHex)(ciphertext)}`,
15947
- nonce: `0x${(0, import_utils28.bytesToHex)(nonce)}`,
15948
- encryptionKeyHash: `0x${(0, import_utils28.bytesToHex)(keyHash)}`,
16742
+ ciphertext: `0x${(0, import_utils29.bytesToHex)(ciphertext)}`,
16743
+ nonce: `0x${(0, import_utils29.bytesToHex)(nonce)}`,
16744
+ encryptionKeyHash: `0x${(0, import_utils29.bytesToHex)(keyHash)}`,
15949
16745
  proposalId,
15950
16746
  voter,
15951
16747
  timestamp: voteData.timestamp
@@ -15991,8 +16787,8 @@ var PrivateVoting = class {
15991
16787
  }
15992
16788
  const derivedKey = this.deriveEncryptionKey(decryptionKey, vote.proposalId);
15993
16789
  try {
15994
- const keyHash = (0, import_sha25620.sha256)((0, import_utils28.hexToBytes)(decryptionKey.slice(2)));
15995
- const expectedKeyHash = `0x${(0, import_utils28.bytesToHex)(keyHash)}`;
16790
+ const keyHash = (0, import_sha25621.sha256)((0, import_utils29.hexToBytes)(decryptionKey.slice(2)));
16791
+ const expectedKeyHash = `0x${(0, import_utils29.bytesToHex)(keyHash)}`;
15996
16792
  if (vote.encryptionKeyHash !== expectedKeyHash) {
15997
16793
  throw new CryptoError(
15998
16794
  "Decryption key hash mismatch - this key cannot decrypt this vote",
@@ -16001,9 +16797,9 @@ var PrivateVoting = class {
16001
16797
  );
16002
16798
  }
16003
16799
  const nonceHex = vote.nonce.startsWith("0x") ? vote.nonce.slice(2) : vote.nonce;
16004
- const nonce = (0, import_utils28.hexToBytes)(nonceHex);
16800
+ const nonce = (0, import_utils29.hexToBytes)(nonceHex);
16005
16801
  const ciphertextHex = vote.ciphertext.startsWith("0x") ? vote.ciphertext.slice(2) : vote.ciphertext;
16006
- const ciphertext = (0, import_utils28.hexToBytes)(ciphertextHex);
16802
+ const ciphertext = (0, import_utils29.hexToBytes)(ciphertextHex);
16007
16803
  const cipher = (0, import_chacha4.xchacha20poly1305)(derivedKey, nonce);
16008
16804
  let plaintext;
16009
16805
  try {
@@ -16092,11 +16888,11 @@ var PrivateVoting = class {
16092
16888
  */
16093
16889
  deriveEncryptionKey(key, proposalId) {
16094
16890
  const keyHex = key.startsWith("0x") ? key.slice(2) : key;
16095
- const keyBytes = (0, import_utils28.hexToBytes)(keyHex);
16891
+ const keyBytes = (0, import_utils29.hexToBytes)(keyHex);
16096
16892
  try {
16097
- const salt = (0, import_utils28.utf8ToBytes)(VOTE_ENCRYPTION_DOMAIN);
16098
- const info = (0, import_utils28.utf8ToBytes)(proposalId);
16099
- return (0, import_hkdf3.hkdf)(import_sha25620.sha256, keyBytes, salt, info, 32);
16893
+ const salt = (0, import_utils29.utf8ToBytes)(VOTE_ENCRYPTION_DOMAIN);
16894
+ const info = (0, import_utils29.utf8ToBytes)(proposalId);
16895
+ return (0, import_hkdf3.hkdf)(import_sha25621.sha256, keyBytes, salt, info, 32);
16100
16896
  } finally {
16101
16897
  secureWipe(keyBytes);
16102
16898
  }
@@ -16241,21 +17037,21 @@ var PrivateVoting = class {
16241
17037
  const blindings = {};
16242
17038
  for (const [choice, weights] of Object.entries(votesByChoice)) {
16243
17039
  const totalWeight = weights.reduce((sum, w) => sum + w, 0n);
16244
- const { commitment, blinding } = commit(totalWeight, (0, import_utils28.hexToBytes)(generateBlinding().slice(2)));
17040
+ const { commitment, blinding } = commit(totalWeight, (0, import_utils29.hexToBytes)(generateBlinding().slice(2)));
16245
17041
  tallies[choice] = commitment;
16246
17042
  blindings[choice] = blinding;
16247
17043
  }
16248
17044
  const encryptedBlindings = {};
16249
17045
  for (const [choice, blinding] of Object.entries(blindings)) {
16250
- const nonce = (0, import_utils28.randomBytes)(NONCE_SIZE2);
17046
+ const nonce = (0, import_utils29.randomBytes)(NONCE_SIZE2);
16251
17047
  const derivedKey = this.deriveEncryptionKey(decryptionKey, `${proposalId}-tally-${choice}`);
16252
17048
  try {
16253
17049
  const cipher = (0, import_chacha4.xchacha20poly1305)(derivedKey, nonce);
16254
- const blindingBytes = (0, import_utils28.hexToBytes)(blinding.slice(2));
17050
+ const blindingBytes = (0, import_utils29.hexToBytes)(blinding.slice(2));
16255
17051
  const ciphertext = cipher.encrypt(blindingBytes);
16256
17052
  encryptedBlindings[choice] = {
16257
- ciphertext: `0x${(0, import_utils28.bytesToHex)(ciphertext)}`,
16258
- nonce: `0x${(0, import_utils28.bytesToHex)(nonce)}`
17053
+ ciphertext: `0x${(0, import_utils29.bytesToHex)(ciphertext)}`,
17054
+ nonce: `0x${(0, import_utils29.bytesToHex)(nonce)}`
16259
17055
  };
16260
17056
  } finally {
16261
17057
  secureWipe(derivedKey);
@@ -16348,9 +17144,9 @@ var PrivateVoting = class {
16348
17144
  }
16349
17145
  let reconstructedKey = null;
16350
17146
  try {
16351
- reconstructedKey = (0, import_utils28.hexToBytes)(decryptionShares[0].share.slice(2));
17147
+ reconstructedKey = (0, import_utils29.hexToBytes)(decryptionShares[0].share.slice(2));
16352
17148
  for (let i = 1; i < decryptionShares.length; i++) {
16353
- const shareBytes = (0, import_utils28.hexToBytes)(decryptionShares[i].share.slice(2));
17149
+ const shareBytes = (0, import_utils29.hexToBytes)(decryptionShares[i].share.slice(2));
16354
17150
  if (shareBytes.length !== reconstructedKey.length) {
16355
17151
  throw new ValidationError(
16356
17152
  "all decryption shares must have the same length",
@@ -16363,7 +17159,7 @@ var PrivateVoting = class {
16363
17159
  reconstructedKey[j] ^= shareBytes[j];
16364
17160
  }
16365
17161
  }
16366
- const reconstructedKeyHex = `0x${(0, import_utils28.bytesToHex)(reconstructedKey)}`;
17162
+ const reconstructedKeyHex = `0x${(0, import_utils29.bytesToHex)(reconstructedKey)}`;
16367
17163
  const results = {};
16368
17164
  for (const [choice, commitmentPoint] of Object.entries(tally.tallies)) {
16369
17165
  const encBlinding = tally.encryptedBlindings[choice];
@@ -16380,11 +17176,11 @@ var PrivateVoting = class {
16380
17176
  );
16381
17177
  let blindingFactor;
16382
17178
  try {
16383
- const nonceBytes = (0, import_utils28.hexToBytes)(encBlinding.nonce.slice(2));
16384
- const ciphertextBytes = (0, import_utils28.hexToBytes)(encBlinding.ciphertext.slice(2));
17179
+ const nonceBytes = (0, import_utils29.hexToBytes)(encBlinding.nonce.slice(2));
17180
+ const ciphertextBytes = (0, import_utils29.hexToBytes)(encBlinding.ciphertext.slice(2));
16385
17181
  const cipher = (0, import_chacha4.xchacha20poly1305)(derivedKey, nonceBytes);
16386
17182
  const blindingBytes = cipher.decrypt(ciphertextBytes);
16387
- blindingFactor = `0x${(0, import_utils28.bytesToHex)(blindingBytes)}`;
17183
+ blindingFactor = `0x${(0, import_utils29.bytesToHex)(blindingBytes)}`;
16388
17184
  } catch (e) {
16389
17185
  throw new CryptoError(
16390
17186
  "failed to decrypt blinding factor",
@@ -16404,7 +17200,7 @@ var PrivateVoting = class {
16404
17200
  try {
16405
17201
  const { commitment: testCommit } = commit(
16406
17202
  value,
16407
- (0, import_utils28.hexToBytes)(blindingFactor.slice(2))
17203
+ (0, import_utils29.hexToBytes)(blindingFactor.slice(2))
16408
17204
  );
16409
17205
  if (testCommit === commitmentPoint) {
16410
17206
  results[choice] = value;
@@ -16604,9 +17400,9 @@ function createPrivateVoting() {
16604
17400
  }
16605
17401
 
16606
17402
  // src/nft/private-nft.ts
16607
- var import_sha25621 = require("@noble/hashes/sha256");
17403
+ var import_sha25622 = require("@noble/hashes/sha256");
16608
17404
  var import_secp256k18 = require("@noble/curves/secp256k1");
16609
- var import_utils29 = require("@noble/hashes/utils");
17405
+ var import_utils30 = require("@noble/hashes/utils");
16610
17406
  init_stealth();
16611
17407
  init_errors();
16612
17408
  init_validation();
@@ -16695,23 +17491,23 @@ var PrivateNFT = class {
16695
17491
  const { ownership, challenge, stealthPrivateKey } = params;
16696
17492
  try {
16697
17493
  const message = this.createProofMessage(ownership, challenge);
16698
- const messageHash = (0, import_sha25621.sha256)(new TextEncoder().encode(message));
16699
- const privateKeyBytes = (0, import_utils29.hexToBytes)(stealthPrivateKey.slice(2));
17494
+ const messageHash = (0, import_sha25622.sha256)(new TextEncoder().encode(message));
17495
+ const privateKeyBytes = (0, import_utils30.hexToBytes)(stealthPrivateKey.slice(2));
16700
17496
  const signature = import_secp256k18.secp256k1.sign(messageHash, privateKeyBytes);
16701
17497
  const zkProof = {
16702
17498
  type: "ownership",
16703
- proof: `0x${(0, import_utils29.bytesToHex)(signature.toCompactRawBytes())}`,
17499
+ proof: `0x${(0, import_utils30.bytesToHex)(signature.toCompactRawBytes())}`,
16704
17500
  publicInputs: [
16705
- `0x${(0, import_utils29.bytesToHex)(messageHash)}`
17501
+ `0x${(0, import_utils30.bytesToHex)(messageHash)}`
16706
17502
  ]
16707
17503
  };
16708
- const stealthHashBytes = (0, import_sha25621.sha256)((0, import_utils29.hexToBytes)(ownership.ownerStealth.address.slice(2)));
17504
+ const stealthHashBytes = (0, import_sha25622.sha256)((0, import_utils30.hexToBytes)(ownership.ownerStealth.address.slice(2)));
16709
17505
  return {
16710
17506
  nftContract: ownership.nftContract,
16711
17507
  tokenId: ownership.tokenId,
16712
17508
  challenge,
16713
17509
  proof: zkProof,
16714
- stealthHash: `0x${(0, import_utils29.bytesToHex)(stealthHashBytes)}`,
17510
+ stealthHash: `0x${(0, import_utils30.bytesToHex)(stealthHashBytes)}`,
16715
17511
  timestamp: Date.now()
16716
17512
  };
16717
17513
  } catch (e) {
@@ -16753,9 +17549,9 @@ var PrivateNFT = class {
16753
17549
  verifyOwnership(proof) {
16754
17550
  try {
16755
17551
  this.validateOwnershipProof(proof);
16756
- const signatureBytes = (0, import_utils29.hexToBytes)(proof.proof.proof.slice(2));
17552
+ const signatureBytes = (0, import_utils30.hexToBytes)(proof.proof.proof.slice(2));
16757
17553
  const signature = import_secp256k18.secp256k1.Signature.fromCompact(signatureBytes);
16758
- const messageHash = (0, import_utils29.hexToBytes)(proof.proof.publicInputs[0].slice(2));
17554
+ const messageHash = (0, import_utils30.hexToBytes)(proof.proof.publicInputs[0].slice(2));
16759
17555
  if (signatureBytes.length !== 64) {
16760
17556
  return {
16761
17557
  valid: false,
@@ -16852,12 +17648,12 @@ var PrivateNFT = class {
16852
17648
  chain: nft.chain,
16853
17649
  timestamp: Date.now()
16854
17650
  };
16855
- const previousOwnerHashBytes = (0, import_sha25621.sha256)((0, import_utils29.hexToBytes)(nft.ownerStealth.address.slice(2)));
17651
+ const previousOwnerHashBytes = (0, import_sha25622.sha256)((0, import_utils30.hexToBytes)(nft.ownerStealth.address.slice(2)));
16856
17652
  const transfer = {
16857
17653
  nftContract: nft.nftContract,
16858
17654
  tokenId: nft.tokenId,
16859
17655
  newOwnerStealth,
16860
- previousOwnerHash: `0x${(0, import_utils29.bytesToHex)(previousOwnerHashBytes)}`,
17656
+ previousOwnerHash: `0x${(0, import_utils30.bytesToHex)(previousOwnerHashBytes)}`,
16861
17657
  chain: nft.chain,
16862
17658
  timestamp: Date.now()
16863
17659
  };
@@ -16924,8 +17720,8 @@ var PrivateNFT = class {
16924
17720
  );
16925
17721
  }
16926
17722
  const ownedNFTs = [];
16927
- const scanKeyHex = `0x${(0, import_utils29.bytesToHex)(scanKey)}`;
16928
- const viewingKeyHex = `0x${(0, import_utils29.bytesToHex)(viewingKey)}`;
17723
+ const scanKeyHex = `0x${(0, import_utils30.bytesToHex)(scanKey)}`;
17724
+ const viewingKeyHex = `0x${(0, import_utils30.bytesToHex)(viewingKey)}`;
16929
17725
  for (const transfer of transfers) {
16930
17726
  try {
16931
17727
  if (!transfer || typeof transfer !== "object") {
@@ -17143,10 +17939,10 @@ function verifyOwnership(proof) {
17143
17939
 
17144
17940
  // src/wallet/errors.ts
17145
17941
  init_errors();
17146
- var import_types21 = require("@sip-protocol/types");
17942
+ var import_types22 = require("@sip-protocol/types");
17147
17943
  var WalletError = class extends SIPError {
17148
17944
  walletCode;
17149
- constructor(message, walletCode = import_types21.WalletErrorCode.UNKNOWN, options) {
17945
+ constructor(message, walletCode = import_types22.WalletErrorCode.UNKNOWN, options) {
17150
17946
  super(message, "SIP_7000" /* WALLET_ERROR */, options);
17151
17947
  this.walletCode = walletCode;
17152
17948
  this.name = "WalletError";
@@ -17156,10 +17952,10 @@ var WalletError = class extends SIPError {
17156
17952
  */
17157
17953
  isConnectionError() {
17158
17954
  const codes = [
17159
- import_types21.WalletErrorCode.NOT_INSTALLED,
17160
- import_types21.WalletErrorCode.CONNECTION_REJECTED,
17161
- import_types21.WalletErrorCode.CONNECTION_FAILED,
17162
- import_types21.WalletErrorCode.NOT_CONNECTED
17955
+ import_types22.WalletErrorCode.NOT_INSTALLED,
17956
+ import_types22.WalletErrorCode.CONNECTION_REJECTED,
17957
+ import_types22.WalletErrorCode.CONNECTION_FAILED,
17958
+ import_types22.WalletErrorCode.NOT_CONNECTED
17163
17959
  ];
17164
17960
  return codes.includes(this.walletCode);
17165
17961
  }
@@ -17168,9 +17964,9 @@ var WalletError = class extends SIPError {
17168
17964
  */
17169
17965
  isSigningError() {
17170
17966
  const codes = [
17171
- import_types21.WalletErrorCode.SIGNING_REJECTED,
17172
- import_types21.WalletErrorCode.SIGNING_FAILED,
17173
- import_types21.WalletErrorCode.INVALID_MESSAGE
17967
+ import_types22.WalletErrorCode.SIGNING_REJECTED,
17968
+ import_types22.WalletErrorCode.SIGNING_FAILED,
17969
+ import_types22.WalletErrorCode.INVALID_MESSAGE
17174
17970
  ];
17175
17971
  return codes.includes(this.walletCode);
17176
17972
  }
@@ -17179,10 +17975,10 @@ var WalletError = class extends SIPError {
17179
17975
  */
17180
17976
  isTransactionError() {
17181
17977
  const codes = [
17182
- import_types21.WalletErrorCode.INSUFFICIENT_FUNDS,
17183
- import_types21.WalletErrorCode.TRANSACTION_REJECTED,
17184
- import_types21.WalletErrorCode.TRANSACTION_FAILED,
17185
- import_types21.WalletErrorCode.INVALID_TRANSACTION
17978
+ import_types22.WalletErrorCode.INSUFFICIENT_FUNDS,
17979
+ import_types22.WalletErrorCode.TRANSACTION_REJECTED,
17980
+ import_types22.WalletErrorCode.TRANSACTION_FAILED,
17981
+ import_types22.WalletErrorCode.INVALID_TRANSACTION
17186
17982
  ];
17187
17983
  return codes.includes(this.walletCode);
17188
17984
  }
@@ -17191,9 +17987,9 @@ var WalletError = class extends SIPError {
17191
17987
  */
17192
17988
  isPrivacyError() {
17193
17989
  const codes = [
17194
- import_types21.WalletErrorCode.STEALTH_NOT_SUPPORTED,
17195
- import_types21.WalletErrorCode.VIEWING_KEY_NOT_SUPPORTED,
17196
- import_types21.WalletErrorCode.SHIELDED_NOT_SUPPORTED
17990
+ import_types22.WalletErrorCode.STEALTH_NOT_SUPPORTED,
17991
+ import_types22.WalletErrorCode.VIEWING_KEY_NOT_SUPPORTED,
17992
+ import_types22.WalletErrorCode.SHIELDED_NOT_SUPPORTED
17197
17993
  ];
17198
17994
  return codes.includes(this.walletCode);
17199
17995
  }
@@ -17202,10 +17998,10 @@ var WalletError = class extends SIPError {
17202
17998
  */
17203
17999
  isUserRejection() {
17204
18000
  const codes = [
17205
- import_types21.WalletErrorCode.CONNECTION_REJECTED,
17206
- import_types21.WalletErrorCode.SIGNING_REJECTED,
17207
- import_types21.WalletErrorCode.TRANSACTION_REJECTED,
17208
- import_types21.WalletErrorCode.CHAIN_SWITCH_REJECTED
18001
+ import_types22.WalletErrorCode.CONNECTION_REJECTED,
18002
+ import_types22.WalletErrorCode.SIGNING_REJECTED,
18003
+ import_types22.WalletErrorCode.TRANSACTION_REJECTED,
18004
+ import_types22.WalletErrorCode.CHAIN_SWITCH_REJECTED
17209
18005
  ];
17210
18006
  return codes.includes(this.walletCode);
17211
18007
  }
@@ -17213,15 +18009,15 @@ var WalletError = class extends SIPError {
17213
18009
  function notConnectedError() {
17214
18010
  return new WalletError(
17215
18011
  "Wallet not connected. Call connect() first.",
17216
- import_types21.WalletErrorCode.NOT_CONNECTED
18012
+ import_types22.WalletErrorCode.NOT_CONNECTED
17217
18013
  );
17218
18014
  }
17219
- function featureNotSupportedError(feature, code = import_types21.WalletErrorCode.UNKNOWN) {
18015
+ function featureNotSupportedError(feature, code = import_types22.WalletErrorCode.UNKNOWN) {
17220
18016
  return new WalletError(`${feature} is not supported by this wallet`, code);
17221
18017
  }
17222
18018
 
17223
18019
  // src/wallet/base-adapter.ts
17224
- var import_types22 = require("@sip-protocol/types");
18020
+ var import_types23 = require("@sip-protocol/types");
17225
18021
  var BaseWalletAdapter = class {
17226
18022
  _address = "";
17227
18023
  _publicKey = "";
@@ -17384,12 +18180,12 @@ var MockWalletAdapter = class extends BaseWalletAdapter {
17384
18180
  this._connectionState = "connecting";
17385
18181
  if (this.shouldFailConnect) {
17386
18182
  this.setError(
17387
- import_types22.WalletErrorCode.CONNECTION_FAILED,
18183
+ import_types23.WalletErrorCode.CONNECTION_FAILED,
17388
18184
  "Mock connection failure"
17389
18185
  );
17390
18186
  throw new WalletError(
17391
18187
  "Mock connection failure",
17392
- import_types22.WalletErrorCode.CONNECTION_FAILED
18188
+ import_types23.WalletErrorCode.CONNECTION_FAILED
17393
18189
  );
17394
18190
  }
17395
18191
  await new Promise((resolve) => setTimeout(resolve, 10));
@@ -17401,7 +18197,7 @@ var MockWalletAdapter = class extends BaseWalletAdapter {
17401
18197
  async signMessage(message) {
17402
18198
  this.requireConnected();
17403
18199
  if (this.shouldFailSign) {
17404
- throw new WalletError("Mock signing failure", import_types22.WalletErrorCode.SIGNING_FAILED);
18200
+ throw new WalletError("Mock signing failure", import_types23.WalletErrorCode.SIGNING_FAILED);
17405
18201
  }
17406
18202
  const mockSig = new Uint8Array(64);
17407
18203
  for (let i = 0; i < 64; i++) {
@@ -17416,7 +18212,7 @@ var MockWalletAdapter = class extends BaseWalletAdapter {
17416
18212
  async signTransaction(tx) {
17417
18213
  this.requireConnected();
17418
18214
  if (this.shouldFailSign) {
17419
- throw new WalletError("Mock signing failure", import_types22.WalletErrorCode.SIGNING_FAILED);
18215
+ throw new WalletError("Mock signing failure", import_types23.WalletErrorCode.SIGNING_FAILED);
17420
18216
  }
17421
18217
  const signature = await this.signMessage(
17422
18218
  new TextEncoder().encode(JSON.stringify(tx.data))
@@ -17598,7 +18394,7 @@ function isPrivateWalletAdapter(adapter) {
17598
18394
  }
17599
18395
 
17600
18396
  // src/wallet/solana/adapter.ts
17601
- var import_types23 = require("@sip-protocol/types");
18397
+ var import_types24 = require("@sip-protocol/types");
17602
18398
 
17603
18399
  // src/wallet/solana/types.ts
17604
18400
  function getSolanaProvider(wallet = "phantom") {
@@ -17719,19 +18515,19 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
17719
18515
  }
17720
18516
  if (!this.provider) {
17721
18517
  this.setError(
17722
- import_types23.WalletErrorCode.NOT_INSTALLED,
18518
+ import_types24.WalletErrorCode.NOT_INSTALLED,
17723
18519
  `${this.walletName} wallet is not installed`
17724
18520
  );
17725
18521
  throw new WalletError(
17726
18522
  `${this.walletName} wallet is not installed`,
17727
- import_types23.WalletErrorCode.NOT_INSTALLED
18523
+ import_types24.WalletErrorCode.NOT_INSTALLED
17728
18524
  );
17729
18525
  }
17730
18526
  const { publicKey } = await this.provider.connect();
17731
18527
  if (!publicKey) {
17732
18528
  throw new WalletError(
17733
18529
  "No public key returned from wallet",
17734
- import_types23.WalletErrorCode.CONNECTION_FAILED
18530
+ import_types24.WalletErrorCode.CONNECTION_FAILED
17735
18531
  );
17736
18532
  }
17737
18533
  this.setupEventHandlers();
@@ -17741,11 +18537,11 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
17741
18537
  } catch (error) {
17742
18538
  const message = error instanceof Error ? error.message : "Connection failed";
17743
18539
  if (message.includes("User rejected") || message.includes("rejected")) {
17744
- this.setError(import_types23.WalletErrorCode.CONNECTION_REJECTED, message);
17745
- throw new WalletError(message, import_types23.WalletErrorCode.CONNECTION_REJECTED);
18540
+ this.setError(import_types24.WalletErrorCode.CONNECTION_REJECTED, message);
18541
+ throw new WalletError(message, import_types24.WalletErrorCode.CONNECTION_REJECTED);
17746
18542
  }
17747
- this.setError(import_types23.WalletErrorCode.CONNECTION_FAILED, message);
17748
- throw error instanceof WalletError ? error : new WalletError(message, import_types23.WalletErrorCode.CONNECTION_FAILED, { cause: error });
18543
+ this.setError(import_types24.WalletErrorCode.CONNECTION_FAILED, message);
18544
+ throw error instanceof WalletError ? error : new WalletError(message, import_types24.WalletErrorCode.CONNECTION_FAILED, { cause: error });
17749
18545
  }
17750
18546
  }
17751
18547
  /**
@@ -17768,7 +18564,7 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
17768
18564
  async signMessage(message) {
17769
18565
  this.requireConnected();
17770
18566
  if (!this.provider) {
17771
- throw new WalletError("Provider not available", import_types23.WalletErrorCode.NOT_CONNECTED);
18567
+ throw new WalletError("Provider not available", import_types24.WalletErrorCode.NOT_CONNECTED);
17772
18568
  }
17773
18569
  try {
17774
18570
  const { signature } = await this.provider.signMessage(message);
@@ -17779,9 +18575,9 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
17779
18575
  } catch (error) {
17780
18576
  const message2 = error instanceof Error ? error.message : "Signing failed";
17781
18577
  if (message2.includes("User rejected") || message2.includes("rejected")) {
17782
- throw new WalletError(message2, import_types23.WalletErrorCode.SIGNING_REJECTED);
18578
+ throw new WalletError(message2, import_types24.WalletErrorCode.SIGNING_REJECTED);
17783
18579
  }
17784
- throw new WalletError(message2, import_types23.WalletErrorCode.SIGNING_FAILED, {
18580
+ throw new WalletError(message2, import_types24.WalletErrorCode.SIGNING_FAILED, {
17785
18581
  cause: error
17786
18582
  });
17787
18583
  }
@@ -17794,7 +18590,7 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
17794
18590
  async signTransaction(tx) {
17795
18591
  this.requireConnected();
17796
18592
  if (!this.provider) {
17797
- throw new WalletError("Provider not available", import_types23.WalletErrorCode.NOT_CONNECTED);
18593
+ throw new WalletError("Provider not available", import_types24.WalletErrorCode.NOT_CONNECTED);
17798
18594
  }
17799
18595
  try {
17800
18596
  const solTx = tx.data;
@@ -17813,9 +18609,9 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
17813
18609
  } catch (error) {
17814
18610
  const message = error instanceof Error ? error.message : "Signing failed";
17815
18611
  if (message.includes("User rejected") || message.includes("rejected")) {
17816
- throw new WalletError(message, import_types23.WalletErrorCode.SIGNING_REJECTED);
18612
+ throw new WalletError(message, import_types24.WalletErrorCode.SIGNING_REJECTED);
17817
18613
  }
17818
- throw new WalletError(message, import_types23.WalletErrorCode.SIGNING_FAILED, {
18614
+ throw new WalletError(message, import_types24.WalletErrorCode.SIGNING_FAILED, {
17819
18615
  cause: error
17820
18616
  });
17821
18617
  }
@@ -17826,7 +18622,7 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
17826
18622
  async signAndSendTransaction(tx) {
17827
18623
  this.requireConnected();
17828
18624
  if (!this.provider) {
17829
- throw new WalletError("Provider not available", import_types23.WalletErrorCode.NOT_CONNECTED);
18625
+ throw new WalletError("Provider not available", import_types24.WalletErrorCode.NOT_CONNECTED);
17830
18626
  }
17831
18627
  try {
17832
18628
  const solTx = tx.data;
@@ -17841,12 +18637,12 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
17841
18637
  } catch (error) {
17842
18638
  const message = error instanceof Error ? error.message : "Transaction failed";
17843
18639
  if (message.includes("User rejected") || message.includes("rejected")) {
17844
- throw new WalletError(message, import_types23.WalletErrorCode.TRANSACTION_REJECTED);
18640
+ throw new WalletError(message, import_types24.WalletErrorCode.TRANSACTION_REJECTED);
17845
18641
  }
17846
18642
  if (message.includes("insufficient") || message.includes("Insufficient")) {
17847
- throw new WalletError(message, import_types23.WalletErrorCode.INSUFFICIENT_FUNDS);
18643
+ throw new WalletError(message, import_types24.WalletErrorCode.INSUFFICIENT_FUNDS);
17848
18644
  }
17849
- throw new WalletError(message, import_types23.WalletErrorCode.TRANSACTION_FAILED, {
18645
+ throw new WalletError(message, import_types24.WalletErrorCode.TRANSACTION_FAILED, {
17850
18646
  cause: error
17851
18647
  });
17852
18648
  }
@@ -17859,16 +18655,16 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
17859
18655
  async signAllTransactions(transactions) {
17860
18656
  this.requireConnected();
17861
18657
  if (!this.provider) {
17862
- throw new WalletError("Provider not available", import_types23.WalletErrorCode.NOT_CONNECTED);
18658
+ throw new WalletError("Provider not available", import_types24.WalletErrorCode.NOT_CONNECTED);
17863
18659
  }
17864
18660
  try {
17865
18661
  return await this.provider.signAllTransactions(transactions);
17866
18662
  } catch (error) {
17867
18663
  const message = error instanceof Error ? error.message : "Signing failed";
17868
18664
  if (message.includes("User rejected") || message.includes("rejected")) {
17869
- throw new WalletError(message, import_types23.WalletErrorCode.SIGNING_REJECTED);
18665
+ throw new WalletError(message, import_types24.WalletErrorCode.SIGNING_REJECTED);
17870
18666
  }
17871
- throw new WalletError(message, import_types23.WalletErrorCode.SIGNING_FAILED, {
18667
+ throw new WalletError(message, import_types24.WalletErrorCode.SIGNING_FAILED, {
17872
18668
  cause: error
17873
18669
  });
17874
18670
  }
@@ -17889,7 +18685,7 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
17889
18685
  } catch (error) {
17890
18686
  throw new WalletError(
17891
18687
  "Failed to get balance",
17892
- import_types23.WalletErrorCode.UNKNOWN,
18688
+ import_types24.WalletErrorCode.UNKNOWN,
17893
18689
  { cause: error }
17894
18690
  );
17895
18691
  }
@@ -17902,7 +18698,7 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
17902
18698
  if (asset.chain !== "solana") {
17903
18699
  throw new WalletError(
17904
18700
  `Asset chain ${asset.chain} not supported by Solana adapter`,
17905
- import_types23.WalletErrorCode.UNSUPPORTED_CHAIN
18701
+ import_types24.WalletErrorCode.UNSUPPORTED_CHAIN
17906
18702
  );
17907
18703
  }
17908
18704
  if (!asset.address) {
@@ -18020,7 +18816,7 @@ function createSolanaAdapter(config = {}) {
18020
18816
  }
18021
18817
 
18022
18818
  // src/wallet/solana/mock.ts
18023
- var import_types25 = require("@sip-protocol/types");
18819
+ var import_types26 = require("@sip-protocol/types");
18024
18820
  var MockPublicKey = class {
18025
18821
  base58;
18026
18822
  bytes;
@@ -18086,8 +18882,8 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
18086
18882
  this._connectionState = "connecting";
18087
18883
  await this.simulateLatency();
18088
18884
  if (this.shouldFailConnect) {
18089
- this.setError(import_types25.WalletErrorCode.CONNECTION_FAILED, "Mock connection failure");
18090
- throw new WalletError("Mock connection failure", import_types25.WalletErrorCode.CONNECTION_FAILED);
18885
+ this.setError(import_types26.WalletErrorCode.CONNECTION_FAILED, "Mock connection failure");
18886
+ throw new WalletError("Mock connection failure", import_types26.WalletErrorCode.CONNECTION_FAILED);
18091
18887
  }
18092
18888
  const hexPubKey = "0x" + Buffer.from(this.mockPublicKey.toBytes()).toString("hex");
18093
18889
  this.setConnected(this.mockAddress, hexPubKey);
@@ -18106,7 +18902,7 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
18106
18902
  this.requireConnected();
18107
18903
  await this.simulateLatency();
18108
18904
  if (this.shouldFailSign) {
18109
- throw new WalletError("Mock signing failure", import_types25.WalletErrorCode.SIGNING_REJECTED);
18905
+ throw new WalletError("Mock signing failure", import_types26.WalletErrorCode.SIGNING_REJECTED);
18110
18906
  }
18111
18907
  const mockSig = new Uint8Array(64);
18112
18908
  for (let i = 0; i < 64; i++) {
@@ -18124,7 +18920,7 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
18124
18920
  this.requireConnected();
18125
18921
  await this.simulateLatency();
18126
18922
  if (this.shouldFailSign) {
18127
- throw new WalletError("Mock signing failure", import_types25.WalletErrorCode.SIGNING_REJECTED);
18923
+ throw new WalletError("Mock signing failure", import_types26.WalletErrorCode.SIGNING_REJECTED);
18128
18924
  }
18129
18925
  const solTx = tx.data;
18130
18926
  this.signedTransactions.push(solTx);
@@ -18144,10 +18940,10 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
18144
18940
  this.requireConnected();
18145
18941
  await this.simulateLatency();
18146
18942
  if (this.shouldFailSign) {
18147
- throw new WalletError("Mock signing failure", import_types25.WalletErrorCode.SIGNING_REJECTED);
18943
+ throw new WalletError("Mock signing failure", import_types26.WalletErrorCode.SIGNING_REJECTED);
18148
18944
  }
18149
18945
  if (this.shouldFailTransaction) {
18150
- throw new WalletError("Mock transaction failure", import_types25.WalletErrorCode.TRANSACTION_FAILED);
18946
+ throw new WalletError("Mock transaction failure", import_types26.WalletErrorCode.TRANSACTION_FAILED);
18151
18947
  }
18152
18948
  const txSig = `mock_tx_${Date.now()}_${Math.random().toString(36).slice(2)}`;
18153
18949
  this.sentTransactions.push(txSig);
@@ -18167,7 +18963,7 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
18167
18963
  this.requireConnected();
18168
18964
  await this.simulateLatency();
18169
18965
  if (this.shouldFailSign) {
18170
- throw new WalletError("Mock signing failure", import_types25.WalletErrorCode.SIGNING_REJECTED);
18966
+ throw new WalletError("Mock signing failure", import_types26.WalletErrorCode.SIGNING_REJECTED);
18171
18967
  }
18172
18968
  this.signedTransactions.push(...transactions);
18173
18969
  return transactions.map((tx) => {
@@ -18194,7 +18990,7 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
18194
18990
  if (asset.chain !== "solana") {
18195
18991
  throw new WalletError(
18196
18992
  `Asset chain ${asset.chain} not supported by Solana adapter`,
18197
- import_types25.WalletErrorCode.UNSUPPORTED_CHAIN
18993
+ import_types26.WalletErrorCode.UNSUPPORTED_CHAIN
18198
18994
  );
18199
18995
  }
18200
18996
  if (!asset.address) {
@@ -18363,7 +19159,7 @@ function createMockSolanaAdapter(config = {}) {
18363
19159
  }
18364
19160
 
18365
19161
  // src/wallet/ethereum/adapter.ts
18366
- var import_types27 = require("@sip-protocol/types");
19162
+ var import_types28 = require("@sip-protocol/types");
18367
19163
 
18368
19164
  // src/wallet/ethereum/types.ts
18369
19165
  var EthereumChainId = {
@@ -18505,7 +19301,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18505
19301
  this._connectionState = "error";
18506
19302
  throw new WalletError(
18507
19303
  `${this.walletType} wallet not found. Please install the extension.`,
18508
- import_types27.WalletErrorCode.NOT_INSTALLED
19304
+ import_types28.WalletErrorCode.NOT_INSTALLED
18509
19305
  );
18510
19306
  }
18511
19307
  const accounts = await this.provider.request({
@@ -18515,7 +19311,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18515
19311
  this._connectionState = "error";
18516
19312
  throw new WalletError(
18517
19313
  "No accounts returned from wallet",
18518
- import_types27.WalletErrorCode.CONNECTION_REJECTED
19314
+ import_types28.WalletErrorCode.CONNECTION_REJECTED
18519
19315
  );
18520
19316
  }
18521
19317
  const address = normalizeAddress(accounts[0]);
@@ -18535,12 +19331,12 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18535
19331
  if (rpcError.code === 4001) {
18536
19332
  throw new WalletError(
18537
19333
  "User rejected connection request",
18538
- import_types27.WalletErrorCode.CONNECTION_REJECTED
19334
+ import_types28.WalletErrorCode.CONNECTION_REJECTED
18539
19335
  );
18540
19336
  }
18541
19337
  throw new WalletError(
18542
19338
  `Failed to connect: ${rpcError.message || String(error)}`,
18543
- import_types27.WalletErrorCode.CONNECTION_FAILED
19339
+ import_types28.WalletErrorCode.CONNECTION_FAILED
18544
19340
  );
18545
19341
  }
18546
19342
  }
@@ -18560,7 +19356,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18560
19356
  if (!this.provider) {
18561
19357
  throw new WalletError(
18562
19358
  "Provider not available",
18563
- import_types27.WalletErrorCode.NOT_CONNECTED
19359
+ import_types28.WalletErrorCode.NOT_CONNECTED
18564
19360
  );
18565
19361
  }
18566
19362
  try {
@@ -18578,12 +19374,12 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18578
19374
  if (rpcError.code === 4001) {
18579
19375
  throw new WalletError(
18580
19376
  "User rejected signing request",
18581
- import_types27.WalletErrorCode.SIGNING_REJECTED
19377
+ import_types28.WalletErrorCode.SIGNING_REJECTED
18582
19378
  );
18583
19379
  }
18584
19380
  throw new WalletError(
18585
19381
  `Failed to sign message: ${rpcError.message || String(error)}`,
18586
- import_types27.WalletErrorCode.SIGNING_FAILED
19382
+ import_types28.WalletErrorCode.SIGNING_FAILED
18587
19383
  );
18588
19384
  }
18589
19385
  }
@@ -18595,7 +19391,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18595
19391
  if (!this.provider) {
18596
19392
  throw new WalletError(
18597
19393
  "Provider not available",
18598
- import_types27.WalletErrorCode.NOT_CONNECTED
19394
+ import_types28.WalletErrorCode.NOT_CONNECTED
18599
19395
  );
18600
19396
  }
18601
19397
  try {
@@ -18612,12 +19408,12 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18612
19408
  if (rpcError.code === 4001) {
18613
19409
  throw new WalletError(
18614
19410
  "User rejected signing request",
18615
- import_types27.WalletErrorCode.SIGNING_REJECTED
19411
+ import_types28.WalletErrorCode.SIGNING_REJECTED
18616
19412
  );
18617
19413
  }
18618
19414
  throw new WalletError(
18619
19415
  `Failed to sign typed data: ${rpcError.message || String(error)}`,
18620
- import_types27.WalletErrorCode.SIGNING_FAILED
19416
+ import_types28.WalletErrorCode.SIGNING_FAILED
18621
19417
  );
18622
19418
  }
18623
19419
  }
@@ -18629,7 +19425,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18629
19425
  if (!this.provider) {
18630
19426
  throw new WalletError(
18631
19427
  "Provider not available",
18632
- import_types27.WalletErrorCode.NOT_CONNECTED
19428
+ import_types28.WalletErrorCode.NOT_CONNECTED
18633
19429
  );
18634
19430
  }
18635
19431
  try {
@@ -18657,7 +19453,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18657
19453
  if (rpcError.code === 4001) {
18658
19454
  throw new WalletError(
18659
19455
  "User rejected transaction signing",
18660
- import_types27.WalletErrorCode.SIGNING_REJECTED
19456
+ import_types28.WalletErrorCode.SIGNING_REJECTED
18661
19457
  );
18662
19458
  }
18663
19459
  if (rpcError.code === -32601 || rpcError.message?.includes("not supported")) {
@@ -18675,7 +19471,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18675
19471
  }
18676
19472
  throw new WalletError(
18677
19473
  `Failed to sign transaction: ${rpcError.message || String(error)}`,
18678
- import_types27.WalletErrorCode.TRANSACTION_FAILED
19474
+ import_types28.WalletErrorCode.TRANSACTION_FAILED
18679
19475
  );
18680
19476
  }
18681
19477
  }
@@ -18687,7 +19483,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18687
19483
  if (!this.provider) {
18688
19484
  throw new WalletError(
18689
19485
  "Provider not available",
18690
- import_types27.WalletErrorCode.NOT_CONNECTED
19486
+ import_types28.WalletErrorCode.NOT_CONNECTED
18691
19487
  );
18692
19488
  }
18693
19489
  try {
@@ -18709,12 +19505,12 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18709
19505
  if (rpcError.code === 4001) {
18710
19506
  throw new WalletError(
18711
19507
  "User rejected transaction",
18712
- import_types27.WalletErrorCode.TRANSACTION_REJECTED
19508
+ import_types28.WalletErrorCode.TRANSACTION_REJECTED
18713
19509
  );
18714
19510
  }
18715
19511
  throw new WalletError(
18716
19512
  `Failed to send transaction: ${rpcError.message || String(error)}`,
18717
- import_types27.WalletErrorCode.TRANSACTION_FAILED
19513
+ import_types28.WalletErrorCode.TRANSACTION_FAILED
18718
19514
  );
18719
19515
  }
18720
19516
  }
@@ -18749,7 +19545,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18749
19545
  } catch (error) {
18750
19546
  throw new WalletError(
18751
19547
  `Failed to fetch balance: ${String(error)}`,
18752
- import_types27.WalletErrorCode.UNKNOWN
19548
+ import_types28.WalletErrorCode.UNKNOWN
18753
19549
  );
18754
19550
  }
18755
19551
  }
@@ -18761,7 +19557,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18761
19557
  if (asset.chain !== "ethereum") {
18762
19558
  throw new WalletError(
18763
19559
  `Asset chain ${asset.chain} not supported by Ethereum adapter`,
18764
- import_types27.WalletErrorCode.UNSUPPORTED_CHAIN
19560
+ import_types28.WalletErrorCode.UNSUPPORTED_CHAIN
18765
19561
  );
18766
19562
  }
18767
19563
  if (!asset.address) {
@@ -18786,7 +19582,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18786
19582
  } catch (error) {
18787
19583
  throw new WalletError(
18788
19584
  `Failed to fetch token balance: ${String(error)}`,
18789
- import_types27.WalletErrorCode.UNKNOWN
19585
+ import_types28.WalletErrorCode.UNKNOWN
18790
19586
  );
18791
19587
  }
18792
19588
  }
@@ -18798,7 +19594,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18798
19594
  if (!this.provider) {
18799
19595
  throw new WalletError(
18800
19596
  "Provider not available",
18801
- import_types27.WalletErrorCode.NOT_CONNECTED
19597
+ import_types28.WalletErrorCode.NOT_CONNECTED
18802
19598
  );
18803
19599
  }
18804
19600
  try {
@@ -18813,18 +19609,18 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18813
19609
  if (rpcError.code === 4001) {
18814
19610
  throw new WalletError(
18815
19611
  "User rejected chain switch",
18816
- import_types27.WalletErrorCode.CHAIN_SWITCH_REJECTED
19612
+ import_types28.WalletErrorCode.CHAIN_SWITCH_REJECTED
18817
19613
  );
18818
19614
  }
18819
19615
  if (rpcError.code === 4902) {
18820
19616
  throw new WalletError(
18821
19617
  `Chain ${chainId} not added to wallet`,
18822
- import_types27.WalletErrorCode.UNSUPPORTED_CHAIN
19618
+ import_types28.WalletErrorCode.UNSUPPORTED_CHAIN
18823
19619
  );
18824
19620
  }
18825
19621
  throw new WalletError(
18826
19622
  `Failed to switch chain: ${rpcError.message || String(error)}`,
18827
- import_types27.WalletErrorCode.CHAIN_SWITCH_FAILED
19623
+ import_types28.WalletErrorCode.CHAIN_SWITCH_FAILED
18828
19624
  );
18829
19625
  }
18830
19626
  }
@@ -18860,7 +19656,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
18860
19656
  }
18861
19657
  throw new WalletError(
18862
19658
  `Transaction ${txHash} not confirmed after ${maxAttempts * 5} seconds`,
18863
- import_types27.WalletErrorCode.TRANSACTION_FAILED
19659
+ import_types28.WalletErrorCode.TRANSACTION_FAILED
18864
19660
  );
18865
19661
  }
18866
19662
  /**
@@ -18934,7 +19730,7 @@ function createEthereumAdapter(config) {
18934
19730
  }
18935
19731
 
18936
19732
  // src/wallet/ethereum/mock.ts
18937
- var import_types29 = require("@sip-protocol/types");
19733
+ var import_types30 = require("@sip-protocol/types");
18938
19734
  var MockEthereumAdapter = class extends BaseWalletAdapter {
18939
19735
  chain = "ethereum";
18940
19736
  name = "mock-ethereum";
@@ -18975,7 +19771,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
18975
19771
  this._connectionState = "error";
18976
19772
  throw new WalletError(
18977
19773
  "Mock connection rejected",
18978
- import_types29.WalletErrorCode.CONNECTION_REJECTED
19774
+ import_types30.WalletErrorCode.CONNECTION_REJECTED
18979
19775
  );
18980
19776
  }
18981
19777
  await new Promise((resolve) => setTimeout(resolve, 10));
@@ -18987,7 +19783,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
18987
19783
  this._connectionState = "error";
18988
19784
  throw new WalletError(
18989
19785
  `Mock connection failed: ${String(error)}`,
18990
- import_types29.WalletErrorCode.CONNECTION_FAILED
19786
+ import_types30.WalletErrorCode.CONNECTION_FAILED
18991
19787
  );
18992
19788
  }
18993
19789
  }
@@ -19005,7 +19801,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
19005
19801
  if (this._shouldFailSign) {
19006
19802
  throw new WalletError(
19007
19803
  "Mock signing rejected",
19008
- import_types29.WalletErrorCode.SIGNING_REJECTED
19804
+ import_types30.WalletErrorCode.SIGNING_REJECTED
19009
19805
  );
19010
19806
  }
19011
19807
  const msgHex = Buffer.from(message).toString("hex");
@@ -19023,7 +19819,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
19023
19819
  if (this._shouldFailSign) {
19024
19820
  throw new WalletError(
19025
19821
  "Mock signing rejected",
19026
- import_types29.WalletErrorCode.SIGNING_REJECTED
19822
+ import_types30.WalletErrorCode.SIGNING_REJECTED
19027
19823
  );
19028
19824
  }
19029
19825
  const mockSig = `0x${"1".repeat(130)}`;
@@ -19040,7 +19836,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
19040
19836
  if (this._shouldFailSign) {
19041
19837
  throw new WalletError(
19042
19838
  "Mock signing rejected",
19043
- import_types29.WalletErrorCode.SIGNING_REJECTED
19839
+ import_types30.WalletErrorCode.SIGNING_REJECTED
19044
19840
  );
19045
19841
  }
19046
19842
  this._signedTransactions.push(tx);
@@ -19065,7 +19861,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
19065
19861
  if (this._shouldFailTransaction) {
19066
19862
  throw new WalletError(
19067
19863
  "Mock transaction failed",
19068
- import_types29.WalletErrorCode.TRANSACTION_FAILED
19864
+ import_types30.WalletErrorCode.TRANSACTION_FAILED
19069
19865
  );
19070
19866
  }
19071
19867
  this._signedTransactions.push(tx);
@@ -19095,7 +19891,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
19095
19891
  if (asset.chain !== "ethereum") {
19096
19892
  throw new WalletError(
19097
19893
  `Asset chain ${asset.chain} not supported by Ethereum adapter`,
19098
- import_types29.WalletErrorCode.UNSUPPORTED_CHAIN
19894
+ import_types30.WalletErrorCode.UNSUPPORTED_CHAIN
19099
19895
  );
19100
19896
  }
19101
19897
  if (!asset.address) {
@@ -19300,28 +20096,28 @@ function createMockEthereumProvider(config = {}) {
19300
20096
  }
19301
20097
 
19302
20098
  // src/wallet/cosmos/adapter.ts
19303
- var import_types32 = require("@sip-protocol/types");
20099
+ var import_types33 = require("@sip-protocol/types");
19304
20100
 
19305
20101
  // src/wallet/cosmos/mock.ts
19306
- var import_types34 = require("@sip-protocol/types");
20102
+ var import_types35 = require("@sip-protocol/types");
19307
20103
 
19308
20104
  // src/wallet/bitcoin/adapter.ts
19309
- var import_types37 = require("@sip-protocol/types");
20105
+ var import_types38 = require("@sip-protocol/types");
19310
20106
 
19311
20107
  // src/wallet/bitcoin/mock.ts
19312
- var import_types39 = require("@sip-protocol/types");
20108
+ var import_types40 = require("@sip-protocol/types");
19313
20109
 
19314
20110
  // src/wallet/aptos/adapter.ts
19315
- var import_types42 = require("@sip-protocol/types");
20111
+ var import_types43 = require("@sip-protocol/types");
19316
20112
 
19317
20113
  // src/wallet/aptos/mock.ts
19318
- var import_types44 = require("@sip-protocol/types");
20114
+ var import_types45 = require("@sip-protocol/types");
19319
20115
 
19320
20116
  // src/wallet/sui/adapter.ts
19321
- var import_types46 = require("@sip-protocol/types");
20117
+ var import_types47 = require("@sip-protocol/types");
19322
20118
 
19323
20119
  // src/wallet/sui/mock.ts
19324
- var import_types48 = require("@sip-protocol/types");
20120
+ var import_types49 = require("@sip-protocol/types");
19325
20121
 
19326
20122
  // src/wallet/hardware/types.ts
19327
20123
  var DerivationPath = {
@@ -19401,7 +20197,7 @@ function getAvailableTransports() {
19401
20197
 
19402
20198
  // src/wallet/hardware/ledger.ts
19403
20199
  var import_rlp = require("@ethereumjs/rlp");
19404
- var import_types50 = require("@sip-protocol/types");
20200
+ var import_types51 = require("@sip-protocol/types");
19405
20201
  var LedgerWalletAdapter = class extends BaseWalletAdapter {
19406
20202
  chain;
19407
20203
  name = "ledger";
@@ -19554,7 +20350,7 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
19554
20350
  async getBalance() {
19555
20351
  throw new WalletError(
19556
20352
  "Hardware wallets do not track balances. Use an RPC provider.",
19557
- import_types50.WalletErrorCode.UNSUPPORTED_OPERATION
20353
+ import_types51.WalletErrorCode.UNSUPPORTED_OPERATION
19558
20354
  );
19559
20355
  }
19560
20356
  /**
@@ -19565,7 +20361,7 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
19565
20361
  async getTokenBalance(_asset) {
19566
20362
  throw new WalletError(
19567
20363
  "Hardware wallets do not track balances. Use an RPC provider.",
19568
- import_types50.WalletErrorCode.UNSUPPORTED_OPERATION
20364
+ import_types51.WalletErrorCode.UNSUPPORTED_OPERATION
19569
20365
  );
19570
20366
  }
19571
20367
  // ─── Account Management ─────────────────────────────────────────────────────
@@ -19792,7 +20588,7 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
19792
20588
  * @see https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/
19793
20589
  */
19794
20590
  buildRawEthereumTx(tx) {
19795
- const hexToBytes24 = (hex) => {
20591
+ const hexToBytes25 = (hex) => {
19796
20592
  if (!hex || hex === "0x" || hex === "0x0" || hex === "0x00") {
19797
20593
  return new Uint8Array(0);
19798
20594
  }
@@ -19809,21 +20605,21 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
19809
20605
  const isEIP1559 = tx.maxFeePerGas !== void 0 && tx.maxPriorityFeePerGas !== void 0;
19810
20606
  if (isEIP1559) {
19811
20607
  const txData = [
19812
- hexToBytes24(`0x${tx.chainId.toString(16)}`),
20608
+ hexToBytes25(`0x${tx.chainId.toString(16)}`),
19813
20609
  // chainId
19814
- hexToBytes24(tx.nonce),
20610
+ hexToBytes25(tx.nonce),
19815
20611
  // nonce
19816
- hexToBytes24(tx.maxPriorityFeePerGas),
20612
+ hexToBytes25(tx.maxPriorityFeePerGas),
19817
20613
  // maxPriorityFeePerGas
19818
- hexToBytes24(tx.maxFeePerGas),
20614
+ hexToBytes25(tx.maxFeePerGas),
19819
20615
  // maxFeePerGas
19820
- hexToBytes24(tx.gasLimit),
20616
+ hexToBytes25(tx.gasLimit),
19821
20617
  // gasLimit
19822
- hexToBytes24(tx.to),
20618
+ hexToBytes25(tx.to),
19823
20619
  // to
19824
- hexToBytes24(tx.value),
20620
+ hexToBytes25(tx.value),
19825
20621
  // value
19826
- hexToBytes24(tx.data),
20622
+ hexToBytes25(tx.data),
19827
20623
  // data
19828
20624
  []
19829
20625
  // accessList (empty)
@@ -19842,19 +20638,19 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
19842
20638
  );
19843
20639
  }
19844
20640
  const txData = [
19845
- hexToBytes24(tx.nonce),
20641
+ hexToBytes25(tx.nonce),
19846
20642
  // nonce
19847
- hexToBytes24(tx.gasPrice),
20643
+ hexToBytes25(tx.gasPrice),
19848
20644
  // gasPrice
19849
- hexToBytes24(tx.gasLimit),
20645
+ hexToBytes25(tx.gasLimit),
19850
20646
  // gasLimit
19851
- hexToBytes24(tx.to),
20647
+ hexToBytes25(tx.to),
19852
20648
  // to
19853
- hexToBytes24(tx.value),
20649
+ hexToBytes25(tx.value),
19854
20650
  // value
19855
- hexToBytes24(tx.data),
20651
+ hexToBytes25(tx.data),
19856
20652
  // data
19857
- hexToBytes24(`0x${tx.chainId.toString(16)}`),
20653
+ hexToBytes25(`0x${tx.chainId.toString(16)}`),
19858
20654
  // v (chainId for EIP-155)
19859
20655
  new Uint8Array(0),
19860
20656
  // r (empty for unsigned)
@@ -19931,7 +20727,7 @@ function createLedgerAdapter(config) {
19931
20727
  }
19932
20728
 
19933
20729
  // src/wallet/hardware/trezor.ts
19934
- var import_types52 = require("@sip-protocol/types");
20730
+ var import_types53 = require("@sip-protocol/types");
19935
20731
  var TrezorWalletAdapter = class extends BaseWalletAdapter {
19936
20732
  chain;
19937
20733
  name = "trezor";
@@ -20077,7 +20873,7 @@ var TrezorWalletAdapter = class extends BaseWalletAdapter {
20077
20873
  async getBalance() {
20078
20874
  throw new WalletError(
20079
20875
  "Hardware wallets do not track balances. Use an RPC provider.",
20080
- import_types52.WalletErrorCode.UNSUPPORTED_OPERATION
20876
+ import_types53.WalletErrorCode.UNSUPPORTED_OPERATION
20081
20877
  );
20082
20878
  }
20083
20879
  /**
@@ -20088,7 +20884,7 @@ var TrezorWalletAdapter = class extends BaseWalletAdapter {
20088
20884
  async getTokenBalance(_asset) {
20089
20885
  throw new WalletError(
20090
20886
  "Hardware wallets do not track balances. Use an RPC provider.",
20091
- import_types52.WalletErrorCode.UNSUPPORTED_OPERATION
20887
+ import_types53.WalletErrorCode.UNSUPPORTED_OPERATION
20092
20888
  );
20093
20889
  }
20094
20890
  // ─── Account Management ─────────────────────────────────────────────────────
@@ -20369,8 +21165,8 @@ function createTrezorAdapter(config) {
20369
21165
  }
20370
21166
 
20371
21167
  // src/wallet/hardware/mock.ts
20372
- var import_types54 = require("@sip-protocol/types");
20373
- var import_utils30 = require("@noble/hashes/utils");
21168
+ var import_types55 = require("@sip-protocol/types");
21169
+ var import_utils31 = require("@noble/hashes/utils");
20374
21170
  var MockLedgerAdapter = class extends BaseWalletAdapter {
20375
21171
  chain;
20376
21172
  name = "mock-ledger";
@@ -20517,7 +21313,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
20517
21313
  async getBalance() {
20518
21314
  throw new WalletError(
20519
21315
  "Hardware wallets do not track balances",
20520
- import_types54.WalletErrorCode.UNSUPPORTED_OPERATION
21316
+ import_types55.WalletErrorCode.UNSUPPORTED_OPERATION
20521
21317
  );
20522
21318
  }
20523
21319
  /**
@@ -20526,7 +21322,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
20526
21322
  async getTokenBalance(_asset) {
20527
21323
  throw new WalletError(
20528
21324
  "Hardware wallets do not track balances",
20529
- import_types54.WalletErrorCode.UNSUPPORTED_OPERATION
21325
+ import_types55.WalletErrorCode.UNSUPPORTED_OPERATION
20530
21326
  );
20531
21327
  }
20532
21328
  /**
@@ -20615,15 +21411,15 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
20615
21411
  }
20616
21412
  }
20617
21413
  generateMockAddress(index) {
20618
- const bytes = (0, import_utils30.randomBytes)(20);
21414
+ const bytes = (0, import_utils31.randomBytes)(20);
20619
21415
  bytes[0] = index;
20620
- return `0x${(0, import_utils30.bytesToHex)(bytes)}`;
21416
+ return `0x${(0, import_utils31.bytesToHex)(bytes)}`;
20621
21417
  }
20622
21418
  generateMockPublicKey(index) {
20623
- const bytes = (0, import_utils30.randomBytes)(33);
21419
+ const bytes = (0, import_utils31.randomBytes)(33);
20624
21420
  bytes[0] = 2;
20625
21421
  bytes[1] = index;
20626
- return `0x${(0, import_utils30.bytesToHex)(bytes)}`;
21422
+ return `0x${(0, import_utils31.bytesToHex)(bytes)}`;
20627
21423
  }
20628
21424
  generateMockSignature(data) {
20629
21425
  const sig = new Uint8Array(65);
@@ -20632,7 +21428,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
20632
21428
  sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 11;
20633
21429
  }
20634
21430
  sig[64] = 27;
20635
- return `0x${(0, import_utils30.bytesToHex)(sig)}`;
21431
+ return `0x${(0, import_utils31.bytesToHex)(sig)}`;
20636
21432
  }
20637
21433
  delay(ms) {
20638
21434
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -20756,13 +21552,13 @@ var MockTrezorAdapter = class extends BaseWalletAdapter {
20756
21552
  async getBalance() {
20757
21553
  throw new WalletError(
20758
21554
  "Hardware wallets do not track balances",
20759
- import_types54.WalletErrorCode.UNSUPPORTED_OPERATION
21555
+ import_types55.WalletErrorCode.UNSUPPORTED_OPERATION
20760
21556
  );
20761
21557
  }
20762
21558
  async getTokenBalance(_asset) {
20763
21559
  throw new WalletError(
20764
21560
  "Hardware wallets do not track balances",
20765
- import_types54.WalletErrorCode.UNSUPPORTED_OPERATION
21561
+ import_types55.WalletErrorCode.UNSUPPORTED_OPERATION
20766
21562
  );
20767
21563
  }
20768
21564
  async getAccounts(startIndex = 0, count = 5) {
@@ -20821,15 +21617,15 @@ var MockTrezorAdapter = class extends BaseWalletAdapter {
20821
21617
  }
20822
21618
  }
20823
21619
  generateMockAddress(index) {
20824
- const bytes = (0, import_utils30.randomBytes)(20);
21620
+ const bytes = (0, import_utils31.randomBytes)(20);
20825
21621
  bytes[0] = index + 100;
20826
- return `0x${(0, import_utils30.bytesToHex)(bytes)}`;
21622
+ return `0x${(0, import_utils31.bytesToHex)(bytes)}`;
20827
21623
  }
20828
21624
  generateMockPublicKey(index) {
20829
- const bytes = (0, import_utils30.randomBytes)(33);
21625
+ const bytes = (0, import_utils31.randomBytes)(33);
20830
21626
  bytes[0] = 3;
20831
21627
  bytes[1] = index + 100;
20832
- return `0x${(0, import_utils30.bytesToHex)(bytes)}`;
21628
+ return `0x${(0, import_utils31.bytesToHex)(bytes)}`;
20833
21629
  }
20834
21630
  generateMockSignature(data) {
20835
21631
  const sig = new Uint8Array(65);
@@ -20838,7 +21634,7 @@ var MockTrezorAdapter = class extends BaseWalletAdapter {
20838
21634
  sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 17;
20839
21635
  }
20840
21636
  sig[64] = 28;
20841
- return `0x${(0, import_utils30.bytesToHex)(sig)}`;
21637
+ return `0x${(0, import_utils31.bytesToHex)(sig)}`;
20842
21638
  }
20843
21639
  delay(ms) {
20844
21640
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -20852,7 +21648,7 @@ function createMockTrezorAdapter(config) {
20852
21648
  }
20853
21649
 
20854
21650
  // src/wallet/index.ts
20855
- var import_types57 = require("@sip-protocol/types");
21651
+ var import_types58 = require("@sip-protocol/types");
20856
21652
 
20857
21653
  // src/index.ts
20858
21654
  init_solana();
@@ -20905,10 +21701,1778 @@ function isSameChainSupported(chain) {
20905
21701
  function getSupportedSameChainChains() {
20906
21702
  return ["solana"];
20907
21703
  }
21704
+
21705
+ // src/privacy-backends/registry.ts
21706
+ var DEFAULT_PRIORITY = 50;
21707
+ var PrivacyBackendRegistry = class {
21708
+ backends = /* @__PURE__ */ new Map();
21709
+ /**
21710
+ * Register a privacy backend
21711
+ *
21712
+ * @param backend - Backend instance to register
21713
+ * @param options - Registration options
21714
+ * @throws Error if backend with same name exists and override is false
21715
+ *
21716
+ * @example
21717
+ * ```typescript
21718
+ * registry.register(new SIPNativeBackend())
21719
+ * registry.register(new PrivacyCashBackend(), { priority: 100 })
21720
+ * ```
21721
+ */
21722
+ register(backend, options = {}) {
21723
+ const { override = false, priority = DEFAULT_PRIORITY, enabled = true } = options;
21724
+ if (this.backends.has(backend.name) && !override) {
21725
+ throw new Error(
21726
+ `Backend '${backend.name}' is already registered. Use { override: true } to replace it.`
21727
+ );
21728
+ }
21729
+ this.backends.set(backend.name, {
21730
+ backend,
21731
+ priority,
21732
+ enabled,
21733
+ registeredAt: Date.now()
21734
+ });
21735
+ }
21736
+ /**
21737
+ * Unregister a backend by name
21738
+ *
21739
+ * @param name - Backend name to unregister
21740
+ * @returns true if backend was removed, false if not found
21741
+ */
21742
+ unregister(name) {
21743
+ return this.backends.delete(name);
21744
+ }
21745
+ /**
21746
+ * Get a backend by name
21747
+ *
21748
+ * @param name - Backend name
21749
+ * @returns Backend instance or undefined if not found
21750
+ */
21751
+ get(name) {
21752
+ const entry = this.backends.get(name);
21753
+ return entry?.enabled ? entry.backend : void 0;
21754
+ }
21755
+ /**
21756
+ * Check if a backend is registered
21757
+ *
21758
+ * @param name - Backend name
21759
+ * @returns true if registered (regardless of enabled state)
21760
+ */
21761
+ has(name) {
21762
+ return this.backends.has(name);
21763
+ }
21764
+ /**
21765
+ * Get all enabled backends sorted by priority
21766
+ *
21767
+ * @returns Array of backends (highest priority first)
21768
+ */
21769
+ getAll() {
21770
+ return Array.from(this.backends.values()).filter((entry) => entry.enabled).sort((a, b) => b.priority - a.priority).map((entry) => entry.backend);
21771
+ }
21772
+ /**
21773
+ * Get all registered entries (including disabled)
21774
+ *
21775
+ * @returns Array of registered backend entries
21776
+ */
21777
+ getAllEntries() {
21778
+ return Array.from(this.backends.values()).sort((a, b) => b.priority - a.priority);
21779
+ }
21780
+ /**
21781
+ * Get backends supporting a specific chain
21782
+ *
21783
+ * @param chain - Chain type to filter by
21784
+ * @returns Array of backends supporting the chain
21785
+ */
21786
+ getByChain(chain) {
21787
+ return this.getAll().filter(
21788
+ (backend) => backend.chains.includes(chain)
21789
+ );
21790
+ }
21791
+ /**
21792
+ * Get backends of a specific type
21793
+ *
21794
+ * @param type - Backend type to filter by
21795
+ * @returns Array of backends of the specified type
21796
+ */
21797
+ getByType(type) {
21798
+ return this.getAll().filter(
21799
+ (backend) => backend.type === type || backend.type === "both"
21800
+ );
21801
+ }
21802
+ /**
21803
+ * Get backends that support compliance (viewing keys)
21804
+ *
21805
+ * @returns Array of compliance-supporting backends
21806
+ */
21807
+ getCompliant() {
21808
+ return this.getAll().filter(
21809
+ (backend) => backend.getCapabilities().complianceSupport
21810
+ );
21811
+ }
21812
+ /**
21813
+ * Find available backends for a transfer
21814
+ *
21815
+ * @param params - Transfer parameters
21816
+ * @returns Array of available backends with availability info
21817
+ */
21818
+ async findAvailable(params) {
21819
+ const chainBackends = this.getByChain(params.chain);
21820
+ const results = [];
21821
+ for (const backend of chainBackends) {
21822
+ const availability = await backend.checkAvailability(params);
21823
+ if (availability.available) {
21824
+ results.push({ backend, availability });
21825
+ }
21826
+ }
21827
+ return results;
21828
+ }
21829
+ /**
21830
+ * Enable a backend
21831
+ *
21832
+ * @param name - Backend name
21833
+ * @returns true if backend was enabled, false if not found
21834
+ */
21835
+ enable(name) {
21836
+ const entry = this.backends.get(name);
21837
+ if (entry) {
21838
+ entry.enabled = true;
21839
+ return true;
21840
+ }
21841
+ return false;
21842
+ }
21843
+ /**
21844
+ * Disable a backend
21845
+ *
21846
+ * @param name - Backend name
21847
+ * @returns true if backend was disabled, false if not found
21848
+ */
21849
+ disable(name) {
21850
+ const entry = this.backends.get(name);
21851
+ if (entry) {
21852
+ entry.enabled = false;
21853
+ return true;
21854
+ }
21855
+ return false;
21856
+ }
21857
+ /**
21858
+ * Set backend priority
21859
+ *
21860
+ * @param name - Backend name
21861
+ * @param priority - New priority value
21862
+ * @returns true if priority was set, false if not found
21863
+ */
21864
+ setPriority(name, priority) {
21865
+ const entry = this.backends.get(name);
21866
+ if (entry) {
21867
+ entry.priority = priority;
21868
+ return true;
21869
+ }
21870
+ return false;
21871
+ }
21872
+ /**
21873
+ * Get count of registered backends
21874
+ *
21875
+ * @param enabledOnly - If true, only count enabled backends
21876
+ * @returns Number of backends
21877
+ */
21878
+ count(enabledOnly = false) {
21879
+ if (enabledOnly) {
21880
+ return Array.from(this.backends.values()).filter((e) => e.enabled).length;
21881
+ }
21882
+ return this.backends.size;
21883
+ }
21884
+ /**
21885
+ * Clear all registered backends
21886
+ */
21887
+ clear() {
21888
+ this.backends.clear();
21889
+ }
21890
+ /**
21891
+ * Get backend names
21892
+ *
21893
+ * @param enabledOnly - If true, only return enabled backend names
21894
+ * @returns Array of backend names
21895
+ */
21896
+ getNames(enabledOnly = false) {
21897
+ if (enabledOnly) {
21898
+ return Array.from(this.backends.entries()).filter(([, entry]) => entry.enabled).map(([name]) => name);
21899
+ }
21900
+ return Array.from(this.backends.keys());
21901
+ }
21902
+ };
21903
+ var defaultRegistry = new PrivacyBackendRegistry();
21904
+
21905
+ // src/privacy-backends/sip-native.ts
21906
+ var SUPPORTED_CHAINS = [
21907
+ "solana",
21908
+ "ethereum",
21909
+ "near",
21910
+ "polygon",
21911
+ "arbitrum",
21912
+ "optimism",
21913
+ "base",
21914
+ "avalanche",
21915
+ "bsc"
21916
+ ];
21917
+ var SIP_NATIVE_CAPABILITIES = {
21918
+ hiddenAmount: true,
21919
+ hiddenSender: true,
21920
+ hiddenRecipient: true,
21921
+ hiddenCompute: false,
21922
+ complianceSupport: true,
21923
+ anonymitySet: void 0,
21924
+ // Not pool-based
21925
+ setupRequired: false,
21926
+ latencyEstimate: "fast",
21927
+ supportedTokens: "all",
21928
+ minAmount: void 0,
21929
+ maxAmount: void 0
21930
+ };
21931
+ var SIPNativeBackend = class {
21932
+ name = "sip-native";
21933
+ type = "transaction";
21934
+ chains;
21935
+ config;
21936
+ /**
21937
+ * Create a new SIP Native backend
21938
+ *
21939
+ * @param config - Backend configuration
21940
+ */
21941
+ constructor(config = {}) {
21942
+ this.chains = config.chains ?? SUPPORTED_CHAINS;
21943
+ this.config = {
21944
+ chains: this.chains,
21945
+ requireViewingKey: config.requireViewingKey ?? false,
21946
+ minAmount: config.minAmount ?? BigInt(0),
21947
+ maxAmount: config.maxAmount ?? BigInt(Number.MAX_SAFE_INTEGER)
21948
+ };
21949
+ }
21950
+ /**
21951
+ * Check if backend is available for given parameters
21952
+ */
21953
+ async checkAvailability(params) {
21954
+ if (!this.chains.includes(params.chain)) {
21955
+ return {
21956
+ available: false,
21957
+ reason: `Chain '${params.chain}' not supported by SIP Native backend`
21958
+ };
21959
+ }
21960
+ if (this.config.requireViewingKey && !params.viewingKey) {
21961
+ return {
21962
+ available: false,
21963
+ reason: "Viewing key required for SIP Native backend"
21964
+ };
21965
+ }
21966
+ if (params.amount < this.config.minAmount) {
21967
+ return {
21968
+ available: false,
21969
+ reason: `Amount ${params.amount} below minimum ${this.config.minAmount}`
21970
+ };
21971
+ }
21972
+ if (params.amount > this.config.maxAmount) {
21973
+ return {
21974
+ available: false,
21975
+ reason: `Amount ${params.amount} above maximum ${this.config.maxAmount}`
21976
+ };
21977
+ }
21978
+ const estimatedCost = this.getEstimatedCostForChain(params.chain);
21979
+ return {
21980
+ available: true,
21981
+ estimatedCost,
21982
+ estimatedTime: 1e3
21983
+ // ~1 second for stealth address operations
21984
+ };
21985
+ }
21986
+ /**
21987
+ * Get backend capabilities
21988
+ */
21989
+ getCapabilities() {
21990
+ return {
21991
+ ...SIP_NATIVE_CAPABILITIES,
21992
+ minAmount: this.config.minAmount > BigInt(0) ? this.config.minAmount : void 0,
21993
+ maxAmount: this.config.maxAmount < BigInt(Number.MAX_SAFE_INTEGER) ? this.config.maxAmount : void 0
21994
+ };
21995
+ }
21996
+ /**
21997
+ * Execute a privacy-preserving transfer
21998
+ *
21999
+ * This creates a stealth address transfer with:
22000
+ * - Ephemeral keypair generation
22001
+ * - Stealth address derivation
22002
+ * - Pedersen commitment for amount
22003
+ * - Optional viewing key encryption
22004
+ */
22005
+ async execute(params) {
22006
+ const availability = await this.checkAvailability(params);
22007
+ if (!availability.available) {
22008
+ return {
22009
+ success: false,
22010
+ error: availability.reason,
22011
+ backend: this.name
22012
+ };
22013
+ }
22014
+ try {
22015
+ const simulatedSignature = `sim_${Date.now()}_${Math.random().toString(36).slice(2)}`;
22016
+ return {
22017
+ success: true,
22018
+ signature: simulatedSignature,
22019
+ backend: this.name,
22020
+ metadata: {
22021
+ chain: params.chain,
22022
+ amount: params.amount.toString(),
22023
+ hasViewingKey: !!params.viewingKey,
22024
+ timestamp: Date.now()
22025
+ }
22026
+ };
22027
+ } catch (error) {
22028
+ return {
22029
+ success: false,
22030
+ error: error instanceof Error ? error.message : "Unknown error",
22031
+ backend: this.name
22032
+ };
22033
+ }
22034
+ }
22035
+ /**
22036
+ * Estimate cost for a transfer
22037
+ */
22038
+ async estimateCost(params) {
22039
+ return this.getEstimatedCostForChain(params.chain);
22040
+ }
22041
+ /**
22042
+ * Get estimated cost based on chain
22043
+ */
22044
+ getEstimatedCostForChain(chain) {
22045
+ const costMap = {
22046
+ solana: BigInt(5e3),
22047
+ // ~0.000005 SOL
22048
+ ethereum: BigInt("50000000000000"),
22049
+ // ~0.00005 ETH
22050
+ near: BigInt("1000000000000000000000"),
22051
+ // ~0.001 NEAR
22052
+ polygon: BigInt("50000000000000"),
22053
+ // ~0.00005 MATIC
22054
+ arbitrum: BigInt("50000000000000"),
22055
+ optimism: BigInt("50000000000000"),
22056
+ base: BigInt("50000000000000"),
22057
+ avalanche: BigInt("50000000000000"),
22058
+ bsc: BigInt("50000000000000")
22059
+ };
22060
+ return costMap[chain] ?? BigInt(0);
22061
+ }
22062
+ };
22063
+
22064
+ // src/privacy-backends/privacycash-types.ts
22065
+ var SOL_POOL_SIZES = {
22066
+ /** 0.1 SOL pool */
22067
+ SMALL: BigInt(1e8),
22068
+ /** 1 SOL pool */
22069
+ MEDIUM: BigInt(1e9),
22070
+ /** 10 SOL pool */
22071
+ LARGE: BigInt(1e10),
22072
+ /** 100 SOL pool */
22073
+ WHALE: BigInt(1e11)
22074
+ };
22075
+ var USDC_POOL_SIZES = {
22076
+ /** 10 USDC pool */
22077
+ SMALL: BigInt(1e7),
22078
+ /** 100 USDC pool */
22079
+ MEDIUM: BigInt(1e8),
22080
+ /** 1,000 USDC pool */
22081
+ LARGE: BigInt(1e9),
22082
+ /** 10,000 USDC pool */
22083
+ WHALE: BigInt(1e10)
22084
+ };
22085
+ var USDT_POOL_SIZES = {
22086
+ /** 10 USDT pool */
22087
+ SMALL: BigInt(1e7),
22088
+ /** 100 USDT pool */
22089
+ MEDIUM: BigInt(1e8),
22090
+ /** 1,000 USDT pool */
22091
+ LARGE: BigInt(1e9),
22092
+ /** 10,000 USDT pool */
22093
+ WHALE: BigInt(1e10)
22094
+ };
22095
+ var SOL_POOL_AMOUNTS = [
22096
+ SOL_POOL_SIZES.SMALL,
22097
+ SOL_POOL_SIZES.MEDIUM,
22098
+ SOL_POOL_SIZES.LARGE,
22099
+ SOL_POOL_SIZES.WHALE
22100
+ ];
22101
+ var SPL_POOL_AMOUNTS = [
22102
+ USDC_POOL_SIZES.SMALL,
22103
+ USDC_POOL_SIZES.MEDIUM,
22104
+ USDC_POOL_SIZES.LARGE,
22105
+ USDC_POOL_SIZES.WHALE
22106
+ ];
22107
+
22108
+ // src/privacy-backends/privacycash.ts
22109
+ var DEFAULT_ANONYMITY_SET = 50;
22110
+ var BASE_COST_LAMPORTS = BigInt(1e7);
22111
+ var PRIVACYCASH_CAPABILITIES = {
22112
+ hiddenAmount: false,
22113
+ // Fixed pool sizes, amount is known
22114
+ hiddenSender: true,
22115
+ // Pool mixing hides sender
22116
+ hiddenRecipient: true,
22117
+ // Withdrawal to fresh address
22118
+ hiddenCompute: false,
22119
+ // No compute privacy
22120
+ complianceSupport: false,
22121
+ // No viewing keys
22122
+ anonymitySet: DEFAULT_ANONYMITY_SET,
22123
+ setupRequired: false,
22124
+ // No setup needed
22125
+ latencyEstimate: "medium",
22126
+ // Need to wait for pool
22127
+ supportedTokens: "all",
22128
+ // SOL + USDC/USDT
22129
+ minAmount: SOL_POOL_AMOUNTS[0],
22130
+ // Smallest pool
22131
+ maxAmount: SOL_POOL_AMOUNTS[SOL_POOL_AMOUNTS.length - 1]
22132
+ // Largest pool
22133
+ };
22134
+
22135
+ // src/privacy-backends/router.ts
22136
+ var DEFAULT_CONFIG2 = {
22137
+ prioritize: "privacy",
22138
+ requireViewingKeys: false,
22139
+ allowComputePrivacy: true
22140
+ };
22141
+ var PRIORITY_WEIGHTS = {
22142
+ privacy: {
22143
+ hiddenAmount: 25,
22144
+ hiddenSender: 25,
22145
+ hiddenRecipient: 25,
22146
+ hiddenCompute: 10,
22147
+ anonymitySet: 15
22148
+ },
22149
+ speed: {
22150
+ fast: 40,
22151
+ medium: 25,
22152
+ slow: 10,
22153
+ setupRequired: -20
22154
+ },
22155
+ cost: {
22156
+ baseCost: 50,
22157
+ estimatedCost: 50
22158
+ },
22159
+ compliance: {
22160
+ complianceSupport: 60,
22161
+ hiddenAmount: 15,
22162
+ hiddenSender: 15,
22163
+ hiddenRecipient: 10
22164
+ }
22165
+ };
22166
+ var SmartRouter2 = class {
22167
+ registry;
22168
+ /**
22169
+ * Create a new SmartRouter
22170
+ *
22171
+ * @param registry - Backend registry to use for selection
22172
+ */
22173
+ constructor(registry) {
22174
+ this.registry = registry;
22175
+ }
22176
+ /**
22177
+ * Select the best backend for a transfer
22178
+ *
22179
+ * @param params - Transfer parameters
22180
+ * @param config - Router configuration
22181
+ * @returns Selection result with backend and reasoning
22182
+ * @throws Error if no suitable backend is found
22183
+ */
22184
+ async selectBackend(params, config = {}) {
22185
+ const fullConfig = { ...DEFAULT_CONFIG2, ...config };
22186
+ const chainBackends = this.registry.getByChain(params.chain);
22187
+ if (chainBackends.length === 0) {
22188
+ throw new Error(
22189
+ `No backends available for chain '${params.chain}'. Register a backend that supports this chain.`
22190
+ );
22191
+ }
22192
+ const scoredBackends = [];
22193
+ for (const backend of chainBackends) {
22194
+ if (fullConfig.excludeBackends?.includes(backend.name)) {
22195
+ continue;
22196
+ }
22197
+ const availability = await backend.checkAvailability(params);
22198
+ if (!availability.available) {
22199
+ continue;
22200
+ }
22201
+ const capabilities = backend.getCapabilities();
22202
+ if (fullConfig.requireViewingKeys && !capabilities.complianceSupport) {
22203
+ continue;
22204
+ }
22205
+ if (fullConfig.minAnonymitySet && capabilities.anonymitySet !== void 0 && capabilities.anonymitySet < fullConfig.minAnonymitySet) {
22206
+ continue;
22207
+ }
22208
+ if (!fullConfig.allowComputePrivacy && backend.type === "compute") {
22209
+ continue;
22210
+ }
22211
+ if (fullConfig.maxCost && availability.estimatedCost) {
22212
+ if (availability.estimatedCost > fullConfig.maxCost) {
22213
+ continue;
22214
+ }
22215
+ }
22216
+ if (fullConfig.maxLatency && availability.estimatedTime) {
22217
+ if (availability.estimatedTime > fullConfig.maxLatency) {
22218
+ continue;
22219
+ }
22220
+ }
22221
+ const { score, reason } = this.scoreBackend(
22222
+ backend,
22223
+ availability,
22224
+ fullConfig
22225
+ );
22226
+ scoredBackends.push({
22227
+ backend,
22228
+ availability,
22229
+ score,
22230
+ reason
22231
+ });
22232
+ }
22233
+ if (scoredBackends.length === 0) {
22234
+ throw new Error(
22235
+ `No backends meet the requirements for this transfer. Check your router configuration and registered backends.`
22236
+ );
22237
+ }
22238
+ scoredBackends.sort((a, b) => b.score - a.score);
22239
+ if (fullConfig.preferredBackend) {
22240
+ const preferredIndex = scoredBackends.findIndex(
22241
+ (s) => s.backend.name === fullConfig.preferredBackend
22242
+ );
22243
+ if (preferredIndex > 0) {
22244
+ const preferred = scoredBackends[preferredIndex];
22245
+ const leader = scoredBackends[0];
22246
+ if (leader.score - preferred.score <= 10) {
22247
+ scoredBackends.splice(preferredIndex, 1);
22248
+ scoredBackends.unshift(preferred);
22249
+ preferred.reason = `Preferred backend (within 10pts of optimal)`;
22250
+ }
22251
+ }
22252
+ }
22253
+ const selected = scoredBackends[0];
22254
+ const alternatives = scoredBackends.slice(1).map((s) => ({
22255
+ backend: s.backend,
22256
+ score: s.score,
22257
+ reason: s.reason
22258
+ }));
22259
+ return {
22260
+ backend: selected.backend,
22261
+ reason: selected.reason,
22262
+ alternatives,
22263
+ score: selected.score
22264
+ };
22265
+ }
22266
+ /**
22267
+ * Execute a transfer using the best available backend
22268
+ *
22269
+ * @param params - Transfer parameters
22270
+ * @param config - Router configuration
22271
+ * @returns Transaction result
22272
+ */
22273
+ async execute(params, config = {}) {
22274
+ const selection = await this.selectBackend(params, config);
22275
+ return selection.backend.execute(params);
22276
+ }
22277
+ /**
22278
+ * Get available backends for a transfer (without selecting)
22279
+ *
22280
+ * @param params - Transfer parameters
22281
+ * @returns Array of available backends with scores
22282
+ */
22283
+ async getAvailableBackends(params) {
22284
+ return this.registry.findAvailable(params);
22285
+ }
22286
+ /**
22287
+ * Score a backend based on configuration priority
22288
+ */
22289
+ scoreBackend(backend, availability, config) {
22290
+ const capabilities = backend.getCapabilities();
22291
+ let score = 0;
22292
+ const reasons = [];
22293
+ switch (config.prioritize) {
22294
+ case "privacy":
22295
+ if (capabilities.hiddenAmount) {
22296
+ score += PRIORITY_WEIGHTS.privacy.hiddenAmount;
22297
+ reasons.push("hidden amounts");
22298
+ }
22299
+ if (capabilities.hiddenSender) {
22300
+ score += PRIORITY_WEIGHTS.privacy.hiddenSender;
22301
+ reasons.push("hidden sender");
22302
+ }
22303
+ if (capabilities.hiddenRecipient) {
22304
+ score += PRIORITY_WEIGHTS.privacy.hiddenRecipient;
22305
+ reasons.push("hidden recipient");
22306
+ }
22307
+ if (capabilities.hiddenCompute) {
22308
+ score += PRIORITY_WEIGHTS.privacy.hiddenCompute;
22309
+ reasons.push("private compute");
22310
+ }
22311
+ if (capabilities.anonymitySet && capabilities.anonymitySet >= 100) {
22312
+ score += PRIORITY_WEIGHTS.privacy.anonymitySet;
22313
+ reasons.push(`anonymity set: ${capabilities.anonymitySet}`);
22314
+ }
22315
+ break;
22316
+ case "speed":
22317
+ score += PRIORITY_WEIGHTS.speed[capabilities.latencyEstimate];
22318
+ reasons.push(`${capabilities.latencyEstimate} latency`);
22319
+ if (capabilities.setupRequired) {
22320
+ score += PRIORITY_WEIGHTS.speed.setupRequired;
22321
+ reasons.push("setup required");
22322
+ }
22323
+ break;
22324
+ case "cost":
22325
+ if (availability.estimatedCost !== void 0) {
22326
+ const logCost = availability.estimatedCost > BigInt(0) ? Math.log10(Number(availability.estimatedCost)) : 0;
22327
+ const costScore = Math.max(0, 70 - logCost * 5);
22328
+ score += costScore;
22329
+ reasons.push(`low cost`);
22330
+ }
22331
+ break;
22332
+ case "compliance":
22333
+ if (capabilities.complianceSupport) {
22334
+ score += PRIORITY_WEIGHTS.compliance.complianceSupport;
22335
+ reasons.push("viewing key support");
22336
+ }
22337
+ if (capabilities.hiddenAmount) {
22338
+ score += PRIORITY_WEIGHTS.compliance.hiddenAmount;
22339
+ }
22340
+ if (capabilities.hiddenSender) {
22341
+ score += PRIORITY_WEIGHTS.compliance.hiddenSender;
22342
+ }
22343
+ if (capabilities.hiddenRecipient) {
22344
+ score += PRIORITY_WEIGHTS.compliance.hiddenRecipient;
22345
+ }
22346
+ break;
22347
+ }
22348
+ score = Math.min(100, Math.max(0, score));
22349
+ return {
22350
+ score,
22351
+ reason: reasons.length > 0 ? reasons.join(", ") : "default selection"
22352
+ };
22353
+ }
22354
+ };
22355
+
22356
+ // src/surveillance/algorithms/address-reuse.ts
22357
+ var MAX_DEDUCTION = 25;
22358
+ var DEDUCTION_PER_REUSE = 2;
22359
+ var REUSE_THRESHOLD = 1;
22360
+ function analyzeAddressReuse(transactions, walletAddress) {
22361
+ const receiveAddresses = /* @__PURE__ */ new Map();
22362
+ const sendAddresses = /* @__PURE__ */ new Map();
22363
+ for (const tx of transactions) {
22364
+ if (!tx.success) continue;
22365
+ if (tx.recipient === walletAddress) {
22366
+ const count = receiveAddresses.get(walletAddress) ?? 0;
22367
+ receiveAddresses.set(walletAddress, count + 1);
22368
+ }
22369
+ if (tx.sender === walletAddress) {
22370
+ const count = sendAddresses.get(walletAddress) ?? 0;
22371
+ sendAddresses.set(walletAddress, count + 1);
22372
+ }
22373
+ for (const addr of tx.involvedAddresses) {
22374
+ if (addr === walletAddress) continue;
22375
+ if (tx.sender === walletAddress) {
22376
+ const count = sendAddresses.get(addr) ?? 0;
22377
+ sendAddresses.set(addr, count + 1);
22378
+ }
22379
+ if (tx.recipient === walletAddress) {
22380
+ const count = receiveAddresses.get(addr) ?? 0;
22381
+ receiveAddresses.set(addr, count + 1);
22382
+ }
22383
+ }
22384
+ }
22385
+ let receiveReuseCount = 0;
22386
+ let sendReuseCount = 0;
22387
+ const reusedAddresses = [];
22388
+ for (const [address, count] of Array.from(receiveAddresses.entries())) {
22389
+ if (count > REUSE_THRESHOLD) {
22390
+ const reuseCount = count - REUSE_THRESHOLD;
22391
+ receiveReuseCount += reuseCount;
22392
+ const existing = reusedAddresses.find((r) => r.address === address);
22393
+ if (existing) {
22394
+ existing.useCount = Math.max(existing.useCount, count);
22395
+ existing.type = "both";
22396
+ } else {
22397
+ reusedAddresses.push({
22398
+ address,
22399
+ useCount: count,
22400
+ type: "receive"
22401
+ });
22402
+ }
22403
+ }
22404
+ }
22405
+ for (const [address, count] of Array.from(sendAddresses.entries())) {
22406
+ if (count > REUSE_THRESHOLD) {
22407
+ const reuseCount = count - REUSE_THRESHOLD;
22408
+ sendReuseCount += reuseCount;
22409
+ const existing = reusedAddresses.find((r) => r.address === address);
22410
+ if (existing) {
22411
+ existing.useCount = Math.max(existing.useCount, count);
22412
+ existing.type = "both";
22413
+ } else {
22414
+ reusedAddresses.push({
22415
+ address,
22416
+ useCount: count,
22417
+ type: "send"
22418
+ });
22419
+ }
22420
+ }
22421
+ }
22422
+ const totalReuseCount = receiveReuseCount + sendReuseCount;
22423
+ const rawDeduction = totalReuseCount * DEDUCTION_PER_REUSE;
22424
+ const scoreDeduction = Math.min(rawDeduction, MAX_DEDUCTION);
22425
+ reusedAddresses.sort((a, b) => b.useCount - a.useCount);
22426
+ return {
22427
+ receiveReuseCount,
22428
+ sendReuseCount,
22429
+ totalReuseCount,
22430
+ scoreDeduction,
22431
+ reusedAddresses: reusedAddresses.slice(0, 10)
22432
+ // Top 10 most reused
22433
+ };
22434
+ }
22435
+
22436
+ // src/surveillance/algorithms/cluster.ts
22437
+ var MAX_DEDUCTION2 = 25;
22438
+ var DEDUCTION_PER_LINK = 3;
22439
+ var MIN_LINK_THRESHOLD = 2;
22440
+ var UnionFind = class {
22441
+ parent;
22442
+ rank;
22443
+ constructor() {
22444
+ this.parent = /* @__PURE__ */ new Map();
22445
+ this.rank = /* @__PURE__ */ new Map();
22446
+ }
22447
+ find(x) {
22448
+ if (!this.parent.has(x)) {
22449
+ this.parent.set(x, x);
22450
+ this.rank.set(x, 0);
22451
+ }
22452
+ if (this.parent.get(x) !== x) {
22453
+ this.parent.set(x, this.find(this.parent.get(x)));
22454
+ }
22455
+ return this.parent.get(x);
22456
+ }
22457
+ union(x, y) {
22458
+ const rootX = this.find(x);
22459
+ const rootY = this.find(y);
22460
+ if (rootX === rootY) return;
22461
+ const rankX = this.rank.get(rootX) ?? 0;
22462
+ const rankY = this.rank.get(rootY) ?? 0;
22463
+ if (rankX < rankY) {
22464
+ this.parent.set(rootX, rootY);
22465
+ } else if (rankX > rankY) {
22466
+ this.parent.set(rootY, rootX);
22467
+ } else {
22468
+ this.parent.set(rootY, rootX);
22469
+ this.rank.set(rootX, rankX + 1);
22470
+ }
22471
+ }
22472
+ getClusters() {
22473
+ const clusters = /* @__PURE__ */ new Map();
22474
+ for (const addr of Array.from(this.parent.keys())) {
22475
+ const root = this.find(addr);
22476
+ if (!clusters.has(root)) {
22477
+ clusters.set(root, []);
22478
+ }
22479
+ clusters.get(root).push(addr);
22480
+ }
22481
+ return clusters;
22482
+ }
22483
+ };
22484
+ function detectClusters(transactions, walletAddress) {
22485
+ const uf = new UnionFind();
22486
+ const linkCounts = /* @__PURE__ */ new Map();
22487
+ const linkTypes = /* @__PURE__ */ new Map();
22488
+ const txCountPerPair = /* @__PURE__ */ new Map();
22489
+ uf.find(walletAddress);
22490
+ for (const tx of transactions) {
22491
+ if (!tx.success) continue;
22492
+ const involvedWithWallet = tx.involvedAddresses.filter(
22493
+ (addr) => addr !== walletAddress
22494
+ );
22495
+ if (tx.sender === walletAddress && involvedWithWallet.length > 0) {
22496
+ for (const addr of involvedWithWallet) {
22497
+ const pairKey = [walletAddress, addr].sort().join(":");
22498
+ const count = (txCountPerPair.get(pairKey) ?? 0) + 1;
22499
+ txCountPerPair.set(pairKey, count);
22500
+ if (count >= MIN_LINK_THRESHOLD) {
22501
+ uf.union(walletAddress, addr);
22502
+ linkCounts.set(addr, count);
22503
+ linkTypes.set(addr, "common-input");
22504
+ }
22505
+ }
22506
+ }
22507
+ if (tx.sender === walletAddress && tx.recipient !== walletAddress) {
22508
+ const otherRecipients = involvedWithWallet.filter(
22509
+ (addr) => addr !== tx.recipient
22510
+ );
22511
+ for (const addr of otherRecipients) {
22512
+ const pairKey = [walletAddress, addr].sort().join(":");
22513
+ const count = (txCountPerPair.get(pairKey) ?? 0) + 1;
22514
+ txCountPerPair.set(pairKey, count);
22515
+ if (count >= MIN_LINK_THRESHOLD) {
22516
+ uf.union(walletAddress, addr);
22517
+ if (!linkTypes.has(addr)) {
22518
+ linkTypes.set(addr, "change-address");
22519
+ }
22520
+ linkCounts.set(addr, count);
22521
+ }
22522
+ }
22523
+ }
22524
+ if (tx.recipient === walletAddress && involvedWithWallet.length > 1) {
22525
+ for (let i = 0; i < involvedWithWallet.length; i++) {
22526
+ for (let j = i + 1; j < involvedWithWallet.length; j++) {
22527
+ const addr1 = involvedWithWallet[i];
22528
+ const addr2 = involvedWithWallet[j];
22529
+ const pairKey2 = [addr1, addr2].sort().join(":");
22530
+ const count2 = (txCountPerPair.get(pairKey2) ?? 0) + 1;
22531
+ txCountPerPair.set(pairKey2, count2);
22532
+ if (count2 >= MIN_LINK_THRESHOLD) {
22533
+ uf.union(addr1, addr2);
22534
+ linkTypes.set(addr1, "consolidation");
22535
+ linkTypes.set(addr2, "consolidation");
22536
+ }
22537
+ }
22538
+ const pairKey = [walletAddress, involvedWithWallet[i]].sort().join(":");
22539
+ const count = (txCountPerPair.get(pairKey) ?? 0) + 1;
22540
+ txCountPerPair.set(pairKey, count);
22541
+ if (count >= MIN_LINK_THRESHOLD) {
22542
+ uf.union(walletAddress, involvedWithWallet[i]);
22543
+ linkCounts.set(involvedWithWallet[i], count);
22544
+ }
22545
+ }
22546
+ }
22547
+ }
22548
+ const allClusters = uf.getClusters();
22549
+ const walletRoot = uf.find(walletAddress);
22550
+ const walletCluster = allClusters.get(walletRoot) ?? [walletAddress];
22551
+ const linkedAddresses = walletCluster.filter((addr) => addr !== walletAddress);
22552
+ const linkedAddressCount = linkedAddresses.length;
22553
+ const totalLinkTxs = Array.from(linkCounts.values()).reduce((a, b) => a + b, 0);
22554
+ const confidence = Math.min(totalLinkTxs / (linkedAddressCount * 5), 1);
22555
+ const rawDeduction = linkedAddressCount * DEDUCTION_PER_LINK;
22556
+ const scoreDeduction = Math.min(rawDeduction, MAX_DEDUCTION2);
22557
+ const clusters = [];
22558
+ if (linkedAddressCount > 0) {
22559
+ const byType = /* @__PURE__ */ new Map();
22560
+ for (const addr of linkedAddresses) {
22561
+ const type = linkTypes.get(addr) ?? "common-input";
22562
+ if (!byType.has(type)) {
22563
+ byType.set(type, []);
22564
+ }
22565
+ byType.get(type).push(addr);
22566
+ }
22567
+ for (const [type, addresses] of Array.from(byType.entries())) {
22568
+ const txCount = addresses.reduce(
22569
+ (sum, addr) => sum + (linkCounts.get(addr) ?? 0),
22570
+ 0
22571
+ );
22572
+ clusters.push({
22573
+ addresses: [walletAddress, ...addresses],
22574
+ linkType: type,
22575
+ transactionCount: txCount
22576
+ });
22577
+ }
22578
+ }
22579
+ return {
22580
+ linkedAddressCount,
22581
+ confidence,
22582
+ scoreDeduction,
22583
+ clusters
22584
+ };
22585
+ }
22586
+
22587
+ // src/surveillance/algorithms/exchange.ts
22588
+ var MAX_DEDUCTION3 = 20;
22589
+ var DEDUCTION_PER_CEX = 8;
22590
+ var DEDUCTION_PER_DEX = 2;
22591
+ var KNOWN_EXCHANGES = [
22592
+ // Centralized Exchanges (KYC Required)
22593
+ {
22594
+ name: "Binance",
22595
+ addresses: [
22596
+ "5tzFkiKscXHK5ZXCGbXZxdw7gTjjD1mBwuoFbhUvuAi9",
22597
+ "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
22598
+ "AC5RDfQFmDS1deWZos921JfqscXdByf8BKHs5ACWjtW2"
22599
+ ],
22600
+ type: "cex",
22601
+ kycRequired: true
22602
+ },
22603
+ {
22604
+ name: "Coinbase",
22605
+ addresses: [
22606
+ "H8sMJSCQxfKiFTCfDR3DUMLPwcRbM61LGFJ8N4dK3WjS",
22607
+ "2ojv9BAiHUrvsm9gxDe7fJSzbNZSJcxZvf8dqmWGHG8S",
22608
+ "GJRs4FwHtemZ5ZE9x3FNvJ8TMwitKTh21yxdRPqn7npE"
22609
+ ],
22610
+ type: "cex",
22611
+ kycRequired: true
22612
+ },
22613
+ {
22614
+ name: "Kraken",
22615
+ addresses: [
22616
+ "krakenmRKej41L9sX8N8Z2mhjZ8UpVHHBMzkKzfBh54"
22617
+ ],
22618
+ type: "cex",
22619
+ kycRequired: true
22620
+ },
22621
+ {
22622
+ name: "FTX (Defunct)",
22623
+ addresses: [
22624
+ "FTXkd8cjuYGRLzPVdvqxNxNNNYBfFPPjrF3vW2Yq8p7"
22625
+ ],
22626
+ type: "cex",
22627
+ kycRequired: true
22628
+ },
22629
+ {
22630
+ name: "KuCoin",
22631
+ addresses: [
22632
+ "BmFdpraQhkiDQE6SnfG5omcA1VwzqfXrwtNYBwWTymy6"
22633
+ ],
22634
+ type: "cex",
22635
+ kycRequired: true
22636
+ },
22637
+ {
22638
+ name: "OKX",
22639
+ addresses: [
22640
+ "GGztQqQ6pCPaJQnNpXBgELr5cs3WwDakRbh1iEMzjgSJ"
22641
+ ],
22642
+ type: "cex",
22643
+ kycRequired: true
22644
+ },
22645
+ {
22646
+ name: "Bybit",
22647
+ addresses: [
22648
+ "AC5RDfQFmDS1deWZos921JfqscXdByf8BKHs5ACWjtW3"
22649
+ ],
22650
+ type: "cex",
22651
+ kycRequired: true
22652
+ },
22653
+ {
22654
+ name: "Gate.io",
22655
+ addresses: [
22656
+ "u6PJ8DtQuPFnfmwHbGFULQ4u4EgjDiyYKjVEsynXq2w"
22657
+ ],
22658
+ type: "cex",
22659
+ kycRequired: true
22660
+ },
22661
+ // Decentralized Exchanges (No KYC but traceable)
22662
+ {
22663
+ name: "Jupiter",
22664
+ addresses: [
22665
+ "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
22666
+ "JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB"
22667
+ ],
22668
+ type: "dex",
22669
+ kycRequired: false
22670
+ },
22671
+ {
22672
+ name: "Raydium",
22673
+ addresses: [
22674
+ "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8",
22675
+ "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1"
22676
+ ],
22677
+ type: "dex",
22678
+ kycRequired: false
22679
+ },
22680
+ {
22681
+ name: "Orca",
22682
+ addresses: [
22683
+ "9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP",
22684
+ "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc"
22685
+ ],
22686
+ type: "dex",
22687
+ kycRequired: false
22688
+ },
22689
+ {
22690
+ name: "Marinade",
22691
+ addresses: [
22692
+ "MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD"
22693
+ ],
22694
+ type: "dex",
22695
+ kycRequired: false
22696
+ },
22697
+ {
22698
+ name: "Phantom Swap",
22699
+ addresses: [
22700
+ "PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY"
22701
+ ],
22702
+ type: "dex",
22703
+ kycRequired: false
22704
+ }
22705
+ ];
22706
+ function buildExchangeLookup(exchanges) {
22707
+ const lookup = /* @__PURE__ */ new Map();
22708
+ for (const exchange of exchanges) {
22709
+ for (const address of exchange.addresses) {
22710
+ lookup.set(address, exchange);
22711
+ }
22712
+ }
22713
+ return lookup;
22714
+ }
22715
+ function detectExchangeExposure(transactions, walletAddress, customExchanges) {
22716
+ const exchanges = customExchanges ? [...KNOWN_EXCHANGES, ...customExchanges] : KNOWN_EXCHANGES;
22717
+ const lookup = buildExchangeLookup(exchanges);
22718
+ const exchangeStats = /* @__PURE__ */ new Map();
22719
+ for (const tx of transactions) {
22720
+ if (!tx.success) continue;
22721
+ for (const addr of tx.involvedAddresses) {
22722
+ const exchange = lookup.get(addr);
22723
+ if (!exchange) continue;
22724
+ if (!exchangeStats.has(exchange.name)) {
22725
+ exchangeStats.set(exchange.name, {
22726
+ exchange,
22727
+ deposits: 0,
22728
+ withdrawals: 0,
22729
+ firstInteraction: tx.timestamp,
22730
+ lastInteraction: tx.timestamp
22731
+ });
22732
+ }
22733
+ const stats = exchangeStats.get(exchange.name);
22734
+ stats.firstInteraction = Math.min(stats.firstInteraction, tx.timestamp);
22735
+ stats.lastInteraction = Math.max(stats.lastInteraction, tx.timestamp);
22736
+ if (tx.sender === walletAddress && tx.recipient === addr) {
22737
+ stats.deposits++;
22738
+ } else if (tx.sender === addr && tx.recipient === walletAddress) {
22739
+ stats.withdrawals++;
22740
+ } else if (tx.sender === walletAddress) {
22741
+ stats.deposits++;
22742
+ }
22743
+ }
22744
+ }
22745
+ let totalDeposits = 0;
22746
+ let totalWithdrawals = 0;
22747
+ let cexCount = 0;
22748
+ let dexCount = 0;
22749
+ const exchangeResults = [];
22750
+ for (const [name, stats] of Array.from(exchangeStats.entries())) {
22751
+ totalDeposits += stats.deposits;
22752
+ totalWithdrawals += stats.withdrawals;
22753
+ if (stats.exchange.type === "cex") {
22754
+ cexCount++;
22755
+ } else {
22756
+ dexCount++;
22757
+ }
22758
+ exchangeResults.push({
22759
+ name,
22760
+ type: stats.exchange.type,
22761
+ kycRequired: stats.exchange.kycRequired,
22762
+ deposits: stats.deposits,
22763
+ withdrawals: stats.withdrawals,
22764
+ firstInteraction: stats.firstInteraction,
22765
+ lastInteraction: stats.lastInteraction
22766
+ });
22767
+ }
22768
+ exchangeResults.sort(
22769
+ (a, b) => b.deposits + b.withdrawals - (a.deposits + a.withdrawals)
22770
+ );
22771
+ const cexDeduction = cexCount * DEDUCTION_PER_CEX;
22772
+ const dexDeduction = dexCount * DEDUCTION_PER_DEX;
22773
+ const rawDeduction = cexDeduction + dexDeduction;
22774
+ const scoreDeduction = Math.min(rawDeduction, MAX_DEDUCTION3);
22775
+ return {
22776
+ exchangeCount: exchangeStats.size,
22777
+ depositCount: totalDeposits,
22778
+ withdrawalCount: totalWithdrawals,
22779
+ scoreDeduction,
22780
+ exchanges: exchangeResults
22781
+ };
22782
+ }
22783
+
22784
+ // src/surveillance/algorithms/temporal.ts
22785
+ var MAX_DEDUCTION4 = 15;
22786
+ var DEDUCTION_PER_PATTERN = 5;
22787
+ var MIN_TRANSACTIONS_FOR_PATTERN = 5;
22788
+ var DAY_REGULARITY_THRESHOLD = 0.3;
22789
+ var HOUR_REGULARITY_THRESHOLD = 0.25;
22790
+ var TIMEZONES = {
22791
+ "UTC-12": -12,
22792
+ "UTC-11": -11,
22793
+ "HST": -10,
22794
+ "AKST": -9,
22795
+ "PST": -8,
22796
+ "MST": -7,
22797
+ "CST": -6,
22798
+ "EST": -5,
22799
+ "AST": -4,
22800
+ "BRT": -3,
22801
+ "UTC-2": -2,
22802
+ "UTC-1": -1,
22803
+ "UTC": 0,
22804
+ "CET": 1,
22805
+ "EET": 2,
22806
+ "MSK": 3,
22807
+ "GST": 4,
22808
+ "PKT": 5,
22809
+ "BST": 6,
22810
+ "ICT": 7,
22811
+ "CST_ASIA": 8,
22812
+ "JST": 9,
22813
+ "AEST": 10,
22814
+ "AEDT": 11,
22815
+ "NZST": 12
22816
+ };
22817
+ function analyzeTemporalPatterns(transactions) {
22818
+ const patterns = [];
22819
+ if (transactions.length < MIN_TRANSACTIONS_FOR_PATTERN) {
22820
+ return {
22821
+ patterns: [],
22822
+ scoreDeduction: 0
22823
+ };
22824
+ }
22825
+ const txTimes = transactions.filter((tx) => tx.success && tx.timestamp > 0).map((tx) => new Date(tx.timestamp * 1e3));
22826
+ if (txTimes.length < MIN_TRANSACTIONS_FOR_PATTERN) {
22827
+ return {
22828
+ patterns: [],
22829
+ scoreDeduction: 0
22830
+ };
22831
+ }
22832
+ const dayOfWeekPattern = analyzeDayOfWeekPattern(txTimes);
22833
+ if (dayOfWeekPattern) {
22834
+ patterns.push(dayOfWeekPattern);
22835
+ }
22836
+ const hourPattern = analyzeHourPattern(txTimes);
22837
+ if (hourPattern) {
22838
+ patterns.push(hourPattern);
22839
+ }
22840
+ const inferredTimezone = inferTimezone(txTimes);
22841
+ const burstPattern = detectActivityBursts(transactions);
22842
+ if (burstPattern) {
22843
+ patterns.push(burstPattern);
22844
+ }
22845
+ const rawDeduction = patterns.length * DEDUCTION_PER_PATTERN;
22846
+ const scoreDeduction = Math.min(rawDeduction, MAX_DEDUCTION4);
22847
+ return {
22848
+ patterns,
22849
+ inferredTimezone,
22850
+ scoreDeduction
22851
+ };
22852
+ }
22853
+ function analyzeDayOfWeekPattern(times) {
22854
+ const dayCount = new Array(7).fill(0);
22855
+ for (const time of times) {
22856
+ dayCount[time.getUTCDay()]++;
22857
+ }
22858
+ const total = times.length;
22859
+ const dominantDays = [];
22860
+ for (let day = 0; day < 7; day++) {
22861
+ const percentage = dayCount[day] / total;
22862
+ if (percentage >= DAY_REGULARITY_THRESHOLD) {
22863
+ dominantDays.push(day);
22864
+ }
22865
+ }
22866
+ if (dominantDays.length === 0 || dominantDays.length > 3) {
22867
+ return null;
22868
+ }
22869
+ const dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
22870
+ const dominantDayNames = dominantDays.map((d) => dayNames[d]).join(", ");
22871
+ return {
22872
+ type: "regular-schedule",
22873
+ description: `Most transactions occur on ${dominantDayNames}`,
22874
+ confidence: Math.max(...dominantDays.map((d) => dayCount[d] / total)),
22875
+ evidence: {
22876
+ dayOfWeek: dominantDays
22877
+ }
22878
+ };
22879
+ }
22880
+ function analyzeHourPattern(times) {
22881
+ const hourCount = new Array(24).fill(0);
22882
+ for (const time of times) {
22883
+ hourCount[time.getUTCHours()]++;
22884
+ }
22885
+ const total = times.length;
22886
+ const activeHours = [];
22887
+ for (let hour = 0; hour < 24; hour++) {
22888
+ const windowCount = hourCount[hour] + hourCount[(hour + 1) % 24] + hourCount[(hour + 2) % 24];
22889
+ const windowPercentage = windowCount / total;
22890
+ if (windowPercentage >= HOUR_REGULARITY_THRESHOLD) {
22891
+ if (!activeHours.includes(hour)) {
22892
+ activeHours.push(hour);
22893
+ }
22894
+ }
22895
+ }
22896
+ if (activeHours.length === 0 || activeHours.length > 8) {
22897
+ return null;
22898
+ }
22899
+ const activeHourRange = Math.max(...activeHours) - Math.min(...activeHours);
22900
+ if (activeHourRange <= 6) {
22901
+ const startHour = Math.min(...activeHours);
22902
+ const endHour = Math.max(...activeHours) + 2;
22903
+ return {
22904
+ type: "timezone-inference",
22905
+ description: `Activity concentrated between ${startHour}:00-${endHour}:00 UTC`,
22906
+ confidence: 0.7,
22907
+ evidence: {
22908
+ hourOfDay: activeHours
22909
+ }
22910
+ };
22911
+ }
22912
+ return null;
22913
+ }
22914
+ function inferTimezone(times) {
22915
+ const hourCount = new Array(24).fill(0);
22916
+ for (const time of times) {
22917
+ hourCount[time.getUTCHours()]++;
22918
+ }
22919
+ let maxActivity = 0;
22920
+ let bestStartHour = 0;
22921
+ for (let start = 0; start < 24; start++) {
22922
+ let windowActivity = 0;
22923
+ for (let i = 0; i < 8; i++) {
22924
+ windowActivity += hourCount[(start + i) % 24];
22925
+ }
22926
+ if (windowActivity > maxActivity) {
22927
+ maxActivity = windowActivity;
22928
+ bestStartHour = start;
22929
+ }
22930
+ }
22931
+ const totalActivity = times.length;
22932
+ if (maxActivity / totalActivity < 0.6) {
22933
+ return void 0;
22934
+ }
22935
+ const assumedLocalNoon = 12;
22936
+ const peakMidpoint = (bestStartHour + 4) % 24;
22937
+ const inferredOffset = (assumedLocalNoon - peakMidpoint + 24) % 24;
22938
+ const normalizedOffset = inferredOffset > 12 ? inferredOffset - 24 : inferredOffset;
22939
+ for (const [name, offset] of Object.entries(TIMEZONES)) {
22940
+ if (Math.abs(offset - normalizedOffset) <= 1) {
22941
+ return name;
22942
+ }
22943
+ }
22944
+ return `UTC${normalizedOffset >= 0 ? "+" : ""}${normalizedOffset}`;
22945
+ }
22946
+ function detectActivityBursts(transactions) {
22947
+ if (transactions.length < 10) {
22948
+ return null;
22949
+ }
22950
+ const sorted = [...transactions].filter((tx) => tx.timestamp > 0).sort((a, b) => a.timestamp - b.timestamp);
22951
+ const gaps = [];
22952
+ for (let i = 1; i < sorted.length; i++) {
22953
+ gaps.push(sorted[i].timestamp - sorted[i - 1].timestamp);
22954
+ }
22955
+ const avgGap = gaps.reduce((a, b) => a + b, 0) / gaps.length;
22956
+ const burstThreshold = avgGap * 0.1;
22957
+ let burstCount = 0;
22958
+ for (const gap of gaps) {
22959
+ if (gap < burstThreshold && gap < 3600) {
22960
+ burstCount++;
22961
+ }
22962
+ }
22963
+ const burstPercentage = burstCount / gaps.length;
22964
+ if (burstPercentage > 0.2) {
22965
+ return {
22966
+ type: "activity-burst",
22967
+ description: `${Math.round(burstPercentage * 100)}% of transactions occur in rapid succession`,
22968
+ confidence: burstPercentage,
22969
+ evidence: {
22970
+ frequency: `${burstCount} bursts detected`
22971
+ }
22972
+ };
22973
+ }
22974
+ return null;
22975
+ }
22976
+
22977
+ // src/surveillance/scoring.ts
22978
+ var MAX_POINTS = {
22979
+ addressReuse: 25,
22980
+ clusterExposure: 25,
22981
+ exchangeExposure: 20,
22982
+ temporalPatterns: 15,
22983
+ socialLinks: 15
22984
+ };
22985
+ var TOTAL_MAX_SCORE = Object.values(MAX_POINTS).reduce((a, b) => a + b, 0);
22986
+ var RISK_THRESHOLDS = {
22987
+ critical: 30,
22988
+ high: 50,
22989
+ medium: 70,
22990
+ low: 100
22991
+ };
22992
+ function calculatePrivacyScore(addressReuse, cluster, exchangeExposure, temporalPatterns, socialLinks, walletAddress) {
22993
+ const breakdown = {
22994
+ addressReuse: MAX_POINTS.addressReuse - addressReuse.scoreDeduction,
22995
+ clusterExposure: MAX_POINTS.clusterExposure - cluster.scoreDeduction,
22996
+ exchangeExposure: MAX_POINTS.exchangeExposure - exchangeExposure.scoreDeduction,
22997
+ temporalPatterns: MAX_POINTS.temporalPatterns - temporalPatterns.scoreDeduction,
22998
+ socialLinks: MAX_POINTS.socialLinks - socialLinks.scoreDeduction
22999
+ };
23000
+ const totalScore = breakdown.addressReuse + breakdown.clusterExposure + breakdown.exchangeExposure + breakdown.temporalPatterns + breakdown.socialLinks;
23001
+ const overall = Math.round(totalScore / TOTAL_MAX_SCORE * 100);
23002
+ let risk = "low";
23003
+ if (overall < RISK_THRESHOLDS.critical) {
23004
+ risk = "critical";
23005
+ } else if (overall < RISK_THRESHOLDS.high) {
23006
+ risk = "high";
23007
+ } else if (overall < RISK_THRESHOLDS.medium) {
23008
+ risk = "medium";
23009
+ }
23010
+ const recommendations = generateRecommendations(
23011
+ addressReuse,
23012
+ cluster,
23013
+ exchangeExposure,
23014
+ temporalPatterns,
23015
+ socialLinks
23016
+ );
23017
+ return {
23018
+ overall,
23019
+ breakdown,
23020
+ risk,
23021
+ recommendations,
23022
+ analyzedAt: Date.now(),
23023
+ walletAddress
23024
+ };
23025
+ }
23026
+ function generateRecommendations(addressReuse, cluster, exchangeExposure, temporalPatterns, socialLinks) {
23027
+ const recommendations = [];
23028
+ if (addressReuse.scoreDeduction > 0) {
23029
+ const severity = getSeverity(addressReuse.scoreDeduction, MAX_POINTS.addressReuse);
23030
+ recommendations.push({
23031
+ id: "address-reuse-001",
23032
+ severity,
23033
+ category: "addressReuse",
23034
+ title: `Address reused ${addressReuse.totalReuseCount} times`,
23035
+ description: "Reusing the same address for multiple transactions creates linkability between your transactions, allowing observers to track your activity.",
23036
+ action: "Use SIP stealth addresses for each transaction. Each payment uses a unique one-time address that cannot be linked to your main address.",
23037
+ potentialGain: addressReuse.scoreDeduction
23038
+ });
23039
+ }
23040
+ if (cluster.scoreDeduction > 0) {
23041
+ const severity = getSeverity(cluster.scoreDeduction, MAX_POINTS.clusterExposure);
23042
+ recommendations.push({
23043
+ id: "cluster-001",
23044
+ severity,
23045
+ category: "clusterExposure",
23046
+ title: `${cluster.linkedAddressCount} addresses linked to your wallet`,
23047
+ description: "Transaction analysis has linked multiple addresses to your wallet through common input ownership patterns. This expands your privacy exposure.",
23048
+ action: "Use SIP for all transactions to prevent cluster analysis. Stealth addresses break the link between your spending and receiving addresses.",
23049
+ potentialGain: cluster.scoreDeduction
23050
+ });
23051
+ }
23052
+ if (exchangeExposure.scoreDeduction > 0) {
23053
+ const cexes = exchangeExposure.exchanges.filter((e) => e.kycRequired);
23054
+ const severity = getSeverity(exchangeExposure.scoreDeduction, MAX_POINTS.exchangeExposure);
23055
+ if (cexes.length > 0) {
23056
+ recommendations.push({
23057
+ id: "exchange-cex-001",
23058
+ severity,
23059
+ category: "exchangeExposure",
23060
+ title: `Interacted with ${cexes.length} KYC exchange(s)`,
23061
+ description: `Deposits to ${cexes.map((e) => e.name).join(", ")} link your on-chain activity to your verified identity. This is one of the biggest privacy risks.`,
23062
+ action: "Use SIP viewing keys for selective disclosure. You can prove compliance to exchanges without exposing your full transaction history.",
23063
+ potentialGain: Math.min(cexes.length * 8, MAX_POINTS.exchangeExposure)
23064
+ });
23065
+ }
23066
+ const dexes = exchangeExposure.exchanges.filter((e) => !e.kycRequired);
23067
+ if (dexes.length > 0) {
23068
+ recommendations.push({
23069
+ id: "exchange-dex-001",
23070
+ severity: "low",
23071
+ category: "exchangeExposure",
23072
+ title: `Used ${dexes.length} DEX(es) without privacy`,
23073
+ description: "DEX swaps are public and can be traced. While no KYC is required, your swap patterns can reveal trading strategies.",
23074
+ action: "Use SIP for private swaps. Amounts and swap details are hidden while still using your preferred DEX.",
23075
+ potentialGain: Math.min(dexes.length * 2, 6)
23076
+ });
23077
+ }
23078
+ }
23079
+ if (temporalPatterns.scoreDeduction > 0) {
23080
+ const severity = getSeverity(temporalPatterns.scoreDeduction, MAX_POINTS.temporalPatterns);
23081
+ for (const pattern of temporalPatterns.patterns) {
23082
+ if (pattern.type === "regular-schedule") {
23083
+ recommendations.push({
23084
+ id: "temporal-schedule-001",
23085
+ severity,
23086
+ category: "temporalPatterns",
23087
+ title: "Regular transaction schedule detected",
23088
+ description: `${pattern.description}. Predictable patterns make your activity easier to track and attribute.`,
23089
+ action: "Vary your transaction timing. Consider using scheduled private transactions through SIP to obscure timing patterns.",
23090
+ potentialGain: 5
23091
+ });
23092
+ }
23093
+ if (pattern.type === "timezone-inference") {
23094
+ recommendations.push({
23095
+ id: "temporal-timezone-001",
23096
+ severity: "medium",
23097
+ category: "temporalPatterns",
23098
+ title: "Timezone can be inferred from activity",
23099
+ description: `${pattern.description}. This narrows down your geographic location based on when you transact.`,
23100
+ action: "Use time-delayed transactions or vary your active hours. SIP can queue transactions for random future execution.",
23101
+ potentialGain: 5
23102
+ });
23103
+ }
23104
+ }
23105
+ }
23106
+ if (socialLinks.scoreDeduction > 0) {
23107
+ const severity = getSeverity(socialLinks.scoreDeduction, MAX_POINTS.socialLinks);
23108
+ if (socialLinks.isDoxxed) {
23109
+ recommendations.push({
23110
+ id: "social-doxxed-001",
23111
+ severity: "critical",
23112
+ category: "socialLinks",
23113
+ title: "Wallet publicly linked to your identity",
23114
+ description: "Your wallet address is publicly associated with your real identity through ENS/SNS names or social profiles. All transactions are attributable to you.",
23115
+ action: "Use a fresh wallet with SIP for private transactions. Your viewing keys let you prove ownership when needed without constant exposure.",
23116
+ potentialGain: 15
23117
+ });
23118
+ } else if (socialLinks.partialExposure) {
23119
+ recommendations.push({
23120
+ id: "social-partial-001",
23121
+ severity,
23122
+ category: "socialLinks",
23123
+ title: "Partial identity exposure detected",
23124
+ description: "Some identifying information is linked to your wallet, such as ENS names or labeled addresses on block explorers.",
23125
+ action: "Consider using a separate wallet for private activities. SIP stealth addresses prevent linking to your main identity.",
23126
+ potentialGain: socialLinks.scoreDeduction
23127
+ });
23128
+ }
23129
+ }
23130
+ recommendations.sort((a, b) => b.potentialGain - a.potentialGain);
23131
+ return recommendations;
23132
+ }
23133
+ function getSeverity(deduction, maxPoints) {
23134
+ const percentage = deduction / maxPoints;
23135
+ if (percentage >= 0.8) return "critical";
23136
+ if (percentage >= 0.5) return "high";
23137
+ if (percentage >= 0.25) return "medium";
23138
+ return "low";
23139
+ }
23140
+ function calculateSIPComparison(currentScore) {
23141
+ const improvements = [];
23142
+ const addressReuseImprovement = MAX_POINTS.addressReuse - currentScore.breakdown.addressReuse;
23143
+ if (addressReuseImprovement > 0) {
23144
+ improvements.push({
23145
+ category: "addressReuse",
23146
+ currentScore: currentScore.breakdown.addressReuse,
23147
+ projectedScore: MAX_POINTS.addressReuse,
23148
+ reason: "Stealth addresses prevent any address reuse"
23149
+ });
23150
+ }
23151
+ const clusterImprovement = MAX_POINTS.clusterExposure - currentScore.breakdown.clusterExposure;
23152
+ if (clusterImprovement > 0) {
23153
+ improvements.push({
23154
+ category: "clusterExposure",
23155
+ currentScore: currentScore.breakdown.clusterExposure,
23156
+ projectedScore: MAX_POINTS.clusterExposure,
23157
+ reason: "Stealth addresses cannot be linked via common input analysis"
23158
+ });
23159
+ }
23160
+ const exchangeImprovement = Math.min(
23161
+ (MAX_POINTS.exchangeExposure - currentScore.breakdown.exchangeExposure) * 0.5,
23162
+ 10
23163
+ );
23164
+ if (exchangeImprovement > 0) {
23165
+ improvements.push({
23166
+ category: "exchangeExposure",
23167
+ currentScore: currentScore.breakdown.exchangeExposure,
23168
+ projectedScore: currentScore.breakdown.exchangeExposure + Math.round(exchangeImprovement),
23169
+ reason: "Viewing keys allow selective disclosure without exposing full history"
23170
+ });
23171
+ }
23172
+ const temporalImprovement = Math.min(
23173
+ (MAX_POINTS.temporalPatterns - currentScore.breakdown.temporalPatterns) * 0.3,
23174
+ 5
23175
+ );
23176
+ if (temporalImprovement > 0) {
23177
+ improvements.push({
23178
+ category: "temporalPatterns",
23179
+ currentScore: currentScore.breakdown.temporalPatterns,
23180
+ projectedScore: currentScore.breakdown.temporalPatterns + Math.round(temporalImprovement),
23181
+ reason: "Private transactions reduce pattern correlation"
23182
+ });
23183
+ }
23184
+ const totalImprovement = improvements.reduce(
23185
+ (sum, imp) => sum + (imp.projectedScore - imp.currentScore),
23186
+ 0
23187
+ );
23188
+ const projectedTotal = currentScore.overall / 100 * TOTAL_MAX_SCORE + totalImprovement;
23189
+ const projectedScore = Math.min(Math.round(projectedTotal / TOTAL_MAX_SCORE * 100), 100);
23190
+ return {
23191
+ currentScore: currentScore.overall,
23192
+ projectedScore,
23193
+ improvement: projectedScore - currentScore.overall,
23194
+ improvements
23195
+ };
23196
+ }
23197
+
23198
+ // src/surveillance/analyzer.ts
23199
+ var SurveillanceAnalyzer = class _SurveillanceAnalyzer {
23200
+ config;
23201
+ heliusUrl;
23202
+ constructor(config) {
23203
+ if (!config.heliusApiKey) {
23204
+ throw new Error(
23205
+ "Helius API key is required. Get one at https://dev.helius.xyz"
23206
+ );
23207
+ }
23208
+ this.config = {
23209
+ heliusApiKey: config.heliusApiKey,
23210
+ cluster: config.cluster ?? "mainnet-beta",
23211
+ maxTransactions: config.maxTransactions ?? 1e3,
23212
+ includeSocialLinks: config.includeSocialLinks ?? false,
23213
+ customExchangeAddresses: config.customExchangeAddresses ?? []
23214
+ };
23215
+ this.heliusUrl = this.config.cluster === "devnet" ? `https://api-devnet.helius.xyz/v0` : `https://api.helius.xyz/v0`;
23216
+ }
23217
+ /**
23218
+ * Perform full privacy analysis on a wallet
23219
+ *
23220
+ * @param walletAddress - Solana wallet address to analyze
23221
+ * @returns Complete analysis result with all details
23222
+ */
23223
+ async analyze(walletAddress) {
23224
+ const startTime = Date.now();
23225
+ const transactions = await this.fetchTransactionHistory(walletAddress);
23226
+ const addressReuse = analyzeAddressReuse(transactions, walletAddress);
23227
+ const cluster = detectClusters(transactions, walletAddress);
23228
+ const exchangeExposure = detectExchangeExposure(
23229
+ transactions,
23230
+ walletAddress,
23231
+ this.config.customExchangeAddresses
23232
+ );
23233
+ const temporalPatterns = analyzeTemporalPatterns(transactions);
23234
+ const socialLinks = await this.analyzeSocialLinks(walletAddress);
23235
+ const privacyScore = calculatePrivacyScore(
23236
+ addressReuse,
23237
+ cluster,
23238
+ exchangeExposure,
23239
+ temporalPatterns,
23240
+ socialLinks,
23241
+ walletAddress
23242
+ );
23243
+ const sipComparison = calculateSIPComparison(privacyScore);
23244
+ const analysisDurationMs = Date.now() - startTime;
23245
+ return {
23246
+ privacyScore,
23247
+ addressReuse,
23248
+ cluster,
23249
+ exchangeExposure,
23250
+ temporalPatterns,
23251
+ socialLinks,
23252
+ sipComparison,
23253
+ transactionCount: transactions.length,
23254
+ analysisDurationMs
23255
+ };
23256
+ }
23257
+ /**
23258
+ * Fetch transaction history using Helius Enhanced Transactions API
23259
+ */
23260
+ async fetchTransactionHistory(walletAddress) {
23261
+ const transactions = [];
23262
+ let beforeSignature;
23263
+ let hasMore = true;
23264
+ while (hasMore && transactions.length < this.config.maxTransactions) {
23265
+ const url = new URL(`${this.heliusUrl}/addresses/${walletAddress}/transactions`);
23266
+ url.searchParams.set("api-key", this.config.heliusApiKey);
23267
+ url.searchParams.set("limit", "100");
23268
+ if (beforeSignature) {
23269
+ url.searchParams.set("before", beforeSignature);
23270
+ }
23271
+ const controller = new AbortController();
23272
+ const timeoutId = setTimeout(() => controller.abort(), 3e4);
23273
+ let response;
23274
+ try {
23275
+ response = await fetch(url.toString(), {
23276
+ signal: controller.signal
23277
+ });
23278
+ } catch (error) {
23279
+ clearTimeout(timeoutId);
23280
+ if (error instanceof Error && error.name === "AbortError") {
23281
+ throw new Error("Helius API request timed out after 30 seconds");
23282
+ }
23283
+ throw error;
23284
+ }
23285
+ clearTimeout(timeoutId);
23286
+ if (!response.ok) {
23287
+ throw new Error(
23288
+ `Helius API error: ${response.status} ${response.statusText}`
23289
+ );
23290
+ }
23291
+ const data = await response.json();
23292
+ if (data.length === 0) {
23293
+ hasMore = false;
23294
+ break;
23295
+ }
23296
+ for (const tx of data) {
23297
+ const analyzable = this.parseTransaction(tx, walletAddress);
23298
+ if (analyzable) {
23299
+ transactions.push(analyzable);
23300
+ }
23301
+ }
23302
+ beforeSignature = data[data.length - 1]?.signature;
23303
+ hasMore = data.length === 100;
23304
+ await new Promise((resolve) => setTimeout(resolve, 100));
23305
+ }
23306
+ return transactions;
23307
+ }
23308
+ /**
23309
+ * Parse Helius transaction into analyzable format
23310
+ */
23311
+ parseTransaction(tx, walletAddress) {
23312
+ const involvedAddresses = /* @__PURE__ */ new Set();
23313
+ if (tx.feePayer) {
23314
+ involvedAddresses.add(tx.feePayer);
23315
+ }
23316
+ let sender = null;
23317
+ let recipient = null;
23318
+ let amount = BigInt(0);
23319
+ if (tx.nativeTransfers && tx.nativeTransfers.length > 0) {
23320
+ for (const transfer of tx.nativeTransfers) {
23321
+ involvedAddresses.add(transfer.fromUserAccount);
23322
+ involvedAddresses.add(transfer.toUserAccount);
23323
+ if (transfer.fromUserAccount === walletAddress) {
23324
+ sender = walletAddress;
23325
+ recipient = transfer.toUserAccount;
23326
+ amount = BigInt(transfer.amount);
23327
+ } else if (transfer.toUserAccount === walletAddress) {
23328
+ sender = transfer.fromUserAccount;
23329
+ recipient = walletAddress;
23330
+ amount = BigInt(transfer.amount);
23331
+ }
23332
+ }
23333
+ }
23334
+ let mint = null;
23335
+ if (tx.tokenTransfers && tx.tokenTransfers.length > 0) {
23336
+ for (const transfer of tx.tokenTransfers) {
23337
+ if (transfer.fromUserAccount) {
23338
+ involvedAddresses.add(transfer.fromUserAccount);
23339
+ }
23340
+ if (transfer.toUserAccount) {
23341
+ involvedAddresses.add(transfer.toUserAccount);
23342
+ }
23343
+ if (transfer.fromUserAccount === walletAddress) {
23344
+ sender = walletAddress;
23345
+ recipient = transfer.toUserAccount;
23346
+ amount = BigInt(Math.floor(transfer.tokenAmount));
23347
+ mint = transfer.mint;
23348
+ } else if (transfer.toUserAccount === walletAddress) {
23349
+ sender = transfer.fromUserAccount;
23350
+ recipient = walletAddress;
23351
+ amount = BigInt(Math.floor(transfer.tokenAmount));
23352
+ mint = transfer.mint;
23353
+ }
23354
+ }
23355
+ }
23356
+ if (tx.accountData) {
23357
+ for (const account of tx.accountData) {
23358
+ involvedAddresses.add(account.account);
23359
+ }
23360
+ }
23361
+ let type = "other";
23362
+ if (tx.type === "SWAP" || tx.events?.swap) {
23363
+ type = "swap";
23364
+ } else if (tx.type === "TRANSFER" || tx.nativeTransfers?.length || tx.tokenTransfers?.length) {
23365
+ type = "transfer";
23366
+ } else if (tx.type?.includes("STAKE")) {
23367
+ type = "stake";
23368
+ }
23369
+ return {
23370
+ signature: tx.signature,
23371
+ slot: tx.slot,
23372
+ timestamp: tx.timestamp,
23373
+ sender,
23374
+ recipient,
23375
+ amount,
23376
+ mint,
23377
+ fee: BigInt(tx.fee || 0),
23378
+ involvedAddresses: Array.from(involvedAddresses),
23379
+ type,
23380
+ success: true
23381
+ // Helius only returns successful transactions
23382
+ };
23383
+ }
23384
+ /**
23385
+ * Analyze social links (placeholder for external API integration)
23386
+ *
23387
+ * In production, this would query:
23388
+ * - SNS (Solana Name Service)
23389
+ * - Arkham Intelligence
23390
+ * - 0xppl API
23391
+ * - Other identity providers
23392
+ */
23393
+ async analyzeSocialLinks(walletAddress) {
23394
+ if (!this.config.includeSocialLinks) {
23395
+ return {
23396
+ isDoxxed: false,
23397
+ partialExposure: false,
23398
+ scoreDeduction: 0,
23399
+ links: []
23400
+ };
23401
+ }
23402
+ try {
23403
+ const snsResult = await this.checkSNS(walletAddress);
23404
+ if (snsResult) {
23405
+ return {
23406
+ isDoxxed: false,
23407
+ partialExposure: true,
23408
+ scoreDeduction: 7,
23409
+ links: [snsResult]
23410
+ };
23411
+ }
23412
+ } catch {
23413
+ }
23414
+ return {
23415
+ isDoxxed: false,
23416
+ partialExposure: false,
23417
+ scoreDeduction: 0,
23418
+ links: []
23419
+ };
23420
+ }
23421
+ /**
23422
+ * Check Solana Name Service for domain names
23423
+ */
23424
+ async checkSNS(walletAddress) {
23425
+ try {
23426
+ const url = `${this.heliusUrl}/addresses/${walletAddress}/names?api-key=${this.config.heliusApiKey}`;
23427
+ const response = await fetch(url);
23428
+ if (!response.ok) {
23429
+ return null;
23430
+ }
23431
+ const data = await response.json();
23432
+ if (Array.isArray(data) && data.length > 0) {
23433
+ return {
23434
+ platform: "sns",
23435
+ identifier: data[0].name || data[0],
23436
+ confidence: 1
23437
+ };
23438
+ }
23439
+ } catch {
23440
+ }
23441
+ return null;
23442
+ }
23443
+ /**
23444
+ * Get quick privacy score without full analysis
23445
+ *
23446
+ * Performs a lighter analysis suitable for real-time display.
23447
+ * Uses only the most recent transactions (100 max).
23448
+ */
23449
+ async quickScore(walletAddress) {
23450
+ const quickAnalyzer = new _SurveillanceAnalyzer({
23451
+ heliusApiKey: this.config.heliusApiKey,
23452
+ cluster: this.config.cluster,
23453
+ maxTransactions: 100,
23454
+ includeSocialLinks: false,
23455
+ // Skip social links for speed
23456
+ customExchangeAddresses: this.config.customExchangeAddresses
23457
+ });
23458
+ const result = await quickAnalyzer.analyze(walletAddress);
23459
+ const topRecommendation = result.privacyScore.recommendations[0];
23460
+ return {
23461
+ score: result.privacyScore.overall,
23462
+ risk: result.privacyScore.risk,
23463
+ topIssue: topRecommendation?.title ?? null
23464
+ };
23465
+ }
23466
+ };
23467
+ function createSurveillanceAnalyzer(config) {
23468
+ return new SurveillanceAnalyzer(config);
23469
+ }
20908
23470
  // Annotate the CommonJS export names for ESM import in node:
20909
23471
  0 && (module.exports = {
20910
23472
  ATTESTATION_VERSION,
20911
23473
  AptosStealthService,
23474
+ AttestationGatedDisclosure,
23475
+ AttestationSchema,
20912
23476
  AuditorKeyDerivation,
20913
23477
  AuditorType,
20914
23478
  BaseWalletAdapter,
@@ -20926,11 +23490,14 @@ function getSupportedSameChainChains() {
20926
23490
  ErrorCode,
20927
23491
  EthereumChainId,
20928
23492
  EthereumWalletAdapter,
23493
+ GenericProvider,
20929
23494
  HardwareErrorCode,
20930
23495
  HardwareWalletError,
23496
+ HeliusProvider,
20931
23497
  IntentBuilder,
20932
23498
  IntentError,
20933
23499
  IntentStatus,
23500
+ KNOWN_EXCHANGES,
20934
23501
  LedgerWalletAdapter,
20935
23502
  MEMO_PROGRAM_ID,
20936
23503
  MockEthereumAdapter,
@@ -20952,7 +23519,9 @@ function getSupportedSameChainChains() {
20952
23519
  OneClickSwapType,
20953
23520
  PaymentBuilder,
20954
23521
  PaymentStatus,
23522
+ PrivacyBackendRegistry,
20955
23523
  PrivacyLevel,
23524
+ PrivacySmartRouter,
20956
23525
  PrivateNFT,
20957
23526
  PrivateVoting,
20958
23527
  ProofError,
@@ -20962,6 +23531,7 @@ function getSupportedSameChainChains() {
20962
23531
  ReportStatus,
20963
23532
  SIP,
20964
23533
  SIPError,
23534
+ SIPNativeBackend,
20965
23535
  SIP_MEMO_PREFIX,
20966
23536
  SIP_VERSION,
20967
23537
  SOLANA_EXPLORER_URLS,
@@ -20978,6 +23548,7 @@ function getSupportedSameChainChains() {
20978
23548
  SolanaSameChainExecutor,
20979
23549
  SolanaWalletAdapter,
20980
23550
  SuiStealthService,
23551
+ SurveillanceAnalyzer,
20981
23552
  SwapStatus,
20982
23553
  ThresholdViewingKey,
20983
23554
  Treasury,
@@ -20994,11 +23565,15 @@ function getSupportedSameChainChains() {
20994
23565
  addBlindings,
20995
23566
  addCommitments,
20996
23567
  addOracle,
23568
+ analyzeAddressReuse,
23569
+ analyzeTemporalPatterns,
20997
23570
  aptosAddressToAuthKey,
20998
23571
  attachProofs,
20999
23572
  base58ToHex,
21000
23573
  browserBytesToHex,
21001
23574
  browserHexToBytes,
23575
+ calculatePrivacyScore,
23576
+ calculateSIPComparison,
21002
23577
  checkAptosStealthAddress,
21003
23578
  checkEd25519StealthAddress,
21004
23579
  checkStealthAddress,
@@ -21013,6 +23588,7 @@ function getSupportedSameChainChains() {
21013
23588
  createEthereumAdapter,
21014
23589
  createKeySpendOnlyOutput,
21015
23590
  createLedgerAdapter,
23591
+ createMockAttestation,
21016
23592
  createMockEthereumAdapter,
21017
23593
  createMockEthereumProvider,
21018
23594
  createMockLedgerAdapter,
@@ -21027,6 +23603,7 @@ function getSupportedSameChainChains() {
21027
23603
  createPrivateOwnership,
21028
23604
  createPrivateVoting,
21029
23605
  createProductionSIP,
23606
+ createProvider,
21030
23607
  createSIP,
21031
23608
  createSameChainExecutor,
21032
23609
  createSealedBidAuction,
@@ -21034,9 +23611,11 @@ function getSupportedSameChainChains() {
21034
23611
  createShieldedPayment,
21035
23612
  createSmartRouter,
21036
23613
  createSolanaAdapter,
23614
+ createSurveillanceAnalyzer,
21037
23615
  createTaprootOutput,
21038
23616
  createTrezorAdapter,
21039
23617
  createWalletFactory,
23618
+ createWebhookHandler,
21040
23619
  createZcashClient,
21041
23620
  createZcashNativeBackend,
21042
23621
  createZcashShieldedService,
@@ -21045,6 +23624,7 @@ function getSupportedSameChainChains() {
21045
23624
  decodeTaprootAddress,
21046
23625
  decryptMemo,
21047
23626
  decryptWithViewing,
23627
+ defaultRegistry,
21048
23628
  deriveAptosStealthPrivateKey,
21049
23629
  deriveEd25519StealthPrivateKey,
21050
23630
  deriveOracleId,
@@ -21054,7 +23634,9 @@ function getSupportedSameChainChains() {
21054
23634
  deserializeAttestationMessage,
21055
23635
  deserializeIntent,
21056
23636
  deserializePayment,
23637
+ detectClusters,
21057
23638
  detectEthereumWallets,
23639
+ detectExchangeExposure,
21058
23640
  detectSolanaWallets,
21059
23641
  ed25519PublicKeyToAptosAddress,
21060
23642
  ed25519PublicKeyToNearAddress,
@@ -21064,6 +23646,7 @@ function getSupportedSameChainChains() {
21064
23646
  encryptForViewing,
21065
23647
  estimatePrivateTransferFee,
21066
23648
  featureNotSupportedError,
23649
+ fetchAttestation,
21067
23650
  formatStablecoinAmount,
21068
23651
  fromHex,
21069
23652
  fromStablecoinUnits,
@@ -21148,6 +23731,7 @@ function getSupportedSameChainChains() {
21148
23731
  normalizeSuiAddress,
21149
23732
  notConnectedError,
21150
23733
  parseAnnouncement,
23734
+ processWebhookTransaction,
21151
23735
  proveOwnership,
21152
23736
  publicKeyToEthAddress,
21153
23737
  registerWallet,
@@ -21188,6 +23772,7 @@ function getSupportedSameChainChains() {
21188
23772
  validateScalar,
21189
23773
  validateViewingKey,
21190
23774
  verifyAttestation,
23775
+ verifyAttestationSignature,
21191
23776
  verifyCommitment,
21192
23777
  verifyOpening,
21193
23778
  verifyOracleSignature,