@drift-labs/sdk 2.54.0-beta.0 → 2.54.0-beta.10
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/VERSION +1 -1
- package/lib/accounts/pollingInsuranceFundStakeAccountSubscriber.js +0 -1
- package/lib/constants/perpMarkets.js +20 -0
- package/lib/driftClient.d.ts +8 -2
- package/lib/driftClient.js +95 -20
- package/lib/events/webSocketLogProvider.js +3 -0
- package/lib/idl/drift.json +7 -1
- package/lib/jupiter/jupiterClient.d.ts +6 -0
- package/lib/jupiter/jupiterClient.js +2 -2
- package/lib/math/funding.js +24 -1
- package/lib/math/oracles.js +2 -2
- package/lib/math/superStake.d.ts +51 -0
- package/lib/math/superStake.js +10 -2
- package/lib/priorityFee/averageOverSlotsStrategy.d.ts +0 -5
- package/lib/priorityFee/averageOverSlotsStrategy.js +1 -13
- package/lib/priorityFee/maxOverSlotsStrategy.d.ts +0 -5
- package/lib/priorityFee/maxOverSlotsStrategy.js +1 -13
- package/lib/priorityFee/priorityFeeSubscriber.d.ts +5 -4
- package/lib/priorityFee/priorityFeeSubscriber.js +15 -21
- package/lib/tx/baseTxSender.d.ts +6 -2
- package/lib/tx/baseTxSender.js +47 -2
- package/lib/tx/fastSingleTxSender.d.ts +3 -2
- package/lib/tx/fastSingleTxSender.js +10 -2
- package/lib/tx/retryTxSender.d.ts +3 -2
- package/lib/tx/retryTxSender.js +14 -23
- package/lib/tx/types.d.ts +5 -0
- package/lib/tx/types.js +7 -0
- package/lib/tx/utils.d.ts +5 -1
- package/lib/tx/utils.js +20 -1
- package/lib/userMap/userMap.js +4 -0
- package/package.json +1 -1
- package/src/accounts/pollingInsuranceFundStakeAccountSubscriber.ts +0 -1
- package/src/constants/perpMarkets.ts +20 -0
- package/src/driftClient.ts +197 -39
- package/src/events/webSocketLogProvider.ts +11 -2
- package/src/idl/drift.json +7 -1
- package/src/jupiter/jupiterClient.ts +8 -2
- package/src/math/funding.ts +28 -1
- package/src/math/oracles.ts +2 -2
- package/src/math/superStake.ts +60 -1
- package/src/priorityFee/averageOverSlotsStrategy.ts +1 -16
- package/src/priorityFee/maxOverSlotsStrategy.ts +1 -16
- package/src/priorityFee/priorityFeeSubscriber.ts +22 -26
- package/src/tx/baseTxSender.ts +64 -2
- package/src/tx/fastSingleTxSender.ts +11 -2
- package/src/tx/retryTxSender.ts +16 -25
- package/src/tx/types.ts +6 -0
- package/src/tx/utils.ts +32 -0
- package/src/userMap/userMap.ts +3 -0
- package/tests/amm/test.ts +275 -2
- package/tests/dlob/test.ts +2 -2
- package/tests/tx/priorityFeeStrategy.ts +2 -2
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.54.0-beta.
|
|
1
|
+
2.54.0-beta.10
|
|
@@ -224,6 +224,16 @@ exports.DevnetPerpMarkets = [
|
|
|
224
224
|
launchTs: 1703173331000,
|
|
225
225
|
oracleSource: __1.OracleSource.PYTH,
|
|
226
226
|
},
|
|
227
|
+
{
|
|
228
|
+
fullName: 'AVAX',
|
|
229
|
+
category: ['Rollup', 'Infra'],
|
|
230
|
+
symbol: 'AVAX-PERP',
|
|
231
|
+
baseAssetSymbol: 'AVAX',
|
|
232
|
+
marketIndex: 22,
|
|
233
|
+
oracle: new web3_js_1.PublicKey('FVb5h1VmHPfVb1RfqZckchq18GxRv4iKt8T4eVTQAqdz'),
|
|
234
|
+
launchTs: 1704209558000,
|
|
235
|
+
oracleSource: __1.OracleSource.PYTH,
|
|
236
|
+
},
|
|
227
237
|
];
|
|
228
238
|
exports.MainnetPerpMarkets = [
|
|
229
239
|
{
|
|
@@ -446,6 +456,16 @@ exports.MainnetPerpMarkets = [
|
|
|
446
456
|
launchTs: 1703173331000,
|
|
447
457
|
oracleSource: __1.OracleSource.PYTH,
|
|
448
458
|
},
|
|
459
|
+
{
|
|
460
|
+
fullName: 'AVAX',
|
|
461
|
+
category: ['Rollup', 'Infra'],
|
|
462
|
+
symbol: 'AVAX-PERP',
|
|
463
|
+
baseAssetSymbol: 'AVAX',
|
|
464
|
+
marketIndex: 22,
|
|
465
|
+
oracle: new web3_js_1.PublicKey('Ax9ujW5B9oqcv59N8m6f1BpTBq2rGeGaBcpKjC5UYsXU'),
|
|
466
|
+
launchTs: 1704209558000,
|
|
467
|
+
oracleSource: __1.OracleSource.PYTH,
|
|
468
|
+
},
|
|
449
469
|
];
|
|
450
470
|
exports.PerpMarkets = {
|
|
451
471
|
devnet: exports.DevnetPerpMarkets,
|
package/lib/driftClient.d.ts
CHANGED
|
@@ -284,10 +284,11 @@ export declare class DriftClient {
|
|
|
284
284
|
* @param cancelExistingOrders - Builds and returns an extra transaciton to cancel the existing orders in the same perp market. Intended use is to auto-cancel TP/SL orders when closing a position. Ignored if orderParams.marketType is not MarketType.PERP
|
|
285
285
|
* @returns
|
|
286
286
|
*/
|
|
287
|
-
sendMarketOrderAndGetSignedFillTx(orderParams: OptionalOrderParams, userAccountPublicKey: PublicKey, userAccount: UserAccount, makerInfo?: MakerInfo | MakerInfo[], txParams?: TxParams, bracketOrdersParams?: OptionalOrderParams[], referrerInfo?: ReferrerInfo, cancelExistingOrders?: boolean): Promise<{
|
|
287
|
+
sendMarketOrderAndGetSignedFillTx(orderParams: OptionalOrderParams, userAccountPublicKey: PublicKey, userAccount: UserAccount, makerInfo?: MakerInfo | MakerInfo[], txParams?: TxParams, bracketOrdersParams?: OptionalOrderParams[], referrerInfo?: ReferrerInfo, cancelExistingOrders?: boolean, settlePnl?: boolean): Promise<{
|
|
288
288
|
txSig: TransactionSignature;
|
|
289
289
|
signedFillTx?: Transaction;
|
|
290
290
|
signedCancelExistingOrdersTx?: Transaction;
|
|
291
|
+
signedSettlePnlTx?: Transaction;
|
|
291
292
|
}>;
|
|
292
293
|
placePerpOrder(orderParams: OptionalOrderParams, txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
|
|
293
294
|
getPlacePerpOrderIx(orderParams: OptionalOrderParams, subAccountId?: number): Promise<TransactionInstruction>;
|
|
@@ -310,7 +311,7 @@ export declare class DriftClient {
|
|
|
310
311
|
direction?: PositionDirection;
|
|
311
312
|
}, placeOrderParams: OrderParams[], txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
|
|
312
313
|
placeOrders(params: OrderParams[], txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
|
|
313
|
-
getPlaceOrdersIx(params:
|
|
314
|
+
getPlaceOrdersIx(params: OptionalOrderParams[], subAccountId?: number): Promise<TransactionInstruction>;
|
|
314
315
|
fillPerpOrder(userAccountPublicKey: PublicKey, user: UserAccount, order?: Pick<Order, 'marketIndex' | 'orderId'>, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, txParams?: TxParams, fillerPublicKey?: number): Promise<TransactionSignature>;
|
|
315
316
|
getFillPerpOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Pick<Order, 'marketIndex' | 'orderId'>, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, fillerSubAccountId?: number): Promise<TransactionInstruction>;
|
|
316
317
|
getRevertFillIx(fillerPublicKey?: PublicKey): Promise<TransactionInstruction>;
|
|
@@ -427,6 +428,11 @@ export declare class DriftClient {
|
|
|
427
428
|
updateUserOpenOrdersCount(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams, fillerPublicKey?: PublicKey): Promise<TransactionSignature>;
|
|
428
429
|
getUpdateUserOpenOrdersCountIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, fillerPublicKey?: PublicKey): Promise<TransactionInstruction>;
|
|
429
430
|
placeAndTakePerpOrder(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
|
|
431
|
+
placeAndTakePerpWithAdditionalOrders(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, bracketOrdersParams?: OptionalOrderParams[], txParams?: TxParams, subAccountId?: number, cancelExistingOrders?: boolean, settlePnl?: boolean): Promise<{
|
|
432
|
+
txSig: TransactionSignature;
|
|
433
|
+
signedCancelExistingOrdersTx?: Transaction;
|
|
434
|
+
signedSettlePnlTx?: Transaction;
|
|
435
|
+
}>;
|
|
430
436
|
getPlaceAndTakePerpOrderIx(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, subAccountId?: number): Promise<TransactionInstruction>;
|
|
431
437
|
placeAndMakePerpOrder(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
|
|
432
438
|
getPlaceAndMakePerpOrderIx(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo, subAccountId?: number): Promise<TransactionInstruction>;
|
package/lib/driftClient.js
CHANGED
|
@@ -1419,35 +1419,47 @@ class DriftClient {
|
|
|
1419
1419
|
* @param cancelExistingOrders - Builds and returns an extra transaciton to cancel the existing orders in the same perp market. Intended use is to auto-cancel TP/SL orders when closing a position. Ignored if orderParams.marketType is not MarketType.PERP
|
|
1420
1420
|
* @returns
|
|
1421
1421
|
*/
|
|
1422
|
-
async sendMarketOrderAndGetSignedFillTx(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo, cancelExistingOrders) {
|
|
1422
|
+
async sendMarketOrderAndGetSignedFillTx(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo, cancelExistingOrders, settlePnl) {
|
|
1423
1423
|
const marketIndex = orderParams.marketIndex;
|
|
1424
1424
|
const orderId = userAccount.nextOrderId;
|
|
1425
|
-
const
|
|
1426
|
-
|
|
1427
|
-
for (const bracketOrderParams of bracketOrdersParams) {
|
|
1428
|
-
const placeBracketOrderIx = await this.getPlacePerpOrderIx(bracketOrderParams, userAccount.subAccountId);
|
|
1429
|
-
bracketOrderIxs.push(placeBracketOrderIx);
|
|
1430
|
-
}
|
|
1431
|
-
let cancelOrdersIx;
|
|
1425
|
+
const ordersIx = await this.getPlaceOrdersIx([orderParams, ...bracketOrdersParams], userAccount.subAccountId);
|
|
1426
|
+
/* Cancel open orders in market if requested */
|
|
1432
1427
|
let cancelExistingOrdersTx;
|
|
1433
1428
|
if (cancelExistingOrders && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
|
|
1434
|
-
cancelOrdersIx = await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, userAccount.subAccountId);
|
|
1429
|
+
const cancelOrdersIx = await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, userAccount.subAccountId);
|
|
1435
1430
|
//@ts-ignore
|
|
1436
1431
|
cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion);
|
|
1437
1432
|
}
|
|
1433
|
+
/* Settle PnL after fill if requested */
|
|
1434
|
+
let settlePnlTx;
|
|
1435
|
+
if (settlePnl && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
|
|
1436
|
+
const settlePnlIx = await this.settlePNLIx(userAccountPublicKey, userAccount, marketIndex);
|
|
1437
|
+
//@ts-ignore
|
|
1438
|
+
settlePnlTx = await this.buildTransaction([settlePnlIx], txParams, this.txVersion);
|
|
1439
|
+
}
|
|
1438
1440
|
// use versioned transactions if there is a lookup table account and wallet is compatible
|
|
1439
1441
|
if (this.txVersion === 0) {
|
|
1440
|
-
const versionedMarketOrderTx = await this.buildTransaction(
|
|
1442
|
+
const versionedMarketOrderTx = await this.buildTransaction(ordersIx, txParams, 0);
|
|
1441
1443
|
const fillPerpOrderIx = await this.getFillPerpOrderIx(userAccountPublicKey, userAccount, {
|
|
1442
1444
|
orderId,
|
|
1443
1445
|
marketIndex,
|
|
1444
1446
|
}, makerInfo, referrerInfo, userAccount.subAccountId);
|
|
1445
1447
|
const versionedFillTx = await this.buildTransaction([fillPerpOrderIx], txParams, 0);
|
|
1446
|
-
const
|
|
1448
|
+
const allPossibleTxs = [
|
|
1447
1449
|
versionedMarketOrderTx,
|
|
1448
1450
|
versionedFillTx,
|
|
1449
1451
|
cancelExistingOrdersTx,
|
|
1450
|
-
|
|
1452
|
+
settlePnlTx,
|
|
1453
|
+
];
|
|
1454
|
+
const txKeys = [
|
|
1455
|
+
'signedVersionedMarketOrderTx',
|
|
1456
|
+
'signedVersionedFillTx',
|
|
1457
|
+
'signedCancelExistingOrdersTx',
|
|
1458
|
+
'signedSettlePnlTx',
|
|
1459
|
+
];
|
|
1460
|
+
const { signedVersionedMarketOrderTx, signedVersionedFillTx, signedCancelExistingOrdersTx, signedSettlePnlTx, } = await (0, utils_1.getSignedTransactionMap)(
|
|
1461
|
+
//@ts-ignore
|
|
1462
|
+
this.provider.wallet, allPossibleTxs, txKeys);
|
|
1451
1463
|
const { txSig, slot } = await this.txSender.sendRawTransaction(signedVersionedMarketOrderTx.serialize(), this.opts);
|
|
1452
1464
|
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
1453
1465
|
return {
|
|
@@ -1456,13 +1468,12 @@ class DriftClient {
|
|
|
1456
1468
|
signedFillTx: signedVersionedFillTx,
|
|
1457
1469
|
// @ts-ignore
|
|
1458
1470
|
signedCancelExistingOrdersTx,
|
|
1471
|
+
// @ts-ignore
|
|
1472
|
+
signedSettlePnlTx,
|
|
1459
1473
|
};
|
|
1460
1474
|
}
|
|
1461
1475
|
else {
|
|
1462
|
-
const marketOrderTx = (0, utils_1.wrapInTx)(
|
|
1463
|
-
if (bracketOrderIxs.length > 0) {
|
|
1464
|
-
marketOrderTx.add(...bracketOrderIxs);
|
|
1465
|
-
}
|
|
1476
|
+
const marketOrderTx = (0, utils_1.wrapInTx)(ordersIx, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice);
|
|
1466
1477
|
// Apply the latest blockhash to the txs so that we can sign before sending them
|
|
1467
1478
|
const currentBlockHash = (await this.connection.getLatestBlockhash('finalized')).blockhash;
|
|
1468
1479
|
marketOrderTx.recentBlockhash = currentBlockHash;
|
|
@@ -1471,10 +1482,33 @@ class DriftClient {
|
|
|
1471
1482
|
cancelExistingOrdersTx.recentBlockhash = currentBlockHash;
|
|
1472
1483
|
cancelExistingOrdersTx.feePayer = userAccount.authority;
|
|
1473
1484
|
}
|
|
1474
|
-
|
|
1485
|
+
if (settlePnlTx) {
|
|
1486
|
+
settlePnlTx.recentBlockhash = currentBlockHash;
|
|
1487
|
+
settlePnlTx.feePayer = userAccount.authority;
|
|
1488
|
+
}
|
|
1489
|
+
const allPossibleTxs = [
|
|
1490
|
+
marketOrderTx,
|
|
1491
|
+
cancelExistingOrdersTx,
|
|
1492
|
+
settlePnlTx,
|
|
1493
|
+
];
|
|
1494
|
+
const txKeys = [
|
|
1495
|
+
'signedMarketOrderTx',
|
|
1496
|
+
'signedCancelExistingOrdersTx',
|
|
1497
|
+
'signedSettlePnlTx',
|
|
1498
|
+
];
|
|
1499
|
+
const { signedMarketOrderTx, signedCancelExistingOrdersTx, signedSettlePnlTx, } = await (0, utils_1.getSignedTransactionMap)(
|
|
1500
|
+
//@ts-ignore
|
|
1501
|
+
this.provider.wallet, allPossibleTxs, txKeys);
|
|
1475
1502
|
const { txSig, slot } = await this.sendTransaction(signedMarketOrderTx, [], this.opts, true);
|
|
1476
1503
|
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
1477
|
-
return {
|
|
1504
|
+
return {
|
|
1505
|
+
txSig,
|
|
1506
|
+
signedFillTx: undefined,
|
|
1507
|
+
//@ts-ignore
|
|
1508
|
+
signedCancelExistingOrdersTx,
|
|
1509
|
+
//@ts-ignore
|
|
1510
|
+
signedSettlePnlTx,
|
|
1511
|
+
};
|
|
1478
1512
|
}
|
|
1479
1513
|
}
|
|
1480
1514
|
async placePerpOrder(orderParams, txParams, subAccountId) {
|
|
@@ -1708,7 +1742,8 @@ class DriftClient {
|
|
|
1708
1742
|
readableSpotMarketIndexes,
|
|
1709
1743
|
useMarketLastSlotCache: true,
|
|
1710
1744
|
});
|
|
1711
|
-
|
|
1745
|
+
const formattedParams = params.map((item) => (0, orderParams_1.getOrderParams)(item));
|
|
1746
|
+
return await this.program.instruction.placeOrders(formattedParams, {
|
|
1712
1747
|
accounts: {
|
|
1713
1748
|
state: await this.getStatePublicKey(),
|
|
1714
1749
|
user,
|
|
@@ -2168,7 +2203,6 @@ class DriftClient {
|
|
|
2168
2203
|
slippageBps,
|
|
2169
2204
|
swapMode,
|
|
2170
2205
|
onlyDirectRoutes,
|
|
2171
|
-
excludeDexes: ['Raydium CLMM'], // temp exclude to workaround bug with raydium clmm
|
|
2172
2206
|
});
|
|
2173
2207
|
quote = fetchedQuote;
|
|
2174
2208
|
}
|
|
@@ -2412,6 +2446,47 @@ class DriftClient {
|
|
|
2412
2446
|
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
2413
2447
|
return txSig;
|
|
2414
2448
|
}
|
|
2449
|
+
async placeAndTakePerpWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders, settlePnl) {
|
|
2450
|
+
let cancelExistingOrdersTx;
|
|
2451
|
+
if (cancelExistingOrders && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
|
|
2452
|
+
const cancelOrdersIx = await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, subAccountId);
|
|
2453
|
+
//@ts-ignore
|
|
2454
|
+
cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion);
|
|
2455
|
+
}
|
|
2456
|
+
/* Settle PnL after fill if requested */
|
|
2457
|
+
let settlePnlTx;
|
|
2458
|
+
if (settlePnl && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
|
|
2459
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey(subAccountId);
|
|
2460
|
+
const settlePnlIx = await this.settlePNLIx(userAccountPublicKey, this.getUserAccount(subAccountId), orderParams.marketIndex);
|
|
2461
|
+
//@ts-ignore
|
|
2462
|
+
settlePnlTx = await this.buildTransaction([settlePnlIx], txParams, this.txVersion);
|
|
2463
|
+
}
|
|
2464
|
+
const ixs = [];
|
|
2465
|
+
const placeAndTakeIx = await this.getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo, subAccountId);
|
|
2466
|
+
ixs.push(placeAndTakeIx);
|
|
2467
|
+
if (bracketOrdersParams.length > 0) {
|
|
2468
|
+
const bracketOrdersIx = await this.getPlaceOrdersIx(bracketOrdersParams, subAccountId);
|
|
2469
|
+
ixs.push(bracketOrdersIx);
|
|
2470
|
+
}
|
|
2471
|
+
const placeAndTakeTx = await this.buildTransaction(ixs, txParams);
|
|
2472
|
+
const allPossibleTxs = [
|
|
2473
|
+
placeAndTakeTx,
|
|
2474
|
+
cancelExistingOrdersTx,
|
|
2475
|
+
settlePnlTx,
|
|
2476
|
+
];
|
|
2477
|
+
const txKeys = [
|
|
2478
|
+
'signedPlaceAndTakeTx',
|
|
2479
|
+
'signedCancelExistingOrdersTx',
|
|
2480
|
+
'signedSettlePnlTx',
|
|
2481
|
+
];
|
|
2482
|
+
const { signedPlaceAndTakeTx, signedCancelExistingOrdersTx, signedSettlePnlTx, } = await (0, utils_1.getSignedTransactionMap)(
|
|
2483
|
+
//@ts-ignore
|
|
2484
|
+
this.provider.wallet, allPossibleTxs, txKeys);
|
|
2485
|
+
const { txSig, slot } = await this.sendTransaction(signedPlaceAndTakeTx, [], this.opts, true);
|
|
2486
|
+
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
2487
|
+
//@ts-ignore
|
|
2488
|
+
return { txSig, signedCancelExistingOrdersTx, signedSettlePnlTx };
|
|
2489
|
+
}
|
|
2415
2490
|
async getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo, subAccountId) {
|
|
2416
2491
|
orderParams = (0, orderParams_1.getOrderParams)(orderParams, { marketType: types_1.MarketType.PERP });
|
|
2417
2492
|
const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
package/lib/idl/drift.json
CHANGED
|
@@ -8524,7 +8524,13 @@
|
|
|
8524
8524
|
"kind": "enum",
|
|
8525
8525
|
"variants": [
|
|
8526
8526
|
{
|
|
8527
|
-
"name": "Standard"
|
|
8527
|
+
"name": "Standard",
|
|
8528
|
+
"fields": [
|
|
8529
|
+
{
|
|
8530
|
+
"name": "track_open_orders_fraction",
|
|
8531
|
+
"type": "bool"
|
|
8532
|
+
}
|
|
8533
|
+
]
|
|
8528
8534
|
},
|
|
8529
8535
|
{
|
|
8530
8536
|
"name": "Liquidation",
|
|
@@ -195,6 +195,12 @@ export interface QuoteResponse {
|
|
|
195
195
|
* @memberof QuoteResponse
|
|
196
196
|
*/
|
|
197
197
|
timeTaken?: number;
|
|
198
|
+
/**
|
|
199
|
+
*
|
|
200
|
+
* @type {string}
|
|
201
|
+
* @memberof QuoteResponse
|
|
202
|
+
*/
|
|
203
|
+
error?: string;
|
|
198
204
|
}
|
|
199
205
|
export declare class JupiterClient {
|
|
200
206
|
url: string;
|
|
@@ -44,7 +44,7 @@ class JupiterClient {
|
|
|
44
44
|
* @param onlyDirectRoutes whether to only return direct routes
|
|
45
45
|
*/
|
|
46
46
|
async getQuote({ inputMint, outputMint, amount, maxAccounts = 50, // 50 is an estimated amount with buffer
|
|
47
|
-
slippageBps = 50, swapMode = 'ExactIn', onlyDirectRoutes = false, excludeDexes
|
|
47
|
+
slippageBps = 50, swapMode = 'ExactIn', onlyDirectRoutes = false, excludeDexes, }) {
|
|
48
48
|
const params = new URLSearchParams({
|
|
49
49
|
inputMint: inputMint.toString(),
|
|
50
50
|
outputMint: outputMint.toString(),
|
|
@@ -53,7 +53,7 @@ class JupiterClient {
|
|
|
53
53
|
swapMode,
|
|
54
54
|
onlyDirectRoutes: onlyDirectRoutes.toString(),
|
|
55
55
|
maxAccounts: maxAccounts.toString(),
|
|
56
|
-
excludeDexes: excludeDexes.join(','),
|
|
56
|
+
...(excludeDexes && { excludeDexes: excludeDexes.join(',') }),
|
|
57
57
|
}).toString();
|
|
58
58
|
const quote = await (await (0, node_fetch_1.default)(`${this.url}/v6/quote?${params}`)).json();
|
|
59
59
|
return quote;
|
package/lib/math/funding.js
CHANGED
|
@@ -6,6 +6,7 @@ const numericConstants_1 = require("../constants/numericConstants");
|
|
|
6
6
|
const types_1 = require("../types");
|
|
7
7
|
const amm_1 = require("./amm");
|
|
8
8
|
const oracles_1 = require("./oracles");
|
|
9
|
+
const utils_1 = require("./utils");
|
|
9
10
|
function calculateLiveMarkTwap(market, oraclePriceData, markPrice, now, period = new anchor_1.BN(3600)) {
|
|
10
11
|
now = now || new anchor_1.BN((Date.now() / 1000).toFixed(0));
|
|
11
12
|
const lastMarkTwapWithMantissa = market.amm.lastMarkPriceTwap;
|
|
@@ -73,7 +74,9 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, markPri
|
|
|
73
74
|
// }
|
|
74
75
|
const twapSpread = markTwap.sub(oracleTwap);
|
|
75
76
|
const twapSpreadWithOffset = twapSpread.add(oracleTwap.abs().div(numericConstants_1.FUNDING_RATE_OFFSET_DENOMINATOR));
|
|
76
|
-
const
|
|
77
|
+
const maxSpread = getMaxPriceDivergenceForFundingRate(market, oracleTwap);
|
|
78
|
+
const clampedSpreadWithOffset = (0, utils_1.clampBN)(twapSpreadWithOffset, maxSpread.mul(new anchor_1.BN(-1)), maxSpread);
|
|
79
|
+
const twapSpreadPct = clampedSpreadWithOffset
|
|
77
80
|
.mul(numericConstants_1.PRICE_PRECISION)
|
|
78
81
|
.mul(new anchor_1.BN(100))
|
|
79
82
|
.div(oracleTwap);
|
|
@@ -135,6 +138,26 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, markPri
|
|
|
135
138
|
return [markTwap, oracleTwap, lowerboundEst, cappedAltEst, interpEst];
|
|
136
139
|
}
|
|
137
140
|
exports.calculateAllEstimatedFundingRate = calculateAllEstimatedFundingRate;
|
|
141
|
+
function getMaxPriceDivergenceForFundingRate(market, oracleTwap) {
|
|
142
|
+
if ((0, types_1.isVariant)(market.contractTier, 'a')) {
|
|
143
|
+
return oracleTwap.divn(33);
|
|
144
|
+
}
|
|
145
|
+
else if ((0, types_1.isVariant)(market.contractTier, 'b')) {
|
|
146
|
+
return oracleTwap.divn(33);
|
|
147
|
+
}
|
|
148
|
+
else if ((0, types_1.isVariant)(market.contractTier, 'c')) {
|
|
149
|
+
return oracleTwap.divn(20);
|
|
150
|
+
}
|
|
151
|
+
else if ((0, types_1.isVariant)(market.contractTier, 'speculative')) {
|
|
152
|
+
return oracleTwap.divn(10);
|
|
153
|
+
}
|
|
154
|
+
else if ((0, types_1.isVariant)(market.contractTier, 'isolated')) {
|
|
155
|
+
return oracleTwap.divn(10);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
return oracleTwap.divn(10);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
138
161
|
/**
|
|
139
162
|
*
|
|
140
163
|
* @param market
|
package/lib/math/oracles.js
CHANGED
|
@@ -25,8 +25,8 @@ function isOracleValid(amm, oraclePriceData, oracleGuardRails, slot) {
|
|
|
25
25
|
.mul(numericConstants_1.BID_ASK_SPREAD_PRECISION)
|
|
26
26
|
.div(oraclePriceData.price)
|
|
27
27
|
.gt(oracleGuardRails.validity.confidenceIntervalMaxSize);
|
|
28
|
-
const oracleIsStale =
|
|
29
|
-
.sub(
|
|
28
|
+
const oracleIsStale = new index_1.BN(slot)
|
|
29
|
+
.sub(oraclePriceData.slot)
|
|
30
30
|
.gt(oracleGuardRails.validity.slotsBeforeStaleForAmm);
|
|
31
31
|
return !(!oraclePriceData.hasSufficientNumberOfDataPoints ||
|
|
32
32
|
oracleIsStale ||
|
package/lib/math/superStake.d.ts
CHANGED
|
@@ -111,6 +111,57 @@ export type JITO_SOL_METRICS_ENDPOINT_RESPONSE = {
|
|
|
111
111
|
};
|
|
112
112
|
};
|
|
113
113
|
export declare function fetchJitoSolMetrics(): Promise<JITO_SOL_METRICS_ENDPOINT_RESPONSE>;
|
|
114
|
+
export type MSOL_METRICS_ENDPOINT_RESPONSE = {
|
|
115
|
+
total_active_balance: number;
|
|
116
|
+
available_reserve_balance: number;
|
|
117
|
+
emergency_cooling_down: number;
|
|
118
|
+
tvl_sol: number;
|
|
119
|
+
msol_directed_stake_sol: number;
|
|
120
|
+
msol_directed_stake_msol: number;
|
|
121
|
+
mnde_total_supply: number;
|
|
122
|
+
mnde_circulating_supply: number;
|
|
123
|
+
validators_count: number;
|
|
124
|
+
stake_accounts: number;
|
|
125
|
+
staking_sol_cap: number;
|
|
126
|
+
m_sol_price: number;
|
|
127
|
+
avg_staking_apy: number;
|
|
128
|
+
msol_price_apy_14d: number;
|
|
129
|
+
msol_price_apy_30d: number;
|
|
130
|
+
msol_price_apy_90d: number;
|
|
131
|
+
msol_price_apy_365d: number;
|
|
132
|
+
reserve_pda: number;
|
|
133
|
+
treasury_m_sol_amount: number;
|
|
134
|
+
m_sol_mint_supply: number;
|
|
135
|
+
m_sol_supply_state: number;
|
|
136
|
+
liq_pool_sol: number;
|
|
137
|
+
liq_pool_m_sol: number;
|
|
138
|
+
liq_pool_value: number;
|
|
139
|
+
liq_pool_token_supply: number;
|
|
140
|
+
liq_pool_token_price: number;
|
|
141
|
+
liq_pool_target: number;
|
|
142
|
+
liq_pool_min_fee: number;
|
|
143
|
+
liq_pool_max_fee: number;
|
|
144
|
+
liq_pool_current_fee: number;
|
|
145
|
+
liq_pool_treasury_cut: number;
|
|
146
|
+
liq_pool_cap: number;
|
|
147
|
+
total_cooling_down: number;
|
|
148
|
+
last_stake_delta_epoch: number;
|
|
149
|
+
circulating_ticket_count: number;
|
|
150
|
+
circulating_ticket_balance: number;
|
|
151
|
+
reward_fee_bp: number;
|
|
152
|
+
lido_staking: number;
|
|
153
|
+
lido_st_sol_price: number;
|
|
154
|
+
lido_stsol_price_apy_14d: number;
|
|
155
|
+
lido_stsol_price_apy_30d: number;
|
|
156
|
+
lido_stsol_price_apy_90d: number;
|
|
157
|
+
lido_stsol_price_apy_365d: number;
|
|
158
|
+
stake_delta: number;
|
|
159
|
+
bot_balance: number;
|
|
160
|
+
treasury_farm_claim_mnde_balance: number;
|
|
161
|
+
last_3_epochs_avg_duration_hs: number;
|
|
162
|
+
mnde_votes_validators: number;
|
|
163
|
+
};
|
|
164
|
+
export declare const fetchMSolMetrics: () => Promise<MSOL_METRICS_ENDPOINT_RESPONSE>;
|
|
114
165
|
export declare function calculateSolEarned({ marketIndex, user, depositRecords, }: {
|
|
115
166
|
marketIndex: number;
|
|
116
167
|
user: User;
|
package/lib/math/superStake.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.calculateEstimatedSuperStakeLiquidationPrice = exports.calculateSolEarned = exports.fetchJitoSolMetrics = exports.findBestLstSuperStakeIxs = exports.findBestJitoSolSuperStakeIxs = exports.findBestMSolSuperStakeIxs = exports.findBestSuperStakeIxs = exports.fetchBSolDriftEmissions = exports.fetchBSolMetrics = void 0;
|
|
6
|
+
exports.calculateEstimatedSuperStakeLiquidationPrice = exports.calculateSolEarned = exports.fetchMSolMetrics = exports.fetchJitoSolMetrics = exports.findBestLstSuperStakeIxs = exports.findBestJitoSolSuperStakeIxs = exports.findBestMSolSuperStakeIxs = exports.findBestSuperStakeIxs = exports.fetchBSolDriftEmissions = exports.fetchBSolMetrics = void 0;
|
|
7
7
|
const web3_js_1 = require("@solana/web3.js");
|
|
8
8
|
const marinade_1 = require("../marinade");
|
|
9
9
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
@@ -194,6 +194,12 @@ async function fetchJitoSolMetrics() {
|
|
|
194
194
|
return data;
|
|
195
195
|
}
|
|
196
196
|
exports.fetchJitoSolMetrics = fetchJitoSolMetrics;
|
|
197
|
+
const fetchMSolMetrics = async () => {
|
|
198
|
+
const res = await (0, node_fetch_1.default)('https://api2.marinade.finance/metrics_json');
|
|
199
|
+
const data = await res.json();
|
|
200
|
+
return data;
|
|
201
|
+
};
|
|
202
|
+
exports.fetchMSolMetrics = fetchMSolMetrics;
|
|
197
203
|
const getJitoSolHistoricalPriceMap = async (timestamps) => {
|
|
198
204
|
try {
|
|
199
205
|
const data = await fetchJitoSolMetrics();
|
|
@@ -227,7 +233,9 @@ async function calculateSolEarned({ marketIndex, user, depositRecords, }) {
|
|
|
227
233
|
const now = Date.now() / 1000;
|
|
228
234
|
const timestamps = [
|
|
229
235
|
now,
|
|
230
|
-
...depositRecords
|
|
236
|
+
...depositRecords
|
|
237
|
+
.filter((r) => r.marketIndex === marketIndex)
|
|
238
|
+
.map((r) => r.ts.toNumber()),
|
|
231
239
|
];
|
|
232
240
|
let lstRatios = new Map();
|
|
233
241
|
const getMsolPrice = async (timestamp) => {
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import { PriorityFeeStrategy } from './types';
|
|
2
2
|
export declare class AverageOverSlotsStrategy implements PriorityFeeStrategy {
|
|
3
|
-
private lookbackSlots;
|
|
4
|
-
/**
|
|
5
|
-
* @param lookbackSlots The number of slots to look back from the max slot in the sample
|
|
6
|
-
*/
|
|
7
|
-
constructor(lookbackSlots?: number);
|
|
8
3
|
calculate(samples: {
|
|
9
4
|
slot: number;
|
|
10
5
|
prioritizationFee: number;
|
|
@@ -2,27 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AverageOverSlotsStrategy = void 0;
|
|
4
4
|
class AverageOverSlotsStrategy {
|
|
5
|
-
/**
|
|
6
|
-
* @param lookbackSlots The number of slots to look back from the max slot in the sample
|
|
7
|
-
*/
|
|
8
|
-
constructor(lookbackSlots = 10) {
|
|
9
|
-
this.lookbackSlots = lookbackSlots;
|
|
10
|
-
}
|
|
11
5
|
calculate(samples) {
|
|
12
6
|
if (samples.length === 0) {
|
|
13
7
|
return 0;
|
|
14
8
|
}
|
|
15
|
-
const stopSlot = samples[0].slot - this.lookbackSlots;
|
|
16
9
|
let runningSumFees = 0;
|
|
17
|
-
let countFees = 0;
|
|
18
10
|
for (let i = 0; i < samples.length; i++) {
|
|
19
|
-
if (samples[i].slot <= stopSlot) {
|
|
20
|
-
return runningSumFees / countFees;
|
|
21
|
-
}
|
|
22
11
|
runningSumFees += samples[i].prioritizationFee;
|
|
23
|
-
countFees++;
|
|
24
12
|
}
|
|
25
|
-
return runningSumFees /
|
|
13
|
+
return runningSumFees / samples.length;
|
|
26
14
|
}
|
|
27
15
|
}
|
|
28
16
|
exports.AverageOverSlotsStrategy = AverageOverSlotsStrategy;
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import { PriorityFeeStrategy } from './types';
|
|
2
2
|
export declare class MaxOverSlotsStrategy implements PriorityFeeStrategy {
|
|
3
|
-
private lookbackSlots;
|
|
4
|
-
/**
|
|
5
|
-
* @param lookbackSlots The number of slots to look back from the max slot in the sample
|
|
6
|
-
*/
|
|
7
|
-
constructor(lookbackSlots?: number);
|
|
8
3
|
calculate(samples: {
|
|
9
4
|
slot: number;
|
|
10
5
|
prioritizationFee: number;
|
|
@@ -2,26 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MaxOverSlotsStrategy = void 0;
|
|
4
4
|
class MaxOverSlotsStrategy {
|
|
5
|
-
/**
|
|
6
|
-
* @param lookbackSlots The number of slots to look back from the max slot in the sample
|
|
7
|
-
*/
|
|
8
|
-
constructor(lookbackSlots = 10) {
|
|
9
|
-
this.lookbackSlots = lookbackSlots;
|
|
10
|
-
}
|
|
11
5
|
calculate(samples) {
|
|
12
6
|
if (samples.length === 0) {
|
|
13
7
|
return 0;
|
|
14
8
|
}
|
|
15
9
|
// Assuming samples are sorted in descending order of slot.
|
|
16
|
-
const stopSlot = samples[0].slot - this.lookbackSlots;
|
|
17
10
|
let currMaxFee = samples[0].prioritizationFee;
|
|
18
11
|
for (let i = 0; i < samples.length; i++) {
|
|
19
|
-
|
|
20
|
-
return currMaxFee;
|
|
21
|
-
}
|
|
22
|
-
if (samples[i].prioritizationFee > currMaxFee) {
|
|
23
|
-
currMaxFee = samples[i].prioritizationFee;
|
|
24
|
-
}
|
|
12
|
+
currMaxFee = Math.max(samples[i].prioritizationFee, currMaxFee);
|
|
25
13
|
}
|
|
26
14
|
return currMaxFee;
|
|
27
15
|
}
|
|
@@ -9,13 +9,17 @@ export declare class PriorityFeeSubscriber {
|
|
|
9
9
|
customStrategy?: PriorityFeeStrategy;
|
|
10
10
|
averageStrategy: AverageOverSlotsStrategy;
|
|
11
11
|
maxStrategy: MaxOverSlotsStrategy;
|
|
12
|
+
lookbackDistance: number;
|
|
12
13
|
intervalId?: ReturnType<typeof setTimeout>;
|
|
13
14
|
latestPriorityFee: number;
|
|
14
|
-
lastStrategyResult: number;
|
|
15
15
|
lastCustomStrategyResult: number;
|
|
16
16
|
lastAvgStrategyResult: number;
|
|
17
17
|
lastMaxStrategyResult: number;
|
|
18
18
|
lastSlotSeen: number;
|
|
19
|
+
/**
|
|
20
|
+
* @param props
|
|
21
|
+
* customStrategy : strategy to return the priority fee to use based on recent samples. defaults to AVERAGE.
|
|
22
|
+
*/
|
|
19
23
|
constructor({ connection, frequencyMs, addresses, customStrategy, slotsToCheck, }: {
|
|
20
24
|
connection: Connection;
|
|
21
25
|
frequencyMs: number;
|
|
@@ -23,9 +27,6 @@ export declare class PriorityFeeSubscriber {
|
|
|
23
27
|
customStrategy?: PriorityFeeStrategy;
|
|
24
28
|
slotsToCheck?: number;
|
|
25
29
|
});
|
|
26
|
-
get avgPriorityFee(): number;
|
|
27
|
-
get maxPriorityFee(): number;
|
|
28
|
-
get customPriorityFee(): number;
|
|
29
30
|
subscribe(): Promise<void>;
|
|
30
31
|
load(): Promise<void>;
|
|
31
32
|
unsubscribe(): Promise<void>;
|
|
@@ -4,11 +4,14 @@ exports.PriorityFeeSubscriber = void 0;
|
|
|
4
4
|
const averageOverSlotsStrategy_1 = require("./averageOverSlotsStrategy");
|
|
5
5
|
const maxOverSlotsStrategy_1 = require("./maxOverSlotsStrategy");
|
|
6
6
|
class PriorityFeeSubscriber {
|
|
7
|
+
/**
|
|
8
|
+
* @param props
|
|
9
|
+
* customStrategy : strategy to return the priority fee to use based on recent samples. defaults to AVERAGE.
|
|
10
|
+
*/
|
|
7
11
|
constructor({ connection, frequencyMs, addresses, customStrategy, slotsToCheck = 10, }) {
|
|
8
12
|
this.averageStrategy = new averageOverSlotsStrategy_1.AverageOverSlotsStrategy();
|
|
9
13
|
this.maxStrategy = new maxOverSlotsStrategy_1.MaxOverSlotsStrategy();
|
|
10
14
|
this.latestPriorityFee = 0;
|
|
11
|
-
this.lastStrategyResult = 0;
|
|
12
15
|
this.lastCustomStrategyResult = 0;
|
|
13
16
|
this.lastAvgStrategyResult = 0;
|
|
14
17
|
this.lastMaxStrategyResult = 0;
|
|
@@ -16,25 +19,13 @@ class PriorityFeeSubscriber {
|
|
|
16
19
|
this.connection = connection;
|
|
17
20
|
this.frequencyMs = frequencyMs;
|
|
18
21
|
this.addresses = addresses;
|
|
19
|
-
if (
|
|
20
|
-
this.
|
|
21
|
-
this.maxStrategy = new maxOverSlotsStrategy_1.MaxOverSlotsStrategy(slotsToCheck);
|
|
22
|
+
if (!customStrategy) {
|
|
23
|
+
this.customStrategy = new averageOverSlotsStrategy_1.AverageOverSlotsStrategy();
|
|
22
24
|
}
|
|
23
|
-
|
|
25
|
+
else {
|
|
24
26
|
this.customStrategy = customStrategy;
|
|
25
27
|
}
|
|
26
|
-
|
|
27
|
-
get avgPriorityFee() {
|
|
28
|
-
return Math.floor(this.lastAvgStrategyResult);
|
|
29
|
-
}
|
|
30
|
-
get maxPriorityFee() {
|
|
31
|
-
return Math.floor(this.lastMaxStrategyResult);
|
|
32
|
-
}
|
|
33
|
-
get customPriorityFee() {
|
|
34
|
-
if (!this.customStrategy) {
|
|
35
|
-
console.error('Custom strategy not set');
|
|
36
|
-
}
|
|
37
|
-
return Math.floor(this.lastCustomStrategyResult);
|
|
28
|
+
this.lookbackDistance = slotsToCheck;
|
|
38
29
|
}
|
|
39
30
|
async subscribe() {
|
|
40
31
|
if (this.intervalId) {
|
|
@@ -45,19 +36,22 @@ class PriorityFeeSubscriber {
|
|
|
45
36
|
async load() {
|
|
46
37
|
// @ts-ignore
|
|
47
38
|
const rpcJSONResponse = await this.connection._rpcRequest('getRecentPrioritizationFees', [this.addresses]);
|
|
48
|
-
// getRecentPrioritizationFees returns results unsorted
|
|
49
39
|
const results = rpcJSONResponse === null || rpcJSONResponse === void 0 ? void 0 : rpcJSONResponse.result;
|
|
50
40
|
if (!results.length)
|
|
51
41
|
return;
|
|
42
|
+
// # Sort and filter results based on the slot lookback setting
|
|
52
43
|
const descResults = results.sort((a, b) => b.slot - a.slot);
|
|
53
44
|
const mostRecentResult = descResults[0];
|
|
45
|
+
const cutoffSlot = mostRecentResult.slot - this.lookbackDistance;
|
|
46
|
+
const resultsToUse = descResults.filter((result) => result.slot >= cutoffSlot);
|
|
47
|
+
// # Handle results
|
|
54
48
|
this.latestPriorityFee = mostRecentResult.prioritizationFee;
|
|
55
49
|
this.lastSlotSeen = mostRecentResult.slot;
|
|
56
|
-
this.lastAvgStrategyResult = this.averageStrategy.calculate(
|
|
57
|
-
this.lastMaxStrategyResult = this.maxStrategy.calculate(
|
|
50
|
+
this.lastAvgStrategyResult = this.averageStrategy.calculate(resultsToUse);
|
|
51
|
+
this.lastMaxStrategyResult = this.maxStrategy.calculate(resultsToUse);
|
|
58
52
|
if (this.customStrategy) {
|
|
59
53
|
this.lastCustomStrategyResult =
|
|
60
|
-
this.customStrategy.calculate(
|
|
54
|
+
this.customStrategy.calculate(resultsToUse);
|
|
61
55
|
}
|
|
62
56
|
}
|
|
63
57
|
async unsubscribe() {
|