@d8x/perpetuals-sdk 0.0.21 → 0.0.22
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/abi/IPerpetualManager.json +51 -2
- package/abi/LimitOrderBook.json +75 -45
- package/config/defaultConfig.json +5 -4
- package/config/oldConfig.json +5 -4
- package/config/symbolList.json +9 -0
- package/dist/accountTrade.js +2 -2
- package/dist/d8XMath.d.ts +16 -0
- package/dist/d8XMath.js +48 -1
- package/dist/liquiditatorTool.d.ts +14 -0
- package/dist/liquiditatorTool.js +21 -0
- package/dist/marketData.d.ts +41 -5
- package/dist/marketData.js +139 -6
- package/dist/nodeSDKTypes.d.ts +14 -0
- package/dist/orderReferrerTool.js +4 -4
- package/dist/perpetualDataHandler.d.ts +21 -4
- package/dist/perpetualDataHandler.js +71 -24
- package/dist/perpetualEventHandler.d.ts +181 -0
- package/dist/perpetualEventHandler.js +390 -0
- package/dist/utils.d.ts +18 -0
- package/dist/utils.js +37 -1
- package/package.json +1 -1
- package/src/accountTrade.ts +2 -2
- package/src/d8XMath.ts +85 -0
- package/src/liquidityProviderTool.ts +0 -8
- package/src/marketData.ts +226 -8
- package/src/nodeSDKTypes.ts +16 -0
- package/src/orderReferrerTool.ts +4 -4
- package/src/perpetualDataHandler.ts +93 -27
- package/src/perpetualEventHandler.ts +441 -0
- package/src/utils.ts +36 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { BigNumber } from "ethers";
|
|
2
|
+
import { PerpetualState, ExchangeInfo, SmartContractOrder, MarginAccount, OrderStruct, TradeEvent } from "./nodeSDKTypes";
|
|
3
|
+
import MarketData from "./marketData";
|
|
4
|
+
/**
|
|
5
|
+
* This class handles events and stores relevant variables
|
|
6
|
+
* as member variables. The events change the state of the member variables:
|
|
7
|
+
* mktData : MarketData relevant market data with current state (e.g. index price)
|
|
8
|
+
* ordersInPerpetual: Map<number, OrderStruct> all open orders for the given trader
|
|
9
|
+
* positionInPerpetual: Map<number, MarginAccount> all open positions for the given trader
|
|
10
|
+
*
|
|
11
|
+
* TODO:
|
|
12
|
+
* - update functions for midprice & index & collateral prices without event
|
|
13
|
+
* - testing
|
|
14
|
+
*
|
|
15
|
+
* Get data:
|
|
16
|
+
* - getPerpetualData(perp id (string) or symbol) : PerpetualState. This is a reference!
|
|
17
|
+
* - getExchangeInfo() : ExchangeInfo. This is a reference!
|
|
18
|
+
* - getCurrentPositionRisk(perp id (string) or symbol) : MarginAccount. This is a reference!
|
|
19
|
+
* - getOrdersInPerpetualMap : Map<number, OrderStruct>. This is a reference!
|
|
20
|
+
* - getpositionInPerpetualMap : Map<number, MarginAccount>. This is a reference!
|
|
21
|
+
*
|
|
22
|
+
* Construct with a trader address and a marketData object
|
|
23
|
+
* Initialize to gather all the relevant data.
|
|
24
|
+
* Send event variables to event handler "on<EventName>" - this updates members
|
|
25
|
+
* - [x] onUpdateMarkPrice : emitted on proxy; updates markprice and index price data
|
|
26
|
+
* - [x] onUpdateUpdateFundingRate : emitted on proxy; sets funding rate
|
|
27
|
+
* - [x] onExecutionFailed : emitted on order book; removes an open order
|
|
28
|
+
* - [x] onPerpetualLimitOrderCancelled : emitted on order book; removes an open order
|
|
29
|
+
* - [x] onPerpetualLimitOrderCreated : emitted on order book; adds an open order to the data
|
|
30
|
+
* - [x] async onUpdateMarginAccount : emitted on proxy; updates position data and open interest
|
|
31
|
+
* - [x] onTrade : emitted on proxy; returns TradeEvent to be displayed
|
|
32
|
+
*/
|
|
33
|
+
export default class PerpetualEventHandler {
|
|
34
|
+
private mktData;
|
|
35
|
+
private traderAddr;
|
|
36
|
+
private ordersInPerpetual;
|
|
37
|
+
private positionInPerpetual;
|
|
38
|
+
private exchangeInfo;
|
|
39
|
+
constructor(mktData: MarketData, traderAddr: string);
|
|
40
|
+
/**
|
|
41
|
+
* Call this async function to initialize the
|
|
42
|
+
* market data
|
|
43
|
+
*/
|
|
44
|
+
initialize(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Get the current exchange info
|
|
47
|
+
* @returns exchange info
|
|
48
|
+
*/
|
|
49
|
+
getExchangeInfo(): ExchangeInfo | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* getOrdersInPerpetualMap
|
|
52
|
+
* @returns this.ordersInPerpetual
|
|
53
|
+
*/
|
|
54
|
+
getOrdersInPerpetualMap(): Map<number, OrderStruct>;
|
|
55
|
+
/**
|
|
56
|
+
* getpositionInPerpetualMap
|
|
57
|
+
* @returns this.positionInPerpetual
|
|
58
|
+
*/
|
|
59
|
+
getpositionInPerpetualMap(): Map<number, MarginAccount>;
|
|
60
|
+
/**
|
|
61
|
+
* Get the data for a perpetual with a given index
|
|
62
|
+
* @param perpetualIdOrSymbol perpetual idx as string or symbol for which we want the data
|
|
63
|
+
* @returns perpetual data for this idx
|
|
64
|
+
*/
|
|
65
|
+
getPerpetualData(perpetualIdOrSymbol: string): PerpetualState | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Get the trader's current position risk (margin account data)
|
|
68
|
+
* @param perpetualIdOrSymbol perpetual id as string ('100003') or symbol ('BTC-USD-MATIC')
|
|
69
|
+
* @returns undefined if no position or margin account (='position risk')
|
|
70
|
+
*/
|
|
71
|
+
getCurrentPositionRisk(perpetualIdOrSymbol: string): MarginAccount | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Update the following prices:
|
|
74
|
+
* - index price
|
|
75
|
+
* - collateral price
|
|
76
|
+
* - mid-price
|
|
77
|
+
* @param perpetualIdOrSymbol perpetual id as string ('100003') or symbol ('BTC-USD-MATIC')
|
|
78
|
+
*/
|
|
79
|
+
updatePrices(perpetualIdOrSymbol: string): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Handle the event UpdateMarkPrice and update relevant
|
|
82
|
+
* data
|
|
83
|
+
* @param perpetualId perpetual Id
|
|
84
|
+
* @param fMarkPricePremium premium rate in ABDK format
|
|
85
|
+
* @param fSpotIndexPrice spot index price in ABDK format
|
|
86
|
+
* @returns void
|
|
87
|
+
*/
|
|
88
|
+
onUpdateMarkPrice(perpetualId: number, fMarkPricePremium: BigNumber, fSpotIndexPrice: BigNumber): void;
|
|
89
|
+
/**
|
|
90
|
+
* Handle the event UpdateFundingRate and update relevant
|
|
91
|
+
* data
|
|
92
|
+
* UpdateFundingRate(uint24 indexed perpetualId, int128 fFundingRate)
|
|
93
|
+
* @param fFundingRate funding rate in ABDK format
|
|
94
|
+
*/
|
|
95
|
+
onUpdateUpdateFundingRate(perpetualId: number, fFundingRate: BigNumber): void;
|
|
96
|
+
/**
|
|
97
|
+
* event ExecutionFailed(
|
|
98
|
+
uint24 indexed perpetualId,
|
|
99
|
+
address indexed trader,
|
|
100
|
+
bytes32 digest,
|
|
101
|
+
string reason
|
|
102
|
+
);
|
|
103
|
+
* @param perpetualId id of the perpetual
|
|
104
|
+
* @param trader address of the trader
|
|
105
|
+
* @param digest digest of the order/cancel order
|
|
106
|
+
* @param reason reason why the execution failed
|
|
107
|
+
*/
|
|
108
|
+
onExecutionFailed(perpetualId: number, trader: string, digest: string, reason: string): void;
|
|
109
|
+
/**
|
|
110
|
+
* Event emitted by perpetual proxy
|
|
111
|
+
* event PerpetualLimitOrderCancelled(bytes32 indexed orderHash);
|
|
112
|
+
* @param orderId string order id/digest
|
|
113
|
+
*/
|
|
114
|
+
onPerpetualLimitOrderCancelled(orderId: string): void;
|
|
115
|
+
/**
|
|
116
|
+
* event PerpetualLimitOrderCreated(
|
|
117
|
+
* uint24 indexed perpetualId,
|
|
118
|
+
* address indexed trader,
|
|
119
|
+
* address referrerAddr,
|
|
120
|
+
* address brokerAddr,
|
|
121
|
+
* Order order,
|
|
122
|
+
* bytes32 digest
|
|
123
|
+
*)
|
|
124
|
+
* @param perpetualId id of the perpetual
|
|
125
|
+
* @param trader address of the trader
|
|
126
|
+
* @param referrerAddr address of the referrer
|
|
127
|
+
* @param brokerAddr address of the broker
|
|
128
|
+
* @param Order order struct
|
|
129
|
+
* @param digest order id
|
|
130
|
+
*/
|
|
131
|
+
onPerpetualLimitOrderCreated(perpetualId: number, trader: string, referrerAddr: string, brokerAddr: string, Order: SmartContractOrder, digest: string): void;
|
|
132
|
+
/**
|
|
133
|
+
* This function is async -> queries the margin account
|
|
134
|
+
* @param perpetualId id of the perpetual
|
|
135
|
+
* @param trader trader address
|
|
136
|
+
* @param positionId position id
|
|
137
|
+
* @param fPositionBC position size in base currency
|
|
138
|
+
* @param fCashCC margin collateral in margin account
|
|
139
|
+
* @param fLockedInValueQC pos*average opening price
|
|
140
|
+
* @param fFundingPaymentCC funding payment made
|
|
141
|
+
* @param fOpenInterestBC open interest
|
|
142
|
+
*/
|
|
143
|
+
onUpdateMarginAccount(perpetualId: number, trader: string, positionId: string, fPositionBC: BigNumber, fCashCC: BigNumber, fLockedInValueQC: BigNumber, fFundingPaymentCC: BigNumber, fOpenInterestBC: BigNumber): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
*
|
|
146
|
+
* @param perpetualId perpetual id
|
|
147
|
+
* @param trader trader address
|
|
148
|
+
* @param positionId position id
|
|
149
|
+
* @param order order struct
|
|
150
|
+
* @param orderDigest order id
|
|
151
|
+
* @param newPositionSizeBC new pos size in base currency ABDK
|
|
152
|
+
* @param price price in ABDK format
|
|
153
|
+
* @returns trade event data in regular number format
|
|
154
|
+
*/
|
|
155
|
+
onTrade(perpetualId: number, trader: string, positionId: string, order: SmartContractOrder, orderDigest: string, newPositionSizeBC: BigNumber, price: BigNumber): TradeEvent;
|
|
156
|
+
/**
|
|
157
|
+
* static function to find the number of the OrderStruct with given orderId
|
|
158
|
+
* @param orderId id/digest of order
|
|
159
|
+
* @param orderMap mapping for perpetualId->OrderStruct
|
|
160
|
+
* @returns id of perpetual that contains order with id = orderId or undefined
|
|
161
|
+
*/
|
|
162
|
+
private static findOrderForId;
|
|
163
|
+
/**
|
|
164
|
+
* Delete the order with given id from the class member data
|
|
165
|
+
* @param orderStructs array of order struct as stored for the trader and a given perpetual
|
|
166
|
+
* @param orderId digest/order id
|
|
167
|
+
* @returns void
|
|
168
|
+
*/
|
|
169
|
+
private static deleteOrder;
|
|
170
|
+
/**
|
|
171
|
+
* UpdateMarkPrice(
|
|
172
|
+
* uint24 indexed perpetualId,
|
|
173
|
+
* int128 fMarkPricePremium,
|
|
174
|
+
* int128 fSpotIndexPrice
|
|
175
|
+
* )
|
|
176
|
+
* @param fMarkPricePremium premium rate in ABDK format
|
|
177
|
+
* @param fSpotIndexPrice spot index price in ABDK format
|
|
178
|
+
* @returns mark price and spot index in float
|
|
179
|
+
*/
|
|
180
|
+
private static ConvertUpdateMarkPrice;
|
|
181
|
+
}
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const d8XMath_1 = require("./d8XMath");
|
|
13
|
+
const nodeSDKTypes_1 = require("./nodeSDKTypes");
|
|
14
|
+
const process_1 = require("process");
|
|
15
|
+
/**
|
|
16
|
+
* This class handles events and stores relevant variables
|
|
17
|
+
* as member variables. The events change the state of the member variables:
|
|
18
|
+
* mktData : MarketData relevant market data with current state (e.g. index price)
|
|
19
|
+
* ordersInPerpetual: Map<number, OrderStruct> all open orders for the given trader
|
|
20
|
+
* positionInPerpetual: Map<number, MarginAccount> all open positions for the given trader
|
|
21
|
+
*
|
|
22
|
+
* TODO:
|
|
23
|
+
* - update functions for midprice & index & collateral prices without event
|
|
24
|
+
* - testing
|
|
25
|
+
*
|
|
26
|
+
* Get data:
|
|
27
|
+
* - getPerpetualData(perp id (string) or symbol) : PerpetualState. This is a reference!
|
|
28
|
+
* - getExchangeInfo() : ExchangeInfo. This is a reference!
|
|
29
|
+
* - getCurrentPositionRisk(perp id (string) or symbol) : MarginAccount. This is a reference!
|
|
30
|
+
* - getOrdersInPerpetualMap : Map<number, OrderStruct>. This is a reference!
|
|
31
|
+
* - getpositionInPerpetualMap : Map<number, MarginAccount>. This is a reference!
|
|
32
|
+
*
|
|
33
|
+
* Construct with a trader address and a marketData object
|
|
34
|
+
* Initialize to gather all the relevant data.
|
|
35
|
+
* Send event variables to event handler "on<EventName>" - this updates members
|
|
36
|
+
* - [x] onUpdateMarkPrice : emitted on proxy; updates markprice and index price data
|
|
37
|
+
* - [x] onUpdateUpdateFundingRate : emitted on proxy; sets funding rate
|
|
38
|
+
* - [x] onExecutionFailed : emitted on order book; removes an open order
|
|
39
|
+
* - [x] onPerpetualLimitOrderCancelled : emitted on order book; removes an open order
|
|
40
|
+
* - [x] onPerpetualLimitOrderCreated : emitted on order book; adds an open order to the data
|
|
41
|
+
* - [x] async onUpdateMarginAccount : emitted on proxy; updates position data and open interest
|
|
42
|
+
* - [x] onTrade : emitted on proxy; returns TradeEvent to be displayed
|
|
43
|
+
*/
|
|
44
|
+
class PerpetualEventHandler {
|
|
45
|
+
constructor(mktData, traderAddr) {
|
|
46
|
+
this.mktData = mktData;
|
|
47
|
+
this.traderAddr = traderAddr;
|
|
48
|
+
this.ordersInPerpetual = new Map();
|
|
49
|
+
this.positionInPerpetual = new Map();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Call this async function to initialize the
|
|
53
|
+
* market data
|
|
54
|
+
*/
|
|
55
|
+
initialize() {
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
this.exchangeInfo = yield this.mktData.exchangeInfo();
|
|
58
|
+
// loop through all pools and perpetuals and get
|
|
59
|
+
// open positions and open orders
|
|
60
|
+
for (let k = 0; k < this.exchangeInfo.pools.length; k++) {
|
|
61
|
+
let poolState = this.exchangeInfo.pools[k];
|
|
62
|
+
let poolSymbol = poolState.poolSymbol;
|
|
63
|
+
for (let j = 0; j < poolState.perpetuals.length; j++) {
|
|
64
|
+
let perpState = poolState.perpetuals[j];
|
|
65
|
+
let perpSymbol = perpState.baseCurrency + "-" + perpState.quoteCurrency + "-" + poolSymbol;
|
|
66
|
+
let orders = yield this.mktData.openOrders(this.traderAddr, perpSymbol);
|
|
67
|
+
let perpId = perpState.id;
|
|
68
|
+
this.ordersInPerpetual.set(perpId, orders);
|
|
69
|
+
let position = yield this.mktData.positionRisk(this.traderAddr, perpSymbol);
|
|
70
|
+
this.positionInPerpetual.set(perpId, position);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get the current exchange info
|
|
77
|
+
* @returns exchange info
|
|
78
|
+
*/
|
|
79
|
+
getExchangeInfo() {
|
|
80
|
+
return this.exchangeInfo;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* getOrdersInPerpetualMap
|
|
84
|
+
* @returns this.ordersInPerpetual
|
|
85
|
+
*/
|
|
86
|
+
getOrdersInPerpetualMap() {
|
|
87
|
+
return this.ordersInPerpetual;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* getpositionInPerpetualMap
|
|
91
|
+
* @returns this.positionInPerpetual
|
|
92
|
+
*/
|
|
93
|
+
getpositionInPerpetualMap() {
|
|
94
|
+
return this.positionInPerpetual;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get the data for a perpetual with a given index
|
|
98
|
+
* @param perpetualIdOrSymbol perpetual idx as string or symbol for which we want the data
|
|
99
|
+
* @returns perpetual data for this idx
|
|
100
|
+
*/
|
|
101
|
+
getPerpetualData(perpetualIdOrSymbol) {
|
|
102
|
+
var _a;
|
|
103
|
+
let perpId = Number(perpetualIdOrSymbol);
|
|
104
|
+
if (isNaN(perpId)) {
|
|
105
|
+
perpId = this.mktData.getPerpIdFromSymbol(perpetualIdOrSymbol);
|
|
106
|
+
}
|
|
107
|
+
//uint24 perpetualId = uint24(_iPoolId) * 100_000 + iPerpetualIndex;
|
|
108
|
+
let poolIdx = Math.floor(perpId / 100000);
|
|
109
|
+
let perpetuals = (_a = this.exchangeInfo) === null || _a === void 0 ? void 0 : _a.pools[poolIdx].perpetuals;
|
|
110
|
+
if (perpetuals == undefined) {
|
|
111
|
+
(0, process_1.emitWarning)(`exchangeInfo not found, initialize perpetualEventHandler`);
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
// find perpetual
|
|
115
|
+
let k;
|
|
116
|
+
for (k = 0; k < (perpetuals === null || perpetuals === void 0 ? void 0 : perpetuals.length) && perpetuals[k].id != perpId; k++)
|
|
117
|
+
;
|
|
118
|
+
if (perpetuals[k].id != perpId) {
|
|
119
|
+
(0, process_1.emitWarning)(`getPerpetualData: perpetual id ${perpId} not found`);
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
return perpetuals[k];
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get the trader's current position risk (margin account data)
|
|
126
|
+
* @param perpetualIdOrSymbol perpetual id as string ('100003') or symbol ('BTC-USD-MATIC')
|
|
127
|
+
* @returns undefined if no position or margin account (='position risk')
|
|
128
|
+
*/
|
|
129
|
+
getCurrentPositionRisk(perpetualIdOrSymbol) {
|
|
130
|
+
let perpId = Number(perpetualIdOrSymbol);
|
|
131
|
+
if (isNaN(perpId)) {
|
|
132
|
+
perpId = this.mktData.getPerpIdFromSymbol(perpetualIdOrSymbol);
|
|
133
|
+
}
|
|
134
|
+
return this.positionInPerpetual.get(perpId);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Update the following prices:
|
|
138
|
+
* - index price
|
|
139
|
+
* - collateral price
|
|
140
|
+
* - mid-price
|
|
141
|
+
* @param perpetualIdOrSymbol perpetual id as string ('100003') or symbol ('BTC-USD-MATIC')
|
|
142
|
+
*/
|
|
143
|
+
updatePrices(perpetualIdOrSymbol) {
|
|
144
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
145
|
+
let perpId = Number(perpetualIdOrSymbol);
|
|
146
|
+
let symbol = perpetualIdOrSymbol;
|
|
147
|
+
if (!isNaN(perpId)) {
|
|
148
|
+
let sym = this.mktData.getSymbolFromPerpId(perpId);
|
|
149
|
+
if (sym == undefined) {
|
|
150
|
+
throw new Error(`Symbol not found for perpetual ${perpId}`);
|
|
151
|
+
}
|
|
152
|
+
symbol = sym;
|
|
153
|
+
}
|
|
154
|
+
let perpState = yield this.mktData.getPerpetualState(symbol);
|
|
155
|
+
let perp = this.getPerpetualData(symbol);
|
|
156
|
+
if (perp == undefined) {
|
|
157
|
+
throw new Error(`Perpetual not found: ${symbol}`);
|
|
158
|
+
}
|
|
159
|
+
perp.state = perpState.state;
|
|
160
|
+
perp.indexPrice = perpState.indexPrice;
|
|
161
|
+
perp.collToQuoteIndexPrice = perpState.collToQuoteIndexPrice;
|
|
162
|
+
perp.markPrice = perpState.markPrice;
|
|
163
|
+
perp.midPrice = perpState.midPrice;
|
|
164
|
+
perp.currentFundingRateBps = perpState.currentFundingRateBps;
|
|
165
|
+
perp.openInterestBC = perpState.openInterestBC;
|
|
166
|
+
perp.maxPositionBC = perpState.maxPositionBC;
|
|
167
|
+
perp.indexPrice = perpState.indexPrice;
|
|
168
|
+
perp.collToQuoteIndexPrice = perpState.collToQuoteIndexPrice;
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Handle the event UpdateMarkPrice and update relevant
|
|
173
|
+
* data
|
|
174
|
+
* @param perpetualId perpetual Id
|
|
175
|
+
* @param fMarkPricePremium premium rate in ABDK format
|
|
176
|
+
* @param fSpotIndexPrice spot index price in ABDK format
|
|
177
|
+
* @returns void
|
|
178
|
+
*/
|
|
179
|
+
onUpdateMarkPrice(perpetualId, fMarkPricePremium, fSpotIndexPrice) {
|
|
180
|
+
let [newMarkPrice, newIndexPrice] = PerpetualEventHandler.ConvertUpdateMarkPrice(fMarkPricePremium, fSpotIndexPrice);
|
|
181
|
+
let perpetual = this.getPerpetualData(perpetualId.toString());
|
|
182
|
+
if (perpetual == undefined) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
perpetual.markPrice = newMarkPrice;
|
|
186
|
+
perpetual.indexPrice = newIndexPrice;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Handle the event UpdateFundingRate and update relevant
|
|
190
|
+
* data
|
|
191
|
+
* UpdateFundingRate(uint24 indexed perpetualId, int128 fFundingRate)
|
|
192
|
+
* @param fFundingRate funding rate in ABDK format
|
|
193
|
+
*/
|
|
194
|
+
onUpdateUpdateFundingRate(perpetualId, fFundingRate) {
|
|
195
|
+
let newRate = (0, d8XMath_1.ABK64x64ToFloat)(fFundingRate);
|
|
196
|
+
let perpetual = this.getPerpetualData(perpetualId.toString());
|
|
197
|
+
if (perpetual == undefined) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
perpetual.currentFundingRateBps = newRate * 1e4;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* event ExecutionFailed(
|
|
204
|
+
uint24 indexed perpetualId,
|
|
205
|
+
address indexed trader,
|
|
206
|
+
bytes32 digest,
|
|
207
|
+
string reason
|
|
208
|
+
);
|
|
209
|
+
* @param perpetualId id of the perpetual
|
|
210
|
+
* @param trader address of the trader
|
|
211
|
+
* @param digest digest of the order/cancel order
|
|
212
|
+
* @param reason reason why the execution failed
|
|
213
|
+
*/
|
|
214
|
+
onExecutionFailed(perpetualId, trader, digest, reason) {
|
|
215
|
+
if (trader != this.traderAddr) {
|
|
216
|
+
(0, process_1.emitWarning)(`onExecutionFailed: trader ${trader} not relevant`);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
// remove order from open orders
|
|
220
|
+
let orderStructs = this.ordersInPerpetual.get(perpetualId);
|
|
221
|
+
if (orderStructs == undefined) {
|
|
222
|
+
(0, process_1.emitWarning)(`onExecutionFailed: no order found for perpetual ${perpetualId}`);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (reason == "cancel delay required") {
|
|
226
|
+
// canceling failed. We don't remove the order
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
PerpetualEventHandler.deleteOrder(orderStructs, digest);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Event emitted by perpetual proxy
|
|
233
|
+
* event PerpetualLimitOrderCancelled(bytes32 indexed orderHash);
|
|
234
|
+
* @param orderId string order id/digest
|
|
235
|
+
*/
|
|
236
|
+
onPerpetualLimitOrderCancelled(orderId) {
|
|
237
|
+
// remove order from open orders
|
|
238
|
+
let perpId = PerpetualEventHandler.findOrderForId(orderId, this.ordersInPerpetual);
|
|
239
|
+
if (perpId == undefined) {
|
|
240
|
+
(0, process_1.emitWarning)(`onPerpetualLimitOrderCancelled: no order found with id ${orderId}`);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
let orderStruct = this.ordersInPerpetual.get(perpId);
|
|
244
|
+
PerpetualEventHandler.deleteOrder(orderStruct, orderId);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* event PerpetualLimitOrderCreated(
|
|
248
|
+
* uint24 indexed perpetualId,
|
|
249
|
+
* address indexed trader,
|
|
250
|
+
* address referrerAddr,
|
|
251
|
+
* address brokerAddr,
|
|
252
|
+
* Order order,
|
|
253
|
+
* bytes32 digest
|
|
254
|
+
*)
|
|
255
|
+
* @param perpetualId id of the perpetual
|
|
256
|
+
* @param trader address of the trader
|
|
257
|
+
* @param referrerAddr address of the referrer
|
|
258
|
+
* @param brokerAddr address of the broker
|
|
259
|
+
* @param Order order struct
|
|
260
|
+
* @param digest order id
|
|
261
|
+
*/
|
|
262
|
+
onPerpetualLimitOrderCreated(perpetualId, trader, referrerAddr, brokerAddr, Order, digest) {
|
|
263
|
+
if (trader != this.traderAddr) {
|
|
264
|
+
(0, process_1.emitWarning)(`onPerpetualLimitOrderCreated: trader ${trader} not relevant`);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
let order = this.mktData.smartContractOrderToOrder(Order);
|
|
268
|
+
let orderStruct = this.ordersInPerpetual.get(perpetualId);
|
|
269
|
+
if (orderStruct == undefined) {
|
|
270
|
+
// no order for this perpetual so far
|
|
271
|
+
this.ordersInPerpetual.set(perpetualId, { orders: [order], orderIds: [digest] });
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
orderStruct.orderIds.push(digest);
|
|
275
|
+
orderStruct.orders.push(order);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* This function is async -> queries the margin account
|
|
280
|
+
* @param perpetualId id of the perpetual
|
|
281
|
+
* @param trader trader address
|
|
282
|
+
* @param positionId position id
|
|
283
|
+
* @param fPositionBC position size in base currency
|
|
284
|
+
* @param fCashCC margin collateral in margin account
|
|
285
|
+
* @param fLockedInValueQC pos*average opening price
|
|
286
|
+
* @param fFundingPaymentCC funding payment made
|
|
287
|
+
* @param fOpenInterestBC open interest
|
|
288
|
+
*/
|
|
289
|
+
onUpdateMarginAccount(perpetualId, trader, positionId, fPositionBC, fCashCC, fLockedInValueQC, fFundingPaymentCC, fOpenInterestBC) {
|
|
290
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
291
|
+
let perpetual = this.getPerpetualData(perpetualId.toString());
|
|
292
|
+
if (perpetual == undefined) {
|
|
293
|
+
(0, process_1.emitWarning)(`onUpdateMarginAccount: perpetual ${perpetualId} not found`);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
perpetual.openInterestBC = (0, d8XMath_1.ABK64x64ToFloat)(fOpenInterestBC);
|
|
297
|
+
if (trader != this.traderAddr) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
let perpetualIdStr = perpetualId.toString();
|
|
301
|
+
let margin = yield this.mktData.positionRisk(this.traderAddr, perpetualIdStr);
|
|
302
|
+
this.positionInPerpetual.set(perpetualId, margin);
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
*
|
|
307
|
+
* @param perpetualId perpetual id
|
|
308
|
+
* @param trader trader address
|
|
309
|
+
* @param positionId position id
|
|
310
|
+
* @param order order struct
|
|
311
|
+
* @param orderDigest order id
|
|
312
|
+
* @param newPositionSizeBC new pos size in base currency ABDK
|
|
313
|
+
* @param price price in ABDK format
|
|
314
|
+
* @returns trade event data in regular number format
|
|
315
|
+
*/
|
|
316
|
+
onTrade(perpetualId, trader, positionId, order, orderDigest, newPositionSizeBC, price) {
|
|
317
|
+
// remove order digest from open orders
|
|
318
|
+
let orderStructs = this.ordersInPerpetual.get(perpetualId);
|
|
319
|
+
if (orderStructs == undefined) {
|
|
320
|
+
(0, process_1.emitWarning)(`onTrade: executed order not found ${orderDigest}`);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
PerpetualEventHandler.deleteOrder(orderStructs, orderDigest);
|
|
324
|
+
}
|
|
325
|
+
// return transformed trade info
|
|
326
|
+
return {
|
|
327
|
+
perpetualId: perpetualId,
|
|
328
|
+
positionId: positionId,
|
|
329
|
+
orderId: orderDigest,
|
|
330
|
+
newPositionSizeBC: (0, d8XMath_1.ABK64x64ToFloat)(newPositionSizeBC),
|
|
331
|
+
executionPrice: (0, d8XMath_1.ABK64x64ToFloat)(newPositionSizeBC),
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* static function to find the number of the OrderStruct with given orderId
|
|
336
|
+
* @param orderId id/digest of order
|
|
337
|
+
* @param orderMap mapping for perpetualId->OrderStruct
|
|
338
|
+
* @returns id of perpetual that contains order with id = orderId or undefined
|
|
339
|
+
*/
|
|
340
|
+
static findOrderForId(orderId, orderMap) {
|
|
341
|
+
/*orderMapMap<number, {
|
|
342
|
+
orders: Order[];
|
|
343
|
+
orderIds: string[];*/
|
|
344
|
+
for (const perpId of orderMap.keys()) {
|
|
345
|
+
let orderStructs = orderMap.get(perpId);
|
|
346
|
+
if (orderStructs === null || orderStructs === void 0 ? void 0 : orderStructs.orderIds.includes(orderId)) {
|
|
347
|
+
return perpId;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return undefined;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Delete the order with given id from the class member data
|
|
354
|
+
* @param orderStructs array of order struct as stored for the trader and a given perpetual
|
|
355
|
+
* @param orderId digest/order id
|
|
356
|
+
* @returns void
|
|
357
|
+
*/
|
|
358
|
+
static deleteOrder(orderStructs, orderId) {
|
|
359
|
+
// find order
|
|
360
|
+
let k;
|
|
361
|
+
for (k = 0; k < orderStructs.orderIds.length && orderStructs.orderIds[k] != orderId; k++)
|
|
362
|
+
;
|
|
363
|
+
if (orderStructs.orderIds[k] != orderId) {
|
|
364
|
+
(0, process_1.emitWarning)(`deleteOrder: no order found with digest ${orderId}`);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
// delete element k on reference of orders
|
|
368
|
+
orderStructs.orders[k] = orderStructs.orders[orderStructs.orders.length - 1];
|
|
369
|
+
orderStructs.orders.pop();
|
|
370
|
+
orderStructs.orderIds[k] = orderStructs.orderIds[orderStructs.orderIds.length - 1];
|
|
371
|
+
orderStructs.orderIds.pop();
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* UpdateMarkPrice(
|
|
375
|
+
* uint24 indexed perpetualId,
|
|
376
|
+
* int128 fMarkPricePremium,
|
|
377
|
+
* int128 fSpotIndexPrice
|
|
378
|
+
* )
|
|
379
|
+
* @param fMarkPricePremium premium rate in ABDK format
|
|
380
|
+
* @param fSpotIndexPrice spot index price in ABDK format
|
|
381
|
+
* @returns mark price and spot index in float
|
|
382
|
+
*/
|
|
383
|
+
static ConvertUpdateMarkPrice(fMarkPricePremium, fSpotIndexPrice) {
|
|
384
|
+
let fMarkPrice = (0, d8XMath_1.mul64x64)(fSpotIndexPrice, nodeSDKTypes_1.ONE_64x64.add(fMarkPricePremium));
|
|
385
|
+
let markPrice = (0, d8XMath_1.ABK64x64ToFloat)(fMarkPrice);
|
|
386
|
+
let indexPrice = (0, d8XMath_1.ABK64x64ToFloat)(fSpotIndexPrice);
|
|
387
|
+
return [markPrice, indexPrice];
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
exports.default = PerpetualEventHandler;
|
package/dist/utils.d.ts
CHANGED
|
@@ -33,5 +33,23 @@ export declare function fromBytes4(b: Buffer): string;
|
|
|
33
33
|
* returned by the smart contract as bytes4
|
|
34
34
|
*/
|
|
35
35
|
export declare function fromBytes4HexString(s: string): string;
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @param {string} s string representing a hex-number ("0x...")
|
|
39
|
+
* @param {Object} mapping list of symbol and clean symbol pairs, e.g. [{symbol: "MATIC", cleanSymbol: "MATC"}, ...]
|
|
40
|
+
* @returns {string} user friendly currency symbol, e.g. "MATIC"
|
|
41
|
+
*/
|
|
42
|
+
export declare function contractSymbolToSymbol(s: string, mapping: Array<{
|
|
43
|
+
[key: string]: string;
|
|
44
|
+
}>): string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Converts symbol or symbol combination into long format
|
|
47
|
+
* @param {string} s symbol, e.g., USDC-MATC-USDC, MATC, USDC, ...
|
|
48
|
+
* @param {Object} mapping list of symbol and clean symbol pairs, e.g. [{symbol: "MATIC", cleanSymbol: "MATC"}, ...]
|
|
49
|
+
* @returns {string} long format e.g. MATIC. if not found the element is ""
|
|
50
|
+
*/
|
|
51
|
+
export declare function symbol4BToLongSymbol(s: string, mapping: Array<{
|
|
52
|
+
[key: string]: string;
|
|
53
|
+
}>): string;
|
|
36
54
|
export declare function combineFlags(f1: BigNumber, f2: BigNumber): BigNumber;
|
|
37
55
|
export declare function containsFlag(f1: BigNumber, f2: BigNumber): boolean;
|
package/dist/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.containsFlag = exports.combineFlags = exports.fromBytes4HexString = exports.fromBytes4 = exports.toBytes4 = exports.to4Chars = void 0;
|
|
3
|
+
exports.containsFlag = exports.combineFlags = exports.symbol4BToLongSymbol = exports.contractSymbolToSymbol = exports.fromBytes4HexString = exports.fromBytes4 = exports.toBytes4 = exports.to4Chars = void 0;
|
|
4
4
|
const ethers_1 = require("ethers");
|
|
5
5
|
/**
|
|
6
6
|
* @module utils
|
|
@@ -76,6 +76,42 @@ function fromBytes4HexString(s) {
|
|
|
76
76
|
return res;
|
|
77
77
|
}
|
|
78
78
|
exports.fromBytes4HexString = fromBytes4HexString;
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @param {string} s string representing a hex-number ("0x...")
|
|
82
|
+
* @param {Object} mapping list of symbol and clean symbol pairs, e.g. [{symbol: "MATIC", cleanSymbol: "MATC"}, ...]
|
|
83
|
+
* @returns {string} user friendly currency symbol, e.g. "MATIC"
|
|
84
|
+
*/
|
|
85
|
+
function contractSymbolToSymbol(s, mapping) {
|
|
86
|
+
s = fromBytes4HexString(s);
|
|
87
|
+
for (let pair of mapping) {
|
|
88
|
+
if (pair.cleanSymbol == s) {
|
|
89
|
+
return pair.symbol;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
exports.contractSymbolToSymbol = contractSymbolToSymbol;
|
|
94
|
+
/**
|
|
95
|
+
* Converts symbol or symbol combination into long format
|
|
96
|
+
* @param {string} s symbol, e.g., USDC-MATC-USDC, MATC, USDC, ...
|
|
97
|
+
* @param {Object} mapping list of symbol and clean symbol pairs, e.g. [{symbol: "MATIC", cleanSymbol: "MATC"}, ...]
|
|
98
|
+
* @returns {string} long format e.g. MATIC. if not found the element is ""
|
|
99
|
+
*/
|
|
100
|
+
function symbol4BToLongSymbol(s, mapping) {
|
|
101
|
+
let ccy = s.split("-");
|
|
102
|
+
let longCCY = "";
|
|
103
|
+
for (let k = 0; k < ccy.length; k++) {
|
|
104
|
+
let sym = ccy[k];
|
|
105
|
+
for (let pair of mapping) {
|
|
106
|
+
if (pair.cleanSymbol == sym) {
|
|
107
|
+
longCCY = longCCY + "-" + pair.symbol;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return longCCY.substring(1);
|
|
113
|
+
}
|
|
114
|
+
exports.symbol4BToLongSymbol = symbol4BToLongSymbol;
|
|
79
115
|
function combineFlags(f1, f2) {
|
|
80
116
|
return ethers_1.BigNumber.from(parseInt(f1.toString()) | parseInt(f2.toString()));
|
|
81
117
|
}
|
package/package.json
CHANGED
package/src/accountTrade.ts
CHANGED
|
@@ -190,13 +190,13 @@ export default class AccountTrade extends WriteAccessHandler {
|
|
|
190
190
|
* @returns Exchange fee, in decimals (i.e. 0.1% is 0.001).
|
|
191
191
|
*/
|
|
192
192
|
public async queryExchangeFee(poolSymbolName: string, brokerAddr?: string): Promise<number> {
|
|
193
|
-
if (this.proxyContract == null
|
|
193
|
+
if (this.proxyContract == null) {
|
|
194
194
|
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
|
|
195
195
|
}
|
|
196
196
|
if (typeof brokerAddr == "undefined") {
|
|
197
197
|
brokerAddr = ZERO_ADDRESS;
|
|
198
198
|
}
|
|
199
|
-
let poolId =
|
|
199
|
+
let poolId = PerpetualDataHandler._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
|
|
200
200
|
let feeTbps = await this.proxyContract.queryExchangeFee(poolId, this.traderAddr, brokerAddr);
|
|
201
201
|
return feeTbps / 100_000;
|
|
202
202
|
}
|