@d8x/perpetuals-sdk 0.0.45 → 0.0.46

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 (40) hide show
  1. package/README.md +12 -0
  2. package/abi/MockTokenSwap.json +186 -0
  3. package/config/defaultConfig.json +36 -10
  4. package/config/mockSwap.json +4 -0
  5. package/config/oldConfig.json +2 -1
  6. package/config/priceFeedConfig.json +18 -0
  7. package/dist/accountTrade.d.ts +1 -0
  8. package/dist/accountTrade.js +31 -7
  9. package/dist/d8XMath.d.ts +6 -0
  10. package/dist/d8XMath.js +19 -1
  11. package/dist/liquidatorTool.d.ts +6 -4
  12. package/dist/liquidatorTool.js +13 -7
  13. package/dist/marketData.d.ts +6 -11
  14. package/dist/marketData.js +59 -41
  15. package/dist/nodeSDKTypes.d.ts +33 -2
  16. package/dist/nodeSDKTypes.js +3 -18
  17. package/dist/orderReferrerTool.d.ts +17 -7
  18. package/dist/orderReferrerTool.js +43 -13
  19. package/dist/perpetualDataHandler.d.ts +46 -6
  20. package/dist/perpetualDataHandler.js +143 -16
  21. package/dist/perpetualEventHandler.d.ts +0 -3
  22. package/dist/perpetualEventHandler.js +0 -3
  23. package/dist/priceFeeds.d.ts +115 -0
  24. package/dist/priceFeeds.js +373 -0
  25. package/dist/triangulator.d.ts +27 -0
  26. package/dist/triangulator.js +107 -0
  27. package/dist/version.d.ts +1 -1
  28. package/dist/version.js +1 -1
  29. package/package.json +1 -1
  30. package/src/accountTrade.ts +31 -8
  31. package/src/d8XMath.ts +18 -0
  32. package/src/liquidatorTool.ts +28 -8
  33. package/src/marketData.ts +66 -41
  34. package/src/nodeSDKTypes.ts +30 -3
  35. package/src/orderReferrerTool.ts +56 -13
  36. package/src/perpetualDataHandler.ts +149 -21
  37. package/src/perpetualEventHandler.ts +0 -3
  38. package/src/priceFeeds.ts +371 -0
  39. package/src/triangulator.ts +105 -0
  40. package/src/version.ts +1 -1
@@ -128,7 +128,7 @@ class MarketData extends perpetualDataHandler_1.default {
128
128
  if (this.proxyContract == null) {
129
129
  throw Error("no proxy contract initialized. Use createProxyInstance().");
130
130
  }
131
- return yield MarketData._exchangeInfo(this.proxyContract, this.poolStaticInfos, this.symbolList);
131
+ return yield MarketData._exchangeInfo(this.proxyContract, this.poolStaticInfos, this.symbolToPerpStaticInfo, this.symbolList, this.priceFeedGetter);
132
132
  });
133
133
  }
134
134
  /**
@@ -319,24 +319,6 @@ class MarketData extends perpetualDataHandler_1.default {
319
319
  };
320
320
  return newPositionRisk;
321
321
  }
322
- /**
323
- * Gets the pool index (in exchangeInfo) corresponding to a given symbol.
324
- * @param symbol Symbol of the form ETH-USD-MATIC
325
- * @returns Pool index
326
- */
327
- getPoolIndexFromSymbol(symbol) {
328
- let pools = this.poolStaticInfos;
329
- let poolId = this.getPoolIdFromSymbol(symbol);
330
- let k = 0;
331
- while (k < pools.length) {
332
- if (pools[k].poolId == poolId) {
333
- // pool found
334
- return k;
335
- }
336
- k++;
337
- }
338
- return -1;
339
- }
340
322
  /**
341
323
  * Gets the wallet balance in the collateral currency corresponding to a given perpetual symbol.
342
324
  * @param address Address to check
@@ -434,12 +416,16 @@ class MarketData extends perpetualDataHandler_1.default {
434
416
  *
435
417
  * @returns mark price
436
418
  */
437
- getMarkPrice(symbol) {
419
+ getMarkPrice(symbol, indexPrices) {
438
420
  return __awaiter(this, void 0, void 0, function* () {
439
421
  if (this.proxyContract == null) {
440
422
  throw Error("no proxy contract initialized. Use createProxyInstance().");
441
423
  }
442
- return yield perpetualDataHandler_1.default._queryPerpetualMarkPrice(symbol, this.symbolToPerpStaticInfo, this.proxyContract);
424
+ if (indexPrices == undefined) {
425
+ let obj = yield this.priceFeedGetter.fetchPricesForPerpetual(symbol);
426
+ indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
427
+ }
428
+ return yield perpetualDataHandler_1.default._queryPerpetualMarkPrice(symbol, this.symbolToPerpStaticInfo, this.proxyContract, indexPrices);
443
429
  });
444
430
  }
445
431
  /**
@@ -462,25 +448,35 @@ class MarketData extends perpetualDataHandler_1.default {
462
448
  *
463
449
  * @returns price (number)
464
450
  */
465
- getPerpetualPrice(symbol, quantity) {
451
+ getPerpetualPrice(symbol, quantity, indexPrices) {
466
452
  return __awaiter(this, void 0, void 0, function* () {
467
453
  if (this.proxyContract == null) {
468
454
  throw Error("no proxy contract initialized. Use createProxyInstance().");
469
455
  }
470
- return yield perpetualDataHandler_1.default._queryPerpetualPrice(symbol, quantity, this.symbolToPerpStaticInfo, this.proxyContract);
456
+ if (indexPrices == undefined) {
457
+ // fetch from API
458
+ let obj = yield this.priceFeedGetter.fetchPricesForPerpetual(symbol);
459
+ indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
460
+ }
461
+ return yield perpetualDataHandler_1.default._queryPerpetualPrice(symbol, quantity, this.symbolToPerpStaticInfo, this.proxyContract, indexPrices);
471
462
  });
472
463
  }
473
464
  /**
474
465
  * Query recent perpetual state from blockchain
475
466
  * @param symbol symbol of the form ETH-USD-MATIC
467
+ * @param indexPrices S2 and S3 prices/isMarketOpen if not provided fetch via REST API
476
468
  * @returns PerpetualState reference
477
469
  */
478
- getPerpetualState(symbol) {
470
+ getPerpetualState(symbol, indexPriceInfo) {
479
471
  return __awaiter(this, void 0, void 0, function* () {
480
472
  if (this.proxyContract == null) {
481
473
  throw Error("no proxy contract initialized. Use createProxyInstance().");
482
474
  }
483
- let state = yield perpetualDataHandler_1.default._queryPerpetualState(symbol, this.symbolToPerpStaticInfo, this.proxyContract);
475
+ if (indexPriceInfo == undefined) {
476
+ let obj = yield this.priceFeedGetter.fetchPricesForPerpetual(symbol);
477
+ indexPriceInfo = [obj.idxPrices[0], obj.idxPrices[1], obj.mktClosed[0], obj.mktClosed[1]];
478
+ }
479
+ let state = yield perpetualDataHandler_1.default._queryPerpetualState(symbol, this.symbolToPerpStaticInfo, this.proxyContract, indexPriceInfo);
484
480
  return state;
485
481
  });
486
482
  }
@@ -505,6 +501,7 @@ class MarketData extends perpetualDataHandler_1.default {
505
501
  S2Symbol: perpInfo.S2Symbol,
506
502
  S3Symbol: perpInfo.S3Symbol,
507
503
  lotSizeBC: perpInfo.lotSizeBC,
504
+ priceIds: perpInfo.priceIds,
508
505
  };
509
506
  return res;
510
507
  }
@@ -587,22 +584,23 @@ class MarketData extends perpetualDataHandler_1.default {
587
584
  return balanceCC - initalMarginCC;
588
585
  });
589
586
  }
590
- getPythIds(symbol) {
591
- return __awaiter(this, void 0, void 0, function* () {
592
- if (this.proxyContract == null) {
593
- throw Error("no proxy contract initialized. Use createProxyInstance().");
594
- }
595
- let perpId = this.getPerpIdFromSymbol(symbol);
596
- let idsB32 = yield this.proxyContract.getPythIds(perpId);
597
- return idsB32.apply((id) => ethers_1.ethers.utils.parseBytes32String(id));
598
- });
599
- }
600
- static _exchangeInfo(_proxyContract, _poolStaticInfos, _symbolList) {
587
+ static _exchangeInfo(_proxyContract, _poolStaticInfos, _symbolToPerpStaticInfo, _symbolList, _priceFeedGetter) {
601
588
  return __awaiter(this, void 0, void 0, function* () {
602
589
  let nestedPerpetualIDs = yield perpetualDataHandler_1.default.getNestedPerpetualIds(_proxyContract);
603
590
  let factory = yield _proxyContract.getOracleFactory();
604
591
  let info = { pools: [], oracleFactoryAddr: factory, proxyAddr: _proxyContract.address };
605
592
  const numPools = nestedPerpetualIDs.length;
593
+ // get all prices
594
+ let allSym = new Set();
595
+ for (let perpSymbol of _symbolToPerpStaticInfo.keys()) {
596
+ let sInfo = _symbolToPerpStaticInfo.get(perpSymbol);
597
+ allSym.add(sInfo.S2Symbol);
598
+ if (sInfo.S3Symbol != '') {
599
+ allSym.add(sInfo.S3Symbol);
600
+ }
601
+ }
602
+ let allSymArr = Array.from(allSym.values());
603
+ let idxPriceMap = yield _priceFeedGetter.fetchPrices(allSymArr);
606
604
  for (var j = 0; j < numPools; j++) {
607
605
  let perpetualIDs = nestedPerpetualIDs[j];
608
606
  let pool = yield _proxyContract.getLiquidityPool(j + 1);
@@ -618,18 +616,37 @@ class MarketData extends perpetualDataHandler_1.default {
618
616
  brokerCollateralLotSize: (0, d8XMath_1.ABK64x64ToFloat)(pool.fBrokerCollateralLotSize),
619
617
  perpetuals: [],
620
618
  };
619
+ let poolSymbol = PoolState.poolSymbol;
621
620
  for (var k = 0; k < perpetualIDs.length; k++) {
622
621
  let perp = yield _proxyContract.getPerpetual(perpetualIDs[k]);
623
- let fIndexS2 = yield _proxyContract.getOraclePrice([perp.S2BaseCCY, perp.S2QuoteCCY]);
624
- let fMidPrice = yield _proxyContract.queryPerpetualPrice(perpetualIDs[k], ethers_1.BigNumber.from(0));
625
- let indexS2 = (0, d8XMath_1.ABK64x64ToFloat)(fIndexS2);
622
+ let symS2 = (0, utils_1.contractSymbolToSymbol)(perp.S2BaseCCY, _symbolList) + "-" + (0, utils_1.contractSymbolToSymbol)(perp.S2QuoteCCY, _symbolList);
623
+ let symS3 = (0, utils_1.contractSymbolToSymbol)(perp.S3BaseCCY, _symbolList) + "-" + (0, utils_1.contractSymbolToSymbol)(perp.S3QuoteCCY, _symbolList);
624
+ let perpSymbol = symS2 + "-" + poolSymbol;
625
+ //console.log("perpsymbol=",perpSymbol);
626
+ let res = idxPriceMap.get(symS2);
627
+ if (res == undefined) {
628
+ throw new Error(`Price for index ${symS2} could not be fetched - config issue`);
629
+ }
630
+ let [indexS2, isS2MktClosed] = [res[0], res[1]];
626
631
  let indexS3 = 1;
632
+ let isS3MktClosed = false;
627
633
  if (perp.eCollateralCurrency == nodeSDKTypes_1.COLLATERAL_CURRENCY_BASE) {
628
634
  indexS3 = indexS2;
629
635
  }
630
636
  else if (perp.eCollateralCurrency == nodeSDKTypes_1.COLLATERAL_CURRENCY_QUANTO) {
631
- indexS3 = (0, d8XMath_1.ABK64x64ToFloat)(yield _proxyContract.getOraclePrice([perp.S3BaseCCY, perp.S3QuoteCCY]));
637
+ res = idxPriceMap.get(symS3);
638
+ if (res == undefined) {
639
+ throw new Error(`Price for index ${symS3} could not be fetched - config issue`);
640
+ }
641
+ else {
642
+ indexS3 = res[0];
643
+ isS3MktClosed = res[1];
644
+ }
632
645
  }
646
+ let fMidPrice = yield _proxyContract.queryPerpetualPrice(perpetualIDs[k], ethers_1.BigNumber.from(0), [
647
+ (0, d8XMath_1.floatToABK64x64)(indexS2),
648
+ (0, d8XMath_1.floatToABK64x64)(indexS3)
649
+ ]);
633
650
  let markPremiumRate = (0, d8XMath_1.ABK64x64ToFloat)(perp.currentMarkPremiumRate.fPrice);
634
651
  let currentFundingRateBps = 1e4 * (0, d8XMath_1.ABK64x64ToFloat)(perp.fCurrentFundingRate);
635
652
  let state = nodeSDKTypes_1.PERP_STATE_STR[perp.state];
@@ -644,7 +661,8 @@ class MarketData extends perpetualDataHandler_1.default {
644
661
  midPrice: (0, d8XMath_1.ABK64x64ToFloat)(fMidPrice),
645
662
  currentFundingRateBps: currentFundingRateBps,
646
663
  openInterestBC: (0, d8XMath_1.ABK64x64ToFloat)(perp.fOpenInterest),
647
- maxPositionBC: (0, d8XMath_1.ABK64x64ToFloat)(perp.fMaxPositionBC),
664
+ maxPositionBC: Infinity,
665
+ isMarketClosed: isS2MktClosed || isS3MktClosed
648
666
  };
649
667
  PoolState.perpetuals.push(PerpetualState);
650
668
  }
@@ -1,9 +1,9 @@
1
1
  import { BigNumber, BigNumberish, BytesLike, ContractTransaction } from "ethers";
2
- export declare const DEFAULT_CONFIG_TESTNET = "../config/defaultConfig.json";
3
- export declare const DEFAULT_CONFIG_MAINNET = "notthereyet";
2
+ export declare const DEFAULT_CONFIG = "../config/defaultConfig.json";
4
3
  export declare const DEFAULT_CONFIG_TESTNET_NAME = "testnet";
5
4
  export declare const DEFAULT_CONFIG_MAINNET_NAME = "mainnet";
6
5
  export declare const ERC20_ABI: any;
6
+ export declare const MOCK_TOKEN_SWAP_ABI: any;
7
7
  export declare const COLLATERAL_CURRENCY_QUOTE = 0;
8
8
  export declare const COLLATERAL_CURRENCY_BASE = 1;
9
9
  export declare const COLLATERAL_CURRENCY_QUANTO = 2;
@@ -28,6 +28,8 @@ export declare const BUY_SIDE = "BUY";
28
28
  export declare const SELL_SIDE = "SELL";
29
29
  export declare const CLOSED_SIDE = "CLOSED";
30
30
  export interface NodeSDKConfig {
31
+ name: string | undefined;
32
+ version: number;
31
33
  nodeURL: string;
32
34
  proxyAddr: string;
33
35
  proxyABILocation: string;
@@ -35,6 +37,7 @@ export interface NodeSDKConfig {
35
37
  limitOrderBookABILocation: string;
36
38
  limitOrderBookFactoryABILocation: string;
37
39
  symbolListLocation: string;
40
+ priceFeedConfigNetwork: string;
38
41
  gasLimit?: number | undefined;
39
42
  }
40
43
  export interface MarginAccount {
@@ -72,6 +75,7 @@ export interface PerpetualStaticInfo {
72
75
  S2Symbol: string;
73
76
  S3Symbol: string;
74
77
  lotSizeBC: number;
78
+ priceIds: string[];
75
79
  }
76
80
  /**
77
81
  * @global
@@ -123,6 +127,7 @@ export interface PerpetualState {
123
127
  currentFundingRateBps: number;
124
128
  openInterestBC: number;
125
129
  maxPositionBC: number;
130
+ isMarketClosed: boolean;
126
131
  }
127
132
  export interface OrderResponse {
128
133
  tx: ContractTransaction;
@@ -172,3 +177,29 @@ export interface SmartContractOrder {
172
177
  createdTimestamp: BigNumberish;
173
178
  submittedBlock: BigNumberish;
174
179
  }
180
+ export interface PriceFeedConfig {
181
+ network: string;
182
+ ids: Array<{
183
+ symbol: string;
184
+ id: string;
185
+ type: string;
186
+ origin: string;
187
+ }>;
188
+ endpoints: Array<{
189
+ type: string;
190
+ endpoint: string;
191
+ }>;
192
+ }
193
+ export interface PriceFeedSubmission {
194
+ symbols: string[];
195
+ priceFeedVaas: string[];
196
+ prices: number[];
197
+ isMarketClosed: boolean[];
198
+ timestamps: number[];
199
+ }
200
+ export interface PriceFeedFormat {
201
+ conf: BigNumber;
202
+ expo: number;
203
+ price: BigNumber;
204
+ publish_time: number;
205
+ }
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CollaterlCCY = exports.CLOSED_SIDE = exports.SELL_SIDE = exports.BUY_SIDE = exports.ORDER_TYPE_STOP_LIMIT = exports.ORDER_TYPE_STOP_MARKET = exports.ORDER_TYPE_MARKET = exports.ORDER_TYPE_LIMIT = exports.MASK_KEEP_POS_LEVERAGE = exports.MASK_STOP_ORDER = exports.MASK_MARKET_ORDER = exports.MASK_LIMIT_ORDER = exports.MASK_CLOSE_ONLY = exports.ORDER_MAX_DURATION_SEC = exports.DECIMALS = exports.MAX_UINT_256 = exports.MAX_64x64 = exports.ONE_64x64 = exports.ZERO_ORDER_ID = exports.ZERO_ADDRESS = exports.PERP_STATE_STR = exports.COLLATERAL_CURRENCY_QUANTO = exports.COLLATERAL_CURRENCY_BASE = exports.COLLATERAL_CURRENCY_QUOTE = exports.ERC20_ABI = exports.DEFAULT_CONFIG_MAINNET_NAME = exports.DEFAULT_CONFIG_TESTNET_NAME = exports.DEFAULT_CONFIG_MAINNET = exports.DEFAULT_CONFIG_TESTNET = void 0;
3
+ exports.CollaterlCCY = exports.CLOSED_SIDE = exports.SELL_SIDE = exports.BUY_SIDE = exports.ORDER_TYPE_STOP_LIMIT = exports.ORDER_TYPE_STOP_MARKET = exports.ORDER_TYPE_MARKET = exports.ORDER_TYPE_LIMIT = exports.MASK_KEEP_POS_LEVERAGE = exports.MASK_STOP_ORDER = exports.MASK_MARKET_ORDER = exports.MASK_LIMIT_ORDER = exports.MASK_CLOSE_ONLY = exports.ORDER_MAX_DURATION_SEC = exports.DECIMALS = exports.MAX_UINT_256 = exports.MAX_64x64 = exports.ONE_64x64 = exports.ZERO_ORDER_ID = exports.ZERO_ADDRESS = exports.PERP_STATE_STR = exports.COLLATERAL_CURRENCY_QUANTO = exports.COLLATERAL_CURRENCY_BASE = exports.COLLATERAL_CURRENCY_QUOTE = exports.MOCK_TOKEN_SWAP_ABI = exports.ERC20_ABI = exports.DEFAULT_CONFIG_MAINNET_NAME = exports.DEFAULT_CONFIG_TESTNET_NAME = exports.DEFAULT_CONFIG = void 0;
4
4
  const ethers_1 = require("ethers");
5
- exports.DEFAULT_CONFIG_TESTNET = "../config/defaultConfig.json";
6
- exports.DEFAULT_CONFIG_MAINNET = "notthereyet";
5
+ exports.DEFAULT_CONFIG = "../config/defaultConfig.json";
7
6
  exports.DEFAULT_CONFIG_TESTNET_NAME = "testnet";
8
7
  exports.DEFAULT_CONFIG_MAINNET_NAME = "mainnet";
9
8
  exports.ERC20_ABI = require("../abi/ERC20.json");
9
+ exports.MOCK_TOKEN_SWAP_ABI = require("../abi/MockTokenSwap.json");
10
10
  exports.COLLATERAL_CURRENCY_QUOTE = 0;
11
11
  exports.COLLATERAL_CURRENCY_BASE = 1;
12
12
  exports.COLLATERAL_CURRENCY_QUANTO = 2;
@@ -36,18 +36,3 @@ var CollaterlCCY;
36
36
  CollaterlCCY[CollaterlCCY["BASE"] = 1] = "BASE";
37
37
  CollaterlCCY[CollaterlCCY["QUANTO"] = 2] = "QUANTO";
38
38
  })(CollaterlCCY = exports.CollaterlCCY || (exports.CollaterlCCY = {}));
39
- /*
40
- t32 flags;
41
- uint24 iPerpetualId;
42
- uint16 brokerFeeTbps;
43
- address traderAddr;
44
- address brokerAddr;
45
- address referrerAddr;
46
- bytes brokerSignature;
47
- int128 fAmount;
48
- int128 fLimitPrice;
49
- int128 fTriggerPrice;
50
- int128 fLeverage; // 0 if deposit and trade separate
51
- uint256 iDeadline;
52
- uint256 createdTimestamp;
53
- */
@@ -1,5 +1,5 @@
1
1
  import { ethers } from "ethers";
2
- import { NodeSDKConfig, Order, PerpetualStaticInfo } from "./nodeSDKTypes";
2
+ import { NodeSDKConfig, Order, PerpetualStaticInfo, PriceFeedSubmission } from "./nodeSDKTypes";
3
3
  import WriteAccessHandler from "./writeAccessHandler";
4
4
  /**
5
5
  * Functions to execute existing conditional orders from the limit order book. This class
@@ -33,8 +33,9 @@ export default class OrderReferrerTool extends WriteAccessHandler {
33
33
  * Executes an order by symbol and ID. This action interacts with the blockchain and incurs gas costs.
34
34
  * @param {string} symbol Symbol of the form ETH-USD-MATIC.
35
35
  * @param {string} orderId ID of the order to be executed.
36
- * @param {string=} referrerAddr Address of the wallet to be credited for executing the order,
37
- * if different from the one submitting this transaction.
36
+ * @param {string=} referrerAddr optional address of the wallet to be credited for executing the order, if different from the one submitting this transaction.
37
+ * @param {number=} nonce optional nonce
38
+ * @param {PriceFeedSubmission=} submission optional signed prices obtained via PriceFeeds::fetchLatestFeedPriceInfoForPerpetual
38
39
  * @example
39
40
  * import { OrderReferrerTool, PerpetualDataHandler, Order } from "@d8x/perpetuals-sdk";
40
41
  * async function main() {
@@ -62,7 +63,7 @@ export default class OrderReferrerTool extends WriteAccessHandler {
62
63
  * main();
63
64
  * @returns Transaction object.
64
65
  */
65
- executeOrder(symbol: string, orderId: string, referrerAddr?: string, nonce?: number): Promise<ethers.ContractTransaction>;
66
+ executeOrder(symbol: string, orderId: string, referrerAddr?: string, nonce?: number, submission?: PriceFeedSubmission): Promise<ethers.ContractTransaction>;
66
67
  /**
67
68
  * All the orders in the order book for a given symbol that are currently open.
68
69
  * @param {string} symbol Symbol of the form ETH-USD-MATIC.
@@ -155,6 +156,8 @@ export default class OrderReferrerTool extends WriteAccessHandler {
155
156
  /**
156
157
  * Check if a conditional order can be executed
157
158
  * @param order order structure
159
+ * @param indexPrices pair of index prices S2 and S3. S3 set to zero if not required. If undefined
160
+ * the function will fetch the latest prices from the REST API
158
161
  * @example
159
162
  * import { OrderReferrerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
160
163
  * async function main() {
@@ -172,8 +175,15 @@ export default class OrderReferrerTool extends WriteAccessHandler {
172
175
  * main();
173
176
  * @returns true if order can be executed for the current state of the perpetuals
174
177
  */
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;
178
+ isTradeable(order: Order, indexPrices?: [number, number]): Promise<boolean>;
179
+ /**
180
+ * Check for a batch of orders on the same perpetual whether they can be traded
181
+ * @param orders orders belonging to 1 perpetual
182
+ * @param indexPrice S2,S3-index prices for the given perpetual. Will fetch prices from REST API
183
+ * if not defined.
184
+ * @returns array of tradeable boolean
185
+ */
186
+ isTradeableBatch(orders: Order[], indexPrices?: [number, number, boolean, boolean]): Promise<boolean[]>;
187
+ static _isTradeable(order: Order, tradePrice: number, markPrice: number, block: number, symbolToPerpInfoMap: Map<string, PerpetualStaticInfo>): boolean;
178
188
  getTransactionCount(blockTag?: ethers.providers.BlockTag): Promise<number>;
179
189
  }
@@ -49,8 +49,9 @@ class OrderReferrerTool extends writeAccessHandler_1.default {
49
49
  * Executes an order by symbol and ID. This action interacts with the blockchain and incurs gas costs.
50
50
  * @param {string} symbol Symbol of the form ETH-USD-MATIC.
51
51
  * @param {string} orderId ID of the order to be executed.
52
- * @param {string=} referrerAddr Address of the wallet to be credited for executing the order,
53
- * if different from the one submitting this transaction.
52
+ * @param {string=} referrerAddr optional address of the wallet to be credited for executing the order, if different from the one submitting this transaction.
53
+ * @param {number=} nonce optional nonce
54
+ * @param {PriceFeedSubmission=} submission optional signed prices obtained via PriceFeeds::fetchLatestFeedPriceInfoForPerpetual
54
55
  * @example
55
56
  * import { OrderReferrerTool, PerpetualDataHandler, Order } from "@d8x/perpetuals-sdk";
56
57
  * async function main() {
@@ -78,7 +79,7 @@ class OrderReferrerTool extends writeAccessHandler_1.default {
78
79
  * main();
79
80
  * @returns Transaction object.
80
81
  */
81
- executeOrder(symbol, orderId, referrerAddr, nonce) {
82
+ executeOrder(symbol, orderId, referrerAddr, nonce, submission) {
82
83
  return __awaiter(this, void 0, void 0, function* () {
83
84
  if (this.proxyContract == null || this.signer == null) {
84
85
  throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
@@ -87,8 +88,16 @@ class OrderReferrerTool extends writeAccessHandler_1.default {
87
88
  if (typeof referrerAddr == "undefined") {
88
89
  referrerAddr = this.traderAddr;
89
90
  }
90
- const options = { gasLimit: this.gasLimit, nonce: nonce };
91
- return yield orderBookSC.executeOrder(orderId, referrerAddr, options);
91
+ if (submission == undefined) {
92
+ submission = yield this.priceFeedGetter.fetchLatestFeedPriceInfoForPerpetual(symbol);
93
+ }
94
+ const options = {
95
+ gasLimit: this.gasLimit,
96
+ nonce: nonce,
97
+ value: this.PRICE_UPDATE_FEE_GWEI * (submission === null || submission === void 0 ? void 0 : submission.priceFeedVaas.length),
98
+ };
99
+ console.log(submission);
100
+ return yield orderBookSC.executeOrder(orderId, referrerAddr, submission === null || submission === void 0 ? void 0 : submission.priceFeedVaas, submission === null || submission === void 0 ? void 0 : submission.timestamps, options);
92
101
  });
93
102
  }
94
103
  /**
@@ -227,6 +236,8 @@ class OrderReferrerTool extends writeAccessHandler_1.default {
227
236
  /**
228
237
  * Check if a conditional order can be executed
229
238
  * @param order order structure
239
+ * @param indexPrices pair of index prices S2 and S3. S3 set to zero if not required. If undefined
240
+ * the function will fetch the latest prices from the REST API
230
241
  * @example
231
242
  * import { OrderReferrerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
232
243
  * async function main() {
@@ -244,18 +255,29 @@ class OrderReferrerTool extends writeAccessHandler_1.default {
244
255
  * main();
245
256
  * @returns true if order can be executed for the current state of the perpetuals
246
257
  */
247
- isTradeable(order) {
258
+ isTradeable(order, indexPrices) {
248
259
  return __awaiter(this, void 0, void 0, function* () {
249
260
  if (this.proxyContract == null) {
250
261
  throw Error("no proxy contract initialized. Use createProxyInstance().");
251
262
  }
252
- let orderPrice = yield perpetualDataHandler_1.default._queryPerpetualPrice(order.symbol, order.quantity, this.symbolToPerpStaticInfo, this.proxyContract);
253
- let markPrice = yield perpetualDataHandler_1.default._queryPerpetualMarkPrice(order.symbol, this.symbolToPerpStaticInfo, this.proxyContract);
263
+ if (indexPrices == undefined) {
264
+ let obj = yield this.priceFeedGetter.fetchPricesForPerpetual(order.symbol);
265
+ indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
266
+ }
267
+ let orderPrice = yield perpetualDataHandler_1.default._queryPerpetualPrice(order.symbol, order.quantity, this.symbolToPerpStaticInfo, this.proxyContract, indexPrices);
268
+ let markPrice = yield perpetualDataHandler_1.default._queryPerpetualMarkPrice(order.symbol, this.symbolToPerpStaticInfo, this.proxyContract, indexPrices);
254
269
  let block = yield this.provider.getBlockNumber();
255
270
  return OrderReferrerTool._isTradeable(order, orderPrice, markPrice, block, this.symbolToPerpStaticInfo);
256
271
  });
257
272
  }
258
- isTradeableBatch(orders) {
273
+ /**
274
+ * Check for a batch of orders on the same perpetual whether they can be traded
275
+ * @param orders orders belonging to 1 perpetual
276
+ * @param indexPrice S2,S3-index prices for the given perpetual. Will fetch prices from REST API
277
+ * if not defined.
278
+ * @returns array of tradeable boolean
279
+ */
280
+ isTradeableBatch(orders, indexPrices) {
259
281
  return __awaiter(this, void 0, void 0, function* () {
260
282
  if (orders.length == 0) {
261
283
  return [];
@@ -266,13 +288,21 @@ class OrderReferrerTool extends writeAccessHandler_1.default {
266
288
  if (orders.filter((o) => o.symbol == orders[0].symbol).length < orders.length) {
267
289
  throw Error("all orders in a batch must have the same symbol");
268
290
  }
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);
291
+ if (indexPrices == undefined) {
292
+ let obj = yield this.priceFeedGetter.fetchPricesForPerpetual(orders[0].symbol);
293
+ indexPrices = [obj.idxPrices[0], obj.idxPrices[1], obj.mktClosed[0], obj.mktClosed[1]];
294
+ }
295
+ if (indexPrices[2] || indexPrices[3]) {
296
+ // market closed
297
+ return orders.map((o) => false);
298
+ }
299
+ let orderPrice = yield Promise.all(orders.map((o) => perpetualDataHandler_1.default._queryPerpetualPrice(o.symbol, o.quantity, this.symbolToPerpStaticInfo, this.proxyContract, [indexPrices[0], indexPrices[1]])));
300
+ let markPrice = yield perpetualDataHandler_1.default._queryPerpetualMarkPrice(orders[0].symbol, this.symbolToPerpStaticInfo, this.proxyContract, [indexPrices[0], indexPrices[1]]);
271
301
  let block = yield this.provider.getBlockNumber();
272
302
  return orders.map((o, idx) => OrderReferrerTool._isTradeable(o, orderPrice[idx], markPrice, block, this.symbolToPerpStaticInfo));
273
303
  });
274
304
  }
275
- static _isTradeable(order, orderPrice, markPrice, block, symbolToPerpInfoMap) {
305
+ static _isTradeable(order, tradePrice, markPrice, block, symbolToPerpInfoMap) {
276
306
  // check expiration date
277
307
  if (order.deadline != undefined && order.deadline < Date.now() / 1000) {
278
308
  return false;
@@ -289,7 +319,7 @@ class OrderReferrerTool extends writeAccessHandler_1.default {
289
319
  return false;
290
320
  }
291
321
  let limitPrice = order.limitPrice;
292
- if ((order.side == nodeSDKTypes_1.BUY_SIDE && orderPrice > limitPrice) || (order.side == nodeSDKTypes_1.SELL_SIDE && orderPrice < limitPrice)) {
322
+ if ((order.side == nodeSDKTypes_1.BUY_SIDE && tradePrice > limitPrice) || (order.side == nodeSDKTypes_1.SELL_SIDE && tradePrice < limitPrice)) {
293
323
  return false;
294
324
  }
295
325
  // do we need to check trigger/stop?
@@ -1,10 +1,12 @@
1
1
  import { ethers, BigNumber } from "ethers";
2
- import { NodeSDKConfig, Order, SmartContractOrder, PerpetualStaticInfo, MarginAccount, PoolStaticInfo, PerpetualState } from "./nodeSDKTypes";
2
+ import { NodeSDKConfig, Order, SmartContractOrder, PerpetualStaticInfo, MarginAccount, PoolStaticInfo, PerpetualState, PriceFeedSubmission } from "./nodeSDKTypes";
3
+ import PriceFeeds from "./priceFeeds";
3
4
  /**
4
5
  * Parent class for MarketData and WriteAccessHandler that handles
5
6
  * common data and chain operations.
6
7
  */
7
8
  export default class PerpetualDataHandler {
9
+ PRICE_UPDATE_FEE_GWEI: number;
8
10
  protected symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>;
9
11
  protected poolStaticInfos: Array<PoolStaticInfo>;
10
12
  protected symbolList: Map<string, string>;
@@ -19,6 +21,7 @@ export default class PerpetualDataHandler {
19
21
  protected nodeURL: string;
20
22
  protected provider: ethers.providers.JsonRpcProvider | null;
21
23
  private signerOrProvider;
24
+ protected priceFeedGetter: PriceFeeds;
22
25
  protected nestedPerpetualIDs: number[][];
23
26
  constructor(config: NodeSDKConfig);
24
27
  protected initContractsAndData(signerOrProvider: ethers.Signer | ethers.providers.Provider): Promise<void>;
@@ -58,13 +61,43 @@ export default class PerpetualDataHandler {
58
61
  */
59
62
  getSymbolFromPerpId(perpId: number): string | undefined;
60
63
  symbol4BToLongSymbol(sym: string): string;
64
+ /**
65
+ * Get PriceFeedSubmission data required for blockchain queries that involve price data, and the corresponding
66
+ * triangulated prices for the indices S2 and S3
67
+ * @param symbol pool symbol of the form "ETH-USD-MATIC"
68
+ * @returns PriceFeedSubmission and prices for S2 and S3. [S2price, 0] if S3 not defined.
69
+ */
70
+ fetchPriceSubmissionInfoForPerpetual(symbol: string): Promise<{
71
+ submission: PriceFeedSubmission;
72
+ pxS2S3: [number, number];
73
+ }>;
74
+ /**
75
+ * Get the symbols required as indices for the given perpetual
76
+ * @param symbol of the form ETH-USD-MATIC, specifying the perpetual
77
+ * @returns name of underlying index prices, e.g. ["MATIC-USD", ""]
78
+ */
79
+ getIndexSymbols(symbol: string): [string, string];
80
+ /**
81
+ * Get the latest prices for a given perpetual from the offchain oracle
82
+ * networks
83
+ * @param symbol perpetual symbol of the form BTC-USD-MATIC
84
+ * @returns array of price feed updates that can be submitted to the smart contract
85
+ * and corresponding price information
86
+ */
87
+ fetchLatestFeedPriceInfo(symbol: string): Promise<PriceFeedSubmission>;
88
+ /**
89
+ * Get list of required pyth price source IDs for given perpetual
90
+ * @param symbol perpetual symbol, e.g., BTC-USD-MATIC
91
+ * @returns list of required pyth price sources for this perpetual
92
+ */
93
+ getPriceIds(symbol: string): string[];
61
94
  protected static _getSymbolFromPoolId(poolId: number, staticInfos: PoolStaticInfo[]): string;
62
95
  protected static _getPoolIdFromSymbol(symbol: string, staticInfos: PoolStaticInfo[]): number;
63
96
  static getNestedPerpetualIds(_proxyContract: ethers.Contract): Promise<number[][]>;
64
97
  static getMarginAccount(traderAddr: string, symbol: string, symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>, _proxyContract: ethers.Contract): Promise<MarginAccount>;
65
- protected static _queryPerpetualPrice(symbol: string, tradeAmount: number, symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>, _proxyContract: ethers.Contract): Promise<number>;
66
- protected static _queryPerpetualMarkPrice(symbol: string, symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>, _proxyContract: ethers.Contract): Promise<number>;
67
- protected static _queryPerpetualState(symbol: string, symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>, _proxyContract: ethers.Contract): Promise<PerpetualState>;
98
+ protected static _queryPerpetualPrice(symbol: string, tradeAmount: number, symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>, _proxyContract: ethers.Contract, indexPrices: [number, number]): Promise<number>;
99
+ protected static _queryPerpetualMarkPrice(symbol: string, symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>, _proxyContract: ethers.Contract, indexPrices: [number, number]): Promise<number>;
100
+ protected static _queryPerpetualState(symbol: string, symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>, _proxyContract: ethers.Contract, indexPrices: [number, number, boolean, boolean]): Promise<PerpetualState>;
68
101
  /**
69
102
  * Liquidation price
70
103
  * @param symbol symbol of the form BTC-USD-MATIC
@@ -113,10 +146,10 @@ export default class PerpetualDataHandler {
113
146
  protected static _getMinimalPositionSize(symbol: string, symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>): number;
114
147
  /**
115
148
  * Read config file into NodeSDKConfig interface
116
- * @param fileLocation json-file with required variables for config
149
+ * @param configNameOrfileLocation json-file with required variables for config, or name of a default known config
117
150
  * @returns NodeSDKConfig
118
151
  */
119
- static readSDKConfig(fileLocation: string): NodeSDKConfig;
152
+ static readSDKConfig(configNameOrFileLocation: string, version?: string): NodeSDKConfig;
120
153
  /**
121
154
  * Get the ABI of a function in a given contract
122
155
  * @param contract A contract instance, e.g. this.proxyContract
@@ -124,4 +157,11 @@ export default class PerpetualDataHandler {
124
157
  * @returns Function ABI as a single JSON string
125
158
  */
126
159
  protected static _getABIFromContract(contract: ethers.Contract, functionName: string): string;
160
+ /**
161
+ * Gets the pool index (in exchangeInfo) corresponding to a given symbol.
162
+ * @param symbol Symbol of the form ETH-USD-MATIC
163
+ * @returns Pool index
164
+ */
165
+ getPoolIndexFromSymbol(symbol: string): number;
166
+ getMarginTokenFromSymbol(symbol: string): string | undefined;
127
167
  }