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.
Files changed (117) hide show
  1. package/.claude/settings.local.json +11 -0
  2. package/CONTRACT_METHOD_FIXES.md +189 -0
  3. package/INTEGRATION_SUMMARY.md +219 -0
  4. package/OPTIMIZATION_GUIDE.md +238 -0
  5. package/README.md +384 -0
  6. package/SNAPSHOT_FIX_SUMMARY.md +161 -0
  7. package/SNAPSHOT_OPTIMIZATION_SUMMARY.md +199 -0
  8. package/dist/abis/Referral.d.ts +36 -0
  9. package/dist/abis/Referral.js +4 -0
  10. package/dist/abis/Trading.d.ts +57 -0
  11. package/dist/abis/Trading.js +742 -0
  12. package/dist/abis/erc20.d.ts +51 -0
  13. package/dist/abis/erc20.js +4 -0
  14. package/dist/abis/index.d.ts +8 -0
  15. package/dist/abis/index.js +24 -0
  16. package/dist/abis/multicall.d.ts +85 -0
  17. package/dist/abis/multicall.js +4 -0
  18. package/dist/abis/pairInfos.d.ts +77 -0
  19. package/dist/abis/pairInfos.js +4 -0
  20. package/dist/abis/pairStorage.d.ts +124 -0
  21. package/dist/abis/pairStorage.js +4 -0
  22. package/dist/abis/priceAggregator.d.ts +77 -0
  23. package/dist/abis/priceAggregator.js +4 -0
  24. package/dist/abis/tardingStorage.d.ts +97 -0
  25. package/dist/abis/tardingStorage.js +1295 -0
  26. package/dist/abis.d.ts +623 -0
  27. package/dist/abis.js +49 -0
  28. package/dist/client.d.ts +118 -0
  29. package/dist/client.js +224 -0
  30. package/dist/config.d.ts +43 -0
  31. package/dist/config.js +42 -0
  32. package/dist/crypto/spki.d.ts +55 -0
  33. package/dist/crypto/spki.js +160 -0
  34. package/dist/feed/feed_client.d.ts +68 -0
  35. package/dist/feed/feed_client.js +239 -0
  36. package/dist/index.d.ts +28 -0
  37. package/dist/index.js +87 -0
  38. package/dist/rpc/asset_parameters.d.ts +62 -0
  39. package/dist/rpc/asset_parameters.js +169 -0
  40. package/dist/rpc/blended.d.ts +23 -0
  41. package/dist/rpc/blended.js +55 -0
  42. package/dist/rpc/category_parameters.d.ts +34 -0
  43. package/dist/rpc/category_parameters.js +105 -0
  44. package/dist/rpc/delegation.d.ts +81 -0
  45. package/dist/rpc/delegation.js +180 -0
  46. package/dist/rpc/fee_parameters.d.ts +46 -0
  47. package/dist/rpc/fee_parameters.js +113 -0
  48. package/dist/rpc/multicall.d.ts +83 -0
  49. package/dist/rpc/multicall.js +117 -0
  50. package/dist/rpc/pair_info_queries.d.ts +101 -0
  51. package/dist/rpc/pair_info_queries.js +161 -0
  52. package/dist/rpc/pairs_cache.d.ts +62 -0
  53. package/dist/rpc/pairs_cache.js +240 -0
  54. package/dist/rpc/referral_operations.d.ts +67 -0
  55. package/dist/rpc/referral_operations.js +143 -0
  56. package/dist/rpc/snapshot.d.ts +49 -0
  57. package/dist/rpc/snapshot.js +162 -0
  58. package/dist/rpc/trade.d.ts +84 -0
  59. package/dist/rpc/trade.js +249 -0
  60. package/dist/rpc/trading_operations.d.ts +103 -0
  61. package/dist/rpc/trading_operations.js +295 -0
  62. package/dist/rpc/trading_parameters.d.ts +49 -0
  63. package/dist/rpc/trading_parameters.js +94 -0
  64. package/dist/signers/base.d.ts +24 -0
  65. package/dist/signers/base.js +10 -0
  66. package/dist/signers/kms.d.ts +47 -0
  67. package/dist/signers/kms.js +172 -0
  68. package/dist/signers/local.d.ts +43 -0
  69. package/dist/signers/local.js +64 -0
  70. package/dist/types.d.ts +1419 -0
  71. package/dist/types.js +245 -0
  72. package/dist/utils.d.ts +52 -0
  73. package/dist/utils.js +134 -0
  74. package/examples/advanced-queries.ts +181 -0
  75. package/examples/basic-usage.ts +78 -0
  76. package/examples/delegation-and-referrals.ts +130 -0
  77. package/examples/get-pyth-ids.ts +61 -0
  78. package/examples/kms-signer.ts +31 -0
  79. package/examples/optimized-snapshot.ts +153 -0
  80. package/examples/price-feed-with-sdk-ids.ts +97 -0
  81. package/examples/price-feed.ts +36 -0
  82. package/examples/trading-operations.ts +149 -0
  83. package/package.json +41 -0
  84. package/src/abis/Referral.ts +3 -0
  85. package/src/abis/Trading.ts +741 -0
  86. package/src/abis/erc20.ts +3 -0
  87. package/src/abis/index.ts +8 -0
  88. package/src/abis/multicall.ts +3 -0
  89. package/src/abis/pairInfos.ts +3 -0
  90. package/src/abis/pairStorage.ts +3 -0
  91. package/src/abis/priceAggregator.ts +3 -0
  92. package/src/abis/tardingStorage.ts +1294 -0
  93. package/src/abis.ts +56 -0
  94. package/src/client.ts +373 -0
  95. package/src/config.ts +62 -0
  96. package/src/crypto/spki.ts +197 -0
  97. package/src/feed/feed_client.ts +288 -0
  98. package/src/index.ts +114 -0
  99. package/src/rpc/asset_parameters.ts +217 -0
  100. package/src/rpc/blended.ts +77 -0
  101. package/src/rpc/category_parameters.ts +128 -0
  102. package/src/rpc/delegation.ts +225 -0
  103. package/src/rpc/fee_parameters.ts +150 -0
  104. package/src/rpc/multicall.ts +164 -0
  105. package/src/rpc/pair_info_queries.ts +208 -0
  106. package/src/rpc/pairs_cache.ts +268 -0
  107. package/src/rpc/referral_operations.ts +164 -0
  108. package/src/rpc/snapshot.ts +210 -0
  109. package/src/rpc/trade.ts +306 -0
  110. package/src/rpc/trading_operations.ts +378 -0
  111. package/src/rpc/trading_parameters.ts +127 -0
  112. package/src/signers/base.ts +27 -0
  113. package/src/signers/kms.ts +212 -0
  114. package/src/signers/local.ts +70 -0
  115. package/src/types.ts +410 -0
  116. package/src/utils.ts +155 -0
  117. package/tsconfig.json +18 -0
@@ -0,0 +1,210 @@
1
+ import { Contract, Provider } from 'ethers';
2
+ import { Snapshot, Group, PairData, PairsBackendReturn, fromBlockchain10, fromBlockchain6, fromBlockchain12 } from '../types';
3
+ import { PairsCache } from './pairs_cache';
4
+ import { AssetParametersRPC } from './asset_parameters';
5
+ import { CategoryParametersRPC } from './category_parameters';
6
+ import { FeeParametersRPC } from './fee_parameters';
7
+ import { BlendedRPC } from './blended';
8
+
9
+ /**
10
+ * RPC module for aggregating all market data into a snapshot
11
+ * Optimized to use getPairBackend() to reduce duplicate contract calls
12
+ */
13
+ export class SnapshotRPC {
14
+ private pairsCache: PairsCache;
15
+ private assetParams: AssetParametersRPC;
16
+ private categoryParams: CategoryParametersRPC;
17
+ private feeParams: FeeParametersRPC;
18
+ private blendedParams: BlendedRPC;
19
+
20
+ constructor(
21
+ pairsCache: PairsCache,
22
+ assetParams: AssetParametersRPC,
23
+ categoryParams: CategoryParametersRPC,
24
+ feeParams: FeeParametersRPC,
25
+ blendedParams: BlendedRPC
26
+ ) {
27
+ this.pairsCache = pairsCache;
28
+ this.assetParams = assetParams;
29
+ this.categoryParams = categoryParams;
30
+ this.feeParams = feeParams;
31
+ this.blendedParams = blendedParams;
32
+ }
33
+
34
+ /**
35
+ * Get comprehensive market snapshot with all data
36
+ * Optimized to use getPairBackend() to reduce contract calls
37
+ * @returns Snapshot object containing all market parameters
38
+ */
39
+ async getSnapshot(): Promise<Snapshot> {
40
+ console.log('Fetching market snapshot (optimized)...');
41
+
42
+ // Get basic pair info first to know how many pairs exist
43
+ const pairs = await this.pairsCache.getPairsInfo();
44
+ const pairIndices = Array.from(pairs.keys());
45
+
46
+ // Fetch all pair backend data in parallel (includes pair config, group info, and fees)
47
+ const pairBackendPromises = pairIndices.map(idx => this.pairsCache.getPairBackend(idx));
48
+
49
+ // Fetch only the dynamic data that changes (OI, utilization, skew, depth)
50
+ // Note: Category-level metrics may not be available if contract methods don't exist
51
+ const [
52
+ pairBackendData,
53
+ assetOI,
54
+ assetUtilization,
55
+ assetSkew,
56
+ blendedUtilization,
57
+ blendedSkew,
58
+ depth,
59
+ ] = await Promise.all([
60
+ Promise.all(pairBackendPromises),
61
+ this.assetParams.getOI(),
62
+ this.assetParams.getUtilization(),
63
+ this.assetParams.getAssetSkew(),
64
+ this.blendedParams.getBlendedUtilization(),
65
+ this.blendedParams.getBlendedSkew(),
66
+ this.assetParams.getOnePercentDepth(),
67
+ ]);
68
+
69
+ // Try to get category data, but don't fail if it's not available
70
+ let categoryOI = new Map();
71
+ let categoryUtilization = new Map();
72
+ let categorySkew = new Map();
73
+
74
+ try {
75
+ categoryOI = await this.categoryParams.getOI();
76
+ categoryUtilization = await this.categoryParams.getUtilization();
77
+ categorySkew = await this.categoryParams.getCategorySkew();
78
+ } catch (error) {
79
+ console.warn('Category-level metrics not available:', error);
80
+ }
81
+
82
+ // Build a map of pairIndex -> backend data
83
+ const backendDataMap = new Map<number, PairsBackendReturn>();
84
+ pairIndices.forEach((idx, i) => {
85
+ backendDataMap.set(idx, pairBackendData[i]);
86
+ });
87
+
88
+ // Build a map of groupIndex -> group info (from backend data)
89
+ const groupInfoMap = new Map<number, { name: string; maxOpenInterestP: bigint; isSpreadDynamic: boolean }>();
90
+ pairBackendData.forEach(data => {
91
+ const groupIdx = Number(data.pair.groupIndex);
92
+ if (!groupInfoMap.has(groupIdx)) {
93
+ groupInfoMap.set(groupIdx, data.group);
94
+ }
95
+ });
96
+
97
+ // Build snapshot structure
98
+ const snapshot: Snapshot = {
99
+ groups: {},
100
+ };
101
+
102
+ // Group pairs by category
103
+ for (const [groupIndex, groupInfo] of groupInfoMap) {
104
+ const group: Group = {
105
+ groupIndex,
106
+ pairs: {},
107
+ openInterest: categoryOI.get(groupIndex),
108
+ utilization: categoryUtilization.get(groupIndex),
109
+ skew: categorySkew.get(groupIndex),
110
+ };
111
+
112
+ // Get all pairs in this group
113
+ const pairsInGroup = pairIndices.filter(idx => {
114
+ const backend = backendDataMap.get(idx);
115
+ return backend && Number(backend.pair.groupIndex) === groupIndex;
116
+ });
117
+
118
+ for (const pairIndex of pairsInGroup) {
119
+ const pairInfo = pairs.get(pairIndex);
120
+ const backend = backendDataMap.get(pairIndex);
121
+ if (!pairInfo || !backend) continue;
122
+
123
+ const pairName = `${pairInfo.from}/${pairInfo.to}`;
124
+
125
+ // Extract fee data from backend (no separate call needed)
126
+ const feeData = {
127
+ feeP: fromBlockchain12(backend.fee.openFeeP), // Using openFeeP as the main fee
128
+ };
129
+
130
+ const pairData: PairData = {
131
+ pairInfo,
132
+ openInterest: assetOI.get(pairIndex),
133
+ utilization: blendedUtilization.get(pairIndex),
134
+ skew: blendedSkew.get(pairIndex),
135
+ fee: feeData,
136
+ depth: {
137
+ onePercentDepthAboveUsdc: depth.get(pairIndex)?.above || 0,
138
+ onePercentDepthBelowUsdc: depth.get(pairIndex)?.below || 0,
139
+ },
140
+ spread: fromBlockchain10(backend.pair.spreadP), // Use spread from backend
141
+ };
142
+
143
+ group.pairs[pairName] = pairData;
144
+ }
145
+
146
+ snapshot.groups[`group_${groupIndex}`] = group;
147
+ }
148
+
149
+ console.log('Market snapshot complete (optimized)');
150
+ return snapshot;
151
+ }
152
+
153
+ /**
154
+ * Get snapshot for a specific group
155
+ * @param groupIndex - Group index
156
+ * @returns Group data
157
+ */
158
+ async getGroupSnapshot(groupIndex: number): Promise<Group | undefined> {
159
+ const snapshot = await this.getSnapshot();
160
+ return snapshot.groups[`group_${groupIndex}`];
161
+ }
162
+
163
+ /**
164
+ * Get snapshot for a specific pair
165
+ * @param pairName - Pair name (e.g., "BTC/USD")
166
+ * @returns Pair data
167
+ */
168
+ async getPairSnapshot(pairName: string): Promise<PairData | undefined> {
169
+ const snapshot = await this.getSnapshot();
170
+
171
+ // Find the pair in all groups
172
+ for (const group of Object.values(snapshot.groups)) {
173
+ if (group.pairs[pairName]) {
174
+ return group.pairs[pairName];
175
+ }
176
+ }
177
+
178
+ return undefined;
179
+ }
180
+
181
+ /**
182
+ * Get full backend data for a specific pair (includes all pair config, group, and fee info)
183
+ * This provides more detailed information than the standard snapshot
184
+ * @param pairIndex - Pair index
185
+ * @returns Complete backend data for the pair
186
+ */
187
+ async getPairFullData(pairIndex: number): Promise<PairsBackendReturn> {
188
+ return await this.pairsCache.getPairBackend(pairIndex);
189
+ }
190
+
191
+ /**
192
+ * Get full backend data for all pairs
193
+ * Useful for getting complete configuration data in one call
194
+ * @returns Map of pair index to full backend data
195
+ */
196
+ async getAllPairsFullData(): Promise<Map<number, PairsBackendReturn>> {
197
+ const pairs = await this.pairsCache.getPairsInfo();
198
+ const pairIndices = Array.from(pairs.keys());
199
+
200
+ const backendDataPromises = pairIndices.map(idx => this.pairsCache.getPairBackend(idx));
201
+ const backendData = await Promise.all(backendDataPromises);
202
+
203
+ const dataMap = new Map<number, PairsBackendReturn>();
204
+ pairIndices.forEach((idx, i) => {
205
+ dataMap.set(idx, backendData[i]);
206
+ });
207
+
208
+ return dataMap;
209
+ }
210
+ }
@@ -0,0 +1,306 @@
1
+ import { Contract, ethers, Provider, TransactionRequest } from 'ethers';
2
+ import {
3
+ TradeInput,
4
+ TradeResponse,
5
+ MarginUpdateType,
6
+ toBlockchain6,
7
+ toBlockchain10,
8
+ fromBlockchain6,
9
+ fromBlockchain10,
10
+ } from '../types';
11
+ import { PairsCache } from './pairs_cache';
12
+
13
+ /**
14
+ * RPC module for trading operations
15
+ */
16
+ export class TradeRPC {
17
+ private provider: Provider;
18
+ private tradingContract: Contract;
19
+ private tradingStorageContract: Contract;
20
+ private pairsCache: PairsCache;
21
+
22
+ constructor(
23
+ provider: Provider,
24
+ tradingContract: Contract,
25
+ tradingStorageContract: Contract,
26
+ pairsCache: PairsCache
27
+ ) {
28
+ this.provider = provider;
29
+ this.tradingContract = tradingContract;
30
+ this.tradingStorageContract = tradingStorageContract;
31
+ this.pairsCache = pairsCache;
32
+ }
33
+
34
+ /**
35
+ * Build transaction to open a trade
36
+ * @param tradeInput - Trade input parameters
37
+ * @returns Transaction request
38
+ */
39
+ async buildTradeOpenTx(tradeInput: TradeInput, trader:string): Promise<TransactionRequest> {
40
+ // const pairIndex = await this.pairsCache.getPairIndex(tradeInput.pair);
41
+ const pairIndex = 1
42
+ console.log("pairIndex", pairIndex);
43
+ if (pairIndex === undefined) {
44
+ throw new Error(`Pair ${tradeInput.pair} not found`);
45
+ }
46
+
47
+ const sl = toBlockchain10(tradeInput.sl);
48
+ console.log("sl", sl);
49
+ const tp = toBlockchain10(tradeInput.tp);
50
+ console.log("tp", tp);
51
+ const leverage = toBlockchain10(tradeInput.leverage);
52
+ console.log("leverage", leverage);
53
+ const openPrice = toBlockchain10(tradeInput.openPrice);
54
+ console.log("openPrice", openPrice);
55
+ // positionSizeUSDC is actually the collateral amount, not position size
56
+ const positionSizeUsdc = toBlockchain6(tradeInput.collateralInTrade);
57
+ console.log("positionSizeUsdc", positionSizeUsdc);
58
+
59
+ const trade = {
60
+ trader,
61
+ pairIndex: pairIndex,
62
+ index: 0,
63
+ initialPosToken: 0,
64
+ positionSizeUSDC: positionSizeUsdc,
65
+ openPrice: openPrice,
66
+ buy: tradeInput.isLong,
67
+ leverage: leverage,
68
+ tp: tp,
69
+ sl: sl,
70
+ timestamp: 0,
71
+ };
72
+
73
+ console.log("trade", trade);
74
+ const orderType = this.getOrderTypeValue(tradeInput.orderType);
75
+ console.log("orderType", orderType);
76
+ const slippageP = toBlockchain10(tradeInput.maxSlippageP);
77
+ console.log("slippageP", slippageP);
78
+ // const executionFee = await this.getTradeExecutionFee();
79
+ const value = ethers.parseEther("0.00035");
80
+ console.log("execution fee (wei)", value);
81
+ return {
82
+ to: await this.tradingContract.getAddress(),
83
+ data: this.tradingContract.interface.encodeFunctionData('openTrade', [
84
+ trade,
85
+ orderType,
86
+ slippageP,
87
+ // tradeInput.referrer || '0x0000000000000000000000000000000000000000',
88
+ ]),
89
+ value: value,
90
+ };
91
+ }
92
+
93
+ /**
94
+ * Build transaction to open a trade via delegation
95
+ * @param tradeInput - Trade input parameters
96
+ * @param trader - Trader address
97
+ * @returns Transaction request
98
+ */
99
+ async buildTradeOpenTxDelegate(
100
+ tradeInput: TradeInput,
101
+ trader: string
102
+ ): Promise<TransactionRequest> {
103
+ const tx = await this.buildTradeOpenTx(tradeInput, trader);
104
+ // Add delegation logic if needed
105
+ return tx;
106
+ }
107
+
108
+ /**
109
+ * Build transaction to close a trade
110
+ * @param pairIndex - Pair index
111
+ * @param tradeIndex - Trade index
112
+ * @returns Transaction request
113
+ */
114
+ async buildTradeCloseTx(
115
+ pairIndex: number,
116
+ tradeIndex: number
117
+ ): Promise<TransactionRequest> {
118
+ return {
119
+ to: await this.tradingContract.getAddress(),
120
+ data: this.tradingContract.interface.encodeFunctionData('closeTradeMarket', [
121
+ pairIndex,
122
+ tradeIndex,
123
+ ]),
124
+ };
125
+ }
126
+
127
+ /**
128
+ * Build transaction to close a trade via delegation
129
+ * @param pairIndex - Pair index
130
+ * @param tradeIndex - Trade index
131
+ * @param trader - Trader address
132
+ * @returns Transaction request
133
+ */
134
+ async buildTradeCloseTxDelegate(
135
+ pairIndex: number,
136
+ tradeIndex: number,
137
+ trader: string
138
+ ): Promise<TransactionRequest> {
139
+ const tx = await this.buildTradeCloseTx(pairIndex, tradeIndex);
140
+ // Add delegation logic if needed
141
+ return tx;
142
+ }
143
+
144
+ /**
145
+ * Build transaction to cancel a pending order
146
+ * @param pairIndex - Pair index
147
+ * @param orderIndex - Order index
148
+ * @returns Transaction request
149
+ */
150
+ async buildOrderCancelTx(
151
+ pairIndex: number,
152
+ orderIndex: number
153
+ ): Promise<TransactionRequest> {
154
+ return {
155
+ to: await this.tradingContract.getAddress(),
156
+ data: this.tradingContract.interface.encodeFunctionData('cancelOpenOrder', [
157
+ pairIndex,
158
+ orderIndex,
159
+ ]),
160
+ };
161
+ }
162
+
163
+ /**
164
+ * Build transaction to update trade margin
165
+ * @param pairIndex - Pair index
166
+ * @param tradeIndex - Trade index
167
+ * @param marginDelta - Margin change amount (USDC)
168
+ * @param updateType - Deposit or withdraw
169
+ * @returns Transaction request
170
+ */
171
+ async buildTradeMarginUpdateTx(
172
+ pairIndex: number,
173
+ tradeIndex: number,
174
+ marginDelta: number,
175
+ updateType: MarginUpdateType
176
+ ): Promise<TransactionRequest> {
177
+ const isDeposit = updateType === MarginUpdateType.DEPOSIT;
178
+
179
+ return {
180
+ to: await this.tradingContract.getAddress(),
181
+ data: this.tradingContract.interface.encodeFunctionData('updateMargin', [
182
+ pairIndex,
183
+ tradeIndex,
184
+ toBlockchain6(marginDelta),
185
+ isDeposit,
186
+ ]),
187
+ };
188
+ }
189
+
190
+ /**
191
+ * Build transaction to update take profit and stop loss
192
+ * @param pairIndex - Pair index
193
+ * @param tradeIndex - Trade index
194
+ * @param tp - Take profit price
195
+ * @param sl - Stop loss price
196
+ * @returns Transaction request
197
+ */
198
+ async buildTradeTpSlUpdateTx(
199
+ pairIndex: number,
200
+ tradeIndex: number,
201
+ tp: number,
202
+ sl: number
203
+ ): Promise<TransactionRequest> {
204
+ return {
205
+ to: await this.tradingContract.getAddress(),
206
+ data: this.tradingContract.interface.encodeFunctionData('updateTpSl', [
207
+ pairIndex,
208
+ tradeIndex,
209
+ toBlockchain10(tp),
210
+ toBlockchain10(sl),
211
+ ]),
212
+ };
213
+ }
214
+
215
+ /**
216
+ * Get trade execution fee
217
+ * @returns Execution fee in native token (wei)
218
+ */
219
+ async getTradeExecutionFee(): Promise<bigint> {
220
+ try {
221
+ return await this.tradingContract.getExecutionFee();
222
+ } catch (error) {
223
+ console.error('Error getting execution fee:', error);
224
+ return BigInt(0);
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Get all trades for a trader
230
+ * @param traderAddress - Trader address
231
+ * @param maxPairs - Maximum pair indices to check (default: 100)
232
+ * @returns Array of trades
233
+ */
234
+ async getTrades(traderAddress: string, maxPairs: number = 100): Promise<TradeResponse[]> {
235
+ try {
236
+ const trades: TradeResponse[] = [];
237
+
238
+ // Check pairs concurrently for better performance
239
+ const pairPromises: Promise<void>[] = [];
240
+
241
+ for (let pairIndex = 0; pairIndex < maxPairs; pairIndex++) {
242
+ const pairPromise = (async () => {
243
+ try {
244
+ // Get the count of trades for this trader on this pair
245
+ const count = await this.tradingStorageContract.openTradesCount(traderAddress, pairIndex);
246
+
247
+ if (count === 0n || count === 0) return;
248
+
249
+ // Fetch all trades for this pair
250
+ const tradePromises = [];
251
+ for (let index = 0; index < Number(count); index++) {
252
+ tradePromises.push(
253
+ this.tradingStorageContract.openTrades(traderAddress, pairIndex, index)
254
+ .then((trade) => {
255
+ // Only add if the trade exists (leverage > 0)
256
+ if (trade.leverage > 0) {
257
+ trades.push({
258
+ trader: trade.trader,
259
+ pairIndex: Number(trade.pairIndex),
260
+ index: Number(trade.index),
261
+ initialPosUsdc: fromBlockchain6(trade.initialPosToken || trade.positionSizeUSDC),
262
+ openPrice: fromBlockchain10(trade.openPrice),
263
+ buy: trade.buy,
264
+ leverage: Number(fromBlockchain10(trade.leverage)),
265
+ tp: fromBlockchain10(trade.tp),
266
+ sl: fromBlockchain10(trade.sl),
267
+ });
268
+ }
269
+ })
270
+ .catch(() => {
271
+ // Skip if trade doesn't exist at this index
272
+ })
273
+ );
274
+ }
275
+ await Promise.all(tradePromises);
276
+ } catch (err) {
277
+ // Skip if no trades for this pair
278
+ }
279
+ })();
280
+
281
+ pairPromises.push(pairPromise);
282
+ }
283
+
284
+ await Promise.all(pairPromises);
285
+ return trades;
286
+ } catch (error) {
287
+ console.error('Error getting trades:', error);
288
+ return [];
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Convert order type string to numeric value
294
+ * @param orderType - Order type string
295
+ * @returns Numeric order type
296
+ */
297
+ private getOrderTypeValue(orderType: string): number {
298
+ const orderTypes: Record<string, number> = {
299
+ market: 0,
300
+ limit: 1,
301
+ stop_limit: 2,
302
+ market_zero_fee: 3,
303
+ };
304
+ return orderTypes[orderType] || 0;
305
+ }
306
+ }