@epicentral/sos-sdk 0.11.2-beta → 0.12.1-beta

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
@@ -287,13 +287,24 @@ Use `calculateRequiredCollateral` to estimate collateral needs before minting:
287
287
  ```ts
288
288
  import { calculateRequiredCollateral } from "@epicentral/sos-sdk";
289
289
 
290
- const required = calculateRequiredCollateral(
291
- 1_000_000n, // 1 contract in base units
292
- 150.0, // $150 strike price
293
- 145.23, // Current spot price (USD)
294
- 6 // USDC decimals
290
+ // Cash-settled SOL call backed by USDC (~$1 collateral price)
291
+ const requiredUsdc = calculateRequiredCollateral(
292
+ 1_000_000n,
293
+ 150.0,
294
+ 1.0,
295
+ 6,
296
+ "cash"
297
+ );
298
+ // ~15_000_000_000 micro-USDC for 1 contract at $150 strike
299
+
300
+ // Physical SOL collateral (underlying spot)
301
+ const requiredSol = calculateRequiredCollateral(
302
+ 1_000_000n,
303
+ 150.0,
304
+ 145.23,
305
+ 9,
306
+ "physical"
295
307
  );
296
- // Returns: USDC base units needed
297
308
  ```
298
309
 
299
310
  ## Unwind with Loan Repayment (theta-hedge model)
@@ -431,7 +442,8 @@ const tx = await buildBuyFromPoolMarketOrderTransactionWithDerivation({
431
442
 
432
443
  ### Buy premium semantics (market orders)
433
444
 
434
- - Premium is paid in the **option pool underlying** token; `buyer_payment_account` must match that mint (see program `buy_from_pool`).
445
+ - Premium is paid in **`premium_vault.mint`** (on-chain source of truth). For **new** pools: underlying when physical (`collateral == underlying`), collateral mint when cash (e.g. USDC). **Legacy** cash pools may still use SOL premium vault — resolve mint from chain before building `buyer_payment_account`.
446
+ - `buyer_payment_account.mint` must match `premium_vault.mint`; pass `payment_mint` to `buy_from_pool`.
435
447
  - `premiumAmount` / `max_premium_amount` is a **max premium cap**, not an exact premium target.
436
448
  - Program computes premium on-chain at execution time and fails with `SlippageToleranceExceeded` if computed premium exceeds the cap.
437
449
  - High-level market builder computes cap as `quotedPremiumTotal + buffer`:
@@ -567,19 +579,22 @@ The SDK exports `calculateRequiredCollateral` for pre-flight collateral estimati
567
579
  import { calculateRequiredCollateral } from "@epicentral/sos-sdk";
568
580
 
569
581
  const required = calculateRequiredCollateral(
570
- 1_000_000n, // 1 contract in base units
571
- 150.0, // $150 strike price
572
- 145.23, // Current spot price (USD)
573
- 9 // Token decimals (9 for SOL)
582
+ 1_000_000n,
583
+ 150.0,
584
+ 145.23,
585
+ 9,
586
+ "physical"
574
587
  );
575
- // Returns: token base units needed (e.g., 103_280_000_000 lamports for ~103.28 SOL)
576
588
  ```
577
589
 
578
590
  **Formula:**
579
591
  ```
580
592
  contracts = quantity / 1_000_000
581
593
  usd_value = contracts * 100 * strike_price
582
- collateral = (usd_value / spot_price) * 10^token_decimals
594
+ physical = (usd_value / underlying_spot) * 10^decimals
595
+ cash = usd_value * 10^collateral_decimals // conversionPrice ≈ $1 for USDC
583
596
  ```
584
597
 
598
+ `buildCloseLongToPoolTransactionWithDerivation` auto-derives `buyerPayoutAccount` (collateral mint) and `buyerUnderlyingPayoutAccount` (premium leg) when omitted.
599
+
585
600
  This matches the on-chain formula in `Vault::calculate_required_collateral` and can be used to display required collateral to users before submitting an `option_mint` transaction.
@@ -65,9 +65,11 @@ export type BuyFromPoolInstruction<
65
65
  "Sysvar1nstructions1111111111111111111111111",
66
66
  TAccountBuyerPosition extends string | AccountMeta<string> = string,
67
67
  TAccountBuyerOptionAccount extends string | AccountMeta<string> = string,
68
+ TAccountPaymentMint extends string | AccountMeta<string> = string,
68
69
  TAccountBuyerPaymentAccount extends string | AccountMeta<string> = string,
69
70
  TAccountEscrowLongAccount extends string | AccountMeta<string> = string,
70
71
  TAccountPremiumVault extends string | AccountMeta<string> = string,
72
+ TAccountCollateralPool extends string | AccountMeta<string> = string,
71
73
  TAccountBuyer extends string | AccountMeta<string> = string,
72
74
  TAccountTokenProgram extends string | AccountMeta<string> =
73
75
  "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
@@ -110,6 +112,9 @@ export type BuyFromPoolInstruction<
110
112
  TAccountBuyerOptionAccount extends string
111
113
  ? WritableAccount<TAccountBuyerOptionAccount>
112
114
  : TAccountBuyerOptionAccount,
115
+ TAccountPaymentMint extends string
116
+ ? ReadonlyAccount<TAccountPaymentMint>
117
+ : TAccountPaymentMint,
113
118
  TAccountBuyerPaymentAccount extends string
114
119
  ? WritableAccount<TAccountBuyerPaymentAccount>
115
120
  : TAccountBuyerPaymentAccount,
@@ -119,6 +124,9 @@ export type BuyFromPoolInstruction<
119
124
  TAccountPremiumVault extends string
120
125
  ? WritableAccount<TAccountPremiumVault>
121
126
  : TAccountPremiumVault,
127
+ TAccountCollateralPool extends string
128
+ ? ReadonlyAccount<TAccountCollateralPool>
129
+ : TAccountCollateralPool,
122
130
  TAccountBuyer extends string
123
131
  ? WritableSignerAccount<TAccountBuyer> &
124
132
  AccountSignerMeta<TAccountBuyer>
@@ -187,9 +195,11 @@ export type BuyFromPoolAsyncInput<
187
195
  TAccountInstructionsSysvar extends string = string,
188
196
  TAccountBuyerPosition extends string = string,
189
197
  TAccountBuyerOptionAccount extends string = string,
198
+ TAccountPaymentMint extends string = string,
190
199
  TAccountBuyerPaymentAccount extends string = string,
191
200
  TAccountEscrowLongAccount extends string = string,
192
201
  TAccountPremiumVault extends string = string,
202
+ TAccountCollateralPool extends string = string,
193
203
  TAccountBuyer extends string = string,
194
204
  TAccountTokenProgram extends string = string,
195
205
  TAccountAssociatedTokenProgram extends string = string,
@@ -215,12 +225,16 @@ export type BuyFromPoolAsyncInput<
215
225
  buyerPosition?: Address<TAccountBuyerPosition>;
216
226
  /** Buyer's LONG token account (receives LONG tokens) */
217
227
  buyerOptionAccount?: Address<TAccountBuyerOptionAccount>;
228
+ /** Premium payment mint (must match premium_vault.mint on-chain) */
229
+ paymentMint: Address<TAccountPaymentMint>;
218
230
  /** Buyer's payment account (source of premium) */
219
231
  buyerPaymentAccount: Address<TAccountBuyerPaymentAccount>;
220
232
  /** Pool's LONG escrow (source of LONG tokens) */
221
233
  escrowLongAccount: Address<TAccountEscrowLongAccount>;
222
234
  /** Pool's premium vault (receives premium) */
223
235
  premiumVault: Address<TAccountPremiumVault>;
236
+ /** Collateral pool (settlement mint for buyer position tracking) */
237
+ collateralPool?: Address<TAccountCollateralPool>;
224
238
  buyer: TransactionSigner<TAccountBuyer>;
225
239
  tokenProgram?: Address<TAccountTokenProgram>;
226
240
  associatedTokenProgram?: Address<TAccountAssociatedTokenProgram>;
@@ -240,9 +254,11 @@ export async function getBuyFromPoolInstructionAsync<
240
254
  TAccountInstructionsSysvar extends string,
241
255
  TAccountBuyerPosition extends string,
242
256
  TAccountBuyerOptionAccount extends string,
257
+ TAccountPaymentMint extends string,
243
258
  TAccountBuyerPaymentAccount extends string,
244
259
  TAccountEscrowLongAccount extends string,
245
260
  TAccountPremiumVault extends string,
261
+ TAccountCollateralPool extends string,
246
262
  TAccountBuyer extends string,
247
263
  TAccountTokenProgram extends string,
248
264
  TAccountAssociatedTokenProgram extends string,
@@ -260,9 +276,11 @@ export async function getBuyFromPoolInstructionAsync<
260
276
  TAccountInstructionsSysvar,
261
277
  TAccountBuyerPosition,
262
278
  TAccountBuyerOptionAccount,
279
+ TAccountPaymentMint,
263
280
  TAccountBuyerPaymentAccount,
264
281
  TAccountEscrowLongAccount,
265
282
  TAccountPremiumVault,
283
+ TAccountCollateralPool,
266
284
  TAccountBuyer,
267
285
  TAccountTokenProgram,
268
286
  TAccountAssociatedTokenProgram,
@@ -282,9 +300,11 @@ export async function getBuyFromPoolInstructionAsync<
282
300
  TAccountInstructionsSysvar,
283
301
  TAccountBuyerPosition,
284
302
  TAccountBuyerOptionAccount,
303
+ TAccountPaymentMint,
285
304
  TAccountBuyerPaymentAccount,
286
305
  TAccountEscrowLongAccount,
287
306
  TAccountPremiumVault,
307
+ TAccountCollateralPool,
288
308
  TAccountBuyer,
289
309
  TAccountTokenProgram,
290
310
  TAccountAssociatedTokenProgram,
@@ -319,6 +339,7 @@ export async function getBuyFromPoolInstructionAsync<
319
339
  value: input.buyerOptionAccount ?? null,
320
340
  isWritable: true,
321
341
  },
342
+ paymentMint: { value: input.paymentMint ?? null, isWritable: false },
322
343
  buyerPaymentAccount: {
323
344
  value: input.buyerPaymentAccount ?? null,
324
345
  isWritable: true,
@@ -328,6 +349,7 @@ export async function getBuyFromPoolInstructionAsync<
328
349
  isWritable: true,
329
350
  },
330
351
  premiumVault: { value: input.premiumVault ?? null, isWritable: true },
352
+ collateralPool: { value: input.collateralPool ?? null, isWritable: false },
331
353
  buyer: { value: input.buyer ?? null, isWritable: true },
332
354
  tokenProgram: { value: input.tokenProgram ?? null, isWritable: false },
333
355
  associatedTokenProgram: {
@@ -382,6 +404,20 @@ export async function getBuyFromPoolInstructionAsync<
382
404
  ],
383
405
  });
384
406
  }
407
+ if (!accounts.collateralPool.value) {
408
+ accounts.collateralPool.value = await getProgramDerivedAddress({
409
+ programAddress,
410
+ seeds: [
411
+ getBytesEncoder().encode(
412
+ new Uint8Array([
413
+ 99, 111, 108, 108, 97, 116, 101, 114, 97, 108, 95, 112, 111, 111,
414
+ 108,
415
+ ]),
416
+ ),
417
+ getAddressEncoder().encode(expectAddress(accounts.optionAccount.value)),
418
+ ],
419
+ });
420
+ }
385
421
  if (!accounts.tokenProgram.value) {
386
422
  accounts.tokenProgram.value =
387
423
  "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" as Address<"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA">;
@@ -408,9 +444,11 @@ export async function getBuyFromPoolInstructionAsync<
408
444
  getAccountMeta(accounts.instructionsSysvar),
409
445
  getAccountMeta(accounts.buyerPosition),
410
446
  getAccountMeta(accounts.buyerOptionAccount),
447
+ getAccountMeta(accounts.paymentMint),
411
448
  getAccountMeta(accounts.buyerPaymentAccount),
412
449
  getAccountMeta(accounts.escrowLongAccount),
413
450
  getAccountMeta(accounts.premiumVault),
451
+ getAccountMeta(accounts.collateralPool),
414
452
  getAccountMeta(accounts.buyer),
415
453
  getAccountMeta(accounts.tokenProgram),
416
454
  getAccountMeta(accounts.associatedTokenProgram),
@@ -432,9 +470,11 @@ export async function getBuyFromPoolInstructionAsync<
432
470
  TAccountInstructionsSysvar,
433
471
  TAccountBuyerPosition,
434
472
  TAccountBuyerOptionAccount,
473
+ TAccountPaymentMint,
435
474
  TAccountBuyerPaymentAccount,
436
475
  TAccountEscrowLongAccount,
437
476
  TAccountPremiumVault,
477
+ TAccountCollateralPool,
438
478
  TAccountBuyer,
439
479
  TAccountTokenProgram,
440
480
  TAccountAssociatedTokenProgram,
@@ -453,9 +493,11 @@ export type BuyFromPoolInput<
453
493
  TAccountInstructionsSysvar extends string = string,
454
494
  TAccountBuyerPosition extends string = string,
455
495
  TAccountBuyerOptionAccount extends string = string,
496
+ TAccountPaymentMint extends string = string,
456
497
  TAccountBuyerPaymentAccount extends string = string,
457
498
  TAccountEscrowLongAccount extends string = string,
458
499
  TAccountPremiumVault extends string = string,
500
+ TAccountCollateralPool extends string = string,
459
501
  TAccountBuyer extends string = string,
460
502
  TAccountTokenProgram extends string = string,
461
503
  TAccountAssociatedTokenProgram extends string = string,
@@ -481,12 +523,16 @@ export type BuyFromPoolInput<
481
523
  buyerPosition: Address<TAccountBuyerPosition>;
482
524
  /** Buyer's LONG token account (receives LONG tokens) */
483
525
  buyerOptionAccount: Address<TAccountBuyerOptionAccount>;
526
+ /** Premium payment mint (must match premium_vault.mint on-chain) */
527
+ paymentMint: Address<TAccountPaymentMint>;
484
528
  /** Buyer's payment account (source of premium) */
485
529
  buyerPaymentAccount: Address<TAccountBuyerPaymentAccount>;
486
530
  /** Pool's LONG escrow (source of LONG tokens) */
487
531
  escrowLongAccount: Address<TAccountEscrowLongAccount>;
488
532
  /** Pool's premium vault (receives premium) */
489
533
  premiumVault: Address<TAccountPremiumVault>;
534
+ /** Collateral pool (settlement mint for buyer position tracking) */
535
+ collateralPool: Address<TAccountCollateralPool>;
490
536
  buyer: TransactionSigner<TAccountBuyer>;
491
537
  tokenProgram?: Address<TAccountTokenProgram>;
492
538
  associatedTokenProgram?: Address<TAccountAssociatedTokenProgram>;
@@ -506,9 +552,11 @@ export function getBuyFromPoolInstruction<
506
552
  TAccountInstructionsSysvar extends string,
507
553
  TAccountBuyerPosition extends string,
508
554
  TAccountBuyerOptionAccount extends string,
555
+ TAccountPaymentMint extends string,
509
556
  TAccountBuyerPaymentAccount extends string,
510
557
  TAccountEscrowLongAccount extends string,
511
558
  TAccountPremiumVault extends string,
559
+ TAccountCollateralPool extends string,
512
560
  TAccountBuyer extends string,
513
561
  TAccountTokenProgram extends string,
514
562
  TAccountAssociatedTokenProgram extends string,
@@ -526,9 +574,11 @@ export function getBuyFromPoolInstruction<
526
574
  TAccountInstructionsSysvar,
527
575
  TAccountBuyerPosition,
528
576
  TAccountBuyerOptionAccount,
577
+ TAccountPaymentMint,
529
578
  TAccountBuyerPaymentAccount,
530
579
  TAccountEscrowLongAccount,
531
580
  TAccountPremiumVault,
581
+ TAccountCollateralPool,
532
582
  TAccountBuyer,
533
583
  TAccountTokenProgram,
534
584
  TAccountAssociatedTokenProgram,
@@ -547,9 +597,11 @@ export function getBuyFromPoolInstruction<
547
597
  TAccountInstructionsSysvar,
548
598
  TAccountBuyerPosition,
549
599
  TAccountBuyerOptionAccount,
600
+ TAccountPaymentMint,
550
601
  TAccountBuyerPaymentAccount,
551
602
  TAccountEscrowLongAccount,
552
603
  TAccountPremiumVault,
604
+ TAccountCollateralPool,
553
605
  TAccountBuyer,
554
606
  TAccountTokenProgram,
555
607
  TAccountAssociatedTokenProgram,
@@ -583,6 +635,7 @@ export function getBuyFromPoolInstruction<
583
635
  value: input.buyerOptionAccount ?? null,
584
636
  isWritable: true,
585
637
  },
638
+ paymentMint: { value: input.paymentMint ?? null, isWritable: false },
586
639
  buyerPaymentAccount: {
587
640
  value: input.buyerPaymentAccount ?? null,
588
641
  isWritable: true,
@@ -592,6 +645,7 @@ export function getBuyFromPoolInstruction<
592
645
  isWritable: true,
593
646
  },
594
647
  premiumVault: { value: input.premiumVault ?? null, isWritable: true },
648
+ collateralPool: { value: input.collateralPool ?? null, isWritable: false },
595
649
  buyer: { value: input.buyer ?? null, isWritable: true },
596
650
  tokenProgram: { value: input.tokenProgram ?? null, isWritable: false },
597
651
  associatedTokenProgram: {
@@ -643,9 +697,11 @@ export function getBuyFromPoolInstruction<
643
697
  getAccountMeta(accounts.instructionsSysvar),
644
698
  getAccountMeta(accounts.buyerPosition),
645
699
  getAccountMeta(accounts.buyerOptionAccount),
700
+ getAccountMeta(accounts.paymentMint),
646
701
  getAccountMeta(accounts.buyerPaymentAccount),
647
702
  getAccountMeta(accounts.escrowLongAccount),
648
703
  getAccountMeta(accounts.premiumVault),
704
+ getAccountMeta(accounts.collateralPool),
649
705
  getAccountMeta(accounts.buyer),
650
706
  getAccountMeta(accounts.tokenProgram),
651
707
  getAccountMeta(accounts.associatedTokenProgram),
@@ -667,9 +723,11 @@ export function getBuyFromPoolInstruction<
667
723
  TAccountInstructionsSysvar,
668
724
  TAccountBuyerPosition,
669
725
  TAccountBuyerOptionAccount,
726
+ TAccountPaymentMint,
670
727
  TAccountBuyerPaymentAccount,
671
728
  TAccountEscrowLongAccount,
672
729
  TAccountPremiumVault,
730
+ TAccountCollateralPool,
673
731
  TAccountBuyer,
674
732
  TAccountTokenProgram,
675
733
  TAccountAssociatedTokenProgram,
@@ -703,16 +761,20 @@ export type ParsedBuyFromPoolInstruction<
703
761
  buyerPosition: TAccountMetas[8];
704
762
  /** Buyer's LONG token account (receives LONG tokens) */
705
763
  buyerOptionAccount: TAccountMetas[9];
764
+ /** Premium payment mint (must match premium_vault.mint on-chain) */
765
+ paymentMint: TAccountMetas[10];
706
766
  /** Buyer's payment account (source of premium) */
707
- buyerPaymentAccount: TAccountMetas[10];
767
+ buyerPaymentAccount: TAccountMetas[11];
708
768
  /** Pool's LONG escrow (source of LONG tokens) */
709
- escrowLongAccount: TAccountMetas[11];
769
+ escrowLongAccount: TAccountMetas[12];
710
770
  /** Pool's premium vault (receives premium) */
711
- premiumVault: TAccountMetas[12];
712
- buyer: TAccountMetas[13];
713
- tokenProgram: TAccountMetas[14];
714
- associatedTokenProgram: TAccountMetas[15];
715
- systemProgram: TAccountMetas[16];
771
+ premiumVault: TAccountMetas[13];
772
+ /** Collateral pool (settlement mint for buyer position tracking) */
773
+ collateralPool: TAccountMetas[14];
774
+ buyer: TAccountMetas[15];
775
+ tokenProgram: TAccountMetas[16];
776
+ associatedTokenProgram: TAccountMetas[17];
777
+ systemProgram: TAccountMetas[18];
716
778
  };
717
779
  data: BuyFromPoolInstructionData;
718
780
  };
@@ -725,7 +787,7 @@ export function parseBuyFromPoolInstruction<
725
787
  InstructionWithAccounts<TAccountMetas> &
726
788
  InstructionWithData<ReadonlyUint8Array>,
727
789
  ): ParsedBuyFromPoolInstruction<TProgram, TAccountMetas> {
728
- if (instruction.accounts.length < 17) {
790
+ if (instruction.accounts.length < 19) {
729
791
  // TODO: Coded error.
730
792
  throw new Error("Not enough accounts");
731
793
  }
@@ -748,9 +810,11 @@ export function parseBuyFromPoolInstruction<
748
810
  instructionsSysvar: getNextAccount(),
749
811
  buyerPosition: getNextAccount(),
750
812
  buyerOptionAccount: getNextAccount(),
813
+ paymentMint: getNextAccount(),
751
814
  buyerPaymentAccount: getNextAccount(),
752
815
  escrowLongAccount: getNextAccount(),
753
816
  premiumVault: getNextAccount(),
817
+ collateralPool: getNextAccount(),
754
818
  buyer: getNextAccount(),
755
819
  tokenProgram: getNextAccount(),
756
820
  associatedTokenProgram: getNextAccount(),