@epicentral/sos-sdk 0.1.1 → 0.2.0
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/accounts/resolve-option.ts +104 -0
- package/index.ts +1 -0
- package/long/builders.ts +143 -1
- package/package.json +3 -1
- package/shared/transactions.ts +47 -3
- package/short/builders.ts +158 -2
- package/tsconfig.json +2 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { Address } from "@solana/kit";
|
|
2
|
+
import { OptionType } from "../generated/types";
|
|
3
|
+
import { toAddress } from "../client/program";
|
|
4
|
+
import type { AddressLike, KitRpc } from "../client/types";
|
|
5
|
+
import {
|
|
6
|
+
deriveCollateralPoolPda,
|
|
7
|
+
deriveLongMintPda,
|
|
8
|
+
deriveMarketDataPda,
|
|
9
|
+
deriveMintAuthorityPda,
|
|
10
|
+
deriveOptionAccountPda,
|
|
11
|
+
deriveOptionPoolPda,
|
|
12
|
+
deriveShortMintPda,
|
|
13
|
+
} from "./pdas";
|
|
14
|
+
import { fetchCollateralPool, fetchOptionAccount, fetchOptionPool } from "./fetchers";
|
|
15
|
+
|
|
16
|
+
export interface ResolveOptionAccountsParams {
|
|
17
|
+
underlyingAsset: AddressLike;
|
|
18
|
+
optionType: OptionType;
|
|
19
|
+
strikePrice: number;
|
|
20
|
+
expirationDate: bigint | number;
|
|
21
|
+
programId?: AddressLike;
|
|
22
|
+
rpc?: KitRpc;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ResolvedOptionAccounts {
|
|
26
|
+
optionAccount: Address;
|
|
27
|
+
longMint: Address;
|
|
28
|
+
shortMint: Address;
|
|
29
|
+
optionPool: Address;
|
|
30
|
+
marketData: Address;
|
|
31
|
+
collateralPool: Address;
|
|
32
|
+
mintAuthority: Address;
|
|
33
|
+
underlyingMint?: Address;
|
|
34
|
+
escrowLongAccount?: Address;
|
|
35
|
+
premiumVault?: Address;
|
|
36
|
+
collateralVault?: Address;
|
|
37
|
+
optionPoolData?: Awaited<ReturnType<typeof fetchOptionPool>>;
|
|
38
|
+
optionAccountData?: Awaited<ReturnType<typeof fetchOptionAccount>>;
|
|
39
|
+
collateralPoolData?: Awaited<ReturnType<typeof fetchCollateralPool>>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Resolves all derived and optionally fetched accounts for an option.
|
|
44
|
+
* Given option identity (underlyingAsset, optionType, strikePrice, expirationDate),
|
|
45
|
+
* returns PDAs and, when rpc is provided, fetches OptionPool and CollateralPool
|
|
46
|
+
* to expose escrowLongAccount, premiumVault, collateralVault, underlyingMint.
|
|
47
|
+
*/
|
|
48
|
+
export async function resolveOptionAccounts(
|
|
49
|
+
params: ResolveOptionAccountsParams
|
|
50
|
+
): Promise<ResolvedOptionAccounts> {
|
|
51
|
+
const programId = params.programId;
|
|
52
|
+
|
|
53
|
+
const [optionAccount] = await deriveOptionAccountPda({
|
|
54
|
+
underlyingAsset: params.underlyingAsset,
|
|
55
|
+
optionType: params.optionType,
|
|
56
|
+
strikePrice: params.strikePrice,
|
|
57
|
+
expirationDate: params.expirationDate,
|
|
58
|
+
programId,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const [longMint] = await deriveLongMintPda(optionAccount, programId);
|
|
62
|
+
const [shortMint] = await deriveShortMintPda(optionAccount, programId);
|
|
63
|
+
const [optionPool] = await deriveOptionPoolPda(optionAccount, programId);
|
|
64
|
+
const [marketData] = await deriveMarketDataPda(params.underlyingAsset, programId);
|
|
65
|
+
const [collateralPool] = await deriveCollateralPoolPda(optionAccount, programId);
|
|
66
|
+
const [mintAuthority] = await deriveMintAuthorityPda(programId);
|
|
67
|
+
|
|
68
|
+
const result: ResolvedOptionAccounts = {
|
|
69
|
+
optionAccount,
|
|
70
|
+
longMint,
|
|
71
|
+
shortMint,
|
|
72
|
+
optionPool,
|
|
73
|
+
marketData,
|
|
74
|
+
collateralPool,
|
|
75
|
+
mintAuthority,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
if (params.rpc) {
|
|
79
|
+
const [optionPoolFetched, optionAccountFetched, collateralPoolFetched] =
|
|
80
|
+
await Promise.all([
|
|
81
|
+
fetchOptionPool(params.rpc, optionPool),
|
|
82
|
+
fetchOptionAccount(params.rpc, optionAccount),
|
|
83
|
+
fetchCollateralPool(params.rpc, collateralPool),
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
if (optionPoolFetched) {
|
|
87
|
+
result.optionPoolData = optionPoolFetched;
|
|
88
|
+
result.escrowLongAccount = optionPoolFetched.escrowLongAccount;
|
|
89
|
+
result.premiumVault = optionPoolFetched.premiumVault;
|
|
90
|
+
result.underlyingMint = optionPoolFetched.underlyingMint;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (optionAccountFetched) {
|
|
94
|
+
result.optionAccountData = optionAccountFetched;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (collateralPoolFetched) {
|
|
98
|
+
result.collateralPoolData = collateralPoolFetched;
|
|
99
|
+
result.collateralVault = collateralPoolFetched.collateralVault;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return result;
|
|
104
|
+
}
|
package/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { OptionType } from "./generated/types";
|
|
|
6
6
|
export * from "./accounts/pdas";
|
|
7
7
|
export * from "./accounts/fetchers";
|
|
8
8
|
export * from "./accounts/list";
|
|
9
|
+
export * from "./accounts/resolve-option";
|
|
9
10
|
|
|
10
11
|
export * from "./shared/amounts";
|
|
11
12
|
export * from "./shared/errors";
|
package/long/builders.ts
CHANGED
|
@@ -4,13 +4,19 @@ import {
|
|
|
4
4
|
} from "../generated/instructions";
|
|
5
5
|
import type { Instruction } from "@solana/kit";
|
|
6
6
|
import { toAddress } from "../client/program";
|
|
7
|
-
import type { AddressLike, BuiltTransaction } from "../client/types";
|
|
7
|
+
import type { AddressLike, BuiltTransaction, KitRpc } from "../client/types";
|
|
8
|
+
import { resolveOptionAccounts } from "../accounts/resolve-option";
|
|
9
|
+
import {
|
|
10
|
+
deriveAssociatedTokenAddress,
|
|
11
|
+
deriveBuyerPositionPda,
|
|
12
|
+
} from "../accounts/pdas";
|
|
8
13
|
import { assertPositiveAmount } from "../shared/amounts";
|
|
9
14
|
import { invariant } from "../shared/errors";
|
|
10
15
|
import {
|
|
11
16
|
appendRemainingAccounts,
|
|
12
17
|
type RemainingAccountInput,
|
|
13
18
|
} from "../shared/remaining-accounts";
|
|
19
|
+
import type { OptionType } from "../generated/types";
|
|
14
20
|
|
|
15
21
|
export interface BuildBuyFromPoolParams {
|
|
16
22
|
optionPool: AddressLike;
|
|
@@ -86,6 +92,74 @@ export async function buildBuyFromPoolTransaction(
|
|
|
86
92
|
return { instructions: [instruction] };
|
|
87
93
|
}
|
|
88
94
|
|
|
95
|
+
export interface BuildBuyFromPoolTransactionWithDerivationParams {
|
|
96
|
+
underlyingAsset: AddressLike;
|
|
97
|
+
optionType: OptionType;
|
|
98
|
+
strikePrice: number;
|
|
99
|
+
expirationDate: bigint | number;
|
|
100
|
+
buyer: AddressLike;
|
|
101
|
+
buyerPaymentAccount: AddressLike;
|
|
102
|
+
priceUpdate: AddressLike;
|
|
103
|
+
quantity: bigint | number;
|
|
104
|
+
premiumAmount: bigint | number;
|
|
105
|
+
rpc: KitRpc;
|
|
106
|
+
programId?: AddressLike;
|
|
107
|
+
buyerPosition?: AddressLike;
|
|
108
|
+
buyerOptionAccount?: AddressLike;
|
|
109
|
+
remainingAccounts?: RemainingAccountInput[];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function buildBuyFromPoolTransactionWithDerivation(
|
|
113
|
+
params: BuildBuyFromPoolTransactionWithDerivationParams
|
|
114
|
+
): Promise<BuiltTransaction> {
|
|
115
|
+
const resolved = await resolveOptionAccounts({
|
|
116
|
+
underlyingAsset: params.underlyingAsset,
|
|
117
|
+
optionType: params.optionType,
|
|
118
|
+
strikePrice: params.strikePrice,
|
|
119
|
+
expirationDate: params.expirationDate,
|
|
120
|
+
programId: params.programId,
|
|
121
|
+
rpc: params.rpc,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
invariant(
|
|
125
|
+
!!resolved.escrowLongAccount &&
|
|
126
|
+
!!resolved.premiumVault &&
|
|
127
|
+
!!resolved.underlyingMint,
|
|
128
|
+
"Option pool must exist; ensure rpc is provided and pool is initialized."
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const [buyerPosition, buyerOptionAccount] = await Promise.all([
|
|
132
|
+
params.buyerPosition
|
|
133
|
+
? Promise.resolve(params.buyerPosition)
|
|
134
|
+
: deriveBuyerPositionPda(
|
|
135
|
+
params.buyer,
|
|
136
|
+
resolved.optionAccount,
|
|
137
|
+
params.programId
|
|
138
|
+
).then(([addr]) => addr),
|
|
139
|
+
params.buyerOptionAccount
|
|
140
|
+
? Promise.resolve(params.buyerOptionAccount)
|
|
141
|
+
: deriveAssociatedTokenAddress(params.buyer, resolved.longMint),
|
|
142
|
+
]);
|
|
143
|
+
|
|
144
|
+
return buildBuyFromPoolTransaction({
|
|
145
|
+
optionPool: resolved.optionPool,
|
|
146
|
+
optionAccount: resolved.optionAccount,
|
|
147
|
+
longMint: resolved.longMint,
|
|
148
|
+
underlyingMint: resolved.underlyingMint!,
|
|
149
|
+
marketData: resolved.marketData,
|
|
150
|
+
priceUpdate: params.priceUpdate,
|
|
151
|
+
buyer: params.buyer,
|
|
152
|
+
buyerPaymentAccount: params.buyerPaymentAccount,
|
|
153
|
+
escrowLongAccount: resolved.escrowLongAccount!,
|
|
154
|
+
premiumVault: resolved.premiumVault!,
|
|
155
|
+
quantity: params.quantity,
|
|
156
|
+
premiumAmount: params.premiumAmount,
|
|
157
|
+
buyerPosition,
|
|
158
|
+
buyerOptionAccount,
|
|
159
|
+
remainingAccounts: params.remainingAccounts,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
89
163
|
export async function buildCloseLongToPoolInstruction(
|
|
90
164
|
params: BuildCloseLongToPoolParams
|
|
91
165
|
): Promise<Instruction<string>> {
|
|
@@ -124,3 +198,71 @@ export async function buildCloseLongToPoolTransaction(
|
|
|
124
198
|
const instruction = await buildCloseLongToPoolInstruction(params);
|
|
125
199
|
return { instructions: [instruction] };
|
|
126
200
|
}
|
|
201
|
+
|
|
202
|
+
export interface BuildCloseLongToPoolTransactionWithDerivationParams {
|
|
203
|
+
underlyingAsset: AddressLike;
|
|
204
|
+
optionType: OptionType;
|
|
205
|
+
strikePrice: number;
|
|
206
|
+
expirationDate: bigint | number;
|
|
207
|
+
buyer: AddressLike;
|
|
208
|
+
buyerLongAccount: AddressLike;
|
|
209
|
+
buyerPayoutAccount: AddressLike;
|
|
210
|
+
priceUpdate: AddressLike;
|
|
211
|
+
quantity: bigint | number;
|
|
212
|
+
minPayoutAmount: bigint | number;
|
|
213
|
+
rpc: KitRpc;
|
|
214
|
+
programId?: AddressLike;
|
|
215
|
+
buyerPosition?: AddressLike;
|
|
216
|
+
omlpVault?: AddressLike;
|
|
217
|
+
remainingAccounts?: RemainingAccountInput[];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export async function buildCloseLongToPoolTransactionWithDerivation(
|
|
221
|
+
params: BuildCloseLongToPoolTransactionWithDerivationParams
|
|
222
|
+
): Promise<BuiltTransaction> {
|
|
223
|
+
const resolved = await resolveOptionAccounts({
|
|
224
|
+
underlyingAsset: params.underlyingAsset,
|
|
225
|
+
optionType: params.optionType,
|
|
226
|
+
strikePrice: params.strikePrice,
|
|
227
|
+
expirationDate: params.expirationDate,
|
|
228
|
+
programId: params.programId,
|
|
229
|
+
rpc: params.rpc,
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
invariant(
|
|
233
|
+
!!resolved.escrowLongAccount &&
|
|
234
|
+
!!resolved.premiumVault &&
|
|
235
|
+
!!resolved.collateralVault &&
|
|
236
|
+
!!resolved.underlyingMint,
|
|
237
|
+
"Option pool and collateral pool must exist; ensure rpc is provided and pools are initialized."
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
const buyerPosition = params.buyerPosition
|
|
241
|
+
? params.buyerPosition
|
|
242
|
+
: (await deriveBuyerPositionPda(
|
|
243
|
+
params.buyer,
|
|
244
|
+
resolved.optionAccount,
|
|
245
|
+
params.programId
|
|
246
|
+
))[0];
|
|
247
|
+
|
|
248
|
+
return buildCloseLongToPoolTransaction({
|
|
249
|
+
optionPool: resolved.optionPool,
|
|
250
|
+
optionAccount: resolved.optionAccount,
|
|
251
|
+
collateralPool: resolved.collateralPool,
|
|
252
|
+
underlyingMint: resolved.underlyingMint!,
|
|
253
|
+
longMint: resolved.longMint,
|
|
254
|
+
escrowLongAccount: resolved.escrowLongAccount!,
|
|
255
|
+
premiumVault: resolved.premiumVault!,
|
|
256
|
+
marketData: resolved.marketData,
|
|
257
|
+
priceUpdate: params.priceUpdate,
|
|
258
|
+
buyer: params.buyer,
|
|
259
|
+
buyerLongAccount: params.buyerLongAccount,
|
|
260
|
+
buyerPayoutAccount: params.buyerPayoutAccount,
|
|
261
|
+
collateralVault: resolved.collateralVault!,
|
|
262
|
+
quantity: params.quantity,
|
|
263
|
+
minPayoutAmount: params.minPayoutAmount,
|
|
264
|
+
buyerPosition,
|
|
265
|
+
omlpVault: params.omlpVault,
|
|
266
|
+
remainingAccounts: params.remainingAccounts,
|
|
267
|
+
});
|
|
268
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epicentral/sos-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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",
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
"dotenv-cli": "^8.0.0"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
+
"@solana-program/address-lookup-table": "^0.11.0",
|
|
19
|
+
"@solana-program/compute-budget": "^0.13.0",
|
|
18
20
|
"@solana/kit": "^6.1.0",
|
|
19
21
|
"bs58": "^6.0.0",
|
|
20
22
|
"decimal.js": "^10.4.3"
|
package/shared/transactions.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
appendTransactionMessageInstructions,
|
|
3
|
+
compressTransactionMessageUsingAddressLookupTables,
|
|
3
4
|
createTransactionMessage,
|
|
4
5
|
getSignatureFromTransaction,
|
|
5
6
|
pipe,
|
|
@@ -7,22 +8,34 @@ import {
|
|
|
7
8
|
setTransactionMessageFeePayerSigner,
|
|
8
9
|
setTransactionMessageLifetimeUsingBlockhash,
|
|
9
10
|
signTransactionMessageWithSigners,
|
|
11
|
+
type AddressesByLookupTableAddress,
|
|
10
12
|
type RpcSubscriptions,
|
|
11
13
|
type SolanaRpcSubscriptionsApi,
|
|
12
14
|
type TransactionSigner,
|
|
13
15
|
} from "@solana/kit";
|
|
14
|
-
import
|
|
16
|
+
import { fetchAddressLookupTable } from "@solana-program/address-lookup-table";
|
|
17
|
+
import {
|
|
18
|
+
getSetComputeUnitLimitInstruction,
|
|
19
|
+
getSetComputeUnitPriceInstruction,
|
|
20
|
+
} from "@solana-program/compute-budget";
|
|
21
|
+
import type { Instruction } from "@solana/kit";
|
|
22
|
+
import { toAddress } from "../client/program";
|
|
23
|
+
import type { AddressLike, BuiltTransaction, KitRpc } from "../client/types";
|
|
15
24
|
|
|
16
25
|
export interface SendBuiltTransactionParams extends BuiltTransaction {
|
|
17
26
|
rpc: KitRpc;
|
|
18
27
|
rpcSubscriptions: RpcSubscriptions<SolanaRpcSubscriptionsApi>;
|
|
19
28
|
feePayer: TransactionSigner<string>;
|
|
20
29
|
commitment?: "processed" | "confirmed" | "finalized";
|
|
30
|
+
computeUnitLimit?: number;
|
|
31
|
+
computeUnitPriceMicroLamports?: number;
|
|
32
|
+
addressLookupTableAddresses?: AddressLike[];
|
|
21
33
|
}
|
|
22
34
|
|
|
23
35
|
/**
|
|
24
36
|
* Sends a built SDK transaction with common Solana Kit defaults.
|
|
25
37
|
* The caller still controls the RPC clients and fee-payer signer.
|
|
38
|
+
* Supports optional compute budget (limit + priority fee) and ALT compression.
|
|
26
39
|
*/
|
|
27
40
|
export async function sendBuiltTransaction(
|
|
28
41
|
params: SendBuiltTransactionParams
|
|
@@ -30,13 +43,44 @@ export async function sendBuiltTransaction(
|
|
|
30
43
|
const commitment = params.commitment ?? "confirmed";
|
|
31
44
|
const { value: latestBlockhash } = await params.rpc.getLatestBlockhash().send();
|
|
32
45
|
|
|
33
|
-
const
|
|
46
|
+
const computeBudgetInstructions: Instruction<string>[] = [];
|
|
47
|
+
if (params.computeUnitLimit !== undefined) {
|
|
48
|
+
computeBudgetInstructions.push(
|
|
49
|
+
getSetComputeUnitLimitInstruction({ units: params.computeUnitLimit })
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (params.computeUnitPriceMicroLamports !== undefined) {
|
|
53
|
+
computeBudgetInstructions.push(
|
|
54
|
+
getSetComputeUnitPriceInstruction({
|
|
55
|
+
microLamports: params.computeUnitPriceMicroLamports,
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
const allInstructions = [...computeBudgetInstructions, ...params.instructions];
|
|
60
|
+
|
|
61
|
+
let txMessage = pipe(
|
|
34
62
|
createTransactionMessage({ version: 0 }),
|
|
35
63
|
(tx) => setTransactionMessageFeePayerSigner(params.feePayer, tx),
|
|
36
64
|
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
|
|
37
|
-
(tx) => appendTransactionMessageInstructions(
|
|
65
|
+
(tx) => appendTransactionMessageInstructions(allInstructions, tx)
|
|
38
66
|
);
|
|
39
67
|
|
|
68
|
+
if (
|
|
69
|
+
params.addressLookupTableAddresses &&
|
|
70
|
+
params.addressLookupTableAddresses.length > 0
|
|
71
|
+
) {
|
|
72
|
+
const addressesByAddressLookupTable: AddressesByLookupTableAddress = {};
|
|
73
|
+
for (const altAddress of params.addressLookupTableAddresses) {
|
|
74
|
+
const resolvedAddress = toAddress(altAddress);
|
|
75
|
+
const { data } = await fetchAddressLookupTable(params.rpc, resolvedAddress);
|
|
76
|
+
addressesByAddressLookupTable[resolvedAddress] = data.addresses;
|
|
77
|
+
}
|
|
78
|
+
txMessage = compressTransactionMessageUsingAddressLookupTables(
|
|
79
|
+
txMessage,
|
|
80
|
+
addressesByAddressLookupTable
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
40
84
|
const signedTx = await signTransactionMessageWithSigners(txMessage);
|
|
41
85
|
const sendAndConfirm = sendAndConfirmTransactionFactory({
|
|
42
86
|
rpc: params.rpc,
|
package/short/builders.ts
CHANGED
|
@@ -7,8 +7,14 @@ import {
|
|
|
7
7
|
} from "../generated";
|
|
8
8
|
import type { Instruction } from "@solana/kit";
|
|
9
9
|
import { toAddress } from "../client/program";
|
|
10
|
-
import type { AddressLike, BuiltTransaction } from "../client/types";
|
|
11
|
-
import {
|
|
10
|
+
import type { AddressLike, BuiltTransaction, KitRpc } from "../client/types";
|
|
11
|
+
import { resolveOptionAccounts } from "../accounts/resolve-option";
|
|
12
|
+
import {
|
|
13
|
+
deriveAssociatedTokenAddress,
|
|
14
|
+
deriveMakerCollateralSharePda,
|
|
15
|
+
deriveMetadataPda,
|
|
16
|
+
deriveWriterPositionPda,
|
|
17
|
+
} from "../accounts/pdas";
|
|
12
18
|
import { assertNonNegativeAmount, assertPositiveAmount } from "../shared/amounts";
|
|
13
19
|
import { invariant } from "../shared/errors";
|
|
14
20
|
import {
|
|
@@ -184,6 +190,99 @@ export async function buildOptionMintTransaction(
|
|
|
184
190
|
return { instructions: [instruction] };
|
|
185
191
|
}
|
|
186
192
|
|
|
193
|
+
export interface BuildOptionMintTransactionWithDerivationParams {
|
|
194
|
+
underlyingAsset: AddressLike;
|
|
195
|
+
optionType: OptionType;
|
|
196
|
+
strikePrice: number;
|
|
197
|
+
expirationDate: bigint | number;
|
|
198
|
+
quantity: bigint | number;
|
|
199
|
+
underlyingMint: AddressLike;
|
|
200
|
+
underlyingSymbol: string;
|
|
201
|
+
makerCollateralAmount: bigint | number;
|
|
202
|
+
borrowedAmount: bigint | number;
|
|
203
|
+
maker: AddressLike;
|
|
204
|
+
makerCollateralAccount: AddressLike;
|
|
205
|
+
rpc: KitRpc;
|
|
206
|
+
programId?: AddressLike;
|
|
207
|
+
vault?: AddressLike;
|
|
208
|
+
vaultTokenAccount?: AddressLike;
|
|
209
|
+
escrowState?: AddressLike;
|
|
210
|
+
escrowAuthority?: AddressLike;
|
|
211
|
+
escrowTokenAccount?: AddressLike;
|
|
212
|
+
poolLoan?: AddressLike;
|
|
213
|
+
liquidityRouter?: AddressLike;
|
|
214
|
+
remainingAccounts?: RemainingAccountInput[];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export async function buildOptionMintTransactionWithDerivation(
|
|
218
|
+
params: BuildOptionMintTransactionWithDerivationParams
|
|
219
|
+
): Promise<BuiltTransaction> {
|
|
220
|
+
const borrowedAmount = BigInt(params.borrowedAmount);
|
|
221
|
+
if (borrowedAmount > 0n) {
|
|
222
|
+
invariant(!!params.vault, "vault is required when borrowedAmount > 0");
|
|
223
|
+
invariant(
|
|
224
|
+
!!params.vaultTokenAccount,
|
|
225
|
+
"vaultTokenAccount is required when borrowedAmount > 0"
|
|
226
|
+
);
|
|
227
|
+
invariant(!!params.escrowState, "escrowState is required when borrowedAmount > 0");
|
|
228
|
+
invariant(
|
|
229
|
+
!!params.escrowAuthority,
|
|
230
|
+
"escrowAuthority is required when borrowedAmount > 0"
|
|
231
|
+
);
|
|
232
|
+
invariant(
|
|
233
|
+
!!params.escrowTokenAccount,
|
|
234
|
+
"escrowTokenAccount is required when borrowedAmount > 0"
|
|
235
|
+
);
|
|
236
|
+
invariant(!!params.poolLoan, "poolLoan is required when borrowedAmount > 0");
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const resolved = await resolveOptionAccounts({
|
|
240
|
+
underlyingAsset: params.underlyingAsset,
|
|
241
|
+
optionType: params.optionType,
|
|
242
|
+
strikePrice: params.strikePrice,
|
|
243
|
+
expirationDate: params.expirationDate,
|
|
244
|
+
programId: params.programId,
|
|
245
|
+
rpc: params.rpc,
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
invariant(
|
|
249
|
+
!!resolved.escrowLongAccount && !!resolved.premiumVault && !!resolved.collateralVault,
|
|
250
|
+
"Option pool and collateral pool must exist; ensure rpc is provided and pools are initialized."
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
const underlyingMint = resolved.underlyingMint ?? params.underlyingMint;
|
|
254
|
+
const [makerLongAccount, makerShortAccount] = await Promise.all([
|
|
255
|
+
deriveAssociatedTokenAddress(params.maker, resolved.longMint),
|
|
256
|
+
deriveAssociatedTokenAddress(params.maker, resolved.shortMint),
|
|
257
|
+
]);
|
|
258
|
+
|
|
259
|
+
return buildOptionMintTransaction({
|
|
260
|
+
...params,
|
|
261
|
+
underlyingAsset: params.underlyingAsset,
|
|
262
|
+
underlyingMint,
|
|
263
|
+
optionAccount: resolved.optionAccount,
|
|
264
|
+
longMint: resolved.longMint,
|
|
265
|
+
shortMint: resolved.shortMint,
|
|
266
|
+
mintAuthority: resolved.mintAuthority,
|
|
267
|
+
makerLongAccount,
|
|
268
|
+
makerShortAccount,
|
|
269
|
+
marketData: resolved.marketData,
|
|
270
|
+
optionPool: resolved.optionPool,
|
|
271
|
+
escrowLongAccount: resolved.escrowLongAccount,
|
|
272
|
+
premiumVault: resolved.premiumVault,
|
|
273
|
+
collateralPool: resolved.collateralPool,
|
|
274
|
+
collateralVault: resolved.collateralVault,
|
|
275
|
+
vault: params.vault,
|
|
276
|
+
vaultTokenAccount: params.vaultTokenAccount,
|
|
277
|
+
escrowState: params.escrowState,
|
|
278
|
+
escrowAuthority: params.escrowAuthority,
|
|
279
|
+
escrowTokenAccount: params.escrowTokenAccount,
|
|
280
|
+
poolLoan: params.poolLoan,
|
|
281
|
+
liquidityRouter: params.liquidityRouter,
|
|
282
|
+
remainingAccounts: params.remainingAccounts,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
187
286
|
export async function buildUnwindWriterUnsoldInstruction(
|
|
188
287
|
params: BuildUnwindWriterUnsoldParams
|
|
189
288
|
): Promise<Instruction<string>> {
|
|
@@ -216,6 +315,63 @@ export async function buildUnwindWriterUnsoldTransaction(
|
|
|
216
315
|
return { instructions: [instruction] };
|
|
217
316
|
}
|
|
218
317
|
|
|
318
|
+
export interface BuildUnwindWriterUnsoldTransactionWithDerivationParams {
|
|
319
|
+
underlyingAsset: AddressLike;
|
|
320
|
+
optionType: OptionType;
|
|
321
|
+
strikePrice: number;
|
|
322
|
+
expirationDate: bigint | number;
|
|
323
|
+
writer: AddressLike;
|
|
324
|
+
unwindQty: bigint | number;
|
|
325
|
+
rpc: KitRpc;
|
|
326
|
+
programId?: AddressLike;
|
|
327
|
+
omlpVault?: AddressLike;
|
|
328
|
+
feeWallet?: AddressLike;
|
|
329
|
+
remainingAccounts?: RemainingAccountInput[];
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export async function buildUnwindWriterUnsoldTransactionWithDerivation(
|
|
333
|
+
params: BuildUnwindWriterUnsoldTransactionWithDerivationParams
|
|
334
|
+
): Promise<BuiltTransaction> {
|
|
335
|
+
const resolved = await resolveOptionAccounts({
|
|
336
|
+
underlyingAsset: params.underlyingAsset,
|
|
337
|
+
optionType: params.optionType,
|
|
338
|
+
strikePrice: params.strikePrice,
|
|
339
|
+
expirationDate: params.expirationDate,
|
|
340
|
+
programId: params.programId,
|
|
341
|
+
rpc: params.rpc,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
invariant(
|
|
345
|
+
!!resolved.escrowLongAccount && !!resolved.collateralVault && !!resolved.underlyingMint,
|
|
346
|
+
"Option pool and collateral pool must exist; ensure rpc is provided and pools are initialized."
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
const [writerShortAccount, writerCollateralAccount, writerPosition] =
|
|
350
|
+
await Promise.all([
|
|
351
|
+
deriveAssociatedTokenAddress(params.writer, resolved.shortMint),
|
|
352
|
+
deriveAssociatedTokenAddress(params.writer, resolved.underlyingMint),
|
|
353
|
+
deriveWriterPositionPda(resolved.optionPool, params.writer, params.programId),
|
|
354
|
+
]);
|
|
355
|
+
|
|
356
|
+
return buildUnwindWriterUnsoldTransaction({
|
|
357
|
+
optionPool: resolved.optionPool,
|
|
358
|
+
optionAccount: resolved.optionAccount,
|
|
359
|
+
longMint: resolved.longMint,
|
|
360
|
+
shortMint: resolved.shortMint,
|
|
361
|
+
escrowLongAccount: resolved.escrowLongAccount!,
|
|
362
|
+
writerShortAccount,
|
|
363
|
+
collateralVault: resolved.collateralVault!,
|
|
364
|
+
writerCollateralAccount,
|
|
365
|
+
writer: params.writer,
|
|
366
|
+
unwindQty: params.unwindQty,
|
|
367
|
+
collateralPool: resolved.collateralPool,
|
|
368
|
+
writerPosition: writerPosition[0],
|
|
369
|
+
omlpVault: params.omlpVault,
|
|
370
|
+
feeWallet: params.feeWallet,
|
|
371
|
+
remainingAccounts: params.remainingAccounts,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
|
|
219
375
|
export function buildSyncWriterPositionInstruction(
|
|
220
376
|
params: BuildSyncWriterPositionParams
|
|
221
377
|
): Instruction<string> {
|