avantis-trader-sdk 0.6.0__py3-none-any.whl → 0.8.0__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.
@@ -150,9 +150,8 @@ class TraderClient:
150
150
  if not self.has_signer():
151
151
  return transaction
152
152
 
153
- signed_txn = await self.sign_transaction(transaction)
154
- tx_hash = await self.send_and_get_transaction_hash(signed_txn)
155
- return tx_hash
153
+ receipt = await self.sign_and_get_receipt(transaction)
154
+ return receipt
156
155
 
157
156
  def set_signer(self, signer: BaseSigner):
158
157
  """
@@ -290,7 +289,8 @@ class TraderClient:
290
289
  """
291
290
  if address is None:
292
291
  address = self.get_signer().get_ethereum_address()
293
- return await self.async_web3.eth.get_balance(address)
292
+ balance = await self.async_web3.eth.get_balance(address)
293
+ return balance / 10**18
294
294
 
295
295
  async def get_usdc_balance(self, address=None):
296
296
  """
@@ -4,9 +4,11 @@ MAINNET_ADDRESSES = {
4
4
  "PairInfos": "0x81F22d0Cc22977c91bEfE648C9fddf1f2bd977e5",
5
5
  "PriceAggregator": "0x64e2625621970F8cfA17B294670d61CB883dA511",
6
6
  "USDC": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
7
- "Trading": "0x5FF292d70bA9cD9e7CCb313782811b3D7120535f",
8
- "Multicall": "0xD4693314460d6fb598C1124aeC40C03e2Aa0A8a4",
9
- "Referral": "0xA96f577821933d127B491D0F91202405B0dbB1bd",
7
+ "Trading": "0x44914408af82bC9983bbb330e3578E1105e11d4e",
8
+ "Multicall": "0x7A829c5C97A2Bf8BeFB4b01d96A282E4763848d8",
9
+ "Referral": "0x1A110bBA13A1f16cCa4b79758BD39290f29De82D",
10
10
  }
11
11
 
12
+ AVANTIS_SOCKET_API = "https://socket-api.avantisfi.com/v1/data"
13
+
12
14
  CONTRACT_ADDRESSES = MAINNET_ADDRESSES
@@ -1,9 +1,12 @@
1
1
  import json
2
2
  import websockets
3
- from pathlib import Path
4
- from ..types import PriceFeedResponse, PriceFeedUpdatesResponse
5
- from typing import List
3
+ from ..types import PriceFeedResponse, PriceFeedUpdatesResponse, PairInfoFeed
4
+ from typing import List, Callable
6
5
  import requests
6
+ from pydantic import ValidationError
7
+ from ..config import AVANTIS_SOCKET_API
8
+ import asyncio
9
+ from concurrent.futures import ThreadPoolExecutor
7
10
 
8
11
 
9
12
  class FeedClient:
@@ -17,6 +20,7 @@ class FeedClient:
17
20
  on_error=None,
18
21
  on_close=None,
19
22
  hermes_url="https://hermes.pyth.network/v2/updates/price/latest",
23
+ pair_fetcher: Callable = None,
20
24
  ):
21
25
  """
22
26
  Constructor for the FeedClient class.
@@ -42,6 +46,7 @@ class FeedClient:
42
46
  self._connected = False
43
47
  self._on_error = on_error
44
48
  self._on_close = on_close
49
+ self.pair_fetcher = pair_fetcher or self.default_pair_fetcher
45
50
  self._load_pair_feeds()
46
51
 
47
52
  async def listen_for_price_updates(self):
@@ -95,14 +100,65 @@ class FeedClient:
95
100
  else:
96
101
  raise e
97
102
 
103
+ async def default_pair_fetcher(self) -> List[dict]:
104
+ """
105
+ Default pair fetcher that retrieves data from the Avantis API.
106
+ Returns:
107
+ A list of validated trading pairs.
108
+ Raises:
109
+ ValueError if API response is invalid.
110
+ """
111
+ if not AVANTIS_SOCKET_API:
112
+ raise ValueError("AVANTIS_SOCKET_API is not set")
113
+ try:
114
+ response = requests.get(AVANTIS_SOCKET_API)
115
+ response.raise_for_status()
116
+
117
+ result = response.json()
118
+ pairs = result["data"]["pairInfos"].values()
119
+
120
+ return pairs
121
+ except (requests.RequestException, ValidationError) as e:
122
+ print(f"Error fetching pair feeds: {e}")
123
+ return []
124
+
98
125
  def _load_pair_feeds(self):
99
126
  """
100
- Loads the pair feeds from the json file.
127
+ Loads the pair feeds dynamically using the provided pair_fetcher function.
101
128
  """
102
- feed_path = Path(__file__).parent / "feedIds.json"
103
- with open(feed_path) as feed_file:
104
- self.pair_feeds = json.load(feed_file)
105
- self.feed_pairs = {v["id"]: k for k, v in self.pair_feeds.items()}
129
+
130
+ try:
131
+ try:
132
+ asyncio.get_running_loop()
133
+ except RuntimeError:
134
+ asyncio.set_event_loop(asyncio.new_event_loop())
135
+
136
+ with ThreadPoolExecutor() as executor:
137
+ future = executor.submit(lambda: asyncio.run(self.pair_fetcher()))
138
+ pairs = future.result()
139
+
140
+ if not pairs:
141
+ raise ValueError("Fetched pair feed data is empty or invalid.")
142
+
143
+ if isinstance(pairs, dict):
144
+ pairs = list(pairs.values())
145
+ else:
146
+ pairs = list(pairs)
147
+
148
+ if hasattr(pairs[0], "model_dump_json"):
149
+ pairs = [json.loads(pair.model_dump_json()) for pair in pairs]
150
+
151
+ validated_pairs = [PairInfoFeed.model_validate(pair) for pair in pairs]
152
+
153
+ self.pair_feeds = {
154
+ f"{pair.from_}/{pair.to}": {"id": pair.feed.feed_id}
155
+ for pair in validated_pairs
156
+ }
157
+ self.feed_pairs = {
158
+ pair.feed.feed_id: f"{pair.from_}/{pair.to}" for pair in validated_pairs
159
+ }
160
+ except Exception as e:
161
+ print(f"Failed to load pair feeds: {e}")
106
162
 
107
163
  def get_pair_from_feed_id(self, feed_id):
108
164
  """
@@ -161,21 +161,21 @@ class AssetParametersRPC:
161
161
  PairInfos.address,
162
162
  PairInfos.encodeABI(
163
163
  fn_name="getPriceImpactSpread",
164
- args=[pair_index, True, position_size],
164
+ args=[pair_index, True, position_size, False],
165
165
  ),
166
166
  ),
167
167
  (
168
168
  PairInfos.address,
169
169
  PairInfos.encodeABI(
170
170
  fn_name="getPriceImpactSpread",
171
- args=[pair_index, False, position_size],
171
+ args=[pair_index, False, position_size, False],
172
172
  ),
173
173
  ),
174
174
  ]
175
175
  )
176
176
  else:
177
177
  response = await PairInfos.functions.getPriceImpactSpread(
178
- pair_index, is_long, position_size
178
+ pair_index, is_long, position_size, False
179
179
  ).call()
180
180
  else:
181
181
  pairs_info = await self.client.pairs_cache.get_pairs_info()
@@ -189,14 +189,14 @@ class AssetParametersRPC:
189
189
  PairInfos.address,
190
190
  PairInfos.encodeABI(
191
191
  fn_name="getPriceImpactSpread",
192
- args=[pair_index, True, position_size],
192
+ args=[pair_index, True, position_size, False],
193
193
  ),
194
194
  ),
195
195
  (
196
196
  PairInfos.address,
197
197
  PairInfos.encodeABI(
198
198
  fn_name="getPriceImpactSpread",
199
- args=[pair_index, False, position_size],
199
+ args=[pair_index, False, position_size, False],
200
200
  ),
201
201
  ),
202
202
  ]
@@ -207,7 +207,7 @@ class AssetParametersRPC:
207
207
  PairInfos.address,
208
208
  PairInfos.encodeABI(
209
209
  fn_name="getPriceImpactSpread",
210
- args=[pair_index, is_long, position_size],
210
+ args=[pair_index, is_long, position_size, False],
211
211
  ),
212
212
  )
213
213
  )
@@ -295,21 +295,21 @@ class AssetParametersRPC:
295
295
  PairInfos.address,
296
296
  PairInfos.encodeABI(
297
297
  fn_name="getSkewImpactSpread",
298
- args=[pair_index, True, position_size],
298
+ args=[pair_index, True, position_size, False],
299
299
  ),
300
300
  ),
301
301
  (
302
302
  PairInfos.address,
303
303
  PairInfos.encodeABI(
304
304
  fn_name="getSkewImpactSpread",
305
- args=[pair_index, False, position_size],
305
+ args=[pair_index, False, position_size, False],
306
306
  ),
307
307
  ),
308
308
  ]
309
309
  )
310
310
  else:
311
311
  response = await PairInfos.functions.getSkewImpactSpread(
312
- pair_index, is_long, position_size
312
+ pair_index, is_long, position_size, False
313
313
  ).call()
314
314
  else:
315
315
  pairs_info = await self.client.pairs_cache.get_pairs_info()
@@ -322,14 +322,14 @@ class AssetParametersRPC:
322
322
  PairInfos.address,
323
323
  PairInfos.encodeABI(
324
324
  fn_name="getSkewImpactSpread",
325
- args=[pair_index, True, position_size],
325
+ args=[pair_index, True, position_size, False],
326
326
  ),
327
327
  ),
328
328
  (
329
329
  PairInfos.address,
330
330
  PairInfos.encodeABI(
331
331
  fn_name="getSkewImpactSpread",
332
- args=[pair_index, False, position_size],
332
+ args=[pair_index, False, position_size, False],
333
333
  ),
334
334
  ),
335
335
  ]
@@ -340,7 +340,7 @@ class AssetParametersRPC:
340
340
  PairInfos.address,
341
341
  PairInfos.encodeABI(
342
342
  fn_name="getSkewImpactSpread",
343
- args=[pair_index, is_long, position_size],
343
+ args=[pair_index, is_long, position_size, False],
344
344
  ),
345
345
  )
346
346
  )
@@ -423,21 +423,21 @@ class AssetParametersRPC:
423
423
  PairInfos.address,
424
424
  PairInfos.encodeABI(
425
425
  fn_name="getTradePriceImpact",
426
- args=[open_price, pair_index, True, position_size],
426
+ args=[open_price, pair_index, True, position_size, False],
427
427
  ),
428
428
  ),
429
429
  (
430
430
  PairInfos.address,
431
431
  PairInfos.encodeABI(
432
432
  fn_name="getTradePriceImpact",
433
- args=[open_price, pair_index, False, position_size],
433
+ args=[open_price, pair_index, False, position_size, False],
434
434
  ),
435
435
  ),
436
436
  ]
437
437
  )
438
438
  else:
439
439
  response = await PairInfos.functions.getTradePriceImpact(
440
- open_price, pair_index, is_long, position_size
440
+ open_price, pair_index, is_long, position_size, False
441
441
  ).call()
442
442
 
443
443
  if response is None:
@@ -60,9 +60,10 @@ class TradeRPC:
60
60
 
61
61
  if (
62
62
  trade_input_order_type == TradeInputOrderType.MARKET
63
- and not trade_input.openPrice
64
- ):
63
+ or trade_input_order_type == TradeInputOrderType.MARKET_PNL
64
+ ) and not trade_input.openPrice:
65
65
  feed_client = self.FeedClient()
66
+
66
67
  pair_name = await self.client.pairs_cache.get_pair_name_from_index(
67
68
  trade_input.pairIndex
68
69
  )
@@ -80,7 +81,6 @@ class TradeRPC:
80
81
  trade_input.model_dump(),
81
82
  trade_input_order_type.value,
82
83
  slippage_percentage * 10**10,
83
- 0,
84
84
  ).build_transaction(
85
85
  {
86
86
  "from": trade_input.trader,
@@ -92,6 +92,86 @@ class TradeRPC:
92
92
 
93
93
  return transaction
94
94
 
95
+ async def build_trade_open_tx_delegate(
96
+ self,
97
+ trade_input: TradeInput,
98
+ trade_input_order_type: TradeInputOrderType,
99
+ slippage_percentage: int,
100
+ execution_fee: Optional[float] = None,
101
+ ):
102
+ """
103
+ Builds a transaction to open a trade.
104
+
105
+ Args:
106
+ trade: The trade input object.
107
+ trade_input_order_type: The trade input order type.
108
+ slippage_percentage: The slippage percentage.
109
+
110
+ Returns:
111
+ A transaction object.
112
+ """
113
+ Trading = self.client.contracts.get("Trading")
114
+
115
+ if (
116
+ trade_input.trader == "0x1234567890123456789012345678901234567890"
117
+ and self.client.get_signer() is not None
118
+ ):
119
+ trade_input.trader = await self.client.get_signer().get_ethereum_address()
120
+
121
+ if execution_fee is not None:
122
+ execution_fee_wei = int(execution_fee * 10**18)
123
+ else:
124
+ execution_fee_wei = await self.get_trade_execution_fee()
125
+
126
+ if (
127
+ trade_input_order_type == TradeInputOrderType.MARKET
128
+ or trade_input_order_type == TradeInputOrderType.MARKET_PNL
129
+ ) and not trade_input.openPrice:
130
+ feed_client = self.FeedClient()
131
+
132
+ pair_name = await self.client.pairs_cache.get_pair_name_from_index(
133
+ trade_input.pairIndex
134
+ )
135
+ price_data = await feed_client.get_latest_price_updates([pair_name])
136
+ price = int(price_data.parsed[0].converted_price * 10**10)
137
+ trade_input.openPrice = price
138
+
139
+ if (
140
+ trade_input_order_type == TradeInputOrderType.LIMIT
141
+ or trade_input_order_type == TradeInputOrderType.STOP_LIMIT
142
+ ) and not trade_input.openPrice:
143
+ raise Exception("Open price is required for LIMIT/STOP LIMIT order type")
144
+
145
+ transaction = await Trading.functions.openTrade(
146
+ trade_input.model_dump(),
147
+ trade_input_order_type.value,
148
+ slippage_percentage * 10**10,
149
+ ).build_transaction(
150
+ {
151
+ "from": trade_input.trader,
152
+ "value": 0,
153
+ "chainId": self.client.chain_id,
154
+ "nonce": await self.client.get_transaction_count(trade_input.trader),
155
+ }
156
+ )
157
+
158
+ print("transaction: ", trade_input.trader)
159
+
160
+ delegate_transaction = await Trading.functions.delegatedAction(
161
+ trade_input.trader, transaction["data"]
162
+ ).build_transaction(
163
+ {
164
+ "from": self.client.get_signer().get_ethereum_address(),
165
+ "value": execution_fee_wei,
166
+ "chainId": self.client.chain_id,
167
+ "nonce": await self.client.get_transaction_count(
168
+ self.client.get_signer().get_ethereum_address()
169
+ ),
170
+ }
171
+ )
172
+
173
+ return delegate_transaction
174
+
95
175
  async def get_trade_execution_fee(self):
96
176
  """
97
177
  Gets the correct trade execution fee.
@@ -241,7 +321,9 @@ class TradeRPC:
241
321
  execution_fee = await self.get_trade_execution_fee()
242
322
 
243
323
  transaction = await Trading.functions.closeTradeMarket(
244
- pair_index, trade_index, collateral_to_close, 0
324
+ pair_index,
325
+ trade_index,
326
+ collateral_to_close,
245
327
  ).build_transaction(
246
328
  {
247
329
  "from": trader,
@@ -253,6 +335,62 @@ class TradeRPC:
253
335
 
254
336
  return transaction
255
337
 
338
+ async def build_trade_close_tx_delegate(
339
+ self,
340
+ pair_index: int,
341
+ trade_index: int,
342
+ collateral_to_close: float,
343
+ trader: Optional[str] = None,
344
+ ):
345
+ """
346
+ Builds a transaction to close a trade.
347
+
348
+ Args:
349
+ pair_index: The pair index.
350
+ trade_index: The trade index.
351
+ collateral_to_close: The collateral to close.
352
+ trader (optional): The trader's wallet address.
353
+
354
+ Returns:
355
+ A transaction object.
356
+ """
357
+ Trading = self.client.contracts.get("Trading")
358
+
359
+ if trader is None:
360
+ trader = self.client.get_signer().get_ethereum_address()
361
+
362
+ collateral_to_close = int(collateral_to_close * 10**6)
363
+
364
+ execution_fee = await self.get_trade_execution_fee()
365
+
366
+ transaction = await Trading.functions.closeTradeMarket(
367
+ pair_index,
368
+ trade_index,
369
+ collateral_to_close,
370
+ ).build_transaction(
371
+ {
372
+ "from": trader,
373
+ "chainId": self.client.chain_id,
374
+ "nonce": await self.client.get_transaction_count(trader),
375
+ "value": 0,
376
+ }
377
+ )
378
+
379
+ delegate_transaction = await Trading.functions.delegatedAction(
380
+ trader, transaction["data"]
381
+ ).build_transaction(
382
+ {
383
+ "from": self.client.get_signer().get_ethereum_address(),
384
+ "value": execution_fee,
385
+ "chainId": self.client.chain_id,
386
+ "nonce": await self.client.get_transaction_count(
387
+ self.client.get_signer().get_ethereum_address()
388
+ ),
389
+ }
390
+ )
391
+
392
+ return delegate_transaction
393
+
256
394
  async def build_order_cancel_tx(
257
395
  self, pair_index: int, trade_index: int, trader: Optional[str] = None
258
396
  ):
@@ -284,6 +422,49 @@ class TradeRPC:
284
422
 
285
423
  return transaction
286
424
 
425
+ async def build_order_cancel_tx_delegate(
426
+ self, pair_index: int, trade_index: int, trader: Optional[str] = None
427
+ ):
428
+ """
429
+ Builds a transaction to cancel an order.
430
+
431
+ Args:
432
+ pair_index: The pair index.
433
+ trade_index: The trade/order index.
434
+ trader (optional): The trader's wallet address.
435
+
436
+ Returns:
437
+ A transaction object.
438
+ """
439
+ Trading = self.client.contracts.get("Trading")
440
+
441
+ if trader is None:
442
+ trader = self.client.get_signer().get_ethereum_address()
443
+
444
+ transaction = await Trading.functions.cancelOpenLimitOrder(
445
+ pair_index, trade_index
446
+ ).build_transaction(
447
+ {
448
+ "from": trader,
449
+ "chainId": self.client.chain_id,
450
+ "nonce": await self.client.get_transaction_count(trader),
451
+ }
452
+ )
453
+
454
+ delegate_transaction = await Trading.functions.delegatedAction(
455
+ trader, transaction["data"]
456
+ ).build_transaction(
457
+ {
458
+ "from": self.client.get_signer().get_ethereum_address(),
459
+ "chainId": self.client.chain_id,
460
+ "nonce": await self.client.get_transaction_count(
461
+ self.client.get_signer().get_ethereum_address()
462
+ ),
463
+ }
464
+ )
465
+
466
+ return delegate_transaction
467
+
287
468
  async def build_trade_margin_update_tx(
288
469
  self,
289
470
  pair_index: int,
@@ -336,6 +517,71 @@ class TradeRPC:
336
517
 
337
518
  return transaction
338
519
 
520
+ async def build_trade_margin_update_tx_delegate(
521
+ self,
522
+ pair_index: int,
523
+ trade_index: int,
524
+ margin_update_type: MarginUpdateType,
525
+ collateral_change: float,
526
+ trader: Optional[str] = None,
527
+ ):
528
+ """
529
+ Builds a transaction to update the margin of a trade.
530
+
531
+ Args:
532
+ pair_index: The pair index.
533
+ trade_index: The trade index.
534
+ margin_update_type: The margin update type.
535
+ collateral_change: The collateral change.
536
+ trader (optional): The trader's wallet address.
537
+ Returns:
538
+ A transaction object.
539
+ """
540
+ Trading = self.client.contracts.get("Trading")
541
+
542
+ if trader is None:
543
+ trader = self.client.get_signer().get_ethereum_address()
544
+
545
+ collateral_change = int(collateral_change * 10**6)
546
+
547
+ feed_client = self.FeedClient()
548
+
549
+ pair_name = await self.client.pairs_cache.get_pair_name_from_index(pair_index)
550
+
551
+ price_data = await feed_client.get_latest_price_updates([pair_name])
552
+
553
+ price_update_data = "0x" + price_data.binary.data[0]
554
+
555
+ transaction = await Trading.functions.updateMargin(
556
+ pair_index,
557
+ trade_index,
558
+ margin_update_type.value,
559
+ collateral_change,
560
+ [price_update_data],
561
+ ).build_transaction(
562
+ {
563
+ "from": trader,
564
+ "chainId": self.client.chain_id,
565
+ "value": 0,
566
+ "nonce": await self.client.get_transaction_count(trader),
567
+ }
568
+ )
569
+
570
+ delegate_transaction = await Trading.functions.delegatedAction(
571
+ trader, transaction["data"]
572
+ ).build_transaction(
573
+ {
574
+ "from": self.client.get_signer().get_ethereum_address(),
575
+ "chainId": self.client.chain_id,
576
+ "nonce": await self.client.get_transaction_count(
577
+ self.client.get_signer().get_ethereum_address()
578
+ ),
579
+ "value": 1,
580
+ }
581
+ )
582
+
583
+ return delegate_transaction
584
+
339
585
  async def build_trade_tp_sl_update_tx(
340
586
  self,
341
587
  pair_index: int,
@@ -392,3 +638,73 @@ class TradeRPC:
392
638
  )
393
639
 
394
640
  return transaction
641
+
642
+ async def build_trade_tp_sl_update_tx_delegate(
643
+ self,
644
+ pair_index: int,
645
+ trade_index: int,
646
+ take_profit_price: float,
647
+ stop_loss_price: float,
648
+ trader: str = None,
649
+ ):
650
+ """
651
+ Builds a transaction to update the stop loss and take profit of a trade.
652
+
653
+ Args:
654
+ pair_index: The pair index.
655
+ trade_index: The trade index.
656
+ take_profit_price: The take profit price.
657
+ stop_loss_price: The stop loss price. Pass 0 if you want to remove the stop loss.
658
+ trader (optional): The trader's wallet address.
659
+ Returns:
660
+ A transaction object.
661
+ """
662
+ Trading = self.client.contracts.get("Trading")
663
+
664
+ if take_profit_price == 0:
665
+ raise ValueError("Take profit price cannot be 0")
666
+
667
+ if trader is None:
668
+ trader = self.client.get_signer().get_ethereum_address()
669
+
670
+ feed_client = self.FeedClient()
671
+
672
+ pair_name = await self.client.pairs_cache.get_pair_name_from_index(pair_index)
673
+
674
+ price_data = await feed_client.get_latest_price_updates([pair_name])
675
+
676
+ price_update_data = "0x" + price_data.binary.data[0]
677
+
678
+ take_profit_price = int(take_profit_price * 10**10)
679
+ stop_loss_price = int(stop_loss_price * 10**10)
680
+
681
+ transaction = await Trading.functions.updateTpAndSl(
682
+ pair_index,
683
+ trade_index,
684
+ stop_loss_price,
685
+ take_profit_price,
686
+ [price_update_data],
687
+ ).build_transaction(
688
+ {
689
+ "from": trader,
690
+ "chainId": self.client.chain_id,
691
+ "value": 0,
692
+ "nonce": await self.client.get_transaction_count(trader),
693
+ "gas": 1_000_000,
694
+ }
695
+ )
696
+
697
+ delegate_transaction = await Trading.functions.delegatedAction(
698
+ trader, transaction["data"]
699
+ ).build_transaction(
700
+ {
701
+ "from": self.client.get_signer().get_ethereum_address(),
702
+ "chainId": self.client.chain_id,
703
+ "nonce": await self.client.get_transaction_count(
704
+ self.client.get_signer().get_ethereum_address()
705
+ ),
706
+ "value": 1,
707
+ "gas": 1_000_000,
708
+ }
709
+ )
710
+ return delegate_transaction
@@ -16,7 +16,7 @@ class TradingParametersRPC:
16
16
  """
17
17
  self.client = client
18
18
 
19
- async def get_loss_protection_tier(self, trade: TradeInput):
19
+ async def get_loss_protection_tier(self, trade: TradeInput, is_pnl: bool = False):
20
20
  """
21
21
  Retrieves the loss protection tier for a trade. Read more about loss protection tiers here: https://docs.avantisfi.com/rewards/loss-protection
22
22
 
@@ -33,7 +33,7 @@ class TradingParametersRPC:
33
33
  trade.trader,
34
34
  trade.pairIndex,
35
35
  trade.index,
36
- trade.initialPosToken,
36
+ trade.positionSizeUSDC,
37
37
  trade.positionSizeUSDC,
38
38
  trade.openPrice,
39
39
  trade.buy,
@@ -41,7 +41,8 @@ class TradingParametersRPC:
41
41
  trade.tp,
42
42
  trade.sl,
43
43
  trade.timestamp,
44
- )
44
+ ),
45
+ is_pnl,
45
46
  ).call()
46
47
  return response
47
48
 
@@ -131,6 +132,8 @@ class TradingParametersRPC:
131
132
  referrer_tier = await Referral.functions.referrerTiers(
132
133
  trader_referral_info[1]
133
134
  ).call() # trader_referral_info[1] is the referrer address
134
- tier_info = await self.client.read_contract("Referral", "tiers", referrer_tier)
135
+ tier_info = await self.client.read_contract(
136
+ "Referral", "referralTiers", referrer_tier
137
+ )
135
138
  discount_percentage = tier_info["feeDiscountPct"] / 100
136
139
  return discount_percentage