@epicentral/sos-sdk 0.6.1-alpha → 0.7.0-alpha

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
@@ -89,6 +89,22 @@ Additional modules:
89
89
 
90
90
  Borrow/repay for writers: use `buildOptionMintTransactionWithDerivation` (with vault/poolLoan) and `buildRepayPoolLoanFromCollateralInstruction` or `buildUnwindWriterUnsoldWithLoanRepayment`.
91
91
 
92
+ ### Transaction size and Address Lookup Tables
93
+
94
+ Option mint (and buy/close) transactions exceed Solana's 1232-byte limit without compression. If you see **"encoding overruns Uint8Array"** when minting, pass `network` to `sendBuiltTransaction`:
95
+
96
+ ```ts
97
+ await sendBuiltTransaction({
98
+ instructions: tx.instructions,
99
+ rpc,
100
+ rpcSubscriptions,
101
+ feePayer: walletSigner,
102
+ network: "devnet", // or "mainnet" — auto-includes lookup table when configured
103
+ });
104
+ ```
105
+
106
+ Or pass `addressLookupTableAddresses: [getLookupTableAddressForNetwork("devnet")]` when non-null. Mainnet lookup table is `null` by default; create one via `yarn update:lookuptable` for mainnet.
107
+
92
108
  ### Token account closing (option mint and close long)
93
109
 
94
110
  - **Option mint (seller/writer):** After `option_mint`, all LONG tokens go to the pool escrow; the maker's LONG ATA is left with zero balance. The SDK **automatically appends an SPL CloseAccount instruction** (when `closeMakerLongAccount` is not set to `false`) so the maker reclaims rent. Use `buildOptionMintTransaction` or `buildOptionMintTransactionWithDerivation`; pass `closeMakerLongAccount: false` to skip closing the LONG ATA.
@@ -120,10 +136,25 @@ Borrow/repay for writers: use `buildOptionMintTransactionWithDerivation` (with v
120
136
  | Function | Description |
121
137
  |----------|-------------|
122
138
  | `resolveSwitchboardFeedFromMarketData` | Resolves Switchboard feed address from market data account. |
123
- | `buildSwitchboardPullFeedUpdate` | Builds Switchboard pull-feed update instructions for prepending to trade transactions. |
139
+ | `buildSwitchboardPullFeedUpdate` | Low-level helper that fetches Switchboard pull-feed update instructions. |
140
+ | `buildSwitchboardCrank` | Returns Kit-native crank instructions plus lookup tables for the configured feed. |
141
+ | `prependSwitchboardCrank` | Prepends crank instructions/ALTs to a built SDK transaction. |
142
+
143
+ Price-sensitive option builders and OMLP deposit/withdraw builders now prepend Switchboard crank instructions by default, so frontends can keep using the same Kit transaction pipeline without managing a separate oracle update step.
124
144
 
125
145
  See [Frontend Switchboard Integration](../../docs/FRONTEND_SWITCHBOARD_INTEGRATION.md) for full setup and usage.
126
146
 
147
+ ### Global Trade Config
148
+
149
+ Use the shared trade config helpers to set SDK-wide defaults for slippage and compute-budget settings:
150
+
151
+ - `setGlobalTradeConfig`
152
+ - `updateGlobalTradeConfig`
153
+ - `getGlobalTradeConfig`
154
+ - `resetGlobalTradeConfig`
155
+
156
+ These defaults are used by the high-level builders unless an action-specific override is provided. `option_mint` also forwards a max-collateral bound on-chain so signer delays cannot silently widen required collateral past the configured tolerance.
157
+
127
158
  ## Multi-Collateral Settlement
128
159
 
129
160
  The SDK supports universal multi-collateral settlement, allowing writers to use ANY supported asset as collateral for options (not just the underlying). This enables:
@@ -199,7 +230,7 @@ When a writer unwinds an unsold short that had borrowed from the OMLP pool, the
199
230
  **Collateral Return:**
200
231
  - Proportional collateral share = `(collateral_deposited * unwind_qty) / written_qty`
201
232
  - Returnable collateral = `proportional_share - amount_already_repaid_from_vault`
202
- - If vault lacks sufficient post-repayment balance, fails with `InsufficientCollateralVault` (6090)
233
+ - If vault lacks sufficient post-repayment balance, fails with `InsufficientCollateralVault` (6092)
203
234
 
204
235
  Use **`buildUnwindWriterUnsoldWithLoanRepayment`** so that:
205
236
 
@@ -216,7 +247,8 @@ Use **`preflightUnwindWriterUnsold`** before building the transaction to get:
216
247
  - Collateral-vault available, wallet fallback required, and shortfall.
217
248
  - **Top-up UX fields:** `collateralVaultShortfall`, `needsWalletTopUp`.
218
249
  - WSOL repay metadata: `solTopUpRequired`, `topUpRequiredForRepay`, `nativeSolAvailable`.
219
- - `canRepayFully`, which now reflects effective repay solvency (including native SOL top-up capacity for WSOL paths).
250
+ - `canRepayRequestedSlice`, which reflects solvency for the proportional unwind slice (including native SOL top-up capacity for WSOL paths).
251
+ - Deprecated compatibility field: `canRepayFully` mirrors the slice-based result for older callers.
220
252
 
221
253
  If there are no active pool loans for that vault, the API still works and passes empty `remaining_accounts`.
222
254
 
@@ -317,7 +349,7 @@ The program uses distinct error codes for liquidity failures:
317
349
  - `InsufficientPoolAggregateLiquidity` (6042) – `option_pool.total_available < quantity`
318
350
  - `InsufficientWriterPositionLiquidity` (6043) – remaining writer-position accounts cannot cover full quantity in the smallest-first fill loop
319
351
 
320
- **Ghost Liquidity:** When `total_available` appears sufficient but active writer positions cannot cover the request. This happens when positions are settled/liquidated but still counted in the aggregate. The SDK now filters inactive positions, and the program skips them in the fill loop.
352
+ `option_pool.total_available` is now treated as writer-backed unsold inventory. `close_long_to_pool` no longer inflates the aggregate counter by re-adding buyer-closed LONGs, which removes the false-liquidity drift behind `InsufficientWriterPositionLiquidity`.
321
353
 
322
354
  **Recommended client flow:**
323
355
  1. Run `preflightBuyFromPoolMarketOrder` for UX gating (checks both pool and active writer liquidity).
@@ -349,7 +381,7 @@ The program uses the **Switchboard pull feed account** you pass in (or that the
349
381
  - **Buy:** Premium computation (Black-Scholes).
350
382
  - **Close:** Payout computation (mark-to-market). If the price is stale, the close payout will not reflect the current option value; the buyer may receive back only their premium instead of profit.
351
383
 
352
- **You must ensure the Switchboard feed is recently updated** when building buy and close transactions. The SDK does not post oracle updates by default; use the Switchboard helper exports and your update pipeline before trading instructions.
384
+ The SDK now prepends Switchboard crank instructions by default for mint, buy, close, unwind, exercise/settle/liquidate, and OMLP deposit/withdraw builders. Keep feeds configured correctly, but frontends no longer need a separate crank transaction in the standard path.
353
385
 
354
386
  - **Mainnet:** keep feed updates fresh enough to satisfy the feed's configured `max_staleness`.
355
387
  - **Devnet:** ensure your keeper/update pipeline runs before user trade flows; payouts reflect the feed's staleness config.
@@ -4,13 +4,15 @@ 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("FTLPczoQpTmND126pMiJpnPudsDxfGuCNUQAPk4SUcJd"),
7
+ devnet: address("CxJn2cyXF8wRr4Cg7GKhSbGS7VW8wAnz3C4uQq537kXr"),
8
8
  mainnet: null,
9
9
  };
10
10
 
11
11
  export const LOOKUP_TABLE_ADDRESS: Address | null = LOOKUP_TABLE_ADDRESSES.devnet;
12
12
 
13
- export function detectNetwork(rpcUrl: string): "devnet" | "mainnet" {
13
+ export type LookupTableNetwork = "devnet" | "mainnet";
14
+
15
+ export function detectNetwork(rpcUrl: string): LookupTableNetwork {
14
16
  const lower = rpcUrl.toLowerCase();
15
17
  return lower.includes("mainnet") ? "mainnet" : "devnet";
16
18
  }
package/client/types.ts CHANGED
@@ -5,4 +5,5 @@ export type KitRpc = Rpc<SolanaRpcApi>;
5
5
 
6
6
  export interface BuiltTransaction {
7
7
  instructions: Instruction<string>[];
8
+ addressLookupTableAddresses?: AddressLike[];
8
9
  }
@@ -111,6 +111,11 @@ export type Vault = {
111
111
  * Set by admin, enforced on deposits. 0 = unlimited.
112
112
  */
113
113
  supplyLimit: bigint;
114
+ /**
115
+ * Maximum aggregate borrow cap as a share of total liquidity (basis points).
116
+ * Example: 9000 = at most 90% of liquidity may be loaned out.
117
+ */
118
+ maxBorrowCapBps: number;
114
119
  /**
115
120
  * Cumulative interest earned per deposited unit (fixed-point)
116
121
  * Increases whenever loans are repaid/liquidated
@@ -177,6 +182,11 @@ export type VaultArgs = {
177
182
  * Set by admin, enforced on deposits. 0 = unlimited.
178
183
  */
179
184
  supplyLimit: number | bigint;
185
+ /**
186
+ * Maximum aggregate borrow cap as a share of total liquidity (basis points).
187
+ * Example: 9000 = at most 90% of liquidity may be loaned out.
188
+ */
189
+ maxBorrowCapBps: number;
180
190
  /**
181
191
  * Cumulative interest earned per deposited unit (fixed-point)
182
192
  * Increases whenever loans are repaid/liquidated
@@ -208,6 +218,7 @@ export function getVaultEncoder(): FixedSizeEncoder<VaultArgs> {
208
218
  ["rateSlope1Bps", getU16Encoder()],
209
219
  ["rateSlope2Bps", getU16Encoder()],
210
220
  ["supplyLimit", getU64Encoder()],
221
+ ["maxBorrowCapBps", getU16Encoder()],
211
222
  ["accInterestPerShareFp", getU128Encoder()],
212
223
  ["lastInterestUpdateSlot", getU64Encoder()],
213
224
  ]),
@@ -236,6 +247,7 @@ export function getVaultDecoder(): FixedSizeDecoder<Vault> {
236
247
  ["rateSlope1Bps", getU16Decoder()],
237
248
  ["rateSlope2Bps", getU16Decoder()],
238
249
  ["supplyLimit", getU64Decoder()],
250
+ ["maxBorrowCapBps", getU16Decoder()],
239
251
  ["accInterestPerShareFp", getU128Decoder()],
240
252
  ["lastInterestUpdateSlot", getU64Decoder()],
241
253
  ]);
@@ -300,5 +312,5 @@ export async function fetchAllMaybeVault(
300
312
  }
301
313
 
302
314
  export function getVaultSize(): number {
303
- return 191;
315
+ return 193;
304
316
  }
@@ -23,6 +23,7 @@ export * from "./initializeMarketData";
23
23
  export * from "./initOptionPool";
24
24
  export * from "./liquidateWriterPosition";
25
25
  export * from "./omlpCreateVault";
26
+ export * from "./omlpUpdateMaxBorrowCap";
26
27
  export * from "./omlpUpdateMaxLeverage";
27
28
  export * from "./omlpUpdateProtocolFee";
28
29
  export * from "./omlpUpdateSupplyLimit";
@@ -107,6 +107,7 @@ export type OmlpCreateVaultInstruction<
107
107
  export type OmlpCreateVaultInstructionData = {
108
108
  discriminator: ReadonlyUint8Array;
109
109
  liqThresholdBps: number;
110
+ maxBorrowCapBps: number;
110
111
  maxLeverageMultiplier: number;
111
112
  baseRateBps: number;
112
113
  optimalUtilizationBps: number;
@@ -117,6 +118,7 @@ export type OmlpCreateVaultInstructionData = {
117
118
 
118
119
  export type OmlpCreateVaultInstructionDataArgs = {
119
120
  liqThresholdBps: number;
121
+ maxBorrowCapBps: number;
120
122
  maxLeverageMultiplier: number;
121
123
  baseRateBps: number;
122
124
  optimalUtilizationBps: number;
@@ -130,6 +132,7 @@ export function getOmlpCreateVaultInstructionDataEncoder(): FixedSizeEncoder<Oml
130
132
  getStructEncoder([
131
133
  ["discriminator", fixEncoderSize(getBytesEncoder(), 8)],
132
134
  ["liqThresholdBps", getU16Encoder()],
135
+ ["maxBorrowCapBps", getU16Encoder()],
133
136
  ["maxLeverageMultiplier", getU16Encoder()],
134
137
  ["baseRateBps", getU16Encoder()],
135
138
  ["optimalUtilizationBps", getU16Encoder()],
@@ -145,6 +148,7 @@ export function getOmlpCreateVaultInstructionDataDecoder(): FixedSizeDecoder<Oml
145
148
  return getStructDecoder([
146
149
  ["discriminator", fixDecoderSize(getBytesDecoder(), 8)],
147
150
  ["liqThresholdBps", getU16Decoder()],
151
+ ["maxBorrowCapBps", getU16Decoder()],
148
152
  ["maxLeverageMultiplier", getU16Decoder()],
149
153
  ["baseRateBps", getU16Decoder()],
150
154
  ["optimalUtilizationBps", getU16Decoder()],
@@ -189,6 +193,7 @@ export type OmlpCreateVaultAsyncInput<
189
193
  associatedTokenProgram?: Address<TAccountAssociatedTokenProgram>;
190
194
  systemProgram?: Address<TAccountSystemProgram>;
191
195
  liqThresholdBps: OmlpCreateVaultInstructionDataArgs["liqThresholdBps"];
196
+ maxBorrowCapBps: OmlpCreateVaultInstructionDataArgs["maxBorrowCapBps"];
192
197
  maxLeverageMultiplier: OmlpCreateVaultInstructionDataArgs["maxLeverageMultiplier"];
193
198
  baseRateBps: OmlpCreateVaultInstructionDataArgs["baseRateBps"];
194
199
  optimalUtilizationBps: OmlpCreateVaultInstructionDataArgs["optimalUtilizationBps"];
@@ -369,6 +374,7 @@ export type OmlpCreateVaultInput<
369
374
  associatedTokenProgram?: Address<TAccountAssociatedTokenProgram>;
370
375
  systemProgram?: Address<TAccountSystemProgram>;
371
376
  liqThresholdBps: OmlpCreateVaultInstructionDataArgs["liqThresholdBps"];
377
+ maxBorrowCapBps: OmlpCreateVaultInstructionDataArgs["maxBorrowCapBps"];
372
378
  maxLeverageMultiplier: OmlpCreateVaultInstructionDataArgs["maxLeverageMultiplier"];
373
379
  baseRateBps: OmlpCreateVaultInstructionDataArgs["baseRateBps"];
374
380
  optimalUtilizationBps: OmlpCreateVaultInstructionDataArgs["optimalUtilizationBps"];
@@ -0,0 +1,304 @@
1
+ /**
2
+ * This code was AUTOGENERATED using the Codama library.
3
+ * Please DO NOT EDIT THIS FILE, instead use visitors
4
+ * to add features, then rerun Codama to update it.
5
+ *
6
+ * @see https://github.com/codama-idl/codama
7
+ */
8
+
9
+ import {
10
+ combineCodec,
11
+ fixDecoderSize,
12
+ fixEncoderSize,
13
+ getBytesDecoder,
14
+ getBytesEncoder,
15
+ getProgramDerivedAddress,
16
+ getStructDecoder,
17
+ getStructEncoder,
18
+ getU16Decoder,
19
+ getU16Encoder,
20
+ transformEncoder,
21
+ type AccountMeta,
22
+ type AccountSignerMeta,
23
+ type Address,
24
+ type FixedSizeCodec,
25
+ type FixedSizeDecoder,
26
+ type FixedSizeEncoder,
27
+ type Instruction,
28
+ type InstructionWithAccounts,
29
+ type InstructionWithData,
30
+ type ReadonlyAccount,
31
+ type ReadonlySignerAccount,
32
+ type ReadonlyUint8Array,
33
+ type TransactionSigner,
34
+ type WritableAccount,
35
+ } from "@solana/kit";
36
+ import { OPTION_PROGRAM_PROGRAM_ADDRESS } from "../programs";
37
+ import { getAccountMetaFactory, type ResolvedAccount } from "../shared";
38
+
39
+ export const OMLP_UPDATE_MAX_BORROW_CAP_DISCRIMINATOR = new Uint8Array([
40
+ 156, 196, 135, 28, 127, 162, 101, 52,
41
+ ]);
42
+
43
+ export function getOmlpUpdateMaxBorrowCapDiscriminatorBytes() {
44
+ return fixEncoderSize(getBytesEncoder(), 8).encode(
45
+ OMLP_UPDATE_MAX_BORROW_CAP_DISCRIMINATOR,
46
+ );
47
+ }
48
+
49
+ export type OmlpUpdateMaxBorrowCapInstruction<
50
+ TProgram extends string = typeof OPTION_PROGRAM_PROGRAM_ADDRESS,
51
+ TAccountConfig extends string | AccountMeta<string> = string,
52
+ TAccountVault extends string | AccountMeta<string> = string,
53
+ TAccountAdmin extends string | AccountMeta<string> = string,
54
+ TRemainingAccounts extends readonly AccountMeta<string>[] = [],
55
+ > = Instruction<TProgram> &
56
+ InstructionWithData<ReadonlyUint8Array> &
57
+ InstructionWithAccounts<
58
+ [
59
+ TAccountConfig extends string
60
+ ? ReadonlyAccount<TAccountConfig>
61
+ : TAccountConfig,
62
+ TAccountVault extends string
63
+ ? WritableAccount<TAccountVault>
64
+ : TAccountVault,
65
+ TAccountAdmin extends string
66
+ ? ReadonlySignerAccount<TAccountAdmin> &
67
+ AccountSignerMeta<TAccountAdmin>
68
+ : TAccountAdmin,
69
+ ...TRemainingAccounts,
70
+ ]
71
+ >;
72
+
73
+ export type OmlpUpdateMaxBorrowCapInstructionData = {
74
+ discriminator: ReadonlyUint8Array;
75
+ newMaxBorrowCapBps: number;
76
+ };
77
+
78
+ export type OmlpUpdateMaxBorrowCapInstructionDataArgs = {
79
+ newMaxBorrowCapBps: number;
80
+ };
81
+
82
+ export function getOmlpUpdateMaxBorrowCapInstructionDataEncoder(): FixedSizeEncoder<OmlpUpdateMaxBorrowCapInstructionDataArgs> {
83
+ return transformEncoder(
84
+ getStructEncoder([
85
+ ["discriminator", fixEncoderSize(getBytesEncoder(), 8)],
86
+ ["newMaxBorrowCapBps", getU16Encoder()],
87
+ ]),
88
+ (value) => ({
89
+ ...value,
90
+ discriminator: OMLP_UPDATE_MAX_BORROW_CAP_DISCRIMINATOR,
91
+ }),
92
+ );
93
+ }
94
+
95
+ export function getOmlpUpdateMaxBorrowCapInstructionDataDecoder(): FixedSizeDecoder<OmlpUpdateMaxBorrowCapInstructionData> {
96
+ return getStructDecoder([
97
+ ["discriminator", fixDecoderSize(getBytesDecoder(), 8)],
98
+ ["newMaxBorrowCapBps", getU16Decoder()],
99
+ ]);
100
+ }
101
+
102
+ export function getOmlpUpdateMaxBorrowCapInstructionDataCodec(): FixedSizeCodec<
103
+ OmlpUpdateMaxBorrowCapInstructionDataArgs,
104
+ OmlpUpdateMaxBorrowCapInstructionData
105
+ > {
106
+ return combineCodec(
107
+ getOmlpUpdateMaxBorrowCapInstructionDataEncoder(),
108
+ getOmlpUpdateMaxBorrowCapInstructionDataDecoder(),
109
+ );
110
+ }
111
+
112
+ export type OmlpUpdateMaxBorrowCapAsyncInput<
113
+ TAccountConfig extends string = string,
114
+ TAccountVault extends string = string,
115
+ TAccountAdmin extends string = string,
116
+ > = {
117
+ /** Protocol config - stores admin authority */
118
+ config?: Address<TAccountConfig>;
119
+ vault: Address<TAccountVault>;
120
+ /** Admin signer - must match config.admin */
121
+ admin: TransactionSigner<TAccountAdmin>;
122
+ newMaxBorrowCapBps: OmlpUpdateMaxBorrowCapInstructionDataArgs["newMaxBorrowCapBps"];
123
+ };
124
+
125
+ export async function getOmlpUpdateMaxBorrowCapInstructionAsync<
126
+ TAccountConfig extends string,
127
+ TAccountVault extends string,
128
+ TAccountAdmin extends string,
129
+ TProgramAddress extends Address = typeof OPTION_PROGRAM_PROGRAM_ADDRESS,
130
+ >(
131
+ input: OmlpUpdateMaxBorrowCapAsyncInput<
132
+ TAccountConfig,
133
+ TAccountVault,
134
+ TAccountAdmin
135
+ >,
136
+ config?: { programAddress?: TProgramAddress },
137
+ ): Promise<
138
+ OmlpUpdateMaxBorrowCapInstruction<
139
+ TProgramAddress,
140
+ TAccountConfig,
141
+ TAccountVault,
142
+ TAccountAdmin
143
+ >
144
+ > {
145
+ // Program address.
146
+ const programAddress =
147
+ config?.programAddress ?? OPTION_PROGRAM_PROGRAM_ADDRESS;
148
+
149
+ // Original accounts.
150
+ const originalAccounts = {
151
+ config: { value: input.config ?? null, isWritable: false },
152
+ vault: { value: input.vault ?? null, isWritable: true },
153
+ admin: { value: input.admin ?? null, isWritable: false },
154
+ };
155
+ const accounts = originalAccounts as Record<
156
+ keyof typeof originalAccounts,
157
+ ResolvedAccount
158
+ >;
159
+
160
+ // Original args.
161
+ const args = { ...input };
162
+
163
+ // Resolve default values.
164
+ if (!accounts.config.value) {
165
+ accounts.config.value = await getProgramDerivedAddress({
166
+ programAddress,
167
+ seeds: [
168
+ getBytesEncoder().encode(new Uint8Array([99, 111, 110, 102, 105, 103])),
169
+ ],
170
+ });
171
+ }
172
+
173
+ const getAccountMeta = getAccountMetaFactory(programAddress, "programId");
174
+ return Object.freeze({
175
+ accounts: [
176
+ getAccountMeta(accounts.config),
177
+ getAccountMeta(accounts.vault),
178
+ getAccountMeta(accounts.admin),
179
+ ],
180
+ data: getOmlpUpdateMaxBorrowCapInstructionDataEncoder().encode(
181
+ args as OmlpUpdateMaxBorrowCapInstructionDataArgs,
182
+ ),
183
+ programAddress,
184
+ } as OmlpUpdateMaxBorrowCapInstruction<
185
+ TProgramAddress,
186
+ TAccountConfig,
187
+ TAccountVault,
188
+ TAccountAdmin
189
+ >);
190
+ }
191
+
192
+ export type OmlpUpdateMaxBorrowCapInput<
193
+ TAccountConfig extends string = string,
194
+ TAccountVault extends string = string,
195
+ TAccountAdmin extends string = string,
196
+ > = {
197
+ /** Protocol config - stores admin authority */
198
+ config: Address<TAccountConfig>;
199
+ vault: Address<TAccountVault>;
200
+ /** Admin signer - must match config.admin */
201
+ admin: TransactionSigner<TAccountAdmin>;
202
+ newMaxBorrowCapBps: OmlpUpdateMaxBorrowCapInstructionDataArgs["newMaxBorrowCapBps"];
203
+ };
204
+
205
+ export function getOmlpUpdateMaxBorrowCapInstruction<
206
+ TAccountConfig extends string,
207
+ TAccountVault extends string,
208
+ TAccountAdmin extends string,
209
+ TProgramAddress extends Address = typeof OPTION_PROGRAM_PROGRAM_ADDRESS,
210
+ >(
211
+ input: OmlpUpdateMaxBorrowCapInput<
212
+ TAccountConfig,
213
+ TAccountVault,
214
+ TAccountAdmin
215
+ >,
216
+ config?: { programAddress?: TProgramAddress },
217
+ ): OmlpUpdateMaxBorrowCapInstruction<
218
+ TProgramAddress,
219
+ TAccountConfig,
220
+ TAccountVault,
221
+ TAccountAdmin
222
+ > {
223
+ // Program address.
224
+ const programAddress =
225
+ config?.programAddress ?? OPTION_PROGRAM_PROGRAM_ADDRESS;
226
+
227
+ // Original accounts.
228
+ const originalAccounts = {
229
+ config: { value: input.config ?? null, isWritable: false },
230
+ vault: { value: input.vault ?? null, isWritable: true },
231
+ admin: { value: input.admin ?? null, isWritable: false },
232
+ };
233
+ const accounts = originalAccounts as Record<
234
+ keyof typeof originalAccounts,
235
+ ResolvedAccount
236
+ >;
237
+
238
+ // Original args.
239
+ const args = { ...input };
240
+
241
+ const getAccountMeta = getAccountMetaFactory(programAddress, "programId");
242
+ return Object.freeze({
243
+ accounts: [
244
+ getAccountMeta(accounts.config),
245
+ getAccountMeta(accounts.vault),
246
+ getAccountMeta(accounts.admin),
247
+ ],
248
+ data: getOmlpUpdateMaxBorrowCapInstructionDataEncoder().encode(
249
+ args as OmlpUpdateMaxBorrowCapInstructionDataArgs,
250
+ ),
251
+ programAddress,
252
+ } as OmlpUpdateMaxBorrowCapInstruction<
253
+ TProgramAddress,
254
+ TAccountConfig,
255
+ TAccountVault,
256
+ TAccountAdmin
257
+ >);
258
+ }
259
+
260
+ export type ParsedOmlpUpdateMaxBorrowCapInstruction<
261
+ TProgram extends string = typeof OPTION_PROGRAM_PROGRAM_ADDRESS,
262
+ TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[],
263
+ > = {
264
+ programAddress: Address<TProgram>;
265
+ accounts: {
266
+ /** Protocol config - stores admin authority */
267
+ config: TAccountMetas[0];
268
+ vault: TAccountMetas[1];
269
+ /** Admin signer - must match config.admin */
270
+ admin: TAccountMetas[2];
271
+ };
272
+ data: OmlpUpdateMaxBorrowCapInstructionData;
273
+ };
274
+
275
+ export function parseOmlpUpdateMaxBorrowCapInstruction<
276
+ TProgram extends string,
277
+ TAccountMetas extends readonly AccountMeta[],
278
+ >(
279
+ instruction: Instruction<TProgram> &
280
+ InstructionWithAccounts<TAccountMetas> &
281
+ InstructionWithData<ReadonlyUint8Array>,
282
+ ): ParsedOmlpUpdateMaxBorrowCapInstruction<TProgram, TAccountMetas> {
283
+ if (instruction.accounts.length < 3) {
284
+ // TODO: Coded error.
285
+ throw new Error("Not enough accounts");
286
+ }
287
+ let accountIndex = 0;
288
+ const getNextAccount = () => {
289
+ const accountMeta = (instruction.accounts as TAccountMetas)[accountIndex]!;
290
+ accountIndex += 1;
291
+ return accountMeta;
292
+ };
293
+ return {
294
+ programAddress: instruction.programAddress,
295
+ accounts: {
296
+ config: getNextAccount(),
297
+ vault: getNextAccount(),
298
+ admin: getNextAccount(),
299
+ },
300
+ data: getOmlpUpdateMaxBorrowCapInstructionDataDecoder().decode(
301
+ instruction.data,
302
+ ),
303
+ };
304
+ }
@@ -219,6 +219,7 @@ export type OptionMintInstructionData = {
219
219
  collateralMint: Address;
220
220
  makerCollateralAmount: bigint;
221
221
  borrowedAmount: bigint;
222
+ maxRequiredCollateralAmount: bigint;
222
223
  };
223
224
 
224
225
  export type OptionMintInstructionDataArgs = {
@@ -231,6 +232,7 @@ export type OptionMintInstructionDataArgs = {
231
232
  collateralMint: Address;
232
233
  makerCollateralAmount: number | bigint;
233
234
  borrowedAmount: number | bigint;
235
+ maxRequiredCollateralAmount: number | bigint;
234
236
  };
235
237
 
236
238
  export function getOptionMintInstructionDataEncoder(): Encoder<OptionMintInstructionDataArgs> {
@@ -249,6 +251,7 @@ export function getOptionMintInstructionDataEncoder(): Encoder<OptionMintInstruc
249
251
  ["collateralMint", getAddressEncoder()],
250
252
  ["makerCollateralAmount", getU64Encoder()],
251
253
  ["borrowedAmount", getU64Encoder()],
254
+ ["maxRequiredCollateralAmount", getU64Encoder()],
252
255
  ]),
253
256
  (value) => ({ ...value, discriminator: OPTION_MINT_DISCRIMINATOR }),
254
257
  );
@@ -269,6 +272,7 @@ export function getOptionMintInstructionDataDecoder(): Decoder<OptionMintInstruc
269
272
  ["collateralMint", getAddressDecoder()],
270
273
  ["makerCollateralAmount", getU64Decoder()],
271
274
  ["borrowedAmount", getU64Decoder()],
275
+ ["maxRequiredCollateralAmount", getU64Decoder()],
272
276
  ]);
273
277
  }
274
278
 
@@ -389,6 +393,7 @@ export type OptionMintAsyncInput<
389
393
  collateralMintArg: OptionMintInstructionDataArgs["collateralMint"];
390
394
  makerCollateralAmount: OptionMintInstructionDataArgs["makerCollateralAmount"];
391
395
  borrowedAmount: OptionMintInstructionDataArgs["borrowedAmount"];
396
+ maxRequiredCollateralAmount: OptionMintInstructionDataArgs["maxRequiredCollateralAmount"];
392
397
  };
393
398
 
394
399
  export async function getOptionMintInstructionAsync<
@@ -973,6 +978,7 @@ export type OptionMintInput<
973
978
  collateralMintArg: OptionMintInstructionDataArgs["collateralMint"];
974
979
  makerCollateralAmount: OptionMintInstructionDataArgs["makerCollateralAmount"];
975
980
  borrowedAmount: OptionMintInstructionDataArgs["borrowedAmount"];
981
+ maxRequiredCollateralAmount: OptionMintInstructionDataArgs["maxRequiredCollateralAmount"];
976
982
  };
977
983
 
978
984
  export function getOptionMintInstruction<
@@ -31,6 +31,7 @@ import {
31
31
  type ParsedInitOptionPoolInstruction,
32
32
  type ParsedLiquidateWriterPositionInstruction,
33
33
  type ParsedOmlpCreateVaultInstruction,
34
+ type ParsedOmlpUpdateMaxBorrowCapInstruction,
34
35
  type ParsedOmlpUpdateMaxLeverageInstruction,
35
36
  type ParsedOmlpUpdateProtocolFeeInstruction,
36
37
  type ParsedOmlpUpdateSupplyLimitInstruction,
@@ -51,7 +52,7 @@ import {
51
52
  } from "../instructions";
52
53
 
53
54
  export const OPTION_PROGRAM_PROGRAM_ADDRESS =
54
- "ASTGCefQVGEQ79ZSC6d2G9oMqmn2dk1onb4N75Bc5djQ" as Address<"ASTGCefQVGEQ79ZSC6d2G9oMqmn2dk1onb4N75Bc5djQ">;
55
+ "CCigZRDDjYiJCRL3FfkG3LbNYBpYaG6mGRiYGQnct1co" as Address<"CCigZRDDjYiJCRL3FfkG3LbNYBpYaG6mGRiYGQnct1co">;
55
56
 
56
57
  export enum OptionProgramAccount {
57
58
  CollateralPool,
@@ -227,6 +228,7 @@ export enum OptionProgramInstruction {
227
228
  InitializeMarketData,
228
229
  LiquidateWriterPosition,
229
230
  OmlpCreateVault,
231
+ OmlpUpdateMaxBorrowCap,
230
232
  OmlpUpdateMaxLeverage,
231
233
  OmlpUpdateProtocolFee,
232
234
  OmlpUpdateSupplyLimit,
@@ -437,6 +439,17 @@ export function identifyOptionProgramInstruction(
437
439
  ) {
438
440
  return OptionProgramInstruction.OmlpCreateVault;
439
441
  }
442
+ if (
443
+ containsBytes(
444
+ data,
445
+ fixEncoderSize(getBytesEncoder(), 8).encode(
446
+ new Uint8Array([156, 196, 135, 28, 127, 162, 101, 52]),
447
+ ),
448
+ 0,
449
+ )
450
+ ) {
451
+ return OptionProgramInstruction.OmlpUpdateMaxBorrowCap;
452
+ }
440
453
  if (
441
454
  containsBytes(
442
455
  data,
@@ -630,7 +643,7 @@ export function identifyOptionProgramInstruction(
630
643
  }
631
644
 
632
645
  export type ParsedOptionProgramInstruction<
633
- TProgram extends string = "ASTGCefQVGEQ79ZSC6d2G9oMqmn2dk1onb4N75Bc5djQ",
646
+ TProgram extends string = "CCigZRDDjYiJCRL3FfkG3LbNYBpYaG6mGRiYGQnct1co",
634
647
  > =
635
648
  | ({
636
649
  instructionType: OptionProgramInstruction.AcceptAdmin;
@@ -683,6 +696,9 @@ export type ParsedOptionProgramInstruction<
683
696
  | ({
684
697
  instructionType: OptionProgramInstruction.OmlpCreateVault;
685
698
  } & ParsedOmlpCreateVaultInstruction<TProgram>)
699
+ | ({
700
+ instructionType: OptionProgramInstruction.OmlpUpdateMaxBorrowCap;
701
+ } & ParsedOmlpUpdateMaxBorrowCapInstruction<TProgram>)
686
702
  | ({
687
703
  instructionType: OptionProgramInstruction.OmlpUpdateMaxLeverage;
688
704
  } & ParsedOmlpUpdateMaxLeverageInstruction<TProgram>)
package/index.ts CHANGED
@@ -30,11 +30,18 @@ export * from "./short/preflight";
30
30
 
31
31
  export * from "./omlp/builders";
32
32
  export * from "./omlp/service";
33
+ export * from "./shared/trade-config";
33
34
  export {
34
35
  resolveSwitchboardFeedFromMarketData,
35
36
  buildSwitchboardPullFeedUpdate,
37
+ buildSwitchboardCrank,
38
+ inferSwitchboardNetwork,
39
+ prependSwitchboardCrank,
36
40
  type SwitchboardPullFeedLike,
37
41
  type BuildSwitchboardPullFeedUpdateParams,
42
+ type BuildSwitchboardCrankParams,
43
+ type SwitchboardCrankResult,
44
+ type SwitchboardNetwork,
38
45
  } from "./oracle/switchboard";
39
46
 
40
47
  export {