@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/src/liquidatorTool.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import WriteAccessHandler from "./writeAccessHandler";
|
|
2
|
-
import { NodeSDKConfig } from "./nodeSDKTypes";
|
|
2
|
+
import { NodeSDKConfig, PriceFeedSubmission } from "./nodeSDKTypes";
|
|
3
3
|
import { ethers } from "ethers";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -37,6 +37,7 @@ export default class LiquidatorTool extends WriteAccessHandler {
|
|
|
37
37
|
* @param {string} symbol Symbol of the form ETH-USD-MATIC.
|
|
38
38
|
* @param {string} traderAddr Address of the trader to be liquidated.
|
|
39
39
|
* @param {string=} liquidatorAddr Address to be credited if the liquidation succeeds.
|
|
40
|
+
* @param {PriceFeedSubmission} priceFeedData optional. VAA and timestamps for oracle. If not provided will query from REST API.
|
|
40
41
|
* Defaults to the wallet used to execute the liquidation.
|
|
41
42
|
* @example
|
|
42
43
|
* import { LiquidatorTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
@@ -59,7 +60,8 @@ export default class LiquidatorTool extends WriteAccessHandler {
|
|
|
59
60
|
public async liquidateTrader(
|
|
60
61
|
symbol: string,
|
|
61
62
|
traderAddr: string,
|
|
62
|
-
liquidatorAddr: string = ""
|
|
63
|
+
liquidatorAddr: string = "",
|
|
64
|
+
priceFeedData?: PriceFeedSubmission
|
|
63
65
|
): Promise<ethers.ContractTransaction> {
|
|
64
66
|
// this operation spends gas, so signer is required
|
|
65
67
|
if (this.proxyContract == null || this.signer == null) {
|
|
@@ -70,7 +72,13 @@ export default class LiquidatorTool extends WriteAccessHandler {
|
|
|
70
72
|
liquidatorAddr = this.traderAddr;
|
|
71
73
|
}
|
|
72
74
|
let perpID = LiquidatorTool.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
|
|
73
|
-
|
|
75
|
+
if (priceFeedData == undefined) {
|
|
76
|
+
priceFeedData = await this.fetchLatestFeedPriceInfo(symbol);
|
|
77
|
+
}
|
|
78
|
+
return await this._liquidateByAMM(perpID, liquidatorAddr, traderAddr, priceFeedData, {
|
|
79
|
+
gasLimit: this.gasLimit,
|
|
80
|
+
value: this.PRICE_UPDATE_FEE_GWEI * priceFeedData.priceFeedVaas.length,
|
|
81
|
+
});
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
/**
|
|
@@ -116,13 +124,25 @@ export default class LiquidatorTool extends WriteAccessHandler {
|
|
|
116
124
|
* @param perpetualId Perpetual id.
|
|
117
125
|
* @param liquidatorAddr Address to be credited for the liquidation.
|
|
118
126
|
* @param traderAddr Address of the trader to be liquidated.
|
|
119
|
-
* @param
|
|
127
|
+
* @param priceFeedData contains VAA and timestamps required
|
|
128
|
+
* @param options E.g., Gas limit, fee.
|
|
120
129
|
* @ignore
|
|
121
130
|
*/
|
|
122
|
-
public async _liquidateByAMM(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
131
|
+
public async _liquidateByAMM(
|
|
132
|
+
perpetualId: number,
|
|
133
|
+
liquidatorAddr: string,
|
|
134
|
+
traderAddr: string,
|
|
135
|
+
priceFeedData: PriceFeedSubmission,
|
|
136
|
+
options: object
|
|
137
|
+
) {
|
|
138
|
+
return await this.proxyContract!.liquidateByAMM(
|
|
139
|
+
perpetualId,
|
|
140
|
+
liquidatorAddr,
|
|
141
|
+
traderAddr,
|
|
142
|
+
priceFeedData.priceFeedVaas,
|
|
143
|
+
priceFeedData.timestamps,
|
|
144
|
+
options
|
|
145
|
+
);
|
|
126
146
|
}
|
|
127
147
|
|
|
128
148
|
/**
|
package/src/marketData.ts
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
ZERO_ADDRESS,
|
|
33
33
|
} from "./nodeSDKTypes";
|
|
34
34
|
import PerpetualDataHandler from "./perpetualDataHandler";
|
|
35
|
+
import PriceFeeds from "./priceFeeds";
|
|
35
36
|
import { contractSymbolToSymbol, toBytes4 } from "./utils";
|
|
36
37
|
|
|
37
38
|
/**
|
|
@@ -145,7 +146,7 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
145
146
|
if (this.proxyContract == null) {
|
|
146
147
|
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
147
148
|
}
|
|
148
|
-
return await MarketData._exchangeInfo(this.proxyContract, this.poolStaticInfos, this.symbolList);
|
|
149
|
+
return await MarketData._exchangeInfo(this.proxyContract, this.poolStaticInfos, this.symbolToPerpStaticInfo, this.symbolList, this.priceFeedGetter);
|
|
149
150
|
}
|
|
150
151
|
|
|
151
152
|
/**
|
|
@@ -431,25 +432,6 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
431
432
|
return newPositionRisk;
|
|
432
433
|
}
|
|
433
434
|
|
|
434
|
-
/**
|
|
435
|
-
* Gets the pool index (in exchangeInfo) corresponding to a given symbol.
|
|
436
|
-
* @param symbol Symbol of the form ETH-USD-MATIC
|
|
437
|
-
* @returns Pool index
|
|
438
|
-
*/
|
|
439
|
-
public getPoolIndexFromSymbol(symbol: string): number {
|
|
440
|
-
let pools = this.poolStaticInfos!;
|
|
441
|
-
let poolId = this.getPoolIdFromSymbol(symbol);
|
|
442
|
-
let k = 0;
|
|
443
|
-
while (k < pools.length) {
|
|
444
|
-
if (pools[k].poolId == poolId) {
|
|
445
|
-
// pool found
|
|
446
|
-
return k;
|
|
447
|
-
}
|
|
448
|
-
k++;
|
|
449
|
-
}
|
|
450
|
-
return -1;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
435
|
/**
|
|
454
436
|
* Gets the wallet balance in the collateral currency corresponding to a given perpetual symbol.
|
|
455
437
|
* @param address Address to check
|
|
@@ -563,11 +545,15 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
563
545
|
*
|
|
564
546
|
* @returns mark price
|
|
565
547
|
*/
|
|
566
|
-
public async getMarkPrice(symbol: string): Promise<number> {
|
|
548
|
+
public async getMarkPrice(symbol: string, indexPrices?: [number, number]): Promise<number> {
|
|
567
549
|
if (this.proxyContract == null) {
|
|
568
550
|
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
569
551
|
}
|
|
570
|
-
|
|
552
|
+
if(indexPrices==undefined) {
|
|
553
|
+
let obj = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
|
|
554
|
+
indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
|
|
555
|
+
}
|
|
556
|
+
return await PerpetualDataHandler._queryPerpetualMarkPrice(symbol, this.symbolToPerpStaticInfo, this.proxyContract, indexPrices);
|
|
571
557
|
}
|
|
572
558
|
|
|
573
559
|
/**
|
|
@@ -590,31 +576,43 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
590
576
|
*
|
|
591
577
|
* @returns price (number)
|
|
592
578
|
*/
|
|
593
|
-
public async getPerpetualPrice(symbol: string, quantity: number): Promise<number> {
|
|
579
|
+
public async getPerpetualPrice(symbol: string, quantity: number, indexPrices?:[number, number]): Promise<number> {
|
|
594
580
|
if (this.proxyContract == null) {
|
|
595
581
|
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
596
582
|
}
|
|
583
|
+
if (indexPrices==undefined) {
|
|
584
|
+
// fetch from API
|
|
585
|
+
let obj = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
|
|
586
|
+
indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
|
|
587
|
+
}
|
|
597
588
|
return await PerpetualDataHandler._queryPerpetualPrice(
|
|
598
589
|
symbol,
|
|
599
590
|
quantity,
|
|
600
591
|
this.symbolToPerpStaticInfo,
|
|
601
|
-
this.proxyContract
|
|
592
|
+
this.proxyContract,
|
|
593
|
+
indexPrices
|
|
602
594
|
);
|
|
603
595
|
}
|
|
604
596
|
|
|
605
597
|
/**
|
|
606
598
|
* Query recent perpetual state from blockchain
|
|
607
599
|
* @param symbol symbol of the form ETH-USD-MATIC
|
|
600
|
+
* @param indexPrices S2 and S3 prices/isMarketOpen if not provided fetch via REST API
|
|
608
601
|
* @returns PerpetualState reference
|
|
609
602
|
*/
|
|
610
|
-
public async getPerpetualState(symbol: string): Promise<PerpetualState> {
|
|
603
|
+
public async getPerpetualState(symbol: string, indexPriceInfo?: [number, number, boolean, boolean]): Promise<PerpetualState> {
|
|
611
604
|
if (this.proxyContract == null) {
|
|
612
605
|
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
613
606
|
}
|
|
607
|
+
if (indexPriceInfo==undefined) {
|
|
608
|
+
let obj = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
|
|
609
|
+
indexPriceInfo = [obj.idxPrices[0], obj.idxPrices[1], obj.mktClosed[0], obj.mktClosed[1]];
|
|
610
|
+
}
|
|
614
611
|
let state: PerpetualState = await PerpetualDataHandler._queryPerpetualState(
|
|
615
612
|
symbol,
|
|
616
613
|
this.symbolToPerpStaticInfo,
|
|
617
|
-
this.proxyContract
|
|
614
|
+
this.proxyContract,
|
|
615
|
+
indexPriceInfo
|
|
618
616
|
);
|
|
619
617
|
return state;
|
|
620
618
|
}
|
|
@@ -640,6 +638,7 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
640
638
|
S2Symbol: perpInfo.S2Symbol,
|
|
641
639
|
S3Symbol: perpInfo.S3Symbol,
|
|
642
640
|
lotSizeBC: perpInfo.lotSizeBC,
|
|
641
|
+
priceIds: perpInfo.priceIds,
|
|
643
642
|
};
|
|
644
643
|
return res;
|
|
645
644
|
}
|
|
@@ -726,24 +725,30 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
726
725
|
return balanceCC - initalMarginCC;
|
|
727
726
|
}
|
|
728
727
|
|
|
729
|
-
public async getPythIds(symbol: string): Promise<string[]> {
|
|
730
|
-
if (this.proxyContract == null) {
|
|
731
|
-
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
732
|
-
}
|
|
733
|
-
let perpId = this.getPerpIdFromSymbol(symbol);
|
|
734
|
-
let idsB32 = await this.proxyContract.getPythIds(perpId);
|
|
735
|
-
return idsB32.apply((id: string) => ethers.utils.parseBytes32String(id));
|
|
736
|
-
}
|
|
737
|
-
|
|
738
728
|
public static async _exchangeInfo(
|
|
739
729
|
_proxyContract: ethers.Contract,
|
|
740
730
|
_poolStaticInfos: Array<PoolStaticInfo>,
|
|
741
|
-
|
|
731
|
+
_symbolToPerpStaticInfo : Map<string, PerpetualStaticInfo>,
|
|
732
|
+
_symbolList: Map<string, string>,
|
|
733
|
+
_priceFeedGetter: PriceFeeds
|
|
742
734
|
): Promise<ExchangeInfo> {
|
|
743
735
|
let nestedPerpetualIDs = await PerpetualDataHandler.getNestedPerpetualIds(_proxyContract);
|
|
744
736
|
let factory = await _proxyContract.getOracleFactory();
|
|
745
737
|
let info: ExchangeInfo = { pools: [], oracleFactoryAddr: factory, proxyAddr: _proxyContract.address };
|
|
746
738
|
const numPools = nestedPerpetualIDs.length;
|
|
739
|
+
|
|
740
|
+
// get all prices
|
|
741
|
+
let allSym = new Set<string>();
|
|
742
|
+
for(let perpSymbol of _symbolToPerpStaticInfo.keys()) {
|
|
743
|
+
let sInfo : PerpetualStaticInfo | undefined = _symbolToPerpStaticInfo.get(perpSymbol);
|
|
744
|
+
allSym.add(sInfo!.S2Symbol);
|
|
745
|
+
if(sInfo!.S3Symbol!='') {
|
|
746
|
+
allSym.add(sInfo!.S3Symbol);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
let allSymArr = Array.from(allSym.values());
|
|
750
|
+
let idxPriceMap : Map<string, [number,boolean]> = await _priceFeedGetter.fetchPrices(allSymArr);
|
|
751
|
+
|
|
747
752
|
for (var j = 0; j < numPools; j++) {
|
|
748
753
|
let perpetualIDs = nestedPerpetualIDs[j];
|
|
749
754
|
let pool = await _proxyContract.getLiquidityPool(j + 1);
|
|
@@ -759,17 +764,36 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
759
764
|
brokerCollateralLotSize: ABK64x64ToFloat(pool.fBrokerCollateralLotSize),
|
|
760
765
|
perpetuals: [],
|
|
761
766
|
};
|
|
767
|
+
let poolSymbol = PoolState.poolSymbol;
|
|
762
768
|
for (var k = 0; k < perpetualIDs.length; k++) {
|
|
763
769
|
let perp = await _proxyContract.getPerpetual(perpetualIDs[k]);
|
|
764
|
-
let
|
|
765
|
-
let
|
|
766
|
-
let
|
|
770
|
+
let symS2 = contractSymbolToSymbol(perp.S2BaseCCY, _symbolList)+"-"+contractSymbolToSymbol(perp.S2QuoteCCY, _symbolList);
|
|
771
|
+
let symS3 = contractSymbolToSymbol(perp.S3BaseCCY, _symbolList)+"-"+contractSymbolToSymbol(perp.S3QuoteCCY, _symbolList);
|
|
772
|
+
let perpSymbol = symS2+"-"+poolSymbol;
|
|
773
|
+
//console.log("perpsymbol=",perpSymbol);
|
|
774
|
+
let res = idxPriceMap.get(symS2)
|
|
775
|
+
if (res==undefined) {
|
|
776
|
+
throw new Error(`Price for index ${symS2} could not be fetched - config issue`);
|
|
777
|
+
}
|
|
778
|
+
let [indexS2, isS2MktClosed] : [number, boolean] = [res[0], res[1]];
|
|
767
779
|
let indexS3 = 1;
|
|
780
|
+
let isS3MktClosed = false;
|
|
768
781
|
if (perp.eCollateralCurrency == COLLATERAL_CURRENCY_BASE) {
|
|
769
782
|
indexS3 = indexS2;
|
|
770
783
|
} else if (perp.eCollateralCurrency == COLLATERAL_CURRENCY_QUANTO) {
|
|
771
|
-
|
|
784
|
+
res = idxPriceMap.get(symS3);
|
|
785
|
+
if (res==undefined) {
|
|
786
|
+
throw new Error(`Price for index ${symS3} could not be fetched - config issue`);
|
|
787
|
+
} else {
|
|
788
|
+
indexS3 = res[0];
|
|
789
|
+
isS3MktClosed = res[1];
|
|
790
|
+
}
|
|
772
791
|
}
|
|
792
|
+
let fMidPrice = await _proxyContract.queryPerpetualPrice(perpetualIDs[k], BigNumber.from(0), [
|
|
793
|
+
floatToABK64x64(indexS2),
|
|
794
|
+
floatToABK64x64(indexS3)
|
|
795
|
+
]);
|
|
796
|
+
|
|
773
797
|
let markPremiumRate = ABK64x64ToFloat(perp.currentMarkPremiumRate.fPrice);
|
|
774
798
|
let currentFundingRateBps = 1e4 * ABK64x64ToFloat(perp.fCurrentFundingRate);
|
|
775
799
|
let state = PERP_STATE_STR[perp.state];
|
|
@@ -784,7 +808,8 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
784
808
|
midPrice: ABK64x64ToFloat(fMidPrice),
|
|
785
809
|
currentFundingRateBps: currentFundingRateBps,
|
|
786
810
|
openInterestBC: ABK64x64ToFloat(perp.fOpenInterest),
|
|
787
|
-
maxPositionBC:
|
|
811
|
+
maxPositionBC: Infinity,
|
|
812
|
+
isMarketClosed: isS2MktClosed || isS3MktClosed
|
|
788
813
|
};
|
|
789
814
|
PoolState.perpetuals.push(PerpetualState);
|
|
790
815
|
}
|
package/src/nodeSDKTypes.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { BigNumber, BigNumberish, BytesLike, constants, ContractTransaction } from "ethers";
|
|
2
|
-
|
|
3
|
-
export const
|
|
2
|
+
import { NumberLiteralType } from "typescript";
|
|
3
|
+
export const DEFAULT_CONFIG = "../config/defaultConfig.json";
|
|
4
4
|
export const DEFAULT_CONFIG_TESTNET_NAME = "testnet";
|
|
5
5
|
export const DEFAULT_CONFIG_MAINNET_NAME = "mainnet";
|
|
6
6
|
|
|
7
7
|
export const ERC20_ABI = require("../abi/ERC20.json");
|
|
8
|
+
export const MOCK_TOKEN_SWAP_ABI = require("../abi/MockTokenSwap.json");
|
|
8
9
|
export const COLLATERAL_CURRENCY_QUOTE = 0;
|
|
9
10
|
export const COLLATERAL_CURRENCY_BASE = 1;
|
|
10
11
|
export const COLLATERAL_CURRENCY_QUANTO = 2;
|
|
@@ -33,6 +34,8 @@ export const BUY_SIDE = "BUY";
|
|
|
33
34
|
export const SELL_SIDE = "SELL";
|
|
34
35
|
export const CLOSED_SIDE = "CLOSED";
|
|
35
36
|
export interface NodeSDKConfig {
|
|
37
|
+
name: string | undefined;
|
|
38
|
+
version: number;
|
|
36
39
|
nodeURL: string;
|
|
37
40
|
proxyAddr: string;
|
|
38
41
|
proxyABILocation: string;
|
|
@@ -40,6 +43,7 @@ export interface NodeSDKConfig {
|
|
|
40
43
|
limitOrderBookABILocation: string;
|
|
41
44
|
limitOrderBookFactoryABILocation: string;
|
|
42
45
|
symbolListLocation: string;
|
|
46
|
+
priceFeedConfigNetwork: string;
|
|
43
47
|
gasLimit?: number | undefined;
|
|
44
48
|
}
|
|
45
49
|
|
|
@@ -81,6 +85,7 @@ export interface PerpetualStaticInfo {
|
|
|
81
85
|
S2Symbol: string;
|
|
82
86
|
S3Symbol: string;
|
|
83
87
|
lotSizeBC: number;
|
|
88
|
+
priceIds: string[];
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
/**
|
|
@@ -135,6 +140,7 @@ export interface PerpetualState {
|
|
|
135
140
|
currentFundingRateBps: number;
|
|
136
141
|
openInterestBC: number;
|
|
137
142
|
maxPositionBC: number;
|
|
143
|
+
isMarketClosed: boolean;
|
|
138
144
|
}
|
|
139
145
|
|
|
140
146
|
export interface OrderResponse {
|
|
@@ -148,7 +154,7 @@ export interface OrderStruct {
|
|
|
148
154
|
}
|
|
149
155
|
|
|
150
156
|
export interface Order {
|
|
151
|
-
symbol: string
|
|
157
|
+
symbol: string;//symbol of the form ETH-USD-MATIC
|
|
152
158
|
side: string;
|
|
153
159
|
type: string;
|
|
154
160
|
quantity: number;
|
|
@@ -204,3 +210,24 @@ export interface SmartContractOrder {
|
|
|
204
210
|
uint256 iDeadline;
|
|
205
211
|
uint256 createdTimestamp;
|
|
206
212
|
*/
|
|
213
|
+
|
|
214
|
+
export interface PriceFeedConfig {
|
|
215
|
+
network: string;
|
|
216
|
+
ids: Array<{ symbol: string; id: string; type: string; origin: string }>;
|
|
217
|
+
endpoints: Array<{ type: string; endpoint: string }>;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export interface PriceFeedSubmission {
|
|
221
|
+
symbols: string[];
|
|
222
|
+
priceFeedVaas: string[];
|
|
223
|
+
prices: number[];
|
|
224
|
+
isMarketClosed: boolean[];
|
|
225
|
+
timestamps: number[];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export interface PriceFeedFormat {
|
|
229
|
+
conf: BigNumber;
|
|
230
|
+
expo: number;
|
|
231
|
+
price: BigNumber;
|
|
232
|
+
publish_time: number;
|
|
233
|
+
}
|
package/src/orderReferrerTool.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
SELL_SIDE,
|
|
8
8
|
ZERO_ADDRESS,
|
|
9
9
|
ZERO_ORDER_ID,
|
|
10
|
+
PriceFeedSubmission,
|
|
10
11
|
} from "./nodeSDKTypes";
|
|
11
12
|
import PerpetualDataHandler from "./perpetualDataHandler";
|
|
12
13
|
import WriteAccessHandler from "./writeAccessHandler";
|
|
@@ -46,8 +47,9 @@ export default class OrderReferrerTool extends WriteAccessHandler {
|
|
|
46
47
|
* Executes an order by symbol and ID. This action interacts with the blockchain and incurs gas costs.
|
|
47
48
|
* @param {string} symbol Symbol of the form ETH-USD-MATIC.
|
|
48
49
|
* @param {string} orderId ID of the order to be executed.
|
|
49
|
-
* @param {string=} referrerAddr
|
|
50
|
-
*
|
|
50
|
+
* @param {string=} referrerAddr optional address of the wallet to be credited for executing the order, if different from the one submitting this transaction.
|
|
51
|
+
* @param {number=} nonce optional nonce
|
|
52
|
+
* @param {PriceFeedSubmission=} submission optional signed prices obtained via PriceFeeds::fetchLatestFeedPriceInfoForPerpetual
|
|
51
53
|
* @example
|
|
52
54
|
* import { OrderReferrerTool, PerpetualDataHandler, Order } from "@d8x/perpetuals-sdk";
|
|
53
55
|
* async function main() {
|
|
@@ -79,7 +81,8 @@ export default class OrderReferrerTool extends WriteAccessHandler {
|
|
|
79
81
|
symbol: string,
|
|
80
82
|
orderId: string,
|
|
81
83
|
referrerAddr?: string,
|
|
82
|
-
nonce?: number
|
|
84
|
+
nonce?: number,
|
|
85
|
+
submission?: PriceFeedSubmission
|
|
83
86
|
): Promise<ethers.ContractTransaction> {
|
|
84
87
|
if (this.proxyContract == null || this.signer == null) {
|
|
85
88
|
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
|
|
@@ -88,8 +91,22 @@ export default class OrderReferrerTool extends WriteAccessHandler {
|
|
|
88
91
|
if (typeof referrerAddr == "undefined") {
|
|
89
92
|
referrerAddr = this.traderAddr;
|
|
90
93
|
}
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
if (submission == undefined) {
|
|
95
|
+
submission = await this.priceFeedGetter.fetchLatestFeedPriceInfoForPerpetual(symbol);
|
|
96
|
+
}
|
|
97
|
+
const options = {
|
|
98
|
+
gasLimit: this.gasLimit,
|
|
99
|
+
nonce: nonce,
|
|
100
|
+
value: this.PRICE_UPDATE_FEE_GWEI * submission?.priceFeedVaas.length,
|
|
101
|
+
};
|
|
102
|
+
console.log(submission);
|
|
103
|
+
return await orderBookSC.executeOrder(
|
|
104
|
+
orderId,
|
|
105
|
+
referrerAddr,
|
|
106
|
+
submission?.priceFeedVaas,
|
|
107
|
+
submission?.timestamps,
|
|
108
|
+
options
|
|
109
|
+
);
|
|
93
110
|
}
|
|
94
111
|
|
|
95
112
|
/**
|
|
@@ -224,6 +241,8 @@ export default class OrderReferrerTool extends WriteAccessHandler {
|
|
|
224
241
|
/**
|
|
225
242
|
* Check if a conditional order can be executed
|
|
226
243
|
* @param order order structure
|
|
244
|
+
* @param indexPrices pair of index prices S2 and S3. S3 set to zero if not required. If undefined
|
|
245
|
+
* the function will fetch the latest prices from the REST API
|
|
227
246
|
* @example
|
|
228
247
|
* import { OrderReferrerTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
229
248
|
* async function main() {
|
|
@@ -241,26 +260,39 @@ export default class OrderReferrerTool extends WriteAccessHandler {
|
|
|
241
260
|
* main();
|
|
242
261
|
* @returns true if order can be executed for the current state of the perpetuals
|
|
243
262
|
*/
|
|
244
|
-
public async isTradeable(order: Order): Promise<boolean> {
|
|
263
|
+
public async isTradeable(order: Order, indexPrices?: [number, number]): Promise<boolean> {
|
|
245
264
|
if (this.proxyContract == null) {
|
|
246
265
|
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
247
266
|
}
|
|
267
|
+
if (indexPrices == undefined) {
|
|
268
|
+
let obj = await this.priceFeedGetter.fetchPricesForPerpetual(order.symbol);
|
|
269
|
+
indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
|
|
270
|
+
}
|
|
248
271
|
let orderPrice = await PerpetualDataHandler._queryPerpetualPrice(
|
|
249
272
|
order.symbol,
|
|
250
273
|
order.quantity,
|
|
251
274
|
this.symbolToPerpStaticInfo,
|
|
252
|
-
this.proxyContract
|
|
275
|
+
this.proxyContract,
|
|
276
|
+
indexPrices
|
|
253
277
|
);
|
|
254
278
|
let markPrice = await PerpetualDataHandler._queryPerpetualMarkPrice(
|
|
255
279
|
order.symbol,
|
|
256
280
|
this.symbolToPerpStaticInfo,
|
|
257
|
-
this.proxyContract
|
|
281
|
+
this.proxyContract,
|
|
282
|
+
indexPrices
|
|
258
283
|
);
|
|
259
284
|
let block = await this.provider!.getBlockNumber();
|
|
260
285
|
return OrderReferrerTool._isTradeable(order, orderPrice, markPrice, block, this.symbolToPerpStaticInfo);
|
|
261
286
|
}
|
|
262
287
|
|
|
263
|
-
|
|
288
|
+
/**
|
|
289
|
+
* Check for a batch of orders on the same perpetual whether they can be traded
|
|
290
|
+
* @param orders orders belonging to 1 perpetual
|
|
291
|
+
* @param indexPrice S2,S3-index prices for the given perpetual. Will fetch prices from REST API
|
|
292
|
+
* if not defined.
|
|
293
|
+
* @returns array of tradeable boolean
|
|
294
|
+
*/
|
|
295
|
+
public async isTradeableBatch(orders: Order[], indexPrices?: [number, number, boolean, boolean]): Promise<boolean[]> {
|
|
264
296
|
if (orders.length == 0) {
|
|
265
297
|
return [];
|
|
266
298
|
}
|
|
@@ -270,20 +302,31 @@ export default class OrderReferrerTool extends WriteAccessHandler {
|
|
|
270
302
|
if (orders.filter((o) => o.symbol == orders[0].symbol).length < orders.length) {
|
|
271
303
|
throw Error("all orders in a batch must have the same symbol");
|
|
272
304
|
}
|
|
305
|
+
if (indexPrices == undefined) {
|
|
306
|
+
let obj = await this.priceFeedGetter.fetchPricesForPerpetual(orders[0].symbol);
|
|
307
|
+
indexPrices = [obj.idxPrices[0], obj.idxPrices[1], obj.mktClosed[0], obj.mktClosed[1]];
|
|
308
|
+
}
|
|
309
|
+
if (indexPrices[2] || indexPrices[3]) {
|
|
310
|
+
// market closed
|
|
311
|
+
return orders.map((o) => false);
|
|
312
|
+
}
|
|
313
|
+
|
|
273
314
|
let orderPrice = await Promise.all(
|
|
274
315
|
orders.map((o) =>
|
|
275
316
|
PerpetualDataHandler._queryPerpetualPrice(
|
|
276
317
|
o.symbol,
|
|
277
318
|
o.quantity,
|
|
278
319
|
this.symbolToPerpStaticInfo,
|
|
279
|
-
this.proxyContract
|
|
320
|
+
this.proxyContract!,
|
|
321
|
+
[indexPrices![0], indexPrices![1]]
|
|
280
322
|
)
|
|
281
323
|
)
|
|
282
324
|
);
|
|
283
325
|
let markPrice = await PerpetualDataHandler._queryPerpetualMarkPrice(
|
|
284
326
|
orders[0].symbol,
|
|
285
327
|
this.symbolToPerpStaticInfo,
|
|
286
|
-
this.proxyContract
|
|
328
|
+
this.proxyContract,
|
|
329
|
+
[indexPrices![0], indexPrices![1]]
|
|
287
330
|
);
|
|
288
331
|
let block = await this.provider!.getBlockNumber();
|
|
289
332
|
return orders.map((o, idx) =>
|
|
@@ -293,7 +336,7 @@ export default class OrderReferrerTool extends WriteAccessHandler {
|
|
|
293
336
|
|
|
294
337
|
public static _isTradeable(
|
|
295
338
|
order: Order,
|
|
296
|
-
|
|
339
|
+
tradePrice: number,
|
|
297
340
|
markPrice: number,
|
|
298
341
|
block: number,
|
|
299
342
|
symbolToPerpInfoMap: Map<string, PerpetualStaticInfo>
|
|
@@ -316,7 +359,7 @@ export default class OrderReferrerTool extends WriteAccessHandler {
|
|
|
316
359
|
return false;
|
|
317
360
|
}
|
|
318
361
|
let limitPrice = order.limitPrice!;
|
|
319
|
-
if ((order.side == BUY_SIDE &&
|
|
362
|
+
if ((order.side == BUY_SIDE && tradePrice > limitPrice) || (order.side == SELL_SIDE && tradePrice < limitPrice)) {
|
|
320
363
|
return false;
|
|
321
364
|
}
|
|
322
365
|
// do we need to check trigger/stop?
|