@epicentral/sos-sdk 0.4.0-alpha.3 → 0.5.0-alpha.2
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 +83 -1
- package/client/lookup-table.ts +1 -1
- package/generated/accounts/positionAccount.ts +15 -1
- package/generated/accounts/writerPosition.ts +25 -1
- package/generated/errors/optionProgram.ts +12 -0
- package/generated/instructions/optionMint.ts +102 -25
- package/package.json +1 -1
- package/shared/amounts.ts +23 -2
- package/short/builders.ts +33 -3
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ Additional modules:
|
|
|
57
57
|
|
|
58
58
|
| Function | Description |
|
|
59
59
|
|----------|-------------|
|
|
60
|
-
| `buildOptionMintTransactionWithDerivation` | Builds option mint (write) transaction. |
|
|
60
|
+
| `buildOptionMintTransactionWithDerivation` | Builds option mint (write) transaction. Supports multi-collateral: use `collateralMint` to back positions with any supported asset (USDC, BTC, SOL, etc.). |
|
|
61
61
|
| `buildUnwindWriterUnsoldTransactionWithDerivation` | Builds unwind unsold transaction. |
|
|
62
62
|
| `buildUnwindWriterUnsoldWithLoanRepayment` | **Unwind + repay pool loans in one tx.** Use when closing unsold shorts that borrowed from OMLP. |
|
|
63
63
|
| `buildSyncWriterPositionTransaction` | Syncs writer position with pool accumulators. |
|
|
@@ -88,6 +88,63 @@ Borrow/repay for writers: use `buildOptionMintTransactionWithDerivation` (with v
|
|
|
88
88
|
| `getCreateAssociatedTokenIdempotentInstructionWithAddress` | Creates ATA if missing (idempotent). |
|
|
89
89
|
| `NATIVE_MINT` | WSOL mint address. |
|
|
90
90
|
|
|
91
|
+
## Multi-Collateral Settlement
|
|
92
|
+
|
|
93
|
+
The SDK supports universal multi-collateral settlement, allowing writers to use ANY supported asset as collateral for options (not just the underlying). This enables:
|
|
94
|
+
|
|
95
|
+
- **Capital Efficiency**: Writers use whatever assets they hold (USDC, BTC, SOL, BONK, etc.)
|
|
96
|
+
- **No Forced Conversions**: No swap fees or slippage to get the "correct" collateral
|
|
97
|
+
- **Lender Flexibility**: Lend any supported asset, earn yield in that asset
|
|
98
|
+
|
|
99
|
+
### How it works
|
|
100
|
+
|
|
101
|
+
When minting an option, specify `collateralMint` to choose the backing asset:
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import {
|
|
105
|
+
buildOptionMintTransactionWithDerivation,
|
|
106
|
+
OptionType,
|
|
107
|
+
} from "@epicentral/sos-sdk";
|
|
108
|
+
|
|
109
|
+
// Write SOL calls backed by USDC
|
|
110
|
+
const tx = await buildOptionMintTransactionWithDerivation({
|
|
111
|
+
underlyingAsset: SOL_MINT,
|
|
112
|
+
optionType: OptionType.Call,
|
|
113
|
+
strikePrice: 150.0,
|
|
114
|
+
expirationDate: BigInt(1735689600),
|
|
115
|
+
quantity: 1_000_000, // 1 contract
|
|
116
|
+
underlyingMint: SOL_MINT,
|
|
117
|
+
underlyingSymbol: "SOL",
|
|
118
|
+
collateralMint: USDC_MINT, // Back with USDC instead of SOL
|
|
119
|
+
makerCollateralAmount: 780_000_000, // $780 (10% of $7,800)
|
|
120
|
+
borrowedAmount: 7_020_000_000, // $7,020 (90% borrowed)
|
|
121
|
+
maker: walletAddress,
|
|
122
|
+
rpc,
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Key points:**
|
|
127
|
+
- `collateralMint` defaults to `underlyingMint` if not provided (backwards compatible)
|
|
128
|
+
- OMLP vault routing is based on `collateralMint` - the vault must exist for the collateral asset
|
|
129
|
+
- At settlement, buyers receive payout in the collateral currency that backed the position
|
|
130
|
+
- The `WriterPosition` account tracks `collateralMint` and `settlementMint` for each position
|
|
131
|
+
|
|
132
|
+
### Collateral Calculation
|
|
133
|
+
|
|
134
|
+
Use `calculateRequiredCollateral` to estimate collateral needs before minting:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import { calculateRequiredCollateral } from "@epicentral/sos-sdk";
|
|
138
|
+
|
|
139
|
+
const required = calculateRequiredCollateral(
|
|
140
|
+
1_000_000n, // 1 contract in base units
|
|
141
|
+
150.0, // $150 strike price
|
|
142
|
+
145.23, // Current spot price (USD)
|
|
143
|
+
6 // USDC decimals
|
|
144
|
+
);
|
|
145
|
+
// Returns: USDC base units needed
|
|
146
|
+
```
|
|
147
|
+
|
|
91
148
|
## Unwind with Loan Repayment
|
|
92
149
|
|
|
93
150
|
When a writer unwinds an unsold short that had borrowed from the OMLP pool, the program repays proportionally to the unwind ratio inside `unwind_writer_unsold`:
|
|
@@ -260,3 +317,28 @@ PDAs, fetchers, and builders are exported from the package root.
|
|
|
260
317
|
## Program Compatibility
|
|
261
318
|
|
|
262
319
|
The SDK targets the Solana Option Standard program. Use `PROGRAM_ID` (or `getProgramId()`) from the package for the program address. Pass `programId` in builder params when using a different deployment.
|
|
320
|
+
|
|
321
|
+
## Collateral Calculation Helper
|
|
322
|
+
|
|
323
|
+
The SDK exports `calculateRequiredCollateral` for pre-flight collateral estimation:
|
|
324
|
+
|
|
325
|
+
```ts
|
|
326
|
+
import { calculateRequiredCollateral } from "@epicentral/sos-sdk";
|
|
327
|
+
|
|
328
|
+
const required = calculateRequiredCollateral(
|
|
329
|
+
1_000_000n, // 1 contract in base units
|
|
330
|
+
150.0, // $150 strike price
|
|
331
|
+
145.23, // Current spot price (USD)
|
|
332
|
+
9 // Token decimals (9 for SOL)
|
|
333
|
+
);
|
|
334
|
+
// Returns: token base units needed (e.g., 103_280_000_000 lamports for ~103.28 SOL)
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Formula:**
|
|
338
|
+
```
|
|
339
|
+
contracts = quantity / 1_000_000
|
|
340
|
+
usd_value = contracts * 100 * strike_price
|
|
341
|
+
collateral = (usd_value / spot_price) * 10^token_decimals
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
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.
|
package/client/lookup-table.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { PROGRAM_ID } from "./program";
|
|
|
4
4
|
import type { KitRpc } from "./types";
|
|
5
5
|
|
|
6
6
|
export const LOOKUP_TABLE_ADDRESSES: Record<"devnet" | "mainnet", Address | null> = {
|
|
7
|
-
devnet: address("
|
|
7
|
+
devnet: address("EheW9UCUDMFybVKKXh5Eyg8hgVQpVc3uBZjBpu9gai4L"),
|
|
8
8
|
mainnet: null,
|
|
9
9
|
};
|
|
10
10
|
|
|
@@ -62,6 +62,12 @@ export type PositionAccount = {
|
|
|
62
62
|
isClosed: boolean;
|
|
63
63
|
isExercised: boolean;
|
|
64
64
|
pnl: bigint;
|
|
65
|
+
/**
|
|
66
|
+
* Collateral mint used for settlement (e.g., USDC, BTC, SOL)
|
|
67
|
+
* Tracks which currency the buyer will receive at exercise/close
|
|
68
|
+
* Matches the WriterPosition.collateral_mint of the writer(s) who filled this position
|
|
69
|
+
*/
|
|
70
|
+
collateralMint: Address;
|
|
65
71
|
};
|
|
66
72
|
|
|
67
73
|
export type PositionAccountArgs = {
|
|
@@ -74,6 +80,12 @@ export type PositionAccountArgs = {
|
|
|
74
80
|
isClosed: boolean;
|
|
75
81
|
isExercised: boolean;
|
|
76
82
|
pnl: number | bigint;
|
|
83
|
+
/**
|
|
84
|
+
* Collateral mint used for settlement (e.g., USDC, BTC, SOL)
|
|
85
|
+
* Tracks which currency the buyer will receive at exercise/close
|
|
86
|
+
* Matches the WriterPosition.collateral_mint of the writer(s) who filled this position
|
|
87
|
+
*/
|
|
88
|
+
collateralMint: Address;
|
|
77
89
|
};
|
|
78
90
|
|
|
79
91
|
/** Gets the encoder for {@link PositionAccountArgs} account data. */
|
|
@@ -90,6 +102,7 @@ export function getPositionAccountEncoder(): FixedSizeEncoder<PositionAccountArg
|
|
|
90
102
|
["isClosed", getBooleanEncoder()],
|
|
91
103
|
["isExercised", getBooleanEncoder()],
|
|
92
104
|
["pnl", getI64Encoder()],
|
|
105
|
+
["collateralMint", getAddressEncoder()],
|
|
93
106
|
]),
|
|
94
107
|
(value) => ({ ...value, discriminator: POSITION_ACCOUNT_DISCRIMINATOR }),
|
|
95
108
|
);
|
|
@@ -108,6 +121,7 @@ export function getPositionAccountDecoder(): FixedSizeDecoder<PositionAccount> {
|
|
|
108
121
|
["isClosed", getBooleanDecoder()],
|
|
109
122
|
["isExercised", getBooleanDecoder()],
|
|
110
123
|
["pnl", getI64Decoder()],
|
|
124
|
+
["collateralMint", getAddressDecoder()],
|
|
111
125
|
]);
|
|
112
126
|
}
|
|
113
127
|
|
|
@@ -183,5 +197,5 @@ export async function fetchAllMaybePositionAccount(
|
|
|
183
197
|
}
|
|
184
198
|
|
|
185
199
|
export function getPositionAccountSize(): number {
|
|
186
|
-
return
|
|
200
|
+
return 146;
|
|
187
201
|
}
|
|
@@ -63,6 +63,16 @@ export type WriterPosition = {
|
|
|
63
63
|
optionPool: Address;
|
|
64
64
|
/** Reference to the option account */
|
|
65
65
|
optionAccount: Address;
|
|
66
|
+
/**
|
|
67
|
+
* Mint used for collateral backing this position (e.g., USDC, BTC, SOL)
|
|
68
|
+
* Can differ from the underlying asset - enables multi-collateral system
|
|
69
|
+
*/
|
|
70
|
+
collateralMint: Address;
|
|
71
|
+
/**
|
|
72
|
+
* Mint used for settlement (same as collateral_mint)
|
|
73
|
+
* Buyers receive payout in this currency
|
|
74
|
+
*/
|
|
75
|
+
settlementMint: Address;
|
|
66
76
|
/** Total contracts written (minted) by this writer */
|
|
67
77
|
writtenQty: bigint;
|
|
68
78
|
/** Total contracts sold to buyers (open interest from this writer) */
|
|
@@ -115,6 +125,16 @@ export type WriterPositionArgs = {
|
|
|
115
125
|
optionPool: Address;
|
|
116
126
|
/** Reference to the option account */
|
|
117
127
|
optionAccount: Address;
|
|
128
|
+
/**
|
|
129
|
+
* Mint used for collateral backing this position (e.g., USDC, BTC, SOL)
|
|
130
|
+
* Can differ from the underlying asset - enables multi-collateral system
|
|
131
|
+
*/
|
|
132
|
+
collateralMint: Address;
|
|
133
|
+
/**
|
|
134
|
+
* Mint used for settlement (same as collateral_mint)
|
|
135
|
+
* Buyers receive payout in this currency
|
|
136
|
+
*/
|
|
137
|
+
settlementMint: Address;
|
|
118
138
|
/** Total contracts written (minted) by this writer */
|
|
119
139
|
writtenQty: number | bigint;
|
|
120
140
|
/** Total contracts sold to buyers (open interest from this writer) */
|
|
@@ -168,6 +188,8 @@ export function getWriterPositionEncoder(): FixedSizeEncoder<WriterPositionArgs>
|
|
|
168
188
|
["writerAuthority", getAddressEncoder()],
|
|
169
189
|
["optionPool", getAddressEncoder()],
|
|
170
190
|
["optionAccount", getAddressEncoder()],
|
|
191
|
+
["collateralMint", getAddressEncoder()],
|
|
192
|
+
["settlementMint", getAddressEncoder()],
|
|
171
193
|
["writtenQty", getU64Encoder()],
|
|
172
194
|
["soldQty", getU64Encoder()],
|
|
173
195
|
["unsoldQty", getU64Encoder()],
|
|
@@ -203,6 +225,8 @@ export function getWriterPositionDecoder(): FixedSizeDecoder<WriterPosition> {
|
|
|
203
225
|
["writerAuthority", getAddressDecoder()],
|
|
204
226
|
["optionPool", getAddressDecoder()],
|
|
205
227
|
["optionAccount", getAddressDecoder()],
|
|
228
|
+
["collateralMint", getAddressDecoder()],
|
|
229
|
+
["settlementMint", getAddressDecoder()],
|
|
206
230
|
["writtenQty", getU64Decoder()],
|
|
207
231
|
["soldQty", getU64Decoder()],
|
|
208
232
|
["unsoldQty", getU64Decoder()],
|
|
@@ -299,5 +323,5 @@ export async function fetchAllMaybeWriterPosition(
|
|
|
299
323
|
}
|
|
300
324
|
|
|
301
325
|
export function getWriterPositionSize(): number {
|
|
302
|
-
return
|
|
326
|
+
return 364;
|
|
303
327
|
}
|
|
@@ -196,6 +196,12 @@ export const OPTION_PROGRAM_ERROR__UNWIND_REPAY_WALLET_SOURCE_MISSING = 0x17c8;
|
|
|
196
196
|
export const OPTION_PROGRAM_ERROR__UNWIND_REPAY_INSUFFICIENT_TOTAL_FUNDS = 0x17c9; // 6089
|
|
197
197
|
/** InsufficientCollateralVault: Collateral vault has insufficient funds for unwind collateral return */
|
|
198
198
|
export const OPTION_PROGRAM_ERROR__INSUFFICIENT_COLLATERAL_VAULT = 0x17ca; // 6090
|
|
199
|
+
/** InvalidVaultMint: Invalid vault mint - does not match expected collateral mint */
|
|
200
|
+
export const OPTION_PROGRAM_ERROR__INVALID_VAULT_MINT = 0x17cb; // 6091
|
|
201
|
+
/** InvalidCollateralMint: Invalid collateral mint - not supported or no vault exists */
|
|
202
|
+
export const OPTION_PROGRAM_ERROR__INVALID_COLLATERAL_MINT = 0x17cc; // 6092
|
|
203
|
+
/** CollateralMismatch: Collateral mint mismatch - position uses different collateral type */
|
|
204
|
+
export const OPTION_PROGRAM_ERROR__COLLATERAL_MISMATCH = 0x17cd; // 6093
|
|
199
205
|
|
|
200
206
|
export type OptionProgramError =
|
|
201
207
|
| typeof OPTION_PROGRAM_ERROR__ACCOUNT_FROZEN
|
|
@@ -203,6 +209,7 @@ export type OptionProgramError =
|
|
|
203
209
|
| typeof OPTION_PROGRAM_ERROR__ARITHMETIC_OVERFLOW
|
|
204
210
|
| typeof OPTION_PROGRAM_ERROR__ARITHMETIC_UNDERFLOW
|
|
205
211
|
| typeof OPTION_PROGRAM_ERROR__BATCH_SIZE_EXCEEDED
|
|
212
|
+
| typeof OPTION_PROGRAM_ERROR__COLLATERAL_MISMATCH
|
|
206
213
|
| typeof OPTION_PROGRAM_ERROR__COLLATERAL_POOL_NOT_FOUND
|
|
207
214
|
| typeof OPTION_PROGRAM_ERROR__CONTRACT_ALREADY_SETTLED
|
|
208
215
|
| typeof OPTION_PROGRAM_ERROR__DIVISION_BY_ZERO
|
|
@@ -227,6 +234,7 @@ export type OptionProgramError =
|
|
|
227
234
|
| typeof OPTION_PROGRAM_ERROR__INVALID_ACCOUNT
|
|
228
235
|
| typeof OPTION_PROGRAM_ERROR__INVALID_AUTHORITY
|
|
229
236
|
| typeof OPTION_PROGRAM_ERROR__INVALID_BUYER_AUTHORITY
|
|
237
|
+
| typeof OPTION_PROGRAM_ERROR__INVALID_COLLATERAL_MINT
|
|
230
238
|
| typeof OPTION_PROGRAM_ERROR__INVALID_ESCROW_AUTHORITY
|
|
231
239
|
| typeof OPTION_PROGRAM_ERROR__INVALID_ESCROW_MAKER
|
|
232
240
|
| typeof OPTION_PROGRAM_ERROR__INVALID_ESCROW_MINT
|
|
@@ -248,6 +256,7 @@ export type OptionProgramError =
|
|
|
248
256
|
| typeof OPTION_PROGRAM_ERROR__INVALID_TENOR
|
|
249
257
|
| typeof OPTION_PROGRAM_ERROR__INVALID_TIME_TO_EXPIRATION
|
|
250
258
|
| typeof OPTION_PROGRAM_ERROR__INVALID_UNDERLYING_PRICE
|
|
259
|
+
| typeof OPTION_PROGRAM_ERROR__INVALID_VAULT_MINT
|
|
251
260
|
| typeof OPTION_PROGRAM_ERROR__INVALID_VOLATILITY
|
|
252
261
|
| typeof OPTION_PROGRAM_ERROR__LOW_ORACLE_PRICE_CONFIDENCE
|
|
253
262
|
| typeof OPTION_PROGRAM_ERROR__MARKET_CLOSED
|
|
@@ -298,6 +307,7 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
298
307
|
[OPTION_PROGRAM_ERROR__ARITHMETIC_OVERFLOW]: `Arithmetic overflow occurred`,
|
|
299
308
|
[OPTION_PROGRAM_ERROR__ARITHMETIC_UNDERFLOW]: `Arithmetic underflow occurred`,
|
|
300
309
|
[OPTION_PROGRAM_ERROR__BATCH_SIZE_EXCEEDED]: `Batch size exceeds maximum allowed (10 positions)`,
|
|
310
|
+
[OPTION_PROGRAM_ERROR__COLLATERAL_MISMATCH]: `Collateral mint mismatch - position uses different collateral type`,
|
|
301
311
|
[OPTION_PROGRAM_ERROR__COLLATERAL_POOL_NOT_FOUND]: `Collateral pool does not exist`,
|
|
302
312
|
[OPTION_PROGRAM_ERROR__CONTRACT_ALREADY_SETTLED]: `Contract already settled`,
|
|
303
313
|
[OPTION_PROGRAM_ERROR__DIVISION_BY_ZERO]: `Division by zero`,
|
|
@@ -322,6 +332,7 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
322
332
|
[OPTION_PROGRAM_ERROR__INVALID_ACCOUNT]: `Invalid account - does not match expected account`,
|
|
323
333
|
[OPTION_PROGRAM_ERROR__INVALID_AUTHORITY]: `Invalid authority - does not match escrow authority`,
|
|
324
334
|
[OPTION_PROGRAM_ERROR__INVALID_BUYER_AUTHORITY]: `Invalid buyer authority`,
|
|
335
|
+
[OPTION_PROGRAM_ERROR__INVALID_COLLATERAL_MINT]: `Invalid collateral mint - not supported or no vault exists`,
|
|
325
336
|
[OPTION_PROGRAM_ERROR__INVALID_ESCROW_AUTHORITY]: `Invalid escrow authority`,
|
|
326
337
|
[OPTION_PROGRAM_ERROR__INVALID_ESCROW_MAKER]: `Escrow state maker does not match instruction maker`,
|
|
327
338
|
[OPTION_PROGRAM_ERROR__INVALID_ESCROW_MINT]: `Escrow token account mint mismatch`,
|
|
@@ -343,6 +354,7 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
343
354
|
[OPTION_PROGRAM_ERROR__INVALID_TENOR]: `Invalid loan tenor`,
|
|
344
355
|
[OPTION_PROGRAM_ERROR__INVALID_TIME_TO_EXPIRATION]: `Time to expiration must be positive`,
|
|
345
356
|
[OPTION_PROGRAM_ERROR__INVALID_UNDERLYING_PRICE]: `Underlying price is invalid`,
|
|
357
|
+
[OPTION_PROGRAM_ERROR__INVALID_VAULT_MINT]: `Invalid vault mint - does not match expected collateral mint`,
|
|
346
358
|
[OPTION_PROGRAM_ERROR__INVALID_VOLATILITY]: `Volatility must be greater than zero`,
|
|
347
359
|
[OPTION_PROGRAM_ERROR__LOW_ORACLE_PRICE_CONFIDENCE]: `Oracle price confidence is too low`,
|
|
348
360
|
[OPTION_PROGRAM_ERROR__MARKET_CLOSED]: `Market is closed`,
|
|
@@ -79,6 +79,7 @@ export type OptionMintInstruction<
|
|
|
79
79
|
TAccountShortMetadataAccount extends string | AccountMeta<string> = string,
|
|
80
80
|
TAccountMarketData extends string | AccountMeta<string> = string,
|
|
81
81
|
TAccountUnderlyingMint extends string | AccountMeta<string> = string,
|
|
82
|
+
TAccountCollateralMint extends string | AccountMeta<string> = string,
|
|
82
83
|
TAccountOptionPool extends string | AccountMeta<string> = string,
|
|
83
84
|
TAccountEscrowLongAccount extends string | AccountMeta<string> = string,
|
|
84
85
|
TAccountPremiumVault extends string | AccountMeta<string> = string,
|
|
@@ -92,6 +93,7 @@ export type OptionMintInstruction<
|
|
|
92
93
|
TAccountEscrowAuthority extends string | AccountMeta<string> = string,
|
|
93
94
|
TAccountEscrowTokenAccount extends string | AccountMeta<string> = string,
|
|
94
95
|
TAccountPoolLoan extends string | AccountMeta<string> = string,
|
|
96
|
+
TAccountPriceUpdate extends string | AccountMeta<string> = string,
|
|
95
97
|
TAccountMaker extends string | AccountMeta<string> = string,
|
|
96
98
|
TAccountTokenProgram extends string | AccountMeta<string> =
|
|
97
99
|
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
|
|
@@ -138,6 +140,9 @@ export type OptionMintInstruction<
|
|
|
138
140
|
TAccountUnderlyingMint extends string
|
|
139
141
|
? ReadonlyAccount<TAccountUnderlyingMint>
|
|
140
142
|
: TAccountUnderlyingMint,
|
|
143
|
+
TAccountCollateralMint extends string
|
|
144
|
+
? ReadonlyAccount<TAccountCollateralMint>
|
|
145
|
+
: TAccountCollateralMint,
|
|
141
146
|
TAccountOptionPool extends string
|
|
142
147
|
? WritableAccount<TAccountOptionPool>
|
|
143
148
|
: TAccountOptionPool,
|
|
@@ -177,6 +182,9 @@ export type OptionMintInstruction<
|
|
|
177
182
|
TAccountPoolLoan extends string
|
|
178
183
|
? WritableAccount<TAccountPoolLoan>
|
|
179
184
|
: TAccountPoolLoan,
|
|
185
|
+
TAccountPriceUpdate extends string
|
|
186
|
+
? ReadonlyAccount<TAccountPriceUpdate>
|
|
187
|
+
: TAccountPriceUpdate,
|
|
180
188
|
TAccountMaker extends string
|
|
181
189
|
? WritableSignerAccount<TAccountMaker> &
|
|
182
190
|
AccountSignerMeta<TAccountMaker>
|
|
@@ -208,6 +216,7 @@ export type OptionMintInstructionData = {
|
|
|
208
216
|
quantity: bigint;
|
|
209
217
|
underlyingAsset: Address;
|
|
210
218
|
underlyingSymbol: string;
|
|
219
|
+
collateralMint: Address;
|
|
211
220
|
makerCollateralAmount: bigint;
|
|
212
221
|
borrowedAmount: bigint;
|
|
213
222
|
};
|
|
@@ -219,6 +228,7 @@ export type OptionMintInstructionDataArgs = {
|
|
|
219
228
|
quantity: number | bigint;
|
|
220
229
|
underlyingAsset: Address;
|
|
221
230
|
underlyingSymbol: string;
|
|
231
|
+
collateralMint: Address;
|
|
222
232
|
makerCollateralAmount: number | bigint;
|
|
223
233
|
borrowedAmount: number | bigint;
|
|
224
234
|
};
|
|
@@ -236,6 +246,7 @@ export function getOptionMintInstructionDataEncoder(): Encoder<OptionMintInstruc
|
|
|
236
246
|
"underlyingSymbol",
|
|
237
247
|
addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder()),
|
|
238
248
|
],
|
|
249
|
+
["collateralMint", getAddressEncoder()],
|
|
239
250
|
["makerCollateralAmount", getU64Encoder()],
|
|
240
251
|
["borrowedAmount", getU64Encoder()],
|
|
241
252
|
]),
|
|
@@ -255,6 +266,7 @@ export function getOptionMintInstructionDataDecoder(): Decoder<OptionMintInstruc
|
|
|
255
266
|
"underlyingSymbol",
|
|
256
267
|
addDecoderSizePrefix(getUtf8Decoder(), getU32Decoder()),
|
|
257
268
|
],
|
|
269
|
+
["collateralMint", getAddressDecoder()],
|
|
258
270
|
["makerCollateralAmount", getU64Decoder()],
|
|
259
271
|
["borrowedAmount", getU64Decoder()],
|
|
260
272
|
]);
|
|
@@ -281,6 +293,7 @@ export type OptionMintAsyncInput<
|
|
|
281
293
|
TAccountShortMetadataAccount extends string = string,
|
|
282
294
|
TAccountMarketData extends string = string,
|
|
283
295
|
TAccountUnderlyingMint extends string = string,
|
|
296
|
+
TAccountCollateralMint extends string = string,
|
|
284
297
|
TAccountOptionPool extends string = string,
|
|
285
298
|
TAccountEscrowLongAccount extends string = string,
|
|
286
299
|
TAccountPremiumVault extends string = string,
|
|
@@ -294,6 +307,7 @@ export type OptionMintAsyncInput<
|
|
|
294
307
|
TAccountEscrowAuthority extends string = string,
|
|
295
308
|
TAccountEscrowTokenAccount extends string = string,
|
|
296
309
|
TAccountPoolLoan extends string = string,
|
|
310
|
+
TAccountPriceUpdate extends string = string,
|
|
297
311
|
TAccountMaker extends string = string,
|
|
298
312
|
TAccountTokenProgram extends string = string,
|
|
299
313
|
TAccountAssociatedTokenProgram extends string = string,
|
|
@@ -325,8 +339,14 @@ export type OptionMintAsyncInput<
|
|
|
325
339
|
shortMetadataAccount: Address<TAccountShortMetadataAccount>;
|
|
326
340
|
/** Market data account - provides baseline historical volatility for initial IV */
|
|
327
341
|
marketData?: Address<TAccountMarketData>;
|
|
328
|
-
/** Underlying asset mint (e.g., WSOL) - required for
|
|
342
|
+
/** Underlying asset mint (e.g., WSOL) - required for pricing and pool initialization */
|
|
329
343
|
underlyingMint: Address<TAccountUnderlyingMint>;
|
|
344
|
+
/**
|
|
345
|
+
* Collateral mint (e.g., USDC, BTC, SOL) - Writer's choice for backing the position
|
|
346
|
+
* Can differ from underlying_mint - enables multi-collateral settlement
|
|
347
|
+
* OMLP vault routing is based on this mint
|
|
348
|
+
*/
|
|
349
|
+
collateralMint: Address<TAccountCollateralMint>;
|
|
330
350
|
/** Option pool - aggregated liquidity pool for this option */
|
|
331
351
|
optionPool?: Address<TAccountOptionPool>;
|
|
332
352
|
/** Pool's escrow for holding LONG tokens (for buyers to purchase) */
|
|
@@ -353,6 +373,11 @@ export type OptionMintAsyncInput<
|
|
|
353
373
|
escrowTokenAccount?: Address<TAccountEscrowTokenAccount>;
|
|
354
374
|
/** Pool loan account (optional - only required if borrowing) */
|
|
355
375
|
poolLoan?: Address<TAccountPoolLoan>;
|
|
376
|
+
/**
|
|
377
|
+
* Pyth price update account for collateral calculation
|
|
378
|
+
* Required to convert USD collateral requirement to token units
|
|
379
|
+
*/
|
|
380
|
+
priceUpdate: Address<TAccountPriceUpdate>;
|
|
356
381
|
maker: TransactionSigner<TAccountMaker>;
|
|
357
382
|
tokenProgram?: Address<TAccountTokenProgram>;
|
|
358
383
|
associatedTokenProgram?: Address<TAccountAssociatedTokenProgram>;
|
|
@@ -365,6 +390,7 @@ export type OptionMintAsyncInput<
|
|
|
365
390
|
quantity: OptionMintInstructionDataArgs["quantity"];
|
|
366
391
|
underlyingAsset: OptionMintInstructionDataArgs["underlyingAsset"];
|
|
367
392
|
underlyingSymbol: OptionMintInstructionDataArgs["underlyingSymbol"];
|
|
393
|
+
collateralMintArg: OptionMintInstructionDataArgs["collateralMint"];
|
|
368
394
|
makerCollateralAmount: OptionMintInstructionDataArgs["makerCollateralAmount"];
|
|
369
395
|
borrowedAmount: OptionMintInstructionDataArgs["borrowedAmount"];
|
|
370
396
|
};
|
|
@@ -380,6 +406,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
380
406
|
TAccountShortMetadataAccount extends string,
|
|
381
407
|
TAccountMarketData extends string,
|
|
382
408
|
TAccountUnderlyingMint extends string,
|
|
409
|
+
TAccountCollateralMint extends string,
|
|
383
410
|
TAccountOptionPool extends string,
|
|
384
411
|
TAccountEscrowLongAccount extends string,
|
|
385
412
|
TAccountPremiumVault extends string,
|
|
@@ -393,6 +420,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
393
420
|
TAccountEscrowAuthority extends string,
|
|
394
421
|
TAccountEscrowTokenAccount extends string,
|
|
395
422
|
TAccountPoolLoan extends string,
|
|
423
|
+
TAccountPriceUpdate extends string,
|
|
396
424
|
TAccountMaker extends string,
|
|
397
425
|
TAccountTokenProgram extends string,
|
|
398
426
|
TAccountAssociatedTokenProgram extends string,
|
|
@@ -412,6 +440,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
412
440
|
TAccountShortMetadataAccount,
|
|
413
441
|
TAccountMarketData,
|
|
414
442
|
TAccountUnderlyingMint,
|
|
443
|
+
TAccountCollateralMint,
|
|
415
444
|
TAccountOptionPool,
|
|
416
445
|
TAccountEscrowLongAccount,
|
|
417
446
|
TAccountPremiumVault,
|
|
@@ -425,6 +454,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
425
454
|
TAccountEscrowAuthority,
|
|
426
455
|
TAccountEscrowTokenAccount,
|
|
427
456
|
TAccountPoolLoan,
|
|
457
|
+
TAccountPriceUpdate,
|
|
428
458
|
TAccountMaker,
|
|
429
459
|
TAccountTokenProgram,
|
|
430
460
|
TAccountAssociatedTokenProgram,
|
|
@@ -446,6 +476,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
446
476
|
TAccountShortMetadataAccount,
|
|
447
477
|
TAccountMarketData,
|
|
448
478
|
TAccountUnderlyingMint,
|
|
479
|
+
TAccountCollateralMint,
|
|
449
480
|
TAccountOptionPool,
|
|
450
481
|
TAccountEscrowLongAccount,
|
|
451
482
|
TAccountPremiumVault,
|
|
@@ -459,6 +490,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
459
490
|
TAccountEscrowAuthority,
|
|
460
491
|
TAccountEscrowTokenAccount,
|
|
461
492
|
TAccountPoolLoan,
|
|
493
|
+
TAccountPriceUpdate,
|
|
462
494
|
TAccountMaker,
|
|
463
495
|
TAccountTokenProgram,
|
|
464
496
|
TAccountAssociatedTokenProgram,
|
|
@@ -495,6 +527,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
495
527
|
},
|
|
496
528
|
marketData: { value: input.marketData ?? null, isWritable: false },
|
|
497
529
|
underlyingMint: { value: input.underlyingMint ?? null, isWritable: false },
|
|
530
|
+
collateralMint: { value: input.collateralMint ?? null, isWritable: false },
|
|
498
531
|
optionPool: { value: input.optionPool ?? null, isWritable: true },
|
|
499
532
|
escrowLongAccount: {
|
|
500
533
|
value: input.escrowLongAccount ?? null,
|
|
@@ -523,6 +556,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
523
556
|
isWritable: true,
|
|
524
557
|
},
|
|
525
558
|
poolLoan: { value: input.poolLoan ?? null, isWritable: true },
|
|
559
|
+
priceUpdate: { value: input.priceUpdate ?? null, isWritable: false },
|
|
526
560
|
maker: { value: input.maker ?? null, isWritable: true },
|
|
527
561
|
tokenProgram: { value: input.tokenProgram ?? null, isWritable: false },
|
|
528
562
|
associatedTokenProgram: {
|
|
@@ -542,7 +576,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
542
576
|
>;
|
|
543
577
|
|
|
544
578
|
// Original args.
|
|
545
|
-
const args = { ...input };
|
|
579
|
+
const args = { ...input, collateralMint: input.collateralMintArg };
|
|
546
580
|
|
|
547
581
|
// Resolve default values.
|
|
548
582
|
if (!accounts.optionAccount.value) {
|
|
@@ -771,6 +805,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
771
805
|
getAccountMeta(accounts.shortMetadataAccount),
|
|
772
806
|
getAccountMeta(accounts.marketData),
|
|
773
807
|
getAccountMeta(accounts.underlyingMint),
|
|
808
|
+
getAccountMeta(accounts.collateralMint),
|
|
774
809
|
getAccountMeta(accounts.optionPool),
|
|
775
810
|
getAccountMeta(accounts.escrowLongAccount),
|
|
776
811
|
getAccountMeta(accounts.premiumVault),
|
|
@@ -784,6 +819,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
784
819
|
getAccountMeta(accounts.escrowAuthority),
|
|
785
820
|
getAccountMeta(accounts.escrowTokenAccount),
|
|
786
821
|
getAccountMeta(accounts.poolLoan),
|
|
822
|
+
getAccountMeta(accounts.priceUpdate),
|
|
787
823
|
getAccountMeta(accounts.maker),
|
|
788
824
|
getAccountMeta(accounts.tokenProgram),
|
|
789
825
|
getAccountMeta(accounts.associatedTokenProgram),
|
|
@@ -807,6 +843,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
807
843
|
TAccountShortMetadataAccount,
|
|
808
844
|
TAccountMarketData,
|
|
809
845
|
TAccountUnderlyingMint,
|
|
846
|
+
TAccountCollateralMint,
|
|
810
847
|
TAccountOptionPool,
|
|
811
848
|
TAccountEscrowLongAccount,
|
|
812
849
|
TAccountPremiumVault,
|
|
@@ -820,6 +857,7 @@ export async function getOptionMintInstructionAsync<
|
|
|
820
857
|
TAccountEscrowAuthority,
|
|
821
858
|
TAccountEscrowTokenAccount,
|
|
822
859
|
TAccountPoolLoan,
|
|
860
|
+
TAccountPriceUpdate,
|
|
823
861
|
TAccountMaker,
|
|
824
862
|
TAccountTokenProgram,
|
|
825
863
|
TAccountAssociatedTokenProgram,
|
|
@@ -840,6 +878,7 @@ export type OptionMintInput<
|
|
|
840
878
|
TAccountShortMetadataAccount extends string = string,
|
|
841
879
|
TAccountMarketData extends string = string,
|
|
842
880
|
TAccountUnderlyingMint extends string = string,
|
|
881
|
+
TAccountCollateralMint extends string = string,
|
|
843
882
|
TAccountOptionPool extends string = string,
|
|
844
883
|
TAccountEscrowLongAccount extends string = string,
|
|
845
884
|
TAccountPremiumVault extends string = string,
|
|
@@ -853,6 +892,7 @@ export type OptionMintInput<
|
|
|
853
892
|
TAccountEscrowAuthority extends string = string,
|
|
854
893
|
TAccountEscrowTokenAccount extends string = string,
|
|
855
894
|
TAccountPoolLoan extends string = string,
|
|
895
|
+
TAccountPriceUpdate extends string = string,
|
|
856
896
|
TAccountMaker extends string = string,
|
|
857
897
|
TAccountTokenProgram extends string = string,
|
|
858
898
|
TAccountAssociatedTokenProgram extends string = string,
|
|
@@ -884,8 +924,14 @@ export type OptionMintInput<
|
|
|
884
924
|
shortMetadataAccount: Address<TAccountShortMetadataAccount>;
|
|
885
925
|
/** Market data account - provides baseline historical volatility for initial IV */
|
|
886
926
|
marketData: Address<TAccountMarketData>;
|
|
887
|
-
/** Underlying asset mint (e.g., WSOL) - required for
|
|
927
|
+
/** Underlying asset mint (e.g., WSOL) - required for pricing and pool initialization */
|
|
888
928
|
underlyingMint: Address<TAccountUnderlyingMint>;
|
|
929
|
+
/**
|
|
930
|
+
* Collateral mint (e.g., USDC, BTC, SOL) - Writer's choice for backing the position
|
|
931
|
+
* Can differ from underlying_mint - enables multi-collateral settlement
|
|
932
|
+
* OMLP vault routing is based on this mint
|
|
933
|
+
*/
|
|
934
|
+
collateralMint: Address<TAccountCollateralMint>;
|
|
889
935
|
/** Option pool - aggregated liquidity pool for this option */
|
|
890
936
|
optionPool: Address<TAccountOptionPool>;
|
|
891
937
|
/** Pool's escrow for holding LONG tokens (for buyers to purchase) */
|
|
@@ -912,6 +958,11 @@ export type OptionMintInput<
|
|
|
912
958
|
escrowTokenAccount?: Address<TAccountEscrowTokenAccount>;
|
|
913
959
|
/** Pool loan account (optional - only required if borrowing) */
|
|
914
960
|
poolLoan?: Address<TAccountPoolLoan>;
|
|
961
|
+
/**
|
|
962
|
+
* Pyth price update account for collateral calculation
|
|
963
|
+
* Required to convert USD collateral requirement to token units
|
|
964
|
+
*/
|
|
965
|
+
priceUpdate: Address<TAccountPriceUpdate>;
|
|
915
966
|
maker: TransactionSigner<TAccountMaker>;
|
|
916
967
|
tokenProgram?: Address<TAccountTokenProgram>;
|
|
917
968
|
associatedTokenProgram?: Address<TAccountAssociatedTokenProgram>;
|
|
@@ -924,6 +975,7 @@ export type OptionMintInput<
|
|
|
924
975
|
quantity: OptionMintInstructionDataArgs["quantity"];
|
|
925
976
|
underlyingAsset: OptionMintInstructionDataArgs["underlyingAsset"];
|
|
926
977
|
underlyingSymbol: OptionMintInstructionDataArgs["underlyingSymbol"];
|
|
978
|
+
collateralMintArg: OptionMintInstructionDataArgs["collateralMint"];
|
|
927
979
|
makerCollateralAmount: OptionMintInstructionDataArgs["makerCollateralAmount"];
|
|
928
980
|
borrowedAmount: OptionMintInstructionDataArgs["borrowedAmount"];
|
|
929
981
|
};
|
|
@@ -939,6 +991,7 @@ export function getOptionMintInstruction<
|
|
|
939
991
|
TAccountShortMetadataAccount extends string,
|
|
940
992
|
TAccountMarketData extends string,
|
|
941
993
|
TAccountUnderlyingMint extends string,
|
|
994
|
+
TAccountCollateralMint extends string,
|
|
942
995
|
TAccountOptionPool extends string,
|
|
943
996
|
TAccountEscrowLongAccount extends string,
|
|
944
997
|
TAccountPremiumVault extends string,
|
|
@@ -952,6 +1005,7 @@ export function getOptionMintInstruction<
|
|
|
952
1005
|
TAccountEscrowAuthority extends string,
|
|
953
1006
|
TAccountEscrowTokenAccount extends string,
|
|
954
1007
|
TAccountPoolLoan extends string,
|
|
1008
|
+
TAccountPriceUpdate extends string,
|
|
955
1009
|
TAccountMaker extends string,
|
|
956
1010
|
TAccountTokenProgram extends string,
|
|
957
1011
|
TAccountAssociatedTokenProgram extends string,
|
|
@@ -971,6 +1025,7 @@ export function getOptionMintInstruction<
|
|
|
971
1025
|
TAccountShortMetadataAccount,
|
|
972
1026
|
TAccountMarketData,
|
|
973
1027
|
TAccountUnderlyingMint,
|
|
1028
|
+
TAccountCollateralMint,
|
|
974
1029
|
TAccountOptionPool,
|
|
975
1030
|
TAccountEscrowLongAccount,
|
|
976
1031
|
TAccountPremiumVault,
|
|
@@ -984,6 +1039,7 @@ export function getOptionMintInstruction<
|
|
|
984
1039
|
TAccountEscrowAuthority,
|
|
985
1040
|
TAccountEscrowTokenAccount,
|
|
986
1041
|
TAccountPoolLoan,
|
|
1042
|
+
TAccountPriceUpdate,
|
|
987
1043
|
TAccountMaker,
|
|
988
1044
|
TAccountTokenProgram,
|
|
989
1045
|
TAccountAssociatedTokenProgram,
|
|
@@ -1004,6 +1060,7 @@ export function getOptionMintInstruction<
|
|
|
1004
1060
|
TAccountShortMetadataAccount,
|
|
1005
1061
|
TAccountMarketData,
|
|
1006
1062
|
TAccountUnderlyingMint,
|
|
1063
|
+
TAccountCollateralMint,
|
|
1007
1064
|
TAccountOptionPool,
|
|
1008
1065
|
TAccountEscrowLongAccount,
|
|
1009
1066
|
TAccountPremiumVault,
|
|
@@ -1017,6 +1074,7 @@ export function getOptionMintInstruction<
|
|
|
1017
1074
|
TAccountEscrowAuthority,
|
|
1018
1075
|
TAccountEscrowTokenAccount,
|
|
1019
1076
|
TAccountPoolLoan,
|
|
1077
|
+
TAccountPriceUpdate,
|
|
1020
1078
|
TAccountMaker,
|
|
1021
1079
|
TAccountTokenProgram,
|
|
1022
1080
|
TAccountAssociatedTokenProgram,
|
|
@@ -1052,6 +1110,7 @@ export function getOptionMintInstruction<
|
|
|
1052
1110
|
},
|
|
1053
1111
|
marketData: { value: input.marketData ?? null, isWritable: false },
|
|
1054
1112
|
underlyingMint: { value: input.underlyingMint ?? null, isWritable: false },
|
|
1113
|
+
collateralMint: { value: input.collateralMint ?? null, isWritable: false },
|
|
1055
1114
|
optionPool: { value: input.optionPool ?? null, isWritable: true },
|
|
1056
1115
|
escrowLongAccount: {
|
|
1057
1116
|
value: input.escrowLongAccount ?? null,
|
|
@@ -1080,6 +1139,7 @@ export function getOptionMintInstruction<
|
|
|
1080
1139
|
isWritable: true,
|
|
1081
1140
|
},
|
|
1082
1141
|
poolLoan: { value: input.poolLoan ?? null, isWritable: true },
|
|
1142
|
+
priceUpdate: { value: input.priceUpdate ?? null, isWritable: false },
|
|
1083
1143
|
maker: { value: input.maker ?? null, isWritable: true },
|
|
1084
1144
|
tokenProgram: { value: input.tokenProgram ?? null, isWritable: false },
|
|
1085
1145
|
associatedTokenProgram: {
|
|
@@ -1099,7 +1159,7 @@ export function getOptionMintInstruction<
|
|
|
1099
1159
|
>;
|
|
1100
1160
|
|
|
1101
1161
|
// Original args.
|
|
1102
|
-
const args = { ...input };
|
|
1162
|
+
const args = { ...input, collateralMint: input.collateralMintArg };
|
|
1103
1163
|
|
|
1104
1164
|
// Resolve default values.
|
|
1105
1165
|
if (!accounts.tokenProgram.value) {
|
|
@@ -1136,6 +1196,7 @@ export function getOptionMintInstruction<
|
|
|
1136
1196
|
getAccountMeta(accounts.shortMetadataAccount),
|
|
1137
1197
|
getAccountMeta(accounts.marketData),
|
|
1138
1198
|
getAccountMeta(accounts.underlyingMint),
|
|
1199
|
+
getAccountMeta(accounts.collateralMint),
|
|
1139
1200
|
getAccountMeta(accounts.optionPool),
|
|
1140
1201
|
getAccountMeta(accounts.escrowLongAccount),
|
|
1141
1202
|
getAccountMeta(accounts.premiumVault),
|
|
@@ -1149,6 +1210,7 @@ export function getOptionMintInstruction<
|
|
|
1149
1210
|
getAccountMeta(accounts.escrowAuthority),
|
|
1150
1211
|
getAccountMeta(accounts.escrowTokenAccount),
|
|
1151
1212
|
getAccountMeta(accounts.poolLoan),
|
|
1213
|
+
getAccountMeta(accounts.priceUpdate),
|
|
1152
1214
|
getAccountMeta(accounts.maker),
|
|
1153
1215
|
getAccountMeta(accounts.tokenProgram),
|
|
1154
1216
|
getAccountMeta(accounts.associatedTokenProgram),
|
|
@@ -1172,6 +1234,7 @@ export function getOptionMintInstruction<
|
|
|
1172
1234
|
TAccountShortMetadataAccount,
|
|
1173
1235
|
TAccountMarketData,
|
|
1174
1236
|
TAccountUnderlyingMint,
|
|
1237
|
+
TAccountCollateralMint,
|
|
1175
1238
|
TAccountOptionPool,
|
|
1176
1239
|
TAccountEscrowLongAccount,
|
|
1177
1240
|
TAccountPremiumVault,
|
|
@@ -1185,6 +1248,7 @@ export function getOptionMintInstruction<
|
|
|
1185
1248
|
TAccountEscrowAuthority,
|
|
1186
1249
|
TAccountEscrowTokenAccount,
|
|
1187
1250
|
TAccountPoolLoan,
|
|
1251
|
+
TAccountPriceUpdate,
|
|
1188
1252
|
TAccountMaker,
|
|
1189
1253
|
TAccountTokenProgram,
|
|
1190
1254
|
TAccountAssociatedTokenProgram,
|
|
@@ -1224,40 +1288,51 @@ export type ParsedOptionMintInstruction<
|
|
|
1224
1288
|
shortMetadataAccount: TAccountMetas[7];
|
|
1225
1289
|
/** Market data account - provides baseline historical volatility for initial IV */
|
|
1226
1290
|
marketData: TAccountMetas[8];
|
|
1227
|
-
/** Underlying asset mint (e.g., WSOL) - required for
|
|
1291
|
+
/** Underlying asset mint (e.g., WSOL) - required for pricing and pool initialization */
|
|
1228
1292
|
underlyingMint: TAccountMetas[9];
|
|
1293
|
+
/**
|
|
1294
|
+
* Collateral mint (e.g., USDC, BTC, SOL) - Writer's choice for backing the position
|
|
1295
|
+
* Can differ from underlying_mint - enables multi-collateral settlement
|
|
1296
|
+
* OMLP vault routing is based on this mint
|
|
1297
|
+
*/
|
|
1298
|
+
collateralMint: TAccountMetas[10];
|
|
1229
1299
|
/** Option pool - aggregated liquidity pool for this option */
|
|
1230
|
-
optionPool: TAccountMetas[
|
|
1300
|
+
optionPool: TAccountMetas[11];
|
|
1231
1301
|
/** Pool's escrow for holding LONG tokens (for buyers to purchase) */
|
|
1232
|
-
escrowLongAccount: TAccountMetas[
|
|
1302
|
+
escrowLongAccount: TAccountMetas[12];
|
|
1233
1303
|
/** Pool's vault for collecting premiums (in underlying asset) */
|
|
1234
|
-
premiumVault: TAccountMetas[
|
|
1304
|
+
premiumVault: TAccountMetas[13];
|
|
1235
1305
|
/** Collateral pool for this option */
|
|
1236
|
-
collateralPool: TAccountMetas[
|
|
1306
|
+
collateralPool: TAccountMetas[14];
|
|
1237
1307
|
/** Collateral vault (ATA holding collateral) */
|
|
1238
|
-
collateralVault: TAccountMetas[
|
|
1308
|
+
collateralVault: TAccountMetas[15];
|
|
1239
1309
|
/** Maker's collateral account (source of maker's own collateral) */
|
|
1240
|
-
makerCollateralAccount: TAccountMetas[
|
|
1310
|
+
makerCollateralAccount: TAccountMetas[16];
|
|
1241
1311
|
/** Writer's unified position account (single source of truth) */
|
|
1242
|
-
writerPosition: TAccountMetas[
|
|
1312
|
+
writerPosition: TAccountMetas[17];
|
|
1243
1313
|
/** OMLP vault (optional - only required if borrowing) */
|
|
1244
|
-
vault?: TAccountMetas[
|
|
1314
|
+
vault?: TAccountMetas[18] | undefined;
|
|
1245
1315
|
/** Vault's token account (optional - only required if borrowing) */
|
|
1246
|
-
vaultTokenAccount?: TAccountMetas[
|
|
1316
|
+
vaultTokenAccount?: TAccountMetas[19] | undefined;
|
|
1247
1317
|
/** Escrow state PDA (optional - only required if borrowing) */
|
|
1248
|
-
escrowState?: TAccountMetas[
|
|
1318
|
+
escrowState?: TAccountMetas[20] | undefined;
|
|
1249
1319
|
/** Escrow authority PDA (optional - only required if borrowing) */
|
|
1250
|
-
escrowAuthority?: TAccountMetas[
|
|
1320
|
+
escrowAuthority?: TAccountMetas[21] | undefined;
|
|
1251
1321
|
/** Escrow token account (optional - only required if borrowing) */
|
|
1252
|
-
escrowTokenAccount?: TAccountMetas[
|
|
1322
|
+
escrowTokenAccount?: TAccountMetas[22] | undefined;
|
|
1253
1323
|
/** Pool loan account (optional - only required if borrowing) */
|
|
1254
|
-
poolLoan?: TAccountMetas[
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1324
|
+
poolLoan?: TAccountMetas[23] | undefined;
|
|
1325
|
+
/**
|
|
1326
|
+
* Pyth price update account for collateral calculation
|
|
1327
|
+
* Required to convert USD collateral requirement to token units
|
|
1328
|
+
*/
|
|
1329
|
+
priceUpdate: TAccountMetas[24];
|
|
1330
|
+
maker: TAccountMetas[25];
|
|
1331
|
+
tokenProgram: TAccountMetas[26];
|
|
1332
|
+
associatedTokenProgram: TAccountMetas[27];
|
|
1333
|
+
tokenMetadataProgram: TAccountMetas[28];
|
|
1334
|
+
systemProgram: TAccountMetas[29];
|
|
1335
|
+
rent: TAccountMetas[30];
|
|
1261
1336
|
};
|
|
1262
1337
|
data: OptionMintInstructionData;
|
|
1263
1338
|
};
|
|
@@ -1270,7 +1345,7 @@ export function parseOptionMintInstruction<
|
|
|
1270
1345
|
InstructionWithAccounts<TAccountMetas> &
|
|
1271
1346
|
InstructionWithData<ReadonlyUint8Array>,
|
|
1272
1347
|
): ParsedOptionMintInstruction<TProgram, TAccountMetas> {
|
|
1273
|
-
if (instruction.accounts.length <
|
|
1348
|
+
if (instruction.accounts.length < 31) {
|
|
1274
1349
|
// TODO: Coded error.
|
|
1275
1350
|
throw new Error("Not enough accounts");
|
|
1276
1351
|
}
|
|
@@ -1299,6 +1374,7 @@ export function parseOptionMintInstruction<
|
|
|
1299
1374
|
shortMetadataAccount: getNextAccount(),
|
|
1300
1375
|
marketData: getNextAccount(),
|
|
1301
1376
|
underlyingMint: getNextAccount(),
|
|
1377
|
+
collateralMint: getNextAccount(),
|
|
1302
1378
|
optionPool: getNextAccount(),
|
|
1303
1379
|
escrowLongAccount: getNextAccount(),
|
|
1304
1380
|
premiumVault: getNextAccount(),
|
|
@@ -1312,6 +1388,7 @@ export function parseOptionMintInstruction<
|
|
|
1312
1388
|
escrowAuthority: getNextOptionalAccount(),
|
|
1313
1389
|
escrowTokenAccount: getNextOptionalAccount(),
|
|
1314
1390
|
poolLoan: getNextOptionalAccount(),
|
|
1391
|
+
priceUpdate: getNextAccount(),
|
|
1315
1392
|
maker: getNextAccount(),
|
|
1316
1393
|
tokenProgram: getNextAccount(),
|
|
1317
1394
|
associatedTokenProgram: getNextAccount(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epicentral/sos-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-alpha.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Solana Option Standard SDK. The frontend-first SDK for Native Options Trading on Solana. Created by Epicentral Labs.",
|
|
6
6
|
"type": "module",
|
package/shared/amounts.ts
CHANGED
|
@@ -24,9 +24,30 @@ export function assertNonNegativeAmount(value: bigint | number, label: string):
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Calculate required collateral for option position in token base units
|
|
29
|
+
* Matches on-chain formula: ((qty / 1_000_000) * 100 * strike) / spot * 10^decimals
|
|
30
|
+
*
|
|
31
|
+
* @param quantity - Option quantity in base units (1 contract = 1_000_000)
|
|
32
|
+
* @param strikePrice - Strike price in USD
|
|
33
|
+
* @param spotPrice - Current spot price of underlying in USD (from oracle)
|
|
34
|
+
* @param tokenDecimals - Number of decimals for the underlying token (e.g., 9 for SOL)
|
|
35
|
+
* @returns Required collateral in token base units
|
|
36
|
+
*/
|
|
27
37
|
export function calculateRequiredCollateral(
|
|
28
38
|
quantity: bigint | number,
|
|
29
|
-
strikePrice: number
|
|
39
|
+
strikePrice: number,
|
|
40
|
+
spotPrice: number,
|
|
41
|
+
tokenDecimals: number
|
|
30
42
|
): number {
|
|
31
|
-
|
|
43
|
+
// Convert base units to contract count
|
|
44
|
+
const contracts = Number(quantity) / 1_000_000;
|
|
45
|
+
const contractSize = 100; // 1 contract = 100 units of underlying
|
|
46
|
+
|
|
47
|
+
// USD value needed for collateral
|
|
48
|
+
const usdRequired = contracts * contractSize * strikePrice;
|
|
49
|
+
|
|
50
|
+
// Convert USD to token base units
|
|
51
|
+
const baseUnits = 10 ** tokenDecimals;
|
|
52
|
+
return (usdRequired / spotPrice) * baseUnits;
|
|
32
53
|
}
|
package/short/builders.ts
CHANGED
|
@@ -38,11 +38,22 @@ export interface BuildOptionMintParams {
|
|
|
38
38
|
quantity: bigint | number;
|
|
39
39
|
underlyingAsset: AddressLike;
|
|
40
40
|
underlyingSymbol: string;
|
|
41
|
+
/**
|
|
42
|
+
* Collateral mint (e.g., USDC, BTC, SOL) - Writer's choice for backing the position.
|
|
43
|
+
* Can differ from underlying asset - enables multi-collateral settlement.
|
|
44
|
+
* OMLP vault routing is based on this mint. Defaults to underlyingMint if not provided.
|
|
45
|
+
*/
|
|
46
|
+
collateralMint?: AddressLike;
|
|
41
47
|
makerCollateralAmount: bigint | number;
|
|
42
48
|
borrowedAmount: bigint | number;
|
|
43
49
|
maker: AddressLike;
|
|
44
50
|
makerCollateralAccount: AddressLike;
|
|
45
51
|
underlyingMint: AddressLike;
|
|
52
|
+
/**
|
|
53
|
+
* Pyth price update account for collateral calculation.
|
|
54
|
+
* Required to convert USD collateral requirement to token units.
|
|
55
|
+
*/
|
|
56
|
+
priceUpdate: AddressLike;
|
|
46
57
|
longMetadataAccount?: AddressLike;
|
|
47
58
|
shortMetadataAccount?: AddressLike;
|
|
48
59
|
optionAccount?: AddressLike;
|
|
@@ -162,6 +173,7 @@ export async function buildOptionMintInstruction(
|
|
|
162
173
|
shortMetadataAccount: toAddress(shortMetadata!),
|
|
163
174
|
marketData: params.marketData ? toAddress(params.marketData) : undefined,
|
|
164
175
|
underlyingMint: toAddress(params.underlyingMint),
|
|
176
|
+
collateralMint: toAddress(params.collateralMint ?? params.underlyingMint),
|
|
165
177
|
optionPool: params.optionPool ? toAddress(params.optionPool) : undefined,
|
|
166
178
|
escrowLongAccount: params.escrowLongAccount
|
|
167
179
|
? toAddress(params.escrowLongAccount)
|
|
@@ -181,6 +193,7 @@ export async function buildOptionMintInstruction(
|
|
|
181
193
|
? toAddress(params.escrowTokenAccount)
|
|
182
194
|
: undefined,
|
|
183
195
|
poolLoan: params.poolLoan ? toAddress(params.poolLoan) : undefined,
|
|
196
|
+
priceUpdate: toAddress(params.priceUpdate),
|
|
184
197
|
maker: toAddress(params.maker) as any,
|
|
185
198
|
optionType: params.optionType,
|
|
186
199
|
strikePrice: params.strikePrice,
|
|
@@ -188,6 +201,7 @@ export async function buildOptionMintInstruction(
|
|
|
188
201
|
quantity: params.quantity,
|
|
189
202
|
underlyingAsset: toAddress(params.underlyingAsset),
|
|
190
203
|
underlyingSymbol: params.underlyingSymbol,
|
|
204
|
+
collateralMintArg: toAddress(params.collateralMint ?? params.underlyingMint),
|
|
191
205
|
makerCollateralAmount: params.makerCollateralAmount,
|
|
192
206
|
borrowedAmount: params.borrowedAmount,
|
|
193
207
|
});
|
|
@@ -210,11 +224,25 @@ export interface BuildOptionMintTransactionWithDerivationParams {
|
|
|
210
224
|
quantity: bigint | number;
|
|
211
225
|
underlyingMint: AddressLike;
|
|
212
226
|
underlyingSymbol: string;
|
|
227
|
+
/**
|
|
228
|
+
* Collateral mint (e.g., USDC, BTC, SOL) - Writer's choice for backing the position.
|
|
229
|
+
* Can differ from underlying asset - enables multi-collateral settlement.
|
|
230
|
+
* OMLP vault routing is based on this mint. Defaults to underlyingMint if not provided.
|
|
231
|
+
*/
|
|
232
|
+
collateralMint?: AddressLike;
|
|
213
233
|
makerCollateralAmount: bigint | number;
|
|
214
234
|
borrowedAmount: bigint | number;
|
|
215
235
|
maker: AddressLike;
|
|
216
|
-
/**
|
|
236
|
+
/**
|
|
237
|
+
* Optional. When omitted, the SDK derives the maker's collateral ATA for collateralMint
|
|
238
|
+
* (or underlyingMint if collateralMint is not provided).
|
|
239
|
+
*/
|
|
217
240
|
makerCollateralAccount?: AddressLike;
|
|
241
|
+
/**
|
|
242
|
+
* Pyth price update account for collateral calculation.
|
|
243
|
+
* Required to convert USD collateral requirement to token units.
|
|
244
|
+
*/
|
|
245
|
+
priceUpdate: AddressLike;
|
|
218
246
|
rpc: KitRpc;
|
|
219
247
|
programId?: AddressLike;
|
|
220
248
|
vault?: AddressLike;
|
|
@@ -258,18 +286,20 @@ export async function buildOptionMintTransactionWithDerivation(
|
|
|
258
286
|
});
|
|
259
287
|
|
|
260
288
|
const underlyingMint = resolved.underlyingMint ?? params.underlyingMint;
|
|
289
|
+
const collateralMint = params.collateralMint ?? underlyingMint;
|
|
261
290
|
const [makerLongAccount, makerShortAccount] = await Promise.all([
|
|
262
291
|
deriveAssociatedTokenAddress(params.maker, resolved.longMint),
|
|
263
292
|
deriveAssociatedTokenAddress(params.maker, resolved.shortMint),
|
|
264
293
|
]);
|
|
265
294
|
const makerCollateralAccount = params.makerCollateralAccount
|
|
266
295
|
? toAddress(params.makerCollateralAccount)
|
|
267
|
-
: await deriveAssociatedTokenAddress(params.maker,
|
|
296
|
+
: await deriveAssociatedTokenAddress(params.maker, collateralMint);
|
|
268
297
|
|
|
269
298
|
const tx = await buildOptionMintTransaction({
|
|
270
299
|
...params,
|
|
271
300
|
underlyingAsset: params.underlyingAsset,
|
|
272
301
|
underlyingMint,
|
|
302
|
+
collateralMint,
|
|
273
303
|
makerCollateralAccount,
|
|
274
304
|
optionAccount: resolved.optionAccount,
|
|
275
305
|
longMint: resolved.longMint,
|
|
@@ -296,7 +326,7 @@ export async function buildOptionMintTransactionWithDerivation(
|
|
|
296
326
|
await getCreateAssociatedTokenIdempotentInstructionWithAddress(
|
|
297
327
|
params.maker,
|
|
298
328
|
params.maker,
|
|
299
|
-
|
|
329
|
+
collateralMint,
|
|
300
330
|
makerCollateralAccount
|
|
301
331
|
);
|
|
302
332
|
|