lightcone 0.5.1

Rust SDK for the Lightcone Protocol — unified native + WASM client
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
# Program Module

On-chain Solana smart contract interaction for Lightcone markets.

[← Overview](../../README.md#on-chain-program)

## Overview

The program module provides:
- Account type definitions with serialization/deserialization
- Transaction builders for all 14 instructions
- PDA derivation utilities
- Order creation, signing, and verification
- Ed25519 signature verification strategies

## Account Types

### Exchange (88 bytes)

Singleton account storing global exchange state.

| Field | Offset | Size | Type | Description |
|-------|--------|------|------|-------------|
| discriminator | 0 | 8 | `[u8; 8]` | `"exchange"` |
| authority | 8 | 32 | `Pubkey` | Can pause exchange, set operator, create markets |
| operator | 40 | 32 | `Pubkey` | Can match orders |
| market_count | 72 | 8 | `u64` | Number of markets created |
| paused | 80 | 1 | `bool` | Whether exchange is paused |
| bump | 81 | 1 | `u8` | PDA bump seed |
| _padding | 82 | 6 | - | Reserved |

### Market (120 bytes)

Individual market state.

| Field | Offset | Size | Type | Description |
|-------|--------|------|------|-------------|
| discriminator | 0 | 8 | `[u8; 8]` | `"market\0\0"` |
| market_id | 8 | 8 | `u64` | Sequential market identifier |
| num_outcomes | 16 | 1 | `u8` | Number of outcomes (2-6) |
| status | 17 | 1 | `MarketStatus` | Pending=0, Active=1, Resolved=2, Cancelled=3 |
| winning_outcome | 18 | 1 | `u8` | Winning outcome index (255 if unresolved) |
| has_winning_outcome | 19 | 1 | `bool` | Whether market has resolved |
| bump | 20 | 1 | `u8` | PDA bump seed |
| _padding | 21 | 3 | - | Reserved |
| oracle | 24 | 32 | `Pubkey` | Resolution authority |
| question_id | 56 | 32 | `[u8; 32]` | Unique question identifier |
| condition_id | 88 | 32 | `[u8; 32]` | Keccak256(oracle \|\| question_id \|\| num_outcomes) |

### Position (80 bytes)

User's custody account for a specific market.

| Field | Offset | Size | Type | Description |
|-------|--------|------|------|-------------|
| discriminator | 0 | 8 | `[u8; 8]` | `"position"` |
| owner | 8 | 32 | `Pubkey` | Position owner |
| market | 40 | 32 | `Pubkey` | Market this position belongs to |
| bump | 72 | 1 | `u8` | PDA bump seed |
| _padding | 73 | 7 | - | Reserved |

### OrderStatus (24 bytes)

Tracks order fill state and cancellation.

| Field | Offset | Size | Type | Description |
|-------|--------|------|------|-------------|
| discriminator | 0 | 8 | `[u8; 8]` | `"ordstat\0"` |
| remaining | 8 | 8 | `u64` | Remaining amount_in to be filled |
| is_cancelled | 16 | 1 | `bool` | Whether order has been cancelled |
| _padding | 17 | 7 | - | Reserved |

### UserNonce (16 bytes)

User's nonce for mass order cancellation.

| Field | Offset | Size | Type | Description |
|-------|--------|------|------|-------------|
| discriminator | 0 | 8 | `[u8; 8]` | `"usrnonce"` |
| nonce | 8 | 8 | `u64` | Current nonce value |

## LightconeClient — On-Chain Operations

All on-chain operations are available through `LightconeClient` and its domain sub-clients.
Configure with `.rpc_url()` on the builder for RPC-dependent operations.

### Creation

```rust
use lightcone::prelude::*;

// Standard creation with RPC
let client = LightconeClient::builder()
    .rpc_url("https://api.devnet.solana.com")
    .build()?;

// With custom program ID
let client = LightconeClient::builder()
    .rpc_url("https://api.devnet.solana.com")
    .program_id(custom_program_id)
    .build()?;
```

### Account Fetchers

Account fetchers are on the `client.rpc()` sub-client (require RPC):

```rust
let rpc = client.rpc();

// Exchange (singleton)
let exchange = rpc.get_exchange().await?;

// Market by ID or pubkey
let market = rpc.get_market_by_id(0).await?;
let market = rpc.get_market_onchain(&market_pda).await?;

// Position (returns None if not found)
let position = rpc.get_position_onchain(&owner, &market_pda).await?;

// Order status (returns None if not found)
let status = rpc.get_order_status(&order_hash).await?;

// User nonce (returns 0 if account doesn't exist)
let nonce = rpc.get_user_nonce(&user).await?;
let nonce_u32 = rpc.get_current_nonce(&user).await?;

// Next market ID
let next_id = rpc.get_next_market_id().await?;

// Orderbook by mint pair
let orderbook = rpc.get_orderbook_onchain(&mint_a, &mint_b).await?;

// Global deposit token
let gdt = rpc.get_global_deposit_token(&mint).await?;

// Latest blockhash
let blockhash = rpc.get_latest_blockhash().await?;

// Access the underlying Solana RpcClient
let solana_rpc = rpc.inner()?;
```

### Instruction Builders

Instruction builders are organized by domain sub-client. `_ix` methods return an `Instruction` (or `Result<Instruction, SdkError>` for fallible builders). `_tx` convenience methods wrap the instruction in a `Transaction` and return `Result<Transaction, SdkError>`.

**Admin — Exchange Management (`client.admin()`):**
```rust
// Instructions (for custom transaction composition)
let ix = client.admin().initialize_ix(&authority);
let ix = client.admin().set_paused_ix(&authority, true);
let ix = client.admin().set_operator_ix(&authority, &new_operator);
let ix = client.admin().set_authority_ix(&SetAuthorityParams { ... });
let ix = client.admin().whitelist_deposit_token_ix(&WhitelistDepositTokenParams { ... });

// Transactions (ready to sign)
let tx = client.admin().initialize_tx(&authority)?;
let tx = client.admin().set_paused_tx(&authority, true)?;
```

**Admin — Market Lifecycle (`client.admin()`):**
```rust
// create_market_ix is async (fetches next market ID via RPC)
let ix = client.admin().create_market_ix(CreateMarketParams {
    authority,
    oracle,
    question_id,
    num_outcomes,
}).await?;

let ix = client.admin().add_deposit_mint_ix(&AddDepositMintParams {
    authority,
    deposit_mint: usdc_mint,
    outcome_metadata: vec![
        OutcomeMetadata { name: "Yes".into(), symbol: "YES".into(), uri: "".into() },
        OutcomeMetadata { name: "No".into(), symbol: "NO".into(), uri: "".into() },
    ],
}, &market, num_outcomes)?;

let ix = client.admin().activate_market_ix(&ActivateMarketParams {
    authority,
    market_id,
});

let ix = client.admin().settle_market_ix(&SettleMarketParams {
    oracle,
    market_id,
    winning_outcome,
});
```

**Admin — Operator (`client.admin()`):**
```rust
let ix = client.admin().match_orders_multi_ix(&MatchOrdersMultiParams { ... })?;
let ix = client.admin().deposit_and_swap_ix(&DepositAndSwapParams { ... })?;
```

**Positions — Deposit/Merge/Withdraw (`client.positions()`):**
```rust
// Deposit (dispatches on deposit source: Global or Market)
let ix = client.positions().deposit().await
    .user(keypair.pubkey())
    .mint(deposit_mint)
    .amount(1_000_000)
    .with_market_deposit_source(&market)
    .build_ix()
    .await?;

// Merge (market-only — burns conditional tokens, returns collateral)
let ix = client.positions().merge()
    .user(keypair.pubkey())
    .market(&market)
    .mint(deposit_mint)
    .amount(1_000_000)
    .build_ix()?;

// Withdraw (dispatches on deposit source: Global or Market)
let ix = client.positions().withdraw().await
    .user(keypair.pubkey())
    .mint(deposit_mint)
    .amount(1_000_000)
    .build_ix()
    .await?;
```

**Orders — On-Chain Order Operations (`client.orders()`):**
```rust
let ix = client.orders().cancel_order_ix(&maker, &market, &order);
let ix = client.orders().increment_nonce_ix(&user);
```

**Positions — Position Management (`client.positions()`):**
```rust
let ix = client.positions().redeem_winnings_ix(&RedeemWinningsParams {
    user, market, deposit_mint: usdc_mint, amount,
}, winning_outcome);

let ix = client.positions().withdraw_from_position_ix(&WithdrawFromPositionParams {
    user, market, mint: conditional_mint, amount, outcome_index,
}, is_token_2022);

let ix = client.positions().init_position_tokens_ix(&InitPositionTokensParams {
    payer, user, market, deposit_mints, recent_slot,
}, num_outcomes);

let ix = client.positions().extend_position_tokens_ix(&ExtendPositionTokensParams {
    payer, user, market, lookup_table, deposit_mints,
}, num_outcomes)?;

let ix = client.positions().deposit_to_global_ix(&DepositToGlobalParams {
    user, mint, amount,
});

let ix = client.positions().global_to_market_deposit_ix(&GlobalToMarketDepositParams {
    user, market, deposit_mint, amount,
}, num_outcomes);
```

### Order Helpers

Order helpers are on the `client.orders()` sub-client:

```rust
// Create unsigned orders
let order = client.orders().create_bid_order(BidOrderParams {
    nonce: 1,
    maker: pubkey,
    market: market_pda,
    base_mint: yes_token,
    quote_mint: no_token,
    amount_in: 100_000,
    amount_out: 50_000,
    expiration: 0,
});

let order = client.orders().create_ask_order(AskOrderParams { ... });

// Create and sign in one step (native-auth feature)
let order = client.orders().create_signed_bid_order(params, &keypair);
let order = client.orders().create_signed_ask_order(params, &keypair);

// Manual signing
client.orders().sign_order(&mut order, &keypair);

// Get order hash
let hash = client.orders().hash_order(&order);
```

## PDA Derivation

All functions return `(Pubkey, u8)` (address, bump).

| Function | Seeds | Description |
|----------|-------|-------------|
| `get_exchange_pda(program_id)` | `["central_state"]` | Exchange singleton |
| `get_market_pda(market_id, program_id)` | `["market", market_id.to_le_bytes()]` | Market account |
| `get_vault_pda(deposit_mint, market, program_id)` | `["market_deposit_token_account", deposit_mint, market]` | Deposit vault |
| `get_mint_authority_pda(market, program_id)` | `["market_mint_authority", market]` | Conditional token mint authority |
| `get_conditional_mint_pda(market, deposit_mint, outcome, program_id)` | `["conditional_mint", market, deposit_mint, [outcome]]` | Conditional token mint |
| `get_order_status_pda(order_hash, program_id)` | `["order_status", order_hash]` | Order fill status |
| `get_user_nonce_pda(user, program_id)` | `["user_nonce", user]` | User nonce account |
| `get_position_pda(owner, market, program_id)` | `["position", owner, market]` | User position |

```rust
use lightcone::program::*;

let (exchange, _) = get_exchange_pda(&program_id);
let (market, _) = get_market_pda(market_id, &program_id);
let (position, _) = get_position_pda(&owner, &market, &program_id);
let (vault, _) = get_vault_pda(&deposit_mint, &market, &program_id);
let (cond_mint, _) = get_conditional_mint_pda(&market, &deposit_mint, 0, &program_id);
```

## Order Types

### OrderPayload (225 bytes)

Complete order with signature for off-chain storage and API submission.

| Field | Offset | Size | Type | Description |
|-------|--------|------|------|-------------|
| nonce | 0 | 8 | `u64` | Unique order identifier (must exceed user's on-chain nonce) |
| maker | 8 | 32 | `Pubkey` | Order creator |
| market | 40 | 32 | `Pubkey` | Market pubkey |
| base_mint | 72 | 32 | `Pubkey` | Token being bought (bids) or sold (asks) |
| quote_mint | 104 | 32 | `Pubkey` | Token being given (bids) or received (asks) |
| side | 136 | 1 | `OrderSide` | Bid=0, Ask=1 |
| amount_in | 137 | 8 | `u64` | Amount maker gives (quote for bids, base for asks) |
| amount_out | 145 | 8 | `u64` | Amount maker receives (base for bids, quote for asks) |
| expiration | 153 | 8 | `i64` | Unix timestamp (0 = no expiration) |
| signature | 161 | 64 | `[u8; 64]` | Ed25519 signature |

**Methods:**
```rust
// Construction
OrderPayload::new_bid(params) -> OrderPayload
OrderPayload::new_ask(params) -> OrderPayload
OrderPayload::new_bid_signed(params, &keypair) -> OrderPayload
OrderPayload::new_ask_signed(params, &keypair) -> OrderPayload

// Hashing and signing
order.hash() -> [u8; 32]           // Keccak256 of fields (excludes signature)
order.sign(&keypair)               // Sign in place
order.verify_signature() -> Result<()>

// Serialization
order.serialize() -> [u8; 225]
OrderPayload::deserialize(data) -> Result<OrderPayload>

// Conversion
order.to_order() -> Order
```

### Order (29 bytes)

On-chain transmission format. Excludes maker/market/base_mint/quote_mint (passed via accounts).

| Field | Offset | Size | Type | Description |
|-------|--------|------|------|-------------|
| nonce | 0 | 4 | `u32` | Order nonce |
| side | 4 | 1 | `OrderSide` | Bid=0, Ask=1 |
| amount_in | 5 | 8 | `u64` | Amount maker gives |
| amount_out | 13 | 8 | `u64` | Amount maker receives |
| expiration | 21 | 8 | `i64` | Expiration timestamp |

```rust
let compact = order.to_order();
```

### Order Utilities

```rust
// Check expiration
let expired = is_order_expired(&order, current_timestamp);

// Check if orders can match (bid price >= ask price)
let can_cross = orders_can_cross(&bid_order, &ask_order);

// Calculate taker fill for a given maker fill
let taker_fill = calculate_taker_fill(&maker_order, maker_fill_amount)?;

// Derive condition ID from market parameters
let condition_id = derive_condition_id(&oracle, &question_id, num_outcomes);

// Get all conditional mints for a market
let mints = client.markets().get_conditional_mints(&market, &deposit_mint, num_outcomes);
```

## Ed25519 Signature Verification

Orders are signed off-chain with Ed25519 and verified on-chain. Three strategies available:

### Strategy 1: Individual Instructions (Simplest)

Each order gets its own Ed25519 instruction. 144 bytes per instruction.

```rust
let ix = create_ed25519_verify_instruction(&Ed25519VerifyParams::from_order(&order));
```

### Strategy 2: Batch Verification (More Efficient)

Single Ed25519 instruction verifies multiple signatures.

```rust
let ix = create_batch_ed25519_verify_instruction(&[
    Ed25519VerifyParams::from_order(&order1),
    Ed25519VerifyParams::from_order(&order2),
]);
```

Size: `2 + (num_signatures * 14) + (num_signatures * 128)` bytes

### Strategy 3: Cross-Instruction References (Most Efficient)

Ed25519 instructions reference data embedded in the match instruction. Saves ~128 bytes per order.

```rust
let ixs = create_cross_ref_ed25519_instructions(num_makers, match_ix_index);
```

The match instruction embeds order data at known offsets:
- Taker hash at offset 1
- Taker pubkey at offset 41
- Taker signature at offset 98
- Each maker: hash, pubkey, signature at `162 + (i * 169)`

## Instruction Reference

All instructions use a single-byte discriminator.

| Instruction | Discriminator | Description |
|-------------|---------------|-------------|
| Initialize | 0 | Create exchange singleton |
| CreateMarket | 1 | Create a new market |
| AddDepositMint | 2 | Add deposit token to market |
| MintCompleteSet | 3 | Deposit and mint conditional tokens |
| MergeCompleteSet | 4 | Burn conditionals and withdraw deposit |
| CancelOrder | 5 | Cancel a specific order |
| IncrementNonce | 6 | Invalidate all orders with lower nonces |
| SettleMarket | 7 | Resolve market with winning outcome |
| RedeemWinnings | 8 | Redeem winning tokens for deposit |
| SetPaused | 9 | Pause/unpause exchange |
| SetOperator | 10 | Change exchange operator |
| WithdrawFromPosition | 11 | Withdraw tokens from position |
| ActivateMarket | 12 | Activate pending market |
| MatchOrdersMulti | 13 | Match taker against makers |

## Constants

### Program IDs

The Lightcone program ID is derived from `LightconeEnv` and accessed via `LightconeEnv::program_id()` or `LightconeClient::program_id()`. Other program IDs are constants:

```rust
TOKEN_PROGRAM_ID: Pubkey              // SPL Token
TOKEN_2022_PROGRAM_ID: Pubkey         // Token-2022 (conditional tokens)
ASSOCIATED_TOKEN_PROGRAM_ID: Pubkey
SYSTEM_PROGRAM_ID: Pubkey
RENT_SYSVAR_ID: Pubkey
```

### Discriminators

```rust
EXCHANGE_DISCRIMINATOR: [u8; 8]       // b"exchange"
MARKET_DISCRIMINATOR: [u8; 8]         // b"market\0\0"
ORDER_STATUS_DISCRIMINATOR: [u8; 8]   // b"ordstat\0"
USER_NONCE_DISCRIMINATOR: [u8; 8]     // b"usrnonce"
POSITION_DISCRIMINATOR: [u8; 8]       // b"position"
```

### Seeds

```rust
EXCHANGE_SEED: &[u8]                  // b"central_state"
MARKET_SEED: &[u8]                    // b"market"
VAULT_SEED: &[u8]                     // b"market_deposit_token_account"
MINT_AUTHORITY_SEED: &[u8]            // b"market_mint_authority"
CONDITIONAL_MINT_SEED: &[u8]          // b"conditional_mint"
ORDER_STATUS_SEED: &[u8]              // b"order_status"
USER_NONCE_SEED: &[u8]                // b"user_nonce"
POSITION_SEED: &[u8]                  // b"position"
```

### Sizes

```rust
EXCHANGE_SIZE: usize                  // 88
MARKET_SIZE: usize                    // 120
POSITION_SIZE: usize                  // 80
ORDER_STATUS_SIZE: usize              // 24
USER_NONCE_SIZE: usize                // 16
SIGNED_ORDER_SIZE: usize             // 225
ORDER_SIZE: usize                    // 29
SIGNATURE_SIZE: usize                 // 64
```

### Limits

```rust
MAX_OUTCOMES: u8                      // 6
MIN_OUTCOMES: u8                      // 2
MAX_MAKERS: usize                     // 5 (per match_orders_multi instruction)
```

## Type Definitions

### MarketStatus

```rust
#[repr(u8)]
pub enum MarketStatus {
    Pending = 0,   // Market created, not yet active
    Active = 1,    // Market accepting orders
    Resolved = 2,  // Market has winning outcome
    Cancelled = 3, // Market cancelled
}
```

### OrderSide

```rust
#[repr(u8)]
pub enum OrderSide {
    Bid = 0,  // Maker buys base, gives quote
    Ask = 1,  // Maker sells base, receives quote
}
```

### Parameter Structs

All parameter structs use owned types (no lifetimes):

```rust
pub struct CreateMarketParams {
    pub authority: Pubkey,
    pub num_outcomes: u8,
    pub oracle: Pubkey,
    pub question_id: [u8; 32],
}

pub struct AddDepositMintParams {
    pub authority: Pubkey,
    pub deposit_mint: Pubkey,
    pub outcome_metadata: Vec<OutcomeMetadata>,
}

pub struct OutcomeMetadata {
    pub name: String,    // max 32 chars
    pub symbol: String,  // max 10 chars
    pub uri: String,     // max 200 chars
}

pub struct ActivateMarketParams {
    pub authority: Pubkey,
    pub market_id: u64,
}

pub struct SettleMarketParams {
    pub oracle: Pubkey,
    pub market_id: u64,
    pub winning_outcome: u8,
}

pub struct BuildDepositParams {
    pub user: Pubkey,
    pub market: Pubkey,
    pub deposit_mint: Pubkey,
    pub amount: u64,
}

pub struct BuildMergeParams {
    pub user: Pubkey,
    pub market: Pubkey,
    pub deposit_mint: Pubkey,
    pub amount: u64,
}

pub struct RedeemWinningsParams {
    pub user: Pubkey,
    pub market: Pubkey,
    pub deposit_mint: Pubkey,
    pub amount: u64,
}

pub struct WithdrawFromPositionParams {
    pub user: Pubkey,
    pub market: Pubkey,
    pub mint: Pubkey,
    pub amount: u64,
}

pub struct MatchOrdersMultiParams {
    pub operator: Pubkey,
    pub market: Pubkey,
    pub base_mint: Pubkey,
    pub quote_mint: Pubkey,
    pub taker_order: OrderPayload,
    pub maker_orders: Vec<OrderPayload>,
    pub maker_fill_amounts: Vec<u64>,
    pub taker_fill_amounts: Vec<u64>,
    pub full_fill_bitmask: u8,
}

pub struct BidOrderParams {
    pub nonce: u64,
    pub maker: Pubkey,
    pub market: Pubkey,
    pub base_mint: Pubkey,
    pub quote_mint: Pubkey,
    pub amount_in: u64,
    pub amount_out: u64,
    pub expiration: i64,
}

pub struct AskOrderParams {
    pub nonce: u64,
    pub maker: Pubkey,
    pub market: Pubkey,
    pub base_mint: Pubkey,
    pub quote_mint: Pubkey,
    pub amount_in: u64,
    pub amount_out: u64,
    pub expiration: i64,
}
```

## Error Types

```rust
pub enum SdkError {
    Rpc(solana_client::client_error::ClientError),
    InvalidDiscriminator { expected: String, actual: String },
    AccountNotFound(String),
    InvalidDataLength { expected: usize, actual: usize },
    InvalidOrderHash,
    InvalidSignature,
    OrderExpired,
    InvalidOutcomeCount { count: u8 },
    InvalidOutcomeIndex { index: u8, max: u8 },
    TooManyMakers { count: usize },
    Serialization(String),
    InvalidSide(u8),
    InvalidMarketStatus(u8),
    SignatureVerificationFailed,
    MissingField(String),
    OrdersDoNotCross,
    FillAmountExceedsRemaining { fill: u64, remaining: u64 },
    Overflow,
    InvalidPubkey(String),
}

pub type SdkResult<T> = Result<T, SdkError>;
```

---

[← Overview](../../README.md#on-chain-program)