@cypher-zk/sdk 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,32 @@
1
+ Cypher SDK — Source Available License
2
+
3
+ Copyright (c) 2026 Cypher Labs. All rights reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a
6
+ copy of this software and associated documentation files (the "Software"),
7
+ to use the Software solely for the purpose of integrating with and building
8
+ applications on the Cypher, subject to the following conditions:
9
+
10
+ 1. USE: You may use, copy, and modify the Software for internal development,
11
+ testing, and production use in applications that interact with the Cypher.
12
+
13
+ 2. NO REDISTRIBUTION: You may NOT redistribute, sublicense, publish, sell,
14
+ or otherwise make available the Software or any derivative works thereof
15
+ to any third party, whether in source code or compiled form, without the
16
+ prior written consent of Cypher.
17
+
18
+ 3. NO COMPETING PRODUCTS: You may NOT use the Software or any portion thereof
19
+ to build or operate a prediction market protocol, SDK, or competing
20
+ product that is not built on the Cypher.
21
+
22
+ 4. ATTRIBUTION: All copies or substantial portions of the Software used in
23
+ your applications must retain the above copyright notice and this
24
+ permission notice.
25
+
26
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
31
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
32
+ IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,266 @@
1
+ # Cypher SDK
2
+
3
+ > **TypeScript SDK for the [Cypher](https://cyphers.live) privacy-preserving prediction market on Solana**, powered by [Arcium](https://arcium.com) MPC.
4
+
5
+ [![Tests](https://img.shields.io/badge/tests-107%20passing-brightgreen)]()
6
+ [![License: Source Available](https://img.shields.io/badge/license-Source%20Available-orange.svg)]()
7
+
8
+ ---
9
+
10
+ ## Features
11
+
12
+ - **Full instruction coverage** — builders for all 26 Anchor instructions
13
+ - **High-level action helpers** — encrypt → send → await MPC callback → refetch, in one call
14
+ - **Typed event parsing** — 7 on-chain events decoded and narrowed via discriminated unions
15
+ - **Real-time & poll-based subscriptions** — WebSocket `onLogs` + HTTP fallback
16
+ - **Framework-agnostic core** — works in any TS environment (Node, Deno, Bun, browser)
17
+ - **React hooks layer** — optional `@cypher/sdk/react` with React Query integration
18
+ - **Cluster-aware** — reads `GlobalState.accepted_mint` on-chain (devnet=CSDC, mainnet=USDC)
19
+ - **Deterministic test suite** — 107 unit tests, 581 assertions
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install @cypher-zk/sdk
25
+ # or
26
+ bun add @cypher-zk/sdk
27
+ ```
28
+
29
+ ### Peer dependencies
30
+
31
+ | Package | Required for |
32
+ | --- | --- |
33
+ | `react` ^18/^19 | `@cypher-zk/sdk/react` hooks only |
34
+ | `@tanstack/react-query` ^5 | `@cypher-zk/sdk/react` hooks only |
35
+ | `typescript` ^5 | Type checking |
36
+
37
+ ## Quick Start
38
+
39
+ ### Core SDK
40
+
41
+ ```ts
42
+ import { CypherClient, keypairToWallet } from "@cypher-zk/sdk";
43
+ import { Connection, Keypair } from "@solana/web3.js";
44
+
45
+ const connection = new Connection("https://api.devnet.solana.com");
46
+ const wallet = keypairToWallet(Keypair.generate());
47
+
48
+ const client = new CypherClient({ connection, wallet, cluster: "devnet" });
49
+
50
+ // Fetch protocol state
51
+ const gs = await client.globalState.fetch();
52
+ console.log("Market counter:", gs.marketCounter);
53
+
54
+ // Fetch a specific market
55
+ const market = await client.markets.fetch(0n);
56
+ console.log("Question:", market?.question);
57
+
58
+ // Fetch all active markets
59
+ const active = await client.markets.byState(0); // MarketState.Active
60
+ ```
61
+
62
+ ### Place a Private Bet (end-to-end)
63
+
64
+ ```ts
65
+ import { MarketType } from "@cypher-zk/sdk";
66
+
67
+ const result = await client.actions.placeBet({
68
+ payer: wallet.publicKey,
69
+ user: wallet.publicKey,
70
+ marketId: 0n,
71
+ marketType: MarketType.YesNo,
72
+ side: 0, // 0=YES, 1=NO
73
+ amountUsdc: 5_000_000n, // $5 USDC (6 decimals)
74
+ });
75
+
76
+ console.log("Tx:", result.signature);
77
+ console.log("Entry odds:", result.position?.entryOdds);
78
+ ```
79
+
80
+ ### Create a Market
81
+
82
+ ```ts
83
+ const result = await client.actions.createMarket({
84
+ creator: wallet.publicKey,
85
+ question: "Will ETH hit $10k by end of 2026?",
86
+ closeTime: BigInt(Math.floor(Date.now() / 1000) + 7 * 24 * 3600),
87
+ category: 0, // Crypto
88
+ });
89
+
90
+ console.log("Market ID:", result.marketId);
91
+ console.log("Market PDA:", result.marketPda.toBase58());
92
+ ```
93
+
94
+ ### Subscribe to Events
95
+
96
+ ```ts
97
+ // Real-time (WebSocket)
98
+ const sub = client.events.onBetPlaced((data) => {
99
+ console.log("Bet placed! Odds:", data.entryOdds);
100
+ });
101
+
102
+ // Later: sub.unsubscribe();
103
+
104
+ // Poll-based (no WS needed)
105
+ const recent = await client.events.pollEvents({ limit: 20 });
106
+ for (const { event } of recent) {
107
+ console.log(event.name, event.data);
108
+ }
109
+ ```
110
+
111
+ ### Parse Transaction Logs
112
+
113
+ ```ts
114
+ import { parseLogs } from "@cypher-zk/sdk";
115
+
116
+ const tx = await connection.getTransaction(sig, { commitment: "confirmed" });
117
+ const events = parseLogs(tx.meta?.logMessages ?? []);
118
+
119
+ for (const evt of events) {
120
+ if (evt.name === "MarketResolvedEvent") {
121
+ console.log("Outcome:", evt.data.outcome);
122
+ }
123
+ }
124
+ ```
125
+
126
+ ## React Hooks
127
+
128
+ ```tsx
129
+ import { CypherProvider, useMarket, usePlaceBet } from "@cypher-zk/sdk/react";
130
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
131
+
132
+ const queryClient = new QueryClient();
133
+
134
+ function App() {
135
+ return (
136
+ <QueryClientProvider client={queryClient}>
137
+ <CypherProvider client={client}>
138
+ <MarketView />
139
+ </CypherProvider>
140
+ </QueryClientProvider>
141
+ );
142
+ }
143
+
144
+ function MarketView() {
145
+ const { data: market, isLoading } = useMarket(0n);
146
+ const { mutateAsync: placeBet, isPending } = usePlaceBet();
147
+
148
+ if (isLoading) return <p>Loading…</p>;
149
+
150
+ return (
151
+ <div>
152
+ <h1>{market?.question}</h1>
153
+ <button
154
+ disabled={isPending}
155
+ onClick={() => placeBet({
156
+ payer: wallet.publicKey,
157
+ user: wallet.publicKey,
158
+ marketId: 0n,
159
+ marketType: 0,
160
+ side: 0,
161
+ amountUsdc: 1_000_000n,
162
+ })}
163
+ >
164
+ Bet YES ($1)
165
+ </button>
166
+ </div>
167
+ );
168
+ }
169
+ ```
170
+
171
+ ### Available Hooks
172
+
173
+ | Hook | Type | Description |
174
+ | --- | --- | --- |
175
+ | `useGlobalState()` | Query | Protocol config (fees, mint, admin) |
176
+ | `useMarket(id)` | Query | Single market by ID |
177
+ | `useMarkets(filter?)` | Query | All/filtered markets |
178
+ | `useUserPositions(user)` | Query | User's bet positions |
179
+ | `usePlaceBet()` | Mutation | End-to-end private bet |
180
+ | `useResolveMarket()` | Mutation | Resolve a market |
181
+ | `useClaimPayout()` | Mutation | Claim winning payout |
182
+ | `useClaimRefund()` | Mutation | Claim refund on unresolved market |
183
+ | `useCreateMarket()` | Mutation | Create a new market |
184
+ | `useCancelMarket()` | Mutation | Cancel a zero-bet market |
185
+ | `useMarketEvents()` | Subscription | Live event stream |
186
+
187
+ ## Architecture
188
+
189
+ ```
190
+ cypher-sdk/
191
+ ├── src/ # Framework-agnostic core
192
+ │ ├── config.ts # Program ID, cluster presets, on-chain constants
193
+ │ ├── pda.ts # PDA derivation helpers
194
+ │ ├── wallet.ts # Wallet adapter interface
195
+ │ ├── fees.ts # Fee calculation (mirrors on-chain math)
196
+ │ ├── deadlines.ts # Market lifecycle phase computation
197
+ │ ├── errors.ts # Typed error codes + parsing
198
+ │ ├── client.ts # CypherClient — unified entry point
199
+ │ ├── accounts/ # Account fetchers (GlobalState, Market, Position, LP)
200
+ │ ├── arcium/ # MPC glue (cipher, encoding, queue accounts, offsets)
201
+ │ ├── instructions/ # Raw instruction builders (26 instructions)
202
+ │ ├── actions/ # High-level flows (encrypt → send → callback → refetch)
203
+ │ ├── events/ # Event parser + WebSocket/poll subscriptions
204
+ │ ├── idl/ # Synced Anchor IDL (source of truth)
205
+ │ └── node/ # Node-only admin helpers
206
+ ├── react/src/ # Optional React hooks layer
207
+ │ ├── CypherProvider.tsx # Context + provider
208
+ │ ├── useGlobalState.ts # Read hook
209
+ │ ├── useMarket.ts # Read hooks (single + filtered)
210
+ │ ├── useUserPositions.ts # Read hook
211
+ │ ├── mutations.ts # Write hooks (all actions)
212
+ │ └── useMarketEvents.ts # Live event subscription hook
213
+ └── tests/
214
+ ├── unit/ # 107 tests, 581 assertions
215
+ ├── integration/ # Localnet lifecycle (INTEGRATION=1)
216
+ └── devnet/ # Devnet smoke test (DEVNET=1)
217
+ ```
218
+
219
+ ## Cluster Configuration
220
+
221
+ The SDK is **cluster-agnostic** — it reads `GlobalState.accepted_mint` on-chain at runtime:
222
+
223
+ | Cluster | Accepted Mint | Arcium Cluster Offset |
224
+ | --- | --- | --- |
225
+ | `devnet` | CSDC (`8AF9BABN…`) | `456` |
226
+ | `mainnet` | USDC (`EPjFWdd5…`) | TBD |
227
+ | `localnet` | CSDC (same as devnet) | `1116522022` |
228
+
229
+ Override cluster detection:
230
+
231
+ ```ts
232
+ // Explicit preset
233
+ const client = new CypherClient({ connection, wallet, cluster: "devnet" });
234
+
235
+ // Fully custom
236
+ const client = new CypherClient({
237
+ connection, wallet,
238
+ cluster: {
239
+ name: "devnet",
240
+ rpc: "https://my-helius-rpc.com",
241
+ arciumClusterOffset: 456,
242
+ expectedMint: new PublicKey("8AF9BABNWwEhipRxtXPYoWSZW24SKjUn6YqbKd9ZqhwB"),
243
+ },
244
+ });
245
+ ```
246
+
247
+ ## Scripts
248
+
249
+ ```bash
250
+ bun run build # Build dist/ with tsup
251
+ bun run typecheck # Type-check without emitting
252
+ bun run test # All unit tests
253
+ bun run test:unit # Unit tests only
254
+ bun run test:integration # Integration (requires localnet)
255
+ bun run test:devnet # Devnet smoke (requires DEVNET_KEYPAIR)
256
+ bun run sync:idl # Copy IDL from ../cypher-main
257
+ bun run clean # Remove dist/
258
+ ```
259
+
260
+ ## Security
261
+
262
+ The Cypher protocol has undergone a comprehensive security audit (June 2026). All 9 findings — including 3 critical, 2 high, and 4 medium/low — have been fully remediated and verified in a second-round audit. See `cypher-main/audit_report.md` for the full report.
263
+
264
+ ## License
265
+
266
+ Source Available — use is permitted, redistribution is not. See [LICENSE](./LICENSE) for full terms.
@@ -0,0 +1,29 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ export { __commonJS, __toESM };
28
+ //# sourceMappingURL=chunk-5WRI5ZAA.js.map
29
+ //# sourceMappingURL=chunk-5WRI5ZAA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-5WRI5ZAA.js"}