@obelyzk/sdk 1.1.0 → 1.3.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 +109 -428
- package/dist/chunk-BHUXKNDT.mjs +206 -0
- package/dist/chunk-MDF4P52S.mjs +697 -0
- package/dist/chunk-Y6FXYEAI.mjs +10 -0
- package/dist/firewall/index.d.mts +166 -0
- package/dist/firewall/index.d.ts +166 -0
- package/dist/firewall/index.js +232 -0
- package/dist/firewall/index.mjs +7 -0
- package/dist/index.d.mts +50 -4
- package/dist/index.d.ts +50 -4
- package/dist/index.js +235 -0
- package/dist/index.mjs +36 -1
- package/dist/obelysk/index.mjs +4 -2
- package/dist/privacy/index.d.mts +1 -1
- package/dist/privacy/index.d.ts +1 -1
- package/dist/privacy/index.mjs +2 -1
- package/dist/react/index.d.mts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.mjs +2 -1
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -1,505 +1,186 @@
|
|
|
1
1
|
# @obelyzk/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript SDK for ObelyZK -- verifiable ML inference on Starknet.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Prove any supported model and get an on-chain verification receipt in a single call. All proofs use full OODS + Merkle + FRI + PoW (trustless) verification.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install @obelyzk/sdk
|
|
10
|
+
npm install @obelyzk/sdk
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
## Entry Points
|
|
16
|
-
|
|
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 |
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## Quick Start (Read-Only)
|
|
27
|
-
|
|
28
|
-
No wallet or account needed for read-only queries:
|
|
29
|
-
|
|
30
|
-
```typescript
|
|
31
|
-
import { ObelyskClient } from '@obelyzk/sdk/obelysk';
|
|
32
|
-
|
|
33
|
-
const obelysk = new ObelyskClient({
|
|
34
|
-
network: 'mainnet',
|
|
35
|
-
rpcUrl: 'https://your-rpc.com',
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
// Query DarkPool epoch
|
|
39
|
-
const epoch = await obelysk.darkPool.getEpochInfo();
|
|
40
|
-
console.log('Epoch:', epoch.epoch, 'Phase:', epoch.phase);
|
|
41
|
-
|
|
42
|
-
// Query privacy pool stats
|
|
43
|
-
const root = await obelysk.privacyPool.getMerkleRoot('eth');
|
|
44
|
-
console.log('ETH pool Merkle root:', root);
|
|
45
|
-
|
|
46
|
-
// Query staking
|
|
47
|
-
const totalStaked = await obelysk.staking.getTotalStaked();
|
|
48
|
-
console.log('Total SAGE staked:', totalStaked);
|
|
49
|
-
|
|
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
|
-
```
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## ObelyskClient Configuration
|
|
13
|
+
## Quick Start
|
|
58
14
|
|
|
59
15
|
```typescript
|
|
60
|
-
import {
|
|
61
|
-
import { Account, RpcProvider } from 'starknet';
|
|
62
|
-
|
|
63
|
-
const provider = new RpcProvider({ nodeUrl: 'https://your-rpc.com' });
|
|
64
|
-
const account = new Account(provider, '0xADDRESS', '0xPRIVATE_KEY');
|
|
16
|
+
import { createProverClient } from "@obelyzk/sdk";
|
|
65
17
|
|
|
66
|
-
const
|
|
67
|
-
// Required
|
|
68
|
-
network: 'mainnet', // 'mainnet' | 'sepolia'
|
|
18
|
+
const client = createProverClient();
|
|
69
19
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// Optional: VM31 relayer (for UTXO vault operations)
|
|
77
|
-
relayerUrl: 'https://relay.bitsage.network:3080',
|
|
78
|
-
relayerApiKey: 'your-api-key',
|
|
79
|
-
|
|
80
|
-
// Optional: ElGamal private key (hex). If omitted, generated fresh.
|
|
81
|
-
privacyPrivateKey: '0x...',
|
|
20
|
+
// Prove a model and verify on-chain
|
|
21
|
+
const result = await client.prove({
|
|
22
|
+
model: "smollm2-135m",
|
|
23
|
+
input: [1.0, 2.0, 3.0],
|
|
24
|
+
onChain: true,
|
|
82
25
|
});
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
All 14 mainnet contract addresses are baked into the SDK. No manual address configuration is needed.
|
|
86
26
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
27
|
+
console.log("Output:", result.output);
|
|
28
|
+
console.log("Proof hash:", result.proofHash);
|
|
29
|
+
console.log("TX hash:", result.txHash);
|
|
30
|
+
console.log("Verified:", result.verified);
|
|
31
|
+
```
|
|
90
32
|
|
|
91
|
-
|
|
33
|
+
## API Reference
|
|
92
34
|
|
|
93
|
-
###
|
|
35
|
+
### `createProverClient(options?)`
|
|
94
36
|
|
|
95
|
-
|
|
37
|
+
Create a prover client instance.
|
|
96
38
|
|
|
97
39
|
```typescript
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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,
|
|
40
|
+
const client = createProverClient({
|
|
41
|
+
url: "https://api.obelysk.com", // default; or your own GPU prover
|
|
42
|
+
apiKey: "your-api-key", // optional, for rate limiting
|
|
43
|
+
timeout: 300_000, // request timeout in ms (default: 5 min)
|
|
111
44
|
});
|
|
112
|
-
|
|
113
|
-
// Read-only queries
|
|
114
|
-
const root = await obelysk.privacyPool.getMerkleRoot('eth');
|
|
115
|
-
const stats = await obelysk.privacyPool.getPoolStats('eth');
|
|
116
45
|
```
|
|
117
46
|
|
|
118
|
-
###
|
|
47
|
+
### `client.prove(request)`
|
|
119
48
|
|
|
120
|
-
|
|
49
|
+
Prove an ML model execution and optionally verify on-chain.
|
|
121
50
|
|
|
122
51
|
```typescript
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
side: 'sell',
|
|
130
|
-
price: '0.011',
|
|
131
|
-
amount: '5000',
|
|
52
|
+
const result = await client.prove({
|
|
53
|
+
model: "smollm2-135m", // model name or HuggingFace ID
|
|
54
|
+
input: [1.0, 2.0, 3.0], // input tensor (flat array)
|
|
55
|
+
onChain: true, // submit to Starknet (default: false)
|
|
56
|
+
recursive: true, // use recursive STARK (default: true)
|
|
57
|
+
network: "sepolia", // Starknet network (default: "sepolia")
|
|
132
58
|
});
|
|
133
|
-
// Save `orderData` -- needed for reveal
|
|
134
|
-
|
|
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
59
|
|
|
141
|
-
//
|
|
142
|
-
|
|
60
|
+
// result: {
|
|
61
|
+
// output: number[], // model output tensor
|
|
62
|
+
// proofHash: string, // Poseidon hash of the proof
|
|
63
|
+
// txHash?: string, // Starknet TX hash (if onChain: true)
|
|
64
|
+
// verified?: boolean, // on-chain verification status
|
|
65
|
+
// proveTime: number, // proving time in seconds (~102s for SmolLM2)
|
|
66
|
+
// recursiveTime: number, // recursive STARK time (~3.55s)
|
|
67
|
+
// felts: number, // calldata size in felts (~942)
|
|
68
|
+
// modelId: string, // hex model identifier
|
|
69
|
+
// }
|
|
143
70
|
```
|
|
144
71
|
|
|
145
|
-
###
|
|
72
|
+
### `client.attest(request)`
|
|
146
73
|
|
|
147
|
-
|
|
74
|
+
Prove and submit a full attestation with streaming verification.
|
|
148
75
|
|
|
149
76
|
```typescript
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
amount: '1000',
|
|
77
|
+
const attestation = await client.attest({
|
|
78
|
+
model: "smollm2-135m",
|
|
79
|
+
input: [1.0, 2.0, 3.0],
|
|
80
|
+
submitOnChain: true,
|
|
155
81
|
});
|
|
156
|
-
|
|
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...' });
|
|
161
82
|
```
|
|
162
83
|
|
|
163
|
-
###
|
|
84
|
+
### `client.getModels()`
|
|
164
85
|
|
|
165
|
-
|
|
86
|
+
List all available models on the prover.
|
|
166
87
|
|
|
167
88
|
```typescript
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
to: '0xRecipient...',
|
|
171
|
-
recipientPublicKey: { x: 0x...n, y: 0x...n },
|
|
172
|
-
amount: '500',
|
|
173
|
-
token: 'sage',
|
|
174
|
-
});
|
|
175
|
-
|
|
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);
|
|
89
|
+
const models = await client.getModels();
|
|
90
|
+
// [{ name: "smollm2-135m", params: "135M", layers: 30, ... }, ...]
|
|
181
91
|
```
|
|
182
92
|
|
|
183
|
-
###
|
|
93
|
+
### `client.getJob(jobId)`
|
|
184
94
|
|
|
185
|
-
|
|
95
|
+
Check the status of an async proving job.
|
|
186
96
|
|
|
187
97
|
```typescript
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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();
|
|
98
|
+
const job = await client.getJob("job-abc123");
|
|
99
|
+
// { status: "completed", progress: 100, result: { ... } }
|
|
198
100
|
```
|
|
199
101
|
|
|
200
|
-
|
|
102
|
+
## Async Jobs
|
|
201
103
|
|
|
202
|
-
|
|
104
|
+
For large models, proving runs asynchronously:
|
|
203
105
|
|
|
204
106
|
```typescript
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const spent = await obelysk.router.isNullifierUsed('0xNullifier...');
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### 7. Shielded Swap (`obelysk.swap`)
|
|
107
|
+
const { jobId } = await client.prove({
|
|
108
|
+
model: "phi-3-mini",
|
|
109
|
+
input: data,
|
|
110
|
+
async: true,
|
|
111
|
+
});
|
|
215
112
|
|
|
216
|
-
|
|
113
|
+
// Poll for completion
|
|
114
|
+
let job;
|
|
115
|
+
do {
|
|
116
|
+
await new Promise(r => setTimeout(r, 5000));
|
|
117
|
+
job = await client.getJob(jobId);
|
|
118
|
+
console.log(`Progress: ${job.progress}%`);
|
|
119
|
+
} while (job.status === "running");
|
|
217
120
|
|
|
218
|
-
|
|
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();
|
|
121
|
+
console.log("Result:", job.result);
|
|
223
122
|
```
|
|
224
123
|
|
|
225
|
-
|
|
124
|
+
## Supported Models
|
|
226
125
|
|
|
227
|
-
|
|
126
|
+
| Model | Params | Prove Time (GPU) | Recursive Felts |
|
|
127
|
+
|-------|--------|-------------------|-----------------|
|
|
128
|
+
| SmolLM2-135M | 135M | ~102s | 942 |
|
|
129
|
+
| Qwen2-0.5B | 500M | ~45s | ~900 |
|
|
130
|
+
| Phi-3-mini | 3.8B | ~180s | ~950 |
|
|
228
131
|
|
|
229
|
-
|
|
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 */],
|
|
236
|
-
});
|
|
132
|
+
## On-Chain Verification
|
|
237
133
|
|
|
238
|
-
|
|
239
|
-
const batch = await obelysk.vm31.getBatchStatus(result.batchId);
|
|
240
|
-
|
|
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
|
-
```
|
|
134
|
+
When `onChain: true`, the SDK submits the proof to the ObelyZK Recursive Verifier contract on Starknet Sepolia. Verification uses full OODS + Merkle + FRI + PoW (trustless).
|
|
246
135
|
|
|
247
|
-
|
|
136
|
+
- **Contract:** `0x707819dea6210ab58b358151419a604ffdb16809b568bf6f8933067c2a28715`
|
|
137
|
+
- **Method:** `verify_recursive(model_id, io_commitment, stark_proof_data)`
|
|
138
|
+
- **Verification:** Full OODS + Merkle + FRI + PoW (trustless)
|
|
139
|
+
- **Felts:** ~942 per proof (49x compression)
|
|
140
|
+
- **Cost:** ~$0.02 per verification on Sepolia
|
|
248
141
|
|
|
249
|
-
|
|
142
|
+
You can verify independently:
|
|
250
143
|
|
|
251
144
|
```typescript
|
|
252
|
-
|
|
253
|
-
const assetPair = await obelysk.bridge.getAssetPair(0); // wBTC mapping
|
|
254
|
-
const relayer = await obelysk.bridge.getRelayer();
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### 10. OTC Orderbook (`obelysk.otc`)
|
|
258
|
-
|
|
259
|
-
On-chain limit and market order book for peer-to-peer token trading.
|
|
145
|
+
import { RpcProvider } from "starknet";
|
|
260
146
|
|
|
261
|
-
|
|
262
|
-
|
|
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,
|
|
147
|
+
const provider = new RpcProvider({
|
|
148
|
+
nodeUrl: "https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_8/demo",
|
|
270
149
|
});
|
|
271
150
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
amount: 1000_000_000_000_000_000_000n,
|
|
151
|
+
const result = await provider.callContract({
|
|
152
|
+
contractAddress: "0x707819dea6210ab58b358151419a604ffdb16809b568bf6f8933067c2a28715",
|
|
153
|
+
entrypoint: "get_recursive_verification_count",
|
|
154
|
+
calldata: [modelId],
|
|
277
155
|
});
|
|
278
156
|
|
|
279
|
-
|
|
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);
|
|
284
|
-
|
|
285
|
-
// Cancel
|
|
286
|
-
await obelysk.otc.cancelOrder(orderId);
|
|
157
|
+
console.log("Verification count:", result[0]);
|
|
287
158
|
```
|
|
288
159
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
## ElGamal Privacy Primitives
|
|
292
|
-
|
|
293
|
-
Available from both `@obelyzk/sdk/privacy` and `@obelyzk/sdk/obelysk`.
|
|
294
|
-
|
|
295
|
-
```typescript
|
|
296
|
-
import { ObelyskPrivacy } from '@obelyzk/sdk/privacy';
|
|
297
|
-
|
|
298
|
-
const privacy = new ObelyskPrivacy();
|
|
299
|
-
|
|
300
|
-
// Generate a key pair
|
|
301
|
-
const keyPair = privacy.generateKeyPair();
|
|
302
|
-
console.log('Public key:', keyPair.publicKey); // ECPoint { x, y }
|
|
160
|
+
## Environment Variables
|
|
303
161
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
162
|
+
| Variable | Description | Required |
|
|
163
|
+
|----------|-------------|----------|
|
|
164
|
+
| `OBELYSK_API_KEY` | API key for hosted prover | For hosted |
|
|
165
|
+
| `OBELYSK_PROVER_URL` | Custom prover URL | For self-hosted |
|
|
166
|
+
| `STARKNET_ACCOUNT` | Starknet account address | For on-chain |
|
|
167
|
+
| `STARKNET_PRIVATE_KEY` | Starknet private key | For on-chain |
|
|
307
168
|
|
|
308
|
-
|
|
309
|
-
const amount = privacy.decrypt(ciphertext, keyPair.privateKey);
|
|
310
|
-
console.log(amount); // 1000000n
|
|
169
|
+
## Self-Hosted Prover
|
|
311
170
|
|
|
312
|
-
|
|
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);
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
### Low-Level Crypto Functions
|
|
325
|
-
|
|
326
|
-
```typescript
|
|
327
|
-
import {
|
|
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));
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
---
|
|
363
|
-
|
|
364
|
-
## ECIES Encryption
|
|
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`).
|
|
171
|
+
Point the SDK at your own GPU prover instead of the hosted service:
|
|
367
172
|
|
|
368
173
|
```typescript
|
|
369
|
-
|
|
370
|
-
|
|
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),
|
|
174
|
+
const client = createProverClient({
|
|
175
|
+
url: "http://your-gpu-server:8080",
|
|
382
176
|
});
|
|
383
177
|
```
|
|
384
178
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
---
|
|
388
|
-
|
|
389
|
-
## Denomination Validation
|
|
390
|
-
|
|
391
|
-
Privacy pool and VM31 vault deposits must use standard denominations to prevent exact-amount correlation attacks. The SDK enforces this client-side.
|
|
392
|
-
|
|
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
|
|
412
|
-
|
|
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
|
-
```
|
|
417
|
-
|
|
418
|
-
Supported tokens: wBTC, SAGE, ETH, STRK, USDC. Unknown assets pass through without restriction.
|
|
419
|
-
|
|
420
|
-
---
|
|
421
|
-
|
|
422
|
-
## Contract Addresses
|
|
423
|
-
|
|
424
|
-
All mainnet and Sepolia addresses are available programmatically:
|
|
425
|
-
|
|
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"
|
|
447
|
-
```
|
|
448
|
-
|
|
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` |
|
|
469
|
-
|
|
470
|
-
---
|
|
471
|
-
|
|
472
|
-
## React Hooks
|
|
473
|
-
|
|
474
|
-
```typescript
|
|
475
|
-
import { useBitSage, usePrivacy, useStwoProver } from '@obelyzk/sdk/react';
|
|
476
|
-
|
|
477
|
-
function App() {
|
|
478
|
-
const { client, isConnected } = useBitSage();
|
|
479
|
-
const { privacy, keyPair, generateKeyPair } = usePrivacy();
|
|
480
|
-
const { prover, submitJob, status } = useStwoProver();
|
|
481
|
-
|
|
482
|
-
return (
|
|
483
|
-
<div>
|
|
484
|
-
<p>Connected: {String(isConnected)}</p>
|
|
485
|
-
<button onClick={generateKeyPair}>Generate Keys</button>
|
|
486
|
-
</div>
|
|
487
|
-
);
|
|
488
|
-
}
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
Requires `react >= 18` as a peer dependency (optional -- only needed if you use this entry point).
|
|
492
|
-
|
|
493
|
-
---
|
|
494
|
-
|
|
495
|
-
## Requirements
|
|
496
|
-
|
|
497
|
-
- Node.js >= 18
|
|
498
|
-
- `starknet` >= 6.0.0
|
|
499
|
-
- TypeScript >= 5.0 (recommended)
|
|
500
|
-
|
|
501
|
-
---
|
|
179
|
+
See the [Self-Hosting Guide](../../libs/stwo-ml/scripts/pipeline/GETTING_STARTED.md#option-3-self-host-a-gpu-prover) for setup instructions.
|
|
502
180
|
|
|
503
|
-
##
|
|
181
|
+
## Links
|
|
504
182
|
|
|
505
|
-
|
|
183
|
+
- [GitHub](https://github.com/obelyzk/stwo-ml)
|
|
184
|
+
- [npm](https://www.npmjs.com/package/@obelyzk/sdk)
|
|
185
|
+
- [Getting Started](../../libs/stwo-ml/scripts/pipeline/GETTING_STARTED.md)
|
|
186
|
+
- [On-Chain Docs](../../libs/stwo-ml/docs/ON_CHAIN_VERIFICATION.md)
|