@drift-labs/sdk 0.1.32 → 0.1.34-master.1

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 (58) hide show
  1. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +1 -0
  2. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +17 -4
  3. package/lib/accounts/pollingUserAccountSubscriber.d.ts +1 -0
  4. package/lib/accounts/pollingUserAccountSubscriber.js +17 -3
  5. package/lib/admin.d.ts +1 -0
  6. package/lib/admin.js +11 -0
  7. package/lib/constants/numericConstants.d.ts +2 -0
  8. package/lib/constants/numericConstants.js +3 -1
  9. package/lib/idl/clearing_house.json +40 -2
  10. package/lib/math/amm.d.ts +7 -2
  11. package/lib/math/amm.js +45 -6
  12. package/lib/math/funding.js +3 -1
  13. package/lib/math/market.d.ts +15 -0
  14. package/lib/math/market.js +29 -2
  15. package/lib/math/orders.js +4 -3
  16. package/lib/math/trade.d.ts +3 -1
  17. package/lib/math/trade.js +18 -6
  18. package/lib/orders.js +38 -5
  19. package/lib/types.d.ts +2 -1
  20. package/package.json +1 -1
  21. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +19 -4
  22. package/src/accounts/pollingUserAccountSubscriber.ts +20 -3
  23. package/src/admin.ts +17 -0
  24. package/src/constants/numericConstants.ts +2 -0
  25. package/src/idl/clearing_house.json +40 -2
  26. package/src/math/amm.ts +71 -6
  27. package/src/math/funding.ts +11 -8
  28. package/src/math/market.ts +47 -1
  29. package/src/math/orders.ts +6 -3
  30. package/src/math/trade.ts +24 -13
  31. package/src/orders.ts +51 -7
  32. package/src/types.ts +2 -1
  33. package/src/assert/assert.js +0 -10
  34. package/src/assert/assert.js.map +0 -1
  35. package/src/math/conversion.js +0 -16
  36. package/src/math/conversion.js.map +0 -1
  37. package/src/math/funding.js +0 -223
  38. package/src/math/funding.js.map +0 -1
  39. package/src/math/insuranceFund.js +0 -23
  40. package/src/math/insuranceFund.js.map +0 -1
  41. package/src/math/position.js +0 -121
  42. package/src/math/position.js.map +0 -1
  43. package/src/math/utils.js +0 -27
  44. package/src/math/utils.js.map +0 -1
  45. package/src/oracles/switchboardClient.js +0 -60
  46. package/src/oracles/switchboardClient.js.map +0 -1
  47. package/src/token/index.js +0 -39
  48. package/src/token/index.js.map +0 -1
  49. package/src/tx/defaultTxSender.js +0 -13
  50. package/src/tx/defaultTxSender.js.map +0 -1
  51. package/src/tx/types.js +0 -3
  52. package/src/tx/types.js.map +0 -1
  53. package/src/tx/utils.js +0 -9
  54. package/src/tx/utils.js.map +0 -1
  55. package/src/util/computeUnits.js +0 -17
  56. package/src/util/computeUnits.js.map +0 -1
  57. package/src/util/tps.js +0 -17
  58. package/src/util/tps.js.map +0 -1
@@ -35,6 +35,7 @@ export declare class PollingClearingHouseAccountSubscriber implements ClearingHo
35
35
  getClearingHouseAccounts(): Promise<ClearingHouseAccounts>;
36
36
  addToAccountLoader(): Promise<void>;
37
37
  fetch(): Promise<void>;
38
+ didSubscriptionSucceed(): boolean;
38
39
  unsubscribe(): Promise<void>;
39
40
  assertIsSubscribed(): void;
40
41
  assertOptionalIsSubscribed(optionalSubscription: ClearingHouseAccountTypes): void;
@@ -42,11 +42,14 @@ class PollingClearingHouseAccountSubscriber {
42
42
  yield this.updateAccountsToPoll();
43
43
  yield this.addToAccountLoader();
44
44
  yield this.fetch();
45
- this.eventEmitter.emit('update');
45
+ const subscriptionSucceeded = this.didSubscriptionSucceed();
46
+ if (subscriptionSucceeded) {
47
+ this.eventEmitter.emit('update');
48
+ }
46
49
  this.isSubscribing = false;
47
- this.isSubscribed = true;
48
- this.subscriptionPromiseResolver(true);
49
- return true;
50
+ this.isSubscribed = subscriptionSucceeded;
51
+ this.subscriptionPromiseResolver(subscriptionSucceeded);
52
+ return subscriptionSucceeded;
50
53
  });
51
54
  }
52
55
  updateAccountsToPoll() {
@@ -177,6 +180,16 @@ class PollingClearingHouseAccountSubscriber {
177
180
  }
178
181
  });
179
182
  }
183
+ didSubscriptionSucceed() {
184
+ let success = true;
185
+ for (const [_, accountToPoll] of this.accountsToPoll) {
186
+ if (!this[accountToPoll.key]) {
187
+ success = false;
188
+ break;
189
+ }
190
+ }
191
+ return success;
192
+ }
180
193
  unsubscribe() {
181
194
  return __awaiter(this, void 0, void 0, function* () {
182
195
  if (!this.isSubscribed) {
@@ -24,6 +24,7 @@ export declare class PollingUserAccountSubscriber implements UserAccountSubscrib
24
24
  addToAccountLoader(userPublicKeys?: UserPublicKeys): Promise<void>;
25
25
  fetchIfUnloaded(): Promise<void>;
26
26
  fetch(): Promise<void>;
27
+ didSubscriptionSucceed(): boolean;
27
28
  unsubscribe(): Promise<void>;
28
29
  assertIsSubscribed(): void;
29
30
  getUserAccount(): UserAccount;
@@ -31,9 +31,12 @@ class PollingUserAccountSubscriber {
31
31
  }
32
32
  yield this.addToAccountLoader();
33
33
  yield this.fetchIfUnloaded();
34
- this.eventEmitter.emit('update');
35
- this.isSubscribed = true;
36
- return true;
34
+ const subscriptionSucceeded = this.didSubscriptionSucceed();
35
+ if (subscriptionSucceeded) {
36
+ this.eventEmitter.emit('update');
37
+ }
38
+ this.isSubscribed = subscriptionSucceeded;
39
+ return subscriptionSucceeded;
37
40
  });
38
41
  }
39
42
  addToAccountLoader(userPublicKeys) {
@@ -122,6 +125,17 @@ class PollingUserAccountSubscriber {
122
125
  }
123
126
  });
124
127
  }
128
+ didSubscriptionSucceed() {
129
+ let success = true;
130
+ for (const [_, accountToPoll] of this.accountsToPoll) {
131
+ // userOrders may not exist
132
+ if (accountToPoll.key !== 'userOrders' && !this[accountToPoll.key]) {
133
+ success = false;
134
+ break;
135
+ }
136
+ }
137
+ return success;
138
+ }
125
139
  unsubscribe() {
126
140
  return __awaiter(this, void 0, void 0, function* () {
127
141
  if (!this.isSubscribed) {
package/lib/admin.d.ts CHANGED
@@ -24,6 +24,7 @@ export declare class Admin extends ClearingHouse {
24
24
  withdrawFromInsuranceVaultToMarket(marketIndex: BN, amount: BN): Promise<TransactionSignature>;
25
25
  updateAdmin(admin: PublicKey): Promise<TransactionSignature>;
26
26
  updateMarginRatio(marketIndex: BN, marginRatioInitial: number, marginRatioPartial: number, marginRatioMaintenance: number): Promise<TransactionSignature>;
27
+ updateMarketBaseSpread(marketIndex: BN, baseSpread: number): Promise<TransactionSignature>;
27
28
  updatePartialLiquidationClosePercentage(numerator: BN, denominator: BN): Promise<TransactionSignature>;
28
29
  updatePartialLiquidationPenaltyPercentage(numerator: BN, denominator: BN): Promise<TransactionSignature>;
29
30
  updateFullLiquidationPenaltyPercentage(numerator: BN, denominator: BN): Promise<TransactionSignature>;
package/lib/admin.js CHANGED
@@ -338,6 +338,17 @@ class Admin extends clearingHouse_1.ClearingHouse {
338
338
  });
339
339
  });
340
340
  }
341
+ updateMarketBaseSpread(marketIndex, baseSpread) {
342
+ return __awaiter(this, void 0, void 0, function* () {
343
+ return yield this.program.rpc.updateMarketBaseSpread(marketIndex, baseSpread, {
344
+ accounts: {
345
+ admin: this.wallet.publicKey,
346
+ state: yield this.getStatePublicKey(),
347
+ markets: this.getStateAccount().markets,
348
+ },
349
+ });
350
+ });
351
+ }
341
352
  updatePartialLiquidationClosePercentage(numerator, denominator) {
342
353
  return __awaiter(this, void 0, void 0, function* () {
343
354
  return yield this.program.rpc.updatePartialLiquidationClosePercentage(numerator, denominator, {
@@ -6,6 +6,7 @@ export declare const TWO: BN;
6
6
  export declare const TEN: BN;
7
7
  export declare const TEN_THOUSAND: BN;
8
8
  export declare const BN_MAX: BN;
9
+ export declare const TEN_MILLION: BN;
9
10
  export declare const MAX_LEVERAGE: BN;
10
11
  export declare const QUOTE_PRECISION: BN;
11
12
  export declare const MARK_PRICE_PRECISION: BN;
@@ -17,3 +18,4 @@ export declare const AMM_TO_QUOTE_PRECISION_RATIO: BN;
17
18
  export declare const PRICE_TO_QUOTE_PRECISION: BN;
18
19
  export declare const AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO: BN;
19
20
  export declare const MARGIN_PRECISION: BN;
21
+ export declare const BID_ASK_SPREAD_PRECISION: BN;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MARGIN_PRECISION = exports.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO = exports.PRICE_TO_QUOTE_PRECISION = exports.AMM_TO_QUOTE_PRECISION_RATIO = exports.BASE_PRECISION = exports.AMM_RESERVE_PRECISION = exports.PEG_PRECISION = exports.FUNDING_PAYMENT_PRECISION = exports.MARK_PRICE_PRECISION = exports.QUOTE_PRECISION = exports.MAX_LEVERAGE = exports.BN_MAX = exports.TEN_THOUSAND = exports.TEN = exports.TWO = exports.ONE = exports.ZERO = void 0;
3
+ exports.BID_ASK_SPREAD_PRECISION = exports.MARGIN_PRECISION = exports.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO = exports.PRICE_TO_QUOTE_PRECISION = exports.AMM_TO_QUOTE_PRECISION_RATIO = exports.BASE_PRECISION = exports.AMM_RESERVE_PRECISION = exports.PEG_PRECISION = exports.FUNDING_PAYMENT_PRECISION = exports.MARK_PRICE_PRECISION = exports.QUOTE_PRECISION = exports.MAX_LEVERAGE = exports.TEN_MILLION = exports.BN_MAX = exports.TEN_THOUSAND = exports.TEN = exports.TWO = exports.ONE = exports.ZERO = void 0;
4
4
  const __1 = require("../");
5
5
  exports.ZERO = new __1.BN(0);
6
6
  exports.ONE = new __1.BN(1);
@@ -8,6 +8,7 @@ exports.TWO = new __1.BN(2);
8
8
  exports.TEN = new __1.BN(10);
9
9
  exports.TEN_THOUSAND = new __1.BN(10000);
10
10
  exports.BN_MAX = new __1.BN(Number.MAX_SAFE_INTEGER);
11
+ exports.TEN_MILLION = exports.TEN_THOUSAND.mul(exports.TEN_THOUSAND);
11
12
  exports.MAX_LEVERAGE = new __1.BN(5);
12
13
  exports.QUOTE_PRECISION = new __1.BN(Math.pow(10, 6));
13
14
  exports.MARK_PRICE_PRECISION = new __1.BN(Math.pow(10, 10));
@@ -19,3 +20,4 @@ exports.AMM_TO_QUOTE_PRECISION_RATIO = exports.AMM_RESERVE_PRECISION.div(exports
19
20
  exports.PRICE_TO_QUOTE_PRECISION = exports.MARK_PRICE_PRECISION.div(exports.QUOTE_PRECISION);
20
21
  exports.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO = exports.AMM_RESERVE_PRECISION.mul(exports.PEG_PRECISION).div(exports.QUOTE_PRECISION); // 10^10
21
22
  exports.MARGIN_PRECISION = exports.TEN_THOUSAND;
23
+ exports.BID_ASK_SPREAD_PRECISION = new __1.BN(1000000);
@@ -1905,6 +1905,36 @@
1905
1905
  }
1906
1906
  ]
1907
1907
  },
1908
+ {
1909
+ "name": "updateMarketBaseSpread",
1910
+ "accounts": [
1911
+ {
1912
+ "name": "admin",
1913
+ "isMut": false,
1914
+ "isSigner": true
1915
+ },
1916
+ {
1917
+ "name": "state",
1918
+ "isMut": false,
1919
+ "isSigner": false
1920
+ },
1921
+ {
1922
+ "name": "markets",
1923
+ "isMut": true,
1924
+ "isSigner": false
1925
+ }
1926
+ ],
1927
+ "args": [
1928
+ {
1929
+ "name": "marketIndex",
1930
+ "type": "u64"
1931
+ },
1932
+ {
1933
+ "name": "baseSpread",
1934
+ "type": "u16"
1935
+ }
1936
+ ]
1937
+ },
1908
1938
  {
1909
1939
  "name": "updateMarketMinimumBaseAssetTradeSize",
1910
1940
  "accounts": [
@@ -3265,9 +3295,17 @@
3265
3295
  "name": "minimumBaseAssetTradeSize",
3266
3296
  "type": "u128"
3267
3297
  },
3298
+ {
3299
+ "name": "baseSpread",
3300
+ "type": "u16"
3301
+ },
3302
+ {
3303
+ "name": "padding0",
3304
+ "type": "u16"
3305
+ },
3268
3306
  {
3269
3307
  "name": "padding1",
3270
- "type": "u64"
3308
+ "type": "u32"
3271
3309
  },
3272
3310
  {
3273
3311
  "name": "padding2",
@@ -3585,7 +3623,7 @@
3585
3623
  "type": "u128"
3586
3624
  },
3587
3625
  {
3588
- "name": "referrerReward",
3626
+ "name": "quoteAssetAmountSurplus",
3589
3627
  "type": "u128"
3590
3628
  },
3591
3629
  {
package/lib/math/amm.d.ts CHANGED
@@ -20,7 +20,11 @@ export declare type AssetType = 'quote' | 'base';
20
20
  * @param swapDirection
21
21
  * @returns quoteAssetReserve and baseAssetReserve after swap. : Precision AMM_RESERVE_PRECISION
22
22
  */
23
- export declare function calculateAmmReservesAfterSwap(amm: AMM, inputAssetType: AssetType, swapAmount: BN, swapDirection: SwapDirection): [BN, BN];
23
+ export declare function calculateAmmReservesAfterSwap(amm: Pick<AMM, 'pegMultiplier' | 'quoteAssetReserve' | 'sqrtK' | 'baseAssetReserve'>, inputAssetType: AssetType, swapAmount: BN, swapDirection: SwapDirection): [BN, BN];
24
+ export declare function calculateSpreadReserves(amm: AMM, direction: PositionDirection): {
25
+ baseAssetReserve: BN;
26
+ quoteAssetReserve: BN;
27
+ };
24
28
  /**
25
29
  * Helper function calculating constant product curve output. Agnostic to whether input asset is quote or base
26
30
  *
@@ -63,6 +67,7 @@ export declare function calculateRepegCost(market: Market, marketIndex: BN, newP
63
67
  * @returns cost : Precision MARK_PRICE_PRECISION
64
68
  */
65
69
  export declare function calculateTerminalPrice(market: Market): BN;
66
- export declare function calculateMaxBaseAssetAmountToTrade(amm: AMM, limit_price: BN): [BN, PositionDirection];
70
+ export declare function calculateMaxBaseAssetAmountToTrade(amm: AMM, limit_price: BN, direction: PositionDirection, useSpread: boolean): [BN, PositionDirection];
67
71
  export declare function calculateBudgetedK(market: Market, cost: BN): [BN, BN];
68
72
  export declare function calculateBudgetedPeg(market: Market, cost: BN): BN;
73
+ export declare function calculateQuoteAssetAmountSwapped(quoteAssetReserves: BN, pegMultiplier: BN, swapDirection: SwapDirection): BN;
package/lib/math/amm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateBudgetedPeg = exports.calculateBudgetedK = exports.calculateMaxBaseAssetAmountToTrade = exports.calculateTerminalPrice = exports.calculateRepegCost = exports.calculateAdjustKCost = exports.getSwapDirection = exports.calculateSwapOutput = exports.calculateAmmReservesAfterSwap = exports.calculatePrice = void 0;
3
+ exports.calculateQuoteAssetAmountSwapped = exports.calculateBudgetedPeg = exports.calculateBudgetedK = exports.calculateMaxBaseAssetAmountToTrade = exports.calculateTerminalPrice = exports.calculateRepegCost = exports.calculateAdjustKCost = exports.getSwapDirection = exports.calculateSwapOutput = exports.calculateSpreadReserves = exports.calculateAmmReservesAfterSwap = exports.calculatePrice = void 0;
4
4
  const anchor_1 = require("@project-serum/anchor");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const position_1 = require("./position");
@@ -51,6 +51,28 @@ function calculateAmmReservesAfterSwap(amm, inputAssetType, swapAmount, swapDire
51
51
  return [newQuoteAssetReserve, newBaseAssetReserve];
52
52
  }
53
53
  exports.calculateAmmReservesAfterSwap = calculateAmmReservesAfterSwap;
54
+ function calculateSpreadReserves(amm, direction) {
55
+ if (amm.baseSpread === 0) {
56
+ return {
57
+ baseAssetReserve: amm.baseAssetReserve,
58
+ quoteAssetReserve: amm.quoteAssetReserve,
59
+ };
60
+ }
61
+ const quoteAsserReserveDelta = amm.quoteAssetReserve.div(numericConstants_1.BID_ASK_SPREAD_PRECISION.div(new anchor_1.BN(amm.baseSpread / 4)));
62
+ let quoteAssetReserve;
63
+ if ((0, types_1.isVariant)(direction, 'long')) {
64
+ quoteAssetReserve = amm.quoteAssetReserve.add(quoteAsserReserveDelta);
65
+ }
66
+ else {
67
+ quoteAssetReserve = amm.quoteAssetReserve.sub(quoteAsserReserveDelta);
68
+ }
69
+ const baseAssetReserve = amm.sqrtK.mul(amm.sqrtK).div(quoteAssetReserve);
70
+ return {
71
+ baseAssetReserve,
72
+ quoteAssetReserve,
73
+ };
74
+ }
75
+ exports.calculateSpreadReserves = calculateSpreadReserves;
54
76
  /**
55
77
  * Helper function calculating constant product curve output. Agnostic to whether input asset is quote or base
56
78
  *
@@ -193,7 +215,7 @@ function calculateTerminalPrice(market) {
193
215
  return terminalPrice;
194
216
  }
195
217
  exports.calculateTerminalPrice = calculateTerminalPrice;
196
- function calculateMaxBaseAssetAmountToTrade(amm, limit_price) {
218
+ function calculateMaxBaseAssetAmountToTrade(amm, limit_price, direction, useSpread) {
197
219
  const invariant = amm.sqrtK.mul(amm.sqrtK);
198
220
  const newBaseAssetReserveSquared = invariant
199
221
  .mul(numericConstants_1.MARK_PRICE_PRECISION)
@@ -201,15 +223,22 @@ function calculateMaxBaseAssetAmountToTrade(amm, limit_price) {
201
223
  .div(limit_price)
202
224
  .div(numericConstants_1.PEG_PRECISION);
203
225
  const newBaseAssetReserve = (0, __1.squareRootBN)(newBaseAssetReserveSquared);
204
- if (newBaseAssetReserve.gt(amm.baseAssetReserve)) {
226
+ let baseAssetReserveBefore;
227
+ if (useSpread) {
228
+ baseAssetReserveBefore = calculateSpreadReserves(amm, direction).baseAssetReserve;
229
+ }
230
+ else {
231
+ baseAssetReserveBefore = amm.baseAssetReserve;
232
+ }
233
+ if (newBaseAssetReserve.gt(baseAssetReserveBefore)) {
205
234
  return [
206
- newBaseAssetReserve.sub(amm.baseAssetReserve),
235
+ newBaseAssetReserve.sub(baseAssetReserveBefore),
207
236
  types_1.PositionDirection.SHORT,
208
237
  ];
209
238
  }
210
- else if (newBaseAssetReserve.lt(amm.baseAssetReserve)) {
239
+ else if (newBaseAssetReserve.lt(baseAssetReserveBefore)) {
211
240
  return [
212
- amm.baseAssetReserve.sub(newBaseAssetReserve),
241
+ baseAssetReserveBefore.sub(newBaseAssetReserve),
213
242
  types_1.PositionDirection.LONG,
214
243
  ];
215
244
  }
@@ -282,3 +311,13 @@ function calculateBudgetedPeg(market, cost) {
282
311
  return newPeg;
283
312
  }
284
313
  exports.calculateBudgetedPeg = calculateBudgetedPeg;
314
+ function calculateQuoteAssetAmountSwapped(quoteAssetReserves, pegMultiplier, swapDirection) {
315
+ let quoteAssetAmount = quoteAssetReserves
316
+ .mul(pegMultiplier)
317
+ .div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
318
+ if ((0, types_1.isVariant)(swapDirection, 'remove')) {
319
+ quoteAssetAmount = quoteAssetAmount.add(numericConstants_1.ONE);
320
+ }
321
+ return quoteAssetAmount;
322
+ }
323
+ exports.calculateQuoteAssetAmountSwapped = calculateQuoteAssetAmountSwapped;
@@ -66,7 +66,9 @@ function calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustm
66
66
  .mul(lastOracleTwapWithMantissa)
67
67
  .add(timeSinceLastMarkChange.mul(oraclePrice))
68
68
  .add(oracleInvalidDuration.mul(lastMarkTwapWithMantissa))
69
- .div(timeSinceLastMarkChange.add(oracleTwapTimeSinceLastUpdate).add(oracleInvalidDuration));
69
+ .div(timeSinceLastMarkChange
70
+ .add(oracleTwapTimeSinceLastUpdate)
71
+ .add(oracleInvalidDuration));
70
72
  }
71
73
  const twapSpread = lastMarkTwapWithMantissa.sub(lastOracleTwapWithMantissa);
72
74
  const twapSpreadPct = twapSpread
@@ -9,5 +9,20 @@ import { OraclePriceData } from '../oracles/types';
9
9
  * @return markPrice : Precision MARK_PRICE_PRECISION
10
10
  */
11
11
  export declare function calculateMarkPrice(market: Market): BN;
12
+ /**
13
+ * Calculates market bid price
14
+ *
15
+ * @param market
16
+ * @return bidPrice : Precision MARK_PRICE_PRECISION
17
+ */
18
+ export declare function calculateBidPrice(market: Market): BN;
19
+ /**
20
+ * Calculates market ask price
21
+ *
22
+ * @param market
23
+ * @return bidPrice : Precision MARK_PRICE_PRECISION
24
+ */
25
+ export declare function calculateAskPrice(market: Market): BN;
12
26
  export declare function calculateNewMarketAfterTrade(baseAssetAmount: BN, direction: PositionDirection, market: Market): Market;
13
27
  export declare function calculateMarkOracleSpread(market: Market, oraclePriceData: OraclePriceData): BN;
28
+ export declare function calculateOracleSpread(price: BN, oraclePriceData: OraclePriceData): BN;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateMarkOracleSpread = exports.calculateNewMarketAfterTrade = exports.calculateMarkPrice = void 0;
3
+ exports.calculateOracleSpread = exports.calculateMarkOracleSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateMarkPrice = void 0;
4
+ const types_1 = require("../types");
4
5
  const amm_1 = require("./amm");
5
6
  /**
6
7
  * Calculates market mark price
@@ -12,6 +13,28 @@ function calculateMarkPrice(market) {
12
13
  return (0, amm_1.calculatePrice)(market.amm.baseAssetReserve, market.amm.quoteAssetReserve, market.amm.pegMultiplier);
13
14
  }
14
15
  exports.calculateMarkPrice = calculateMarkPrice;
16
+ /**
17
+ * Calculates market bid price
18
+ *
19
+ * @param market
20
+ * @return bidPrice : Precision MARK_PRICE_PRECISION
21
+ */
22
+ function calculateBidPrice(market) {
23
+ const { baseAssetReserve, quoteAssetReserve } = (0, amm_1.calculateSpreadReserves)(market.amm, types_1.PositionDirection.SHORT);
24
+ return (0, amm_1.calculatePrice)(baseAssetReserve, quoteAssetReserve, market.amm.pegMultiplier);
25
+ }
26
+ exports.calculateBidPrice = calculateBidPrice;
27
+ /**
28
+ * Calculates market ask price
29
+ *
30
+ * @param market
31
+ * @return bidPrice : Precision MARK_PRICE_PRECISION
32
+ */
33
+ function calculateAskPrice(market) {
34
+ const { baseAssetReserve, quoteAssetReserve } = (0, amm_1.calculateSpreadReserves)(market.amm, types_1.PositionDirection.LONG);
35
+ return (0, amm_1.calculatePrice)(baseAssetReserve, quoteAssetReserve, market.amm.pegMultiplier);
36
+ }
37
+ exports.calculateAskPrice = calculateAskPrice;
15
38
  function calculateNewMarketAfterTrade(baseAssetAmount, direction, market) {
16
39
  const [newQuoteAssetReserve, newBaseAssetReserve] = (0, amm_1.calculateAmmReservesAfterSwap)(market.amm, 'base', baseAssetAmount.abs(), (0, amm_1.getSwapDirection)('base', direction));
17
40
  const newAmm = Object.assign({}, market.amm);
@@ -24,6 +47,10 @@ function calculateNewMarketAfterTrade(baseAssetAmount, direction, market) {
24
47
  exports.calculateNewMarketAfterTrade = calculateNewMarketAfterTrade;
25
48
  function calculateMarkOracleSpread(market, oraclePriceData) {
26
49
  const markPrice = calculateMarkPrice(market);
27
- return markPrice.sub(oraclePriceData.price);
50
+ return calculateOracleSpread(markPrice, oraclePriceData);
28
51
  }
29
52
  exports.calculateMarkOracleSpread = calculateMarkOracleSpread;
53
+ function calculateOracleSpread(price, oraclePriceData) {
54
+ return price.sub(oraclePriceData.price);
55
+ }
56
+ exports.calculateOracleSpread = calculateOracleSpread;
@@ -59,14 +59,15 @@ function isOrderReduceOnly(user, order) {
59
59
  const position = user.getUserPosition(order.marketIndex) ||
60
60
  user.getEmptyPosition(order.marketIndex);
61
61
  // if position is long and order is long
62
- if (position.baseAssetAmount.gt(numericConstants_1.ZERO) && (0, types_1.isVariant)(order.direction, 'long')) {
62
+ if (position.baseAssetAmount.gte(numericConstants_1.ZERO) &&
63
+ (0, types_1.isVariant)(order.direction, 'long')) {
63
64
  return false;
64
65
  }
65
66
  // if position is short and order is short
66
- if (position.baseAssetAmount.lt(numericConstants_1.ZERO) &&
67
+ if (position.baseAssetAmount.lte(numericConstants_1.ZERO) &&
67
68
  (0, types_1.isVariant)(order.direction, 'short')) {
68
69
  return false;
69
70
  }
70
- return order.baseAssetAmount.abs().lte(position.baseAssetAmount.abs());
71
+ return true;
71
72
  }
72
73
  exports.isOrderReduceOnly = isOrderReduceOnly;
@@ -24,11 +24,13 @@ export declare function calculateTradeSlippage(direction: PositionDirection, amo
24
24
  * @param direction
25
25
  * @param amount
26
26
  * @param market
27
+ * @param inputAssetType
28
+ * @param useSpread
27
29
  * @return
28
30
  * | 'acquiredBase' => positive/negative change in user's base : BN TODO-PRECISION
29
31
  * | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
30
32
  */
31
- export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: Market, inputAssetType?: AssetType): [BN, BN];
33
+ export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: Market, inputAssetType?: AssetType, useSpread?: boolean): [BN, BN];
32
34
  /**
33
35
  * calculateTargetPriceTrade
34
36
  * simple function for finding arbitraging trades
package/lib/math/trade.js CHANGED
@@ -56,21 +56,33 @@ exports.calculateTradeSlippage = calculateTradeSlippage;
56
56
  * @param direction
57
57
  * @param amount
58
58
  * @param market
59
+ * @param inputAssetType
60
+ * @param useSpread
59
61
  * @return
60
62
  * | 'acquiredBase' => positive/negative change in user's base : BN TODO-PRECISION
61
63
  * | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
62
64
  */
63
- function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType = 'quote') {
65
+ function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType = 'quote', useSpread = true) {
64
66
  if (amount.eq(numericConstants_1.ZERO)) {
65
67
  return [numericConstants_1.ZERO, numericConstants_1.ZERO];
66
68
  }
67
69
  const swapDirection = (0, amm_1.getSwapDirection)(inputAssetType, direction);
68
- const [newQuoteAssetReserve, newBaseAssetReserve] = (0, amm_1.calculateAmmReservesAfterSwap)(market.amm, inputAssetType, amount, swapDirection);
69
- const acquiredBase = market.amm.baseAssetReserve.sub(newBaseAssetReserve);
70
- let acquiredQuote = market.amm.quoteAssetReserve.sub(newQuoteAssetReserve);
71
- if (inputAssetType === 'base' && (0, types_1.isVariant)(swapDirection, 'remove')) {
72
- acquiredQuote = acquiredQuote.sub(numericConstants_1.ONE);
70
+ let amm;
71
+ if (useSpread && market.amm.baseSpread > 0) {
72
+ const { baseAssetReserve, quoteAssetReserve } = (0, amm_1.calculateSpreadReserves)(market.amm, direction);
73
+ amm = {
74
+ baseAssetReserve,
75
+ quoteAssetReserve,
76
+ sqrtK: market.amm.sqrtK,
77
+ pegMultiplier: market.amm.pegMultiplier,
78
+ };
73
79
  }
80
+ else {
81
+ amm = market.amm;
82
+ }
83
+ const [newQuoteAssetReserve, newBaseAssetReserve] = (0, amm_1.calculateAmmReservesAfterSwap)(amm, inputAssetType, amount, swapDirection);
84
+ const acquiredBase = amm.baseAssetReserve.sub(newBaseAssetReserve);
85
+ const acquiredQuote = amm.quoteAssetReserve.sub(newQuoteAssetReserve);
74
86
  return [acquiredBase, acquiredQuote];
75
87
  }
76
88
  exports.calculateTradeAcquiredAmounts = calculateTradeAcquiredAmounts;
package/lib/orders.js CHANGED
@@ -112,7 +112,7 @@ function calculateAmountToTradeForLimit(market, order, oraclePriceData) {
112
112
  limitPrice = floatingPrice;
113
113
  }
114
114
  }
115
- const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice);
115
+ const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction, !order.postOnly);
116
116
  // Check that directions are the same
117
117
  const sameDirection = isSameDirection(direction, order.direction);
118
118
  if (!sameDirection) {
@@ -170,10 +170,43 @@ function calculateBaseAssetAmountUserCanExecute(market, order, user) {
170
170
  if (quoteAssetAmount.lte(numericConstants_1.ZERO)) {
171
171
  return numericConstants_1.ZERO;
172
172
  }
173
- const baseAssetReservesBefore = market.amm.baseAssetReserve;
174
- const [_, baseAssetReservesAfter] = (0, _1.calculateAmmReservesAfterSwap)(market.amm, 'quote', quoteAssetAmount, (0, types_1.isVariant)(order.direction, 'long')
173
+ const swapDirection = (0, types_1.isVariant)(order.direction, 'long')
175
174
  ? types_1.SwapDirection.ADD
176
- : types_1.SwapDirection.REMOVE);
177
- return baseAssetReservesBefore.sub(baseAssetReservesAfter).abs();
175
+ : types_1.SwapDirection.REMOVE;
176
+ const useSpread = !order.postOnly;
177
+ let amm;
178
+ if (useSpread) {
179
+ const { baseAssetReserve, quoteAssetReserve } = (0, _1.calculateSpreadReserves)(market.amm, order.direction);
180
+ amm = {
181
+ baseAssetReserve,
182
+ quoteAssetReserve,
183
+ sqrtK: market.amm.sqrtK,
184
+ pegMultiplier: market.amm.pegMultiplier,
185
+ };
186
+ }
187
+ else {
188
+ amm = market.amm;
189
+ }
190
+ const baseAssetReservesBefore = amm.baseAssetReserve;
191
+ const [_, baseAssetReservesAfter] = (0, _1.calculateAmmReservesAfterSwap)(amm, 'quote', quoteAssetAmount, swapDirection);
192
+ let baseAssetAmount = baseAssetReservesBefore
193
+ .sub(baseAssetReservesAfter)
194
+ .abs();
195
+ if (order.reduceOnly) {
196
+ const position = user.getUserPosition(order.marketIndex) ||
197
+ user.getEmptyPosition(order.marketIndex);
198
+ if ((0, types_1.isVariant)(order.direction, 'long') &&
199
+ position.baseAssetAmount.gte(numericConstants_1.ZERO)) {
200
+ baseAssetAmount = numericConstants_1.ZERO;
201
+ }
202
+ else if ((0, types_1.isVariant)(order.direction, 'short') &&
203
+ position.baseAssetAmount.lte(numericConstants_1.ZERO)) {
204
+ baseAssetAmount = numericConstants_1.ZERO;
205
+ }
206
+ else {
207
+ _1.BN.min(baseAssetAmount, position.baseAssetAmount.abs());
208
+ }
209
+ }
210
+ return baseAssetAmount;
178
211
  }
179
212
  exports.calculateBaseAssetAmountUserCanExecute = calculateBaseAssetAmountUserCanExecute;
package/lib/types.d.ts CHANGED
@@ -168,7 +168,7 @@ export declare type TradeRecord = {
168
168
  markPriceBefore: BN;
169
169
  markPriceAfter: BN;
170
170
  fee: BN;
171
- referrerReward: BN;
171
+ quoteAssetAmountSurplus: BN;
172
172
  refereeDiscount: BN;
173
173
  tokenDiscount: BN;
174
174
  marketIndex: BN;
@@ -314,6 +314,7 @@ export declare type AMM = {
314
314
  minimumQuoteAssetTradeSize: BN;
315
315
  minimumBaseAssetTradeSize: BN;
316
316
  lastOraclePrice: BN;
317
+ baseSpread: number;
317
318
  };
318
319
  export declare type UserPosition = {
319
320
  baseAssetAmount: BN;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.1.32",
3
+ "version": "0.1.34-master.1",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -86,13 +86,17 @@ export class PollingClearingHouseAccountSubscriber
86
86
  await this.updateAccountsToPoll();
87
87
  await this.addToAccountLoader();
88
88
  await this.fetch();
89
- this.eventEmitter.emit('update');
89
+ const subscriptionSucceeded = this.didSubscriptionSucceed();
90
+
91
+ if (subscriptionSucceeded) {
92
+ this.eventEmitter.emit('update');
93
+ }
90
94
 
91
95
  this.isSubscribing = false;
92
- this.isSubscribed = true;
93
- this.subscriptionPromiseResolver(true);
96
+ this.isSubscribed = subscriptionSucceeded;
97
+ this.subscriptionPromiseResolver(subscriptionSucceeded);
94
98
 
95
- return true;
99
+ return subscriptionSucceeded;
96
100
  }
97
101
 
98
102
  async updateAccountsToPoll(): Promise<void> {
@@ -254,6 +258,17 @@ export class PollingClearingHouseAccountSubscriber
254
258
  }
255
259
  }
256
260
 
261
+ didSubscriptionSucceed(): boolean {
262
+ let success = true;
263
+ for (const [_, accountToPoll] of this.accountsToPoll) {
264
+ if (!this[accountToPoll.key]) {
265
+ success = false;
266
+ break;
267
+ }
268
+ }
269
+ return success;
270
+ }
271
+
257
272
  public async unsubscribe(): Promise<void> {
258
273
  if (!this.isSubscribed) {
259
274
  return;
@@ -53,10 +53,15 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
53
53
 
54
54
  await this.addToAccountLoader();
55
55
  await this.fetchIfUnloaded();
56
- this.eventEmitter.emit('update');
57
56
 
58
- this.isSubscribed = true;
59
- return true;
57
+ const subscriptionSucceeded = this.didSubscriptionSucceed();
58
+
59
+ if (subscriptionSucceeded) {
60
+ this.eventEmitter.emit('update');
61
+ }
62
+
63
+ this.isSubscribed = subscriptionSucceeded;
64
+ return subscriptionSucceeded;
60
65
  }
61
66
 
62
67
  async addToAccountLoader(userPublicKeys?: UserPublicKeys): Promise<void> {
@@ -168,6 +173,18 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
168
173
  }
169
174
  }
170
175
 
176
+ didSubscriptionSucceed(): boolean {
177
+ let success = true;
178
+ for (const [_, accountToPoll] of this.accountsToPoll) {
179
+ // userOrders may not exist
180
+ if (accountToPoll.key !== 'userOrders' && !this[accountToPoll.key]) {
181
+ success = false;
182
+ break;
183
+ }
184
+ }
185
+ return success;
186
+ }
187
+
171
188
  async unsubscribe(): Promise<void> {
172
189
  if (!this.isSubscribed) {
173
190
  return;