@d8x/perpetuals-sdk 0.0.1
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/LICENSE +21 -0
- package/README.md +17 -0
- package/abi/ERC20.json +288 -0
- package/abi/IPerpetualManager.json +4674 -0
- package/abi/LimitOrderBook.json +865 -0
- package/abi/LimitOrderBookFactory.json +166 -0
- package/config/defaultConfig.json +9 -0
- package/config/oldConfig.json +9 -0
- package/dist/accountTrade.d.ts +54 -0
- package/dist/accountTrade.js +164 -0
- package/dist/brokerTool.d.ts +41 -0
- package/dist/brokerTool.js +129 -0
- package/dist/d8XMath.d.ts +71 -0
- package/dist/d8XMath.js +162 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +49 -0
- package/dist/liquiditatorTool.d.ts +14 -0
- package/dist/liquiditatorTool.js +21 -0
- package/dist/liquidityProviderTool.d.ts +39 -0
- package/dist/liquidityProviderTool.js +100 -0
- package/dist/marketData.d.ts +39 -0
- package/dist/marketData.js +160 -0
- package/dist/nodeSDKTypes.d.ts +130 -0
- package/dist/nodeSDKTypes.js +52 -0
- package/dist/orderReferrerTool.d.ts +14 -0
- package/dist/orderReferrerTool.js +21 -0
- package/dist/perpetualDataHandler.d.ts +85 -0
- package/dist/perpetualDataHandler.js +474 -0
- package/dist/utils.d.ts +37 -0
- package/dist/utils.js +84 -0
- package/dist/writeAccessHandler.d.ts +36 -0
- package/dist/writeAccessHandler.js +95 -0
- package/module.d.ts +1 -0
- package/package.json +63 -0
- package/src/accountTrade.ts +217 -0
- package/src/brokerTool.ts +155 -0
- package/src/d8XMath.ts +176 -0
- package/src/index.ts +32 -0
- package/src/liquiditatorTool.ts +21 -0
- package/src/liquidityProviderTool.ts +100 -0
- package/src/marketData.ts +149 -0
- package/src/nodeSDKTypes.ts +158 -0
- package/src/orderReferrerTool.ts +17 -0
- package/src/perpetualDataHandler.ts +549 -0
- package/src/utils.ts +83 -0
- package/src/writeAccessHandler.ts +83 -0
package/src/d8XMath.ts
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { BigNumber } from "ethers";
|
|
2
|
+
import { DECIMALS, ONE_64x64 } from "./nodeSDKTypes";
|
|
3
|
+
const BN = BigNumber;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Convert ABK64x64 bigint-format to float.
|
|
7
|
+
* Result = x/2^64 if big number, x/2^29 if number
|
|
8
|
+
* @param x number in ABDK-format or 2^29
|
|
9
|
+
* @returns x/2^64 in number-format (float)
|
|
10
|
+
*/
|
|
11
|
+
export function ABK64x64ToFloat(x: BigNumber | number): number {
|
|
12
|
+
if (typeof x == "number") {
|
|
13
|
+
return x / 2 ** 29;
|
|
14
|
+
}
|
|
15
|
+
let s = x.lt(0) ? -1 : 1;
|
|
16
|
+
x = x.mul(s);
|
|
17
|
+
let xInt = x.div(ONE_64x64);
|
|
18
|
+
let dec18 = BigNumber.from(10).pow(BigNumber.from(18));
|
|
19
|
+
let xDec = x.sub(xInt.mul(ONE_64x64));
|
|
20
|
+
xDec = xDec.mul(dec18).div(ONE_64x64);
|
|
21
|
+
let k = 18 - xDec.toString().length;
|
|
22
|
+
// console.assert(k >= 0);
|
|
23
|
+
let sPad = "0".repeat(k);
|
|
24
|
+
let NumberStr = xInt.toString() + "." + sPad + xDec.toString();
|
|
25
|
+
return parseFloat(NumberStr) * s;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @param x BigNumber in Dec18 format
|
|
31
|
+
* @returns x as a float (number)
|
|
32
|
+
*/
|
|
33
|
+
export function dec18ToFloat(x: BigNumber): number {
|
|
34
|
+
//x: BigNumber in Dec18 format to float
|
|
35
|
+
let s = x.lt(0) ? -1 : 1;
|
|
36
|
+
x = x.mul(s);
|
|
37
|
+
let xInt = x.div(DECIMALS);
|
|
38
|
+
let xDec = x.sub(xInt.mul(DECIMALS));
|
|
39
|
+
let k = 18 - xDec.toString().length;
|
|
40
|
+
let sPad = "0".repeat(k);
|
|
41
|
+
let NumberStr = xInt.toString() + "." + sPad + xDec.toString();
|
|
42
|
+
return parseFloat(NumberStr) * s;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Converts x into ABDK64x64 format
|
|
47
|
+
* @param x number (float)
|
|
48
|
+
* @returns x^64 in big number format
|
|
49
|
+
*/
|
|
50
|
+
export function floatToABK64x64(x: number): BigNumber {
|
|
51
|
+
// convert float to ABK64x64 bigint-format
|
|
52
|
+
// Create string from number with 18 decimals
|
|
53
|
+
if (x === 0) {
|
|
54
|
+
return BigNumber.from(0);
|
|
55
|
+
}
|
|
56
|
+
let sg = Math.sign(x);
|
|
57
|
+
x = Math.abs(x);
|
|
58
|
+
let strX = Number(x).toFixed(18);
|
|
59
|
+
const arrX = strX.split(".");
|
|
60
|
+
let xInt = BigNumber.from(arrX[0]);
|
|
61
|
+
let xDec = BigNumber.from(arrX[1]);
|
|
62
|
+
let xIntBig = xInt.mul(ONE_64x64);
|
|
63
|
+
let dec18 = BigNumber.from(10).pow(BigNumber.from(18));
|
|
64
|
+
let xDecBig = xDec.mul(ONE_64x64).div(dec18);
|
|
65
|
+
return xIntBig.add(xDecBig).mul(sg);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
* @param x number (float)
|
|
71
|
+
* @returns x as a BigNumber in Dec18 format
|
|
72
|
+
*/
|
|
73
|
+
export function floatToDec18(x: number): BigNumber {
|
|
74
|
+
// float number to dec 18
|
|
75
|
+
if (x === 0) {
|
|
76
|
+
return BigNumber.from(0);
|
|
77
|
+
}
|
|
78
|
+
let sg = Math.sign(x);
|
|
79
|
+
x = Math.abs(x);
|
|
80
|
+
let strX = x.toFixed(18);
|
|
81
|
+
const arrX = strX.split(".");
|
|
82
|
+
let xInt = BigNumber.from(arrX[0]);
|
|
83
|
+
let xDec = BigNumber.from(arrX[1]);
|
|
84
|
+
let xIntBig = xInt.mul(DECIMALS);
|
|
85
|
+
return xIntBig.add(xDec).mul(sg);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
*
|
|
90
|
+
* @param x
|
|
91
|
+
* @param y
|
|
92
|
+
* @returns x * y
|
|
93
|
+
*/
|
|
94
|
+
export function mul64x64(x: BigNumber, y: BigNumber) {
|
|
95
|
+
return x.mul(y).div(ONE_64x64);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
*
|
|
100
|
+
* @param x
|
|
101
|
+
* @param y
|
|
102
|
+
* @returns x / y
|
|
103
|
+
*/
|
|
104
|
+
export function div64x64(x: BigNumber, y: BigNumber) {
|
|
105
|
+
return x.mul(ONE_64x64).div(y);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Determine the liquidation price
|
|
110
|
+
* @param {number} LockedInValueQC - trader locked in value in quote currency
|
|
111
|
+
* @param {number} position - trader position in base currency
|
|
112
|
+
* @param {number} cash_cc - trader available margin cash in collateral currency
|
|
113
|
+
* @param {number} maintenance_margin_rate - maintenance margin ratio
|
|
114
|
+
* @param {number} S3 - collateral to quote conversion (=S2 if base-collateral, =1 if quuote collateral, = index S3 if quanto)
|
|
115
|
+
* @returns {number} Amount to be deposited to have the given leverage when trading into position pos
|
|
116
|
+
*/
|
|
117
|
+
export function calculateLiquidationPriceCollateralBase(
|
|
118
|
+
LockedInValueQC: number,
|
|
119
|
+
position: number,
|
|
120
|
+
cash_cc: number,
|
|
121
|
+
maintenance_margin_rate: number
|
|
122
|
+
): number {
|
|
123
|
+
// correct only if markprice = spot price
|
|
124
|
+
// m_r <= (Sm * Pi - L + cash * S3) / (Sm * |Pi|)
|
|
125
|
+
// -> Sm * (Pi + cash - m_r|Pi|) => L
|
|
126
|
+
return LockedInValueQC / (position - maintenance_margin_rate * Math.abs(position) + cash_cc);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Determine the liquidation price
|
|
131
|
+
* @param {number} LockedInValueQC - trader locked in value in quote currency
|
|
132
|
+
* @param {number} position - trader position in base currency
|
|
133
|
+
* @param {number} cash_cc - trader available margin cash in collateral currency
|
|
134
|
+
* @param {number} maintenance_margin_rate - maintenance margin ratio
|
|
135
|
+
* @param {number} S3 - collateral to quote conversion (=S2 if base-collateral, =1 if quuote collateral, = index S3 if quanto)
|
|
136
|
+
* @param {number} Sm - mark price
|
|
137
|
+
* @returns {number} Amount to be deposited to have the given leverage when trading into position pos
|
|
138
|
+
*/
|
|
139
|
+
export function calculateLiquidationPriceCollateralQuanto(
|
|
140
|
+
LockedInValueQC: number,
|
|
141
|
+
position: number,
|
|
142
|
+
cash_cc: number,
|
|
143
|
+
maintenance_margin_rate: number,
|
|
144
|
+
S3: number,
|
|
145
|
+
Sm: number
|
|
146
|
+
): number {
|
|
147
|
+
// correct only if markprice = spot price and S3 co-moves with Sm
|
|
148
|
+
// m_r = (Sm * Pi - L + cash * S3) / (Sm * |Pi|)
|
|
149
|
+
// m_r = [Sm * Pi - L + cash * S3(0) * (1 + sign(Pi) (Sm / Sm(0) - 1)] / (Sm * |Pi|)
|
|
150
|
+
// -> Sm * (m_r |Pi| - Pi - cash * S3(0) * sign(Pi) / Sm(0)) = - L + cash * S3(0) * (1 - sign(Pi))
|
|
151
|
+
let numerator = -LockedInValueQC + cash_cc * S3 * (1 - Math.sign(position));
|
|
152
|
+
let denominator = maintenance_margin_rate * Math.abs(position) - position - (cash_cc * S3 * Math.sign(position)) / Sm;
|
|
153
|
+
return numerator / denominator;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Determine the liquidation price
|
|
158
|
+
* @param {number} LockedInValueQC - trader locked in value in quote currency
|
|
159
|
+
* @param {number} position - trader position in base currency
|
|
160
|
+
* @param {number} cash_cc - trader available margin cash in collateral currency
|
|
161
|
+
* @param {number} maintenance_margin_rate - maintenance margin ratio
|
|
162
|
+
* @param {number} S3 - collateral to quote conversion (=S2 if base-collateral, =1 if quuote collateral, = index S3 if quanto)
|
|
163
|
+
* @returns {number} Amount to be deposited to have the given leverage when trading into position pos
|
|
164
|
+
*/
|
|
165
|
+
export function calculateLiquidationPriceCollateralQuote(
|
|
166
|
+
LockedInValueQC: number,
|
|
167
|
+
position: number,
|
|
168
|
+
cash_cc: number,
|
|
169
|
+
maintenance_margin_rate: number
|
|
170
|
+
): number {
|
|
171
|
+
// m_r = (Sm * Pi - L + cash ) / (Sm * |Pi|)
|
|
172
|
+
// -> Sm * (m_r |Pi| - Pi) = - L + cash
|
|
173
|
+
let numerator = -LockedInValueQC + cash_cc;
|
|
174
|
+
let denominator = maintenance_margin_rate * Math.abs(position) - position;
|
|
175
|
+
return numerator / denominator;
|
|
176
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import AccountTrade from "./accountTrade";
|
|
2
|
+
import BrokerTool from "./brokerTool";
|
|
3
|
+
import LiquidityProviderTool from "./liquidityProviderTool";
|
|
4
|
+
import MarketData from "./marketData";
|
|
5
|
+
import OrderReferrerTool from "./orderReferrerTool";
|
|
6
|
+
import PerpetualDataHandler from "./perpetualDataHandler";
|
|
7
|
+
import WriteAccessHandler from "./writeAccessHandler";
|
|
8
|
+
// import {
|
|
9
|
+
// NodeSDKConfig,
|
|
10
|
+
// MarginAccount,
|
|
11
|
+
// CollaterlCCY,
|
|
12
|
+
// PoolStaticInfo,
|
|
13
|
+
// PerpetualStaticInfo,
|
|
14
|
+
// ExchangeInfo,
|
|
15
|
+
// PoolState,
|
|
16
|
+
// PerpetualState,
|
|
17
|
+
// Order,
|
|
18
|
+
// SmartContractOrder,
|
|
19
|
+
// } from "./nodeSDKTypes";
|
|
20
|
+
export * from "./nodeSDKTypes";
|
|
21
|
+
export * from "./utils";
|
|
22
|
+
export * from "./d8XMath";
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
AccountTrade,
|
|
26
|
+
BrokerTool,
|
|
27
|
+
LiquidityProviderTool,
|
|
28
|
+
MarketData,
|
|
29
|
+
OrderReferrerTool,
|
|
30
|
+
PerpetualDataHandler,
|
|
31
|
+
WriteAccessHandler,
|
|
32
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import WriteAccessHandler from "./writeAccessHandler";
|
|
2
|
+
import { NodeSDKConfig } from "./nodeSDKTypes";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* LiquidatorTool
|
|
6
|
+
* Methods to liquidate traders
|
|
7
|
+
*/
|
|
8
|
+
export default class LiquidatorTool extends WriteAccessHandler {
|
|
9
|
+
/**
|
|
10
|
+
* Constructor
|
|
11
|
+
* @param config configuration
|
|
12
|
+
* @param privateKey private key of account that trades
|
|
13
|
+
*/
|
|
14
|
+
public constructor(config: NodeSDKConfig, privateKey: string) {
|
|
15
|
+
super(config, privateKey);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
TODO
|
|
20
|
+
*/
|
|
21
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { ethers } from "ethers";
|
|
2
|
+
import WriteAccessHandler from "./writeAccessHandler";
|
|
3
|
+
import { NodeSDKConfig, ERC20_ABI } from "./nodeSDKTypes";
|
|
4
|
+
import PerpetualDataHandler from "./perpetualDataHandler";
|
|
5
|
+
import { floatToABK64x64, dec18ToFloat, ABK64x64ToFloat } from "./d8XMath";
|
|
6
|
+
/**
|
|
7
|
+
* LiquidityProviderTool
|
|
8
|
+
* Methods to provide liquidity
|
|
9
|
+
*/
|
|
10
|
+
export default class LiquidityProviderTool extends WriteAccessHandler {
|
|
11
|
+
/**
|
|
12
|
+
* Constructor
|
|
13
|
+
* @param config configuration
|
|
14
|
+
* @param privateKey private key of account that trades
|
|
15
|
+
*/
|
|
16
|
+
public constructor(config: NodeSDKConfig, privateKey: string) {
|
|
17
|
+
super(config, privateKey);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Returns the value of the share tokens for this liquidity provider
|
|
22
|
+
* in poolSymbol-currency (e.g. MATIC, USDC)
|
|
23
|
+
* @param poolSymbolName pool symbol name (e.g. MATIC)
|
|
24
|
+
*/
|
|
25
|
+
public async getParticipationValue(
|
|
26
|
+
poolSymbolName: string
|
|
27
|
+
): Promise<{ value: number; shareTokenBalance: number; poolShareToken: string }> {
|
|
28
|
+
if (
|
|
29
|
+
this.proxyContract == null ||
|
|
30
|
+
this.signer == null ||
|
|
31
|
+
this.poolStaticInfos.length == 0 ||
|
|
32
|
+
this.provider == null
|
|
33
|
+
) {
|
|
34
|
+
throw Error("no proxy contract or wallet or data initialized. Use createProxyInstance().");
|
|
35
|
+
}
|
|
36
|
+
let poolId = PerpetualDataHandler._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
|
|
37
|
+
|
|
38
|
+
let shareTokenAddr = this.poolStaticInfos[poolId - 1].shareTokenAddr;
|
|
39
|
+
let shareToken = new ethers.Contract(shareTokenAddr, ERC20_ABI, this.signer);
|
|
40
|
+
let dShareTokenBalanceOfAddr = await shareToken.balanceOf(this.traderAddr);
|
|
41
|
+
let shareTokenBalanceOfAddr = dec18ToFloat(dShareTokenBalanceOfAddr);
|
|
42
|
+
if (shareTokenBalanceOfAddr == 0) {
|
|
43
|
+
return { value: 0, shareTokenBalance: 0, poolShareToken: shareTokenAddr };
|
|
44
|
+
}
|
|
45
|
+
let pool = await this.proxyContract.getLiquidityPool(poolId);
|
|
46
|
+
let fPnLParticipantFundCash = pool.fPnLparticipantsCashCC;
|
|
47
|
+
let pnlParticipantFundCash = ABK64x64ToFloat(fPnLParticipantFundCash);
|
|
48
|
+
|
|
49
|
+
let dTotalSupply = await shareToken.totalSupply();
|
|
50
|
+
|
|
51
|
+
let totalSupply = dec18ToFloat(dTotalSupply);
|
|
52
|
+
let valueCC = (shareTokenBalanceOfAddr / totalSupply) * pnlParticipantFundCash;
|
|
53
|
+
return { value: valueCC, shareTokenBalance: shareTokenBalanceOfAddr, poolShareToken: shareTokenAddr };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Add liquidity to the PnL participant fund. The address gets pool shares in return.
|
|
58
|
+
* @param poolname name of pool symbol (e.g. MATIC)
|
|
59
|
+
* @param amountCC amount in pool-collateral currency
|
|
60
|
+
* @return transaction object
|
|
61
|
+
*/
|
|
62
|
+
public async addLiquidity(poolSymbolName: string, amountCC: number): Promise<ethers.providers.TransactionResponse> {
|
|
63
|
+
if (this.proxyContract == null || this.signer == null) {
|
|
64
|
+
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
|
|
65
|
+
}
|
|
66
|
+
let poolId = PerpetualDataHandler._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
|
|
67
|
+
let tx = await this.proxyContract.addLiquidity(poolId, floatToABK64x64(amountCC), {
|
|
68
|
+
gasLimit: this.gasLimit,
|
|
69
|
+
});
|
|
70
|
+
return tx;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Remove liquidity from the pool
|
|
75
|
+
* @param poolSymbolName name of pool symbol (e.g. MATIC)
|
|
76
|
+
* @param amountPoolShares amount in pool-tokens, removes everything if > available amount
|
|
77
|
+
* @return transaction object
|
|
78
|
+
*/
|
|
79
|
+
public async removeLiquidity(
|
|
80
|
+
poolSymbolName: string,
|
|
81
|
+
amountPoolShares: number
|
|
82
|
+
): Promise<ethers.providers.TransactionResponse> {
|
|
83
|
+
if (this.proxyContract == null || this.signer == null) {
|
|
84
|
+
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
|
|
85
|
+
}
|
|
86
|
+
let poolId = PerpetualDataHandler._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
|
|
87
|
+
let tx = await this.proxyContract.addLiquidity(poolId, floatToABK64x64(amountPoolShares), {
|
|
88
|
+
gasLimit: this.gasLimit,
|
|
89
|
+
});
|
|
90
|
+
return tx;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
TODO:
|
|
95
|
+
- add liquidity
|
|
96
|
+
addLiquidity(uint8 _poolId, int128 _fTokenAmount)
|
|
97
|
+
- remove liquidity
|
|
98
|
+
function removeLiquidity(uint8 _poolId, int128 _fShareAmount) external override nonReentrant
|
|
99
|
+
*/
|
|
100
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ExchangeInfo,
|
|
3
|
+
NodeSDKConfig,
|
|
4
|
+
MarginAccount,
|
|
5
|
+
PoolState,
|
|
6
|
+
PerpetualState,
|
|
7
|
+
COLLATERAL_CURRENCY_BASE,
|
|
8
|
+
COLLATERAL_CURRENCY_QUANTO,
|
|
9
|
+
PERP_STATE_STR,
|
|
10
|
+
ZERO_ADDRESS,
|
|
11
|
+
} from "./nodeSDKTypes";
|
|
12
|
+
import { BigNumber, BytesLike, ethers } from "ethers";
|
|
13
|
+
import { floatToABK64x64, ABK64x64ToFloat } from "./d8XMath";
|
|
14
|
+
import { fromBytes4HexString } from "./utils";
|
|
15
|
+
import PerpetualDataHandler from "./perpetualDataHandler";
|
|
16
|
+
import { SmartContractOrder, Order } from "./nodeSDKTypes";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* This class requires no private key and is blockchain read-only.
|
|
20
|
+
* No gas required for the queries here.
|
|
21
|
+
*/
|
|
22
|
+
export default class MarketData extends PerpetualDataHandler {
|
|
23
|
+
public constructor(config: NodeSDKConfig) {
|
|
24
|
+
super(config);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public async createProxyInstance() {
|
|
28
|
+
this.provider = new ethers.providers.JsonRpcProvider(this.nodeURL);
|
|
29
|
+
await this.initContractsAndData(this.provider);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public async exchangeInfo(): Promise<ExchangeInfo> {
|
|
33
|
+
if (this.proxyContract == null) {
|
|
34
|
+
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
35
|
+
}
|
|
36
|
+
return await MarketData._exchangeInfo(this.proxyContract);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get all open orders for a trader-address and a symbol
|
|
41
|
+
* @param traderAddr address of the trader for which we get the open order
|
|
42
|
+
* @param symbol symbol of the form ETH-USD-MATIC
|
|
43
|
+
* @returns array of open orders and corresponding order-ids
|
|
44
|
+
*/
|
|
45
|
+
public async openOrders(traderAddr: string, symbol: string): Promise<{ orders: Order[]; orderIds: string[] }> {
|
|
46
|
+
// open orders requested only for given symbol
|
|
47
|
+
let orderBookContract = this.getOrderBookContract(symbol);
|
|
48
|
+
let [orders, digests] = await Promise.all([
|
|
49
|
+
this.openOrdersOnOrderBook(traderAddr, orderBookContract),
|
|
50
|
+
this.orderIdsOfTrader(traderAddr, orderBookContract),
|
|
51
|
+
]);
|
|
52
|
+
return { orders: orders, orderIds: digests };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public async positionRisk(traderAddr: string, symbol: string): Promise<MarginAccount> {
|
|
56
|
+
if (this.proxyContract == null) {
|
|
57
|
+
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
58
|
+
}
|
|
59
|
+
let mgnAcct = await PerpetualDataHandler.getMarginAccount(traderAddr, symbol, this.symbolToPerpStaticInfo, this.proxyContract);
|
|
60
|
+
return mgnAcct;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Query smart contract to get user orders and convert to user friendly order format
|
|
65
|
+
* @param traderAddr address of trader
|
|
66
|
+
* @param orderBookContract instance of order book
|
|
67
|
+
* @returns array of user friendly order struct
|
|
68
|
+
*/
|
|
69
|
+
protected async openOrdersOnOrderBook(traderAddr: string, orderBookContract: ethers.Contract): Promise<Order[]> {
|
|
70
|
+
let orders: SmartContractOrder[] = await orderBookContract.getOrders(traderAddr, 0, 15);
|
|
71
|
+
//eliminate empty orders and map to user friendly orders
|
|
72
|
+
let userFriendlyOrders: Order[] = new Array<Order>();
|
|
73
|
+
let k = 0;
|
|
74
|
+
while (k < orders.length && orders[k].traderAddr != ZERO_ADDRESS) {
|
|
75
|
+
userFriendlyOrders.push(PerpetualDataHandler.fromSmartContractOrder(orders[k], this.symbolToPerpStaticInfo));
|
|
76
|
+
k++;
|
|
77
|
+
}
|
|
78
|
+
return userFriendlyOrders;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
*
|
|
83
|
+
* @param traderAddr address of the trader
|
|
84
|
+
* @param orderBookContract instance of order book contract
|
|
85
|
+
* @returns array of order-id's
|
|
86
|
+
*/
|
|
87
|
+
protected async orderIdsOfTrader(traderAddr: string, orderBookContract: ethers.Contract): Promise<string[]> {
|
|
88
|
+
let digestsRaw: string[] = await orderBookContract.limitDigestsOfTrader(traderAddr, 0, 15);
|
|
89
|
+
let k: number = 0;
|
|
90
|
+
let digests: string[] = [];
|
|
91
|
+
while (k < digestsRaw.length && BigNumber.from(digestsRaw[k]).gt(0)) {
|
|
92
|
+
digests.push(digestsRaw[k]);
|
|
93
|
+
k++;
|
|
94
|
+
}
|
|
95
|
+
return digests;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public static async _exchangeInfo(_proxyContract: ethers.Contract): Promise<ExchangeInfo> {
|
|
99
|
+
let nestedPerpetualIDs = await PerpetualDataHandler.getNestedPerpetualIds(_proxyContract);
|
|
100
|
+
let info: ExchangeInfo = { pools: [] };
|
|
101
|
+
const numPools = nestedPerpetualIDs.length;
|
|
102
|
+
for (var j = 0; j < numPools; j++) {
|
|
103
|
+
let perpetualIDs = nestedPerpetualIDs[j];
|
|
104
|
+
let pool = await _proxyContract.getLiquidityPool(j + 1);
|
|
105
|
+
let PoolState: PoolState = {
|
|
106
|
+
isRunning: pool.isRunning,
|
|
107
|
+
marginTokenAddr: pool.marginTokenAddress,
|
|
108
|
+
poolShareTokenAddr: pool.shareTokenAddress,
|
|
109
|
+
defaultFundCashCC: ABK64x64ToFloat(pool.fDefaultFundCashCC),
|
|
110
|
+
pnlParticipantCashCC: ABK64x64ToFloat(pool.fPnLparticipantsCashCC),
|
|
111
|
+
totalAMMFundCashCC: ABK64x64ToFloat(pool.fAMMFundCashCC),
|
|
112
|
+
totalTargetAMMFundSizeCC: ABK64x64ToFloat(pool.fTargetAMMFundSize),
|
|
113
|
+
brokerCollateralLotSize: ABK64x64ToFloat(pool.fBrokerCollateralLotSize),
|
|
114
|
+
perpetuals: [],
|
|
115
|
+
};
|
|
116
|
+
for (var k = 0; k < perpetualIDs.length; k++) {
|
|
117
|
+
let perp = await _proxyContract.getPerpetual(perpetualIDs[k]);
|
|
118
|
+
let fIndexS2 = await _proxyContract.getOraclePrice([perp.S2BaseCCY, perp.S2QuoteCCY]);
|
|
119
|
+
let indexS2 = ABK64x64ToFloat(fIndexS2);
|
|
120
|
+
let indexS3 = 1;
|
|
121
|
+
if (perp.eCollateralCurrency == COLLATERAL_CURRENCY_BASE) {
|
|
122
|
+
indexS3 = indexS2;
|
|
123
|
+
} else if (perp.eCollateralCurrency == COLLATERAL_CURRENCY_QUANTO) {
|
|
124
|
+
indexS3 = ABK64x64ToFloat(await _proxyContract.getOraclePrice([perp.S3BaseCCY, perp.S3QuoteCCY]));
|
|
125
|
+
}
|
|
126
|
+
let markPremiumRate = ABK64x64ToFloat(perp.currentMarkPremiumRate.fPrice);
|
|
127
|
+
let currentFundingRateBps = 1e4 * ABK64x64ToFloat(perp.fCurrentFundingRate);
|
|
128
|
+
let state = PERP_STATE_STR[perp.state];
|
|
129
|
+
let PerpetualState: PerpetualState = {
|
|
130
|
+
id: perp.id,
|
|
131
|
+
state: state,
|
|
132
|
+
baseCurrency: fromBytes4HexString(perp.S2BaseCCY),
|
|
133
|
+
quoteCurrency: fromBytes4HexString(perp.S2QuoteCCY),
|
|
134
|
+
indexPrice: indexS2,
|
|
135
|
+
collToQuoteIndexPrice: indexS3,
|
|
136
|
+
markPrice: indexS2 * (1 + markPremiumRate),
|
|
137
|
+
currentFundingRateBps: currentFundingRateBps,
|
|
138
|
+
initialMarginRate: ABK64x64ToFloat(perp.fInitialMarginRate),
|
|
139
|
+
maintenanceMarginRate: ABK64x64ToFloat(perp.fMaintenanceMarginRate),
|
|
140
|
+
openInterestBC: ABK64x64ToFloat(perp.fOpenInterest),
|
|
141
|
+
maxPositionBC: ABK64x64ToFloat(perp.fMaxPositionBC),
|
|
142
|
+
};
|
|
143
|
+
PoolState.perpetuals.push(PerpetualState);
|
|
144
|
+
}
|
|
145
|
+
info.pools.push(PoolState);
|
|
146
|
+
}
|
|
147
|
+
return info;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { BytesLike, BigNumber, BigNumberish } from "ethers";
|
|
2
|
+
export const DEFAULT_CONFIG_TESTNET = "../config/defaultConfig.json";
|
|
3
|
+
export const DEFAULT_CONFIG_MAINNET = "notthereyet";
|
|
4
|
+
export const DEFAULT_CONFIG_TESTNET_NAME = "testnet";
|
|
5
|
+
export const DEFAULT_CONFIG_MAINNET_NAME = "mainnet";
|
|
6
|
+
|
|
7
|
+
export const ERC20_ABI = require("../abi/ERC20.json");
|
|
8
|
+
export const COLLATERAL_CURRENCY_QUOTE = 0;
|
|
9
|
+
export const COLLATERAL_CURRENCY_BASE = 1;
|
|
10
|
+
export const COLLATERAL_CURRENCY_QUANTO = 2;
|
|
11
|
+
export const PERP_STATE_STR = ["INVALID", "INITIALIZING", "NORMAL", "EMERGENCY", "CLEARED"];
|
|
12
|
+
export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
13
|
+
|
|
14
|
+
export const ONE_64x64 = BigNumber.from("0x010000000000000000");
|
|
15
|
+
export const MAX_64x64 = BigNumber.from("0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
|
|
16
|
+
export const MAX_UINT_256 = BigNumber.from(2).pow(256).sub(BigNumber.from(1));
|
|
17
|
+
export const DECIMALS = BigNumber.from(10).pow(BigNumber.from(18));
|
|
18
|
+
|
|
19
|
+
export const ORDER_MAX_DURATION_SEC = 60 * 60 * 24 * 30 * 4;
|
|
20
|
+
|
|
21
|
+
export const MASK_CLOSE_ONLY = BigNumber.from("0x80000000");
|
|
22
|
+
export const MASK_LIMIT_ORDER = BigNumber.from("0x04000000");
|
|
23
|
+
export const MASK_MARKET_ORDER = BigNumber.from("0x40000000");
|
|
24
|
+
export const MASK_STOP_ORDER = BigNumber.from("0x20000000");
|
|
25
|
+
export const MASK_KEEP_POS_LEVERAGE = BigNumber.from("0x08000000");
|
|
26
|
+
|
|
27
|
+
export const ORDER_TYPE_LIMIT = "LIMIT";
|
|
28
|
+
export const ORDER_TYPE_MARKET = "MARKET";
|
|
29
|
+
export const ORDER_TYPE_STOP_MARKET = "STOP_MARKET";
|
|
30
|
+
export const ORDER_TYPE_STOP_LIMIT = "STOP_LIMIT";
|
|
31
|
+
export const BUY_SIDE = "BUY";
|
|
32
|
+
export const SELL_SIDE = "SELL";
|
|
33
|
+
export const CLOSED_SIDE = "CLOSED";
|
|
34
|
+
export interface NodeSDKConfig {
|
|
35
|
+
nodeURL: string;
|
|
36
|
+
proxyAddr: string;
|
|
37
|
+
proxyABILocation: string;
|
|
38
|
+
limitOrderBookFactoryAddr: string;
|
|
39
|
+
limitOrderBookABILocation: string;
|
|
40
|
+
limitOrderBookFactoryABILocation: string;
|
|
41
|
+
gasLimit?: number | undefined;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface MarginAccount {
|
|
45
|
+
symbol: string;
|
|
46
|
+
positionNotionalBaseCCY: number;
|
|
47
|
+
side: string;
|
|
48
|
+
entryPrice: number;
|
|
49
|
+
leverage: number;
|
|
50
|
+
markPrice: number;
|
|
51
|
+
unrealizedPnlQuoteCCY: number;
|
|
52
|
+
unrealizedFundingCollateralCCY: number;
|
|
53
|
+
collateralCC: number;
|
|
54
|
+
liquidationPrice: [number, number | undefined];
|
|
55
|
+
liquidationLvg: number;
|
|
56
|
+
collToQuoteConversion: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export enum CollaterlCCY {
|
|
60
|
+
QUOTE = 0,
|
|
61
|
+
BASE,
|
|
62
|
+
QUANTO,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface PoolStaticInfo {
|
|
66
|
+
poolId: number;
|
|
67
|
+
poolMarginSymbol: string;
|
|
68
|
+
poolMarginTokenAddr: string;
|
|
69
|
+
shareTokenAddr: string;
|
|
70
|
+
oracleFactoryAddr: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface PerpetualStaticInfo {
|
|
74
|
+
id: number;
|
|
75
|
+
limitOrderBookAddr: string;
|
|
76
|
+
maintenanceMarginRate: number;
|
|
77
|
+
collateralCurrencyType: CollaterlCCY;
|
|
78
|
+
S2Symbol: string;
|
|
79
|
+
S3Symbol: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface ExchangeInfo {
|
|
83
|
+
pools: PoolState[];
|
|
84
|
+
}
|
|
85
|
+
export interface PoolState {
|
|
86
|
+
isRunning: boolean;
|
|
87
|
+
marginTokenAddr: string;
|
|
88
|
+
poolShareTokenAddr: string;
|
|
89
|
+
defaultFundCashCC: number;
|
|
90
|
+
pnlParticipantCashCC: number;
|
|
91
|
+
totalAMMFundCashCC: number;
|
|
92
|
+
totalTargetAMMFundSizeCC: number;
|
|
93
|
+
brokerCollateralLotSize: number;
|
|
94
|
+
perpetuals: PerpetualState[];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface PerpetualState {
|
|
98
|
+
id: number;
|
|
99
|
+
state: string;
|
|
100
|
+
baseCurrency: string;
|
|
101
|
+
quoteCurrency: string;
|
|
102
|
+
indexPrice: number;
|
|
103
|
+
collToQuoteIndexPrice: number;
|
|
104
|
+
markPrice: number;
|
|
105
|
+
currentFundingRateBps: number;
|
|
106
|
+
initialMarginRate: number;
|
|
107
|
+
maintenanceMarginRate: number;
|
|
108
|
+
openInterestBC: number;
|
|
109
|
+
maxPositionBC: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface Order {
|
|
113
|
+
symbol: string;
|
|
114
|
+
side: string;
|
|
115
|
+
type: string;
|
|
116
|
+
quantity: number;
|
|
117
|
+
reduceOnly?: boolean | undefined;
|
|
118
|
+
limitPrice?: number | undefined;
|
|
119
|
+
keepPositionLvg?: boolean | undefined;
|
|
120
|
+
brokerFeeTbps?: number | undefined;
|
|
121
|
+
brokerAddr?: string | undefined;
|
|
122
|
+
brokerSignature?: BytesLike | undefined;
|
|
123
|
+
stopPrice?: number | undefined;
|
|
124
|
+
leverage?: number | undefined;
|
|
125
|
+
deadline?: number | undefined;
|
|
126
|
+
timestamp: number;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface SmartContractOrder {
|
|
130
|
+
flags: BigNumberish;
|
|
131
|
+
iPerpetualId: BigNumberish;
|
|
132
|
+
brokerFeeTbps: BigNumberish;
|
|
133
|
+
traderAddr: string;
|
|
134
|
+
brokerAddr: string;
|
|
135
|
+
referrerAddr: string;
|
|
136
|
+
brokerSignature: BytesLike;
|
|
137
|
+
fAmount: BigNumberish;
|
|
138
|
+
fLimitPrice: BigNumberish;
|
|
139
|
+
fTriggerPrice: BigNumberish;
|
|
140
|
+
fLeverage: BigNumberish;
|
|
141
|
+
iDeadline: BigNumberish;
|
|
142
|
+
createdTimestamp: BigNumberish;
|
|
143
|
+
}
|
|
144
|
+
/*
|
|
145
|
+
t32 flags;
|
|
146
|
+
uint24 iPerpetualId;
|
|
147
|
+
uint16 brokerFeeTbps;
|
|
148
|
+
address traderAddr;
|
|
149
|
+
address brokerAddr;
|
|
150
|
+
address referrerAddr;
|
|
151
|
+
bytes brokerSignature;
|
|
152
|
+
int128 fAmount;
|
|
153
|
+
int128 fLimitPrice;
|
|
154
|
+
int128 fTriggerPrice;
|
|
155
|
+
int128 fLeverage; // 0 if deposit and trade separate
|
|
156
|
+
uint256 iDeadline;
|
|
157
|
+
uint256 createdTimestamp;
|
|
158
|
+
*/
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import WriteAccessHandler from "./writeAccessHandler";
|
|
2
|
+
import { NodeSDKConfig } from "./nodeSDKTypes";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* OrderReferrerTool
|
|
6
|
+
* Methods to refer orders from the limit order book
|
|
7
|
+
*/
|
|
8
|
+
export default class OrderReferrerTool extends WriteAccessHandler {
|
|
9
|
+
/**
|
|
10
|
+
* Constructor
|
|
11
|
+
* @param config configuration
|
|
12
|
+
* @param privateKey private key of account that trades
|
|
13
|
+
*/
|
|
14
|
+
public constructor(config: NodeSDKConfig, privateKey: string) {
|
|
15
|
+
super(config, privateKey);
|
|
16
|
+
}
|
|
17
|
+
}
|