@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.
- package/README.md +12 -0
- package/abi/MockTokenSwap.json +186 -0
- package/config/defaultConfig.json +36 -10
- package/config/mockSwap.json +4 -0
- package/config/oldConfig.json +2 -1
- package/config/priceFeedConfig.json +18 -0
- package/dist/accountTrade.d.ts +1 -0
- package/dist/accountTrade.js +31 -7
- package/dist/d8XMath.d.ts +6 -0
- package/dist/d8XMath.js +19 -1
- package/dist/liquidatorTool.d.ts +6 -4
- package/dist/liquidatorTool.js +13 -7
- package/dist/marketData.d.ts +6 -11
- package/dist/marketData.js +59 -41
- package/dist/nodeSDKTypes.d.ts +33 -2
- package/dist/nodeSDKTypes.js +3 -18
- package/dist/orderReferrerTool.d.ts +17 -7
- package/dist/orderReferrerTool.js +43 -13
- package/dist/perpetualDataHandler.d.ts +46 -6
- package/dist/perpetualDataHandler.js +143 -16
- package/dist/perpetualEventHandler.d.ts +0 -3
- package/dist/perpetualEventHandler.js +0 -3
- package/dist/priceFeeds.d.ts +115 -0
- package/dist/priceFeeds.js +373 -0
- package/dist/triangulator.d.ts +27 -0
- package/dist/triangulator.js +107 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/accountTrade.ts +31 -8
- package/src/d8XMath.ts +18 -0
- package/src/liquidatorTool.ts +28 -8
- package/src/marketData.ts +66 -41
- package/src/nodeSDKTypes.ts +30 -3
- package/src/orderReferrerTool.ts +56 -13
- package/src/perpetualDataHandler.ts +149 -21
- package/src/perpetualEventHandler.ts +0 -3
- package/src/priceFeeds.ts +371 -0
- package/src/triangulator.ts +105 -0
- package/src/version.ts +1 -1
package/dist/marketData.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
624
|
-
let
|
|
625
|
-
let
|
|
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
|
-
|
|
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:
|
|
664
|
+
maxPositionBC: Infinity,
|
|
665
|
+
isMarketClosed: isS2MktClosed || isS3MktClosed
|
|
648
666
|
};
|
|
649
667
|
PoolState.perpetuals.push(PerpetualState);
|
|
650
668
|
}
|
package/dist/nodeSDKTypes.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BigNumber, BigNumberish, BytesLike, ContractTransaction } from "ethers";
|
|
2
|
-
export declare const
|
|
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
|
+
}
|
package/dist/nodeSDKTypes.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
|
37
|
-
*
|
|
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
|
-
|
|
177
|
-
|
|
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
|
|
53
|
-
*
|
|
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
|
-
|
|
91
|
-
|
|
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
|
-
|
|
253
|
-
|
|
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
|
-
|
|
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
|
-
|
|
270
|
-
|
|
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,
|
|
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 &&
|
|
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
|
|
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(
|
|
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
|
}
|