@obelyzk/sdk 1.0.0 → 1.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/README.md CHANGED
@@ -1,478 +1,502 @@
1
- # @bitsage/sdk
1
+ # @obelyzk/sdk
2
2
 
3
- Official TypeScript SDK for the BitSage Network - Decentralized Compute with Privacy.
3
+ Official TypeScript SDK for the **Obelysk Protocol** -- privacy-first DeFi on Starknet.
4
+
5
+ All cryptography runs client-side. The SDK provides ~150 methods across 10 protocol sub-clients, covering privacy pools, dark pool auctions, stealth payments, confidential transfers, shielded swaps, UTXO vaults, OTC trading, and staking.
4
6
 
5
7
  ## Installation
6
8
 
7
9
  ```bash
8
- npm install @bitsage/sdk
9
- # or
10
- yarn add @bitsage/sdk
11
- # or
12
- pnpm add @bitsage/sdk
10
+ npm install @obelyzk/sdk starknet
13
11
  ```
14
12
 
15
- ## Features
13
+ `starknet` (v6+) is a required peer dependency. For React hooks, also ensure `react >= 18`.
14
+
15
+ ## Entry Points
16
16
 
17
- - **Obelysk Privacy Layer** - Client-side ElGamal encryption and Schnorr proofs for private payments
18
- - **STWO GPU Prover** - GPU-accelerated proof generation for batch operations
19
- - **Confidential Swaps** - Trade tokens privately with encrypted amounts
20
- - **Staking & Workers** - Manage stake and worker nodes
21
- - **React Hooks** - Ready-to-use hooks for React applications
17
+ | Import path | Description |
18
+ |---|---|
19
+ | `@obelyzk/sdk` | Main SDK (distributed compute, STWO prover, ZKML) |
20
+ | `@obelyzk/sdk/obelysk` | Obelysk Protocol client (privacy DeFi -- this document) |
21
+ | `@obelyzk/sdk/privacy` | ElGamal primitives, EC math, Schnorr proofs |
22
+ | `@obelyzk/sdk/react` | React hooks for wallet, privacy, and prover state |
22
23
 
23
24
  ---
24
25
 
25
- ## Quick Start
26
+ ## Quick Start (Read-Only)
26
27
 
27
- ### Basic Setup
28
+ No wallet or account needed for read-only queries:
28
29
 
29
30
  ```typescript
30
- import { BitSageClient } from '@bitsage/sdk';
31
+ import { ObelyskClient } from '@obelyzk/sdk/obelysk';
31
32
 
32
- const client = new BitSageClient({
33
- network: 'sepolia', // or 'mainnet'
34
- apiKey: 'your-api-key',
33
+ const obelysk = new ObelyskClient({
34
+ network: 'mainnet',
35
+ rpcUrl: 'https://your-rpc.com',
35
36
  });
36
37
 
37
- // Submit a compute job
38
- const job = await client.submitJob({
39
- job_type: { type: 'ai_inference', model_type: 'llama-7b', batch_size: 1 },
40
- input_data: btoa('Hello, BitSage!'),
41
- max_cost_sage: 100n,
42
- priority: 5,
43
- });
38
+ // Query DarkPool epoch
39
+ const epoch = await obelysk.darkPool.getEpochInfo();
40
+ console.log('Epoch:', epoch.epoch, 'Phase:', epoch.phase);
44
41
 
45
- console.log('Job ID:', job.job_id);
46
- ```
42
+ // Query privacy pool stats
43
+ const root = await obelysk.privacyPool.getMerkleRoot('eth');
44
+ console.log('ETH pool Merkle root:', root);
47
45
 
48
- ---
46
+ // Query staking
47
+ const totalStaked = await obelysk.staking.getTotalStaked();
48
+ console.log('Total SAGE staked:', totalStaked);
49
49
 
50
- ## Obelysk Privacy Layer
50
+ // Query OTC orderbook depth
51
+ const depth = await obelysk.otc.getOrderbookDepth(0);
52
+ console.log('Bids:', depth.bids.length, 'Asks:', depth.asks.length);
53
+ ```
51
54
 
52
- The Obelysk Privacy Layer enables fully private on-chain payments using ElGamal encryption and Schnorr zero-knowledge proofs. **All cryptography runs client-side** - no server ever sees your amounts.
55
+ ---
53
56
 
54
- ### Private Payments
57
+ ## ObelyskClient Configuration
55
58
 
56
59
  ```typescript
57
- import { ObelyskPrivacy, ConfidentialSwapClient } from '@bitsage/sdk';
60
+ import { ObelyskClient } from '@obelyzk/sdk/obelysk';
61
+ import { Account, RpcProvider } from 'starknet';
58
62
 
59
- // Initialize privacy module
60
- const privacy = new ObelyskPrivacy();
61
-
62
- // Generate your key pair (store securely!)
63
- const keyPair = privacy.generateKeyPair();
64
- console.log('Public Key:', keyPair.publicKey);
63
+ const provider = new RpcProvider({ nodeUrl: 'https://your-rpc.com' });
64
+ const account = new Account(provider, '0xADDRESS', '0xPRIVATE_KEY');
65
65
 
66
- // Encrypt an amount (only you and recipient can see it)
67
- const amount = 1000n; // 1000 SAGE
68
- const encrypted = privacy.encrypt(amount, recipientPublicKey);
69
- console.log('Encrypted:', encrypted.c1, encrypted.c2);
66
+ const obelysk = new ObelyskClient({
67
+ // Required
68
+ network: 'mainnet', // 'mainnet' | 'sepolia'
70
69
 
71
- // Create a proof that amount is valid (without revealing it)
72
- const proof = privacy.createEncryptionProof(amount, keyPair, encrypted);
70
+ // Recommended
71
+ rpcUrl: 'https://your-rpc.com', // default public RPCs have rate limits
73
72
 
74
- // Verify proof (anyone can do this)
75
- const isValid = privacy.verifyEncryptionProof(proof, keyPair.publicKey, encrypted);
76
- console.log('Proof valid:', isValid); // true
77
- ```
78
-
79
- ### Confidential Swaps
73
+ // Required for write operations
74
+ account, // starknet.js Account
80
75
 
81
- ```typescript
82
- import { ConfidentialSwapClient } from '@bitsage/sdk';
76
+ // Optional: VM31 relayer (for UTXO vault operations)
77
+ relayerUrl: 'https://relay.bitsage.network:3080',
78
+ relayerApiKey: 'your-api-key',
83
79
 
84
- const swapClient = new ConfidentialSwapClient({
85
- contractAddress: '0x...',
86
- proverUrl: 'https://prover.bitsage.network',
80
+ // Optional: ElGamal private key (hex). If omitted, generated fresh.
81
+ privacyPrivateKey: '0x...',
87
82
  });
83
+ ```
88
84
 
89
- // Create a private order (amounts hidden on-chain)
90
- const order = await swapClient.createPrivateOrder({
91
- giveAsset: 'SAGE',
92
- wantAsset: 'USDC',
93
- giveAmount: 1000n,
94
- wantAmount: 100n,
95
- });
85
+ All 14 mainnet contract addresses are baked into the SDK. No manual address configuration is needed.
96
86
 
97
- console.log('Order ID:', order.orderId);
98
- console.log('Encrypted amounts:', order.encryptedGive, order.encryptedWant);
99
- ```
87
+ ---
100
88
 
101
- ### Privacy Operations Reference
89
+ ## Sub-Clients
102
90
 
103
- | Operation | Privacy | Speed | Cost |
104
- |-----------|---------|-------|------|
105
- | `encrypt()` | Full | < 1ms | Free |
106
- | `createEncryptionProof()` | Full | ~50ms | Free |
107
- | `createRangeProof()` | Full | ~100ms | Free |
108
- | `verifyProof()` | N/A | < 10ms | Free |
109
- | On-chain verification | Full | N/A | ~$0.03 |
91
+ The `ObelyskClient` exposes 10 sub-clients, each handling a specific protocol domain.
110
92
 
111
- ---
93
+ ### 1. Privacy Pool (`obelysk.privacyPool`)
112
94
 
113
- ## STWO GPU Prover
95
+ Deposit tokens into shielded pools using Pedersen commitments. Withdraw with nullifier + Merkle proof to break the on-chain link between depositor and recipient.
114
96
 
115
- For batch operations and complex computations, use the STWO GPU Prover to generate proofs efficiently.
97
+ ```typescript
98
+ // Deposit 0.1 ETH into the privacy pool
99
+ const { txHash, note, commitmentHash } = await obelysk.privacyPool.deposit({
100
+ token: 'eth',
101
+ amount: '0.1',
102
+ });
103
+ // IMPORTANT: Save `note` securely -- it is required for withdrawal.
104
+
105
+ // Withdraw to a different address
106
+ const result = await obelysk.privacyPool.withdraw({
107
+ note,
108
+ recipient: '0xRecipient...',
109
+ merkleProof: ['0x...', '0x...'],
110
+ leafIndex: 42,
111
+ });
116
112
 
117
- ### When to Use STWO GPU
113
+ // Read-only queries
114
+ const root = await obelysk.privacyPool.getMerkleRoot('eth');
115
+ const stats = await obelysk.privacyPool.getPoolStats('eth');
116
+ ```
118
117
 
119
- | Scenario | Recommendation | Savings |
120
- |----------|---------------|---------|
121
- | Single payment | Client-side Schnorr | - |
122
- | 100+ payments | STWO GPU batch | 95% |
123
- | AI/ML inference | STWO GPU | Required |
124
- | Cross-chain bridge | STWO GPU | 98% |
125
- | Gaming state | STWO GPU batch | 99% |
118
+ ### 2. DarkPool (`obelysk.darkPool`)
126
119
 
127
- ### Basic Usage
120
+ Commit-reveal batch auction trading. Orders are committed as hashes during the commit phase, revealed during the reveal phase, and matched during settlement.
128
121
 
129
122
  ```typescript
130
- import { createStwoProverClient, PROOF_TYPES, GPU_TIERS } from '@bitsage/sdk';
131
-
132
- const prover = createStwoProverClient({
133
- baseUrl: 'https://prover.bitsage.network',
134
- apiKey: 'your-api-key',
123
+ // Fund your DarkPool balance
124
+ await obelysk.darkPool.deposit({ token: 'sage', amount: '10000' });
125
+
126
+ // Commit an order (commit phase)
127
+ const { orderData } = await obelysk.darkPool.commitOrder({
128
+ pair: 'SAGE/STRK',
129
+ side: 'sell',
130
+ price: '0.011',
131
+ amount: '5000',
135
132
  });
133
+ // Save `orderData` -- needed for reveal
136
134
 
137
- // Submit a proof generation job
138
- const job = await prover.submitProofJob({
139
- proofType: PROOF_TYPES.BATCH_PAYMENTS,
140
- publicInputs: [/* payment data */],
141
- priority: 'high',
142
- gpuTier: GPU_TIERS.H100,
143
- });
135
+ // Reveal the order (reveal phase)
136
+ await obelysk.darkPool.revealOrder({ orderData });
137
+
138
+ // Claim fills after settlement
139
+ await obelysk.darkPool.claimFills({ epoch: orderData.epoch });
140
+
141
+ // Read-only
142
+ const epoch = await obelysk.darkPool.getEpochInfo();
143
+ ```
144
+
145
+ ### 3. Stealth Payments (`obelysk.stealth`)
144
146
 
145
- console.log('Job ID:', job.jobId);
146
- console.log('Estimated cost:', job.estimatedCostUsdc, 'USDC');
147
- console.log('Estimated time:', job.estimatedTimeSecs, 'seconds');
147
+ Send tokens to one-time stealth addresses. The sender derives an ephemeral address from the receiver's stealth meta-address. Only the receiver can detect and claim the payment.
148
148
 
149
- // Wait for completion with progress updates
150
- const result = await prover.waitForProof(job.jobId, {
151
- onProgress: (status) => {
152
- console.log(`Progress: ${status.progressBps / 100}%`);
153
- console.log(`Phase: ${status.currentPhase}`);
154
- },
149
+ ```typescript
150
+ // Send 1000 SAGE to a stealth address
151
+ const { txHash, announcement } = await obelysk.stealth.send({
152
+ to: '0xReceiverAddress...',
153
+ token: 'sage',
154
+ amount: '1000',
155
155
  });
156
156
 
157
- console.log('Proof hash:', result.proofHash);
158
- console.log('Actual cost:', result.costUsdc, 'USDC');
157
+ // Receiver: scan announcements and claim
158
+ const announcements = await obelysk.stealth.getAnnouncements(fromBlock);
159
+ const claimable = await obelysk.stealth.scanForPayments(announcements, viewKey);
160
+ await obelysk.stealth.claim({ announcementIndex: 5, spendingProof, recipient: '0x...' });
159
161
  ```
160
162
 
161
- ### Batch Operations (95-99% Cost Savings)
163
+ ### 4. Confidential Transfer (`obelysk.confidentialTransfer`)
164
+
165
+ Peer-to-peer transfers where the amount is encrypted on-chain using ElGamal. Only sender and recipient can see the value.
162
166
 
163
167
  ```typescript
164
- // Batch 1000 payments into a single proof
165
- const payments = [
166
- { sender: '0x...', recipient: '0x...', amount: 100n, asset: 'SAGE' },
167
- // ... 999 more payments
168
- ];
169
-
170
- const result = await prover.proveBatchPayments(payments, {
171
- priority: 'high',
172
- requireTee: true, // Use TEE for privacy
168
+ // Transfer 500 SAGE with encrypted amount
169
+ const { txHash } = await obelysk.confidentialTransfer.transfer({
170
+ to: '0xRecipient...',
171
+ recipientPublicKey: { x: 0x...n, y: 0x...n },
172
+ amount: '500',
173
+ token: 'sage',
173
174
  });
174
175
 
175
- // Cost: ~$0.25 instead of $30 (99% savings!)
176
- console.log('Batch proof hash:', result.proofHash);
176
+ // Query encrypted balance
177
+ const encBalance = await obelysk.confidentialTransfer.getEncryptedBalance('0xAddress...');
178
+
179
+ // Decrypt locally (requires private key)
180
+ const balance = obelysk.privacy.decrypt(encBalance, privateKey);
177
181
  ```
178
182
 
179
- ### AI/ML Inference Proofs
183
+ ### 5. Prover Staking (`obelysk.staking`)
184
+
185
+ Stake SAGE tokens to participate as a GPU prover in the network. Four tiers: Consumer, Professional, DataCenter, H100.
180
186
 
181
187
  ```typescript
182
- // Prove AI inference was computed correctly
183
- const result = await prover.proveInference(
184
- 'llama-7b', // Model ID
185
- [/* input tokens */], // Inputs
186
- [/* output tokens */], // Outputs
187
- { requireTee: true } // Keep data private
188
- );
188
+ // Stake 50,000 SAGE as a DataCenter prover
189
+ await obelysk.staking.stake({ amount: '50000', gpuTier: 'DataCenter' });
189
190
 
190
- console.log('Inference proof:', result.proofHash);
191
+ // Query staking info
192
+ const config = await obelysk.staking.getConfig();
193
+ const worker = await obelysk.staking.getWorkerStake('0xWorker...');
194
+ const total = await obelysk.staking.getTotalStaked();
195
+
196
+ // Unstake (after cooldown)
197
+ await obelysk.staking.unstake();
191
198
  ```
192
199
 
193
- ### Cross-Chain Bridge Proofs
200
+ ### 6. Privacy Router (`obelysk.router`)
201
+
202
+ Read-only views into the Privacy Router contract -- private account registration, encrypted balances, nullifier tracking, and audit support.
194
203
 
195
204
  ```typescript
196
- // Prove a transaction occurred on another chain
197
- const result = await prover.proveBridge(
198
- 'ethereum', // Source chain
199
- '0xabc...def', // Transaction hash
200
- ['0x...', '0x...', '0x...'], // Block headers
201
- { priority: 'critical' }
202
- );
205
+ const account = await obelysk.router.getAccount('0xAddress...');
206
+ if (account?.registered) {
207
+ console.log('Public key:', account.publicKey);
208
+ console.log('Encrypted balance:', account.encryptedBalance);
209
+ }
203
210
 
204
- console.log('Bridge proof:', result.proofHash);
211
+ const spent = await obelysk.router.isNullifierUsed('0xNullifier...');
205
212
  ```
206
213
 
207
- ### Recursive Proof Aggregation
214
+ ### 7. Shielded Swap (`obelysk.swap`)
215
+
216
+ Privacy-preserving AMM swaps routed through Ekubo. Swaps consume a privacy pool withdrawal proof and produce a new shielded commitment.
208
217
 
209
218
  ```typescript
210
- // Aggregate multiple proofs into one
211
- const proofHashes = [
212
- '0x111...',
213
- '0x222...',
214
- '0x333...',
215
- ];
216
-
217
- const aggregated = await prover.aggregateProofs(proofHashes);
218
- console.log('Aggregated proof:', aggregated.proofHash);
219
- // Verify once instead of 3 times!
219
+ // Query swap router state
220
+ const swapCount = await obelysk.swap.getSwapCount();
221
+ const pool = await obelysk.swap.getPool(tokenAddress);
222
+ const fee = await obelysk.swap.getFee();
220
223
  ```
221
224
 
222
- ### Cost Estimation
225
+ ### 8. VM31 UTXO Vault (`obelysk.vm31`)
226
+
227
+ UTXO-based privacy vault using Poseidon2-M31 hashing. Transactions are submitted to the VM31 relayer, which batches and proves them on-chain.
223
228
 
224
229
  ```typescript
225
- // Estimate cost before submitting
226
- const estimate = await prover.estimateCost({
227
- proofType: PROOF_TYPES.BATCH_PAYMENTS,
228
- publicInputs: new Array(1000).fill(0n),
229
- priority: 'high',
230
- requireTee: true,
230
+ // Deposit 0.01 BTC (denomination-safe)
231
+ const result = await obelysk.vm31.deposit({
232
+ amount: 1_000_000n, // 0.01 BTC in satoshis
233
+ assetId: 0, // wBTC
234
+ recipientPubkey: [/* M31 field elements */],
235
+ recipientViewingKey: [/* M31 field elements */],
231
236
  });
232
237
 
233
- console.log('Estimated cost:', estimate.costUsdc, 'USDC');
234
- console.log('Breakdown:');
235
- console.log(' Base:', estimate.breakdown.baseCost);
236
- console.log(' Priority:', estimate.breakdown.prioritySurcharge);
237
- console.log(' TEE:', estimate.breakdown.teeSurcharge);
238
- ```
238
+ // Check batch status
239
+ const batch = await obelysk.vm31.getBatchStatus(result.batchId);
239
240
 
240
- ### Network Metrics
241
+ // Query on-chain state
242
+ const root = await obelysk.vm31.getMerkleRoot();
243
+ const noteCount = await obelysk.vm31.getNoteCount();
244
+ const relayer = await obelysk.vm31.getRelayerInfo();
245
+ ```
241
246
 
242
- ```typescript
243
- // Check network status
244
- const metrics = await prover.getMetrics();
247
+ ### 9. VM31 Bridge (`obelysk.bridge`)
245
248
 
246
- console.log('Available GPUs:');
247
- for (const gpu of metrics.availableGpus) {
248
- console.log(` ${gpu.tier}: ${gpu.count} (${gpu.teeEnabled} TEE)`);
249
- }
249
+ Bridge between the VM31 UTXO pool and ElGamal-based ConfidentialTransfer system.
250
250
 
251
- console.log('Queue depth:', metrics.queueDepth);
252
- console.log('Avg wait time:', metrics.avgWaitTimeSecs, 'seconds');
253
- console.log('Utilization:', metrics.networkUtilization * 100, '%');
251
+ ```typescript
252
+ const config = await obelysk.bridge.getConfig();
253
+ const assetPair = await obelysk.bridge.getAssetPair(0); // wBTC mapping
254
+ const relayer = await obelysk.bridge.getRelayer();
254
255
  ```
255
256
 
256
- ---
257
-
258
- ## Full Privacy Client
257
+ ### 10. OTC Orderbook (`obelysk.otc`)
259
258
 
260
- For advanced privacy operations including steganographic transactions, ring signatures, and threshold decryption.
259
+ On-chain limit and market order book for peer-to-peer token trading.
261
260
 
262
261
  ```typescript
263
- import { createPrivacyClient } from '@bitsage/sdk';
264
-
265
- const privacy = createPrivacyClient({
266
- contractAddress: '0x...',
267
- httpUrl: 'https://api.bitsage.network',
262
+ import { OrderSide, OrderType } from '@obelyzk/sdk/obelysk';
263
+
264
+ // Place a limit order
265
+ const orderId = await obelysk.otc.placeLimitOrder({
266
+ pairId: 0,
267
+ side: OrderSide.Buy,
268
+ price: 11_000_000_000_000_000n, // 0.011 in 18-decimal
269
+ amount: 5000_000_000_000_000_000_000n,
268
270
  });
269
271
 
270
- // Register a private account
271
- const account = await privacy.registerAccount(keyPair);
272
-
273
- // Private transfer
274
- const tx = await privacy.privateTransfer({
275
- recipientPublicKey: recipient.publicKey,
276
- amount: 500n,
277
- asset: 'SAGE',
272
+ // Place a market order
273
+ await obelysk.otc.placeMarketOrder({
274
+ pairId: 0,
275
+ side: OrderSide.Sell,
276
+ amount: 1000_000_000_000_000_000_000n,
278
277
  });
279
278
 
280
- // Check encrypted balance
281
- const balance = await privacy.getEncryptedBalance(myAddress, 'SAGE');
279
+ // Query orderbook
280
+ const depth = await obelysk.otc.getOrderbookDepth(0);
281
+ const stats = await obelysk.otc.get24hStats(0);
282
+ const order = await obelysk.otc.getOrder(orderId);
283
+ const trades = await obelysk.otc.getRecentTrades(0);
282
284
 
283
- // Reveal balance (client-side decryption)
284
- const revealed = await privacy.revealBalance(keyPair, 'SAGE');
285
- console.log('My SAGE balance:', revealed);
285
+ // Cancel
286
+ await obelysk.otc.cancelOrder(orderId);
286
287
  ```
287
288
 
288
289
  ---
289
290
 
290
- ## React Hooks
291
+ ## ElGamal Privacy Primitives
292
+
293
+ Available from both `@obelyzk/sdk/privacy` and `@obelyzk/sdk/obelysk`.
291
294
 
292
295
  ```typescript
293
- import { useBitSage, usePrivacy, useStwoProver } from '@bitsage/sdk/react';
296
+ import { ObelyskPrivacy } from '@obelyzk/sdk/privacy';
294
297
 
295
- function App() {
296
- const { client, isConnected } = useBitSage();
297
- const { privacy, keyPair, generateKeyPair } = usePrivacy();
298
- const { prover, submitJob, status } = useStwoProver();
298
+ const privacy = new ObelyskPrivacy();
299
299
 
300
- return (
301
- <div>
302
- <button onClick={generateKeyPair}>Generate Keys</button>
303
- <button onClick={() => submitJob({ ... })}>Submit Proof</button>
304
- {status && <p>Progress: {status.progressBps / 100}%</p>}
305
- </div>
306
- );
307
- }
300
+ // Generate a key pair
301
+ const keyPair = privacy.generateKeyPair();
302
+ console.log('Public key:', keyPair.publicKey); // ECPoint { x, y }
303
+
304
+ // Encrypt an amount (only the private key holder can decrypt)
305
+ const ciphertext = privacy.encrypt(1_000_000n, keyPair.publicKey);
306
+ // ciphertext = { c1: ECPoint, c2: ECPoint }
307
+
308
+ // Decrypt
309
+ const amount = privacy.decrypt(ciphertext, keyPair.privateKey);
310
+ console.log(amount); // 1000000n
311
+
312
+ // Homomorphic addition (add encrypted values without decrypting)
313
+ const ct1 = privacy.encrypt(100n, keyPair.publicKey);
314
+ const ct2 = privacy.encrypt(200n, keyPair.publicKey);
315
+ const ctSum = privacy.homomorphicAdd(ct1, ct2);
316
+ const sum = privacy.decrypt(ctSum, keyPair.privateKey);
317
+ console.log(sum); // 300n
318
+
319
+ // Schnorr proof of correct encryption
320
+ const proof = privacy.createEncryptionProof(1_000_000n, keyPair, ciphertext);
321
+ const valid = privacy.verifyEncryptionProof(proof, keyPair.publicKey, ciphertext);
308
322
  ```
309
323
 
310
- ---
311
-
312
- ## Contract Registry
324
+ ### Low-Level Crypto Functions
313
325
 
314
326
  ```typescript
315
327
  import {
316
- SEPOLIA_CONTRACTS,
317
- MAINNET_CONTRACTS,
318
- getContractsForNetwork
319
- } from '@bitsage/sdk';
320
-
321
- // Get contracts for a network
322
- const contracts = getContractsForNetwork('sepolia');
323
-
324
- console.log('SAGE Token:', contracts.sageToken);
325
- console.log('Confidential Swap:', contracts.confidentialSwap);
326
- console.log('Privacy Router:', contracts.privacyRouter);
327
- console.log('STWO Verifier:', contracts.stwoVerifier);
328
+ elgamalEncrypt,
329
+ pedersenCommit,
330
+ createEncryptionProof,
331
+ createAEHint,
332
+ commitmentToHash,
333
+ deriveNullifier,
334
+ randomScalar,
335
+ ecAdd,
336
+ ecMul,
337
+ mod,
338
+ modInverse,
339
+ FIELD_PRIME,
340
+ CURVE_ORDER,
341
+ GENERATOR_G,
342
+ GENERATOR_H,
343
+ } from '@obelyzk/sdk/obelysk';
344
+
345
+ // Pedersen commitment: C = value * G + blinding * H
346
+ const blinding = randomScalar();
347
+ const commitment = pedersenCommit(1000n, blinding);
348
+
349
+ // ElGamal encrypt: (r*G, amount*H + r*PK)
350
+ const { c1, c2, randomness } = elgamalEncrypt(500n, publicKey);
351
+
352
+ // Schnorr proof of knowledge of r
353
+ const proof = createEncryptionProof(randomness, c1);
354
+
355
+ // AE hint for O(1) decryption
356
+ const { encryptedAmount, mac } = createAEHint(500n, sharedSecret);
357
+
358
+ // Nullifier derivation (Poseidon hash)
359
+ const nullifier = deriveNullifier(nullifierSecret, commitmentToHash(commitment));
328
360
  ```
329
361
 
330
362
  ---
331
363
 
332
- ## Architecture
364
+ ## ECIES Encryption
333
365
 
366
+ ECIES (X25519 + HKDF-SHA256 + AES-256-GCM) is used to encrypt transaction payloads for the VM31 relayer. Compatible with the Rust relayer (`x25519-dalek` + `aes-gcm` + `hkdf`).
367
+
368
+ ```typescript
369
+ import { eciesEncrypt } from '@obelyzk/sdk/obelysk';
370
+ import type { ECIESEnvelope } from '@obelyzk/sdk/obelysk';
371
+
372
+ const envelope: ECIESEnvelope = await eciesEncrypt(
373
+ { action: 'deposit', amount: '1000000', assetId: 0 },
374
+ relayerPublicKeyHex, // 64-char hex X25519 public key
375
+ );
376
+
377
+ // POST the envelope to the relayer
378
+ const response = await fetch('https://relay.bitsage.network:3080/submit', {
379
+ method: 'POST',
380
+ headers: { 'Content-Type': 'application/json' },
381
+ body: JSON.stringify(envelope),
382
+ });
334
383
  ```
335
- ┌─────────────────────────────────────────────────────────────────────────────┐
336
- │ @bitsage/sdk │
337
- ├─────────────────────────────────────────────────────────────────────────────┤
338
- │ │
339
- │ OBELYSK PRIVACY (Client-Side) STWO GPU PROVER (Server-Side) │
340
- │ ───────────────────────────── ────────────────────────────── │
341
- │ • ElGamal encryption • Batch proof generation │
342
- │ • Schnorr proofs • GPU acceleration (H100/H200) │
343
- │ • Range proofs • TEE privacy (optional) │
344
- │ • Confidential swaps • Recursive aggregation │
345
- │ │
346
- │ import { ObelyskPrivacy } import { createStwoProverClient } │
347
- │ │
348
- ├─────────────────────────────────────────────────────────────────────────────┤
349
- │ │
350
- │ STARKNET L2 │
351
- │ • Proof verification │
352
- │ • Encrypted balances │
353
- │ • Atomic swaps │
354
- │ │
355
- └─────────────────────────────────────────────────────────────────────────────┘
356
- ```
384
+
385
+ Requires Web Crypto API (Node 20+ or any modern browser).
357
386
 
358
387
  ---
359
388
 
360
- ## API Reference
361
-
362
- ### ObelyskPrivacy
363
-
364
- | Method | Description |
365
- |--------|-------------|
366
- | `generateKeyPair()` | Generate ElGamal key pair |
367
- | `encrypt(amount, publicKey)` | Encrypt amount |
368
- | `decrypt(ciphertext, privateKey)` | Decrypt ciphertext |
369
- | `homomorphicAdd(c1, c2)` | Add encrypted values |
370
- | `createEncryptionProof()` | Create Schnorr proof |
371
- | `verifyEncryptionProof()` | Verify proof |
372
-
373
- ### StwoProverClient
374
-
375
- | Method | Description |
376
- |--------|-------------|
377
- | `submitProofJob(request)` | Submit proof generation job |
378
- | `getJobStatus(jobId)` | Get job status |
379
- | `waitForProof(jobId)` | Wait for completion |
380
- | `cancelJob(jobId)` | Cancel pending job |
381
- | `submitBatch(request)` | Submit batch of proofs |
382
- | `estimateCost(request)` | Estimate proof cost |
383
- | `getMetrics()` | Get network metrics |
384
- | `proveBatchPayments()` | Helper for batch payments |
385
- | `proveInference()` | Helper for AI inference |
386
- | `proveBridge()` | Helper for bridge proofs |
387
- | `aggregateProofs()` | Recursive aggregation |
388
- | `loadZkmlModel(req)` | Load ONNX model on prover server |
389
- | `submitZkmlProve(req)` | Submit ZKML proving job |
390
- | `getZkmlProveStatus(jobId)` | Get ZKML job progress |
391
- | `getZkmlProveResult(jobId)` | Get proof calldata + commitments |
392
- | `proveZkml(req, opts?)` | Full prove pipeline with progress callback |
393
-
394
- ### StwoClient (On-Chain Verification)
395
-
396
- | Method | Description |
397
- |--------|-------------|
398
- | `submitProof(data, hash)` | Submit proof for verification |
399
- | `verifyProof(hash)` | Verify proof via contract |
400
- | `submitGpuTeeProof(params)` | Submit GPU-TEE optimistic proof |
401
- | `registerZkmlModel(id, commitment)` | Register model on verifier contract |
402
- | `verifyZkmlModel(id, calldata)` | Verify ML model proof on-chain |
403
- | `isZkmlProofVerified(hash)` | Check if proof is verified |
404
- | `getZkmlVerificationCount(id)` | Get verification count for model |
405
- | `getZkmlModelCommitment(id)` | Get registered weight commitment |
406
- | `proveAndVerifyOnChain(prover, req)` | End-to-end: prove via API + verify on-chain |
389
+ ## Denomination Validation
407
390
 
408
- ---
391
+ Privacy pool and VM31 vault deposits must use standard denominations to prevent exact-amount correlation attacks. The SDK enforces this client-side.
409
392
 
410
- ## ZKML Proving
393
+ ```typescript
394
+ import {
395
+ validateDenomination,
396
+ splitIntoDenominations,
397
+ getDenominations,
398
+ ETH_DENOMINATIONS,
399
+ } from '@obelyzk/sdk/obelysk';
400
+
401
+ // Validate a deposit amount
402
+ validateDenomination(10_000_000_000_000_000n, 'eth'); // 0.01 ETH -- OK
403
+ validateDenomination(12_345_678n, 'eth'); // throws Error
404
+
405
+ // Auto-split an arbitrary amount into denomination-safe batches
406
+ const { denominations, remainder } = splitIntoDenominations(
407
+ 350_000_000_000_000_000n, // 0.35 ETH
408
+ 'eth',
409
+ );
410
+ // denominations = [0.1 ETH, 0.1 ETH, 0.1 ETH, 0.05 ETH]
411
+ // remainder = 0n
411
412
 
412
- End-to-end ML inference proving and on-chain verification.
413
+ // List valid denominations for an asset
414
+ const denoms = getDenominations('usdc');
415
+ // [1 USDC, 5 USDC, 10 USDC, 50 USDC, 100 USDC, 500 USDC]
416
+ ```
413
417
 
414
- ### Prove a Model
418
+ Supported tokens: wBTC, SAGE, ETH, STRK, USDC. Unknown assets pass through without restriction.
415
419
 
416
- ```typescript
417
- import { createStwoProverClient } from '@bitsage/sdk';
420
+ ---
418
421
 
419
- const prover = createStwoProverClient({
420
- baseUrl: 'http://your-gpu-server:8080',
421
- });
422
+ ## Contract Addresses
422
423
 
423
- // Load an ONNX model
424
- const model = await prover.loadZkmlModel({
425
- modelPath: '/path/to/model.onnx',
426
- description: 'Qwen3-14B block 0',
427
- });
428
- console.log('Model ID:', model.modelId);
429
- console.log('Weight commitment:', model.weightCommitment);
430
-
431
- // Prove with progress tracking
432
- const result = await prover.proveZkml(
433
- { modelId: model.modelId, gpu: true },
434
- {
435
- onProgress: (status) => {
436
- console.log(`${(status.progressBps / 100).toFixed(1)}% — ${status.elapsedSecs.toFixed(1)}s`);
437
- },
438
- pollIntervalMs: 2000,
439
- timeoutMs: 300_000,
440
- }
441
- );
424
+ All mainnet and Sepolia addresses are available programmatically:
442
425
 
443
- console.log('Calldata:', result.calldataLength, 'felts');
444
- console.log('Gas estimate:', result.estimatedGas);
445
- console.log('Prove time:', (result.proveTimeMs / 1000).toFixed(1), 's');
426
+ ```typescript
427
+ import {
428
+ getContracts,
429
+ getRpcUrl,
430
+ MAINNET_TOKENS,
431
+ MAINNET_PRIVACY_POOLS,
432
+ TOKEN_DECIMALS,
433
+ DARKPOOL_ASSET_IDS,
434
+ VM31_ASSET_IDS,
435
+ parseAmount,
436
+ formatAmount,
437
+ } from '@obelyzk/sdk/obelysk';
438
+
439
+ const contracts = getContracts('mainnet');
440
+ console.log('SAGE Token:', contracts.sage_token);
441
+ console.log('DarkPool:', contracts.dark_pool);
442
+ console.log('VM31 Pool:', contracts.vm31_pool);
443
+
444
+ // Token utilities
445
+ const wei = parseAmount('1.5', 'eth'); // 1500000000000000000n
446
+ const str = formatAmount(wei, 'eth'); // "1.5"
446
447
  ```
447
448
 
448
- ### Verify On-Chain
449
+ ### Mainnet Contracts (14 total)
450
+
451
+ | Contract | Address |
452
+ |---|---|
453
+ | SAGE Token | `0x0098d563...931c799` |
454
+ | ConfidentialTransfer | `0x0673685b...a979d2` |
455
+ | PrivacyRouter | `0x00f3fd87...bfbdfbd` |
456
+ | ProverStaking | `0x07d2ecff...293e3` |
457
+ | DarkPool | `0x0230b582...ea7727` |
458
+ | ShieldedSwap | `0x05a7f8a6...29725b` |
459
+ | StealthRegistry | `0x077ee4c3...fcaea8` |
460
+ | OTC Orderbook | `0x04165f8f...941b19` |
461
+ | SumcheckVerifier | `0x05071a94...d330e8` |
462
+ | VM31Pool | `0x0230eb35...1400d` |
463
+ | VM31Bridge | `0x048f481c...0356c` |
464
+ | PrivacyPool (wBTC) | `0x030fcfd4...d5e5e2` |
465
+ | PrivacyPool (SAGE) | `0x0224977...ac724f` |
466
+ | PrivacyPool (ETH) | `0x06d0b41c...e82b5` |
467
+ | PrivacyPool (STRK) | `0x02c348e8...c9cf1` |
468
+ | PrivacyPool (USDC) | `0x05d36d7f...d4d59b` |
449
469
 
450
- ```typescript
451
- import { createStwoClient } from '@bitsage/sdk';
470
+ ---
452
471
 
453
- const verifier = createStwoClient({ /* ... */ });
472
+ ## React Hooks
454
473
 
455
- // Set verifier contract (default: deployed v3 on Sepolia)
456
- verifier.setZkmlVerifier('0x048070fbd531a0192f3d4a37eb019ae3174600cae15e08c737982fae5d929160');
474
+ ```typescript
475
+ import { useBitSage, usePrivacy, useStwoProver } from '@obelyzk/sdk/react';
457
476
 
458
- // Register model
459
- await verifier.registerZkmlModel(model.modelId, model.weightCommitment);
477
+ function App() {
478
+ const { client, isConnected } = useBitSage();
479
+ const { privacy, keyPair, generateKeyPair } = usePrivacy();
480
+ const { prover, submitJob, status } = useStwoProver();
460
481
 
461
- // Check verification status
462
- const count = await verifier.getZkmlVerificationCount(model.modelId);
463
- console.log('Verified', count, 'times');
482
+ return (
483
+ <div>
484
+ <p>Connected: {String(isConnected)}</p>
485
+ <button onClick={generateKeyPair}>Generate Keys</button>
486
+ </div>
487
+ );
488
+ }
464
489
  ```
465
490
 
466
- ### Full Pipeline
491
+ Requires `react >= 18` as a peer dependency (optional -- only needed if you use this entry point).
467
492
 
468
- ```typescript
469
- // Prove on GPU server + verify on Starknet in one call
470
- const tx = await verifier.proveAndVerifyOnChain(prover, {
471
- modelId: model.modelId,
472
- gpu: true,
473
- });
474
- console.log('Transaction hash:', tx);
475
- ```
493
+ ---
494
+
495
+ ## Requirements
496
+
497
+ - Node.js >= 18
498
+ - `starknet` >= 6.0.0
499
+ - TypeScript >= 5.0 (recommended)
476
500
 
477
501
  ---
478
502