perps-sdk-ts 1.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/.claude/settings.local.json +11 -0
- package/CONTRACT_METHOD_FIXES.md +189 -0
- package/INTEGRATION_SUMMARY.md +219 -0
- package/OPTIMIZATION_GUIDE.md +238 -0
- package/README.md +384 -0
- package/SNAPSHOT_FIX_SUMMARY.md +161 -0
- package/SNAPSHOT_OPTIMIZATION_SUMMARY.md +199 -0
- package/dist/abis/Referral.d.ts +36 -0
- package/dist/abis/Referral.js +4 -0
- package/dist/abis/Trading.d.ts +57 -0
- package/dist/abis/Trading.js +742 -0
- package/dist/abis/erc20.d.ts +51 -0
- package/dist/abis/erc20.js +4 -0
- package/dist/abis/index.d.ts +8 -0
- package/dist/abis/index.js +24 -0
- package/dist/abis/multicall.d.ts +85 -0
- package/dist/abis/multicall.js +4 -0
- package/dist/abis/pairInfos.d.ts +77 -0
- package/dist/abis/pairInfos.js +4 -0
- package/dist/abis/pairStorage.d.ts +124 -0
- package/dist/abis/pairStorage.js +4 -0
- package/dist/abis/priceAggregator.d.ts +77 -0
- package/dist/abis/priceAggregator.js +4 -0
- package/dist/abis/tardingStorage.d.ts +97 -0
- package/dist/abis/tardingStorage.js +1295 -0
- package/dist/abis.d.ts +623 -0
- package/dist/abis.js +49 -0
- package/dist/client.d.ts +118 -0
- package/dist/client.js +224 -0
- package/dist/config.d.ts +43 -0
- package/dist/config.js +42 -0
- package/dist/crypto/spki.d.ts +55 -0
- package/dist/crypto/spki.js +160 -0
- package/dist/feed/feed_client.d.ts +68 -0
- package/dist/feed/feed_client.js +239 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +87 -0
- package/dist/rpc/asset_parameters.d.ts +62 -0
- package/dist/rpc/asset_parameters.js +169 -0
- package/dist/rpc/blended.d.ts +23 -0
- package/dist/rpc/blended.js +55 -0
- package/dist/rpc/category_parameters.d.ts +34 -0
- package/dist/rpc/category_parameters.js +105 -0
- package/dist/rpc/delegation.d.ts +81 -0
- package/dist/rpc/delegation.js +180 -0
- package/dist/rpc/fee_parameters.d.ts +46 -0
- package/dist/rpc/fee_parameters.js +113 -0
- package/dist/rpc/multicall.d.ts +83 -0
- package/dist/rpc/multicall.js +117 -0
- package/dist/rpc/pair_info_queries.d.ts +101 -0
- package/dist/rpc/pair_info_queries.js +161 -0
- package/dist/rpc/pairs_cache.d.ts +62 -0
- package/dist/rpc/pairs_cache.js +240 -0
- package/dist/rpc/referral_operations.d.ts +67 -0
- package/dist/rpc/referral_operations.js +143 -0
- package/dist/rpc/snapshot.d.ts +49 -0
- package/dist/rpc/snapshot.js +162 -0
- package/dist/rpc/trade.d.ts +84 -0
- package/dist/rpc/trade.js +249 -0
- package/dist/rpc/trading_operations.d.ts +103 -0
- package/dist/rpc/trading_operations.js +295 -0
- package/dist/rpc/trading_parameters.d.ts +49 -0
- package/dist/rpc/trading_parameters.js +94 -0
- package/dist/signers/base.d.ts +24 -0
- package/dist/signers/base.js +10 -0
- package/dist/signers/kms.d.ts +47 -0
- package/dist/signers/kms.js +172 -0
- package/dist/signers/local.d.ts +43 -0
- package/dist/signers/local.js +64 -0
- package/dist/types.d.ts +1419 -0
- package/dist/types.js +245 -0
- package/dist/utils.d.ts +52 -0
- package/dist/utils.js +134 -0
- package/examples/advanced-queries.ts +181 -0
- package/examples/basic-usage.ts +78 -0
- package/examples/delegation-and-referrals.ts +130 -0
- package/examples/get-pyth-ids.ts +61 -0
- package/examples/kms-signer.ts +31 -0
- package/examples/optimized-snapshot.ts +153 -0
- package/examples/price-feed-with-sdk-ids.ts +97 -0
- package/examples/price-feed.ts +36 -0
- package/examples/trading-operations.ts +149 -0
- package/package.json +41 -0
- package/src/abis/Referral.ts +3 -0
- package/src/abis/Trading.ts +741 -0
- package/src/abis/erc20.ts +3 -0
- package/src/abis/index.ts +8 -0
- package/src/abis/multicall.ts +3 -0
- package/src/abis/pairInfos.ts +3 -0
- package/src/abis/pairStorage.ts +3 -0
- package/src/abis/priceAggregator.ts +3 -0
- package/src/abis/tardingStorage.ts +1294 -0
- package/src/abis.ts +56 -0
- package/src/client.ts +373 -0
- package/src/config.ts +62 -0
- package/src/crypto/spki.ts +197 -0
- package/src/feed/feed_client.ts +288 -0
- package/src/index.ts +114 -0
- package/src/rpc/asset_parameters.ts +217 -0
- package/src/rpc/blended.ts +77 -0
- package/src/rpc/category_parameters.ts +128 -0
- package/src/rpc/delegation.ts +225 -0
- package/src/rpc/fee_parameters.ts +150 -0
- package/src/rpc/multicall.ts +164 -0
- package/src/rpc/pair_info_queries.ts +208 -0
- package/src/rpc/pairs_cache.ts +268 -0
- package/src/rpc/referral_operations.ts +164 -0
- package/src/rpc/snapshot.ts +210 -0
- package/src/rpc/trade.ts +306 -0
- package/src/rpc/trading_operations.ts +378 -0
- package/src/rpc/trading_parameters.ts +127 -0
- package/src/signers/base.ts +27 -0
- package/src/signers/kms.ts +212 -0
- package/src/signers/local.ts +70 -0
- package/src/types.ts +410 -0
- package/src/utils.ts +155 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { Contract, TransactionReceipt, TransactionRequest } from 'ethers';
|
|
2
|
+
import {
|
|
3
|
+
Trade,
|
|
4
|
+
TradeInfo,
|
|
5
|
+
OpenLimitOrder,
|
|
6
|
+
TradeInputOrderType,
|
|
7
|
+
MarginUpdateType,
|
|
8
|
+
toBlockchain6,
|
|
9
|
+
toBlockchain10,
|
|
10
|
+
toBlockchain18,
|
|
11
|
+
fromBlockchain6,
|
|
12
|
+
fromBlockchain10,
|
|
13
|
+
fromBlockchain18,
|
|
14
|
+
} from '../types';
|
|
15
|
+
import { BaseSigner } from '../signers/base';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Trading Operations RPC
|
|
19
|
+
* Handles all trading contract interactions including opening/closing trades,
|
|
20
|
+
* updating margins, and managing limit orders.
|
|
21
|
+
*/
|
|
22
|
+
export class TradingOperationsRPC {
|
|
23
|
+
constructor(
|
|
24
|
+
private tradingContract: Contract,
|
|
25
|
+
private tradingStorageContract: Contract,
|
|
26
|
+
private signer?: BaseSigner
|
|
27
|
+
) {}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get execution fee required for trading operations
|
|
31
|
+
* @returns Execution fee in ETH
|
|
32
|
+
*/
|
|
33
|
+
async getExecutionFee(): Promise<number> {
|
|
34
|
+
const fee = await this.tradingContract.getExecutionFee();
|
|
35
|
+
return fromBlockchain18(fee);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Open a new trade position
|
|
40
|
+
* @param trade - Trade parameters
|
|
41
|
+
* @param orderType - Order type (MARKET, LIMIT, etc.)
|
|
42
|
+
* @param slippageP - Slippage percentage (e.g., 1 for 1%)
|
|
43
|
+
* @param executionFeeEth - Execution fee in ETH (optional, will fetch if not provided)
|
|
44
|
+
* @returns Transaction receipt
|
|
45
|
+
*/
|
|
46
|
+
async openTrade(
|
|
47
|
+
trade: Omit<Trade, 'timestamp'>,
|
|
48
|
+
orderType: TradeInputOrderType,
|
|
49
|
+
slippageP: number,
|
|
50
|
+
executionFeeEth?: number
|
|
51
|
+
): Promise<TransactionReceipt | null> {
|
|
52
|
+
if (!this.signer) {
|
|
53
|
+
throw new Error('Signer required for trading operations');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Get execution fee if not provided
|
|
57
|
+
if (!executionFeeEth) {
|
|
58
|
+
executionFeeEth = await this.getExecutionFee();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Convert order type to number
|
|
62
|
+
const orderTypeMap: Record<TradeInputOrderType, number> = {
|
|
63
|
+
[TradeInputOrderType.MARKET]: 0,
|
|
64
|
+
[TradeInputOrderType.STOP_LIMIT]: 1,
|
|
65
|
+
[TradeInputOrderType.LIMIT]: 2,
|
|
66
|
+
[TradeInputOrderType.MARKET_ZERO_FEE]: 3,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Prepare trade struct with blockchain values
|
|
70
|
+
const tradeStruct = {
|
|
71
|
+
trader: trade.trader,
|
|
72
|
+
pairIndex: trade.pairIndex,
|
|
73
|
+
index: trade.index,
|
|
74
|
+
initialPosToken: toBlockchain6(trade.initialPosToken),
|
|
75
|
+
positionSizeUSDC: toBlockchain6(trade.positionSizeUSDC),
|
|
76
|
+
openPrice: toBlockchain10(trade.openPrice),
|
|
77
|
+
buy: trade.buy,
|
|
78
|
+
leverage: toBlockchain10(trade.leverage),
|
|
79
|
+
tp: toBlockchain10(trade.tp),
|
|
80
|
+
sl: toBlockchain10(trade.sl),
|
|
81
|
+
timestamp: Math.floor(Date.now() / 1000),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const slippageBlockchain = toBlockchain10(slippageP);
|
|
85
|
+
const executionFeeWei = toBlockchain18(executionFeeEth);
|
|
86
|
+
|
|
87
|
+
// Create transaction
|
|
88
|
+
const tx: TransactionRequest = {
|
|
89
|
+
to: await this.tradingContract.getAddress(),
|
|
90
|
+
data: this.tradingContract.interface.encodeFunctionData('openTrade', [
|
|
91
|
+
tradeStruct,
|
|
92
|
+
orderTypeMap[orderType],
|
|
93
|
+
slippageBlockchain,
|
|
94
|
+
]),
|
|
95
|
+
value: executionFeeWei,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
return await this.signAndSend(tx);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Close a trade position at market price
|
|
103
|
+
* @param pairIndex - Trading pair index
|
|
104
|
+
* @param index - Trade index
|
|
105
|
+
* @param closeAmount - Amount of collateral to close (USDC)
|
|
106
|
+
* @param executionFeeEth - Execution fee in ETH (optional)
|
|
107
|
+
* @returns Transaction receipt
|
|
108
|
+
*/
|
|
109
|
+
async closeTradeMarket(
|
|
110
|
+
pairIndex: number,
|
|
111
|
+
index: number,
|
|
112
|
+
closeAmount: number,
|
|
113
|
+
executionFeeEth?: number
|
|
114
|
+
): Promise<TransactionReceipt | null> {
|
|
115
|
+
if (!this.signer) {
|
|
116
|
+
throw new Error('Signer required for trading operations');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!executionFeeEth) {
|
|
120
|
+
executionFeeEth = await this.getExecutionFee();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const closeAmountBlockchain = toBlockchain6(closeAmount);
|
|
124
|
+
const executionFeeWei = toBlockchain18(executionFeeEth);
|
|
125
|
+
|
|
126
|
+
const tx: TransactionRequest = {
|
|
127
|
+
to: await this.tradingContract.getAddress(),
|
|
128
|
+
data: this.tradingContract.interface.encodeFunctionData('closeTradeMarket', [
|
|
129
|
+
pairIndex,
|
|
130
|
+
index,
|
|
131
|
+
closeAmountBlockchain,
|
|
132
|
+
]),
|
|
133
|
+
value: executionFeeWei,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
return await this.signAndSend(tx);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Update margin for an existing trade
|
|
141
|
+
* @param pairIndex - Trading pair index
|
|
142
|
+
* @param index - Trade index
|
|
143
|
+
* @param updateType - DEPOSIT or WITHDRAW
|
|
144
|
+
* @param amount - Amount to add/remove (USDC)
|
|
145
|
+
* @param priceUpdateData - Price oracle update data
|
|
146
|
+
* @returns Transaction receipt
|
|
147
|
+
*/
|
|
148
|
+
async updateMargin(
|
|
149
|
+
pairIndex: number,
|
|
150
|
+
index: number,
|
|
151
|
+
updateType: MarginUpdateType,
|
|
152
|
+
amount: number,
|
|
153
|
+
priceUpdateData: string[] = []
|
|
154
|
+
): Promise<TransactionReceipt | null> {
|
|
155
|
+
if (!this.signer) {
|
|
156
|
+
throw new Error('Signer required for trading operations');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const amountBlockchain = toBlockchain6(amount);
|
|
160
|
+
|
|
161
|
+
const tx: TransactionRequest = {
|
|
162
|
+
to: await this.tradingContract.getAddress(),
|
|
163
|
+
data: this.tradingContract.interface.encodeFunctionData('updateMargin', [
|
|
164
|
+
pairIndex,
|
|
165
|
+
index,
|
|
166
|
+
updateType,
|
|
167
|
+
amountBlockchain,
|
|
168
|
+
priceUpdateData,
|
|
169
|
+
]),
|
|
170
|
+
value: 1n, // 1 wei for price update
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
return await this.signAndSend(tx);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Update take profit and stop loss for a trade
|
|
178
|
+
* @param pairIndex - Trading pair index
|
|
179
|
+
* @param index - Trade index
|
|
180
|
+
* @param newSl - New stop loss price
|
|
181
|
+
* @param newTp - New take profit price
|
|
182
|
+
* @param priceUpdateData - Price oracle update data
|
|
183
|
+
* @returns Transaction receipt
|
|
184
|
+
*/
|
|
185
|
+
async updateTpAndSl(
|
|
186
|
+
pairIndex: number,
|
|
187
|
+
index: number,
|
|
188
|
+
newSl: number,
|
|
189
|
+
newTp: number,
|
|
190
|
+
priceUpdateData: string[] = []
|
|
191
|
+
): Promise<TransactionReceipt | null> {
|
|
192
|
+
if (!this.signer) {
|
|
193
|
+
throw new Error('Signer required for trading operations');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const slBlockchain = toBlockchain10(newSl);
|
|
197
|
+
const tpBlockchain = toBlockchain10(newTp);
|
|
198
|
+
|
|
199
|
+
const tx: TransactionRequest = {
|
|
200
|
+
to: await this.tradingContract.getAddress(),
|
|
201
|
+
data: this.tradingContract.interface.encodeFunctionData('updateTpAndSl', [
|
|
202
|
+
pairIndex,
|
|
203
|
+
index,
|
|
204
|
+
slBlockchain,
|
|
205
|
+
tpBlockchain,
|
|
206
|
+
priceUpdateData,
|
|
207
|
+
]),
|
|
208
|
+
value: 1n, // 1 wei for price update
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
return await this.signAndSend(tx);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Cancel a pending limit order
|
|
216
|
+
* @param pairIndex - Trading pair index
|
|
217
|
+
* @param index - Order index
|
|
218
|
+
* @returns Transaction receipt
|
|
219
|
+
*/
|
|
220
|
+
async cancelOpenLimitOrder(
|
|
221
|
+
pairIndex: number,
|
|
222
|
+
index: number
|
|
223
|
+
): Promise<TransactionReceipt | null> {
|
|
224
|
+
if (!this.signer) {
|
|
225
|
+
throw new Error('Signer required for trading operations');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const tx: TransactionRequest = {
|
|
229
|
+
to: await this.tradingContract.getAddress(),
|
|
230
|
+
data: this.tradingContract.interface.encodeFunctionData('cancelOpenLimitOrder', [
|
|
231
|
+
pairIndex,
|
|
232
|
+
index,
|
|
233
|
+
]),
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
return await this.signAndSend(tx);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Get open trade information
|
|
241
|
+
* @param trader - Trader address
|
|
242
|
+
* @param pairIndex - Trading pair index
|
|
243
|
+
* @param index - Trade index
|
|
244
|
+
* @returns Trade information
|
|
245
|
+
*/
|
|
246
|
+
async getOpenTrade(trader: string, pairIndex: number, index: number): Promise<Trade> {
|
|
247
|
+
const result = await this.tradingStorageContract.openTrades(trader, pairIndex, index);
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
trader: result.trader,
|
|
251
|
+
pairIndex: Number(result.pairIndex),
|
|
252
|
+
index: Number(result.index),
|
|
253
|
+
initialPosToken: fromBlockchain6(result.initialPosToken),
|
|
254
|
+
positionSizeUSDC: fromBlockchain6(result.positionSizeUSDC),
|
|
255
|
+
openPrice: fromBlockchain10(result.openPrice),
|
|
256
|
+
buy: result.buy,
|
|
257
|
+
leverage: fromBlockchain10(result.leverage),
|
|
258
|
+
tp: fromBlockchain10(result.tp),
|
|
259
|
+
sl: fromBlockchain10(result.sl),
|
|
260
|
+
timestamp: Number(result.timestamp),
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get additional trade information
|
|
266
|
+
* @param trader - Trader address
|
|
267
|
+
* @param pairIndex - Trading pair index
|
|
268
|
+
* @param index - Trade index
|
|
269
|
+
* @returns Trade info
|
|
270
|
+
*/
|
|
271
|
+
async getOpenTradeInfo(
|
|
272
|
+
trader: string,
|
|
273
|
+
pairIndex: number,
|
|
274
|
+
index: number
|
|
275
|
+
): Promise<TradeInfo> {
|
|
276
|
+
const result = await this.tradingStorageContract.openTradesInfo(trader, pairIndex, index);
|
|
277
|
+
|
|
278
|
+
return {
|
|
279
|
+
openInterestUSDC: fromBlockchain6(result.openInterestUSDC),
|
|
280
|
+
tpLastUpdated: Number(result.tpLastUpdated),
|
|
281
|
+
slLastUpdated: Number(result.slLastUpdated),
|
|
282
|
+
beingMarketClosed: result.beingMarketClosed,
|
|
283
|
+
lossProtection: Number(result.lossProtection),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Get number of open trades for a trader on a pair
|
|
289
|
+
* @param trader - Trader address
|
|
290
|
+
* @param pairIndex - Trading pair index
|
|
291
|
+
* @returns Number of open trades
|
|
292
|
+
*/
|
|
293
|
+
async getOpenTradesCount(trader: string, pairIndex: number): Promise<number> {
|
|
294
|
+
const count = await this.tradingStorageContract.openTradesCount(trader, pairIndex);
|
|
295
|
+
return Number(count);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Get limit order information
|
|
300
|
+
* @param trader - Trader address
|
|
301
|
+
* @param pairIndex - Trading pair index
|
|
302
|
+
* @param index - Order index
|
|
303
|
+
* @returns Limit order information
|
|
304
|
+
*/
|
|
305
|
+
async getOpenLimitOrder(
|
|
306
|
+
trader: string,
|
|
307
|
+
pairIndex: number,
|
|
308
|
+
index: number
|
|
309
|
+
): Promise<OpenLimitOrder> {
|
|
310
|
+
const result = await this.tradingStorageContract.getOpenLimitOrder(trader, pairIndex, index);
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
trader: result.trader,
|
|
314
|
+
pairIndex: Number(result.pairIndex),
|
|
315
|
+
index: Number(result.index),
|
|
316
|
+
positionSize: fromBlockchain6(result.positionSize),
|
|
317
|
+
buy: result.buy,
|
|
318
|
+
leverage: fromBlockchain10(result.leverage),
|
|
319
|
+
tp: fromBlockchain10(result.tp),
|
|
320
|
+
sl: fromBlockchain10(result.sl),
|
|
321
|
+
price: fromBlockchain10(result.price),
|
|
322
|
+
slippageP: fromBlockchain10(result.slippageP),
|
|
323
|
+
block: Number(result.block),
|
|
324
|
+
executionFee: fromBlockchain18(result.executionFee),
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Helper method to sign and send transactions
|
|
330
|
+
*/
|
|
331
|
+
private async signAndSend(tx: TransactionRequest): Promise<TransactionReceipt | null> {
|
|
332
|
+
if (!this.signer) {
|
|
333
|
+
throw new Error('Signer not set');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const address = await this.signer.getAddress();
|
|
337
|
+
tx.from = address;
|
|
338
|
+
|
|
339
|
+
const provider = this.tradingContract.runner?.provider;
|
|
340
|
+
if (!provider) {
|
|
341
|
+
throw new Error('Provider not available');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (!tx.chainId) {
|
|
345
|
+
const network = await provider.getNetwork();
|
|
346
|
+
tx.chainId = network.chainId;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (tx.nonce === undefined) {
|
|
350
|
+
tx.nonce = await provider.getTransactionCount(address);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (!tx.gasLimit) {
|
|
354
|
+
tx.gasLimit = await provider.estimateGas(tx);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (!tx.maxFeePerGas && !tx.gasPrice) {
|
|
358
|
+
const feeData = await provider.getFeeData();
|
|
359
|
+
if (feeData.maxFeePerGas) {
|
|
360
|
+
tx.maxFeePerGas = feeData.maxFeePerGas;
|
|
361
|
+
tx.maxPriorityFeePerGas = feeData.maxPriorityFeePerGas || feeData.maxFeePerGas;
|
|
362
|
+
} else {
|
|
363
|
+
tx.gasPrice = feeData.gasPrice || undefined;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const signedTx = await this.signer.signTransaction(tx);
|
|
368
|
+
const txResponse = await provider.broadcastTransaction(signedTx);
|
|
369
|
+
return await txResponse.wait();
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Set signer for transactions
|
|
374
|
+
*/
|
|
375
|
+
setSigner(signer: BaseSigner): void {
|
|
376
|
+
this.signer = signer;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { Contract, Provider } from 'ethers';
|
|
2
|
+
import { TradeInput, LossProtectionInfo, fromBlockchain10, toBlockchain6 } from '../types';
|
|
3
|
+
import { PairsCache } from './pairs_cache';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* RPC module for trading-related parameters
|
|
7
|
+
*/
|
|
8
|
+
export class TradingParametersRPC {
|
|
9
|
+
private provider: Provider;
|
|
10
|
+
private pairInfosContract: Contract;
|
|
11
|
+
private pairsCache: PairsCache;
|
|
12
|
+
|
|
13
|
+
constructor(
|
|
14
|
+
provider: Provider,
|
|
15
|
+
pairInfosContract: Contract,
|
|
16
|
+
pairsCache: PairsCache
|
|
17
|
+
) {
|
|
18
|
+
this.provider = provider;
|
|
19
|
+
this.pairInfosContract = pairInfosContract;
|
|
20
|
+
this.pairsCache = pairsCache;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get loss protection tier for a trade
|
|
25
|
+
* @param tradeInput - Trade input parameters
|
|
26
|
+
* @returns Loss protection tier
|
|
27
|
+
*/
|
|
28
|
+
async getLossProtectionTier(tradeInput: TradeInput): Promise<number> {
|
|
29
|
+
const pairIndex = await this.pairsCache.getPairIndex(tradeInput.pair);
|
|
30
|
+
if (pairIndex === undefined) {
|
|
31
|
+
throw new Error(`Pair ${tradeInput.pair} not found`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const tier = await this.pairInfosContract.getLossProtectionTier(
|
|
36
|
+
pairIndex,
|
|
37
|
+
toBlockchain6(tradeInput.collateralInTrade)
|
|
38
|
+
);
|
|
39
|
+
return Number(tier);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error('Error getting loss protection tier:', error);
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get loss protection percentage for a tier
|
|
48
|
+
* @param tier - Loss protection tier
|
|
49
|
+
* @param pairIndex - Pair index
|
|
50
|
+
* @returns Loss protection percentage
|
|
51
|
+
*/
|
|
52
|
+
async getLossProtectionPercentage(tier: number, pairIndex: number): Promise<number> {
|
|
53
|
+
try {
|
|
54
|
+
const percentage = await this.pairInfosContract.getLossProtectionP(tier, pairIndex);
|
|
55
|
+
return fromBlockchain10(percentage);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Error getting loss protection percentage:', error);
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Calculate loss protection amount
|
|
64
|
+
* @param tier - Loss protection tier
|
|
65
|
+
* @param pairIndex - Pair index
|
|
66
|
+
* @param collateral - Collateral amount
|
|
67
|
+
* @param openingFee - Opening fee amount
|
|
68
|
+
* @returns Loss protection amount
|
|
69
|
+
*/
|
|
70
|
+
async getLossProtectionAmount(
|
|
71
|
+
tier: number,
|
|
72
|
+
pairIndex: number,
|
|
73
|
+
collateral: number,
|
|
74
|
+
openingFee: number
|
|
75
|
+
): Promise<number> {
|
|
76
|
+
const percentage = await this.getLossProtectionPercentage(tier, pairIndex);
|
|
77
|
+
return openingFee * (percentage / 100);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get complete loss protection info for a trade
|
|
82
|
+
* @param tradeInput - Trade input parameters
|
|
83
|
+
* @param openingFee - Opening fee amount
|
|
84
|
+
* @returns Loss protection info
|
|
85
|
+
*/
|
|
86
|
+
async getLossProtectionInfo(
|
|
87
|
+
tradeInput: TradeInput,
|
|
88
|
+
openingFee: number
|
|
89
|
+
): Promise<LossProtectionInfo> {
|
|
90
|
+
const pairIndex = await this.pairsCache.getPairIndex(tradeInput.pair);
|
|
91
|
+
if (pairIndex === undefined) {
|
|
92
|
+
throw new Error(`Pair ${tradeInput.pair} not found`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const tier = await this.getLossProtectionTier(tradeInput);
|
|
96
|
+
const percentage = await this.getLossProtectionPercentage(tier, pairIndex);
|
|
97
|
+
const amount = await this.getLossProtectionAmount(
|
|
98
|
+
tier,
|
|
99
|
+
pairIndex,
|
|
100
|
+
tradeInput.collateralInTrade,
|
|
101
|
+
openingFee
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
tier,
|
|
106
|
+
percentage,
|
|
107
|
+
amount,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get referral rebate for a trader
|
|
113
|
+
* @param trader - Trader address
|
|
114
|
+
* @param referrer - Referrer address
|
|
115
|
+
* @param openingFee - Opening fee amount
|
|
116
|
+
* @returns Rebate amount
|
|
117
|
+
*/
|
|
118
|
+
async getTradeReferralRebate(
|
|
119
|
+
trader: string,
|
|
120
|
+
referrer: string,
|
|
121
|
+
openingFee: number
|
|
122
|
+
): Promise<number> {
|
|
123
|
+
// This would typically call the referral contract
|
|
124
|
+
// For now, return 0 as a placeholder
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { TransactionRequest, TransactionResponse } from 'ethers';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for transaction signers
|
|
5
|
+
* Implementations can use local private keys, AWS KMS, or other signing methods
|
|
6
|
+
*/
|
|
7
|
+
export abstract class BaseSigner {
|
|
8
|
+
/**
|
|
9
|
+
* Sign a transaction
|
|
10
|
+
* @param transaction - Transaction to sign
|
|
11
|
+
* @returns Signed transaction
|
|
12
|
+
*/
|
|
13
|
+
abstract signTransaction(transaction: TransactionRequest): Promise<string>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get the Ethereum address associated with this signer
|
|
17
|
+
* @returns Ethereum address
|
|
18
|
+
*/
|
|
19
|
+
abstract getAddress(): Promise<string>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Sign a message
|
|
23
|
+
* @param message - Message to sign
|
|
24
|
+
* @returns Signature
|
|
25
|
+
*/
|
|
26
|
+
abstract signMessage(message: string | Uint8Array): Promise<string>;
|
|
27
|
+
}
|