@sip-protocol/sdk 0.7.2 → 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 (262) 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 +48874 -18336
  7. package/dist/browser.mjs +674 -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-YWGJ77A2.mjs +33806 -0
  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-DXh2IGkz.d.ts +24681 -0
  24. package/dist/index-DeE1ZzA4.d.mts +24681 -0
  25. package/dist/index.d.mts +9 -3
  26. package/dist/index.d.ts +9 -3
  27. package/dist/index.js +48676 -17318
  28. package/dist/index.mjs +583 -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 +276 -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 +201 -0
  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 +402 -0
  98. package/src/chains/solana/providers/index.ts +85 -0
  99. package/src/chains/solana/providers/interface.ts +221 -0
  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 +790 -0
  103. package/src/chains/solana/rpc-client.ts +1150 -0
  104. package/src/chains/solana/scan.ts +170 -73
  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 +77 -7
  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 +37 -0
  116. package/src/compliance/range-sas.ts +956 -0
  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 +785 -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 +336 -0
  143. package/src/privacy-backends/interface.ts +906 -0
  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-types.ts +278 -0
  148. package/src/privacy-backends/privacycash.ts +456 -0
  149. package/src/privacy-backends/private-swap.ts +570 -0
  150. package/src/privacy-backends/rate-limiter.ts +683 -0
  151. package/src/privacy-backends/registry.ts +690 -0
  152. package/src/privacy-backends/router.ts +626 -0
  153. package/src/privacy-backends/shadowwire.ts +449 -0
  154. package/src/privacy-backends/sip-native.ts +256 -0
  155. package/src/privacy-logger.ts +191 -0
  156. package/src/production-safety.ts +373 -0
  157. package/src/proofs/aggregator.ts +1029 -0
  158. package/src/proofs/browser-composer.ts +1150 -0
  159. package/src/proofs/browser.ts +113 -25
  160. package/src/proofs/cache/index.ts +127 -0
  161. package/src/proofs/cache/interface.ts +545 -0
  162. package/src/proofs/cache/key-generator.ts +188 -0
  163. package/src/proofs/cache/lru-cache.ts +481 -0
  164. package/src/proofs/cache/multi-tier-cache.ts +575 -0
  165. package/src/proofs/cache/persistent-cache.ts +788 -0
  166. package/src/proofs/compliance-proof.ts +872 -0
  167. package/src/proofs/composer/base.ts +923 -0
  168. package/src/proofs/composer/index.ts +25 -0
  169. package/src/proofs/composer/interface.ts +518 -0
  170. package/src/proofs/composer/types.ts +383 -0
  171. package/src/proofs/converters/halo2.ts +452 -0
  172. package/src/proofs/converters/index.ts +208 -0
  173. package/src/proofs/converters/interface.ts +363 -0
  174. package/src/proofs/converters/kimchi.ts +462 -0
  175. package/src/proofs/converters/noir.ts +451 -0
  176. package/src/proofs/fallback.ts +888 -0
  177. package/src/proofs/halo2.ts +42 -0
  178. package/src/proofs/index.ts +471 -0
  179. package/src/proofs/interface.ts +13 -0
  180. package/src/proofs/kimchi.ts +42 -0
  181. package/src/proofs/lazy.ts +1004 -0
  182. package/src/proofs/mock.ts +25 -1
  183. package/src/proofs/noir.ts +111 -30
  184. package/src/proofs/orchestrator.ts +960 -0
  185. package/src/proofs/parallel/concurrency.ts +297 -0
  186. package/src/proofs/parallel/dependency-graph.ts +602 -0
  187. package/src/proofs/parallel/executor.ts +420 -0
  188. package/src/proofs/parallel/index.ts +131 -0
  189. package/src/proofs/parallel/interface.ts +685 -0
  190. package/src/proofs/parallel/worker-pool.ts +644 -0
  191. package/src/proofs/providers/halo2.ts +560 -0
  192. package/src/proofs/providers/index.ts +34 -0
  193. package/src/proofs/providers/kimchi.ts +641 -0
  194. package/src/proofs/validator.ts +881 -0
  195. package/src/proofs/verifier.ts +867 -0
  196. package/src/quantum/index.ts +112 -0
  197. package/src/quantum/winternitz-vault.ts +639 -0
  198. package/src/quantum/wots.ts +611 -0
  199. package/src/settlement/backends/direct-chain.ts +1 -0
  200. package/src/settlement/index.ts +9 -0
  201. package/src/settlement/router.ts +732 -46
  202. package/src/solana/index.ts +72 -0
  203. package/src/solana/jito-relayer.ts +687 -0
  204. package/src/solana/noir-verifier-types.ts +430 -0
  205. package/src/solana/noir-verifier.ts +816 -0
  206. package/src/stealth/address-derivation.ts +193 -0
  207. package/src/stealth/ed25519.ts +431 -0
  208. package/src/stealth/index.ts +233 -0
  209. package/src/stealth/meta-address.ts +221 -0
  210. package/src/stealth/secp256k1.ts +368 -0
  211. package/src/stealth/utils.ts +194 -0
  212. package/src/stealth.ts +50 -1504
  213. package/src/surveillance/algorithms/address-reuse.ts +143 -0
  214. package/src/surveillance/algorithms/cluster.ts +247 -0
  215. package/src/surveillance/algorithms/exchange.ts +295 -0
  216. package/src/surveillance/algorithms/temporal.ts +337 -0
  217. package/src/surveillance/analyzer.ts +442 -0
  218. package/src/surveillance/index.ts +64 -0
  219. package/src/surveillance/scoring.ts +372 -0
  220. package/src/surveillance/types.ts +264 -0
  221. package/src/sync/index.ts +106 -0
  222. package/src/sync/manager.ts +504 -0
  223. package/src/sync/mock-provider.ts +318 -0
  224. package/src/sync/oblivious.ts +625 -0
  225. package/src/tokens/index.ts +15 -0
  226. package/src/tokens/registry.ts +301 -0
  227. package/src/utils/deprecation.ts +94 -0
  228. package/src/utils/index.ts +9 -0
  229. package/src/wallet/ethereum/index.ts +68 -0
  230. package/src/wallet/ethereum/metamask-privacy.ts +420 -0
  231. package/src/wallet/ethereum/multi-wallet.ts +646 -0
  232. package/src/wallet/ethereum/privacy-adapter.ts +700 -0
  233. package/src/wallet/ethereum/types.ts +3 -1
  234. package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
  235. package/src/wallet/hardware/index.ts +10 -0
  236. package/src/wallet/hardware/ledger-privacy.ts +414 -0
  237. package/src/wallet/index.ts +71 -0
  238. package/src/wallet/near/adapter.ts +626 -0
  239. package/src/wallet/near/index.ts +86 -0
  240. package/src/wallet/near/meteor-wallet.ts +1153 -0
  241. package/src/wallet/near/my-near-wallet.ts +790 -0
  242. package/src/wallet/near/wallet-selector.ts +702 -0
  243. package/src/wallet/solana/adapter.ts +6 -4
  244. package/src/wallet/solana/index.ts +13 -0
  245. package/src/wallet/solana/privacy-adapter.ts +567 -0
  246. package/src/wallet/sui/types.ts +6 -4
  247. package/src/zcash/rpc-client.ts +13 -6
  248. package/dist/chunk-3INS3PR5.mjs +0 -884
  249. package/dist/chunk-3OVABDRH.mjs +0 -17096
  250. package/dist/chunk-DLDWZFYC.mjs +0 -1495
  251. package/dist/chunk-E6SZWREQ.mjs +0 -57
  252. package/dist/chunk-G33LB27A.mjs +0 -16166
  253. package/dist/chunk-HGU6HZRC.mjs +0 -231
  254. package/dist/chunk-L2K34JCU.mjs +0 -1496
  255. package/dist/chunk-SN4ZDTVW.mjs +0 -16166
  256. package/dist/constants-VOI7BSLK.mjs +0 -27
  257. package/dist/index-BYZbDjal.d.ts +0 -11390
  258. package/dist/index-CHB3KuOB.d.mts +0 -11859
  259. package/dist/index-CzWPI6Le.d.ts +0 -11859
  260. package/dist/index-xbWjohNq.d.mts +0 -11390
  261. package/dist/solana-5EMCTPTS.mjs +0 -46
  262. package/dist/solana-Q4NAVBTS.mjs +0 -46
@@ -0,0 +1,702 @@
1
+ /**
2
+ * NEAR Wallet Selector Privacy Integration
3
+ *
4
+ * Integrates SIP privacy features with NEAR Wallet Selector,
5
+ * enabling privacy transactions across all compatible wallets.
6
+ *
7
+ * @example Basic usage
8
+ * ```typescript
9
+ * import { setupWalletSelector } from '@near-wallet-selector/core'
10
+ * import { setupModal } from '@near-wallet-selector/modal-ui'
11
+ * import { createPrivacyWalletSelector } from '@sip-protocol/sdk'
12
+ *
13
+ * // Setup standard wallet selector
14
+ * const selector = await setupWalletSelector({
15
+ * network: 'testnet',
16
+ * modules: [setupMyNearWallet(), setupMeteorWallet()],
17
+ * })
18
+ *
19
+ * // Wrap with privacy support
20
+ * const privacySelector = createPrivacyWalletSelector(selector, {
21
+ * network: 'testnet',
22
+ * })
23
+ *
24
+ * // Generate stealth meta-address for receiving
25
+ * const { metaAddress, encoded } = await privacySelector.generateStealthMetaAddress()
26
+ *
27
+ * // Send private transfer
28
+ * const result = await privacySelector.sendPrivateTransfer({
29
+ * recipientMetaAddress: encoded,
30
+ * amount: '1000000000000000000000000', // 1 NEAR
31
+ * })
32
+ * ```
33
+ *
34
+ * @packageDocumentation
35
+ */
36
+
37
+ import { sha256 } from '@noble/hashes/sha2'
38
+ import { bytesToHex, hexToBytes } from '@noble/hashes/utils'
39
+ import { ed25519 } from '@noble/curves/ed25519'
40
+ import type { HexString, StealthMetaAddress, StealthAddress } from '@sip-protocol/types'
41
+ import type { NEARNetwork } from '../../chains/near/constants'
42
+ import {
43
+ generateNEARStealthAddress,
44
+ deriveNEARStealthPrivateKey,
45
+ checkNEARStealthAddress,
46
+ encodeNEARStealthMetaAddress,
47
+ parseNEARStealthMetaAddress,
48
+ } from '../../chains/near/stealth'
49
+ import { buildPrivateTransfer } from '../../chains/near/implicit-account'
50
+
51
+ // ─── Types ────────────────────────────────────────────────────────────────────
52
+
53
+ /**
54
+ * NEAR Wallet Selector interface (minimal type for compatibility)
55
+ * This matches the core interface from @near-wallet-selector/core
56
+ */
57
+ export interface WalletSelector {
58
+ /** Get the currently selected wallet */
59
+ wallet(): Promise<Wallet | null>
60
+ /** Check if connected */
61
+ isSignedIn(): boolean
62
+ /** Get account ID */
63
+ getAccounts(): Promise<Array<{ accountId: string; publicKey?: string }>>
64
+ /** Subscribe to state changes */
65
+ on(event: string, callback: (state: unknown) => void): () => void
66
+ /** Get current state */
67
+ store: {
68
+ getState(): WalletSelectorState
69
+ observable: {
70
+ subscribe(callback: (state: WalletSelectorState) => void): { unsubscribe(): void }
71
+ }
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Wallet Selector state
77
+ */
78
+ export interface WalletSelectorState {
79
+ accounts: Array<{ accountId: string; publicKey?: string }>
80
+ selectedWalletId: string | null
81
+ }
82
+
83
+ /**
84
+ * Wallet interface from Wallet Selector
85
+ */
86
+ export interface Wallet {
87
+ id: string
88
+ type: string
89
+ metadata: {
90
+ name: string
91
+ description?: string
92
+ iconUrl?: string
93
+ }
94
+ signAndSendTransaction(params: SignAndSendTransactionParams): Promise<WalletTransactionResult>
95
+ signAndSendTransactions?(params: SignAndSendTransactionsParams): Promise<WalletTransactionResult[]>
96
+ signMessage?(params: SignMessageParams): Promise<SignedMessage>
97
+ }
98
+
99
+ /**
100
+ * Transaction parameters for Wallet Selector
101
+ */
102
+ export interface SignAndSendTransactionParams {
103
+ signerId?: string
104
+ receiverId: string
105
+ actions: WalletAction[]
106
+ }
107
+
108
+ /**
109
+ * Batch transaction parameters
110
+ */
111
+ export interface SignAndSendTransactionsParams {
112
+ transactions: SignAndSendTransactionParams[]
113
+ }
114
+
115
+ /**
116
+ * Wallet action types
117
+ */
118
+ export interface WalletAction {
119
+ type: 'Transfer' | 'FunctionCall' | 'AddKey' | 'DeleteKey' | 'DeleteAccount'
120
+ params: Record<string, unknown>
121
+ }
122
+
123
+ /**
124
+ * Transaction result from wallet
125
+ */
126
+ export interface WalletTransactionResult {
127
+ transaction: {
128
+ hash: string
129
+ signerId: string
130
+ receiverId: string
131
+ }
132
+ receipts?: unknown[]
133
+ }
134
+
135
+ /**
136
+ * Sign message parameters
137
+ */
138
+ export interface SignMessageParams {
139
+ message: string
140
+ recipient: string
141
+ nonce: Buffer
142
+ }
143
+
144
+ /**
145
+ * Signed message result
146
+ */
147
+ export interface SignedMessage {
148
+ signature: string
149
+ publicKey: string
150
+ accountId: string
151
+ }
152
+
153
+ /**
154
+ * Privacy Wallet Selector configuration
155
+ */
156
+ export interface PrivacyWalletSelectorConfig {
157
+ /** NEAR network */
158
+ network: NEARNetwork
159
+ /** Custom RPC URL */
160
+ rpcUrl?: string
161
+ /** Auto-derive privacy keys on connect */
162
+ autoDerive?: boolean
163
+ }
164
+
165
+ /**
166
+ * Privacy key pair derived from wallet
167
+ */
168
+ export interface PrivacyKeyPair {
169
+ spendingPrivateKey: HexString
170
+ spendingPublicKey: HexString
171
+ viewingPrivateKey: HexString
172
+ viewingPublicKey: HexString
173
+ derivationLabel: string
174
+ }
175
+
176
+ /**
177
+ * Stealth address result with account ID
178
+ */
179
+ export interface StealthAddressResult {
180
+ stealthAddress: StealthAddress
181
+ stealthAccountId: string
182
+ ephemeralPublicKey: HexString
183
+ }
184
+
185
+ /**
186
+ * Private transfer parameters
187
+ */
188
+ export interface PrivateTransferParams {
189
+ /** Recipient's stealth meta-address (encoded or object) */
190
+ recipientMetaAddress: string | StealthMetaAddress
191
+ /** Amount in yoctoNEAR */
192
+ amount: string | bigint
193
+ /** Optional memo */
194
+ memo?: string
195
+ }
196
+
197
+ /**
198
+ * Private transfer result
199
+ */
200
+ export interface PrivateTransferResult {
201
+ /** Transaction hash */
202
+ txHash: string
203
+ /** Stealth address created */
204
+ stealthAddress: StealthAddress
205
+ /** Stealth account ID (implicit account) */
206
+ stealthAccountId: string
207
+ /** Announcement memo for recipient scanning */
208
+ announcementMemo: string
209
+ }
210
+
211
+ /**
212
+ * Wallet privacy capabilities
213
+ */
214
+ export interface WalletPrivacyCapabilities {
215
+ /** Wallet ID */
216
+ walletId: string
217
+ /** Wallet name */
218
+ walletName: string
219
+ /** Supports message signing (required for key derivation) */
220
+ supportsMessageSigning: boolean
221
+ /** Supports transaction signing */
222
+ supportsTransactionSigning: boolean
223
+ /** Supports batch transactions */
224
+ supportsBatchTransactions: boolean
225
+ /** Overall privacy support level */
226
+ privacySupport: 'full' | 'partial' | 'none'
227
+ }
228
+
229
+ /**
230
+ * Viewing key export
231
+ */
232
+ export interface ViewingKeyExport {
233
+ network: NEARNetwork
234
+ viewingPublicKey: HexString
235
+ viewingPrivateKey: HexString
236
+ spendingPublicKey: HexString
237
+ accountId: string
238
+ createdAt: number
239
+ label?: string
240
+ }
241
+
242
+ // ─── Privacy Wallet Selector ──────────────────────────────────────────────────
243
+
244
+ /**
245
+ * Privacy-enhanced Wallet Selector wrapper
246
+ *
247
+ * Wraps the standard NEAR Wallet Selector to add privacy capabilities.
248
+ */
249
+ export class PrivacyWalletSelector {
250
+ private selector: WalletSelector
251
+ private config: PrivacyWalletSelectorConfig
252
+ private privacyKeys: PrivacyKeyPair | null = null
253
+ private stealthAddresses: Map<string, StealthAddressResult> = new Map()
254
+ private connectionListeners: Set<(connected: boolean) => void> = new Set()
255
+
256
+ constructor(selector: WalletSelector, config: PrivacyWalletSelectorConfig) {
257
+ this.selector = selector
258
+ this.config = config
259
+
260
+ // Subscribe to wallet selector state changes
261
+ this.selector.store.observable.subscribe((state) => {
262
+ const isConnected = state.accounts.length > 0
263
+ this.connectionListeners.forEach((listener) => listener(isConnected))
264
+
265
+ // Clear privacy keys on disconnect
266
+ if (!isConnected) {
267
+ this.privacyKeys = null
268
+ this.stealthAddresses.clear()
269
+ }
270
+ })
271
+ }
272
+
273
+ // ─── Connection State ───────────────────────────────────────────────────────
274
+
275
+ /**
276
+ * Check if wallet is connected
277
+ */
278
+ isConnected(): boolean {
279
+ return this.selector.isSignedIn()
280
+ }
281
+
282
+ /**
283
+ * Get connected account ID
284
+ */
285
+ async getAccountId(): Promise<string | null> {
286
+ const accounts = await this.selector.getAccounts()
287
+ return accounts[0]?.accountId ?? null
288
+ }
289
+
290
+ /**
291
+ * Get connected wallet
292
+ */
293
+ async getWallet(): Promise<Wallet | null> {
294
+ return this.selector.wallet()
295
+ }
296
+
297
+ /**
298
+ * Subscribe to connection state changes
299
+ */
300
+ onConnectionChange(callback: (connected: boolean) => void): () => void {
301
+ this.connectionListeners.add(callback)
302
+ return () => this.connectionListeners.delete(callback)
303
+ }
304
+
305
+ // ─── Wallet Capabilities ────────────────────────────────────────────────────
306
+
307
+ /**
308
+ * Detect privacy capabilities of the current wallet
309
+ */
310
+ async detectCapabilities(): Promise<WalletPrivacyCapabilities | null> {
311
+ const wallet = await this.selector.wallet()
312
+ if (!wallet) return null
313
+
314
+ const supportsMessageSigning = typeof wallet.signMessage === 'function'
315
+ const supportsTransactionSigning = typeof wallet.signAndSendTransaction === 'function'
316
+ const supportsBatchTransactions = typeof wallet.signAndSendTransactions === 'function'
317
+
318
+ // Determine privacy support level
319
+ let privacySupport: 'full' | 'partial' | 'none' = 'none'
320
+ if (supportsMessageSigning && supportsTransactionSigning) {
321
+ privacySupport = supportsBatchTransactions ? 'full' : 'partial'
322
+ } else if (supportsTransactionSigning) {
323
+ privacySupport = 'partial'
324
+ }
325
+
326
+ return {
327
+ walletId: wallet.id,
328
+ walletName: wallet.metadata.name,
329
+ supportsMessageSigning,
330
+ supportsTransactionSigning,
331
+ supportsBatchTransactions,
332
+ privacySupport,
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Check if current wallet supports full privacy operations
338
+ */
339
+ async supportsPrivacy(): Promise<boolean> {
340
+ const capabilities = await this.detectCapabilities()
341
+ return capabilities?.privacySupport !== 'none'
342
+ }
343
+
344
+ // ─── Privacy Key Management ─────────────────────────────────────────────────
345
+
346
+ /**
347
+ * Derive privacy keys from wallet
348
+ *
349
+ * Uses message signing to deterministically derive privacy keys
350
+ * without exposing the wallet's seed phrase.
351
+ */
352
+ async derivePrivacyKeys(label: string = 'default'): Promise<PrivacyKeyPair> {
353
+ const wallet = await this.selector.wallet()
354
+ if (!wallet) {
355
+ throw new Error('No wallet connected')
356
+ }
357
+
358
+ if (!wallet.signMessage) {
359
+ throw new Error('Wallet does not support message signing for key derivation')
360
+ }
361
+
362
+ const accountId = await this.getAccountId()
363
+ if (!accountId) {
364
+ throw new Error('No account connected')
365
+ }
366
+
367
+ // Create derivation message
368
+ const derivationPath = `sip/near/${this.config.network}/${label}`
369
+ const nonce = Buffer.from(sha256(new TextEncoder().encode(derivationPath)).slice(0, 32))
370
+
371
+ // Sign the derivation message
372
+ const signed = await wallet.signMessage({
373
+ message: `SIP Privacy Key Derivation: ${derivationPath}`,
374
+ recipient: accountId,
375
+ nonce,
376
+ })
377
+
378
+ // Derive keys from signature
379
+ const entropy = hexToBytes(signed.signature.replace(/^0x/, '').slice(0, 128))
380
+
381
+ // Derive spending key
382
+ const spendingEntropy = sha256(new Uint8Array([...entropy.slice(0, 32), 0x01]))
383
+ const spendingPrivateKey = clampScalar(spendingEntropy)
384
+ const spendingPublicKey = ed25519.getPublicKey(spendingPrivateKey)
385
+
386
+ // Derive viewing key
387
+ const viewingEntropy = sha256(new Uint8Array([...entropy.slice(32, 64), 0x02]))
388
+ const viewingPrivateKey = clampScalar(viewingEntropy)
389
+ const viewingPublicKey = ed25519.getPublicKey(viewingPrivateKey)
390
+
391
+ const keyPair: PrivacyKeyPair = {
392
+ spendingPrivateKey: `0x${bytesToHex(spendingPrivateKey)}` as HexString,
393
+ spendingPublicKey: `0x${bytesToHex(spendingPublicKey)}` as HexString,
394
+ viewingPrivateKey: `0x${bytesToHex(viewingPrivateKey)}` as HexString,
395
+ viewingPublicKey: `0x${bytesToHex(viewingPublicKey)}` as HexString,
396
+ derivationLabel: label,
397
+ }
398
+
399
+ this.privacyKeys = keyPair
400
+ return keyPair
401
+ }
402
+
403
+ /**
404
+ * Check if privacy keys are derived
405
+ */
406
+ hasPrivacyKeys(): boolean {
407
+ return this.privacyKeys !== null
408
+ }
409
+
410
+ /**
411
+ * Get derived privacy keys
412
+ */
413
+ getPrivacyKeys(): PrivacyKeyPair | null {
414
+ return this.privacyKeys
415
+ }
416
+
417
+ // ─── Stealth Address Operations ─────────────────────────────────────────────
418
+
419
+ /**
420
+ * Generate a stealth meta-address for receiving private payments
421
+ */
422
+ async generateStealthMetaAddress(label?: string): Promise<{
423
+ metaAddress: StealthMetaAddress
424
+ encoded: string
425
+ viewingPrivateKey: HexString
426
+ spendingPrivateKey: HexString
427
+ }> {
428
+ const keys = this.privacyKeys ?? await this.derivePrivacyKeys(label)
429
+
430
+ const metaAddress: StealthMetaAddress = {
431
+ chain: 'near',
432
+ spendingKey: keys.spendingPublicKey,
433
+ viewingKey: keys.viewingPublicKey,
434
+ }
435
+
436
+ const encoded = encodeNEARStealthMetaAddress(metaAddress)
437
+
438
+ return {
439
+ metaAddress,
440
+ encoded,
441
+ viewingPrivateKey: keys.viewingPrivateKey,
442
+ spendingPrivateKey: keys.spendingPrivateKey,
443
+ }
444
+ }
445
+
446
+ /**
447
+ * Generate a one-time stealth address from a meta-address
448
+ */
449
+ generateStealthAddress(metaAddress: string | StealthMetaAddress): StealthAddressResult {
450
+ const meta = typeof metaAddress === 'string'
451
+ ? parseNEARStealthMetaAddress(metaAddress)
452
+ : metaAddress
453
+
454
+ const { stealthAddress, implicitAccountId } = generateNEARStealthAddress(meta)
455
+
456
+ const result: StealthAddressResult = {
457
+ stealthAddress,
458
+ stealthAccountId: implicitAccountId,
459
+ ephemeralPublicKey: stealthAddress.ephemeralPublicKey,
460
+ }
461
+
462
+ this.stealthAddresses.set(implicitAccountId, result)
463
+ return result
464
+ }
465
+
466
+ /**
467
+ * Check if a stealth address belongs to this wallet
468
+ */
469
+ async checkStealthAddress(stealthAddress: StealthAddress): Promise<boolean> {
470
+ const keys = this.privacyKeys ?? await this.derivePrivacyKeys()
471
+
472
+ return checkNEARStealthAddress(
473
+ stealthAddress,
474
+ keys.spendingPublicKey,
475
+ keys.viewingPrivateKey
476
+ )
477
+ }
478
+
479
+ /**
480
+ * Derive private key for a stealth address
481
+ */
482
+ async deriveStealthPrivateKey(stealthAddress: StealthAddress): Promise<HexString> {
483
+ const keys = this.privacyKeys ?? await this.derivePrivacyKeys()
484
+
485
+ const isOwner = await this.checkStealthAddress(stealthAddress)
486
+ if (!isOwner) {
487
+ throw new Error('Stealth address does not belong to this wallet')
488
+ }
489
+
490
+ const recovery = deriveNEARStealthPrivateKey(
491
+ stealthAddress,
492
+ keys.spendingPrivateKey,
493
+ keys.viewingPrivateKey
494
+ )
495
+
496
+ return recovery.privateKey
497
+ }
498
+
499
+ // ─── Private Transfers ──────────────────────────────────────────────────────
500
+
501
+ /**
502
+ * Send a private NEAR transfer
503
+ */
504
+ async sendPrivateTransfer(params: PrivateTransferParams): Promise<PrivateTransferResult> {
505
+ const wallet = await this.selector.wallet()
506
+ if (!wallet) {
507
+ throw new Error('No wallet connected')
508
+ }
509
+
510
+ const accountId = await this.getAccountId()
511
+ if (!accountId) {
512
+ throw new Error('No account connected')
513
+ }
514
+
515
+ // Parse recipient meta-address
516
+ const recipientMeta = typeof params.recipientMetaAddress === 'string'
517
+ ? parseNEARStealthMetaAddress(params.recipientMetaAddress)
518
+ : params.recipientMetaAddress
519
+
520
+ // Build the transfer (generates stealth address internally)
521
+ const amount = typeof params.amount === 'string' ? BigInt(params.amount) : params.amount
522
+ const transfer = buildPrivateTransfer(recipientMeta, amount)
523
+
524
+ // Get stealth address info from the transfer result
525
+ const { stealthAddress, stealthAccountId: implicitAccountId, announcementMemo } = transfer
526
+
527
+ // Convert actions to wallet selector format
528
+ const walletActions: WalletAction[] = transfer.actions.map((action) => ({
529
+ type: action.type,
530
+ params: action.params as unknown as Record<string, unknown>,
531
+ }))
532
+
533
+ // Send transaction
534
+ const result = await wallet.signAndSendTransaction({
535
+ signerId: accountId,
536
+ receiverId: implicitAccountId,
537
+ actions: walletActions,
538
+ })
539
+
540
+ return {
541
+ txHash: result.transaction.hash,
542
+ stealthAddress,
543
+ stealthAccountId: implicitAccountId,
544
+ announcementMemo,
545
+ }
546
+ }
547
+
548
+ /**
549
+ * Send multiple private transfers in a batch
550
+ */
551
+ async sendBatchPrivateTransfers(
552
+ transfers: PrivateTransferParams[]
553
+ ): Promise<PrivateTransferResult[]> {
554
+ const wallet = await this.selector.wallet()
555
+ if (!wallet) {
556
+ throw new Error('No wallet connected')
557
+ }
558
+
559
+ if (!wallet.signAndSendTransactions) {
560
+ throw new Error('Wallet does not support batch transactions')
561
+ }
562
+
563
+ const accountId = await this.getAccountId()
564
+ if (!accountId) {
565
+ throw new Error('No account connected')
566
+ }
567
+
568
+ // Build all transfers
569
+ const transactions: SignAndSendTransactionParams[] = []
570
+ const transferResults: Array<{
571
+ stealthAddress: StealthAddress
572
+ stealthAccountId: string
573
+ announcementMemo: string
574
+ }> = []
575
+
576
+ for (const params of transfers) {
577
+ const recipientMeta = typeof params.recipientMetaAddress === 'string'
578
+ ? parseNEARStealthMetaAddress(params.recipientMetaAddress)
579
+ : params.recipientMetaAddress
580
+
581
+ const amount = typeof params.amount === 'string' ? BigInt(params.amount) : params.amount
582
+ const transfer = buildPrivateTransfer(recipientMeta, amount)
583
+
584
+ const { stealthAddress, stealthAccountId, announcementMemo } = transfer
585
+
586
+ const walletActions: WalletAction[] = transfer.actions.map((action) => ({
587
+ type: action.type,
588
+ params: action.params as unknown as Record<string, unknown>,
589
+ }))
590
+
591
+ transactions.push({
592
+ signerId: accountId,
593
+ receiverId: stealthAccountId,
594
+ actions: walletActions,
595
+ })
596
+
597
+ transferResults.push({
598
+ stealthAddress,
599
+ stealthAccountId,
600
+ announcementMemo,
601
+ })
602
+ }
603
+
604
+ // Send batch
605
+ const results = await wallet.signAndSendTransactions({ transactions })
606
+
607
+ return results.map((result, index) => ({
608
+ txHash: result.transaction.hash,
609
+ ...transferResults[index],
610
+ }))
611
+ }
612
+
613
+ // ─── Viewing Key Export ─────────────────────────────────────────────────────
614
+
615
+ /**
616
+ * Export viewing key for compliance/audit sharing
617
+ */
618
+ async exportViewingKey(label?: string): Promise<ViewingKeyExport> {
619
+ const keys = this.privacyKeys ?? await this.derivePrivacyKeys(label)
620
+ const accountId = await this.getAccountId()
621
+
622
+ if (!accountId) {
623
+ throw new Error('No account connected')
624
+ }
625
+
626
+ return {
627
+ network: this.config.network,
628
+ viewingPublicKey: keys.viewingPublicKey,
629
+ viewingPrivateKey: keys.viewingPrivateKey,
630
+ spendingPublicKey: keys.spendingPublicKey,
631
+ accountId,
632
+ createdAt: Date.now(),
633
+ label,
634
+ }
635
+ }
636
+
637
+ // ─── Utility Methods ────────────────────────────────────────────────────────
638
+
639
+ /**
640
+ * Get all tracked stealth addresses
641
+ */
642
+ getStealthAddresses(): Map<string, StealthAddressResult> {
643
+ return new Map(this.stealthAddresses)
644
+ }
645
+
646
+ /**
647
+ * Get the underlying wallet selector
648
+ */
649
+ getSelector(): WalletSelector {
650
+ return this.selector
651
+ }
652
+
653
+ /**
654
+ * Get configuration
655
+ */
656
+ getConfig(): PrivacyWalletSelectorConfig {
657
+ return { ...this.config }
658
+ }
659
+ }
660
+
661
+ // ─── Factory Functions ────────────────────────────────────────────────────────
662
+
663
+ /**
664
+ * Create a privacy-enhanced wallet selector wrapper
665
+ */
666
+ export function createPrivacyWalletSelector(
667
+ selector: WalletSelector,
668
+ config: PrivacyWalletSelectorConfig
669
+ ): PrivacyWalletSelector {
670
+ return new PrivacyWalletSelector(selector, config)
671
+ }
672
+
673
+ /**
674
+ * Create privacy wallet selector for mainnet
675
+ */
676
+ export function createMainnetPrivacySelector(
677
+ selector: WalletSelector
678
+ ): PrivacyWalletSelector {
679
+ return new PrivacyWalletSelector(selector, { network: 'mainnet' })
680
+ }
681
+
682
+ /**
683
+ * Create privacy wallet selector for testnet
684
+ */
685
+ export function createTestnetPrivacySelector(
686
+ selector: WalletSelector
687
+ ): PrivacyWalletSelector {
688
+ return new PrivacyWalletSelector(selector, { network: 'testnet' })
689
+ }
690
+
691
+ // ─── Utility Functions ────────────────────────────────────────────────────────
692
+
693
+ /**
694
+ * Clamp a 32-byte scalar for ed25519
695
+ */
696
+ function clampScalar(bytes: Uint8Array): Uint8Array {
697
+ const clamped = new Uint8Array(bytes)
698
+ clamped[0] &= 248
699
+ clamped[31] &= 127
700
+ clamped[31] |= 64
701
+ return clamped
702
+ }