@cypher-zk/sdk 0.5.0 → 0.6.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
@@ -5,7 +5,7 @@
5
5
  [![tests](https://img.shields.io/badge/tests-150%20passing-brightgreen)]()
6
6
  [![typecheck](https://img.shields.io/badge/typecheck-clean-brightgreen)]()
7
7
  [![bundle](https://img.shields.io/badge/dist-ESM%20%2B%20.d.ts-blue)]()
8
- [![version](https://img.shields.io/badge/version-0.2.0-blue)]()
8
+ [![version](https://img.shields.io/badge/version-0.5.0-blue)]()
9
9
  [![license](https://img.shields.io/badge/license-Source%20Available-orange.svg)](./LICENSE)
10
10
 
11
11
  A framework-agnostic core (Node, Bun, browser) with an optional React
@@ -42,8 +42,8 @@ const result = await client.actions.placeBet({
42
42
  payer: wallet.publicKey,
43
43
  user: wallet.publicKey,
44
44
  marketId: 7n,
45
- side: 1, // 1 = YES
46
- amountUsdc: 5_000_000n, // $5 (6 decimals)
45
+ side: 1, // 1 = YES
46
+ amountUsdc: 5_000_000n, // $5 (6 decimals)
47
47
  onProgress: (e) => updateLoaderUI(e.stage, e.message),
48
48
  });
49
49
  // Persist result.userKeypair.privateKey under the wallet's key — that's
@@ -102,9 +102,9 @@ npm install @cypher-zk/sdk
102
102
 
103
103
  ### Peer dependencies
104
104
 
105
- | Package | Required for |
106
- | --- | --- |
107
- | `react` ^18 \|\| ^19 | `@cypher-zk/sdk/react` subpath only |
105
+ | Package | Required for |
106
+ | -------------------------- | ----------------------------------- |
107
+ | `react` ^18 \|\| ^19 | `@cypher-zk/sdk/react` subpath only |
108
108
  | `@tanstack/react-query` ^5 | `@cypher-zk/sdk/react` subpath only |
109
109
 
110
110
  Core SDK works in any TypeScript environment with no peer requirements.
@@ -134,8 +134,8 @@ const gs = await client.globalState.fetch();
134
134
  console.log("Protocol fee:", gs.protocolFeeRate, "bps");
135
135
 
136
136
  const market = await client.markets.fetch(0n);
137
- const active = await client.markets.byState(0); // MarketState.Active
138
- const mine = await client.markets.byCreator(wallet.publicKey);
137
+ const active = await client.markets.byState(0); // MarketState.Active
138
+ const mine = await client.markets.byCreator(wallet.publicKey);
139
139
  const myBets = await client.positions.byUser(wallet.publicKey);
140
140
  ```
141
141
 
@@ -149,15 +149,20 @@ const preview = computeFees(5_000_000n, {
149
149
  protocolFeeRateBps: gs.protocolFeeRate,
150
150
  lpFeeRateBps: gs.lpFeeRate,
151
151
  });
152
- console.log("Net stake:", preview.netAmount, "after fees:", preview.protocolFee + preview.lpFee);
152
+ console.log(
153
+ "Net stake:",
154
+ preview.netAmount,
155
+ "after fees:",
156
+ preview.protocolFee + preview.lpFee,
157
+ );
153
158
 
154
159
  // Fire the end-to-end flow:
155
160
  const { signature, position, userKeypair } = await client.actions.placeBet({
156
161
  payer: wallet.publicKey,
157
162
  user: wallet.publicKey,
158
163
  marketId: 0n,
159
- side: 1, // 0 = NO, 1 = YES
160
- amountUsdc: 5_000_000n, // $5 (USDC has 6 decimals)
164
+ side: 1, // 0 = NO, 1 = YES
165
+ amountUsdc: 5_000_000n, // $5 (USDC has 6 decimals)
161
166
  onProgress: ({ stage, message, signature }) => {
162
167
  // stage ∈ "validating" | "fetching-state" | "encrypting" | "submitting"
163
168
  // | "awaiting-callback" | "refetching" | "done"
@@ -190,7 +195,7 @@ const { marketId, marketPda, signature } = await client.actions.createMarket({
190
195
  creator: wallet.publicKey,
191
196
  question: "Will ETH hit $10k by end of 2026?",
192
197
  closeTime: BigInt(Math.floor(Date.now() / 1000) + 7 * 24 * 3600),
193
- category: 0, // MarketCategory.Crypto
198
+ category: 0, // MarketCategory.Crypto
194
199
  // v0.2+: optional. Defaults to MIN_CHALLENGE_PERIOD_SECS (24h).
195
200
  // Must be in [MIN_CHALLENGE_PERIOD_SECS, MAX_CHALLENGE_PERIOD_SECS]
196
201
  // (24h–48h). Pin shorter for prediction markets that settle fast.
@@ -244,7 +249,9 @@ refund) so the user never burns gas on a guaranteed-to-fail tx.
244
249
  // Real-time (WebSocket):
245
250
  const sub = client.events.onBetPlaced((data) => {
246
251
  // `data` is BetPlacedEvent — fully typed (camelCase fields, bigint amounts):
247
- console.log(`Bet placed on market ${data.market.toBase58()} — odds ${data.entryOdds}`);
252
+ console.log(
253
+ `Bet placed on market ${data.market.toBase58()} — odds ${data.entryOdds}`,
254
+ );
248
255
  });
249
256
 
250
257
  // Generic, typed by name:
@@ -275,9 +282,14 @@ for (const { event, signature, slot } of recent) {
275
282
 
276
283
  // Parse events out of a known transaction:
277
284
  import { parseLogs, parseLogsFor } from "@cypher-zk/sdk";
278
- const tx = await connection.getTransaction(sig, { maxSupportedTransactionVersion: 0 });
279
- const allEvents = parseLogs(tx?.meta?.logMessages ?? []);
280
- const payoutsOnly = parseLogsFor(tx?.meta?.logMessages ?? [], "PayoutClaimedEvent");
285
+ const tx = await connection.getTransaction(sig, {
286
+ maxSupportedTransactionVersion: 0,
287
+ });
288
+ const allEvents = parseLogs(tx?.meta?.logMessages ?? []);
289
+ const payoutsOnly = parseLogsFor(
290
+ tx?.meta?.logMessages ?? [],
291
+ "PayoutClaimedEvent",
292
+ );
281
293
  ```
282
294
 
283
295
  ### 7. Phase helpers
@@ -287,20 +299,32 @@ import { marketPhase, projectDeadlines } from "@cypher-zk/sdk";
287
299
 
288
300
  // Compute what action is currently available on a market:
289
301
  switch (marketPhase(market)) {
290
- case "betting": /* show "Bet" button */ break;
291
- case "awaitingResolve": /* show "Pending resolution" */ break;
292
- case "pendingResolution": /* v0.2: in challenge window — show countdown + "Flag" */ break;
293
- case "awaitingFinalize": /* v0.2: window elapsed — show "Finalize" button */ break;
294
- case "disputed": /* v0.2: flagged — admin override required */ break;
295
- case "claimable": /* show "Claim payout" */ break;
296
- case "refundable": /* show "Claim refund" */ break;
297
- case "expired": /* show "Admin sweep eligible" */ break;
298
- case "cancelled": /* show "Cancelled" */ break;
302
+ case "betting":
303
+ /* show "Bet" button */ break;
304
+ case "awaitingResolve":
305
+ /* show "Pending resolution" */ break;
306
+ case "pendingResolution":
307
+ /* v0.2: in challenge window — show countdown + "Flag" */ break;
308
+ case "awaitingFinalize":
309
+ /* v0.2: window elapsed — show "Finalize" button */ break;
310
+ case "disputed":
311
+ /* v0.2: flagged — admin override required */ break;
312
+ case "claimable":
313
+ /* show "Claim payout" */ break;
314
+ case "refundable":
315
+ /* show "Claim refund" */ break;
316
+ case "expired":
317
+ /* show "Admin sweep eligible" */ break;
318
+ case "cancelled":
319
+ /* show "Cancelled" */ break;
299
320
  }
300
321
 
301
322
  // Preview deadlines for a draft market the user is filling in:
302
323
  const projected = projectDeadlines(BigInt(closeTimeSec));
303
- console.log("Resolution deadline:", new Date(Number(projected.resolutionDeadline) * 1000));
324
+ console.log(
325
+ "Resolution deadline:",
326
+ new Date(Number(projected.resolutionDeadline) * 1000),
327
+ );
304
328
  ```
305
329
 
306
330
  ---
@@ -376,12 +400,12 @@ stages and refuses pre-flight if the market isn't in the right phase
376
400
  `marketPhase(market)` returns the three new values whenever
377
401
  `state === PendingResolution`:
378
402
 
379
- | `marketPhase` | Meaning | Clickable |
380
- | --- | --- | --- |
381
- | `"pendingResolution"` | inside challenge window, not flagged | `flagResolution` (any user) |
382
- | `"awaitingFinalize"` | window elapsed, not flagged | `finalizeResolution` (any user) |
383
- | `"disputed"` | flagged during window | `adminOverrideResolution` (admin only) |
384
- | `"claimable"` | finalized → window closed (state=Resolved) | `claimPayout` |
403
+ | `marketPhase` | Meaning | Clickable |
404
+ | --------------------- | ------------------------------------------ | -------------------------------------- |
405
+ | `"pendingResolution"` | inside challenge window, not flagged | `flagResolution` (any user) |
406
+ | `"awaitingFinalize"` | window elapsed, not flagged | `finalizeResolution` (any user) |
407
+ | `"disputed"` | flagged during window | `adminOverrideResolution` (admin only) |
408
+ | `"claimable"` | finalized → window closed (state=Resolved) | `claimPayout` |
385
409
 
386
410
  `claimPayoutAction` and `useClaimPayout` reject pre-flight in the
387
411
  first three phases with a hint to call `finalizeResolution` first.
@@ -406,8 +430,13 @@ function ChallengeWindowControls({ marketId }: { marketId: bigint }) {
406
430
  if (phase === "pendingResolution") {
407
431
  return (
408
432
  <>
409
- <p>Challenge closes at {new Date(Number(market.challengeDeadline) * 1000).toLocaleString()}</p>
410
- <button onClick={() => flag.mutate({ flagger: wallet.publicKey!, marketId })}>
433
+ <p>
434
+ Challenge closes at{" "}
435
+ {new Date(Number(market.challengeDeadline) * 1000).toLocaleString()}
436
+ </p>
437
+ <button
438
+ onClick={() => flag.mutate({ flagger: wallet.publicKey!, marketId })}
439
+ >
411
440
  Flag this resolution
412
441
  </button>
413
442
  </>
@@ -415,7 +444,9 @@ function ChallengeWindowControls({ marketId }: { marketId: bigint }) {
415
444
  }
416
445
  if (phase === "awaitingFinalize") {
417
446
  return (
418
- <button onClick={() => finalize.mutate({ caller: wallet.publicKey!, marketId })}>
447
+ <button
448
+ onClick={() => finalize.mutate({ caller: wallet.publicKey!, marketId })}
449
+ >
419
450
  Finalize resolution
420
451
  </button>
421
452
  );
@@ -429,9 +460,9 @@ function ChallengeWindowControls({ marketId }: { marketId: bigint }) {
429
460
 
430
461
  ### Defaults & bounds
431
462
 
432
- | Constant | Value | Notes |
433
- | --- | --- | --- |
434
- | `MIN_CHALLENGE_PERIOD_SECS` | `24 * 3600` (24h) | Action helpers default here |
463
+ | Constant | Value | Notes |
464
+ | --------------------------- | ----------------- | --------------------------------- |
465
+ | `MIN_CHALLENGE_PERIOD_SECS` | `24 * 3600` (24h) | Action helpers default here |
435
466
  | `MAX_CHALLENGE_PERIOD_SECS` | `48 * 3600` (48h) | Hard ceiling enforced by contract |
436
467
 
437
468
  The high-level `client.actions.createMarket` makes `challengePeriod`
@@ -441,14 +472,14 @@ client-side before the tx is built.
441
472
 
442
473
  ### Six new error codes
443
474
 
444
- | Code | Name | When |
445
- | --- | --- | --- |
446
- | `6036` | `InvalidChallengePeriod` | `challengePeriod` outside 24h–48h |
447
- | `6037` | `NotPendingResolution` | flag/finalize/override on wrong state |
448
- | `6038` | `ChallengePeriodNotElapsed` | finalize called too early |
449
- | `6039` | `ChallengePeriodElapsed` | flag called after window closed |
450
- | `6040` | `MarketDisputed` | finalize on a flagged market |
451
- | `6041` | `MarketNotDisputed` | admin override on a clean market |
475
+ | Code | Name | When |
476
+ | ------ | --------------------------- | ------------------------------------- |
477
+ | `6036` | `InvalidChallengePeriod` | `challengePeriod` outside 24h–48h |
478
+ | `6037` | `NotPendingResolution` | flag/finalize/override on wrong state |
479
+ | `6038` | `ChallengePeriodNotElapsed` | finalize called too early |
480
+ | `6039` | `ChallengePeriodElapsed` | flag called after window closed |
481
+ | `6040` | `MarketDisputed` | finalize on a flagged market |
482
+ | `6041` | `MarketNotDisputed` | admin override on a clean market |
452
483
 
453
484
  Use `parseCypherError(err)` to extract a typed `CypherErrorCode` for
454
485
  branching.
@@ -498,7 +529,7 @@ function MarketView({ marketId }: { marketId: bigint }) {
498
529
  });
499
530
 
500
531
  if (isLoading) return <p>Loading market…</p>;
501
- if (!market) return <p>Market not found.</p>;
532
+ if (!market) return <p>Market not found.</p>;
502
533
 
503
534
  return (
504
535
  <div>
@@ -518,7 +549,9 @@ function MarketView({ marketId }: { marketId: bigint }) {
518
549
  >
519
550
  {placeBet.isPending && stage ? `Bet → ${stage.stage}` : "Bet $5 YES"}
520
551
  </button>
521
- {placeBet.error && <p style={{ color: "crimson" }}>{placeBet.error.message}</p>}
552
+ {placeBet.error && (
553
+ <p style={{ color: "crimson" }}>{placeBet.error.message}</p>
554
+ )}
522
555
  </div>
523
556
  );
524
557
  }
@@ -526,22 +559,22 @@ function MarketView({ marketId }: { marketId: bigint }) {
526
559
 
527
560
  ### Available hooks
528
561
 
529
- | Hook | Kind | Description |
530
- | --- | --- | --- |
531
- | `useGlobalState()` | Query | Protocol config (fees, mint, admin, counter) |
532
- | `useMarket(id)` | Query | Single market by ID |
533
- | `useMarkets(filter?)` | Query | All/filtered markets (creator, state) |
534
- | `useUserPositions(user)` | Query | All bet positions for a user |
535
- | `usePlaceBet()` | Mutation | End-to-end private bet |
536
- | `useCreateMarket()` | Mutation | Create a new market |
537
- | `useResolveMarket()` | Mutation | Submit outcome + await reveal |
538
- | `useClaimPayout()` | Mutation | Claim winning payout |
539
- | `useClaimRefund()` | Mutation | Claim refund on unresolved market |
540
- | `useCancelMarket()` | Mutation | Cancel a zero-bet market |
541
- | `useFlagResolution()` *(v0.2)* | Mutation | Flag a pending resolution during the challenge window |
542
- | `useFinalizeResolution()` *(v0.2)* | Mutation | Finalize a pending resolution after the window elapses undisputed |
543
- | `useAdminOverrideResolution()` *(v0.2)* | Mutation | Admin re-resolves a disputed market |
544
- | `useMarketEvents()` | Subscription | Live event stream (component-scoped) |
562
+ | Hook | Kind | Description |
563
+ | --------------------------------------- | ------------ | ----------------------------------------------------------------- |
564
+ | `useGlobalState()` | Query | Protocol config (fees, mint, admin, counter) |
565
+ | `useMarket(id)` | Query | Single market by ID |
566
+ | `useMarkets(filter?)` | Query | All/filtered markets (creator, state) |
567
+ | `useUserPositions(user)` | Query | All bet positions for a user |
568
+ | `usePlaceBet()` | Mutation | End-to-end private bet |
569
+ | `useCreateMarket()` | Mutation | Create a new market |
570
+ | `useResolveMarket()` | Mutation | Submit outcome + await reveal |
571
+ | `useClaimPayout()` | Mutation | Claim winning payout |
572
+ | `useClaimRefund()` | Mutation | Claim refund on unresolved market |
573
+ | `useCancelMarket()` | Mutation | Cancel a zero-bet market |
574
+ | `useFlagResolution()` _(v0.2)_ | Mutation | Flag a pending resolution during the challenge window |
575
+ | `useFinalizeResolution()` _(v0.2)_ | Mutation | Finalize a pending resolution after the window elapses undisputed |
576
+ | `useAdminOverrideResolution()` _(v0.2)_ | Mutation | Admin re-resolves a disputed market |
577
+ | `useMarketEvents()` | Subscription | Live event stream (component-scoped) |
545
578
 
546
579
  Mutation hooks auto-invalidate the relevant query keys on success. Read
547
580
  hooks expose their `queryKey` factories (`marketKeys.one(id)`,
@@ -597,11 +630,11 @@ The SDK is **cluster-agnostic at runtime**: it reads the accepted SPL mint
597
630
  from `GlobalState.accepted_mint` on every flow rather than hard-coding
598
631
  CSDC vs USDC. The same build works against any Cypher deployment.
599
632
 
600
- | Cluster | RPC default | Accepted mint | Arcium offset |
601
- | --- | --- | --- | --- |
602
- | `devnet` | `api.devnet.solana.com` | CSDC (`8AF9BABN…`) | `456` |
603
- | `mainnet` | `api.mainnet-beta.solana.com` | USDC (`EPjFWdd5…`) | (set at deploy) |
604
- | `localnet` | `localhost:8899` | CSDC (test build) | `1116522022` |
633
+ | Cluster | RPC default | Accepted mint | Arcium offset |
634
+ | ---------- | ----------------------------- | ------------------ | --------------- |
635
+ | `devnet` | `api.devnet.solana.com` | CSDC (`8AF9BABN…`) | `456` |
636
+ | `mainnet` | `api.mainnet-beta.solana.com` | USDC (`EPjFWdd5…`) | (set at deploy) |
637
+ | `localnet` | `localhost:8899` | CSDC (test build) | `1116522022` |
605
638
 
606
639
  ```ts
607
640
  // Explicit preset:
@@ -624,17 +657,17 @@ const client = new CypherClient({
624
657
 
625
658
  ## Scripts
626
659
 
627
- | Command | Purpose |
628
- | --- | --- |
629
- | `bun install` | Install deps |
630
- | `bun test` | All unit suites (gates skipped) |
631
- | `bun run test:unit` | Unit-only |
632
- | `bun run test:integration` | `INTEGRATION=1` — Arcium localnet lifecycle |
633
- | `bun run test:devnet` | `DEVNET=1` — devnet read-only + opt-in writes |
634
- | `bun run typecheck` | `tsc --noEmit` (strict) |
635
- | `bun run build` | ESM + `.d.ts` via tsup → `dist/` |
636
- | `bun run sync:idl` | Re-copy IDL + types from `../cypher-main` |
637
- | `bun run prepublishOnly` | sync IDL → typecheck → unit tests → build |
660
+ | Command | Purpose |
661
+ | -------------------------- | --------------------------------------------- |
662
+ | `bun install` | Install deps |
663
+ | `bun test` | All unit suites (gates skipped) |
664
+ | `bun run test:unit` | Unit-only |
665
+ | `bun run test:integration` | `INTEGRATION=1` — Arcium localnet lifecycle |
666
+ | `bun run test:devnet` | `DEVNET=1` — devnet read-only + opt-in writes |
667
+ | `bun run typecheck` | `tsc --noEmit` (strict) |
668
+ | `bun run build` | ESM + `.d.ts` via tsup → `dist/` |
669
+ | `bun run sync:idl` | Re-copy IDL + types from `../cypher-main` |
670
+ | `bun run prepublishOnly` | sync IDL → typecheck → unit tests → build |
638
671
 
639
672
  ---
640
673
 
@@ -674,7 +707,7 @@ The SDK adds defense-in-depth client-side:
674
707
 
675
708
  - **NEW**: 3 instructions (`flagResolution`, `finalizeResolution`,
676
709
  `adminOverrideResolution`) + 3 actions + 3 React hooks + 3 events
677
- + 6 error codes (6036–6041).
710
+ - 6 error codes (6036–6041).
678
711
  - **NEW**: `MarketState.PendingResolution = 4` and three new
679
712
  `marketPhase` values: `pendingResolution`, `awaitingFinalize`,
680
713
  `disputed`.
@@ -105,12 +105,15 @@ declare const positionKeys: {
105
105
  /**
106
106
  * Fetch all positions for a given user across all markets.
107
107
  *
108
+ * Accepts `PublicKey | null` — when `user` is `null` the query is
109
+ * automatically disabled so no RPC call is made and no crash occurs.
110
+ *
108
111
  * @example
109
112
  * ```tsx
110
113
  * const { data: positions } = useUserPositions(wallet.publicKey);
111
114
  * ```
112
115
  */
113
- declare function useUserPositions(user: PublicKey, opts?: Omit<UseQueryOptions<Array<{
116
+ declare function useUserPositions(user: PublicKey | null, opts?: Omit<UseQueryOptions<Array<{
114
117
  publicKey: PublicKey;
115
118
  account: EncryptedPositionAccount;
116
119
  }>, Error>, "queryKey" | "queryFn">): _tanstack_react_query.UseQueryResult<NoInfer<{
@@ -66,9 +66,10 @@ var positionKeys = {
66
66
  function useUserPositions(user, opts) {
67
67
  const client = useCypherClient();
68
68
  return useQuery({
69
- queryKey: positionKeys.byUser(user),
69
+ queryKey: user ? positionKeys.byUser(user) : ["cypher", "position", "user", null],
70
70
  queryFn: () => client.positions.byUser(user),
71
71
  staleTime: 5e3,
72
+ enabled: !!user,
72
73
  ...opts
73
74
  });
74
75
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../react/src/CypherProvider.tsx","../../react/src/useGlobalState.ts","../../react/src/useMarket.ts","../../react/src/useUserPositions.ts","../../react/src/mutations.ts","../../react/src/useMarketEvents.ts"],"names":["useQuery"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { CypherClient } from \"../../src/client.ts\";\n\n/* -----------------------------------------------------------------------\n * Context\n * ----------------------------------------------------------------------- */\n\ninterface CypherContextValue {\n client: CypherClient;\n}\n\nconst CypherContext = createContext<CypherContextValue | null>(null);\n\n/* -----------------------------------------------------------------------\n * Provider\n * ----------------------------------------------------------------------- */\n\nexport interface CypherProviderProps {\n /**\n * A fully-constructed `CypherClient`. The provider does NOT manage\n * lifecycle — the host app creates the client (with its own connection\n * + wallet) and passes it in.\n */\n client: CypherClient;\n children: ReactNode;\n}\n\n/**\n * Provides a `CypherClient` instance to the React tree. All SDK hooks\n * read from this context — mount exactly one `<CypherProvider>` at the\n * top of your app (or the feature subtree that needs it).\n *\n * @example\n * ```tsx\n * import { CypherClient } from \"@cypher/sdk\";\n * import { CypherProvider } from \"@cypher/sdk/react\";\n *\n * const client = new CypherClient({ connection, wallet, cluster: \"devnet\" });\n *\n * function App() {\n * return (\n * <CypherProvider client={client}>\n * <MarketList />\n * </CypherProvider>\n * );\n * }\n * ```\n */\nexport function CypherProvider({ client, children }: CypherProviderProps) {\n const value = useMemo<CypherContextValue>(() => ({ client }), [client]);\n return React.createElement(CypherContext.Provider, { value }, children);\n}\n\n/* -----------------------------------------------------------------------\n * Hook\n * ----------------------------------------------------------------------- */\n\n/**\n * Returns the `CypherClient` from the nearest `<CypherProvider>`.\n * Throws if called outside the provider tree.\n */\nexport function useCypherClient(): CypherClient {\n const ctx = useContext(CypherContext);\n if (!ctx) {\n throw new Error(\n \"useCypherClient must be used within a <CypherProvider>. \" +\n \"Wrap your component tree with <CypherProvider client={client}>.\",\n );\n }\n return ctx.client;\n}\n","\"use client\";\n\nimport { useQuery, type UseQueryOptions } from \"@tanstack/react-query\";\nimport { useCypherClient } from \"./CypherProvider.tsx\";\nimport type { GlobalStateAccount } from \"../../src/accounts/globalState.ts\";\n\n/** Query key factory — keeps cache keys stable across the app. */\nexport const globalStateKeys = {\n all: [\"cypher\", \"globalState\"] as const,\n};\n\n/**\n * Fetches the on-chain `GlobalState` singleton (protocol fees, admin,\n * accepted mint, market counter). Automatically cached via React Query.\n *\n * @example\n * ```tsx\n * const { data: gs, isLoading } = useGlobalState();\n * if (gs) console.log(\"Fee rate:\", gs.protocolFeeRate);\n * ```\n */\nexport function useGlobalState(\n opts?: Omit<\n UseQueryOptions<GlobalStateAccount, Error>,\n \"queryKey\" | \"queryFn\"\n >,\n) {\n const client = useCypherClient();\n return useQuery<GlobalStateAccount, Error>({\n queryKey: globalStateKeys.all,\n queryFn: () => client.globalState.fetch({ refresh: true }),\n staleTime: 30_000, // 30s — global state changes rarely\n ...opts,\n });\n}\n","\"use client\";\n\nimport { useQuery, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type { PublicKey } from \"@solana/web3.js\";\nimport { useCypherClient } from \"./CypherProvider.tsx\";\nimport type { MarketAccount } from \"../../src/accounts/market.ts\";\n\nexport const marketKeys = {\n all: [\"cypher\", \"market\"] as const,\n one: (id: bigint | number) => [\"cypher\", \"market\", String(id)] as const,\n byCreator: (creator: PublicKey) =>\n [\"cypher\", \"market\", \"creator\", creator.toBase58()] as const,\n byState: (state: number) =>\n [\"cypher\", \"market\", \"state\", state] as const,\n};\n\n/**\n * Fetch a single market by its numeric `marketId`.\n *\n * @example\n * ```tsx\n * const { data: market } = useMarket(42n);\n * ```\n */\nexport function useMarket(\n marketId: bigint | number,\n opts?: Omit<\n UseQueryOptions<MarketAccount | null, Error>,\n \"queryKey\" | \"queryFn\"\n >,\n) {\n const client = useCypherClient();\n return useQuery<MarketAccount | null, Error>({\n queryKey: marketKeys.one(marketId),\n queryFn: () => client.markets.fetch(marketId),\n staleTime: 10_000,\n ...opts,\n });\n}\n\nexport interface UseMarketsFilter {\n creator?: PublicKey;\n state?: number;\n}\n\n/**\n * Fetch multiple markets, optionally filtered by creator or state.\n * With no filter, fetches **all** markets (expensive on large deployments).\n *\n * @example\n * ```tsx\n * const { data: active } = useMarkets({ state: MarketState.Active });\n * ```\n */\nexport function useMarkets(\n filter?: UseMarketsFilter,\n opts?: Omit<\n UseQueryOptions<\n Array<{ publicKey: PublicKey; account: MarketAccount }>,\n Error\n >,\n \"queryKey\" | \"queryFn\"\n >,\n) {\n const client = useCypherClient();\n\n const queryKey = filter?.creator\n ? marketKeys.byCreator(filter.creator)\n : filter?.state !== undefined\n ? marketKeys.byState(filter.state)\n : marketKeys.all;\n\n const queryFn = () => {\n if (filter?.creator) return client.markets.byCreator(filter.creator);\n if (filter?.state !== undefined) return client.markets.byState(filter.state);\n return client.markets.all();\n };\n\n return useQuery({\n queryKey,\n queryFn,\n staleTime: 10_000,\n ...opts,\n });\n}\n","\"use client\";\n\nimport { useQuery, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type { PublicKey } from \"@solana/web3.js\";\nimport { useCypherClient } from \"./CypherProvider.tsx\";\nimport type { EncryptedPositionAccount } from \"../../src/accounts/position.ts\";\n\nexport const positionKeys = {\n byUser: (user: PublicKey) =>\n [\"cypher\", \"position\", \"user\", user.toBase58()] as const,\n forMarket: (market: PublicKey) =>\n [\"cypher\", \"position\", \"market\", market.toBase58()] as const,\n};\n\n/**\n * Fetch all positions for a given user across all markets.\n *\n * @example\n * ```tsx\n * const { data: positions } = useUserPositions(wallet.publicKey);\n * ```\n */\nexport function useUserPositions(\n user: PublicKey,\n opts?: Omit<\n UseQueryOptions<\n Array<{ publicKey: PublicKey; account: EncryptedPositionAccount }>,\n Error\n >,\n \"queryKey\" | \"queryFn\"\n >,\n) {\n const client = useCypherClient();\n return useQuery({\n queryKey: positionKeys.byUser(user),\n queryFn: () => client.positions.byUser(user),\n staleTime: 5_000,\n ...opts,\n });\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient, type UseMutationOptions } from \"@tanstack/react-query\";\nimport { useCypherClient } from \"./CypherProvider.tsx\";\nimport { marketKeys } from \"./useMarket.ts\";\nimport { positionKeys } from \"./useUserPositions.ts\";\nimport type { PlaceBetInputs, PlaceBetResult } from \"../../src/actions/placeBet.ts\";\nimport type { ResolveMarketInputs, ResolveMarketResult } from \"../../src/actions/resolveMarket.ts\";\nimport type { ClaimInputs, ClaimResult } from \"../../src/actions/claim.ts\";\nimport type { CreateMarketResult } from \"../../src/actions/createMarket.ts\";\nimport type {\n CreateMarketParams,\n CancelMarketParams,\n} from \"../../src/instructions/market.ts\";\nimport type { PublicKey } from \"@solana/web3.js\";\nimport type { MarketAccount } from \"../../src/accounts/market.ts\";\n\n/* -----------------------------------------------------------------------\n * usePlaceBet\n * ----------------------------------------------------------------------- */\n\n/**\n * Mutation hook for the end-to-end `placeBet` action: encrypt → send →\n * await callback → refetch position. Invalidates the market + position\n * queries on success.\n *\n * @example\n * ```tsx\n * const { mutateAsync: placeBet, isPending } = usePlaceBet();\n * await placeBet({ payer: wallet.publicKey, user: wallet.publicKey, marketId: 1n, side: 0, amountUsdc: 5_000_000n });\n * ```\n */\nexport function usePlaceBet(\n opts?: Omit<UseMutationOptions<PlaceBetResult, Error, PlaceBetInputs>, \"mutationFn\">,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<PlaceBetResult, Error, PlaceBetInputs>({\n mutationFn: (inputs) => client.actions.placeBet(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n qc.invalidateQueries({ queryKey: positionKeys.byUser(vars.user) });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * useResolveMarket\n * ----------------------------------------------------------------------- */\n\nexport function useResolveMarket(\n opts?: Omit<UseMutationOptions<ResolveMarketResult, Error, ResolveMarketInputs>, \"mutationFn\">,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ResolveMarketResult, Error, ResolveMarketInputs>({\n mutationFn: (inputs) => client.actions.resolveMarket(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * useClaimPayout\n * ----------------------------------------------------------------------- */\n\nexport function useClaimPayout(\n opts?: Omit<UseMutationOptions<ClaimResult, Error, ClaimInputs>, \"mutationFn\">,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ClaimResult, Error, ClaimInputs>({\n mutationFn: (inputs) => client.actions.claimPayout(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n qc.invalidateQueries({ queryKey: positionKeys.byUser(vars.user) });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * useClaimRefund\n * ----------------------------------------------------------------------- */\n\nexport function useClaimRefund(\n opts?: Omit<UseMutationOptions<ClaimResult, Error, ClaimInputs>, \"mutationFn\">,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ClaimResult, Error, ClaimInputs>({\n mutationFn: (inputs) => client.actions.claimRefund(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n qc.invalidateQueries({ queryKey: positionKeys.byUser(vars.user) });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * useCreateMarket\n * ----------------------------------------------------------------------- */\n\ntype CreateMarketInputs = Omit<CreateMarketParams, \"expectedMarketId\" | \"acceptedMint\"> & {\n acceptedMint?: PublicKey;\n};\n\nexport function useCreateMarket(\n opts?: Omit<UseMutationOptions<CreateMarketResult, Error, CreateMarketInputs>, \"mutationFn\">,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<CreateMarketResult, Error, CreateMarketInputs>({\n mutationFn: (inputs) => client.actions.createMarket(inputs),\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: marketKeys.all });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * useCancelMarket\n * ----------------------------------------------------------------------- */\n\ntype CancelMarketInputs = Omit<CancelMarketParams, \"acceptedMint\"> & {\n acceptedMint?: PublicKey;\n};\n\nexport function useCancelMarket(\n opts?: Omit<\n UseMutationOptions<{ signature: string; market: MarketAccount | null }, Error, CancelMarketInputs>,\n \"mutationFn\"\n >,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (inputs: CancelMarketInputs) => client.actions.cancelMarket(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n qc.invalidateQueries({ queryKey: marketKeys.all });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * Dispute / challenge window mutation hooks (v0.2+)\n * ----------------------------------------------------------------------- */\n\nimport type {\n FlagResolutionInputs,\n FinalizeResolutionInputs,\n AdminOverrideResolutionInputs,\n ResolutionActionResult,\n} from \"../../src/actions/resolution.ts\";\n\nexport function useFlagResolution(\n opts?: Omit<\n UseMutationOptions<ResolutionActionResult, Error, FlagResolutionInputs>,\n \"mutationFn\"\n >,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ResolutionActionResult, Error, FlagResolutionInputs>({\n mutationFn: (inputs) => client.actions.flagResolution(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n },\n ...opts,\n });\n}\n\nexport function useFinalizeResolution(\n opts?: Omit<\n UseMutationOptions<ResolutionActionResult, Error, FinalizeResolutionInputs>,\n \"mutationFn\"\n >,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ResolutionActionResult, Error, FinalizeResolutionInputs>({\n mutationFn: (inputs) => client.actions.finalizeResolution(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n },\n ...opts,\n });\n}\n\nexport function useAdminOverrideResolution(\n opts?: Omit<\n UseMutationOptions<ResolutionActionResult, Error, AdminOverrideResolutionInputs>,\n \"mutationFn\"\n >,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ResolutionActionResult, Error, AdminOverrideResolutionInputs>({\n mutationFn: (inputs) => client.actions.adminOverrideResolution(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n },\n ...opts,\n });\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { useCypherClient } from \"./CypherProvider.tsx\";\nimport type { CypherEvent } from \"../../src/events/parser.ts\";\nimport type { EventSubscription, SubscribeOptions } from \"../../src/events/subscribe.ts\";\n\n/**\n * Subscribe to all Cypher events for the lifetime of the component.\n * Returns the latest batch of events as an ever-growing array (newest\n * last). Clear the buffer by re-mounting the component.\n *\n * @example\n * ```tsx\n * const events = useMarketEvents();\n * // events: CypherEvent[]\n * ```\n */\nexport function useMarketEvents(opts?: SubscribeOptions): CypherEvent[] {\n const client = useCypherClient();\n const [events, setEvents] = useState<CypherEvent[]>([]);\n const subRef = useRef<EventSubscription | null>(null);\n\n useEffect(() => {\n subRef.current = client.events.subscribeAll((event) => {\n setEvents((prev) => [...prev, event]);\n }, opts);\n return () => {\n subRef.current?.unsubscribe();\n subRef.current = null;\n };\n // Re-subscribe when the client identity changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client]);\n\n return events;\n}\n"]}
1
+ {"version":3,"sources":["../../react/src/CypherProvider.tsx","../../react/src/useGlobalState.ts","../../react/src/useMarket.ts","../../react/src/useUserPositions.ts","../../react/src/mutations.ts","../../react/src/useMarketEvents.ts"],"names":["useQuery"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { CypherClient } from \"../../src/client.ts\";\n\n/* -----------------------------------------------------------------------\n * Context\n * ----------------------------------------------------------------------- */\n\ninterface CypherContextValue {\n client: CypherClient;\n}\n\nconst CypherContext = createContext<CypherContextValue | null>(null);\n\n/* -----------------------------------------------------------------------\n * Provider\n * ----------------------------------------------------------------------- */\n\nexport interface CypherProviderProps {\n /**\n * A fully-constructed `CypherClient`. The provider does NOT manage\n * lifecycle — the host app creates the client (with its own connection\n * + wallet) and passes it in.\n */\n client: CypherClient;\n children: ReactNode;\n}\n\n/**\n * Provides a `CypherClient` instance to the React tree. All SDK hooks\n * read from this context — mount exactly one `<CypherProvider>` at the\n * top of your app (or the feature subtree that needs it).\n *\n * @example\n * ```tsx\n * import { CypherClient } from \"@cypher/sdk\";\n * import { CypherProvider } from \"@cypher/sdk/react\";\n *\n * const client = new CypherClient({ connection, wallet, cluster: \"devnet\" });\n *\n * function App() {\n * return (\n * <CypherProvider client={client}>\n * <MarketList />\n * </CypherProvider>\n * );\n * }\n * ```\n */\nexport function CypherProvider({ client, children }: CypherProviderProps) {\n const value = useMemo<CypherContextValue>(() => ({ client }), [client]);\n return React.createElement(CypherContext.Provider, { value }, children);\n}\n\n/* -----------------------------------------------------------------------\n * Hook\n * ----------------------------------------------------------------------- */\n\n/**\n * Returns the `CypherClient` from the nearest `<CypherProvider>`.\n * Throws if called outside the provider tree.\n */\nexport function useCypherClient(): CypherClient {\n const ctx = useContext(CypherContext);\n if (!ctx) {\n throw new Error(\n \"useCypherClient must be used within a <CypherProvider>. \" +\n \"Wrap your component tree with <CypherProvider client={client}>.\",\n );\n }\n return ctx.client;\n}\n","\"use client\";\n\nimport { useQuery, type UseQueryOptions } from \"@tanstack/react-query\";\nimport { useCypherClient } from \"./CypherProvider.tsx\";\nimport type { GlobalStateAccount } from \"../../src/accounts/globalState.ts\";\n\n/** Query key factory — keeps cache keys stable across the app. */\nexport const globalStateKeys = {\n all: [\"cypher\", \"globalState\"] as const,\n};\n\n/**\n * Fetches the on-chain `GlobalState` singleton (protocol fees, admin,\n * accepted mint, market counter). Automatically cached via React Query.\n *\n * @example\n * ```tsx\n * const { data: gs, isLoading } = useGlobalState();\n * if (gs) console.log(\"Fee rate:\", gs.protocolFeeRate);\n * ```\n */\nexport function useGlobalState(\n opts?: Omit<\n UseQueryOptions<GlobalStateAccount, Error>,\n \"queryKey\" | \"queryFn\"\n >,\n) {\n const client = useCypherClient();\n return useQuery<GlobalStateAccount, Error>({\n queryKey: globalStateKeys.all,\n queryFn: () => client.globalState.fetch({ refresh: true }),\n staleTime: 30_000, // 30s — global state changes rarely\n ...opts,\n });\n}\n","\"use client\";\n\nimport { useQuery, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type { PublicKey } from \"@solana/web3.js\";\nimport { useCypherClient } from \"./CypherProvider.tsx\";\nimport type { MarketAccount } from \"../../src/accounts/market.ts\";\n\nexport const marketKeys = {\n all: [\"cypher\", \"market\"] as const,\n one: (id: bigint | number) => [\"cypher\", \"market\", String(id)] as const,\n byCreator: (creator: PublicKey) =>\n [\"cypher\", \"market\", \"creator\", creator.toBase58()] as const,\n byState: (state: number) =>\n [\"cypher\", \"market\", \"state\", state] as const,\n};\n\n/**\n * Fetch a single market by its numeric `marketId`.\n *\n * @example\n * ```tsx\n * const { data: market } = useMarket(42n);\n * ```\n */\nexport function useMarket(\n marketId: bigint | number,\n opts?: Omit<\n UseQueryOptions<MarketAccount | null, Error>,\n \"queryKey\" | \"queryFn\"\n >,\n) {\n const client = useCypherClient();\n return useQuery<MarketAccount | null, Error>({\n queryKey: marketKeys.one(marketId),\n queryFn: () => client.markets.fetch(marketId),\n staleTime: 10_000,\n ...opts,\n });\n}\n\nexport interface UseMarketsFilter {\n creator?: PublicKey;\n state?: number;\n}\n\n/**\n * Fetch multiple markets, optionally filtered by creator or state.\n * With no filter, fetches **all** markets (expensive on large deployments).\n *\n * @example\n * ```tsx\n * const { data: active } = useMarkets({ state: MarketState.Active });\n * ```\n */\nexport function useMarkets(\n filter?: UseMarketsFilter,\n opts?: Omit<\n UseQueryOptions<\n Array<{ publicKey: PublicKey; account: MarketAccount }>,\n Error\n >,\n \"queryKey\" | \"queryFn\"\n >,\n) {\n const client = useCypherClient();\n\n const queryKey = filter?.creator\n ? marketKeys.byCreator(filter.creator)\n : filter?.state !== undefined\n ? marketKeys.byState(filter.state)\n : marketKeys.all;\n\n const queryFn = () => {\n if (filter?.creator) return client.markets.byCreator(filter.creator);\n if (filter?.state !== undefined) return client.markets.byState(filter.state);\n return client.markets.all();\n };\n\n return useQuery({\n queryKey,\n queryFn,\n staleTime: 10_000,\n ...opts,\n });\n}\n","\"use client\";\n\nimport { useQuery, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type { PublicKey } from \"@solana/web3.js\";\nimport { useCypherClient } from \"./CypherProvider.tsx\";\nimport type { EncryptedPositionAccount } from \"../../src/accounts/position.ts\";\n\nexport const positionKeys = {\n byUser: (user: PublicKey) =>\n [\"cypher\", \"position\", \"user\", user.toBase58()] as const,\n forMarket: (market: PublicKey) =>\n [\"cypher\", \"position\", \"market\", market.toBase58()] as const,\n};\n\n/**\n * Fetch all positions for a given user across all markets.\n *\n * Accepts `PublicKey | null` — when `user` is `null` the query is\n * automatically disabled so no RPC call is made and no crash occurs.\n *\n * @example\n * ```tsx\n * const { data: positions } = useUserPositions(wallet.publicKey);\n * ```\n */\nexport function useUserPositions(\n user: PublicKey | null,\n opts?: Omit<\n UseQueryOptions<\n Array<{ publicKey: PublicKey; account: EncryptedPositionAccount }>,\n Error\n >,\n \"queryKey\" | \"queryFn\"\n >,\n) {\n const client = useCypherClient();\n return useQuery({\n queryKey: user\n ? positionKeys.byUser(user)\n : [\"cypher\", \"position\", \"user\", null],\n queryFn: () => client.positions.byUser(user!),\n staleTime: 5_000,\n enabled: !!user,\n ...opts,\n });\n}\n","\"use client\";\n\nimport { useMutation, useQueryClient, type UseMutationOptions } from \"@tanstack/react-query\";\nimport { useCypherClient } from \"./CypherProvider.tsx\";\nimport { marketKeys } from \"./useMarket.ts\";\nimport { positionKeys } from \"./useUserPositions.ts\";\nimport type { PlaceBetInputs, PlaceBetResult } from \"../../src/actions/placeBet.ts\";\nimport type { ResolveMarketInputs, ResolveMarketResult } from \"../../src/actions/resolveMarket.ts\";\nimport type { ClaimInputs, ClaimResult } from \"../../src/actions/claim.ts\";\nimport type { CreateMarketResult } from \"../../src/actions/createMarket.ts\";\nimport type {\n CreateMarketParams,\n CancelMarketParams,\n} from \"../../src/instructions/market.ts\";\nimport type { PublicKey } from \"@solana/web3.js\";\nimport type { MarketAccount } from \"../../src/accounts/market.ts\";\n\n/* -----------------------------------------------------------------------\n * usePlaceBet\n * ----------------------------------------------------------------------- */\n\n/**\n * Mutation hook for the end-to-end `placeBet` action: encrypt → send →\n * await callback → refetch position. Invalidates the market + position\n * queries on success.\n *\n * @example\n * ```tsx\n * const { mutateAsync: placeBet, isPending } = usePlaceBet();\n * await placeBet({ payer: wallet.publicKey, user: wallet.publicKey, marketId: 1n, side: 0, amountUsdc: 5_000_000n });\n * ```\n */\nexport function usePlaceBet(\n opts?: Omit<UseMutationOptions<PlaceBetResult, Error, PlaceBetInputs>, \"mutationFn\">,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<PlaceBetResult, Error, PlaceBetInputs>({\n mutationFn: (inputs) => client.actions.placeBet(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n qc.invalidateQueries({ queryKey: positionKeys.byUser(vars.user) });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * useResolveMarket\n * ----------------------------------------------------------------------- */\n\nexport function useResolveMarket(\n opts?: Omit<UseMutationOptions<ResolveMarketResult, Error, ResolveMarketInputs>, \"mutationFn\">,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ResolveMarketResult, Error, ResolveMarketInputs>({\n mutationFn: (inputs) => client.actions.resolveMarket(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * useClaimPayout\n * ----------------------------------------------------------------------- */\n\nexport function useClaimPayout(\n opts?: Omit<UseMutationOptions<ClaimResult, Error, ClaimInputs>, \"mutationFn\">,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ClaimResult, Error, ClaimInputs>({\n mutationFn: (inputs) => client.actions.claimPayout(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n qc.invalidateQueries({ queryKey: positionKeys.byUser(vars.user) });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * useClaimRefund\n * ----------------------------------------------------------------------- */\n\nexport function useClaimRefund(\n opts?: Omit<UseMutationOptions<ClaimResult, Error, ClaimInputs>, \"mutationFn\">,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ClaimResult, Error, ClaimInputs>({\n mutationFn: (inputs) => client.actions.claimRefund(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n qc.invalidateQueries({ queryKey: positionKeys.byUser(vars.user) });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * useCreateMarket\n * ----------------------------------------------------------------------- */\n\ntype CreateMarketInputs = Omit<CreateMarketParams, \"expectedMarketId\" | \"acceptedMint\"> & {\n acceptedMint?: PublicKey;\n};\n\nexport function useCreateMarket(\n opts?: Omit<UseMutationOptions<CreateMarketResult, Error, CreateMarketInputs>, \"mutationFn\">,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<CreateMarketResult, Error, CreateMarketInputs>({\n mutationFn: (inputs) => client.actions.createMarket(inputs),\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: marketKeys.all });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * useCancelMarket\n * ----------------------------------------------------------------------- */\n\ntype CancelMarketInputs = Omit<CancelMarketParams, \"acceptedMint\"> & {\n acceptedMint?: PublicKey;\n};\n\nexport function useCancelMarket(\n opts?: Omit<\n UseMutationOptions<{ signature: string; market: MarketAccount | null }, Error, CancelMarketInputs>,\n \"mutationFn\"\n >,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (inputs: CancelMarketInputs) => client.actions.cancelMarket(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n qc.invalidateQueries({ queryKey: marketKeys.all });\n },\n ...opts,\n });\n}\n\n/* -----------------------------------------------------------------------\n * Dispute / challenge window mutation hooks (v0.2+)\n * ----------------------------------------------------------------------- */\n\nimport type {\n FlagResolutionInputs,\n FinalizeResolutionInputs,\n AdminOverrideResolutionInputs,\n ResolutionActionResult,\n} from \"../../src/actions/resolution.ts\";\n\nexport function useFlagResolution(\n opts?: Omit<\n UseMutationOptions<ResolutionActionResult, Error, FlagResolutionInputs>,\n \"mutationFn\"\n >,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ResolutionActionResult, Error, FlagResolutionInputs>({\n mutationFn: (inputs) => client.actions.flagResolution(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n },\n ...opts,\n });\n}\n\nexport function useFinalizeResolution(\n opts?: Omit<\n UseMutationOptions<ResolutionActionResult, Error, FinalizeResolutionInputs>,\n \"mutationFn\"\n >,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ResolutionActionResult, Error, FinalizeResolutionInputs>({\n mutationFn: (inputs) => client.actions.finalizeResolution(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n },\n ...opts,\n });\n}\n\nexport function useAdminOverrideResolution(\n opts?: Omit<\n UseMutationOptions<ResolutionActionResult, Error, AdminOverrideResolutionInputs>,\n \"mutationFn\"\n >,\n) {\n const client = useCypherClient();\n const qc = useQueryClient();\n return useMutation<ResolutionActionResult, Error, AdminOverrideResolutionInputs>({\n mutationFn: (inputs) => client.actions.adminOverrideResolution(inputs),\n onSuccess: (_data, vars) => {\n qc.invalidateQueries({ queryKey: marketKeys.one(vars.marketId) });\n },\n ...opts,\n });\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { useCypherClient } from \"./CypherProvider.tsx\";\nimport type { CypherEvent } from \"../../src/events/parser.ts\";\nimport type { EventSubscription, SubscribeOptions } from \"../../src/events/subscribe.ts\";\n\n/**\n * Subscribe to all Cypher events for the lifetime of the component.\n * Returns the latest batch of events as an ever-growing array (newest\n * last). Clear the buffer by re-mounting the component.\n *\n * @example\n * ```tsx\n * const events = useMarketEvents();\n * // events: CypherEvent[]\n * ```\n */\nexport function useMarketEvents(opts?: SubscribeOptions): CypherEvent[] {\n const client = useCypherClient();\n const [events, setEvents] = useState<CypherEvent[]>([]);\n const subRef = useRef<EventSubscription | null>(null);\n\n useEffect(() => {\n subRef.current = client.events.subscribeAll((event) => {\n setEvents((prev) => [...prev, event]);\n }, opts);\n return () => {\n subRef.current?.unsubscribe();\n subRef.current = null;\n };\n // Re-subscribe when the client identity changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client]);\n\n return events;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cypher-zk/sdk",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "TypeScript SDK for the Cypher prediction market (Arcium + Anchor on Solana)",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",