@drift-labs/sdk 2.38.1-beta.1 → 2.38.1-beta.11
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/fetch.js +2 -2
- package/lib/accounts/pollingDriftClientAccountSubscriber.js +2 -14
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +2 -2
- package/lib/adminClient.d.ts +1 -0
- package/lib/adminClient.js +11 -0
- package/lib/config.d.ts +1 -0
- package/lib/config.js +2 -0
- package/lib/driftClient.d.ts +22 -2
- package/lib/driftClient.js +101 -15
- package/lib/examples/loadDlob.js +3 -1
- package/lib/examples/makeTradeExample.js +3 -1
- package/lib/idl/drift.json +36 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/jupiter/jupiterClient.d.ts +197 -0
- package/lib/jupiter/jupiterClient.js +48 -3
- 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/priorityFee/priorityFeeSubscriber.d.ts +22 -0
- package/lib/priorityFee/priorityFeeSubscriber.js +46 -0
- package/lib/tokenFaucet.js +1 -0
- package/lib/types.d.ts +4 -0
- package/lib/types.js +3 -0
- package/lib/user.d.ts +5 -4
- package/lib/user.js +71 -105
- package/package.json +2 -2
- package/src/accounts/fetch.ts +2 -2
- package/src/accounts/pollingDriftClientAccountSubscriber.ts +5 -23
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +10 -8
- package/src/adminClient.ts +23 -0
- package/src/config.ts +3 -0
- package/src/driftClient.ts +173 -13
- package/src/examples/loadDlob.ts +1 -0
- package/src/examples/makeTradeExample.ts +1 -0
- package/src/idl/drift.json +36 -1
- package/src/index.ts +3 -0
- package/src/jupiter/jupiterClient.ts +246 -3
- 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/priorityFee/priorityFeeSubscriber.ts +75 -0
- package/src/tokenFaucet.ts +1 -0
- package/src/types.ts +4 -0
- package/src/user.ts +171 -228
- package/tests/dlob/helpers.ts +10 -7
- package/tests/user/test.ts +77 -4
|
@@ -28,6 +28,173 @@ export interface Route {
|
|
|
28
28
|
slippageBps: number;
|
|
29
29
|
swapMode: SwapMode;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @export
|
|
34
|
+
* @interface RoutePlanStep
|
|
35
|
+
*/
|
|
36
|
+
export interface RoutePlanStep {
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* @type {SwapInfo}
|
|
40
|
+
* @memberof RoutePlanStep
|
|
41
|
+
*/
|
|
42
|
+
swapInfo: SwapInfo;
|
|
43
|
+
/**
|
|
44
|
+
*
|
|
45
|
+
* @type {number}
|
|
46
|
+
* @memberof RoutePlanStep
|
|
47
|
+
*/
|
|
48
|
+
percent: number;
|
|
49
|
+
}
|
|
50
|
+
export interface SwapInfo {
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @type {string}
|
|
54
|
+
* @memberof SwapInfo
|
|
55
|
+
*/
|
|
56
|
+
ammKey: string;
|
|
57
|
+
/**
|
|
58
|
+
*
|
|
59
|
+
* @type {string}
|
|
60
|
+
* @memberof SwapInfo
|
|
61
|
+
*/
|
|
62
|
+
label?: string;
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
* @type {string}
|
|
66
|
+
* @memberof SwapInfo
|
|
67
|
+
*/
|
|
68
|
+
inputMint: string;
|
|
69
|
+
/**
|
|
70
|
+
*
|
|
71
|
+
* @type {string}
|
|
72
|
+
* @memberof SwapInfo
|
|
73
|
+
*/
|
|
74
|
+
outputMint: string;
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @type {string}
|
|
78
|
+
* @memberof SwapInfo
|
|
79
|
+
*/
|
|
80
|
+
inAmount: string;
|
|
81
|
+
/**
|
|
82
|
+
*
|
|
83
|
+
* @type {string}
|
|
84
|
+
* @memberof SwapInfo
|
|
85
|
+
*/
|
|
86
|
+
outAmount: string;
|
|
87
|
+
/**
|
|
88
|
+
*
|
|
89
|
+
* @type {string}
|
|
90
|
+
* @memberof SwapInfo
|
|
91
|
+
*/
|
|
92
|
+
feeAmount: string;
|
|
93
|
+
/**
|
|
94
|
+
*
|
|
95
|
+
* @type {string}
|
|
96
|
+
* @memberof SwapInfo
|
|
97
|
+
*/
|
|
98
|
+
feeMint: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
*
|
|
102
|
+
* @export
|
|
103
|
+
* @interface PlatformFee
|
|
104
|
+
*/
|
|
105
|
+
export interface PlatformFee {
|
|
106
|
+
/**
|
|
107
|
+
*
|
|
108
|
+
* @type {string}
|
|
109
|
+
* @memberof PlatformFee
|
|
110
|
+
*/
|
|
111
|
+
amount?: string;
|
|
112
|
+
/**
|
|
113
|
+
*
|
|
114
|
+
* @type {number}
|
|
115
|
+
* @memberof PlatformFee
|
|
116
|
+
*/
|
|
117
|
+
feeBps?: number;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
*
|
|
121
|
+
* @export
|
|
122
|
+
* @interface QuoteResponse
|
|
123
|
+
*/
|
|
124
|
+
export interface QuoteResponse {
|
|
125
|
+
/**
|
|
126
|
+
*
|
|
127
|
+
* @type {string}
|
|
128
|
+
* @memberof QuoteResponse
|
|
129
|
+
*/
|
|
130
|
+
inputMint: string;
|
|
131
|
+
/**
|
|
132
|
+
*
|
|
133
|
+
* @type {string}
|
|
134
|
+
* @memberof QuoteResponse
|
|
135
|
+
*/
|
|
136
|
+
inAmount: string;
|
|
137
|
+
/**
|
|
138
|
+
*
|
|
139
|
+
* @type {string}
|
|
140
|
+
* @memberof QuoteResponse
|
|
141
|
+
*/
|
|
142
|
+
outputMint: string;
|
|
143
|
+
/**
|
|
144
|
+
*
|
|
145
|
+
* @type {string}
|
|
146
|
+
* @memberof QuoteResponse
|
|
147
|
+
*/
|
|
148
|
+
outAmount: string;
|
|
149
|
+
/**
|
|
150
|
+
*
|
|
151
|
+
* @type {string}
|
|
152
|
+
* @memberof QuoteResponse
|
|
153
|
+
*/
|
|
154
|
+
otherAmountThreshold: string;
|
|
155
|
+
/**
|
|
156
|
+
*
|
|
157
|
+
* @type {SwapMode}
|
|
158
|
+
* @memberof QuoteResponse
|
|
159
|
+
*/
|
|
160
|
+
swapMode: SwapMode;
|
|
161
|
+
/**
|
|
162
|
+
*
|
|
163
|
+
* @type {number}
|
|
164
|
+
* @memberof QuoteResponse
|
|
165
|
+
*/
|
|
166
|
+
slippageBps: number;
|
|
167
|
+
/**
|
|
168
|
+
*
|
|
169
|
+
* @type {PlatformFee}
|
|
170
|
+
* @memberof QuoteResponse
|
|
171
|
+
*/
|
|
172
|
+
platformFee?: PlatformFee;
|
|
173
|
+
/**
|
|
174
|
+
*
|
|
175
|
+
* @type {string}
|
|
176
|
+
* @memberof QuoteResponse
|
|
177
|
+
*/
|
|
178
|
+
priceImpactPct: string;
|
|
179
|
+
/**
|
|
180
|
+
*
|
|
181
|
+
* @type {Array<RoutePlanStep>}
|
|
182
|
+
* @memberof QuoteResponse
|
|
183
|
+
*/
|
|
184
|
+
routePlan: Array<RoutePlanStep>;
|
|
185
|
+
/**
|
|
186
|
+
*
|
|
187
|
+
* @type {number}
|
|
188
|
+
* @memberof QuoteResponse
|
|
189
|
+
*/
|
|
190
|
+
contextSlot?: number;
|
|
191
|
+
/**
|
|
192
|
+
*
|
|
193
|
+
* @type {number}
|
|
194
|
+
* @memberof QuoteResponse
|
|
195
|
+
*/
|
|
196
|
+
timeTaken?: number;
|
|
197
|
+
}
|
|
31
198
|
export declare class JupiterClient {
|
|
32
199
|
url: string;
|
|
33
200
|
connection: Connection;
|
|
@@ -36,6 +203,7 @@ export declare class JupiterClient {
|
|
|
36
203
|
connection: Connection;
|
|
37
204
|
});
|
|
38
205
|
/**
|
|
206
|
+
* ** @deprecated - use getQuote
|
|
39
207
|
* Get routes for a swap
|
|
40
208
|
* @param inputMint the mint of the input token
|
|
41
209
|
* @param outputMint the mint of the output token
|
|
@@ -53,6 +221,35 @@ export declare class JupiterClient {
|
|
|
53
221
|
onlyDirectRoutes?: boolean;
|
|
54
222
|
}): Promise<Route[]>;
|
|
55
223
|
/**
|
|
224
|
+
* Get routes for a swap
|
|
225
|
+
* @param inputMint the mint of the input token
|
|
226
|
+
* @param outputMint the mint of the output token
|
|
227
|
+
* @param amount the amount of the input token
|
|
228
|
+
* @param slippageBps the slippage tolerance in basis points
|
|
229
|
+
* @param swapMode the swap mode (ExactIn or ExactOut)
|
|
230
|
+
* @param onlyDirectRoutes whether to only return direct routes
|
|
231
|
+
*/
|
|
232
|
+
getQuote({ inputMint, outputMint, amount, slippageBps, swapMode, onlyDirectRoutes, }: {
|
|
233
|
+
inputMint: PublicKey;
|
|
234
|
+
outputMint: PublicKey;
|
|
235
|
+
amount: BN;
|
|
236
|
+
slippageBps?: number;
|
|
237
|
+
swapMode?: SwapMode;
|
|
238
|
+
onlyDirectRoutes?: boolean;
|
|
239
|
+
}): Promise<QuoteResponse>;
|
|
240
|
+
/**
|
|
241
|
+
* Get a swap transaction for quote
|
|
242
|
+
* @param quoteResponse quote to perform swap
|
|
243
|
+
* @param userPublicKey the signer's wallet public key
|
|
244
|
+
* @param slippageBps the slippage tolerance in basis points
|
|
245
|
+
*/
|
|
246
|
+
getSwap({ quote, userPublicKey, slippageBps, }: {
|
|
247
|
+
quote: QuoteResponse;
|
|
248
|
+
userPublicKey: PublicKey;
|
|
249
|
+
slippageBps?: number;
|
|
250
|
+
}): Promise<VersionedTransaction>;
|
|
251
|
+
/**
|
|
252
|
+
* ** @deprecated - use getSwap
|
|
56
253
|
* Get a swap transaction for a route
|
|
57
254
|
* @param route the route to perform swap
|
|
58
255
|
* @param userPublicKey the signer's wallet public key
|
|
@@ -8,11 +8,12 @@ const web3_js_1 = require("@solana/web3.js");
|
|
|
8
8
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
9
9
|
class JupiterClient {
|
|
10
10
|
constructor({ connection }) {
|
|
11
|
-
this.url = 'https://quote-api.jup.ag
|
|
11
|
+
this.url = 'https://quote-api.jup.ag';
|
|
12
12
|
this.lookupTableCahce = new Map();
|
|
13
13
|
this.connection = connection;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
+
* ** @deprecated - use getQuote
|
|
16
17
|
* Get routes for a swap
|
|
17
18
|
* @param inputMint the mint of the input token
|
|
18
19
|
* @param outputMint the mint of the output token
|
|
@@ -30,17 +31,61 @@ class JupiterClient {
|
|
|
30
31
|
swapMode,
|
|
31
32
|
onlyDirectRoutes: onlyDirectRoutes.toString(),
|
|
32
33
|
}).toString();
|
|
33
|
-
const { data: routes } = await (await (0, node_fetch_1.default)(
|
|
34
|
+
const { data: routes } = await (await (0, node_fetch_1.default)(`${this.url}/v4/quote?${params}`)).json();
|
|
34
35
|
return routes;
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
38
|
+
* Get routes for a swap
|
|
39
|
+
* @param inputMint the mint of the input token
|
|
40
|
+
* @param outputMint the mint of the output token
|
|
41
|
+
* @param amount the amount of the input token
|
|
42
|
+
* @param slippageBps the slippage tolerance in basis points
|
|
43
|
+
* @param swapMode the swap mode (ExactIn or ExactOut)
|
|
44
|
+
* @param onlyDirectRoutes whether to only return direct routes
|
|
45
|
+
*/
|
|
46
|
+
async getQuote({ inputMint, outputMint, amount, slippageBps = 50, swapMode = 'ExactIn', onlyDirectRoutes = false, }) {
|
|
47
|
+
const params = new URLSearchParams({
|
|
48
|
+
inputMint: inputMint.toString(),
|
|
49
|
+
outputMint: outputMint.toString(),
|
|
50
|
+
amount: amount.toString(),
|
|
51
|
+
slippageBps: slippageBps.toString(),
|
|
52
|
+
swapMode,
|
|
53
|
+
onlyDirectRoutes: onlyDirectRoutes.toString(),
|
|
54
|
+
}).toString();
|
|
55
|
+
const quote = await (await (0, node_fetch_1.default)(`${this.url}/v6/quote?${params}`)).json();
|
|
56
|
+
return quote;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get a swap transaction for quote
|
|
60
|
+
* @param quoteResponse quote to perform swap
|
|
61
|
+
* @param userPublicKey the signer's wallet public key
|
|
62
|
+
* @param slippageBps the slippage tolerance in basis points
|
|
63
|
+
*/
|
|
64
|
+
async getSwap({ quote, userPublicKey, slippageBps = 50, }) {
|
|
65
|
+
const resp = await (await (0, node_fetch_1.default)(`${this.url}/v6/swap`, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: {
|
|
68
|
+
'Content-Type': 'application/json',
|
|
69
|
+
},
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
quoteResponse: quote,
|
|
72
|
+
userPublicKey,
|
|
73
|
+
slippageBps,
|
|
74
|
+
}),
|
|
75
|
+
})).json();
|
|
76
|
+
const { swapTransaction } = resp;
|
|
77
|
+
const swapTransactionBuf = Buffer.from(swapTransaction, 'base64');
|
|
78
|
+
return web3_js_1.VersionedTransaction.deserialize(swapTransactionBuf);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* ** @deprecated - use getSwap
|
|
37
82
|
* Get a swap transaction for a route
|
|
38
83
|
* @param route the route to perform swap
|
|
39
84
|
* @param userPublicKey the signer's wallet public key
|
|
40
85
|
* @param slippageBps the slippage tolerance in basis points
|
|
41
86
|
*/
|
|
42
87
|
async getSwapTransaction({ route, userPublicKey, slippageBps = 50, }) {
|
|
43
|
-
const resp = await (await (0, node_fetch_1.default)(`${this.url}/swap`, {
|
|
88
|
+
const resp = await (await (0, node_fetch_1.default)(`${this.url}/v4/swap`, {
|
|
44
89
|
method: 'POST',
|
|
45
90
|
headers: {
|
|
46
91
|
'Content-Type': 'application/json',
|
|
@@ -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,22 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
|
+
export declare class PriorityFeeSubscriber {
|
|
4
|
+
connection: Connection;
|
|
5
|
+
frequencyMs: number;
|
|
6
|
+
addresses: PublicKey[];
|
|
7
|
+
slotsToCheck: number;
|
|
8
|
+
intervalId?: NodeJS.Timer;
|
|
9
|
+
latestPriorityFee: number;
|
|
10
|
+
avgPriorityFee: number;
|
|
11
|
+
maxPriorityFee: number;
|
|
12
|
+
lastSlotSeen: number;
|
|
13
|
+
constructor({ connection, frequencyMs, addresses, slotsToCheck, }: {
|
|
14
|
+
connection: Connection;
|
|
15
|
+
frequencyMs: number;
|
|
16
|
+
addresses: PublicKey[];
|
|
17
|
+
slotsToCheck?: number;
|
|
18
|
+
});
|
|
19
|
+
subscribe(): Promise<void>;
|
|
20
|
+
load(): Promise<void>;
|
|
21
|
+
unsubscribe(): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PriorityFeeSubscriber = void 0;
|
|
4
|
+
class PriorityFeeSubscriber {
|
|
5
|
+
constructor({ connection, frequencyMs, addresses, slotsToCheck = 10, }) {
|
|
6
|
+
this.latestPriorityFee = 0;
|
|
7
|
+
// avg of last {slotsToCheck} slots
|
|
8
|
+
this.avgPriorityFee = 0;
|
|
9
|
+
// max of last {slotsToCheck} slots
|
|
10
|
+
this.maxPriorityFee = 0;
|
|
11
|
+
this.lastSlotSeen = 0;
|
|
12
|
+
this.connection = connection;
|
|
13
|
+
this.frequencyMs = frequencyMs;
|
|
14
|
+
this.addresses = addresses;
|
|
15
|
+
this.slotsToCheck = slotsToCheck;
|
|
16
|
+
}
|
|
17
|
+
async subscribe() {
|
|
18
|
+
if (this.intervalId) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
this.intervalId = setInterval(this.load.bind(this), this.frequencyMs);
|
|
22
|
+
}
|
|
23
|
+
async load() {
|
|
24
|
+
var _a, _b, _c;
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
const rpcJSONResponse = await this.connection._rpcRequest('getRecentPrioritizationFees', [this.addresses]);
|
|
27
|
+
const descResults = (_c = (_b = (_a = rpcJSONResponse === null || rpcJSONResponse === void 0 ? void 0 : rpcJSONResponse.result) === null || _a === void 0 ? void 0 : _a.sort((a, b) => b.slot - a.slot)) === null || _b === void 0 ? void 0 : _b.slice(0, this.slotsToCheck)) !== null && _c !== void 0 ? _c : [];
|
|
28
|
+
if (!(descResults === null || descResults === void 0 ? void 0 : descResults.length))
|
|
29
|
+
return;
|
|
30
|
+
const mostRecentResult = descResults[0];
|
|
31
|
+
this.latestPriorityFee = mostRecentResult.prioritizationFee;
|
|
32
|
+
this.lastSlotSeen = mostRecentResult.slot;
|
|
33
|
+
this.avgPriorityFee =
|
|
34
|
+
descResults.reduce((a, b) => {
|
|
35
|
+
return a + b.prioritizationFee;
|
|
36
|
+
}, 0) / descResults.length;
|
|
37
|
+
this.maxPriorityFee = Math.max(...descResults.map((result) => result.prioritizationFee));
|
|
38
|
+
}
|
|
39
|
+
async unsubscribe() {
|
|
40
|
+
if (this.intervalId) {
|
|
41
|
+
clearInterval(this.intervalId);
|
|
42
|
+
this.intervalId = undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.PriorityFeeSubscriber = PriorityFeeSubscriber;
|
package/lib/tokenFaucet.js
CHANGED
|
@@ -37,6 +37,7 @@ class TokenFaucet {
|
|
|
37
37
|
this.connection = connection;
|
|
38
38
|
this.wallet = wallet;
|
|
39
39
|
this.opts = opts || anchor_1.AnchorProvider.defaultOptions();
|
|
40
|
+
// @ts-ignore
|
|
40
41
|
const provider = new anchor_1.AnchorProvider(connection, wallet, this.opts);
|
|
41
42
|
this.provider = provider;
|
|
42
43
|
this.program = new anchor_1.Program(token_faucet_json_1.default, programId, provider);
|
package/lib/types.d.ts
CHANGED
|
@@ -242,6 +242,9 @@ export declare class OrderActionExplanation {
|
|
|
242
242
|
static readonly ORDER_FILLED_WITH_SERUM: {
|
|
243
243
|
orderFillWithSerum: {};
|
|
244
244
|
};
|
|
245
|
+
static readonly ORDER_FILLED_WITH_PHOENIX: {
|
|
246
|
+
orderFillWithPhoenix: {};
|
|
247
|
+
};
|
|
245
248
|
static readonly REDUCE_ONLY_ORDER_INCREASED_POSITION: {
|
|
246
249
|
reduceOnlyOrderIncreasedPosition: {};
|
|
247
250
|
};
|
|
@@ -721,6 +724,7 @@ export type SpotMarketAccount = {
|
|
|
721
724
|
maintenanceLiabilityWeight: number;
|
|
722
725
|
liquidatorFee: number;
|
|
723
726
|
imfFactor: number;
|
|
727
|
+
scaleInitialAssetWeightStart: BN;
|
|
724
728
|
withdrawGuardThreshold: BN;
|
|
725
729
|
depositTokenTwap: BN;
|
|
726
730
|
borrowTokenTwap: BN;
|