@d8x/perpetuals-sdk 0.0.33 → 0.0.35

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.
@@ -1,4 +1,4 @@
1
- import { ExchangeInfo, NodeSDKConfig, MarginAccount, PerpetualState, PoolStaticInfo } from "./nodeSDKTypes";
1
+ import { ExchangeInfo, NodeSDKConfig, MarginAccount, PerpetualState, PoolStaticInfo, PerpetualStaticInfo } from "./nodeSDKTypes";
2
2
  import { ethers } from "ethers";
3
3
  import PerpetualDataHandler from "./perpetualDataHandler";
4
4
  import { SmartContractOrder, Order } from "./nodeSDKTypes";
@@ -198,6 +198,13 @@ export default class MarketData extends PerpetualDataHandler {
198
198
  * @returns PerpetualState reference
199
199
  */
200
200
  getPerpetualState(symbol: string): Promise<PerpetualState>;
201
+ /**
202
+ * Query perpetual static info.
203
+ * This information is queried once at createProxyInstance-time and remains static after that.
204
+ * @param symbol symbol of the form ETH-USD-MATIC
205
+ * @returns PerpetualStaticInfo copy.
206
+ */
207
+ getPerpetualStaticInfo(symbol: string): PerpetualStaticInfo;
201
208
  /**
202
209
  * get the current mid-price for a perpetual
203
210
  * @param symbol symbol of the form ETH-USD-MATIC
@@ -373,6 +373,30 @@ class MarketData extends perpetualDataHandler_1.default {
373
373
  return state;
374
374
  });
375
375
  }
376
+ /**
377
+ * Query perpetual static info.
378
+ * This information is queried once at createProxyInstance-time and remains static after that.
379
+ * @param symbol symbol of the form ETH-USD-MATIC
380
+ * @returns PerpetualStaticInfo copy.
381
+ */
382
+ getPerpetualStaticInfo(symbol) {
383
+ let perpInfo = this.symbolToPerpStaticInfo.get(symbol);
384
+ if (perpInfo == undefined) {
385
+ throw Error(`Perpetual with symbol ${symbol} not found. Check symbol or use createProxyInstance().`);
386
+ }
387
+ // return new copy, not a reference
388
+ let res = {
389
+ id: perpInfo.id,
390
+ limitOrderBookAddr: perpInfo.limitOrderBookAddr,
391
+ initialMarginRate: perpInfo.initialMarginRate,
392
+ maintenanceMarginRate: perpInfo.maintenanceMarginRate,
393
+ collateralCurrencyType: perpInfo.collateralCurrencyType,
394
+ S2Symbol: perpInfo.S2Symbol,
395
+ S3Symbol: perpInfo.S3Symbol,
396
+ lotSizeBC: perpInfo.lotSizeBC,
397
+ };
398
+ return res;
399
+ }
376
400
  /**
377
401
  * get the current mid-price for a perpetual
378
402
  * @param symbol symbol of the form ETH-USD-MATIC
@@ -1,5 +1,5 @@
1
1
  import WriteAccessHandler from "./writeAccessHandler";
2
- import { NodeSDKConfig, Order } from "./nodeSDKTypes";
2
+ import { NodeSDKConfig, Order, PerpetualStaticInfo } from "./nodeSDKTypes";
3
3
  import { ethers } from "ethers";
4
4
  /**
5
5
  * Functions to execute existing conditional orders from the limit order book. This class
@@ -8,6 +8,7 @@ import { ethers } from "ethers";
8
8
  * @extends WriteAccessHandler
9
9
  */
10
10
  export default class OrderReferrerTool extends WriteAccessHandler {
11
+ static BLOCK_DELAY: number;
11
12
  /**
12
13
  * Constructor.
13
14
  * @param {NodeSDKConfig} config Configuration object, see PerpetualDataHandler.readSDKConfig.
@@ -172,5 +173,7 @@ export default class OrderReferrerTool extends WriteAccessHandler {
172
173
  * @returns true if order can be executed for the current state of the perpetuals
173
174
  */
174
175
  isTradeable(order: Order): Promise<boolean>;
176
+ isTradeableBatch(orders: Order[]): Promise<boolean[]>;
177
+ static _isTradeable(order: Order, orderPrice: number, markPrice: number, block: number, symbolToPerpInfoMap: Map<string, PerpetualStaticInfo>): boolean;
175
178
  getTransactionCount(blockTag?: ethers.providers.BlockTag): Promise<number>;
176
179
  }
@@ -249,38 +249,61 @@ class OrderReferrerTool extends writeAccessHandler_1.default {
249
249
  if (this.proxyContract == null) {
250
250
  throw Error("no proxy contract initialized. Use createProxyInstance().");
251
251
  }
252
- // check expiration date
253
- if (order.deadline != undefined && order.deadline < Date.now() / 1000) {
254
- return false;
255
- }
256
- // check order size
257
- if (order.quantity < perpetualDataHandler_1.default._getLotSize(order.symbol, this.symbolToPerpStaticInfo)) {
258
- return false;
259
- }
260
- // check limit price, which may be undefined if it's an unrestricted market order
261
- if (order.limitPrice == undefined) {
262
- order.limitPrice = order.side == nodeSDKTypes_1.BUY_SIDE ? Infinity : 0;
263
- }
264
252
  let orderPrice = yield perpetualDataHandler_1.default._queryPerpetualPrice(order.symbol, order.quantity, this.symbolToPerpStaticInfo, this.proxyContract);
265
- if ((order.side == nodeSDKTypes_1.BUY_SIDE && orderPrice > order.limitPrice) ||
266
- (order.side == nodeSDKTypes_1.SELL_SIDE && orderPrice < order.limitPrice)) {
267
- return false;
253
+ let markPrice = yield perpetualDataHandler_1.default._queryPerpetualMarkPrice(order.symbol, this.symbolToPerpStaticInfo, this.proxyContract);
254
+ let block = yield this.provider.getBlockNumber();
255
+ return OrderReferrerTool._isTradeable(order, orderPrice, markPrice, block, this.symbolToPerpStaticInfo);
256
+ });
257
+ }
258
+ isTradeableBatch(orders) {
259
+ return __awaiter(this, void 0, void 0, function* () {
260
+ if (orders.length == 0) {
261
+ return [];
268
262
  }
269
- // do we need to check trigger/stop?
270
- if (order.stopPrice == undefined) {
271
- // nothing to check, order is tradeable
272
- return true;
263
+ if (this.proxyContract == null) {
264
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
273
265
  }
274
- // we need the mark price to check
275
- let markPrice = yield perpetualDataHandler_1.default._queryPerpetualMarkPrice(order.symbol, this.symbolToPerpStaticInfo, this.proxyContract);
276
- if ((order.side == nodeSDKTypes_1.BUY_SIDE && markPrice < order.stopPrice) ||
277
- (order.side == nodeSDKTypes_1.SELL_SIDE && markPrice > order.stopPrice)) {
278
- return false;
266
+ if (orders.filter((o) => o.symbol == orders[0].symbol).length < orders.length) {
267
+ throw Error("all orders in a batch must have the same symbol");
279
268
  }
280
- // all checks passed -> order is tradeable
281
- return true;
269
+ let orderPrice = yield Promise.all(orders.map((o) => perpetualDataHandler_1.default._queryPerpetualPrice(o.symbol, o.quantity, this.symbolToPerpStaticInfo, this.proxyContract)));
270
+ let markPrice = yield perpetualDataHandler_1.default._queryPerpetualMarkPrice(orders[0].symbol, this.symbolToPerpStaticInfo, this.proxyContract);
271
+ let block = yield this.provider.getBlockNumber();
272
+ return orders.map((o, idx) => OrderReferrerTool._isTradeable(o, orderPrice[idx], markPrice, block, this.symbolToPerpStaticInfo));
282
273
  });
283
274
  }
275
+ static _isTradeable(order, orderPrice, markPrice, block, symbolToPerpInfoMap) {
276
+ // check expiration date
277
+ if (order.deadline != undefined && order.deadline < Date.now() / 1000) {
278
+ return false;
279
+ }
280
+ if (order.submittedBlock == undefined || order.submittedBlock + this.BLOCK_DELAY > block) {
281
+ return false;
282
+ }
283
+ // check order size
284
+ if (order.quantity < perpetualDataHandler_1.default._getLotSize(order.symbol, symbolToPerpInfoMap)) {
285
+ return false;
286
+ }
287
+ // check limit price, which may be undefined if it's an unrestricted market order
288
+ if (order.limitPrice == undefined) {
289
+ order.limitPrice = order.side == nodeSDKTypes_1.BUY_SIDE ? Infinity : 0;
290
+ }
291
+ if ((order.side == nodeSDKTypes_1.BUY_SIDE && orderPrice > order.limitPrice) ||
292
+ (order.side == nodeSDKTypes_1.SELL_SIDE && orderPrice < order.limitPrice)) {
293
+ return false;
294
+ }
295
+ // do we need to check trigger/stop?
296
+ if (order.stopPrice == undefined) {
297
+ // nothing to check, order is tradeable
298
+ return true;
299
+ }
300
+ if ((order.side == nodeSDKTypes_1.BUY_SIDE && markPrice < order.stopPrice) ||
301
+ (order.side == nodeSDKTypes_1.SELL_SIDE && markPrice > order.stopPrice)) {
302
+ return false;
303
+ }
304
+ // all checks passed -> order is tradeable
305
+ return true;
306
+ }
284
307
  getTransactionCount(blockTag) {
285
308
  return __awaiter(this, void 0, void 0, function* () {
286
309
  if (this.signer == null) {
@@ -291,3 +314,4 @@ class OrderReferrerTool extends writeAccessHandler_1.default {
291
314
  }
292
315
  }
293
316
  exports.default = OrderReferrerTool;
317
+ OrderReferrerTool.BLOCK_DELAY = 2;
@@ -84,7 +84,7 @@ export default class PerpetualDataHandler {
84
84
  */
85
85
  protected static symbolToPerpetualId(symbol: string, symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>): number;
86
86
  /**
87
- * Find the symbol ("ETH-USD-MATC") of the given perpetual id
87
+ * Find the long symbol ("ETH-USD-MATIC") of the given perpetual id
88
88
  * @param id perpetual id
89
89
  * @param symbolToPerpStaticInfo map that contains the bytes4-symbol to PerpetualStaticInfo
90
90
  * @returns symbol string or undefined
@@ -174,10 +174,7 @@ class PerpetualDataHandler {
174
174
  * @param perpId perpetual id
175
175
  */
176
176
  getSymbolFromPerpId(perpId) {
177
- let symbol4Bytes = PerpetualDataHandler.perpetualIdToSymbol(perpId, this.symbolToPerpStaticInfo);
178
- if (symbol4Bytes == undefined) {
179
- return undefined;
180
- }
177
+ return PerpetualDataHandler.perpetualIdToSymbol(perpId, this.symbolToPerpStaticInfo);
181
178
  }
182
179
  symbol4BToLongSymbol(sym) {
183
180
  return (0, utils_1.symbol4BToLongSymbol)(sym, this.symbolList);
@@ -354,7 +351,7 @@ class PerpetualDataHandler {
354
351
  return id;
355
352
  }
356
353
  /**
357
- * Find the symbol ("ETH-USD-MATC") of the given perpetual id
354
+ * Find the long symbol ("ETH-USD-MATIC") of the given perpetual id
358
355
  * @param id perpetual id
359
356
  * @param symbolToPerpStaticInfo map that contains the bytes4-symbol to PerpetualStaticInfo
360
357
  * @returns symbol string or undefined
package/package.json CHANGED
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "name": "@d8x/perpetuals-sdk",
29
29
  "description": "Node TypeScript SDK for D8X Perpetual Futures",
30
- "version": "0.0.33",
30
+ "version": "0.0.35",
31
31
  "main": "./dist/index.js",
32
32
  "types": "./dist/index.d.ts",
33
33
  "directories": {
package/src/marketData.ts CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  CLOSED_SIDE,
14
14
  SELL_SIDE,
15
15
  CollaterlCCY,
16
+ PerpetualStaticInfo,
16
17
  } from "./nodeSDKTypes";
17
18
  import { BigNumber, BytesLike, ethers } from "ethers";
18
19
  import {
@@ -456,6 +457,31 @@ export default class MarketData extends PerpetualDataHandler {
456
457
  return state;
457
458
  }
458
459
 
460
+ /**
461
+ * Query perpetual static info.
462
+ * This information is queried once at createProxyInstance-time and remains static after that.
463
+ * @param symbol symbol of the form ETH-USD-MATIC
464
+ * @returns PerpetualStaticInfo copy.
465
+ */
466
+ public getPerpetualStaticInfo(symbol: string): PerpetualStaticInfo {
467
+ let perpInfo = this.symbolToPerpStaticInfo.get(symbol);
468
+ if (perpInfo == undefined) {
469
+ throw Error(`Perpetual with symbol ${symbol} not found. Check symbol or use createProxyInstance().`);
470
+ }
471
+ // return new copy, not a reference
472
+ let res: PerpetualStaticInfo = {
473
+ id: perpInfo.id,
474
+ limitOrderBookAddr: perpInfo.limitOrderBookAddr,
475
+ initialMarginRate: perpInfo.initialMarginRate,
476
+ maintenanceMarginRate: perpInfo.maintenanceMarginRate,
477
+ collateralCurrencyType: perpInfo.collateralCurrencyType,
478
+ S2Symbol: perpInfo.S2Symbol,
479
+ S3Symbol: perpInfo.S3Symbol,
480
+ lotSizeBC: perpInfo.lotSizeBC,
481
+ };
482
+ return res;
483
+ }
484
+
459
485
  /**
460
486
  * get the current mid-price for a perpetual
461
487
  * @param symbol symbol of the form ETH-USD-MATIC
@@ -1,5 +1,13 @@
1
1
  import WriteAccessHandler from "./writeAccessHandler";
2
- import { BUY_SIDE, NodeSDKConfig, Order, SELL_SIDE, ZERO_ADDRESS, ZERO_ORDER_ID } from "./nodeSDKTypes";
2
+ import {
3
+ BUY_SIDE,
4
+ NodeSDKConfig,
5
+ Order,
6
+ PerpetualStaticInfo,
7
+ SELL_SIDE,
8
+ ZERO_ADDRESS,
9
+ ZERO_ORDER_ID,
10
+ } from "./nodeSDKTypes";
3
11
  import { BigNumber, ethers } from "ethers";
4
12
  import PerpetualDataHandler from "./perpetualDataHandler";
5
13
 
@@ -10,6 +18,7 @@ import PerpetualDataHandler from "./perpetualDataHandler";
10
18
  * @extends WriteAccessHandler
11
19
  */
12
20
  export default class OrderReferrerTool extends WriteAccessHandler {
21
+ static BLOCK_DELAY = 2;
13
22
  /**
14
23
  * Constructor.
15
24
  * @param {NodeSDKConfig} config Configuration object, see PerpetualDataHandler.readSDKConfig.
@@ -236,24 +245,77 @@ export default class OrderReferrerTool extends WriteAccessHandler {
236
245
  if (this.proxyContract == null) {
237
246
  throw Error("no proxy contract initialized. Use createProxyInstance().");
238
247
  }
248
+ let orderPrice = await PerpetualDataHandler._queryPerpetualPrice(
249
+ order.symbol,
250
+ order.quantity,
251
+ this.symbolToPerpStaticInfo,
252
+ this.proxyContract
253
+ );
254
+ let markPrice = await PerpetualDataHandler._queryPerpetualMarkPrice(
255
+ order.symbol,
256
+ this.symbolToPerpStaticInfo,
257
+ this.proxyContract
258
+ );
259
+ let block = await this.provider!.getBlockNumber();
260
+ return OrderReferrerTool._isTradeable(order, orderPrice, markPrice, block, this.symbolToPerpStaticInfo);
261
+ }
262
+
263
+ public async isTradeableBatch(orders: Order[]): Promise<boolean[]> {
264
+ if (orders.length == 0) {
265
+ return [];
266
+ }
267
+ if (this.proxyContract == null) {
268
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
269
+ }
270
+ if (orders.filter((o) => o.symbol == orders[0].symbol).length < orders.length) {
271
+ throw Error("all orders in a batch must have the same symbol");
272
+ }
273
+ let orderPrice = await Promise.all(
274
+ orders.map((o) =>
275
+ PerpetualDataHandler._queryPerpetualPrice(
276
+ o.symbol,
277
+ o.quantity,
278
+ this.symbolToPerpStaticInfo,
279
+ this.proxyContract!
280
+ )
281
+ )
282
+ );
283
+ let markPrice = await PerpetualDataHandler._queryPerpetualMarkPrice(
284
+ orders[0].symbol,
285
+ this.symbolToPerpStaticInfo,
286
+ this.proxyContract
287
+ );
288
+ let block = await this.provider!.getBlockNumber();
289
+ return orders.map((o, idx) =>
290
+ OrderReferrerTool._isTradeable(o, orderPrice[idx], markPrice, block, this.symbolToPerpStaticInfo)
291
+ );
292
+ }
293
+
294
+ public static _isTradeable(
295
+ order: Order,
296
+ orderPrice: number,
297
+ markPrice: number,
298
+ block: number,
299
+ symbolToPerpInfoMap: Map<string, PerpetualStaticInfo>
300
+ ): boolean {
239
301
  // check expiration date
240
302
  if (order.deadline != undefined && order.deadline < Date.now() / 1000) {
241
303
  return false;
242
304
  }
305
+
306
+ if (order.submittedBlock == undefined || order.submittedBlock + this.BLOCK_DELAY > block) {
307
+ return false;
308
+ }
309
+
243
310
  // check order size
244
- if (order.quantity < PerpetualDataHandler._getLotSize(order.symbol, this.symbolToPerpStaticInfo)) {
311
+ if (order.quantity < PerpetualDataHandler._getLotSize(order.symbol, symbolToPerpInfoMap)) {
245
312
  return false;
246
313
  }
247
314
  // check limit price, which may be undefined if it's an unrestricted market order
248
315
  if (order.limitPrice == undefined) {
249
316
  order.limitPrice = order.side == BUY_SIDE ? Infinity : 0;
250
317
  }
251
- let orderPrice = await PerpetualDataHandler._queryPerpetualPrice(
252
- order.symbol,
253
- order.quantity,
254
- this.symbolToPerpStaticInfo,
255
- this.proxyContract
256
- );
318
+
257
319
  if (
258
320
  (order.side == BUY_SIDE && orderPrice > order.limitPrice) ||
259
321
  (order.side == SELL_SIDE && orderPrice < order.limitPrice)
@@ -265,12 +327,6 @@ export default class OrderReferrerTool extends WriteAccessHandler {
265
327
  // nothing to check, order is tradeable
266
328
  return true;
267
329
  }
268
- // we need the mark price to check
269
- let markPrice = await PerpetualDataHandler._queryPerpetualMarkPrice(
270
- order.symbol,
271
- this.symbolToPerpStaticInfo,
272
- this.proxyContract
273
- );
274
330
  if (
275
331
  (order.side == BUY_SIDE && markPrice < order.stopPrice) ||
276
332
  (order.side == SELL_SIDE && markPrice > order.stopPrice)
@@ -234,10 +234,7 @@ export default class PerpetualDataHandler {
234
234
  * @param perpId perpetual id
235
235
  */
236
236
  public getSymbolFromPerpId(perpId: number): string | undefined {
237
- let symbol4Bytes = PerpetualDataHandler.perpetualIdToSymbol(perpId, this.symbolToPerpStaticInfo);
238
- if (symbol4Bytes == undefined) {
239
- return undefined;
240
- }
237
+ return PerpetualDataHandler.perpetualIdToSymbol(perpId, this.symbolToPerpStaticInfo);
241
238
  }
242
239
 
243
240
  public symbol4BToLongSymbol(sym: string): string {
@@ -449,7 +446,7 @@ export default class PerpetualDataHandler {
449
446
  }
450
447
 
451
448
  /**
452
- * Find the symbol ("ETH-USD-MATC") of the given perpetual id
449
+ * Find the long symbol ("ETH-USD-MATIC") of the given perpetual id
453
450
  * @param id perpetual id
454
451
  * @param symbolToPerpStaticInfo map that contains the bytes4-symbol to PerpetualStaticInfo
455
452
  * @returns symbol string or undefined