@d8x/perpetuals-sdk 0.0.44 → 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 +3 -2
- package/src/accountTrade.ts +31 -8
- package/src/d8XMath.ts +47 -22
- package/src/index.ts +2 -0
- package/src/liquidatorTool.ts +28 -8
- package/src/marketData.ts +99 -61
- 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/d8XMath.ts
CHANGED
|
@@ -28,6 +28,24 @@ export function ABK64x64ToFloat(x: BigNumber | number): number {
|
|
|
28
28
|
return parseFloat(NumberStr) * s;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @param {BigNumber} x BigNumber in Dec-N format
|
|
34
|
+
* @returns {number} x as a float (number)
|
|
35
|
+
*/
|
|
36
|
+
export function decNToFloat(x: BigNumber, numDec: number) {
|
|
37
|
+
//x: BigNumber in DecN format to float
|
|
38
|
+
const DECIMALS = BigNumber.from(10).pow(BigNumber.from(numDec));
|
|
39
|
+
let s = x.lt(0) ? -1 : 1;
|
|
40
|
+
x = x.mul(s);
|
|
41
|
+
let xInt = x.div(DECIMALS);
|
|
42
|
+
let xDec = x.sub(xInt.mul(DECIMALS));
|
|
43
|
+
let k = numDec - xDec.toString().length;
|
|
44
|
+
let sPad = "0".repeat(k);
|
|
45
|
+
let NumberStr = xInt.toString() + "." + sPad + xDec.toString();
|
|
46
|
+
return parseFloat(NumberStr) * s;
|
|
47
|
+
}
|
|
48
|
+
|
|
31
49
|
/**
|
|
32
50
|
*
|
|
33
51
|
* @param {BigNumber} x BigNumber in Dec18 format
|
|
@@ -275,26 +293,33 @@ export function getNewPositionLeverage(
|
|
|
275
293
|
);
|
|
276
294
|
}
|
|
277
295
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
296
|
+
/**
|
|
297
|
+
* Determine amount to be deposited into margin account so that the given leverage
|
|
298
|
+
* is obtained when trading a position pos (trade amount = position)
|
|
299
|
+
* Does NOT include fees
|
|
300
|
+
* Smart contract equivalent: calcMarginForTargetLeverage(..., _ignorePosBalance = false & balance = b0)
|
|
301
|
+
* @param {number} pos0 - current position
|
|
302
|
+
* @param {number} b0 - current balance
|
|
303
|
+
* @param {number} tradeAmnt - amount to trade
|
|
304
|
+
* @param {number} targetLvg - target leverage
|
|
305
|
+
* @param {number} price - price to trade amount 'tradeAmnt'
|
|
306
|
+
* @param {number} S3 - collateral to quote conversion (=S2 if base-collateral, =1 if quote collateral, = index S3 if quanto)
|
|
307
|
+
* @param {number} S2Mark - mark price
|
|
308
|
+
* @returns {number} Amount to be deposited to have the given leverage when trading into position pos before fees
|
|
309
|
+
*/
|
|
310
|
+
export function getDepositAmountForLvgTrade(
|
|
311
|
+
pos0: number,
|
|
312
|
+
b0: number,
|
|
313
|
+
tradeAmnt: number,
|
|
314
|
+
targetLvg: number,
|
|
315
|
+
price: number,
|
|
316
|
+
S3: number,
|
|
317
|
+
S2Mark: number
|
|
318
|
+
) {
|
|
319
|
+
let pnl = (tradeAmnt * (S2Mark - price)) / S3;
|
|
320
|
+
if (targetLvg == 0) {
|
|
321
|
+
targetLvg = (Math.abs(pos0) * S2Mark) / S3 / b0;
|
|
322
|
+
}
|
|
323
|
+
let b = (Math.abs(pos0 + tradeAmnt) * S2Mark) / S3 / targetLvg;
|
|
324
|
+
return -(b0 + pnl - b);
|
|
300
325
|
}
|
package/src/index.ts
CHANGED
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
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
calculateLiquidationPriceCollateralQuanto,
|
|
6
6
|
calculateLiquidationPriceCollateralQuote,
|
|
7
7
|
floatToABK64x64,
|
|
8
|
+
getDepositAmountForLvgTrade,
|
|
8
9
|
getMarginRequiredForLeveragedTrade,
|
|
9
10
|
getMaxSignedPositionSize,
|
|
10
11
|
getNewPositionLeverage,
|
|
@@ -31,6 +32,7 @@ import {
|
|
|
31
32
|
ZERO_ADDRESS,
|
|
32
33
|
} from "./nodeSDKTypes";
|
|
33
34
|
import PerpetualDataHandler from "./perpetualDataHandler";
|
|
35
|
+
import PriceFeeds from "./priceFeeds";
|
|
34
36
|
import { contractSymbolToSymbol, toBytes4 } from "./utils";
|
|
35
37
|
|
|
36
38
|
/**
|
|
@@ -144,7 +146,7 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
144
146
|
if (this.proxyContract == null) {
|
|
145
147
|
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
146
148
|
}
|
|
147
|
-
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);
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
/**
|
|
@@ -297,13 +299,17 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
297
299
|
currentPositionRisk: MarginAccount,
|
|
298
300
|
symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>
|
|
299
301
|
): MarginAccount {
|
|
300
|
-
let
|
|
301
|
-
let
|
|
302
|
-
let
|
|
302
|
+
let currentSide = currentPositionRisk.side;
|
|
303
|
+
let currentPosition = (currentSide == BUY_SIDE ? 1 : -1) * currentPositionRisk.positionNotionalBaseCCY;
|
|
304
|
+
let newPosition = currentPosition + tradeAmount;
|
|
305
|
+
let newSide = newPosition > 0 ? BUY_SIDE : newPosition < 0 ? SELL_SIDE : CLOSED_SIDE;
|
|
303
306
|
let lockedInValue = currentPositionRisk.entryPrice * currentPosition;
|
|
304
307
|
if (tradeAmount == 0) {
|
|
305
308
|
keepPositionLvg = false;
|
|
306
309
|
}
|
|
310
|
+
let isOpen = newPosition != 0 && (tradeAmount == 0 || currentPosition == 0 || tradeAmount * currentPosition > 0);
|
|
311
|
+
let isFlip = Math.abs(tradeAmount) > Math.abs(currentPosition) && !isOpen;
|
|
312
|
+
let keepPositionLvgOnClose = keepPositionLvg && !isOpen;
|
|
307
313
|
// need these for leverage/margin calculations
|
|
308
314
|
let [markPrice, indexPriceS2, indexPriceS3] = [
|
|
309
315
|
perpetualState.markPrice,
|
|
@@ -339,19 +345,26 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
339
345
|
feeRate
|
|
340
346
|
);
|
|
341
347
|
} else if (tradeAmount != 0) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
348
|
+
let depositAtTradeTime: number;
|
|
349
|
+
if (!isOpen && !isFlip && !keepPositionLvgOnClose) {
|
|
350
|
+
// no deposit from trader's wallet, but there is realized pnl
|
|
351
|
+
depositAtTradeTime = tradeAmount * (tradePrice - currentPositionRisk.entryPrice);
|
|
352
|
+
} else {
|
|
353
|
+
// target lvg will default current lvg if not specified
|
|
354
|
+
let targetLvg = isFlip || isOpen ? tradeLeverage ?? 0 : 0;
|
|
355
|
+
let b0, pos0;
|
|
356
|
+
[b0, pos0] = isOpen ? [0, 0] : [currentPositionRisk.collateralCC, currentPosition];
|
|
357
|
+
depositAtTradeTime = getDepositAmountForLvgTrade(
|
|
358
|
+
b0,
|
|
359
|
+
pos0,
|
|
360
|
+
tradeAmount,
|
|
361
|
+
targetLvg,
|
|
362
|
+
tradePrice,
|
|
363
|
+
indexPriceS2,
|
|
364
|
+
markPrice
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
newCollateral = currentPositionRisk.collateralCC + depositAtTradeTime;
|
|
355
368
|
// the new leverage corresponds to increasing the position and collateral according to the order
|
|
356
369
|
newLeverage = getNewPositionLeverage(
|
|
357
370
|
tradeAmount,
|
|
@@ -380,7 +393,7 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
380
393
|
);
|
|
381
394
|
}
|
|
382
395
|
let newLockedInValue = lockedInValue + tradeAmount * tradePrice;
|
|
383
|
-
|
|
396
|
+
let entryPrice = newPosition == 0 ? 0 : Math.abs(newLockedInValue / newPosition);
|
|
384
397
|
// liquidation vars
|
|
385
398
|
let S2Liq: number, S3Liq: number | undefined;
|
|
386
399
|
let tau = symbolToPerpStaticInfo.get(symbol)!.maintenanceMarginRate;
|
|
@@ -401,14 +414,15 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
401
414
|
} else {
|
|
402
415
|
S2Liq = calculateLiquidationPriceCollateralQuote(newLockedInValue, newPosition, newCollateral, tau);
|
|
403
416
|
}
|
|
417
|
+
|
|
404
418
|
let newPositionRisk: MarginAccount = {
|
|
405
419
|
symbol: currentPositionRisk.symbol,
|
|
406
420
|
positionNotionalBaseCCY: Math.abs(newPosition),
|
|
407
|
-
side:
|
|
408
|
-
entryPrice:
|
|
421
|
+
side: newSide,
|
|
422
|
+
entryPrice: entryPrice,
|
|
409
423
|
leverage: newLeverage,
|
|
410
424
|
markPrice: markPrice,
|
|
411
|
-
unrealizedPnlQuoteCCY:
|
|
425
|
+
unrealizedPnlQuoteCCY: newPosition * markPrice - newLockedInValue,
|
|
412
426
|
unrealizedFundingCollateralCCY: currentPositionRisk.unrealizedFundingCollateralCCY,
|
|
413
427
|
collateralCC: newCollateral,
|
|
414
428
|
collToQuoteConversion: indexPriceS3,
|
|
@@ -418,25 +432,6 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
418
432
|
return newPositionRisk;
|
|
419
433
|
}
|
|
420
434
|
|
|
421
|
-
/**
|
|
422
|
-
* Gets the pool index (in exchangeInfo) corresponding to a given symbol.
|
|
423
|
-
* @param symbol Symbol of the form ETH-USD-MATIC
|
|
424
|
-
* @returns Pool index
|
|
425
|
-
*/
|
|
426
|
-
public getPoolIndexFromSymbol(symbol: string): number {
|
|
427
|
-
let pools = this.poolStaticInfos!;
|
|
428
|
-
let poolId = this.getPoolIdFromSymbol(symbol);
|
|
429
|
-
let k = 0;
|
|
430
|
-
while (k < pools.length) {
|
|
431
|
-
if (pools[k].poolId == poolId) {
|
|
432
|
-
// pool found
|
|
433
|
-
return k;
|
|
434
|
-
}
|
|
435
|
-
k++;
|
|
436
|
-
}
|
|
437
|
-
return -1;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
435
|
/**
|
|
441
436
|
* Gets the wallet balance in the collateral currency corresponding to a given perpetual symbol.
|
|
442
437
|
* @param address Address to check
|
|
@@ -550,11 +545,15 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
550
545
|
*
|
|
551
546
|
* @returns mark price
|
|
552
547
|
*/
|
|
553
|
-
public async getMarkPrice(symbol: string): Promise<number> {
|
|
548
|
+
public async getMarkPrice(symbol: string, indexPrices?: [number, number]): Promise<number> {
|
|
554
549
|
if (this.proxyContract == null) {
|
|
555
550
|
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
556
551
|
}
|
|
557
|
-
|
|
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);
|
|
558
557
|
}
|
|
559
558
|
|
|
560
559
|
/**
|
|
@@ -577,31 +576,43 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
577
576
|
*
|
|
578
577
|
* @returns price (number)
|
|
579
578
|
*/
|
|
580
|
-
public async getPerpetualPrice(symbol: string, quantity: number): Promise<number> {
|
|
579
|
+
public async getPerpetualPrice(symbol: string, quantity: number, indexPrices?:[number, number]): Promise<number> {
|
|
581
580
|
if (this.proxyContract == null) {
|
|
582
581
|
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
583
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
|
+
}
|
|
584
588
|
return await PerpetualDataHandler._queryPerpetualPrice(
|
|
585
589
|
symbol,
|
|
586
590
|
quantity,
|
|
587
591
|
this.symbolToPerpStaticInfo,
|
|
588
|
-
this.proxyContract
|
|
592
|
+
this.proxyContract,
|
|
593
|
+
indexPrices
|
|
589
594
|
);
|
|
590
595
|
}
|
|
591
596
|
|
|
592
597
|
/**
|
|
593
598
|
* Query recent perpetual state from blockchain
|
|
594
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
|
|
595
601
|
* @returns PerpetualState reference
|
|
596
602
|
*/
|
|
597
|
-
public async getPerpetualState(symbol: string): Promise<PerpetualState> {
|
|
603
|
+
public async getPerpetualState(symbol: string, indexPriceInfo?: [number, number, boolean, boolean]): Promise<PerpetualState> {
|
|
598
604
|
if (this.proxyContract == null) {
|
|
599
605
|
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
600
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
|
+
}
|
|
601
611
|
let state: PerpetualState = await PerpetualDataHandler._queryPerpetualState(
|
|
602
612
|
symbol,
|
|
603
613
|
this.symbolToPerpStaticInfo,
|
|
604
|
-
this.proxyContract
|
|
614
|
+
this.proxyContract,
|
|
615
|
+
indexPriceInfo
|
|
605
616
|
);
|
|
606
617
|
return state;
|
|
607
618
|
}
|
|
@@ -627,6 +638,7 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
627
638
|
S2Symbol: perpInfo.S2Symbol,
|
|
628
639
|
S3Symbol: perpInfo.S3Symbol,
|
|
629
640
|
lotSizeBC: perpInfo.lotSizeBC,
|
|
641
|
+
priceIds: perpInfo.priceIds,
|
|
630
642
|
};
|
|
631
643
|
return res;
|
|
632
644
|
}
|
|
@@ -713,24 +725,30 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
713
725
|
return balanceCC - initalMarginCC;
|
|
714
726
|
}
|
|
715
727
|
|
|
716
|
-
public async getPythIds(symbol: string): Promise<string[]> {
|
|
717
|
-
if (this.proxyContract == null) {
|
|
718
|
-
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
719
|
-
}
|
|
720
|
-
let perpId = this.getPerpIdFromSymbol(symbol);
|
|
721
|
-
let idsB32 = await this.proxyContract.getPythIds(perpId);
|
|
722
|
-
return idsB32.apply((id: string) => ethers.utils.parseBytes32String(id));
|
|
723
|
-
}
|
|
724
|
-
|
|
725
728
|
public static async _exchangeInfo(
|
|
726
729
|
_proxyContract: ethers.Contract,
|
|
727
730
|
_poolStaticInfos: Array<PoolStaticInfo>,
|
|
728
|
-
|
|
731
|
+
_symbolToPerpStaticInfo : Map<string, PerpetualStaticInfo>,
|
|
732
|
+
_symbolList: Map<string, string>,
|
|
733
|
+
_priceFeedGetter: PriceFeeds
|
|
729
734
|
): Promise<ExchangeInfo> {
|
|
730
735
|
let nestedPerpetualIDs = await PerpetualDataHandler.getNestedPerpetualIds(_proxyContract);
|
|
731
736
|
let factory = await _proxyContract.getOracleFactory();
|
|
732
737
|
let info: ExchangeInfo = { pools: [], oracleFactoryAddr: factory, proxyAddr: _proxyContract.address };
|
|
733
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
|
+
|
|
734
752
|
for (var j = 0; j < numPools; j++) {
|
|
735
753
|
let perpetualIDs = nestedPerpetualIDs[j];
|
|
736
754
|
let pool = await _proxyContract.getLiquidityPool(j + 1);
|
|
@@ -746,17 +764,36 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
746
764
|
brokerCollateralLotSize: ABK64x64ToFloat(pool.fBrokerCollateralLotSize),
|
|
747
765
|
perpetuals: [],
|
|
748
766
|
};
|
|
767
|
+
let poolSymbol = PoolState.poolSymbol;
|
|
749
768
|
for (var k = 0; k < perpetualIDs.length; k++) {
|
|
750
769
|
let perp = await _proxyContract.getPerpetual(perpetualIDs[k]);
|
|
751
|
-
let
|
|
752
|
-
let
|
|
753
|
-
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]];
|
|
754
779
|
let indexS3 = 1;
|
|
780
|
+
let isS3MktClosed = false;
|
|
755
781
|
if (perp.eCollateralCurrency == COLLATERAL_CURRENCY_BASE) {
|
|
756
782
|
indexS3 = indexS2;
|
|
757
783
|
} else if (perp.eCollateralCurrency == COLLATERAL_CURRENCY_QUANTO) {
|
|
758
|
-
|
|
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
|
+
}
|
|
759
791
|
}
|
|
792
|
+
let fMidPrice = await _proxyContract.queryPerpetualPrice(perpetualIDs[k], BigNumber.from(0), [
|
|
793
|
+
floatToABK64x64(indexS2),
|
|
794
|
+
floatToABK64x64(indexS3)
|
|
795
|
+
]);
|
|
796
|
+
|
|
760
797
|
let markPremiumRate = ABK64x64ToFloat(perp.currentMarkPremiumRate.fPrice);
|
|
761
798
|
let currentFundingRateBps = 1e4 * ABK64x64ToFloat(perp.fCurrentFundingRate);
|
|
762
799
|
let state = PERP_STATE_STR[perp.state];
|
|
@@ -771,7 +808,8 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
771
808
|
midPrice: ABK64x64ToFloat(fMidPrice),
|
|
772
809
|
currentFundingRateBps: currentFundingRateBps,
|
|
773
810
|
openInterestBC: ABK64x64ToFloat(perp.fOpenInterest),
|
|
774
|
-
maxPositionBC:
|
|
811
|
+
maxPositionBC: Infinity,
|
|
812
|
+
isMarketClosed: isS2MktClosed || isS3MktClosed
|
|
775
813
|
};
|
|
776
814
|
PoolState.perpetuals.push(PerpetualState);
|
|
777
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
|
+
}
|