@drift-labs/sdk 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -228,3 +228,4 @@ Drift Protocol v1 is licensed under [Apache 2.0](./LICENSE).
228
228
  Unless you explicitly state otherwise, any contribution intentionally submitted
229
229
  for inclusion in Drift SDK by you, as defined in the Apache-2.0 license, shall be
230
230
  licensed as above, without any additional terms or conditions.
231
+
@@ -1,6 +1,6 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { User } from '../user';
3
- import { PerpMarketAccount, Order } from '../types';
3
+ import { PerpMarketAccount, AMM, Order } from '../types';
4
4
  import { BN } from '@project-serum/anchor';
5
5
  import { OraclePriceData } from '../oracles/types';
6
6
  export declare function isOrderRiskIncreasing(user: User, order: Order): boolean;
@@ -12,7 +12,7 @@ export declare function getOptionalLimitPrice(order: Order, oraclePriceData: Ora
12
12
  export declare function hasLimitPrice(order: Order, slot: number): boolean;
13
13
  export declare function isFillableByVAMM(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number, ts: number): boolean;
14
14
  export declare function calculateBaseAssetAmountForAmmToFulfill(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
15
- export declare function calculateBaseAssetAmountToFillUpToLimitPrice(order: Order, market: PerpMarketAccount, limitPrice: BN, oraclePriceData: OraclePriceData): BN;
15
+ export declare function calculateBaseAssetAmountToFillUpToLimitPrice(order: Order, amm: AMM, limitPrice: BN, oraclePriceData: OraclePriceData): BN;
16
16
  export declare function isOrderExpired(order: Order, ts: number): boolean;
17
17
  export declare function isMarketOrder(order: Order): boolean;
18
18
  export declare function isLimitOrder(order: Order): boolean;
@@ -135,19 +135,20 @@ function calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData,
135
135
  }
136
136
  const limitPrice = getOptionalLimitPrice(order, oraclePriceData, slot);
137
137
  let baseAssetAmount;
138
+ const updatedAMM = (0, amm_1.calculateUpdatedAMM)(market.amm, oraclePriceData);
138
139
  if (limitPrice !== undefined) {
139
- baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData);
140
+ baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(order, updatedAMM, limitPrice, oraclePriceData);
140
141
  }
141
142
  else {
142
143
  baseAssetAmount = order.baseAssetAmount.sub(order.baseAssetAmountFilled);
143
144
  }
144
- const maxBaseAssetAmount = (0, amm_1.calculateMaxBaseAssetAmountFillable)(market.amm, order.direction);
145
+ const maxBaseAssetAmount = (0, amm_1.calculateMaxBaseAssetAmountFillable)(updatedAMM, order.direction);
145
146
  return anchor_1.BN.min(maxBaseAssetAmount, baseAssetAmount);
146
147
  }
147
148
  exports.calculateBaseAssetAmountForAmmToFulfill = calculateBaseAssetAmountForAmmToFulfill;
148
- function calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData) {
149
- const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction, oraclePriceData);
150
- const baseAssetAmount = standardizeBaseAssetAmount(maxAmountToTrade, market.amm.orderStepSize);
149
+ function calculateBaseAssetAmountToFillUpToLimitPrice(order, amm, limitPrice, oraclePriceData) {
150
+ const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(amm, limitPrice, order.direction, oraclePriceData);
151
+ const baseAssetAmount = standardizeBaseAssetAmount(maxAmountToTrade, amm.orderStepSize);
151
152
  // Check that directions are the same
152
153
  const sameDirection = isSameDirection(direction, order.direction);
153
154
  if (!sameDirection) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -3,6 +3,7 @@ import {
3
3
  isOneOfVariant,
4
4
  isVariant,
5
5
  PerpMarketAccount,
6
+ AMM,
6
7
  Order,
7
8
  PositionDirection,
8
9
  } from '../types';
@@ -13,6 +14,7 @@ import { getAuctionPrice, isAuctionComplete } from './auction';
13
14
  import {
14
15
  calculateMaxBaseAssetAmountFillable,
15
16
  calculateMaxBaseAssetAmountToTrade,
17
+ calculateUpdatedAMM,
16
18
  } from './amm';
17
19
 
18
20
  export function isOrderRiskIncreasing(user: User, order: Order): boolean {
@@ -202,10 +204,12 @@ export function calculateBaseAssetAmountForAmmToFulfill(
202
204
 
203
205
  const limitPrice = getOptionalLimitPrice(order, oraclePriceData, slot);
204
206
  let baseAssetAmount;
207
+
208
+ const updatedAMM = calculateUpdatedAMM(market.amm, oraclePriceData);
205
209
  if (limitPrice !== undefined) {
206
210
  baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(
207
211
  order,
208
- market,
212
+ updatedAMM,
209
213
  limitPrice,
210
214
  oraclePriceData
211
215
  );
@@ -214,7 +218,7 @@ export function calculateBaseAssetAmountForAmmToFulfill(
214
218
  }
215
219
 
216
220
  const maxBaseAssetAmount = calculateMaxBaseAssetAmountFillable(
217
- market.amm,
221
+ updatedAMM,
218
222
  order.direction
219
223
  );
220
224
 
@@ -223,12 +227,12 @@ export function calculateBaseAssetAmountForAmmToFulfill(
223
227
 
224
228
  export function calculateBaseAssetAmountToFillUpToLimitPrice(
225
229
  order: Order,
226
- market: PerpMarketAccount,
230
+ amm: AMM,
227
231
  limitPrice: BN,
228
232
  oraclePriceData: OraclePriceData
229
233
  ): BN {
230
234
  const [maxAmountToTrade, direction] = calculateMaxBaseAssetAmountToTrade(
231
- market.amm,
235
+ amm,
232
236
  limitPrice,
233
237
  order.direction,
234
238
  oraclePriceData
@@ -236,7 +240,7 @@ export function calculateBaseAssetAmountToFillUpToLimitPrice(
236
240
 
237
241
  const baseAssetAmount = standardizeBaseAssetAmount(
238
242
  maxAmountToTrade,
239
- market.amm.orderStepSize
243
+ amm.orderStepSize
240
244
  );
241
245
 
242
246
  // Check that directions are the same
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.assert = void 0;
4
- function assert(condition, error) {
5
- if (!condition) {
6
- throw new Error(error || 'Unspecified AssertionError');
7
- }
8
- }
9
- exports.assert = assert;
@@ -1,77 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EventList = void 0;
4
- class Node {
5
- constructor(event, next, prev) {
6
- this.event = event;
7
- this.next = next;
8
- this.prev = prev;
9
- }
10
- }
11
- class EventList {
12
- constructor(eventType, maxSize, sortFn, orderDirection) {
13
- this.eventType = eventType;
14
- this.maxSize = maxSize;
15
- this.sortFn = sortFn;
16
- this.orderDirection = orderDirection;
17
- this.size = 0;
18
- }
19
- insert(event) {
20
- this.size++;
21
- const newNode = new Node(event);
22
- if (this.head === undefined) {
23
- this.head = this.tail = newNode;
24
- return;
25
- }
26
- if (this.sortFn(this.head.event, newNode.event) ===
27
- (this.orderDirection === 'asc' ? 'less than' : 'greater than')) {
28
- this.head.prev = newNode;
29
- newNode.next = this.head;
30
- this.head = newNode;
31
- }
32
- else {
33
- let currentNode = this.head;
34
- while (currentNode.next !== undefined &&
35
- this.sortFn(currentNode.next.event, newNode.event) !==
36
- (this.orderDirection === 'asc' ? 'less than' : 'greater than')) {
37
- currentNode = currentNode.next;
38
- }
39
- newNode.next = currentNode.next;
40
- if (currentNode.next !== undefined) {
41
- newNode.next.prev = newNode;
42
- }
43
- currentNode.next = newNode;
44
- newNode.prev = currentNode;
45
- }
46
- if (this.size > this.maxSize) {
47
- this.detach();
48
- }
49
- }
50
- detach() {
51
- const node = this.tail;
52
- if (node.prev !== undefined) {
53
- node.prev.next = node.next;
54
- }
55
- else {
56
- this.head = node.next;
57
- }
58
- if (node.next !== undefined) {
59
- node.next.prev = node.prev;
60
- }
61
- else {
62
- this.tail = node.prev;
63
- }
64
- this.size--;
65
- }
66
- toArray() {
67
- return Array.from(this);
68
- }
69
- *[Symbol.iterator]() {
70
- let node = this.head;
71
- while (node) {
72
- yield node.event;
73
- node = node.next;
74
- }
75
- }
76
- }
77
- exports.EventList = EventList;
@@ -1,157 +0,0 @@
1
- 'use strict';
2
- var __awaiter =
3
- (this && this.__awaiter) ||
4
- function (thisArg, _arguments, P, generator) {
5
- function adopt(value) {
6
- return value instanceof P
7
- ? value
8
- : new P(function (resolve) {
9
- resolve(value);
10
- });
11
- }
12
- return new (P || (P = Promise))(function (resolve, reject) {
13
- function fulfilled(value) {
14
- try {
15
- step(generator.next(value));
16
- } catch (e) {
17
- reject(e);
18
- }
19
- }
20
- function rejected(value) {
21
- try {
22
- step(generator['throw'](value));
23
- } catch (e) {
24
- reject(e);
25
- }
26
- }
27
- function step(result) {
28
- result.done
29
- ? resolve(result.value)
30
- : adopt(result.value).then(fulfilled, rejected);
31
- }
32
- step((generator = generator.apply(thisArg, _arguments || [])).next());
33
- });
34
- };
35
- Object.defineProperty(exports, '__esModule', { value: true });
36
- exports.getTokenAddress = void 0;
37
- const anchor_1 = require('@project-serum/anchor');
38
- const __1 = require('..');
39
- const spl_token_1 = require('@solana/spl-token');
40
- const web3_js_1 = require('@solana/web3.js');
41
- const __2 = require('..');
42
- const banks_1 = require('../constants/spotMarkets');
43
- const getTokenAddress = (mintAddress, userPubKey) => {
44
- return spl_token_1.Token.getAssociatedTokenAddress(
45
- new web3_js_1.PublicKey(`ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`),
46
- spl_token_1.TOKEN_PROGRAM_ID,
47
- new web3_js_1.PublicKey(mintAddress),
48
- new web3_js_1.PublicKey(userPubKey)
49
- );
50
- };
51
- exports.getTokenAddress = getTokenAddress;
52
- const main = () =>
53
- __awaiter(void 0, void 0, void 0, function* () {
54
- // Initialize Drift SDK
55
- const sdkConfig = __2.initialize({ env: 'devnet' });
56
- // Set up the Wallet and Provider
57
- const privateKey = process.env.BOT_PRIVATE_KEY; // stored as an array string
58
- const keypair = web3_js_1.Keypair.fromSecretKey(
59
- Uint8Array.from(JSON.parse(privateKey))
60
- );
61
- const wallet = new __1.Wallet(keypair);
62
- // Set up the Connection
63
- const rpcAddress = process.env.RPC_ADDRESS; // can use: https://api.devnet.solana.com for devnet; https://api.mainnet-beta.solana.com for mainnet;
64
- const connection = new web3_js_1.Connection(rpcAddress);
65
- // Set up the Provider
66
- const provider = new anchor_1.AnchorProvider(
67
- connection,
68
- wallet,
69
- anchor_1.AnchorProvider.defaultOptions()
70
- );
71
- // Check SOL Balance
72
- const lamportsBalance = yield connection.getBalance(wallet.publicKey);
73
- console.log('SOL balance:', lamportsBalance / Math.pow(10, 9));
74
- // Misc. other things to set up
75
- const usdcTokenAddress = yield exports.getTokenAddress(
76
- sdkConfig.USDC_MINT_ADDRESS,
77
- wallet.publicKey.toString()
78
- );
79
- // Set up the Drift Clearing House
80
- const clearingHousePublicKey = new web3_js_1.PublicKey(
81
- sdkConfig.DRIFT_PROGRAM_ID
82
- );
83
- const clearingHouse = new __2.ClearingHouse({
84
- connection,
85
- wallet: provider.wallet,
86
- programID: clearingHousePublicKey,
87
- });
88
- yield clearingHouse.subscribe();
89
- // Set up Clearing House user client
90
- const user = new __2.ClearingHouseUser({
91
- clearingHouse,
92
- userAccountPublicKey: yield clearingHouse.getUserAccountPublicKey(),
93
- });
94
- //// Check if clearing house account exists for the current wallet
95
- const userAccountExists = yield user.exists();
96
- if (!userAccountExists) {
97
- //// Create a Clearing House account by Depositing some USDC ($10,000 in this case)
98
- const depositAmount = new anchor_1.BN(10000).mul(__2.QUOTE_PRECISION);
99
- yield clearingHouse.initializeUserAccountAndDepositCollateral(
100
- depositAmount,
101
- yield exports.getTokenAddress(
102
- usdcTokenAddress.toString(),
103
- wallet.publicKey.toString()
104
- ),
105
- banks_1.SpotMarkets['devnet'][0].marketIndex
106
- );
107
- }
108
- yield user.subscribe();
109
- // Get current price
110
- const solMarketInfo = sdkConfig.PERP_MARKETS.find(
111
- (market) => market.baseAssetSymbol === 'SOL'
112
- );
113
- const currentMarketPrice = __2.calculateMarkPrice(
114
- clearingHouse.getMarketAccount(solMarketInfo.marketIndex),
115
- undefined
116
- );
117
- const formattedPrice = __2.convertToNumber(
118
- currentMarketPrice,
119
- __2.PRICE_PRECISION
120
- );
121
- console.log(`Current Market Price is $${formattedPrice}`);
122
- // Estimate the slippage for a $5000 LONG trade
123
- const solMarketAccount = clearingHouse.getMarketAccount(
124
- solMarketInfo.marketIndex
125
- );
126
- const longAmount = new anchor_1.BN(5000).mul(__2.QUOTE_PRECISION);
127
- const slippage = __2.convertToNumber(
128
- __2.calculateTradeSlippage(
129
- __2.PositionDirection.LONG,
130
- longAmount,
131
- solMarketAccount,
132
- 'quote',
133
- undefined
134
- )[0],
135
- __2.PRICE_PRECISION
136
- );
137
- console.log(
138
- `Slippage for a $5000 LONG on the SOL market would be $${slippage}`
139
- );
140
- // Make a $5000 LONG trade
141
- yield clearingHouse.openPosition(
142
- __2.PositionDirection.LONG,
143
- longAmount,
144
- solMarketInfo.marketIndex
145
- );
146
- console.log(`LONGED $5000 SOL`);
147
- // Reduce the position by $2000
148
- const reduceAmount = new anchor_1.BN(2000).mul(__2.QUOTE_PRECISION);
149
- yield clearingHouse.openPosition(
150
- __2.PositionDirection.SHORT,
151
- reduceAmount,
152
- solMarketInfo.marketIndex
153
- );
154
- // Close the rest of the position
155
- yield clearingHouse.closePosition(solMarketInfo.marketIndex);
156
- });
157
- main();
@@ -1,38 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseTokenAccount = void 0;
4
- const spl_token_1 = require("@solana/spl-token");
5
- const web3_js_1 = require("@solana/web3.js");
6
- function parseTokenAccount(data) {
7
- const accountInfo = spl_token_1.AccountLayout.decode(data);
8
- accountInfo.mint = new web3_js_1.PublicKey(accountInfo.mint);
9
- accountInfo.owner = new web3_js_1.PublicKey(accountInfo.owner);
10
- accountInfo.amount = spl_token_1.u64.fromBuffer(accountInfo.amount);
11
- if (accountInfo.delegateOption === 0) {
12
- accountInfo.delegate = null;
13
- // eslint-disable-next-line new-cap
14
- accountInfo.delegatedAmount = new spl_token_1.u64(0);
15
- }
16
- else {
17
- accountInfo.delegate = new web3_js_1.PublicKey(accountInfo.delegate);
18
- accountInfo.delegatedAmount = spl_token_1.u64.fromBuffer(accountInfo.delegatedAmount);
19
- }
20
- accountInfo.isInitialized = accountInfo.state !== 0;
21
- accountInfo.isFrozen = accountInfo.state === 2;
22
- if (accountInfo.isNativeOption === 1) {
23
- accountInfo.rentExemptReserve = spl_token_1.u64.fromBuffer(accountInfo.isNative);
24
- accountInfo.isNative = true;
25
- }
26
- else {
27
- accountInfo.rentExemptReserve = null;
28
- accountInfo.isNative = false;
29
- }
30
- if (accountInfo.closeAuthorityOption === 0) {
31
- accountInfo.closeAuthority = null;
32
- }
33
- else {
34
- accountInfo.closeAuthority = new web3_js_1.PublicKey(accountInfo.closeAuthority);
35
- }
36
- return accountInfo;
37
- }
38
- exports.parseTokenAccount = parseTokenAccount;
package/src/tx/types.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
package/src/tx/utils.js DELETED
@@ -1,17 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.wrapInTx = void 0;
4
- const web3_js_1 = require("@solana/web3.js");
5
- const COMPUTE_UNITS_DEFAULT = 200000;
6
- function wrapInTx(instruction, computeUnits = 600000 // TODO, requires less code change
7
- ) {
8
- const tx = new web3_js_1.Transaction();
9
- if (computeUnits != COMPUTE_UNITS_DEFAULT) {
10
- tx.add(web3_js_1.ComputeBudgetProgram.requestUnits({
11
- units: computeUnits,
12
- additionalFee: 0,
13
- }));
14
- }
15
- return tx.add(instruction);
16
- }
17
- exports.wrapInTx = wrapInTx;
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.findComputeUnitConsumption = void 0;
13
- function findComputeUnitConsumption(programId, connection, txSignature, commitment = 'confirmed') {
14
- return __awaiter(this, void 0, void 0, function* () {
15
- const tx = yield connection.getTransaction(txSignature, { commitment });
16
- const computeUnits = [];
17
- const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of ([0-9]{0,7}) compute units`);
18
- tx.meta.logMessages.forEach((logMessage) => {
19
- const match = logMessage.match(regex);
20
- if (match && match[1]) {
21
- computeUnits.push(match[1]);
22
- }
23
- });
24
- return computeUnits;
25
- });
26
- }
27
- exports.findComputeUnitConsumption = findComputeUnitConsumption;
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getTokenAddress = void 0;
4
- const spl_token_1 = require("@solana/spl-token");
5
- const web3_js_1 = require("@solana/web3.js");
6
- const getTokenAddress = (mintAddress, userPubKey) => {
7
- return spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey(mintAddress), new web3_js_1.PublicKey(userPubKey));
8
- };
9
- exports.getTokenAddress = getTokenAddress;
@@ -1,14 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.promiseTimeout = void 0;
4
- function promiseTimeout(promise, timeoutMs) {
5
- let timeoutId;
6
- const timeoutPromise = new Promise((resolve) => {
7
- timeoutId = setTimeout(() => resolve(null), timeoutMs);
8
- });
9
- return Promise.race([promise, timeoutPromise]).then((result) => {
10
- clearTimeout(timeoutId);
11
- return result;
12
- });
13
- }
14
- exports.promiseTimeout = promiseTimeout;
package/src/util/tps.js DELETED
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.estimateTps = void 0;
13
- function estimateTps(programId, connection, failed) {
14
- return __awaiter(this, void 0, void 0, function* () {
15
- let signatures = yield connection.getSignaturesForAddress(programId, undefined, 'finalized');
16
- if (failed) {
17
- signatures = signatures.filter((signature) => signature.err);
18
- }
19
- const numberOfSignatures = signatures.length;
20
- if (numberOfSignatures === 0) {
21
- return 0;
22
- }
23
- return (numberOfSignatures /
24
- (signatures[0].blockTime - signatures[numberOfSignatures - 1].blockTime));
25
- });
26
- }
27
- exports.estimateTps = estimateTps;