@drift-labs/sdk 0.1.13 → 0.1.17-master.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +2 -2
  2. package/lib/accounts/defaultClearingHouseAccountSubscriber.d.ts +1 -0
  3. package/lib/accounts/defaultClearingHouseAccountSubscriber.d.ts.map +1 -1
  4. package/lib/accounts/defaultClearingHouseAccountSubscriber.js +18 -1
  5. package/lib/accounts/defaultUserAccountSubscriber.d.ts +2 -0
  6. package/lib/accounts/defaultUserAccountSubscriber.d.ts.map +1 -1
  7. package/lib/accounts/defaultUserAccountSubscriber.js +17 -1
  8. package/lib/accounts/types.d.ts +3 -0
  9. package/lib/accounts/types.d.ts.map +1 -1
  10. package/lib/accounts/webSocketAccountSubscriber.d.ts +2 -0
  11. package/lib/accounts/webSocketAccountSubscriber.d.ts.map +1 -1
  12. package/lib/accounts/webSocketAccountSubscriber.js +13 -3
  13. package/lib/admin.js +3 -3
  14. package/lib/clearingHouse.d.ts +4 -0
  15. package/lib/clearingHouse.d.ts.map +1 -1
  16. package/lib/clearingHouse.js +17 -9
  17. package/lib/clearingHouseUser.d.ts +4 -0
  18. package/lib/clearingHouseUser.d.ts.map +1 -1
  19. package/lib/clearingHouseUser.js +33 -13
  20. package/lib/constants/markets.d.ts.map +1 -1
  21. package/lib/constants/markets.js +14 -0
  22. package/lib/examples/makeTradeExample.js +10 -11
  23. package/lib/index.d.ts +2 -0
  24. package/lib/index.d.ts.map +1 -1
  25. package/lib/index.js +2 -0
  26. package/lib/math/amm.d.ts.map +1 -1
  27. package/lib/math/amm.js +9 -8
  28. package/lib/math/conversion.js +1 -1
  29. package/lib/math/funding.d.ts +2 -4
  30. package/lib/math/funding.d.ts.map +1 -1
  31. package/lib/math/funding.js +5 -7
  32. package/lib/math/insuranceFund.d.ts +4 -3
  33. package/lib/math/insuranceFund.d.ts.map +1 -1
  34. package/lib/math/insuranceFund.js +1 -0
  35. package/lib/math/market.js +1 -1
  36. package/lib/math/position.d.ts.map +1 -1
  37. package/lib/math/position.js +1 -1
  38. package/lib/math/trade.js +16 -16
  39. package/lib/pythClient.js +1 -1
  40. package/lib/util/computeUnits.d.ts +3 -0
  41. package/lib/util/computeUnits.d.ts.map +1 -0
  42. package/lib/util/computeUnits.js +27 -0
  43. package/lib/util/tps.d.ts +3 -0
  44. package/lib/util/tps.d.ts.map +1 -0
  45. package/lib/util/tps.js +27 -0
  46. package/lib/wallet.d.ts +2 -2
  47. package/lib/wallet.d.ts.map +1 -1
  48. package/package.json +2 -12
  49. package/src/accounts/defaultClearingHouseAccountSubscriber.ts +18 -0
  50. package/src/accounts/defaultUserAccountSubscriber.ts +18 -0
  51. package/src/accounts/types.ts +3 -1
  52. package/src/accounts/webSocketAccountSubscriber.ts +16 -6
  53. package/src/clearingHouse.ts +7 -1
  54. package/src/clearingHouseUser.ts +29 -4
  55. package/src/constants/markets.ts +14 -0
  56. package/src/constants/numericConstants.ts +0 -1
  57. package/src/examples/makeTradeExample.ts +6 -12
  58. package/src/index.ts +2 -0
  59. package/src/math/amm.ts +2 -2
  60. package/src/math/funding.ts +7 -6
  61. package/src/math/insuranceFund.ts +16 -9
  62. package/src/math/position.ts +6 -5
  63. package/src/util/computeUnits.ts +21 -0
  64. package/src/util/tps.ts +27 -0
  65. package/src/wallet.ts +17 -17
  66. package/.eslintrc.json +0 -36
  67. package/.prettierignore +0 -1
  68. package/.prettierrc.js +0 -9
@@ -25,6 +25,7 @@ import {
25
25
  calculatePositionFundingPNL,
26
26
  calculatePositionPNL,
27
27
  PositionDirection,
28
+ calculateTradeSlippage,
28
29
  } from '.';
29
30
  import { getUserAccountPublicKey } from './addresses';
30
31
 
@@ -70,6 +71,13 @@ export class ClearingHouseUser {
70
71
  return this.isSubscribed;
71
72
  }
72
73
 
74
+ /**
75
+ * Forces the accountSubscriber to fetch account updates from rpc
76
+ */
77
+ public async fetchAccounts(): Promise<void> {
78
+ await this.accountSubscriber.fetch();
79
+ }
80
+
73
81
  public async unsubscribe(): Promise<void> {
74
82
  await this.accountSubscriber.unsubscribe();
75
83
  this.isSubscribed = false;
@@ -570,7 +578,7 @@ export class ClearingHouseUser {
570
578
  }
571
579
 
572
580
  let priceDelt;
573
- if (currentMarketPositionBaseSize.lt(ZERO)) {
581
+ if (proposedBaseAssetAmount.lt(ZERO)) {
574
582
  priceDelt = tc
575
583
  .mul(thisLev)
576
584
  .sub(tpv)
@@ -584,9 +592,22 @@ export class ClearingHouseUser {
584
592
  .div(thisLev.sub(new BN(1)));
585
593
  }
586
594
 
587
- const currentPrice = calculateMarkPrice(
588
- this.clearingHouse.getMarket(targetMarket.marketIndex)
589
- );
595
+ let currentPrice;
596
+ if (positionBaseSizeChange.eq(ZERO)) {
597
+ currentPrice = calculateMarkPrice(
598
+ this.clearingHouse.getMarket(targetMarket.marketIndex)
599
+ );
600
+ } else {
601
+ const direction = positionBaseSizeChange.gt(ZERO)
602
+ ? PositionDirection.LONG
603
+ : PositionDirection.SHORT;
604
+ currentPrice = calculateTradeSlippage(
605
+ direction,
606
+ positionBaseSizeChange.abs(),
607
+ this.clearingHouse.getMarket(targetMarket.marketIndex),
608
+ 'base'
609
+ )[3]; // newPrice after swap
610
+ }
590
611
 
591
612
  // if the position value after the trade is less than total collateral, there is no liq price
592
613
  if (
@@ -602,6 +623,10 @@ export class ClearingHouseUser {
602
623
  .mul(AMM_RESERVE_PRECISION)
603
624
  .div(proposedBaseAssetAmount);
604
625
 
626
+ if (eatMargin2.gt(currentPrice)) {
627
+ return new BN(-1);
628
+ }
629
+
605
630
  const liqPrice = currentPrice.sub(eatMargin2);
606
631
  return liqPrice;
607
632
  }
@@ -58,4 +58,18 @@ export const Markets: Market[] = [
58
58
  devnetPythOracle: 'FBirwuDFuRAu4iSGc7RGxN5koHB7EJM1wbCmyPuQoGur',
59
59
  mainnetPythOracle: '7KVswB9vkCgeM3SHP7aGDijvdRAHK8P5wi9JXViCrtYh',
60
60
  },
61
+ {
62
+ symbol: 'ATOM-PERP',
63
+ baseAssetSymbol: 'ATOM',
64
+ marketIndex: new BN(7),
65
+ devnetPythOracle: '7YAze8qFUMkBnyLVdKT4TFUUFui99EwS5gfRArMcrvFk',
66
+ mainnetPythOracle: 'CrCpTerNqtZvqLcKqz1k13oVeXV9WkMD2zA9hBKXrsbN',
67
+ },
68
+ {
69
+ symbol: 'DOT-PERP',
70
+ baseAssetSymbol: 'DOT',
71
+ marketIndex: new BN(8),
72
+ devnetPythOracle: '4dqq5VBpN4EwYb7wyywjjfknvMKu7m78j9mKZRXTj462',
73
+ mainnetPythOracle: 'EcV1X1gY2yb4KXxjVQtTHTbioum2gvmPnFk4zYAt7zne',
74
+ },
61
75
  ];
@@ -21,4 +21,3 @@ export const PRICE_TO_QUOTE_PRECISION =
21
21
  MARK_PRICE_PRECISION.div(QUOTE_PRECISION);
22
22
  export const AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO =
23
23
  AMM_RESERVE_PRECISION.mul(PEG_PRECISION).div(QUOTE_PRECISION); // 10^10
24
-
@@ -1,5 +1,5 @@
1
1
  import { BN, Provider } from '@project-serum/anchor';
2
- import {Wallet} from "..";
2
+ import { Wallet } from '..';
3
3
  import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token';
4
4
  import { Connection, Keypair, PublicKey } from '@solana/web3.js';
5
5
  import {
@@ -102,10 +102,11 @@ const main = async () => {
102
102
  // Estimate the slippage for a $5000 LONG trade
103
103
  const solMarketAccount = clearingHouse.getMarket(solMarketInfo.marketIndex);
104
104
 
105
+ const longAmount = new BN(5000).mul(QUOTE_PRECISION);
105
106
  const slippage = convertToNumber(
106
107
  calculateTradeSlippage(
107
108
  PositionDirection.LONG,
108
- new BN(5000).mul(QUOTE_PRECISION),
109
+ longAmount,
109
110
  solMarketAccount
110
111
  )[0],
111
112
  MARK_PRICE_PRECISION
@@ -118,23 +119,16 @@ const main = async () => {
118
119
  // Make a $5000 LONG trade
119
120
  await clearingHouse.openPosition(
120
121
  PositionDirection.LONG,
121
- new BN(5000).mul(QUOTE_PRECISION),
122
+ longAmount,
122
123
  solMarketInfo.marketIndex
123
124
  );
124
125
  console.log(`LONGED $5000 SOL`);
125
126
 
126
- // Make a $5000 LONG trade
127
- await clearingHouse.openPosition(
128
- PositionDirection.LONG,
129
- new BN(5000).mul(QUOTE_PRECISION),
130
- solMarketInfo.marketIndex
131
- );
132
- console.log(`LONGED $5000 worth of SOL`);
133
-
134
127
  // Reduce the position by $2000
128
+ const reduceAmount = new BN(2000).mul(QUOTE_PRECISION);
135
129
  await clearingHouse.openPosition(
136
130
  PositionDirection.SHORT,
137
- new BN(2000).mul(QUOTE_PRECISION),
131
+ reduceAmount,
138
132
  solMarketInfo.marketIndex
139
133
  );
140
134
 
package/src/index.ts CHANGED
@@ -22,5 +22,7 @@ export * from './types';
22
22
  export * from './math/utils';
23
23
  export * from './config';
24
24
  export * from './constants/numericConstants';
25
+ export * from './util/computeUnits';
26
+ export * from './util/tps';
25
27
 
26
28
  export { BN };
package/src/math/amm.ts CHANGED
@@ -2,7 +2,6 @@ import { BN } from '@project-serum/anchor';
2
2
  import {
3
3
  AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO,
4
4
  MARK_PRICE_PRECISION,
5
- ONE,
6
5
  PEG_PRECISION,
7
6
  ZERO,
8
7
  } from '../constants/numericConstants';
@@ -58,7 +57,8 @@ export function calculateAmmReservesAfterSwap(
58
57
  let newBaseAssetReserve;
59
58
 
60
59
  if (inputAssetType === 'quote') {
61
- swapAmount = swapAmount.mul(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
60
+ swapAmount = swapAmount
61
+ .mul(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
62
62
  .div(amm.pegMultiplier);
63
63
 
64
64
  [newQuoteAssetReserve, newBaseAssetReserve] = calculateSwapOutput(
@@ -99,7 +99,7 @@ export async function calculateAllEstimatedFundingRate(
99
99
  .div(timeSinceLastOracleTwapUpdate.add(oracleTwapTimeSinceLastUpdate));
100
100
  }
101
101
 
102
- const twapSpread = markTwapWithMantissa.sub(oracleTwapWithMantissa);
102
+ const twapSpread = lastMarkTwapWithMantissa.sub(lastOracleTwapWithMantissa);
103
103
 
104
104
  const twapSpreadPct = twapSpread
105
105
  .mul(MARK_PRICE_PRECISION)
@@ -226,9 +226,8 @@ export async function calculateEstimatedFundingRate(
226
226
  /**
227
227
  *
228
228
  * @param market
229
- * @param pythClient
229
+ * @param oraclePriceData
230
230
  * @param periodAdjustment
231
- * @param estimationMethod
232
231
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
233
232
  */
234
233
  export async function calculateLongShortFundingRate(
@@ -255,9 +254,8 @@ export async function calculateLongShortFundingRate(
255
254
  /**
256
255
  *
257
256
  * @param market
258
- * @param pythClient
257
+ * @param oraclePriceData
259
258
  * @param periodAdjustment
260
- * @param estimationMethod
261
259
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
262
260
  */
263
261
  export async function calculateLongShortFundingRateAndLiveTwaps(
@@ -289,6 +287,9 @@ export async function calculateLongShortFundingRateAndLiveTwaps(
289
287
  export function calculateFundingPool(market: Market): BN {
290
288
  // todo
291
289
  const totalFeeLB = market.amm.totalFee.div(new BN(2));
292
- const feePool = market.amm.totalFeeMinusDistributions.sub(totalFeeLB);
290
+ const feePool = BN.max(
291
+ ZERO,
292
+ market.amm.totalFeeMinusDistributions.sub(totalFeeLB)
293
+ );
293
294
  return feePool;
294
295
  }
@@ -1,6 +1,6 @@
1
- import {MarketsAccount, StateAccount} from "../types";
2
- import BN from "bn.js";
3
- import {Connection} from "@solana/web3.js";
1
+ import { MarketsAccount, StateAccount } from '../types';
2
+ import BN from 'bn.js';
3
+ import { Connection } from '@solana/web3.js';
4
4
 
5
5
  /**
6
6
  * In the case of a levered loss, the exchange first pays out undistributed fees and then the insurance fund.
@@ -10,13 +10,20 @@ import {Connection} from "@solana/web3.js";
10
10
  * @param connection
11
11
  * @param state
12
12
  * @param marketsAccount
13
+ * @returns Precision : QUOTE_ASSET_PRECISION
13
14
  */
14
- export async function calculateInsuranceFundSize(connection: Connection, state: StateAccount, marketsAccount: MarketsAccount) : Promise<BN> {
15
+ export async function calculateInsuranceFundSize(
16
+ connection: Connection,
17
+ state: StateAccount,
18
+ marketsAccount: MarketsAccount
19
+ ): Promise<BN> {
15
20
  const insuranceVaultPublicKey = state.insuranceVault;
16
- const insuranceVaultAmount = new BN((await connection.getTokenAccountBalance(insuranceVaultPublicKey)).value.amount);
21
+ const insuranceVaultAmount = new BN(
22
+ (
23
+ await connection.getTokenAccountBalance(insuranceVaultPublicKey)
24
+ ).value.amount
25
+ );
17
26
  return marketsAccount.markets.reduce((insuranceVaultAmount, market) => {
18
- return insuranceVaultAmount.add(
19
- market.amm.totalFee.div(new BN(2))
20
- )
27
+ return insuranceVaultAmount.add(market.amm.totalFee.div(new BN(2)));
21
28
  }, insuranceVaultAmount);
22
- }
29
+ }
@@ -1,10 +1,11 @@
1
1
  import BN from 'bn.js';
2
2
  import {
3
- AMM_RESERVE_PRECISION, AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO,
3
+ AMM_RESERVE_PRECISION,
4
+ AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO,
4
5
  AMM_TO_QUOTE_PRECISION_RATIO,
5
6
  FUNDING_PAYMENT_PRECISION,
6
- MARK_PRICE_PRECISION, ONE,
7
- PEG_PRECISION,
7
+ MARK_PRICE_PRECISION,
8
+ ONE,
8
9
  PRICE_TO_QUOTE_PRECISION,
9
10
  ZERO,
10
11
  } from '../constants/numericConstants';
@@ -42,13 +43,13 @@ export function calculateBaseAssetValue(
42
43
  return market.amm.quoteAssetReserve
43
44
  .sub(newQuoteAssetReserve)
44
45
  .mul(market.amm.pegMultiplier)
45
- .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
46
+ .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
46
47
 
47
48
  case PositionDirection.LONG:
48
49
  return newQuoteAssetReserve
49
50
  .sub(market.amm.quoteAssetReserve)
50
51
  .mul(market.amm.pegMultiplier)
51
- .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
52
+ .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
52
53
  }
53
54
  }
54
55
 
@@ -0,0 +1,21 @@
1
+ import { Connection, Finality, PublicKey } from '@solana/web3.js';
2
+
3
+ export async function findComputeUnitConsumption(
4
+ programId: PublicKey,
5
+ connection: Connection,
6
+ txSignature: string,
7
+ commitment: Finality = 'confirmed'
8
+ ): Promise<number[]> {
9
+ const tx = await connection.getTransaction(txSignature, { commitment });
10
+ const computeUnits = [];
11
+ const regex = new RegExp(
12
+ `Program ${programId.toString()} consumed ([0-9]{0,6}) of 200000 compute units`
13
+ );
14
+ tx.meta.logMessages.forEach((logMessage) => {
15
+ const match = logMessage.match(regex);
16
+ if (match && match[1]) {
17
+ computeUnits.push(match[1]);
18
+ }
19
+ });
20
+ return computeUnits;
21
+ }
@@ -0,0 +1,27 @@
1
+ import { Connection, PublicKey } from '@solana/web3.js';
2
+
3
+ export async function estimateTps(
4
+ programId: PublicKey,
5
+ connection: Connection,
6
+ failed: boolean
7
+ ): Promise<number> {
8
+ let signatures = await connection.getSignaturesForAddress(
9
+ programId,
10
+ undefined,
11
+ 'finalized'
12
+ );
13
+ if (failed) {
14
+ signatures = signatures.filter((signature) => signature.err);
15
+ }
16
+
17
+ const numberOfSignatures = signatures.length;
18
+
19
+ if (numberOfSignatures === 0) {
20
+ return 0;
21
+ }
22
+
23
+ return (
24
+ numberOfSignatures /
25
+ (signatures[0].blockTime - signatures[numberOfSignatures - 1].blockTime)
26
+ );
27
+ }
package/src/wallet.ts CHANGED
@@ -1,22 +1,22 @@
1
- import {Keypair, PublicKey, Transaction} from "@solana/web3.js";
2
- import {IWallet} from "./types";
1
+ import { Keypair, PublicKey, Transaction } from '@solana/web3.js';
2
+ import { IWallet } from './types';
3
3
 
4
4
  export class Wallet implements IWallet {
5
- constructor(readonly payer: Keypair) {}
5
+ constructor(readonly payer: Keypair) {}
6
6
 
7
- async signTransaction(tx: Transaction): Promise<Transaction> {
8
- tx.partialSign(this.payer);
9
- return tx;
10
- }
7
+ async signTransaction(tx: Transaction): Promise<Transaction> {
8
+ tx.partialSign(this.payer);
9
+ return tx;
10
+ }
11
11
 
12
- async signAllTransactions(txs: Transaction[]): Promise<Transaction[]> {
13
- return txs.map((t) => {
14
- t.partialSign(this.payer);
15
- return t;
16
- });
17
- }
12
+ async signAllTransactions(txs: Transaction[]): Promise<Transaction[]> {
13
+ return txs.map((t) => {
14
+ t.partialSign(this.payer);
15
+ return t;
16
+ });
17
+ }
18
18
 
19
- get publicKey(): PublicKey {
20
- return this.payer.publicKey;
21
- }
22
- }
19
+ get publicKey(): PublicKey {
20
+ return this.payer.publicKey;
21
+ }
22
+ }
package/.eslintrc.json DELETED
@@ -1,36 +0,0 @@
1
- {
2
- "root": true,
3
- "parser": "@typescript-eslint/parser",
4
- "env": {
5
- "browser": true
6
- },
7
- "ignorePatterns": ["**/lib"],
8
- "plugins": [],
9
- "extends": [
10
- "eslint:recommended",
11
- "plugin:@typescript-eslint/eslint-recommended",
12
- "plugin:@typescript-eslint/recommended"
13
- ],
14
- "rules": {
15
- "@typescript-eslint/explicit-function-return-type": "off",
16
- "@typescript-eslint/ban-ts-ignore": "off",
17
- "@typescript-eslint/ban-ts-comment": "off",
18
- "@typescript-eslint/no-explicit-any": "off",
19
- "@typescript-eslint/no-unused-vars": [
20
- 2,
21
- {
22
- "argsIgnorePattern": "^_",
23
- "varsIgnorePattern": "^_"
24
- }
25
- ],
26
- "@typescript-eslint/no-var-requires": 0,
27
- "@typescript-eslint/no-empty-function": 0,
28
- "no-mixed-spaces-and-tabs": [2, "smart-tabs"],
29
- "semi": 2
30
- },
31
- "settings": {
32
- "react": {
33
- "version": "detect"
34
- }
35
- }
36
- }
package/.prettierignore DELETED
@@ -1 +0,0 @@
1
- **/node_modules/**
package/.prettierrc.js DELETED
@@ -1,9 +0,0 @@
1
- module.exports = {
2
- semi: true,
3
- trailingComma: 'es5',
4
- singleQuote: true,
5
- printWidth: 80,
6
- tabWidth: 2,
7
- useTabs: true,
8
- bracketSameLine: false,
9
- };