Skip to content

Commit 398f13a

Browse files
authored
[SDK] Add retry for subgraph requests that return bad indexer (#3661)
1 parent 1522416 commit 398f13a

File tree

31 files changed

+1130
-385
lines changed

31 files changed

+1130
-385
lines changed

.changeset/wide-sites-pull.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@human-protocol/sdk": minor
3+
"@human-protocol/python-sdk": minor
4+
---
5+
6+
Added new optional config for querying subgraph with retries when failuers are due to bad indexers errors in Python and Typescript SDK

packages/sdk/python/human-protocol-sdk/example.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from human_protocol_sdk.operator import OperatorUtils, OperatorFilter
1919
from human_protocol_sdk.agreement import agreement
2020
from human_protocol_sdk.staking.staking_utils import StakingUtils
21+
from human_protocol_sdk.utils import SubgraphOptions
2122

2223

2324
def get_escrow_statistics(statistics_client: StatisticsClient):
@@ -162,7 +163,8 @@ def get_escrows():
162163
status=Status.Pending,
163164
date_from=datetime.datetime(2023, 5, 8),
164165
date_to=datetime.datetime(2023, 6, 8),
165-
)
166+
),
167+
SubgraphOptions(3, 1000),
166168
)
167169
)
168170

@@ -232,12 +234,13 @@ def get_stakers_example():
232234
chain_id=ChainId.POLYGON_AMOY,
233235
order_by="lastDepositTimestamp",
234236
order_direction=OrderDirection.ASC,
235-
)
237+
),
238+
SubgraphOptions(3, 1000),
236239
)
237240
print("Filtered stakers:", len(stakers))
238241

239242
if stakers:
240-
staker = StakingUtils.get_staker(ChainId.LOCALHOST, stakers[0].address)
243+
staker = StakingUtils.get_staker(ChainId.POLYGON_AMOY, stakers[0].address)
241244
print("Staker info:", staker.address)
242245
else:
243246
print("No stakers found.")

packages/sdk/python/human-protocol-sdk/human_protocol_sdk/escrow/escrow_utils.py

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
------
2525
"""
2626

27-
from datetime import datetime
2827
import logging
2928
from typing import List, Optional
3029

@@ -38,7 +37,8 @@
3837
PayoutFilter,
3938
)
4039
from human_protocol_sdk.utils import (
41-
get_data_from_subgraph,
40+
SubgraphOptions,
41+
custom_gql_fetch,
4242
)
4343

4444
from human_protocol_sdk.escrow.escrow_client import EscrowClientError
@@ -219,10 +219,12 @@ class EscrowUtils:
219219
@staticmethod
220220
def get_escrows(
221221
filter: EscrowFilter,
222+
options: Optional[SubgraphOptions] = None,
222223
) -> List[EscrowData]:
223224
"""Get an array of escrow addresses based on the specified filter parameters.
224225
225226
:param filter: Object containing all the necessary parameters to filter
227+
:param options: Optional config for subgraph requests
226228
227229
:return: List of escrows
228230
@@ -257,7 +259,7 @@ def get_escrows(
257259
else:
258260
statuses = [filter.status.name]
259261

260-
escrows_data = get_data_from_subgraph(
262+
escrows_data = custom_gql_fetch(
261263
network,
262264
query=get_escrows_query(filter),
263265
params={
@@ -283,6 +285,7 @@ def get_escrows(
283285
"skip": filter.skip,
284286
"orderDirection": filter.order_direction.value,
285287
},
288+
options=options,
286289
)
287290

288291
if (
@@ -334,11 +337,13 @@ def get_escrows(
334337
def get_escrow(
335338
chain_id: ChainId,
336339
escrow_address: str,
340+
options: Optional[SubgraphOptions] = None,
337341
) -> Optional[EscrowData]:
338342
"""Returns the escrow for a given address.
339343
340344
:param chain_id: Network in which the escrow has been deployed
341345
:param escrow_address: Address of the escrow
346+
:param options: Optional config for subgraph requests
342347
343348
:return: Escrow data
344349
@@ -367,12 +372,13 @@ def get_escrow(
367372

368373
network = NETWORKS[ChainId(chain_id)]
369374

370-
escrow_data = get_data_from_subgraph(
375+
escrow_data = custom_gql_fetch(
371376
network,
372377
query=get_escrow_query(),
373378
params={
374379
"escrowAddress": escrow_address.lower(),
375380
},
381+
options=options,
376382
)
377383

378384
if (
@@ -414,11 +420,15 @@ def get_escrow(
414420
)
415421

416422
@staticmethod
417-
def get_status_events(filter: StatusEventFilter) -> List[StatusEvent]:
423+
def get_status_events(
424+
filter: StatusEventFilter,
425+
options: Optional[SubgraphOptions] = None,
426+
) -> List[StatusEvent]:
418427
"""
419428
Retrieve status events for specified networks and statuses within a date range.
420429
421430
:param filter: Object containing all the necessary parameters to filter status events.
431+
:param options: Optional config for subgraph requests
422432
423433
:return List[StatusEvent]: List of status events matching the query parameters.
424434
@@ -435,7 +445,7 @@ def get_status_events(filter: StatusEventFilter) -> List[StatusEvent]:
435445

436446
status_names = [status.name for status in filter.statuses]
437447

438-
data = get_data_from_subgraph(
448+
data = custom_gql_fetch(
439449
network,
440450
get_status_query(filter.date_from, filter.date_to, filter.launcher),
441451
{
@@ -447,6 +457,7 @@ def get_status_events(filter: StatusEventFilter) -> List[StatusEvent]:
447457
"skip": filter.skip,
448458
"orderDirection": filter.order_direction.value,
449459
},
460+
options=options,
450461
)
451462

452463
if (
@@ -472,11 +483,15 @@ def get_status_events(filter: StatusEventFilter) -> List[StatusEvent]:
472483
return events_with_chain_id
473484

474485
@staticmethod
475-
def get_payouts(filter: PayoutFilter) -> List[Payout]:
486+
def get_payouts(
487+
filter: PayoutFilter,
488+
options: Optional[SubgraphOptions] = None,
489+
) -> List[Payout]:
476490
"""
477491
Fetch payouts from the subgraph based on the provided filter.
478492
479493
:param filter: Object containing all the necessary parameters to filter payouts.
494+
:param options: Optional config for subgraph requests
480495
481496
:return List[Payout]: List of payouts matching the query parameters.
482497
@@ -494,7 +509,7 @@ def get_payouts(filter: PayoutFilter) -> List[Payout]:
494509
if not network:
495510
raise EscrowClientError("Unsupported Chain ID")
496511

497-
data = get_data_from_subgraph(
512+
data = custom_gql_fetch(
498513
network,
499514
get_payouts_query(filter),
500515
{
@@ -508,6 +523,7 @@ def get_payouts(filter: PayoutFilter) -> List[Payout]:
508523
"skip": filter.skip,
509524
"orderDirection": filter.order_direction.value,
510525
},
526+
options=options,
511527
)
512528

513529
if (
@@ -536,11 +552,13 @@ def get_payouts(filter: PayoutFilter) -> List[Payout]:
536552
@staticmethod
537553
def get_cancellation_refunds(
538554
filter: CancellationRefundFilter,
555+
options: Optional[SubgraphOptions] = None,
539556
) -> List[CancellationRefund]:
540557
"""
541558
Fetch cancellation refunds from the subgraph based on the provided filter.
542559
543560
:param filter: Object containing all the necessary parameters to filter cancellation refunds.
561+
:param options: Optional config for subgraph requests
544562
545563
:return List[CancellationRefund]: List of cancellation refunds matching the query parameters.
546564
@@ -558,7 +576,7 @@ def get_cancellation_refunds(
558576
if not network:
559577
raise EscrowClientError("Unsupported Chain ID")
560578

561-
data = get_data_from_subgraph(
579+
data = custom_gql_fetch(
562580
network,
563581
get_cancellation_refunds_query(filter),
564582
{
@@ -572,6 +590,7 @@ def get_cancellation_refunds(
572590
"skip": filter.skip,
573591
"orderDirection": filter.order_direction.value,
574592
},
593+
options=options,
575594
)
576595

577596
if (
@@ -601,13 +620,16 @@ def get_cancellation_refunds(
601620

602621
@staticmethod
603622
def get_cancellation_refund(
604-
chain_id: ChainId, escrow_address: str
623+
chain_id: ChainId,
624+
escrow_address: str,
625+
options: Optional[SubgraphOptions] = None,
605626
) -> CancellationRefund:
606627
"""
607628
Returns the cancellation refund for a given escrow address.
608629
609630
:param chain_id: Network in which the escrow has been deployed
610631
:param escrow_address: Address of the escrow
632+
:param options: Optional config for subgraph requests
611633
612634
:return: CancellationRefund data or None
613635
@@ -635,12 +657,13 @@ def get_cancellation_refund(
635657
if not network:
636658
raise EscrowClientError("Unsupported Chain ID")
637659

638-
data = get_data_from_subgraph(
660+
data = custom_gql_fetch(
639661
network,
640662
get_cancellation_refund_by_escrow_query(),
641663
{
642664
"escrowAddress": escrow_address.lower(),
643665
},
666+
options=options,
644667
)
645668

646669
if (

packages/sdk/python/human-protocol-sdk/human_protocol_sdk/kvstore/kvstore_utils.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import requests
3030

3131
from human_protocol_sdk.constants import NETWORKS, ChainId, KVStoreKeys
32-
from human_protocol_sdk.utils import get_data_from_subgraph
32+
from human_protocol_sdk.utils import SubgraphOptions, custom_gql_fetch
3333

3434
from human_protocol_sdk.kvstore.kvstore_client import KVStoreClientError
3535

@@ -57,11 +57,13 @@ class KVStoreUtils:
5757
def get_kvstore_data(
5858
chain_id: ChainId,
5959
address: str,
60+
options: Optional[SubgraphOptions] = None,
6061
) -> Optional[List[KVStoreData]]:
6162
"""Returns the KVStore data for a given address.
6263
6364
:param chain_id: Network in which the KVStore data has been deployed
6465
:param address: Address of the KVStore
66+
:param options: Optional config for subgraph requests
6567
6668
:return: List of KVStore data
6769
@@ -88,12 +90,13 @@ def get_kvstore_data(
8890

8991
network = NETWORKS[ChainId(chain_id)]
9092

91-
kvstore_data = get_data_from_subgraph(
93+
kvstore_data = custom_gql_fetch(
9294
network,
9395
query=get_kvstore_by_address_query(),
9496
params={
9597
"address": address.lower(),
9698
},
99+
options=options,
97100
)
98101

99102
if (
@@ -111,12 +114,18 @@ def get_kvstore_data(
111114
]
112115

113116
@staticmethod
114-
def get(chain_id: ChainId, address: str, key: str) -> str:
117+
def get(
118+
chain_id: ChainId,
119+
address: str,
120+
key: str,
121+
options: Optional[SubgraphOptions] = None,
122+
) -> str:
115123
"""Gets the value of a key-value pair in the contract.
116124
117125
:param chain_id: Network in which the KVStore data has been deployed
118126
:param address: The Ethereum address associated with the key-value pair
119127
:param key: The key of the key-value pair to get
128+
:param options: Optional config for subgraph requests
120129
121130
:return: The value of the key-value pair if it exists
122131
@@ -142,13 +151,14 @@ def get(chain_id: ChainId, address: str, key: str) -> str:
142151

143152
network = NETWORKS[ChainId(chain_id)]
144153

145-
kvstore_data = get_data_from_subgraph(
154+
kvstore_data = custom_gql_fetch(
146155
network,
147156
query=get_kvstore_by_address_and_key_query(),
148157
params={
149158
"address": address.lower(),
150159
"key": key,
151160
},
161+
options=options,
152162
)
153163

154164
if (
@@ -163,13 +173,17 @@ def get(chain_id: ChainId, address: str, key: str) -> str:
163173

164174
@staticmethod
165175
def get_file_url_and_verify_hash(
166-
chain_id: ChainId, address: str, key: Optional[str] = "url"
176+
chain_id: ChainId,
177+
address: str,
178+
key: Optional[str] = "url",
179+
options: Optional[SubgraphOptions] = None,
167180
) -> str:
168181
"""Gets the URL value of the given entity, and verify its hash.
169182
170183
:param chain_id: Network in which the KVStore data has been deployed
171184
:param address: Address from which to get the URL value.
172185
:param key: Configurable URL key. `url` by default.
186+
:param options: Optional config for subgraph requests
173187
174188
:return url: The URL value of the given address if exists, and the content is valid
175189
@@ -189,8 +203,8 @@ def get_file_url_and_verify_hash(
189203
if not Web3.is_address(address):
190204
raise KVStoreClientError(f"Invalid address: {address}")
191205

192-
url = KVStoreUtils.get(chain_id, address, key)
193-
hash = KVStoreUtils.get(chain_id, address, key + "_hash")
206+
url = KVStoreUtils.get(chain_id, address, key, options=options)
207+
hash = KVStoreUtils.get(chain_id, address, key + "_hash", options=options)
194208

195209
if len(url) == 0:
196210
return url

0 commit comments

Comments
 (0)