@drift-labs/sdk 2.34.1-beta.2 → 2.34.1-beta.3
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/math/funding.d.ts +3 -12
- package/lib/math/funding.js +71 -113
- package/lib/user.d.ts +2 -1
- package/lib/user.js +36 -3
- package/package.json +2 -1
- package/src/math/funding.ts +142 -142
- package/src/user.ts +57 -6
- package/tests/amm/test.ts +122 -0
- package/tests/dlob/helpers.ts +6 -5
- package/tests/spot/test.ts +43 -2
- package/tests/user/helpers.ts +89 -0
- package/tests/user/test.ts +286 -0
package/tests/spot/test.ts
CHANGED
|
@@ -3,14 +3,55 @@ import {
|
|
|
3
3
|
ZERO,
|
|
4
4
|
calculateSpotMarketBorrowCapacity,
|
|
5
5
|
SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION,
|
|
6
|
+
calculateSizePremiumLiabilityWeight,
|
|
6
7
|
} from '../../src';
|
|
7
8
|
import { mockSpotMarkets } from '../dlob/helpers';
|
|
9
|
+
import * as _ from 'lodash';
|
|
8
10
|
|
|
9
11
|
import { assert } from '../../src/assert/assert';
|
|
10
12
|
|
|
11
13
|
describe('Spot Tests', () => {
|
|
14
|
+
it('size premium via imf factor', () => {
|
|
15
|
+
const maintLiabWgt = new BN(1.1 * 1e4);
|
|
16
|
+
|
|
17
|
+
const ans0 = calculateSizePremiumLiabilityWeight(
|
|
18
|
+
new BN(200000 * 1e9),
|
|
19
|
+
ZERO,
|
|
20
|
+
maintLiabWgt,
|
|
21
|
+
new BN(1e4)
|
|
22
|
+
);
|
|
23
|
+
assert(ans0.eq(maintLiabWgt));
|
|
24
|
+
|
|
25
|
+
const ans = calculateSizePremiumLiabilityWeight(
|
|
26
|
+
new BN(200000 * 1e9),
|
|
27
|
+
new BN(0.00055 * 1e6),
|
|
28
|
+
maintLiabWgt,
|
|
29
|
+
new BN(1e4)
|
|
30
|
+
);
|
|
31
|
+
assert(ans.eq(new BN('11259')));
|
|
32
|
+
assert(ans.gt(maintLiabWgt));
|
|
33
|
+
|
|
34
|
+
const ans2 = calculateSizePremiumLiabilityWeight(
|
|
35
|
+
new BN(10000 * 1e9),
|
|
36
|
+
new BN(0.003 * 1e6),
|
|
37
|
+
maintLiabWgt,
|
|
38
|
+
new BN(1e4)
|
|
39
|
+
);
|
|
40
|
+
assert(ans2.eq(new BN('11800')));
|
|
41
|
+
assert(ans.gt(maintLiabWgt));
|
|
42
|
+
|
|
43
|
+
const ans3 = calculateSizePremiumLiabilityWeight(
|
|
44
|
+
new BN(100000 * 1e9),
|
|
45
|
+
new BN(0.003 * 1e6),
|
|
46
|
+
maintLiabWgt,
|
|
47
|
+
new BN(1e4)
|
|
48
|
+
);
|
|
49
|
+
assert(ans3.eq(new BN('18286')));
|
|
50
|
+
assert(ans3.gt(maintLiabWgt));
|
|
51
|
+
});
|
|
52
|
+
|
|
12
53
|
it('base borrow capacity', () => {
|
|
13
|
-
const mockSpot = mockSpotMarkets[0];
|
|
54
|
+
const mockSpot = _.cloneDeep(mockSpotMarkets[0]);
|
|
14
55
|
mockSpot.maxBorrowRate = 1000000;
|
|
15
56
|
mockSpot.optimalBorrowRate = 100000;
|
|
16
57
|
mockSpot.optimalUtilization = 700000;
|
|
@@ -70,7 +111,7 @@ describe('Spot Tests', () => {
|
|
|
70
111
|
});
|
|
71
112
|
|
|
72
113
|
it('complex borrow capacity', () => {
|
|
73
|
-
const mockSpot = mockSpotMarkets[0];
|
|
114
|
+
const mockSpot = _.cloneDeep(mockSpotMarkets[0]);
|
|
74
115
|
mockSpot.maxBorrowRate = 1000000;
|
|
75
116
|
mockSpot.optimalBorrowRate = 70000;
|
|
76
117
|
mockSpot.optimalUtilization = 700000;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { PublicKey } from '@solana/web3.js';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
SpotPosition,
|
|
5
|
+
SpotBalanceType,
|
|
6
|
+
Order,
|
|
7
|
+
OrderStatus,
|
|
8
|
+
MarketType,
|
|
9
|
+
OrderType,
|
|
10
|
+
PositionDirection,
|
|
11
|
+
OrderTriggerCondition,
|
|
12
|
+
UserStatus,
|
|
13
|
+
UserAccount,
|
|
14
|
+
ZERO,
|
|
15
|
+
} from '../../src';
|
|
16
|
+
|
|
17
|
+
import { mockPerpPosition } from '../dlob/helpers';
|
|
18
|
+
|
|
19
|
+
export const mockOrder: Order = {
|
|
20
|
+
status: OrderStatus.INIT,
|
|
21
|
+
orderType: OrderType.MARKET,
|
|
22
|
+
marketType: MarketType.PERP,
|
|
23
|
+
slot: ZERO,
|
|
24
|
+
orderId: 0,
|
|
25
|
+
userOrderId: 0,
|
|
26
|
+
marketIndex: 0,
|
|
27
|
+
price: ZERO,
|
|
28
|
+
baseAssetAmount: ZERO,
|
|
29
|
+
baseAssetAmountFilled: ZERO,
|
|
30
|
+
quoteAssetAmount: ZERO,
|
|
31
|
+
quoteAssetAmountFilled: ZERO,
|
|
32
|
+
direction: PositionDirection.LONG,
|
|
33
|
+
reduceOnly: false,
|
|
34
|
+
triggerPrice: ZERO,
|
|
35
|
+
triggerCondition: OrderTriggerCondition.ABOVE,
|
|
36
|
+
existingPositionDirection: PositionDirection.LONG,
|
|
37
|
+
postOnly: false,
|
|
38
|
+
immediateOrCancel: false,
|
|
39
|
+
oraclePriceOffset: 0,
|
|
40
|
+
auctionDuration: 0,
|
|
41
|
+
auctionStartPrice: ZERO,
|
|
42
|
+
auctionEndPrice: ZERO,
|
|
43
|
+
maxTs: ZERO,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const mockSpotPosition: SpotPosition = {
|
|
47
|
+
marketIndex: 0,
|
|
48
|
+
balanceType: SpotBalanceType.DEPOSIT,
|
|
49
|
+
scaledBalance: ZERO,
|
|
50
|
+
openOrders: 0,
|
|
51
|
+
openBids: ZERO,
|
|
52
|
+
openAsks: ZERO,
|
|
53
|
+
cumulativeDeposits: ZERO,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const mockUserAccount: UserAccount = {
|
|
57
|
+
authority: PublicKey.default,
|
|
58
|
+
delegate: PublicKey.default,
|
|
59
|
+
name: [1],
|
|
60
|
+
subAccountId: 0,
|
|
61
|
+
spotPositions: Array.from({ length: 8 }, function () {
|
|
62
|
+
return Object.assign({}, mockSpotPosition);
|
|
63
|
+
}),
|
|
64
|
+
perpPositions: Array.from({ length: 8 }, function () {
|
|
65
|
+
return Object.assign({}, mockPerpPosition);
|
|
66
|
+
}),
|
|
67
|
+
orders: Array.from({ length: 8 }, function () {
|
|
68
|
+
return Object.assign({}, mockOrder);
|
|
69
|
+
}),
|
|
70
|
+
status: UserStatus.ACTIVE,
|
|
71
|
+
nextLiquidationId: 0,
|
|
72
|
+
nextOrderId: 0,
|
|
73
|
+
maxMarginRatio: 0,
|
|
74
|
+
lastAddPerpLpSharesTs: ZERO,
|
|
75
|
+
settledPerpPnl: ZERO,
|
|
76
|
+
totalDeposits: ZERO,
|
|
77
|
+
totalWithdraws: ZERO,
|
|
78
|
+
totalSocialLoss: ZERO,
|
|
79
|
+
cumulativePerpFunding: ZERO,
|
|
80
|
+
cumulativeSpotFees: ZERO,
|
|
81
|
+
liquidationMarginFreed: ZERO,
|
|
82
|
+
lastActiveSlot: ZERO,
|
|
83
|
+
isMarginTradingEnabled: true,
|
|
84
|
+
idle: false,
|
|
85
|
+
openOrders: 0,
|
|
86
|
+
hasOpenOrder: false,
|
|
87
|
+
openAuctions: 0,
|
|
88
|
+
hasOpenAuction: false,
|
|
89
|
+
};
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BN,
|
|
3
|
+
ZERO,
|
|
4
|
+
User,
|
|
5
|
+
UserAccount,
|
|
6
|
+
PublicKey,
|
|
7
|
+
PerpMarketAccount,
|
|
8
|
+
SpotMarketAccount,
|
|
9
|
+
PRICE_PRECISION,
|
|
10
|
+
OraclePriceData,
|
|
11
|
+
BASE_PRECISION,
|
|
12
|
+
QUOTE_PRECISION,
|
|
13
|
+
calculatePositionPNL,
|
|
14
|
+
SPOT_MARKET_BALANCE_PRECISION,
|
|
15
|
+
} from '../../src';
|
|
16
|
+
import { MockUserMap, mockPerpMarkets, mockSpotMarkets } from '../dlob/helpers';
|
|
17
|
+
import { assert } from '../../src/assert/assert';
|
|
18
|
+
import { mockUserAccount } from './helpers';
|
|
19
|
+
import * as _ from 'lodash';
|
|
20
|
+
|
|
21
|
+
async function makeMockUser(
|
|
22
|
+
myMockPerpMarkets,
|
|
23
|
+
myMockSpotMarkets,
|
|
24
|
+
myMockUserAccount,
|
|
25
|
+
perpOraclePriceList,
|
|
26
|
+
spotOraclePriceList
|
|
27
|
+
): Promise<User> {
|
|
28
|
+
const umap = new MockUserMap();
|
|
29
|
+
const mockUser: User = await umap.mustGet('1');
|
|
30
|
+
mockUser._isSubscribed = true;
|
|
31
|
+
mockUser.driftClient._isSubscribed = true;
|
|
32
|
+
const oraclePriceMap = {};
|
|
33
|
+
// console.log(perpOraclePriceList, myMockPerpMarkets.length);
|
|
34
|
+
// console.log(spotOraclePriceList, myMockSpotMarkets.length);
|
|
35
|
+
|
|
36
|
+
for (let i = 0; i < myMockPerpMarkets.length; i++) {
|
|
37
|
+
oraclePriceMap[myMockPerpMarkets[i].amm.oracle.toString()] =
|
|
38
|
+
perpOraclePriceList[i];
|
|
39
|
+
}
|
|
40
|
+
for (let i = 0; i < myMockSpotMarkets.length; i++) {
|
|
41
|
+
oraclePriceMap[myMockSpotMarkets[i].oracle.toString()] =
|
|
42
|
+
spotOraclePriceList[i];
|
|
43
|
+
}
|
|
44
|
+
// console.log(oraclePriceMap);
|
|
45
|
+
|
|
46
|
+
function getMockUserAccount(): UserAccount {
|
|
47
|
+
return myMockUserAccount;
|
|
48
|
+
}
|
|
49
|
+
function getMockPerpMarket(marketIndex): PerpMarketAccount {
|
|
50
|
+
return myMockPerpMarkets[marketIndex];
|
|
51
|
+
}
|
|
52
|
+
function getMockSpotMarket(marketIndex): SpotMarketAccount {
|
|
53
|
+
return myMockSpotMarkets[marketIndex];
|
|
54
|
+
}
|
|
55
|
+
function getMockOracle(oracleKey: PublicKey) {
|
|
56
|
+
// console.log('oracleKey.toString():', oracleKey.toString());
|
|
57
|
+
// console.log(
|
|
58
|
+
// 'oraclePriceMap[oracleKey.toString()]:',
|
|
59
|
+
// oraclePriceMap[oracleKey.toString()]
|
|
60
|
+
// );
|
|
61
|
+
|
|
62
|
+
const QUOTE_ORACLE_PRICE_DATA: OraclePriceData = {
|
|
63
|
+
price: new BN(
|
|
64
|
+
oraclePriceMap[oracleKey.toString()] * PRICE_PRECISION.toNumber()
|
|
65
|
+
),
|
|
66
|
+
slot: new BN(0),
|
|
67
|
+
confidence: new BN(1),
|
|
68
|
+
hasSufficientNumberOfDataPoints: true,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
data: QUOTE_ORACLE_PRICE_DATA,
|
|
73
|
+
slot: 0,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
mockUser.getUserAccount = getMockUserAccount;
|
|
78
|
+
mockUser.driftClient.getPerpMarketAccount = getMockPerpMarket;
|
|
79
|
+
mockUser.driftClient.getSpotMarketAccount = getMockSpotMarket;
|
|
80
|
+
mockUser.driftClient.getOraclePriceDataAndSlot = getMockOracle;
|
|
81
|
+
return mockUser;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
describe('User Tests', () => {
|
|
85
|
+
it('empty user account', async () => {
|
|
86
|
+
console.log(mockSpotMarkets[0]);
|
|
87
|
+
const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
|
|
88
|
+
const myMockSpotMarkets = _.cloneDeep(mockSpotMarkets);
|
|
89
|
+
const myMockUserAccount = _.cloneDeep(mockUserAccount);
|
|
90
|
+
console.log(
|
|
91
|
+
'spot cumulativeDepositInterest:',
|
|
92
|
+
mockSpotMarkets[0].cumulativeDepositInterest.toString()
|
|
93
|
+
);
|
|
94
|
+
const mockUser: User = await makeMockUser(
|
|
95
|
+
myMockPerpMarkets,
|
|
96
|
+
myMockSpotMarkets,
|
|
97
|
+
myMockUserAccount,
|
|
98
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
|
99
|
+
[1, 1, 1, 1, 1, 1, 1, 1]
|
|
100
|
+
);
|
|
101
|
+
const uA = mockUser.getUserAccount();
|
|
102
|
+
assert(uA.idle == false);
|
|
103
|
+
console.log(
|
|
104
|
+
'spot cumulativeDepositInterest:',
|
|
105
|
+
myMockSpotMarkets[0].cumulativeDepositInterest.toString()
|
|
106
|
+
);
|
|
107
|
+
assert(mockUser.getFreeCollateral().eq(ZERO));
|
|
108
|
+
|
|
109
|
+
console.log(mockUser.getHealth());
|
|
110
|
+
assert(mockUser.getHealth() == 100);
|
|
111
|
+
|
|
112
|
+
console.log(mockUser.getMaxLeverageForPerp(0));
|
|
113
|
+
assert(mockUser.getMaxLeverageForPerp(0).eq(ZERO));
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('user account unsettled pnl', async () => {
|
|
117
|
+
// no collateral, but positive upnl no liability
|
|
118
|
+
const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
|
|
119
|
+
const myMockSpotMarkets = _.cloneDeep(mockSpotMarkets);
|
|
120
|
+
const myMockUserAccount = _.cloneDeep(mockUserAccount);
|
|
121
|
+
|
|
122
|
+
myMockUserAccount.perpPositions[0].baseAssetAmount = new BN(
|
|
123
|
+
0 * BASE_PRECISION.toNumber()
|
|
124
|
+
);
|
|
125
|
+
myMockUserAccount.perpPositions[0].quoteAssetAmount = new BN(
|
|
126
|
+
10 * QUOTE_PRECISION.toNumber()
|
|
127
|
+
);
|
|
128
|
+
assert(
|
|
129
|
+
myMockUserAccount.perpPositions[0].quoteAssetAmount.eq(new BN('10000000'))
|
|
130
|
+
); // $10
|
|
131
|
+
|
|
132
|
+
const mockUser: User = await makeMockUser(
|
|
133
|
+
myMockPerpMarkets,
|
|
134
|
+
myMockSpotMarkets,
|
|
135
|
+
myMockUserAccount,
|
|
136
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
|
137
|
+
[1, 1, 1, 1, 1, 1, 1, 1]
|
|
138
|
+
);
|
|
139
|
+
const uA = mockUser.getUserAccount();
|
|
140
|
+
assert(uA.idle == false);
|
|
141
|
+
const activePerps = mockUser.getActivePerpPositions();
|
|
142
|
+
assert(activePerps.length == 1);
|
|
143
|
+
assert(uA.perpPositions[0].quoteAssetAmount.eq(new BN('10000000'))); // $10
|
|
144
|
+
assert(mockUser.getFreeCollateral().eq(ZERO));
|
|
145
|
+
|
|
146
|
+
const quotePrice = mockUser.driftClient.getOracleDataForSpotMarket(0).price;
|
|
147
|
+
console.log('quotePrice:', quotePrice.toString());
|
|
148
|
+
assert(quotePrice.eq(new BN('1000000')));
|
|
149
|
+
const pnl1 = calculatePositionPNL(
|
|
150
|
+
myMockPerpMarkets[0],
|
|
151
|
+
activePerps[0],
|
|
152
|
+
false,
|
|
153
|
+
mockUser.driftClient.getOracleDataForPerpMarket(0)
|
|
154
|
+
);
|
|
155
|
+
console.log('pnl1:', pnl1.toString());
|
|
156
|
+
assert(pnl1.eq(new BN('10000000')));
|
|
157
|
+
|
|
158
|
+
const upnl = mockUser.getUnrealizedPNL(false, undefined, undefined, false);
|
|
159
|
+
console.log('upnl:', upnl.toString());
|
|
160
|
+
assert(upnl.eq(new BN('10000000'))); // $10
|
|
161
|
+
|
|
162
|
+
const liqResult = mockUser.canBeLiquidated();
|
|
163
|
+
console.log(liqResult);
|
|
164
|
+
assert(liqResult.canBeLiquidated == false);
|
|
165
|
+
assert(liqResult.marginRequirement.eq(ZERO));
|
|
166
|
+
assert(liqResult.totalCollateral.eq(ZERO));
|
|
167
|
+
|
|
168
|
+
console.log(mockUser.getHealth());
|
|
169
|
+
assert(mockUser.getHealth() == 100);
|
|
170
|
+
|
|
171
|
+
console.log(mockUser.getMaxLeverageForPerp(0));
|
|
172
|
+
assert(mockUser.getMaxLeverageForPerp(0).eq(ZERO));
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('liquidatable long user account', async () => {
|
|
176
|
+
// no collateral, but positive upnl w/ liability
|
|
177
|
+
|
|
178
|
+
const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
|
|
179
|
+
const myMockSpotMarkets = _.cloneDeep(mockSpotMarkets);
|
|
180
|
+
const myMockUserAccount = _.cloneDeep(mockUserAccount);
|
|
181
|
+
myMockUserAccount.perpPositions[0].baseAssetAmount = new BN(
|
|
182
|
+
20 * BASE_PRECISION.toNumber()
|
|
183
|
+
);
|
|
184
|
+
myMockUserAccount.perpPositions[0].quoteAssetAmount = new BN(
|
|
185
|
+
-10 * QUOTE_PRECISION.toNumber()
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const mockUser: User = await makeMockUser(
|
|
189
|
+
myMockPerpMarkets,
|
|
190
|
+
myMockSpotMarkets,
|
|
191
|
+
myMockUserAccount,
|
|
192
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
|
193
|
+
[1, 1, 1, 1, 1, 1, 1, 1]
|
|
194
|
+
);
|
|
195
|
+
const uA = mockUser.getUserAccount();
|
|
196
|
+
assert(uA.idle == false);
|
|
197
|
+
|
|
198
|
+
assert(mockUser.getFreeCollateral().eq(ZERO));
|
|
199
|
+
const upnl = mockUser.getUnrealizedPNL(true, 0, undefined, false);
|
|
200
|
+
console.log('upnl:', upnl.toString());
|
|
201
|
+
assert(upnl.eq(new BN('10000000'))); // $10
|
|
202
|
+
|
|
203
|
+
const liqResult = mockUser.canBeLiquidated();
|
|
204
|
+
console.log(liqResult);
|
|
205
|
+
assert(liqResult.canBeLiquidated == true);
|
|
206
|
+
assert(liqResult.marginRequirement.eq(new BN('2000000'))); //10x maint leverage
|
|
207
|
+
assert(liqResult.totalCollateral.eq(ZERO));
|
|
208
|
+
|
|
209
|
+
console.log(mockUser.getHealth());
|
|
210
|
+
assert(mockUser.getHealth() == 0);
|
|
211
|
+
|
|
212
|
+
console.log(mockUser.getMaxLeverageForPerp(0));
|
|
213
|
+
assert(mockUser.getMaxLeverageForPerp(0).eq(new BN('20000')));
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('large usdc user account', async () => {
|
|
217
|
+
// no collateral, but positive upnl w/ liability
|
|
218
|
+
|
|
219
|
+
const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
|
|
220
|
+
const myMockSpotMarkets = _.cloneDeep(mockSpotMarkets);
|
|
221
|
+
const myMockUserAccount = _.cloneDeep(mockUserAccount);
|
|
222
|
+
|
|
223
|
+
myMockPerpMarkets[0].imfFactor = 550;
|
|
224
|
+
myMockUserAccount.spotPositions[0].scaledBalance = new BN(
|
|
225
|
+
100000 * SPOT_MARKET_BALANCE_PRECISION.toNumber()
|
|
226
|
+
); //100k
|
|
227
|
+
|
|
228
|
+
const mockUser: User = await makeMockUser(
|
|
229
|
+
myMockPerpMarkets,
|
|
230
|
+
myMockSpotMarkets,
|
|
231
|
+
myMockUserAccount,
|
|
232
|
+
[1, 1, 1, 1, 1, 1, 1, 1],
|
|
233
|
+
[1, 1, 1, 1, 1, 1, 1, 1]
|
|
234
|
+
);
|
|
235
|
+
const uA = mockUser.getUserAccount();
|
|
236
|
+
assert(uA.idle == false);
|
|
237
|
+
|
|
238
|
+
assert(uA.perpPositions[0].baseAssetAmount.eq(ZERO));
|
|
239
|
+
assert(uA.perpPositions[0].quoteAssetAmount.eq(ZERO));
|
|
240
|
+
assert(mockUser.getActivePerpPositions().length == 0);
|
|
241
|
+
|
|
242
|
+
assert(
|
|
243
|
+
uA.spotPositions[0].scaledBalance.eq(
|
|
244
|
+
new BN(100000 * SPOT_MARKET_BALANCE_PRECISION.toNumber())
|
|
245
|
+
)
|
|
246
|
+
);
|
|
247
|
+
for (let i = 1; i < 8; i++) {
|
|
248
|
+
assert(uA.spotPositions[i].scaledBalance.eq(ZERO));
|
|
249
|
+
}
|
|
250
|
+
console.log(
|
|
251
|
+
'mockUser.getTokenAmount():',
|
|
252
|
+
mockUser.getTokenAmount(0).toString()
|
|
253
|
+
);
|
|
254
|
+
console.log(
|
|
255
|
+
'spot cumulativeDepositInterest:',
|
|
256
|
+
mockSpotMarkets[0].cumulativeDepositInterest.toString()
|
|
257
|
+
);
|
|
258
|
+
assert(mockUser.getTokenAmount(0).eq(new BN('10000000000')));
|
|
259
|
+
assert(mockUser.getNetSpotMarketValue().eq(new BN('10000000000')));
|
|
260
|
+
assert(
|
|
261
|
+
mockUser
|
|
262
|
+
.getSpotMarketAssetAndLiabilityValue()
|
|
263
|
+
.totalLiabilityValue.eq(ZERO)
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
assert(mockUser.getFreeCollateral().eq(ZERO));
|
|
267
|
+
const upnl = mockUser.getUnrealizedPNL(true, 0, undefined, false);
|
|
268
|
+
console.log('upnl:', upnl.toString());
|
|
269
|
+
assert(upnl.eq(new BN('0'))); // $10
|
|
270
|
+
|
|
271
|
+
const liqResult = mockUser.canBeLiquidated();
|
|
272
|
+
console.log(liqResult);
|
|
273
|
+
assert(liqResult.canBeLiquidated == false);
|
|
274
|
+
assert(liqResult.marginRequirement.eq(new BN('0'))); //10x maint leverage
|
|
275
|
+
assert(liqResult.totalCollateral.eq(ZERO));
|
|
276
|
+
|
|
277
|
+
console.log(mockUser.getHealth());
|
|
278
|
+
assert(mockUser.getHealth() == 100);
|
|
279
|
+
|
|
280
|
+
console.log(
|
|
281
|
+
'getMaxLeverageForPerp:',
|
|
282
|
+
mockUser.getMaxLeverageForPerp(0).toString()
|
|
283
|
+
);
|
|
284
|
+
assert(mockUser.getMaxLeverageForPerp(0).eq(new BN('0')));
|
|
285
|
+
});
|
|
286
|
+
});
|