@optionsfi/sdk 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/CHANGELOG.md +113 -0
- package/MIGRATION.md +56 -0
- package/README.md +227 -0
- package/dist/index.d.mts +3315 -0
- package/dist/index.d.ts +3315 -0
- package/dist/index.js +3529 -0
- package/dist/index.mjs +3457 -0
- package/package.json +74 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3529 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
DEFAULT_PRICING_PARAMS: () => DEFAULT_PRICING_PARAMS,
|
|
34
|
+
DEVNET_CONFIG: () => DEVNET_CONFIG,
|
|
35
|
+
DEVNET_USDC_MINT: () => DEVNET_USDC_MINT,
|
|
36
|
+
MAINNET_CONFIG: () => MAINNET_CONFIG,
|
|
37
|
+
MAINNET_USDC_MINT: () => MAINNET_USDC_MINT,
|
|
38
|
+
OptionPricing: () => OptionPricing,
|
|
39
|
+
PYTH_HERMES_URL: () => PYTH_HERMES_URL,
|
|
40
|
+
PYTH_PRICE_FEEDS: () => PYTH_PRICE_FEEDS,
|
|
41
|
+
RFQClient: () => RFQClient,
|
|
42
|
+
RFQ_DEFAULTS: () => RFQ_DEFAULTS,
|
|
43
|
+
TOKEN_DECIMALS: () => TOKEN_DECIMALS,
|
|
44
|
+
VAULT_IDL: () => vault_default,
|
|
45
|
+
VAULT_PROGRAM_ID: () => VAULT_PROGRAM_ID,
|
|
46
|
+
ValidationError: () => ValidationError,
|
|
47
|
+
VaultInstructions: () => VaultInstructions,
|
|
48
|
+
bpsToPercent: () => bpsToPercent,
|
|
49
|
+
deriveShareEscrowPda: () => deriveShareEscrowPda,
|
|
50
|
+
deriveVaultPda: () => deriveVaultPda,
|
|
51
|
+
deriveWhitelistPda: () => deriveWhitelistPda,
|
|
52
|
+
deriveWithdrawalPda: () => deriveWithdrawalPda,
|
|
53
|
+
formatBps: () => formatBps,
|
|
54
|
+
formatDate: () => formatDate,
|
|
55
|
+
formatPercent: () => formatPercent,
|
|
56
|
+
formatPrice: () => formatPrice,
|
|
57
|
+
formatRFQId: () => formatRFQId,
|
|
58
|
+
formatTimeToExpiry: () => formatTimeToExpiry,
|
|
59
|
+
formatTimestamp: () => formatTimestamp,
|
|
60
|
+
formatTokenAmount: () => formatTokenAmount,
|
|
61
|
+
formatUSDC: () => formatUSDC,
|
|
62
|
+
parseTokenAmount: () => parseTokenAmount,
|
|
63
|
+
parseUSDC: () => parseUSDC,
|
|
64
|
+
percentToBps: () => percentToBps,
|
|
65
|
+
shortenAddress: () => shortenAddress,
|
|
66
|
+
validateBlackScholesParams: () => validateBlackScholesParams,
|
|
67
|
+
validatePublicKey: () => validatePublicKey,
|
|
68
|
+
validateRFQParams: () => validateRFQParams,
|
|
69
|
+
validateTimestamp: () => validateTimestamp,
|
|
70
|
+
validateTokenAmount: () => validateTokenAmount
|
|
71
|
+
});
|
|
72
|
+
module.exports = __toCommonJS(index_exports);
|
|
73
|
+
|
|
74
|
+
// src/client/RFQClient.ts
|
|
75
|
+
var import_ws = __toESM(require("ws"));
|
|
76
|
+
var import_web3 = require("@solana/web3.js");
|
|
77
|
+
|
|
78
|
+
// src/constants/config.ts
|
|
79
|
+
var DEVNET_CONFIG = {
|
|
80
|
+
rpcUrl: "https://api.devnet.solana.com",
|
|
81
|
+
rfqRouterUrl: "wss://rfq.optionsfi.xyz",
|
|
82
|
+
programId: "A4jgqct3bwTwRmHECHdPpbH3a8ksaVb7rny9pMUGFo94",
|
|
83
|
+
network: "devnet",
|
|
84
|
+
rfqTimeoutMs: 3e4
|
|
85
|
+
};
|
|
86
|
+
var MAINNET_CONFIG = {
|
|
87
|
+
rpcUrl: "https://api.mainnet-beta.solana.com",
|
|
88
|
+
rfqRouterUrl: "wss://rfq.optionsfi.xyz",
|
|
89
|
+
programId: "A4jgqct3bwTwRmHECHdPpbH3a8ksaVb7rny9pMUGFo94",
|
|
90
|
+
network: "mainnet-beta",
|
|
91
|
+
rfqTimeoutMs: 3e4
|
|
92
|
+
};
|
|
93
|
+
var DEFAULT_PRICING_PARAMS = {
|
|
94
|
+
/** Default risk-free rate (5%) */
|
|
95
|
+
riskFreeRate: 0.05,
|
|
96
|
+
/** Default volatility lookback period in days */
|
|
97
|
+
volatilityLookbackDays: 30,
|
|
98
|
+
/** Maximum acceptable deviation from fair value (5%) */
|
|
99
|
+
maxQuoteDeviationBps: 500,
|
|
100
|
+
/** Trading days per year for volatility annualization */
|
|
101
|
+
tradingDaysPerYear: 252
|
|
102
|
+
};
|
|
103
|
+
var RFQ_DEFAULTS = {
|
|
104
|
+
/** Default RFQ timeout in milliseconds */
|
|
105
|
+
timeoutMs: 3e4,
|
|
106
|
+
/** Minimum quote collection time */
|
|
107
|
+
minQuoteTimeMs: 5e3,
|
|
108
|
+
/** Quote expiry buffer (how long before expiry to stop accepting) */
|
|
109
|
+
quoteExpiryBufferMs: 2e3
|
|
110
|
+
};
|
|
111
|
+
var TOKEN_DECIMALS = {
|
|
112
|
+
USDC: 6,
|
|
113
|
+
SOL: 9,
|
|
114
|
+
NVDAX: 6
|
|
115
|
+
// Example: tokenized NVIDIA stock
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// src/client/RFQClient.ts
|
|
119
|
+
var RFQClient = class {
|
|
120
|
+
connection;
|
|
121
|
+
wsConnection = null;
|
|
122
|
+
config;
|
|
123
|
+
quoteCallbacks = /* @__PURE__ */ new Map();
|
|
124
|
+
eventCallbacks = /* @__PURE__ */ new Set();
|
|
125
|
+
activeRFQs = /* @__PURE__ */ new Map();
|
|
126
|
+
isConnected = false;
|
|
127
|
+
reconnectAttempts = 0;
|
|
128
|
+
maxReconnectAttempts = 5;
|
|
129
|
+
/**
|
|
130
|
+
* Create a new RFQ Client
|
|
131
|
+
*
|
|
132
|
+
* @param config - Configuration for connecting to OptionsFi
|
|
133
|
+
*/
|
|
134
|
+
constructor(config) {
|
|
135
|
+
this.config = {
|
|
136
|
+
...config,
|
|
137
|
+
rfqTimeoutMs: config.rfqTimeoutMs ?? RFQ_DEFAULTS.timeoutMs
|
|
138
|
+
};
|
|
139
|
+
this.connection = new import_web3.Connection(config.rpcUrl, "confirmed");
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Connect to the RFQ router WebSocket
|
|
143
|
+
*
|
|
144
|
+
* @returns Promise that resolves when connected
|
|
145
|
+
* @throws Error if connection fails
|
|
146
|
+
*/
|
|
147
|
+
async connect() {
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
try {
|
|
150
|
+
this.wsConnection = new import_ws.default(this.config.rfqRouterUrl);
|
|
151
|
+
this.wsConnection.on("open", () => {
|
|
152
|
+
console.log("Connected to OptionsFi RFQ Router");
|
|
153
|
+
this.isConnected = true;
|
|
154
|
+
this.reconnectAttempts = 0;
|
|
155
|
+
resolve();
|
|
156
|
+
});
|
|
157
|
+
this.wsConnection.on("message", (data) => {
|
|
158
|
+
try {
|
|
159
|
+
const message = JSON.parse(data.toString());
|
|
160
|
+
this.handleMessage(message);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error("Failed to parse WebSocket message:", error);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
this.wsConnection.on("error", (error) => {
|
|
166
|
+
console.error("WebSocket error:", error);
|
|
167
|
+
this.emitEvent({
|
|
168
|
+
type: "connection_error",
|
|
169
|
+
rfqId: "",
|
|
170
|
+
data: error,
|
|
171
|
+
timestamp: Date.now()
|
|
172
|
+
});
|
|
173
|
+
if (!this.isConnected) {
|
|
174
|
+
reject(error);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
this.wsConnection.on("close", () => {
|
|
178
|
+
console.log("WebSocket connection closed");
|
|
179
|
+
this.isConnected = false;
|
|
180
|
+
this.attemptReconnect();
|
|
181
|
+
});
|
|
182
|
+
} catch (error) {
|
|
183
|
+
reject(error);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Disconnect from the RFQ router
|
|
189
|
+
*/
|
|
190
|
+
disconnect() {
|
|
191
|
+
if (this.wsConnection) {
|
|
192
|
+
this.wsConnection.close();
|
|
193
|
+
this.wsConnection = null;
|
|
194
|
+
this.isConnected = false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Check if the client is connected
|
|
199
|
+
*/
|
|
200
|
+
get connected() {
|
|
201
|
+
return this.isConnected;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Create a new RFQ and broadcast to market makers
|
|
205
|
+
*
|
|
206
|
+
* @param params - RFQ parameters
|
|
207
|
+
* @returns RFQ ID
|
|
208
|
+
* @throws Error if not connected or params invalid
|
|
209
|
+
*/
|
|
210
|
+
async createRFQ(params) {
|
|
211
|
+
if (!this.wsConnection || !this.isConnected) {
|
|
212
|
+
throw new Error("Not connected. Call connect() first.");
|
|
213
|
+
}
|
|
214
|
+
this.validateRFQParams(params);
|
|
215
|
+
const rfqId = this.generateRFQId();
|
|
216
|
+
const rfq = {
|
|
217
|
+
id: rfqId,
|
|
218
|
+
params,
|
|
219
|
+
quotes: [],
|
|
220
|
+
status: "open",
|
|
221
|
+
createdAt: Date.now()
|
|
222
|
+
};
|
|
223
|
+
this.activeRFQs.set(rfqId, rfq);
|
|
224
|
+
const message = {
|
|
225
|
+
type: "create_rfq",
|
|
226
|
+
rfqId,
|
|
227
|
+
underlying: params.asset,
|
|
228
|
+
optionType: params.optionType,
|
|
229
|
+
strike: params.strike,
|
|
230
|
+
expiry: params.expiry,
|
|
231
|
+
size: params.quantity.toString(),
|
|
232
|
+
premiumFloor: params.premiumFloor?.toString() ?? "0",
|
|
233
|
+
timestamp: Date.now()
|
|
234
|
+
};
|
|
235
|
+
this.wsConnection.send(JSON.stringify(message));
|
|
236
|
+
return rfqId;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Subscribe to quotes for a specific RFQ
|
|
240
|
+
*
|
|
241
|
+
* @param rfqId - RFQ to subscribe to
|
|
242
|
+
* @param callback - Called when a quote is received
|
|
243
|
+
*/
|
|
244
|
+
subscribeToQuotes(rfqId, callback) {
|
|
245
|
+
this.quoteCallbacks.set(rfqId, callback);
|
|
246
|
+
if (this.wsConnection && this.isConnected) {
|
|
247
|
+
this.wsConnection.send(JSON.stringify({
|
|
248
|
+
type: "subscribe_quotes",
|
|
249
|
+
rfqId
|
|
250
|
+
}));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Unsubscribe from quotes for an RFQ
|
|
255
|
+
*
|
|
256
|
+
* @param rfqId - RFQ to unsubscribe from
|
|
257
|
+
*/
|
|
258
|
+
unsubscribeFromQuotes(rfqId) {
|
|
259
|
+
this.quoteCallbacks.delete(rfqId);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Accept a quote and execute the option trade
|
|
263
|
+
*
|
|
264
|
+
* @param rfqId - RFQ ID
|
|
265
|
+
* @param quoteId - Quote to accept
|
|
266
|
+
* @param wallet - Solana wallet for signing
|
|
267
|
+
* @returns Transaction signature
|
|
268
|
+
*/
|
|
269
|
+
async executeOption(rfqId, quoteId, wallet) {
|
|
270
|
+
const rfq = this.activeRFQs.get(rfqId);
|
|
271
|
+
if (!rfq) {
|
|
272
|
+
throw new Error(`RFQ ${rfqId} not found`);
|
|
273
|
+
}
|
|
274
|
+
const quote = rfq.quotes.find((q) => q.id === quoteId);
|
|
275
|
+
if (!quote) {
|
|
276
|
+
throw new Error(`Quote ${quoteId} not found in RFQ ${rfqId}`);
|
|
277
|
+
}
|
|
278
|
+
if (this.wsConnection && this.isConnected) {
|
|
279
|
+
this.wsConnection.send(JSON.stringify({
|
|
280
|
+
type: "accept_quote",
|
|
281
|
+
rfqId,
|
|
282
|
+
quoteId
|
|
283
|
+
}));
|
|
284
|
+
}
|
|
285
|
+
const tx = await this.buildExecutionTransaction(rfq, quote);
|
|
286
|
+
const signedTx = await wallet.signTransaction(tx);
|
|
287
|
+
const signature = await this.connection.sendRawTransaction(
|
|
288
|
+
signedTx.serialize()
|
|
289
|
+
);
|
|
290
|
+
await this.connection.confirmTransaction(signature, "confirmed");
|
|
291
|
+
rfq.status = "filled";
|
|
292
|
+
rfq.fill = {
|
|
293
|
+
quoteId,
|
|
294
|
+
marketMaker: quote.marketMaker,
|
|
295
|
+
premium: quote.premium,
|
|
296
|
+
filledAt: Date.now(),
|
|
297
|
+
transactionSignature: signature
|
|
298
|
+
};
|
|
299
|
+
return signature;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Cancel an open RFQ
|
|
303
|
+
*
|
|
304
|
+
* @param rfqId - RFQ to cancel
|
|
305
|
+
*/
|
|
306
|
+
async cancelRFQ(rfqId) {
|
|
307
|
+
const rfq = this.activeRFQs.get(rfqId);
|
|
308
|
+
if (!rfq) {
|
|
309
|
+
throw new Error(`RFQ ${rfqId} not found`);
|
|
310
|
+
}
|
|
311
|
+
if (rfq.status !== "open") {
|
|
312
|
+
throw new Error(`Cannot cancel RFQ with status: ${rfq.status}`);
|
|
313
|
+
}
|
|
314
|
+
if (this.wsConnection && this.isConnected) {
|
|
315
|
+
this.wsConnection.send(JSON.stringify({
|
|
316
|
+
type: "cancel_rfq",
|
|
317
|
+
rfqId
|
|
318
|
+
}));
|
|
319
|
+
}
|
|
320
|
+
rfq.status = "cancelled";
|
|
321
|
+
this.quoteCallbacks.delete(rfqId);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Get an active RFQ by ID
|
|
325
|
+
*
|
|
326
|
+
* @param rfqId - RFQ ID
|
|
327
|
+
* @returns RFQ or undefined
|
|
328
|
+
*/
|
|
329
|
+
getRFQ(rfqId) {
|
|
330
|
+
return this.activeRFQs.get(rfqId);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Get all active RFQs
|
|
334
|
+
*/
|
|
335
|
+
getAllRFQs() {
|
|
336
|
+
return Array.from(this.activeRFQs.values());
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Subscribe to all RFQ events
|
|
340
|
+
*
|
|
341
|
+
* @param callback - Called for each event
|
|
342
|
+
* @returns Unsubscribe function
|
|
343
|
+
*/
|
|
344
|
+
onEvent(callback) {
|
|
345
|
+
this.eventCallbacks.add(callback);
|
|
346
|
+
return () => this.eventCallbacks.delete(callback);
|
|
347
|
+
}
|
|
348
|
+
// ============================================================================
|
|
349
|
+
// Private Methods
|
|
350
|
+
// ============================================================================
|
|
351
|
+
handleMessage(message) {
|
|
352
|
+
if (message.type === "quote" && message.rfqId) {
|
|
353
|
+
const quote = {
|
|
354
|
+
id: message.quoteId || `quote_${Date.now()}`,
|
|
355
|
+
rfqId: message.rfqId,
|
|
356
|
+
marketMaker: message.maker,
|
|
357
|
+
premium: BigInt(message.premium),
|
|
358
|
+
timestamp: Date.now(),
|
|
359
|
+
expiresAt: message.expiresAt || Date.now() + 6e4
|
|
360
|
+
};
|
|
361
|
+
const rfq = this.activeRFQs.get(message.rfqId);
|
|
362
|
+
if (rfq && rfq.status === "open") {
|
|
363
|
+
rfq.quotes.push(quote);
|
|
364
|
+
}
|
|
365
|
+
const callback = this.quoteCallbacks.get(message.rfqId);
|
|
366
|
+
if (callback) {
|
|
367
|
+
callback(quote);
|
|
368
|
+
}
|
|
369
|
+
this.emitEvent({
|
|
370
|
+
type: "quote_received",
|
|
371
|
+
rfqId: message.rfqId,
|
|
372
|
+
data: quote,
|
|
373
|
+
timestamp: Date.now()
|
|
374
|
+
});
|
|
375
|
+
} else if (message.type === "fill" && message.rfqId) {
|
|
376
|
+
const rfq = this.activeRFQs.get(message.rfqId);
|
|
377
|
+
if (rfq) {
|
|
378
|
+
rfq.status = "filled";
|
|
379
|
+
this.emitEvent({
|
|
380
|
+
type: "rfq_filled",
|
|
381
|
+
rfqId: message.rfqId,
|
|
382
|
+
data: rfq,
|
|
383
|
+
timestamp: Date.now()
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
emitEvent(event) {
|
|
389
|
+
for (const callback of this.eventCallbacks) {
|
|
390
|
+
try {
|
|
391
|
+
callback(event);
|
|
392
|
+
} catch (error) {
|
|
393
|
+
console.error("Event callback error:", error);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
validateRFQParams(params) {
|
|
398
|
+
if (!params.asset || params.asset.length === 0) {
|
|
399
|
+
throw new Error("Asset is required");
|
|
400
|
+
}
|
|
401
|
+
if (params.quantity <= 0) {
|
|
402
|
+
throw new Error("Quantity must be positive");
|
|
403
|
+
}
|
|
404
|
+
if (params.strike <= 0) {
|
|
405
|
+
throw new Error("Strike must be positive");
|
|
406
|
+
}
|
|
407
|
+
if (params.expiry <= Math.floor(Date.now() / 1e3)) {
|
|
408
|
+
throw new Error("Expiry must be in the future");
|
|
409
|
+
}
|
|
410
|
+
if (!["call", "put"].includes(params.optionType)) {
|
|
411
|
+
throw new Error('Option type must be "call" or "put"');
|
|
412
|
+
}
|
|
413
|
+
if (!["buy", "sell"].includes(params.side)) {
|
|
414
|
+
throw new Error('Side must be "buy" or "sell"');
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
generateRFQId() {
|
|
418
|
+
return `rfq_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
|
|
419
|
+
}
|
|
420
|
+
async buildExecutionTransaction(rfq, quote) {
|
|
421
|
+
throw new Error(
|
|
422
|
+
"Transaction building not yet implemented. Use VaultInstructions class to build transactions manually."
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
attemptReconnect() {
|
|
426
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
427
|
+
console.error("Max reconnection attempts reached");
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
this.reconnectAttempts++;
|
|
431
|
+
const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts), 3e4);
|
|
432
|
+
console.log(`Attempting reconnection in ${delay}ms (attempt ${this.reconnectAttempts})`);
|
|
433
|
+
setTimeout(() => {
|
|
434
|
+
this.connect().catch((error) => {
|
|
435
|
+
console.error("Reconnection failed:", error);
|
|
436
|
+
});
|
|
437
|
+
}, delay);
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
// src/client/VaultInstructions.ts
|
|
442
|
+
var anchor = __toESM(require("@coral-xyz/anchor"));
|
|
443
|
+
var import_web33 = require("@solana/web3.js");
|
|
444
|
+
|
|
445
|
+
// src/constants/addresses.ts
|
|
446
|
+
var import_web32 = require("@solana/web3.js");
|
|
447
|
+
var VAULT_PROGRAM_ID = new import_web32.PublicKey(
|
|
448
|
+
"A4jgqct3bwTwRmHECHdPpbH3a8ksaVb7rny9pMUGFo94"
|
|
449
|
+
);
|
|
450
|
+
var DEVNET_USDC_MINT = new import_web32.PublicKey(
|
|
451
|
+
"Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr"
|
|
452
|
+
);
|
|
453
|
+
var MAINNET_USDC_MINT = new import_web32.PublicKey(
|
|
454
|
+
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
|
|
455
|
+
);
|
|
456
|
+
var PYTH_PRICE_FEEDS = {
|
|
457
|
+
/** NVDA/USD price feed */
|
|
458
|
+
NVDA: "0x4244d07890e4610f46bbde67de8f43a4bf8b569eebe904f136b469f148503b7f",
|
|
459
|
+
/** SOL/USD price feed */
|
|
460
|
+
SOL: "0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d",
|
|
461
|
+
/** BTC/USD price feed */
|
|
462
|
+
BTC: "0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43",
|
|
463
|
+
/** ETH/USD price feed */
|
|
464
|
+
ETH: "0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace"
|
|
465
|
+
};
|
|
466
|
+
var PYTH_HERMES_URL = "https://hermes.pyth.network";
|
|
467
|
+
function deriveVaultPda(assetId) {
|
|
468
|
+
return import_web32.PublicKey.findProgramAddressSync(
|
|
469
|
+
[Buffer.from("vault"), Buffer.from(assetId)],
|
|
470
|
+
VAULT_PROGRAM_ID
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
function deriveWithdrawalPda(vault, user, epoch) {
|
|
474
|
+
return import_web32.PublicKey.findProgramAddressSync(
|
|
475
|
+
[
|
|
476
|
+
Buffer.from("withdrawal"),
|
|
477
|
+
vault.toBuffer(),
|
|
478
|
+
user.toBuffer(),
|
|
479
|
+
Buffer.from(epoch.toString())
|
|
480
|
+
],
|
|
481
|
+
VAULT_PROGRAM_ID
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
function deriveShareEscrowPda(vault) {
|
|
485
|
+
return import_web32.PublicKey.findProgramAddressSync(
|
|
486
|
+
[Buffer.from("share_escrow"), vault.toBuffer()],
|
|
487
|
+
VAULT_PROGRAM_ID
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
function deriveWhitelistPda(vault) {
|
|
491
|
+
return import_web32.PublicKey.findProgramAddressSync(
|
|
492
|
+
[Buffer.from("whitelist"), vault.toBuffer()],
|
|
493
|
+
VAULT_PROGRAM_ID
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// src/idl/vault.json
|
|
498
|
+
var vault_default = {
|
|
499
|
+
address: "A4jgqct3bwTwRmHECHdPpbH3a8ksaVb7rny9pMUGFo94",
|
|
500
|
+
metadata: {
|
|
501
|
+
name: "vault",
|
|
502
|
+
version: "0.1.0",
|
|
503
|
+
spec: "0.1.0",
|
|
504
|
+
description: "OptionsFi V2 - Covered Call Vault"
|
|
505
|
+
},
|
|
506
|
+
instructions: [
|
|
507
|
+
{
|
|
508
|
+
name: "add_market_maker",
|
|
509
|
+
docs: [
|
|
510
|
+
"Add a market maker to the whitelist"
|
|
511
|
+
],
|
|
512
|
+
discriminator: [
|
|
513
|
+
24,
|
|
514
|
+
255,
|
|
515
|
+
135,
|
|
516
|
+
32,
|
|
517
|
+
193,
|
|
518
|
+
2,
|
|
519
|
+
112,
|
|
520
|
+
44
|
|
521
|
+
],
|
|
522
|
+
accounts: [
|
|
523
|
+
{
|
|
524
|
+
name: "vault",
|
|
525
|
+
pda: {
|
|
526
|
+
seeds: [
|
|
527
|
+
{
|
|
528
|
+
kind: "const",
|
|
529
|
+
value: [
|
|
530
|
+
118,
|
|
531
|
+
97,
|
|
532
|
+
117,
|
|
533
|
+
108,
|
|
534
|
+
116
|
|
535
|
+
]
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
kind: "account",
|
|
539
|
+
path: "vault.asset_id",
|
|
540
|
+
account: "Vault"
|
|
541
|
+
}
|
|
542
|
+
]
|
|
543
|
+
},
|
|
544
|
+
relations: [
|
|
545
|
+
"whitelist"
|
|
546
|
+
]
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
name: "whitelist",
|
|
550
|
+
writable: true,
|
|
551
|
+
pda: {
|
|
552
|
+
seeds: [
|
|
553
|
+
{
|
|
554
|
+
kind: "const",
|
|
555
|
+
value: [
|
|
556
|
+
119,
|
|
557
|
+
104,
|
|
558
|
+
105,
|
|
559
|
+
116,
|
|
560
|
+
101,
|
|
561
|
+
108,
|
|
562
|
+
105,
|
|
563
|
+
115,
|
|
564
|
+
116
|
|
565
|
+
]
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
kind: "account",
|
|
569
|
+
path: "vault"
|
|
570
|
+
}
|
|
571
|
+
]
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
name: "authority",
|
|
576
|
+
writable: true,
|
|
577
|
+
signer: true,
|
|
578
|
+
relations: [
|
|
579
|
+
"vault",
|
|
580
|
+
"whitelist"
|
|
581
|
+
]
|
|
582
|
+
}
|
|
583
|
+
],
|
|
584
|
+
args: [
|
|
585
|
+
{
|
|
586
|
+
name: "market_maker",
|
|
587
|
+
type: "pubkey"
|
|
588
|
+
}
|
|
589
|
+
]
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
name: "advance_epoch",
|
|
593
|
+
docs: [
|
|
594
|
+
"Advance epoch (called by keeper after settlement)",
|
|
595
|
+
"Premium earned is credited to total_assets, increasing share value"
|
|
596
|
+
],
|
|
597
|
+
discriminator: [
|
|
598
|
+
93,
|
|
599
|
+
138,
|
|
600
|
+
234,
|
|
601
|
+
218,
|
|
602
|
+
241,
|
|
603
|
+
230,
|
|
604
|
+
132,
|
|
605
|
+
38
|
|
606
|
+
],
|
|
607
|
+
accounts: [
|
|
608
|
+
{
|
|
609
|
+
name: "vault",
|
|
610
|
+
writable: true,
|
|
611
|
+
pda: {
|
|
612
|
+
seeds: [
|
|
613
|
+
{
|
|
614
|
+
kind: "const",
|
|
615
|
+
value: [
|
|
616
|
+
118,
|
|
617
|
+
97,
|
|
618
|
+
117,
|
|
619
|
+
108,
|
|
620
|
+
116
|
|
621
|
+
]
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
kind: "account",
|
|
625
|
+
path: "vault.asset_id",
|
|
626
|
+
account: "Vault"
|
|
627
|
+
}
|
|
628
|
+
]
|
|
629
|
+
}
|
|
630
|
+
},
|
|
631
|
+
{
|
|
632
|
+
name: "authority",
|
|
633
|
+
signer: true,
|
|
634
|
+
relations: [
|
|
635
|
+
"vault"
|
|
636
|
+
]
|
|
637
|
+
}
|
|
638
|
+
],
|
|
639
|
+
args: [
|
|
640
|
+
{
|
|
641
|
+
name: "premium_earned",
|
|
642
|
+
type: "u64"
|
|
643
|
+
}
|
|
644
|
+
]
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
name: "cancel_param_change",
|
|
648
|
+
docs: [
|
|
649
|
+
"Cancel a queued parameter change"
|
|
650
|
+
],
|
|
651
|
+
discriminator: [
|
|
652
|
+
150,
|
|
653
|
+
147,
|
|
654
|
+
92,
|
|
655
|
+
108,
|
|
656
|
+
72,
|
|
657
|
+
160,
|
|
658
|
+
224,
|
|
659
|
+
55
|
|
660
|
+
],
|
|
661
|
+
accounts: [
|
|
662
|
+
{
|
|
663
|
+
name: "vault",
|
|
664
|
+
writable: true,
|
|
665
|
+
pda: {
|
|
666
|
+
seeds: [
|
|
667
|
+
{
|
|
668
|
+
kind: "const",
|
|
669
|
+
value: [
|
|
670
|
+
118,
|
|
671
|
+
97,
|
|
672
|
+
117,
|
|
673
|
+
108,
|
|
674
|
+
116
|
|
675
|
+
]
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
kind: "account",
|
|
679
|
+
path: "vault.asset_id",
|
|
680
|
+
account: "Vault"
|
|
681
|
+
}
|
|
682
|
+
]
|
|
683
|
+
}
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
name: "authority",
|
|
687
|
+
signer: true,
|
|
688
|
+
relations: [
|
|
689
|
+
"vault"
|
|
690
|
+
]
|
|
691
|
+
}
|
|
692
|
+
],
|
|
693
|
+
args: []
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
name: "close_orphaned_token_account",
|
|
697
|
+
docs: [
|
|
698
|
+
"Close an orphaned token account that was owned by a vault PDA",
|
|
699
|
+
"This is used to clean up old share escrows, vault token accounts, etc.",
|
|
700
|
+
"after a vault has been force-closed, enabling reuse of asset IDs.",
|
|
701
|
+
"",
|
|
702
|
+
"The caller must provide the correct asset_id that was used to derive the vault PDA.",
|
|
703
|
+
"The vault PDA must NOT exist anymore (force-closed)."
|
|
704
|
+
],
|
|
705
|
+
discriminator: [
|
|
706
|
+
232,
|
|
707
|
+
127,
|
|
708
|
+
173,
|
|
709
|
+
13,
|
|
710
|
+
92,
|
|
711
|
+
144,
|
|
712
|
+
116,
|
|
713
|
+
98
|
|
714
|
+
],
|
|
715
|
+
accounts: [
|
|
716
|
+
{
|
|
717
|
+
name: "vault_pda",
|
|
718
|
+
docs: [
|
|
719
|
+
"We verify this matches the derived PDA in the instruction"
|
|
720
|
+
],
|
|
721
|
+
writable: true
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
name: "token_account",
|
|
725
|
+
docs: [
|
|
726
|
+
"The token account to close (share escrow, vault token account, etc.)"
|
|
727
|
+
],
|
|
728
|
+
writable: true
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
name: "authority",
|
|
732
|
+
docs: [
|
|
733
|
+
"Authority receiving the lamports"
|
|
734
|
+
],
|
|
735
|
+
writable: true,
|
|
736
|
+
signer: true
|
|
737
|
+
},
|
|
738
|
+
{
|
|
739
|
+
name: "token_program",
|
|
740
|
+
address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
|
741
|
+
}
|
|
742
|
+
],
|
|
743
|
+
args: [
|
|
744
|
+
{
|
|
745
|
+
name: "asset_id",
|
|
746
|
+
type: "string"
|
|
747
|
+
}
|
|
748
|
+
]
|
|
749
|
+
},
|
|
750
|
+
{
|
|
751
|
+
name: "close_vault",
|
|
752
|
+
docs: [
|
|
753
|
+
"Close a vault and recover rent (authority only)",
|
|
754
|
+
"Vault must be empty (no assets, shares, or pending withdrawals)"
|
|
755
|
+
],
|
|
756
|
+
discriminator: [
|
|
757
|
+
141,
|
|
758
|
+
103,
|
|
759
|
+
17,
|
|
760
|
+
126,
|
|
761
|
+
72,
|
|
762
|
+
75,
|
|
763
|
+
29,
|
|
764
|
+
29
|
|
765
|
+
],
|
|
766
|
+
accounts: [
|
|
767
|
+
{
|
|
768
|
+
name: "vault",
|
|
769
|
+
writable: true,
|
|
770
|
+
pda: {
|
|
771
|
+
seeds: [
|
|
772
|
+
{
|
|
773
|
+
kind: "const",
|
|
774
|
+
value: [
|
|
775
|
+
118,
|
|
776
|
+
97,
|
|
777
|
+
117,
|
|
778
|
+
108,
|
|
779
|
+
116
|
|
780
|
+
]
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
kind: "account",
|
|
784
|
+
path: "vault.asset_id",
|
|
785
|
+
account: "Vault"
|
|
786
|
+
}
|
|
787
|
+
]
|
|
788
|
+
}
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
name: "authority",
|
|
792
|
+
writable: true,
|
|
793
|
+
signer: true,
|
|
794
|
+
relations: [
|
|
795
|
+
"vault"
|
|
796
|
+
]
|
|
797
|
+
}
|
|
798
|
+
],
|
|
799
|
+
args: []
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
name: "collect_premium",
|
|
803
|
+
docs: [
|
|
804
|
+
"Collect premium from market maker (called during epoch roll)",
|
|
805
|
+
"Transfers USDC from payer to vault's premium account",
|
|
806
|
+
"SECURITY FIX M-1: Now requires authority signature to prevent front-running"
|
|
807
|
+
],
|
|
808
|
+
discriminator: [
|
|
809
|
+
166,
|
|
810
|
+
199,
|
|
811
|
+
123,
|
|
812
|
+
128,
|
|
813
|
+
71,
|
|
814
|
+
141,
|
|
815
|
+
223,
|
|
816
|
+
204
|
|
817
|
+
],
|
|
818
|
+
accounts: [
|
|
819
|
+
{
|
|
820
|
+
name: "vault",
|
|
821
|
+
pda: {
|
|
822
|
+
seeds: [
|
|
823
|
+
{
|
|
824
|
+
kind: "const",
|
|
825
|
+
value: [
|
|
826
|
+
118,
|
|
827
|
+
97,
|
|
828
|
+
117,
|
|
829
|
+
108,
|
|
830
|
+
116
|
|
831
|
+
]
|
|
832
|
+
},
|
|
833
|
+
{
|
|
834
|
+
kind: "account",
|
|
835
|
+
path: "vault.asset_id",
|
|
836
|
+
account: "Vault"
|
|
837
|
+
}
|
|
838
|
+
]
|
|
839
|
+
}
|
|
840
|
+
},
|
|
841
|
+
{
|
|
842
|
+
name: "vault_premium_account",
|
|
843
|
+
writable: true
|
|
844
|
+
},
|
|
845
|
+
{
|
|
846
|
+
name: "payer_token_account",
|
|
847
|
+
writable: true
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
name: "payer",
|
|
851
|
+
writable: true,
|
|
852
|
+
signer: true
|
|
853
|
+
},
|
|
854
|
+
{
|
|
855
|
+
name: "authority",
|
|
856
|
+
docs: [
|
|
857
|
+
"SECURITY FIX M-1: Authority must sign to prevent front-running premium collection"
|
|
858
|
+
],
|
|
859
|
+
signer: true,
|
|
860
|
+
relations: [
|
|
861
|
+
"vault"
|
|
862
|
+
]
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
name: "token_program",
|
|
866
|
+
address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
|
867
|
+
}
|
|
868
|
+
],
|
|
869
|
+
args: [
|
|
870
|
+
{
|
|
871
|
+
name: "amount",
|
|
872
|
+
type: "u64"
|
|
873
|
+
}
|
|
874
|
+
]
|
|
875
|
+
},
|
|
876
|
+
{
|
|
877
|
+
name: "create_share_metadata",
|
|
878
|
+
docs: [
|
|
879
|
+
"Create metadata for the share token (vNVDAx, etc.)",
|
|
880
|
+
"Only callable by vault authority since vault PDA is the mint authority"
|
|
881
|
+
],
|
|
882
|
+
discriminator: [
|
|
883
|
+
176,
|
|
884
|
+
243,
|
|
885
|
+
233,
|
|
886
|
+
202,
|
|
887
|
+
218,
|
|
888
|
+
168,
|
|
889
|
+
53,
|
|
890
|
+
158
|
|
891
|
+
],
|
|
892
|
+
accounts: [
|
|
893
|
+
{
|
|
894
|
+
name: "vault",
|
|
895
|
+
pda: {
|
|
896
|
+
seeds: [
|
|
897
|
+
{
|
|
898
|
+
kind: "const",
|
|
899
|
+
value: [
|
|
900
|
+
118,
|
|
901
|
+
97,
|
|
902
|
+
117,
|
|
903
|
+
108,
|
|
904
|
+
116
|
|
905
|
+
]
|
|
906
|
+
},
|
|
907
|
+
{
|
|
908
|
+
kind: "account",
|
|
909
|
+
path: "vault.asset_id",
|
|
910
|
+
account: "Vault"
|
|
911
|
+
}
|
|
912
|
+
]
|
|
913
|
+
}
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
name: "share_mint",
|
|
917
|
+
relations: [
|
|
918
|
+
"vault"
|
|
919
|
+
]
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
name: "metadata",
|
|
923
|
+
writable: true
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
name: "payer",
|
|
927
|
+
writable: true,
|
|
928
|
+
signer: true
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
name: "authority",
|
|
932
|
+
signer: true,
|
|
933
|
+
relations: [
|
|
934
|
+
"vault"
|
|
935
|
+
]
|
|
936
|
+
},
|
|
937
|
+
{
|
|
938
|
+
name: "system_program",
|
|
939
|
+
address: "11111111111111111111111111111111"
|
|
940
|
+
},
|
|
941
|
+
{
|
|
942
|
+
name: "rent",
|
|
943
|
+
address: "SysvarRent111111111111111111111111111111111"
|
|
944
|
+
},
|
|
945
|
+
{
|
|
946
|
+
name: "token_metadata_program",
|
|
947
|
+
address: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
|
|
948
|
+
}
|
|
949
|
+
],
|
|
950
|
+
args: [
|
|
951
|
+
{
|
|
952
|
+
name: "name",
|
|
953
|
+
type: "string"
|
|
954
|
+
},
|
|
955
|
+
{
|
|
956
|
+
name: "symbol",
|
|
957
|
+
type: "string"
|
|
958
|
+
},
|
|
959
|
+
{
|
|
960
|
+
name: "uri",
|
|
961
|
+
type: "string"
|
|
962
|
+
}
|
|
963
|
+
]
|
|
964
|
+
},
|
|
965
|
+
{
|
|
966
|
+
name: "deposit",
|
|
967
|
+
docs: [
|
|
968
|
+
"Deposit underlying tokens and receive vault shares"
|
|
969
|
+
],
|
|
970
|
+
discriminator: [
|
|
971
|
+
242,
|
|
972
|
+
35,
|
|
973
|
+
198,
|
|
974
|
+
137,
|
|
975
|
+
82,
|
|
976
|
+
225,
|
|
977
|
+
242,
|
|
978
|
+
182
|
|
979
|
+
],
|
|
980
|
+
accounts: [
|
|
981
|
+
{
|
|
982
|
+
name: "vault",
|
|
983
|
+
writable: true,
|
|
984
|
+
pda: {
|
|
985
|
+
seeds: [
|
|
986
|
+
{
|
|
987
|
+
kind: "const",
|
|
988
|
+
value: [
|
|
989
|
+
118,
|
|
990
|
+
97,
|
|
991
|
+
117,
|
|
992
|
+
108,
|
|
993
|
+
116
|
|
994
|
+
]
|
|
995
|
+
},
|
|
996
|
+
{
|
|
997
|
+
kind: "account",
|
|
998
|
+
path: "vault.asset_id",
|
|
999
|
+
account: "Vault"
|
|
1000
|
+
}
|
|
1001
|
+
]
|
|
1002
|
+
}
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
name: "share_mint",
|
|
1006
|
+
writable: true
|
|
1007
|
+
},
|
|
1008
|
+
{
|
|
1009
|
+
name: "vault_token_account",
|
|
1010
|
+
writable: true
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
name: "user_token_account",
|
|
1014
|
+
writable: true
|
|
1015
|
+
},
|
|
1016
|
+
{
|
|
1017
|
+
name: "user_share_account",
|
|
1018
|
+
writable: true
|
|
1019
|
+
},
|
|
1020
|
+
{
|
|
1021
|
+
name: "share_escrow",
|
|
1022
|
+
writable: true
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
name: "user",
|
|
1026
|
+
writable: true,
|
|
1027
|
+
signer: true
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
name: "token_program",
|
|
1031
|
+
address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
|
1032
|
+
}
|
|
1033
|
+
],
|
|
1034
|
+
args: [
|
|
1035
|
+
{
|
|
1036
|
+
name: "amount",
|
|
1037
|
+
type: "u64"
|
|
1038
|
+
}
|
|
1039
|
+
]
|
|
1040
|
+
},
|
|
1041
|
+
{
|
|
1042
|
+
name: "execute_param_change",
|
|
1043
|
+
docs: [
|
|
1044
|
+
"SECURITY FIX M-3: Execute queued parameter changes after timelock"
|
|
1045
|
+
],
|
|
1046
|
+
discriminator: [
|
|
1047
|
+
162,
|
|
1048
|
+
166,
|
|
1049
|
+
56,
|
|
1050
|
+
243,
|
|
1051
|
+
168,
|
|
1052
|
+
135,
|
|
1053
|
+
66,
|
|
1054
|
+
175
|
|
1055
|
+
],
|
|
1056
|
+
accounts: [
|
|
1057
|
+
{
|
|
1058
|
+
name: "vault",
|
|
1059
|
+
writable: true,
|
|
1060
|
+
pda: {
|
|
1061
|
+
seeds: [
|
|
1062
|
+
{
|
|
1063
|
+
kind: "const",
|
|
1064
|
+
value: [
|
|
1065
|
+
118,
|
|
1066
|
+
97,
|
|
1067
|
+
117,
|
|
1068
|
+
108,
|
|
1069
|
+
116
|
|
1070
|
+
]
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
kind: "account",
|
|
1074
|
+
path: "vault.asset_id",
|
|
1075
|
+
account: "Vault"
|
|
1076
|
+
}
|
|
1077
|
+
]
|
|
1078
|
+
}
|
|
1079
|
+
},
|
|
1080
|
+
{
|
|
1081
|
+
name: "authority",
|
|
1082
|
+
signer: true,
|
|
1083
|
+
relations: [
|
|
1084
|
+
"vault"
|
|
1085
|
+
]
|
|
1086
|
+
}
|
|
1087
|
+
],
|
|
1088
|
+
args: []
|
|
1089
|
+
},
|
|
1090
|
+
{
|
|
1091
|
+
name: "force_close_vault",
|
|
1092
|
+
docs: [
|
|
1093
|
+
"Force close a vault account (bypasses deserialization)",
|
|
1094
|
+
"USE WITH CAUTION: Only for recovering from incompatible account structures",
|
|
1095
|
+
"SECURITY FIX C-2: Now verifies caller is the stored vault authority"
|
|
1096
|
+
],
|
|
1097
|
+
discriminator: [
|
|
1098
|
+
229,
|
|
1099
|
+
45,
|
|
1100
|
+
206,
|
|
1101
|
+
4,
|
|
1102
|
+
96,
|
|
1103
|
+
129,
|
|
1104
|
+
140,
|
|
1105
|
+
24
|
|
1106
|
+
],
|
|
1107
|
+
accounts: [
|
|
1108
|
+
{
|
|
1109
|
+
name: "vault",
|
|
1110
|
+
writable: true
|
|
1111
|
+
},
|
|
1112
|
+
{
|
|
1113
|
+
name: "authority",
|
|
1114
|
+
writable: true,
|
|
1115
|
+
signer: true
|
|
1116
|
+
}
|
|
1117
|
+
],
|
|
1118
|
+
args: [
|
|
1119
|
+
{
|
|
1120
|
+
name: "asset_id",
|
|
1121
|
+
type: "string"
|
|
1122
|
+
}
|
|
1123
|
+
]
|
|
1124
|
+
},
|
|
1125
|
+
{
|
|
1126
|
+
name: "initialize_vault",
|
|
1127
|
+
docs: [
|
|
1128
|
+
"Initialize a new vault for a specific xStock asset"
|
|
1129
|
+
],
|
|
1130
|
+
discriminator: [
|
|
1131
|
+
48,
|
|
1132
|
+
191,
|
|
1133
|
+
163,
|
|
1134
|
+
44,
|
|
1135
|
+
71,
|
|
1136
|
+
129,
|
|
1137
|
+
63,
|
|
1138
|
+
164
|
|
1139
|
+
],
|
|
1140
|
+
accounts: [
|
|
1141
|
+
{
|
|
1142
|
+
name: "vault",
|
|
1143
|
+
writable: true,
|
|
1144
|
+
pda: {
|
|
1145
|
+
seeds: [
|
|
1146
|
+
{
|
|
1147
|
+
kind: "const",
|
|
1148
|
+
value: [
|
|
1149
|
+
118,
|
|
1150
|
+
97,
|
|
1151
|
+
117,
|
|
1152
|
+
108,
|
|
1153
|
+
116
|
|
1154
|
+
]
|
|
1155
|
+
},
|
|
1156
|
+
{
|
|
1157
|
+
kind: "arg",
|
|
1158
|
+
path: "asset_id"
|
|
1159
|
+
}
|
|
1160
|
+
]
|
|
1161
|
+
}
|
|
1162
|
+
},
|
|
1163
|
+
{
|
|
1164
|
+
name: "underlying_mint"
|
|
1165
|
+
},
|
|
1166
|
+
{
|
|
1167
|
+
name: "premium_mint"
|
|
1168
|
+
},
|
|
1169
|
+
{
|
|
1170
|
+
name: "share_mint",
|
|
1171
|
+
writable: true,
|
|
1172
|
+
signer: true
|
|
1173
|
+
},
|
|
1174
|
+
{
|
|
1175
|
+
name: "vault_token_account",
|
|
1176
|
+
writable: true,
|
|
1177
|
+
signer: true
|
|
1178
|
+
},
|
|
1179
|
+
{
|
|
1180
|
+
name: "premium_token_account",
|
|
1181
|
+
writable: true,
|
|
1182
|
+
signer: true
|
|
1183
|
+
},
|
|
1184
|
+
{
|
|
1185
|
+
name: "share_escrow",
|
|
1186
|
+
writable: true,
|
|
1187
|
+
pda: {
|
|
1188
|
+
seeds: [
|
|
1189
|
+
{
|
|
1190
|
+
kind: "const",
|
|
1191
|
+
value: [
|
|
1192
|
+
115,
|
|
1193
|
+
104,
|
|
1194
|
+
97,
|
|
1195
|
+
114,
|
|
1196
|
+
101,
|
|
1197
|
+
95,
|
|
1198
|
+
101,
|
|
1199
|
+
115,
|
|
1200
|
+
99,
|
|
1201
|
+
114,
|
|
1202
|
+
111,
|
|
1203
|
+
119
|
|
1204
|
+
]
|
|
1205
|
+
},
|
|
1206
|
+
{
|
|
1207
|
+
kind: "account",
|
|
1208
|
+
path: "vault"
|
|
1209
|
+
}
|
|
1210
|
+
]
|
|
1211
|
+
}
|
|
1212
|
+
},
|
|
1213
|
+
{
|
|
1214
|
+
name: "authority",
|
|
1215
|
+
writable: true,
|
|
1216
|
+
signer: true
|
|
1217
|
+
},
|
|
1218
|
+
{
|
|
1219
|
+
name: "system_program",
|
|
1220
|
+
address: "11111111111111111111111111111111"
|
|
1221
|
+
},
|
|
1222
|
+
{
|
|
1223
|
+
name: "token_program",
|
|
1224
|
+
address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
|
1225
|
+
},
|
|
1226
|
+
{
|
|
1227
|
+
name: "rent",
|
|
1228
|
+
address: "SysvarRent111111111111111111111111111111111"
|
|
1229
|
+
}
|
|
1230
|
+
],
|
|
1231
|
+
args: [
|
|
1232
|
+
{
|
|
1233
|
+
name: "asset_id",
|
|
1234
|
+
type: "string"
|
|
1235
|
+
},
|
|
1236
|
+
{
|
|
1237
|
+
name: "utilization_cap_bps",
|
|
1238
|
+
type: "u16"
|
|
1239
|
+
},
|
|
1240
|
+
{
|
|
1241
|
+
name: "min_epoch_duration",
|
|
1242
|
+
type: "i64"
|
|
1243
|
+
}
|
|
1244
|
+
]
|
|
1245
|
+
},
|
|
1246
|
+
{
|
|
1247
|
+
name: "initialize_whitelist",
|
|
1248
|
+
docs: [
|
|
1249
|
+
"Initialize the market maker whitelist"
|
|
1250
|
+
],
|
|
1251
|
+
discriminator: [
|
|
1252
|
+
223,
|
|
1253
|
+
228,
|
|
1254
|
+
11,
|
|
1255
|
+
219,
|
|
1256
|
+
112,
|
|
1257
|
+
174,
|
|
1258
|
+
108,
|
|
1259
|
+
18
|
|
1260
|
+
],
|
|
1261
|
+
accounts: [
|
|
1262
|
+
{
|
|
1263
|
+
name: "vault",
|
|
1264
|
+
pda: {
|
|
1265
|
+
seeds: [
|
|
1266
|
+
{
|
|
1267
|
+
kind: "const",
|
|
1268
|
+
value: [
|
|
1269
|
+
118,
|
|
1270
|
+
97,
|
|
1271
|
+
117,
|
|
1272
|
+
108,
|
|
1273
|
+
116
|
|
1274
|
+
]
|
|
1275
|
+
},
|
|
1276
|
+
{
|
|
1277
|
+
kind: "account",
|
|
1278
|
+
path: "vault.asset_id",
|
|
1279
|
+
account: "Vault"
|
|
1280
|
+
}
|
|
1281
|
+
]
|
|
1282
|
+
}
|
|
1283
|
+
},
|
|
1284
|
+
{
|
|
1285
|
+
name: "whitelist",
|
|
1286
|
+
writable: true,
|
|
1287
|
+
pda: {
|
|
1288
|
+
seeds: [
|
|
1289
|
+
{
|
|
1290
|
+
kind: "const",
|
|
1291
|
+
value: [
|
|
1292
|
+
119,
|
|
1293
|
+
104,
|
|
1294
|
+
105,
|
|
1295
|
+
116,
|
|
1296
|
+
101,
|
|
1297
|
+
108,
|
|
1298
|
+
105,
|
|
1299
|
+
115,
|
|
1300
|
+
116
|
|
1301
|
+
]
|
|
1302
|
+
},
|
|
1303
|
+
{
|
|
1304
|
+
kind: "account",
|
|
1305
|
+
path: "vault"
|
|
1306
|
+
}
|
|
1307
|
+
]
|
|
1308
|
+
}
|
|
1309
|
+
},
|
|
1310
|
+
{
|
|
1311
|
+
name: "authority",
|
|
1312
|
+
writable: true,
|
|
1313
|
+
signer: true,
|
|
1314
|
+
relations: [
|
|
1315
|
+
"vault"
|
|
1316
|
+
]
|
|
1317
|
+
},
|
|
1318
|
+
{
|
|
1319
|
+
name: "system_program",
|
|
1320
|
+
address: "11111111111111111111111111111111"
|
|
1321
|
+
}
|
|
1322
|
+
],
|
|
1323
|
+
args: []
|
|
1324
|
+
},
|
|
1325
|
+
{
|
|
1326
|
+
name: "pay_settlement",
|
|
1327
|
+
docs: [
|
|
1328
|
+
"Pay out to market maker for ITM settlement",
|
|
1329
|
+
"Only callable by vault authority",
|
|
1330
|
+
"SECURITY: Settlement capped at epoch premium earned"
|
|
1331
|
+
],
|
|
1332
|
+
discriminator: [
|
|
1333
|
+
65,
|
|
1334
|
+
54,
|
|
1335
|
+
44,
|
|
1336
|
+
166,
|
|
1337
|
+
205,
|
|
1338
|
+
55,
|
|
1339
|
+
164,
|
|
1340
|
+
205
|
|
1341
|
+
],
|
|
1342
|
+
accounts: [
|
|
1343
|
+
{
|
|
1344
|
+
name: "vault",
|
|
1345
|
+
pda: {
|
|
1346
|
+
seeds: [
|
|
1347
|
+
{
|
|
1348
|
+
kind: "const",
|
|
1349
|
+
value: [
|
|
1350
|
+
118,
|
|
1351
|
+
97,
|
|
1352
|
+
117,
|
|
1353
|
+
108,
|
|
1354
|
+
116
|
|
1355
|
+
]
|
|
1356
|
+
},
|
|
1357
|
+
{
|
|
1358
|
+
kind: "account",
|
|
1359
|
+
path: "vault.asset_id",
|
|
1360
|
+
account: "Vault"
|
|
1361
|
+
}
|
|
1362
|
+
]
|
|
1363
|
+
},
|
|
1364
|
+
relations: [
|
|
1365
|
+
"whitelist"
|
|
1366
|
+
]
|
|
1367
|
+
},
|
|
1368
|
+
{
|
|
1369
|
+
name: "whitelist",
|
|
1370
|
+
pda: {
|
|
1371
|
+
seeds: [
|
|
1372
|
+
{
|
|
1373
|
+
kind: "const",
|
|
1374
|
+
value: [
|
|
1375
|
+
119,
|
|
1376
|
+
104,
|
|
1377
|
+
105,
|
|
1378
|
+
116,
|
|
1379
|
+
101,
|
|
1380
|
+
108,
|
|
1381
|
+
105,
|
|
1382
|
+
115,
|
|
1383
|
+
116
|
|
1384
|
+
]
|
|
1385
|
+
},
|
|
1386
|
+
{
|
|
1387
|
+
kind: "account",
|
|
1388
|
+
path: "vault"
|
|
1389
|
+
}
|
|
1390
|
+
]
|
|
1391
|
+
}
|
|
1392
|
+
},
|
|
1393
|
+
{
|
|
1394
|
+
name: "vault_premium_account",
|
|
1395
|
+
writable: true
|
|
1396
|
+
},
|
|
1397
|
+
{
|
|
1398
|
+
name: "recipient_token_account",
|
|
1399
|
+
writable: true
|
|
1400
|
+
},
|
|
1401
|
+
{
|
|
1402
|
+
name: "recipient"
|
|
1403
|
+
},
|
|
1404
|
+
{
|
|
1405
|
+
name: "authority",
|
|
1406
|
+
signer: true,
|
|
1407
|
+
relations: [
|
|
1408
|
+
"vault"
|
|
1409
|
+
]
|
|
1410
|
+
},
|
|
1411
|
+
{
|
|
1412
|
+
name: "token_program",
|
|
1413
|
+
address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
|
1414
|
+
}
|
|
1415
|
+
],
|
|
1416
|
+
args: [
|
|
1417
|
+
{
|
|
1418
|
+
name: "amount",
|
|
1419
|
+
type: "u64"
|
|
1420
|
+
}
|
|
1421
|
+
]
|
|
1422
|
+
},
|
|
1423
|
+
{
|
|
1424
|
+
name: "process_withdrawal",
|
|
1425
|
+
docs: [
|
|
1426
|
+
"Process withdrawal after epoch settles",
|
|
1427
|
+
"SECURITY FIX H-3: Added min_expected_amount for slippage protection"
|
|
1428
|
+
],
|
|
1429
|
+
discriminator: [
|
|
1430
|
+
51,
|
|
1431
|
+
97,
|
|
1432
|
+
236,
|
|
1433
|
+
17,
|
|
1434
|
+
37,
|
|
1435
|
+
33,
|
|
1436
|
+
196,
|
|
1437
|
+
64
|
|
1438
|
+
],
|
|
1439
|
+
accounts: [
|
|
1440
|
+
{
|
|
1441
|
+
name: "vault",
|
|
1442
|
+
writable: true,
|
|
1443
|
+
pda: {
|
|
1444
|
+
seeds: [
|
|
1445
|
+
{
|
|
1446
|
+
kind: "const",
|
|
1447
|
+
value: [
|
|
1448
|
+
118,
|
|
1449
|
+
97,
|
|
1450
|
+
117,
|
|
1451
|
+
108,
|
|
1452
|
+
116
|
|
1453
|
+
]
|
|
1454
|
+
},
|
|
1455
|
+
{
|
|
1456
|
+
kind: "account",
|
|
1457
|
+
path: "vault.asset_id",
|
|
1458
|
+
account: "Vault"
|
|
1459
|
+
}
|
|
1460
|
+
]
|
|
1461
|
+
},
|
|
1462
|
+
relations: [
|
|
1463
|
+
"withdrawal_request"
|
|
1464
|
+
]
|
|
1465
|
+
},
|
|
1466
|
+
{
|
|
1467
|
+
name: "withdrawal_request",
|
|
1468
|
+
writable: true
|
|
1469
|
+
},
|
|
1470
|
+
{
|
|
1471
|
+
name: "share_mint",
|
|
1472
|
+
writable: true
|
|
1473
|
+
},
|
|
1474
|
+
{
|
|
1475
|
+
name: "vault_token_account",
|
|
1476
|
+
writable: true
|
|
1477
|
+
},
|
|
1478
|
+
{
|
|
1479
|
+
name: "user_token_account",
|
|
1480
|
+
writable: true
|
|
1481
|
+
},
|
|
1482
|
+
{
|
|
1483
|
+
name: "share_escrow",
|
|
1484
|
+
writable: true
|
|
1485
|
+
},
|
|
1486
|
+
{
|
|
1487
|
+
name: "vault_premium_account",
|
|
1488
|
+
writable: true
|
|
1489
|
+
},
|
|
1490
|
+
{
|
|
1491
|
+
name: "user_premium_account",
|
|
1492
|
+
writable: true,
|
|
1493
|
+
pda: {
|
|
1494
|
+
seeds: [
|
|
1495
|
+
{
|
|
1496
|
+
kind: "account",
|
|
1497
|
+
path: "user"
|
|
1498
|
+
},
|
|
1499
|
+
{
|
|
1500
|
+
kind: "const",
|
|
1501
|
+
value: [
|
|
1502
|
+
6,
|
|
1503
|
+
221,
|
|
1504
|
+
246,
|
|
1505
|
+
225,
|
|
1506
|
+
215,
|
|
1507
|
+
101,
|
|
1508
|
+
161,
|
|
1509
|
+
147,
|
|
1510
|
+
217,
|
|
1511
|
+
203,
|
|
1512
|
+
225,
|
|
1513
|
+
70,
|
|
1514
|
+
206,
|
|
1515
|
+
235,
|
|
1516
|
+
121,
|
|
1517
|
+
172,
|
|
1518
|
+
28,
|
|
1519
|
+
180,
|
|
1520
|
+
133,
|
|
1521
|
+
237,
|
|
1522
|
+
95,
|
|
1523
|
+
91,
|
|
1524
|
+
55,
|
|
1525
|
+
145,
|
|
1526
|
+
58,
|
|
1527
|
+
140,
|
|
1528
|
+
245,
|
|
1529
|
+
133,
|
|
1530
|
+
126,
|
|
1531
|
+
255,
|
|
1532
|
+
0,
|
|
1533
|
+
169
|
|
1534
|
+
]
|
|
1535
|
+
},
|
|
1536
|
+
{
|
|
1537
|
+
kind: "account",
|
|
1538
|
+
path: "premium_mint"
|
|
1539
|
+
}
|
|
1540
|
+
],
|
|
1541
|
+
program: {
|
|
1542
|
+
kind: "const",
|
|
1543
|
+
value: [
|
|
1544
|
+
140,
|
|
1545
|
+
151,
|
|
1546
|
+
37,
|
|
1547
|
+
143,
|
|
1548
|
+
78,
|
|
1549
|
+
36,
|
|
1550
|
+
137,
|
|
1551
|
+
241,
|
|
1552
|
+
187,
|
|
1553
|
+
61,
|
|
1554
|
+
16,
|
|
1555
|
+
41,
|
|
1556
|
+
20,
|
|
1557
|
+
142,
|
|
1558
|
+
13,
|
|
1559
|
+
131,
|
|
1560
|
+
11,
|
|
1561
|
+
90,
|
|
1562
|
+
19,
|
|
1563
|
+
153,
|
|
1564
|
+
218,
|
|
1565
|
+
255,
|
|
1566
|
+
16,
|
|
1567
|
+
132,
|
|
1568
|
+
4,
|
|
1569
|
+
142,
|
|
1570
|
+
123,
|
|
1571
|
+
216,
|
|
1572
|
+
219,
|
|
1573
|
+
233,
|
|
1574
|
+
248,
|
|
1575
|
+
89
|
|
1576
|
+
]
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
},
|
|
1580
|
+
{
|
|
1581
|
+
name: "premium_mint"
|
|
1582
|
+
},
|
|
1583
|
+
{
|
|
1584
|
+
name: "user",
|
|
1585
|
+
writable: true,
|
|
1586
|
+
signer: true,
|
|
1587
|
+
relations: [
|
|
1588
|
+
"withdrawal_request"
|
|
1589
|
+
]
|
|
1590
|
+
},
|
|
1591
|
+
{
|
|
1592
|
+
name: "token_program",
|
|
1593
|
+
address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
|
1594
|
+
},
|
|
1595
|
+
{
|
|
1596
|
+
name: "associated_token_program",
|
|
1597
|
+
address: "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
|
|
1598
|
+
},
|
|
1599
|
+
{
|
|
1600
|
+
name: "system_program",
|
|
1601
|
+
address: "11111111111111111111111111111111"
|
|
1602
|
+
}
|
|
1603
|
+
],
|
|
1604
|
+
args: [
|
|
1605
|
+
{
|
|
1606
|
+
name: "min_expected_amount",
|
|
1607
|
+
type: "u64"
|
|
1608
|
+
}
|
|
1609
|
+
]
|
|
1610
|
+
},
|
|
1611
|
+
{
|
|
1612
|
+
name: "queue_param_change",
|
|
1613
|
+
docs: [
|
|
1614
|
+
"SECURITY FIX M-3: Queue a parameter change with timelock",
|
|
1615
|
+
"Changes take effect after TIMELOCK_DURATION (24 hours)"
|
|
1616
|
+
],
|
|
1617
|
+
discriminator: [
|
|
1618
|
+
140,
|
|
1619
|
+
242,
|
|
1620
|
+
124,
|
|
1621
|
+
63,
|
|
1622
|
+
143,
|
|
1623
|
+
237,
|
|
1624
|
+
195,
|
|
1625
|
+
231
|
|
1626
|
+
],
|
|
1627
|
+
accounts: [
|
|
1628
|
+
{
|
|
1629
|
+
name: "vault",
|
|
1630
|
+
writable: true,
|
|
1631
|
+
pda: {
|
|
1632
|
+
seeds: [
|
|
1633
|
+
{
|
|
1634
|
+
kind: "const",
|
|
1635
|
+
value: [
|
|
1636
|
+
118,
|
|
1637
|
+
97,
|
|
1638
|
+
117,
|
|
1639
|
+
108,
|
|
1640
|
+
116
|
|
1641
|
+
]
|
|
1642
|
+
},
|
|
1643
|
+
{
|
|
1644
|
+
kind: "account",
|
|
1645
|
+
path: "vault.asset_id",
|
|
1646
|
+
account: "Vault"
|
|
1647
|
+
}
|
|
1648
|
+
]
|
|
1649
|
+
}
|
|
1650
|
+
},
|
|
1651
|
+
{
|
|
1652
|
+
name: "authority",
|
|
1653
|
+
signer: true,
|
|
1654
|
+
relations: [
|
|
1655
|
+
"vault"
|
|
1656
|
+
]
|
|
1657
|
+
}
|
|
1658
|
+
],
|
|
1659
|
+
args: [
|
|
1660
|
+
{
|
|
1661
|
+
name: "new_min_epoch_duration",
|
|
1662
|
+
type: {
|
|
1663
|
+
option: "i64"
|
|
1664
|
+
}
|
|
1665
|
+
},
|
|
1666
|
+
{
|
|
1667
|
+
name: "new_utilization_cap_bps",
|
|
1668
|
+
type: {
|
|
1669
|
+
option: "u16"
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
]
|
|
1673
|
+
},
|
|
1674
|
+
{
|
|
1675
|
+
name: "record_notional_exposure",
|
|
1676
|
+
docs: [
|
|
1677
|
+
"Record notional exposure when an RFQ is filled (fractional options)",
|
|
1678
|
+
"Premium is in premium_mint tokens (USDC)"
|
|
1679
|
+
],
|
|
1680
|
+
discriminator: [
|
|
1681
|
+
26,
|
|
1682
|
+
180,
|
|
1683
|
+
108,
|
|
1684
|
+
160,
|
|
1685
|
+
15,
|
|
1686
|
+
34,
|
|
1687
|
+
179,
|
|
1688
|
+
128
|
|
1689
|
+
],
|
|
1690
|
+
accounts: [
|
|
1691
|
+
{
|
|
1692
|
+
name: "vault",
|
|
1693
|
+
writable: true,
|
|
1694
|
+
pda: {
|
|
1695
|
+
seeds: [
|
|
1696
|
+
{
|
|
1697
|
+
kind: "const",
|
|
1698
|
+
value: [
|
|
1699
|
+
118,
|
|
1700
|
+
97,
|
|
1701
|
+
117,
|
|
1702
|
+
108,
|
|
1703
|
+
116
|
|
1704
|
+
]
|
|
1705
|
+
},
|
|
1706
|
+
{
|
|
1707
|
+
kind: "account",
|
|
1708
|
+
path: "vault.asset_id",
|
|
1709
|
+
account: "Vault"
|
|
1710
|
+
}
|
|
1711
|
+
]
|
|
1712
|
+
}
|
|
1713
|
+
},
|
|
1714
|
+
{
|
|
1715
|
+
name: "authority",
|
|
1716
|
+
signer: true,
|
|
1717
|
+
relations: [
|
|
1718
|
+
"vault"
|
|
1719
|
+
]
|
|
1720
|
+
}
|
|
1721
|
+
],
|
|
1722
|
+
args: [
|
|
1723
|
+
{
|
|
1724
|
+
name: "notional_tokens",
|
|
1725
|
+
type: "u64"
|
|
1726
|
+
},
|
|
1727
|
+
{
|
|
1728
|
+
name: "premium",
|
|
1729
|
+
type: "u64"
|
|
1730
|
+
}
|
|
1731
|
+
]
|
|
1732
|
+
},
|
|
1733
|
+
{
|
|
1734
|
+
name: "remove_market_maker",
|
|
1735
|
+
docs: [
|
|
1736
|
+
"SECURITY FIX M-4: Remove a market maker from the whitelist"
|
|
1737
|
+
],
|
|
1738
|
+
discriminator: [
|
|
1739
|
+
101,
|
|
1740
|
+
241,
|
|
1741
|
+
39,
|
|
1742
|
+
132,
|
|
1743
|
+
210,
|
|
1744
|
+
208,
|
|
1745
|
+
183,
|
|
1746
|
+
254
|
|
1747
|
+
],
|
|
1748
|
+
accounts: [
|
|
1749
|
+
{
|
|
1750
|
+
name: "vault",
|
|
1751
|
+
pda: {
|
|
1752
|
+
seeds: [
|
|
1753
|
+
{
|
|
1754
|
+
kind: "const",
|
|
1755
|
+
value: [
|
|
1756
|
+
118,
|
|
1757
|
+
97,
|
|
1758
|
+
117,
|
|
1759
|
+
108,
|
|
1760
|
+
116
|
|
1761
|
+
]
|
|
1762
|
+
},
|
|
1763
|
+
{
|
|
1764
|
+
kind: "account",
|
|
1765
|
+
path: "vault.asset_id",
|
|
1766
|
+
account: "Vault"
|
|
1767
|
+
}
|
|
1768
|
+
]
|
|
1769
|
+
},
|
|
1770
|
+
relations: [
|
|
1771
|
+
"whitelist"
|
|
1772
|
+
]
|
|
1773
|
+
},
|
|
1774
|
+
{
|
|
1775
|
+
name: "whitelist",
|
|
1776
|
+
writable: true,
|
|
1777
|
+
pda: {
|
|
1778
|
+
seeds: [
|
|
1779
|
+
{
|
|
1780
|
+
kind: "const",
|
|
1781
|
+
value: [
|
|
1782
|
+
119,
|
|
1783
|
+
104,
|
|
1784
|
+
105,
|
|
1785
|
+
116,
|
|
1786
|
+
101,
|
|
1787
|
+
108,
|
|
1788
|
+
105,
|
|
1789
|
+
115,
|
|
1790
|
+
116
|
|
1791
|
+
]
|
|
1792
|
+
},
|
|
1793
|
+
{
|
|
1794
|
+
kind: "account",
|
|
1795
|
+
path: "vault"
|
|
1796
|
+
}
|
|
1797
|
+
]
|
|
1798
|
+
}
|
|
1799
|
+
},
|
|
1800
|
+
{
|
|
1801
|
+
name: "authority",
|
|
1802
|
+
writable: true,
|
|
1803
|
+
signer: true,
|
|
1804
|
+
relations: [
|
|
1805
|
+
"vault",
|
|
1806
|
+
"whitelist"
|
|
1807
|
+
]
|
|
1808
|
+
}
|
|
1809
|
+
],
|
|
1810
|
+
args: [
|
|
1811
|
+
{
|
|
1812
|
+
name: "market_maker",
|
|
1813
|
+
type: "pubkey"
|
|
1814
|
+
}
|
|
1815
|
+
]
|
|
1816
|
+
},
|
|
1817
|
+
{
|
|
1818
|
+
name: "request_withdrawal",
|
|
1819
|
+
docs: [
|
|
1820
|
+
"Request withdrawal (queued until epoch end)"
|
|
1821
|
+
],
|
|
1822
|
+
discriminator: [
|
|
1823
|
+
251,
|
|
1824
|
+
85,
|
|
1825
|
+
121,
|
|
1826
|
+
205,
|
|
1827
|
+
56,
|
|
1828
|
+
201,
|
|
1829
|
+
12,
|
|
1830
|
+
177
|
|
1831
|
+
],
|
|
1832
|
+
accounts: [
|
|
1833
|
+
{
|
|
1834
|
+
name: "vault",
|
|
1835
|
+
writable: true,
|
|
1836
|
+
pda: {
|
|
1837
|
+
seeds: [
|
|
1838
|
+
{
|
|
1839
|
+
kind: "const",
|
|
1840
|
+
value: [
|
|
1841
|
+
118,
|
|
1842
|
+
97,
|
|
1843
|
+
117,
|
|
1844
|
+
108,
|
|
1845
|
+
116
|
|
1846
|
+
]
|
|
1847
|
+
},
|
|
1848
|
+
{
|
|
1849
|
+
kind: "account",
|
|
1850
|
+
path: "vault.asset_id",
|
|
1851
|
+
account: "Vault"
|
|
1852
|
+
}
|
|
1853
|
+
]
|
|
1854
|
+
}
|
|
1855
|
+
},
|
|
1856
|
+
{
|
|
1857
|
+
name: "withdrawal_request",
|
|
1858
|
+
writable: true,
|
|
1859
|
+
pda: {
|
|
1860
|
+
seeds: [
|
|
1861
|
+
{
|
|
1862
|
+
kind: "const",
|
|
1863
|
+
value: [
|
|
1864
|
+
119,
|
|
1865
|
+
105,
|
|
1866
|
+
116,
|
|
1867
|
+
104,
|
|
1868
|
+
100,
|
|
1869
|
+
114,
|
|
1870
|
+
97,
|
|
1871
|
+
119,
|
|
1872
|
+
97,
|
|
1873
|
+
108
|
|
1874
|
+
]
|
|
1875
|
+
},
|
|
1876
|
+
{
|
|
1877
|
+
kind: "account",
|
|
1878
|
+
path: "vault"
|
|
1879
|
+
},
|
|
1880
|
+
{
|
|
1881
|
+
kind: "account",
|
|
1882
|
+
path: "user"
|
|
1883
|
+
},
|
|
1884
|
+
{
|
|
1885
|
+
kind: "account",
|
|
1886
|
+
path: "vault.epoch",
|
|
1887
|
+
account: "Vault"
|
|
1888
|
+
}
|
|
1889
|
+
]
|
|
1890
|
+
}
|
|
1891
|
+
},
|
|
1892
|
+
{
|
|
1893
|
+
name: "share_escrow",
|
|
1894
|
+
writable: true
|
|
1895
|
+
},
|
|
1896
|
+
{
|
|
1897
|
+
name: "user_share_account",
|
|
1898
|
+
writable: true
|
|
1899
|
+
},
|
|
1900
|
+
{
|
|
1901
|
+
name: "user",
|
|
1902
|
+
writable: true,
|
|
1903
|
+
signer: true
|
|
1904
|
+
},
|
|
1905
|
+
{
|
|
1906
|
+
name: "system_program",
|
|
1907
|
+
address: "11111111111111111111111111111111"
|
|
1908
|
+
},
|
|
1909
|
+
{
|
|
1910
|
+
name: "token_program",
|
|
1911
|
+
address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
|
1912
|
+
}
|
|
1913
|
+
],
|
|
1914
|
+
args: [
|
|
1915
|
+
{
|
|
1916
|
+
name: "shares",
|
|
1917
|
+
type: "u64"
|
|
1918
|
+
}
|
|
1919
|
+
]
|
|
1920
|
+
},
|
|
1921
|
+
{
|
|
1922
|
+
name: "set_min_epoch_duration",
|
|
1923
|
+
docs: [
|
|
1924
|
+
"DEPRECATED: Direct parameter changes now require timelock",
|
|
1925
|
+
"Kept for backwards compatibility but will fail"
|
|
1926
|
+
],
|
|
1927
|
+
discriminator: [
|
|
1928
|
+
172,
|
|
1929
|
+
45,
|
|
1930
|
+
116,
|
|
1931
|
+
18,
|
|
1932
|
+
195,
|
|
1933
|
+
137,
|
|
1934
|
+
80,
|
|
1935
|
+
225
|
|
1936
|
+
],
|
|
1937
|
+
accounts: [
|
|
1938
|
+
{
|
|
1939
|
+
name: "vault",
|
|
1940
|
+
writable: true,
|
|
1941
|
+
pda: {
|
|
1942
|
+
seeds: [
|
|
1943
|
+
{
|
|
1944
|
+
kind: "const",
|
|
1945
|
+
value: [
|
|
1946
|
+
118,
|
|
1947
|
+
97,
|
|
1948
|
+
117,
|
|
1949
|
+
108,
|
|
1950
|
+
116
|
|
1951
|
+
]
|
|
1952
|
+
},
|
|
1953
|
+
{
|
|
1954
|
+
kind: "account",
|
|
1955
|
+
path: "vault.asset_id",
|
|
1956
|
+
account: "Vault"
|
|
1957
|
+
}
|
|
1958
|
+
]
|
|
1959
|
+
}
|
|
1960
|
+
},
|
|
1961
|
+
{
|
|
1962
|
+
name: "authority",
|
|
1963
|
+
signer: true,
|
|
1964
|
+
relations: [
|
|
1965
|
+
"vault"
|
|
1966
|
+
]
|
|
1967
|
+
}
|
|
1968
|
+
],
|
|
1969
|
+
args: [
|
|
1970
|
+
{
|
|
1971
|
+
name: "_duration",
|
|
1972
|
+
type: "i64"
|
|
1973
|
+
}
|
|
1974
|
+
]
|
|
1975
|
+
},
|
|
1976
|
+
{
|
|
1977
|
+
name: "set_pause",
|
|
1978
|
+
docs: [
|
|
1979
|
+
"SECURITY: Pause or unpause the vault (emergency control)",
|
|
1980
|
+
"When paused, deposits and withdrawal requests are blocked"
|
|
1981
|
+
],
|
|
1982
|
+
discriminator: [
|
|
1983
|
+
63,
|
|
1984
|
+
32,
|
|
1985
|
+
154,
|
|
1986
|
+
2,
|
|
1987
|
+
56,
|
|
1988
|
+
103,
|
|
1989
|
+
79,
|
|
1990
|
+
45
|
|
1991
|
+
],
|
|
1992
|
+
accounts: [
|
|
1993
|
+
{
|
|
1994
|
+
name: "vault",
|
|
1995
|
+
writable: true,
|
|
1996
|
+
pda: {
|
|
1997
|
+
seeds: [
|
|
1998
|
+
{
|
|
1999
|
+
kind: "const",
|
|
2000
|
+
value: [
|
|
2001
|
+
118,
|
|
2002
|
+
97,
|
|
2003
|
+
117,
|
|
2004
|
+
108,
|
|
2005
|
+
116
|
|
2006
|
+
]
|
|
2007
|
+
},
|
|
2008
|
+
{
|
|
2009
|
+
kind: "account",
|
|
2010
|
+
path: "vault.asset_id",
|
|
2011
|
+
account: "Vault"
|
|
2012
|
+
}
|
|
2013
|
+
]
|
|
2014
|
+
}
|
|
2015
|
+
},
|
|
2016
|
+
{
|
|
2017
|
+
name: "authority",
|
|
2018
|
+
signer: true,
|
|
2019
|
+
relations: [
|
|
2020
|
+
"vault"
|
|
2021
|
+
]
|
|
2022
|
+
}
|
|
2023
|
+
],
|
|
2024
|
+
args: [
|
|
2025
|
+
{
|
|
2026
|
+
name: "paused",
|
|
2027
|
+
type: "bool"
|
|
2028
|
+
}
|
|
2029
|
+
]
|
|
2030
|
+
},
|
|
2031
|
+
{
|
|
2032
|
+
name: "set_utilization_cap",
|
|
2033
|
+
docs: [
|
|
2034
|
+
"DEPRECATED: Direct parameter changes now require timelock",
|
|
2035
|
+
"Kept for backwards compatibility but will fail"
|
|
2036
|
+
],
|
|
2037
|
+
discriminator: [
|
|
2038
|
+
54,
|
|
2039
|
+
143,
|
|
2040
|
+
110,
|
|
2041
|
+
156,
|
|
2042
|
+
48,
|
|
2043
|
+
172,
|
|
2044
|
+
7,
|
|
2045
|
+
64
|
|
2046
|
+
],
|
|
2047
|
+
accounts: [
|
|
2048
|
+
{
|
|
2049
|
+
name: "vault",
|
|
2050
|
+
writable: true,
|
|
2051
|
+
pda: {
|
|
2052
|
+
seeds: [
|
|
2053
|
+
{
|
|
2054
|
+
kind: "const",
|
|
2055
|
+
value: [
|
|
2056
|
+
118,
|
|
2057
|
+
97,
|
|
2058
|
+
117,
|
|
2059
|
+
108,
|
|
2060
|
+
116
|
|
2061
|
+
]
|
|
2062
|
+
},
|
|
2063
|
+
{
|
|
2064
|
+
kind: "account",
|
|
2065
|
+
path: "vault.asset_id",
|
|
2066
|
+
account: "Vault"
|
|
2067
|
+
}
|
|
2068
|
+
]
|
|
2069
|
+
}
|
|
2070
|
+
},
|
|
2071
|
+
{
|
|
2072
|
+
name: "authority",
|
|
2073
|
+
signer: true,
|
|
2074
|
+
relations: [
|
|
2075
|
+
"vault"
|
|
2076
|
+
]
|
|
2077
|
+
}
|
|
2078
|
+
],
|
|
2079
|
+
args: [
|
|
2080
|
+
{
|
|
2081
|
+
name: "_cap_bps",
|
|
2082
|
+
type: "u16"
|
|
2083
|
+
}
|
|
2084
|
+
]
|
|
2085
|
+
}
|
|
2086
|
+
],
|
|
2087
|
+
accounts: [
|
|
2088
|
+
{
|
|
2089
|
+
name: "Vault",
|
|
2090
|
+
discriminator: [
|
|
2091
|
+
211,
|
|
2092
|
+
8,
|
|
2093
|
+
232,
|
|
2094
|
+
43,
|
|
2095
|
+
2,
|
|
2096
|
+
152,
|
|
2097
|
+
117,
|
|
2098
|
+
119
|
|
2099
|
+
]
|
|
2100
|
+
},
|
|
2101
|
+
{
|
|
2102
|
+
name: "VaultWhitelist",
|
|
2103
|
+
discriminator: [
|
|
2104
|
+
82,
|
|
2105
|
+
19,
|
|
2106
|
+
233,
|
|
2107
|
+
96,
|
|
2108
|
+
174,
|
|
2109
|
+
0,
|
|
2110
|
+
57,
|
|
2111
|
+
17
|
|
2112
|
+
]
|
|
2113
|
+
},
|
|
2114
|
+
{
|
|
2115
|
+
name: "WithdrawalRequest",
|
|
2116
|
+
discriminator: [
|
|
2117
|
+
242,
|
|
2118
|
+
88,
|
|
2119
|
+
147,
|
|
2120
|
+
173,
|
|
2121
|
+
182,
|
|
2122
|
+
62,
|
|
2123
|
+
229,
|
|
2124
|
+
193
|
|
2125
|
+
]
|
|
2126
|
+
}
|
|
2127
|
+
],
|
|
2128
|
+
events: [
|
|
2129
|
+
{
|
|
2130
|
+
name: "DepositEvent",
|
|
2131
|
+
discriminator: [
|
|
2132
|
+
120,
|
|
2133
|
+
248,
|
|
2134
|
+
61,
|
|
2135
|
+
83,
|
|
2136
|
+
31,
|
|
2137
|
+
142,
|
|
2138
|
+
107,
|
|
2139
|
+
144
|
|
2140
|
+
]
|
|
2141
|
+
},
|
|
2142
|
+
{
|
|
2143
|
+
name: "EpochAdvancedEvent",
|
|
2144
|
+
discriminator: [
|
|
2145
|
+
26,
|
|
2146
|
+
197,
|
|
2147
|
+
195,
|
|
2148
|
+
116,
|
|
2149
|
+
126,
|
|
2150
|
+
48,
|
|
2151
|
+
210,
|
|
2152
|
+
42
|
|
2153
|
+
]
|
|
2154
|
+
},
|
|
2155
|
+
{
|
|
2156
|
+
name: "MarketMakerRemovedEvent",
|
|
2157
|
+
discriminator: [
|
|
2158
|
+
238,
|
|
2159
|
+
48,
|
|
2160
|
+
105,
|
|
2161
|
+
84,
|
|
2162
|
+
228,
|
|
2163
|
+
245,
|
|
2164
|
+
204,
|
|
2165
|
+
75
|
|
2166
|
+
]
|
|
2167
|
+
},
|
|
2168
|
+
{
|
|
2169
|
+
name: "NotionalExposureEvent",
|
|
2170
|
+
discriminator: [
|
|
2171
|
+
220,
|
|
2172
|
+
74,
|
|
2173
|
+
165,
|
|
2174
|
+
136,
|
|
2175
|
+
237,
|
|
2176
|
+
183,
|
|
2177
|
+
23,
|
|
2178
|
+
38
|
|
2179
|
+
]
|
|
2180
|
+
},
|
|
2181
|
+
{
|
|
2182
|
+
name: "ParamChangeExecutedEvent",
|
|
2183
|
+
discriminator: [
|
|
2184
|
+
208,
|
|
2185
|
+
23,
|
|
2186
|
+
211,
|
|
2187
|
+
151,
|
|
2188
|
+
8,
|
|
2189
|
+
56,
|
|
2190
|
+
124,
|
|
2191
|
+
26
|
|
2192
|
+
]
|
|
2193
|
+
},
|
|
2194
|
+
{
|
|
2195
|
+
name: "ParamChangeQueuedEvent",
|
|
2196
|
+
discriminator: [
|
|
2197
|
+
44,
|
|
2198
|
+
143,
|
|
2199
|
+
34,
|
|
2200
|
+
222,
|
|
2201
|
+
153,
|
|
2202
|
+
125,
|
|
2203
|
+
73,
|
|
2204
|
+
23
|
|
2205
|
+
]
|
|
2206
|
+
},
|
|
2207
|
+
{
|
|
2208
|
+
name: "PremiumCollectedEvent",
|
|
2209
|
+
discriminator: [
|
|
2210
|
+
76,
|
|
2211
|
+
52,
|
|
2212
|
+
166,
|
|
2213
|
+
111,
|
|
2214
|
+
182,
|
|
2215
|
+
211,
|
|
2216
|
+
215,
|
|
2217
|
+
144
|
|
2218
|
+
]
|
|
2219
|
+
},
|
|
2220
|
+
{
|
|
2221
|
+
name: "SettlementPaidEvent",
|
|
2222
|
+
discriminator: [
|
|
2223
|
+
97,
|
|
2224
|
+
3,
|
|
2225
|
+
234,
|
|
2226
|
+
177,
|
|
2227
|
+
141,
|
|
2228
|
+
83,
|
|
2229
|
+
59,
|
|
2230
|
+
26
|
|
2231
|
+
]
|
|
2232
|
+
},
|
|
2233
|
+
{
|
|
2234
|
+
name: "VaultPausedEvent",
|
|
2235
|
+
discriminator: [
|
|
2236
|
+
75,
|
|
2237
|
+
189,
|
|
2238
|
+
120,
|
|
2239
|
+
167,
|
|
2240
|
+
117,
|
|
2241
|
+
229,
|
|
2242
|
+
155,
|
|
2243
|
+
60
|
|
2244
|
+
]
|
|
2245
|
+
},
|
|
2246
|
+
{
|
|
2247
|
+
name: "WithdrawalProcessedEvent",
|
|
2248
|
+
discriminator: [
|
|
2249
|
+
23,
|
|
2250
|
+
252,
|
|
2251
|
+
30,
|
|
2252
|
+
4,
|
|
2253
|
+
24,
|
|
2254
|
+
110,
|
|
2255
|
+
166,
|
|
2256
|
+
133
|
|
2257
|
+
]
|
|
2258
|
+
},
|
|
2259
|
+
{
|
|
2260
|
+
name: "WithdrawalRequestedEvent",
|
|
2261
|
+
discriminator: [
|
|
2262
|
+
82,
|
|
2263
|
+
227,
|
|
2264
|
+
155,
|
|
2265
|
+
140,
|
|
2266
|
+
223,
|
|
2267
|
+
124,
|
|
2268
|
+
77,
|
|
2269
|
+
243
|
|
2270
|
+
]
|
|
2271
|
+
}
|
|
2272
|
+
],
|
|
2273
|
+
errors: [
|
|
2274
|
+
{
|
|
2275
|
+
code: 6e3,
|
|
2276
|
+
name: "ZeroAmount",
|
|
2277
|
+
msg: "Amount must be greater than zero"
|
|
2278
|
+
},
|
|
2279
|
+
{
|
|
2280
|
+
code: 6001,
|
|
2281
|
+
name: "ZeroShares",
|
|
2282
|
+
msg: "Calculated shares must be greater than zero"
|
|
2283
|
+
},
|
|
2284
|
+
{
|
|
2285
|
+
code: 6002,
|
|
2286
|
+
name: "InsufficientShares",
|
|
2287
|
+
msg: "Insufficient shares"
|
|
2288
|
+
},
|
|
2289
|
+
{
|
|
2290
|
+
code: 6003,
|
|
2291
|
+
name: "AlreadyProcessed",
|
|
2292
|
+
msg: "Withdrawal already processed"
|
|
2293
|
+
},
|
|
2294
|
+
{
|
|
2295
|
+
code: 6004,
|
|
2296
|
+
name: "EpochNotSettled",
|
|
2297
|
+
msg: "Epoch has not settled yet"
|
|
2298
|
+
},
|
|
2299
|
+
{
|
|
2300
|
+
code: 6005,
|
|
2301
|
+
name: "Overflow",
|
|
2302
|
+
msg: "Arithmetic overflow"
|
|
2303
|
+
},
|
|
2304
|
+
{
|
|
2305
|
+
code: 6006,
|
|
2306
|
+
name: "ExceedsUtilizationCap",
|
|
2307
|
+
msg: "Exceeds utilization cap"
|
|
2308
|
+
},
|
|
2309
|
+
{
|
|
2310
|
+
code: 6007,
|
|
2311
|
+
name: "NotWhitelisted",
|
|
2312
|
+
msg: "Recipient is not whitelisted"
|
|
2313
|
+
},
|
|
2314
|
+
{
|
|
2315
|
+
code: 6008,
|
|
2316
|
+
name: "WhitelistFull",
|
|
2317
|
+
msg: "Whitelist is full"
|
|
2318
|
+
},
|
|
2319
|
+
{
|
|
2320
|
+
code: 6009,
|
|
2321
|
+
name: "AlreadyWhitelisted",
|
|
2322
|
+
msg: "Market maker already whitelisted"
|
|
2323
|
+
},
|
|
2324
|
+
{
|
|
2325
|
+
code: 6010,
|
|
2326
|
+
name: "InsufficientLiquidity",
|
|
2327
|
+
msg: "Insufficient liquidity for first deposit"
|
|
2328
|
+
},
|
|
2329
|
+
{
|
|
2330
|
+
code: 6011,
|
|
2331
|
+
name: "EpochTooShort",
|
|
2332
|
+
msg: "Epoch duration too short"
|
|
2333
|
+
},
|
|
2334
|
+
{
|
|
2335
|
+
code: 6012,
|
|
2336
|
+
name: "ExcessivePremium",
|
|
2337
|
+
msg: "Premium exceeds safety limits"
|
|
2338
|
+
},
|
|
2339
|
+
{
|
|
2340
|
+
code: 6013,
|
|
2341
|
+
name: "ExcessiveYield",
|
|
2342
|
+
msg: "Implied yield too high"
|
|
2343
|
+
},
|
|
2344
|
+
{
|
|
2345
|
+
code: 6014,
|
|
2346
|
+
name: "ExcessiveSettlement",
|
|
2347
|
+
msg: "Settlement exceeds epoch premium earned"
|
|
2348
|
+
},
|
|
2349
|
+
{
|
|
2350
|
+
code: 6015,
|
|
2351
|
+
name: "InsufficientVaultBalance",
|
|
2352
|
+
msg: "Insufficient vault balance for withdrawal"
|
|
2353
|
+
},
|
|
2354
|
+
{
|
|
2355
|
+
code: 6016,
|
|
2356
|
+
name: "VaultPaused",
|
|
2357
|
+
msg: "Vault is paused"
|
|
2358
|
+
},
|
|
2359
|
+
{
|
|
2360
|
+
code: 6017,
|
|
2361
|
+
name: "VaultNotEmpty",
|
|
2362
|
+
msg: "Vault must be empty to close"
|
|
2363
|
+
},
|
|
2364
|
+
{
|
|
2365
|
+
code: 6018,
|
|
2366
|
+
name: "InvalidVaultPda",
|
|
2367
|
+
msg: "Invalid vault PDA"
|
|
2368
|
+
},
|
|
2369
|
+
{
|
|
2370
|
+
code: 6019,
|
|
2371
|
+
name: "SlippageExceeded",
|
|
2372
|
+
msg: "Withdrawal amount below minimum expected (slippage protection)"
|
|
2373
|
+
},
|
|
2374
|
+
{
|
|
2375
|
+
code: 6020,
|
|
2376
|
+
name: "DivisionByZero",
|
|
2377
|
+
msg: "Division by zero"
|
|
2378
|
+
},
|
|
2379
|
+
{
|
|
2380
|
+
code: 6021,
|
|
2381
|
+
name: "TimelockNotExpired",
|
|
2382
|
+
msg: "Timelock has not expired yet"
|
|
2383
|
+
},
|
|
2384
|
+
{
|
|
2385
|
+
code: 6022,
|
|
2386
|
+
name: "UseTimelockForParamChange",
|
|
2387
|
+
msg: "Direct param changes deprecated - use queue_param_change"
|
|
2388
|
+
},
|
|
2389
|
+
{
|
|
2390
|
+
code: 6023,
|
|
2391
|
+
name: "InvalidParameter",
|
|
2392
|
+
msg: "Invalid parameter value"
|
|
2393
|
+
},
|
|
2394
|
+
{
|
|
2395
|
+
code: 6024,
|
|
2396
|
+
name: "UnauthorizedForceClose",
|
|
2397
|
+
msg: "Caller is not the vault authority"
|
|
2398
|
+
},
|
|
2399
|
+
{
|
|
2400
|
+
code: 6025,
|
|
2401
|
+
name: "VaultStillExists",
|
|
2402
|
+
msg: "Vault still exists - close it first before cleaning up token accounts"
|
|
2403
|
+
}
|
|
2404
|
+
],
|
|
2405
|
+
types: [
|
|
2406
|
+
{
|
|
2407
|
+
name: "DepositEvent",
|
|
2408
|
+
type: {
|
|
2409
|
+
kind: "struct",
|
|
2410
|
+
fields: [
|
|
2411
|
+
{
|
|
2412
|
+
name: "vault",
|
|
2413
|
+
type: "pubkey"
|
|
2414
|
+
},
|
|
2415
|
+
{
|
|
2416
|
+
name: "user",
|
|
2417
|
+
type: "pubkey"
|
|
2418
|
+
},
|
|
2419
|
+
{
|
|
2420
|
+
name: "amount",
|
|
2421
|
+
type: "u64"
|
|
2422
|
+
},
|
|
2423
|
+
{
|
|
2424
|
+
name: "shares_minted",
|
|
2425
|
+
type: "u64"
|
|
2426
|
+
},
|
|
2427
|
+
{
|
|
2428
|
+
name: "epoch",
|
|
2429
|
+
type: "u64"
|
|
2430
|
+
}
|
|
2431
|
+
]
|
|
2432
|
+
}
|
|
2433
|
+
},
|
|
2434
|
+
{
|
|
2435
|
+
name: "EpochAdvancedEvent",
|
|
2436
|
+
type: {
|
|
2437
|
+
kind: "struct",
|
|
2438
|
+
fields: [
|
|
2439
|
+
{
|
|
2440
|
+
name: "vault",
|
|
2441
|
+
type: "pubkey"
|
|
2442
|
+
},
|
|
2443
|
+
{
|
|
2444
|
+
name: "new_epoch",
|
|
2445
|
+
type: "u64"
|
|
2446
|
+
},
|
|
2447
|
+
{
|
|
2448
|
+
name: "premium_earned",
|
|
2449
|
+
type: "u64"
|
|
2450
|
+
},
|
|
2451
|
+
{
|
|
2452
|
+
name: "notional_exposed",
|
|
2453
|
+
type: "u64"
|
|
2454
|
+
},
|
|
2455
|
+
{
|
|
2456
|
+
name: "avg_premium_bps",
|
|
2457
|
+
type: "u32"
|
|
2458
|
+
},
|
|
2459
|
+
{
|
|
2460
|
+
name: "total_assets",
|
|
2461
|
+
type: "u64"
|
|
2462
|
+
},
|
|
2463
|
+
{
|
|
2464
|
+
name: "total_shares",
|
|
2465
|
+
type: "u64"
|
|
2466
|
+
},
|
|
2467
|
+
{
|
|
2468
|
+
name: "premium_balance_usdc",
|
|
2469
|
+
type: "u64"
|
|
2470
|
+
}
|
|
2471
|
+
]
|
|
2472
|
+
}
|
|
2473
|
+
},
|
|
2474
|
+
{
|
|
2475
|
+
name: "MarketMakerRemovedEvent",
|
|
2476
|
+
docs: [
|
|
2477
|
+
"SECURITY FIX M-4: Event emitted when a market maker is removed"
|
|
2478
|
+
],
|
|
2479
|
+
type: {
|
|
2480
|
+
kind: "struct",
|
|
2481
|
+
fields: [
|
|
2482
|
+
{
|
|
2483
|
+
name: "vault",
|
|
2484
|
+
type: "pubkey"
|
|
2485
|
+
},
|
|
2486
|
+
{
|
|
2487
|
+
name: "market_maker",
|
|
2488
|
+
type: "pubkey"
|
|
2489
|
+
}
|
|
2490
|
+
]
|
|
2491
|
+
}
|
|
2492
|
+
},
|
|
2493
|
+
{
|
|
2494
|
+
name: "NotionalExposureEvent",
|
|
2495
|
+
type: {
|
|
2496
|
+
kind: "struct",
|
|
2497
|
+
fields: [
|
|
2498
|
+
{
|
|
2499
|
+
name: "vault",
|
|
2500
|
+
type: "pubkey"
|
|
2501
|
+
},
|
|
2502
|
+
{
|
|
2503
|
+
name: "epoch",
|
|
2504
|
+
type: "u64"
|
|
2505
|
+
},
|
|
2506
|
+
{
|
|
2507
|
+
name: "notional_tokens",
|
|
2508
|
+
type: "u64"
|
|
2509
|
+
},
|
|
2510
|
+
{
|
|
2511
|
+
name: "premium",
|
|
2512
|
+
type: "u64"
|
|
2513
|
+
},
|
|
2514
|
+
{
|
|
2515
|
+
name: "total_notional_this_epoch",
|
|
2516
|
+
type: "u64"
|
|
2517
|
+
},
|
|
2518
|
+
{
|
|
2519
|
+
name: "total_premium_this_epoch",
|
|
2520
|
+
type: "u64"
|
|
2521
|
+
},
|
|
2522
|
+
{
|
|
2523
|
+
name: "avg_premium_bps",
|
|
2524
|
+
type: "u32"
|
|
2525
|
+
}
|
|
2526
|
+
]
|
|
2527
|
+
}
|
|
2528
|
+
},
|
|
2529
|
+
{
|
|
2530
|
+
name: "ParamChangeExecutedEvent",
|
|
2531
|
+
type: {
|
|
2532
|
+
kind: "struct",
|
|
2533
|
+
fields: [
|
|
2534
|
+
{
|
|
2535
|
+
name: "vault",
|
|
2536
|
+
type: "pubkey"
|
|
2537
|
+
},
|
|
2538
|
+
{
|
|
2539
|
+
name: "new_min_epoch_duration",
|
|
2540
|
+
type: "i64"
|
|
2541
|
+
},
|
|
2542
|
+
{
|
|
2543
|
+
name: "new_utilization_cap_bps",
|
|
2544
|
+
type: "u16"
|
|
2545
|
+
}
|
|
2546
|
+
]
|
|
2547
|
+
}
|
|
2548
|
+
},
|
|
2549
|
+
{
|
|
2550
|
+
name: "ParamChangeQueuedEvent",
|
|
2551
|
+
type: {
|
|
2552
|
+
kind: "struct",
|
|
2553
|
+
fields: [
|
|
2554
|
+
{
|
|
2555
|
+
name: "vault",
|
|
2556
|
+
type: "pubkey"
|
|
2557
|
+
},
|
|
2558
|
+
{
|
|
2559
|
+
name: "new_min_epoch_duration",
|
|
2560
|
+
type: {
|
|
2561
|
+
option: "i64"
|
|
2562
|
+
}
|
|
2563
|
+
},
|
|
2564
|
+
{
|
|
2565
|
+
name: "new_utilization_cap_bps",
|
|
2566
|
+
type: {
|
|
2567
|
+
option: "u16"
|
|
2568
|
+
}
|
|
2569
|
+
},
|
|
2570
|
+
{
|
|
2571
|
+
name: "unlock_time",
|
|
2572
|
+
type: "i64"
|
|
2573
|
+
}
|
|
2574
|
+
]
|
|
2575
|
+
}
|
|
2576
|
+
},
|
|
2577
|
+
{
|
|
2578
|
+
name: "PremiumCollectedEvent",
|
|
2579
|
+
type: {
|
|
2580
|
+
kind: "struct",
|
|
2581
|
+
fields: [
|
|
2582
|
+
{
|
|
2583
|
+
name: "vault",
|
|
2584
|
+
type: "pubkey"
|
|
2585
|
+
},
|
|
2586
|
+
{
|
|
2587
|
+
name: "payer",
|
|
2588
|
+
type: "pubkey"
|
|
2589
|
+
},
|
|
2590
|
+
{
|
|
2591
|
+
name: "amount",
|
|
2592
|
+
type: "u64"
|
|
2593
|
+
},
|
|
2594
|
+
{
|
|
2595
|
+
name: "epoch",
|
|
2596
|
+
type: "u64"
|
|
2597
|
+
}
|
|
2598
|
+
]
|
|
2599
|
+
}
|
|
2600
|
+
},
|
|
2601
|
+
{
|
|
2602
|
+
name: "SettlementPaidEvent",
|
|
2603
|
+
type: {
|
|
2604
|
+
kind: "struct",
|
|
2605
|
+
fields: [
|
|
2606
|
+
{
|
|
2607
|
+
name: "vault",
|
|
2608
|
+
type: "pubkey"
|
|
2609
|
+
},
|
|
2610
|
+
{
|
|
2611
|
+
name: "recipient",
|
|
2612
|
+
type: "pubkey"
|
|
2613
|
+
},
|
|
2614
|
+
{
|
|
2615
|
+
name: "amount",
|
|
2616
|
+
type: "u64"
|
|
2617
|
+
},
|
|
2618
|
+
{
|
|
2619
|
+
name: "epoch",
|
|
2620
|
+
type: "u64"
|
|
2621
|
+
}
|
|
2622
|
+
]
|
|
2623
|
+
}
|
|
2624
|
+
},
|
|
2625
|
+
{
|
|
2626
|
+
name: "Vault",
|
|
2627
|
+
type: {
|
|
2628
|
+
kind: "struct",
|
|
2629
|
+
fields: [
|
|
2630
|
+
{
|
|
2631
|
+
name: "authority",
|
|
2632
|
+
type: "pubkey"
|
|
2633
|
+
},
|
|
2634
|
+
{
|
|
2635
|
+
name: "asset_id",
|
|
2636
|
+
type: "string"
|
|
2637
|
+
},
|
|
2638
|
+
{
|
|
2639
|
+
name: "underlying_mint",
|
|
2640
|
+
type: "pubkey"
|
|
2641
|
+
},
|
|
2642
|
+
{
|
|
2643
|
+
name: "share_mint",
|
|
2644
|
+
type: "pubkey"
|
|
2645
|
+
},
|
|
2646
|
+
{
|
|
2647
|
+
name: "vault_token_account",
|
|
2648
|
+
type: "pubkey"
|
|
2649
|
+
},
|
|
2650
|
+
{
|
|
2651
|
+
name: "premium_mint",
|
|
2652
|
+
type: "pubkey"
|
|
2653
|
+
},
|
|
2654
|
+
{
|
|
2655
|
+
name: "premium_token_account",
|
|
2656
|
+
type: "pubkey"
|
|
2657
|
+
},
|
|
2658
|
+
{
|
|
2659
|
+
name: "share_escrow",
|
|
2660
|
+
type: "pubkey"
|
|
2661
|
+
},
|
|
2662
|
+
{
|
|
2663
|
+
name: "total_assets",
|
|
2664
|
+
type: "u64"
|
|
2665
|
+
},
|
|
2666
|
+
{
|
|
2667
|
+
name: "total_shares",
|
|
2668
|
+
type: "u64"
|
|
2669
|
+
},
|
|
2670
|
+
{
|
|
2671
|
+
name: "virtual_offset",
|
|
2672
|
+
docs: [
|
|
2673
|
+
"Virtual offset for share calculations (prevents first-depositor attacks)",
|
|
2674
|
+
"effective_shares = total_shares + virtual_offset"
|
|
2675
|
+
],
|
|
2676
|
+
type: "u64"
|
|
2677
|
+
},
|
|
2678
|
+
{
|
|
2679
|
+
name: "epoch",
|
|
2680
|
+
type: "u64"
|
|
2681
|
+
},
|
|
2682
|
+
{
|
|
2683
|
+
name: "utilization_cap_bps",
|
|
2684
|
+
type: "u16"
|
|
2685
|
+
},
|
|
2686
|
+
{
|
|
2687
|
+
name: "min_epoch_duration",
|
|
2688
|
+
type: "i64"
|
|
2689
|
+
},
|
|
2690
|
+
{
|
|
2691
|
+
name: "last_roll_timestamp",
|
|
2692
|
+
type: "i64"
|
|
2693
|
+
},
|
|
2694
|
+
{
|
|
2695
|
+
name: "pending_withdrawals",
|
|
2696
|
+
type: "u64"
|
|
2697
|
+
},
|
|
2698
|
+
{
|
|
2699
|
+
name: "epoch_notional_exposed",
|
|
2700
|
+
type: "u64"
|
|
2701
|
+
},
|
|
2702
|
+
{
|
|
2703
|
+
name: "epoch_premium_earned",
|
|
2704
|
+
type: "u64"
|
|
2705
|
+
},
|
|
2706
|
+
{
|
|
2707
|
+
name: "epoch_premium_per_token_bps",
|
|
2708
|
+
type: "u32"
|
|
2709
|
+
},
|
|
2710
|
+
{
|
|
2711
|
+
name: "premium_balance_usdc",
|
|
2712
|
+
docs: [
|
|
2713
|
+
"Accumulated USDC premium balance (separate from underlying TVL)"
|
|
2714
|
+
],
|
|
2715
|
+
type: "u64"
|
|
2716
|
+
},
|
|
2717
|
+
{
|
|
2718
|
+
name: "is_paused",
|
|
2719
|
+
docs: [
|
|
2720
|
+
"SECURITY: Emergency pause flag"
|
|
2721
|
+
],
|
|
2722
|
+
type: "bool"
|
|
2723
|
+
},
|
|
2724
|
+
{
|
|
2725
|
+
name: "pending_min_epoch_duration",
|
|
2726
|
+
docs: [
|
|
2727
|
+
"SECURITY FIX M-3: Timelock for parameter changes"
|
|
2728
|
+
],
|
|
2729
|
+
type: "i64"
|
|
2730
|
+
},
|
|
2731
|
+
{
|
|
2732
|
+
name: "pending_utilization_cap",
|
|
2733
|
+
type: "u16"
|
|
2734
|
+
},
|
|
2735
|
+
{
|
|
2736
|
+
name: "param_change_unlock_time",
|
|
2737
|
+
type: "i64"
|
|
2738
|
+
},
|
|
2739
|
+
{
|
|
2740
|
+
name: "bump",
|
|
2741
|
+
type: "u8"
|
|
2742
|
+
}
|
|
2743
|
+
]
|
|
2744
|
+
}
|
|
2745
|
+
},
|
|
2746
|
+
{
|
|
2747
|
+
name: "VaultPausedEvent",
|
|
2748
|
+
type: {
|
|
2749
|
+
kind: "struct",
|
|
2750
|
+
fields: [
|
|
2751
|
+
{
|
|
2752
|
+
name: "vault",
|
|
2753
|
+
type: "pubkey"
|
|
2754
|
+
},
|
|
2755
|
+
{
|
|
2756
|
+
name: "paused",
|
|
2757
|
+
type: "bool"
|
|
2758
|
+
},
|
|
2759
|
+
{
|
|
2760
|
+
name: "timestamp",
|
|
2761
|
+
type: "i64"
|
|
2762
|
+
}
|
|
2763
|
+
]
|
|
2764
|
+
}
|
|
2765
|
+
},
|
|
2766
|
+
{
|
|
2767
|
+
name: "VaultWhitelist",
|
|
2768
|
+
type: {
|
|
2769
|
+
kind: "struct",
|
|
2770
|
+
fields: [
|
|
2771
|
+
{
|
|
2772
|
+
name: "authority",
|
|
2773
|
+
type: "pubkey"
|
|
2774
|
+
},
|
|
2775
|
+
{
|
|
2776
|
+
name: "vault",
|
|
2777
|
+
type: "pubkey"
|
|
2778
|
+
},
|
|
2779
|
+
{
|
|
2780
|
+
name: "market_makers",
|
|
2781
|
+
type: {
|
|
2782
|
+
vec: "pubkey"
|
|
2783
|
+
}
|
|
2784
|
+
},
|
|
2785
|
+
{
|
|
2786
|
+
name: "bump",
|
|
2787
|
+
type: "u8"
|
|
2788
|
+
}
|
|
2789
|
+
]
|
|
2790
|
+
}
|
|
2791
|
+
},
|
|
2792
|
+
{
|
|
2793
|
+
name: "WithdrawalProcessedEvent",
|
|
2794
|
+
type: {
|
|
2795
|
+
kind: "struct",
|
|
2796
|
+
fields: [
|
|
2797
|
+
{
|
|
2798
|
+
name: "vault",
|
|
2799
|
+
type: "pubkey"
|
|
2800
|
+
},
|
|
2801
|
+
{
|
|
2802
|
+
name: "user",
|
|
2803
|
+
type: "pubkey"
|
|
2804
|
+
},
|
|
2805
|
+
{
|
|
2806
|
+
name: "shares",
|
|
2807
|
+
type: "u64"
|
|
2808
|
+
},
|
|
2809
|
+
{
|
|
2810
|
+
name: "amount",
|
|
2811
|
+
type: "u64"
|
|
2812
|
+
},
|
|
2813
|
+
{
|
|
2814
|
+
name: "epoch",
|
|
2815
|
+
type: "u64"
|
|
2816
|
+
}
|
|
2817
|
+
]
|
|
2818
|
+
}
|
|
2819
|
+
},
|
|
2820
|
+
{
|
|
2821
|
+
name: "WithdrawalRequest",
|
|
2822
|
+
type: {
|
|
2823
|
+
kind: "struct",
|
|
2824
|
+
fields: [
|
|
2825
|
+
{
|
|
2826
|
+
name: "user",
|
|
2827
|
+
type: "pubkey"
|
|
2828
|
+
},
|
|
2829
|
+
{
|
|
2830
|
+
name: "vault",
|
|
2831
|
+
type: "pubkey"
|
|
2832
|
+
},
|
|
2833
|
+
{
|
|
2834
|
+
name: "shares",
|
|
2835
|
+
type: "u64"
|
|
2836
|
+
},
|
|
2837
|
+
{
|
|
2838
|
+
name: "request_epoch",
|
|
2839
|
+
type: "u64"
|
|
2840
|
+
},
|
|
2841
|
+
{
|
|
2842
|
+
name: "processed",
|
|
2843
|
+
type: "bool"
|
|
2844
|
+
}
|
|
2845
|
+
]
|
|
2846
|
+
}
|
|
2847
|
+
},
|
|
2848
|
+
{
|
|
2849
|
+
name: "WithdrawalRequestedEvent",
|
|
2850
|
+
type: {
|
|
2851
|
+
kind: "struct",
|
|
2852
|
+
fields: [
|
|
2853
|
+
{
|
|
2854
|
+
name: "vault",
|
|
2855
|
+
type: "pubkey"
|
|
2856
|
+
},
|
|
2857
|
+
{
|
|
2858
|
+
name: "user",
|
|
2859
|
+
type: "pubkey"
|
|
2860
|
+
},
|
|
2861
|
+
{
|
|
2862
|
+
name: "shares",
|
|
2863
|
+
type: "u64"
|
|
2864
|
+
},
|
|
2865
|
+
{
|
|
2866
|
+
name: "epoch",
|
|
2867
|
+
type: "u64"
|
|
2868
|
+
}
|
|
2869
|
+
]
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
]
|
|
2873
|
+
};
|
|
2874
|
+
|
|
2875
|
+
// src/client/VaultInstructions.ts
|
|
2876
|
+
var TOKEN_PROGRAM_ID = new import_web33.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
|
|
2877
|
+
var VaultInstructions = class {
|
|
2878
|
+
connection;
|
|
2879
|
+
program = null;
|
|
2880
|
+
idl;
|
|
2881
|
+
/**
|
|
2882
|
+
* Create a new VaultInstructions client
|
|
2883
|
+
*
|
|
2884
|
+
* @param connection - Solana connection
|
|
2885
|
+
* @param idl - Optional IDL (uses bundled vault IDL by default)
|
|
2886
|
+
*/
|
|
2887
|
+
constructor(connection, idl) {
|
|
2888
|
+
this.connection = connection;
|
|
2889
|
+
this.idl = idl || vault_default;
|
|
2890
|
+
}
|
|
2891
|
+
/**
|
|
2892
|
+
* Initialize the Anchor program interface
|
|
2893
|
+
*
|
|
2894
|
+
* @param wallet - Optional wallet for signing (not required for instruction building)
|
|
2895
|
+
*/
|
|
2896
|
+
async initialize(wallet) {
|
|
2897
|
+
const provider = new anchor.AnchorProvider(
|
|
2898
|
+
this.connection,
|
|
2899
|
+
wallet || {},
|
|
2900
|
+
{ commitment: "confirmed" }
|
|
2901
|
+
);
|
|
2902
|
+
this.program = new anchor.Program(this.idl, VAULT_PROGRAM_ID, provider);
|
|
2903
|
+
}
|
|
2904
|
+
/**
|
|
2905
|
+
* Set the program IDL
|
|
2906
|
+
*
|
|
2907
|
+
* @param idl - Vault program IDL
|
|
2908
|
+
*/
|
|
2909
|
+
setIDL(idl) {
|
|
2910
|
+
this.idl = idl;
|
|
2911
|
+
}
|
|
2912
|
+
/**
|
|
2913
|
+
* Check if the client is initialized
|
|
2914
|
+
*/
|
|
2915
|
+
get isInitialized() {
|
|
2916
|
+
return this.program !== null;
|
|
2917
|
+
}
|
|
2918
|
+
/**
|
|
2919
|
+
* Fetch vault account data
|
|
2920
|
+
*
|
|
2921
|
+
* @param assetId - Asset identifier (e.g., "NVDAX")
|
|
2922
|
+
* @returns Vault data or null if not found
|
|
2923
|
+
*/
|
|
2924
|
+
async fetchVault(assetId) {
|
|
2925
|
+
if (!this.program) {
|
|
2926
|
+
throw new Error("Client not initialized. Call initialize() first.");
|
|
2927
|
+
}
|
|
2928
|
+
try {
|
|
2929
|
+
const [vaultPda] = deriveVaultPda(assetId);
|
|
2930
|
+
const vault = await this.program.account.vault.fetch(vaultPda);
|
|
2931
|
+
return {
|
|
2932
|
+
authority: vault.authority,
|
|
2933
|
+
assetId: vault.assetId,
|
|
2934
|
+
underlyingMint: vault.underlyingMint,
|
|
2935
|
+
shareMint: vault.shareMint,
|
|
2936
|
+
vaultTokenAccount: vault.vaultTokenAccount,
|
|
2937
|
+
premiumMint: vault.premiumMint,
|
|
2938
|
+
premiumTokenAccount: vault.premiumTokenAccount,
|
|
2939
|
+
shareEscrow: vault.shareEscrow,
|
|
2940
|
+
totalAssets: BigInt(vault.totalAssets.toString()),
|
|
2941
|
+
totalShares: BigInt(vault.totalShares.toString()),
|
|
2942
|
+
virtualOffset: BigInt(vault.virtualOffset.toString()),
|
|
2943
|
+
epoch: BigInt(vault.epoch.toString()),
|
|
2944
|
+
utilizationCapBps: vault.utilizationCapBps,
|
|
2945
|
+
minEpochDuration: BigInt(vault.minEpochDuration.toString()),
|
|
2946
|
+
lastRollTimestamp: BigInt(vault.lastRollTimestamp.toString()),
|
|
2947
|
+
pendingWithdrawals: BigInt(vault.pendingWithdrawals.toString()),
|
|
2948
|
+
epochNotionalExposed: BigInt(vault.epochNotionalExposed.toString()),
|
|
2949
|
+
epochPremiumEarned: BigInt(vault.epochPremiumEarned.toString()),
|
|
2950
|
+
epochPremiumPerTokenBps: vault.epochPremiumPerTokenBps,
|
|
2951
|
+
isPaused: vault.isPaused,
|
|
2952
|
+
bump: vault.bump
|
|
2953
|
+
};
|
|
2954
|
+
} catch (error) {
|
|
2955
|
+
if (error.message?.includes("Account does not exist")) {
|
|
2956
|
+
return null;
|
|
2957
|
+
}
|
|
2958
|
+
throw error;
|
|
2959
|
+
}
|
|
2960
|
+
}
|
|
2961
|
+
/**
|
|
2962
|
+
* Build instruction to record notional exposure after RFQ execution
|
|
2963
|
+
*
|
|
2964
|
+
* @param params - Exposure parameters
|
|
2965
|
+
* @returns TransactionInstruction
|
|
2966
|
+
*/
|
|
2967
|
+
async recordNotionalExposure(params) {
|
|
2968
|
+
if (!this.program) {
|
|
2969
|
+
throw new Error("Client not initialized. Call initialize() first.");
|
|
2970
|
+
}
|
|
2971
|
+
return await this.program.methods.recordNotionalExposure(
|
|
2972
|
+
new anchor.BN(params.notionalTokens.toString()),
|
|
2973
|
+
new anchor.BN(params.premium.toString())
|
|
2974
|
+
).accounts({
|
|
2975
|
+
vault: params.vault,
|
|
2976
|
+
authority: params.authority
|
|
2977
|
+
}).instruction();
|
|
2978
|
+
}
|
|
2979
|
+
/**
|
|
2980
|
+
* Build instruction to collect premium from market maker
|
|
2981
|
+
*
|
|
2982
|
+
* @param params - Collection parameters
|
|
2983
|
+
* @returns TransactionInstruction
|
|
2984
|
+
*/
|
|
2985
|
+
async collectPremium(params) {
|
|
2986
|
+
if (!this.program) {
|
|
2987
|
+
throw new Error("Client not initialized. Call initialize() first.");
|
|
2988
|
+
}
|
|
2989
|
+
const vault = await this.program.account.vault.fetch(params.vault);
|
|
2990
|
+
return await this.program.methods.collectPremium(new anchor.BN(params.amount.toString())).accounts({
|
|
2991
|
+
vault: params.vault,
|
|
2992
|
+
vaultPremiumAccount: vault.premiumTokenAccount,
|
|
2993
|
+
payerTokenAccount: params.payerTokenAccount,
|
|
2994
|
+
payer: params.authority,
|
|
2995
|
+
// Payer is typically the authority
|
|
2996
|
+
authority: params.authority,
|
|
2997
|
+
tokenProgram: TOKEN_PROGRAM_ID
|
|
2998
|
+
}).instruction();
|
|
2999
|
+
}
|
|
3000
|
+
/**
|
|
3001
|
+
* Build instruction to pay settlement to market maker
|
|
3002
|
+
*
|
|
3003
|
+
* @param params - Settlement parameters
|
|
3004
|
+
* @returns TransactionInstruction
|
|
3005
|
+
*/
|
|
3006
|
+
async paySettlement(params) {
|
|
3007
|
+
if (!this.program) {
|
|
3008
|
+
throw new Error("Client not initialized. Call initialize() first.");
|
|
3009
|
+
}
|
|
3010
|
+
const vault = await this.program.account.vault.fetch(params.vault);
|
|
3011
|
+
return await this.program.methods.paySettlement(new anchor.BN(params.amount.toString())).accounts({
|
|
3012
|
+
vault: params.vault,
|
|
3013
|
+
vaultPremiumAccount: vault.premiumTokenAccount,
|
|
3014
|
+
recipientTokenAccount: params.recipientTokenAccount,
|
|
3015
|
+
recipient: params.recipient,
|
|
3016
|
+
authority: params.authority,
|
|
3017
|
+
tokenProgram: TOKEN_PROGRAM_ID
|
|
3018
|
+
}).instruction();
|
|
3019
|
+
}
|
|
3020
|
+
/**
|
|
3021
|
+
* Build instruction to advance epoch
|
|
3022
|
+
*
|
|
3023
|
+
* @param params - Advance epoch parameters
|
|
3024
|
+
* @returns TransactionInstruction
|
|
3025
|
+
*/
|
|
3026
|
+
async advanceEpoch(params) {
|
|
3027
|
+
if (!this.program) {
|
|
3028
|
+
throw new Error("Client not initialized. Call initialize() first.");
|
|
3029
|
+
}
|
|
3030
|
+
return await this.program.methods.advanceEpoch(new anchor.BN(params.premiumEarned.toString())).accounts({
|
|
3031
|
+
vault: params.vault,
|
|
3032
|
+
authority: params.authority
|
|
3033
|
+
}).instruction();
|
|
3034
|
+
}
|
|
3035
|
+
/**
|
|
3036
|
+
* Calculate share price from vault data
|
|
3037
|
+
*
|
|
3038
|
+
* @param vault - Vault data
|
|
3039
|
+
* @param decimals - Token decimals (default: 6)
|
|
3040
|
+
* @returns Share price as a number
|
|
3041
|
+
*/
|
|
3042
|
+
static calculateSharePrice(vault, decimals = 6) {
|
|
3043
|
+
if (vault.totalShares === 0n) {
|
|
3044
|
+
return 1;
|
|
3045
|
+
}
|
|
3046
|
+
const totalAssets = Number(vault.totalAssets) / 10 ** decimals;
|
|
3047
|
+
const totalShares = Number(vault.totalShares) / 10 ** decimals;
|
|
3048
|
+
const virtualOffset = Number(vault.virtualOffset) / 10 ** decimals;
|
|
3049
|
+
return (totalAssets + virtualOffset) / totalShares;
|
|
3050
|
+
}
|
|
3051
|
+
/**
|
|
3052
|
+
* Calculate utilization percentage from vault data
|
|
3053
|
+
*
|
|
3054
|
+
* @param vault - Vault data
|
|
3055
|
+
* @returns Utilization as decimal (0-1)
|
|
3056
|
+
*/
|
|
3057
|
+
static calculateUtilization(vault) {
|
|
3058
|
+
if (vault.totalAssets === 0n) {
|
|
3059
|
+
return 0;
|
|
3060
|
+
}
|
|
3061
|
+
return Number(vault.epochNotionalExposed) / Number(vault.totalAssets);
|
|
3062
|
+
}
|
|
3063
|
+
/**
|
|
3064
|
+
* Check if vault can accept more exposure
|
|
3065
|
+
*
|
|
3066
|
+
* @param vault - Vault data
|
|
3067
|
+
* @param additionalNotional - Additional notional to expose
|
|
3068
|
+
* @returns Whether the vault can accept the exposure
|
|
3069
|
+
*/
|
|
3070
|
+
static canAcceptExposure(vault, additionalNotional) {
|
|
3071
|
+
const maxExposure = vault.totalAssets * BigInt(vault.utilizationCapBps) / 10000n;
|
|
3072
|
+
const newExposure = vault.epochNotionalExposed + additionalNotional;
|
|
3073
|
+
return newExposure <= maxExposure;
|
|
3074
|
+
}
|
|
3075
|
+
/**
|
|
3076
|
+
* Calculate remaining capacity for option writing
|
|
3077
|
+
*
|
|
3078
|
+
* @param vault - Vault data
|
|
3079
|
+
* @returns Remaining notional capacity
|
|
3080
|
+
*/
|
|
3081
|
+
static getRemainingCapacity(vault) {
|
|
3082
|
+
const maxExposure = vault.totalAssets * BigInt(vault.utilizationCapBps) / 10000n;
|
|
3083
|
+
const remaining = maxExposure - vault.epochNotionalExposed;
|
|
3084
|
+
return remaining > 0n ? remaining : 0n;
|
|
3085
|
+
}
|
|
3086
|
+
};
|
|
3087
|
+
|
|
3088
|
+
// src/utils/pricing.ts
|
|
3089
|
+
var OptionPricing = class {
|
|
3090
|
+
/**
|
|
3091
|
+
* Calculate option prices using Black-Scholes formula
|
|
3092
|
+
*
|
|
3093
|
+
* @param params - Pricing parameters
|
|
3094
|
+
* @returns Call and put prices with deltas
|
|
3095
|
+
*/
|
|
3096
|
+
static blackScholes(params) {
|
|
3097
|
+
const { spot, strike, timeToExpiry, riskFreeRate, volatility } = params;
|
|
3098
|
+
if (timeToExpiry <= 0) {
|
|
3099
|
+
const intrinsicCall = Math.max(0, spot - strike);
|
|
3100
|
+
const intrinsicPut = Math.max(0, strike - spot);
|
|
3101
|
+
return {
|
|
3102
|
+
call: intrinsicCall,
|
|
3103
|
+
put: intrinsicPut,
|
|
3104
|
+
delta: {
|
|
3105
|
+
call: intrinsicCall > 0 ? 1 : 0,
|
|
3106
|
+
put: intrinsicPut > 0 ? -1 : 0
|
|
3107
|
+
}
|
|
3108
|
+
};
|
|
3109
|
+
}
|
|
3110
|
+
if (volatility <= 0) {
|
|
3111
|
+
throw new Error("Volatility must be positive");
|
|
3112
|
+
}
|
|
3113
|
+
const sqrtT = Math.sqrt(timeToExpiry);
|
|
3114
|
+
const d1 = (Math.log(spot / strike) + (riskFreeRate + 0.5 * volatility * volatility) * timeToExpiry) / (volatility * sqrtT);
|
|
3115
|
+
const d2 = d1 - volatility * sqrtT;
|
|
3116
|
+
const callPrice = spot * this.normalCDF(d1) - strike * Math.exp(-riskFreeRate * timeToExpiry) * this.normalCDF(d2);
|
|
3117
|
+
const putPrice = strike * Math.exp(-riskFreeRate * timeToExpiry) * this.normalCDF(-d2) - spot * this.normalCDF(-d1);
|
|
3118
|
+
const callDelta = this.normalCDF(d1);
|
|
3119
|
+
const putDelta = callDelta - 1;
|
|
3120
|
+
return {
|
|
3121
|
+
call: Math.max(0, callPrice),
|
|
3122
|
+
put: Math.max(0, putPrice),
|
|
3123
|
+
delta: { call: callDelta, put: putDelta }
|
|
3124
|
+
};
|
|
3125
|
+
}
|
|
3126
|
+
/**
|
|
3127
|
+
* Calculate covered call premium
|
|
3128
|
+
*
|
|
3129
|
+
* @param params - Premium calculation parameters
|
|
3130
|
+
* @returns Premium in same units as spot price
|
|
3131
|
+
*/
|
|
3132
|
+
static calculateCoveredCallPremium(params) {
|
|
3133
|
+
const {
|
|
3134
|
+
spot,
|
|
3135
|
+
strikePercent,
|
|
3136
|
+
daysToExpiry,
|
|
3137
|
+
volatility,
|
|
3138
|
+
riskFreeRate = DEFAULT_PRICING_PARAMS.riskFreeRate
|
|
3139
|
+
} = params;
|
|
3140
|
+
const strike = spot * strikePercent;
|
|
3141
|
+
const timeToExpiry = daysToExpiry / 365;
|
|
3142
|
+
const prices = this.blackScholes({
|
|
3143
|
+
spot,
|
|
3144
|
+
strike,
|
|
3145
|
+
timeToExpiry,
|
|
3146
|
+
riskFreeRate,
|
|
3147
|
+
volatility
|
|
3148
|
+
});
|
|
3149
|
+
return prices.call;
|
|
3150
|
+
}
|
|
3151
|
+
/**
|
|
3152
|
+
* Calculate premium as basis points of notional
|
|
3153
|
+
*
|
|
3154
|
+
* @param premium - Premium amount
|
|
3155
|
+
* @param spot - Spot price
|
|
3156
|
+
* @returns Premium in basis points
|
|
3157
|
+
*/
|
|
3158
|
+
static premiumToBps(premium, spot) {
|
|
3159
|
+
return Math.round(premium / spot * 1e4);
|
|
3160
|
+
}
|
|
3161
|
+
/**
|
|
3162
|
+
* Convert basis points to premium
|
|
3163
|
+
*
|
|
3164
|
+
* @param bps - Basis points
|
|
3165
|
+
* @param spot - Spot price
|
|
3166
|
+
* @returns Premium amount
|
|
3167
|
+
*/
|
|
3168
|
+
static bpsToPremium(bps, spot) {
|
|
3169
|
+
return bps / 1e4 * spot;
|
|
3170
|
+
}
|
|
3171
|
+
/**
|
|
3172
|
+
* Calculate time to expiry in years
|
|
3173
|
+
*
|
|
3174
|
+
* @param expiryTimestamp - Expiry Unix timestamp (seconds)
|
|
3175
|
+
* @returns Time in years
|
|
3176
|
+
*/
|
|
3177
|
+
static timeToExpiry(expiryTimestamp) {
|
|
3178
|
+
const now = Date.now() / 1e3;
|
|
3179
|
+
const secondsToExpiry = expiryTimestamp - now;
|
|
3180
|
+
return secondsToExpiry / (365.25 * 24 * 60 * 60);
|
|
3181
|
+
}
|
|
3182
|
+
/**
|
|
3183
|
+
* Suggest a strike price based on delta target
|
|
3184
|
+
*
|
|
3185
|
+
* @param spotPrice - Current spot price
|
|
3186
|
+
* @param deltaBps - Delta in basis points (e.g., 1000 = 10% OTM)
|
|
3187
|
+
* @param optionType - 'call' or 'put'
|
|
3188
|
+
* @returns Suggested strike price
|
|
3189
|
+
*/
|
|
3190
|
+
static suggestStrike(spotPrice, deltaBps, optionType = "call") {
|
|
3191
|
+
const multiplier = optionType === "call" ? 1 : -1;
|
|
3192
|
+
return spotPrice * (1 + multiplier * deltaBps / 1e4);
|
|
3193
|
+
}
|
|
3194
|
+
/**
|
|
3195
|
+
* Validate a quote against fair value
|
|
3196
|
+
*
|
|
3197
|
+
* @param quotePremium - Premium from quote
|
|
3198
|
+
* @param fairValue - Calculated fair value
|
|
3199
|
+
* @param maxDeviationBps - Maximum acceptable deviation in bps (default: 500)
|
|
3200
|
+
* @returns Validation result
|
|
3201
|
+
*/
|
|
3202
|
+
static validateQuote(quotePremium, fairValue, maxDeviationBps = DEFAULT_PRICING_PARAMS.maxQuoteDeviationBps) {
|
|
3203
|
+
if (fairValue <= 0) {
|
|
3204
|
+
return {
|
|
3205
|
+
isValid: false,
|
|
3206
|
+
reason: "Fair value must be positive",
|
|
3207
|
+
fairValue
|
|
3208
|
+
};
|
|
3209
|
+
}
|
|
3210
|
+
const deviation = Math.abs(quotePremium - fairValue) / fairValue;
|
|
3211
|
+
const deviationBps = Math.round(deviation * 1e4);
|
|
3212
|
+
const maxDeviation = maxDeviationBps / 1e4;
|
|
3213
|
+
if (deviation > maxDeviation) {
|
|
3214
|
+
return {
|
|
3215
|
+
isValid: false,
|
|
3216
|
+
reason: `Quote deviates ${deviationBps} bps from fair value (max: ${maxDeviationBps} bps)`,
|
|
3217
|
+
fairValue,
|
|
3218
|
+
deviationBps
|
|
3219
|
+
};
|
|
3220
|
+
}
|
|
3221
|
+
return {
|
|
3222
|
+
isValid: true,
|
|
3223
|
+
fairValue,
|
|
3224
|
+
deviationBps
|
|
3225
|
+
};
|
|
3226
|
+
}
|
|
3227
|
+
/**
|
|
3228
|
+
* Calculate historical volatility from price data
|
|
3229
|
+
*
|
|
3230
|
+
* @param prices - Array of closing prices (oldest first)
|
|
3231
|
+
* @param tradingDaysPerYear - Trading days for annualization (default: 252)
|
|
3232
|
+
* @returns Annualized volatility
|
|
3233
|
+
*/
|
|
3234
|
+
static calculateHistoricalVolatility(prices, tradingDaysPerYear = DEFAULT_PRICING_PARAMS.tradingDaysPerYear) {
|
|
3235
|
+
if (prices.length < 2) {
|
|
3236
|
+
throw new Error("Need at least 2 prices to calculate volatility");
|
|
3237
|
+
}
|
|
3238
|
+
const logReturns = [];
|
|
3239
|
+
for (let i = 1; i < prices.length; i++) {
|
|
3240
|
+
const logReturn = Math.log(prices[i] / prices[i - 1]);
|
|
3241
|
+
logReturns.push(logReturn);
|
|
3242
|
+
}
|
|
3243
|
+
const mean = logReturns.reduce((sum, r) => sum + r, 0) / logReturns.length;
|
|
3244
|
+
const variance = logReturns.reduce((sum, r) => sum + Math.pow(r - mean, 2), 0) / (logReturns.length - 1);
|
|
3245
|
+
const dailyStdDev = Math.sqrt(variance);
|
|
3246
|
+
return dailyStdDev * Math.sqrt(tradingDaysPerYear);
|
|
3247
|
+
}
|
|
3248
|
+
/**
|
|
3249
|
+
* Calculate implied volatility from option price using Newton-Raphson
|
|
3250
|
+
*
|
|
3251
|
+
* @param optionPrice - Market price of option
|
|
3252
|
+
* @param spot - Spot price
|
|
3253
|
+
* @param strike - Strike price
|
|
3254
|
+
* @param timeToExpiry - Time to expiry in years
|
|
3255
|
+
* @param riskFreeRate - Risk-free rate
|
|
3256
|
+
* @param optionType - 'call' or 'put'
|
|
3257
|
+
* @param maxIterations - Maximum iterations (default: 100)
|
|
3258
|
+
* @returns Implied volatility
|
|
3259
|
+
*/
|
|
3260
|
+
static calculateImpliedVolatility(optionPrice, spot, strike, timeToExpiry, riskFreeRate, optionType, maxIterations = 100) {
|
|
3261
|
+
let sigma = Math.sqrt(2 * Math.PI / timeToExpiry) * (optionPrice / spot);
|
|
3262
|
+
const tolerance = 1e-6;
|
|
3263
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
3264
|
+
const prices = this.blackScholes({
|
|
3265
|
+
spot,
|
|
3266
|
+
strike,
|
|
3267
|
+
timeToExpiry,
|
|
3268
|
+
riskFreeRate,
|
|
3269
|
+
volatility: sigma
|
|
3270
|
+
});
|
|
3271
|
+
const price = optionType === "call" ? prices.call : prices.put;
|
|
3272
|
+
const diff = price - optionPrice;
|
|
3273
|
+
if (Math.abs(diff) < tolerance) {
|
|
3274
|
+
return sigma;
|
|
3275
|
+
}
|
|
3276
|
+
const sqrtT = Math.sqrt(timeToExpiry);
|
|
3277
|
+
const d1 = (Math.log(spot / strike) + (riskFreeRate + 0.5 * sigma * sigma) * timeToExpiry) / (sigma * sqrtT);
|
|
3278
|
+
const vega = spot * sqrtT * this.normalPDF(d1);
|
|
3279
|
+
if (vega < 1e-10) {
|
|
3280
|
+
throw new Error("Implied volatility calculation failed: vega too small");
|
|
3281
|
+
}
|
|
3282
|
+
sigma = sigma - diff / vega;
|
|
3283
|
+
sigma = Math.max(0.01, Math.min(5, sigma));
|
|
3284
|
+
}
|
|
3285
|
+
throw new Error("Implied volatility calculation did not converge");
|
|
3286
|
+
}
|
|
3287
|
+
// ============================================================================
|
|
3288
|
+
// Private Helper Functions
|
|
3289
|
+
// ============================================================================
|
|
3290
|
+
/**
|
|
3291
|
+
* Standard normal CDF using Abramowitz & Stegun approximation
|
|
3292
|
+
*/
|
|
3293
|
+
static normalCDF(x) {
|
|
3294
|
+
const a1 = 0.254829592;
|
|
3295
|
+
const a2 = -0.284496736;
|
|
3296
|
+
const a3 = 1.421413741;
|
|
3297
|
+
const a4 = -1.453152027;
|
|
3298
|
+
const a5 = 1.061405429;
|
|
3299
|
+
const p = 0.3275911;
|
|
3300
|
+
const sign = x < 0 ? -1 : 1;
|
|
3301
|
+
x = Math.abs(x) / Math.sqrt(2);
|
|
3302
|
+
const t = 1 / (1 + p * x);
|
|
3303
|
+
const y = 1 - ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t * Math.exp(-x * x);
|
|
3304
|
+
return 0.5 * (1 + sign * y);
|
|
3305
|
+
}
|
|
3306
|
+
/**
|
|
3307
|
+
* Standard normal PDF
|
|
3308
|
+
*/
|
|
3309
|
+
static normalPDF(x) {
|
|
3310
|
+
return Math.exp(-0.5 * x * x) / Math.sqrt(2 * Math.PI);
|
|
3311
|
+
}
|
|
3312
|
+
};
|
|
3313
|
+
|
|
3314
|
+
// src/utils/validation.ts
|
|
3315
|
+
var ValidationError = class extends Error {
|
|
3316
|
+
field;
|
|
3317
|
+
constructor(field, message) {
|
|
3318
|
+
super(`Validation error on '${field}': ${message}`);
|
|
3319
|
+
this.name = "ValidationError";
|
|
3320
|
+
this.field = field;
|
|
3321
|
+
}
|
|
3322
|
+
};
|
|
3323
|
+
function validateRFQParams(params) {
|
|
3324
|
+
if (!params.asset || params.asset.trim().length === 0) {
|
|
3325
|
+
throw new ValidationError("asset", "Asset identifier is required");
|
|
3326
|
+
}
|
|
3327
|
+
if (!["buy", "sell"].includes(params.side)) {
|
|
3328
|
+
throw new ValidationError("side", 'Side must be "buy" or "sell"');
|
|
3329
|
+
}
|
|
3330
|
+
if (!["call", "put"].includes(params.optionType)) {
|
|
3331
|
+
throw new ValidationError("optionType", 'Option type must be "call" or "put"');
|
|
3332
|
+
}
|
|
3333
|
+
if (params.strike <= 0) {
|
|
3334
|
+
throw new ValidationError("strike", "Strike must be a positive number");
|
|
3335
|
+
}
|
|
3336
|
+
if (params.expiry <= Math.floor(Date.now() / 1e3)) {
|
|
3337
|
+
throw new ValidationError("expiry", "Expiry must be in the future");
|
|
3338
|
+
}
|
|
3339
|
+
if (params.quantity <= 0n) {
|
|
3340
|
+
throw new ValidationError("quantity", "Quantity must be positive");
|
|
3341
|
+
}
|
|
3342
|
+
if (!params.vaultAddress || params.vaultAddress.length < 32) {
|
|
3343
|
+
throw new ValidationError("vaultAddress", "Valid vault address is required");
|
|
3344
|
+
}
|
|
3345
|
+
if (params.premiumFloor !== void 0 && params.premiumFloor < 0n) {
|
|
3346
|
+
throw new ValidationError("premiumFloor", "Premium floor cannot be negative");
|
|
3347
|
+
}
|
|
3348
|
+
}
|
|
3349
|
+
function validateBlackScholesParams(params) {
|
|
3350
|
+
if (params.spot <= 0) {
|
|
3351
|
+
throw new ValidationError("spot", "Spot price must be positive");
|
|
3352
|
+
}
|
|
3353
|
+
if (params.strike <= 0) {
|
|
3354
|
+
throw new ValidationError("strike", "Strike price must be positive");
|
|
3355
|
+
}
|
|
3356
|
+
if (params.timeToExpiry <= 0) {
|
|
3357
|
+
throw new ValidationError("timeToExpiry", "Time to expiry must be positive");
|
|
3358
|
+
}
|
|
3359
|
+
if (params.volatility <= 0) {
|
|
3360
|
+
throw new ValidationError("volatility", "Volatility must be positive");
|
|
3361
|
+
}
|
|
3362
|
+
if (params.volatility > 5) {
|
|
3363
|
+
throw new ValidationError("volatility", "Volatility seems too high (>500%)");
|
|
3364
|
+
}
|
|
3365
|
+
if (params.riskFreeRate < -0.1 || params.riskFreeRate > 1) {
|
|
3366
|
+
throw new ValidationError("riskFreeRate", "Risk-free rate seems unreasonable");
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
function validatePublicKey(address, fieldName = "address") {
|
|
3370
|
+
const base58Regex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
|
3371
|
+
if (!base58Regex.test(address)) {
|
|
3372
|
+
throw new ValidationError(fieldName, "Invalid Solana public key format");
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
function validateTokenAmount(amount, fieldName = "amount", decimals = 6) {
|
|
3376
|
+
if (amount < 0n) {
|
|
3377
|
+
throw new ValidationError(fieldName, "Amount cannot be negative");
|
|
3378
|
+
}
|
|
3379
|
+
const maxReasonable = BigInt(1e15) * BigInt(10 ** decimals);
|
|
3380
|
+
if (amount > maxReasonable) {
|
|
3381
|
+
throw new ValidationError(fieldName, "Amount seems unreasonably large");
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
function validateTimestamp(timestamp, fieldName = "timestamp", options = {}) {
|
|
3385
|
+
if (!Number.isInteger(timestamp) || timestamp < 0) {
|
|
3386
|
+
throw new ValidationError(fieldName, "Invalid timestamp");
|
|
3387
|
+
}
|
|
3388
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
3389
|
+
if (options.mustBeFuture && timestamp <= now) {
|
|
3390
|
+
throw new ValidationError(fieldName, "Timestamp must be in the future");
|
|
3391
|
+
}
|
|
3392
|
+
if (options.maxFutureDays) {
|
|
3393
|
+
const maxTimestamp = now + options.maxFutureDays * 24 * 60 * 60;
|
|
3394
|
+
if (timestamp > maxTimestamp) {
|
|
3395
|
+
throw new ValidationError(
|
|
3396
|
+
fieldName,
|
|
3397
|
+
`Timestamp cannot be more than ${options.maxFutureDays} days in the future`
|
|
3398
|
+
);
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
|
|
3403
|
+
// src/utils/formatting.ts
|
|
3404
|
+
function formatTokenAmount(amount, decimals, maxDecimals = 2) {
|
|
3405
|
+
const divisor = BigInt(10 ** decimals);
|
|
3406
|
+
const intPart = amount / divisor;
|
|
3407
|
+
const fracPart = amount % divisor;
|
|
3408
|
+
const fracStr = fracPart.toString().padStart(decimals, "0");
|
|
3409
|
+
const truncatedFrac = fracStr.slice(0, maxDecimals);
|
|
3410
|
+
if (maxDecimals === 0 || parseInt(truncatedFrac) === 0) {
|
|
3411
|
+
return intPart.toString();
|
|
3412
|
+
}
|
|
3413
|
+
const trimmedFrac = truncatedFrac.replace(/0+$/, "");
|
|
3414
|
+
return trimmedFrac ? `${intPart}.${trimmedFrac}` : intPart.toString();
|
|
3415
|
+
}
|
|
3416
|
+
function parseTokenAmount(amount, decimals) {
|
|
3417
|
+
const parts = amount.split(".");
|
|
3418
|
+
const intPart = parts[0] || "0";
|
|
3419
|
+
let fracPart = parts[1] || "";
|
|
3420
|
+
fracPart = fracPart.slice(0, decimals).padEnd(decimals, "0");
|
|
3421
|
+
return BigInt(intPart) * BigInt(10 ** decimals) + BigInt(fracPart);
|
|
3422
|
+
}
|
|
3423
|
+
function formatUSDC(amount, maxDecimals = 2) {
|
|
3424
|
+
return formatTokenAmount(amount, TOKEN_DECIMALS.USDC, maxDecimals);
|
|
3425
|
+
}
|
|
3426
|
+
function parseUSDC(amount) {
|
|
3427
|
+
return parseTokenAmount(amount, TOKEN_DECIMALS.USDC);
|
|
3428
|
+
}
|
|
3429
|
+
function formatPrice(price, decimals = 2) {
|
|
3430
|
+
return price.toLocaleString("en-US", {
|
|
3431
|
+
minimumFractionDigits: decimals,
|
|
3432
|
+
maximumFractionDigits: decimals
|
|
3433
|
+
});
|
|
3434
|
+
}
|
|
3435
|
+
function formatPercent(value, decimals = 2) {
|
|
3436
|
+
return `${(value * 100).toFixed(decimals)}%`;
|
|
3437
|
+
}
|
|
3438
|
+
function formatBps(bps) {
|
|
3439
|
+
return `${bps.toLocaleString()} bps`;
|
|
3440
|
+
}
|
|
3441
|
+
function bpsToPercent(bps) {
|
|
3442
|
+
return bps / 100;
|
|
3443
|
+
}
|
|
3444
|
+
function percentToBps(percent) {
|
|
3445
|
+
return Math.round(percent * 100);
|
|
3446
|
+
}
|
|
3447
|
+
function formatTimestamp(timestamp) {
|
|
3448
|
+
return new Date(timestamp * 1e3).toISOString();
|
|
3449
|
+
}
|
|
3450
|
+
function formatDate(timestamp, options = {
|
|
3451
|
+
year: "numeric",
|
|
3452
|
+
month: "short",
|
|
3453
|
+
day: "numeric",
|
|
3454
|
+
hour: "2-digit",
|
|
3455
|
+
minute: "2-digit"
|
|
3456
|
+
}) {
|
|
3457
|
+
return new Date(timestamp * 1e3).toLocaleString("en-US", options);
|
|
3458
|
+
}
|
|
3459
|
+
function formatTimeToExpiry(expiryTimestamp) {
|
|
3460
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
3461
|
+
const secondsRemaining = expiryTimestamp - now;
|
|
3462
|
+
if (secondsRemaining <= 0) {
|
|
3463
|
+
return "Expired";
|
|
3464
|
+
}
|
|
3465
|
+
const days = Math.floor(secondsRemaining / 86400);
|
|
3466
|
+
const hours = Math.floor(secondsRemaining % 86400 / 3600);
|
|
3467
|
+
const minutes = Math.floor(secondsRemaining % 3600 / 60);
|
|
3468
|
+
if (days > 0) {
|
|
3469
|
+
return `${days}d ${hours}h`;
|
|
3470
|
+
}
|
|
3471
|
+
if (hours > 0) {
|
|
3472
|
+
return `${hours}h ${minutes}m`;
|
|
3473
|
+
}
|
|
3474
|
+
return `${minutes}m`;
|
|
3475
|
+
}
|
|
3476
|
+
function shortenAddress(address, chars = 4) {
|
|
3477
|
+
if (address.length <= chars * 2 + 3) {
|
|
3478
|
+
return address;
|
|
3479
|
+
}
|
|
3480
|
+
return `${address.slice(0, chars)}...${address.slice(-chars)}`;
|
|
3481
|
+
}
|
|
3482
|
+
function formatRFQId(rfqId) {
|
|
3483
|
+
const parts = rfqId.split("_");
|
|
3484
|
+
if (parts.length >= 3) {
|
|
3485
|
+
return `RFQ-${parts[2].toUpperCase()}`;
|
|
3486
|
+
}
|
|
3487
|
+
return rfqId.slice(0, 12);
|
|
3488
|
+
}
|
|
3489
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
3490
|
+
0 && (module.exports = {
|
|
3491
|
+
DEFAULT_PRICING_PARAMS,
|
|
3492
|
+
DEVNET_CONFIG,
|
|
3493
|
+
DEVNET_USDC_MINT,
|
|
3494
|
+
MAINNET_CONFIG,
|
|
3495
|
+
MAINNET_USDC_MINT,
|
|
3496
|
+
OptionPricing,
|
|
3497
|
+
PYTH_HERMES_URL,
|
|
3498
|
+
PYTH_PRICE_FEEDS,
|
|
3499
|
+
RFQClient,
|
|
3500
|
+
RFQ_DEFAULTS,
|
|
3501
|
+
TOKEN_DECIMALS,
|
|
3502
|
+
VAULT_IDL,
|
|
3503
|
+
VAULT_PROGRAM_ID,
|
|
3504
|
+
ValidationError,
|
|
3505
|
+
VaultInstructions,
|
|
3506
|
+
bpsToPercent,
|
|
3507
|
+
deriveShareEscrowPda,
|
|
3508
|
+
deriveVaultPda,
|
|
3509
|
+
deriveWhitelistPda,
|
|
3510
|
+
deriveWithdrawalPda,
|
|
3511
|
+
formatBps,
|
|
3512
|
+
formatDate,
|
|
3513
|
+
formatPercent,
|
|
3514
|
+
formatPrice,
|
|
3515
|
+
formatRFQId,
|
|
3516
|
+
formatTimeToExpiry,
|
|
3517
|
+
formatTimestamp,
|
|
3518
|
+
formatTokenAmount,
|
|
3519
|
+
formatUSDC,
|
|
3520
|
+
parseTokenAmount,
|
|
3521
|
+
parseUSDC,
|
|
3522
|
+
percentToBps,
|
|
3523
|
+
shortenAddress,
|
|
3524
|
+
validateBlackScholesParams,
|
|
3525
|
+
validatePublicKey,
|
|
3526
|
+
validateRFQParams,
|
|
3527
|
+
validateTimestamp,
|
|
3528
|
+
validateTokenAmount
|
|
3529
|
+
});
|