@drift-labs/sdk 2.38.1-beta.8 → 2.39.1-beta.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/VERSION +1 -1
- package/lib/adminClient.d.ts +1 -0
- package/lib/adminClient.js +11 -0
- package/lib/driftClient.d.ts +22 -2
- package/lib/driftClient.js +94 -13
- package/lib/idl/drift.json +37 -2
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/math/spotBalance.d.ts +6 -5
- package/lib/math/spotBalance.js +29 -12
- package/lib/math/spotMarket.d.ts +1 -1
- package/lib/math/spotMarket.js +2 -2
- package/lib/math/spotPosition.d.ts +16 -3
- package/lib/math/spotPosition.js +53 -9
- package/lib/oracles/strictOraclePrice.d.ts +8 -0
- package/lib/oracles/strictOraclePrice.js +17 -0
- package/lib/tx/priorityFeeCalculator.d.ts +44 -0
- package/lib/tx/priorityFeeCalculator.js +85 -0
- package/lib/types.d.ts +1 -0
- package/lib/user.d.ts +5 -4
- package/lib/user.js +71 -105
- package/package.json +1 -1
- package/src/adminClient.ts +23 -0
- package/src/driftClient.ts +170 -13
- package/src/idl/drift.json +37 -2
- package/src/index.ts +3 -0
- package/src/math/spotBalance.ts +38 -12
- package/src/math/spotMarket.ts +7 -1
- package/src/math/spotPosition.ts +133 -18
- package/src/oracles/strictOraclePrice.ts +19 -0
- package/src/tx/priorityFeeCalculator.ts +117 -0
- package/src/types.ts +1 -0
- package/src/user.ts +171 -228
- package/tests/dlob/helpers.ts +10 -7
- package/tests/tx/priorityFeeCalculator.ts +77 -0
- package/tests/user/test.ts +77 -4
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.39.1-beta.0
|
package/lib/adminClient.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export declare class AdminClient extends DriftClient {
|
|
|
38
38
|
updateSpotMarketIfFactor(spotMarketIndex: number, userIfFactor: BN, totalIfFactor: BN): Promise<TransactionSignature>;
|
|
39
39
|
updateSpotMarketRevenueSettlePeriod(spotMarketIndex: number, revenueSettlePeriod: BN): Promise<TransactionSignature>;
|
|
40
40
|
updateSpotMarketMaxTokenDeposits(spotMarketIndex: number, maxTokenDeposits: BN): Promise<TransactionSignature>;
|
|
41
|
+
updateSpotMarketScaleInitialAssetWeightStart(spotMarketIndex: number, scaleInitialAssetWeightStart: BN): Promise<TransactionSignature>;
|
|
41
42
|
updateInsuranceFundUnstakingPeriod(spotMarketIndex: number, insuranceWithdrawEscrowPeriod: BN): Promise<TransactionSignature>;
|
|
42
43
|
updateLpCooldownTime(cooldownTime: BN): Promise<TransactionSignature>;
|
|
43
44
|
updatePerpMarketOracle(perpMarketIndex: number, oracle: PublicKey, oracleSource: OracleSource): Promise<TransactionSignature>;
|
package/lib/adminClient.js
CHANGED
|
@@ -483,6 +483,17 @@ class AdminClient extends driftClient_1.DriftClient {
|
|
|
483
483
|
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
484
484
|
return txSig;
|
|
485
485
|
}
|
|
486
|
+
async updateSpotMarketScaleInitialAssetWeightStart(spotMarketIndex, scaleInitialAssetWeightStart) {
|
|
487
|
+
const tx = this.program.transaction.updateSpotMarketScaleInitialAssetWeightStart(scaleInitialAssetWeightStart, {
|
|
488
|
+
accounts: {
|
|
489
|
+
admin: this.wallet.publicKey,
|
|
490
|
+
state: await this.getStatePublicKey(),
|
|
491
|
+
spotMarket: await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex),
|
|
492
|
+
},
|
|
493
|
+
});
|
|
494
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
495
|
+
return txSig;
|
|
496
|
+
}
|
|
486
497
|
async updateInsuranceFundUnstakingPeriod(spotMarketIndex, insuranceWithdrawEscrowPeriod) {
|
|
487
498
|
const tx = await this.program.transaction.updateInsuranceFundUnstakingPeriod(insuranceWithdrawEscrowPeriod, {
|
|
488
499
|
accounts: {
|
package/lib/driftClient.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { DriftClientConfig } from './driftClientConfig';
|
|
|
13
13
|
import { User } from './user';
|
|
14
14
|
import { UserSubscriptionConfig } from './userConfig';
|
|
15
15
|
import { UserStats } from './userStats';
|
|
16
|
-
import { JupiterClient, Route, SwapMode } from './jupiter/jupiterClient';
|
|
16
|
+
import { JupiterClient, QuoteResponse, Route, SwapMode } from './jupiter/jupiterClient';
|
|
17
17
|
import { UserStatsSubscriptionConfig } from './userStatsConfig';
|
|
18
18
|
type RemainingAccountParams = {
|
|
19
19
|
userAccounts: UserAccount[];
|
|
@@ -319,7 +319,7 @@ export declare class DriftClient {
|
|
|
319
319
|
* @param reduceOnly specify if In or Out token on the drift account must reduceOnly, checked at end of swap
|
|
320
320
|
* @param txParams
|
|
321
321
|
*/
|
|
322
|
-
swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, }: {
|
|
322
|
+
swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, v6, }: {
|
|
323
323
|
jupiterClient: JupiterClient;
|
|
324
324
|
outMarketIndex: number;
|
|
325
325
|
inMarketIndex: number;
|
|
@@ -331,6 +331,9 @@ export declare class DriftClient {
|
|
|
331
331
|
route?: Route;
|
|
332
332
|
reduceOnly?: SwapReduceOnly;
|
|
333
333
|
txParams?: TxParams;
|
|
334
|
+
v6?: {
|
|
335
|
+
quote?: QuoteResponse;
|
|
336
|
+
};
|
|
334
337
|
}): Promise<TransactionSignature>;
|
|
335
338
|
getJupiterSwapIx({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, onlyDirectRoutes, route, reduceOnly, userAccountPublicKey, }: {
|
|
336
339
|
jupiterClient: JupiterClient;
|
|
@@ -349,6 +352,23 @@ export declare class DriftClient {
|
|
|
349
352
|
ixs: TransactionInstruction[];
|
|
350
353
|
lookupTables: AddressLookupTableAccount[];
|
|
351
354
|
}>;
|
|
355
|
+
getJupiterSwapIxV6({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, onlyDirectRoutes, quote, reduceOnly, userAccountPublicKey, }: {
|
|
356
|
+
jupiterClient: JupiterClient;
|
|
357
|
+
outMarketIndex: number;
|
|
358
|
+
inMarketIndex: number;
|
|
359
|
+
outAssociatedTokenAccount?: PublicKey;
|
|
360
|
+
inAssociatedTokenAccount?: PublicKey;
|
|
361
|
+
amount: BN;
|
|
362
|
+
slippageBps?: number;
|
|
363
|
+
swapMode?: SwapMode;
|
|
364
|
+
onlyDirectRoutes?: boolean;
|
|
365
|
+
quote?: QuoteResponse;
|
|
366
|
+
reduceOnly?: SwapReduceOnly;
|
|
367
|
+
userAccountPublicKey?: PublicKey;
|
|
368
|
+
}): Promise<{
|
|
369
|
+
ixs: TransactionInstruction[];
|
|
370
|
+
lookupTables: AddressLookupTableAccount[];
|
|
371
|
+
}>;
|
|
352
372
|
/**
|
|
353
373
|
* Get the drift begin_swap and end_swap instructions
|
|
354
374
|
*
|
package/lib/driftClient.js
CHANGED
|
@@ -1975,19 +1975,41 @@ class DriftClient {
|
|
|
1975
1975
|
* @param reduceOnly specify if In or Out token on the drift account must reduceOnly, checked at end of swap
|
|
1976
1976
|
* @param txParams
|
|
1977
1977
|
*/
|
|
1978
|
-
async swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, }) {
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1978
|
+
async swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, v6, }) {
|
|
1979
|
+
let ixs;
|
|
1980
|
+
let lookupTables;
|
|
1981
|
+
if (v6) {
|
|
1982
|
+
const res = await this.getJupiterSwapIxV6({
|
|
1983
|
+
jupiterClient,
|
|
1984
|
+
outMarketIndex,
|
|
1985
|
+
inMarketIndex,
|
|
1986
|
+
outAssociatedTokenAccount,
|
|
1987
|
+
inAssociatedTokenAccount,
|
|
1988
|
+
amount,
|
|
1989
|
+
slippageBps,
|
|
1990
|
+
swapMode,
|
|
1991
|
+
quote: v6.quote,
|
|
1992
|
+
reduceOnly,
|
|
1993
|
+
});
|
|
1994
|
+
ixs = res.ixs;
|
|
1995
|
+
lookupTables = res.lookupTables;
|
|
1996
|
+
}
|
|
1997
|
+
else {
|
|
1998
|
+
const res = await this.getJupiterSwapIx({
|
|
1999
|
+
jupiterClient,
|
|
2000
|
+
outMarketIndex,
|
|
2001
|
+
inMarketIndex,
|
|
2002
|
+
outAssociatedTokenAccount,
|
|
2003
|
+
inAssociatedTokenAccount,
|
|
2004
|
+
amount,
|
|
2005
|
+
slippageBps,
|
|
2006
|
+
swapMode,
|
|
2007
|
+
route,
|
|
2008
|
+
reduceOnly,
|
|
2009
|
+
});
|
|
2010
|
+
ixs = res.ixs;
|
|
2011
|
+
lookupTables = res.lookupTables;
|
|
2012
|
+
}
|
|
1991
2013
|
const tx = (await this.buildTransaction(ixs, txParams, 0, lookupTables));
|
|
1992
2014
|
const { txSig, slot } = await this.sendTransaction(tx);
|
|
1993
2015
|
this.spotMarketLastSlotCache.set(outMarketIndex, slot);
|
|
@@ -2056,6 +2078,65 @@ class DriftClient {
|
|
|
2056
2078
|
];
|
|
2057
2079
|
return { ixs, lookupTables };
|
|
2058
2080
|
}
|
|
2081
|
+
async getJupiterSwapIxV6({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, onlyDirectRoutes, quote, reduceOnly, userAccountPublicKey, }) {
|
|
2082
|
+
const outMarket = this.getSpotMarketAccount(outMarketIndex);
|
|
2083
|
+
const inMarket = this.getSpotMarketAccount(inMarketIndex);
|
|
2084
|
+
if (!quote) {
|
|
2085
|
+
const fetchedQuote = await jupiterClient.getQuote({
|
|
2086
|
+
inputMint: inMarket.mint,
|
|
2087
|
+
outputMint: outMarket.mint,
|
|
2088
|
+
amount,
|
|
2089
|
+
slippageBps,
|
|
2090
|
+
swapMode,
|
|
2091
|
+
onlyDirectRoutes,
|
|
2092
|
+
});
|
|
2093
|
+
quote = fetchedQuote;
|
|
2094
|
+
}
|
|
2095
|
+
const transaction = await jupiterClient.getSwap({
|
|
2096
|
+
quote,
|
|
2097
|
+
userPublicKey: this.provider.wallet.publicKey,
|
|
2098
|
+
slippageBps,
|
|
2099
|
+
});
|
|
2100
|
+
const { transactionMessage, lookupTables } = await jupiterClient.getTransactionMessageAndLookupTables({
|
|
2101
|
+
transaction,
|
|
2102
|
+
});
|
|
2103
|
+
const jupiterInstructions = jupiterClient.getJupiterInstructions({
|
|
2104
|
+
transactionMessage,
|
|
2105
|
+
inputMint: inMarket.mint,
|
|
2106
|
+
outputMint: outMarket.mint,
|
|
2107
|
+
});
|
|
2108
|
+
const preInstructions = [];
|
|
2109
|
+
if (!outAssociatedTokenAccount) {
|
|
2110
|
+
outAssociatedTokenAccount = await this.getAssociatedTokenAccount(outMarket.marketIndex, false);
|
|
2111
|
+
const accountInfo = await this.connection.getAccountInfo(outAssociatedTokenAccount);
|
|
2112
|
+
if (!accountInfo) {
|
|
2113
|
+
preInstructions.push(this.createAssociatedTokenAccountIdempotentInstruction(outAssociatedTokenAccount, this.provider.wallet.publicKey, this.provider.wallet.publicKey, outMarket.mint));
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
if (!inAssociatedTokenAccount) {
|
|
2117
|
+
inAssociatedTokenAccount = await this.getAssociatedTokenAccount(inMarket.marketIndex, false);
|
|
2118
|
+
const accountInfo = await this.connection.getAccountInfo(inAssociatedTokenAccount);
|
|
2119
|
+
if (!accountInfo) {
|
|
2120
|
+
preInstructions.push(this.createAssociatedTokenAccountIdempotentInstruction(inAssociatedTokenAccount, this.provider.wallet.publicKey, this.provider.wallet.publicKey, inMarket.mint));
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
const { beginSwapIx, endSwapIx } = await this.getSwapIx({
|
|
2124
|
+
outMarketIndex,
|
|
2125
|
+
inMarketIndex,
|
|
2126
|
+
amountIn: amount,
|
|
2127
|
+
inTokenAccount: inAssociatedTokenAccount,
|
|
2128
|
+
outTokenAccount: outAssociatedTokenAccount,
|
|
2129
|
+
reduceOnly,
|
|
2130
|
+
userAccountPublicKey,
|
|
2131
|
+
});
|
|
2132
|
+
const ixs = [
|
|
2133
|
+
...preInstructions,
|
|
2134
|
+
beginSwapIx,
|
|
2135
|
+
...jupiterInstructions,
|
|
2136
|
+
endSwapIx,
|
|
2137
|
+
];
|
|
2138
|
+
return { ixs, lookupTables };
|
|
2139
|
+
}
|
|
2059
2140
|
/**
|
|
2060
2141
|
* Get the drift begin_swap and end_swap instructions
|
|
2061
2142
|
*
|
package/lib/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.39.0",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -3538,6 +3538,32 @@
|
|
|
3538
3538
|
}
|
|
3539
3539
|
]
|
|
3540
3540
|
},
|
|
3541
|
+
{
|
|
3542
|
+
"name": "updateSpotMarketScaleInitialAssetWeightStart",
|
|
3543
|
+
"accounts": [
|
|
3544
|
+
{
|
|
3545
|
+
"name": "admin",
|
|
3546
|
+
"isMut": false,
|
|
3547
|
+
"isSigner": true
|
|
3548
|
+
},
|
|
3549
|
+
{
|
|
3550
|
+
"name": "state",
|
|
3551
|
+
"isMut": false,
|
|
3552
|
+
"isSigner": false
|
|
3553
|
+
},
|
|
3554
|
+
{
|
|
3555
|
+
"name": "spotMarket",
|
|
3556
|
+
"isMut": true,
|
|
3557
|
+
"isSigner": false
|
|
3558
|
+
}
|
|
3559
|
+
],
|
|
3560
|
+
"args": [
|
|
3561
|
+
{
|
|
3562
|
+
"name": "scaleInitialAssetWeightStart",
|
|
3563
|
+
"type": "u64"
|
|
3564
|
+
}
|
|
3565
|
+
]
|
|
3566
|
+
},
|
|
3541
3567
|
{
|
|
3542
3568
|
"name": "updateSpotMarketOracle",
|
|
3543
3569
|
"accounts": [
|
|
@@ -5357,12 +5383,21 @@
|
|
|
5357
5383
|
],
|
|
5358
5384
|
"type": "u64"
|
|
5359
5385
|
},
|
|
5386
|
+
{
|
|
5387
|
+
"name": "scaleInitialAssetWeightStart",
|
|
5388
|
+
"docs": [
|
|
5389
|
+
"When to begin scaling down the initial asset weight",
|
|
5390
|
+
"disabled when 0",
|
|
5391
|
+
"precision: QUOTE_PRECISION"
|
|
5392
|
+
],
|
|
5393
|
+
"type": "u64"
|
|
5394
|
+
},
|
|
5360
5395
|
{
|
|
5361
5396
|
"name": "padding",
|
|
5362
5397
|
"type": {
|
|
5363
5398
|
"array": [
|
|
5364
5399
|
"u8",
|
|
5365
|
-
|
|
5400
|
+
48
|
|
5366
5401
|
]
|
|
5367
5402
|
}
|
|
5368
5403
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import pyth from '@pythnetwork/client';
|
|
|
4
4
|
export * from './tokenFaucet';
|
|
5
5
|
export * from './oracles/types';
|
|
6
6
|
export * from './oracles/pythClient';
|
|
7
|
+
export * from './oracles/strictOraclePrice';
|
|
7
8
|
export * from './types';
|
|
8
9
|
export * from './constants/perpMarkets';
|
|
9
10
|
export * from './accounts/fetch';
|
|
@@ -48,6 +49,7 @@ export * from './math/repeg';
|
|
|
48
49
|
export * from './math/margin';
|
|
49
50
|
export * from './math/insurance';
|
|
50
51
|
export * from './math/superStake';
|
|
52
|
+
export * from './math/spotPosition';
|
|
51
53
|
export * from './marinade';
|
|
52
54
|
export * from './orderParams';
|
|
53
55
|
export * from './slot/SlotSubscriber';
|
|
@@ -63,6 +65,7 @@ export * from './priorityFee/priorityFeeSubscriber';
|
|
|
63
65
|
export * from './phoenix/phoenixFulfillmentConfigMap';
|
|
64
66
|
export * from './tx/fastSingleTxSender';
|
|
65
67
|
export * from './tx/retryTxSender';
|
|
68
|
+
export * from './tx/priorityFeeCalculator';
|
|
66
69
|
export * from './tx/types';
|
|
67
70
|
export * from './util/computeUnits';
|
|
68
71
|
export * from './util/tps';
|
package/lib/index.js
CHANGED
|
@@ -27,6 +27,7 @@ exports.pyth = client_1.default;
|
|
|
27
27
|
__exportStar(require("./tokenFaucet"), exports);
|
|
28
28
|
__exportStar(require("./oracles/types"), exports);
|
|
29
29
|
__exportStar(require("./oracles/pythClient"), exports);
|
|
30
|
+
__exportStar(require("./oracles/strictOraclePrice"), exports);
|
|
30
31
|
__exportStar(require("./types"), exports);
|
|
31
32
|
__exportStar(require("./constants/perpMarkets"), exports);
|
|
32
33
|
__exportStar(require("./accounts/fetch"), exports);
|
|
@@ -71,6 +72,7 @@ __exportStar(require("./math/repeg"), exports);
|
|
|
71
72
|
__exportStar(require("./math/margin"), exports);
|
|
72
73
|
__exportStar(require("./math/insurance"), exports);
|
|
73
74
|
__exportStar(require("./math/superStake"), exports);
|
|
75
|
+
__exportStar(require("./math/spotPosition"), exports);
|
|
74
76
|
__exportStar(require("./marinade"), exports);
|
|
75
77
|
__exportStar(require("./orderParams"), exports);
|
|
76
78
|
__exportStar(require("./slot/SlotSubscriber"), exports);
|
|
@@ -86,6 +88,7 @@ __exportStar(require("./priorityFee/priorityFeeSubscriber"), exports);
|
|
|
86
88
|
__exportStar(require("./phoenix/phoenixFulfillmentConfigMap"), exports);
|
|
87
89
|
__exportStar(require("./tx/fastSingleTxSender"), exports);
|
|
88
90
|
__exportStar(require("./tx/retryTxSender"), exports);
|
|
91
|
+
__exportStar(require("./tx/priorityFeeCalculator"), exports);
|
|
89
92
|
__exportStar(require("./tx/types"), exports);
|
|
90
93
|
__exportStar(require("./util/computeUnits"), exports);
|
|
91
94
|
__exportStar(require("./util/tps"), exports);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SpotMarketAccount, SpotBalanceType, MarginCategory } from '../types';
|
|
2
2
|
import { BN } from '@coral-xyz/anchor';
|
|
3
3
|
import { OraclePriceData } from '../oracles/types';
|
|
4
|
+
import { StrictOraclePrice } from '../oracles/strictOraclePrice';
|
|
4
5
|
/**
|
|
5
6
|
* Calculates the balance of a given token amount including any accumulated interest. This
|
|
6
7
|
* is the same as `SpotPosition.scaledBalance`.
|
|
@@ -33,11 +34,10 @@ export declare function getSignedTokenAmount(tokenAmount: BN, balanceType: SpotB
|
|
|
33
34
|
*
|
|
34
35
|
* @param {BN} tokenAmount - The amount of tokens to calculate the value for (from `getTokenAmount`)
|
|
35
36
|
* @param {number} spotDecimals - The number of decimals in the token.
|
|
36
|
-
* @param {
|
|
37
|
-
* @param {BN} oraclePriceTwap - The Time-Weighted Average Price of the oracle.
|
|
37
|
+
* @param {StrictOraclePrice} strictOraclePrice - Contains oracle price and 5min twap.
|
|
38
38
|
* @return {BN} The calculated value of the given token amount, scaled by `PRICE_PRECISION`
|
|
39
39
|
*/
|
|
40
|
-
export declare function getStrictTokenValue(tokenAmount: BN, spotDecimals: number,
|
|
40
|
+
export declare function getStrictTokenValue(tokenAmount: BN, spotDecimals: number, strictOraclePrice: StrictOraclePrice): BN;
|
|
41
41
|
/**
|
|
42
42
|
* Calculates the value of a given token amount in relation to an oracle price data
|
|
43
43
|
*
|
|
@@ -46,8 +46,9 @@ export declare function getStrictTokenValue(tokenAmount: BN, spotDecimals: numbe
|
|
|
46
46
|
* @param {OraclePriceData} oraclePriceData - The oracle price data (typically a token/USD oracle).
|
|
47
47
|
* @return {BN} The value of the token based on the oracle, scaled by `PRICE_PRECISION`
|
|
48
48
|
*/
|
|
49
|
-
export declare function getTokenValue(tokenAmount: BN, spotDecimals: number, oraclePriceData: OraclePriceData): BN;
|
|
50
|
-
export declare function calculateAssetWeight(balanceAmount: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
|
|
49
|
+
export declare function getTokenValue(tokenAmount: BN, spotDecimals: number, oraclePriceData: Pick<OraclePriceData, 'price'>): BN;
|
|
50
|
+
export declare function calculateAssetWeight(balanceAmount: BN, oraclePrice: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
|
|
51
|
+
export declare function calculateScaledInitialAssetWeight(spotMarket: SpotMarketAccount, oraclePrice: BN): BN;
|
|
51
52
|
export declare function calculateLiabilityWeight(size: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
|
|
52
53
|
export declare function calculateUtilization(bank: SpotMarketAccount, delta?: any): BN;
|
|
53
54
|
/**
|
package/lib/math/spotBalance.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateWithdrawLimit = exports.calculateTokenUtilizationLimits = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateSpotMarketBorrowCapacity = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateAssetWeight = exports.getTokenValue = exports.getStrictTokenValue = exports.getSignedTokenAmount = exports.getTokenAmount = exports.getBalance = void 0;
|
|
3
|
+
exports.calculateWithdrawLimit = exports.calculateTokenUtilizationLimits = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateSpotMarketBorrowCapacity = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateScaledInitialAssetWeight = exports.calculateAssetWeight = exports.getTokenValue = exports.getStrictTokenValue = exports.getSignedTokenAmount = exports.getTokenAmount = exports.getBalance = void 0;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
5
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
6
6
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
@@ -69,20 +69,19 @@ exports.getSignedTokenAmount = getSignedTokenAmount;
|
|
|
69
69
|
*
|
|
70
70
|
* @param {BN} tokenAmount - The amount of tokens to calculate the value for (from `getTokenAmount`)
|
|
71
71
|
* @param {number} spotDecimals - The number of decimals in the token.
|
|
72
|
-
* @param {
|
|
73
|
-
* @param {BN} oraclePriceTwap - The Time-Weighted Average Price of the oracle.
|
|
72
|
+
* @param {StrictOraclePrice} strictOraclePrice - Contains oracle price and 5min twap.
|
|
74
73
|
* @return {BN} The calculated value of the given token amount, scaled by `PRICE_PRECISION`
|
|
75
74
|
*/
|
|
76
|
-
function getStrictTokenValue(tokenAmount, spotDecimals,
|
|
75
|
+
function getStrictTokenValue(tokenAmount, spotDecimals, strictOraclePrice) {
|
|
77
76
|
if (tokenAmount.eq(numericConstants_1.ZERO)) {
|
|
78
77
|
return numericConstants_1.ZERO;
|
|
79
78
|
}
|
|
80
|
-
let price
|
|
81
|
-
if (tokenAmount.
|
|
82
|
-
price =
|
|
79
|
+
let price;
|
|
80
|
+
if (tokenAmount.gte(numericConstants_1.ZERO)) {
|
|
81
|
+
price = strictOraclePrice.min();
|
|
83
82
|
}
|
|
84
83
|
else {
|
|
85
|
-
price =
|
|
84
|
+
price = strictOraclePrice.max();
|
|
86
85
|
}
|
|
87
86
|
const precisionDecrease = numericConstants_1.TEN.pow(new anchor_1.BN(spotDecimals));
|
|
88
87
|
return tokenAmount.mul(price).div(precisionDecrease);
|
|
@@ -104,7 +103,7 @@ function getTokenValue(tokenAmount, spotDecimals, oraclePriceData) {
|
|
|
104
103
|
return tokenAmount.mul(oraclePriceData.price).div(precisionDecrease);
|
|
105
104
|
}
|
|
106
105
|
exports.getTokenValue = getTokenValue;
|
|
107
|
-
function calculateAssetWeight(balanceAmount, spotMarket, marginCategory) {
|
|
106
|
+
function calculateAssetWeight(balanceAmount, oraclePrice, spotMarket, marginCategory) {
|
|
108
107
|
const sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(spotMarket.decimals));
|
|
109
108
|
let sizeInAmmReservePrecision;
|
|
110
109
|
if (sizePrecision.gt(numericConstants_1.AMM_RESERVE_PRECISION)) {
|
|
@@ -118,18 +117,36 @@ function calculateAssetWeight(balanceAmount, spotMarket, marginCategory) {
|
|
|
118
117
|
let assetWeight;
|
|
119
118
|
switch (marginCategory) {
|
|
120
119
|
case 'Initial':
|
|
121
|
-
assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor),
|
|
120
|
+
assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), calculateScaledInitialAssetWeight(spotMarket, oraclePrice));
|
|
122
121
|
break;
|
|
123
122
|
case 'Maintenance':
|
|
124
123
|
assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), new anchor_1.BN(spotMarket.maintenanceAssetWeight));
|
|
125
124
|
break;
|
|
126
125
|
default:
|
|
127
|
-
assetWeight =
|
|
126
|
+
assetWeight = calculateScaledInitialAssetWeight(spotMarket, oraclePrice);
|
|
128
127
|
break;
|
|
129
128
|
}
|
|
130
129
|
return assetWeight;
|
|
131
130
|
}
|
|
132
131
|
exports.calculateAssetWeight = calculateAssetWeight;
|
|
132
|
+
function calculateScaledInitialAssetWeight(spotMarket, oraclePrice) {
|
|
133
|
+
if (spotMarket.scaleInitialAssetWeightStart.eq(numericConstants_1.ZERO)) {
|
|
134
|
+
return new anchor_1.BN(spotMarket.initialAssetWeight);
|
|
135
|
+
}
|
|
136
|
+
const deposits = getTokenAmount(spotMarket.depositBalance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
|
|
137
|
+
const depositsValue = getTokenValue(deposits, spotMarket.decimals, {
|
|
138
|
+
price: oraclePrice,
|
|
139
|
+
});
|
|
140
|
+
if (depositsValue.lt(spotMarket.scaleInitialAssetWeightStart)) {
|
|
141
|
+
return new anchor_1.BN(spotMarket.initialAssetWeight);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
return new anchor_1.BN(spotMarket.initialAssetWeight)
|
|
145
|
+
.mul(spotMarket.scaleInitialAssetWeightStart)
|
|
146
|
+
.div(depositsValue);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.calculateScaledInitialAssetWeight = calculateScaledInitialAssetWeight;
|
|
133
150
|
function calculateLiabilityWeight(size, spotMarket, marginCategory) {
|
|
134
151
|
const sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(spotMarket.decimals));
|
|
135
152
|
let sizeInAmmReservePrecision;
|
|
@@ -150,7 +167,7 @@ function calculateLiabilityWeight(size, spotMarket, marginCategory) {
|
|
|
150
167
|
liabilityWeight = (0, margin_1.calculateSizePremiumLiabilityWeight)(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), new anchor_1.BN(spotMarket.maintenanceLiabilityWeight), numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
151
168
|
break;
|
|
152
169
|
default:
|
|
153
|
-
liabilityWeight = spotMarket.initialLiabilityWeight;
|
|
170
|
+
liabilityWeight = new anchor_1.BN(spotMarket.initialLiabilityWeight);
|
|
154
171
|
break;
|
|
155
172
|
}
|
|
156
173
|
return liabilityWeight;
|
package/lib/math/spotMarket.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { BN } from '@coral-xyz/anchor';
|
|
2
2
|
import { MarginCategory, SpotBalanceType, SpotMarketAccount } from '../types';
|
|
3
3
|
export declare function castNumberToSpotPrecision(value: number | BN, spotMarket: SpotMarketAccount): BN;
|
|
4
|
-
export declare function calculateSpotMarketMarginRatio(market: SpotMarketAccount, marginCategory: MarginCategory, size: BN, balanceType: SpotBalanceType): number;
|
|
4
|
+
export declare function calculateSpotMarketMarginRatio(market: SpotMarketAccount, oraclePrice: BN, marginCategory: MarginCategory, size: BN, balanceType: SpotBalanceType): number;
|
package/lib/math/spotMarket.js
CHANGED
|
@@ -14,9 +14,9 @@ function castNumberToSpotPrecision(value, spotMarket) {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
exports.castNumberToSpotPrecision = castNumberToSpotPrecision;
|
|
17
|
-
function calculateSpotMarketMarginRatio(market, marginCategory, size, balanceType) {
|
|
17
|
+
function calculateSpotMarketMarginRatio(market, oraclePrice, marginCategory, size, balanceType) {
|
|
18
18
|
if ((0, types_1.isVariant)(balanceType, 'deposit')) {
|
|
19
|
-
const assetWeight = (0, spotBalance_1.calculateAssetWeight)(size, market, marginCategory);
|
|
19
|
+
const assetWeight = (0, spotBalance_1.calculateAssetWeight)(size, oraclePrice, market, marginCategory);
|
|
20
20
|
return numericConstants_1.MARGIN_PRECISION.sub(assetWeight).toNumber();
|
|
21
21
|
}
|
|
22
22
|
else {
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
import { SpotMarketAccount, SpotPosition } from '../types';
|
|
1
|
+
import { MarginCategory, SpotMarketAccount, SpotPosition } from '../types';
|
|
2
2
|
import { BN } from '@coral-xyz/anchor';
|
|
3
|
-
import {
|
|
3
|
+
import { StrictOraclePrice } from '../oracles/strictOraclePrice';
|
|
4
4
|
export declare function isSpotPositionAvailable(position: SpotPosition): boolean;
|
|
5
|
-
export
|
|
5
|
+
export type OrderFillSimulation = {
|
|
6
|
+
tokenAmount: BN;
|
|
7
|
+
ordersValue: BN;
|
|
8
|
+
tokenValue: BN;
|
|
9
|
+
weight: BN;
|
|
10
|
+
weightedTokenValue: BN;
|
|
11
|
+
freeCollateralContribution: any;
|
|
12
|
+
};
|
|
13
|
+
export declare function getWorstCaseTokenAmounts(spotPosition: SpotPosition, spotMarketAccount: SpotMarketAccount, strictOraclePrice: StrictOraclePrice, marginCategory: MarginCategory): OrderFillSimulation;
|
|
14
|
+
export declare function calculateWeightedTokenValue(tokenAmount: BN, tokenValue: BN, oraclePrice: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): {
|
|
15
|
+
weight: BN;
|
|
16
|
+
weightedTokenValue: BN;
|
|
17
|
+
};
|
|
18
|
+
export declare function simulateOrderFill(tokenAmount: BN, tokenValue: BN, openOrders: BN, strictOraclePrice: StrictOraclePrice, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): OrderFillSimulation;
|
package/lib/math/spotPosition.js
CHANGED
|
@@ -1,23 +1,67 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getWorstCaseTokenAmounts = exports.isSpotPositionAvailable = void 0;
|
|
3
|
+
exports.simulateOrderFill = exports.calculateWeightedTokenValue = exports.getWorstCaseTokenAmounts = exports.isSpotPositionAvailable = void 0;
|
|
4
4
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
5
5
|
const spotBalance_1 = require("./spotBalance");
|
|
6
6
|
function isSpotPositionAvailable(position) {
|
|
7
7
|
return position.scaledBalance.eq(numericConstants_1.ZERO) && position.openOrders === 0;
|
|
8
8
|
}
|
|
9
9
|
exports.isSpotPositionAvailable = isSpotPositionAvailable;
|
|
10
|
-
function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount,
|
|
10
|
+
function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory) {
|
|
11
11
|
const tokenAmount = (0, spotBalance_1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
const tokenValue = (0, spotBalance_1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
|
|
13
|
+
if (spotPosition.openBids.eq(numericConstants_1.ZERO) && spotPosition.openAsks.eq(numericConstants_1.ZERO)) {
|
|
14
|
+
const { weight, weightedTokenValue } = calculateWeightedTokenValue(tokenAmount, tokenValue, strictOraclePrice.current, spotMarketAccount, marginCategory);
|
|
15
|
+
return {
|
|
16
|
+
tokenAmount,
|
|
17
|
+
ordersValue: numericConstants_1.ZERO,
|
|
18
|
+
tokenValue,
|
|
19
|
+
weight,
|
|
20
|
+
weightedTokenValue,
|
|
21
|
+
freeCollateralContribution: weightedTokenValue,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const bidsSimulation = simulateOrderFill(tokenAmount, tokenValue, spotPosition.openBids, strictOraclePrice, spotMarketAccount, marginCategory);
|
|
25
|
+
const asksSimulation = simulateOrderFill(tokenAmount, tokenValue, spotPosition.openAsks, strictOraclePrice, spotMarketAccount, marginCategory);
|
|
26
|
+
if (asksSimulation.freeCollateralContribution.lt(bidsSimulation.freeCollateralContribution)) {
|
|
27
|
+
return asksSimulation;
|
|
17
28
|
}
|
|
18
29
|
else {
|
|
19
|
-
|
|
20
|
-
return [tokenAmountAllAsksFill, worstCaseQuoteTokenAmount];
|
|
30
|
+
return bidsSimulation;
|
|
21
31
|
}
|
|
22
32
|
}
|
|
23
33
|
exports.getWorstCaseTokenAmounts = getWorstCaseTokenAmounts;
|
|
34
|
+
function calculateWeightedTokenValue(tokenAmount, tokenValue, oraclePrice, spotMarket, marginCategory) {
|
|
35
|
+
let weight;
|
|
36
|
+
if (tokenValue.gte(numericConstants_1.ZERO)) {
|
|
37
|
+
weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, oraclePrice, spotMarket, marginCategory);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
weight = (0, spotBalance_1.calculateLiabilityWeight)(tokenAmount.abs(), spotMarket, marginCategory);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
weight: weight,
|
|
44
|
+
weightedTokenValue: tokenValue
|
|
45
|
+
.mul(weight)
|
|
46
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
exports.calculateWeightedTokenValue = calculateWeightedTokenValue;
|
|
50
|
+
function simulateOrderFill(tokenAmount, tokenValue, openOrders, strictOraclePrice, spotMarket, marginCategory) {
|
|
51
|
+
const ordersValue = (0, spotBalance_1.getTokenValue)(openOrders.neg(), spotMarket.decimals, {
|
|
52
|
+
price: strictOraclePrice.max(),
|
|
53
|
+
});
|
|
54
|
+
const tokenAmountAfterFill = tokenAmount.add(openOrders);
|
|
55
|
+
const tokenValueAfterFill = tokenValue.add(ordersValue.neg());
|
|
56
|
+
const { weight, weightedTokenValue: weightedTokenValueAfterFill } = calculateWeightedTokenValue(tokenAmountAfterFill, tokenValueAfterFill, strictOraclePrice.current, spotMarket, marginCategory);
|
|
57
|
+
const freeCollateralContribution = weightedTokenValueAfterFill.add(ordersValue);
|
|
58
|
+
return {
|
|
59
|
+
tokenAmount: tokenAmountAfterFill,
|
|
60
|
+
ordersValue: ordersValue,
|
|
61
|
+
tokenValue: tokenValueAfterFill,
|
|
62
|
+
weight,
|
|
63
|
+
weightedTokenValue: weightedTokenValueAfterFill,
|
|
64
|
+
freeCollateralContribution,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
exports.simulateOrderFill = simulateOrderFill;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StrictOraclePrice = void 0;
|
|
4
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
5
|
+
class StrictOraclePrice {
|
|
6
|
+
constructor(current, twap) {
|
|
7
|
+
this.current = current;
|
|
8
|
+
this.twap = twap;
|
|
9
|
+
}
|
|
10
|
+
max() {
|
|
11
|
+
return this.twap ? anchor_1.BN.max(this.twap, this.current) : this.current;
|
|
12
|
+
}
|
|
13
|
+
min() {
|
|
14
|
+
return this.twap ? anchor_1.BN.min(this.twap, this.current) : this.current;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.StrictOraclePrice = StrictOraclePrice;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { TransactionInstruction } from '@solana/web3.js';
|
|
2
|
+
/**
|
|
3
|
+
* This class determines whether a priority fee needs to be included in a transaction based on
|
|
4
|
+
* a recent history of timed out transactions.
|
|
5
|
+
*/
|
|
6
|
+
export declare class PriorityFeeCalculator {
|
|
7
|
+
lastTxTimeoutCount: number;
|
|
8
|
+
priorityFeeTriggered: boolean;
|
|
9
|
+
lastTxTimeoutCountTriggered: number;
|
|
10
|
+
priorityFeeLatchDurationMs: number;
|
|
11
|
+
/**
|
|
12
|
+
* Constructor for the PriorityFeeCalculator class.
|
|
13
|
+
* @param currentTimeMs - The current time in milliseconds.
|
|
14
|
+
* @param priorityFeeLatchDurationMs - The duration for how long to stay in triggered state before resetting. Default value is 10 seconds.
|
|
15
|
+
*/
|
|
16
|
+
constructor(currentTimeMs: number, priorityFeeLatchDurationMs?: number);
|
|
17
|
+
/**
|
|
18
|
+
* Update the priority fee state based on the current time and the current timeout count.
|
|
19
|
+
* @param currentTimeMs current time in milliseconds
|
|
20
|
+
* @returns true if priority fee should be included in the next transaction
|
|
21
|
+
*/
|
|
22
|
+
updatePriorityFee(currentTimeMs: number, txTimeoutCount: number): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* This method returns a transaction instruction list that sets the compute limit on the ComputeBudget program.
|
|
25
|
+
* @param computeUnitLimit - The maximum number of compute units that can be used by the transaction.
|
|
26
|
+
* @returns An array of transaction instructions.
|
|
27
|
+
*/
|
|
28
|
+
generateComputeBudgetIxs(computeUnitLimit: number): Array<TransactionInstruction>;
|
|
29
|
+
/**
|
|
30
|
+
* Calculates the compute unit price to use based on the desired additional fee to pay and the compute unit limit.
|
|
31
|
+
* @param computeUnitLimit desired CU to use
|
|
32
|
+
* @param additionalFeeMicroLamports desired additional fee to pay, in micro lamports
|
|
33
|
+
* @returns the compute unit price to use, in micro lamports
|
|
34
|
+
*/
|
|
35
|
+
calculateComputeUnitPrice(computeUnitLimit: number, additionalFeeMicroLamports: number): number;
|
|
36
|
+
/**
|
|
37
|
+
* This method generates a list of transaction instructions for the ComputeBudget program, and includes a priority fee if it's required
|
|
38
|
+
* @param computeUnitLimit - The maximum number of compute units that can be used by the transaction.
|
|
39
|
+
* @param usePriorityFee - A boolean indicating whether to include a priority fee in the transaction, this should be from `this.updatePriorityFee()` or `this.priorityFeeTriggered()`.
|
|
40
|
+
* @param additionalFeeMicroLamports - The additional fee to be paid, in micro lamports, the actual price will be calculated.
|
|
41
|
+
* @returns An array of transaction instructions.
|
|
42
|
+
*/
|
|
43
|
+
generateComputeBudgetWithPriorityFeeIx(computeUnitLimit: number, usePriorityFee: boolean, additionalFeeMicroLamports: number): Array<TransactionInstruction>;
|
|
44
|
+
}
|