flash-sdk 1.0.21 → 1.0.23

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.
Files changed (48) hide show
  1. package/{lib → dist}/PerpetualsClient.d.ts +4 -0
  2. package/{lib → dist}/PerpetualsClient.js +121 -0
  3. package/{lib → dist}/tsconfig.tsbuildinfo +1 -1
  4. package/package.json +10 -4
  5. package/src/CustodyAccount.ts +0 -125
  6. package/src/OraclePrice.ts +0 -111
  7. package/src/PerpetualsClient.ts +0 -1961
  8. package/src/PoolAccount.ts +0 -491
  9. package/src/PoolConfig.json +0 -322
  10. package/src/PoolConfig.ts +0 -182
  11. package/src/PoolDataClient.ts +0 -173
  12. package/src/PositionAccount.ts +0 -58
  13. package/src/Token.ts +0 -1
  14. package/src/constants/index.ts +0 -21
  15. package/src/idl/perpetuals.ts +0 -7561
  16. package/src/index.ts +0 -19
  17. package/src/type-rules.md +0 -4
  18. package/src/types/index.ts +0 -290
  19. package/src/utils/index.ts +0 -234
  20. package/src/utils/rpc.ts +0 -162
  21. package/tsconfig.json +0 -23
  22. /package/{lib → dist}/CustodyAccount.d.ts +0 -0
  23. /package/{lib → dist}/CustodyAccount.js +0 -0
  24. /package/{lib → dist}/OraclePrice.d.ts +0 -0
  25. /package/{lib → dist}/OraclePrice.js +0 -0
  26. /package/{lib → dist}/PoolAccount.d.ts +0 -0
  27. /package/{lib → dist}/PoolAccount.js +0 -0
  28. /package/{lib → dist}/PoolConfig.d.ts +0 -0
  29. /package/{lib → dist}/PoolConfig.js +0 -0
  30. /package/{lib → dist}/PoolConfig.json +0 -0
  31. /package/{lib → dist}/PoolDataClient.d.ts +0 -0
  32. /package/{lib → dist}/PoolDataClient.js +0 -0
  33. /package/{lib → dist}/PositionAccount.d.ts +0 -0
  34. /package/{lib → dist}/PositionAccount.js +0 -0
  35. /package/{lib → dist}/Token.d.ts +0 -0
  36. /package/{lib → dist}/Token.js +0 -0
  37. /package/{lib → dist}/constants/index.d.ts +0 -0
  38. /package/{lib → dist}/constants/index.js +0 -0
  39. /package/{lib → dist}/idl/perpetuals.d.ts +0 -0
  40. /package/{lib → dist}/idl/perpetuals.js +0 -0
  41. /package/{lib → dist}/index.d.ts +0 -0
  42. /package/{lib → dist}/index.js +0 -0
  43. /package/{lib → dist}/types/index.d.ts +0 -0
  44. /package/{lib → dist}/types/index.js +0 -0
  45. /package/{lib → dist}/utils/index.d.ts +0 -0
  46. /package/{lib → dist}/utils/index.js +0 -0
  47. /package/{lib → dist}/utils/rpc.d.ts +0 -0
  48. /package/{lib → dist}/utils/rpc.js +0 -0
@@ -1,491 +0,0 @@
1
-
2
- import { BN_ZERO, BPS_DECIMALS, BPS_POWER, PERCENTAGE_DECIMALS, PRICE_DECIMALS, USD_DECIMALS } from "./constants";
3
- import { BN } from "@coral-xyz/anchor";
4
- import { Mint } from "@solana/spl-token";
5
- import { AumCalcMode, Custody, FeesMode, Pool, Side, TokenRatios, isVariant } from "./types";
6
- import { PublicKey } from "@solana/web3.js";
7
- import {CustodyAccount} from "./CustodyAccount";
8
- import { OraclePrice } from "./OraclePrice";
9
- import { PositionAccount } from "./PositionAccount";
10
- import { checkedCeilDiv, checkedDecimalCeilMul, checkedDecimalMul, scaleToExponent } from "./utils";
11
-
12
-
13
-
14
- export class PoolAccount implements Pool {
15
-
16
- publicKey: PublicKey;
17
-
18
- // all Pool Type data IMP:: SHOULD MATCH NAMES
19
- name: string;
20
- custodies: PublicKey[];
21
- ratios: TokenRatios[];
22
- aumUsd: BN;
23
- bump: number;
24
- lpTokenBump: number;
25
- inceptionTime: BN;
26
-
27
-
28
- constructor(publicKey: PublicKey, parseData: Pool) {
29
- this.publicKey = publicKey;
30
- Object.assign(this, parseData);
31
- }
32
-
33
- static from(publicKey: PublicKey, parseData: Pool): PoolAccount {
34
- return new PoolAccount(publicKey, parseData);
35
- }
36
-
37
-
38
- updatePoolData(parseData: Pool) {
39
- Object.assign(this, parseData);
40
- }
41
-
42
- getTokenId(custodyKey: PublicKey) : number {
43
- return this.custodies.findIndex(i => i.toBase58()==custodyKey.toBase58())
44
- }
45
-
46
-
47
- getAddLiquidityFee(
48
- tokenId: number,
49
- amount: BN,
50
- custody: CustodyAccount,
51
- tokenPrice: OraclePrice,
52
- ) : BN {
53
- return this.getFee(
54
- tokenId,
55
- custody.fees.addLiquidity,
56
- amount,
57
- new BN(0),
58
- custody,
59
- tokenPrice,
60
- )
61
- }
62
-
63
- // TODO
64
- getFee(
65
- tokenId: number,
66
- baseFee: BN,
67
- amountAdd: BN,
68
- amountRemove: BN,
69
- custody: CustodyAccount,
70
- tokenPrice: OraclePrice,
71
- ) : BN {
72
- if (custody.fees.mode === FeesMode.Fixed) {
73
- // return Self::get_fee_amount(base_fee, std::cmp::max(amount_add, amount_remove));
74
- return this.getFeeAmount(baseFee,BN.max(amountAdd, amountRemove))
75
- }
76
- // === NOW FEE MODE IS FeesMode.Linear
77
- // if token ratio is improved:
78
- // fee = base_fee / ratio_fee
79
- // otherwise:
80
- // fee = base_fee * ratio_fee
81
- // where:
82
- // if new_ratio < ratios.target:
83
- // ratio_fee = 1 + custody.fees.ratio_mult * (ratios.target - new_ratio) / (ratios.target - ratios.min);
84
- // otherwise:
85
- // ratio_fee = 1 + custody.fees.ratio_mult * (new_ratio - ratios.target) / (ratios.max - ratios.target);
86
-
87
- let ratios = this.ratios[tokenId];
88
- let current_ratio = this.getCurrentRatio(custody, tokenPrice);
89
- throw Error("TODODO");
90
-
91
- return new BN(0);
92
- }
93
-
94
- getFeeAmount(fee: BN, amount: BN) : BN {
95
- if (fee.isZero() || amount.isZero() ){
96
- return new BN(0);
97
- }
98
-
99
- return checkedCeilDiv(
100
- (amount.mul(fee)),
101
- new BN(BPS_POWER)
102
- )
103
- }
104
-
105
- getExitFee( size: BN, custody: CustodyAccount) : BN {
106
- return this.getFeeAmount(custody.fees.closePosition, size)
107
- }
108
-
109
- getLiquidationFee( size: BN, custody: CustodyAccount) : BN {
110
- return this.getFeeAmount(custody.fees.closePosition, size);
111
- }
112
-
113
- getCurrentRatio(
114
- custody : CustodyAccount,
115
- tokenPrice : OraclePrice
116
- ) :BN {
117
- if (this.aumUsd.isZero()) {
118
- return new BN(0);
119
- }
120
- // let ratio = math::checked_as_u64(math::checked_div(
121
- // math::checked_mul(
122
- // token_price.get_asset_amount_usd(custody.assets.owned, custody.decimals)? as u128,
123
- // Perpetuals::BPS_POWER,
124
- // )?,
125
- // self.aum_usd,
126
- // )?)?;
127
-
128
- // Ok(std::cmp::min(ratio, Perpetuals::BPS_POWER as u64))
129
- }
130
-
131
- static getEntryPrice(
132
- token_price: OraclePrice,
133
- token_ema_price: OraclePrice,
134
- side: Side,
135
- custody: CustodyAccount,
136
- ) : BN {
137
- let price = PoolAccount.getPrice(
138
- token_price,
139
- token_ema_price,
140
- (isVariant(side, 'long')) ? Side.Long : Side.Short,
141
- (isVariant(side, 'long')) ? custody.pricing.tradeSpreadLong : custody.pricing.tradeSpreadShort,
142
- );
143
- return price.scale_to_exponent(new BN(-1*PRICE_DECIMALS)).price
144
- }
145
-
146
- static getExitPrice(
147
- token_price: OraclePrice,
148
- token_ema_price: OraclePrice,
149
- side: Side,
150
- custody: CustodyAccount,
151
- ) : BN {
152
- let price = PoolAccount.getPrice(
153
- token_price,
154
- token_ema_price,
155
- (isVariant(side, 'long')) ? Side.Short : Side.Long,
156
- (isVariant(side, 'long')) ? custody.pricing.tradeSpreadShort : custody.pricing.tradeSpreadLong,
157
- );
158
- return price.scale_to_exponent(new BN(-1*PRICE_DECIMALS)).price
159
- }
160
-
161
- static getPriceAfterSlippage (
162
- isEntry : boolean,
163
- slippageBps : BN,
164
- token_price: OraclePrice,
165
- token_ema_price: OraclePrice,
166
- side: Side,
167
- custody: CustodyAccount,
168
- ) : BN {
169
- if(isEntry){
170
- const current_price = this.getEntryPrice(token_price, token_ema_price, side, custody);
171
- // console.log("getEntryPrice current_price:",current_price.toString())
172
- // TODO:: checked USE
173
- let spread_i = checkedDecimalCeilMul(
174
- current_price,
175
- new BN(-1*PRICE_DECIMALS),
176
- slippageBps,
177
- new BN(-1 * BPS_DECIMALS),
178
- new BN(-1*PRICE_DECIMALS),
179
- );
180
- // console.log("getPriceAfterSlippage spread_i:",spread_i.toString());
181
-
182
- if (isVariant(side, 'long')) {
183
- return current_price.add(spread_i);
184
- } else {
185
- if (spread_i.lt(current_price) ){
186
- return current_price.sub(spread_i)
187
- } else {
188
- return BN_ZERO;
189
- };
190
- }
191
- } else {
192
- // Opp in during close
193
- const current_price = this.getExitPrice(token_price, token_ema_price, side, custody);
194
- // console.log("getExitPrice current_price:",current_price.toString())
195
- // TODO:: checked USE
196
- let spread_i = checkedDecimalCeilMul(
197
- current_price,
198
- new BN(-1*PRICE_DECIMALS),
199
- slippageBps,
200
- new BN(-1 * BPS_DECIMALS),
201
- new BN(-1*PRICE_DECIMALS),
202
- );
203
- // console.log("spread_i:",spread_i);
204
- if (isVariant(side, 'long')) {
205
- if (spread_i.lt(current_price) ){
206
- return current_price.sub(spread_i)
207
- } else {
208
- return BN_ZERO;
209
- };
210
- } else {
211
- return current_price.add(spread_i);
212
- }
213
-
214
- }
215
- }
216
-
217
- static getPrice(
218
- token_price: OraclePrice,
219
- token_ema_price: OraclePrice,
220
- side: Side,
221
- spread: BN,
222
- ) : OraclePrice {
223
- if (isVariant(side, 'long')) {
224
- // console.log("inside long")
225
- let max_price : OraclePrice;
226
- if (token_price.cmp(token_ema_price)) {
227
- max_price = token_price;
228
- } else {
229
- max_price = token_ema_price;
230
- };
231
-
232
- let spread_i = checkedDecimalCeilMul(
233
- max_price.price,
234
- max_price.exponent,
235
- spread,
236
- new BN(-1 * BPS_DECIMALS),
237
- max_price.exponent,
238
- );
239
- // console.log("getPrice spread_i:",spread_i.toString());
240
-
241
- return new OraclePrice({
242
- price : max_price.price.add(spread_i),
243
- exponent : max_price.exponent,
244
- })
245
- } else {
246
- // console.log("inside short ")
247
- let min_price:OraclePrice;
248
- if (token_price.cmp(token_ema_price) ) {
249
- min_price = token_ema_price;
250
- } else {
251
- min_price = token_price;
252
- };
253
-
254
- let spread_i = checkedDecimalMul(
255
- min_price.price,
256
- min_price.exponent,
257
- spread,
258
- new BN(-1 * BPS_DECIMALS),
259
- min_price.exponent,
260
- );
261
- // console.log("spread_i:",spread_i.toString())
262
-
263
- let price : BN;
264
- if (spread_i.lt(min_price.price) ){
265
- price = min_price.price.sub(spread_i)
266
- } else {
267
- price = BN_ZERO;
268
- };
269
-
270
- return new OraclePrice({
271
- price : price,
272
- exponent : min_price.exponent
273
- })
274
-
275
- }
276
- }
277
-
278
- getPnlUsd(
279
- position: PositionAccount,
280
- token_price: OraclePrice,
281
- token_ema_price: OraclePrice,
282
- custody: CustodyAccount,
283
- curtime: BN,
284
- liquidation: boolean,
285
- ) {
286
-
287
- if (position.sizeUsd.isZero() || position.price.isZero()){
288
- return {
289
- profit: BN_ZERO,
290
- loss: BN_ZERO,
291
- exitFee: BN_ZERO
292
- }
293
- }
294
- let min_price: OraclePrice;
295
- if (token_price.cmp(token_ema_price)) {
296
- min_price = token_price
297
- } else {
298
- min_price = token_ema_price
299
- };
300
-
301
-
302
- let exit_price = PoolAccount.getExitPrice(token_price, token_ema_price, position.side, custody);
303
- // console.log("exit_price:",exit_price, exit_price?.toString())
304
-
305
-
306
- let size = token_ema_price.getTokenAmount(position.sizeUsd, custody.decimals);
307
- // console.log("size:",size, size?.toString())
308
-
309
- let exit_fee :BN;
310
- if (liquidation) {
311
- exit_fee = this.getLiquidationFee(size, custody)
312
- } else {
313
- exit_fee = this.getExitFee(size, custody)
314
- };
315
- // console.log("exit_fee:",exit_fee.toString())
316
-
317
- let exit_fee_usd = token_ema_price.getAssetAmountUsd(exit_fee, custody.decimals);
318
- // console.log("exit_fee_usd:",exit_fee_usd.toString())
319
-
320
- let interest_usd = custody.getInterestAmountUsd(position, curtime);
321
- // console.log("interest_usd:",interest_usd.toString())
322
-
323
- let unrealized_loss_usd = (exit_fee_usd.add(interest_usd)).add(position.unrealizedLossUsd);
324
- // console.log("unrealized_loss_usd:",unrealized_loss_usd.toString())
325
-
326
- let price_diff_profit, price_diff_loss ;
327
- if (isVariant(position.side, 'long')) {
328
- if (exit_price.gt(position.price)) {
329
- price_diff_profit = exit_price.sub(position.price)
330
- price_diff_loss = BN_ZERO
331
- } else {
332
- price_diff_profit = BN_ZERO;
333
- price_diff_loss = position.price.sub(exit_price);
334
- }
335
- } else if (exit_price.lt(position.price) ){
336
- price_diff_profit = position.price.sub(exit_price);
337
- price_diff_loss = BN_ZERO
338
- } else {
339
- price_diff_profit = BN_ZERO;
340
- price_diff_loss = exit_price.sub(position.price);
341
- };
342
- // console.log("1 price_diff_profit:",price_diff_profit.toString())
343
- // console.log("2 price_diff_loss:",price_diff_loss.toString())
344
-
345
-
346
- let position_price = scaleToExponent(
347
- position.price,
348
- new BN(-1 * PRICE_DECIMALS),
349
- new BN(-1 * USD_DECIMALS ),
350
- );
351
- // console.log("position_price:",position_price.toString())
352
-
353
- if (price_diff_profit.gt(BN_ZERO)) {
354
-
355
- let potential_profit_usd = (position.sizeUsd.mul(price_diff_profit)).div(position_price);
356
-
357
- potential_profit_usd = potential_profit_usd.add(position.unrealizedProfitUsd);
358
- // console.log("potential_profit_usd:",potential_profit_usd.toString())
359
-
360
-
361
- if (potential_profit_usd.gte(unrealized_loss_usd)) {
362
- let cur_profit_usd = potential_profit_usd.sub(unrealized_loss_usd);
363
- let max_profit_usd =
364
- min_price.getAssetAmountUsd(position.lockedAmount, custody.decimals);
365
-
366
- // console.log("cur_profit_usd:",cur_profit_usd.toString())
367
- // console.log("max_profit_usd:",max_profit_usd.toString())
368
-
369
- return {
370
- profit: BN.min(max_profit_usd, cur_profit_usd),
371
- loss: BN_ZERO,
372
- exitFee: exit_fee
373
- }
374
- } else {
375
- // console.log(" -- unrealized_loss_usd:",unrealized_loss_usd.toString())
376
- // console.log(" -- potential_profit_usd:",potential_profit_usd.toString())
377
-
378
- return {
379
- profit: BN_ZERO,
380
- loss: unrealized_loss_usd.sub(potential_profit_usd),
381
- exitFee: exit_fee
382
- }
383
- }
384
- } else {
385
- let potential_loss_usd = checkedCeilDiv(
386
- position.sizeUsd.mul(price_diff_loss),
387
- position_price,
388
- );
389
-
390
- potential_loss_usd = potential_loss_usd.add(unrealized_loss_usd);
391
- // console.log("potential_loss_usd:",potential_loss_usd.toString())
392
-
393
-
394
- if ( potential_loss_usd.gte(position.unrealizedProfitUsd) ) {
395
- // console.log("position.unrealizedProfitUsd:",position.unrealizedProfitUsd.toString())
396
-
397
- return {
398
- profit: BN_ZERO,
399
- loss: potential_loss_usd.sub(position.unrealizedProfitUsd),
400
- exitFee: exit_fee
401
- }
402
- } else {
403
- let cur_profit_usd = position.unrealizedProfitUsd.sub(potential_loss_usd);
404
- let max_profit_usd = min_price.getAssetAmountUsd(position.lockedAmount, custody.decimals);
405
- // console.log("cur_profit_usd:",cur_profit_usd.toString())
406
- // console.log("max_profit_usd:",max_profit_usd.toString())
407
-
408
- return {
409
- profit: BN.min(max_profit_usd, cur_profit_usd),
410
- loss: BN_ZERO,
411
- exitFee: exit_fee
412
- }
413
- }
414
- }
415
- } //getPnlUsd
416
-
417
- getAssetsUnderManagementUsd(
418
- token_prices: OraclePrice[],
419
- token_ema_prices: OraclePrice[],
420
- custodyAccounts : CustodyAccount[],
421
- aum_calc_mode: AumCalcMode,
422
- currentTime : BN
423
- ) : BN {
424
-
425
- let pool_amount_usd: BN = BN_ZERO;
426
-
427
- for (let index=0;index<custodyAccounts.length;index++) {
428
-
429
- if( token_prices.length != custodyAccounts.length || token_prices.length != token_ema_prices.length ){
430
- throw Error("token prices length incorrect");
431
- }
432
-
433
- let aum_token_price : OraclePrice;
434
- // switch unable to match enum
435
- if(isVariant(aum_calc_mode,"last")){
436
- aum_token_price = token_prices[index];
437
- } else if( isVariant(aum_calc_mode, "ema") ){
438
- aum_token_price = token_ema_prices[index];
439
- } else if( isVariant(aum_calc_mode, "min") ) {
440
- if (token_prices[index].cmp(token_ema_prices[index])) {
441
- aum_token_price = token_prices[index];
442
- } else {
443
- aum_token_price = token_ema_prices[index];
444
- }
445
- } else if( isVariant(aum_calc_mode, "max") ) {
446
- if (token_ema_prices[index].cmp(token_prices[index])) {
447
- aum_token_price = token_prices[index];
448
- } else {
449
- aum_token_price = token_ema_prices[index];
450
- }
451
- }
452
-
453
- let token_amount_usd :BN =
454
- aum_token_price.getAssetAmountUsd(custodyAccounts[index].assets.owned, custodyAccounts[index].decimals);
455
-
456
- pool_amount_usd = pool_amount_usd.add(token_amount_usd);
457
-
458
- if (custodyAccounts[index].pricing.useUnrealizedPnlInAum) {
459
- // compute aggregate unrealized pnl
460
- // console.log("long_pos:",custodyAccounts[index].longPositions)
461
- let { profit : long_profit , loss : long_loss } = this.getPnlUsd(
462
- custodyAccounts[index].getCollectivePosition(Side.Long),
463
- token_prices[index],
464
- token_ema_prices[index],
465
- custodyAccounts[index],
466
- currentTime,
467
- false,
468
- );
469
- // console.log("long_pos:",custodyAccounts[index].shortPositions)
470
-
471
- let { profit : short_profit , loss : short_loss } = this.getPnlUsd(
472
- custodyAccounts[index].getCollectivePosition(Side.Short),
473
- token_prices[index],
474
- token_ema_prices[index],
475
- custodyAccounts[index],
476
- currentTime,
477
- false,
478
- );
479
-
480
- // adjust pool amount by collective profit/loss
481
- pool_amount_usd = pool_amount_usd.add(long_profit);
482
- pool_amount_usd = pool_amount_usd.add(short_profit);
483
- pool_amount_usd = pool_amount_usd.sub(long_loss); // check overflow - saturating_sub
484
- pool_amount_usd = pool_amount_usd.sub(short_loss);
485
- }
486
- }
487
-
488
- return pool_amount_usd;
489
- }
490
-
491
- } // Pool