@epicentral/sos-sdk 0.12.2-beta → 0.13.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/generated/accounts/marketDataAccount.ts +13 -1
- package/generated/errors/optionProgram.ts +98 -94
- package/generated/instructions/buyFromPool.ts +43 -15
- package/generated/instructions/closeLongToPool.ts +40 -12
- package/generated/instructions/index.ts +1 -0
- package/generated/instructions/initializeMarketData.ts +13 -0
- package/generated/instructions/liquidateWriterPosition.ts +39 -11
- package/generated/instructions/migrateMarketDataVolOracle.ts +248 -0
- package/generated/instructions/optionMint.ts +50 -22
- package/generated/instructions/updateImpliedVolatility.ts +19 -2
- package/generated/programs/optionProgram.ts +16 -0
- package/index.ts +6 -0
- package/long/builders.ts +36 -10
- package/oracle/volatility-quote.ts +65 -0
- package/package.json +7 -1
- package/shared/option-program-parser.ts +6 -0
- package/short/builders.ts +93 -0
package/long/builders.ts
CHANGED
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
inferSwitchboardNetwork,
|
|
37
37
|
prependSwitchboardQuote,
|
|
38
38
|
} from "../oracle/switchboard";
|
|
39
|
+
import { deriveVolatilityQuoteAddressFromMarketData } from "../oracle/volatility-quote";
|
|
39
40
|
import { fetchWriterPositionsForPool } from "../accounts/list";
|
|
40
41
|
import { getGlobalTradeConfig } from "../shared/trade-config";
|
|
41
42
|
|
|
@@ -45,6 +46,8 @@ export interface BuildBuyFromPoolParams {
|
|
|
45
46
|
longMint: AddressLike;
|
|
46
47
|
underlyingMint: AddressLike;
|
|
47
48
|
marketData: AddressLike;
|
|
49
|
+
/** Authority-updated Switchboard HV quote PDA (see deriveVolatilityQuoteAddressFromMarketData). */
|
|
50
|
+
volatilityQuoteAccount: AddressLike;
|
|
48
51
|
/** Program `switchboard_queue` — use {@link getDefaultSwitchboardQueueAddress} for the cluster. */
|
|
49
52
|
switchboardQueue: AddressLike;
|
|
50
53
|
buyer: AddressLike;
|
|
@@ -92,6 +95,8 @@ export interface BuildCloseLongToPoolParams {
|
|
|
92
95
|
escrowLongAccount: AddressLike;
|
|
93
96
|
premiumVault: AddressLike;
|
|
94
97
|
marketData: AddressLike;
|
|
98
|
+
/** Authority-updated Switchboard HV quote PDA (see deriveVolatilityQuoteAddressFromMarketData). */
|
|
99
|
+
volatilityQuoteAccount: AddressLike;
|
|
95
100
|
switchboardQueue: AddressLike;
|
|
96
101
|
buyer: AddressLike;
|
|
97
102
|
buyerLongAccount: AddressLike;
|
|
@@ -131,6 +136,7 @@ export async function buildBuyFromPoolInstruction(
|
|
|
131
136
|
longMint: toAddress(params.longMint),
|
|
132
137
|
underlyingMint: toAddress(params.underlyingMint),
|
|
133
138
|
marketData: toAddress(params.marketData),
|
|
139
|
+
volatilityQuoteAccount: toAddress(params.volatilityQuoteAccount),
|
|
134
140
|
switchboardQueue: toAddress(params.switchboardQueue),
|
|
135
141
|
buyer: toAddress(params.buyer) as any,
|
|
136
142
|
buyerPosition: params.buyerPosition ? toAddress(params.buyerPosition) : undefined,
|
|
@@ -217,6 +223,8 @@ export interface BuildBuyFromPoolTransactionWithDerivationParams {
|
|
|
217
223
|
* Use **1** if only SetComputeUnitLimit is prepended (e.g. `omitComputeUnitPriceInstruction`); **0** if no CU prepend.
|
|
218
224
|
*/
|
|
219
225
|
switchboardQuoteInstructionIndex?: number;
|
|
226
|
+
/** Optional override — derived from on-chain market data when omitted. */
|
|
227
|
+
volatilityQuoteAccount?: AddressLike;
|
|
220
228
|
}
|
|
221
229
|
|
|
222
230
|
const DEFAULT_MARKET_ORDER_SLIPPAGE_BUFFER_BASE_UNITS = 500_000n;
|
|
@@ -303,12 +311,22 @@ export async function buildBuyFromPoolTransactionWithDerivation(
|
|
|
303
311
|
}),
|
|
304
312
|
]);
|
|
305
313
|
|
|
314
|
+
const marketDataAccount = await fetchMarketDataAccount(params.rpc, resolved.marketData);
|
|
315
|
+
invariant(
|
|
316
|
+
!!marketDataAccount,
|
|
317
|
+
"Market data account not found for resolved option market."
|
|
318
|
+
);
|
|
319
|
+
const volatilityQuoteAccount =
|
|
320
|
+
params.volatilityQuoteAccount ??
|
|
321
|
+
deriveVolatilityQuoteAddressFromMarketData(marketDataAccount);
|
|
322
|
+
|
|
306
323
|
const buyParams = {
|
|
307
324
|
optionPool: resolved.optionPool,
|
|
308
325
|
optionAccount: resolved.optionAccount,
|
|
309
326
|
longMint: resolved.longMint,
|
|
310
327
|
underlyingMint: resolved.underlyingMint!,
|
|
311
328
|
marketData: resolved.marketData,
|
|
329
|
+
volatilityQuoteAccount,
|
|
312
330
|
buyer: params.buyer,
|
|
313
331
|
paymentMint: paymentAccounts.paymentMint,
|
|
314
332
|
buyerPaymentAccount: paymentAccounts.buyerPaymentAccount,
|
|
@@ -321,11 +339,6 @@ export async function buildBuyFromPoolTransactionWithDerivation(
|
|
|
321
339
|
remainingAccounts: params.remainingAccounts,
|
|
322
340
|
};
|
|
323
341
|
|
|
324
|
-
const marketDataAccount = await fetchMarketDataAccount(params.rpc, resolved.marketData);
|
|
325
|
-
invariant(
|
|
326
|
-
!!marketDataAccount,
|
|
327
|
-
"Market data account not found for resolved option market."
|
|
328
|
-
);
|
|
329
342
|
const feedIdHex = feedIdBytesToHex(
|
|
330
343
|
Uint8Array.from(marketDataAccount.switchboardFeedId as unknown as Uint8Array)
|
|
331
344
|
);
|
|
@@ -460,12 +473,22 @@ export async function buildBuyFromPoolMarketOrderTransactionWithDerivation(
|
|
|
460
473
|
const maxPremiumAmount = quotePremium + slippageBuffer;
|
|
461
474
|
assertPositiveAmount(maxPremiumAmount, "maxPremiumAmount");
|
|
462
475
|
|
|
476
|
+
const marketDataAccount = await fetchMarketDataAccount(params.rpc, resolved.marketData);
|
|
477
|
+
invariant(
|
|
478
|
+
!!marketDataAccount,
|
|
479
|
+
"Market data account not found for resolved option market."
|
|
480
|
+
);
|
|
481
|
+
const volatilityQuoteAccount =
|
|
482
|
+
params.volatilityQuoteAccount ??
|
|
483
|
+
deriveVolatilityQuoteAddressFromMarketData(marketDataAccount);
|
|
484
|
+
|
|
463
485
|
const marketBuyParams = {
|
|
464
486
|
optionPool: resolved.optionPool,
|
|
465
487
|
optionAccount: resolved.optionAccount,
|
|
466
488
|
longMint: resolved.longMint,
|
|
467
489
|
underlyingMint: refetchedPool.underlyingMint,
|
|
468
490
|
marketData: resolved.marketData,
|
|
491
|
+
volatilityQuoteAccount,
|
|
469
492
|
buyer: params.buyer,
|
|
470
493
|
paymentMint: paymentAccounts.paymentMint,
|
|
471
494
|
buyerPaymentAccount: paymentAccounts.buyerPaymentAccount,
|
|
@@ -478,11 +501,6 @@ export async function buildBuyFromPoolMarketOrderTransactionWithDerivation(
|
|
|
478
501
|
remainingAccounts,
|
|
479
502
|
};
|
|
480
503
|
|
|
481
|
-
const marketDataAccount = await fetchMarketDataAccount(params.rpc, resolved.marketData);
|
|
482
|
-
invariant(
|
|
483
|
-
!!marketDataAccount,
|
|
484
|
-
"Market data account not found for resolved option market."
|
|
485
|
-
);
|
|
486
504
|
const feedIdHex = feedIdBytesToHex(
|
|
487
505
|
Uint8Array.from(marketDataAccount.switchboardFeedId as unknown as Uint8Array)
|
|
488
506
|
);
|
|
@@ -541,6 +559,7 @@ export async function buildCloseLongToPoolInstruction(
|
|
|
541
559
|
escrowLongAccount: toAddress(params.escrowLongAccount),
|
|
542
560
|
premiumVault: toAddress(params.premiumVault),
|
|
543
561
|
marketData: toAddress(params.marketData),
|
|
562
|
+
volatilityQuoteAccount: toAddress(params.volatilityQuoteAccount),
|
|
544
563
|
switchboardQueue: toAddress(params.switchboardQueue),
|
|
545
564
|
buyer: toAddress(params.buyer) as any,
|
|
546
565
|
buyerLongAccount: toAddress(params.buyerLongAccount),
|
|
@@ -652,6 +671,8 @@ export interface BuildCloseLongToPoolTransactionWithDerivationParams {
|
|
|
652
671
|
* OPX `sendInstructions` prepends only `SetComputeUnitLimit` before program ixs → default **1** (quote after CU limit).
|
|
653
672
|
*/
|
|
654
673
|
switchboardQuoteInstructionIndex?: number;
|
|
674
|
+
/** Optional override — derived from on-chain market data when omitted. */
|
|
675
|
+
volatilityQuoteAccount?: AddressLike;
|
|
655
676
|
}
|
|
656
677
|
|
|
657
678
|
export async function buildCloseLongToPoolTransactionWithDerivation(
|
|
@@ -719,6 +740,9 @@ export async function buildCloseLongToPoolTransactionWithDerivation(
|
|
|
719
740
|
!!marketDataAccount,
|
|
720
741
|
"Market data account not found for resolved option market."
|
|
721
742
|
);
|
|
743
|
+
const volatilityQuoteAccount =
|
|
744
|
+
params.volatilityQuoteAccount ??
|
|
745
|
+
deriveVolatilityQuoteAddressFromMarketData(marketDataAccount);
|
|
722
746
|
const feedIdHex = feedIdBytesToHex(
|
|
723
747
|
Uint8Array.from(marketDataAccount.switchboardFeedId as unknown as Uint8Array)
|
|
724
748
|
);
|
|
@@ -738,6 +762,7 @@ export async function buildCloseLongToPoolTransactionWithDerivation(
|
|
|
738
762
|
escrowLongAccount: resolved.escrowLongAccount!,
|
|
739
763
|
premiumVault: resolved.premiumVault!,
|
|
740
764
|
marketData: resolved.marketData,
|
|
765
|
+
volatilityQuoteAccount,
|
|
741
766
|
switchboardQueue,
|
|
742
767
|
buyer: params.buyer,
|
|
743
768
|
buyerLongAccount: params.buyerLongAccount,
|
|
@@ -778,6 +803,7 @@ export async function buildCloseLongToPoolTransactionWithDerivation(
|
|
|
778
803
|
escrowLongAccount: resolved.escrowLongAccount!,
|
|
779
804
|
premiumVault: resolved.premiumVault!,
|
|
780
805
|
marketData: resolved.marketData,
|
|
806
|
+
volatilityQuoteAccount,
|
|
781
807
|
switchboardQueue: getDefaultSwitchboardQueueAddress(network),
|
|
782
808
|
buyer: params.buyer,
|
|
783
809
|
buyerLongAccount: params.buyerLongAccount,
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import { address, type Address } from "@solana/kit";
|
|
3
|
+
import { toAddress } from "../client/program";
|
|
4
|
+
import type { AddressLike } from "../client/types";
|
|
5
|
+
import type { MarketDataAccount } from "../generated/accounts/marketDataAccount";
|
|
6
|
+
|
|
7
|
+
const ZERO_PUBKEY = "11111111111111111111111111111111";
|
|
8
|
+
const QUOTE_PROGRAM_ID = new PublicKey("orac1eFjzWL5R3RbbdMV68K9H6TaCVVcL6LjvQQWAbz");
|
|
9
|
+
const AUTHORITY_QUOTE_SCHEME_TAG = Buffer.from("AUTH");
|
|
10
|
+
|
|
11
|
+
function feedIdBytes(feedId: MarketDataAccount["switchboardVolatilityFeedId"]): Uint8Array {
|
|
12
|
+
return Uint8Array.from(feedId);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function feedIdIsZero(feedId: MarketDataAccount["switchboardVolatilityFeedId"]): boolean {
|
|
16
|
+
const bytes = feedIdBytes(feedId);
|
|
17
|
+
return bytes.length === 32 && bytes.every((b) => b === 0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function isVolOracleEnabled(
|
|
21
|
+
marketData: Pick<
|
|
22
|
+
MarketDataAccount,
|
|
23
|
+
"switchboardVolatilityFeedId" | "volatilityQuoteAuthority"
|
|
24
|
+
>
|
|
25
|
+
): boolean {
|
|
26
|
+
return (
|
|
27
|
+
!feedIdIsZero(marketData.switchboardVolatilityFeedId) &&
|
|
28
|
+
String(marketData.volatilityQuoteAuthority) !== ZERO_PUBKEY
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Derives the Switchboard authority quote PDA for an HV feed.
|
|
34
|
+
*/
|
|
35
|
+
export function deriveVolatilityQuoteAddress(
|
|
36
|
+
authority: AddressLike,
|
|
37
|
+
switchboardVolatilityFeedId: MarketDataAccount["switchboardVolatilityFeedId"]
|
|
38
|
+
): Address {
|
|
39
|
+
const authorityPk = new PublicKey(String(toAddress(authority)));
|
|
40
|
+
const feedHash = Buffer.from(feedIdBytes(switchboardVolatilityFeedId));
|
|
41
|
+
const [quoteAccount] = PublicKey.findProgramAddressSync(
|
|
42
|
+
[AUTHORITY_QUOTE_SCHEME_TAG, authorityPk.toBuffer(), feedHash],
|
|
43
|
+
QUOTE_PROGRAM_ID
|
|
44
|
+
);
|
|
45
|
+
return address(quoteAccount.toBase58());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* When vol oracle is disabled on market data, returns the system program as a
|
|
50
|
+
* read-only placeholder (the program skips quote reads in that case).
|
|
51
|
+
*/
|
|
52
|
+
export function deriveVolatilityQuoteAddressFromMarketData(
|
|
53
|
+
marketData: Pick<
|
|
54
|
+
MarketDataAccount,
|
|
55
|
+
"volatilityQuoteAuthority" | "switchboardVolatilityFeedId"
|
|
56
|
+
>
|
|
57
|
+
): Address {
|
|
58
|
+
if (!isVolOracleEnabled(marketData)) {
|
|
59
|
+
return address(ZERO_PUBKEY);
|
|
60
|
+
}
|
|
61
|
+
return deriveVolatilityQuoteAddress(
|
|
62
|
+
marketData.volatilityQuoteAuthority,
|
|
63
|
+
marketData.switchboardVolatilityFeedId
|
|
64
|
+
);
|
|
65
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epicentral/sos-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.1-beta",
|
|
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",
|
|
@@ -20,11 +20,17 @@
|
|
|
20
20
|
"@solana-program/system": "^0.11.0",
|
|
21
21
|
"@solana/compat": "^6.1.0",
|
|
22
22
|
"@solana/kit": "^6.1.0",
|
|
23
|
+
"@solana/web3.js": "^1.98.0",
|
|
23
24
|
"@switchboard-xyz/common": "^5.7.0",
|
|
24
25
|
"@switchboard-xyz/on-demand": "^3.9.0",
|
|
25
26
|
"bs58": "^6.0.0",
|
|
26
27
|
"decimal.js": "^10.4.3"
|
|
27
28
|
},
|
|
29
|
+
"overrides": {
|
|
30
|
+
"@switchboard-xyz/on-demand": {
|
|
31
|
+
"@switchboard-xyz/common": "$@switchboard-xyz/common"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
28
34
|
"scripts": {
|
|
29
35
|
"typecheck": "tsc --project tsconfig.json --noEmit",
|
|
30
36
|
"publish-beta": "dotenv -e .env -- pnpm publish --access public --tag beta",
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
parseLiquidateWriterPositionInstruction,
|
|
27
27
|
parseLiquidateWriterPositionRescueInstruction,
|
|
28
28
|
parseMigrateCollateralPoolV1ToV2Instruction,
|
|
29
|
+
parseMigrateMarketDataVolOracleInstruction,
|
|
29
30
|
parseOmlpCreateVaultInstruction,
|
|
30
31
|
parseOmlpUpdateFeeWalletInstruction,
|
|
31
32
|
parseOmlpUpdateInterestModelInstruction,
|
|
@@ -179,6 +180,11 @@ export function parseOptionProgramInstruction<
|
|
|
179
180
|
parseLiquidateWriterPositionRescueInstruction(instruction),
|
|
180
181
|
instructionType,
|
|
181
182
|
);
|
|
183
|
+
case OptionProgramInstruction.MigrateMarketDataVolOracle:
|
|
184
|
+
return withInstructionType(
|
|
185
|
+
parseMigrateMarketDataVolOracleInstruction(instruction),
|
|
186
|
+
instructionType,
|
|
187
|
+
);
|
|
182
188
|
case OptionProgramInstruction.MigrateCollateralPoolV1ToV2:
|
|
183
189
|
return withInstructionType(
|
|
184
190
|
parseMigrateCollateralPoolV1ToV2Instruction(instruction),
|
package/short/builders.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getClaimBuyerSettlementInstructionAsync,
|
|
3
3
|
getClaimMakerSettlementInstructionAsync,
|
|
4
|
+
getLiquidateWriterPositionInstructionAsync,
|
|
4
5
|
getLiquidateWriterPositionRescueInstructionAsync,
|
|
5
6
|
getOptionMintInstructionAsync,
|
|
6
7
|
getPrepareBuyerSettlementInstructionAsync,
|
|
@@ -42,6 +43,7 @@ import {
|
|
|
42
43
|
SLOT_HASHES_SYSVAR_ADDRESS,
|
|
43
44
|
SWITCHBOARD_DEFAULT_DEVNET_QUEUE,
|
|
44
45
|
} from "../oracle/switchboard";
|
|
46
|
+
import { deriveVolatilityQuoteAddressFromMarketData } from "../oracle/volatility-quote";
|
|
45
47
|
import { applySlippageBps } from "../long/quotes";
|
|
46
48
|
import { getGlobalTradeConfig } from "../shared/trade-config";
|
|
47
49
|
|
|
@@ -75,6 +77,8 @@ export interface BuildOptionMintParams {
|
|
|
75
77
|
makerLongAccount?: AddressLike;
|
|
76
78
|
makerShortAccount?: AddressLike;
|
|
77
79
|
marketData?: AddressLike;
|
|
80
|
+
/** Authority-updated Switchboard HV quote PDA (derived from market data when omitted). */
|
|
81
|
+
volatilityQuoteAccount?: AddressLike;
|
|
78
82
|
optionPool?: AddressLike;
|
|
79
83
|
escrowLongAccount?: AddressLike;
|
|
80
84
|
premiumVault?: AddressLike;
|
|
@@ -240,6 +244,10 @@ export async function buildOptionMintInstruction(
|
|
|
240
244
|
!!longMetadata && !!shortMetadata,
|
|
241
245
|
"longMetadataAccount and shortMetadataAccount are required (or provide longMint/shortMint to derive)."
|
|
242
246
|
);
|
|
247
|
+
invariant(
|
|
248
|
+
!!params.volatilityQuoteAccount,
|
|
249
|
+
"volatilityQuoteAccount is required (use buildOptionMintTransactionWithDerivation or deriveVolatilityQuoteAddressFromMarketData)."
|
|
250
|
+
);
|
|
243
251
|
|
|
244
252
|
const kitInstruction = await getOptionMintInstructionAsync(
|
|
245
253
|
{
|
|
@@ -256,6 +264,7 @@ export async function buildOptionMintInstruction(
|
|
|
256
264
|
longMetadataAccount: toAddress(longMetadata!),
|
|
257
265
|
shortMetadataAccount: toAddress(shortMetadata!),
|
|
258
266
|
marketData: params.marketData ? toAddress(params.marketData) : undefined,
|
|
267
|
+
volatilityQuoteAccount: toAddress(params.volatilityQuoteAccount!),
|
|
259
268
|
underlyingMint: toAddress(params.underlyingMint),
|
|
260
269
|
collateralMint: toAddress(params.collateralMint ?? params.underlyingMint),
|
|
261
270
|
optionPool: params.optionPool ? toAddress(params.optionPool) : undefined,
|
|
@@ -383,6 +392,8 @@ export interface BuildOptionMintTransactionWithDerivationParams {
|
|
|
383
392
|
* under Solana's 1232-byte versioned-transaction limit when OMLP accounts are present.
|
|
384
393
|
*/
|
|
385
394
|
skipCreateCollateralAta?: boolean;
|
|
395
|
+
/** Optional override — derived from on-chain market data when omitted. */
|
|
396
|
+
volatilityQuoteAccount?: AddressLike;
|
|
386
397
|
}
|
|
387
398
|
|
|
388
399
|
export async function buildOptionMintTransactionWithDerivation(
|
|
@@ -447,6 +458,9 @@ export async function buildOptionMintTransactionWithDerivation(
|
|
|
447
458
|
!!marketDataAccount,
|
|
448
459
|
"Market data account not found for resolved option market."
|
|
449
460
|
);
|
|
461
|
+
const volatilityQuoteAccount =
|
|
462
|
+
params.volatilityQuoteAccount ??
|
|
463
|
+
deriveVolatilityQuoteAddressFromMarketData(marketDataAccount);
|
|
450
464
|
const switchboardFeedId = feedIdBytesToHex(
|
|
451
465
|
Uint8Array.from(marketDataAccount.switchboardFeedId as unknown as Uint8Array)
|
|
452
466
|
);
|
|
@@ -514,6 +528,7 @@ export async function buildOptionMintTransactionWithDerivation(
|
|
|
514
528
|
makerLongAccount,
|
|
515
529
|
makerShortAccount,
|
|
516
530
|
marketData: resolved.marketData,
|
|
531
|
+
volatilityQuoteAccount,
|
|
517
532
|
optionPool: resolved.optionPool,
|
|
518
533
|
escrowLongAccount: resolved.escrowLongAccount,
|
|
519
534
|
premiumVault: resolved.premiumVault,
|
|
@@ -957,6 +972,84 @@ export async function buildClaimMakerSettlementInstruction(
|
|
|
957
972
|
});
|
|
958
973
|
}
|
|
959
974
|
|
|
975
|
+
export interface BuildLiquidateWriterPositionParams {
|
|
976
|
+
optionPool: AddressLike;
|
|
977
|
+
optionAccount: AddressLike;
|
|
978
|
+
/** Market data PDA (`["market_data", underlying_asset]`). */
|
|
979
|
+
marketData: AddressLike;
|
|
980
|
+
/** Authority-updated Switchboard HV quote PDA (derived from market data when omitted). */
|
|
981
|
+
volatilityQuoteAccount?: AddressLike;
|
|
982
|
+
collateralPool: AddressLike;
|
|
983
|
+
writerPosition: AddressLike;
|
|
984
|
+
longMint: AddressLike;
|
|
985
|
+
escrowLongAccount: AddressLike;
|
|
986
|
+
underlyingMint: AddressLike;
|
|
987
|
+
switchboardQueue: AddressLike;
|
|
988
|
+
/** OMLP Vault state PDA (mut: decrements total_loans, etc.). */
|
|
989
|
+
omlpVault: AddressLike;
|
|
990
|
+
collateralVault: AddressLike;
|
|
991
|
+
premiumVault: AddressLike;
|
|
992
|
+
omlpVaultTokenAccount: AddressLike;
|
|
993
|
+
feeWallet: AddressLike;
|
|
994
|
+
/** Permissionless liquidator signer. */
|
|
995
|
+
liquidator: TransactionSigner<string>;
|
|
996
|
+
/** Every active PoolLoan for this writer/vault (SDK: loadWriterLoans). */
|
|
997
|
+
remainingAccounts?: RemainingAccountInput[];
|
|
998
|
+
rpc?: KitRpc;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
export async function buildLiquidateWriterPositionInstruction(
|
|
1002
|
+
params: BuildLiquidateWriterPositionParams
|
|
1003
|
+
): Promise<Instruction<string>> {
|
|
1004
|
+
let volatilityQuoteAccount = params.volatilityQuoteAccount;
|
|
1005
|
+
if (!volatilityQuoteAccount) {
|
|
1006
|
+
invariant(!!params.rpc, "rpc is required when volatilityQuoteAccount is omitted");
|
|
1007
|
+
const marketDataAccount = await fetchMarketDataAccount(params.rpc!, params.marketData);
|
|
1008
|
+
invariant(
|
|
1009
|
+
!!marketDataAccount,
|
|
1010
|
+
"Market data account not found for resolved option market."
|
|
1011
|
+
);
|
|
1012
|
+
volatilityQuoteAccount = deriveVolatilityQuoteAddressFromMarketData(marketDataAccount);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
const kitInstruction = await getLiquidateWriterPositionInstructionAsync({
|
|
1016
|
+
optionPool: toAddress(params.optionPool),
|
|
1017
|
+
optionAccount: toAddress(params.optionAccount),
|
|
1018
|
+
marketData: toAddress(params.marketData),
|
|
1019
|
+
volatilityQuoteAccount: toAddress(volatilityQuoteAccount),
|
|
1020
|
+
collateralPool: toAddress(params.collateralPool),
|
|
1021
|
+
writerPosition: toAddress(params.writerPosition),
|
|
1022
|
+
longMint: toAddress(params.longMint),
|
|
1023
|
+
escrowLongAccount: toAddress(params.escrowLongAccount),
|
|
1024
|
+
underlyingMint: toAddress(params.underlyingMint),
|
|
1025
|
+
switchboardQueue: toAddress(params.switchboardQueue),
|
|
1026
|
+
omlpVault: toAddress(params.omlpVault),
|
|
1027
|
+
collateralVault: toAddress(params.collateralVault),
|
|
1028
|
+
premiumVault: toAddress(params.premiumVault),
|
|
1029
|
+
omlpVaultTokenAccount: toAddress(params.omlpVaultTokenAccount),
|
|
1030
|
+
feeWallet: toAddress(params.feeWallet),
|
|
1031
|
+
liquidator: params.liquidator as any,
|
|
1032
|
+
});
|
|
1033
|
+
return appendRemainingAccounts(kitInstruction, [
|
|
1034
|
+
{
|
|
1035
|
+
address: SLOT_HASHES_SYSVAR_ADDRESS,
|
|
1036
|
+
isWritable: false,
|
|
1037
|
+
},
|
|
1038
|
+
{
|
|
1039
|
+
address: INSTRUCTIONS_SYSVAR_ADDRESS,
|
|
1040
|
+
isWritable: false,
|
|
1041
|
+
},
|
|
1042
|
+
...(params.remainingAccounts ?? []),
|
|
1043
|
+
]);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
export async function buildLiquidateWriterPositionTransaction(
|
|
1047
|
+
params: BuildLiquidateWriterPositionParams
|
|
1048
|
+
): Promise<BuiltTransaction> {
|
|
1049
|
+
const instruction = await buildLiquidateWriterPositionInstruction(params);
|
|
1050
|
+
return { instructions: [instruction] };
|
|
1051
|
+
}
|
|
1052
|
+
|
|
960
1053
|
/**
|
|
961
1054
|
* Parameters for the permissioned rescue liquidation path. Gated on-chain
|
|
962
1055
|
* to `Vault::keeper`; the SDK does not re-verify keeper identity, but the
|