@sip-protocol/sdk 0.7.2 → 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.
- package/dist/browser.d.mts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +2926 -341
- package/dist/browser.mjs +48 -2
- package/dist/chunk-2XIVXWHA.mjs +1930 -0
- package/dist/chunk-3M3HNQCW.mjs +18253 -0
- package/dist/chunk-7RFRWDCW.mjs +1504 -0
- package/dist/chunk-F6F73W35.mjs +16166 -0
- package/dist/chunk-OFDBEIEK.mjs +16166 -0
- package/dist/chunk-SF7YSLF5.mjs +1515 -0
- package/dist/chunk-WWUSGOXE.mjs +17129 -0
- package/dist/index-8MQz13eJ.d.mts +13746 -0
- package/dist/index-B71aXVzk.d.ts +13264 -0
- package/dist/index-DIBZHOOQ.d.ts +13746 -0
- package/dist/index-pOIIuwfV.d.mts +13264 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2911 -326
- package/dist/index.mjs +48 -2
- package/dist/solana-4O4K45VU.mjs +46 -0
- package/dist/solana-NDABAZ6P.mjs +56 -0
- package/dist/solana-ZYO63LY5.mjs +46 -0
- package/package.json +2 -2
- package/src/chains/solana/index.ts +24 -0
- package/src/chains/solana/providers/generic.ts +160 -0
- package/src/chains/solana/providers/helius.ts +249 -0
- package/src/chains/solana/providers/index.ts +54 -0
- package/src/chains/solana/providers/interface.ts +178 -0
- package/src/chains/solana/providers/webhook.ts +519 -0
- package/src/chains/solana/scan.ts +88 -8
- package/src/chains/solana/types.ts +20 -1
- package/src/compliance/index.ts +14 -0
- package/src/compliance/range-sas.ts +591 -0
- package/src/index.ts +99 -0
- package/src/privacy-backends/index.ts +86 -0
- package/src/privacy-backends/interface.ts +263 -0
- package/src/privacy-backends/privacycash-types.ts +278 -0
- package/src/privacy-backends/privacycash.ts +460 -0
- package/src/privacy-backends/registry.ts +278 -0
- package/src/privacy-backends/router.ts +346 -0
- package/src/privacy-backends/sip-native.ts +253 -0
- package/src/proofs/noir.ts +1 -1
- package/src/surveillance/algorithms/address-reuse.ts +143 -0
- package/src/surveillance/algorithms/cluster.ts +247 -0
- package/src/surveillance/algorithms/exchange.ts +295 -0
- package/src/surveillance/algorithms/temporal.ts +337 -0
- package/src/surveillance/analyzer.ts +442 -0
- package/src/surveillance/index.ts +64 -0
- package/src/surveillance/scoring.ts +372 -0
- package/src/surveillance/types.ts +264 -0
package/dist/browser.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
|
|
1617
|
+
amount,
|
|
1603
1618
|
mint: transferInfo.mint,
|
|
1604
|
-
tokenSymbol
|
|
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, ...
|
|
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
|
-
|
|
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 browser_exports = {};
|
|
|
4947
5415
|
__export(browser_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,
|
|
@@ -4965,11 +5435,14 @@ __export(browser_exports, {
|
|
|
4965
5435
|
ErrorCode: () => ErrorCode,
|
|
4966
5436
|
EthereumChainId: () => EthereumChainId,
|
|
4967
5437
|
EthereumWalletAdapter: () => EthereumWalletAdapter,
|
|
5438
|
+
GenericProvider: () => GenericProvider,
|
|
4968
5439
|
HardwareErrorCode: () => HardwareErrorCode,
|
|
4969
5440
|
HardwareWalletError: () => HardwareWalletError,
|
|
5441
|
+
HeliusProvider: () => HeliusProvider,
|
|
4970
5442
|
IntentBuilder: () => IntentBuilder,
|
|
4971
5443
|
IntentError: () => IntentError,
|
|
4972
|
-
IntentStatus: () =>
|
|
5444
|
+
IntentStatus: () => import_types59.IntentStatus,
|
|
5445
|
+
KNOWN_EXCHANGES: () => KNOWN_EXCHANGES,
|
|
4973
5446
|
LedgerWalletAdapter: () => LedgerWalletAdapter,
|
|
4974
5447
|
MEMO_PROGRAM_ID: () => MEMO_PROGRAM_ID,
|
|
4975
5448
|
MockEthereumAdapter: () => MockEthereumAdapter,
|
|
@@ -4979,31 +5452,34 @@ __export(browser_exports, {
|
|
|
4979
5452
|
MockSolver: () => MockSolver,
|
|
4980
5453
|
MockTrezorAdapter: () => MockTrezorAdapter,
|
|
4981
5454
|
MockWalletAdapter: () => MockWalletAdapter,
|
|
4982
|
-
NATIVE_TOKENS: () =>
|
|
5455
|
+
NATIVE_TOKENS: () => import_types59.NATIVE_TOKENS,
|
|
4983
5456
|
NEARIntentsAdapter: () => NEARIntentsAdapter,
|
|
4984
5457
|
NEARIntentsBackend: () => NEARIntentsBackend,
|
|
4985
5458
|
NetworkError: () => NetworkError,
|
|
4986
5459
|
ORACLE_DOMAIN: () => ORACLE_DOMAIN,
|
|
4987
5460
|
OneClickClient: () => OneClickClient,
|
|
4988
|
-
OneClickDepositMode: () =>
|
|
4989
|
-
OneClickErrorCode: () =>
|
|
4990
|
-
OneClickSwapStatus: () =>
|
|
4991
|
-
OneClickSwapType: () =>
|
|
5461
|
+
OneClickDepositMode: () => import_types63.OneClickDepositMode,
|
|
5462
|
+
OneClickErrorCode: () => import_types63.OneClickErrorCode,
|
|
5463
|
+
OneClickSwapStatus: () => import_types63.OneClickSwapStatus,
|
|
5464
|
+
OneClickSwapType: () => import_types63.OneClickSwapType,
|
|
4992
5465
|
PaymentBuilder: () => PaymentBuilder,
|
|
4993
|
-
PaymentStatus: () =>
|
|
4994
|
-
|
|
5466
|
+
PaymentStatus: () => import_types60.PaymentStatus,
|
|
5467
|
+
PrivacyBackendRegistry: () => PrivacyBackendRegistry,
|
|
5468
|
+
PrivacyLevel: () => import_types59.PrivacyLevel,
|
|
5469
|
+
PrivacySmartRouter: () => SmartRouter2,
|
|
4995
5470
|
PrivateNFT: () => PrivateNFT,
|
|
4996
5471
|
PrivateVoting: () => PrivateVoting,
|
|
4997
5472
|
ProofError: () => ProofError,
|
|
4998
5473
|
ProofGenerationError: () => ProofGenerationError,
|
|
4999
5474
|
ProofNotImplementedError: () => ProofNotImplementedError,
|
|
5000
5475
|
ProofWorker: () => ProofWorker,
|
|
5001
|
-
ProposalStatus: () =>
|
|
5002
|
-
ReportStatus: () =>
|
|
5476
|
+
ProposalStatus: () => import_types61.ProposalStatus,
|
|
5477
|
+
ReportStatus: () => import_types62.ReportStatus,
|
|
5003
5478
|
SIP: () => SIP,
|
|
5004
5479
|
SIPError: () => SIPError,
|
|
5480
|
+
SIPNativeBackend: () => SIPNativeBackend,
|
|
5005
5481
|
SIP_MEMO_PREFIX: () => SIP_MEMO_PREFIX,
|
|
5006
|
-
SIP_VERSION: () =>
|
|
5482
|
+
SIP_VERSION: () => import_types59.SIP_VERSION,
|
|
5007
5483
|
SOLANA_EXPLORER_URLS: () => SOLANA_EXPLORER_URLS,
|
|
5008
5484
|
SOLANA_RPC_ENDPOINTS: () => SOLANA_RPC_ENDPOINTS,
|
|
5009
5485
|
SOLANA_TOKEN_DECIMALS: () => SOLANA_TOKEN_DECIMALS,
|
|
@@ -5018,14 +5494,15 @@ __export(browser_exports, {
|
|
|
5018
5494
|
SolanaSameChainExecutor: () => SolanaSameChainExecutor,
|
|
5019
5495
|
SolanaWalletAdapter: () => SolanaWalletAdapter,
|
|
5020
5496
|
SuiStealthService: () => SuiStealthService,
|
|
5497
|
+
SurveillanceAnalyzer: () => SurveillanceAnalyzer,
|
|
5021
5498
|
SwapStatus: () => SwapStatus,
|
|
5022
5499
|
ThresholdViewingKey: () => ThresholdViewingKey,
|
|
5023
5500
|
Treasury: () => Treasury,
|
|
5024
5501
|
TrezorWalletAdapter: () => TrezorWalletAdapter,
|
|
5025
5502
|
ValidationError: () => ValidationError,
|
|
5026
5503
|
WalletError: () => WalletError,
|
|
5027
|
-
WalletErrorCode: () =>
|
|
5028
|
-
ZcashErrorCode: () =>
|
|
5504
|
+
WalletErrorCode: () => import_types58.WalletErrorCode,
|
|
5505
|
+
ZcashErrorCode: () => import_types64.ZcashErrorCode,
|
|
5029
5506
|
ZcashNativeBackend: () => ZcashNativeBackend,
|
|
5030
5507
|
ZcashRPCClient: () => ZcashRPCClient,
|
|
5031
5508
|
ZcashRPCError: () => ZcashRPCError,
|
|
@@ -5034,11 +5511,15 @@ __export(browser_exports, {
|
|
|
5034
5511
|
addBlindings: () => addBlindings,
|
|
5035
5512
|
addCommitments: () => addCommitments,
|
|
5036
5513
|
addOracle: () => addOracle,
|
|
5514
|
+
analyzeAddressReuse: () => analyzeAddressReuse,
|
|
5515
|
+
analyzeTemporalPatterns: () => analyzeTemporalPatterns,
|
|
5037
5516
|
aptosAddressToAuthKey: () => aptosAddressToAuthKey,
|
|
5038
5517
|
attachProofs: () => attachProofs,
|
|
5039
5518
|
base58ToHex: () => base58ToHex,
|
|
5040
|
-
browserBytesToHex: () =>
|
|
5519
|
+
browserBytesToHex: () => bytesToHex11,
|
|
5041
5520
|
browserHexToBytes: () => hexToBytes10,
|
|
5521
|
+
calculatePrivacyScore: () => calculatePrivacyScore,
|
|
5522
|
+
calculateSIPComparison: () => calculateSIPComparison,
|
|
5042
5523
|
checkAptosStealthAddress: () => checkAptosStealthAddress,
|
|
5043
5524
|
checkEd25519StealthAddress: () => checkEd25519StealthAddress,
|
|
5044
5525
|
checkMobileWASMCompatibility: () => checkMobileWASMCompatibility,
|
|
@@ -5054,6 +5535,7 @@ __export(browser_exports, {
|
|
|
5054
5535
|
createEthereumAdapter: () => createEthereumAdapter,
|
|
5055
5536
|
createKeySpendOnlyOutput: () => createKeySpendOnlyOutput,
|
|
5056
5537
|
createLedgerAdapter: () => createLedgerAdapter,
|
|
5538
|
+
createMockAttestation: () => createMockAttestation,
|
|
5057
5539
|
createMockEthereumAdapter: () => createMockEthereumAdapter,
|
|
5058
5540
|
createMockEthereumProvider: () => createMockEthereumProvider,
|
|
5059
5541
|
createMockLedgerAdapter: () => createMockLedgerAdapter,
|
|
@@ -5068,6 +5550,7 @@ __export(browser_exports, {
|
|
|
5068
5550
|
createPrivateOwnership: () => createPrivateOwnership,
|
|
5069
5551
|
createPrivateVoting: () => createPrivateVoting,
|
|
5070
5552
|
createProductionSIP: () => createProductionSIP,
|
|
5553
|
+
createProvider: () => createProvider,
|
|
5071
5554
|
createSIP: () => createSIP,
|
|
5072
5555
|
createSameChainExecutor: () => createSameChainExecutor,
|
|
5073
5556
|
createSealedBidAuction: () => createSealedBidAuction,
|
|
@@ -5075,9 +5558,11 @@ __export(browser_exports, {
|
|
|
5075
5558
|
createShieldedPayment: () => createShieldedPayment,
|
|
5076
5559
|
createSmartRouter: () => createSmartRouter,
|
|
5077
5560
|
createSolanaAdapter: () => createSolanaAdapter,
|
|
5561
|
+
createSurveillanceAnalyzer: () => createSurveillanceAnalyzer,
|
|
5078
5562
|
createTaprootOutput: () => createTaprootOutput,
|
|
5079
5563
|
createTrezorAdapter: () => createTrezorAdapter,
|
|
5080
5564
|
createWalletFactory: () => createWalletFactory,
|
|
5565
|
+
createWebhookHandler: () => createWebhookHandler,
|
|
5081
5566
|
createWorkerBlobURL: () => createWorkerBlobURL,
|
|
5082
5567
|
createZcashClient: () => createZcashClient,
|
|
5083
5568
|
createZcashNativeBackend: () => createZcashNativeBackend,
|
|
@@ -5087,6 +5572,7 @@ __export(browser_exports, {
|
|
|
5087
5572
|
decodeTaprootAddress: () => decodeTaprootAddress,
|
|
5088
5573
|
decryptMemo: () => decryptMemo,
|
|
5089
5574
|
decryptWithViewing: () => decryptWithViewing,
|
|
5575
|
+
defaultRegistry: () => defaultRegistry,
|
|
5090
5576
|
deriveAptosStealthPrivateKey: () => deriveAptosStealthPrivateKey,
|
|
5091
5577
|
deriveEd25519StealthPrivateKey: () => deriveEd25519StealthPrivateKey,
|
|
5092
5578
|
deriveOracleId: () => deriveOracleId,
|
|
@@ -5096,7 +5582,9 @@ __export(browser_exports, {
|
|
|
5096
5582
|
deserializeAttestationMessage: () => deserializeAttestationMessage,
|
|
5097
5583
|
deserializeIntent: () => deserializeIntent,
|
|
5098
5584
|
deserializePayment: () => deserializePayment,
|
|
5585
|
+
detectClusters: () => detectClusters,
|
|
5099
5586
|
detectEthereumWallets: () => detectEthereumWallets,
|
|
5587
|
+
detectExchangeExposure: () => detectExchangeExposure,
|
|
5100
5588
|
detectMobileBrowser: () => detectMobileBrowser,
|
|
5101
5589
|
detectMobilePlatform: () => detectMobilePlatform,
|
|
5102
5590
|
detectSolanaWallets: () => detectSolanaWallets,
|
|
@@ -5108,6 +5596,7 @@ __export(browser_exports, {
|
|
|
5108
5596
|
encryptForViewing: () => encryptForViewing,
|
|
5109
5597
|
estimatePrivateTransferFee: () => estimatePrivateTransferFee,
|
|
5110
5598
|
featureNotSupportedError: () => featureNotSupportedError,
|
|
5599
|
+
fetchAttestation: () => fetchAttestation,
|
|
5111
5600
|
formatStablecoinAmount: () => formatStablecoinAmount,
|
|
5112
5601
|
fromHex: () => fromHex,
|
|
5113
5602
|
fromStablecoinUnits: () => fromStablecoinUnits,
|
|
@@ -5166,7 +5655,7 @@ __export(browser_exports, {
|
|
|
5166
5655
|
isExpired: () => isExpired,
|
|
5167
5656
|
isNonNegativeAmount: () => isNonNegativeAmount,
|
|
5168
5657
|
isPaymentExpired: () => isPaymentExpired,
|
|
5169
|
-
isPrivate: () =>
|
|
5658
|
+
isPrivate: () => import_types59.isPrivate,
|
|
5170
5659
|
isPrivateWalletAdapter: () => isPrivateWalletAdapter,
|
|
5171
5660
|
isSIPError: () => isSIPError,
|
|
5172
5661
|
isSameChainSupported: () => isSameChainSupported,
|
|
@@ -5196,6 +5685,7 @@ __export(browser_exports, {
|
|
|
5196
5685
|
normalizeSuiAddress: () => normalizeSuiAddress,
|
|
5197
5686
|
notConnectedError: () => notConnectedError,
|
|
5198
5687
|
parseAnnouncement: () => parseAnnouncement,
|
|
5688
|
+
processWebhookTransaction: () => processWebhookTransaction,
|
|
5199
5689
|
proveOwnership: () => proveOwnership,
|
|
5200
5690
|
publicKeyToEthAddress: () => publicKeyToEthAddress,
|
|
5201
5691
|
registerWallet: () => registerWallet,
|
|
@@ -5219,7 +5709,7 @@ __export(browser_exports, {
|
|
|
5219
5709
|
subtractCommitments: () => subtractCommitments,
|
|
5220
5710
|
supportsSharedArrayBuffer: () => supportsSharedArrayBuffer,
|
|
5221
5711
|
supportsTouch: () => supportsTouch,
|
|
5222
|
-
supportsViewingKey: () =>
|
|
5712
|
+
supportsViewingKey: () => import_types59.supportsViewingKey,
|
|
5223
5713
|
supportsWASMBulkMemory: () => supportsWASMBulkMemory,
|
|
5224
5714
|
supportsWASMSimd: () => supportsWASMSimd,
|
|
5225
5715
|
supportsWebBluetooth: () => supportsWebBluetooth,
|
|
@@ -5239,6 +5729,7 @@ __export(browser_exports, {
|
|
|
5239
5729
|
validateScalar: () => validateScalar,
|
|
5240
5730
|
validateViewingKey: () => validateViewingKey,
|
|
5241
5731
|
verifyAttestation: () => verifyAttestation,
|
|
5732
|
+
verifyAttestationSignature: () => verifyAttestationSignature,
|
|
5242
5733
|
verifyCommitment: () => verifyCommitment,
|
|
5243
5734
|
verifyOpening: () => verifyOpening,
|
|
5244
5735
|
verifyOracleSignature: () => verifyOracleSignature,
|
|
@@ -5254,7 +5745,7 @@ module.exports = __toCommonJS(browser_exports);
|
|
|
5254
5745
|
init_errors();
|
|
5255
5746
|
|
|
5256
5747
|
// src/sip.ts
|
|
5257
|
-
var
|
|
5748
|
+
var import_types8 = require("@sip-protocol/types");
|
|
5258
5749
|
|
|
5259
5750
|
// src/intent.ts
|
|
5260
5751
|
var import_types = require("@sip-protocol/types");
|
|
@@ -7173,7 +7664,7 @@ var SIP = class {
|
|
|
7173
7664
|
this.config = {
|
|
7174
7665
|
...config,
|
|
7175
7666
|
mode: config.mode ?? "demo",
|
|
7176
|
-
defaultPrivacy: config.defaultPrivacy ??
|
|
7667
|
+
defaultPrivacy: config.defaultPrivacy ?? import_types8.PrivacyLevel.SHIELDED
|
|
7177
7668
|
};
|
|
7178
7669
|
this.proofProvider = config.proofProvider;
|
|
7179
7670
|
if (config.intentsAdapter) {
|
|
@@ -7378,8 +7869,8 @@ var SIP = class {
|
|
|
7378
7869
|
"intentsAdapter"
|
|
7379
7870
|
);
|
|
7380
7871
|
}
|
|
7381
|
-
const metaAddr = recipientMetaAddress ?? (params.privacy !==
|
|
7382
|
-
if (params.privacy !==
|
|
7872
|
+
const metaAddr = recipientMetaAddress ?? (params.privacy !== import_types8.PrivacyLevel.TRANSPARENT ? this.stealthKeys?.metaAddress : void 0);
|
|
7873
|
+
if (params.privacy !== import_types8.PrivacyLevel.TRANSPARENT && !metaAddr) {
|
|
7383
7874
|
throw new ValidationError(
|
|
7384
7875
|
"Stealth meta-address required for privacy modes. Call generateStealthKeys() or provide recipientMetaAddress.",
|
|
7385
7876
|
"recipientMetaAddress"
|
|
@@ -7470,10 +7961,10 @@ var SIP = class {
|
|
|
7470
7961
|
}
|
|
7471
7962
|
);
|
|
7472
7963
|
this.pendingSwaps.delete(quote.intentId);
|
|
7473
|
-
const isSuccess = finalStatus.status ===
|
|
7964
|
+
const isSuccess = finalStatus.status === import_types8.OneClickSwapStatus.SUCCESS;
|
|
7474
7965
|
return {
|
|
7475
7966
|
intentId: intent.intentId,
|
|
7476
|
-
status: isSuccess ?
|
|
7967
|
+
status: isSuccess ? import_types8.IntentStatus.FULFILLED : import_types8.IntentStatus.FAILED,
|
|
7477
7968
|
outputAmount: quote.outputAmount,
|
|
7478
7969
|
txHash: finalStatus.settlementTxHash ?? depositTxHash,
|
|
7479
7970
|
fulfilledAt: Math.floor(Date.now() / 1e3),
|
|
@@ -7540,9 +8031,9 @@ var SIP = class {
|
|
|
7540
8031
|
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
7541
8032
|
return {
|
|
7542
8033
|
intentId: intent.intentId,
|
|
7543
|
-
status:
|
|
8034
|
+
status: import_types8.IntentStatus.FULFILLED,
|
|
7544
8035
|
outputAmount: quote.outputAmount,
|
|
7545
|
-
txHash: intent.privacyLevel ===
|
|
8036
|
+
txHash: intent.privacyLevel === import_types8.PrivacyLevel.TRANSPARENT ? `0x${Date.now().toString(16)}` : void 0,
|
|
7546
8037
|
fulfilledAt: Math.floor(Date.now() / 1e3)
|
|
7547
8038
|
};
|
|
7548
8039
|
}
|
|
@@ -7584,7 +8075,7 @@ var SIP = class {
|
|
|
7584
8075
|
}
|
|
7585
8076
|
const { sendPrivateSPLTransfer: sendPrivateSPLTransfer2 } = await Promise.resolve().then(() => (init_solana(), solana_exports));
|
|
7586
8077
|
const { PublicKey: SolanaPublicKey } = await import("@solana/web3.js");
|
|
7587
|
-
const { getAssociatedTokenAddress:
|
|
8078
|
+
const { getAssociatedTokenAddress: getAssociatedTokenAddress4 } = await import("@solana/spl-token");
|
|
7588
8079
|
const { SOLANA_TOKEN_MINTS: SOLANA_TOKEN_MINTS2 } = await Promise.resolve().then(() => (init_constants(), constants_exports));
|
|
7589
8080
|
let mint;
|
|
7590
8081
|
if (params.token in SOLANA_TOKEN_MINTS2) {
|
|
@@ -7592,7 +8083,7 @@ var SIP = class {
|
|
|
7592
8083
|
} else {
|
|
7593
8084
|
mint = new SolanaPublicKey(params.token);
|
|
7594
8085
|
}
|
|
7595
|
-
const senderTokenAccount = await
|
|
8086
|
+
const senderTokenAccount = await getAssociatedTokenAddress4(
|
|
7596
8087
|
mint,
|
|
7597
8088
|
params.sender
|
|
7598
8089
|
);
|
|
@@ -8423,7 +8914,7 @@ function hexToBytes10(hex) {
|
|
|
8423
8914
|
}
|
|
8424
8915
|
return bytes;
|
|
8425
8916
|
}
|
|
8426
|
-
function
|
|
8917
|
+
function bytesToHex11(bytes) {
|
|
8427
8918
|
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
8428
8919
|
}
|
|
8429
8920
|
function isBrowser() {
|
|
@@ -8486,7 +8977,7 @@ var CHAIN_NUMERIC_IDS = {
|
|
|
8486
8977
|
};
|
|
8487
8978
|
|
|
8488
8979
|
// src/oracle/verification.ts
|
|
8489
|
-
var
|
|
8980
|
+
var import_ed255193 = require("@noble/curves/ed25519");
|
|
8490
8981
|
var import_sha25610 = require("@noble/hashes/sha256");
|
|
8491
8982
|
var import_utils14 = require("@noble/hashes/utils");
|
|
8492
8983
|
|
|
@@ -8652,7 +9143,7 @@ function verifyAttestation(attestation, registry) {
|
|
|
8652
9143
|
const signatureBytes = (0, import_utils14.hexToBytes)(
|
|
8653
9144
|
sig.signature.startsWith("0x") ? sig.signature.slice(2) : sig.signature
|
|
8654
9145
|
);
|
|
8655
|
-
const isValid =
|
|
9146
|
+
const isValid = import_ed255193.ed25519.verify(signatureBytes, messageHash, publicKeyBytes);
|
|
8656
9147
|
if (isValid) {
|
|
8657
9148
|
validCount++;
|
|
8658
9149
|
validOracles.push(sig.oracleId);
|
|
@@ -8680,14 +9171,14 @@ function verifyOracleSignature(signature, messageHash, oracle) {
|
|
|
8680
9171
|
const signatureBytes = (0, import_utils14.hexToBytes)(
|
|
8681
9172
|
signature.signature.startsWith("0x") ? signature.signature.slice(2) : signature.signature
|
|
8682
9173
|
);
|
|
8683
|
-
return
|
|
9174
|
+
return import_ed255193.ed25519.verify(signatureBytes, messageHash, publicKeyBytes);
|
|
8684
9175
|
} catch {
|
|
8685
9176
|
return false;
|
|
8686
9177
|
}
|
|
8687
9178
|
}
|
|
8688
9179
|
function signAttestationMessage(messageHash, privateKey) {
|
|
8689
|
-
const signature =
|
|
8690
|
-
const publicKey =
|
|
9180
|
+
const signature = import_ed255193.ed25519.sign(messageHash, privateKey);
|
|
9181
|
+
const publicKey = import_ed255193.ed25519.getPublicKey(privateKey);
|
|
8691
9182
|
const oracleId = deriveOracleId(publicKey);
|
|
8692
9183
|
return {
|
|
8693
9184
|
oracleId,
|
|
@@ -8743,13 +9234,13 @@ function hasEnoughOracles(registry) {
|
|
|
8743
9234
|
}
|
|
8744
9235
|
|
|
8745
9236
|
// src/index.ts
|
|
8746
|
-
var import_types58 = require("@sip-protocol/types");
|
|
8747
9237
|
var import_types59 = require("@sip-protocol/types");
|
|
8748
9238
|
var import_types60 = require("@sip-protocol/types");
|
|
8749
9239
|
var import_types61 = require("@sip-protocol/types");
|
|
9240
|
+
var import_types62 = require("@sip-protocol/types");
|
|
8750
9241
|
|
|
8751
9242
|
// src/solver/mock-solver.ts
|
|
8752
|
-
var
|
|
9243
|
+
var import_types11 = require("@sip-protocol/types");
|
|
8753
9244
|
var import_utils15 = require("@noble/hashes/utils");
|
|
8754
9245
|
var MockSolver = class {
|
|
8755
9246
|
info;
|
|
@@ -8875,7 +9366,7 @@ var MockSolver = class {
|
|
|
8875
9366
|
status.error = "Simulated failure for testing";
|
|
8876
9367
|
return {
|
|
8877
9368
|
intentId: intent.intentId,
|
|
8878
|
-
status:
|
|
9369
|
+
status: import_types11.IntentStatus.FAILED,
|
|
8879
9370
|
fulfilledAt: Math.floor(Date.now() / 1e3),
|
|
8880
9371
|
error: status.error
|
|
8881
9372
|
};
|
|
@@ -8885,7 +9376,7 @@ var MockSolver = class {
|
|
|
8885
9376
|
status.txHash = txHash;
|
|
8886
9377
|
return {
|
|
8887
9378
|
intentId: intent.intentId,
|
|
8888
|
-
status:
|
|
9379
|
+
status: import_types11.IntentStatus.FULFILLED,
|
|
8889
9380
|
outputAmount: quote.outputAmount,
|
|
8890
9381
|
txHash: intent.privacyLevel === "transparent" ? txHash : void 0,
|
|
8891
9382
|
fulfillmentProof: {
|
|
@@ -8931,7 +9422,7 @@ function createMockSolver(config) {
|
|
|
8931
9422
|
}
|
|
8932
9423
|
|
|
8933
9424
|
// src/index.ts
|
|
8934
|
-
var
|
|
9425
|
+
var import_types63 = require("@sip-protocol/types");
|
|
8935
9426
|
|
|
8936
9427
|
// src/settlement/interface.ts
|
|
8937
9428
|
var SwapStatus = /* @__PURE__ */ ((SwapStatus2) => {
|
|
@@ -9338,21 +9829,21 @@ function createSmartRouter(registry) {
|
|
|
9338
9829
|
}
|
|
9339
9830
|
|
|
9340
9831
|
// src/settlement/backends/near-intents.ts
|
|
9341
|
-
var
|
|
9832
|
+
var import_types12 = require("@sip-protocol/types");
|
|
9342
9833
|
init_errors();
|
|
9343
9834
|
function mapOneClickStatus(status) {
|
|
9344
9835
|
switch (status) {
|
|
9345
|
-
case
|
|
9836
|
+
case import_types12.OneClickSwapStatus.PENDING_DEPOSIT:
|
|
9346
9837
|
return "pending_deposit" /* PENDING_DEPOSIT */;
|
|
9347
|
-
case
|
|
9838
|
+
case import_types12.OneClickSwapStatus.PROCESSING:
|
|
9348
9839
|
return "in_progress" /* IN_PROGRESS */;
|
|
9349
|
-
case
|
|
9840
|
+
case import_types12.OneClickSwapStatus.SUCCESS:
|
|
9350
9841
|
return "success" /* SUCCESS */;
|
|
9351
|
-
case
|
|
9842
|
+
case import_types12.OneClickSwapStatus.FAILED:
|
|
9352
9843
|
return "failed" /* FAILED */;
|
|
9353
|
-
case
|
|
9844
|
+
case import_types12.OneClickSwapStatus.INCOMPLETE_DEPOSIT:
|
|
9354
9845
|
return "failed" /* FAILED */;
|
|
9355
|
-
case
|
|
9846
|
+
case import_types12.OneClickSwapStatus.REFUNDED:
|
|
9356
9847
|
return "refunded" /* REFUNDED */;
|
|
9357
9848
|
default:
|
|
9358
9849
|
return "pending_deposit" /* PENDING_DEPOSIT */;
|
|
@@ -9390,9 +9881,9 @@ var NEARIntentsBackend = class {
|
|
|
9390
9881
|
"zcash"
|
|
9391
9882
|
],
|
|
9392
9883
|
supportedPrivacyLevels: [
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9884
|
+
import_types12.PrivacyLevel.TRANSPARENT,
|
|
9885
|
+
import_types12.PrivacyLevel.SHIELDED,
|
|
9886
|
+
import_types12.PrivacyLevel.COMPLIANT
|
|
9396
9887
|
],
|
|
9397
9888
|
supportsCancellation: false,
|
|
9398
9889
|
supportsRefunds: true,
|
|
@@ -9649,13 +10140,13 @@ var NEARIntentsBackend = class {
|
|
|
9649
10140
|
if (!params.privacyLevel) {
|
|
9650
10141
|
throw new ValidationError("privacyLevel is required", "privacyLevel");
|
|
9651
10142
|
}
|
|
9652
|
-
if (params.privacyLevel !==
|
|
10143
|
+
if (params.privacyLevel !== import_types12.PrivacyLevel.TRANSPARENT && !params.recipientMetaAddress) {
|
|
9653
10144
|
throw new ValidationError(
|
|
9654
10145
|
"recipientMetaAddress is required for shielded/compliant privacy modes",
|
|
9655
10146
|
"recipientMetaAddress"
|
|
9656
10147
|
);
|
|
9657
10148
|
}
|
|
9658
|
-
if (params.privacyLevel ===
|
|
10149
|
+
if (params.privacyLevel === import_types12.PrivacyLevel.TRANSPARENT && !params.senderAddress) {
|
|
9659
10150
|
throw new ValidationError(
|
|
9660
10151
|
"senderAddress is required for transparent mode",
|
|
9661
10152
|
"senderAddress"
|
|
@@ -9694,7 +10185,7 @@ function createNEARIntentsBackend(config) {
|
|
|
9694
10185
|
}
|
|
9695
10186
|
|
|
9696
10187
|
// src/settlement/backends/zcash-native.ts
|
|
9697
|
-
var
|
|
10188
|
+
var import_types13 = require("@sip-protocol/types");
|
|
9698
10189
|
init_errors();
|
|
9699
10190
|
var ZcashNativeBackend = class {
|
|
9700
10191
|
name = "zcash-native";
|
|
@@ -9713,9 +10204,9 @@ var ZcashNativeBackend = class {
|
|
|
9713
10204
|
supportedSourceChains: ["zcash"],
|
|
9714
10205
|
supportedDestinationChains: ["zcash"],
|
|
9715
10206
|
supportedPrivacyLevels: [
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
10207
|
+
import_types13.PrivacyLevel.TRANSPARENT,
|
|
10208
|
+
import_types13.PrivacyLevel.SHIELDED,
|
|
10209
|
+
import_types13.PrivacyLevel.COMPLIANT
|
|
9719
10210
|
],
|
|
9720
10211
|
supportsCancellation: false,
|
|
9721
10212
|
supportsRefunds: false,
|
|
@@ -9754,7 +10245,7 @@ var ZcashNativeBackend = class {
|
|
|
9754
10245
|
const minAmountOut = amountOut * BigInt(99) / BigInt(100);
|
|
9755
10246
|
let depositAddress;
|
|
9756
10247
|
let recipientAddress;
|
|
9757
|
-
if (privacyLevel ===
|
|
10248
|
+
if (privacyLevel === import_types13.PrivacyLevel.SHIELDED || privacyLevel === import_types13.PrivacyLevel.COMPLIANT) {
|
|
9758
10249
|
if (typeof recipientMetaAddress === "string") {
|
|
9759
10250
|
recipientAddress = recipientMetaAddress;
|
|
9760
10251
|
} else if (recipientMetaAddress) {
|
|
@@ -10039,7 +10530,7 @@ function createZcashNativeBackend(config) {
|
|
|
10039
10530
|
}
|
|
10040
10531
|
|
|
10041
10532
|
// src/settlement/backends/direct-chain.ts
|
|
10042
|
-
var
|
|
10533
|
+
var import_types14 = require("@sip-protocol/types");
|
|
10043
10534
|
init_stealth();
|
|
10044
10535
|
init_errors();
|
|
10045
10536
|
var import_utils16 = require("@noble/hashes/utils");
|
|
@@ -10081,7 +10572,7 @@ var DEFAULT_GAS_FEES = {
|
|
|
10081
10572
|
};
|
|
10082
10573
|
|
|
10083
10574
|
// src/zcash/rpc-client.ts
|
|
10084
|
-
var
|
|
10575
|
+
var import_types15 = require("@sip-protocol/types");
|
|
10085
10576
|
init_errors();
|
|
10086
10577
|
var DEFAULT_CONFIG = {
|
|
10087
10578
|
host: "127.0.0.1",
|
|
@@ -10102,19 +10593,19 @@ var ZcashRPCError = class extends Error {
|
|
|
10102
10593
|
* Check if error is due to insufficient funds
|
|
10103
10594
|
*/
|
|
10104
10595
|
isInsufficientFunds() {
|
|
10105
|
-
return this.code ===
|
|
10596
|
+
return this.code === import_types15.ZcashErrorCode.WALLET_INSUFFICIENT_FUNDS;
|
|
10106
10597
|
}
|
|
10107
10598
|
/**
|
|
10108
10599
|
* Check if error is due to invalid address
|
|
10109
10600
|
*/
|
|
10110
10601
|
isInvalidAddress() {
|
|
10111
|
-
return this.code ===
|
|
10602
|
+
return this.code === import_types15.ZcashErrorCode.INVALID_ADDRESS_OR_KEY;
|
|
10112
10603
|
}
|
|
10113
10604
|
/**
|
|
10114
10605
|
* Check if error is due to wallet being locked
|
|
10115
10606
|
*/
|
|
10116
10607
|
isWalletLocked() {
|
|
10117
|
-
return this.code ===
|
|
10608
|
+
return this.code === import_types15.ZcashErrorCode.WALLET_UNLOCK_NEEDED;
|
|
10118
10609
|
}
|
|
10119
10610
|
};
|
|
10120
10611
|
var ZcashRPCClient = class {
|
|
@@ -10501,7 +10992,7 @@ function createZcashClient(config) {
|
|
|
10501
10992
|
}
|
|
10502
10993
|
|
|
10503
10994
|
// src/zcash/shielded-service.ts
|
|
10504
|
-
var
|
|
10995
|
+
var import_types16 = require("@sip-protocol/types");
|
|
10505
10996
|
init_errors();
|
|
10506
10997
|
var ZcashShieldedService = class _ZcashShieldedService {
|
|
10507
10998
|
client;
|
|
@@ -10688,7 +11179,7 @@ var ZcashShieldedService = class _ZcashShieldedService {
|
|
|
10688
11179
|
* Higher-level method that handles privacy level mapping.
|
|
10689
11180
|
*/
|
|
10690
11181
|
async sendWithPrivacy(to, amount, privacyLevel, memo) {
|
|
10691
|
-
if (privacyLevel ===
|
|
11182
|
+
if (privacyLevel === import_types16.PrivacyLevel.TRANSPARENT) {
|
|
10692
11183
|
throw new ValidationError(
|
|
10693
11184
|
"Transparent mode not supported for Zcash shielded service. Use standard RPC client.",
|
|
10694
11185
|
"privacyLevel",
|
|
@@ -10782,7 +11273,7 @@ var ZcashShieldedService = class _ZcashShieldedService {
|
|
|
10782
11273
|
const viewingKey = await this.exportViewingKey();
|
|
10783
11274
|
return {
|
|
10784
11275
|
viewingKey,
|
|
10785
|
-
privacyLevel:
|
|
11276
|
+
privacyLevel: import_types16.PrivacyLevel.COMPLIANT,
|
|
10786
11277
|
disclaimer: "This viewing key provides read-only access to transaction history. It cannot be used to spend funds. Share only with authorized auditors."
|
|
10787
11278
|
};
|
|
10788
11279
|
}
|
|
@@ -10868,11 +11359,11 @@ var ZcashShieldedService = class _ZcashShieldedService {
|
|
|
10868
11359
|
*/
|
|
10869
11360
|
mapPrivacyLevelToPolicy(level) {
|
|
10870
11361
|
switch (level) {
|
|
10871
|
-
case
|
|
11362
|
+
case import_types16.PrivacyLevel.TRANSPARENT:
|
|
10872
11363
|
return "NoPrivacy";
|
|
10873
|
-
case
|
|
11364
|
+
case import_types16.PrivacyLevel.SHIELDED:
|
|
10874
11365
|
return "FullPrivacy";
|
|
10875
|
-
case
|
|
11366
|
+
case import_types16.PrivacyLevel.COMPLIANT:
|
|
10876
11367
|
return "FullPrivacy";
|
|
10877
11368
|
default:
|
|
10878
11369
|
return "FullPrivacy";
|
|
@@ -10925,7 +11416,7 @@ function createZcashShieldedService(config) {
|
|
|
10925
11416
|
}
|
|
10926
11417
|
|
|
10927
11418
|
// src/zcash/swap-service.ts
|
|
10928
|
-
var
|
|
11419
|
+
var import_types17 = require("@sip-protocol/types");
|
|
10929
11420
|
init_errors();
|
|
10930
11421
|
var MOCK_PRICES = {
|
|
10931
11422
|
ETH: 2500,
|
|
@@ -11039,7 +11530,7 @@ var ZcashSwapService = class {
|
|
|
11039
11530
|
validUntil,
|
|
11040
11531
|
depositAddress: this.generateMockDepositAddress(sourceChain),
|
|
11041
11532
|
estimatedTime: this.getEstimatedTime(sourceChain),
|
|
11042
|
-
privacyLevel:
|
|
11533
|
+
privacyLevel: import_types17.PrivacyLevel.SHIELDED
|
|
11043
11534
|
};
|
|
11044
11535
|
this.quotes.set(quoteId, quote);
|
|
11045
11536
|
return quote;
|
|
@@ -11082,7 +11573,7 @@ var ZcashSwapService = class {
|
|
|
11082
11573
|
depositAddress: "",
|
|
11083
11574
|
// Will be set by bridge
|
|
11084
11575
|
estimatedTime: this.getEstimatedTime(params.sourceChain),
|
|
11085
|
-
privacyLevel:
|
|
11576
|
+
privacyLevel: import_types17.PrivacyLevel.SHIELDED
|
|
11086
11577
|
};
|
|
11087
11578
|
this.quotes.set(quote.quoteId, quote);
|
|
11088
11579
|
return quote;
|
|
@@ -11365,10 +11856,10 @@ function createZcashSwapService(config) {
|
|
|
11365
11856
|
init_errors();
|
|
11366
11857
|
|
|
11367
11858
|
// src/zcash/index.ts
|
|
11368
|
-
var
|
|
11859
|
+
var import_types18 = require("@sip-protocol/types");
|
|
11369
11860
|
|
|
11370
11861
|
// src/index.ts
|
|
11371
|
-
var
|
|
11862
|
+
var import_types64 = require("@sip-protocol/types");
|
|
11372
11863
|
|
|
11373
11864
|
// src/bitcoin/taproot.ts
|
|
11374
11865
|
var import_secp256k14 = require("@noble/curves/secp256k1");
|
|
@@ -11663,7 +12154,7 @@ init_errors();
|
|
|
11663
12154
|
init_validation();
|
|
11664
12155
|
|
|
11665
12156
|
// src/payment/payment.ts
|
|
11666
|
-
var
|
|
12157
|
+
var import_types19 = require("@sip-protocol/types");
|
|
11667
12158
|
var import_sha25613 = require("@noble/hashes/sha256");
|
|
11668
12159
|
var import_utils19 = require("@noble/hashes/utils");
|
|
11669
12160
|
var import_chacha2 = require("@noble/ciphers/chacha.js");
|
|
@@ -11854,7 +12345,7 @@ var PaymentBuilder = class {
|
|
|
11854
12345
|
_amount;
|
|
11855
12346
|
_recipientMetaAddress;
|
|
11856
12347
|
_recipientAddress;
|
|
11857
|
-
_privacy =
|
|
12348
|
+
_privacy = import_types19.PrivacyLevel.SHIELDED;
|
|
11858
12349
|
_viewingKey;
|
|
11859
12350
|
_sourceChain;
|
|
11860
12351
|
_destinationChain;
|
|
@@ -12137,7 +12628,7 @@ async function createShieldedPayment(params, options) {
|
|
|
12137
12628
|
} else {
|
|
12138
12629
|
resolvedToken = token;
|
|
12139
12630
|
}
|
|
12140
|
-
if (privacy !==
|
|
12631
|
+
if (privacy !== import_types19.PrivacyLevel.TRANSPARENT && !recipientMetaAddress) {
|
|
12141
12632
|
throw new ValidationError(
|
|
12142
12633
|
"recipientMetaAddress is required for shielded/compliant privacy modes",
|
|
12143
12634
|
"recipientMetaAddress",
|
|
@@ -12145,7 +12636,7 @@ async function createShieldedPayment(params, options) {
|
|
|
12145
12636
|
"SIP_2008" /* MISSING_REQUIRED */
|
|
12146
12637
|
);
|
|
12147
12638
|
}
|
|
12148
|
-
if (privacy ===
|
|
12639
|
+
if (privacy === import_types19.PrivacyLevel.TRANSPARENT && !recipientAddress) {
|
|
12149
12640
|
throw new ValidationError(
|
|
12150
12641
|
"recipientAddress is required for transparent mode",
|
|
12151
12642
|
"recipientAddress",
|
|
@@ -12153,7 +12644,7 @@ async function createShieldedPayment(params, options) {
|
|
|
12153
12644
|
"SIP_2008" /* MISSING_REQUIRED */
|
|
12154
12645
|
);
|
|
12155
12646
|
}
|
|
12156
|
-
if (privacy ===
|
|
12647
|
+
if (privacy === import_types19.PrivacyLevel.COMPLIANT && !viewingKey) {
|
|
12157
12648
|
throw new ValidationError(
|
|
12158
12649
|
"viewingKey is required for compliant mode",
|
|
12159
12650
|
"viewingKey",
|
|
@@ -12175,7 +12666,7 @@ async function createShieldedPayment(params, options) {
|
|
|
12175
12666
|
const now = Math.floor(Date.now() / 1e3);
|
|
12176
12667
|
const payment = {
|
|
12177
12668
|
paymentId,
|
|
12178
|
-
version:
|
|
12669
|
+
version: import_types19.SIP_VERSION,
|
|
12179
12670
|
privacyLevel: privacy,
|
|
12180
12671
|
createdAt: now,
|
|
12181
12672
|
expiry: now + ttl,
|
|
@@ -12186,7 +12677,7 @@ async function createShieldedPayment(params, options) {
|
|
|
12186
12677
|
purpose,
|
|
12187
12678
|
viewingKeyHash
|
|
12188
12679
|
};
|
|
12189
|
-
if (privacy !==
|
|
12680
|
+
if (privacy !== import_types19.PrivacyLevel.TRANSPARENT && recipientMetaAddress) {
|
|
12190
12681
|
const metaAddress = decodeStealthMetaAddress(recipientMetaAddress);
|
|
12191
12682
|
const { stealthAddress } = generateStealthAddress(metaAddress);
|
|
12192
12683
|
payment.recipientStealth = stealthAddress;
|
|
@@ -12203,7 +12694,7 @@ async function createShieldedPayment(params, options) {
|
|
|
12203
12694
|
payment.recipientAddress = recipientAddress;
|
|
12204
12695
|
payment.memo = memo;
|
|
12205
12696
|
}
|
|
12206
|
-
if (privacy !==
|
|
12697
|
+
if (privacy !== import_types19.PrivacyLevel.TRANSPARENT && proofProvider?.isReady) {
|
|
12207
12698
|
const hexToUint8 = (hex) => {
|
|
12208
12699
|
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
12209
12700
|
return (0, import_utils19.hexToBytes)(cleanHex);
|
|
@@ -12269,7 +12760,7 @@ function decryptMemo(encryptedMemo, viewingKey) {
|
|
|
12269
12760
|
function trackPayment(payment) {
|
|
12270
12761
|
return {
|
|
12271
12762
|
...payment,
|
|
12272
|
-
status:
|
|
12763
|
+
status: import_types19.PaymentStatus.DRAFT
|
|
12273
12764
|
};
|
|
12274
12765
|
}
|
|
12275
12766
|
function isPaymentExpired(payment) {
|
|
@@ -12302,7 +12793,7 @@ function getPaymentSummary(payment) {
|
|
|
12302
12793
|
}
|
|
12303
12794
|
|
|
12304
12795
|
// src/treasury/treasury.ts
|
|
12305
|
-
var
|
|
12796
|
+
var import_types20 = require("@sip-protocol/types");
|
|
12306
12797
|
var import_secp256k16 = require("@noble/curves/secp256k1");
|
|
12307
12798
|
var import_sha25614 = require("@noble/hashes/sha256");
|
|
12308
12799
|
var import_utils20 = require("@noble/hashes/utils");
|
|
@@ -12338,7 +12829,7 @@ var Treasury = class _Treasury {
|
|
|
12338
12829
|
...m,
|
|
12339
12830
|
addedAt: now
|
|
12340
12831
|
})),
|
|
12341
|
-
defaultPrivacy: params.defaultPrivacy ??
|
|
12832
|
+
defaultPrivacy: params.defaultPrivacy ?? import_types20.PrivacyLevel.SHIELDED,
|
|
12342
12833
|
masterViewingKey,
|
|
12343
12834
|
dailyLimit: params.dailyLimit,
|
|
12344
12835
|
transactionLimit: params.transactionLimit,
|
|
@@ -12417,7 +12908,7 @@ var Treasury = class _Treasury {
|
|
|
12417
12908
|
proposalId,
|
|
12418
12909
|
treasuryId: this.config.treasuryId,
|
|
12419
12910
|
type: "payment",
|
|
12420
|
-
status:
|
|
12911
|
+
status: import_types20.ProposalStatus.PENDING,
|
|
12421
12912
|
proposer: "",
|
|
12422
12913
|
// Should be set by caller
|
|
12423
12914
|
title: params.title,
|
|
@@ -12450,7 +12941,7 @@ var Treasury = class _Treasury {
|
|
|
12450
12941
|
proposalId,
|
|
12451
12942
|
treasuryId: this.config.treasuryId,
|
|
12452
12943
|
type: "batch_payment",
|
|
12453
|
-
status:
|
|
12944
|
+
status: import_types20.ProposalStatus.PENDING,
|
|
12454
12945
|
proposer: "",
|
|
12455
12946
|
title: params.title,
|
|
12456
12947
|
description: params.description,
|
|
@@ -12484,7 +12975,7 @@ var Treasury = class _Treasury {
|
|
|
12484
12975
|
* Get pending proposals
|
|
12485
12976
|
*/
|
|
12486
12977
|
getPendingProposals() {
|
|
12487
|
-
return this.getAllProposals().filter((p) => p.status ===
|
|
12978
|
+
return this.getAllProposals().filter((p) => p.status === import_types20.ProposalStatus.PENDING);
|
|
12488
12979
|
}
|
|
12489
12980
|
/**
|
|
12490
12981
|
* Sign a proposal
|
|
@@ -12515,7 +13006,7 @@ var Treasury = class _Treasury {
|
|
|
12515
13006
|
"SIP_2001" /* INVALID_INPUT */
|
|
12516
13007
|
);
|
|
12517
13008
|
}
|
|
12518
|
-
if (proposal.status !==
|
|
13009
|
+
if (proposal.status !== import_types20.ProposalStatus.PENDING) {
|
|
12519
13010
|
throw new ValidationError(
|
|
12520
13011
|
`proposal is not pending: ${proposal.status}`,
|
|
12521
13012
|
"proposalId",
|
|
@@ -12525,7 +13016,7 @@ var Treasury = class _Treasury {
|
|
|
12525
13016
|
}
|
|
12526
13017
|
const now = Math.floor(Date.now() / 1e3);
|
|
12527
13018
|
if (now > proposal.expiresAt) {
|
|
12528
|
-
proposal.status =
|
|
13019
|
+
proposal.status = import_types20.ProposalStatus.EXPIRED;
|
|
12529
13020
|
throw new ValidationError(
|
|
12530
13021
|
"proposal has expired",
|
|
12531
13022
|
"proposalId",
|
|
@@ -12557,9 +13048,9 @@ var Treasury = class _Treasury {
|
|
|
12557
13048
|
const approvals = proposal.signatures.filter((s) => s.approved).length;
|
|
12558
13049
|
const rejections = proposal.signatures.filter((s) => !s.approved).length;
|
|
12559
13050
|
if (approvals >= proposal.requiredSignatures) {
|
|
12560
|
-
proposal.status =
|
|
13051
|
+
proposal.status = import_types20.ProposalStatus.APPROVED;
|
|
12561
13052
|
} else if (rejections > this.config.totalSigners - proposal.requiredSignatures) {
|
|
12562
|
-
proposal.status =
|
|
13053
|
+
proposal.status = import_types20.ProposalStatus.REJECTED;
|
|
12563
13054
|
}
|
|
12564
13055
|
return proposal;
|
|
12565
13056
|
}
|
|
@@ -12576,7 +13067,7 @@ var Treasury = class _Treasury {
|
|
|
12576
13067
|
"SIP_2001" /* INVALID_INPUT */
|
|
12577
13068
|
);
|
|
12578
13069
|
}
|
|
12579
|
-
if (proposal.status !==
|
|
13070
|
+
if (proposal.status !== import_types20.ProposalStatus.APPROVED) {
|
|
12580
13071
|
throw new ValidationError(
|
|
12581
13072
|
`proposal is not approved: ${proposal.status}`,
|
|
12582
13073
|
"proposalId",
|
|
@@ -12589,8 +13080,8 @@ var Treasury = class _Treasury {
|
|
|
12589
13080
|
const payment = await createShieldedPayment({
|
|
12590
13081
|
token: proposal.payment.token,
|
|
12591
13082
|
amount: proposal.payment.amount,
|
|
12592
|
-
recipientMetaAddress: proposal.payment.privacy !==
|
|
12593
|
-
recipientAddress: proposal.payment.privacy ===
|
|
13083
|
+
recipientMetaAddress: proposal.payment.privacy !== import_types20.PrivacyLevel.TRANSPARENT ? proposal.payment.recipient : void 0,
|
|
13084
|
+
recipientAddress: proposal.payment.privacy === import_types20.PrivacyLevel.TRANSPARENT ? proposal.payment.recipient : void 0,
|
|
12594
13085
|
privacy: proposal.payment.privacy,
|
|
12595
13086
|
viewingKey: this.config.masterViewingKey?.key,
|
|
12596
13087
|
sourceChain: this.config.chain,
|
|
@@ -12603,8 +13094,8 @@ var Treasury = class _Treasury {
|
|
|
12603
13094
|
const payment = await createShieldedPayment({
|
|
12604
13095
|
token: proposal.batchPayment.token,
|
|
12605
13096
|
amount: recipient.amount,
|
|
12606
|
-
recipientMetaAddress: proposal.batchPayment.privacy !==
|
|
12607
|
-
recipientAddress: proposal.batchPayment.privacy ===
|
|
13097
|
+
recipientMetaAddress: proposal.batchPayment.privacy !== import_types20.PrivacyLevel.TRANSPARENT ? recipient.address : void 0,
|
|
13098
|
+
recipientAddress: proposal.batchPayment.privacy === import_types20.PrivacyLevel.TRANSPARENT ? recipient.address : void 0,
|
|
12608
13099
|
privacy: proposal.batchPayment.privacy,
|
|
12609
13100
|
viewingKey: this.config.masterViewingKey?.key,
|
|
12610
13101
|
sourceChain: this.config.chain,
|
|
@@ -12614,7 +13105,7 @@ var Treasury = class _Treasury {
|
|
|
12614
13105
|
payments.push(payment);
|
|
12615
13106
|
}
|
|
12616
13107
|
}
|
|
12617
|
-
proposal.status =
|
|
13108
|
+
proposal.status = import_types20.ProposalStatus.EXECUTED;
|
|
12618
13109
|
proposal.executedAt = Math.floor(Date.now() / 1e3);
|
|
12619
13110
|
proposal.resultPayments = payments;
|
|
12620
13111
|
return payments;
|
|
@@ -12643,7 +13134,7 @@ var Treasury = class _Treasury {
|
|
|
12643
13134
|
"SIP_2001" /* INVALID_INPUT */
|
|
12644
13135
|
);
|
|
12645
13136
|
}
|
|
12646
|
-
if (proposal.status !==
|
|
13137
|
+
if (proposal.status !== import_types20.ProposalStatus.PENDING) {
|
|
12647
13138
|
throw new ValidationError(
|
|
12648
13139
|
`proposal is not pending: ${proposal.status}`,
|
|
12649
13140
|
"proposalId",
|
|
@@ -12651,7 +13142,7 @@ var Treasury = class _Treasury {
|
|
|
12651
13142
|
"SIP_2001" /* INVALID_INPUT */
|
|
12652
13143
|
);
|
|
12653
13144
|
}
|
|
12654
|
-
proposal.status =
|
|
13145
|
+
proposal.status = import_types20.ProposalStatus.CANCELLED;
|
|
12655
13146
|
return proposal;
|
|
12656
13147
|
}
|
|
12657
13148
|
// ─── Auditor Access ──────────────────────────────────────────────────────────
|
|
@@ -12748,7 +13239,7 @@ var Treasury = class _Treasury {
|
|
|
12748
13239
|
getCommittedAmount(token) {
|
|
12749
13240
|
let committed = 0n;
|
|
12750
13241
|
for (const proposal of this.proposals.values()) {
|
|
12751
|
-
if (proposal.status !==
|
|
13242
|
+
if (proposal.status !== import_types20.ProposalStatus.PENDING) continue;
|
|
12752
13243
|
if (proposal.type === "payment" && proposal.payment) {
|
|
12753
13244
|
if (proposal.payment.token.symbol === token.symbol && proposal.payment.token.chain === token.chain) {
|
|
12754
13245
|
committed += proposal.payment.amount;
|
|
@@ -12991,7 +13482,7 @@ function validateBatchProposalParams(params, config) {
|
|
|
12991
13482
|
}
|
|
12992
13483
|
|
|
12993
13484
|
// src/compliance/compliance-manager.ts
|
|
12994
|
-
var
|
|
13485
|
+
var import_types21 = require("@sip-protocol/types");
|
|
12995
13486
|
var import_utils21 = require("@noble/hashes/utils");
|
|
12996
13487
|
init_errors();
|
|
12997
13488
|
var DEFAULTS2 = {
|
|
@@ -13360,7 +13851,7 @@ var ComplianceManager = class _ComplianceManager {
|
|
|
13360
13851
|
title: params.title,
|
|
13361
13852
|
description: params.description,
|
|
13362
13853
|
format: params.format,
|
|
13363
|
-
status:
|
|
13854
|
+
status: import_types21.ReportStatus.GENERATING,
|
|
13364
13855
|
requestedBy,
|
|
13365
13856
|
requestedAt: now,
|
|
13366
13857
|
startDate: params.startDate,
|
|
@@ -13389,10 +13880,10 @@ var ComplianceManager = class _ComplianceManager {
|
|
|
13389
13880
|
} else if (params.format === "csv") {
|
|
13390
13881
|
report.content = this.generateCSV(transactions);
|
|
13391
13882
|
}
|
|
13392
|
-
report.status =
|
|
13883
|
+
report.status = import_types21.ReportStatus.COMPLETED;
|
|
13393
13884
|
report.generatedAt = Math.floor(Date.now() / 1e3);
|
|
13394
13885
|
} catch (error) {
|
|
13395
|
-
report.status =
|
|
13886
|
+
report.status = import_types21.ReportStatus.FAILED;
|
|
13396
13887
|
report.error = error instanceof Error ? error.message : "Unknown error";
|
|
13397
13888
|
}
|
|
13398
13889
|
this.addAuditLog(requestedBy, "report_generated", {
|
|
@@ -15463,54 +15954,359 @@ var AuditorKeyDerivation = class {
|
|
|
15463
15954
|
}
|
|
15464
15955
|
};
|
|
15465
15956
|
|
|
15466
|
-
// src/
|
|
15957
|
+
// src/compliance/range-sas.ts
|
|
15958
|
+
var import_sha25620 = require("@noble/hashes/sha256");
|
|
15959
|
+
var import_hmac3 = require("@noble/hashes/hmac");
|
|
15960
|
+
var import_sha5124 = require("@noble/hashes/sha512");
|
|
15467
15961
|
var import_utils27 = require("@noble/hashes/utils");
|
|
15468
15962
|
init_errors();
|
|
15469
|
-
|
|
15963
|
+
init_secure_memory();
|
|
15964
|
+
var AttestationSchema = /* @__PURE__ */ ((AttestationSchema2) => {
|
|
15965
|
+
AttestationSchema2["RANGE_KYC_V1"] = "range-kyc-v1";
|
|
15966
|
+
AttestationSchema2["RANGE_ACCREDITED_INVESTOR"] = "range-accredited-investor";
|
|
15967
|
+
AttestationSchema2["RANGE_INSTITUTIONAL"] = "range-institutional";
|
|
15968
|
+
AttestationSchema2["RANGE_REGULATOR"] = "range-regulator";
|
|
15969
|
+
AttestationSchema2["CUSTOM"] = "custom";
|
|
15970
|
+
return AttestationSchema2;
|
|
15971
|
+
})(AttestationSchema || {});
|
|
15972
|
+
var DEFAULT_MAX_CACHE_SIZE = 1e3;
|
|
15973
|
+
var AttestationGatedDisclosure = class {
|
|
15974
|
+
config;
|
|
15975
|
+
derivedKeys = /* @__PURE__ */ new Map();
|
|
15976
|
+
cacheOrder = [];
|
|
15977
|
+
// LRU tracking
|
|
15470
15978
|
/**
|
|
15471
|
-
* Create a
|
|
15472
|
-
*
|
|
15473
|
-
* Generates a cryptographically binding commitment to a bid amount.
|
|
15474
|
-
* The commitment can be published publicly without revealing the bid.
|
|
15979
|
+
* Create a new attestation-gated disclosure manager
|
|
15475
15980
|
*
|
|
15476
|
-
*
|
|
15477
|
-
|
|
15981
|
+
* @param config - Configuration options
|
|
15982
|
+
*/
|
|
15983
|
+
constructor(config) {
|
|
15984
|
+
if (!config.masterViewingKey) {
|
|
15985
|
+
throw new ValidationError(
|
|
15986
|
+
"masterViewingKey is required",
|
|
15987
|
+
"masterViewingKey",
|
|
15988
|
+
void 0,
|
|
15989
|
+
"SIP_2008" /* MISSING_REQUIRED */
|
|
15990
|
+
);
|
|
15991
|
+
}
|
|
15992
|
+
this.config = {
|
|
15993
|
+
masterViewingKey: config.masterViewingKey,
|
|
15994
|
+
allowedSchemas: config.allowedSchemas ?? [],
|
|
15995
|
+
allowedIssuers: config.allowedIssuers ?? [],
|
|
15996
|
+
verifyOnChain: config.verifyOnChain ?? false,
|
|
15997
|
+
rangeApiEndpoint: config.rangeApiEndpoint ?? "https://api.range.org/v1",
|
|
15998
|
+
minAttestationAge: config.minAttestationAge ?? 0,
|
|
15999
|
+
maxAttestationAge: config.maxAttestationAge ?? 0,
|
|
16000
|
+
// 0 = no limit
|
|
16001
|
+
maxCacheSize: config.maxCacheSize ?? DEFAULT_MAX_CACHE_SIZE,
|
|
16002
|
+
customVerifier: config.customVerifier ?? (async () => true)
|
|
16003
|
+
};
|
|
16004
|
+
}
|
|
16005
|
+
/**
|
|
16006
|
+
* Derive a viewing key for a verified auditor
|
|
15478
16007
|
*
|
|
15479
|
-
* @param
|
|
15480
|
-
* @
|
|
15481
|
-
* @
|
|
16008
|
+
* @param attestation - The auditor's Range SAS attestation
|
|
16009
|
+
* @param scope - Optional scope restrictions for the viewing key
|
|
16010
|
+
* @returns Derivation result with viewing key if granted
|
|
15482
16011
|
*
|
|
15483
16012
|
* @example
|
|
15484
16013
|
* ```typescript
|
|
15485
|
-
* const
|
|
15486
|
-
*
|
|
15487
|
-
*
|
|
15488
|
-
* const receipt = auction.createBid({
|
|
15489
|
-
* auctionId: 'auction-xyz',
|
|
15490
|
-
* amount: 50n * 10n**18n,
|
|
15491
|
-
* })
|
|
15492
|
-
*
|
|
15493
|
-
* // Public data (safe to publish)
|
|
15494
|
-
* console.log({
|
|
15495
|
-
* auctionId: receipt.auctionId,
|
|
15496
|
-
* commitment: receipt.commitment,
|
|
15497
|
-
* timestamp: receipt.timestamp,
|
|
16014
|
+
* const result = await disclosure.deriveViewingKeyForAuditor(attestation, {
|
|
16015
|
+
* startTime: Date.now() / 1000 - 30 * 24 * 60 * 60, // Last 30 days
|
|
16016
|
+
* endTime: Date.now() / 1000,
|
|
15498
16017
|
* })
|
|
15499
16018
|
*
|
|
15500
|
-
*
|
|
15501
|
-
*
|
|
15502
|
-
*
|
|
15503
|
-
* salt: receipt.salt,
|
|
15504
|
-
* })
|
|
16019
|
+
* if (result.granted) {
|
|
16020
|
+
* // Share result.viewingKey with auditor
|
|
16021
|
+
* }
|
|
15505
16022
|
* ```
|
|
15506
16023
|
*/
|
|
15507
|
-
|
|
15508
|
-
|
|
15509
|
-
|
|
15510
|
-
|
|
15511
|
-
|
|
15512
|
-
|
|
15513
|
-
|
|
16024
|
+
async deriveViewingKeyForAuditor(attestation, scope) {
|
|
16025
|
+
const verification = await this.verifyAttestation(attestation);
|
|
16026
|
+
if (!verification.valid) {
|
|
16027
|
+
return {
|
|
16028
|
+
granted: false,
|
|
16029
|
+
reason: verification.errors.join("; ")
|
|
16030
|
+
};
|
|
16031
|
+
}
|
|
16032
|
+
const cacheKey = this.getCacheKey(attestation);
|
|
16033
|
+
const cached = this.derivedKeys.get(cacheKey);
|
|
16034
|
+
if (cached) {
|
|
16035
|
+
this.updateCacheOrder(cacheKey);
|
|
16036
|
+
return {
|
|
16037
|
+
granted: true,
|
|
16038
|
+
viewingKey: cached,
|
|
16039
|
+
scope,
|
|
16040
|
+
expiresAt: attestation.expiresAt
|
|
16041
|
+
// 0 = never expires, undefined = not set
|
|
16042
|
+
};
|
|
16043
|
+
}
|
|
16044
|
+
const viewingKey = this.deriveKeyFromAttestation(attestation);
|
|
16045
|
+
this.cacheKey(cacheKey, viewingKey);
|
|
16046
|
+
return {
|
|
16047
|
+
granted: true,
|
|
16048
|
+
viewingKey,
|
|
16049
|
+
scope,
|
|
16050
|
+
expiresAt: attestation.expiresAt
|
|
16051
|
+
// 0 = never expires, undefined = not set
|
|
16052
|
+
};
|
|
16053
|
+
}
|
|
16054
|
+
/**
|
|
16055
|
+
* Verify a Range SAS attestation
|
|
16056
|
+
*
|
|
16057
|
+
* @param attestation - The attestation to verify
|
|
16058
|
+
* @returns Verification result
|
|
16059
|
+
*/
|
|
16060
|
+
async verifyAttestation(attestation) {
|
|
16061
|
+
const errors = [];
|
|
16062
|
+
if (!attestation || typeof attestation !== "object") {
|
|
16063
|
+
return {
|
|
16064
|
+
valid: false,
|
|
16065
|
+
errors: ["Attestation must be an object"]
|
|
16066
|
+
};
|
|
16067
|
+
}
|
|
16068
|
+
if (!attestation.uid || typeof attestation.uid !== "string" || attestation.uid.trim() === "") {
|
|
16069
|
+
errors.push("Attestation uid is required and must be a non-empty string");
|
|
16070
|
+
}
|
|
16071
|
+
if (!attestation.subject || typeof attestation.subject !== "string" || attestation.subject.trim() === "") {
|
|
16072
|
+
errors.push("Attestation subject is required and must be a non-empty string");
|
|
16073
|
+
}
|
|
16074
|
+
if (!attestation.schema || typeof attestation.schema !== "string" || attestation.schema.trim() === "") {
|
|
16075
|
+
errors.push("Attestation schema is required and must be a non-empty string");
|
|
16076
|
+
}
|
|
16077
|
+
if (!attestation.issuer || typeof attestation.issuer !== "string" || attestation.issuer.trim() === "") {
|
|
16078
|
+
errors.push("Attestation issuer is required and must be a non-empty string");
|
|
16079
|
+
}
|
|
16080
|
+
if (errors.length > 0) {
|
|
16081
|
+
return { valid: false, errors };
|
|
16082
|
+
}
|
|
16083
|
+
if (attestation.revoked) {
|
|
16084
|
+
errors.push("Attestation has been revoked");
|
|
16085
|
+
}
|
|
16086
|
+
const now = Date.now() / 1e3;
|
|
16087
|
+
if (attestation.expiresAt > 0 && attestation.expiresAt < now) {
|
|
16088
|
+
errors.push("Attestation has expired");
|
|
16089
|
+
}
|
|
16090
|
+
const age = now - attestation.timestamp;
|
|
16091
|
+
if (age < this.config.minAttestationAge) {
|
|
16092
|
+
errors.push(`Attestation too new (age: ${age}s, required: ${this.config.minAttestationAge}s)`);
|
|
16093
|
+
}
|
|
16094
|
+
if (this.config.maxAttestationAge > 0 && age > this.config.maxAttestationAge) {
|
|
16095
|
+
errors.push(`Attestation too old (age: ${Math.floor(age)}s, max: ${this.config.maxAttestationAge}s)`);
|
|
16096
|
+
}
|
|
16097
|
+
if (this.config.allowedSchemas.length > 0) {
|
|
16098
|
+
if (!this.config.allowedSchemas.includes(attestation.schema)) {
|
|
16099
|
+
errors.push(`Schema '${attestation.schema}' not in allowed list`);
|
|
16100
|
+
}
|
|
16101
|
+
}
|
|
16102
|
+
if (this.config.allowedIssuers.length > 0) {
|
|
16103
|
+
if (!this.config.allowedIssuers.includes(attestation.issuer)) {
|
|
16104
|
+
errors.push(`Issuer '${attestation.issuer}' not in allowed list`);
|
|
16105
|
+
}
|
|
16106
|
+
}
|
|
16107
|
+
if (errors.length === 0 && this.config.customVerifier) {
|
|
16108
|
+
try {
|
|
16109
|
+
const customValid = await this.config.customVerifier(attestation);
|
|
16110
|
+
if (!customValid) {
|
|
16111
|
+
errors.push("Custom verification failed");
|
|
16112
|
+
}
|
|
16113
|
+
} catch (e) {
|
|
16114
|
+
errors.push(`Custom verification error: ${e instanceof Error ? e.message : "unknown"}`);
|
|
16115
|
+
}
|
|
16116
|
+
}
|
|
16117
|
+
return {
|
|
16118
|
+
valid: errors.length === 0,
|
|
16119
|
+
errors,
|
|
16120
|
+
metadata: {
|
|
16121
|
+
verificationMethod: this.config.verifyOnChain ? "on-chain" : "api",
|
|
16122
|
+
schemaVersion: attestation.schema
|
|
16123
|
+
}
|
|
16124
|
+
};
|
|
16125
|
+
}
|
|
16126
|
+
/**
|
|
16127
|
+
* Revoke a previously derived viewing key
|
|
16128
|
+
*
|
|
16129
|
+
* @param attestation - The attestation whose key should be revoked
|
|
16130
|
+
* @returns Whether revocation was successful
|
|
16131
|
+
*/
|
|
16132
|
+
revokeViewingKey(attestation) {
|
|
16133
|
+
const key = this.getCacheKey(attestation);
|
|
16134
|
+
const deleted = this.derivedKeys.delete(key);
|
|
16135
|
+
if (deleted) {
|
|
16136
|
+
const index = this.cacheOrder.indexOf(key);
|
|
16137
|
+
if (index !== -1) {
|
|
16138
|
+
this.cacheOrder.splice(index, 1);
|
|
16139
|
+
}
|
|
16140
|
+
}
|
|
16141
|
+
return deleted;
|
|
16142
|
+
}
|
|
16143
|
+
/**
|
|
16144
|
+
* Check if a viewing key has been derived for an attestation
|
|
16145
|
+
*
|
|
16146
|
+
* @param attestation - The attestation to check
|
|
16147
|
+
* @returns Whether a key exists
|
|
16148
|
+
*/
|
|
16149
|
+
hasViewingKey(attestation) {
|
|
16150
|
+
const key = this.getCacheKey(attestation);
|
|
16151
|
+
return this.derivedKeys.has(key);
|
|
16152
|
+
}
|
|
16153
|
+
/**
|
|
16154
|
+
* Get the current cache size
|
|
16155
|
+
*
|
|
16156
|
+
* @returns Number of cached viewing keys
|
|
16157
|
+
*/
|
|
16158
|
+
getCacheSize() {
|
|
16159
|
+
return this.derivedKeys.size;
|
|
16160
|
+
}
|
|
16161
|
+
/**
|
|
16162
|
+
* Clear all cached viewing keys
|
|
16163
|
+
*/
|
|
16164
|
+
clearCache() {
|
|
16165
|
+
this.derivedKeys.clear();
|
|
16166
|
+
this.cacheOrder.length = 0;
|
|
16167
|
+
}
|
|
16168
|
+
// ─── Private Methods ────────────────────────────────────────────────────────
|
|
16169
|
+
/**
|
|
16170
|
+
* Add a key to cache with LRU eviction
|
|
16171
|
+
*/
|
|
16172
|
+
cacheKey(key, viewingKey) {
|
|
16173
|
+
while (this.derivedKeys.size >= this.config.maxCacheSize && this.cacheOrder.length > 0) {
|
|
16174
|
+
const oldest = this.cacheOrder.shift();
|
|
16175
|
+
if (oldest) {
|
|
16176
|
+
this.derivedKeys.delete(oldest);
|
|
16177
|
+
}
|
|
16178
|
+
}
|
|
16179
|
+
this.derivedKeys.set(key, viewingKey);
|
|
16180
|
+
this.cacheOrder.push(key);
|
|
16181
|
+
}
|
|
16182
|
+
/**
|
|
16183
|
+
* Update LRU order for a cache key (move to end)
|
|
16184
|
+
*/
|
|
16185
|
+
updateCacheOrder(key) {
|
|
16186
|
+
const index = this.cacheOrder.indexOf(key);
|
|
16187
|
+
if (index !== -1) {
|
|
16188
|
+
this.cacheOrder.splice(index, 1);
|
|
16189
|
+
this.cacheOrder.push(key);
|
|
16190
|
+
}
|
|
16191
|
+
}
|
|
16192
|
+
/**
|
|
16193
|
+
* Derive a viewing key from an attestation
|
|
16194
|
+
*/
|
|
16195
|
+
deriveKeyFromAttestation(attestation) {
|
|
16196
|
+
const masterKeyHex = this.config.masterViewingKey.key.startsWith("0x") ? this.config.masterViewingKey.key.slice(2) : this.config.masterViewingKey.key;
|
|
16197
|
+
const masterKeyBytes = (0, import_utils27.hexToBytes)(masterKeyHex);
|
|
16198
|
+
const derivationData = (0, import_utils27.utf8ToBytes)(
|
|
16199
|
+
`SIP-RANGE-SAS:${attestation.uid}:${attestation.subject}:${attestation.schema}:${attestation.signature}`
|
|
16200
|
+
);
|
|
16201
|
+
const derived = (0, import_hmac3.hmac)(import_sha5124.sha512, masterKeyBytes, derivationData);
|
|
16202
|
+
const keyBytes = derived.slice(0, 32);
|
|
16203
|
+
try {
|
|
16204
|
+
const key = `0x${(0, import_utils27.bytesToHex)(keyBytes)}`;
|
|
16205
|
+
const hashBytes = (0, import_sha25620.sha256)(keyBytes);
|
|
16206
|
+
const hash2 = `0x${(0, import_utils27.bytesToHex)(hashBytes)}`;
|
|
16207
|
+
return {
|
|
16208
|
+
key,
|
|
16209
|
+
path: `${this.config.masterViewingKey.path}/sas/${attestation.uid.slice(0, 8)}`,
|
|
16210
|
+
hash: hash2
|
|
16211
|
+
};
|
|
16212
|
+
} finally {
|
|
16213
|
+
secureWipe(masterKeyBytes);
|
|
16214
|
+
secureWipe(derived);
|
|
16215
|
+
secureWipe(keyBytes);
|
|
16216
|
+
}
|
|
16217
|
+
}
|
|
16218
|
+
/**
|
|
16219
|
+
* Get cache key for an attestation
|
|
16220
|
+
*
|
|
16221
|
+
* Includes schema and issuer to prevent cache poisoning attacks where
|
|
16222
|
+
* an attacker could evict legitimate cache entries with same uid:subject.
|
|
16223
|
+
*/
|
|
16224
|
+
getCacheKey(attestation) {
|
|
16225
|
+
return `${attestation.uid}:${attestation.subject}:${attestation.schema}:${attestation.issuer}`;
|
|
16226
|
+
}
|
|
16227
|
+
};
|
|
16228
|
+
function createMockAttestation(overrides = {}) {
|
|
16229
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
16230
|
+
return {
|
|
16231
|
+
uid: `sas_${Math.random().toString(36).slice(2, 10)}`,
|
|
16232
|
+
schema: "range-kyc-v1" /* RANGE_KYC_V1 */,
|
|
16233
|
+
issuer: "range-protocol",
|
|
16234
|
+
subject: "11111111111111111111111111111112",
|
|
16235
|
+
// System program (placeholder)
|
|
16236
|
+
data: {
|
|
16237
|
+
level: "institutional",
|
|
16238
|
+
jurisdiction: "US",
|
|
16239
|
+
verifiedAt: now
|
|
16240
|
+
},
|
|
16241
|
+
timestamp: now,
|
|
16242
|
+
expiresAt: now + 365 * 24 * 60 * 60,
|
|
16243
|
+
// 1 year
|
|
16244
|
+
signature: "0x" + "00".repeat(64),
|
|
16245
|
+
revoked: false,
|
|
16246
|
+
...overrides
|
|
16247
|
+
};
|
|
16248
|
+
}
|
|
16249
|
+
async function verifyAttestationSignature(_attestation) {
|
|
16250
|
+
console.warn(
|
|
16251
|
+
"[Range SAS] verifyAttestationSignature is a STUB - always returns true. Implement real Ed25519 signature verification before production use."
|
|
16252
|
+
);
|
|
16253
|
+
return true;
|
|
16254
|
+
}
|
|
16255
|
+
async function fetchAttestation(uid, apiEndpoint = "https://api.range.org/v1") {
|
|
16256
|
+
console.warn(
|
|
16257
|
+
`[Range SAS] fetchAttestation is a STUB - returning null for ${uid}. Would fetch from ${apiEndpoint}. Implement Range API integration before production use.`
|
|
16258
|
+
);
|
|
16259
|
+
return null;
|
|
16260
|
+
}
|
|
16261
|
+
|
|
16262
|
+
// src/auction/sealed-bid.ts
|
|
16263
|
+
var import_utils28 = require("@noble/hashes/utils");
|
|
16264
|
+
init_errors();
|
|
16265
|
+
var SealedBidAuction = class {
|
|
16266
|
+
/**
|
|
16267
|
+
* Create a sealed bid for an auction
|
|
16268
|
+
*
|
|
16269
|
+
* Generates a cryptographically binding commitment to a bid amount.
|
|
16270
|
+
* The commitment can be published publicly without revealing the bid.
|
|
16271
|
+
*
|
|
16272
|
+
* **Important:** Keep the returned `BidReceipt` secret! It contains the bid
|
|
16273
|
+
* amount and salt needed to reveal the bid later. Only publish the commitment.
|
|
16274
|
+
*
|
|
16275
|
+
* @param params - Bid creation parameters
|
|
16276
|
+
* @returns Complete bid receipt (keep secret!) and sealed bid (publish this)
|
|
16277
|
+
* @throws {ValidationError} If auctionId is empty, amount is non-positive, or salt is invalid
|
|
16278
|
+
*
|
|
16279
|
+
* @example
|
|
16280
|
+
* ```typescript
|
|
16281
|
+
* const auction = new SealedBidAuction()
|
|
16282
|
+
*
|
|
16283
|
+
* // Create a bid for 50 ETH
|
|
16284
|
+
* const receipt = auction.createBid({
|
|
16285
|
+
* auctionId: 'auction-xyz',
|
|
16286
|
+
* amount: 50n * 10n**18n,
|
|
16287
|
+
* })
|
|
16288
|
+
*
|
|
16289
|
+
* // Public data (safe to publish)
|
|
16290
|
+
* console.log({
|
|
16291
|
+
* auctionId: receipt.auctionId,
|
|
16292
|
+
* commitment: receipt.commitment,
|
|
16293
|
+
* timestamp: receipt.timestamp,
|
|
16294
|
+
* })
|
|
16295
|
+
*
|
|
16296
|
+
* // Secret data (store securely, needed for reveal)
|
|
16297
|
+
* secureStorage.save({
|
|
16298
|
+
* amount: receipt.amount,
|
|
16299
|
+
* salt: receipt.salt,
|
|
16300
|
+
* })
|
|
16301
|
+
* ```
|
|
16302
|
+
*/
|
|
16303
|
+
createBid(params) {
|
|
16304
|
+
if (typeof params.auctionId !== "string" || params.auctionId.length === 0) {
|
|
16305
|
+
throw new ValidationError(
|
|
16306
|
+
"auctionId must be a non-empty string",
|
|
16307
|
+
"auctionId",
|
|
16308
|
+
{ received: params.auctionId }
|
|
16309
|
+
);
|
|
15514
16310
|
}
|
|
15515
16311
|
if (typeof params.amount !== "bigint") {
|
|
15516
16312
|
throw new ValidationError(
|
|
@@ -15542,7 +16338,7 @@ var SealedBidAuction = class {
|
|
|
15542
16338
|
);
|
|
15543
16339
|
}
|
|
15544
16340
|
}
|
|
15545
|
-
const salt = params.salt ?? (0,
|
|
16341
|
+
const salt = params.salt ?? (0, import_utils28.randomBytes)(32);
|
|
15546
16342
|
const { commitment, blinding } = commit(params.amount, salt);
|
|
15547
16343
|
const sealedBid = {
|
|
15548
16344
|
auctionId: params.auctionId,
|
|
@@ -15686,7 +16482,7 @@ var SealedBidAuction = class {
|
|
|
15686
16482
|
* ```
|
|
15687
16483
|
*/
|
|
15688
16484
|
revealBid(bid, amount, salt) {
|
|
15689
|
-
const saltHex = `0x${(0,
|
|
16485
|
+
const saltHex = `0x${(0, import_utils28.bytesToHex)(salt)}`;
|
|
15690
16486
|
const isValid = this.verifyBid({
|
|
15691
16487
|
commitment: bid.commitment,
|
|
15692
16488
|
amount,
|
|
@@ -16171,9 +16967,9 @@ function createSealedBidAuction() {
|
|
|
16171
16967
|
}
|
|
16172
16968
|
|
|
16173
16969
|
// src/governance/private-vote.ts
|
|
16174
|
-
var
|
|
16970
|
+
var import_sha25621 = require("@noble/hashes/sha256");
|
|
16175
16971
|
var import_hkdf3 = require("@noble/hashes/hkdf");
|
|
16176
|
-
var
|
|
16972
|
+
var import_utils29 = require("@noble/hashes/utils");
|
|
16177
16973
|
var import_chacha4 = require("@noble/ciphers/chacha.js");
|
|
16178
16974
|
init_errors();
|
|
16179
16975
|
init_secure_memory();
|
|
@@ -16213,7 +17009,7 @@ var PrivateVoting = class {
|
|
|
16213
17009
|
const { proposalId, choice, weight, encryptionKey, voter = "anonymous" } = params;
|
|
16214
17010
|
const derivedKey = this.deriveEncryptionKey(encryptionKey, proposalId);
|
|
16215
17011
|
try {
|
|
16216
|
-
const nonce = (0,
|
|
17012
|
+
const nonce = (0, import_utils29.randomBytes)(NONCE_SIZE2);
|
|
16217
17013
|
const voteData = {
|
|
16218
17014
|
proposalId,
|
|
16219
17015
|
choice,
|
|
@@ -16221,14 +17017,14 @@ var PrivateVoting = class {
|
|
|
16221
17017
|
voter,
|
|
16222
17018
|
timestamp: Date.now()
|
|
16223
17019
|
};
|
|
16224
|
-
const plaintext = (0,
|
|
17020
|
+
const plaintext = (0, import_utils29.utf8ToBytes)(JSON.stringify(voteData));
|
|
16225
17021
|
const cipher = (0, import_chacha4.xchacha20poly1305)(derivedKey, nonce);
|
|
16226
17022
|
const ciphertext = cipher.encrypt(plaintext);
|
|
16227
|
-
const keyHash = (0,
|
|
17023
|
+
const keyHash = (0, import_sha25621.sha256)((0, import_utils29.hexToBytes)(encryptionKey.slice(2)));
|
|
16228
17024
|
return {
|
|
16229
|
-
ciphertext: `0x${(0,
|
|
16230
|
-
nonce: `0x${(0,
|
|
16231
|
-
encryptionKeyHash: `0x${(0,
|
|
17025
|
+
ciphertext: `0x${(0, import_utils29.bytesToHex)(ciphertext)}`,
|
|
17026
|
+
nonce: `0x${(0, import_utils29.bytesToHex)(nonce)}`,
|
|
17027
|
+
encryptionKeyHash: `0x${(0, import_utils29.bytesToHex)(keyHash)}`,
|
|
16232
17028
|
proposalId,
|
|
16233
17029
|
voter,
|
|
16234
17030
|
timestamp: voteData.timestamp
|
|
@@ -16274,8 +17070,8 @@ var PrivateVoting = class {
|
|
|
16274
17070
|
}
|
|
16275
17071
|
const derivedKey = this.deriveEncryptionKey(decryptionKey, vote.proposalId);
|
|
16276
17072
|
try {
|
|
16277
|
-
const keyHash = (0,
|
|
16278
|
-
const expectedKeyHash = `0x${(0,
|
|
17073
|
+
const keyHash = (0, import_sha25621.sha256)((0, import_utils29.hexToBytes)(decryptionKey.slice(2)));
|
|
17074
|
+
const expectedKeyHash = `0x${(0, import_utils29.bytesToHex)(keyHash)}`;
|
|
16279
17075
|
if (vote.encryptionKeyHash !== expectedKeyHash) {
|
|
16280
17076
|
throw new CryptoError(
|
|
16281
17077
|
"Decryption key hash mismatch - this key cannot decrypt this vote",
|
|
@@ -16284,9 +17080,9 @@ var PrivateVoting = class {
|
|
|
16284
17080
|
);
|
|
16285
17081
|
}
|
|
16286
17082
|
const nonceHex = vote.nonce.startsWith("0x") ? vote.nonce.slice(2) : vote.nonce;
|
|
16287
|
-
const nonce = (0,
|
|
17083
|
+
const nonce = (0, import_utils29.hexToBytes)(nonceHex);
|
|
16288
17084
|
const ciphertextHex = vote.ciphertext.startsWith("0x") ? vote.ciphertext.slice(2) : vote.ciphertext;
|
|
16289
|
-
const ciphertext = (0,
|
|
17085
|
+
const ciphertext = (0, import_utils29.hexToBytes)(ciphertextHex);
|
|
16290
17086
|
const cipher = (0, import_chacha4.xchacha20poly1305)(derivedKey, nonce);
|
|
16291
17087
|
let plaintext;
|
|
16292
17088
|
try {
|
|
@@ -16375,11 +17171,11 @@ var PrivateVoting = class {
|
|
|
16375
17171
|
*/
|
|
16376
17172
|
deriveEncryptionKey(key, proposalId) {
|
|
16377
17173
|
const keyHex = key.startsWith("0x") ? key.slice(2) : key;
|
|
16378
|
-
const keyBytes = (0,
|
|
17174
|
+
const keyBytes = (0, import_utils29.hexToBytes)(keyHex);
|
|
16379
17175
|
try {
|
|
16380
|
-
const salt = (0,
|
|
16381
|
-
const info = (0,
|
|
16382
|
-
return (0, import_hkdf3.hkdf)(
|
|
17176
|
+
const salt = (0, import_utils29.utf8ToBytes)(VOTE_ENCRYPTION_DOMAIN);
|
|
17177
|
+
const info = (0, import_utils29.utf8ToBytes)(proposalId);
|
|
17178
|
+
return (0, import_hkdf3.hkdf)(import_sha25621.sha256, keyBytes, salt, info, 32);
|
|
16383
17179
|
} finally {
|
|
16384
17180
|
secureWipe(keyBytes);
|
|
16385
17181
|
}
|
|
@@ -16524,21 +17320,21 @@ var PrivateVoting = class {
|
|
|
16524
17320
|
const blindings = {};
|
|
16525
17321
|
for (const [choice, weights] of Object.entries(votesByChoice)) {
|
|
16526
17322
|
const totalWeight = weights.reduce((sum, w) => sum + w, 0n);
|
|
16527
|
-
const { commitment, blinding } = commit(totalWeight, (0,
|
|
17323
|
+
const { commitment, blinding } = commit(totalWeight, (0, import_utils29.hexToBytes)(generateBlinding().slice(2)));
|
|
16528
17324
|
tallies[choice] = commitment;
|
|
16529
17325
|
blindings[choice] = blinding;
|
|
16530
17326
|
}
|
|
16531
17327
|
const encryptedBlindings = {};
|
|
16532
17328
|
for (const [choice, blinding] of Object.entries(blindings)) {
|
|
16533
|
-
const nonce = (0,
|
|
17329
|
+
const nonce = (0, import_utils29.randomBytes)(NONCE_SIZE2);
|
|
16534
17330
|
const derivedKey = this.deriveEncryptionKey(decryptionKey, `${proposalId}-tally-${choice}`);
|
|
16535
17331
|
try {
|
|
16536
17332
|
const cipher = (0, import_chacha4.xchacha20poly1305)(derivedKey, nonce);
|
|
16537
|
-
const blindingBytes = (0,
|
|
17333
|
+
const blindingBytes = (0, import_utils29.hexToBytes)(blinding.slice(2));
|
|
16538
17334
|
const ciphertext = cipher.encrypt(blindingBytes);
|
|
16539
17335
|
encryptedBlindings[choice] = {
|
|
16540
|
-
ciphertext: `0x${(0,
|
|
16541
|
-
nonce: `0x${(0,
|
|
17336
|
+
ciphertext: `0x${(0, import_utils29.bytesToHex)(ciphertext)}`,
|
|
17337
|
+
nonce: `0x${(0, import_utils29.bytesToHex)(nonce)}`
|
|
16542
17338
|
};
|
|
16543
17339
|
} finally {
|
|
16544
17340
|
secureWipe(derivedKey);
|
|
@@ -16631,9 +17427,9 @@ var PrivateVoting = class {
|
|
|
16631
17427
|
}
|
|
16632
17428
|
let reconstructedKey = null;
|
|
16633
17429
|
try {
|
|
16634
|
-
reconstructedKey = (0,
|
|
17430
|
+
reconstructedKey = (0, import_utils29.hexToBytes)(decryptionShares[0].share.slice(2));
|
|
16635
17431
|
for (let i = 1; i < decryptionShares.length; i++) {
|
|
16636
|
-
const shareBytes = (0,
|
|
17432
|
+
const shareBytes = (0, import_utils29.hexToBytes)(decryptionShares[i].share.slice(2));
|
|
16637
17433
|
if (shareBytes.length !== reconstructedKey.length) {
|
|
16638
17434
|
throw new ValidationError(
|
|
16639
17435
|
"all decryption shares must have the same length",
|
|
@@ -16646,7 +17442,7 @@ var PrivateVoting = class {
|
|
|
16646
17442
|
reconstructedKey[j] ^= shareBytes[j];
|
|
16647
17443
|
}
|
|
16648
17444
|
}
|
|
16649
|
-
const reconstructedKeyHex = `0x${(0,
|
|
17445
|
+
const reconstructedKeyHex = `0x${(0, import_utils29.bytesToHex)(reconstructedKey)}`;
|
|
16650
17446
|
const results = {};
|
|
16651
17447
|
for (const [choice, commitmentPoint] of Object.entries(tally.tallies)) {
|
|
16652
17448
|
const encBlinding = tally.encryptedBlindings[choice];
|
|
@@ -16663,11 +17459,11 @@ var PrivateVoting = class {
|
|
|
16663
17459
|
);
|
|
16664
17460
|
let blindingFactor;
|
|
16665
17461
|
try {
|
|
16666
|
-
const nonceBytes = (0,
|
|
16667
|
-
const ciphertextBytes = (0,
|
|
17462
|
+
const nonceBytes = (0, import_utils29.hexToBytes)(encBlinding.nonce.slice(2));
|
|
17463
|
+
const ciphertextBytes = (0, import_utils29.hexToBytes)(encBlinding.ciphertext.slice(2));
|
|
16668
17464
|
const cipher = (0, import_chacha4.xchacha20poly1305)(derivedKey, nonceBytes);
|
|
16669
17465
|
const blindingBytes = cipher.decrypt(ciphertextBytes);
|
|
16670
|
-
blindingFactor = `0x${(0,
|
|
17466
|
+
blindingFactor = `0x${(0, import_utils29.bytesToHex)(blindingBytes)}`;
|
|
16671
17467
|
} catch (e) {
|
|
16672
17468
|
throw new CryptoError(
|
|
16673
17469
|
"failed to decrypt blinding factor",
|
|
@@ -16687,7 +17483,7 @@ var PrivateVoting = class {
|
|
|
16687
17483
|
try {
|
|
16688
17484
|
const { commitment: testCommit } = commit(
|
|
16689
17485
|
value,
|
|
16690
|
-
(0,
|
|
17486
|
+
(0, import_utils29.hexToBytes)(blindingFactor.slice(2))
|
|
16691
17487
|
);
|
|
16692
17488
|
if (testCommit === commitmentPoint) {
|
|
16693
17489
|
results[choice] = value;
|
|
@@ -16887,9 +17683,9 @@ function createPrivateVoting() {
|
|
|
16887
17683
|
}
|
|
16888
17684
|
|
|
16889
17685
|
// src/nft/private-nft.ts
|
|
16890
|
-
var
|
|
17686
|
+
var import_sha25622 = require("@noble/hashes/sha256");
|
|
16891
17687
|
var import_secp256k18 = require("@noble/curves/secp256k1");
|
|
16892
|
-
var
|
|
17688
|
+
var import_utils30 = require("@noble/hashes/utils");
|
|
16893
17689
|
init_stealth();
|
|
16894
17690
|
init_errors();
|
|
16895
17691
|
init_validation();
|
|
@@ -16978,23 +17774,23 @@ var PrivateNFT = class {
|
|
|
16978
17774
|
const { ownership, challenge, stealthPrivateKey } = params;
|
|
16979
17775
|
try {
|
|
16980
17776
|
const message = this.createProofMessage(ownership, challenge);
|
|
16981
|
-
const messageHash = (0,
|
|
16982
|
-
const privateKeyBytes = (0,
|
|
17777
|
+
const messageHash = (0, import_sha25622.sha256)(new TextEncoder().encode(message));
|
|
17778
|
+
const privateKeyBytes = (0, import_utils30.hexToBytes)(stealthPrivateKey.slice(2));
|
|
16983
17779
|
const signature = import_secp256k18.secp256k1.sign(messageHash, privateKeyBytes);
|
|
16984
17780
|
const zkProof = {
|
|
16985
17781
|
type: "ownership",
|
|
16986
|
-
proof: `0x${(0,
|
|
17782
|
+
proof: `0x${(0, import_utils30.bytesToHex)(signature.toCompactRawBytes())}`,
|
|
16987
17783
|
publicInputs: [
|
|
16988
|
-
`0x${(0,
|
|
17784
|
+
`0x${(0, import_utils30.bytesToHex)(messageHash)}`
|
|
16989
17785
|
]
|
|
16990
17786
|
};
|
|
16991
|
-
const stealthHashBytes = (0,
|
|
17787
|
+
const stealthHashBytes = (0, import_sha25622.sha256)((0, import_utils30.hexToBytes)(ownership.ownerStealth.address.slice(2)));
|
|
16992
17788
|
return {
|
|
16993
17789
|
nftContract: ownership.nftContract,
|
|
16994
17790
|
tokenId: ownership.tokenId,
|
|
16995
17791
|
challenge,
|
|
16996
17792
|
proof: zkProof,
|
|
16997
|
-
stealthHash: `0x${(0,
|
|
17793
|
+
stealthHash: `0x${(0, import_utils30.bytesToHex)(stealthHashBytes)}`,
|
|
16998
17794
|
timestamp: Date.now()
|
|
16999
17795
|
};
|
|
17000
17796
|
} catch (e) {
|
|
@@ -17036,9 +17832,9 @@ var PrivateNFT = class {
|
|
|
17036
17832
|
verifyOwnership(proof) {
|
|
17037
17833
|
try {
|
|
17038
17834
|
this.validateOwnershipProof(proof);
|
|
17039
|
-
const signatureBytes = (0,
|
|
17835
|
+
const signatureBytes = (0, import_utils30.hexToBytes)(proof.proof.proof.slice(2));
|
|
17040
17836
|
const signature = import_secp256k18.secp256k1.Signature.fromCompact(signatureBytes);
|
|
17041
|
-
const messageHash = (0,
|
|
17837
|
+
const messageHash = (0, import_utils30.hexToBytes)(proof.proof.publicInputs[0].slice(2));
|
|
17042
17838
|
if (signatureBytes.length !== 64) {
|
|
17043
17839
|
return {
|
|
17044
17840
|
valid: false,
|
|
@@ -17135,12 +17931,12 @@ var PrivateNFT = class {
|
|
|
17135
17931
|
chain: nft.chain,
|
|
17136
17932
|
timestamp: Date.now()
|
|
17137
17933
|
};
|
|
17138
|
-
const previousOwnerHashBytes = (0,
|
|
17934
|
+
const previousOwnerHashBytes = (0, import_sha25622.sha256)((0, import_utils30.hexToBytes)(nft.ownerStealth.address.slice(2)));
|
|
17139
17935
|
const transfer = {
|
|
17140
17936
|
nftContract: nft.nftContract,
|
|
17141
17937
|
tokenId: nft.tokenId,
|
|
17142
17938
|
newOwnerStealth,
|
|
17143
|
-
previousOwnerHash: `0x${(0,
|
|
17939
|
+
previousOwnerHash: `0x${(0, import_utils30.bytesToHex)(previousOwnerHashBytes)}`,
|
|
17144
17940
|
chain: nft.chain,
|
|
17145
17941
|
timestamp: Date.now()
|
|
17146
17942
|
};
|
|
@@ -17207,8 +18003,8 @@ var PrivateNFT = class {
|
|
|
17207
18003
|
);
|
|
17208
18004
|
}
|
|
17209
18005
|
const ownedNFTs = [];
|
|
17210
|
-
const scanKeyHex = `0x${(0,
|
|
17211
|
-
const viewingKeyHex = `0x${(0,
|
|
18006
|
+
const scanKeyHex = `0x${(0, import_utils30.bytesToHex)(scanKey)}`;
|
|
18007
|
+
const viewingKeyHex = `0x${(0, import_utils30.bytesToHex)(viewingKey)}`;
|
|
17212
18008
|
for (const transfer of transfers) {
|
|
17213
18009
|
try {
|
|
17214
18010
|
if (!transfer || typeof transfer !== "object") {
|
|
@@ -17426,10 +18222,10 @@ function verifyOwnership(proof) {
|
|
|
17426
18222
|
|
|
17427
18223
|
// src/wallet/errors.ts
|
|
17428
18224
|
init_errors();
|
|
17429
|
-
var
|
|
18225
|
+
var import_types22 = require("@sip-protocol/types");
|
|
17430
18226
|
var WalletError = class extends SIPError {
|
|
17431
18227
|
walletCode;
|
|
17432
|
-
constructor(message, walletCode =
|
|
18228
|
+
constructor(message, walletCode = import_types22.WalletErrorCode.UNKNOWN, options) {
|
|
17433
18229
|
super(message, "SIP_7000" /* WALLET_ERROR */, options);
|
|
17434
18230
|
this.walletCode = walletCode;
|
|
17435
18231
|
this.name = "WalletError";
|
|
@@ -17439,10 +18235,10 @@ var WalletError = class extends SIPError {
|
|
|
17439
18235
|
*/
|
|
17440
18236
|
isConnectionError() {
|
|
17441
18237
|
const codes = [
|
|
17442
|
-
|
|
17443
|
-
|
|
17444
|
-
|
|
17445
|
-
|
|
18238
|
+
import_types22.WalletErrorCode.NOT_INSTALLED,
|
|
18239
|
+
import_types22.WalletErrorCode.CONNECTION_REJECTED,
|
|
18240
|
+
import_types22.WalletErrorCode.CONNECTION_FAILED,
|
|
18241
|
+
import_types22.WalletErrorCode.NOT_CONNECTED
|
|
17446
18242
|
];
|
|
17447
18243
|
return codes.includes(this.walletCode);
|
|
17448
18244
|
}
|
|
@@ -17451,9 +18247,9 @@ var WalletError = class extends SIPError {
|
|
|
17451
18247
|
*/
|
|
17452
18248
|
isSigningError() {
|
|
17453
18249
|
const codes = [
|
|
17454
|
-
|
|
17455
|
-
|
|
17456
|
-
|
|
18250
|
+
import_types22.WalletErrorCode.SIGNING_REJECTED,
|
|
18251
|
+
import_types22.WalletErrorCode.SIGNING_FAILED,
|
|
18252
|
+
import_types22.WalletErrorCode.INVALID_MESSAGE
|
|
17457
18253
|
];
|
|
17458
18254
|
return codes.includes(this.walletCode);
|
|
17459
18255
|
}
|
|
@@ -17462,10 +18258,10 @@ var WalletError = class extends SIPError {
|
|
|
17462
18258
|
*/
|
|
17463
18259
|
isTransactionError() {
|
|
17464
18260
|
const codes = [
|
|
17465
|
-
|
|
17466
|
-
|
|
17467
|
-
|
|
17468
|
-
|
|
18261
|
+
import_types22.WalletErrorCode.INSUFFICIENT_FUNDS,
|
|
18262
|
+
import_types22.WalletErrorCode.TRANSACTION_REJECTED,
|
|
18263
|
+
import_types22.WalletErrorCode.TRANSACTION_FAILED,
|
|
18264
|
+
import_types22.WalletErrorCode.INVALID_TRANSACTION
|
|
17469
18265
|
];
|
|
17470
18266
|
return codes.includes(this.walletCode);
|
|
17471
18267
|
}
|
|
@@ -17474,9 +18270,9 @@ var WalletError = class extends SIPError {
|
|
|
17474
18270
|
*/
|
|
17475
18271
|
isPrivacyError() {
|
|
17476
18272
|
const codes = [
|
|
17477
|
-
|
|
17478
|
-
|
|
17479
|
-
|
|
18273
|
+
import_types22.WalletErrorCode.STEALTH_NOT_SUPPORTED,
|
|
18274
|
+
import_types22.WalletErrorCode.VIEWING_KEY_NOT_SUPPORTED,
|
|
18275
|
+
import_types22.WalletErrorCode.SHIELDED_NOT_SUPPORTED
|
|
17480
18276
|
];
|
|
17481
18277
|
return codes.includes(this.walletCode);
|
|
17482
18278
|
}
|
|
@@ -17485,10 +18281,10 @@ var WalletError = class extends SIPError {
|
|
|
17485
18281
|
*/
|
|
17486
18282
|
isUserRejection() {
|
|
17487
18283
|
const codes = [
|
|
17488
|
-
|
|
17489
|
-
|
|
17490
|
-
|
|
17491
|
-
|
|
18284
|
+
import_types22.WalletErrorCode.CONNECTION_REJECTED,
|
|
18285
|
+
import_types22.WalletErrorCode.SIGNING_REJECTED,
|
|
18286
|
+
import_types22.WalletErrorCode.TRANSACTION_REJECTED,
|
|
18287
|
+
import_types22.WalletErrorCode.CHAIN_SWITCH_REJECTED
|
|
17492
18288
|
];
|
|
17493
18289
|
return codes.includes(this.walletCode);
|
|
17494
18290
|
}
|
|
@@ -17496,15 +18292,15 @@ var WalletError = class extends SIPError {
|
|
|
17496
18292
|
function notConnectedError() {
|
|
17497
18293
|
return new WalletError(
|
|
17498
18294
|
"Wallet not connected. Call connect() first.",
|
|
17499
|
-
|
|
18295
|
+
import_types22.WalletErrorCode.NOT_CONNECTED
|
|
17500
18296
|
);
|
|
17501
18297
|
}
|
|
17502
|
-
function featureNotSupportedError(feature, code =
|
|
18298
|
+
function featureNotSupportedError(feature, code = import_types22.WalletErrorCode.UNKNOWN) {
|
|
17503
18299
|
return new WalletError(`${feature} is not supported by this wallet`, code);
|
|
17504
18300
|
}
|
|
17505
18301
|
|
|
17506
18302
|
// src/wallet/base-adapter.ts
|
|
17507
|
-
var
|
|
18303
|
+
var import_types23 = require("@sip-protocol/types");
|
|
17508
18304
|
var BaseWalletAdapter = class {
|
|
17509
18305
|
_address = "";
|
|
17510
18306
|
_publicKey = "";
|
|
@@ -17667,12 +18463,12 @@ var MockWalletAdapter = class extends BaseWalletAdapter {
|
|
|
17667
18463
|
this._connectionState = "connecting";
|
|
17668
18464
|
if (this.shouldFailConnect) {
|
|
17669
18465
|
this.setError(
|
|
17670
|
-
|
|
18466
|
+
import_types23.WalletErrorCode.CONNECTION_FAILED,
|
|
17671
18467
|
"Mock connection failure"
|
|
17672
18468
|
);
|
|
17673
18469
|
throw new WalletError(
|
|
17674
18470
|
"Mock connection failure",
|
|
17675
|
-
|
|
18471
|
+
import_types23.WalletErrorCode.CONNECTION_FAILED
|
|
17676
18472
|
);
|
|
17677
18473
|
}
|
|
17678
18474
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
@@ -17684,7 +18480,7 @@ var MockWalletAdapter = class extends BaseWalletAdapter {
|
|
|
17684
18480
|
async signMessage(message) {
|
|
17685
18481
|
this.requireConnected();
|
|
17686
18482
|
if (this.shouldFailSign) {
|
|
17687
|
-
throw new WalletError("Mock signing failure",
|
|
18483
|
+
throw new WalletError("Mock signing failure", import_types23.WalletErrorCode.SIGNING_FAILED);
|
|
17688
18484
|
}
|
|
17689
18485
|
const mockSig = new Uint8Array(64);
|
|
17690
18486
|
for (let i = 0; i < 64; i++) {
|
|
@@ -17699,7 +18495,7 @@ var MockWalletAdapter = class extends BaseWalletAdapter {
|
|
|
17699
18495
|
async signTransaction(tx) {
|
|
17700
18496
|
this.requireConnected();
|
|
17701
18497
|
if (this.shouldFailSign) {
|
|
17702
|
-
throw new WalletError("Mock signing failure",
|
|
18498
|
+
throw new WalletError("Mock signing failure", import_types23.WalletErrorCode.SIGNING_FAILED);
|
|
17703
18499
|
}
|
|
17704
18500
|
const signature = await this.signMessage(
|
|
17705
18501
|
new TextEncoder().encode(JSON.stringify(tx.data))
|
|
@@ -17881,7 +18677,7 @@ function isPrivateWalletAdapter(adapter) {
|
|
|
17881
18677
|
}
|
|
17882
18678
|
|
|
17883
18679
|
// src/wallet/solana/adapter.ts
|
|
17884
|
-
var
|
|
18680
|
+
var import_types24 = require("@sip-protocol/types");
|
|
17885
18681
|
|
|
17886
18682
|
// src/wallet/solana/types.ts
|
|
17887
18683
|
function getSolanaProvider(wallet = "phantom") {
|
|
@@ -18002,19 +18798,19 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18002
18798
|
}
|
|
18003
18799
|
if (!this.provider) {
|
|
18004
18800
|
this.setError(
|
|
18005
|
-
|
|
18801
|
+
import_types24.WalletErrorCode.NOT_INSTALLED,
|
|
18006
18802
|
`${this.walletName} wallet is not installed`
|
|
18007
18803
|
);
|
|
18008
18804
|
throw new WalletError(
|
|
18009
18805
|
`${this.walletName} wallet is not installed`,
|
|
18010
|
-
|
|
18806
|
+
import_types24.WalletErrorCode.NOT_INSTALLED
|
|
18011
18807
|
);
|
|
18012
18808
|
}
|
|
18013
18809
|
const { publicKey } = await this.provider.connect();
|
|
18014
18810
|
if (!publicKey) {
|
|
18015
18811
|
throw new WalletError(
|
|
18016
18812
|
"No public key returned from wallet",
|
|
18017
|
-
|
|
18813
|
+
import_types24.WalletErrorCode.CONNECTION_FAILED
|
|
18018
18814
|
);
|
|
18019
18815
|
}
|
|
18020
18816
|
this.setupEventHandlers();
|
|
@@ -18024,11 +18820,11 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18024
18820
|
} catch (error) {
|
|
18025
18821
|
const message = error instanceof Error ? error.message : "Connection failed";
|
|
18026
18822
|
if (message.includes("User rejected") || message.includes("rejected")) {
|
|
18027
|
-
this.setError(
|
|
18028
|
-
throw new WalletError(message,
|
|
18823
|
+
this.setError(import_types24.WalletErrorCode.CONNECTION_REJECTED, message);
|
|
18824
|
+
throw new WalletError(message, import_types24.WalletErrorCode.CONNECTION_REJECTED);
|
|
18029
18825
|
}
|
|
18030
|
-
this.setError(
|
|
18031
|
-
throw error instanceof WalletError ? error : new WalletError(message,
|
|
18826
|
+
this.setError(import_types24.WalletErrorCode.CONNECTION_FAILED, message);
|
|
18827
|
+
throw error instanceof WalletError ? error : new WalletError(message, import_types24.WalletErrorCode.CONNECTION_FAILED, { cause: error });
|
|
18032
18828
|
}
|
|
18033
18829
|
}
|
|
18034
18830
|
/**
|
|
@@ -18051,7 +18847,7 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18051
18847
|
async signMessage(message) {
|
|
18052
18848
|
this.requireConnected();
|
|
18053
18849
|
if (!this.provider) {
|
|
18054
|
-
throw new WalletError("Provider not available",
|
|
18850
|
+
throw new WalletError("Provider not available", import_types24.WalletErrorCode.NOT_CONNECTED);
|
|
18055
18851
|
}
|
|
18056
18852
|
try {
|
|
18057
18853
|
const { signature } = await this.provider.signMessage(message);
|
|
@@ -18062,9 +18858,9 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18062
18858
|
} catch (error) {
|
|
18063
18859
|
const message2 = error instanceof Error ? error.message : "Signing failed";
|
|
18064
18860
|
if (message2.includes("User rejected") || message2.includes("rejected")) {
|
|
18065
|
-
throw new WalletError(message2,
|
|
18861
|
+
throw new WalletError(message2, import_types24.WalletErrorCode.SIGNING_REJECTED);
|
|
18066
18862
|
}
|
|
18067
|
-
throw new WalletError(message2,
|
|
18863
|
+
throw new WalletError(message2, import_types24.WalletErrorCode.SIGNING_FAILED, {
|
|
18068
18864
|
cause: error
|
|
18069
18865
|
});
|
|
18070
18866
|
}
|
|
@@ -18077,7 +18873,7 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18077
18873
|
async signTransaction(tx) {
|
|
18078
18874
|
this.requireConnected();
|
|
18079
18875
|
if (!this.provider) {
|
|
18080
|
-
throw new WalletError("Provider not available",
|
|
18876
|
+
throw new WalletError("Provider not available", import_types24.WalletErrorCode.NOT_CONNECTED);
|
|
18081
18877
|
}
|
|
18082
18878
|
try {
|
|
18083
18879
|
const solTx = tx.data;
|
|
@@ -18096,9 +18892,9 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18096
18892
|
} catch (error) {
|
|
18097
18893
|
const message = error instanceof Error ? error.message : "Signing failed";
|
|
18098
18894
|
if (message.includes("User rejected") || message.includes("rejected")) {
|
|
18099
|
-
throw new WalletError(message,
|
|
18895
|
+
throw new WalletError(message, import_types24.WalletErrorCode.SIGNING_REJECTED);
|
|
18100
18896
|
}
|
|
18101
|
-
throw new WalletError(message,
|
|
18897
|
+
throw new WalletError(message, import_types24.WalletErrorCode.SIGNING_FAILED, {
|
|
18102
18898
|
cause: error
|
|
18103
18899
|
});
|
|
18104
18900
|
}
|
|
@@ -18109,7 +18905,7 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18109
18905
|
async signAndSendTransaction(tx) {
|
|
18110
18906
|
this.requireConnected();
|
|
18111
18907
|
if (!this.provider) {
|
|
18112
|
-
throw new WalletError("Provider not available",
|
|
18908
|
+
throw new WalletError("Provider not available", import_types24.WalletErrorCode.NOT_CONNECTED);
|
|
18113
18909
|
}
|
|
18114
18910
|
try {
|
|
18115
18911
|
const solTx = tx.data;
|
|
@@ -18124,12 +18920,12 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18124
18920
|
} catch (error) {
|
|
18125
18921
|
const message = error instanceof Error ? error.message : "Transaction failed";
|
|
18126
18922
|
if (message.includes("User rejected") || message.includes("rejected")) {
|
|
18127
|
-
throw new WalletError(message,
|
|
18923
|
+
throw new WalletError(message, import_types24.WalletErrorCode.TRANSACTION_REJECTED);
|
|
18128
18924
|
}
|
|
18129
18925
|
if (message.includes("insufficient") || message.includes("Insufficient")) {
|
|
18130
|
-
throw new WalletError(message,
|
|
18926
|
+
throw new WalletError(message, import_types24.WalletErrorCode.INSUFFICIENT_FUNDS);
|
|
18131
18927
|
}
|
|
18132
|
-
throw new WalletError(message,
|
|
18928
|
+
throw new WalletError(message, import_types24.WalletErrorCode.TRANSACTION_FAILED, {
|
|
18133
18929
|
cause: error
|
|
18134
18930
|
});
|
|
18135
18931
|
}
|
|
@@ -18142,16 +18938,16 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18142
18938
|
async signAllTransactions(transactions) {
|
|
18143
18939
|
this.requireConnected();
|
|
18144
18940
|
if (!this.provider) {
|
|
18145
|
-
throw new WalletError("Provider not available",
|
|
18941
|
+
throw new WalletError("Provider not available", import_types24.WalletErrorCode.NOT_CONNECTED);
|
|
18146
18942
|
}
|
|
18147
18943
|
try {
|
|
18148
18944
|
return await this.provider.signAllTransactions(transactions);
|
|
18149
18945
|
} catch (error) {
|
|
18150
18946
|
const message = error instanceof Error ? error.message : "Signing failed";
|
|
18151
18947
|
if (message.includes("User rejected") || message.includes("rejected")) {
|
|
18152
|
-
throw new WalletError(message,
|
|
18948
|
+
throw new WalletError(message, import_types24.WalletErrorCode.SIGNING_REJECTED);
|
|
18153
18949
|
}
|
|
18154
|
-
throw new WalletError(message,
|
|
18950
|
+
throw new WalletError(message, import_types24.WalletErrorCode.SIGNING_FAILED, {
|
|
18155
18951
|
cause: error
|
|
18156
18952
|
});
|
|
18157
18953
|
}
|
|
@@ -18172,7 +18968,7 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18172
18968
|
} catch (error) {
|
|
18173
18969
|
throw new WalletError(
|
|
18174
18970
|
"Failed to get balance",
|
|
18175
|
-
|
|
18971
|
+
import_types24.WalletErrorCode.UNKNOWN,
|
|
18176
18972
|
{ cause: error }
|
|
18177
18973
|
);
|
|
18178
18974
|
}
|
|
@@ -18185,7 +18981,7 @@ var SolanaWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18185
18981
|
if (asset.chain !== "solana") {
|
|
18186
18982
|
throw new WalletError(
|
|
18187
18983
|
`Asset chain ${asset.chain} not supported by Solana adapter`,
|
|
18188
|
-
|
|
18984
|
+
import_types24.WalletErrorCode.UNSUPPORTED_CHAIN
|
|
18189
18985
|
);
|
|
18190
18986
|
}
|
|
18191
18987
|
if (!asset.address) {
|
|
@@ -18303,7 +19099,7 @@ function createSolanaAdapter(config = {}) {
|
|
|
18303
19099
|
}
|
|
18304
19100
|
|
|
18305
19101
|
// src/wallet/solana/mock.ts
|
|
18306
|
-
var
|
|
19102
|
+
var import_types26 = require("@sip-protocol/types");
|
|
18307
19103
|
var MockPublicKey = class {
|
|
18308
19104
|
base58;
|
|
18309
19105
|
bytes;
|
|
@@ -18369,8 +19165,8 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
|
|
|
18369
19165
|
this._connectionState = "connecting";
|
|
18370
19166
|
await this.simulateLatency();
|
|
18371
19167
|
if (this.shouldFailConnect) {
|
|
18372
|
-
this.setError(
|
|
18373
|
-
throw new WalletError("Mock connection failure",
|
|
19168
|
+
this.setError(import_types26.WalletErrorCode.CONNECTION_FAILED, "Mock connection failure");
|
|
19169
|
+
throw new WalletError("Mock connection failure", import_types26.WalletErrorCode.CONNECTION_FAILED);
|
|
18374
19170
|
}
|
|
18375
19171
|
const hexPubKey = "0x" + Buffer.from(this.mockPublicKey.toBytes()).toString("hex");
|
|
18376
19172
|
this.setConnected(this.mockAddress, hexPubKey);
|
|
@@ -18389,7 +19185,7 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
|
|
|
18389
19185
|
this.requireConnected();
|
|
18390
19186
|
await this.simulateLatency();
|
|
18391
19187
|
if (this.shouldFailSign) {
|
|
18392
|
-
throw new WalletError("Mock signing failure",
|
|
19188
|
+
throw new WalletError("Mock signing failure", import_types26.WalletErrorCode.SIGNING_REJECTED);
|
|
18393
19189
|
}
|
|
18394
19190
|
const mockSig = new Uint8Array(64);
|
|
18395
19191
|
for (let i = 0; i < 64; i++) {
|
|
@@ -18407,7 +19203,7 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
|
|
|
18407
19203
|
this.requireConnected();
|
|
18408
19204
|
await this.simulateLatency();
|
|
18409
19205
|
if (this.shouldFailSign) {
|
|
18410
|
-
throw new WalletError("Mock signing failure",
|
|
19206
|
+
throw new WalletError("Mock signing failure", import_types26.WalletErrorCode.SIGNING_REJECTED);
|
|
18411
19207
|
}
|
|
18412
19208
|
const solTx = tx.data;
|
|
18413
19209
|
this.signedTransactions.push(solTx);
|
|
@@ -18427,10 +19223,10 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
|
|
|
18427
19223
|
this.requireConnected();
|
|
18428
19224
|
await this.simulateLatency();
|
|
18429
19225
|
if (this.shouldFailSign) {
|
|
18430
|
-
throw new WalletError("Mock signing failure",
|
|
19226
|
+
throw new WalletError("Mock signing failure", import_types26.WalletErrorCode.SIGNING_REJECTED);
|
|
18431
19227
|
}
|
|
18432
19228
|
if (this.shouldFailTransaction) {
|
|
18433
|
-
throw new WalletError("Mock transaction failure",
|
|
19229
|
+
throw new WalletError("Mock transaction failure", import_types26.WalletErrorCode.TRANSACTION_FAILED);
|
|
18434
19230
|
}
|
|
18435
19231
|
const txSig = `mock_tx_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
18436
19232
|
this.sentTransactions.push(txSig);
|
|
@@ -18450,7 +19246,7 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
|
|
|
18450
19246
|
this.requireConnected();
|
|
18451
19247
|
await this.simulateLatency();
|
|
18452
19248
|
if (this.shouldFailSign) {
|
|
18453
|
-
throw new WalletError("Mock signing failure",
|
|
19249
|
+
throw new WalletError("Mock signing failure", import_types26.WalletErrorCode.SIGNING_REJECTED);
|
|
18454
19250
|
}
|
|
18455
19251
|
this.signedTransactions.push(...transactions);
|
|
18456
19252
|
return transactions.map((tx) => {
|
|
@@ -18477,7 +19273,7 @@ var MockSolanaAdapter = class extends BaseWalletAdapter {
|
|
|
18477
19273
|
if (asset.chain !== "solana") {
|
|
18478
19274
|
throw new WalletError(
|
|
18479
19275
|
`Asset chain ${asset.chain} not supported by Solana adapter`,
|
|
18480
|
-
|
|
19276
|
+
import_types26.WalletErrorCode.UNSUPPORTED_CHAIN
|
|
18481
19277
|
);
|
|
18482
19278
|
}
|
|
18483
19279
|
if (!asset.address) {
|
|
@@ -18646,7 +19442,7 @@ function createMockSolanaAdapter(config = {}) {
|
|
|
18646
19442
|
}
|
|
18647
19443
|
|
|
18648
19444
|
// src/wallet/ethereum/adapter.ts
|
|
18649
|
-
var
|
|
19445
|
+
var import_types28 = require("@sip-protocol/types");
|
|
18650
19446
|
|
|
18651
19447
|
// src/wallet/ethereum/types.ts
|
|
18652
19448
|
var EthereumChainId = {
|
|
@@ -18788,7 +19584,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18788
19584
|
this._connectionState = "error";
|
|
18789
19585
|
throw new WalletError(
|
|
18790
19586
|
`${this.walletType} wallet not found. Please install the extension.`,
|
|
18791
|
-
|
|
19587
|
+
import_types28.WalletErrorCode.NOT_INSTALLED
|
|
18792
19588
|
);
|
|
18793
19589
|
}
|
|
18794
19590
|
const accounts = await this.provider.request({
|
|
@@ -18798,7 +19594,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18798
19594
|
this._connectionState = "error";
|
|
18799
19595
|
throw new WalletError(
|
|
18800
19596
|
"No accounts returned from wallet",
|
|
18801
|
-
|
|
19597
|
+
import_types28.WalletErrorCode.CONNECTION_REJECTED
|
|
18802
19598
|
);
|
|
18803
19599
|
}
|
|
18804
19600
|
const address = normalizeAddress(accounts[0]);
|
|
@@ -18818,12 +19614,12 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18818
19614
|
if (rpcError.code === 4001) {
|
|
18819
19615
|
throw new WalletError(
|
|
18820
19616
|
"User rejected connection request",
|
|
18821
|
-
|
|
19617
|
+
import_types28.WalletErrorCode.CONNECTION_REJECTED
|
|
18822
19618
|
);
|
|
18823
19619
|
}
|
|
18824
19620
|
throw new WalletError(
|
|
18825
19621
|
`Failed to connect: ${rpcError.message || String(error)}`,
|
|
18826
|
-
|
|
19622
|
+
import_types28.WalletErrorCode.CONNECTION_FAILED
|
|
18827
19623
|
);
|
|
18828
19624
|
}
|
|
18829
19625
|
}
|
|
@@ -18843,7 +19639,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18843
19639
|
if (!this.provider) {
|
|
18844
19640
|
throw new WalletError(
|
|
18845
19641
|
"Provider not available",
|
|
18846
|
-
|
|
19642
|
+
import_types28.WalletErrorCode.NOT_CONNECTED
|
|
18847
19643
|
);
|
|
18848
19644
|
}
|
|
18849
19645
|
try {
|
|
@@ -18861,12 +19657,12 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18861
19657
|
if (rpcError.code === 4001) {
|
|
18862
19658
|
throw new WalletError(
|
|
18863
19659
|
"User rejected signing request",
|
|
18864
|
-
|
|
19660
|
+
import_types28.WalletErrorCode.SIGNING_REJECTED
|
|
18865
19661
|
);
|
|
18866
19662
|
}
|
|
18867
19663
|
throw new WalletError(
|
|
18868
19664
|
`Failed to sign message: ${rpcError.message || String(error)}`,
|
|
18869
|
-
|
|
19665
|
+
import_types28.WalletErrorCode.SIGNING_FAILED
|
|
18870
19666
|
);
|
|
18871
19667
|
}
|
|
18872
19668
|
}
|
|
@@ -18878,7 +19674,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18878
19674
|
if (!this.provider) {
|
|
18879
19675
|
throw new WalletError(
|
|
18880
19676
|
"Provider not available",
|
|
18881
|
-
|
|
19677
|
+
import_types28.WalletErrorCode.NOT_CONNECTED
|
|
18882
19678
|
);
|
|
18883
19679
|
}
|
|
18884
19680
|
try {
|
|
@@ -18895,12 +19691,12 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18895
19691
|
if (rpcError.code === 4001) {
|
|
18896
19692
|
throw new WalletError(
|
|
18897
19693
|
"User rejected signing request",
|
|
18898
|
-
|
|
19694
|
+
import_types28.WalletErrorCode.SIGNING_REJECTED
|
|
18899
19695
|
);
|
|
18900
19696
|
}
|
|
18901
19697
|
throw new WalletError(
|
|
18902
19698
|
`Failed to sign typed data: ${rpcError.message || String(error)}`,
|
|
18903
|
-
|
|
19699
|
+
import_types28.WalletErrorCode.SIGNING_FAILED
|
|
18904
19700
|
);
|
|
18905
19701
|
}
|
|
18906
19702
|
}
|
|
@@ -18912,7 +19708,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18912
19708
|
if (!this.provider) {
|
|
18913
19709
|
throw new WalletError(
|
|
18914
19710
|
"Provider not available",
|
|
18915
|
-
|
|
19711
|
+
import_types28.WalletErrorCode.NOT_CONNECTED
|
|
18916
19712
|
);
|
|
18917
19713
|
}
|
|
18918
19714
|
try {
|
|
@@ -18940,7 +19736,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18940
19736
|
if (rpcError.code === 4001) {
|
|
18941
19737
|
throw new WalletError(
|
|
18942
19738
|
"User rejected transaction signing",
|
|
18943
|
-
|
|
19739
|
+
import_types28.WalletErrorCode.SIGNING_REJECTED
|
|
18944
19740
|
);
|
|
18945
19741
|
}
|
|
18946
19742
|
if (rpcError.code === -32601 || rpcError.message?.includes("not supported")) {
|
|
@@ -18958,7 +19754,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18958
19754
|
}
|
|
18959
19755
|
throw new WalletError(
|
|
18960
19756
|
`Failed to sign transaction: ${rpcError.message || String(error)}`,
|
|
18961
|
-
|
|
19757
|
+
import_types28.WalletErrorCode.TRANSACTION_FAILED
|
|
18962
19758
|
);
|
|
18963
19759
|
}
|
|
18964
19760
|
}
|
|
@@ -18970,7 +19766,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18970
19766
|
if (!this.provider) {
|
|
18971
19767
|
throw new WalletError(
|
|
18972
19768
|
"Provider not available",
|
|
18973
|
-
|
|
19769
|
+
import_types28.WalletErrorCode.NOT_CONNECTED
|
|
18974
19770
|
);
|
|
18975
19771
|
}
|
|
18976
19772
|
try {
|
|
@@ -18992,12 +19788,12 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
18992
19788
|
if (rpcError.code === 4001) {
|
|
18993
19789
|
throw new WalletError(
|
|
18994
19790
|
"User rejected transaction",
|
|
18995
|
-
|
|
19791
|
+
import_types28.WalletErrorCode.TRANSACTION_REJECTED
|
|
18996
19792
|
);
|
|
18997
19793
|
}
|
|
18998
19794
|
throw new WalletError(
|
|
18999
19795
|
`Failed to send transaction: ${rpcError.message || String(error)}`,
|
|
19000
|
-
|
|
19796
|
+
import_types28.WalletErrorCode.TRANSACTION_FAILED
|
|
19001
19797
|
);
|
|
19002
19798
|
}
|
|
19003
19799
|
}
|
|
@@ -19032,7 +19828,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
19032
19828
|
} catch (error) {
|
|
19033
19829
|
throw new WalletError(
|
|
19034
19830
|
`Failed to fetch balance: ${String(error)}`,
|
|
19035
|
-
|
|
19831
|
+
import_types28.WalletErrorCode.UNKNOWN
|
|
19036
19832
|
);
|
|
19037
19833
|
}
|
|
19038
19834
|
}
|
|
@@ -19044,7 +19840,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
19044
19840
|
if (asset.chain !== "ethereum") {
|
|
19045
19841
|
throw new WalletError(
|
|
19046
19842
|
`Asset chain ${asset.chain} not supported by Ethereum adapter`,
|
|
19047
|
-
|
|
19843
|
+
import_types28.WalletErrorCode.UNSUPPORTED_CHAIN
|
|
19048
19844
|
);
|
|
19049
19845
|
}
|
|
19050
19846
|
if (!asset.address) {
|
|
@@ -19069,7 +19865,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
19069
19865
|
} catch (error) {
|
|
19070
19866
|
throw new WalletError(
|
|
19071
19867
|
`Failed to fetch token balance: ${String(error)}`,
|
|
19072
|
-
|
|
19868
|
+
import_types28.WalletErrorCode.UNKNOWN
|
|
19073
19869
|
);
|
|
19074
19870
|
}
|
|
19075
19871
|
}
|
|
@@ -19081,7 +19877,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
19081
19877
|
if (!this.provider) {
|
|
19082
19878
|
throw new WalletError(
|
|
19083
19879
|
"Provider not available",
|
|
19084
|
-
|
|
19880
|
+
import_types28.WalletErrorCode.NOT_CONNECTED
|
|
19085
19881
|
);
|
|
19086
19882
|
}
|
|
19087
19883
|
try {
|
|
@@ -19096,18 +19892,18 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
19096
19892
|
if (rpcError.code === 4001) {
|
|
19097
19893
|
throw new WalletError(
|
|
19098
19894
|
"User rejected chain switch",
|
|
19099
|
-
|
|
19895
|
+
import_types28.WalletErrorCode.CHAIN_SWITCH_REJECTED
|
|
19100
19896
|
);
|
|
19101
19897
|
}
|
|
19102
19898
|
if (rpcError.code === 4902) {
|
|
19103
19899
|
throw new WalletError(
|
|
19104
19900
|
`Chain ${chainId} not added to wallet`,
|
|
19105
|
-
|
|
19901
|
+
import_types28.WalletErrorCode.UNSUPPORTED_CHAIN
|
|
19106
19902
|
);
|
|
19107
19903
|
}
|
|
19108
19904
|
throw new WalletError(
|
|
19109
19905
|
`Failed to switch chain: ${rpcError.message || String(error)}`,
|
|
19110
|
-
|
|
19906
|
+
import_types28.WalletErrorCode.CHAIN_SWITCH_FAILED
|
|
19111
19907
|
);
|
|
19112
19908
|
}
|
|
19113
19909
|
}
|
|
@@ -19143,7 +19939,7 @@ var EthereumWalletAdapter = class extends BaseWalletAdapter {
|
|
|
19143
19939
|
}
|
|
19144
19940
|
throw new WalletError(
|
|
19145
19941
|
`Transaction ${txHash} not confirmed after ${maxAttempts * 5} seconds`,
|
|
19146
|
-
|
|
19942
|
+
import_types28.WalletErrorCode.TRANSACTION_FAILED
|
|
19147
19943
|
);
|
|
19148
19944
|
}
|
|
19149
19945
|
/**
|
|
@@ -19217,7 +20013,7 @@ function createEthereumAdapter(config) {
|
|
|
19217
20013
|
}
|
|
19218
20014
|
|
|
19219
20015
|
// src/wallet/ethereum/mock.ts
|
|
19220
|
-
var
|
|
20016
|
+
var import_types30 = require("@sip-protocol/types");
|
|
19221
20017
|
var MockEthereumAdapter = class extends BaseWalletAdapter {
|
|
19222
20018
|
chain = "ethereum";
|
|
19223
20019
|
name = "mock-ethereum";
|
|
@@ -19258,7 +20054,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
|
|
|
19258
20054
|
this._connectionState = "error";
|
|
19259
20055
|
throw new WalletError(
|
|
19260
20056
|
"Mock connection rejected",
|
|
19261
|
-
|
|
20057
|
+
import_types30.WalletErrorCode.CONNECTION_REJECTED
|
|
19262
20058
|
);
|
|
19263
20059
|
}
|
|
19264
20060
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
@@ -19270,7 +20066,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
|
|
|
19270
20066
|
this._connectionState = "error";
|
|
19271
20067
|
throw new WalletError(
|
|
19272
20068
|
`Mock connection failed: ${String(error)}`,
|
|
19273
|
-
|
|
20069
|
+
import_types30.WalletErrorCode.CONNECTION_FAILED
|
|
19274
20070
|
);
|
|
19275
20071
|
}
|
|
19276
20072
|
}
|
|
@@ -19288,7 +20084,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
|
|
|
19288
20084
|
if (this._shouldFailSign) {
|
|
19289
20085
|
throw new WalletError(
|
|
19290
20086
|
"Mock signing rejected",
|
|
19291
|
-
|
|
20087
|
+
import_types30.WalletErrorCode.SIGNING_REJECTED
|
|
19292
20088
|
);
|
|
19293
20089
|
}
|
|
19294
20090
|
const msgHex = Buffer.from(message).toString("hex");
|
|
@@ -19306,7 +20102,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
|
|
|
19306
20102
|
if (this._shouldFailSign) {
|
|
19307
20103
|
throw new WalletError(
|
|
19308
20104
|
"Mock signing rejected",
|
|
19309
|
-
|
|
20105
|
+
import_types30.WalletErrorCode.SIGNING_REJECTED
|
|
19310
20106
|
);
|
|
19311
20107
|
}
|
|
19312
20108
|
const mockSig = `0x${"1".repeat(130)}`;
|
|
@@ -19323,7 +20119,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
|
|
|
19323
20119
|
if (this._shouldFailSign) {
|
|
19324
20120
|
throw new WalletError(
|
|
19325
20121
|
"Mock signing rejected",
|
|
19326
|
-
|
|
20122
|
+
import_types30.WalletErrorCode.SIGNING_REJECTED
|
|
19327
20123
|
);
|
|
19328
20124
|
}
|
|
19329
20125
|
this._signedTransactions.push(tx);
|
|
@@ -19348,7 +20144,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
|
|
|
19348
20144
|
if (this._shouldFailTransaction) {
|
|
19349
20145
|
throw new WalletError(
|
|
19350
20146
|
"Mock transaction failed",
|
|
19351
|
-
|
|
20147
|
+
import_types30.WalletErrorCode.TRANSACTION_FAILED
|
|
19352
20148
|
);
|
|
19353
20149
|
}
|
|
19354
20150
|
this._signedTransactions.push(tx);
|
|
@@ -19378,7 +20174,7 @@ var MockEthereumAdapter = class extends BaseWalletAdapter {
|
|
|
19378
20174
|
if (asset.chain !== "ethereum") {
|
|
19379
20175
|
throw new WalletError(
|
|
19380
20176
|
`Asset chain ${asset.chain} not supported by Ethereum adapter`,
|
|
19381
|
-
|
|
20177
|
+
import_types30.WalletErrorCode.UNSUPPORTED_CHAIN
|
|
19382
20178
|
);
|
|
19383
20179
|
}
|
|
19384
20180
|
if (!asset.address) {
|
|
@@ -19583,28 +20379,28 @@ function createMockEthereumProvider(config = {}) {
|
|
|
19583
20379
|
}
|
|
19584
20380
|
|
|
19585
20381
|
// src/wallet/cosmos/adapter.ts
|
|
19586
|
-
var
|
|
20382
|
+
var import_types33 = require("@sip-protocol/types");
|
|
19587
20383
|
|
|
19588
20384
|
// src/wallet/cosmos/mock.ts
|
|
19589
|
-
var
|
|
20385
|
+
var import_types35 = require("@sip-protocol/types");
|
|
19590
20386
|
|
|
19591
20387
|
// src/wallet/bitcoin/adapter.ts
|
|
19592
|
-
var
|
|
20388
|
+
var import_types38 = require("@sip-protocol/types");
|
|
19593
20389
|
|
|
19594
20390
|
// src/wallet/bitcoin/mock.ts
|
|
19595
|
-
var
|
|
20391
|
+
var import_types40 = require("@sip-protocol/types");
|
|
19596
20392
|
|
|
19597
20393
|
// src/wallet/aptos/adapter.ts
|
|
19598
|
-
var
|
|
20394
|
+
var import_types43 = require("@sip-protocol/types");
|
|
19599
20395
|
|
|
19600
20396
|
// src/wallet/aptos/mock.ts
|
|
19601
|
-
var
|
|
20397
|
+
var import_types45 = require("@sip-protocol/types");
|
|
19602
20398
|
|
|
19603
20399
|
// src/wallet/sui/adapter.ts
|
|
19604
|
-
var
|
|
20400
|
+
var import_types47 = require("@sip-protocol/types");
|
|
19605
20401
|
|
|
19606
20402
|
// src/wallet/sui/mock.ts
|
|
19607
|
-
var
|
|
20403
|
+
var import_types49 = require("@sip-protocol/types");
|
|
19608
20404
|
|
|
19609
20405
|
// src/wallet/hardware/types.ts
|
|
19610
20406
|
var DerivationPath = {
|
|
@@ -19684,7 +20480,7 @@ function getAvailableTransports() {
|
|
|
19684
20480
|
|
|
19685
20481
|
// src/wallet/hardware/ledger.ts
|
|
19686
20482
|
var import_rlp = require("@ethereumjs/rlp");
|
|
19687
|
-
var
|
|
20483
|
+
var import_types51 = require("@sip-protocol/types");
|
|
19688
20484
|
var LedgerWalletAdapter = class extends BaseWalletAdapter {
|
|
19689
20485
|
chain;
|
|
19690
20486
|
name = "ledger";
|
|
@@ -19837,7 +20633,7 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
|
|
|
19837
20633
|
async getBalance() {
|
|
19838
20634
|
throw new WalletError(
|
|
19839
20635
|
"Hardware wallets do not track balances. Use an RPC provider.",
|
|
19840
|
-
|
|
20636
|
+
import_types51.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
19841
20637
|
);
|
|
19842
20638
|
}
|
|
19843
20639
|
/**
|
|
@@ -19848,7 +20644,7 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
|
|
|
19848
20644
|
async getTokenBalance(_asset) {
|
|
19849
20645
|
throw new WalletError(
|
|
19850
20646
|
"Hardware wallets do not track balances. Use an RPC provider.",
|
|
19851
|
-
|
|
20647
|
+
import_types51.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
19852
20648
|
);
|
|
19853
20649
|
}
|
|
19854
20650
|
// ─── Account Management ─────────────────────────────────────────────────────
|
|
@@ -20075,7 +20871,7 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
|
|
|
20075
20871
|
* @see https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/
|
|
20076
20872
|
*/
|
|
20077
20873
|
buildRawEthereumTx(tx) {
|
|
20078
|
-
const
|
|
20874
|
+
const hexToBytes25 = (hex) => {
|
|
20079
20875
|
if (!hex || hex === "0x" || hex === "0x0" || hex === "0x00") {
|
|
20080
20876
|
return new Uint8Array(0);
|
|
20081
20877
|
}
|
|
@@ -20092,21 +20888,21 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
|
|
|
20092
20888
|
const isEIP1559 = tx.maxFeePerGas !== void 0 && tx.maxPriorityFeePerGas !== void 0;
|
|
20093
20889
|
if (isEIP1559) {
|
|
20094
20890
|
const txData = [
|
|
20095
|
-
|
|
20891
|
+
hexToBytes25(`0x${tx.chainId.toString(16)}`),
|
|
20096
20892
|
// chainId
|
|
20097
|
-
|
|
20893
|
+
hexToBytes25(tx.nonce),
|
|
20098
20894
|
// nonce
|
|
20099
|
-
|
|
20895
|
+
hexToBytes25(tx.maxPriorityFeePerGas),
|
|
20100
20896
|
// maxPriorityFeePerGas
|
|
20101
|
-
|
|
20897
|
+
hexToBytes25(tx.maxFeePerGas),
|
|
20102
20898
|
// maxFeePerGas
|
|
20103
|
-
|
|
20899
|
+
hexToBytes25(tx.gasLimit),
|
|
20104
20900
|
// gasLimit
|
|
20105
|
-
|
|
20901
|
+
hexToBytes25(tx.to),
|
|
20106
20902
|
// to
|
|
20107
|
-
|
|
20903
|
+
hexToBytes25(tx.value),
|
|
20108
20904
|
// value
|
|
20109
|
-
|
|
20905
|
+
hexToBytes25(tx.data),
|
|
20110
20906
|
// data
|
|
20111
20907
|
[]
|
|
20112
20908
|
// accessList (empty)
|
|
@@ -20125,19 +20921,19 @@ var LedgerWalletAdapter = class extends BaseWalletAdapter {
|
|
|
20125
20921
|
);
|
|
20126
20922
|
}
|
|
20127
20923
|
const txData = [
|
|
20128
|
-
|
|
20924
|
+
hexToBytes25(tx.nonce),
|
|
20129
20925
|
// nonce
|
|
20130
|
-
|
|
20926
|
+
hexToBytes25(tx.gasPrice),
|
|
20131
20927
|
// gasPrice
|
|
20132
|
-
|
|
20928
|
+
hexToBytes25(tx.gasLimit),
|
|
20133
20929
|
// gasLimit
|
|
20134
|
-
|
|
20930
|
+
hexToBytes25(tx.to),
|
|
20135
20931
|
// to
|
|
20136
|
-
|
|
20932
|
+
hexToBytes25(tx.value),
|
|
20137
20933
|
// value
|
|
20138
|
-
|
|
20934
|
+
hexToBytes25(tx.data),
|
|
20139
20935
|
// data
|
|
20140
|
-
|
|
20936
|
+
hexToBytes25(`0x${tx.chainId.toString(16)}`),
|
|
20141
20937
|
// v (chainId for EIP-155)
|
|
20142
20938
|
new Uint8Array(0),
|
|
20143
20939
|
// r (empty for unsigned)
|
|
@@ -20214,7 +21010,7 @@ function createLedgerAdapter(config) {
|
|
|
20214
21010
|
}
|
|
20215
21011
|
|
|
20216
21012
|
// src/wallet/hardware/trezor.ts
|
|
20217
|
-
var
|
|
21013
|
+
var import_types53 = require("@sip-protocol/types");
|
|
20218
21014
|
var TrezorWalletAdapter = class extends BaseWalletAdapter {
|
|
20219
21015
|
chain;
|
|
20220
21016
|
name = "trezor";
|
|
@@ -20360,7 +21156,7 @@ var TrezorWalletAdapter = class extends BaseWalletAdapter {
|
|
|
20360
21156
|
async getBalance() {
|
|
20361
21157
|
throw new WalletError(
|
|
20362
21158
|
"Hardware wallets do not track balances. Use an RPC provider.",
|
|
20363
|
-
|
|
21159
|
+
import_types53.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
20364
21160
|
);
|
|
20365
21161
|
}
|
|
20366
21162
|
/**
|
|
@@ -20371,7 +21167,7 @@ var TrezorWalletAdapter = class extends BaseWalletAdapter {
|
|
|
20371
21167
|
async getTokenBalance(_asset) {
|
|
20372
21168
|
throw new WalletError(
|
|
20373
21169
|
"Hardware wallets do not track balances. Use an RPC provider.",
|
|
20374
|
-
|
|
21170
|
+
import_types53.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
20375
21171
|
);
|
|
20376
21172
|
}
|
|
20377
21173
|
// ─── Account Management ─────────────────────────────────────────────────────
|
|
@@ -20652,8 +21448,8 @@ function createTrezorAdapter(config) {
|
|
|
20652
21448
|
}
|
|
20653
21449
|
|
|
20654
21450
|
// src/wallet/hardware/mock.ts
|
|
20655
|
-
var
|
|
20656
|
-
var
|
|
21451
|
+
var import_types55 = require("@sip-protocol/types");
|
|
21452
|
+
var import_utils31 = require("@noble/hashes/utils");
|
|
20657
21453
|
var MockLedgerAdapter = class extends BaseWalletAdapter {
|
|
20658
21454
|
chain;
|
|
20659
21455
|
name = "mock-ledger";
|
|
@@ -20800,7 +21596,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
|
|
|
20800
21596
|
async getBalance() {
|
|
20801
21597
|
throw new WalletError(
|
|
20802
21598
|
"Hardware wallets do not track balances",
|
|
20803
|
-
|
|
21599
|
+
import_types55.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
20804
21600
|
);
|
|
20805
21601
|
}
|
|
20806
21602
|
/**
|
|
@@ -20809,7 +21605,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
|
|
|
20809
21605
|
async getTokenBalance(_asset) {
|
|
20810
21606
|
throw new WalletError(
|
|
20811
21607
|
"Hardware wallets do not track balances",
|
|
20812
|
-
|
|
21608
|
+
import_types55.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
20813
21609
|
);
|
|
20814
21610
|
}
|
|
20815
21611
|
/**
|
|
@@ -20898,15 +21694,15 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
|
|
|
20898
21694
|
}
|
|
20899
21695
|
}
|
|
20900
21696
|
generateMockAddress(index) {
|
|
20901
|
-
const bytes = (0,
|
|
21697
|
+
const bytes = (0, import_utils31.randomBytes)(20);
|
|
20902
21698
|
bytes[0] = index;
|
|
20903
|
-
return `0x${(0,
|
|
21699
|
+
return `0x${(0, import_utils31.bytesToHex)(bytes)}`;
|
|
20904
21700
|
}
|
|
20905
21701
|
generateMockPublicKey(index) {
|
|
20906
|
-
const bytes = (0,
|
|
21702
|
+
const bytes = (0, import_utils31.randomBytes)(33);
|
|
20907
21703
|
bytes[0] = 2;
|
|
20908
21704
|
bytes[1] = index;
|
|
20909
|
-
return `0x${(0,
|
|
21705
|
+
return `0x${(0, import_utils31.bytesToHex)(bytes)}`;
|
|
20910
21706
|
}
|
|
20911
21707
|
generateMockSignature(data) {
|
|
20912
21708
|
const sig = new Uint8Array(65);
|
|
@@ -20915,7 +21711,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
|
|
|
20915
21711
|
sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 11;
|
|
20916
21712
|
}
|
|
20917
21713
|
sig[64] = 27;
|
|
20918
|
-
return `0x${(0,
|
|
21714
|
+
return `0x${(0, import_utils31.bytesToHex)(sig)}`;
|
|
20919
21715
|
}
|
|
20920
21716
|
delay(ms) {
|
|
20921
21717
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -21039,13 +21835,13 @@ var MockTrezorAdapter = class extends BaseWalletAdapter {
|
|
|
21039
21835
|
async getBalance() {
|
|
21040
21836
|
throw new WalletError(
|
|
21041
21837
|
"Hardware wallets do not track balances",
|
|
21042
|
-
|
|
21838
|
+
import_types55.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
21043
21839
|
);
|
|
21044
21840
|
}
|
|
21045
21841
|
async getTokenBalance(_asset) {
|
|
21046
21842
|
throw new WalletError(
|
|
21047
21843
|
"Hardware wallets do not track balances",
|
|
21048
|
-
|
|
21844
|
+
import_types55.WalletErrorCode.UNSUPPORTED_OPERATION
|
|
21049
21845
|
);
|
|
21050
21846
|
}
|
|
21051
21847
|
async getAccounts(startIndex = 0, count = 5) {
|
|
@@ -21104,15 +21900,15 @@ var MockTrezorAdapter = class extends BaseWalletAdapter {
|
|
|
21104
21900
|
}
|
|
21105
21901
|
}
|
|
21106
21902
|
generateMockAddress(index) {
|
|
21107
|
-
const bytes = (0,
|
|
21903
|
+
const bytes = (0, import_utils31.randomBytes)(20);
|
|
21108
21904
|
bytes[0] = index + 100;
|
|
21109
|
-
return `0x${(0,
|
|
21905
|
+
return `0x${(0, import_utils31.bytesToHex)(bytes)}`;
|
|
21110
21906
|
}
|
|
21111
21907
|
generateMockPublicKey(index) {
|
|
21112
|
-
const bytes = (0,
|
|
21908
|
+
const bytes = (0, import_utils31.randomBytes)(33);
|
|
21113
21909
|
bytes[0] = 3;
|
|
21114
21910
|
bytes[1] = index + 100;
|
|
21115
|
-
return `0x${(0,
|
|
21911
|
+
return `0x${(0, import_utils31.bytesToHex)(bytes)}`;
|
|
21116
21912
|
}
|
|
21117
21913
|
generateMockSignature(data) {
|
|
21118
21914
|
const sig = new Uint8Array(65);
|
|
@@ -21121,7 +21917,7 @@ var MockTrezorAdapter = class extends BaseWalletAdapter {
|
|
|
21121
21917
|
sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 17;
|
|
21122
21918
|
}
|
|
21123
21919
|
sig[64] = 28;
|
|
21124
|
-
return `0x${(0,
|
|
21920
|
+
return `0x${(0, import_utils31.bytesToHex)(sig)}`;
|
|
21125
21921
|
}
|
|
21126
21922
|
delay(ms) {
|
|
21127
21923
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -21135,7 +21931,7 @@ function createMockTrezorAdapter(config) {
|
|
|
21135
21931
|
}
|
|
21136
21932
|
|
|
21137
21933
|
// src/wallet/index.ts
|
|
21138
|
-
var
|
|
21934
|
+
var import_types58 = require("@sip-protocol/types");
|
|
21139
21935
|
|
|
21140
21936
|
// src/index.ts
|
|
21141
21937
|
init_solana();
|
|
@@ -21189,6 +21985,1772 @@ function getSupportedSameChainChains() {
|
|
|
21189
21985
|
return ["solana"];
|
|
21190
21986
|
}
|
|
21191
21987
|
|
|
21988
|
+
// src/privacy-backends/registry.ts
|
|
21989
|
+
var DEFAULT_PRIORITY = 50;
|
|
21990
|
+
var PrivacyBackendRegistry = class {
|
|
21991
|
+
backends = /* @__PURE__ */ new Map();
|
|
21992
|
+
/**
|
|
21993
|
+
* Register a privacy backend
|
|
21994
|
+
*
|
|
21995
|
+
* @param backend - Backend instance to register
|
|
21996
|
+
* @param options - Registration options
|
|
21997
|
+
* @throws Error if backend with same name exists and override is false
|
|
21998
|
+
*
|
|
21999
|
+
* @example
|
|
22000
|
+
* ```typescript
|
|
22001
|
+
* registry.register(new SIPNativeBackend())
|
|
22002
|
+
* registry.register(new PrivacyCashBackend(), { priority: 100 })
|
|
22003
|
+
* ```
|
|
22004
|
+
*/
|
|
22005
|
+
register(backend, options = {}) {
|
|
22006
|
+
const { override = false, priority = DEFAULT_PRIORITY, enabled = true } = options;
|
|
22007
|
+
if (this.backends.has(backend.name) && !override) {
|
|
22008
|
+
throw new Error(
|
|
22009
|
+
`Backend '${backend.name}' is already registered. Use { override: true } to replace it.`
|
|
22010
|
+
);
|
|
22011
|
+
}
|
|
22012
|
+
this.backends.set(backend.name, {
|
|
22013
|
+
backend,
|
|
22014
|
+
priority,
|
|
22015
|
+
enabled,
|
|
22016
|
+
registeredAt: Date.now()
|
|
22017
|
+
});
|
|
22018
|
+
}
|
|
22019
|
+
/**
|
|
22020
|
+
* Unregister a backend by name
|
|
22021
|
+
*
|
|
22022
|
+
* @param name - Backend name to unregister
|
|
22023
|
+
* @returns true if backend was removed, false if not found
|
|
22024
|
+
*/
|
|
22025
|
+
unregister(name) {
|
|
22026
|
+
return this.backends.delete(name);
|
|
22027
|
+
}
|
|
22028
|
+
/**
|
|
22029
|
+
* Get a backend by name
|
|
22030
|
+
*
|
|
22031
|
+
* @param name - Backend name
|
|
22032
|
+
* @returns Backend instance or undefined if not found
|
|
22033
|
+
*/
|
|
22034
|
+
get(name) {
|
|
22035
|
+
const entry = this.backends.get(name);
|
|
22036
|
+
return entry?.enabled ? entry.backend : void 0;
|
|
22037
|
+
}
|
|
22038
|
+
/**
|
|
22039
|
+
* Check if a backend is registered
|
|
22040
|
+
*
|
|
22041
|
+
* @param name - Backend name
|
|
22042
|
+
* @returns true if registered (regardless of enabled state)
|
|
22043
|
+
*/
|
|
22044
|
+
has(name) {
|
|
22045
|
+
return this.backends.has(name);
|
|
22046
|
+
}
|
|
22047
|
+
/**
|
|
22048
|
+
* Get all enabled backends sorted by priority
|
|
22049
|
+
*
|
|
22050
|
+
* @returns Array of backends (highest priority first)
|
|
22051
|
+
*/
|
|
22052
|
+
getAll() {
|
|
22053
|
+
return Array.from(this.backends.values()).filter((entry) => entry.enabled).sort((a, b) => b.priority - a.priority).map((entry) => entry.backend);
|
|
22054
|
+
}
|
|
22055
|
+
/**
|
|
22056
|
+
* Get all registered entries (including disabled)
|
|
22057
|
+
*
|
|
22058
|
+
* @returns Array of registered backend entries
|
|
22059
|
+
*/
|
|
22060
|
+
getAllEntries() {
|
|
22061
|
+
return Array.from(this.backends.values()).sort((a, b) => b.priority - a.priority);
|
|
22062
|
+
}
|
|
22063
|
+
/**
|
|
22064
|
+
* Get backends supporting a specific chain
|
|
22065
|
+
*
|
|
22066
|
+
* @param chain - Chain type to filter by
|
|
22067
|
+
* @returns Array of backends supporting the chain
|
|
22068
|
+
*/
|
|
22069
|
+
getByChain(chain) {
|
|
22070
|
+
return this.getAll().filter(
|
|
22071
|
+
(backend) => backend.chains.includes(chain)
|
|
22072
|
+
);
|
|
22073
|
+
}
|
|
22074
|
+
/**
|
|
22075
|
+
* Get backends of a specific type
|
|
22076
|
+
*
|
|
22077
|
+
* @param type - Backend type to filter by
|
|
22078
|
+
* @returns Array of backends of the specified type
|
|
22079
|
+
*/
|
|
22080
|
+
getByType(type) {
|
|
22081
|
+
return this.getAll().filter(
|
|
22082
|
+
(backend) => backend.type === type || backend.type === "both"
|
|
22083
|
+
);
|
|
22084
|
+
}
|
|
22085
|
+
/**
|
|
22086
|
+
* Get backends that support compliance (viewing keys)
|
|
22087
|
+
*
|
|
22088
|
+
* @returns Array of compliance-supporting backends
|
|
22089
|
+
*/
|
|
22090
|
+
getCompliant() {
|
|
22091
|
+
return this.getAll().filter(
|
|
22092
|
+
(backend) => backend.getCapabilities().complianceSupport
|
|
22093
|
+
);
|
|
22094
|
+
}
|
|
22095
|
+
/**
|
|
22096
|
+
* Find available backends for a transfer
|
|
22097
|
+
*
|
|
22098
|
+
* @param params - Transfer parameters
|
|
22099
|
+
* @returns Array of available backends with availability info
|
|
22100
|
+
*/
|
|
22101
|
+
async findAvailable(params) {
|
|
22102
|
+
const chainBackends = this.getByChain(params.chain);
|
|
22103
|
+
const results = [];
|
|
22104
|
+
for (const backend of chainBackends) {
|
|
22105
|
+
const availability = await backend.checkAvailability(params);
|
|
22106
|
+
if (availability.available) {
|
|
22107
|
+
results.push({ backend, availability });
|
|
22108
|
+
}
|
|
22109
|
+
}
|
|
22110
|
+
return results;
|
|
22111
|
+
}
|
|
22112
|
+
/**
|
|
22113
|
+
* Enable a backend
|
|
22114
|
+
*
|
|
22115
|
+
* @param name - Backend name
|
|
22116
|
+
* @returns true if backend was enabled, false if not found
|
|
22117
|
+
*/
|
|
22118
|
+
enable(name) {
|
|
22119
|
+
const entry = this.backends.get(name);
|
|
22120
|
+
if (entry) {
|
|
22121
|
+
entry.enabled = true;
|
|
22122
|
+
return true;
|
|
22123
|
+
}
|
|
22124
|
+
return false;
|
|
22125
|
+
}
|
|
22126
|
+
/**
|
|
22127
|
+
* Disable a backend
|
|
22128
|
+
*
|
|
22129
|
+
* @param name - Backend name
|
|
22130
|
+
* @returns true if backend was disabled, false if not found
|
|
22131
|
+
*/
|
|
22132
|
+
disable(name) {
|
|
22133
|
+
const entry = this.backends.get(name);
|
|
22134
|
+
if (entry) {
|
|
22135
|
+
entry.enabled = false;
|
|
22136
|
+
return true;
|
|
22137
|
+
}
|
|
22138
|
+
return false;
|
|
22139
|
+
}
|
|
22140
|
+
/**
|
|
22141
|
+
* Set backend priority
|
|
22142
|
+
*
|
|
22143
|
+
* @param name - Backend name
|
|
22144
|
+
* @param priority - New priority value
|
|
22145
|
+
* @returns true if priority was set, false if not found
|
|
22146
|
+
*/
|
|
22147
|
+
setPriority(name, priority) {
|
|
22148
|
+
const entry = this.backends.get(name);
|
|
22149
|
+
if (entry) {
|
|
22150
|
+
entry.priority = priority;
|
|
22151
|
+
return true;
|
|
22152
|
+
}
|
|
22153
|
+
return false;
|
|
22154
|
+
}
|
|
22155
|
+
/**
|
|
22156
|
+
* Get count of registered backends
|
|
22157
|
+
*
|
|
22158
|
+
* @param enabledOnly - If true, only count enabled backends
|
|
22159
|
+
* @returns Number of backends
|
|
22160
|
+
*/
|
|
22161
|
+
count(enabledOnly = false) {
|
|
22162
|
+
if (enabledOnly) {
|
|
22163
|
+
return Array.from(this.backends.values()).filter((e) => e.enabled).length;
|
|
22164
|
+
}
|
|
22165
|
+
return this.backends.size;
|
|
22166
|
+
}
|
|
22167
|
+
/**
|
|
22168
|
+
* Clear all registered backends
|
|
22169
|
+
*/
|
|
22170
|
+
clear() {
|
|
22171
|
+
this.backends.clear();
|
|
22172
|
+
}
|
|
22173
|
+
/**
|
|
22174
|
+
* Get backend names
|
|
22175
|
+
*
|
|
22176
|
+
* @param enabledOnly - If true, only return enabled backend names
|
|
22177
|
+
* @returns Array of backend names
|
|
22178
|
+
*/
|
|
22179
|
+
getNames(enabledOnly = false) {
|
|
22180
|
+
if (enabledOnly) {
|
|
22181
|
+
return Array.from(this.backends.entries()).filter(([, entry]) => entry.enabled).map(([name]) => name);
|
|
22182
|
+
}
|
|
22183
|
+
return Array.from(this.backends.keys());
|
|
22184
|
+
}
|
|
22185
|
+
};
|
|
22186
|
+
var defaultRegistry = new PrivacyBackendRegistry();
|
|
22187
|
+
|
|
22188
|
+
// src/privacy-backends/sip-native.ts
|
|
22189
|
+
var SUPPORTED_CHAINS = [
|
|
22190
|
+
"solana",
|
|
22191
|
+
"ethereum",
|
|
22192
|
+
"near",
|
|
22193
|
+
"polygon",
|
|
22194
|
+
"arbitrum",
|
|
22195
|
+
"optimism",
|
|
22196
|
+
"base",
|
|
22197
|
+
"avalanche",
|
|
22198
|
+
"bsc"
|
|
22199
|
+
];
|
|
22200
|
+
var SIP_NATIVE_CAPABILITIES = {
|
|
22201
|
+
hiddenAmount: true,
|
|
22202
|
+
hiddenSender: true,
|
|
22203
|
+
hiddenRecipient: true,
|
|
22204
|
+
hiddenCompute: false,
|
|
22205
|
+
complianceSupport: true,
|
|
22206
|
+
anonymitySet: void 0,
|
|
22207
|
+
// Not pool-based
|
|
22208
|
+
setupRequired: false,
|
|
22209
|
+
latencyEstimate: "fast",
|
|
22210
|
+
supportedTokens: "all",
|
|
22211
|
+
minAmount: void 0,
|
|
22212
|
+
maxAmount: void 0
|
|
22213
|
+
};
|
|
22214
|
+
var SIPNativeBackend = class {
|
|
22215
|
+
name = "sip-native";
|
|
22216
|
+
type = "transaction";
|
|
22217
|
+
chains;
|
|
22218
|
+
config;
|
|
22219
|
+
/**
|
|
22220
|
+
* Create a new SIP Native backend
|
|
22221
|
+
*
|
|
22222
|
+
* @param config - Backend configuration
|
|
22223
|
+
*/
|
|
22224
|
+
constructor(config = {}) {
|
|
22225
|
+
this.chains = config.chains ?? SUPPORTED_CHAINS;
|
|
22226
|
+
this.config = {
|
|
22227
|
+
chains: this.chains,
|
|
22228
|
+
requireViewingKey: config.requireViewingKey ?? false,
|
|
22229
|
+
minAmount: config.minAmount ?? BigInt(0),
|
|
22230
|
+
maxAmount: config.maxAmount ?? BigInt(Number.MAX_SAFE_INTEGER)
|
|
22231
|
+
};
|
|
22232
|
+
}
|
|
22233
|
+
/**
|
|
22234
|
+
* Check if backend is available for given parameters
|
|
22235
|
+
*/
|
|
22236
|
+
async checkAvailability(params) {
|
|
22237
|
+
if (!this.chains.includes(params.chain)) {
|
|
22238
|
+
return {
|
|
22239
|
+
available: false,
|
|
22240
|
+
reason: `Chain '${params.chain}' not supported by SIP Native backend`
|
|
22241
|
+
};
|
|
22242
|
+
}
|
|
22243
|
+
if (this.config.requireViewingKey && !params.viewingKey) {
|
|
22244
|
+
return {
|
|
22245
|
+
available: false,
|
|
22246
|
+
reason: "Viewing key required for SIP Native backend"
|
|
22247
|
+
};
|
|
22248
|
+
}
|
|
22249
|
+
if (params.amount < this.config.minAmount) {
|
|
22250
|
+
return {
|
|
22251
|
+
available: false,
|
|
22252
|
+
reason: `Amount ${params.amount} below minimum ${this.config.minAmount}`
|
|
22253
|
+
};
|
|
22254
|
+
}
|
|
22255
|
+
if (params.amount > this.config.maxAmount) {
|
|
22256
|
+
return {
|
|
22257
|
+
available: false,
|
|
22258
|
+
reason: `Amount ${params.amount} above maximum ${this.config.maxAmount}`
|
|
22259
|
+
};
|
|
22260
|
+
}
|
|
22261
|
+
const estimatedCost = this.getEstimatedCostForChain(params.chain);
|
|
22262
|
+
return {
|
|
22263
|
+
available: true,
|
|
22264
|
+
estimatedCost,
|
|
22265
|
+
estimatedTime: 1e3
|
|
22266
|
+
// ~1 second for stealth address operations
|
|
22267
|
+
};
|
|
22268
|
+
}
|
|
22269
|
+
/**
|
|
22270
|
+
* Get backend capabilities
|
|
22271
|
+
*/
|
|
22272
|
+
getCapabilities() {
|
|
22273
|
+
return {
|
|
22274
|
+
...SIP_NATIVE_CAPABILITIES,
|
|
22275
|
+
minAmount: this.config.minAmount > BigInt(0) ? this.config.minAmount : void 0,
|
|
22276
|
+
maxAmount: this.config.maxAmount < BigInt(Number.MAX_SAFE_INTEGER) ? this.config.maxAmount : void 0
|
|
22277
|
+
};
|
|
22278
|
+
}
|
|
22279
|
+
/**
|
|
22280
|
+
* Execute a privacy-preserving transfer
|
|
22281
|
+
*
|
|
22282
|
+
* This creates a stealth address transfer with:
|
|
22283
|
+
* - Ephemeral keypair generation
|
|
22284
|
+
* - Stealth address derivation
|
|
22285
|
+
* - Pedersen commitment for amount
|
|
22286
|
+
* - Optional viewing key encryption
|
|
22287
|
+
*/
|
|
22288
|
+
async execute(params) {
|
|
22289
|
+
const availability = await this.checkAvailability(params);
|
|
22290
|
+
if (!availability.available) {
|
|
22291
|
+
return {
|
|
22292
|
+
success: false,
|
|
22293
|
+
error: availability.reason,
|
|
22294
|
+
backend: this.name
|
|
22295
|
+
};
|
|
22296
|
+
}
|
|
22297
|
+
try {
|
|
22298
|
+
const simulatedSignature = `sim_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
22299
|
+
return {
|
|
22300
|
+
success: true,
|
|
22301
|
+
signature: simulatedSignature,
|
|
22302
|
+
backend: this.name,
|
|
22303
|
+
metadata: {
|
|
22304
|
+
chain: params.chain,
|
|
22305
|
+
amount: params.amount.toString(),
|
|
22306
|
+
hasViewingKey: !!params.viewingKey,
|
|
22307
|
+
timestamp: Date.now()
|
|
22308
|
+
}
|
|
22309
|
+
};
|
|
22310
|
+
} catch (error) {
|
|
22311
|
+
return {
|
|
22312
|
+
success: false,
|
|
22313
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
22314
|
+
backend: this.name
|
|
22315
|
+
};
|
|
22316
|
+
}
|
|
22317
|
+
}
|
|
22318
|
+
/**
|
|
22319
|
+
* Estimate cost for a transfer
|
|
22320
|
+
*/
|
|
22321
|
+
async estimateCost(params) {
|
|
22322
|
+
return this.getEstimatedCostForChain(params.chain);
|
|
22323
|
+
}
|
|
22324
|
+
/**
|
|
22325
|
+
* Get estimated cost based on chain
|
|
22326
|
+
*/
|
|
22327
|
+
getEstimatedCostForChain(chain) {
|
|
22328
|
+
const costMap = {
|
|
22329
|
+
solana: BigInt(5e3),
|
|
22330
|
+
// ~0.000005 SOL
|
|
22331
|
+
ethereum: BigInt("50000000000000"),
|
|
22332
|
+
// ~0.00005 ETH
|
|
22333
|
+
near: BigInt("1000000000000000000000"),
|
|
22334
|
+
// ~0.001 NEAR
|
|
22335
|
+
polygon: BigInt("50000000000000"),
|
|
22336
|
+
// ~0.00005 MATIC
|
|
22337
|
+
arbitrum: BigInt("50000000000000"),
|
|
22338
|
+
optimism: BigInt("50000000000000"),
|
|
22339
|
+
base: BigInt("50000000000000"),
|
|
22340
|
+
avalanche: BigInt("50000000000000"),
|
|
22341
|
+
bsc: BigInt("50000000000000")
|
|
22342
|
+
};
|
|
22343
|
+
return costMap[chain] ?? BigInt(0);
|
|
22344
|
+
}
|
|
22345
|
+
};
|
|
22346
|
+
|
|
22347
|
+
// src/privacy-backends/privacycash-types.ts
|
|
22348
|
+
var SOL_POOL_SIZES = {
|
|
22349
|
+
/** 0.1 SOL pool */
|
|
22350
|
+
SMALL: BigInt(1e8),
|
|
22351
|
+
/** 1 SOL pool */
|
|
22352
|
+
MEDIUM: BigInt(1e9),
|
|
22353
|
+
/** 10 SOL pool */
|
|
22354
|
+
LARGE: BigInt(1e10),
|
|
22355
|
+
/** 100 SOL pool */
|
|
22356
|
+
WHALE: BigInt(1e11)
|
|
22357
|
+
};
|
|
22358
|
+
var USDC_POOL_SIZES = {
|
|
22359
|
+
/** 10 USDC pool */
|
|
22360
|
+
SMALL: BigInt(1e7),
|
|
22361
|
+
/** 100 USDC pool */
|
|
22362
|
+
MEDIUM: BigInt(1e8),
|
|
22363
|
+
/** 1,000 USDC pool */
|
|
22364
|
+
LARGE: BigInt(1e9),
|
|
22365
|
+
/** 10,000 USDC pool */
|
|
22366
|
+
WHALE: BigInt(1e10)
|
|
22367
|
+
};
|
|
22368
|
+
var USDT_POOL_SIZES = {
|
|
22369
|
+
/** 10 USDT pool */
|
|
22370
|
+
SMALL: BigInt(1e7),
|
|
22371
|
+
/** 100 USDT pool */
|
|
22372
|
+
MEDIUM: BigInt(1e8),
|
|
22373
|
+
/** 1,000 USDT pool */
|
|
22374
|
+
LARGE: BigInt(1e9),
|
|
22375
|
+
/** 10,000 USDT pool */
|
|
22376
|
+
WHALE: BigInt(1e10)
|
|
22377
|
+
};
|
|
22378
|
+
var SOL_POOL_AMOUNTS = [
|
|
22379
|
+
SOL_POOL_SIZES.SMALL,
|
|
22380
|
+
SOL_POOL_SIZES.MEDIUM,
|
|
22381
|
+
SOL_POOL_SIZES.LARGE,
|
|
22382
|
+
SOL_POOL_SIZES.WHALE
|
|
22383
|
+
];
|
|
22384
|
+
var SPL_POOL_AMOUNTS = [
|
|
22385
|
+
USDC_POOL_SIZES.SMALL,
|
|
22386
|
+
USDC_POOL_SIZES.MEDIUM,
|
|
22387
|
+
USDC_POOL_SIZES.LARGE,
|
|
22388
|
+
USDC_POOL_SIZES.WHALE
|
|
22389
|
+
];
|
|
22390
|
+
|
|
22391
|
+
// src/privacy-backends/privacycash.ts
|
|
22392
|
+
var DEFAULT_ANONYMITY_SET = 50;
|
|
22393
|
+
var BASE_COST_LAMPORTS = BigInt(1e7);
|
|
22394
|
+
var PRIVACYCASH_CAPABILITIES = {
|
|
22395
|
+
hiddenAmount: false,
|
|
22396
|
+
// Fixed pool sizes, amount is known
|
|
22397
|
+
hiddenSender: true,
|
|
22398
|
+
// Pool mixing hides sender
|
|
22399
|
+
hiddenRecipient: true,
|
|
22400
|
+
// Withdrawal to fresh address
|
|
22401
|
+
hiddenCompute: false,
|
|
22402
|
+
// No compute privacy
|
|
22403
|
+
complianceSupport: false,
|
|
22404
|
+
// No viewing keys
|
|
22405
|
+
anonymitySet: DEFAULT_ANONYMITY_SET,
|
|
22406
|
+
setupRequired: false,
|
|
22407
|
+
// No setup needed
|
|
22408
|
+
latencyEstimate: "medium",
|
|
22409
|
+
// Need to wait for pool
|
|
22410
|
+
supportedTokens: "all",
|
|
22411
|
+
// SOL + USDC/USDT
|
|
22412
|
+
minAmount: SOL_POOL_AMOUNTS[0],
|
|
22413
|
+
// Smallest pool
|
|
22414
|
+
maxAmount: SOL_POOL_AMOUNTS[SOL_POOL_AMOUNTS.length - 1]
|
|
22415
|
+
// Largest pool
|
|
22416
|
+
};
|
|
22417
|
+
|
|
22418
|
+
// src/privacy-backends/router.ts
|
|
22419
|
+
var DEFAULT_CONFIG2 = {
|
|
22420
|
+
prioritize: "privacy",
|
|
22421
|
+
requireViewingKeys: false,
|
|
22422
|
+
allowComputePrivacy: true
|
|
22423
|
+
};
|
|
22424
|
+
var PRIORITY_WEIGHTS = {
|
|
22425
|
+
privacy: {
|
|
22426
|
+
hiddenAmount: 25,
|
|
22427
|
+
hiddenSender: 25,
|
|
22428
|
+
hiddenRecipient: 25,
|
|
22429
|
+
hiddenCompute: 10,
|
|
22430
|
+
anonymitySet: 15
|
|
22431
|
+
},
|
|
22432
|
+
speed: {
|
|
22433
|
+
fast: 40,
|
|
22434
|
+
medium: 25,
|
|
22435
|
+
slow: 10,
|
|
22436
|
+
setupRequired: -20
|
|
22437
|
+
},
|
|
22438
|
+
cost: {
|
|
22439
|
+
baseCost: 50,
|
|
22440
|
+
estimatedCost: 50
|
|
22441
|
+
},
|
|
22442
|
+
compliance: {
|
|
22443
|
+
complianceSupport: 60,
|
|
22444
|
+
hiddenAmount: 15,
|
|
22445
|
+
hiddenSender: 15,
|
|
22446
|
+
hiddenRecipient: 10
|
|
22447
|
+
}
|
|
22448
|
+
};
|
|
22449
|
+
var SmartRouter2 = class {
|
|
22450
|
+
registry;
|
|
22451
|
+
/**
|
|
22452
|
+
* Create a new SmartRouter
|
|
22453
|
+
*
|
|
22454
|
+
* @param registry - Backend registry to use for selection
|
|
22455
|
+
*/
|
|
22456
|
+
constructor(registry) {
|
|
22457
|
+
this.registry = registry;
|
|
22458
|
+
}
|
|
22459
|
+
/**
|
|
22460
|
+
* Select the best backend for a transfer
|
|
22461
|
+
*
|
|
22462
|
+
* @param params - Transfer parameters
|
|
22463
|
+
* @param config - Router configuration
|
|
22464
|
+
* @returns Selection result with backend and reasoning
|
|
22465
|
+
* @throws Error if no suitable backend is found
|
|
22466
|
+
*/
|
|
22467
|
+
async selectBackend(params, config = {}) {
|
|
22468
|
+
const fullConfig = { ...DEFAULT_CONFIG2, ...config };
|
|
22469
|
+
const chainBackends = this.registry.getByChain(params.chain);
|
|
22470
|
+
if (chainBackends.length === 0) {
|
|
22471
|
+
throw new Error(
|
|
22472
|
+
`No backends available for chain '${params.chain}'. Register a backend that supports this chain.`
|
|
22473
|
+
);
|
|
22474
|
+
}
|
|
22475
|
+
const scoredBackends = [];
|
|
22476
|
+
for (const backend of chainBackends) {
|
|
22477
|
+
if (fullConfig.excludeBackends?.includes(backend.name)) {
|
|
22478
|
+
continue;
|
|
22479
|
+
}
|
|
22480
|
+
const availability = await backend.checkAvailability(params);
|
|
22481
|
+
if (!availability.available) {
|
|
22482
|
+
continue;
|
|
22483
|
+
}
|
|
22484
|
+
const capabilities = backend.getCapabilities();
|
|
22485
|
+
if (fullConfig.requireViewingKeys && !capabilities.complianceSupport) {
|
|
22486
|
+
continue;
|
|
22487
|
+
}
|
|
22488
|
+
if (fullConfig.minAnonymitySet && capabilities.anonymitySet !== void 0 && capabilities.anonymitySet < fullConfig.minAnonymitySet) {
|
|
22489
|
+
continue;
|
|
22490
|
+
}
|
|
22491
|
+
if (!fullConfig.allowComputePrivacy && backend.type === "compute") {
|
|
22492
|
+
continue;
|
|
22493
|
+
}
|
|
22494
|
+
if (fullConfig.maxCost && availability.estimatedCost) {
|
|
22495
|
+
if (availability.estimatedCost > fullConfig.maxCost) {
|
|
22496
|
+
continue;
|
|
22497
|
+
}
|
|
22498
|
+
}
|
|
22499
|
+
if (fullConfig.maxLatency && availability.estimatedTime) {
|
|
22500
|
+
if (availability.estimatedTime > fullConfig.maxLatency) {
|
|
22501
|
+
continue;
|
|
22502
|
+
}
|
|
22503
|
+
}
|
|
22504
|
+
const { score, reason } = this.scoreBackend(
|
|
22505
|
+
backend,
|
|
22506
|
+
availability,
|
|
22507
|
+
fullConfig
|
|
22508
|
+
);
|
|
22509
|
+
scoredBackends.push({
|
|
22510
|
+
backend,
|
|
22511
|
+
availability,
|
|
22512
|
+
score,
|
|
22513
|
+
reason
|
|
22514
|
+
});
|
|
22515
|
+
}
|
|
22516
|
+
if (scoredBackends.length === 0) {
|
|
22517
|
+
throw new Error(
|
|
22518
|
+
`No backends meet the requirements for this transfer. Check your router configuration and registered backends.`
|
|
22519
|
+
);
|
|
22520
|
+
}
|
|
22521
|
+
scoredBackends.sort((a, b) => b.score - a.score);
|
|
22522
|
+
if (fullConfig.preferredBackend) {
|
|
22523
|
+
const preferredIndex = scoredBackends.findIndex(
|
|
22524
|
+
(s) => s.backend.name === fullConfig.preferredBackend
|
|
22525
|
+
);
|
|
22526
|
+
if (preferredIndex > 0) {
|
|
22527
|
+
const preferred = scoredBackends[preferredIndex];
|
|
22528
|
+
const leader = scoredBackends[0];
|
|
22529
|
+
if (leader.score - preferred.score <= 10) {
|
|
22530
|
+
scoredBackends.splice(preferredIndex, 1);
|
|
22531
|
+
scoredBackends.unshift(preferred);
|
|
22532
|
+
preferred.reason = `Preferred backend (within 10pts of optimal)`;
|
|
22533
|
+
}
|
|
22534
|
+
}
|
|
22535
|
+
}
|
|
22536
|
+
const selected = scoredBackends[0];
|
|
22537
|
+
const alternatives = scoredBackends.slice(1).map((s) => ({
|
|
22538
|
+
backend: s.backend,
|
|
22539
|
+
score: s.score,
|
|
22540
|
+
reason: s.reason
|
|
22541
|
+
}));
|
|
22542
|
+
return {
|
|
22543
|
+
backend: selected.backend,
|
|
22544
|
+
reason: selected.reason,
|
|
22545
|
+
alternatives,
|
|
22546
|
+
score: selected.score
|
|
22547
|
+
};
|
|
22548
|
+
}
|
|
22549
|
+
/**
|
|
22550
|
+
* Execute a transfer using the best available backend
|
|
22551
|
+
*
|
|
22552
|
+
* @param params - Transfer parameters
|
|
22553
|
+
* @param config - Router configuration
|
|
22554
|
+
* @returns Transaction result
|
|
22555
|
+
*/
|
|
22556
|
+
async execute(params, config = {}) {
|
|
22557
|
+
const selection = await this.selectBackend(params, config);
|
|
22558
|
+
return selection.backend.execute(params);
|
|
22559
|
+
}
|
|
22560
|
+
/**
|
|
22561
|
+
* Get available backends for a transfer (without selecting)
|
|
22562
|
+
*
|
|
22563
|
+
* @param params - Transfer parameters
|
|
22564
|
+
* @returns Array of available backends with scores
|
|
22565
|
+
*/
|
|
22566
|
+
async getAvailableBackends(params) {
|
|
22567
|
+
return this.registry.findAvailable(params);
|
|
22568
|
+
}
|
|
22569
|
+
/**
|
|
22570
|
+
* Score a backend based on configuration priority
|
|
22571
|
+
*/
|
|
22572
|
+
scoreBackend(backend, availability, config) {
|
|
22573
|
+
const capabilities = backend.getCapabilities();
|
|
22574
|
+
let score = 0;
|
|
22575
|
+
const reasons = [];
|
|
22576
|
+
switch (config.prioritize) {
|
|
22577
|
+
case "privacy":
|
|
22578
|
+
if (capabilities.hiddenAmount) {
|
|
22579
|
+
score += PRIORITY_WEIGHTS.privacy.hiddenAmount;
|
|
22580
|
+
reasons.push("hidden amounts");
|
|
22581
|
+
}
|
|
22582
|
+
if (capabilities.hiddenSender) {
|
|
22583
|
+
score += PRIORITY_WEIGHTS.privacy.hiddenSender;
|
|
22584
|
+
reasons.push("hidden sender");
|
|
22585
|
+
}
|
|
22586
|
+
if (capabilities.hiddenRecipient) {
|
|
22587
|
+
score += PRIORITY_WEIGHTS.privacy.hiddenRecipient;
|
|
22588
|
+
reasons.push("hidden recipient");
|
|
22589
|
+
}
|
|
22590
|
+
if (capabilities.hiddenCompute) {
|
|
22591
|
+
score += PRIORITY_WEIGHTS.privacy.hiddenCompute;
|
|
22592
|
+
reasons.push("private compute");
|
|
22593
|
+
}
|
|
22594
|
+
if (capabilities.anonymitySet && capabilities.anonymitySet >= 100) {
|
|
22595
|
+
score += PRIORITY_WEIGHTS.privacy.anonymitySet;
|
|
22596
|
+
reasons.push(`anonymity set: ${capabilities.anonymitySet}`);
|
|
22597
|
+
}
|
|
22598
|
+
break;
|
|
22599
|
+
case "speed":
|
|
22600
|
+
score += PRIORITY_WEIGHTS.speed[capabilities.latencyEstimate];
|
|
22601
|
+
reasons.push(`${capabilities.latencyEstimate} latency`);
|
|
22602
|
+
if (capabilities.setupRequired) {
|
|
22603
|
+
score += PRIORITY_WEIGHTS.speed.setupRequired;
|
|
22604
|
+
reasons.push("setup required");
|
|
22605
|
+
}
|
|
22606
|
+
break;
|
|
22607
|
+
case "cost":
|
|
22608
|
+
if (availability.estimatedCost !== void 0) {
|
|
22609
|
+
const logCost = availability.estimatedCost > BigInt(0) ? Math.log10(Number(availability.estimatedCost)) : 0;
|
|
22610
|
+
const costScore = Math.max(0, 70 - logCost * 5);
|
|
22611
|
+
score += costScore;
|
|
22612
|
+
reasons.push(`low cost`);
|
|
22613
|
+
}
|
|
22614
|
+
break;
|
|
22615
|
+
case "compliance":
|
|
22616
|
+
if (capabilities.complianceSupport) {
|
|
22617
|
+
score += PRIORITY_WEIGHTS.compliance.complianceSupport;
|
|
22618
|
+
reasons.push("viewing key support");
|
|
22619
|
+
}
|
|
22620
|
+
if (capabilities.hiddenAmount) {
|
|
22621
|
+
score += PRIORITY_WEIGHTS.compliance.hiddenAmount;
|
|
22622
|
+
}
|
|
22623
|
+
if (capabilities.hiddenSender) {
|
|
22624
|
+
score += PRIORITY_WEIGHTS.compliance.hiddenSender;
|
|
22625
|
+
}
|
|
22626
|
+
if (capabilities.hiddenRecipient) {
|
|
22627
|
+
score += PRIORITY_WEIGHTS.compliance.hiddenRecipient;
|
|
22628
|
+
}
|
|
22629
|
+
break;
|
|
22630
|
+
}
|
|
22631
|
+
score = Math.min(100, Math.max(0, score));
|
|
22632
|
+
return {
|
|
22633
|
+
score,
|
|
22634
|
+
reason: reasons.length > 0 ? reasons.join(", ") : "default selection"
|
|
22635
|
+
};
|
|
22636
|
+
}
|
|
22637
|
+
};
|
|
22638
|
+
|
|
22639
|
+
// src/surveillance/algorithms/address-reuse.ts
|
|
22640
|
+
var MAX_DEDUCTION = 25;
|
|
22641
|
+
var DEDUCTION_PER_REUSE = 2;
|
|
22642
|
+
var REUSE_THRESHOLD = 1;
|
|
22643
|
+
function analyzeAddressReuse(transactions, walletAddress) {
|
|
22644
|
+
const receiveAddresses = /* @__PURE__ */ new Map();
|
|
22645
|
+
const sendAddresses = /* @__PURE__ */ new Map();
|
|
22646
|
+
for (const tx of transactions) {
|
|
22647
|
+
if (!tx.success) continue;
|
|
22648
|
+
if (tx.recipient === walletAddress) {
|
|
22649
|
+
const count = receiveAddresses.get(walletAddress) ?? 0;
|
|
22650
|
+
receiveAddresses.set(walletAddress, count + 1);
|
|
22651
|
+
}
|
|
22652
|
+
if (tx.sender === walletAddress) {
|
|
22653
|
+
const count = sendAddresses.get(walletAddress) ?? 0;
|
|
22654
|
+
sendAddresses.set(walletAddress, count + 1);
|
|
22655
|
+
}
|
|
22656
|
+
for (const addr of tx.involvedAddresses) {
|
|
22657
|
+
if (addr === walletAddress) continue;
|
|
22658
|
+
if (tx.sender === walletAddress) {
|
|
22659
|
+
const count = sendAddresses.get(addr) ?? 0;
|
|
22660
|
+
sendAddresses.set(addr, count + 1);
|
|
22661
|
+
}
|
|
22662
|
+
if (tx.recipient === walletAddress) {
|
|
22663
|
+
const count = receiveAddresses.get(addr) ?? 0;
|
|
22664
|
+
receiveAddresses.set(addr, count + 1);
|
|
22665
|
+
}
|
|
22666
|
+
}
|
|
22667
|
+
}
|
|
22668
|
+
let receiveReuseCount = 0;
|
|
22669
|
+
let sendReuseCount = 0;
|
|
22670
|
+
const reusedAddresses = [];
|
|
22671
|
+
for (const [address, count] of Array.from(receiveAddresses.entries())) {
|
|
22672
|
+
if (count > REUSE_THRESHOLD) {
|
|
22673
|
+
const reuseCount = count - REUSE_THRESHOLD;
|
|
22674
|
+
receiveReuseCount += reuseCount;
|
|
22675
|
+
const existing = reusedAddresses.find((r) => r.address === address);
|
|
22676
|
+
if (existing) {
|
|
22677
|
+
existing.useCount = Math.max(existing.useCount, count);
|
|
22678
|
+
existing.type = "both";
|
|
22679
|
+
} else {
|
|
22680
|
+
reusedAddresses.push({
|
|
22681
|
+
address,
|
|
22682
|
+
useCount: count,
|
|
22683
|
+
type: "receive"
|
|
22684
|
+
});
|
|
22685
|
+
}
|
|
22686
|
+
}
|
|
22687
|
+
}
|
|
22688
|
+
for (const [address, count] of Array.from(sendAddresses.entries())) {
|
|
22689
|
+
if (count > REUSE_THRESHOLD) {
|
|
22690
|
+
const reuseCount = count - REUSE_THRESHOLD;
|
|
22691
|
+
sendReuseCount += reuseCount;
|
|
22692
|
+
const existing = reusedAddresses.find((r) => r.address === address);
|
|
22693
|
+
if (existing) {
|
|
22694
|
+
existing.useCount = Math.max(existing.useCount, count);
|
|
22695
|
+
existing.type = "both";
|
|
22696
|
+
} else {
|
|
22697
|
+
reusedAddresses.push({
|
|
22698
|
+
address,
|
|
22699
|
+
useCount: count,
|
|
22700
|
+
type: "send"
|
|
22701
|
+
});
|
|
22702
|
+
}
|
|
22703
|
+
}
|
|
22704
|
+
}
|
|
22705
|
+
const totalReuseCount = receiveReuseCount + sendReuseCount;
|
|
22706
|
+
const rawDeduction = totalReuseCount * DEDUCTION_PER_REUSE;
|
|
22707
|
+
const scoreDeduction = Math.min(rawDeduction, MAX_DEDUCTION);
|
|
22708
|
+
reusedAddresses.sort((a, b) => b.useCount - a.useCount);
|
|
22709
|
+
return {
|
|
22710
|
+
receiveReuseCount,
|
|
22711
|
+
sendReuseCount,
|
|
22712
|
+
totalReuseCount,
|
|
22713
|
+
scoreDeduction,
|
|
22714
|
+
reusedAddresses: reusedAddresses.slice(0, 10)
|
|
22715
|
+
// Top 10 most reused
|
|
22716
|
+
};
|
|
22717
|
+
}
|
|
22718
|
+
|
|
22719
|
+
// src/surveillance/algorithms/cluster.ts
|
|
22720
|
+
var MAX_DEDUCTION2 = 25;
|
|
22721
|
+
var DEDUCTION_PER_LINK = 3;
|
|
22722
|
+
var MIN_LINK_THRESHOLD = 2;
|
|
22723
|
+
var UnionFind = class {
|
|
22724
|
+
parent;
|
|
22725
|
+
rank;
|
|
22726
|
+
constructor() {
|
|
22727
|
+
this.parent = /* @__PURE__ */ new Map();
|
|
22728
|
+
this.rank = /* @__PURE__ */ new Map();
|
|
22729
|
+
}
|
|
22730
|
+
find(x) {
|
|
22731
|
+
if (!this.parent.has(x)) {
|
|
22732
|
+
this.parent.set(x, x);
|
|
22733
|
+
this.rank.set(x, 0);
|
|
22734
|
+
}
|
|
22735
|
+
if (this.parent.get(x) !== x) {
|
|
22736
|
+
this.parent.set(x, this.find(this.parent.get(x)));
|
|
22737
|
+
}
|
|
22738
|
+
return this.parent.get(x);
|
|
22739
|
+
}
|
|
22740
|
+
union(x, y) {
|
|
22741
|
+
const rootX = this.find(x);
|
|
22742
|
+
const rootY = this.find(y);
|
|
22743
|
+
if (rootX === rootY) return;
|
|
22744
|
+
const rankX = this.rank.get(rootX) ?? 0;
|
|
22745
|
+
const rankY = this.rank.get(rootY) ?? 0;
|
|
22746
|
+
if (rankX < rankY) {
|
|
22747
|
+
this.parent.set(rootX, rootY);
|
|
22748
|
+
} else if (rankX > rankY) {
|
|
22749
|
+
this.parent.set(rootY, rootX);
|
|
22750
|
+
} else {
|
|
22751
|
+
this.parent.set(rootY, rootX);
|
|
22752
|
+
this.rank.set(rootX, rankX + 1);
|
|
22753
|
+
}
|
|
22754
|
+
}
|
|
22755
|
+
getClusters() {
|
|
22756
|
+
const clusters = /* @__PURE__ */ new Map();
|
|
22757
|
+
for (const addr of Array.from(this.parent.keys())) {
|
|
22758
|
+
const root = this.find(addr);
|
|
22759
|
+
if (!clusters.has(root)) {
|
|
22760
|
+
clusters.set(root, []);
|
|
22761
|
+
}
|
|
22762
|
+
clusters.get(root).push(addr);
|
|
22763
|
+
}
|
|
22764
|
+
return clusters;
|
|
22765
|
+
}
|
|
22766
|
+
};
|
|
22767
|
+
function detectClusters(transactions, walletAddress) {
|
|
22768
|
+
const uf = new UnionFind();
|
|
22769
|
+
const linkCounts = /* @__PURE__ */ new Map();
|
|
22770
|
+
const linkTypes = /* @__PURE__ */ new Map();
|
|
22771
|
+
const txCountPerPair = /* @__PURE__ */ new Map();
|
|
22772
|
+
uf.find(walletAddress);
|
|
22773
|
+
for (const tx of transactions) {
|
|
22774
|
+
if (!tx.success) continue;
|
|
22775
|
+
const involvedWithWallet = tx.involvedAddresses.filter(
|
|
22776
|
+
(addr) => addr !== walletAddress
|
|
22777
|
+
);
|
|
22778
|
+
if (tx.sender === walletAddress && involvedWithWallet.length > 0) {
|
|
22779
|
+
for (const addr of involvedWithWallet) {
|
|
22780
|
+
const pairKey = [walletAddress, addr].sort().join(":");
|
|
22781
|
+
const count = (txCountPerPair.get(pairKey) ?? 0) + 1;
|
|
22782
|
+
txCountPerPair.set(pairKey, count);
|
|
22783
|
+
if (count >= MIN_LINK_THRESHOLD) {
|
|
22784
|
+
uf.union(walletAddress, addr);
|
|
22785
|
+
linkCounts.set(addr, count);
|
|
22786
|
+
linkTypes.set(addr, "common-input");
|
|
22787
|
+
}
|
|
22788
|
+
}
|
|
22789
|
+
}
|
|
22790
|
+
if (tx.sender === walletAddress && tx.recipient !== walletAddress) {
|
|
22791
|
+
const otherRecipients = involvedWithWallet.filter(
|
|
22792
|
+
(addr) => addr !== tx.recipient
|
|
22793
|
+
);
|
|
22794
|
+
for (const addr of otherRecipients) {
|
|
22795
|
+
const pairKey = [walletAddress, addr].sort().join(":");
|
|
22796
|
+
const count = (txCountPerPair.get(pairKey) ?? 0) + 1;
|
|
22797
|
+
txCountPerPair.set(pairKey, count);
|
|
22798
|
+
if (count >= MIN_LINK_THRESHOLD) {
|
|
22799
|
+
uf.union(walletAddress, addr);
|
|
22800
|
+
if (!linkTypes.has(addr)) {
|
|
22801
|
+
linkTypes.set(addr, "change-address");
|
|
22802
|
+
}
|
|
22803
|
+
linkCounts.set(addr, count);
|
|
22804
|
+
}
|
|
22805
|
+
}
|
|
22806
|
+
}
|
|
22807
|
+
if (tx.recipient === walletAddress && involvedWithWallet.length > 1) {
|
|
22808
|
+
for (let i = 0; i < involvedWithWallet.length; i++) {
|
|
22809
|
+
for (let j = i + 1; j < involvedWithWallet.length; j++) {
|
|
22810
|
+
const addr1 = involvedWithWallet[i];
|
|
22811
|
+
const addr2 = involvedWithWallet[j];
|
|
22812
|
+
const pairKey2 = [addr1, addr2].sort().join(":");
|
|
22813
|
+
const count2 = (txCountPerPair.get(pairKey2) ?? 0) + 1;
|
|
22814
|
+
txCountPerPair.set(pairKey2, count2);
|
|
22815
|
+
if (count2 >= MIN_LINK_THRESHOLD) {
|
|
22816
|
+
uf.union(addr1, addr2);
|
|
22817
|
+
linkTypes.set(addr1, "consolidation");
|
|
22818
|
+
linkTypes.set(addr2, "consolidation");
|
|
22819
|
+
}
|
|
22820
|
+
}
|
|
22821
|
+
const pairKey = [walletAddress, involvedWithWallet[i]].sort().join(":");
|
|
22822
|
+
const count = (txCountPerPair.get(pairKey) ?? 0) + 1;
|
|
22823
|
+
txCountPerPair.set(pairKey, count);
|
|
22824
|
+
if (count >= MIN_LINK_THRESHOLD) {
|
|
22825
|
+
uf.union(walletAddress, involvedWithWallet[i]);
|
|
22826
|
+
linkCounts.set(involvedWithWallet[i], count);
|
|
22827
|
+
}
|
|
22828
|
+
}
|
|
22829
|
+
}
|
|
22830
|
+
}
|
|
22831
|
+
const allClusters = uf.getClusters();
|
|
22832
|
+
const walletRoot = uf.find(walletAddress);
|
|
22833
|
+
const walletCluster = allClusters.get(walletRoot) ?? [walletAddress];
|
|
22834
|
+
const linkedAddresses = walletCluster.filter((addr) => addr !== walletAddress);
|
|
22835
|
+
const linkedAddressCount = linkedAddresses.length;
|
|
22836
|
+
const totalLinkTxs = Array.from(linkCounts.values()).reduce((a, b) => a + b, 0);
|
|
22837
|
+
const confidence = Math.min(totalLinkTxs / (linkedAddressCount * 5), 1);
|
|
22838
|
+
const rawDeduction = linkedAddressCount * DEDUCTION_PER_LINK;
|
|
22839
|
+
const scoreDeduction = Math.min(rawDeduction, MAX_DEDUCTION2);
|
|
22840
|
+
const clusters = [];
|
|
22841
|
+
if (linkedAddressCount > 0) {
|
|
22842
|
+
const byType = /* @__PURE__ */ new Map();
|
|
22843
|
+
for (const addr of linkedAddresses) {
|
|
22844
|
+
const type = linkTypes.get(addr) ?? "common-input";
|
|
22845
|
+
if (!byType.has(type)) {
|
|
22846
|
+
byType.set(type, []);
|
|
22847
|
+
}
|
|
22848
|
+
byType.get(type).push(addr);
|
|
22849
|
+
}
|
|
22850
|
+
for (const [type, addresses] of Array.from(byType.entries())) {
|
|
22851
|
+
const txCount = addresses.reduce(
|
|
22852
|
+
(sum, addr) => sum + (linkCounts.get(addr) ?? 0),
|
|
22853
|
+
0
|
|
22854
|
+
);
|
|
22855
|
+
clusters.push({
|
|
22856
|
+
addresses: [walletAddress, ...addresses],
|
|
22857
|
+
linkType: type,
|
|
22858
|
+
transactionCount: txCount
|
|
22859
|
+
});
|
|
22860
|
+
}
|
|
22861
|
+
}
|
|
22862
|
+
return {
|
|
22863
|
+
linkedAddressCount,
|
|
22864
|
+
confidence,
|
|
22865
|
+
scoreDeduction,
|
|
22866
|
+
clusters
|
|
22867
|
+
};
|
|
22868
|
+
}
|
|
22869
|
+
|
|
22870
|
+
// src/surveillance/algorithms/exchange.ts
|
|
22871
|
+
var MAX_DEDUCTION3 = 20;
|
|
22872
|
+
var DEDUCTION_PER_CEX = 8;
|
|
22873
|
+
var DEDUCTION_PER_DEX = 2;
|
|
22874
|
+
var KNOWN_EXCHANGES = [
|
|
22875
|
+
// Centralized Exchanges (KYC Required)
|
|
22876
|
+
{
|
|
22877
|
+
name: "Binance",
|
|
22878
|
+
addresses: [
|
|
22879
|
+
"5tzFkiKscXHK5ZXCGbXZxdw7gTjjD1mBwuoFbhUvuAi9",
|
|
22880
|
+
"9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
|
|
22881
|
+
"AC5RDfQFmDS1deWZos921JfqscXdByf8BKHs5ACWjtW2"
|
|
22882
|
+
],
|
|
22883
|
+
type: "cex",
|
|
22884
|
+
kycRequired: true
|
|
22885
|
+
},
|
|
22886
|
+
{
|
|
22887
|
+
name: "Coinbase",
|
|
22888
|
+
addresses: [
|
|
22889
|
+
"H8sMJSCQxfKiFTCfDR3DUMLPwcRbM61LGFJ8N4dK3WjS",
|
|
22890
|
+
"2ojv9BAiHUrvsm9gxDe7fJSzbNZSJcxZvf8dqmWGHG8S",
|
|
22891
|
+
"GJRs4FwHtemZ5ZE9x3FNvJ8TMwitKTh21yxdRPqn7npE"
|
|
22892
|
+
],
|
|
22893
|
+
type: "cex",
|
|
22894
|
+
kycRequired: true
|
|
22895
|
+
},
|
|
22896
|
+
{
|
|
22897
|
+
name: "Kraken",
|
|
22898
|
+
addresses: [
|
|
22899
|
+
"krakenmRKej41L9sX8N8Z2mhjZ8UpVHHBMzkKzfBh54"
|
|
22900
|
+
],
|
|
22901
|
+
type: "cex",
|
|
22902
|
+
kycRequired: true
|
|
22903
|
+
},
|
|
22904
|
+
{
|
|
22905
|
+
name: "FTX (Defunct)",
|
|
22906
|
+
addresses: [
|
|
22907
|
+
"FTXkd8cjuYGRLzPVdvqxNxNNNYBfFPPjrF3vW2Yq8p7"
|
|
22908
|
+
],
|
|
22909
|
+
type: "cex",
|
|
22910
|
+
kycRequired: true
|
|
22911
|
+
},
|
|
22912
|
+
{
|
|
22913
|
+
name: "KuCoin",
|
|
22914
|
+
addresses: [
|
|
22915
|
+
"BmFdpraQhkiDQE6SnfG5omcA1VwzqfXrwtNYBwWTymy6"
|
|
22916
|
+
],
|
|
22917
|
+
type: "cex",
|
|
22918
|
+
kycRequired: true
|
|
22919
|
+
},
|
|
22920
|
+
{
|
|
22921
|
+
name: "OKX",
|
|
22922
|
+
addresses: [
|
|
22923
|
+
"GGztQqQ6pCPaJQnNpXBgELr5cs3WwDakRbh1iEMzjgSJ"
|
|
22924
|
+
],
|
|
22925
|
+
type: "cex",
|
|
22926
|
+
kycRequired: true
|
|
22927
|
+
},
|
|
22928
|
+
{
|
|
22929
|
+
name: "Bybit",
|
|
22930
|
+
addresses: [
|
|
22931
|
+
"AC5RDfQFmDS1deWZos921JfqscXdByf8BKHs5ACWjtW3"
|
|
22932
|
+
],
|
|
22933
|
+
type: "cex",
|
|
22934
|
+
kycRequired: true
|
|
22935
|
+
},
|
|
22936
|
+
{
|
|
22937
|
+
name: "Gate.io",
|
|
22938
|
+
addresses: [
|
|
22939
|
+
"u6PJ8DtQuPFnfmwHbGFULQ4u4EgjDiyYKjVEsynXq2w"
|
|
22940
|
+
],
|
|
22941
|
+
type: "cex",
|
|
22942
|
+
kycRequired: true
|
|
22943
|
+
},
|
|
22944
|
+
// Decentralized Exchanges (No KYC but traceable)
|
|
22945
|
+
{
|
|
22946
|
+
name: "Jupiter",
|
|
22947
|
+
addresses: [
|
|
22948
|
+
"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
|
|
22949
|
+
"JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB"
|
|
22950
|
+
],
|
|
22951
|
+
type: "dex",
|
|
22952
|
+
kycRequired: false
|
|
22953
|
+
},
|
|
22954
|
+
{
|
|
22955
|
+
name: "Raydium",
|
|
22956
|
+
addresses: [
|
|
22957
|
+
"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8",
|
|
22958
|
+
"5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1"
|
|
22959
|
+
],
|
|
22960
|
+
type: "dex",
|
|
22961
|
+
kycRequired: false
|
|
22962
|
+
},
|
|
22963
|
+
{
|
|
22964
|
+
name: "Orca",
|
|
22965
|
+
addresses: [
|
|
22966
|
+
"9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP",
|
|
22967
|
+
"whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc"
|
|
22968
|
+
],
|
|
22969
|
+
type: "dex",
|
|
22970
|
+
kycRequired: false
|
|
22971
|
+
},
|
|
22972
|
+
{
|
|
22973
|
+
name: "Marinade",
|
|
22974
|
+
addresses: [
|
|
22975
|
+
"MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD"
|
|
22976
|
+
],
|
|
22977
|
+
type: "dex",
|
|
22978
|
+
kycRequired: false
|
|
22979
|
+
},
|
|
22980
|
+
{
|
|
22981
|
+
name: "Phantom Swap",
|
|
22982
|
+
addresses: [
|
|
22983
|
+
"PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY"
|
|
22984
|
+
],
|
|
22985
|
+
type: "dex",
|
|
22986
|
+
kycRequired: false
|
|
22987
|
+
}
|
|
22988
|
+
];
|
|
22989
|
+
function buildExchangeLookup(exchanges) {
|
|
22990
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
22991
|
+
for (const exchange of exchanges) {
|
|
22992
|
+
for (const address of exchange.addresses) {
|
|
22993
|
+
lookup.set(address, exchange);
|
|
22994
|
+
}
|
|
22995
|
+
}
|
|
22996
|
+
return lookup;
|
|
22997
|
+
}
|
|
22998
|
+
function detectExchangeExposure(transactions, walletAddress, customExchanges) {
|
|
22999
|
+
const exchanges = customExchanges ? [...KNOWN_EXCHANGES, ...customExchanges] : KNOWN_EXCHANGES;
|
|
23000
|
+
const lookup = buildExchangeLookup(exchanges);
|
|
23001
|
+
const exchangeStats = /* @__PURE__ */ new Map();
|
|
23002
|
+
for (const tx of transactions) {
|
|
23003
|
+
if (!tx.success) continue;
|
|
23004
|
+
for (const addr of tx.involvedAddresses) {
|
|
23005
|
+
const exchange = lookup.get(addr);
|
|
23006
|
+
if (!exchange) continue;
|
|
23007
|
+
if (!exchangeStats.has(exchange.name)) {
|
|
23008
|
+
exchangeStats.set(exchange.name, {
|
|
23009
|
+
exchange,
|
|
23010
|
+
deposits: 0,
|
|
23011
|
+
withdrawals: 0,
|
|
23012
|
+
firstInteraction: tx.timestamp,
|
|
23013
|
+
lastInteraction: tx.timestamp
|
|
23014
|
+
});
|
|
23015
|
+
}
|
|
23016
|
+
const stats = exchangeStats.get(exchange.name);
|
|
23017
|
+
stats.firstInteraction = Math.min(stats.firstInteraction, tx.timestamp);
|
|
23018
|
+
stats.lastInteraction = Math.max(stats.lastInteraction, tx.timestamp);
|
|
23019
|
+
if (tx.sender === walletAddress && tx.recipient === addr) {
|
|
23020
|
+
stats.deposits++;
|
|
23021
|
+
} else if (tx.sender === addr && tx.recipient === walletAddress) {
|
|
23022
|
+
stats.withdrawals++;
|
|
23023
|
+
} else if (tx.sender === walletAddress) {
|
|
23024
|
+
stats.deposits++;
|
|
23025
|
+
}
|
|
23026
|
+
}
|
|
23027
|
+
}
|
|
23028
|
+
let totalDeposits = 0;
|
|
23029
|
+
let totalWithdrawals = 0;
|
|
23030
|
+
let cexCount = 0;
|
|
23031
|
+
let dexCount = 0;
|
|
23032
|
+
const exchangeResults = [];
|
|
23033
|
+
for (const [name, stats] of Array.from(exchangeStats.entries())) {
|
|
23034
|
+
totalDeposits += stats.deposits;
|
|
23035
|
+
totalWithdrawals += stats.withdrawals;
|
|
23036
|
+
if (stats.exchange.type === "cex") {
|
|
23037
|
+
cexCount++;
|
|
23038
|
+
} else {
|
|
23039
|
+
dexCount++;
|
|
23040
|
+
}
|
|
23041
|
+
exchangeResults.push({
|
|
23042
|
+
name,
|
|
23043
|
+
type: stats.exchange.type,
|
|
23044
|
+
kycRequired: stats.exchange.kycRequired,
|
|
23045
|
+
deposits: stats.deposits,
|
|
23046
|
+
withdrawals: stats.withdrawals,
|
|
23047
|
+
firstInteraction: stats.firstInteraction,
|
|
23048
|
+
lastInteraction: stats.lastInteraction
|
|
23049
|
+
});
|
|
23050
|
+
}
|
|
23051
|
+
exchangeResults.sort(
|
|
23052
|
+
(a, b) => b.deposits + b.withdrawals - (a.deposits + a.withdrawals)
|
|
23053
|
+
);
|
|
23054
|
+
const cexDeduction = cexCount * DEDUCTION_PER_CEX;
|
|
23055
|
+
const dexDeduction = dexCount * DEDUCTION_PER_DEX;
|
|
23056
|
+
const rawDeduction = cexDeduction + dexDeduction;
|
|
23057
|
+
const scoreDeduction = Math.min(rawDeduction, MAX_DEDUCTION3);
|
|
23058
|
+
return {
|
|
23059
|
+
exchangeCount: exchangeStats.size,
|
|
23060
|
+
depositCount: totalDeposits,
|
|
23061
|
+
withdrawalCount: totalWithdrawals,
|
|
23062
|
+
scoreDeduction,
|
|
23063
|
+
exchanges: exchangeResults
|
|
23064
|
+
};
|
|
23065
|
+
}
|
|
23066
|
+
|
|
23067
|
+
// src/surveillance/algorithms/temporal.ts
|
|
23068
|
+
var MAX_DEDUCTION4 = 15;
|
|
23069
|
+
var DEDUCTION_PER_PATTERN = 5;
|
|
23070
|
+
var MIN_TRANSACTIONS_FOR_PATTERN = 5;
|
|
23071
|
+
var DAY_REGULARITY_THRESHOLD = 0.3;
|
|
23072
|
+
var HOUR_REGULARITY_THRESHOLD = 0.25;
|
|
23073
|
+
var TIMEZONES = {
|
|
23074
|
+
"UTC-12": -12,
|
|
23075
|
+
"UTC-11": -11,
|
|
23076
|
+
"HST": -10,
|
|
23077
|
+
"AKST": -9,
|
|
23078
|
+
"PST": -8,
|
|
23079
|
+
"MST": -7,
|
|
23080
|
+
"CST": -6,
|
|
23081
|
+
"EST": -5,
|
|
23082
|
+
"AST": -4,
|
|
23083
|
+
"BRT": -3,
|
|
23084
|
+
"UTC-2": -2,
|
|
23085
|
+
"UTC-1": -1,
|
|
23086
|
+
"UTC": 0,
|
|
23087
|
+
"CET": 1,
|
|
23088
|
+
"EET": 2,
|
|
23089
|
+
"MSK": 3,
|
|
23090
|
+
"GST": 4,
|
|
23091
|
+
"PKT": 5,
|
|
23092
|
+
"BST": 6,
|
|
23093
|
+
"ICT": 7,
|
|
23094
|
+
"CST_ASIA": 8,
|
|
23095
|
+
"JST": 9,
|
|
23096
|
+
"AEST": 10,
|
|
23097
|
+
"AEDT": 11,
|
|
23098
|
+
"NZST": 12
|
|
23099
|
+
};
|
|
23100
|
+
function analyzeTemporalPatterns(transactions) {
|
|
23101
|
+
const patterns = [];
|
|
23102
|
+
if (transactions.length < MIN_TRANSACTIONS_FOR_PATTERN) {
|
|
23103
|
+
return {
|
|
23104
|
+
patterns: [],
|
|
23105
|
+
scoreDeduction: 0
|
|
23106
|
+
};
|
|
23107
|
+
}
|
|
23108
|
+
const txTimes = transactions.filter((tx) => tx.success && tx.timestamp > 0).map((tx) => new Date(tx.timestamp * 1e3));
|
|
23109
|
+
if (txTimes.length < MIN_TRANSACTIONS_FOR_PATTERN) {
|
|
23110
|
+
return {
|
|
23111
|
+
patterns: [],
|
|
23112
|
+
scoreDeduction: 0
|
|
23113
|
+
};
|
|
23114
|
+
}
|
|
23115
|
+
const dayOfWeekPattern = analyzeDayOfWeekPattern(txTimes);
|
|
23116
|
+
if (dayOfWeekPattern) {
|
|
23117
|
+
patterns.push(dayOfWeekPattern);
|
|
23118
|
+
}
|
|
23119
|
+
const hourPattern = analyzeHourPattern(txTimes);
|
|
23120
|
+
if (hourPattern) {
|
|
23121
|
+
patterns.push(hourPattern);
|
|
23122
|
+
}
|
|
23123
|
+
const inferredTimezone = inferTimezone(txTimes);
|
|
23124
|
+
const burstPattern = detectActivityBursts(transactions);
|
|
23125
|
+
if (burstPattern) {
|
|
23126
|
+
patterns.push(burstPattern);
|
|
23127
|
+
}
|
|
23128
|
+
const rawDeduction = patterns.length * DEDUCTION_PER_PATTERN;
|
|
23129
|
+
const scoreDeduction = Math.min(rawDeduction, MAX_DEDUCTION4);
|
|
23130
|
+
return {
|
|
23131
|
+
patterns,
|
|
23132
|
+
inferredTimezone,
|
|
23133
|
+
scoreDeduction
|
|
23134
|
+
};
|
|
23135
|
+
}
|
|
23136
|
+
function analyzeDayOfWeekPattern(times) {
|
|
23137
|
+
const dayCount = new Array(7).fill(0);
|
|
23138
|
+
for (const time of times) {
|
|
23139
|
+
dayCount[time.getUTCDay()]++;
|
|
23140
|
+
}
|
|
23141
|
+
const total = times.length;
|
|
23142
|
+
const dominantDays = [];
|
|
23143
|
+
for (let day = 0; day < 7; day++) {
|
|
23144
|
+
const percentage = dayCount[day] / total;
|
|
23145
|
+
if (percentage >= DAY_REGULARITY_THRESHOLD) {
|
|
23146
|
+
dominantDays.push(day);
|
|
23147
|
+
}
|
|
23148
|
+
}
|
|
23149
|
+
if (dominantDays.length === 0 || dominantDays.length > 3) {
|
|
23150
|
+
return null;
|
|
23151
|
+
}
|
|
23152
|
+
const dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
23153
|
+
const dominantDayNames = dominantDays.map((d) => dayNames[d]).join(", ");
|
|
23154
|
+
return {
|
|
23155
|
+
type: "regular-schedule",
|
|
23156
|
+
description: `Most transactions occur on ${dominantDayNames}`,
|
|
23157
|
+
confidence: Math.max(...dominantDays.map((d) => dayCount[d] / total)),
|
|
23158
|
+
evidence: {
|
|
23159
|
+
dayOfWeek: dominantDays
|
|
23160
|
+
}
|
|
23161
|
+
};
|
|
23162
|
+
}
|
|
23163
|
+
function analyzeHourPattern(times) {
|
|
23164
|
+
const hourCount = new Array(24).fill(0);
|
|
23165
|
+
for (const time of times) {
|
|
23166
|
+
hourCount[time.getUTCHours()]++;
|
|
23167
|
+
}
|
|
23168
|
+
const total = times.length;
|
|
23169
|
+
const activeHours = [];
|
|
23170
|
+
for (let hour = 0; hour < 24; hour++) {
|
|
23171
|
+
const windowCount = hourCount[hour] + hourCount[(hour + 1) % 24] + hourCount[(hour + 2) % 24];
|
|
23172
|
+
const windowPercentage = windowCount / total;
|
|
23173
|
+
if (windowPercentage >= HOUR_REGULARITY_THRESHOLD) {
|
|
23174
|
+
if (!activeHours.includes(hour)) {
|
|
23175
|
+
activeHours.push(hour);
|
|
23176
|
+
}
|
|
23177
|
+
}
|
|
23178
|
+
}
|
|
23179
|
+
if (activeHours.length === 0 || activeHours.length > 8) {
|
|
23180
|
+
return null;
|
|
23181
|
+
}
|
|
23182
|
+
const activeHourRange = Math.max(...activeHours) - Math.min(...activeHours);
|
|
23183
|
+
if (activeHourRange <= 6) {
|
|
23184
|
+
const startHour = Math.min(...activeHours);
|
|
23185
|
+
const endHour = Math.max(...activeHours) + 2;
|
|
23186
|
+
return {
|
|
23187
|
+
type: "timezone-inference",
|
|
23188
|
+
description: `Activity concentrated between ${startHour}:00-${endHour}:00 UTC`,
|
|
23189
|
+
confidence: 0.7,
|
|
23190
|
+
evidence: {
|
|
23191
|
+
hourOfDay: activeHours
|
|
23192
|
+
}
|
|
23193
|
+
};
|
|
23194
|
+
}
|
|
23195
|
+
return null;
|
|
23196
|
+
}
|
|
23197
|
+
function inferTimezone(times) {
|
|
23198
|
+
const hourCount = new Array(24).fill(0);
|
|
23199
|
+
for (const time of times) {
|
|
23200
|
+
hourCount[time.getUTCHours()]++;
|
|
23201
|
+
}
|
|
23202
|
+
let maxActivity = 0;
|
|
23203
|
+
let bestStartHour = 0;
|
|
23204
|
+
for (let start = 0; start < 24; start++) {
|
|
23205
|
+
let windowActivity = 0;
|
|
23206
|
+
for (let i = 0; i < 8; i++) {
|
|
23207
|
+
windowActivity += hourCount[(start + i) % 24];
|
|
23208
|
+
}
|
|
23209
|
+
if (windowActivity > maxActivity) {
|
|
23210
|
+
maxActivity = windowActivity;
|
|
23211
|
+
bestStartHour = start;
|
|
23212
|
+
}
|
|
23213
|
+
}
|
|
23214
|
+
const totalActivity = times.length;
|
|
23215
|
+
if (maxActivity / totalActivity < 0.6) {
|
|
23216
|
+
return void 0;
|
|
23217
|
+
}
|
|
23218
|
+
const assumedLocalNoon = 12;
|
|
23219
|
+
const peakMidpoint = (bestStartHour + 4) % 24;
|
|
23220
|
+
const inferredOffset = (assumedLocalNoon - peakMidpoint + 24) % 24;
|
|
23221
|
+
const normalizedOffset = inferredOffset > 12 ? inferredOffset - 24 : inferredOffset;
|
|
23222
|
+
for (const [name, offset] of Object.entries(TIMEZONES)) {
|
|
23223
|
+
if (Math.abs(offset - normalizedOffset) <= 1) {
|
|
23224
|
+
return name;
|
|
23225
|
+
}
|
|
23226
|
+
}
|
|
23227
|
+
return `UTC${normalizedOffset >= 0 ? "+" : ""}${normalizedOffset}`;
|
|
23228
|
+
}
|
|
23229
|
+
function detectActivityBursts(transactions) {
|
|
23230
|
+
if (transactions.length < 10) {
|
|
23231
|
+
return null;
|
|
23232
|
+
}
|
|
23233
|
+
const sorted = [...transactions].filter((tx) => tx.timestamp > 0).sort((a, b) => a.timestamp - b.timestamp);
|
|
23234
|
+
const gaps = [];
|
|
23235
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
23236
|
+
gaps.push(sorted[i].timestamp - sorted[i - 1].timestamp);
|
|
23237
|
+
}
|
|
23238
|
+
const avgGap = gaps.reduce((a, b) => a + b, 0) / gaps.length;
|
|
23239
|
+
const burstThreshold = avgGap * 0.1;
|
|
23240
|
+
let burstCount = 0;
|
|
23241
|
+
for (const gap of gaps) {
|
|
23242
|
+
if (gap < burstThreshold && gap < 3600) {
|
|
23243
|
+
burstCount++;
|
|
23244
|
+
}
|
|
23245
|
+
}
|
|
23246
|
+
const burstPercentage = burstCount / gaps.length;
|
|
23247
|
+
if (burstPercentage > 0.2) {
|
|
23248
|
+
return {
|
|
23249
|
+
type: "activity-burst",
|
|
23250
|
+
description: `${Math.round(burstPercentage * 100)}% of transactions occur in rapid succession`,
|
|
23251
|
+
confidence: burstPercentage,
|
|
23252
|
+
evidence: {
|
|
23253
|
+
frequency: `${burstCount} bursts detected`
|
|
23254
|
+
}
|
|
23255
|
+
};
|
|
23256
|
+
}
|
|
23257
|
+
return null;
|
|
23258
|
+
}
|
|
23259
|
+
|
|
23260
|
+
// src/surveillance/scoring.ts
|
|
23261
|
+
var MAX_POINTS = {
|
|
23262
|
+
addressReuse: 25,
|
|
23263
|
+
clusterExposure: 25,
|
|
23264
|
+
exchangeExposure: 20,
|
|
23265
|
+
temporalPatterns: 15,
|
|
23266
|
+
socialLinks: 15
|
|
23267
|
+
};
|
|
23268
|
+
var TOTAL_MAX_SCORE = Object.values(MAX_POINTS).reduce((a, b) => a + b, 0);
|
|
23269
|
+
var RISK_THRESHOLDS = {
|
|
23270
|
+
critical: 30,
|
|
23271
|
+
high: 50,
|
|
23272
|
+
medium: 70,
|
|
23273
|
+
low: 100
|
|
23274
|
+
};
|
|
23275
|
+
function calculatePrivacyScore(addressReuse, cluster, exchangeExposure, temporalPatterns, socialLinks, walletAddress) {
|
|
23276
|
+
const breakdown = {
|
|
23277
|
+
addressReuse: MAX_POINTS.addressReuse - addressReuse.scoreDeduction,
|
|
23278
|
+
clusterExposure: MAX_POINTS.clusterExposure - cluster.scoreDeduction,
|
|
23279
|
+
exchangeExposure: MAX_POINTS.exchangeExposure - exchangeExposure.scoreDeduction,
|
|
23280
|
+
temporalPatterns: MAX_POINTS.temporalPatterns - temporalPatterns.scoreDeduction,
|
|
23281
|
+
socialLinks: MAX_POINTS.socialLinks - socialLinks.scoreDeduction
|
|
23282
|
+
};
|
|
23283
|
+
const totalScore = breakdown.addressReuse + breakdown.clusterExposure + breakdown.exchangeExposure + breakdown.temporalPatterns + breakdown.socialLinks;
|
|
23284
|
+
const overall = Math.round(totalScore / TOTAL_MAX_SCORE * 100);
|
|
23285
|
+
let risk = "low";
|
|
23286
|
+
if (overall < RISK_THRESHOLDS.critical) {
|
|
23287
|
+
risk = "critical";
|
|
23288
|
+
} else if (overall < RISK_THRESHOLDS.high) {
|
|
23289
|
+
risk = "high";
|
|
23290
|
+
} else if (overall < RISK_THRESHOLDS.medium) {
|
|
23291
|
+
risk = "medium";
|
|
23292
|
+
}
|
|
23293
|
+
const recommendations = generateRecommendations(
|
|
23294
|
+
addressReuse,
|
|
23295
|
+
cluster,
|
|
23296
|
+
exchangeExposure,
|
|
23297
|
+
temporalPatterns,
|
|
23298
|
+
socialLinks
|
|
23299
|
+
);
|
|
23300
|
+
return {
|
|
23301
|
+
overall,
|
|
23302
|
+
breakdown,
|
|
23303
|
+
risk,
|
|
23304
|
+
recommendations,
|
|
23305
|
+
analyzedAt: Date.now(),
|
|
23306
|
+
walletAddress
|
|
23307
|
+
};
|
|
23308
|
+
}
|
|
23309
|
+
function generateRecommendations(addressReuse, cluster, exchangeExposure, temporalPatterns, socialLinks) {
|
|
23310
|
+
const recommendations = [];
|
|
23311
|
+
if (addressReuse.scoreDeduction > 0) {
|
|
23312
|
+
const severity = getSeverity(addressReuse.scoreDeduction, MAX_POINTS.addressReuse);
|
|
23313
|
+
recommendations.push({
|
|
23314
|
+
id: "address-reuse-001",
|
|
23315
|
+
severity,
|
|
23316
|
+
category: "addressReuse",
|
|
23317
|
+
title: `Address reused ${addressReuse.totalReuseCount} times`,
|
|
23318
|
+
description: "Reusing the same address for multiple transactions creates linkability between your transactions, allowing observers to track your activity.",
|
|
23319
|
+
action: "Use SIP stealth addresses for each transaction. Each payment uses a unique one-time address that cannot be linked to your main address.",
|
|
23320
|
+
potentialGain: addressReuse.scoreDeduction
|
|
23321
|
+
});
|
|
23322
|
+
}
|
|
23323
|
+
if (cluster.scoreDeduction > 0) {
|
|
23324
|
+
const severity = getSeverity(cluster.scoreDeduction, MAX_POINTS.clusterExposure);
|
|
23325
|
+
recommendations.push({
|
|
23326
|
+
id: "cluster-001",
|
|
23327
|
+
severity,
|
|
23328
|
+
category: "clusterExposure",
|
|
23329
|
+
title: `${cluster.linkedAddressCount} addresses linked to your wallet`,
|
|
23330
|
+
description: "Transaction analysis has linked multiple addresses to your wallet through common input ownership patterns. This expands your privacy exposure.",
|
|
23331
|
+
action: "Use SIP for all transactions to prevent cluster analysis. Stealth addresses break the link between your spending and receiving addresses.",
|
|
23332
|
+
potentialGain: cluster.scoreDeduction
|
|
23333
|
+
});
|
|
23334
|
+
}
|
|
23335
|
+
if (exchangeExposure.scoreDeduction > 0) {
|
|
23336
|
+
const cexes = exchangeExposure.exchanges.filter((e) => e.kycRequired);
|
|
23337
|
+
const severity = getSeverity(exchangeExposure.scoreDeduction, MAX_POINTS.exchangeExposure);
|
|
23338
|
+
if (cexes.length > 0) {
|
|
23339
|
+
recommendations.push({
|
|
23340
|
+
id: "exchange-cex-001",
|
|
23341
|
+
severity,
|
|
23342
|
+
category: "exchangeExposure",
|
|
23343
|
+
title: `Interacted with ${cexes.length} KYC exchange(s)`,
|
|
23344
|
+
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.`,
|
|
23345
|
+
action: "Use SIP viewing keys for selective disclosure. You can prove compliance to exchanges without exposing your full transaction history.",
|
|
23346
|
+
potentialGain: Math.min(cexes.length * 8, MAX_POINTS.exchangeExposure)
|
|
23347
|
+
});
|
|
23348
|
+
}
|
|
23349
|
+
const dexes = exchangeExposure.exchanges.filter((e) => !e.kycRequired);
|
|
23350
|
+
if (dexes.length > 0) {
|
|
23351
|
+
recommendations.push({
|
|
23352
|
+
id: "exchange-dex-001",
|
|
23353
|
+
severity: "low",
|
|
23354
|
+
category: "exchangeExposure",
|
|
23355
|
+
title: `Used ${dexes.length} DEX(es) without privacy`,
|
|
23356
|
+
description: "DEX swaps are public and can be traced. While no KYC is required, your swap patterns can reveal trading strategies.",
|
|
23357
|
+
action: "Use SIP for private swaps. Amounts and swap details are hidden while still using your preferred DEX.",
|
|
23358
|
+
potentialGain: Math.min(dexes.length * 2, 6)
|
|
23359
|
+
});
|
|
23360
|
+
}
|
|
23361
|
+
}
|
|
23362
|
+
if (temporalPatterns.scoreDeduction > 0) {
|
|
23363
|
+
const severity = getSeverity(temporalPatterns.scoreDeduction, MAX_POINTS.temporalPatterns);
|
|
23364
|
+
for (const pattern of temporalPatterns.patterns) {
|
|
23365
|
+
if (pattern.type === "regular-schedule") {
|
|
23366
|
+
recommendations.push({
|
|
23367
|
+
id: "temporal-schedule-001",
|
|
23368
|
+
severity,
|
|
23369
|
+
category: "temporalPatterns",
|
|
23370
|
+
title: "Regular transaction schedule detected",
|
|
23371
|
+
description: `${pattern.description}. Predictable patterns make your activity easier to track and attribute.`,
|
|
23372
|
+
action: "Vary your transaction timing. Consider using scheduled private transactions through SIP to obscure timing patterns.",
|
|
23373
|
+
potentialGain: 5
|
|
23374
|
+
});
|
|
23375
|
+
}
|
|
23376
|
+
if (pattern.type === "timezone-inference") {
|
|
23377
|
+
recommendations.push({
|
|
23378
|
+
id: "temporal-timezone-001",
|
|
23379
|
+
severity: "medium",
|
|
23380
|
+
category: "temporalPatterns",
|
|
23381
|
+
title: "Timezone can be inferred from activity",
|
|
23382
|
+
description: `${pattern.description}. This narrows down your geographic location based on when you transact.`,
|
|
23383
|
+
action: "Use time-delayed transactions or vary your active hours. SIP can queue transactions for random future execution.",
|
|
23384
|
+
potentialGain: 5
|
|
23385
|
+
});
|
|
23386
|
+
}
|
|
23387
|
+
}
|
|
23388
|
+
}
|
|
23389
|
+
if (socialLinks.scoreDeduction > 0) {
|
|
23390
|
+
const severity = getSeverity(socialLinks.scoreDeduction, MAX_POINTS.socialLinks);
|
|
23391
|
+
if (socialLinks.isDoxxed) {
|
|
23392
|
+
recommendations.push({
|
|
23393
|
+
id: "social-doxxed-001",
|
|
23394
|
+
severity: "critical",
|
|
23395
|
+
category: "socialLinks",
|
|
23396
|
+
title: "Wallet publicly linked to your identity",
|
|
23397
|
+
description: "Your wallet address is publicly associated with your real identity through ENS/SNS names or social profiles. All transactions are attributable to you.",
|
|
23398
|
+
action: "Use a fresh wallet with SIP for private transactions. Your viewing keys let you prove ownership when needed without constant exposure.",
|
|
23399
|
+
potentialGain: 15
|
|
23400
|
+
});
|
|
23401
|
+
} else if (socialLinks.partialExposure) {
|
|
23402
|
+
recommendations.push({
|
|
23403
|
+
id: "social-partial-001",
|
|
23404
|
+
severity,
|
|
23405
|
+
category: "socialLinks",
|
|
23406
|
+
title: "Partial identity exposure detected",
|
|
23407
|
+
description: "Some identifying information is linked to your wallet, such as ENS names or labeled addresses on block explorers.",
|
|
23408
|
+
action: "Consider using a separate wallet for private activities. SIP stealth addresses prevent linking to your main identity.",
|
|
23409
|
+
potentialGain: socialLinks.scoreDeduction
|
|
23410
|
+
});
|
|
23411
|
+
}
|
|
23412
|
+
}
|
|
23413
|
+
recommendations.sort((a, b) => b.potentialGain - a.potentialGain);
|
|
23414
|
+
return recommendations;
|
|
23415
|
+
}
|
|
23416
|
+
function getSeverity(deduction, maxPoints) {
|
|
23417
|
+
const percentage = deduction / maxPoints;
|
|
23418
|
+
if (percentage >= 0.8) return "critical";
|
|
23419
|
+
if (percentage >= 0.5) return "high";
|
|
23420
|
+
if (percentage >= 0.25) return "medium";
|
|
23421
|
+
return "low";
|
|
23422
|
+
}
|
|
23423
|
+
function calculateSIPComparison(currentScore) {
|
|
23424
|
+
const improvements = [];
|
|
23425
|
+
const addressReuseImprovement = MAX_POINTS.addressReuse - currentScore.breakdown.addressReuse;
|
|
23426
|
+
if (addressReuseImprovement > 0) {
|
|
23427
|
+
improvements.push({
|
|
23428
|
+
category: "addressReuse",
|
|
23429
|
+
currentScore: currentScore.breakdown.addressReuse,
|
|
23430
|
+
projectedScore: MAX_POINTS.addressReuse,
|
|
23431
|
+
reason: "Stealth addresses prevent any address reuse"
|
|
23432
|
+
});
|
|
23433
|
+
}
|
|
23434
|
+
const clusterImprovement = MAX_POINTS.clusterExposure - currentScore.breakdown.clusterExposure;
|
|
23435
|
+
if (clusterImprovement > 0) {
|
|
23436
|
+
improvements.push({
|
|
23437
|
+
category: "clusterExposure",
|
|
23438
|
+
currentScore: currentScore.breakdown.clusterExposure,
|
|
23439
|
+
projectedScore: MAX_POINTS.clusterExposure,
|
|
23440
|
+
reason: "Stealth addresses cannot be linked via common input analysis"
|
|
23441
|
+
});
|
|
23442
|
+
}
|
|
23443
|
+
const exchangeImprovement = Math.min(
|
|
23444
|
+
(MAX_POINTS.exchangeExposure - currentScore.breakdown.exchangeExposure) * 0.5,
|
|
23445
|
+
10
|
|
23446
|
+
);
|
|
23447
|
+
if (exchangeImprovement > 0) {
|
|
23448
|
+
improvements.push({
|
|
23449
|
+
category: "exchangeExposure",
|
|
23450
|
+
currentScore: currentScore.breakdown.exchangeExposure,
|
|
23451
|
+
projectedScore: currentScore.breakdown.exchangeExposure + Math.round(exchangeImprovement),
|
|
23452
|
+
reason: "Viewing keys allow selective disclosure without exposing full history"
|
|
23453
|
+
});
|
|
23454
|
+
}
|
|
23455
|
+
const temporalImprovement = Math.min(
|
|
23456
|
+
(MAX_POINTS.temporalPatterns - currentScore.breakdown.temporalPatterns) * 0.3,
|
|
23457
|
+
5
|
|
23458
|
+
);
|
|
23459
|
+
if (temporalImprovement > 0) {
|
|
23460
|
+
improvements.push({
|
|
23461
|
+
category: "temporalPatterns",
|
|
23462
|
+
currentScore: currentScore.breakdown.temporalPatterns,
|
|
23463
|
+
projectedScore: currentScore.breakdown.temporalPatterns + Math.round(temporalImprovement),
|
|
23464
|
+
reason: "Private transactions reduce pattern correlation"
|
|
23465
|
+
});
|
|
23466
|
+
}
|
|
23467
|
+
const totalImprovement = improvements.reduce(
|
|
23468
|
+
(sum, imp) => sum + (imp.projectedScore - imp.currentScore),
|
|
23469
|
+
0
|
|
23470
|
+
);
|
|
23471
|
+
const projectedTotal = currentScore.overall / 100 * TOTAL_MAX_SCORE + totalImprovement;
|
|
23472
|
+
const projectedScore = Math.min(Math.round(projectedTotal / TOTAL_MAX_SCORE * 100), 100);
|
|
23473
|
+
return {
|
|
23474
|
+
currentScore: currentScore.overall,
|
|
23475
|
+
projectedScore,
|
|
23476
|
+
improvement: projectedScore - currentScore.overall,
|
|
23477
|
+
improvements
|
|
23478
|
+
};
|
|
23479
|
+
}
|
|
23480
|
+
|
|
23481
|
+
// src/surveillance/analyzer.ts
|
|
23482
|
+
var SurveillanceAnalyzer = class _SurveillanceAnalyzer {
|
|
23483
|
+
config;
|
|
23484
|
+
heliusUrl;
|
|
23485
|
+
constructor(config) {
|
|
23486
|
+
if (!config.heliusApiKey) {
|
|
23487
|
+
throw new Error(
|
|
23488
|
+
"Helius API key is required. Get one at https://dev.helius.xyz"
|
|
23489
|
+
);
|
|
23490
|
+
}
|
|
23491
|
+
this.config = {
|
|
23492
|
+
heliusApiKey: config.heliusApiKey,
|
|
23493
|
+
cluster: config.cluster ?? "mainnet-beta",
|
|
23494
|
+
maxTransactions: config.maxTransactions ?? 1e3,
|
|
23495
|
+
includeSocialLinks: config.includeSocialLinks ?? false,
|
|
23496
|
+
customExchangeAddresses: config.customExchangeAddresses ?? []
|
|
23497
|
+
};
|
|
23498
|
+
this.heliusUrl = this.config.cluster === "devnet" ? `https://api-devnet.helius.xyz/v0` : `https://api.helius.xyz/v0`;
|
|
23499
|
+
}
|
|
23500
|
+
/**
|
|
23501
|
+
* Perform full privacy analysis on a wallet
|
|
23502
|
+
*
|
|
23503
|
+
* @param walletAddress - Solana wallet address to analyze
|
|
23504
|
+
* @returns Complete analysis result with all details
|
|
23505
|
+
*/
|
|
23506
|
+
async analyze(walletAddress) {
|
|
23507
|
+
const startTime = Date.now();
|
|
23508
|
+
const transactions = await this.fetchTransactionHistory(walletAddress);
|
|
23509
|
+
const addressReuse = analyzeAddressReuse(transactions, walletAddress);
|
|
23510
|
+
const cluster = detectClusters(transactions, walletAddress);
|
|
23511
|
+
const exchangeExposure = detectExchangeExposure(
|
|
23512
|
+
transactions,
|
|
23513
|
+
walletAddress,
|
|
23514
|
+
this.config.customExchangeAddresses
|
|
23515
|
+
);
|
|
23516
|
+
const temporalPatterns = analyzeTemporalPatterns(transactions);
|
|
23517
|
+
const socialLinks = await this.analyzeSocialLinks(walletAddress);
|
|
23518
|
+
const privacyScore = calculatePrivacyScore(
|
|
23519
|
+
addressReuse,
|
|
23520
|
+
cluster,
|
|
23521
|
+
exchangeExposure,
|
|
23522
|
+
temporalPatterns,
|
|
23523
|
+
socialLinks,
|
|
23524
|
+
walletAddress
|
|
23525
|
+
);
|
|
23526
|
+
const sipComparison = calculateSIPComparison(privacyScore);
|
|
23527
|
+
const analysisDurationMs = Date.now() - startTime;
|
|
23528
|
+
return {
|
|
23529
|
+
privacyScore,
|
|
23530
|
+
addressReuse,
|
|
23531
|
+
cluster,
|
|
23532
|
+
exchangeExposure,
|
|
23533
|
+
temporalPatterns,
|
|
23534
|
+
socialLinks,
|
|
23535
|
+
sipComparison,
|
|
23536
|
+
transactionCount: transactions.length,
|
|
23537
|
+
analysisDurationMs
|
|
23538
|
+
};
|
|
23539
|
+
}
|
|
23540
|
+
/**
|
|
23541
|
+
* Fetch transaction history using Helius Enhanced Transactions API
|
|
23542
|
+
*/
|
|
23543
|
+
async fetchTransactionHistory(walletAddress) {
|
|
23544
|
+
const transactions = [];
|
|
23545
|
+
let beforeSignature;
|
|
23546
|
+
let hasMore = true;
|
|
23547
|
+
while (hasMore && transactions.length < this.config.maxTransactions) {
|
|
23548
|
+
const url = new URL(`${this.heliusUrl}/addresses/${walletAddress}/transactions`);
|
|
23549
|
+
url.searchParams.set("api-key", this.config.heliusApiKey);
|
|
23550
|
+
url.searchParams.set("limit", "100");
|
|
23551
|
+
if (beforeSignature) {
|
|
23552
|
+
url.searchParams.set("before", beforeSignature);
|
|
23553
|
+
}
|
|
23554
|
+
const controller = new AbortController();
|
|
23555
|
+
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
23556
|
+
let response;
|
|
23557
|
+
try {
|
|
23558
|
+
response = await fetch(url.toString(), {
|
|
23559
|
+
signal: controller.signal
|
|
23560
|
+
});
|
|
23561
|
+
} catch (error) {
|
|
23562
|
+
clearTimeout(timeoutId);
|
|
23563
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
23564
|
+
throw new Error("Helius API request timed out after 30 seconds");
|
|
23565
|
+
}
|
|
23566
|
+
throw error;
|
|
23567
|
+
}
|
|
23568
|
+
clearTimeout(timeoutId);
|
|
23569
|
+
if (!response.ok) {
|
|
23570
|
+
throw new Error(
|
|
23571
|
+
`Helius API error: ${response.status} ${response.statusText}`
|
|
23572
|
+
);
|
|
23573
|
+
}
|
|
23574
|
+
const data = await response.json();
|
|
23575
|
+
if (data.length === 0) {
|
|
23576
|
+
hasMore = false;
|
|
23577
|
+
break;
|
|
23578
|
+
}
|
|
23579
|
+
for (const tx of data) {
|
|
23580
|
+
const analyzable = this.parseTransaction(tx, walletAddress);
|
|
23581
|
+
if (analyzable) {
|
|
23582
|
+
transactions.push(analyzable);
|
|
23583
|
+
}
|
|
23584
|
+
}
|
|
23585
|
+
beforeSignature = data[data.length - 1]?.signature;
|
|
23586
|
+
hasMore = data.length === 100;
|
|
23587
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
23588
|
+
}
|
|
23589
|
+
return transactions;
|
|
23590
|
+
}
|
|
23591
|
+
/**
|
|
23592
|
+
* Parse Helius transaction into analyzable format
|
|
23593
|
+
*/
|
|
23594
|
+
parseTransaction(tx, walletAddress) {
|
|
23595
|
+
const involvedAddresses = /* @__PURE__ */ new Set();
|
|
23596
|
+
if (tx.feePayer) {
|
|
23597
|
+
involvedAddresses.add(tx.feePayer);
|
|
23598
|
+
}
|
|
23599
|
+
let sender = null;
|
|
23600
|
+
let recipient = null;
|
|
23601
|
+
let amount = BigInt(0);
|
|
23602
|
+
if (tx.nativeTransfers && tx.nativeTransfers.length > 0) {
|
|
23603
|
+
for (const transfer of tx.nativeTransfers) {
|
|
23604
|
+
involvedAddresses.add(transfer.fromUserAccount);
|
|
23605
|
+
involvedAddresses.add(transfer.toUserAccount);
|
|
23606
|
+
if (transfer.fromUserAccount === walletAddress) {
|
|
23607
|
+
sender = walletAddress;
|
|
23608
|
+
recipient = transfer.toUserAccount;
|
|
23609
|
+
amount = BigInt(transfer.amount);
|
|
23610
|
+
} else if (transfer.toUserAccount === walletAddress) {
|
|
23611
|
+
sender = transfer.fromUserAccount;
|
|
23612
|
+
recipient = walletAddress;
|
|
23613
|
+
amount = BigInt(transfer.amount);
|
|
23614
|
+
}
|
|
23615
|
+
}
|
|
23616
|
+
}
|
|
23617
|
+
let mint = null;
|
|
23618
|
+
if (tx.tokenTransfers && tx.tokenTransfers.length > 0) {
|
|
23619
|
+
for (const transfer of tx.tokenTransfers) {
|
|
23620
|
+
if (transfer.fromUserAccount) {
|
|
23621
|
+
involvedAddresses.add(transfer.fromUserAccount);
|
|
23622
|
+
}
|
|
23623
|
+
if (transfer.toUserAccount) {
|
|
23624
|
+
involvedAddresses.add(transfer.toUserAccount);
|
|
23625
|
+
}
|
|
23626
|
+
if (transfer.fromUserAccount === walletAddress) {
|
|
23627
|
+
sender = walletAddress;
|
|
23628
|
+
recipient = transfer.toUserAccount;
|
|
23629
|
+
amount = BigInt(Math.floor(transfer.tokenAmount));
|
|
23630
|
+
mint = transfer.mint;
|
|
23631
|
+
} else if (transfer.toUserAccount === walletAddress) {
|
|
23632
|
+
sender = transfer.fromUserAccount;
|
|
23633
|
+
recipient = walletAddress;
|
|
23634
|
+
amount = BigInt(Math.floor(transfer.tokenAmount));
|
|
23635
|
+
mint = transfer.mint;
|
|
23636
|
+
}
|
|
23637
|
+
}
|
|
23638
|
+
}
|
|
23639
|
+
if (tx.accountData) {
|
|
23640
|
+
for (const account of tx.accountData) {
|
|
23641
|
+
involvedAddresses.add(account.account);
|
|
23642
|
+
}
|
|
23643
|
+
}
|
|
23644
|
+
let type = "other";
|
|
23645
|
+
if (tx.type === "SWAP" || tx.events?.swap) {
|
|
23646
|
+
type = "swap";
|
|
23647
|
+
} else if (tx.type === "TRANSFER" || tx.nativeTransfers?.length || tx.tokenTransfers?.length) {
|
|
23648
|
+
type = "transfer";
|
|
23649
|
+
} else if (tx.type?.includes("STAKE")) {
|
|
23650
|
+
type = "stake";
|
|
23651
|
+
}
|
|
23652
|
+
return {
|
|
23653
|
+
signature: tx.signature,
|
|
23654
|
+
slot: tx.slot,
|
|
23655
|
+
timestamp: tx.timestamp,
|
|
23656
|
+
sender,
|
|
23657
|
+
recipient,
|
|
23658
|
+
amount,
|
|
23659
|
+
mint,
|
|
23660
|
+
fee: BigInt(tx.fee || 0),
|
|
23661
|
+
involvedAddresses: Array.from(involvedAddresses),
|
|
23662
|
+
type,
|
|
23663
|
+
success: true
|
|
23664
|
+
// Helius only returns successful transactions
|
|
23665
|
+
};
|
|
23666
|
+
}
|
|
23667
|
+
/**
|
|
23668
|
+
* Analyze social links (placeholder for external API integration)
|
|
23669
|
+
*
|
|
23670
|
+
* In production, this would query:
|
|
23671
|
+
* - SNS (Solana Name Service)
|
|
23672
|
+
* - Arkham Intelligence
|
|
23673
|
+
* - 0xppl API
|
|
23674
|
+
* - Other identity providers
|
|
23675
|
+
*/
|
|
23676
|
+
async analyzeSocialLinks(walletAddress) {
|
|
23677
|
+
if (!this.config.includeSocialLinks) {
|
|
23678
|
+
return {
|
|
23679
|
+
isDoxxed: false,
|
|
23680
|
+
partialExposure: false,
|
|
23681
|
+
scoreDeduction: 0,
|
|
23682
|
+
links: []
|
|
23683
|
+
};
|
|
23684
|
+
}
|
|
23685
|
+
try {
|
|
23686
|
+
const snsResult = await this.checkSNS(walletAddress);
|
|
23687
|
+
if (snsResult) {
|
|
23688
|
+
return {
|
|
23689
|
+
isDoxxed: false,
|
|
23690
|
+
partialExposure: true,
|
|
23691
|
+
scoreDeduction: 7,
|
|
23692
|
+
links: [snsResult]
|
|
23693
|
+
};
|
|
23694
|
+
}
|
|
23695
|
+
} catch {
|
|
23696
|
+
}
|
|
23697
|
+
return {
|
|
23698
|
+
isDoxxed: false,
|
|
23699
|
+
partialExposure: false,
|
|
23700
|
+
scoreDeduction: 0,
|
|
23701
|
+
links: []
|
|
23702
|
+
};
|
|
23703
|
+
}
|
|
23704
|
+
/**
|
|
23705
|
+
* Check Solana Name Service for domain names
|
|
23706
|
+
*/
|
|
23707
|
+
async checkSNS(walletAddress) {
|
|
23708
|
+
try {
|
|
23709
|
+
const url = `${this.heliusUrl}/addresses/${walletAddress}/names?api-key=${this.config.heliusApiKey}`;
|
|
23710
|
+
const response = await fetch(url);
|
|
23711
|
+
if (!response.ok) {
|
|
23712
|
+
return null;
|
|
23713
|
+
}
|
|
23714
|
+
const data = await response.json();
|
|
23715
|
+
if (Array.isArray(data) && data.length > 0) {
|
|
23716
|
+
return {
|
|
23717
|
+
platform: "sns",
|
|
23718
|
+
identifier: data[0].name || data[0],
|
|
23719
|
+
confidence: 1
|
|
23720
|
+
};
|
|
23721
|
+
}
|
|
23722
|
+
} catch {
|
|
23723
|
+
}
|
|
23724
|
+
return null;
|
|
23725
|
+
}
|
|
23726
|
+
/**
|
|
23727
|
+
* Get quick privacy score without full analysis
|
|
23728
|
+
*
|
|
23729
|
+
* Performs a lighter analysis suitable for real-time display.
|
|
23730
|
+
* Uses only the most recent transactions (100 max).
|
|
23731
|
+
*/
|
|
23732
|
+
async quickScore(walletAddress) {
|
|
23733
|
+
const quickAnalyzer = new _SurveillanceAnalyzer({
|
|
23734
|
+
heliusApiKey: this.config.heliusApiKey,
|
|
23735
|
+
cluster: this.config.cluster,
|
|
23736
|
+
maxTransactions: 100,
|
|
23737
|
+
includeSocialLinks: false,
|
|
23738
|
+
// Skip social links for speed
|
|
23739
|
+
customExchangeAddresses: this.config.customExchangeAddresses
|
|
23740
|
+
});
|
|
23741
|
+
const result = await quickAnalyzer.analyze(walletAddress);
|
|
23742
|
+
const topRecommendation = result.privacyScore.recommendations[0];
|
|
23743
|
+
return {
|
|
23744
|
+
score: result.privacyScore.overall,
|
|
23745
|
+
risk: result.privacyScore.risk,
|
|
23746
|
+
topIssue: topRecommendation?.title ?? null
|
|
23747
|
+
};
|
|
23748
|
+
}
|
|
23749
|
+
};
|
|
23750
|
+
function createSurveillanceAnalyzer(config) {
|
|
23751
|
+
return new SurveillanceAnalyzer(config);
|
|
23752
|
+
}
|
|
23753
|
+
|
|
21192
23754
|
// src/proofs/browser.ts
|
|
21193
23755
|
init_errors();
|
|
21194
23756
|
var import_noir_js = require("@noir-lang/noir_js");
|
|
@@ -22422,7 +24984,7 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
22422
24984
|
message: "Proof generated successfully"
|
|
22423
24985
|
});
|
|
22424
24986
|
const commitmentHashBytes = returnValue;
|
|
22425
|
-
const commitmentHashHex =
|
|
24987
|
+
const commitmentHashHex = bytesToHex11(new Uint8Array(commitmentHashBytes));
|
|
22426
24988
|
const publicInputs = [
|
|
22427
24989
|
`0x${params.minimumRequired.toString(16).padStart(64, "0")}`,
|
|
22428
24990
|
`0x${this.assetIdToField(params.assetId)}`,
|
|
@@ -22430,7 +24992,7 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
22430
24992
|
];
|
|
22431
24993
|
const proof = {
|
|
22432
24994
|
type: "funding",
|
|
22433
|
-
proof: `0x${
|
|
24995
|
+
proof: `0x${bytesToHex11(proofData.proof)}`,
|
|
22434
24996
|
publicInputs
|
|
22435
24997
|
};
|
|
22436
24998
|
return { proof, publicInputs };
|
|
@@ -22545,7 +25107,7 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
22545
25107
|
];
|
|
22546
25108
|
const proof = {
|
|
22547
25109
|
type: "validity",
|
|
22548
|
-
proof: `0x${
|
|
25110
|
+
proof: `0x${bytesToHex11(proofData.proof)}`,
|
|
22549
25111
|
publicInputs
|
|
22550
25112
|
};
|
|
22551
25113
|
return { proof, publicInputs };
|
|
@@ -22647,7 +25209,7 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
22647
25209
|
];
|
|
22648
25210
|
const proof = {
|
|
22649
25211
|
type: "fulfillment",
|
|
22650
|
-
proof: `0x${
|
|
25212
|
+
proof: `0x${bytesToHex11(proofData.proof)}`,
|
|
22651
25213
|
publicInputs
|
|
22652
25214
|
};
|
|
22653
25215
|
return { proof, publicInputs };
|
|
@@ -22761,14 +25323,14 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
22761
25323
|
}
|
|
22762
25324
|
async computeCommitmentHash(balance, blindingFactor, assetId) {
|
|
22763
25325
|
const blindingField = this.bytesToField(blindingFactor);
|
|
22764
|
-
const { sha256:
|
|
25326
|
+
const { sha256: sha25623 } = await import("@noble/hashes/sha256");
|
|
22765
25327
|
const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
|
|
22766
25328
|
const preimage = new Uint8Array([
|
|
22767
25329
|
...this.bigintToBytes(balance, 8),
|
|
22768
25330
|
...blindingFactor.slice(0, 32),
|
|
22769
25331
|
...hexToBytes10(this.assetIdToField(assetId))
|
|
22770
25332
|
]);
|
|
22771
|
-
const hash2 =
|
|
25333
|
+
const hash2 = sha25623(preimage);
|
|
22772
25334
|
const commitmentHash = nobleToHex(hash2);
|
|
22773
25335
|
return { commitmentHash, blindingField };
|
|
22774
25336
|
}
|
|
@@ -22872,8 +25434,8 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
22872
25434
|
const addressBytes = hexToBytes10(senderAddressField.padStart(64, "0"));
|
|
22873
25435
|
const blindingBytes = hexToBytes10(senderBlindingField.padStart(64, "0"));
|
|
22874
25436
|
const result = await api.pedersenCommit({ inputs: [addressBytes, blindingBytes], hashIndex: 0 });
|
|
22875
|
-
const commitmentX =
|
|
22876
|
-
const commitmentY =
|
|
25437
|
+
const commitmentX = bytesToHex11(result.point.x).padStart(64, "0");
|
|
25438
|
+
const commitmentY = bytesToHex11(result.point.y).padStart(64, "0");
|
|
22877
25439
|
return { commitmentX, commitmentY };
|
|
22878
25440
|
} finally {
|
|
22879
25441
|
await api.destroy();
|
|
@@ -22893,7 +25455,7 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
22893
25455
|
const intentBytes = hexToBytes10(intentHashField.padStart(64, "0"));
|
|
22894
25456
|
const nonceBytes = hexToBytes10(nonceField.padStart(64, "0"));
|
|
22895
25457
|
const result = await api.pedersenHash({ inputs: [secretBytes, intentBytes, nonceBytes], hashIndex: 0 });
|
|
22896
|
-
const nullifier =
|
|
25458
|
+
const nullifier = bytesToHex11(result.hash).padStart(64, "0");
|
|
22897
25459
|
return nullifier;
|
|
22898
25460
|
} finally {
|
|
22899
25461
|
await api.destroy();
|
|
@@ -22953,25 +25515,25 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
22953
25515
|
return sig;
|
|
22954
25516
|
}
|
|
22955
25517
|
async computeOutputCommitment(outputAmount, outputBlinding) {
|
|
22956
|
-
const { sha256:
|
|
25518
|
+
const { sha256: sha25623 } = await import("@noble/hashes/sha256");
|
|
22957
25519
|
const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
|
|
22958
25520
|
const amountBytes = this.bigintToBytes(outputAmount, 8);
|
|
22959
25521
|
const blindingBytes = outputBlinding.slice(0, 32);
|
|
22960
25522
|
const preimage = new Uint8Array([...amountBytes, ...blindingBytes]);
|
|
22961
|
-
const hash2 =
|
|
25523
|
+
const hash2 = sha25623(preimage);
|
|
22962
25524
|
const commitmentX = nobleToHex(hash2.slice(0, 16)).padStart(64, "0");
|
|
22963
25525
|
const commitmentY = nobleToHex(hash2.slice(16, 32)).padStart(64, "0");
|
|
22964
25526
|
return { commitmentX, commitmentY };
|
|
22965
25527
|
}
|
|
22966
25528
|
async computeSolverId(solverSecretField) {
|
|
22967
|
-
const { sha256:
|
|
25529
|
+
const { sha256: sha25623 } = await import("@noble/hashes/sha256");
|
|
22968
25530
|
const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
|
|
22969
25531
|
const secretBytes = hexToBytes10(solverSecretField.padStart(64, "0"));
|
|
22970
|
-
const hash2 =
|
|
25532
|
+
const hash2 = sha25623(secretBytes);
|
|
22971
25533
|
return this.reduceToField(nobleToHex(hash2));
|
|
22972
25534
|
}
|
|
22973
25535
|
async computeOracleMessageHash(recipient, amount, txHash, blockNumber) {
|
|
22974
|
-
const { sha256:
|
|
25536
|
+
const { sha256: sha25623 } = await import("@noble/hashes/sha256");
|
|
22975
25537
|
const recipientBytes = hexToBytes10(this.hexToField(recipient));
|
|
22976
25538
|
const amountBytes = this.bigintToBytes(amount, 8);
|
|
22977
25539
|
const txHashBytes = hexToBytes10(this.hexToField(txHash));
|
|
@@ -22982,7 +25544,7 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
22982
25544
|
...txHashBytes,
|
|
22983
25545
|
...blockBytes
|
|
22984
25546
|
]);
|
|
22985
|
-
const hash2 =
|
|
25547
|
+
const hash2 = sha25623(preimage);
|
|
22986
25548
|
return Array.from(hash2);
|
|
22987
25549
|
}
|
|
22988
25550
|
getPublicKeyCoordinates(privateKey) {
|
|
@@ -23542,6 +26104,8 @@ var ProofWorker = class _ProofWorker {
|
|
|
23542
26104
|
0 && (module.exports = {
|
|
23543
26105
|
ATTESTATION_VERSION,
|
|
23544
26106
|
AptosStealthService,
|
|
26107
|
+
AttestationGatedDisclosure,
|
|
26108
|
+
AttestationSchema,
|
|
23545
26109
|
AuditorKeyDerivation,
|
|
23546
26110
|
AuditorType,
|
|
23547
26111
|
BaseWalletAdapter,
|
|
@@ -23560,11 +26124,14 @@ var ProofWorker = class _ProofWorker {
|
|
|
23560
26124
|
ErrorCode,
|
|
23561
26125
|
EthereumChainId,
|
|
23562
26126
|
EthereumWalletAdapter,
|
|
26127
|
+
GenericProvider,
|
|
23563
26128
|
HardwareErrorCode,
|
|
23564
26129
|
HardwareWalletError,
|
|
26130
|
+
HeliusProvider,
|
|
23565
26131
|
IntentBuilder,
|
|
23566
26132
|
IntentError,
|
|
23567
26133
|
IntentStatus,
|
|
26134
|
+
KNOWN_EXCHANGES,
|
|
23568
26135
|
LedgerWalletAdapter,
|
|
23569
26136
|
MEMO_PROGRAM_ID,
|
|
23570
26137
|
MockEthereumAdapter,
|
|
@@ -23586,7 +26153,9 @@ var ProofWorker = class _ProofWorker {
|
|
|
23586
26153
|
OneClickSwapType,
|
|
23587
26154
|
PaymentBuilder,
|
|
23588
26155
|
PaymentStatus,
|
|
26156
|
+
PrivacyBackendRegistry,
|
|
23589
26157
|
PrivacyLevel,
|
|
26158
|
+
PrivacySmartRouter,
|
|
23590
26159
|
PrivateNFT,
|
|
23591
26160
|
PrivateVoting,
|
|
23592
26161
|
ProofError,
|
|
@@ -23597,6 +26166,7 @@ var ProofWorker = class _ProofWorker {
|
|
|
23597
26166
|
ReportStatus,
|
|
23598
26167
|
SIP,
|
|
23599
26168
|
SIPError,
|
|
26169
|
+
SIPNativeBackend,
|
|
23600
26170
|
SIP_MEMO_PREFIX,
|
|
23601
26171
|
SIP_VERSION,
|
|
23602
26172
|
SOLANA_EXPLORER_URLS,
|
|
@@ -23613,6 +26183,7 @@ var ProofWorker = class _ProofWorker {
|
|
|
23613
26183
|
SolanaSameChainExecutor,
|
|
23614
26184
|
SolanaWalletAdapter,
|
|
23615
26185
|
SuiStealthService,
|
|
26186
|
+
SurveillanceAnalyzer,
|
|
23616
26187
|
SwapStatus,
|
|
23617
26188
|
ThresholdViewingKey,
|
|
23618
26189
|
Treasury,
|
|
@@ -23629,11 +26200,15 @@ var ProofWorker = class _ProofWorker {
|
|
|
23629
26200
|
addBlindings,
|
|
23630
26201
|
addCommitments,
|
|
23631
26202
|
addOracle,
|
|
26203
|
+
analyzeAddressReuse,
|
|
26204
|
+
analyzeTemporalPatterns,
|
|
23632
26205
|
aptosAddressToAuthKey,
|
|
23633
26206
|
attachProofs,
|
|
23634
26207
|
base58ToHex,
|
|
23635
26208
|
browserBytesToHex,
|
|
23636
26209
|
browserHexToBytes,
|
|
26210
|
+
calculatePrivacyScore,
|
|
26211
|
+
calculateSIPComparison,
|
|
23637
26212
|
checkAptosStealthAddress,
|
|
23638
26213
|
checkEd25519StealthAddress,
|
|
23639
26214
|
checkMobileWASMCompatibility,
|
|
@@ -23649,6 +26224,7 @@ var ProofWorker = class _ProofWorker {
|
|
|
23649
26224
|
createEthereumAdapter,
|
|
23650
26225
|
createKeySpendOnlyOutput,
|
|
23651
26226
|
createLedgerAdapter,
|
|
26227
|
+
createMockAttestation,
|
|
23652
26228
|
createMockEthereumAdapter,
|
|
23653
26229
|
createMockEthereumProvider,
|
|
23654
26230
|
createMockLedgerAdapter,
|
|
@@ -23663,6 +26239,7 @@ var ProofWorker = class _ProofWorker {
|
|
|
23663
26239
|
createPrivateOwnership,
|
|
23664
26240
|
createPrivateVoting,
|
|
23665
26241
|
createProductionSIP,
|
|
26242
|
+
createProvider,
|
|
23666
26243
|
createSIP,
|
|
23667
26244
|
createSameChainExecutor,
|
|
23668
26245
|
createSealedBidAuction,
|
|
@@ -23670,9 +26247,11 @@ var ProofWorker = class _ProofWorker {
|
|
|
23670
26247
|
createShieldedPayment,
|
|
23671
26248
|
createSmartRouter,
|
|
23672
26249
|
createSolanaAdapter,
|
|
26250
|
+
createSurveillanceAnalyzer,
|
|
23673
26251
|
createTaprootOutput,
|
|
23674
26252
|
createTrezorAdapter,
|
|
23675
26253
|
createWalletFactory,
|
|
26254
|
+
createWebhookHandler,
|
|
23676
26255
|
createWorkerBlobURL,
|
|
23677
26256
|
createZcashClient,
|
|
23678
26257
|
createZcashNativeBackend,
|
|
@@ -23682,6 +26261,7 @@ var ProofWorker = class _ProofWorker {
|
|
|
23682
26261
|
decodeTaprootAddress,
|
|
23683
26262
|
decryptMemo,
|
|
23684
26263
|
decryptWithViewing,
|
|
26264
|
+
defaultRegistry,
|
|
23685
26265
|
deriveAptosStealthPrivateKey,
|
|
23686
26266
|
deriveEd25519StealthPrivateKey,
|
|
23687
26267
|
deriveOracleId,
|
|
@@ -23691,7 +26271,9 @@ var ProofWorker = class _ProofWorker {
|
|
|
23691
26271
|
deserializeAttestationMessage,
|
|
23692
26272
|
deserializeIntent,
|
|
23693
26273
|
deserializePayment,
|
|
26274
|
+
detectClusters,
|
|
23694
26275
|
detectEthereumWallets,
|
|
26276
|
+
detectExchangeExposure,
|
|
23695
26277
|
detectMobileBrowser,
|
|
23696
26278
|
detectMobilePlatform,
|
|
23697
26279
|
detectSolanaWallets,
|
|
@@ -23703,6 +26285,7 @@ var ProofWorker = class _ProofWorker {
|
|
|
23703
26285
|
encryptForViewing,
|
|
23704
26286
|
estimatePrivateTransferFee,
|
|
23705
26287
|
featureNotSupportedError,
|
|
26288
|
+
fetchAttestation,
|
|
23706
26289
|
formatStablecoinAmount,
|
|
23707
26290
|
fromHex,
|
|
23708
26291
|
fromStablecoinUnits,
|
|
@@ -23791,6 +26374,7 @@ var ProofWorker = class _ProofWorker {
|
|
|
23791
26374
|
normalizeSuiAddress,
|
|
23792
26375
|
notConnectedError,
|
|
23793
26376
|
parseAnnouncement,
|
|
26377
|
+
processWebhookTransaction,
|
|
23794
26378
|
proveOwnership,
|
|
23795
26379
|
publicKeyToEthAddress,
|
|
23796
26380
|
registerWallet,
|
|
@@ -23834,6 +26418,7 @@ var ProofWorker = class _ProofWorker {
|
|
|
23834
26418
|
validateScalar,
|
|
23835
26419
|
validateViewingKey,
|
|
23836
26420
|
verifyAttestation,
|
|
26421
|
+
verifyAttestationSignature,
|
|
23837
26422
|
verifyCommitment,
|
|
23838
26423
|
verifyOpening,
|
|
23839
26424
|
verifyOracleSignature,
|