@drift-labs/sdk 0.2.0-master.10 → 0.2.0-master.13
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/lib/admin.d.ts +3 -3
- package/lib/admin.js +6 -6
- package/lib/clearingHouse.d.ts +22 -6
- package/lib/clearingHouse.js +357 -74
- package/lib/clearingHouseUser.d.ts +12 -17
- package/lib/clearingHouseUser.js +97 -88
- package/lib/config.js +1 -1
- package/lib/constants/banks.d.ts +2 -2
- package/lib/constants/banks.js +5 -4
- package/lib/constants/numericConstants.d.ts +3 -0
- package/lib/constants/numericConstants.js +4 -1
- package/lib/events/eventList.js +3 -0
- package/lib/events/types.d.ts +2 -1
- package/lib/factory/bigNum.d.ts +1 -0
- package/lib/factory/bigNum.js +37 -11
- package/lib/idl/clearing_house.json +611 -146
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +2 -1
- package/lib/index.js +2 -1
- package/lib/math/amm.js +2 -2
- package/lib/math/bankBalance.d.ts +3 -1
- package/lib/math/bankBalance.js +54 -1
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +72 -0
- package/lib/math/market.d.ts +4 -1
- package/lib/math/market.js +35 -1
- package/lib/math/position.d.ts +8 -0
- package/lib/math/position.js +42 -12
- package/lib/orders.d.ts +1 -2
- package/lib/orders.js +2 -77
- package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
- package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
- package/lib/tx/retryTxSender.js +9 -2
- package/lib/types.d.ts +86 -16
- package/lib/types.js +18 -1
- package/lib/util/computeUnits.js +1 -1
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +1 -1
- package/src/admin.ts +7 -7
- package/src/clearingHouse.ts +636 -94
- package/src/clearingHouseConfig.js +2 -0
- package/src/clearingHouseUser.ts +219 -121
- package/src/clearingHouseUserConfig.js +2 -0
- package/src/config.ts +1 -1
- package/src/constants/banks.js +42 -0
- package/src/constants/banks.ts +7 -4
- package/src/constants/markets.js +42 -0
- package/src/constants/numericConstants.js +41 -0
- package/src/constants/numericConstants.ts +4 -0
- package/src/events/eventList.ts +3 -0
- package/src/events/types.ts +2 -0
- package/src/factory/bigNum.js +37 -11
- package/src/factory/bigNum.ts +43 -13
- package/src/idl/clearing_house.json +611 -146
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.js +1 -1
- package/src/index.ts +2 -1
- package/src/math/amm.ts +8 -5
- package/src/math/bankBalance.ts +98 -1
- package/src/math/margin.ts +124 -0
- package/src/math/market.ts +66 -1
- package/src/math/position.ts +59 -9
- package/src/mockUSDCFaucet.js +276 -167
- package/src/orders.ts +4 -157
- package/src/tokenFaucet.js +189 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +11 -3
- package/src/types.js +12 -1
- package/src/types.ts +88 -16
- package/src/{accounts/fetch.js → util/computeUnits.js} +11 -13
- package/src/util/computeUnits.ts +1 -1
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/tests/bn/test.ts +2 -0
- package/src/addresses/pda.js +0 -104
- package/src/math/bankBalance.js +0 -75
- package/src/math/market.js +0 -57
- package/src/math/orders.js +0 -110
- package/src/math/position.js +0 -140
- package/src/orders.js +0 -134
- package/src/tx/retryTxSender.js +0 -188
package/src/clearingHouseUser.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
PRICE_TO_QUOTE_PRECISION,
|
|
22
22
|
MARGIN_PRECISION,
|
|
23
23
|
BANK_WEIGHT_PRECISION,
|
|
24
|
+
BANK_BALANCE_PRECISION_EXP,
|
|
24
25
|
} from './constants/numericConstants';
|
|
25
26
|
import {
|
|
26
27
|
UserAccountSubscriber,
|
|
@@ -32,12 +33,22 @@ import {
|
|
|
32
33
|
calculateBaseAssetValue,
|
|
33
34
|
calculatePositionFundingPNL,
|
|
34
35
|
calculatePositionPNL,
|
|
36
|
+
calculateUnsettledAssetWeight,
|
|
37
|
+
calculateMarketMarginRatio,
|
|
35
38
|
PositionDirection,
|
|
36
39
|
calculateTradeSlippage,
|
|
37
40
|
BN,
|
|
38
41
|
BankAccount,
|
|
39
42
|
} from '.';
|
|
40
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
getTokenAmount,
|
|
45
|
+
calculateAssetWeight,
|
|
46
|
+
calculateLiabilityWeight,
|
|
47
|
+
} from './math/bankBalance';
|
|
48
|
+
import {
|
|
49
|
+
calculateMarginBaseAssetValue,
|
|
50
|
+
calculateWorstCaseBaseAssetAmount,
|
|
51
|
+
} from './math/margin';
|
|
41
52
|
import { OraclePriceData } from './oracles/types';
|
|
42
53
|
import { ClearingHouseUserConfig } from './clearingHouseUserConfig';
|
|
43
54
|
import { PollingUserAccountSubscriber } from './accounts/pollingUserAccountSubscriber';
|
|
@@ -124,7 +135,6 @@ export class ClearingHouseUser {
|
|
|
124
135
|
quoteAssetAmount: ZERO,
|
|
125
136
|
quoteEntryAmount: ZERO,
|
|
126
137
|
openOrders: ZERO,
|
|
127
|
-
unsettledPnl: ZERO,
|
|
128
138
|
openBids: ZERO,
|
|
129
139
|
openAsks: ZERO,
|
|
130
140
|
};
|
|
@@ -184,51 +194,84 @@ export class ClearingHouseUser {
|
|
|
184
194
|
}
|
|
185
195
|
|
|
186
196
|
public getInitialMarginRequirement(): BN {
|
|
187
|
-
|
|
188
|
-
|
|
197
|
+
const postionMarginRequirement = this.getUserAccount().positions.reduce(
|
|
198
|
+
(marginRequirement, marketPosition) => {
|
|
189
199
|
const market = this.clearingHouse.getMarketAccount(
|
|
190
200
|
marketPosition.marketIndex
|
|
191
201
|
);
|
|
192
|
-
|
|
193
|
-
|
|
202
|
+
const worstCaseBaseAssetAmount =
|
|
203
|
+
calculateWorstCaseBaseAssetAmount(marketPosition);
|
|
204
|
+
|
|
205
|
+
const worstCaseAssetValue = worstCaseBaseAssetAmount
|
|
206
|
+
.abs()
|
|
207
|
+
.mul(this.getOracleDataForMarket(market.marketIndex).price)
|
|
208
|
+
.div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
|
|
209
|
+
|
|
210
|
+
const marketMarginRatio = new BN(
|
|
211
|
+
calculateMarketMarginRatio(
|
|
194
212
|
market,
|
|
195
|
-
|
|
196
|
-
|
|
213
|
+
worstCaseBaseAssetAmount.abs(),
|
|
214
|
+
'Initial'
|
|
197
215
|
)
|
|
198
|
-
.mul(new BN(market.marginRatioInitial))
|
|
199
|
-
.div(MARGIN_PRECISION)
|
|
200
216
|
);
|
|
201
|
-
|
|
202
|
-
|
|
217
|
+
return marginRequirement.add(
|
|
218
|
+
worstCaseAssetValue.mul(marketMarginRatio).div(MARGIN_PRECISION)
|
|
219
|
+
);
|
|
220
|
+
},
|
|
221
|
+
ZERO
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
const bankMarginRequirement = this.getBankLiabilityValue(
|
|
225
|
+
undefined,
|
|
226
|
+
'Initial'
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
return bankMarginRequirement.add(postionMarginRequirement);
|
|
203
230
|
}
|
|
204
231
|
|
|
205
232
|
/**
|
|
206
|
-
* @returns The
|
|
233
|
+
* @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
|
|
207
234
|
*/
|
|
208
|
-
public
|
|
235
|
+
public getMaintenanceMarginRequirement(): BN {
|
|
209
236
|
return this.getUserAccount()
|
|
210
237
|
.positions.reduce((marginRequirement, marketPosition) => {
|
|
211
238
|
const market = this.clearingHouse.getMarketAccount(
|
|
212
239
|
marketPosition.marketIndex
|
|
213
240
|
);
|
|
241
|
+
const worstCaseBaseAssetAmount =
|
|
242
|
+
calculateWorstCaseBaseAssetAmount(marketPosition);
|
|
243
|
+
|
|
244
|
+
const worstCaseAssetValue = worstCaseBaseAssetAmount
|
|
245
|
+
.abs()
|
|
246
|
+
.mul(this.getOracleDataForMarket(market.marketIndex).price)
|
|
247
|
+
.div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
|
|
248
|
+
|
|
214
249
|
return marginRequirement.add(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
250
|
+
worstCaseAssetValue
|
|
251
|
+
.mul(
|
|
252
|
+
new BN(
|
|
253
|
+
calculateMarketMarginRatio(
|
|
254
|
+
market,
|
|
255
|
+
worstCaseBaseAssetAmount.abs(),
|
|
256
|
+
'Maintenance'
|
|
257
|
+
)
|
|
258
|
+
)
|
|
259
|
+
)
|
|
221
260
|
.div(MARGIN_PRECISION)
|
|
222
261
|
);
|
|
223
262
|
}, ZERO)
|
|
224
|
-
.add(this.
|
|
263
|
+
.add(this.getBankLiabilityValue(undefined, 'Maintenance'));
|
|
225
264
|
}
|
|
226
265
|
|
|
227
266
|
/**
|
|
228
267
|
* calculates unrealized position price pnl
|
|
229
268
|
* @returns : Precision QUOTE_PRECISION
|
|
230
269
|
*/
|
|
231
|
-
public getUnrealizedPNL(
|
|
270
|
+
public getUnrealizedPNL(
|
|
271
|
+
withFunding?: boolean,
|
|
272
|
+
marketIndex?: BN,
|
|
273
|
+
withWeightMarginCategory?: MarginCategory
|
|
274
|
+
): BN {
|
|
232
275
|
return this.getUserAccount()
|
|
233
276
|
.positions.filter((pos) =>
|
|
234
277
|
marketIndex ? pos.marketIndex === marketIndex : true
|
|
@@ -237,28 +280,28 @@ export class ClearingHouseUser {
|
|
|
237
280
|
const market = this.clearingHouse.getMarketAccount(
|
|
238
281
|
marketPosition.marketIndex
|
|
239
282
|
);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
this.getOracleDataForMarket(market.marketIndex)
|
|
246
|
-
)
|
|
283
|
+
let pnl0 = calculatePositionPNL(
|
|
284
|
+
market,
|
|
285
|
+
marketPosition,
|
|
286
|
+
withFunding,
|
|
287
|
+
this.getOracleDataForMarket(market.marketIndex)
|
|
247
288
|
);
|
|
248
|
-
}, ZERO);
|
|
249
|
-
}
|
|
250
289
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
290
|
+
if (withWeightMarginCategory !== undefined) {
|
|
291
|
+
if (pnl0.gt(ZERO)) {
|
|
292
|
+
pnl0 = pnl0
|
|
293
|
+
.mul(
|
|
294
|
+
calculateUnsettledAssetWeight(
|
|
295
|
+
market,
|
|
296
|
+
pnl0,
|
|
297
|
+
withWeightMarginCategory
|
|
298
|
+
)
|
|
299
|
+
)
|
|
300
|
+
.div(new BN(BANK_WEIGHT_PRECISION));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return pnl.add(pnl0);
|
|
262
305
|
}, ZERO);
|
|
263
306
|
}
|
|
264
307
|
|
|
@@ -279,14 +322,18 @@ export class ClearingHouseUser {
|
|
|
279
322
|
}, ZERO);
|
|
280
323
|
}
|
|
281
324
|
|
|
282
|
-
public
|
|
325
|
+
public getBankLiabilityValue(
|
|
326
|
+
bankIndex?: BN,
|
|
327
|
+
withWeightMarginCategory?: MarginCategory
|
|
328
|
+
): BN {
|
|
283
329
|
return this.getUserAccount().bankBalances.reduce(
|
|
284
|
-
(
|
|
330
|
+
(totalLiabilityValue, bankBalance) => {
|
|
285
331
|
if (
|
|
286
332
|
bankBalance.balance.eq(ZERO) ||
|
|
287
|
-
isVariant(bankBalance.balanceType, 'deposit')
|
|
333
|
+
isVariant(bankBalance.balanceType, 'deposit') ||
|
|
334
|
+
(bankIndex !== undefined && !bankBalance.bankIndex.eq(bankIndex))
|
|
288
335
|
) {
|
|
289
|
-
return
|
|
336
|
+
return totalLiabilityValue;
|
|
290
337
|
}
|
|
291
338
|
|
|
292
339
|
// Todo this needs to account for whether it's based on initial or maintenance requirements
|
|
@@ -299,23 +346,42 @@ export class ClearingHouseUser {
|
|
|
299
346
|
bankAccount,
|
|
300
347
|
bankBalance.balanceType
|
|
301
348
|
);
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
.
|
|
308
|
-
|
|
349
|
+
|
|
350
|
+
let liabilityValue = tokenAmount
|
|
351
|
+
.mul(this.getOracleDataForBank(bankAccount.bankIndex).price)
|
|
352
|
+
.div(MARK_PRICE_PRECISION)
|
|
353
|
+
.div(
|
|
354
|
+
new BN(10).pow(
|
|
355
|
+
new BN(bankAccount.decimals).sub(BANK_BALANCE_PRECISION_EXP)
|
|
356
|
+
)
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
if (withWeightMarginCategory !== undefined) {
|
|
360
|
+
const weight = calculateLiabilityWeight(
|
|
361
|
+
tokenAmount,
|
|
362
|
+
bankAccount,
|
|
363
|
+
withWeightMarginCategory
|
|
364
|
+
);
|
|
365
|
+
liabilityValue = liabilityValue
|
|
366
|
+
.mul(weight)
|
|
367
|
+
.div(BANK_WEIGHT_PRECISION);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return totalLiabilityValue.add(liabilityValue);
|
|
309
371
|
},
|
|
310
372
|
ZERO
|
|
311
373
|
);
|
|
312
374
|
}
|
|
313
375
|
|
|
314
|
-
public
|
|
376
|
+
public getBankAssetValue(
|
|
377
|
+
bankIndex?: BN,
|
|
378
|
+
withWeightMarginCategory?: MarginCategory
|
|
379
|
+
): BN {
|
|
315
380
|
return this.getUserAccount().bankBalances.reduce(
|
|
316
381
|
(totalAssetValue, bankBalance) => {
|
|
317
382
|
if (
|
|
318
383
|
bankBalance.balance.eq(ZERO) ||
|
|
384
|
+
isVariant(bankBalance.balanceType, 'borrow') ||
|
|
319
385
|
(bankIndex !== undefined && !bankBalance.bankIndex.eq(bankIndex))
|
|
320
386
|
) {
|
|
321
387
|
return totalAssetValue;
|
|
@@ -326,32 +392,46 @@ export class ClearingHouseUser {
|
|
|
326
392
|
bankBalance.bankIndex
|
|
327
393
|
);
|
|
328
394
|
|
|
329
|
-
|
|
395
|
+
const tokenAmount = getTokenAmount(
|
|
330
396
|
bankBalance.balance,
|
|
331
397
|
bankAccount,
|
|
332
398
|
bankBalance.balanceType
|
|
333
399
|
);
|
|
334
400
|
|
|
335
|
-
|
|
336
|
-
|
|
401
|
+
let assetValue = tokenAmount
|
|
402
|
+
.mul(this.getOracleDataForBank(bankAccount.bankIndex).price)
|
|
403
|
+
.div(MARK_PRICE_PRECISION)
|
|
404
|
+
.div(
|
|
405
|
+
new BN(10).pow(
|
|
406
|
+
new BN(bankAccount.decimals).sub(BANK_BALANCE_PRECISION_EXP)
|
|
407
|
+
)
|
|
408
|
+
);
|
|
409
|
+
if (withWeightMarginCategory !== undefined) {
|
|
410
|
+
const weight = calculateAssetWeight(
|
|
411
|
+
tokenAmount,
|
|
412
|
+
bankAccount,
|
|
413
|
+
withWeightMarginCategory
|
|
414
|
+
);
|
|
415
|
+
assetValue = assetValue.mul(weight).div(BANK_WEIGHT_PRECISION);
|
|
337
416
|
}
|
|
338
417
|
|
|
339
|
-
return totalAssetValue.add(
|
|
340
|
-
tokenAmount
|
|
341
|
-
.mul(this.getOracleDataForBank(bankAccount.bankIndex).price)
|
|
342
|
-
.div(MARK_PRICE_PRECISION)
|
|
343
|
-
);
|
|
418
|
+
return totalAssetValue.add(assetValue);
|
|
344
419
|
},
|
|
345
420
|
ZERO
|
|
346
421
|
);
|
|
347
422
|
}
|
|
348
423
|
|
|
424
|
+
public getNetBankValue(withWeightMarginCategory?: MarginCategory): BN {
|
|
425
|
+
return this.getBankAssetValue(undefined, withWeightMarginCategory).sub(
|
|
426
|
+
this.getBankLiabilityValue(undefined, withWeightMarginCategory)
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
|
|
349
430
|
/**
|
|
350
431
|
* calculates TotalCollateral: collateral + unrealized pnl
|
|
351
|
-
* TODO: rename to total equity (for perpetuals swaps)
|
|
352
432
|
* @returns : Precision QUOTE_PRECISION
|
|
353
433
|
*/
|
|
354
|
-
public getTotalCollateral(): BN {
|
|
434
|
+
public getTotalCollateral(marginCategory: MarginCategory = 'Initial'): BN {
|
|
355
435
|
return this.getUserAccount()
|
|
356
436
|
.bankBalances.reduce((totalAssetValue, bankBalance) => {
|
|
357
437
|
if (
|
|
@@ -371,20 +451,32 @@ export class ClearingHouseUser {
|
|
|
371
451
|
bankAccount,
|
|
372
452
|
bankBalance.balanceType
|
|
373
453
|
);
|
|
454
|
+
|
|
455
|
+
const weight = calculateAssetWeight(
|
|
456
|
+
tokenAmount,
|
|
457
|
+
bankAccount,
|
|
458
|
+
marginCategory
|
|
459
|
+
);
|
|
460
|
+
|
|
374
461
|
return totalAssetValue.add(
|
|
375
462
|
tokenAmount
|
|
376
463
|
.mul(this.getOracleDataForBank(bankAccount.bankIndex).price)
|
|
377
|
-
.mul(
|
|
464
|
+
.mul(weight)
|
|
378
465
|
.div(BANK_WEIGHT_PRECISION)
|
|
379
466
|
.div(MARK_PRICE_PRECISION)
|
|
467
|
+
// Adjust for decimals of bank account
|
|
468
|
+
.div(
|
|
469
|
+
new BN(10).pow(
|
|
470
|
+
new BN(bankAccount.decimals).sub(BANK_BALANCE_PRECISION_EXP)
|
|
471
|
+
)
|
|
472
|
+
)
|
|
380
473
|
);
|
|
381
474
|
}, ZERO)
|
|
382
|
-
.add(this.getUnrealizedPNL(true))
|
|
383
|
-
.add(this.getUnsettledPNL());
|
|
475
|
+
.add(this.getUnrealizedPNL(true, undefined, marginCategory));
|
|
384
476
|
}
|
|
385
477
|
|
|
386
478
|
/**
|
|
387
|
-
* calculates sum of position value across all positions
|
|
479
|
+
* calculates sum of position value across all positions in margin system
|
|
388
480
|
* @returns : Precision QUOTE_PRECISION
|
|
389
481
|
*/
|
|
390
482
|
getTotalPositionValue(): BN {
|
|
@@ -393,20 +485,20 @@ export class ClearingHouseUser {
|
|
|
393
485
|
const market = this.clearingHouse.getMarketAccount(
|
|
394
486
|
marketPosition.marketIndex
|
|
395
487
|
);
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
this.getOracleDataForMarket(market.marketIndex)
|
|
401
|
-
)
|
|
488
|
+
const posVal = calculateMarginBaseAssetValue(
|
|
489
|
+
market,
|
|
490
|
+
marketPosition,
|
|
491
|
+
this.getOracleDataForMarket(market.marketIndex)
|
|
402
492
|
);
|
|
493
|
+
|
|
494
|
+
return positionValue.add(posVal);
|
|
403
495
|
},
|
|
404
496
|
ZERO
|
|
405
497
|
);
|
|
406
498
|
}
|
|
407
499
|
|
|
408
500
|
/**
|
|
409
|
-
* calculates position value
|
|
501
|
+
* calculates position value in margin system
|
|
410
502
|
* @returns : Precision QUOTE_PRECISION
|
|
411
503
|
*/
|
|
412
504
|
public getPositionValue(
|
|
@@ -418,7 +510,7 @@ export class ClearingHouseUser {
|
|
|
418
510
|
const market = this.clearingHouse.getMarketAccount(
|
|
419
511
|
userPosition.marketIndex
|
|
420
512
|
);
|
|
421
|
-
return
|
|
513
|
+
return calculateMarginBaseAssetValue(market, userPosition, oraclePriceData);
|
|
422
514
|
}
|
|
423
515
|
|
|
424
516
|
public getPositionSide(
|
|
@@ -434,12 +526,13 @@ export class ClearingHouseUser {
|
|
|
434
526
|
}
|
|
435
527
|
|
|
436
528
|
/**
|
|
437
|
-
* calculates average exit price for closing 100% of position
|
|
529
|
+
* calculates average exit price (optionally for closing up to 100% of position)
|
|
438
530
|
* @returns : Precision MARK_PRICE_PRECISION
|
|
439
531
|
*/
|
|
440
532
|
public getPositionEstimatedExitPriceAndPnl(
|
|
441
533
|
position: UserPosition,
|
|
442
|
-
amountToClose?: BN
|
|
534
|
+
amountToClose?: BN,
|
|
535
|
+
useAMMClose = false
|
|
443
536
|
): [BN, BN] {
|
|
444
537
|
const market = this.clearingHouse.getMarketAccount(position.marketIndex);
|
|
445
538
|
|
|
@@ -459,11 +552,21 @@ export class ClearingHouseUser {
|
|
|
459
552
|
} as UserPosition;
|
|
460
553
|
}
|
|
461
554
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
555
|
+
let baseAssetValue: BN;
|
|
556
|
+
|
|
557
|
+
if (useAMMClose) {
|
|
558
|
+
baseAssetValue = calculateBaseAssetValue(
|
|
559
|
+
market,
|
|
560
|
+
position,
|
|
561
|
+
oraclePriceData
|
|
562
|
+
);
|
|
563
|
+
} else {
|
|
564
|
+
baseAssetValue = calculateMarginBaseAssetValue(
|
|
565
|
+
market,
|
|
566
|
+
position,
|
|
567
|
+
oraclePriceData
|
|
568
|
+
);
|
|
569
|
+
}
|
|
467
570
|
if (position.baseAssetAmount.eq(ZERO)) {
|
|
468
571
|
return [ZERO, ZERO];
|
|
469
572
|
}
|
|
@@ -505,22 +608,13 @@ export class ClearingHouseUser {
|
|
|
505
608
|
category: MarginCategory = 'Initial'
|
|
506
609
|
): BN {
|
|
507
610
|
const market = this.clearingHouse.getMarketAccount(marketIndex);
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
marginRatioCategory = market.marginRatioMaintenance;
|
|
516
|
-
break;
|
|
517
|
-
case 'Partial':
|
|
518
|
-
marginRatioCategory = market.marginRatioPartial;
|
|
519
|
-
break;
|
|
520
|
-
default:
|
|
521
|
-
marginRatioCategory = market.marginRatioInitial;
|
|
522
|
-
break;
|
|
523
|
-
}
|
|
611
|
+
|
|
612
|
+
const marginRatioCategory = calculateMarketMarginRatio(
|
|
613
|
+
market,
|
|
614
|
+
// worstCaseBaseAssetAmount.abs(),
|
|
615
|
+
ZERO, // todo
|
|
616
|
+
category
|
|
617
|
+
);
|
|
524
618
|
const maxLeverage = TEN_THOUSAND.mul(TEN_THOUSAND).div(
|
|
525
619
|
new BN(marginRatioCategory)
|
|
526
620
|
);
|
|
@@ -543,7 +637,8 @@ export class ClearingHouseUser {
|
|
|
543
637
|
|
|
544
638
|
public canBeLiquidated(): [boolean, BN] {
|
|
545
639
|
const totalCollateral = this.getTotalCollateral();
|
|
546
|
-
const partialMaintenanceRequirement =
|
|
640
|
+
const partialMaintenanceRequirement =
|
|
641
|
+
this.getMaintenanceMarginRequirement();
|
|
547
642
|
const marginRatio = this.getMarginRatio();
|
|
548
643
|
const canLiquidate = totalCollateral.lt(partialMaintenanceRequirement);
|
|
549
644
|
return [canLiquidate, marginRatio];
|
|
@@ -587,8 +682,7 @@ export class ClearingHouseUser {
|
|
|
587
682
|
*/
|
|
588
683
|
public liquidationPrice(
|
|
589
684
|
marketPosition: Pick<UserPosition, 'marketIndex'>,
|
|
590
|
-
positionBaseSizeChange: BN = ZERO
|
|
591
|
-
partial = false
|
|
685
|
+
positionBaseSizeChange: BN = ZERO
|
|
592
686
|
): BN {
|
|
593
687
|
// solves formula for example canBeLiquidated below
|
|
594
688
|
|
|
@@ -627,7 +721,6 @@ export class ClearingHouseUser {
|
|
|
627
721
|
quoteAssetAmount: new BN(0),
|
|
628
722
|
quoteEntryAmount: new BN(0),
|
|
629
723
|
openOrders: new BN(0),
|
|
630
|
-
unsettledPnl: new BN(0),
|
|
631
724
|
openBids: new BN(0),
|
|
632
725
|
openAsks: new BN(0),
|
|
633
726
|
};
|
|
@@ -638,7 +731,7 @@ export class ClearingHouseUser {
|
|
|
638
731
|
proposedMarketPosition.marketIndex
|
|
639
732
|
);
|
|
640
733
|
|
|
641
|
-
const proposedMarketPositionValue =
|
|
734
|
+
const proposedMarketPositionValue = calculateMarginBaseAssetValue(
|
|
642
735
|
market,
|
|
643
736
|
proposedMarketPosition,
|
|
644
737
|
this.getOracleDataForMarket(market.marketIndex)
|
|
@@ -655,18 +748,19 @@ export class ClearingHouseUser {
|
|
|
655
748
|
const market = this.clearingHouse.getMarketAccount(
|
|
656
749
|
position.marketIndex
|
|
657
750
|
);
|
|
658
|
-
const positionValue =
|
|
751
|
+
const positionValue = calculateMarginBaseAssetValue(
|
|
659
752
|
market,
|
|
660
753
|
position,
|
|
661
754
|
this.getOracleDataForMarket(market.marketIndex)
|
|
662
755
|
);
|
|
663
|
-
const marketMarginRequirement = positionValue
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
756
|
+
const marketMarginRequirement = positionValue;
|
|
757
|
+
new BN(
|
|
758
|
+
calculateMarketMarginRatio(
|
|
759
|
+
market,
|
|
760
|
+
position.baseAssetAmount.abs(),
|
|
761
|
+
'Maintenance'
|
|
668
762
|
)
|
|
669
|
-
|
|
763
|
+
).div(MARGIN_PRECISION);
|
|
670
764
|
totalMarginRequirement = totalMarginRequirement.add(
|
|
671
765
|
marketMarginRequirement
|
|
672
766
|
);
|
|
@@ -692,9 +786,13 @@ export class ClearingHouseUser {
|
|
|
692
786
|
marginRequirementExcludingTargetMarket.add(
|
|
693
787
|
proposedMarketPositionValue
|
|
694
788
|
.mul(
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
789
|
+
new BN(
|
|
790
|
+
calculateMarketMarginRatio(
|
|
791
|
+
market,
|
|
792
|
+
proposedMarketPosition.baseAssetAmount.abs(),
|
|
793
|
+
'Maintenance'
|
|
794
|
+
)
|
|
795
|
+
)
|
|
698
796
|
)
|
|
699
797
|
.div(MARGIN_PRECISION)
|
|
700
798
|
);
|
|
@@ -702,9 +800,10 @@ export class ClearingHouseUser {
|
|
|
702
800
|
marginRequirementAfterTrade
|
|
703
801
|
);
|
|
704
802
|
|
|
705
|
-
const marketMaxLeverage =
|
|
706
|
-
|
|
707
|
-
|
|
803
|
+
const marketMaxLeverage = this.getMaxLeverage(
|
|
804
|
+
proposedMarketPosition.marketIndex,
|
|
805
|
+
'Maintenance'
|
|
806
|
+
);
|
|
708
807
|
|
|
709
808
|
let priceDelta;
|
|
710
809
|
if (proposedBaseAssetAmount.lt(ZERO)) {
|
|
@@ -765,11 +864,11 @@ export class ClearingHouseUser {
|
|
|
765
864
|
|
|
766
865
|
const closeBaseAmount = currentPosition.baseAssetAmount
|
|
767
866
|
.mul(closeQuoteAmount)
|
|
768
|
-
.div(currentPosition.quoteAssetAmount)
|
|
867
|
+
.div(currentPosition.quoteAssetAmount.abs())
|
|
769
868
|
.add(
|
|
770
869
|
currentPosition.baseAssetAmount
|
|
771
870
|
.mul(closeQuoteAmount)
|
|
772
|
-
.mod(currentPosition.quoteAssetAmount)
|
|
871
|
+
.mod(currentPosition.quoteAssetAmount.abs())
|
|
773
872
|
)
|
|
774
873
|
.neg();
|
|
775
874
|
|
|
@@ -777,8 +876,7 @@ export class ClearingHouseUser {
|
|
|
777
876
|
{
|
|
778
877
|
marketIndex: positionMarketIndex,
|
|
779
878
|
},
|
|
780
|
-
closeBaseAmount
|
|
781
|
-
true
|
|
879
|
+
closeBaseAmount
|
|
782
880
|
);
|
|
783
881
|
}
|
|
784
882
|
|
package/src/config.ts
CHANGED
|
@@ -28,7 +28,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
|
|
|
28
28
|
devnet: {
|
|
29
29
|
ENV: 'devnet',
|
|
30
30
|
PYTH_ORACLE_MAPPING_ADDRESS: 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2',
|
|
31
|
-
CLEARING_HOUSE_PROGRAM_ID: '
|
|
31
|
+
CLEARING_HOUSE_PROGRAM_ID: '7HDuhZ94TVTWpH3vba3dJhGWyHvQuy2zBjniRxE7PU88',
|
|
32
32
|
USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
|
|
33
33
|
MARKETS: DevnetMarkets,
|
|
34
34
|
BANKS: DevnetBanks,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Banks = exports.MainnetBanks = exports.DevnetBanks = exports.WRAPPED_SOL_MINT = void 0;
|
|
4
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
+
const __1 = require("../");
|
|
6
|
+
exports.WRAPPED_SOL_MINT = new web3_js_1.PublicKey('So11111111111111111111111111111111111111112');
|
|
7
|
+
exports.DevnetBanks = [
|
|
8
|
+
{
|
|
9
|
+
symbol: 'USDC',
|
|
10
|
+
bankIndex: new __1.BN(0),
|
|
11
|
+
oracle: web3_js_1.PublicKey.default,
|
|
12
|
+
oracleSource: __1.OracleSource.QUOTE_ASSET,
|
|
13
|
+
mint: new web3_js_1.PublicKey('8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2'),
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
symbol: 'SOL',
|
|
17
|
+
bankIndex: new __1.BN(1),
|
|
18
|
+
oracle: new web3_js_1.PublicKey('J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix'),
|
|
19
|
+
oracleSource: __1.OracleSource.PYTH,
|
|
20
|
+
mint: new web3_js_1.PublicKey(exports.WRAPPED_SOL_MINT),
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
symbol: 'BTC',
|
|
24
|
+
bankIndex: new __1.BN(2),
|
|
25
|
+
oracle: new web3_js_1.PublicKey('HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J'),
|
|
26
|
+
oracleSource: __1.OracleSource.PYTH,
|
|
27
|
+
mint: new web3_js_1.PublicKey('3BZPwbcqB5kKScF3TEXxwNfx5ipV13kbRVDvfVp5c6fv'),
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
exports.MainnetBanks = [
|
|
31
|
+
{
|
|
32
|
+
symbol: 'USDC',
|
|
33
|
+
bankIndex: new __1.BN(0),
|
|
34
|
+
oracle: web3_js_1.PublicKey.default,
|
|
35
|
+
oracleSource: __1.OracleSource.QUOTE_ASSET,
|
|
36
|
+
mint: new web3_js_1.PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
exports.Banks = {
|
|
40
|
+
devnet: exports.DevnetBanks,
|
|
41
|
+
'mainnet-beta': exports.MainnetBanks,
|
|
42
|
+
};
|
package/src/constants/banks.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { BN, OracleSource } from '../';
|
|
2
|
-
import { DriftEnv } from '../';
|
|
3
1
|
import { PublicKey } from '@solana/web3.js';
|
|
2
|
+
import { BN, DriftEnv, OracleSource } from '../';
|
|
4
3
|
|
|
5
4
|
export type BankConfig = {
|
|
6
5
|
symbol: string;
|
|
@@ -10,6 +9,10 @@ export type BankConfig = {
|
|
|
10
9
|
oracleSource: OracleSource;
|
|
11
10
|
};
|
|
12
11
|
|
|
12
|
+
export const WRAPPED_SOL_MINT = new PublicKey(
|
|
13
|
+
'So11111111111111111111111111111111111111112'
|
|
14
|
+
);
|
|
15
|
+
|
|
13
16
|
export const DevnetBanks: BankConfig[] = [
|
|
14
17
|
{
|
|
15
18
|
symbol: 'USDC',
|
|
@@ -23,14 +26,14 @@ export const DevnetBanks: BankConfig[] = [
|
|
|
23
26
|
bankIndex: new BN(1),
|
|
24
27
|
oracle: new PublicKey('J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix'),
|
|
25
28
|
oracleSource: OracleSource.PYTH,
|
|
26
|
-
mint: new PublicKey(
|
|
29
|
+
mint: new PublicKey(WRAPPED_SOL_MINT),
|
|
27
30
|
},
|
|
28
31
|
{
|
|
29
32
|
symbol: 'BTC',
|
|
30
33
|
bankIndex: new BN(2),
|
|
31
34
|
oracle: new PublicKey('HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J'),
|
|
32
35
|
oracleSource: OracleSource.PYTH,
|
|
33
|
-
mint: new PublicKey('
|
|
36
|
+
mint: new PublicKey('3BZPwbcqB5kKScF3TEXxwNfx5ipV13kbRVDvfVp5c6fv'),
|
|
34
37
|
},
|
|
35
38
|
];
|
|
36
39
|
|