@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.
Files changed (82) hide show
  1. package/lib/admin.d.ts +3 -3
  2. package/lib/admin.js +6 -6
  3. package/lib/clearingHouse.d.ts +22 -6
  4. package/lib/clearingHouse.js +357 -74
  5. package/lib/clearingHouseUser.d.ts +12 -17
  6. package/lib/clearingHouseUser.js +97 -88
  7. package/lib/config.js +1 -1
  8. package/lib/constants/banks.d.ts +2 -2
  9. package/lib/constants/banks.js +5 -4
  10. package/lib/constants/numericConstants.d.ts +3 -0
  11. package/lib/constants/numericConstants.js +4 -1
  12. package/lib/events/eventList.js +3 -0
  13. package/lib/events/types.d.ts +2 -1
  14. package/lib/factory/bigNum.d.ts +1 -0
  15. package/lib/factory/bigNum.js +37 -11
  16. package/lib/idl/clearing_house.json +611 -146
  17. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  18. package/lib/index.d.ts +2 -1
  19. package/lib/index.js +2 -1
  20. package/lib/math/amm.js +2 -2
  21. package/lib/math/bankBalance.d.ts +3 -1
  22. package/lib/math/bankBalance.js +54 -1
  23. package/lib/math/margin.d.ts +11 -0
  24. package/lib/math/margin.js +72 -0
  25. package/lib/math/market.d.ts +4 -1
  26. package/lib/math/market.js +35 -1
  27. package/lib/math/position.d.ts +8 -0
  28. package/lib/math/position.js +42 -12
  29. package/lib/orders.d.ts +1 -2
  30. package/lib/orders.js +2 -77
  31. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  32. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  33. package/lib/tx/retryTxSender.js +9 -2
  34. package/lib/types.d.ts +86 -16
  35. package/lib/types.js +18 -1
  36. package/lib/util/computeUnits.js +1 -1
  37. package/lib/util/getTokenAddress.d.ts +2 -0
  38. package/lib/util/getTokenAddress.js +9 -0
  39. package/package.json +1 -1
  40. package/src/admin.ts +7 -7
  41. package/src/clearingHouse.ts +636 -94
  42. package/src/clearingHouseConfig.js +2 -0
  43. package/src/clearingHouseUser.ts +219 -121
  44. package/src/clearingHouseUserConfig.js +2 -0
  45. package/src/config.ts +1 -1
  46. package/src/constants/banks.js +42 -0
  47. package/src/constants/banks.ts +7 -4
  48. package/src/constants/markets.js +42 -0
  49. package/src/constants/numericConstants.js +41 -0
  50. package/src/constants/numericConstants.ts +4 -0
  51. package/src/events/eventList.ts +3 -0
  52. package/src/events/types.ts +2 -0
  53. package/src/factory/bigNum.js +37 -11
  54. package/src/factory/bigNum.ts +43 -13
  55. package/src/idl/clearing_house.json +611 -146
  56. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  57. package/src/index.js +1 -1
  58. package/src/index.ts +2 -1
  59. package/src/math/amm.ts +8 -5
  60. package/src/math/bankBalance.ts +98 -1
  61. package/src/math/margin.ts +124 -0
  62. package/src/math/market.ts +66 -1
  63. package/src/math/position.ts +59 -9
  64. package/src/mockUSDCFaucet.js +276 -167
  65. package/src/orders.ts +4 -157
  66. package/src/tokenFaucet.js +189 -0
  67. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  68. package/src/tx/retryTxSender.ts +11 -3
  69. package/src/types.js +12 -1
  70. package/src/types.ts +88 -16
  71. package/src/{accounts/fetch.js → util/computeUnits.js} +11 -13
  72. package/src/util/computeUnits.ts +1 -1
  73. package/src/util/getTokenAddress.js +9 -0
  74. package/src/util/getTokenAddress.ts +18 -0
  75. package/tests/bn/test.ts +2 -0
  76. package/src/addresses/pda.js +0 -104
  77. package/src/math/bankBalance.js +0 -75
  78. package/src/math/market.js +0 -57
  79. package/src/math/orders.js +0 -110
  80. package/src/math/position.js +0 -140
  81. package/src/orders.js +0 -134
  82. package/src/tx/retryTxSender.js +0 -188
@@ -1,23 +1,23 @@
1
1
  {
2
- "version": "0.0.0",
3
- "name": "mock_usdc_faucet",
2
+ "version": "0.1.0",
3
+ "name": "token_faucet",
4
4
  "instructions": [
5
5
  {
6
6
  "name": "initialize",
7
7
  "accounts": [
8
8
  {
9
- "name": "mockUsdcFaucetState",
9
+ "name": "faucetConfig",
10
10
  "isMut": true,
11
11
  "isSigner": false
12
12
  },
13
13
  {
14
14
  "name": "admin",
15
- "isMut": false,
15
+ "isMut": true,
16
16
  "isSigner": true
17
17
  },
18
18
  {
19
19
  "name": "mintAccount",
20
- "isMut": false,
20
+ "isMut": true,
21
21
  "isSigner": false
22
22
  },
23
23
  {
@@ -29,20 +29,20 @@
29
29
  "name": "systemProgram",
30
30
  "isMut": false,
31
31
  "isSigner": false
32
- }
33
- ],
34
- "args": [
32
+ },
35
33
  {
36
- "name": "mockUsdcFaucetNonce",
37
- "type": "u8"
34
+ "name": "tokenProgram",
35
+ "isMut": false,
36
+ "isSigner": false
38
37
  }
39
- ]
38
+ ],
39
+ "args": []
40
40
  },
41
41
  {
42
42
  "name": "mintToUser",
43
43
  "accounts": [
44
44
  {
45
- "name": "mockUsdcFaucetState",
45
+ "name": "faucetConfig",
46
46
  "isMut": false,
47
47
  "isSigner": false
48
48
  },
@@ -73,11 +73,42 @@
73
73
  "type": "u64"
74
74
  }
75
75
  ]
76
+ },
77
+ {
78
+ "name": "transferMintAuthority",
79
+ "accounts": [
80
+ {
81
+ "name": "faucetConfig",
82
+ "isMut": false,
83
+ "isSigner": false
84
+ },
85
+ {
86
+ "name": "admin",
87
+ "isMut": true,
88
+ "isSigner": true
89
+ },
90
+ {
91
+ "name": "mintAccount",
92
+ "isMut": true,
93
+ "isSigner": false
94
+ },
95
+ {
96
+ "name": "mintAuthority",
97
+ "isMut": false,
98
+ "isSigner": false
99
+ },
100
+ {
101
+ "name": "tokenProgram",
102
+ "isMut": false,
103
+ "isSigner": false
104
+ }
105
+ ],
106
+ "args": []
76
107
  }
77
108
  ],
78
109
  "accounts": [
79
110
  {
80
- "name": "MockUSDCFaucetState",
111
+ "name": "FaucetConfig",
81
112
  "type": {
82
113
  "kind": "struct",
83
114
  "fields": [
@@ -103,17 +134,9 @@
103
134
  ],
104
135
  "errors": [
105
136
  {
106
- "code": 300,
137
+ "code": 6000,
107
138
  "name": "InvalidMintAccountAuthority",
108
139
  "msg": "Program not mint authority"
109
- },
110
- {
111
- "code": 301,
112
- "name": "Unauthorized",
113
- "msg": "Signer must be MockUSDCFaucet admin"
114
140
  }
115
- ],
116
- "metadata": {
117
- "address": "2z2DLVD3tBWc86pbvvy5qN31v1NXprM6zA5MDr2FMx64"
118
- }
141
+ ]
119
142
  }
package/lib/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { BN } from '@project-serum/anchor';
2
2
  import { PublicKey } from '@solana/web3.js';
3
3
  import pyth from '@pythnetwork/client';
4
- export * from './mockUSDCFaucet';
4
+ export * from './tokenFaucet';
5
5
  export * from './oracles/types';
6
6
  export * from './oracles/pythClient';
7
7
  export * from './oracles/switchboardClient';
@@ -34,6 +34,7 @@ export * from './math/amm';
34
34
  export * from './math/trade';
35
35
  export * from './math/orders';
36
36
  export * from './math/repeg';
37
+ export * from './math/margin';
37
38
  export * from './orders';
38
39
  export * from './orderParams';
39
40
  export * from './slot/SlotSubscriber';
package/lib/index.js CHANGED
@@ -24,7 +24,7 @@ const web3_js_1 = require("@solana/web3.js");
24
24
  Object.defineProperty(exports, "PublicKey", { enumerable: true, get: function () { return web3_js_1.PublicKey; } });
25
25
  const client_1 = __importDefault(require("@pythnetwork/client"));
26
26
  exports.pyth = client_1.default;
27
- __exportStar(require("./mockUSDCFaucet"), exports);
27
+ __exportStar(require("./tokenFaucet"), exports);
28
28
  __exportStar(require("./oracles/types"), exports);
29
29
  __exportStar(require("./oracles/pythClient"), exports);
30
30
  __exportStar(require("./oracles/switchboardClient"), exports);
@@ -57,6 +57,7 @@ __exportStar(require("./math/amm"), exports);
57
57
  __exportStar(require("./math/trade"), exports);
58
58
  __exportStar(require("./math/orders"), exports);
59
59
  __exportStar(require("./math/repeg"), exports);
60
+ __exportStar(require("./math/margin"), exports);
60
61
  __exportStar(require("./orders"), exports);
61
62
  __exportStar(require("./orderParams"), exports);
62
63
  __exportStar(require("./slot/SlotSubscriber"), exports);
package/lib/math/amm.js CHANGED
@@ -8,11 +8,11 @@ const assert_1 = require("../assert/assert");
8
8
  const __1 = require("..");
9
9
  const repeg_1 = require("./repeg");
10
10
  function calculatePegFromTargetPrice(targetPrice, baseAssetReserve, quoteAssetReserve) {
11
- return targetPrice
11
+ return anchor_1.BN.max(targetPrice
12
12
  .mul(baseAssetReserve)
13
13
  .div(quoteAssetReserve)
14
14
  .add(numericConstants_1.PRICE_DIV_PEG.div(new anchor_1.BN(2)))
15
- .div(numericConstants_1.PRICE_DIV_PEG);
15
+ .div(numericConstants_1.PRICE_DIV_PEG), numericConstants_1.ONE);
16
16
  }
17
17
  exports.calculatePegFromTargetPrice = calculatePegFromTargetPrice;
18
18
  function calculateOptimalPegAndBudget(amm, oraclePriceData) {
@@ -1,8 +1,10 @@
1
1
  /// <reference types="bn.js" />
2
- import { BankAccount, BankBalanceType } from '../types';
2
+ import { BankAccount, BankBalanceType, MarginCategory } from '../types';
3
3
  import { BN } from '@project-serum/anchor';
4
4
  export declare function getBalance(tokenAmount: BN, bank: BankAccount, balanceType: BankBalanceType): BN;
5
5
  export declare function getTokenAmount(balanceAmount: BN, bank: BankAccount, balanceType: BankBalanceType): BN;
6
+ export declare function calculateAssetWeight(balanceAmount: BN, bank: BankAccount, marginCategory: MarginCategory): BN;
7
+ export declare function calculateLiabilityWeight(balanceAmount: BN, bank: BankAccount, marginCategory: MarginCategory): BN;
6
8
  export declare function calculateInterestAccumulated(bank: BankAccount, now: BN): {
7
9
  borrowInterest: BN;
8
10
  depositInterest: BN;
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateInterestAccumulated = exports.getTokenAmount = exports.getBalance = void 0;
3
+ exports.calculateInterestAccumulated = exports.calculateLiabilityWeight = exports.calculateAssetWeight = exports.getTokenAmount = exports.getBalance = void 0;
4
4
  const types_1 = require("../types");
5
5
  const anchor_1 = require("@project-serum/anchor");
6
6
  const numericConstants_1 = require("../constants/numericConstants");
7
+ const margin_1 = require("./margin");
7
8
  function getBalance(tokenAmount, bank, balanceType) {
8
9
  const precisionIncrease = numericConstants_1.TEN.pow(new anchor_1.BN(16 - bank.decimals));
9
10
  const cumulativeInterest = (0, types_1.isVariant)(balanceType, 'deposit')
@@ -24,6 +25,58 @@ function getTokenAmount(balanceAmount, bank, balanceType) {
24
25
  return balanceAmount.mul(cumulativeInterest).div(precisionDecrease);
25
26
  }
26
27
  exports.getTokenAmount = getTokenAmount;
28
+ function calculateAssetWeight(balanceAmount, bank, marginCategory) {
29
+ const sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(bank.decimals));
30
+ let sizeInAmmReservePrecision;
31
+ if (sizePrecision.gt(numericConstants_1.AMM_RESERVE_PRECISION)) {
32
+ sizeInAmmReservePrecision = balanceAmount.div(sizePrecision.div(numericConstants_1.AMM_RESERVE_PRECISION));
33
+ }
34
+ else {
35
+ sizeInAmmReservePrecision = balanceAmount
36
+ .mul(numericConstants_1.AMM_RESERVE_PRECISION)
37
+ .div(sizePrecision);
38
+ }
39
+ let assetWeight;
40
+ switch (marginCategory) {
41
+ case 'Initial':
42
+ assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, bank.imfFactor, bank.initialAssetWeight);
43
+ break;
44
+ case 'Maintenance':
45
+ assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, bank.imfFactor, bank.maintenanceAssetWeight);
46
+ break;
47
+ default:
48
+ assetWeight = bank.initialAssetWeight;
49
+ break;
50
+ }
51
+ return assetWeight;
52
+ }
53
+ exports.calculateAssetWeight = calculateAssetWeight;
54
+ function calculateLiabilityWeight(balanceAmount, bank, marginCategory) {
55
+ const sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(bank.decimals));
56
+ let sizeInAmmReservePrecision;
57
+ if (sizePrecision.gt(numericConstants_1.AMM_RESERVE_PRECISION)) {
58
+ sizeInAmmReservePrecision = balanceAmount.div(sizePrecision.div(numericConstants_1.AMM_RESERVE_PRECISION));
59
+ }
60
+ else {
61
+ sizeInAmmReservePrecision = balanceAmount
62
+ .mul(numericConstants_1.AMM_RESERVE_PRECISION)
63
+ .div(sizePrecision);
64
+ }
65
+ let assetWeight;
66
+ switch (marginCategory) {
67
+ case 'Initial':
68
+ assetWeight = (0, margin_1.calculateSizePremiumLiabilityWeight)(sizeInAmmReservePrecision, bank.imfFactor, bank.initialLiabilityWeight, numericConstants_1.BANK_WEIGHT_PRECISION);
69
+ break;
70
+ case 'Maintenance':
71
+ assetWeight = (0, margin_1.calculateSizePremiumLiabilityWeight)(sizeInAmmReservePrecision, bank.imfFactor, bank.maintenanceLiabilityWeight, numericConstants_1.BANK_WEIGHT_PRECISION);
72
+ break;
73
+ default:
74
+ assetWeight = bank.initialLiabilityWeight;
75
+ break;
76
+ }
77
+ return assetWeight;
78
+ }
79
+ exports.calculateLiabilityWeight = calculateLiabilityWeight;
27
80
  function calculateInterestAccumulated(bank, now) {
28
81
  const token_deposit_amount = getTokenAmount(bank.depositBalance, bank, types_1.BankBalanceType.DEPOSIT);
29
82
  const token_borrow_amount = getTokenAmount(bank.borrowBalance, bank, types_1.BankBalanceType.BORROW);
@@ -0,0 +1,11 @@
1
+ /// <reference types="bn.js" />
2
+ import { BN } from '@project-serum/anchor';
3
+ import { OraclePriceData } from '../oracles/types';
4
+ import { MarketAccount, UserPosition } from '..';
5
+ export declare function calculateSizePremiumLiabilityWeight(size: BN, // AMM_RESERVE_PRECISION
6
+ imfFactor: BN, liabilityWeight: BN, precision: BN): BN;
7
+ export declare function calculateSizeDiscountAssetWeight(size: BN, // AMM_RESERVE_PRECISION
8
+ imfFactor: BN, assetWeight: BN): BN;
9
+ export declare function calculateOraclePriceForPerpMargin(marketPosition: UserPosition, market: MarketAccount, oraclePriceData: OraclePriceData): BN;
10
+ export declare function calculateMarginBaseAssetValue(market: MarketAccount, marketPosition: UserPosition, oraclePriceData: OraclePriceData): BN;
11
+ export declare function calculateWorstCaseBaseAssetAmount(marketPosition: UserPosition): BN;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateWorstCaseBaseAssetAmount = exports.calculateMarginBaseAssetValue = exports.calculateOraclePriceForPerpMargin = exports.calculateSizeDiscountAssetWeight = exports.calculateSizePremiumLiabilityWeight = void 0;
4
+ const utils_1 = require("./utils");
5
+ const numericConstants_1 = require("../constants/numericConstants");
6
+ const anchor_1 = require("@project-serum/anchor");
7
+ function calculateSizePremiumLiabilityWeight(size, // AMM_RESERVE_PRECISION
8
+ imfFactor, liabilityWeight, precision) {
9
+ if (imfFactor.eq(numericConstants_1.ZERO)) {
10
+ return liabilityWeight;
11
+ }
12
+ const sizeSqrt = (0, utils_1.squareRootBN)(size.div(new anchor_1.BN(1000)).add(new anchor_1.BN(1))); //1e13 -> 1e10 -> 1e5
13
+ const liabilityWeightNumerator = liabilityWeight.sub(liabilityWeight.div(anchor_1.BN.max(new anchor_1.BN(1), numericConstants_1.BANK_IMF_PRECISION.div(imfFactor))));
14
+ const sizePremiumLiabilityWeight = liabilityWeightNumerator.add(sizeSqrt // 1e5
15
+ .mul(imfFactor)
16
+ .div(new anchor_1.BN(100000).mul(numericConstants_1.BANK_IMF_PRECISION).div(precision)) // 1e5
17
+ );
18
+ const maxLiabilityWeight = anchor_1.BN.max(liabilityWeight, sizePremiumLiabilityWeight);
19
+ return maxLiabilityWeight;
20
+ }
21
+ exports.calculateSizePremiumLiabilityWeight = calculateSizePremiumLiabilityWeight;
22
+ function calculateSizeDiscountAssetWeight(size, // AMM_RESERVE_PRECISION
23
+ imfFactor, assetWeight) {
24
+ if (imfFactor.eq(numericConstants_1.ZERO)) {
25
+ return assetWeight;
26
+ }
27
+ const sizeSqrt = (0, utils_1.squareRootBN)(size.div(new anchor_1.BN(1000)).add(new anchor_1.BN(1))); //1e13 -> 1e10 -> 1e5
28
+ const imfNumerator = numericConstants_1.BANK_IMF_PRECISION.add(numericConstants_1.BANK_IMF_PRECISION.div(new anchor_1.BN(10)));
29
+ const sizeDiscountAssetWeight = imfNumerator.mul(numericConstants_1.BANK_WEIGHT_PRECISION).div(numericConstants_1.BANK_IMF_PRECISION.add(sizeSqrt // 1e5
30
+ .mul(imfFactor)
31
+ .div(new anchor_1.BN(100000)) // 1e5
32
+ ));
33
+ const minAssetWeight = anchor_1.BN.min(assetWeight, sizeDiscountAssetWeight);
34
+ return minAssetWeight;
35
+ }
36
+ exports.calculateSizeDiscountAssetWeight = calculateSizeDiscountAssetWeight;
37
+ function calculateOraclePriceForPerpMargin(marketPosition, market, oraclePriceData) {
38
+ const oraclePriceOffset = anchor_1.BN.min(new anchor_1.BN(market.amm.maxSpread)
39
+ .mul(oraclePriceData.price)
40
+ .div(numericConstants_1.BID_ASK_SPREAD_PRECISION), oraclePriceData.confidence.add(new anchor_1.BN(market.amm.baseSpread)
41
+ .mul(oraclePriceData.price)
42
+ .div(numericConstants_1.BID_ASK_SPREAD_PRECISION)));
43
+ let marginPrice;
44
+ if (marketPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
45
+ marginPrice = oraclePriceData.price.sub(oraclePriceOffset);
46
+ }
47
+ else {
48
+ marginPrice = oraclePriceData.price.add(oraclePriceOffset);
49
+ }
50
+ return marginPrice;
51
+ }
52
+ exports.calculateOraclePriceForPerpMargin = calculateOraclePriceForPerpMargin;
53
+ function calculateMarginBaseAssetValue(market, marketPosition, oraclePriceData) {
54
+ const marginPrice = calculateOraclePriceForPerpMargin(marketPosition, market, oraclePriceData);
55
+ const baseAssetValue = marketPosition.baseAssetAmount
56
+ .abs()
57
+ .mul(marginPrice)
58
+ .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.MARK_PRICE_PRECISION));
59
+ return baseAssetValue;
60
+ }
61
+ exports.calculateMarginBaseAssetValue = calculateMarginBaseAssetValue;
62
+ function calculateWorstCaseBaseAssetAmount(marketPosition) {
63
+ const allBids = marketPosition.baseAssetAmount.add(marketPosition.openBids);
64
+ const allAsks = marketPosition.baseAssetAmount.add(marketPosition.openAsks);
65
+ if (allBids.abs().gt(allAsks.abs())) {
66
+ return allBids;
67
+ }
68
+ else {
69
+ return allAsks;
70
+ }
71
+ }
72
+ exports.calculateWorstCaseBaseAssetAmount = calculateWorstCaseBaseAssetAmount;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { BN } from '@project-serum/anchor';
3
- import { MarketAccount, PositionDirection } from '../types';
3
+ import { MarketAccount, PositionDirection, MarginCategory, BankAccount } from '../types';
4
4
  import { OraclePriceData } from '../oracles/types';
5
5
  /**
6
6
  * Calculates market mark price
@@ -26,3 +26,6 @@ export declare function calculateAskPrice(market: MarketAccount, oraclePriceData
26
26
  export declare function calculateNewMarketAfterTrade(baseAssetAmount: BN, direction: PositionDirection, market: MarketAccount): MarketAccount;
27
27
  export declare function calculateMarkOracleSpread(market: MarketAccount, oraclePriceData: OraclePriceData): BN;
28
28
  export declare function calculateOracleSpread(price: BN, oraclePriceData: OraclePriceData): BN;
29
+ export declare function calculateMarketMarginRatio(market: MarketAccount, size: BN, marginCategory: MarginCategory): number;
30
+ export declare function calculateUnsettledAssetWeight(market: MarketAccount, unsettledPnl: BN, marginCategory: MarginCategory): BN;
31
+ export declare function calculateMarketAvailablePNL(market: MarketAccount, bank: BankAccount): BN;
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateOracleSpread = exports.calculateMarkOracleSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateMarkPrice = void 0;
3
+ exports.calculateMarketAvailablePNL = exports.calculateUnsettledAssetWeight = exports.calculateMarketMarginRatio = exports.calculateOracleSpread = exports.calculateMarkOracleSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateMarkPrice = void 0;
4
+ const anchor_1 = require("@project-serum/anchor");
4
5
  const types_1 = require("../types");
5
6
  const amm_1 = require("./amm");
7
+ const margin_1 = require("./margin");
8
+ const numericConstants_1 = require("../constants/numericConstants");
9
+ const bankBalance_1 = require("./bankBalance");
6
10
  /**
7
11
  * Calculates market mark price
8
12
  *
@@ -55,3 +59,33 @@ function calculateOracleSpread(price, oraclePriceData) {
55
59
  return price.sub(oraclePriceData.price);
56
60
  }
57
61
  exports.calculateOracleSpread = calculateOracleSpread;
62
+ function calculateMarketMarginRatio(market, size, marginCategory) {
63
+ let marginRatio;
64
+ switch (marginCategory) {
65
+ case 'Initial':
66
+ marginRatio = (0, margin_1.calculateSizePremiumLiabilityWeight)(size, market.imfFactor, new anchor_1.BN(market.marginRatioInitial), numericConstants_1.MARGIN_PRECISION).toNumber();
67
+ break;
68
+ case 'Maintenance':
69
+ marginRatio = market.marginRatioMaintenance;
70
+ break;
71
+ }
72
+ return marginRatio;
73
+ }
74
+ exports.calculateMarketMarginRatio = calculateMarketMarginRatio;
75
+ function calculateUnsettledAssetWeight(market, unsettledPnl, marginCategory) {
76
+ let assetWeight;
77
+ switch (marginCategory) {
78
+ case 'Initial':
79
+ assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(unsettledPnl, market.unsettledImfFactor, new anchor_1.BN(market.unsettledInitialAssetWeight));
80
+ break;
81
+ case 'Maintenance':
82
+ assetWeight = new anchor_1.BN(market.unsettledMaintenanceAssetWeight);
83
+ break;
84
+ }
85
+ return assetWeight;
86
+ }
87
+ exports.calculateUnsettledAssetWeight = calculateUnsettledAssetWeight;
88
+ function calculateMarketAvailablePNL(market, bank) {
89
+ return (0, bankBalance_1.getTokenAmount)(market.pnlPool.balance, bank, types_1.BankBalanceType.DEPOSIT);
90
+ }
91
+ exports.calculateMarketAvailablePNL = calculateMarketAvailablePNL;
@@ -17,9 +17,11 @@ export declare function calculateBaseAssetValue(market: MarketAccount, userPosit
17
17
  * @param market
18
18
  * @param marketPosition
19
19
  * @param withFunding (adds unrealized funding payment pnl to result)
20
+ * @param oraclePriceData
20
21
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
21
22
  */
22
23
  export declare function calculatePositionPNL(market: MarketAccount, marketPosition: UserPosition, withFunding: boolean, oraclePriceData: OraclePriceData): BN;
24
+ export declare function calculateUnsettledPnl(market: MarketAccount, marketPosition: UserPosition, oraclePriceData: OraclePriceData): BN;
23
25
  /**
24
26
  *
25
27
  * @param market
@@ -34,6 +36,12 @@ export declare function positionIsAvailable(position: UserPosition): boolean;
34
36
  * @returns Precision: MARK_PRICE_PRECISION (10^10)
35
37
  */
36
38
  export declare function calculateEntryPrice(userPosition: UserPosition): BN;
39
+ /**
40
+ *
41
+ * @param userPosition
42
+ * @returns Precision: MARK_PRICE_PRECISION (10^10)
43
+ */
44
+ export declare function calculateCostBasis(userPosition: UserPosition): BN;
37
45
  export declare function findDirectionToClose(userPosition: UserPosition): PositionDirection;
38
46
  export declare function positionCurrentDirection(userPosition: UserPosition): PositionDirection;
39
47
  export declare function isEmptyPosition(userPosition: UserPosition): boolean;
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
3
+ exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculateUnsettledPnl = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
4
4
  const __1 = require("../");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const types_1 = require("../types");
7
7
  const amm_1 = require("./amm");
8
+ const margin_1 = require("./margin");
8
9
  /**
9
10
  * calculateBaseAssetValue
10
11
  * = market value of closing entire position
@@ -53,20 +54,20 @@ exports.calculateBaseAssetValue = calculateBaseAssetValue;
53
54
  * @param market
54
55
  * @param marketPosition
55
56
  * @param withFunding (adds unrealized funding payment pnl to result)
57
+ * @param oraclePriceData
56
58
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
57
59
  */
58
60
  function calculatePositionPNL(market, marketPosition, withFunding = false, oraclePriceData) {
59
61
  if (marketPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
60
- return numericConstants_1.ZERO;
61
- }
62
- const baseAssetValue = calculateBaseAssetValue(market, marketPosition, oraclePriceData);
63
- let pnl;
64
- if (marketPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
65
- pnl = baseAssetValue.sub(marketPosition.quoteAssetAmount);
66
- }
67
- else {
68
- pnl = marketPosition.quoteAssetAmount.sub(baseAssetValue);
62
+ return marketPosition.quoteAssetAmount;
69
63
  }
64
+ const baseAssetValue = (0, margin_1.calculateMarginBaseAssetValue)(market, marketPosition, oraclePriceData);
65
+ const baseAssetValueSign = marketPosition.baseAssetAmount.isNeg()
66
+ ? new __1.BN(-1)
67
+ : new __1.BN(1);
68
+ let pnl = baseAssetValue
69
+ .mul(baseAssetValueSign)
70
+ .add(marketPosition.quoteAssetAmount);
70
71
  if (withFunding) {
71
72
  const fundingRatePnL = calculatePositionFundingPNL(market, marketPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
72
73
  pnl = pnl.add(fundingRatePnL);
@@ -74,6 +75,19 @@ function calculatePositionPNL(market, marketPosition, withFunding = false, oracl
74
75
  return pnl;
75
76
  }
76
77
  exports.calculatePositionPNL = calculatePositionPNL;
78
+ function calculateUnsettledPnl(market, marketPosition, oraclePriceData) {
79
+ const unrealizedPnl = calculatePositionPNL(market, marketPosition, true, oraclePriceData);
80
+ let unsettledPnl = unrealizedPnl;
81
+ if (unrealizedPnl.gt(numericConstants_1.ZERO)) {
82
+ const fundingPnL = calculatePositionFundingPNL(market, marketPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
83
+ const maxPositivePnl = __1.BN.max(marketPosition.quoteAssetAmount
84
+ .add(marketPosition.quoteEntryAmount)
85
+ .add(fundingPnL), numericConstants_1.ZERO);
86
+ unsettledPnl = __1.BN.min(maxPositivePnl, unrealizedPnl);
87
+ }
88
+ return unsettledPnl;
89
+ }
90
+ exports.calculateUnsettledPnl = calculateUnsettledPnl;
77
91
  /**
78
92
  *
79
93
  * @param market
@@ -103,7 +117,7 @@ exports.calculatePositionFundingPNL = calculatePositionFundingPNL;
103
117
  function positionIsAvailable(position) {
104
118
  return (position.baseAssetAmount.eq(numericConstants_1.ZERO) &&
105
119
  position.openOrders.eq(numericConstants_1.ZERO) &&
106
- position.unsettledPnl.eq(numericConstants_1.ZERO));
120
+ position.quoteAssetAmount.eq(numericConstants_1.ZERO));
107
121
  }
108
122
  exports.positionIsAvailable = positionIsAvailable;
109
123
  /**
@@ -115,13 +129,29 @@ function calculateEntryPrice(userPosition) {
115
129
  if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
116
130
  return numericConstants_1.ZERO;
117
131
  }
118
- return userPosition.quoteAssetAmount
132
+ return userPosition.quoteEntryAmount
119
133
  .mul(numericConstants_1.MARK_PRICE_PRECISION)
120
134
  .mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
121
135
  .div(userPosition.baseAssetAmount)
122
136
  .abs();
123
137
  }
124
138
  exports.calculateEntryPrice = calculateEntryPrice;
139
+ /**
140
+ *
141
+ * @param userPosition
142
+ * @returns Precision: MARK_PRICE_PRECISION (10^10)
143
+ */
144
+ function calculateCostBasis(userPosition) {
145
+ if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
146
+ return numericConstants_1.ZERO;
147
+ }
148
+ return userPosition.quoteAssetAmount
149
+ .mul(numericConstants_1.MARK_PRICE_PRECISION)
150
+ .mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
151
+ .div(userPosition.baseAssetAmount)
152
+ .abs();
153
+ }
154
+ exports.calculateCostBasis = calculateCostBasis;
125
155
  function findDirectionToClose(userPosition) {
126
156
  return userPosition.baseAssetAmount.gt(numericConstants_1.ZERO)
127
157
  ? types_1.PositionDirection.SHORT
package/lib/orders.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  /// <reference types="bn.js" />
2
- import { MarketAccount, Order, UserAccount, UserPosition } from './types';
2
+ import { MarketAccount, Order } from './types';
3
3
  import { BN } from '.';
4
4
  import { OraclePriceData } from '.';
5
- export declare function calculateNewStateAfterOrder(userAccount: UserAccount, userPosition: UserPosition, market: MarketAccount, order: Order): [UserAccount, UserPosition, MarketAccount] | null;
6
5
  export declare function calculateBaseAssetAmountMarketCanExecute(market: MarketAccount, order: Order, oraclePriceData?: OraclePriceData): BN;
7
6
  export declare function calculateAmountToTradeForLimit(market: MarketAccount, order: Order, oraclePriceData?: OraclePriceData): BN;
8
7
  export declare function calculateAmountToTradeForTriggerLimit(market: MarketAccount, order: Order): BN;
package/lib/orders.js CHANGED
@@ -1,85 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateAmountToTradeForTriggerLimit = exports.calculateAmountToTradeForLimit = exports.calculateBaseAssetAmountMarketCanExecute = exports.calculateNewStateAfterOrder = void 0;
3
+ exports.calculateAmountToTradeForTriggerLimit = exports.calculateAmountToTradeForLimit = exports.calculateBaseAssetAmountMarketCanExecute = void 0;
4
4
  const types_1 = require("./types");
5
5
  const _1 = require(".");
6
- const market_1 = require("./math/market");
7
6
  const numericConstants_1 = require("./constants/numericConstants");
8
7
  const amm_1 = require("./math/amm");
9
- const position_1 = require("./math/position");
10
- function calculateNewStateAfterOrder(userAccount, userPosition, market, order) {
11
- if ((0, types_1.isVariant)(order.status, 'init')) {
12
- return null;
13
- }
14
- const baseAssetAmountToTrade = calculateBaseAssetAmountMarketCanExecute(market, order);
15
- if (baseAssetAmountToTrade.lt(market.amm.baseAssetAmountStepSize)) {
16
- return null;
17
- }
18
- const userAccountAfter = Object.assign({}, userAccount);
19
- const userPositionAfter = Object.assign({}, userPosition);
20
- const currentPositionDirection = (0, position_1.positionCurrentDirection)(userPosition);
21
- const increasePosition = userPosition.baseAssetAmount.eq(numericConstants_1.ZERO) ||
22
- isSameDirection(order.direction, currentPositionDirection);
23
- if (increasePosition) {
24
- const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountToTrade, order.direction, market);
25
- const { quoteAssetAmountSwapped, baseAssetAmountSwapped } = calculateAmountSwapped(market, marketAfter);
26
- userPositionAfter.baseAssetAmount = userPositionAfter.baseAssetAmount.add(baseAssetAmountSwapped);
27
- userPositionAfter.quoteAssetAmount = userPositionAfter.quoteAssetAmount.add(quoteAssetAmountSwapped);
28
- return [userAccountAfter, userPositionAfter, marketAfter];
29
- }
30
- else {
31
- const reversePosition = baseAssetAmountToTrade.gt(userPosition.baseAssetAmount.abs());
32
- if (reversePosition) {
33
- const intermediateMarket = (0, market_1.calculateNewMarketAfterTrade)(userPosition.baseAssetAmount, (0, position_1.findDirectionToClose)(userPosition), market);
34
- const { quoteAssetAmountSwapped: baseAssetValue } = calculateAmountSwapped(market, intermediateMarket);
35
- let pnl;
36
- if ((0, types_1.isVariant)(currentPositionDirection, 'long')) {
37
- pnl = baseAssetValue.sub(userPosition.quoteAssetAmount);
38
- }
39
- else {
40
- pnl = userPosition.quoteAssetAmount.sub(baseAssetValue);
41
- }
42
- userAccountAfter.collateral = userAccountAfter.collateral.add(pnl);
43
- const baseAssetAmountLeft = baseAssetAmountToTrade.sub(userPosition.baseAssetAmount.abs());
44
- const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountLeft, order.direction, intermediateMarket);
45
- const { quoteAssetAmountSwapped, baseAssetAmountSwapped } = calculateAmountSwapped(intermediateMarket, marketAfter);
46
- userPositionAfter.quoteAssetAmount = quoteAssetAmountSwapped;
47
- userPositionAfter.baseAssetAmount = baseAssetAmountSwapped;
48
- return [userAccountAfter, userPositionAfter, marketAfter];
49
- }
50
- else {
51
- const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountToTrade, order.direction, market);
52
- const { quoteAssetAmountSwapped: baseAssetValue, baseAssetAmountSwapped, } = calculateAmountSwapped(market, marketAfter);
53
- const costBasisRealized = userPosition.quoteAssetAmount
54
- .mul(baseAssetAmountSwapped.abs())
55
- .div(userPosition.baseAssetAmount.abs());
56
- let pnl;
57
- if ((0, types_1.isVariant)(currentPositionDirection, 'long')) {
58
- pnl = baseAssetValue.sub(costBasisRealized);
59
- }
60
- else {
61
- pnl = costBasisRealized.sub(baseAssetValue);
62
- }
63
- userAccountAfter.collateral = userAccountAfter.collateral.add(pnl);
64
- userPositionAfter.baseAssetAmount = userPositionAfter.baseAssetAmount.add(baseAssetAmountSwapped);
65
- userPositionAfter.quoteAssetAmount =
66
- userPositionAfter.quoteAssetAmount.sub(costBasisRealized);
67
- return [userAccountAfter, userPositionAfter, marketAfter];
68
- }
69
- }
70
- }
71
- exports.calculateNewStateAfterOrder = calculateNewStateAfterOrder;
72
- function calculateAmountSwapped(marketBefore, marketAfter) {
73
- return {
74
- quoteAssetAmountSwapped: marketBefore.amm.quoteAssetReserve
75
- .sub(marketAfter.amm.quoteAssetReserve)
76
- .abs()
77
- .mul(marketBefore.amm.pegMultiplier)
78
- .div(numericConstants_1.PEG_PRECISION)
79
- .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO),
80
- baseAssetAmountSwapped: marketBefore.amm.baseAssetReserve.sub(marketAfter.amm.baseAssetReserve),
81
- };
82
- }
83
8
  function calculateBaseAssetAmountMarketCanExecute(market, order, oraclePriceData) {
84
9
  if ((0, types_1.isVariant)(order.orderType, 'limit')) {
85
10
  return calculateAmountToTradeForLimit(market, order, oraclePriceData);
@@ -103,7 +28,7 @@ function calculateAmountToTradeForLimit(market, order, oraclePriceData) {
103
28
  }
104
29
  limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
105
30
  }
106
- const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction);
31
+ const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction, oraclePriceData);
107
32
  const baseAssetAmount = (0, _1.standardizeBaseAssetAmount)(maxAmountToTrade, market.amm.baseAssetAmountStepSize);
108
33
  // Check that directions are the same
109
34
  const sameDirection = isSameDirection(direction, order.direction);