@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/src/driftClient.ts
CHANGED
|
@@ -88,7 +88,7 @@ import {
|
|
|
88
88
|
DataAndSlot,
|
|
89
89
|
} from './accounts/types';
|
|
90
90
|
import { TxSender, TxSigAndSlot } from './tx/types';
|
|
91
|
-
import { wrapInTx } from './tx/utils';
|
|
91
|
+
import { getSignedTransactionMap, wrapInTx } from './tx/utils';
|
|
92
92
|
import {
|
|
93
93
|
BASE_PRECISION,
|
|
94
94
|
PRICE_PRECISION,
|
|
@@ -2565,33 +2565,26 @@ export class DriftClient {
|
|
|
2565
2565
|
txParams?: TxParams,
|
|
2566
2566
|
bracketOrdersParams = new Array<OptionalOrderParams>(),
|
|
2567
2567
|
referrerInfo?: ReferrerInfo,
|
|
2568
|
-
cancelExistingOrders?: boolean
|
|
2568
|
+
cancelExistingOrders?: boolean,
|
|
2569
|
+
settlePnl?: boolean
|
|
2569
2570
|
): Promise<{
|
|
2570
2571
|
txSig: TransactionSignature;
|
|
2571
2572
|
signedFillTx?: Transaction;
|
|
2572
2573
|
signedCancelExistingOrdersTx?: Transaction;
|
|
2574
|
+
signedSettlePnlTx?: Transaction;
|
|
2573
2575
|
}> {
|
|
2574
2576
|
const marketIndex = orderParams.marketIndex;
|
|
2575
2577
|
const orderId = userAccount.nextOrderId;
|
|
2576
|
-
const bracketOrderIxs = [];
|
|
2577
2578
|
|
|
2578
|
-
const
|
|
2579
|
-
orderParams,
|
|
2579
|
+
const ordersIx = await this.getPlaceOrdersIx(
|
|
2580
|
+
[orderParams, ...bracketOrdersParams],
|
|
2580
2581
|
userAccount.subAccountId
|
|
2581
2582
|
);
|
|
2582
2583
|
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
bracketOrderParams,
|
|
2586
|
-
userAccount.subAccountId
|
|
2587
|
-
);
|
|
2588
|
-
bracketOrderIxs.push(placeBracketOrderIx);
|
|
2589
|
-
}
|
|
2590
|
-
|
|
2591
|
-
let cancelOrdersIx: TransactionInstruction;
|
|
2592
|
-
let cancelExistingOrdersTx: Transaction;
|
|
2584
|
+
/* Cancel open orders in market if requested */
|
|
2585
|
+
let cancelExistingOrdersTx;
|
|
2593
2586
|
if (cancelExistingOrders && isVariant(orderParams.marketType, 'perp')) {
|
|
2594
|
-
cancelOrdersIx = await this.getCancelOrdersIx(
|
|
2587
|
+
const cancelOrdersIx = await this.getCancelOrdersIx(
|
|
2595
2588
|
orderParams.marketType,
|
|
2596
2589
|
orderParams.marketIndex,
|
|
2597
2590
|
null,
|
|
@@ -2606,10 +2599,27 @@ export class DriftClient {
|
|
|
2606
2599
|
);
|
|
2607
2600
|
}
|
|
2608
2601
|
|
|
2602
|
+
/* Settle PnL after fill if requested */
|
|
2603
|
+
let settlePnlTx;
|
|
2604
|
+
if (settlePnl && isVariant(orderParams.marketType, 'perp')) {
|
|
2605
|
+
const settlePnlIx = await this.settlePNLIx(
|
|
2606
|
+
userAccountPublicKey,
|
|
2607
|
+
userAccount,
|
|
2608
|
+
marketIndex
|
|
2609
|
+
);
|
|
2610
|
+
|
|
2611
|
+
//@ts-ignore
|
|
2612
|
+
settlePnlTx = await this.buildTransaction(
|
|
2613
|
+
[settlePnlIx],
|
|
2614
|
+
txParams,
|
|
2615
|
+
this.txVersion
|
|
2616
|
+
);
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2609
2619
|
// use versioned transactions if there is a lookup table account and wallet is compatible
|
|
2610
2620
|
if (this.txVersion === 0) {
|
|
2611
2621
|
const versionedMarketOrderTx = await this.buildTransaction(
|
|
2612
|
-
|
|
2622
|
+
ordersIx,
|
|
2613
2623
|
txParams,
|
|
2614
2624
|
0
|
|
2615
2625
|
);
|
|
@@ -2632,17 +2642,31 @@ export class DriftClient {
|
|
|
2632
2642
|
0
|
|
2633
2643
|
);
|
|
2634
2644
|
|
|
2635
|
-
const [
|
|
2645
|
+
const allPossibleTxs = [
|
|
2646
|
+
versionedMarketOrderTx,
|
|
2647
|
+
versionedFillTx,
|
|
2648
|
+
cancelExistingOrdersTx,
|
|
2649
|
+
settlePnlTx,
|
|
2650
|
+
];
|
|
2651
|
+
const txKeys = [
|
|
2652
|
+
'signedVersionedMarketOrderTx',
|
|
2653
|
+
'signedVersionedFillTx',
|
|
2654
|
+
'signedCancelExistingOrdersTx',
|
|
2655
|
+
'signedSettlePnlTx',
|
|
2656
|
+
];
|
|
2657
|
+
|
|
2658
|
+
const {
|
|
2636
2659
|
signedVersionedMarketOrderTx,
|
|
2637
2660
|
signedVersionedFillTx,
|
|
2638
2661
|
signedCancelExistingOrdersTx,
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2662
|
+
signedSettlePnlTx,
|
|
2663
|
+
} = await getSignedTransactionMap(
|
|
2664
|
+
//@ts-ignore
|
|
2665
|
+
this.provider.wallet,
|
|
2666
|
+
allPossibleTxs,
|
|
2667
|
+
txKeys
|
|
2645
2668
|
);
|
|
2669
|
+
|
|
2646
2670
|
const { txSig, slot } = await this.txSender.sendRawTransaction(
|
|
2647
2671
|
signedVersionedMarketOrderTx.serialize(),
|
|
2648
2672
|
this.opts
|
|
@@ -2655,18 +2679,16 @@ export class DriftClient {
|
|
|
2655
2679
|
signedFillTx: signedVersionedFillTx,
|
|
2656
2680
|
// @ts-ignore
|
|
2657
2681
|
signedCancelExistingOrdersTx,
|
|
2682
|
+
// @ts-ignore
|
|
2683
|
+
signedSettlePnlTx,
|
|
2658
2684
|
};
|
|
2659
2685
|
} else {
|
|
2660
2686
|
const marketOrderTx = wrapInTx(
|
|
2661
|
-
|
|
2687
|
+
ordersIx,
|
|
2662
2688
|
txParams?.computeUnits,
|
|
2663
2689
|
txParams?.computeUnitsPrice
|
|
2664
2690
|
);
|
|
2665
2691
|
|
|
2666
|
-
if (bracketOrderIxs.length > 0) {
|
|
2667
|
-
marketOrderTx.add(...bracketOrderIxs);
|
|
2668
|
-
}
|
|
2669
|
-
|
|
2670
2692
|
// Apply the latest blockhash to the txs so that we can sign before sending them
|
|
2671
2693
|
const currentBlockHash = (
|
|
2672
2694
|
await this.connection.getLatestBlockhash('finalized')
|
|
@@ -2680,12 +2702,33 @@ export class DriftClient {
|
|
|
2680
2702
|
cancelExistingOrdersTx.feePayer = userAccount.authority;
|
|
2681
2703
|
}
|
|
2682
2704
|
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2705
|
+
if (settlePnlTx) {
|
|
2706
|
+
settlePnlTx.recentBlockhash = currentBlockHash;
|
|
2707
|
+
settlePnlTx.feePayer = userAccount.authority;
|
|
2708
|
+
}
|
|
2709
|
+
|
|
2710
|
+
const allPossibleTxs = [
|
|
2711
|
+
marketOrderTx,
|
|
2712
|
+
cancelExistingOrdersTx,
|
|
2713
|
+
settlePnlTx,
|
|
2714
|
+
];
|
|
2715
|
+
const txKeys = [
|
|
2716
|
+
'signedMarketOrderTx',
|
|
2717
|
+
'signedCancelExistingOrdersTx',
|
|
2718
|
+
'signedSettlePnlTx',
|
|
2719
|
+
];
|
|
2720
|
+
|
|
2721
|
+
const {
|
|
2722
|
+
signedMarketOrderTx,
|
|
2723
|
+
signedCancelExistingOrdersTx,
|
|
2724
|
+
signedSettlePnlTx,
|
|
2725
|
+
} = await getSignedTransactionMap(
|
|
2726
|
+
//@ts-ignore
|
|
2727
|
+
this.provider.wallet,
|
|
2728
|
+
allPossibleTxs,
|
|
2729
|
+
txKeys
|
|
2730
|
+
);
|
|
2731
|
+
|
|
2689
2732
|
const { txSig, slot } = await this.sendTransaction(
|
|
2690
2733
|
signedMarketOrderTx,
|
|
2691
2734
|
[],
|
|
@@ -2694,7 +2737,14 @@ export class DriftClient {
|
|
|
2694
2737
|
);
|
|
2695
2738
|
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
2696
2739
|
|
|
2697
|
-
return {
|
|
2740
|
+
return {
|
|
2741
|
+
txSig,
|
|
2742
|
+
signedFillTx: undefined,
|
|
2743
|
+
//@ts-ignore
|
|
2744
|
+
signedCancelExistingOrdersTx,
|
|
2745
|
+
//@ts-ignore
|
|
2746
|
+
signedSettlePnlTx,
|
|
2747
|
+
};
|
|
2698
2748
|
}
|
|
2699
2749
|
}
|
|
2700
2750
|
|
|
@@ -3093,7 +3143,7 @@ export class DriftClient {
|
|
|
3093
3143
|
}
|
|
3094
3144
|
|
|
3095
3145
|
public async getPlaceOrdersIx(
|
|
3096
|
-
params:
|
|
3146
|
+
params: OptionalOrderParams[],
|
|
3097
3147
|
subAccountId?: number
|
|
3098
3148
|
): Promise<TransactionInstruction> {
|
|
3099
3149
|
const user = await this.getUserAccountPublicKey(subAccountId);
|
|
@@ -3118,7 +3168,9 @@ export class DriftClient {
|
|
|
3118
3168
|
useMarketLastSlotCache: true,
|
|
3119
3169
|
});
|
|
3120
3170
|
|
|
3121
|
-
|
|
3171
|
+
const formattedParams = params.map((item) => getOrderParams(item));
|
|
3172
|
+
|
|
3173
|
+
return await this.program.instruction.placeOrders(formattedParams, {
|
|
3122
3174
|
accounts: {
|
|
3123
3175
|
state: await this.getStatePublicKey(),
|
|
3124
3176
|
user,
|
|
@@ -3868,7 +3920,6 @@ export class DriftClient {
|
|
|
3868
3920
|
slippageBps,
|
|
3869
3921
|
swapMode,
|
|
3870
3922
|
onlyDirectRoutes,
|
|
3871
|
-
excludeDexes: ['Raydium CLMM'], // temp exclude to workaround bug with raydium clmm
|
|
3872
3923
|
});
|
|
3873
3924
|
|
|
3874
3925
|
quote = fetchedQuote;
|
|
@@ -4335,6 +4386,113 @@ export class DriftClient {
|
|
|
4335
4386
|
return txSig;
|
|
4336
4387
|
}
|
|
4337
4388
|
|
|
4389
|
+
public async placeAndTakePerpWithAdditionalOrders(
|
|
4390
|
+
orderParams: OptionalOrderParams,
|
|
4391
|
+
makerInfo?: MakerInfo | MakerInfo[],
|
|
4392
|
+
referrerInfo?: ReferrerInfo,
|
|
4393
|
+
bracketOrdersParams = new Array<OptionalOrderParams>(),
|
|
4394
|
+
txParams?: TxParams,
|
|
4395
|
+
subAccountId?: number,
|
|
4396
|
+
cancelExistingOrders?: boolean,
|
|
4397
|
+
settlePnl?: boolean
|
|
4398
|
+
): Promise<{
|
|
4399
|
+
txSig: TransactionSignature;
|
|
4400
|
+
signedCancelExistingOrdersTx?: Transaction;
|
|
4401
|
+
signedSettlePnlTx?: Transaction;
|
|
4402
|
+
}> {
|
|
4403
|
+
let cancelExistingOrdersTx: Transaction;
|
|
4404
|
+
if (cancelExistingOrders && isVariant(orderParams.marketType, 'perp')) {
|
|
4405
|
+
const cancelOrdersIx = await this.getCancelOrdersIx(
|
|
4406
|
+
orderParams.marketType,
|
|
4407
|
+
orderParams.marketIndex,
|
|
4408
|
+
null,
|
|
4409
|
+
subAccountId
|
|
4410
|
+
);
|
|
4411
|
+
|
|
4412
|
+
//@ts-ignore
|
|
4413
|
+
cancelExistingOrdersTx = await this.buildTransaction(
|
|
4414
|
+
[cancelOrdersIx],
|
|
4415
|
+
txParams,
|
|
4416
|
+
this.txVersion
|
|
4417
|
+
);
|
|
4418
|
+
}
|
|
4419
|
+
|
|
4420
|
+
/* Settle PnL after fill if requested */
|
|
4421
|
+
let settlePnlTx: Transaction;
|
|
4422
|
+
if (settlePnl && isVariant(orderParams.marketType, 'perp')) {
|
|
4423
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey(
|
|
4424
|
+
subAccountId
|
|
4425
|
+
);
|
|
4426
|
+
|
|
4427
|
+
const settlePnlIx = await this.settlePNLIx(
|
|
4428
|
+
userAccountPublicKey,
|
|
4429
|
+
this.getUserAccount(subAccountId),
|
|
4430
|
+
orderParams.marketIndex
|
|
4431
|
+
);
|
|
4432
|
+
|
|
4433
|
+
//@ts-ignore
|
|
4434
|
+
settlePnlTx = await this.buildTransaction(
|
|
4435
|
+
[settlePnlIx],
|
|
4436
|
+
txParams,
|
|
4437
|
+
this.txVersion
|
|
4438
|
+
);
|
|
4439
|
+
}
|
|
4440
|
+
|
|
4441
|
+
const ixs = [];
|
|
4442
|
+
|
|
4443
|
+
const placeAndTakeIx = await this.getPlaceAndTakePerpOrderIx(
|
|
4444
|
+
orderParams,
|
|
4445
|
+
makerInfo,
|
|
4446
|
+
referrerInfo,
|
|
4447
|
+
subAccountId
|
|
4448
|
+
);
|
|
4449
|
+
|
|
4450
|
+
ixs.push(placeAndTakeIx);
|
|
4451
|
+
|
|
4452
|
+
if (bracketOrdersParams.length > 0) {
|
|
4453
|
+
const bracketOrdersIx = await this.getPlaceOrdersIx(
|
|
4454
|
+
bracketOrdersParams,
|
|
4455
|
+
subAccountId
|
|
4456
|
+
);
|
|
4457
|
+
ixs.push(bracketOrdersIx);
|
|
4458
|
+
}
|
|
4459
|
+
|
|
4460
|
+
const placeAndTakeTx = await this.buildTransaction(ixs, txParams);
|
|
4461
|
+
|
|
4462
|
+
const allPossibleTxs = [
|
|
4463
|
+
placeAndTakeTx,
|
|
4464
|
+
cancelExistingOrdersTx,
|
|
4465
|
+
settlePnlTx,
|
|
4466
|
+
];
|
|
4467
|
+
const txKeys = [
|
|
4468
|
+
'signedPlaceAndTakeTx',
|
|
4469
|
+
'signedCancelExistingOrdersTx',
|
|
4470
|
+
'signedSettlePnlTx',
|
|
4471
|
+
];
|
|
4472
|
+
|
|
4473
|
+
const {
|
|
4474
|
+
signedPlaceAndTakeTx,
|
|
4475
|
+
signedCancelExistingOrdersTx,
|
|
4476
|
+
signedSettlePnlTx,
|
|
4477
|
+
} = await getSignedTransactionMap(
|
|
4478
|
+
//@ts-ignore
|
|
4479
|
+
this.provider.wallet,
|
|
4480
|
+
allPossibleTxs,
|
|
4481
|
+
txKeys
|
|
4482
|
+
);
|
|
4483
|
+
|
|
4484
|
+
const { txSig, slot } = await this.sendTransaction(
|
|
4485
|
+
signedPlaceAndTakeTx,
|
|
4486
|
+
[],
|
|
4487
|
+
this.opts,
|
|
4488
|
+
true
|
|
4489
|
+
);
|
|
4490
|
+
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
4491
|
+
|
|
4492
|
+
//@ts-ignore
|
|
4493
|
+
return { txSig, signedCancelExistingOrdersTx, signedSettlePnlTx };
|
|
4494
|
+
}
|
|
4495
|
+
|
|
4338
4496
|
public async getPlaceAndTakePerpOrderIx(
|
|
4339
4497
|
orderParams: OptionalOrderParams,
|
|
4340
4498
|
makerInfo?: MakerInfo | MakerInfo[],
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { LogProvider, logProviderCallback } from './types';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Commitment,
|
|
4
|
+
Connection,
|
|
5
|
+
Context,
|
|
6
|
+
Logs,
|
|
7
|
+
PublicKey,
|
|
8
|
+
} from '@solana/web3.js';
|
|
3
9
|
import { EventEmitter } from 'events';
|
|
4
10
|
|
|
5
11
|
export class WebSocketLogProvider implements LogProvider {
|
|
@@ -45,7 +51,7 @@ export class WebSocketLogProvider implements LogProvider {
|
|
|
45
51
|
public setSubscription(callback: logProviderCallback): void {
|
|
46
52
|
this.subscriptionId = this.connection.onLogs(
|
|
47
53
|
this.address,
|
|
48
|
-
(logs, ctx) => {
|
|
54
|
+
(logs: Logs, ctx: Context) => {
|
|
49
55
|
if (this.resubTimeoutMs && !this.isUnsubscribing) {
|
|
50
56
|
this.receivingData = true;
|
|
51
57
|
clearTimeout(this.timeoutId);
|
|
@@ -55,6 +61,9 @@ export class WebSocketLogProvider implements LogProvider {
|
|
|
55
61
|
}
|
|
56
62
|
this.reconnectAttempts = 0;
|
|
57
63
|
}
|
|
64
|
+
if (logs.err !== null) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
58
67
|
callback(logs.signature, ctx.slot, logs.logs, undefined);
|
|
59
68
|
},
|
|
60
69
|
this.commitment
|
package/src/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",
|
|
@@ -210,6 +210,12 @@ export interface QuoteResponse {
|
|
|
210
210
|
* @memberof QuoteResponse
|
|
211
211
|
*/
|
|
212
212
|
timeTaken?: number;
|
|
213
|
+
/**
|
|
214
|
+
*
|
|
215
|
+
* @type {string}
|
|
216
|
+
* @memberof QuoteResponse
|
|
217
|
+
*/
|
|
218
|
+
error?: string;
|
|
213
219
|
}
|
|
214
220
|
|
|
215
221
|
export class JupiterClient {
|
|
@@ -279,7 +285,7 @@ export class JupiterClient {
|
|
|
279
285
|
slippageBps = 50,
|
|
280
286
|
swapMode = 'ExactIn',
|
|
281
287
|
onlyDirectRoutes = false,
|
|
282
|
-
excludeDexes
|
|
288
|
+
excludeDexes,
|
|
283
289
|
}: {
|
|
284
290
|
inputMint: PublicKey;
|
|
285
291
|
outputMint: PublicKey;
|
|
@@ -298,7 +304,7 @@ export class JupiterClient {
|
|
|
298
304
|
swapMode,
|
|
299
305
|
onlyDirectRoutes: onlyDirectRoutes.toString(),
|
|
300
306
|
maxAccounts: maxAccounts.toString(),
|
|
301
|
-
excludeDexes: excludeDexes.join(','),
|
|
307
|
+
...(excludeDexes && { excludeDexes: excludeDexes.join(',') }),
|
|
302
308
|
}).toString();
|
|
303
309
|
const quote = await (await fetch(`${this.url}/v6/quote?${params}`)).json();
|
|
304
310
|
return quote;
|
package/src/math/funding.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { PerpMarketAccount, isVariant } from '../types';
|
|
|
11
11
|
import { OraclePriceData } from '../oracles/types';
|
|
12
12
|
import { calculateBidAskPrice } from './amm';
|
|
13
13
|
import { calculateLiveOracleTwap } from './oracles';
|
|
14
|
+
import { clampBN } from './utils';
|
|
14
15
|
|
|
15
16
|
function calculateLiveMarkTwap(
|
|
16
17
|
market: PerpMarketAccount,
|
|
@@ -160,8 +161,15 @@ export async function calculateAllEstimatedFundingRate(
|
|
|
160
161
|
const twapSpreadWithOffset = twapSpread.add(
|
|
161
162
|
oracleTwap.abs().div(FUNDING_RATE_OFFSET_DENOMINATOR)
|
|
162
163
|
);
|
|
164
|
+
const maxSpread = getMaxPriceDivergenceForFundingRate(market, oracleTwap);
|
|
163
165
|
|
|
164
|
-
const
|
|
166
|
+
const clampedSpreadWithOffset = clampBN(
|
|
167
|
+
twapSpreadWithOffset,
|
|
168
|
+
maxSpread.mul(new BN(-1)),
|
|
169
|
+
maxSpread
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
const twapSpreadPct = clampedSpreadWithOffset
|
|
165
173
|
.mul(PRICE_PRECISION)
|
|
166
174
|
.mul(new BN(100))
|
|
167
175
|
.div(oracleTwap);
|
|
@@ -234,6 +242,25 @@ export async function calculateAllEstimatedFundingRate(
|
|
|
234
242
|
return [markTwap, oracleTwap, lowerboundEst, cappedAltEst, interpEst];
|
|
235
243
|
}
|
|
236
244
|
|
|
245
|
+
function getMaxPriceDivergenceForFundingRate(
|
|
246
|
+
market: PerpMarketAccount,
|
|
247
|
+
oracleTwap: BN
|
|
248
|
+
) {
|
|
249
|
+
if (isVariant(market.contractTier, 'a')) {
|
|
250
|
+
return oracleTwap.divn(33);
|
|
251
|
+
} else if (isVariant(market.contractTier, 'b')) {
|
|
252
|
+
return oracleTwap.divn(33);
|
|
253
|
+
} else if (isVariant(market.contractTier, 'c')) {
|
|
254
|
+
return oracleTwap.divn(20);
|
|
255
|
+
} else if (isVariant(market.contractTier, 'speculative')) {
|
|
256
|
+
return oracleTwap.divn(10);
|
|
257
|
+
} else if (isVariant(market.contractTier, 'isolated')) {
|
|
258
|
+
return oracleTwap.divn(10);
|
|
259
|
+
} else {
|
|
260
|
+
return oracleTwap.divn(10);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
237
264
|
/**
|
|
238
265
|
*
|
|
239
266
|
* @param market
|
package/src/math/oracles.ts
CHANGED
|
@@ -47,8 +47,8 @@ export function isOracleValid(
|
|
|
47
47
|
.div(oraclePriceData.price)
|
|
48
48
|
.gt(oracleGuardRails.validity.confidenceIntervalMaxSize);
|
|
49
49
|
|
|
50
|
-
const oracleIsStale =
|
|
51
|
-
.sub(
|
|
50
|
+
const oracleIsStale = new BN(slot)
|
|
51
|
+
.sub(oraclePriceData.slot)
|
|
52
52
|
.gt(oracleGuardRails.validity.slotsBeforeStaleForAmm);
|
|
53
53
|
|
|
54
54
|
return !(
|
package/src/math/superStake.ts
CHANGED
|
@@ -333,6 +333,63 @@ export async function fetchJitoSolMetrics() {
|
|
|
333
333
|
return data;
|
|
334
334
|
}
|
|
335
335
|
|
|
336
|
+
export type MSOL_METRICS_ENDPOINT_RESPONSE = {
|
|
337
|
+
total_active_balance: number;
|
|
338
|
+
available_reserve_balance: number;
|
|
339
|
+
emergency_cooling_down: number;
|
|
340
|
+
tvl_sol: number;
|
|
341
|
+
msol_directed_stake_sol: number;
|
|
342
|
+
msol_directed_stake_msol: number;
|
|
343
|
+
mnde_total_supply: number;
|
|
344
|
+
mnde_circulating_supply: number;
|
|
345
|
+
validators_count: number;
|
|
346
|
+
stake_accounts: number;
|
|
347
|
+
staking_sol_cap: number;
|
|
348
|
+
m_sol_price: number;
|
|
349
|
+
avg_staking_apy: number;
|
|
350
|
+
msol_price_apy_14d: number;
|
|
351
|
+
msol_price_apy_30d: number;
|
|
352
|
+
msol_price_apy_90d: number;
|
|
353
|
+
msol_price_apy_365d: number;
|
|
354
|
+
reserve_pda: number;
|
|
355
|
+
treasury_m_sol_amount: number;
|
|
356
|
+
m_sol_mint_supply: number;
|
|
357
|
+
m_sol_supply_state: number;
|
|
358
|
+
liq_pool_sol: number;
|
|
359
|
+
liq_pool_m_sol: number;
|
|
360
|
+
liq_pool_value: number;
|
|
361
|
+
liq_pool_token_supply: number;
|
|
362
|
+
liq_pool_token_price: number;
|
|
363
|
+
liq_pool_target: number;
|
|
364
|
+
liq_pool_min_fee: number;
|
|
365
|
+
liq_pool_max_fee: number;
|
|
366
|
+
liq_pool_current_fee: number;
|
|
367
|
+
liq_pool_treasury_cut: number;
|
|
368
|
+
liq_pool_cap: number;
|
|
369
|
+
total_cooling_down: number;
|
|
370
|
+
last_stake_delta_epoch: number;
|
|
371
|
+
circulating_ticket_count: number;
|
|
372
|
+
circulating_ticket_balance: number;
|
|
373
|
+
reward_fee_bp: number;
|
|
374
|
+
lido_staking: number;
|
|
375
|
+
lido_st_sol_price: number;
|
|
376
|
+
lido_stsol_price_apy_14d: number;
|
|
377
|
+
lido_stsol_price_apy_30d: number;
|
|
378
|
+
lido_stsol_price_apy_90d: number;
|
|
379
|
+
lido_stsol_price_apy_365d: number;
|
|
380
|
+
stake_delta: number;
|
|
381
|
+
bot_balance: number;
|
|
382
|
+
treasury_farm_claim_mnde_balance: number;
|
|
383
|
+
last_3_epochs_avg_duration_hs: number;
|
|
384
|
+
mnde_votes_validators: number;
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
export const fetchMSolMetrics = async () => {
|
|
388
|
+
const res = await fetch('https://api2.marinade.finance/metrics_json');
|
|
389
|
+
const data: MSOL_METRICS_ENDPOINT_RESPONSE = await res.json();
|
|
390
|
+
return data;
|
|
391
|
+
};
|
|
392
|
+
|
|
336
393
|
const getJitoSolHistoricalPriceMap = async (timestamps: number[]) => {
|
|
337
394
|
try {
|
|
338
395
|
const data = await fetchJitoSolMetrics();
|
|
@@ -382,7 +439,9 @@ export async function calculateSolEarned({
|
|
|
382
439
|
const now = Date.now() / 1000;
|
|
383
440
|
const timestamps: number[] = [
|
|
384
441
|
now,
|
|
385
|
-
...depositRecords
|
|
442
|
+
...depositRecords
|
|
443
|
+
.filter((r) => r.marketIndex === marketIndex)
|
|
444
|
+
.map((r) => r.ts.toNumber()),
|
|
386
445
|
];
|
|
387
446
|
|
|
388
447
|
let lstRatios = new Map<number, number>();
|
|
@@ -1,30 +1,15 @@
|
|
|
1
1
|
import { PriorityFeeStrategy } from './types';
|
|
2
2
|
|
|
3
3
|
export class AverageOverSlotsStrategy implements PriorityFeeStrategy {
|
|
4
|
-
private lookbackSlots: number;
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @param lookbackSlots The number of slots to look back from the max slot in the sample
|
|
8
|
-
*/
|
|
9
|
-
constructor(lookbackSlots = 10) {
|
|
10
|
-
this.lookbackSlots = lookbackSlots;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
4
|
calculate(samples: { slot: number; prioritizationFee: number }[]): number {
|
|
14
5
|
if (samples.length === 0) {
|
|
15
6
|
return 0;
|
|
16
7
|
}
|
|
17
|
-
const stopSlot = samples[0].slot - this.lookbackSlots;
|
|
18
8
|
let runningSumFees = 0;
|
|
19
|
-
let countFees = 0;
|
|
20
9
|
|
|
21
10
|
for (let i = 0; i < samples.length; i++) {
|
|
22
|
-
if (samples[i].slot <= stopSlot) {
|
|
23
|
-
return runningSumFees / countFees;
|
|
24
|
-
}
|
|
25
11
|
runningSumFees += samples[i].prioritizationFee;
|
|
26
|
-
countFees++;
|
|
27
12
|
}
|
|
28
|
-
return runningSumFees /
|
|
13
|
+
return runningSumFees / samples.length;
|
|
29
14
|
}
|
|
30
15
|
}
|
|
@@ -1,30 +1,15 @@
|
|
|
1
1
|
import { PriorityFeeStrategy } from './types';
|
|
2
2
|
|
|
3
3
|
export class MaxOverSlotsStrategy implements PriorityFeeStrategy {
|
|
4
|
-
private lookbackSlots: number;
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @param lookbackSlots The number of slots to look back from the max slot in the sample
|
|
8
|
-
*/
|
|
9
|
-
constructor(lookbackSlots = 10) {
|
|
10
|
-
this.lookbackSlots = lookbackSlots;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
4
|
calculate(samples: { slot: number; prioritizationFee: number }[]): number {
|
|
14
5
|
if (samples.length === 0) {
|
|
15
6
|
return 0;
|
|
16
7
|
}
|
|
17
8
|
// Assuming samples are sorted in descending order of slot.
|
|
18
|
-
const stopSlot = samples[0].slot - this.lookbackSlots;
|
|
19
9
|
let currMaxFee = samples[0].prioritizationFee;
|
|
20
10
|
|
|
21
11
|
for (let i = 0; i < samples.length; i++) {
|
|
22
|
-
|
|
23
|
-
return currMaxFee;
|
|
24
|
-
}
|
|
25
|
-
if (samples[i].prioritizationFee > currMaxFee) {
|
|
26
|
-
currMaxFee = samples[i].prioritizationFee;
|
|
27
|
-
}
|
|
12
|
+
currMaxFee = Math.max(samples[i].prioritizationFee, currMaxFee);
|
|
28
13
|
}
|
|
29
14
|
return currMaxFee;
|
|
30
15
|
}
|