@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 +21 -0
- package/README.md +124 -0
- package/dist/index.d.mts +404 -0
- package/dist/index.d.ts +404 -0
- package/dist/index.js +389 -0
- package/dist/index.mjs +358 -0
- package/package.json +64 -0
- package/src/hooks/index.ts +10 -0
- package/src/hooks/use-private-swap.ts +268 -0
- package/src/hooks/use-sip.ts +188 -0
- package/src/hooks/use-stealth-address.ts +184 -0
- package/src/hooks/use-viewing-key.ts +190 -0
- package/src/index.ts +10 -0
- package/src/providers/sip-provider.tsx +50 -0
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
|
package/dist/index.d.mts
ADDED
|
@@ -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 };
|