avantis-trader-sdk 0.8.12__py3-none-any.whl → 0.8.14__py3-none-any.whl
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.
- avantis_trader_sdk/__init__.py +2 -1
- avantis_trader_sdk/abis/Trading.sol/Trading.json +1347 -1
- avantis_trader_sdk/config.py +3 -0
- avantis_trader_sdk/feed/feed_client.py +103 -7
- avantis_trader_sdk/rpc/pairs_cache.py +48 -2
- avantis_trader_sdk/rpc/trade.py +307 -86
- avantis_trader_sdk/rpc/trading_parameters.py +3 -1
- avantis_trader_sdk/types.py +144 -26
- {avantis_trader_sdk-0.8.12.dist-info → avantis_trader_sdk-0.8.14.dist-info}/METADATA +1 -1
- {avantis_trader_sdk-0.8.12.dist-info → avantis_trader_sdk-0.8.14.dist-info}/RECORD +12 -12
- {avantis_trader_sdk-0.8.12.dist-info → avantis_trader_sdk-0.8.14.dist-info}/WHEEL +0 -0
- {avantis_trader_sdk-0.8.12.dist-info → avantis_trader_sdk-0.8.14.dist-info}/top_level.txt +0 -0
avantis_trader_sdk/rpc/trade.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from ..feed.feed_client import FeedClient
|
|
2
|
+
from ..config import AVANTIS_CORE_API_BASE_URL
|
|
2
3
|
from ..types import (
|
|
3
4
|
TradeInput,
|
|
4
5
|
TradeInputOrderType,
|
|
@@ -7,9 +8,12 @@ from ..types import (
|
|
|
7
8
|
TradeInfo,
|
|
8
9
|
PendingLimitOrderExtendedResponse,
|
|
9
10
|
MarginUpdateType,
|
|
11
|
+
PriceSourcing,
|
|
10
12
|
)
|
|
11
|
-
from typing import Optional
|
|
13
|
+
from typing import Optional, List, Tuple
|
|
12
14
|
import math
|
|
15
|
+
import asyncio
|
|
16
|
+
import requests
|
|
13
17
|
|
|
14
18
|
|
|
15
19
|
class TradeRPC:
|
|
@@ -17,16 +21,23 @@ class TradeRPC:
|
|
|
17
21
|
The TradeRPC class contains methods for retrieving trading parameters from the Avantis Protocol.
|
|
18
22
|
"""
|
|
19
23
|
|
|
20
|
-
def __init__(
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
client,
|
|
27
|
+
feed_client: FeedClient,
|
|
28
|
+
core_api_base_url: Optional[str] = None,
|
|
29
|
+
):
|
|
21
30
|
"""
|
|
22
31
|
Constructor for the TradeRPC class.
|
|
23
32
|
|
|
24
33
|
Args:
|
|
25
34
|
client: The TraderClient object.
|
|
26
35
|
feed_client: The FeedClient object.
|
|
36
|
+
core_api_base_url: Optional override for the API base URL.
|
|
27
37
|
"""
|
|
28
38
|
self.client = client
|
|
29
39
|
self.feed_client = feed_client
|
|
40
|
+
self.core_api_base_url = core_api_base_url or AVANTIS_CORE_API_BASE_URL
|
|
30
41
|
|
|
31
42
|
async def build_trade_open_tx(
|
|
32
43
|
self,
|
|
@@ -193,28 +204,143 @@ class TradeRPC:
|
|
|
193
204
|
print("Error getting correct trade execution fee. Using fallback: ", e)
|
|
194
205
|
return execution_fee_wei
|
|
195
206
|
|
|
196
|
-
async def get_trades(
|
|
207
|
+
async def get_trades(
|
|
208
|
+
self,
|
|
209
|
+
trader: Optional[str] = None,
|
|
210
|
+
use_api: bool = True,
|
|
211
|
+
) -> Tuple[List[TradeExtendedResponse], List[PendingLimitOrderExtendedResponse]]:
|
|
197
212
|
"""
|
|
198
|
-
Gets the trades.
|
|
213
|
+
Gets the trades and pending limit orders for a trader.
|
|
214
|
+
|
|
215
|
+
Attempts to fetch from API first for better performance. Falls back to
|
|
216
|
+
paginated smart contract calls if API is unavailable or disabled.
|
|
199
217
|
|
|
200
218
|
Args:
|
|
201
219
|
trader: The trader's wallet address.
|
|
220
|
+
use_api: Whether to attempt API fetch first. Defaults to True.
|
|
202
221
|
|
|
203
222
|
Returns:
|
|
204
|
-
|
|
223
|
+
A tuple of (trades, pending_limit_orders).
|
|
205
224
|
"""
|
|
206
225
|
if trader is None:
|
|
207
226
|
trader = self.client.get_signer().get_ethereum_address()
|
|
208
227
|
|
|
228
|
+
if use_api:
|
|
229
|
+
api_enabled = await self._check_api_enabled(trader)
|
|
230
|
+
if api_enabled:
|
|
231
|
+
try:
|
|
232
|
+
return await self._fetch_trades_from_api(trader)
|
|
233
|
+
except Exception:
|
|
234
|
+
pass
|
|
235
|
+
|
|
236
|
+
return await self._fetch_trades_from_contracts(trader)
|
|
237
|
+
|
|
238
|
+
async def _check_api_enabled(self, trader: str) -> bool:
|
|
239
|
+
"""Checks if the API is enabled for the given trader."""
|
|
240
|
+
try:
|
|
241
|
+
response = requests.get(
|
|
242
|
+
f"{self.core_api_base_url}/user-data/config",
|
|
243
|
+
params={"wallet": trader},
|
|
244
|
+
timeout=5,
|
|
245
|
+
)
|
|
246
|
+
response.raise_for_status()
|
|
247
|
+
data = response.json()
|
|
248
|
+
return data.get("globallyEnabled", False) or data.get(
|
|
249
|
+
"enabledForWallet", False
|
|
250
|
+
)
|
|
251
|
+
except Exception:
|
|
252
|
+
return False
|
|
253
|
+
|
|
254
|
+
async def _fetch_trades_from_api(
|
|
255
|
+
self, trader: str
|
|
256
|
+
) -> Tuple[List[TradeExtendedResponse], List[PendingLimitOrderExtendedResponse]]:
|
|
257
|
+
"""Fetches trades from the API."""
|
|
258
|
+
response = requests.get(
|
|
259
|
+
f"{self.core_api_base_url}/user-data",
|
|
260
|
+
params={"trader": trader},
|
|
261
|
+
timeout=10,
|
|
262
|
+
)
|
|
263
|
+
response.raise_for_status()
|
|
264
|
+
data = response.json()
|
|
265
|
+
|
|
266
|
+
trades = []
|
|
267
|
+
for position in data.get("positions", []):
|
|
268
|
+
loss_protection_tier = int(position.get("lossProtection", 0))
|
|
269
|
+
pair_index = int(position.get("pairIndex", 0))
|
|
270
|
+
loss_protection_pct = await self.client.trading_parameters.get_loss_protection_percentage_by_tier(
|
|
271
|
+
loss_protection_tier, pair_index
|
|
272
|
+
)
|
|
273
|
+
position["lossProtectionPercentage"] = loss_protection_pct
|
|
274
|
+
trades.append(TradeExtendedResponse(**position))
|
|
275
|
+
|
|
276
|
+
limit_orders = [
|
|
277
|
+
PendingLimitOrderExtendedResponse(**order)
|
|
278
|
+
for order in data.get("limitOrders", [])
|
|
279
|
+
]
|
|
280
|
+
|
|
281
|
+
return trades, limit_orders
|
|
282
|
+
|
|
283
|
+
async def _fetch_trades_from_contracts(
|
|
284
|
+
self,
|
|
285
|
+
trader: str,
|
|
286
|
+
max_pairs_per_call: int = 12,
|
|
287
|
+
) -> Tuple[List[TradeExtendedResponse], List[PendingLimitOrderExtendedResponse]]:
|
|
288
|
+
"""Fetches trades from smart contracts with paginated calls."""
|
|
289
|
+
socket_info = await self.client.pairs_cache.get_info_from_socket()
|
|
290
|
+
max_trades_per_pair = socket_info.get("maxTradesPerPair", 40)
|
|
291
|
+
|
|
292
|
+
pairs_count = await self.client.pairs_cache.get_pairs_count()
|
|
293
|
+
pair_ranges = self._build_pair_ranges(pairs_count, max_pairs_per_call)
|
|
294
|
+
|
|
295
|
+
tasks = [
|
|
296
|
+
self._fetch_positions_for_range(trader, start, end, max_trades_per_pair)
|
|
297
|
+
for start, end in pair_ranges
|
|
298
|
+
]
|
|
299
|
+
results = await asyncio.gather(*tasks)
|
|
300
|
+
|
|
301
|
+
raw_trades = []
|
|
302
|
+
raw_orders = []
|
|
303
|
+
for trades_batch, orders_batch in results:
|
|
304
|
+
raw_trades.extend(trades_batch)
|
|
305
|
+
raw_orders.extend(orders_batch)
|
|
306
|
+
|
|
307
|
+
trades = await self._parse_raw_trades(raw_trades)
|
|
308
|
+
limit_orders = self._parse_raw_limit_orders(raw_orders)
|
|
309
|
+
|
|
310
|
+
return trades, limit_orders
|
|
311
|
+
|
|
312
|
+
def _build_pair_ranges(
|
|
313
|
+
self, pairs_count: int, max_pairs_per_call: int
|
|
314
|
+
) -> List[Tuple[int, int]]:
|
|
315
|
+
"""Builds pair index ranges for paginated fetching."""
|
|
316
|
+
ranges = []
|
|
317
|
+
for i in range(0, pairs_count, max_pairs_per_call):
|
|
318
|
+
start = i
|
|
319
|
+
end = min(i + max_pairs_per_call, pairs_count)
|
|
320
|
+
ranges.append((start, end))
|
|
321
|
+
return ranges
|
|
322
|
+
|
|
323
|
+
async def _fetch_positions_for_range(
|
|
324
|
+
self,
|
|
325
|
+
trader: str,
|
|
326
|
+
start_pair: int,
|
|
327
|
+
end_pair: int,
|
|
328
|
+
max_trades_per_pair: int,
|
|
329
|
+
) -> Tuple[list, list]:
|
|
330
|
+
"""Fetches positions for a range of pair indexes."""
|
|
209
331
|
result = (
|
|
210
332
|
await self.client.contracts.get("Multicall")
|
|
211
|
-
.functions.
|
|
333
|
+
.functions.getPositionsForPairIndexes(
|
|
334
|
+
trader, start_pair, end_pair, max_trades_per_pair
|
|
335
|
+
)
|
|
212
336
|
.call()
|
|
213
337
|
)
|
|
214
|
-
|
|
215
|
-
pendingOpenLimitOrders = []
|
|
338
|
+
return result[0], result[1]
|
|
216
339
|
|
|
217
|
-
|
|
340
|
+
async def _parse_raw_trades(self, raw_trades: list) -> List[TradeExtendedResponse]:
|
|
341
|
+
"""Parses raw contract trade data into TradeExtendedResponse objects."""
|
|
342
|
+
trades = []
|
|
343
|
+
for aggregated_trade in raw_trades:
|
|
218
344
|
(trade, trade_info, margin_fee, liquidation_price, is_zfp) = (
|
|
219
345
|
aggregated_trade
|
|
220
346
|
)
|
|
@@ -222,71 +348,64 @@ class TradeRPC:
|
|
|
222
348
|
if trade[7] <= 0:
|
|
223
349
|
continue
|
|
224
350
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
"pairIndex": trade[1],
|
|
230
|
-
"index": trade[2],
|
|
231
|
-
"initialPosToken": trade[3],
|
|
232
|
-
"positionSizeUSDC": trade[4],
|
|
233
|
-
"openPrice": trade[5],
|
|
234
|
-
"buy": trade[6],
|
|
235
|
-
"leverage": trade[7],
|
|
236
|
-
"tp": trade[8],
|
|
237
|
-
"sl": trade[9],
|
|
238
|
-
"timestamp": trade[10],
|
|
239
|
-
},
|
|
240
|
-
"additional_info": {
|
|
241
|
-
"openInterestUSDC": trade_info[0],
|
|
242
|
-
"tpLastUpdated": trade_info[1],
|
|
243
|
-
"slLastUpdated": trade_info[2],
|
|
244
|
-
"beingMarketClosed": trade_info[3],
|
|
245
|
-
"lossProtectionPercentage": await self.client.trading_parameters.get_loss_protection_percentage_by_tier(
|
|
246
|
-
trade_info[4], trade[1]
|
|
247
|
-
),
|
|
248
|
-
},
|
|
249
|
-
"margin_fee": margin_fee,
|
|
250
|
-
"liquidationPrice": liquidation_price,
|
|
251
|
-
"is_zfp": is_zfp,
|
|
252
|
-
}
|
|
351
|
+
loss_protection = await self.client.trading_parameters.get_loss_protection_percentage_by_tier(
|
|
352
|
+
trade_info[4], trade[1]
|
|
353
|
+
)
|
|
354
|
+
|
|
253
355
|
trades.append(
|
|
254
356
|
TradeExtendedResponse(
|
|
255
|
-
trade=TradeResponse(
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
357
|
+
trade=TradeResponse(
|
|
358
|
+
trader=trade[0],
|
|
359
|
+
pairIndex=trade[1],
|
|
360
|
+
index=trade[2],
|
|
361
|
+
initialPosToken=trade[3],
|
|
362
|
+
positionSizeUSDC=trade[3],
|
|
363
|
+
openPrice=trade[5],
|
|
364
|
+
buy=trade[6],
|
|
365
|
+
leverage=trade[7],
|
|
366
|
+
tp=trade[8],
|
|
367
|
+
sl=trade[9],
|
|
368
|
+
timestamp=trade[10],
|
|
369
|
+
),
|
|
370
|
+
additional_info=TradeInfo(
|
|
371
|
+
lossProtectionPercentage=loss_protection,
|
|
372
|
+
),
|
|
373
|
+
margin_fee=margin_fee,
|
|
374
|
+
liquidation_price=liquidation_price,
|
|
375
|
+
is_zfp=is_zfp,
|
|
260
376
|
)
|
|
261
377
|
)
|
|
262
|
-
|
|
263
|
-
|
|
378
|
+
return trades
|
|
379
|
+
|
|
380
|
+
def _parse_raw_limit_orders(
|
|
381
|
+
self, raw_orders: list
|
|
382
|
+
) -> List[PendingLimitOrderExtendedResponse]:
|
|
383
|
+
"""Parses raw contract order data into PendingLimitOrderExtendedResponse objects."""
|
|
384
|
+
orders = []
|
|
385
|
+
for aggregated_order in raw_orders:
|
|
264
386
|
(order, liquidation_price) = aggregated_order
|
|
265
387
|
|
|
266
388
|
if order[5] <= 0:
|
|
267
389
|
continue
|
|
268
390
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
pendingOpenLimitOrders.append(
|
|
286
|
-
PendingLimitOrderExtendedResponse(**order_details)
|
|
391
|
+
orders.append(
|
|
392
|
+
PendingLimitOrderExtendedResponse(
|
|
393
|
+
trader=order[0],
|
|
394
|
+
pairIndex=order[1],
|
|
395
|
+
index=order[2],
|
|
396
|
+
positionSize=order[3],
|
|
397
|
+
buy=order[4],
|
|
398
|
+
leverage=order[5],
|
|
399
|
+
tp=order[6],
|
|
400
|
+
sl=order[7],
|
|
401
|
+
price=order[8],
|
|
402
|
+
slippageP=order[9],
|
|
403
|
+
block=order[10],
|
|
404
|
+
executionFee=order[11],
|
|
405
|
+
liquidation_price=liquidation_price,
|
|
406
|
+
)
|
|
287
407
|
)
|
|
288
|
-
|
|
289
|
-
return trades, pendingOpenLimitOrders
|
|
408
|
+
return orders
|
|
290
409
|
|
|
291
410
|
async def build_trade_close_tx(
|
|
292
411
|
self,
|
|
@@ -477,6 +596,7 @@ class TradeRPC:
|
|
|
477
596
|
margin_update_type: MarginUpdateType,
|
|
478
597
|
collateral_change: float,
|
|
479
598
|
trader: Optional[str] = None,
|
|
599
|
+
price_sourcing: PriceSourcing = PriceSourcing.PRO,
|
|
480
600
|
):
|
|
481
601
|
"""
|
|
482
602
|
Builds a transaction to update the margin of a trade.
|
|
@@ -487,6 +607,7 @@ class TradeRPC:
|
|
|
487
607
|
margin_update_type: The margin update type.
|
|
488
608
|
collateral_change: The collateral change.
|
|
489
609
|
trader (optional): The trader's wallet address.
|
|
610
|
+
price_sourcing: The price sourcing to use. Defaults to PriceSourcing.PRO (Pyth Pro/Lazer).
|
|
490
611
|
Returns:
|
|
491
612
|
A transaction object.
|
|
492
613
|
"""
|
|
@@ -497,11 +618,15 @@ class TradeRPC:
|
|
|
497
618
|
|
|
498
619
|
collateral_change = int(collateral_change * 10**6)
|
|
499
620
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
621
|
+
if price_sourcing == PriceSourcing.PRO:
|
|
622
|
+
price_data = await self.feed_client.get_price_update_data(pair_index)
|
|
623
|
+
price_update_data = price_data.pro.price_update_data
|
|
624
|
+
else:
|
|
625
|
+
pair_name = await self.client.pairs_cache.get_pair_name_from_index(
|
|
626
|
+
pair_index
|
|
627
|
+
)
|
|
628
|
+
price_data = await self.feed_client.get_latest_price_updates([pair_name])
|
|
629
|
+
price_update_data = "0x" + price_data.binary.data[0]
|
|
505
630
|
|
|
506
631
|
transaction = await Trading.functions.updateMargin(
|
|
507
632
|
pair_index,
|
|
@@ -509,6 +634,7 @@ class TradeRPC:
|
|
|
509
634
|
margin_update_type.value,
|
|
510
635
|
collateral_change,
|
|
511
636
|
[price_update_data],
|
|
637
|
+
price_sourcing.value,
|
|
512
638
|
).build_transaction(
|
|
513
639
|
{
|
|
514
640
|
"from": trader,
|
|
@@ -527,6 +653,7 @@ class TradeRPC:
|
|
|
527
653
|
margin_update_type: MarginUpdateType,
|
|
528
654
|
collateral_change: float,
|
|
529
655
|
trader: Optional[str] = None,
|
|
656
|
+
price_sourcing: PriceSourcing = PriceSourcing.PRO,
|
|
530
657
|
):
|
|
531
658
|
"""
|
|
532
659
|
Builds a transaction to update the margin of a trade.
|
|
@@ -537,6 +664,7 @@ class TradeRPC:
|
|
|
537
664
|
margin_update_type: The margin update type.
|
|
538
665
|
collateral_change: The collateral change.
|
|
539
666
|
trader (optional): The trader's wallet address.
|
|
667
|
+
price_sourcing: The price sourcing to use. Defaults to PriceSourcing.PRO (Pyth Pro/Lazer).
|
|
540
668
|
Returns:
|
|
541
669
|
A transaction object.
|
|
542
670
|
"""
|
|
@@ -547,11 +675,15 @@ class TradeRPC:
|
|
|
547
675
|
|
|
548
676
|
collateral_change = int(collateral_change * 10**6)
|
|
549
677
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
678
|
+
if price_sourcing == PriceSourcing.PRO:
|
|
679
|
+
price_data = await self.feed_client.get_price_update_data(pair_index)
|
|
680
|
+
price_update_data = price_data.pro.price_update_data
|
|
681
|
+
else:
|
|
682
|
+
pair_name = await self.client.pairs_cache.get_pair_name_from_index(
|
|
683
|
+
pair_index
|
|
684
|
+
)
|
|
685
|
+
price_data = await self.feed_client.get_latest_price_updates([pair_name])
|
|
686
|
+
price_update_data = "0x" + price_data.binary.data[0]
|
|
555
687
|
|
|
556
688
|
transaction = await Trading.functions.updateMargin(
|
|
557
689
|
pair_index,
|
|
@@ -559,6 +691,7 @@ class TradeRPC:
|
|
|
559
691
|
margin_update_type.value,
|
|
560
692
|
collateral_change,
|
|
561
693
|
[price_update_data],
|
|
694
|
+
price_sourcing.value,
|
|
562
695
|
).build_transaction(
|
|
563
696
|
{
|
|
564
697
|
"from": trader,
|
|
@@ -590,6 +723,7 @@ class TradeRPC:
|
|
|
590
723
|
take_profit_price: float,
|
|
591
724
|
stop_loss_price: float,
|
|
592
725
|
trader: str = None,
|
|
726
|
+
price_sourcing: PriceSourcing = PriceSourcing.PRO,
|
|
593
727
|
):
|
|
594
728
|
"""
|
|
595
729
|
Builds a transaction to update the stop loss and take profit of a trade.
|
|
@@ -600,6 +734,7 @@ class TradeRPC:
|
|
|
600
734
|
take_profit_price: The take profit price.
|
|
601
735
|
stop_loss_price: The stop loss price. Pass 0 if you want to remove the stop loss.
|
|
602
736
|
trader (optional): The trader's wallet address.
|
|
737
|
+
price_sourcing: The price sourcing to use. Defaults to PriceSourcing.PRO (Pyth Pro/Lazer).
|
|
603
738
|
Returns:
|
|
604
739
|
A transaction object.
|
|
605
740
|
"""
|
|
@@ -611,11 +746,15 @@ class TradeRPC:
|
|
|
611
746
|
if trader is None:
|
|
612
747
|
trader = self.client.get_signer().get_ethereum_address()
|
|
613
748
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
749
|
+
if price_sourcing == PriceSourcing.PRO:
|
|
750
|
+
price_data = await self.feed_client.get_price_update_data(pair_index)
|
|
751
|
+
price_update_data = price_data.pro.price_update_data
|
|
752
|
+
else:
|
|
753
|
+
pair_name = await self.client.pairs_cache.get_pair_name_from_index(
|
|
754
|
+
pair_index
|
|
755
|
+
)
|
|
756
|
+
price_data = await self.feed_client.get_latest_price_updates([pair_name])
|
|
757
|
+
price_update_data = "0x" + price_data.binary.data[0]
|
|
619
758
|
|
|
620
759
|
take_profit_price = int(take_profit_price * 10**10)
|
|
621
760
|
stop_loss_price = int(stop_loss_price * 10**10)
|
|
@@ -626,6 +765,7 @@ class TradeRPC:
|
|
|
626
765
|
stop_loss_price,
|
|
627
766
|
take_profit_price,
|
|
628
767
|
[price_update_data],
|
|
768
|
+
price_sourcing.value,
|
|
629
769
|
).build_transaction(
|
|
630
770
|
{
|
|
631
771
|
"from": trader,
|
|
@@ -645,6 +785,7 @@ class TradeRPC:
|
|
|
645
785
|
take_profit_price: float,
|
|
646
786
|
stop_loss_price: float,
|
|
647
787
|
trader: str = None,
|
|
788
|
+
price_sourcing: PriceSourcing = PriceSourcing.PRO,
|
|
648
789
|
):
|
|
649
790
|
"""
|
|
650
791
|
Builds a transaction to update the stop loss and take profit of a trade.
|
|
@@ -655,6 +796,7 @@ class TradeRPC:
|
|
|
655
796
|
take_profit_price: The take profit price.
|
|
656
797
|
stop_loss_price: The stop loss price. Pass 0 if you want to remove the stop loss.
|
|
657
798
|
trader (optional): The trader's wallet address.
|
|
799
|
+
price_sourcing: The price sourcing to use. Defaults to PriceSourcing.PRO (Pyth Pro/Lazer).
|
|
658
800
|
Returns:
|
|
659
801
|
A transaction object.
|
|
660
802
|
"""
|
|
@@ -666,13 +808,15 @@ class TradeRPC:
|
|
|
666
808
|
if trader is None:
|
|
667
809
|
trader = self.client.get_signer().get_ethereum_address()
|
|
668
810
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
811
|
+
if price_sourcing == PriceSourcing.PRO:
|
|
812
|
+
price_data = await self.feed_client.get_price_update_data(pair_index)
|
|
813
|
+
price_update_data = price_data.pro.price_update_data
|
|
814
|
+
else:
|
|
815
|
+
pair_name = await self.client.pairs_cache.get_pair_name_from_index(
|
|
816
|
+
pair_index
|
|
817
|
+
)
|
|
818
|
+
price_data = await self.feed_client.get_latest_price_updates([pair_name])
|
|
819
|
+
price_update_data = "0x" + price_data.binary.data[0]
|
|
676
820
|
|
|
677
821
|
take_profit_price = int(take_profit_price * 10**10)
|
|
678
822
|
stop_loss_price = int(stop_loss_price * 10**10)
|
|
@@ -683,6 +827,7 @@ class TradeRPC:
|
|
|
683
827
|
stop_loss_price,
|
|
684
828
|
take_profit_price,
|
|
685
829
|
[price_update_data],
|
|
830
|
+
price_sourcing.value,
|
|
686
831
|
).build_transaction(
|
|
687
832
|
{
|
|
688
833
|
"from": trader,
|
|
@@ -707,3 +852,79 @@ class TradeRPC:
|
|
|
707
852
|
}
|
|
708
853
|
)
|
|
709
854
|
return delegate_transaction
|
|
855
|
+
|
|
856
|
+
async def get_delegate(self, trader: Optional[str] = None) -> str:
|
|
857
|
+
"""
|
|
858
|
+
Gets the delegate address for a trader.
|
|
859
|
+
|
|
860
|
+
Args:
|
|
861
|
+
trader: The trader's wallet address. Defaults to signer's address.
|
|
862
|
+
|
|
863
|
+
Returns:
|
|
864
|
+
The delegate address, or zero address if no delegate is set.
|
|
865
|
+
"""
|
|
866
|
+
Trading = self.client.contracts.get("Trading")
|
|
867
|
+
|
|
868
|
+
if trader is None:
|
|
869
|
+
trader = self.client.get_signer().get_ethereum_address()
|
|
870
|
+
|
|
871
|
+
delegate = await Trading.functions.delegations(trader).call()
|
|
872
|
+
return delegate
|
|
873
|
+
|
|
874
|
+
async def build_set_delegate_tx(
|
|
875
|
+
self,
|
|
876
|
+
delegate: str,
|
|
877
|
+
trader: Optional[str] = None,
|
|
878
|
+
):
|
|
879
|
+
"""
|
|
880
|
+
Builds a transaction to set a delegate for trading.
|
|
881
|
+
|
|
882
|
+
The delegate can perform all trade-related actions on behalf of the trader.
|
|
883
|
+
Each wallet can have at most one delegate.
|
|
884
|
+
|
|
885
|
+
Args:
|
|
886
|
+
delegate: The delegate's wallet address.
|
|
887
|
+
trader: The trader's wallet address. Defaults to signer's address.
|
|
888
|
+
|
|
889
|
+
Returns:
|
|
890
|
+
A transaction object.
|
|
891
|
+
"""
|
|
892
|
+
Trading = self.client.contracts.get("Trading")
|
|
893
|
+
|
|
894
|
+
if trader is None:
|
|
895
|
+
trader = self.client.get_signer().get_ethereum_address()
|
|
896
|
+
|
|
897
|
+
transaction = await Trading.functions.setDelegate(delegate).build_transaction(
|
|
898
|
+
{
|
|
899
|
+
"from": trader,
|
|
900
|
+
"chainId": self.client.chain_id,
|
|
901
|
+
"nonce": await self.client.get_transaction_count(trader),
|
|
902
|
+
}
|
|
903
|
+
)
|
|
904
|
+
|
|
905
|
+
return transaction
|
|
906
|
+
|
|
907
|
+
async def build_remove_delegate_tx(self, trader: Optional[str] = None):
|
|
908
|
+
"""
|
|
909
|
+
Builds a transaction to remove the current delegate.
|
|
910
|
+
|
|
911
|
+
Args:
|
|
912
|
+
trader: The trader's wallet address. Defaults to signer's address.
|
|
913
|
+
|
|
914
|
+
Returns:
|
|
915
|
+
A transaction object.
|
|
916
|
+
"""
|
|
917
|
+
Trading = self.client.contracts.get("Trading")
|
|
918
|
+
|
|
919
|
+
if trader is None:
|
|
920
|
+
trader = self.client.get_signer().get_ethereum_address()
|
|
921
|
+
|
|
922
|
+
transaction = await Trading.functions.removeDelegate().build_transaction(
|
|
923
|
+
{
|
|
924
|
+
"from": trader,
|
|
925
|
+
"chainId": self.client.chain_id,
|
|
926
|
+
"nonce": await self.client.get_transaction_count(trader),
|
|
927
|
+
}
|
|
928
|
+
)
|
|
929
|
+
|
|
930
|
+
return transaction
|
|
@@ -57,7 +57,9 @@ class TradingParametersRPC:
|
|
|
57
57
|
Returns:
|
|
58
58
|
The loss protection percentage.
|
|
59
59
|
"""
|
|
60
|
-
pair_info = await self.client.pairs_cache.get_pair_info_from_socket(
|
|
60
|
+
pair_info = await self.client.pairs_cache.get_pair_info_from_socket(
|
|
61
|
+
pair_index, use_cache=True
|
|
62
|
+
)
|
|
61
63
|
return pair_info["lossProtectionMultiplier"][str(tier)]
|
|
62
64
|
|
|
63
65
|
async def get_loss_protection_percentage(self, trade: TradeInput):
|