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,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
|
+
}
|
package/src/rpc/trade.ts
ADDED
|
@@ -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
|
+
}
|