@sip-protocol/sdk 0.7.3 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +267 -0
  3. package/dist/{TransportWebUSB-TQ7WZ4LE.mjs → TransportWebUSB-YQMAGJAJ.mjs} +12 -9
  4. package/dist/browser.d.mts +10 -4
  5. package/dist/browser.d.ts +10 -4
  6. package/dist/browser.js +47556 -19603
  7. package/dist/browser.mjs +628 -48
  8. package/dist/chunk-4GRJ5MAW.mjs +152 -0
  9. package/dist/chunk-5D7A3L3W.mjs +717 -0
  10. package/dist/chunk-64AYA5F5.mjs +7834 -0
  11. package/dist/chunk-GMDGB22A.mjs +379 -0
  12. package/dist/chunk-I534WKN7.mjs +328 -0
  13. package/dist/chunk-IBZVA5Y7.mjs +1003 -0
  14. package/dist/chunk-PRRZAWJE.mjs +223 -0
  15. package/dist/{chunk-UJCSKKID.mjs → chunk-XGB3TDIC.mjs} +13 -1
  16. package/dist/{chunk-3M3HNQCW.mjs → chunk-YWGJ77A2.mjs} +28656 -13103
  17. package/dist/{chunk-6WGN57S2.mjs → chunk-Z3K7W5S3.mjs} +48 -0
  18. package/dist/constants-LHAAUC2T.mjs +51 -0
  19. package/dist/dist-2OGQ7FED.mjs +3957 -0
  20. package/dist/dist-IFHPYLDX.mjs +254 -0
  21. package/dist/fulfillment_proof-ANHVPKTB.mjs +21 -0
  22. package/dist/funding_proof-ICFZ5LHY.mjs +21 -0
  23. package/dist/{index-DIBZHOOQ.d.ts → index-DXh2IGkz.d.ts} +21239 -10304
  24. package/dist/{index-8MQz13eJ.d.mts → index-DeE1ZzA4.d.mts} +21239 -10304
  25. package/dist/index.d.mts +9 -3
  26. package/dist/index.d.ts +9 -3
  27. package/dist/index.js +48396 -19623
  28. package/dist/index.mjs +537 -19
  29. package/dist/interface-Bf7w1PLW.d.mts +679 -0
  30. package/dist/interface-Bf7w1PLW.d.ts +679 -0
  31. package/dist/{noir-DKfEzWy9.d.mts → noir-kzbLVTei.d.mts} +31 -21
  32. package/dist/{noir-DKfEzWy9.d.ts → noir-kzbLVTei.d.ts} +31 -21
  33. package/dist/proofs/halo2.d.mts +151 -0
  34. package/dist/proofs/halo2.d.ts +151 -0
  35. package/dist/proofs/halo2.js +350 -0
  36. package/dist/proofs/halo2.mjs +11 -0
  37. package/dist/proofs/kimchi.d.mts +160 -0
  38. package/dist/proofs/kimchi.d.ts +160 -0
  39. package/dist/proofs/kimchi.js +431 -0
  40. package/dist/proofs/kimchi.mjs +13 -0
  41. package/dist/proofs/noir.d.mts +1 -1
  42. package/dist/proofs/noir.d.ts +1 -1
  43. package/dist/proofs/noir.js +74 -18
  44. package/dist/proofs/noir.mjs +84 -24
  45. package/dist/solana-U3MEGU7W.mjs +280 -0
  46. package/dist/validity_proof-3POXLPNY.mjs +21 -0
  47. package/package.json +54 -21
  48. package/src/adapters/index.ts +41 -0
  49. package/src/adapters/jupiter.ts +571 -0
  50. package/src/adapters/near-intents.ts +135 -0
  51. package/src/advisor/advisor.ts +653 -0
  52. package/src/advisor/index.ts +54 -0
  53. package/src/advisor/tools.ts +303 -0
  54. package/src/advisor/types.ts +164 -0
  55. package/src/chains/ethereum/announcement.ts +536 -0
  56. package/src/chains/ethereum/bnb-optimizations.ts +474 -0
  57. package/src/chains/ethereum/commitment.ts +522 -0
  58. package/src/chains/ethereum/constants.ts +462 -0
  59. package/src/chains/ethereum/deployment.ts +596 -0
  60. package/src/chains/ethereum/gas-estimation.ts +538 -0
  61. package/src/chains/ethereum/index.ts +268 -0
  62. package/src/chains/ethereum/optimizations.ts +614 -0
  63. package/src/chains/ethereum/privacy-adapter.ts +855 -0
  64. package/src/chains/ethereum/registry.ts +584 -0
  65. package/src/chains/ethereum/rpc.ts +905 -0
  66. package/src/chains/ethereum/stealth.ts +491 -0
  67. package/src/chains/ethereum/token.ts +790 -0
  68. package/src/chains/ethereum/transfer.ts +637 -0
  69. package/src/chains/ethereum/types.ts +456 -0
  70. package/src/chains/ethereum/viewing-key.ts +455 -0
  71. package/src/chains/near/commitment.ts +608 -0
  72. package/src/chains/near/constants.ts +284 -0
  73. package/src/chains/near/function-call.ts +871 -0
  74. package/src/chains/near/history.ts +654 -0
  75. package/src/chains/near/implicit-account.ts +840 -0
  76. package/src/chains/near/index.ts +393 -0
  77. package/src/chains/near/native-transfer.ts +658 -0
  78. package/src/chains/near/nep141.ts +775 -0
  79. package/src/chains/near/privacy-adapter.ts +889 -0
  80. package/src/chains/near/resolver.ts +971 -0
  81. package/src/chains/near/rpc.ts +1016 -0
  82. package/src/chains/near/stealth.ts +419 -0
  83. package/src/chains/near/types.ts +317 -0
  84. package/src/chains/near/viewing-key.ts +876 -0
  85. package/src/chains/solana/anchor-transfer.ts +386 -0
  86. package/src/chains/solana/commitment.ts +577 -0
  87. package/src/chains/solana/constants.ts +126 -12
  88. package/src/chains/solana/ephemeral-keys.ts +543 -0
  89. package/src/chains/solana/index.ts +252 -1
  90. package/src/chains/solana/key-derivation.ts +418 -0
  91. package/src/chains/solana/kit-compat.ts +334 -0
  92. package/src/chains/solana/optimizations.ts +560 -0
  93. package/src/chains/solana/privacy-adapter.ts +605 -0
  94. package/src/chains/solana/providers/generic.ts +47 -6
  95. package/src/chains/solana/providers/helius-enhanced-types.ts +336 -0
  96. package/src/chains/solana/providers/helius-enhanced.ts +623 -0
  97. package/src/chains/solana/providers/helius.ts +186 -33
  98. package/src/chains/solana/providers/index.ts +31 -0
  99. package/src/chains/solana/providers/interface.ts +61 -18
  100. package/src/chains/solana/providers/quicknode.ts +409 -0
  101. package/src/chains/solana/providers/triton.ts +426 -0
  102. package/src/chains/solana/providers/webhook.ts +338 -67
  103. package/src/chains/solana/rpc-client.ts +1150 -0
  104. package/src/chains/solana/scan.ts +83 -66
  105. package/src/chains/solana/sol-transfer.ts +732 -0
  106. package/src/chains/solana/spl-transfer.ts +886 -0
  107. package/src/chains/solana/stealth-scanner.ts +703 -0
  108. package/src/chains/solana/sunspot-verifier.ts +453 -0
  109. package/src/chains/solana/transaction-builder.ts +755 -0
  110. package/src/chains/solana/transfer.ts +74 -5
  111. package/src/chains/solana/types.ts +57 -6
  112. package/src/chains/solana/utils.ts +110 -0
  113. package/src/chains/solana/viewing-key.ts +807 -0
  114. package/src/compliance/fireblocks.ts +921 -0
  115. package/src/compliance/index.ts +23 -0
  116. package/src/compliance/range-sas.ts +398 -33
  117. package/src/config/endpoints.ts +100 -0
  118. package/src/crypto.ts +11 -8
  119. package/src/errors.ts +82 -0
  120. package/src/evm/erc4337-relayer.ts +830 -0
  121. package/src/evm/index.ts +47 -0
  122. package/src/fees/calculator.ts +396 -0
  123. package/src/fees/index.ts +87 -0
  124. package/src/fees/near-contract.ts +429 -0
  125. package/src/fees/types.ts +268 -0
  126. package/src/index.ts +686 -1
  127. package/src/intent.ts +6 -3
  128. package/src/logger.ts +324 -0
  129. package/src/network/index.ts +80 -0
  130. package/src/network/proxy.ts +691 -0
  131. package/src/optimizations/index.ts +541 -0
  132. package/src/oracle/types.ts +1 -0
  133. package/src/privacy-backends/arcium-types.ts +727 -0
  134. package/src/privacy-backends/arcium.ts +719 -0
  135. package/src/privacy-backends/combined-privacy.ts +866 -0
  136. package/src/privacy-backends/cspl-token.ts +595 -0
  137. package/src/privacy-backends/cspl-types.ts +512 -0
  138. package/src/privacy-backends/cspl.ts +907 -0
  139. package/src/privacy-backends/health.ts +488 -0
  140. package/src/privacy-backends/inco-types.ts +323 -0
  141. package/src/privacy-backends/inco.ts +616 -0
  142. package/src/privacy-backends/index.ts +254 -4
  143. package/src/privacy-backends/interface.ts +649 -6
  144. package/src/privacy-backends/lru-cache.ts +343 -0
  145. package/src/privacy-backends/magicblock.ts +458 -0
  146. package/src/privacy-backends/mock.ts +258 -0
  147. package/src/privacy-backends/privacycash.ts +13 -17
  148. package/src/privacy-backends/private-swap.ts +570 -0
  149. package/src/privacy-backends/rate-limiter.ts +683 -0
  150. package/src/privacy-backends/registry.ts +414 -2
  151. package/src/privacy-backends/router.ts +283 -3
  152. package/src/privacy-backends/shadowwire.ts +449 -0
  153. package/src/privacy-backends/sip-native.ts +3 -0
  154. package/src/privacy-logger.ts +191 -0
  155. package/src/production-safety.ts +373 -0
  156. package/src/proofs/aggregator.ts +1029 -0
  157. package/src/proofs/browser-composer.ts +1150 -0
  158. package/src/proofs/browser.ts +113 -25
  159. package/src/proofs/cache/index.ts +127 -0
  160. package/src/proofs/cache/interface.ts +545 -0
  161. package/src/proofs/cache/key-generator.ts +188 -0
  162. package/src/proofs/cache/lru-cache.ts +481 -0
  163. package/src/proofs/cache/multi-tier-cache.ts +575 -0
  164. package/src/proofs/cache/persistent-cache.ts +788 -0
  165. package/src/proofs/compliance-proof.ts +872 -0
  166. package/src/proofs/composer/base.ts +923 -0
  167. package/src/proofs/composer/index.ts +25 -0
  168. package/src/proofs/composer/interface.ts +518 -0
  169. package/src/proofs/composer/types.ts +383 -0
  170. package/src/proofs/converters/halo2.ts +452 -0
  171. package/src/proofs/converters/index.ts +208 -0
  172. package/src/proofs/converters/interface.ts +363 -0
  173. package/src/proofs/converters/kimchi.ts +462 -0
  174. package/src/proofs/converters/noir.ts +451 -0
  175. package/src/proofs/fallback.ts +888 -0
  176. package/src/proofs/halo2.ts +42 -0
  177. package/src/proofs/index.ts +471 -0
  178. package/src/proofs/interface.ts +13 -0
  179. package/src/proofs/kimchi.ts +42 -0
  180. package/src/proofs/lazy.ts +1004 -0
  181. package/src/proofs/mock.ts +25 -1
  182. package/src/proofs/noir.ts +110 -29
  183. package/src/proofs/orchestrator.ts +960 -0
  184. package/src/proofs/parallel/concurrency.ts +297 -0
  185. package/src/proofs/parallel/dependency-graph.ts +602 -0
  186. package/src/proofs/parallel/executor.ts +420 -0
  187. package/src/proofs/parallel/index.ts +131 -0
  188. package/src/proofs/parallel/interface.ts +685 -0
  189. package/src/proofs/parallel/worker-pool.ts +644 -0
  190. package/src/proofs/providers/halo2.ts +560 -0
  191. package/src/proofs/providers/index.ts +34 -0
  192. package/src/proofs/providers/kimchi.ts +641 -0
  193. package/src/proofs/validator.ts +881 -0
  194. package/src/proofs/verifier.ts +867 -0
  195. package/src/quantum/index.ts +112 -0
  196. package/src/quantum/winternitz-vault.ts +639 -0
  197. package/src/quantum/wots.ts +611 -0
  198. package/src/settlement/backends/direct-chain.ts +1 -0
  199. package/src/settlement/index.ts +9 -0
  200. package/src/settlement/router.ts +732 -46
  201. package/src/solana/index.ts +72 -0
  202. package/src/solana/jito-relayer.ts +687 -0
  203. package/src/solana/noir-verifier-types.ts +430 -0
  204. package/src/solana/noir-verifier.ts +816 -0
  205. package/src/stealth/address-derivation.ts +193 -0
  206. package/src/stealth/ed25519.ts +431 -0
  207. package/src/stealth/index.ts +233 -0
  208. package/src/stealth/meta-address.ts +221 -0
  209. package/src/stealth/secp256k1.ts +368 -0
  210. package/src/stealth/utils.ts +194 -0
  211. package/src/stealth.ts +50 -1504
  212. package/src/sync/index.ts +106 -0
  213. package/src/sync/manager.ts +504 -0
  214. package/src/sync/mock-provider.ts +318 -0
  215. package/src/sync/oblivious.ts +625 -0
  216. package/src/tokens/index.ts +15 -0
  217. package/src/tokens/registry.ts +301 -0
  218. package/src/utils/deprecation.ts +94 -0
  219. package/src/utils/index.ts +9 -0
  220. package/src/wallet/ethereum/index.ts +68 -0
  221. package/src/wallet/ethereum/metamask-privacy.ts +420 -0
  222. package/src/wallet/ethereum/multi-wallet.ts +646 -0
  223. package/src/wallet/ethereum/privacy-adapter.ts +700 -0
  224. package/src/wallet/ethereum/types.ts +3 -1
  225. package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
  226. package/src/wallet/hardware/index.ts +10 -0
  227. package/src/wallet/hardware/ledger-privacy.ts +414 -0
  228. package/src/wallet/index.ts +71 -0
  229. package/src/wallet/near/adapter.ts +626 -0
  230. package/src/wallet/near/index.ts +86 -0
  231. package/src/wallet/near/meteor-wallet.ts +1153 -0
  232. package/src/wallet/near/my-near-wallet.ts +790 -0
  233. package/src/wallet/near/wallet-selector.ts +702 -0
  234. package/src/wallet/solana/adapter.ts +6 -4
  235. package/src/wallet/solana/index.ts +13 -0
  236. package/src/wallet/solana/privacy-adapter.ts +567 -0
  237. package/src/wallet/sui/types.ts +6 -4
  238. package/src/zcash/rpc-client.ts +13 -6
  239. package/dist/chunk-2XIVXWHA.mjs +0 -1930
  240. package/dist/chunk-3INS3PR5.mjs +0 -884
  241. package/dist/chunk-3OVABDRH.mjs +0 -17096
  242. package/dist/chunk-7RFRWDCW.mjs +0 -1504
  243. package/dist/chunk-DLDWZFYC.mjs +0 -1495
  244. package/dist/chunk-E6SZWREQ.mjs +0 -57
  245. package/dist/chunk-F6F73W35.mjs +0 -16166
  246. package/dist/chunk-G33LB27A.mjs +0 -16166
  247. package/dist/chunk-HGU6HZRC.mjs +0 -231
  248. package/dist/chunk-L2K34JCU.mjs +0 -1496
  249. package/dist/chunk-OFDBEIEK.mjs +0 -16166
  250. package/dist/chunk-SF7YSLF5.mjs +0 -1515
  251. package/dist/chunk-SN4ZDTVW.mjs +0 -16166
  252. package/dist/chunk-WWUSGOXE.mjs +0 -17129
  253. package/dist/constants-VOI7BSLK.mjs +0 -27
  254. package/dist/index-B71aXVzk.d.ts +0 -13264
  255. package/dist/index-BYZbDjal.d.ts +0 -11390
  256. package/dist/index-CHB3KuOB.d.mts +0 -11859
  257. package/dist/index-CzWPI6Le.d.ts +0 -11859
  258. package/dist/index-pOIIuwfV.d.mts +0 -13264
  259. package/dist/index-xbWjohNq.d.mts +0 -11390
  260. package/dist/solana-4O4K45VU.mjs +0 -46
  261. package/dist/solana-5EMCTPTS.mjs +0 -46
  262. package/dist/solana-NDABAZ6P.mjs +0 -56
  263. package/dist/solana-Q4NAVBTS.mjs +0 -46
  264. package/dist/solana-ZYO63LY5.mjs +0 -46
@@ -0,0 +1,449 @@
1
+ /**
2
+ * ShadowWire Privacy Backend
3
+ *
4
+ * Integrates ShadowWire by Radr Labs as a privacy backend for SIP Protocol.
5
+ * ShadowWire uses Pedersen Commitments + Bulletproofs for amount hiding.
6
+ *
7
+ * SIP adds viewing keys to ShadowWire for compliance support.
8
+ *
9
+ * @see https://radrlabs.io
10
+ * @see https://github.com/Radrdotfun/ShadowWire
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { ShadowWireBackend, PrivacyBackendRegistry } from '@sip-protocol/sdk'
15
+ *
16
+ * const backend = new ShadowWireBackend()
17
+ * const registry = new PrivacyBackendRegistry()
18
+ * registry.register(backend)
19
+ *
20
+ * // Execute private transfer
21
+ * const result = await backend.execute({
22
+ * chain: 'solana',
23
+ * sender: 'sender-pubkey',
24
+ * recipient: 'recipient-pubkey',
25
+ * mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
26
+ * amount: 1000000n, // 1 USDC
27
+ * decimals: 6,
28
+ * })
29
+ * ```
30
+ */
31
+
32
+ import {
33
+ ShadowWireClient,
34
+ type TransferType,
35
+ type TokenSymbol,
36
+ type WalletAdapter,
37
+ InsufficientBalanceError,
38
+ RecipientNotFoundError,
39
+ InvalidAmountError,
40
+ InvalidAddressError,
41
+ } from '@radr/shadowwire'
42
+ import type { ChainType, ViewingKey } from '@sip-protocol/types'
43
+ import type {
44
+ PrivacyBackend,
45
+ BackendType,
46
+ BackendCapabilities,
47
+ TransferParams,
48
+ TransactionResult,
49
+ AvailabilityResult,
50
+ BackendParams,
51
+ } from './interface'
52
+ import { isTransferParams } from './interface'
53
+ import { generateViewingKey, encryptForViewing } from '../privacy'
54
+ import type { HexString } from '@sip-protocol/types'
55
+ import { bytesToHex } from '@noble/hashes/utils'
56
+
57
+ /**
58
+ * ShadowWire supported token mint addresses
59
+ * Note: ShadowWire supports a specific set of tokens. Check SUPPORTED_TOKENS in @radr/shadowwire
60
+ */
61
+ export const SHADOWWIRE_TOKEN_MINTS: Record<TokenSymbol, string> = {
62
+ SOL: 'So11111111111111111111111111111111111111112',
63
+ USDC: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
64
+ RADR: 'RADRi35VqLmMu4t7Gax1KVszxnQnbtqEwJQJVfzpump',
65
+ ORE: 'oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhycK7fw73F', // ORE mining token
66
+ BONK: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263',
67
+ JIM: 'JIMa1xG7h7h7h7h7h7h7h7h7h7h7h7h7h7h7h7h7', // Placeholder
68
+ GODL: 'GODL1111111111111111111111111111111111111', // Placeholder
69
+ HUSTLE: 'HUSTLEexampleaddress1111111111111111111', // Placeholder
70
+ ZEC: 'ZECexampleaddress1111111111111111111111111', // Placeholder
71
+ CRT: 'CRTexampleaddress11111111111111111111111111', // Placeholder
72
+ BLACKCOIN: 'BLACKexampleaddress111111111111111111111', // Placeholder
73
+ GIL: 'GILexampleaddress11111111111111111111111111', // Placeholder
74
+ ANON: 'ANONexampleaddress1111111111111111111111111', // Placeholder
75
+ WLFI: 'WLFIexampleaddress1111111111111111111111111', // Placeholder - World Liberty Financial
76
+ USD1: 'USD1exampleaddress1111111111111111111111111', // Placeholder - USD1 stablecoin
77
+ AOL: 'AOLexampleaddress11111111111111111111111111', // Placeholder
78
+ IQLABS: 'IQLABSexampleaddress111111111111111111111', // Placeholder - IQ Labs token
79
+ }
80
+
81
+ /**
82
+ * Reverse lookup: mint address to symbol
83
+ */
84
+ const MINT_TO_SYMBOL: Record<string, TokenSymbol> = Object.fromEntries(
85
+ Object.entries(SHADOWWIRE_TOKEN_MINTS).map(([symbol, mint]) => [mint, symbol as TokenSymbol])
86
+ )
87
+
88
+ /**
89
+ * ShadowWire backend configuration
90
+ */
91
+ export interface ShadowWireBackendConfig {
92
+ /** API base URL (optional, uses default if not provided) */
93
+ apiBaseUrl?: string
94
+ /** Enable debug logging */
95
+ debug?: boolean
96
+ /** Default transfer type */
97
+ defaultTransferType?: TransferType
98
+ /** Wallet adapter for signing */
99
+ wallet?: WalletAdapter
100
+ /** Enable client-side proof generation (WASM) */
101
+ clientSideProofs?: boolean
102
+ }
103
+
104
+ /**
105
+ * ShadowWire backend capabilities
106
+ */
107
+ const SHADOWWIRE_CAPABILITIES: BackendCapabilities = {
108
+ hiddenAmount: true,
109
+ hiddenSender: true,
110
+ hiddenRecipient: true, // Internal transfers only
111
+ hiddenCompute: false,
112
+ complianceSupport: true, // SIP adds viewing keys
113
+ anonymitySet: undefined, // Not pool-based
114
+ setupRequired: false,
115
+ latencyEstimate: 'medium', // ~500ms for proof generation
116
+ supportedTokens: 'spl',
117
+ minAmount: 1n, // Minimum 1 lamport
118
+ maxAmount: undefined,
119
+ }
120
+
121
+ /**
122
+ * ShadowWire Privacy Backend
123
+ *
124
+ * Wraps the ShadowWire SDK to provide a unified PrivacyBackend interface.
125
+ * Adds SIP's viewing key support for compliance.
126
+ */
127
+ export class ShadowWireBackend implements PrivacyBackend {
128
+ readonly name = 'shadowwire'
129
+ readonly type: BackendType = 'transaction'
130
+ readonly chains: ChainType[] = ['solana']
131
+
132
+ private client: ShadowWireClient
133
+ private config: ShadowWireBackendConfig
134
+ private wallet?: WalletAdapter
135
+
136
+ constructor(config: ShadowWireBackendConfig = {}) {
137
+ this.config = {
138
+ defaultTransferType: 'internal',
139
+ clientSideProofs: false,
140
+ ...config,
141
+ }
142
+
143
+ this.client = new ShadowWireClient({
144
+ debug: config.debug,
145
+ apiBaseUrl: config.apiBaseUrl,
146
+ })
147
+
148
+ this.wallet = config.wallet
149
+ }
150
+
151
+ /**
152
+ * Set wallet adapter for signing
153
+ */
154
+ setWallet(wallet: WalletAdapter): void {
155
+ this.wallet = wallet
156
+ }
157
+
158
+ /**
159
+ * Check if backend is available for given parameters
160
+ */
161
+ async checkAvailability(params: BackendParams): Promise<AvailabilityResult> {
162
+ if (!isTransferParams(params)) {
163
+ return {
164
+ available: false,
165
+ reason: 'ShadowWire only supports transfer operations, not compute',
166
+ }
167
+ }
168
+
169
+ // Check chain support
170
+ if (params.chain !== 'solana') {
171
+ return {
172
+ available: false,
173
+ reason: `Chain '${params.chain}' not supported. ShadowWire only works on Solana`,
174
+ }
175
+ }
176
+
177
+ // Check token support
178
+ const tokenSymbol = this.getTokenSymbol(params.mint)
179
+ if (!tokenSymbol) {
180
+ return {
181
+ available: false,
182
+ reason: `Token mint '${params.mint}' not supported by ShadowWire`,
183
+ }
184
+ }
185
+
186
+ // Check amount validity
187
+ if (params.amount <= 0n) {
188
+ return {
189
+ available: false,
190
+ reason: 'Amount must be greater than 0',
191
+ }
192
+ }
193
+
194
+ // Check balance (if wallet is connected)
195
+ if (this.wallet) {
196
+ try {
197
+ const balance = await this.client.getBalance(params.sender, tokenSymbol)
198
+ if (BigInt(balance.available) < params.amount) {
199
+ return {
200
+ available: false,
201
+ reason: `Insufficient ShadowWire balance. Have: ${balance.available}, Need: ${params.amount}`,
202
+ }
203
+ }
204
+ } catch {
205
+ // Balance check failed, but might still be available
206
+ }
207
+ }
208
+
209
+ return {
210
+ available: true,
211
+ estimatedCost: this.estimateTransferCost(params),
212
+ estimatedTime: 2000, // ~2s for proof generation + confirmation
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Get backend capabilities
218
+ */
219
+ getCapabilities(): BackendCapabilities {
220
+ return { ...SHADOWWIRE_CAPABILITIES }
221
+ }
222
+
223
+ /**
224
+ * Execute a privacy-preserving transfer via ShadowWire
225
+ */
226
+ async execute(params: TransferParams): Promise<TransactionResult> {
227
+ // Validate parameters
228
+ const validation = await this.checkAvailability(params)
229
+ if (!validation.available) {
230
+ return {
231
+ success: false,
232
+ error: validation.reason,
233
+ backend: this.name,
234
+ }
235
+ }
236
+
237
+ // Get token symbol
238
+ const tokenSymbol = this.getTokenSymbol(params.mint)
239
+ if (!tokenSymbol) {
240
+ return {
241
+ success: false,
242
+ error: `Unsupported token: ${params.mint}`,
243
+ backend: this.name,
244
+ }
245
+ }
246
+
247
+ // Determine wallet
248
+ const wallet = this.wallet || (params.options?.wallet as WalletAdapter | undefined)
249
+ if (!wallet) {
250
+ return {
251
+ success: false,
252
+ error: 'Wallet adapter required for ShadowWire transfers. Set via setWallet() or options.wallet',
253
+ backend: this.name,
254
+ }
255
+ }
256
+
257
+ try {
258
+ // Determine transfer type
259
+ const transferType: TransferType =
260
+ (params.options?.transferType as TransferType) ||
261
+ this.config.defaultTransferType ||
262
+ 'internal'
263
+
264
+ // Convert amount to decimal (ShadowWire uses decimal amounts)
265
+ const decimalAmount = Number(params.amount) / Math.pow(10, params.decimals)
266
+
267
+ // Execute ShadowWire transfer
268
+ const response = await this.client.transfer({
269
+ sender: params.sender,
270
+ recipient: params.recipient,
271
+ amount: decimalAmount,
272
+ token: tokenSymbol,
273
+ type: transferType,
274
+ wallet,
275
+ })
276
+
277
+ // Generate SIP viewing key for compliance
278
+ let viewingKey: ViewingKey | undefined
279
+ let encryptedData: HexString | undefined
280
+
281
+ if (params.viewingKey || params.options?.generateViewingKey) {
282
+ viewingKey = params.viewingKey || generateViewingKey()
283
+
284
+ // Encrypt transaction details for viewing key holder
285
+ const txDetails = {
286
+ sender: params.sender,
287
+ recipient: params.recipient,
288
+ amount: params.amount.toString(),
289
+ token: tokenSymbol,
290
+ timestamp: Date.now(),
291
+ shadowwireTxId: response.tx_signature,
292
+ }
293
+
294
+ // encryptForViewing returns EncryptedTransaction object
295
+ const encrypted = encryptForViewing(txDetails, viewingKey)
296
+ // Convert to hex string for storage
297
+ const jsonBytes = new TextEncoder().encode(JSON.stringify(encrypted))
298
+ encryptedData = `0x${bytesToHex(jsonBytes)}` as HexString
299
+ }
300
+
301
+ return {
302
+ success: true,
303
+ signature: response.tx_signature,
304
+ backend: this.name,
305
+ encryptedData,
306
+ metadata: {
307
+ transferType,
308
+ token: tokenSymbol,
309
+ viewingKeyGenerated: !!viewingKey,
310
+ },
311
+ }
312
+ } catch (error) {
313
+ return {
314
+ success: false,
315
+ error: this.formatError(error),
316
+ backend: this.name,
317
+ }
318
+ }
319
+ }
320
+
321
+ /**
322
+ * Estimate cost for a transfer
323
+ */
324
+ async estimateCost(params: BackendParams): Promise<bigint> {
325
+ if (!isTransferParams(params)) {
326
+ return 0n
327
+ }
328
+ return this.estimateTransferCost(params)
329
+ }
330
+
331
+ /**
332
+ * Get ShadowWire balance for a token
333
+ */
334
+ async getBalance(walletAddress: string, token: TokenSymbol): Promise<bigint> {
335
+ const balance = await this.client.getBalance(walletAddress, token)
336
+ return BigInt(balance.available)
337
+ }
338
+
339
+ /**
340
+ * Deposit funds into ShadowWire pool
341
+ * Returns an unsigned transaction that must be signed and sent by the caller
342
+ */
343
+ async deposit(
344
+ walletAddress: string,
345
+ amount: number,
346
+ tokenMint?: string
347
+ ): Promise<{ unsignedTx: string; poolAddress: string }> {
348
+ const response = await this.client.deposit({
349
+ wallet: walletAddress,
350
+ amount,
351
+ token_mint: tokenMint,
352
+ })
353
+ return {
354
+ unsignedTx: response.unsigned_tx_base64,
355
+ poolAddress: response.pool_address,
356
+ }
357
+ }
358
+
359
+ /**
360
+ * Withdraw funds from ShadowWire pool
361
+ * Returns an unsigned transaction that must be signed and sent by the caller
362
+ */
363
+ async withdraw(
364
+ walletAddress: string,
365
+ amount: number,
366
+ tokenMint?: string
367
+ ): Promise<{ unsignedTx: string; amountWithdrawn: number; fee: number }> {
368
+ const response = await this.client.withdraw({
369
+ wallet: walletAddress,
370
+ amount,
371
+ token_mint: tokenMint,
372
+ })
373
+ return {
374
+ unsignedTx: response.unsigned_tx_base64,
375
+ amountWithdrawn: response.amount_withdrawn,
376
+ fee: response.fee,
377
+ }
378
+ }
379
+
380
+ /**
381
+ * Get underlying ShadowWire client
382
+ */
383
+ getClient(): ShadowWireClient {
384
+ return this.client
385
+ }
386
+
387
+ // ─── Private Helpers ───────────────────────────────────────────────────────
388
+
389
+ /**
390
+ * Get token symbol from mint address
391
+ */
392
+ private getTokenSymbol(mint: string | null): TokenSymbol | undefined {
393
+ if (!mint) {
394
+ return 'SOL'
395
+ }
396
+ return MINT_TO_SYMBOL[mint]
397
+ }
398
+
399
+ /**
400
+ * Estimate transfer cost in lamports
401
+ */
402
+ private estimateTransferCost(params: TransferParams): bigint {
403
+ // Base transaction fee
404
+ let cost = 5000n // ~0.000005 SOL
405
+
406
+ // Add proof generation cost estimate
407
+ const transferType =
408
+ (params.options?.transferType as TransferType) ||
409
+ this.config.defaultTransferType ||
410
+ 'internal'
411
+
412
+ if (transferType === 'internal') {
413
+ cost += 10000n // Additional cost for ZK proof verification
414
+ }
415
+
416
+ return cost
417
+ }
418
+
419
+ /**
420
+ * Format error for user-friendly message
421
+ */
422
+ private formatError(error: unknown): string {
423
+ if (error instanceof InsufficientBalanceError) {
424
+ return 'Insufficient balance in ShadowWire pool. Deposit funds first.'
425
+ }
426
+ if (error instanceof RecipientNotFoundError) {
427
+ return 'Recipient must be a ShadowWire user for internal transfers. Use external transfer type for non-users.'
428
+ }
429
+ if (error instanceof InvalidAmountError) {
430
+ return 'Invalid transfer amount'
431
+ }
432
+ if (error instanceof InvalidAddressError) {
433
+ return 'Invalid Solana address'
434
+ }
435
+ if (error instanceof Error) {
436
+ return error.message
437
+ }
438
+ return 'Unknown ShadowWire error'
439
+ }
440
+ }
441
+
442
+ /**
443
+ * Create a ShadowWire backend with default configuration
444
+ */
445
+ export function createShadowWireBackend(
446
+ config?: ShadowWireBackendConfig
447
+ ): ShadowWireBackend {
448
+ return new ShadowWireBackend(config)
449
+ }
@@ -38,7 +38,9 @@ import type {
38
38
  TransferParams,
39
39
  TransactionResult,
40
40
  AvailabilityResult,
41
+ PrivacyBackendVersion,
41
42
  } from './interface'
43
+ import { CURRENT_BACKEND_VERSION } from './interface'
42
44
 
43
45
  /**
44
46
  * Supported chains for SIP Native backend
@@ -93,6 +95,7 @@ export interface SIPNativeBackendConfig {
93
95
  * with viewing key support for regulatory compliance.
94
96
  */
95
97
  export class SIPNativeBackend implements PrivacyBackend {
98
+ readonly version: PrivacyBackendVersion = CURRENT_BACKEND_VERSION
96
99
  readonly name = 'sip-native'
97
100
  readonly type: BackendType = 'transaction'
98
101
  readonly chains: ChainType[]
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Privacy-Aware Logger
3
+ *
4
+ * Provides logging utilities that automatically redact sensitive information
5
+ * like wallet addresses and transaction amounts to prevent privacy leaks
6
+ * through log aggregators or error reporting tools.
7
+ */
8
+
9
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'
10
+
11
+ export interface PrivacyLoggerConfig {
12
+ prefix?: string
13
+ level?: LogLevel
14
+ productionMode?: boolean
15
+ output?: (level: LogLevel, message: string) => void
16
+ silent?: boolean
17
+ }
18
+
19
+ export interface SensitiveData {
20
+ address?: string
21
+ from?: string
22
+ to?: string
23
+ owner?: string
24
+ amount?: bigint | number | string
25
+ signature?: string
26
+ txHash?: string
27
+ [key: string]: unknown
28
+ }
29
+
30
+ const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {
31
+ debug: 0,
32
+ info: 1,
33
+ warn: 2,
34
+ error: 3,
35
+ silent: 4,
36
+ }
37
+
38
+ const ADDRESS_FIELDS = new Set([
39
+ 'address', 'from', 'to', 'owner', 'sender', 'recipient', 'wallet', 'publicKey', 'pubkey',
40
+ ])
41
+
42
+ const TX_FIELDS = new Set([
43
+ 'signature', 'txHash', 'txSignature', 'transactionHash', 'computationId',
44
+ ])
45
+
46
+ export function redactAddress(address: string, chars: number = 4): string {
47
+ if (!address || typeof address !== 'string') return '[invalid]'
48
+ if (address.length <= chars * 2 + 3) return address
49
+ return `${address.slice(0, chars)}...${address.slice(-chars)}`
50
+ }
51
+
52
+ export function redactSignature(signature: string, chars: number = 6): string {
53
+ if (!signature || typeof signature !== 'string') return '[invalid]'
54
+ if (signature.length <= chars * 2 + 3) return signature
55
+ return `${signature.slice(0, chars)}...${signature.slice(-chars)}`
56
+ }
57
+
58
+ export function maskAmount(
59
+ amount: bigint | number | string,
60
+ decimals: number = 9,
61
+ symbol: string = ''
62
+ ): string {
63
+ let value: number
64
+ if (typeof amount === 'bigint') {
65
+ value = Number(amount) / 10 ** decimals
66
+ } else if (typeof amount === 'string') {
67
+ value = parseFloat(amount)
68
+ if (isNaN(value)) return '[hidden]'
69
+ } else {
70
+ value = amount / 10 ** decimals
71
+ }
72
+
73
+ let range: string
74
+ if (value <= 0) range = '0'
75
+ else if (value < 0.01) range = '<0.01'
76
+ else if (value < 0.1) range = '0.01-0.1'
77
+ else if (value < 1) range = '0.1-1'
78
+ else if (value < 10) range = '1-10'
79
+ else if (value < 100) range = '10-100'
80
+ else if (value < 1000) range = '100-1K'
81
+ else if (value < 10000) range = '1K-10K'
82
+ else if (value < 100000) range = '10K-100K'
83
+ else range = '>100K'
84
+
85
+ return symbol ? `${range} ${symbol}` : range
86
+ }
87
+
88
+ export function redactSensitiveData(
89
+ data: SensitiveData,
90
+ productionMode: boolean = false
91
+ ): Record<string, string | undefined> {
92
+ const result: Record<string, string | undefined> = {}
93
+ for (const [key, value] of Object.entries(data)) {
94
+ if (value === undefined || value === null) {
95
+ result[key] = undefined
96
+ continue
97
+ }
98
+ if (ADDRESS_FIELDS.has(key) && typeof value === 'string') {
99
+ result[key] = redactAddress(value)
100
+ continue
101
+ }
102
+ if (TX_FIELDS.has(key) && typeof value === 'string') {
103
+ result[key] = redactSignature(value)
104
+ continue
105
+ }
106
+ if (key === 'amount' || key.toLowerCase().includes('amount')) {
107
+ if (typeof value === 'bigint' || typeof value === 'number' || typeof value === 'string') {
108
+ result[key] = productionMode ? '[hidden]' : maskAmount(value)
109
+ }
110
+ continue
111
+ }
112
+ if (typeof value === 'string') result[key] = value
113
+ else if (typeof value === 'number' || typeof value === 'bigint') result[key] = value.toString()
114
+ else if (typeof value === 'boolean') result[key] = value.toString()
115
+ else result[key] = '[object]'
116
+ }
117
+ return result
118
+ }
119
+
120
+ export class PrivacyLogger {
121
+ private config: Required<PrivacyLoggerConfig>
122
+
123
+ constructor(config: PrivacyLoggerConfig = {}) {
124
+ this.config = {
125
+ prefix: config.prefix ?? '',
126
+ level: config.level ?? 'info',
127
+ productionMode: config.productionMode ?? false,
128
+ silent: config.silent ?? false,
129
+ output: config.output ?? this.defaultOutput.bind(this),
130
+ }
131
+ }
132
+
133
+ private defaultOutput(level: LogLevel, message: string): void {
134
+ switch (level) {
135
+ case 'debug': console.debug(message); break
136
+ case 'info': console.info(message); break
137
+ case 'warn': console.warn(message); break
138
+ case 'error': console.error(message); break
139
+ }
140
+ }
141
+
142
+ private shouldLog(level: LogLevel): boolean {
143
+ if (this.config.silent) return false
144
+ return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[this.config.level]
145
+ }
146
+
147
+ private formatMessage(message: string, data?: SensitiveData): string {
148
+ const prefix = this.config.prefix ? `${this.config.prefix} ` : ''
149
+ if (!data || Object.keys(data).length === 0) return `${prefix}${message}`
150
+ const redacted = redactSensitiveData(data, this.config.productionMode)
151
+ const dataStr = Object.entries(redacted)
152
+ .filter(([, v]) => v !== undefined)
153
+ .map(([k, v]) => `${k}=${v}`)
154
+ .join(' ')
155
+ return `${prefix}${message} ${dataStr}`
156
+ }
157
+
158
+ debug(message: string, data?: SensitiveData): void {
159
+ if (this.shouldLog('debug')) this.config.output('debug', this.formatMessage(message, data))
160
+ }
161
+
162
+ info(message: string, data?: SensitiveData): void {
163
+ if (this.shouldLog('info')) this.config.output('info', this.formatMessage(message, data))
164
+ }
165
+
166
+ warn(message: string, data?: SensitiveData): void {
167
+ if (this.shouldLog('warn')) this.config.output('warn', this.formatMessage(message, data))
168
+ }
169
+
170
+ error(message: string, data?: SensitiveData): void {
171
+ if (this.shouldLog('error')) this.config.output('error', this.formatMessage(message, data))
172
+ }
173
+
174
+ configure(config: Partial<PrivacyLoggerConfig>): void {
175
+ this.config = { ...this.config, ...config }
176
+ }
177
+
178
+ child(prefix: string): PrivacyLogger {
179
+ const childPrefix = this.config.prefix ? `${this.config.prefix}${prefix}` : prefix
180
+ return new PrivacyLogger({ ...this.config, prefix: childPrefix })
181
+ }
182
+ }
183
+
184
+ export const privacyLogger = new PrivacyLogger({ prefix: '[SIP]', level: 'warn' })
185
+
186
+ export function createPrivacyLogger(
187
+ moduleName: string,
188
+ config: Partial<PrivacyLoggerConfig> = {}
189
+ ): PrivacyLogger {
190
+ return new PrivacyLogger({ prefix: `[${moduleName}]`, level: 'warn', ...config })
191
+ }