> ## Documentation Index
> Fetch the complete documentation index at: https://cyphers-3138df4b.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Markets

> Create, cancel, and manage markets.

## createMarket

Creates a YES/NO market. The SDK fetches the current `GlobalState` to auto-assign the next `marketId` and accepted mint - you do not need to provide these.

```typescript TypeScript theme={null}
const result = await client.actions.createMarket({
  payer: walletPublicKey,
  creator: walletPublicKey,
  question: "Will BTC close above $100k on 31 Dec 2026?",
  closeTime: BigInt(Math.floor(Date.now() / 1000) + 7 * 86400), // 7 days from now
  category: 0, // Crypto
  resolver: walletPublicKey, // who can call resolveMarket
  bondAmount: 20_000_000n,  // $20 USDC - minimum is MIN_CREATOR_BOND
  challengePeriod: 86400n,  // 24 hours - minimum is MIN_CHALLENGE_PERIOD_SECS
});

console.log("Created market", result.marketId, result.signature);
```

### Parameters

<ParamField body="payer" type="PublicKey" required>
  Transaction fee payer.
</ParamField>

<ParamField body="creator" type="PublicKey" required>
  Creator's public key. Receives LP fees and can cancel (if no bets) or withdraw funds after resolution.
</ParamField>

<ParamField body="question" type="string" required>
  Market question, max 200 bytes. For the question to display correctly in the protocol's `MarketQuestion` PDA, the SDK writes it to a separate account on creation.
</ParamField>

<ParamField body="closeTime" type="bigint" required>
  Unix timestamp (seconds) when betting closes. Must be at least 60 seconds in the future.
</ParamField>

<ParamField body="category" type="number" required>
  Market category. See the [MarketCategory](/sdk/reference/constants#marketcategory) enum for values (0=Crypto, 1=Politics, 2=Sports, 3=Tech, 4=Economy, 5=Culture, 6=Beyond).
</ParamField>

<ParamField body="resolver" type="PublicKey" required>
  Wallet that can post the outcome after `closeTime`. Usually the creator or a trusted oracle.
</ParamField>

<ParamField body="bondAmount" type="bigint">
  Creator bond in micro-USDC. Defaults to `MIN_CREATOR_BOND` (\$20). Locked until the creator withdraws after resolution. Pass a larger value to signal stronger commitment.
</ParamField>

<ParamField body="challengePeriod" type="bigint">
  Seconds after resolution reveal during which anyone can flag the outcome. Defaults to `MIN_CHALLENGE_PERIOD_SECS` (24h). Max is `MAX_CHALLENGE_PERIOD_SECS` (48h).
</ParamField>

<ParamField body="acceptedMint" type="PublicKey">
  Override the accepted USDC mint. Defaults to `globalState.acceptedMint`. Only use this if you need to bypass the GlobalState fetch.
</ParamField>

### Return value

<ResponseField name="signature" type="string">
  Transaction signature.
</ResponseField>

<ResponseField name="marketId" type="bigint">
  The assigned market ID.
</ResponseField>

<ResponseField name="marketPda" type="PublicKey">
  On-chain address of the new market account.
</ResponseField>

<ResponseField name="market" type="MarketAccount | null">
  Market account refetched after creation. Rarely `null` (RPC lag).
</ResponseField>

***

## createMarketMulti

Creates a multi-outcome market with 2-4 named options. Embed the option labels in the question using a `[A|B|C]` suffix.

```typescript TypeScript theme={null}
const result = await client.actions.createMarketMulti({
  payer: walletPublicKey,
  creator: walletPublicKey,
  question: "Which chain leads TVL on 1 Jan 2026? [Solana|Ethereum|Base]",
  numOutcomes: 3,
  closeTime: BigInt(Math.floor(Date.now() / 1000) + 30 * 86400),
  category: 0,
  resolver: walletPublicKey,
  bondAmount: 20_000_000n,
  challengePeriod: 86400n,
});
```

Takes the same parameters as `createMarket`, plus:

<ParamField body="numOutcomes" type="number" required>
  Number of outcomes (2-4). Must match the number of labels in the `[A|B|C]` suffix.
</ParamField>

<Note>
  The `[A|B|C]` label suffix is the only way to associate labels with outcome indices. Use `parseEmbeddedOptions(question)` from `@cypher-zk/sdk` to extract them on the read side.
</Note>

***

## cancelMarket

Cancels a market with zero bets and returns the creator's bond. The SDK pre-flights eligibility client-side before sending the transaction.

```typescript TypeScript theme={null}
import { cancelEligibility } from "@cypher-zk/sdk";

// Pre-flight check before showing the cancel button
const market = await client.markets.fetch(marketId);
const elig = cancelEligibility(market);

if (!elig.ok) {
  console.log("Cannot cancel:", elig.reason);
  return;
}

const result = await client.actions.cancelMarket({
  creator: walletPublicKey,
  marketId: 42n,
});
```

<Note>
  `cancelEligibility(market)` returns `{ ok: true, reason: null }` or `{ ok: false, reason: string }`. The SDK calls this internally before sending, but checking it first lets you conditionally render the cancel button.
</Note>

### Parameters

<ParamField body="creator" type="PublicKey" required>
  Must match the market's `creator` field on-chain.
</ParamField>

<ParamField body="marketId" type="bigint | number" required>
  Market to cancel.
</ParamField>

<ParamField body="acceptedMint" type="PublicKey">
  Override the mint (fetched from GlobalState by default).
</ParamField>

***

## withdrawCreatorFunds

Pulls the creator's bond and accumulated LP fees from a resolved market.

```typescript TypeScript theme={null}
const result = await client.actions.withdrawCreatorFunds({
  creator: walletPublicKey,
  marketId: 42n,
});
```

<ParamField body="creator" type="PublicKey" required>
  Must match the market's `creator` on-chain.
</ParamField>

<ParamField body="marketId" type="bigint | number" required>
  A resolved (`state === 2`) market.
</ParamField>

<Note>
  This can only be called once per market. The `LpPositionAccount.withdrawn` flag is set to true after the first call - subsequent calls throw `BondAlreadyWithdrawn` (error 6020).
</Note>
