@drift-labs/sdk 2.13.0 → 2.14.0-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/lib/accounts/bulkAccountLoader.d.ts +1 -0
- package/lib/accounts/bulkAccountLoader.js +3 -3
- package/lib/accounts/fetch.js +2 -2
- package/lib/accounts/pollingDriftClientAccountSubscriber.js +7 -7
- package/lib/accounts/pollingTokenAccountSubscriber.js +2 -2
- package/lib/accounts/pollingUserAccountSubscriber.js +2 -2
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +2 -2
- package/lib/accounts/types.d.ts +1 -0
- package/lib/accounts/webSocketAccountSubscriber.js +1 -1
- package/lib/accounts/webSocketDriftClientAccountSubscriber.js +3 -3
- package/lib/addresses/marketAddresses.js +1 -1
- package/lib/addresses/pda.js +5 -1
- package/lib/adminClient.js +61 -57
- package/lib/dlob/DLOB.js +67 -67
- package/lib/dlob/DLOBNode.js +7 -7
- package/lib/dlob/NodeList.js +2 -2
- package/lib/driftClient.d.ts +33 -33
- package/lib/driftClient.js +120 -116
- package/lib/events/eventSubscriber.js +2 -2
- package/lib/events/pollingLogProvider.js +1 -1
- package/lib/events/types.d.ts +1 -0
- package/lib/examples/loadDlob.js +2 -2
- package/lib/examples/makeTradeExample.js +9 -9
- package/lib/factory/bigNum.js +9 -9
- package/lib/factory/oracleClient.js +2 -2
- package/lib/idl/drift.json +1 -1
- package/lib/index.js +5 -1
- package/lib/math/amm.js +23 -23
- package/lib/math/auction.js +6 -6
- package/lib/math/exchangeStatus.js +2 -2
- package/lib/math/funding.d.ts +1 -1
- package/lib/math/funding.js +8 -8
- package/lib/math/margin.js +5 -5
- package/lib/math/market.js +13 -13
- package/lib/math/oracles.js +1 -1
- package/lib/math/orders.js +23 -23
- package/lib/math/position.js +5 -5
- package/lib/math/repeg.js +1 -1
- package/lib/math/spotBalance.js +9 -9
- package/lib/math/spotPosition.js +3 -3
- package/lib/math/trade.js +42 -42
- package/lib/oracles/oracleClientCache.js +1 -1
- package/lib/oracles/pythClient.js +1 -1
- package/lib/token/index.js +1 -1
- package/lib/tokenFaucet.js +5 -1
- package/lib/tx/retryTxSender.js +1 -1
- package/lib/user.d.ts +8 -9
- package/lib/user.js +153 -158
- package/lib/userMap/userMap.js +1 -1
- package/lib/userMap/userStatsMap.js +3 -3
- package/lib/userStats.js +2 -2
- package/package.json +3 -3
- package/src/driftClient.ts +209 -68
- package/src/events/types.ts +15 -0
- package/src/idl/drift.json +1 -1
- package/src/math/funding.ts +7 -8
- package/src/math/spotBalance.ts +14 -7
- package/src/token/index.ts +1 -1
- package/src/user.ts +187 -184
- package/src/assert/assert.js +0 -9
- package/src/token/index.js +0 -38
- package/src/tx/types.js +0 -2
- package/src/tx/utils.js +0 -17
- package/src/util/computeUnits.js +0 -27
- package/src/util/getTokenAddress.js +0 -9
- package/src/util/promiseTimeout.js +0 -14
- package/src/util/tps.js +0 -27
package/src/math/funding.ts
CHANGED
|
@@ -19,7 +19,8 @@ import { calculateBidAskPrice } from './amm';
|
|
|
19
19
|
export async function calculateAllEstimatedFundingRate(
|
|
20
20
|
market: PerpMarketAccount,
|
|
21
21
|
oraclePriceData?: OraclePriceData,
|
|
22
|
-
periodAdjustment: BN = new BN(1)
|
|
22
|
+
periodAdjustment: BN = new BN(1),
|
|
23
|
+
now?: BN
|
|
23
24
|
): Promise<[BN, BN, BN, BN, BN]> {
|
|
24
25
|
// periodAdjustment
|
|
25
26
|
// 1: hourly
|
|
@@ -36,7 +37,7 @@ export async function calculateAllEstimatedFundingRate(
|
|
|
36
37
|
const payFreq = new BN(market.amm.fundingPeriod);
|
|
37
38
|
|
|
38
39
|
// todo: sufficiently differs from blockchain timestamp?
|
|
39
|
-
|
|
40
|
+
now = now || new BN((Date.now() / 1000).toFixed(0));
|
|
40
41
|
const timeSinceLastUpdate = now.sub(market.amm.lastFundingRateTs);
|
|
41
42
|
|
|
42
43
|
// calculate real-time mark twap
|
|
@@ -89,8 +90,8 @@ export async function calculateAllEstimatedFundingRate(
|
|
|
89
90
|
.mul(new BN(100))
|
|
90
91
|
.div(lastOracleTwapWithMantissa);
|
|
91
92
|
|
|
92
|
-
// verify pyth live input is within
|
|
93
|
-
if (oracleLiveVsTwap.lte(PRICE_PRECISION.mul(new BN(
|
|
93
|
+
// verify pyth live input is within 20% of last twap for live update
|
|
94
|
+
if (oracleLiveVsTwap.lte(PRICE_PRECISION.mul(new BN(20)))) {
|
|
94
95
|
oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
|
|
95
96
|
.mul(lastOracleTwapWithMantissa)
|
|
96
97
|
.add(timeSinceLastMarkChange.mul(oraclePrice))
|
|
@@ -99,13 +100,11 @@ export async function calculateAllEstimatedFundingRate(
|
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
const shrunkLastOracleTwapwithMantissa = oracleTwapTimeSinceLastUpdate
|
|
102
|
-
.mul(
|
|
103
|
+
.mul(oracleTwapWithMantissa)
|
|
103
104
|
.add(oracleInvalidDuration.mul(lastMarkTwapWithMantissa))
|
|
104
105
|
.div(oracleTwapTimeSinceLastUpdate.add(oracleInvalidDuration));
|
|
105
106
|
|
|
106
|
-
const twapSpread =
|
|
107
|
-
shrunkLastOracleTwapwithMantissa
|
|
108
|
-
);
|
|
107
|
+
const twapSpread = markTwapWithMantissa.sub(shrunkLastOracleTwapwithMantissa);
|
|
109
108
|
|
|
110
109
|
const twapSpreadPct = twapSpread
|
|
111
110
|
.mul(PRICE_PRECISION)
|
package/src/math/spotBalance.ts
CHANGED
|
@@ -131,7 +131,11 @@ export function calculateAssetWeight(
|
|
|
131
131
|
);
|
|
132
132
|
break;
|
|
133
133
|
case 'Maintenance':
|
|
134
|
-
assetWeight =
|
|
134
|
+
assetWeight = calculateSizeDiscountAssetWeight(
|
|
135
|
+
sizeInAmmReservePrecision,
|
|
136
|
+
new BN(spotMarket.imfFactor),
|
|
137
|
+
new BN(spotMarket.maintenanceAssetWeight)
|
|
138
|
+
);
|
|
135
139
|
break;
|
|
136
140
|
default:
|
|
137
141
|
assetWeight = new BN(spotMarket.initialAssetWeight);
|
|
@@ -322,12 +326,15 @@ export function calculateWithdrawLimit(
|
|
|
322
326
|
.add(marketDepositTokenAmount.mul(sinceLast))
|
|
323
327
|
.div(sinceLast.add(sinceStart));
|
|
324
328
|
|
|
325
|
-
const maxBorrowTokens = BN.
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
329
|
+
const maxBorrowTokens = BN.max(
|
|
330
|
+
spotMarket.withdrawGuardThreshold,
|
|
331
|
+
BN.min(
|
|
332
|
+
BN.max(
|
|
333
|
+
marketDepositTokenAmount.div(new BN(6)),
|
|
334
|
+
borrowTokenTwapLive.add(borrowTokenTwapLive.div(new BN(5)))
|
|
335
|
+
),
|
|
336
|
+
marketDepositTokenAmount.sub(marketDepositTokenAmount.div(new BN(5)))
|
|
337
|
+
)
|
|
331
338
|
); // between ~15-80% utilization with friction on twap
|
|
332
339
|
|
|
333
340
|
const minDepositTokens = depositTokenTwapLive.sub(
|
package/src/token/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ export function parseTokenAccount(data: Buffer): AccountInfo {
|
|
|
10
10
|
if (accountInfo.delegateOption === 0) {
|
|
11
11
|
accountInfo.delegate = null;
|
|
12
12
|
// eslint-disable-next-line new-cap
|
|
13
|
-
accountInfo.delegatedAmount =
|
|
13
|
+
accountInfo.delegatedAmount = u64.fromBuffer(Buffer.from('0'));
|
|
14
14
|
} else {
|
|
15
15
|
accountInfo.delegate = new PublicKey(accountInfo.delegate);
|
|
16
16
|
accountInfo.delegatedAmount = u64.fromBuffer(accountInfo.delegatedAmount);
|
package/src/user.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
PerpPosition,
|
|
11
11
|
SpotPosition,
|
|
12
12
|
isOneOfVariant,
|
|
13
|
+
PerpMarketAccount,
|
|
13
14
|
} from './types';
|
|
14
15
|
import { calculateEntryPrice } from './math/position';
|
|
15
16
|
import {
|
|
@@ -20,13 +21,13 @@ import {
|
|
|
20
21
|
BN_MAX,
|
|
21
22
|
QUOTE_PRECISION,
|
|
22
23
|
AMM_RESERVE_PRECISION,
|
|
23
|
-
PRICE_TO_QUOTE_PRECISION,
|
|
24
24
|
MARGIN_PRECISION,
|
|
25
25
|
SPOT_MARKET_WEIGHT_PRECISION,
|
|
26
26
|
QUOTE_SPOT_MARKET_INDEX,
|
|
27
27
|
TEN,
|
|
28
28
|
OPEN_ORDER_MARGIN_REQUIREMENT,
|
|
29
29
|
FIVE_MINUTE,
|
|
30
|
+
BASE_PRECISION,
|
|
30
31
|
} from './constants/numericConstants';
|
|
31
32
|
import {
|
|
32
33
|
UserAccountSubscriber,
|
|
@@ -45,6 +46,7 @@ import {
|
|
|
45
46
|
SpotMarketAccount,
|
|
46
47
|
getTokenValue,
|
|
47
48
|
getStrictTokenValue,
|
|
49
|
+
getSignedTokenAmount,
|
|
48
50
|
} from '.';
|
|
49
51
|
import {
|
|
50
52
|
getTokenAmount,
|
|
@@ -1279,238 +1281,244 @@ export class User {
|
|
|
1279
1281
|
}
|
|
1280
1282
|
|
|
1281
1283
|
/**
|
|
1282
|
-
* Calculate the liquidation price of a
|
|
1283
|
-
* @param
|
|
1284
|
-
* @param positionBaseSizeChange // change in position size to calculate liquidation price for : Precision 10^13
|
|
1285
|
-
* @param partial
|
|
1284
|
+
* Calculate the liquidation price of a spot position
|
|
1285
|
+
* @param marketIndex
|
|
1286
1286
|
* @returns Precision : PRICE_PRECISION
|
|
1287
1287
|
*/
|
|
1288
|
-
public spotLiquidationPrice(
|
|
1289
|
-
|
|
1290
|
-
): BN {
|
|
1291
|
-
const currentSpotPosition = this.getSpotPosition(spotPosition.marketIndex);
|
|
1288
|
+
public spotLiquidationPrice(marketIndex: number): BN {
|
|
1289
|
+
const currentSpotPosition = this.getSpotPosition(marketIndex);
|
|
1292
1290
|
|
|
1293
1291
|
if (!currentSpotPosition) {
|
|
1294
1292
|
return new BN(-1);
|
|
1295
1293
|
}
|
|
1296
1294
|
|
|
1297
|
-
const
|
|
1298
|
-
const
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
const currentSpotMarket = this.driftClient.getSpotMarketAccount(
|
|
1303
|
-
spotPosition.marketIndex
|
|
1295
|
+
const totalCollateral = this.getTotalCollateral('Maintenance');
|
|
1296
|
+
const maintenanceMarginRequirement = this.getMaintenanceMarginRequirement();
|
|
1297
|
+
const freeCollateral = BN.max(
|
|
1298
|
+
ZERO,
|
|
1299
|
+
totalCollateral.sub(maintenanceMarginRequirement)
|
|
1304
1300
|
);
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1301
|
+
|
|
1302
|
+
const market = this.driftClient.getSpotMarketAccount(marketIndex);
|
|
1303
|
+
const signedTokenAmount = getSignedTokenAmount(
|
|
1304
|
+
getTokenAmount(
|
|
1305
|
+
currentSpotPosition.scaledBalance,
|
|
1306
|
+
market,
|
|
1307
|
+
currentSpotPosition.balanceType
|
|
1308
|
+
),
|
|
1308
1309
|
currentSpotPosition.balanceType
|
|
1309
1310
|
);
|
|
1310
|
-
const tokenAmountQP = tokenAmount
|
|
1311
|
-
.mul(QUOTE_PRECISION)
|
|
1312
|
-
.div(new BN(10 ** currentSpotMarket.decimals));
|
|
1313
1311
|
|
|
1314
|
-
if (
|
|
1312
|
+
if (signedTokenAmount.eq(ZERO)) {
|
|
1315
1313
|
return new BN(-1);
|
|
1316
1314
|
}
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
.
|
|
1330
|
-
|
|
1315
|
+
|
|
1316
|
+
let freeCollateralDelta = this.calculateFreeCollateralDeltaForSpot(
|
|
1317
|
+
market,
|
|
1318
|
+
signedTokenAmount
|
|
1319
|
+
);
|
|
1320
|
+
|
|
1321
|
+
const oracle = market.oracle;
|
|
1322
|
+
const perpMarketWithSameOracle = this.driftClient
|
|
1323
|
+
.getPerpMarketAccounts()
|
|
1324
|
+
.find((market) => market.amm.oracle.equals(oracle));
|
|
1325
|
+
if (perpMarketWithSameOracle) {
|
|
1326
|
+
const perpPosition = this.getPerpPosition(
|
|
1327
|
+
perpMarketWithSameOracle.marketIndex
|
|
1328
|
+
);
|
|
1329
|
+
if (perpPosition) {
|
|
1330
|
+
const freeCollateralDeltaForPerp =
|
|
1331
|
+
this.calculateFreeCollateralDeltaForPerp(
|
|
1332
|
+
perpMarketWithSameOracle,
|
|
1333
|
+
perpPosition,
|
|
1334
|
+
ZERO
|
|
1335
|
+
);
|
|
1336
|
+
|
|
1337
|
+
freeCollateralDelta = freeCollateralDelta.add(
|
|
1338
|
+
freeCollateralDeltaForPerp || ZERO
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1331
1341
|
}
|
|
1332
1342
|
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1343
|
+
if (freeCollateralDelta.eq(ZERO)) {
|
|
1344
|
+
return new BN(-1);
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
const oraclePrice =
|
|
1348
|
+
this.driftClient.getOracleDataForSpotMarket(marketIndex).price;
|
|
1349
|
+
const liqPriceDelta = freeCollateral
|
|
1350
|
+
.mul(QUOTE_PRECISION)
|
|
1351
|
+
.div(freeCollateralDelta);
|
|
1336
1352
|
|
|
1337
|
-
const liqPrice =
|
|
1353
|
+
const liqPrice = oraclePrice.sub(liqPriceDelta);
|
|
1354
|
+
|
|
1355
|
+
if (liqPrice.lt(ZERO)) {
|
|
1356
|
+
return new BN(-1);
|
|
1357
|
+
}
|
|
1338
1358
|
|
|
1339
1359
|
return liqPrice;
|
|
1340
1360
|
}
|
|
1341
1361
|
|
|
1342
1362
|
/**
|
|
1343
1363
|
* Calculate the liquidation price of a perp position, with optional parameter to calculate the liquidation price after a trade
|
|
1344
|
-
* @param
|
|
1364
|
+
* @param marketIndex
|
|
1345
1365
|
* @param positionBaseSizeChange // change in position size to calculate liquidation price for : Precision 10^13
|
|
1346
|
-
* @param partial
|
|
1347
1366
|
* @returns Precision : PRICE_PRECISION
|
|
1348
1367
|
*/
|
|
1349
1368
|
public liquidationPrice(
|
|
1350
|
-
|
|
1369
|
+
marketIndex: number,
|
|
1351
1370
|
positionBaseSizeChange: BN = ZERO
|
|
1352
1371
|
): BN {
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1372
|
+
const totalCollateral = this.getTotalCollateral('Maintenance');
|
|
1373
|
+
const maintenanceMarginRequirement = this.getMaintenanceMarginRequirement();
|
|
1374
|
+
const freeCollateral = BN.max(
|
|
1375
|
+
ZERO,
|
|
1376
|
+
totalCollateral.sub(maintenanceMarginRequirement)
|
|
1377
|
+
);
|
|
1356
1378
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
2. lower collateral (-$4k)
|
|
1360
|
-
3. (10k - 4k)/(100k + 4k) => 6k/104k => .0576
|
|
1379
|
+
const market = this.driftClient.getPerpMarketAccount(marketIndex);
|
|
1380
|
+
const currentPerpPosition = this.getPerpPosition(marketIndex);
|
|
1361
1381
|
|
|
1362
|
-
|
|
1363
|
-
|
|
1382
|
+
let freeCollateralDelta = this.calculateFreeCollateralDeltaForPerp(
|
|
1383
|
+
market,
|
|
1384
|
+
currentPerpPosition,
|
|
1385
|
+
positionBaseSizeChange
|
|
1386
|
+
);
|
|
1364
1387
|
|
|
1365
|
-
|
|
1388
|
+
if (!freeCollateralDelta) {
|
|
1389
|
+
return new BN(-1);
|
|
1390
|
+
}
|
|
1366
1391
|
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1392
|
+
const oracle =
|
|
1393
|
+
this.driftClient.getPerpMarketAccount(marketIndex).amm.oracle;
|
|
1394
|
+
const spotMarketWithSameOracle = this.driftClient
|
|
1395
|
+
.getSpotMarketAccounts()
|
|
1396
|
+
.find((market) => market.oracle.equals(oracle));
|
|
1397
|
+
if (spotMarketWithSameOracle) {
|
|
1398
|
+
const spotPosition = this.getSpotPosition(
|
|
1399
|
+
spotMarketWithSameOracle.marketIndex
|
|
1374
1400
|
);
|
|
1401
|
+
if (spotPosition) {
|
|
1402
|
+
const signedTokenAmount = getSignedTokenAmount(
|
|
1403
|
+
getTokenAmount(
|
|
1404
|
+
spotPosition.scaledBalance,
|
|
1405
|
+
spotMarketWithSameOracle,
|
|
1406
|
+
spotPosition.balanceType
|
|
1407
|
+
),
|
|
1408
|
+
spotPosition.balanceType
|
|
1409
|
+
);
|
|
1375
1410
|
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1411
|
+
const spotFreeCollateralDelta =
|
|
1412
|
+
this.calculateFreeCollateralDeltaForSpot(
|
|
1413
|
+
spotMarketWithSameOracle,
|
|
1414
|
+
signedTokenAmount
|
|
1415
|
+
);
|
|
1416
|
+
freeCollateralDelta = freeCollateralDelta.add(
|
|
1417
|
+
spotFreeCollateralDelta || ZERO
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1379
1421
|
|
|
1380
|
-
|
|
1422
|
+
if (freeCollateralDelta.eq(ZERO)) {
|
|
1423
|
+
return new BN(-1);
|
|
1424
|
+
}
|
|
1381
1425
|
|
|
1382
|
-
const
|
|
1383
|
-
|
|
1384
|
-
|
|
1426
|
+
const oraclePrice =
|
|
1427
|
+
this.driftClient.getOracleDataForPerpMarket(marketIndex).price;
|
|
1428
|
+
const liqPriceDelta = freeCollateral
|
|
1429
|
+
.mul(QUOTE_PRECISION)
|
|
1430
|
+
.div(freeCollateralDelta);
|
|
1385
1431
|
|
|
1386
|
-
|
|
1387
|
-
const proposedPerpPosition: PerpPosition = {
|
|
1388
|
-
marketIndex: perpPosition.marketIndex,
|
|
1389
|
-
baseAssetAmount: proposedBaseAssetAmount,
|
|
1390
|
-
remainderBaseAssetAmount: 0,
|
|
1391
|
-
quoteAssetAmount: currentPerpPosition.quoteAssetAmount,
|
|
1392
|
-
lastCumulativeFundingRate: ZERO,
|
|
1393
|
-
quoteBreakEvenAmount: new BN(0),
|
|
1394
|
-
quoteEntryAmount: new BN(0),
|
|
1395
|
-
openOrders: 0,
|
|
1396
|
-
openBids: currentPerpPosition.openBids,
|
|
1397
|
-
openAsks: currentPerpPosition.openAsks,
|
|
1398
|
-
settledPnl: ZERO,
|
|
1399
|
-
lpShares: ZERO,
|
|
1400
|
-
lastBaseAssetAmountPerLp: ZERO,
|
|
1401
|
-
lastQuoteAssetAmountPerLp: ZERO,
|
|
1402
|
-
};
|
|
1432
|
+
const liqPrice = oraclePrice.sub(liqPriceDelta);
|
|
1403
1433
|
|
|
1404
|
-
if (
|
|
1434
|
+
if (liqPrice.lt(ZERO)) {
|
|
1435
|
+
return new BN(-1);
|
|
1436
|
+
}
|
|
1405
1437
|
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
);
|
|
1438
|
+
return liqPrice;
|
|
1439
|
+
}
|
|
1409
1440
|
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1441
|
+
calculateFreeCollateralDeltaForPerp(
|
|
1442
|
+
market: PerpMarketAccount,
|
|
1443
|
+
perpPosition: PerpPosition,
|
|
1444
|
+
positionBaseSizeChange: BN
|
|
1445
|
+
): BN | undefined {
|
|
1446
|
+
const currentBaseAssetAmount = perpPosition.baseAssetAmount;
|
|
1447
|
+
|
|
1448
|
+
const worstCaseBaseAssetAmount =
|
|
1449
|
+
calculateWorstCaseBaseAssetAmount(perpPosition);
|
|
1450
|
+
const orderBaseAssetAmount = worstCaseBaseAssetAmount.sub(
|
|
1451
|
+
currentBaseAssetAmount
|
|
1452
|
+
);
|
|
1453
|
+
const proposedBaseAssetAmount = currentBaseAssetAmount.add(
|
|
1454
|
+
positionBaseSizeChange
|
|
1455
|
+
);
|
|
1456
|
+
const proposedWorstCaseBaseAssetAmount = worstCaseBaseAssetAmount.add(
|
|
1457
|
+
positionBaseSizeChange
|
|
1415
1458
|
);
|
|
1416
1459
|
|
|
1417
|
-
|
|
1418
|
-
const totalPositionValueAfterTrade =
|
|
1419
|
-
totalPositionValueExcludingTargetMarket.add(proposedPerpPositionValue);
|
|
1420
|
-
|
|
1421
|
-
const marginRequirementOfAll = this.getMaintenanceMarginRequirement();
|
|
1422
|
-
const positionValue = calculateBaseAssetValueWithOracle(
|
|
1460
|
+
const marginRatio = calculateMarketMarginRatio(
|
|
1423
1461
|
market,
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
true
|
|
1462
|
+
proposedWorstCaseBaseAssetAmount.abs(),
|
|
1463
|
+
'Maintenance'
|
|
1427
1464
|
);
|
|
1428
|
-
const
|
|
1429
|
-
.mul(
|
|
1430
|
-
new BN(
|
|
1431
|
-
calculateMarketMarginRatio(
|
|
1432
|
-
market,
|
|
1433
|
-
calculateWorstCaseBaseAssetAmount(currentPerpPosition).abs(),
|
|
1434
|
-
'Maintenance'
|
|
1435
|
-
)
|
|
1436
|
-
)
|
|
1437
|
-
)
|
|
1465
|
+
const marginRatioQuotePrecision = new BN(marginRatio)
|
|
1466
|
+
.mul(QUOTE_PRECISION)
|
|
1438
1467
|
.div(MARGIN_PRECISION);
|
|
1439
1468
|
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1469
|
+
if (proposedWorstCaseBaseAssetAmount.eq(ZERO)) {
|
|
1470
|
+
return undefined;
|
|
1471
|
+
}
|
|
1443
1472
|
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1473
|
+
let freeCollateralDelta = ZERO;
|
|
1474
|
+
if (proposedBaseAssetAmount.gt(ZERO)) {
|
|
1475
|
+
freeCollateralDelta = QUOTE_PRECISION.sub(marginRatioQuotePrecision)
|
|
1476
|
+
.mul(proposedBaseAssetAmount)
|
|
1477
|
+
.div(BASE_PRECISION);
|
|
1478
|
+
} else {
|
|
1479
|
+
freeCollateralDelta = QUOTE_PRECISION.neg()
|
|
1480
|
+
.sub(marginRatioQuotePrecision)
|
|
1481
|
+
.mul(proposedBaseAssetAmount.abs())
|
|
1482
|
+
.div(BASE_PRECISION);
|
|
1483
|
+
}
|
|
1447
1484
|
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
totalPositionValueAfterTrade.lte(freeCollateralExcludingTargetMarket) &&
|
|
1451
|
-
proposedPerpPosition.baseAssetAmount.gt(ZERO)
|
|
1452
|
-
) {
|
|
1453
|
-
return new BN(-1);
|
|
1485
|
+
if (!orderBaseAssetAmount.eq(ZERO)) {
|
|
1486
|
+
freeCollateralDelta = freeCollateralDelta.sub(marginRatioQuotePrecision);
|
|
1454
1487
|
}
|
|
1455
1488
|
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
const marginRequirementTargetMarket = proposedPerpPositionValue
|
|
1459
|
-
.mul(
|
|
1460
|
-
new BN(
|
|
1461
|
-
calculateMarketMarginRatio(
|
|
1462
|
-
market,
|
|
1463
|
-
proposedWorstCastBaseAssetAmount.abs(),
|
|
1464
|
-
'Maintenance'
|
|
1465
|
-
)
|
|
1466
|
-
)
|
|
1467
|
-
)
|
|
1468
|
-
.div(MARGIN_PRECISION);
|
|
1489
|
+
return freeCollateralDelta;
|
|
1490
|
+
}
|
|
1469
1491
|
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
);
|
|
1492
|
+
calculateFreeCollateralDeltaForSpot(
|
|
1493
|
+
market: SpotMarketAccount,
|
|
1494
|
+
signedTokenAmount: BN
|
|
1495
|
+
): BN {
|
|
1496
|
+
const tokenPrecision = new BN(Math.pow(10, market.decimals));
|
|
1475
1497
|
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
)
|
|
1483
|
-
);
|
|
1498
|
+
if (signedTokenAmount.gt(ZERO)) {
|
|
1499
|
+
const assetWeight = calculateAssetWeight(
|
|
1500
|
+
signedTokenAmount,
|
|
1501
|
+
market,
|
|
1502
|
+
'Maintenance'
|
|
1503
|
+
);
|
|
1484
1504
|
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
.
|
|
1489
|
-
.div(marketMaxMaintLeverage.add(TEN_THOUSAND))
|
|
1490
|
-
.mul(PRICE_TO_QUOTE_PRECISION)
|
|
1491
|
-
.mul(AMM_RESERVE_PRECISION)
|
|
1492
|
-
.div(proposedBaseAssetAmount);
|
|
1505
|
+
return QUOTE_PRECISION.mul(assetWeight)
|
|
1506
|
+
.div(SPOT_MARKET_WEIGHT_PRECISION)
|
|
1507
|
+
.mul(signedTokenAmount)
|
|
1508
|
+
.div(tokenPrecision);
|
|
1493
1509
|
} else {
|
|
1494
|
-
|
|
1495
|
-
.
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
.div(proposedBaseAssetAmount);
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
const currentPrice = this.getOracleDataForPerpMarket(
|
|
1503
|
-
perpPosition.marketIndex
|
|
1504
|
-
).price;
|
|
1510
|
+
const liabilityWeight = calculateLiabilityWeight(
|
|
1511
|
+
signedTokenAmount.abs(),
|
|
1512
|
+
market,
|
|
1513
|
+
'Maintenance'
|
|
1514
|
+
);
|
|
1505
1515
|
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1516
|
+
return QUOTE_PRECISION.neg()
|
|
1517
|
+
.mul(liabilityWeight)
|
|
1518
|
+
.div(SPOT_MARKET_WEIGHT_PRECISION)
|
|
1519
|
+
.mul(signedTokenAmount.abs())
|
|
1520
|
+
.div(tokenPrecision);
|
|
1511
1521
|
}
|
|
1512
|
-
|
|
1513
|
-
return currentPrice.sub(priceDelta);
|
|
1514
1522
|
}
|
|
1515
1523
|
|
|
1516
1524
|
/**
|
|
@@ -1537,12 +1545,7 @@ export class User {
|
|
|
1537
1545
|
)
|
|
1538
1546
|
.neg();
|
|
1539
1547
|
|
|
1540
|
-
return this.liquidationPrice(
|
|
1541
|
-
{
|
|
1542
|
-
marketIndex: positionMarketIndex,
|
|
1543
|
-
},
|
|
1544
|
-
closeBaseAmount
|
|
1545
|
-
);
|
|
1548
|
+
return this.liquidationPrice(positionMarketIndex, closeBaseAmount);
|
|
1546
1549
|
}
|
|
1547
1550
|
|
|
1548
1551
|
/**
|
|
@@ -1845,7 +1848,7 @@ export class User {
|
|
|
1845
1848
|
return {
|
|
1846
1849
|
canBypass: false,
|
|
1847
1850
|
maxDepositAmount,
|
|
1848
|
-
depositAmount
|
|
1851
|
+
depositAmount,
|
|
1849
1852
|
netDeposits,
|
|
1850
1853
|
};
|
|
1851
1854
|
}
|
package/src/assert/assert.js
DELETED
package/src/token/index.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseTokenAccount = void 0;
|
|
4
|
-
const spl_token_1 = require("@solana/spl-token");
|
|
5
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
-
function parseTokenAccount(data) {
|
|
7
|
-
const accountInfo = spl_token_1.AccountLayout.decode(data);
|
|
8
|
-
accountInfo.mint = new web3_js_1.PublicKey(accountInfo.mint);
|
|
9
|
-
accountInfo.owner = new web3_js_1.PublicKey(accountInfo.owner);
|
|
10
|
-
accountInfo.amount = spl_token_1.u64.fromBuffer(accountInfo.amount);
|
|
11
|
-
if (accountInfo.delegateOption === 0) {
|
|
12
|
-
accountInfo.delegate = null;
|
|
13
|
-
// eslint-disable-next-line new-cap
|
|
14
|
-
accountInfo.delegatedAmount = new spl_token_1.u64(0);
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
accountInfo.delegate = new web3_js_1.PublicKey(accountInfo.delegate);
|
|
18
|
-
accountInfo.delegatedAmount = spl_token_1.u64.fromBuffer(accountInfo.delegatedAmount);
|
|
19
|
-
}
|
|
20
|
-
accountInfo.isInitialized = accountInfo.state !== 0;
|
|
21
|
-
accountInfo.isFrozen = accountInfo.state === 2;
|
|
22
|
-
if (accountInfo.isNativeOption === 1) {
|
|
23
|
-
accountInfo.rentExemptReserve = spl_token_1.u64.fromBuffer(accountInfo.isNative);
|
|
24
|
-
accountInfo.isNative = true;
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
accountInfo.rentExemptReserve = null;
|
|
28
|
-
accountInfo.isNative = false;
|
|
29
|
-
}
|
|
30
|
-
if (accountInfo.closeAuthorityOption === 0) {
|
|
31
|
-
accountInfo.closeAuthority = null;
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
accountInfo.closeAuthority = new web3_js_1.PublicKey(accountInfo.closeAuthority);
|
|
35
|
-
}
|
|
36
|
-
return accountInfo;
|
|
37
|
-
}
|
|
38
|
-
exports.parseTokenAccount = parseTokenAccount;
|
package/src/tx/types.js
DELETED
package/src/tx/utils.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.wrapInTx = void 0;
|
|
4
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
-
const COMPUTE_UNITS_DEFAULT = 200000;
|
|
6
|
-
function wrapInTx(instruction, computeUnits = 600000 // TODO, requires less code change
|
|
7
|
-
) {
|
|
8
|
-
const tx = new web3_js_1.Transaction();
|
|
9
|
-
if (computeUnits != COMPUTE_UNITS_DEFAULT) {
|
|
10
|
-
tx.add(web3_js_1.ComputeBudgetProgram.requestUnits({
|
|
11
|
-
units: computeUnits,
|
|
12
|
-
additionalFee: 0,
|
|
13
|
-
}));
|
|
14
|
-
}
|
|
15
|
-
return tx.add(instruction);
|
|
16
|
-
}
|
|
17
|
-
exports.wrapInTx = wrapInTx;
|
package/src/util/computeUnits.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.findComputeUnitConsumption = void 0;
|
|
13
|
-
function findComputeUnitConsumption(programId, connection, txSignature, commitment = 'confirmed') {
|
|
14
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
-
const tx = yield connection.getTransaction(txSignature, { commitment });
|
|
16
|
-
const computeUnits = [];
|
|
17
|
-
const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of ([0-9]{0,7}) compute units`);
|
|
18
|
-
tx.meta.logMessages.forEach((logMessage) => {
|
|
19
|
-
const match = logMessage.match(regex);
|
|
20
|
-
if (match && match[1]) {
|
|
21
|
-
computeUnits.push(match[1]);
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
return computeUnits;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
exports.findComputeUnitConsumption = findComputeUnitConsumption;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getTokenAddress = void 0;
|
|
4
|
-
const spl_token_1 = require("@solana/spl-token");
|
|
5
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
-
const getTokenAddress = (mintAddress, userPubKey) => {
|
|
7
|
-
return spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey(mintAddress), new web3_js_1.PublicKey(userPubKey));
|
|
8
|
-
};
|
|
9
|
-
exports.getTokenAddress = getTokenAddress;
|