@sip-protocol/react 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 RECTOR Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # @sip-protocol/react
2
+
3
+ React hooks for [Shielded Intents Protocol](https://sip-protocol.org).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @sip-protocol/react @sip-protocol/sdk
9
+ # or
10
+ pnpm add @sip-protocol/react @sip-protocol/sdk
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ Wrap your app with `SIPProvider`:
16
+
17
+ ```tsx
18
+ import { SIPProvider } from '@sip-protocol/react'
19
+
20
+ function App() {
21
+ return (
22
+ <SIPProvider config={{ network: 'testnet' }}>
23
+ <YourApp />
24
+ </SIPProvider>
25
+ )
26
+ }
27
+ ```
28
+
29
+ Use hooks in your components:
30
+
31
+ ```tsx
32
+ import { useSIP } from '@sip-protocol/react'
33
+
34
+ function MyComponent() {
35
+ const sip = useSIP()
36
+
37
+ const handleCreateIntent = async () => {
38
+ const intent = await sip.createShieldedIntent({
39
+ from: { chain: 'ethereum', token: 'ETH', amount: '1.0' },
40
+ to: { chain: 'solana', token: 'SOL' },
41
+ privacyLevel: 'shielded'
42
+ })
43
+ }
44
+
45
+ return <button onClick={handleCreateIntent}>Create Private Swap</button>
46
+ }
47
+ ```
48
+
49
+ ## Available Hooks
50
+
51
+ ### `useSIP()`
52
+
53
+ Access the SIP client instance directly.
54
+
55
+ ```tsx
56
+ const sip = useSIP()
57
+ ```
58
+
59
+ ### `useStealthAddress()` (stub)
60
+
61
+ Generate and manage stealth addresses. Full implementation coming soon.
62
+
63
+ ```tsx
64
+ const { generate, parse, isValid } = useStealthAddress()
65
+ ```
66
+
67
+ ### `usePrivateSwap()` (stub)
68
+
69
+ Execute private swaps with shielded intents. Full implementation coming soon.
70
+
71
+ ```tsx
72
+ const { execute, status, error } = usePrivateSwap()
73
+ ```
74
+
75
+ ### `useViewingKey()` (stub)
76
+
77
+ Generate and manage viewing keys for compliance. Full implementation coming soon.
78
+
79
+ ```tsx
80
+ const { generate, decrypt, share } = useViewingKey()
81
+ ```
82
+
83
+ ## Configuration
84
+
85
+ The `SIPProvider` accepts the same configuration as the core SDK:
86
+
87
+ ```tsx
88
+ <SIPProvider
89
+ config={{
90
+ network: 'mainnet',
91
+ mode: 'production',
92
+ defaultPrivacy: PrivacyLevel.SHIELDED,
93
+ proofProvider: new MockProofProvider(),
94
+ intentsAdapter: {
95
+ jwtToken: process.env.NEAR_INTENTS_JWT
96
+ }
97
+ }}
98
+ >
99
+ <App />
100
+ </SIPProvider>
101
+ ```
102
+
103
+ See [@sip-protocol/sdk](https://github.com/sip-protocol/sip-protocol/tree/main/packages/sdk) for full configuration options.
104
+
105
+ ## Development Status
106
+
107
+ This package is under active development:
108
+
109
+ - [x] Provider setup
110
+ - [x] `useSIP()` hook
111
+ - [ ] `useStealthAddress()` implementation
112
+ - [ ] `usePrivateSwap()` implementation
113
+ - [ ] `useViewingKey()` implementation
114
+ - [ ] Additional utility hooks
115
+
116
+ ## Documentation
117
+
118
+ - [Full Documentation](https://docs.sip-protocol.org)
119
+ - [SDK Reference](https://docs.sip-protocol.org/sdk)
120
+ - [Examples](https://github.com/sip-protocol/sip-protocol/tree/main/examples)
121
+
122
+ ## License
123
+
124
+ MIT
@@ -0,0 +1,404 @@
1
+ import React, { ReactNode } from 'react';
2
+ import * as _sip_protocol_sdk from '@sip-protocol/sdk';
3
+ import { SIPConfig, SIP } from '@sip-protocol/sdk';
4
+ import { ChainId, Quote, PrivacyLevel, ViewingKey, EncryptedTransaction } from '@sip-protocol/types';
5
+
6
+ interface SIPProviderProps {
7
+ config: SIPConfig;
8
+ children: ReactNode;
9
+ }
10
+ /**
11
+ * SIPProvider wraps your app and provides SIP client instance via context
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * import { SIPProvider } from '@sip-protocol/react'
16
+ *
17
+ * function App() {
18
+ * return (
19
+ * <SIPProvider config={{ nearIntents: { apiUrl: '...' } }}>
20
+ * <YourApp />
21
+ * </SIPProvider>
22
+ * )
23
+ * }
24
+ * ```
25
+ */
26
+ declare function SIPProvider({ config, children }: SIPProviderProps): React.JSX.Element;
27
+
28
+ /**
29
+ * Return type for useSIP hook
30
+ */
31
+ interface UseSIPReturn {
32
+ /** SIP client instance (null if not initialized or no provider) */
33
+ client: SIP | null;
34
+ /** Whether the client is ready to use */
35
+ isReady: boolean;
36
+ /** Error during initialization (if any) */
37
+ error: Error | null;
38
+ /** Manually initialize the SIP client (only for standalone usage) */
39
+ initialize: (config: SIPConfig) => Promise<void>;
40
+ }
41
+ /**
42
+ * useSIP - Main hook for accessing SIP client
43
+ *
44
+ * Provides access to the SIP client instance from SIPProvider, along with
45
+ * initialization state and error handling. Can also be used standalone without
46
+ * a provider by calling `initialize()`.
47
+ *
48
+ * **Usage with SIPProvider (recommended):**
49
+ * ```tsx
50
+ * import { SIPProvider, useSIP } from '@sip-protocol/react'
51
+ *
52
+ * function App() {
53
+ * return (
54
+ * <SIPProvider config={{ network: 'testnet' }}>
55
+ * <MyComponent />
56
+ * </SIPProvider>
57
+ * )
58
+ * }
59
+ *
60
+ * function MyComponent() {
61
+ * const { client, isReady } = useSIP()
62
+ *
63
+ * if (!isReady || !client) {
64
+ * return <div>Loading...</div>
65
+ * }
66
+ *
67
+ * // Use client.createIntent(), client.getQuotes(), etc.
68
+ * }
69
+ * ```
70
+ *
71
+ * **Standalone usage (without provider):**
72
+ * ```tsx
73
+ * function MyComponent() {
74
+ * const { client, isReady, initialize, error } = useSIP()
75
+ *
76
+ * useEffect(() => {
77
+ * initialize({ network: 'testnet' }).catch(console.error)
78
+ * }, [])
79
+ *
80
+ * if (error) {
81
+ * return <div>Error: {error.message}</div>
82
+ * }
83
+ *
84
+ * if (!isReady || !client) {
85
+ * return <div>Initializing...</div>
86
+ * }
87
+ *
88
+ * return <div>Ready!</div>
89
+ * }
90
+ * ```
91
+ *
92
+ * @returns Object with client, isReady, error, and initialize function
93
+ *
94
+ * @example Basic usage with provider
95
+ * ```tsx
96
+ * import { useSIP } from '@sip-protocol/react'
97
+ *
98
+ * function MyComponent() {
99
+ * const { client, isReady } = useSIP()
100
+ *
101
+ * if (!isReady || !client) {
102
+ * return <div>Loading...</div>
103
+ * }
104
+ *
105
+ * // Use client methods
106
+ * const handleCreateIntent = async () => {
107
+ * const intent = await client.createIntent({ ... })
108
+ * }
109
+ * }
110
+ * ```
111
+ *
112
+ * @example With error handling
113
+ * ```tsx
114
+ * function MyComponent() {
115
+ * const { client, isReady, error } = useSIP()
116
+ *
117
+ * if (error) {
118
+ * return <div>Failed to initialize: {error.message}</div>
119
+ * }
120
+ *
121
+ * if (!isReady || !client) {
122
+ * return <div>Initializing SIP client...</div>
123
+ * }
124
+ *
125
+ * return <div>Ready to use SIP!</div>
126
+ * }
127
+ * ```
128
+ *
129
+ * @example Standalone initialization
130
+ * ```tsx
131
+ * function MyComponent() {
132
+ * const { client, isReady, initialize } = useSIP()
133
+ *
134
+ * const handleInit = async () => {
135
+ * try {
136
+ * await initialize({
137
+ * network: 'mainnet',
138
+ * mode: 'production',
139
+ * intentsAdapter: { jwtToken: 'xxx' }
140
+ * })
141
+ * } catch (err) {
142
+ * console.error('Init failed:', err)
143
+ * }
144
+ * }
145
+ *
146
+ * return (
147
+ * <button onClick={handleInit} disabled={isReady}>
148
+ * {isReady ? 'Initialized' : 'Initialize SIP'}
149
+ * </button>
150
+ * )
151
+ * }
152
+ * ```
153
+ */
154
+ declare function useSIP(): UseSIPReturn;
155
+
156
+ /**
157
+ * useStealthAddress - Generate and manage stealth addresses
158
+ *
159
+ * @remarks
160
+ * This hook handles stealth address generation for privacy-preserving transactions.
161
+ * It automatically generates a meta-address on mount and allows regeneration of
162
+ * one-time stealth addresses from that meta-address.
163
+ *
164
+ * Features:
165
+ * - Auto-generates meta-address for the specified chain
166
+ * - Generates one-time stealth addresses
167
+ * - Supports both secp256k1 (EVM) and ed25519 (Solana/NEAR) chains
168
+ * - Copy-to-clipboard functionality
169
+ * - Loading state management
170
+ *
171
+ * @param chain - Target blockchain (determines curve type and address format)
172
+ *
173
+ * @example
174
+ * ```tsx
175
+ * import { useStealthAddress } from '@sip-protocol/react'
176
+ *
177
+ * function ReceivePayment() {
178
+ * const {
179
+ * metaAddress,
180
+ * stealthAddress,
181
+ * isGenerating,
182
+ * regenerate,
183
+ * copyToClipboard,
184
+ * } = useStealthAddress('ethereum')
185
+ *
186
+ * return (
187
+ * <div>
188
+ * <p>Share this: {metaAddress}</p>
189
+ * <p>One-time address: {stealthAddress}</p>
190
+ * <button onClick={regenerate}>Generate New</button>
191
+ * <button onClick={copyToClipboard}>Copy</button>
192
+ * </div>
193
+ * )
194
+ * }
195
+ * ```
196
+ */
197
+ declare function useStealthAddress(chain: ChainId): {
198
+ metaAddress: string | null;
199
+ stealthAddress: string | null;
200
+ isGenerating: boolean;
201
+ regenerate: () => void;
202
+ copyToClipboard: () => Promise<void>;
203
+ };
204
+
205
+ /**
206
+ * Status of the swap lifecycle
207
+ */
208
+ type SwapStatus = 'idle' | 'fetching_quote' | 'pending' | 'confirming' | 'completed' | 'failed';
209
+ /**
210
+ * Parameters for fetching a quote
211
+ */
212
+ interface QuoteParams {
213
+ /** Input chain */
214
+ inputChain: string;
215
+ /** Output chain */
216
+ outputChain: string;
217
+ /** Input token symbol */
218
+ inputToken: string;
219
+ /** Output token symbol */
220
+ outputToken: string;
221
+ /** Input amount (as string, in smallest unit) */
222
+ inputAmount: string;
223
+ /** Privacy level (optional) */
224
+ privacyLevel?: PrivacyLevel;
225
+ /** Maximum acceptable slippage (0-1, e.g. 0.01 = 1%) */
226
+ maxSlippage?: number;
227
+ }
228
+ /**
229
+ * Parameters for executing a swap
230
+ */
231
+ interface SwapParams {
232
+ /** Input asset details */
233
+ input: {
234
+ chain: string;
235
+ token: string;
236
+ amount: bigint;
237
+ };
238
+ /** Output asset details */
239
+ output: {
240
+ chain: string;
241
+ token: string;
242
+ minAmount: bigint;
243
+ };
244
+ /** Privacy level */
245
+ privacyLevel: PrivacyLevel;
246
+ /** Maximum acceptable slippage (0-1, e.g. 0.01 = 1%) */
247
+ maxSlippage?: number;
248
+ }
249
+ /**
250
+ * Result of a swap execution
251
+ */
252
+ interface SwapResult {
253
+ /** Transaction hash (if available) */
254
+ txHash?: string;
255
+ /** Status of the swap */
256
+ status: string;
257
+ /** Output amount received */
258
+ outputAmount?: bigint;
259
+ /** Intent ID */
260
+ intentId: string;
261
+ }
262
+ /**
263
+ * usePrivateSwap - Execute private swaps with shielded intents
264
+ *
265
+ * @remarks
266
+ * Hook for managing the complete lifecycle of a private swap:
267
+ * - Fetch quotes from solvers
268
+ * - Execute swaps with privacy
269
+ * - Track swap status through completion
270
+ * - Handle errors gracefully
271
+ *
272
+ * @example
273
+ * ```tsx
274
+ * import { usePrivateSwap } from '@sip-protocol/react'
275
+ * import { PrivacyLevel } from '@sip-protocol/types'
276
+ *
277
+ * function MyComponent() {
278
+ * const { quote, fetchQuote, swap, status, isLoading, error, reset } = usePrivateSwap()
279
+ *
280
+ * // Fetch a quote
281
+ * const handleGetQuote = async () => {
282
+ * await fetchQuote({
283
+ * inputChain: 'solana',
284
+ * outputChain: 'ethereum',
285
+ * inputToken: 'SOL',
286
+ * outputToken: 'ETH',
287
+ * inputAmount: '1000000000', // 1 SOL
288
+ * })
289
+ * }
290
+ *
291
+ * // Execute the swap
292
+ * const handleSwap = async () => {
293
+ * const result = await swap({
294
+ * input: { chain: 'solana', token: 'SOL', amount: 1000000000n },
295
+ * output: { chain: 'ethereum', token: 'ETH', minAmount: 0n },
296
+ * privacyLevel: PrivacyLevel.SHIELDED,
297
+ * maxSlippage: 0.01,
298
+ * })
299
+ * }
300
+ * }
301
+ * ```
302
+ */
303
+ declare function usePrivateSwap(): {
304
+ quote: Quote | null;
305
+ fetchQuote: (params: QuoteParams) => Promise<void>;
306
+ swap: (params: SwapParams) => Promise<SwapResult>;
307
+ status: SwapStatus;
308
+ isLoading: boolean;
309
+ error: Error | null;
310
+ reset: () => void;
311
+ };
312
+
313
+ /**
314
+ * Auditor share entry
315
+ */
316
+ interface AuditorShare {
317
+ auditorId: string;
318
+ viewingKeyHash: string;
319
+ sharedAt: number;
320
+ }
321
+ /**
322
+ * useViewingKey - Generate and manage viewing keys for compliance
323
+ *
324
+ * @remarks
325
+ * Hook for managing viewing keys that enable selective disclosure of transaction
326
+ * details to auditors or regulators while maintaining on-chain privacy.
327
+ *
328
+ * Features:
329
+ * - Generate cryptographically random viewing keys
330
+ * - Decrypt encrypted transaction data
331
+ * - Share viewing keys with auditors (tracked in state)
332
+ * - Hierarchical key derivation via path parameter
333
+ *
334
+ * @example Basic usage
335
+ * ```tsx
336
+ * import { useViewingKey } from '@sip-protocol/react'
337
+ *
338
+ * function CompliancePanel() {
339
+ * const { viewingKey, generate, decrypt, share } = useViewingKey()
340
+ *
341
+ * const handleGenerateKey = () => {
342
+ * const key = generate('m/0/audit')
343
+ * console.log('Generated viewing key:', key.hash)
344
+ * }
345
+ *
346
+ * const handleDecrypt = async (encrypted: EncryptedTransaction) => {
347
+ * try {
348
+ * const data = await decrypt(encrypted)
349
+ * console.log('Decrypted amount:', data.amount)
350
+ * } catch (e) {
351
+ * console.error('Decryption failed - wrong key')
352
+ * }
353
+ * }
354
+ *
355
+ * return (
356
+ * <div>
357
+ * <button onClick={handleGenerateKey}>Generate Key</button>
358
+ * {viewingKey && <p>Key hash: {viewingKey.hash}</p>}
359
+ * </div>
360
+ * )
361
+ * }
362
+ * ```
363
+ *
364
+ * @example Sharing with auditors
365
+ * ```tsx
366
+ * function AuditManager() {
367
+ * const { viewingKey, generate, share, sharedWith } = useViewingKey()
368
+ *
369
+ * useEffect(() => {
370
+ * generate('m/0/compliance')
371
+ * }, [])
372
+ *
373
+ * const handleShareWithAuditor = async () => {
374
+ * await share('auditor-123')
375
+ * console.log('Shared with:', sharedWith)
376
+ * }
377
+ *
378
+ * return (
379
+ * <div>
380
+ * <button onClick={handleShareWithAuditor}>Share with Auditor</button>
381
+ * <ul>
382
+ * {sharedWith.map(audit => (
383
+ * <li key={audit.auditorId}>{audit.auditorId}</li>
384
+ * ))}
385
+ * </ul>
386
+ * </div>
387
+ * )
388
+ * }
389
+ * ```
390
+ */
391
+ declare function useViewingKey(): {
392
+ /** Current viewing key (null if not generated) */
393
+ viewingKey: ViewingKey | null;
394
+ /** List of auditors who have been given access */
395
+ sharedWith: AuditorShare[];
396
+ /** Generate a new viewing key */
397
+ generate: (path?: string) => ViewingKey;
398
+ /** Decrypt encrypted transaction data */
399
+ decrypt: (encrypted: EncryptedTransaction) => Promise<_sip_protocol_sdk.TransactionData>;
400
+ /** Share viewing key with an auditor */
401
+ share: (auditorId: string) => Promise<void>;
402
+ };
403
+
404
+ export { SIPProvider, type SIPProviderProps, usePrivateSwap, useSIP, useStealthAddress, useViewingKey };