Skip to content

Commit a241415

Browse files
Fix "URI Too Long" error on fetching originations (#65)
1 parent 05f368f commit a241415

File tree

2 files changed

+31
-16
lines changed

2 files changed

+31
-16
lines changed

src/dipdup/datasources/tzkt/datasource.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919
from dipdup.datasources.proxy import DatasourceRequestProxy
2020
from dipdup.datasources.tzkt.enums import TzktMessageType
2121
from dipdup.models import BigMapAction, BigMapData, OperationData
22+
from dipdup.utils import split_by_chunks
2223

2324
OperationID = int
2425

2526
TZKT_HTTP_REQUEST_LIMIT = 10000
27+
TZKT_ORIGINATIONS_REQUEST_LIMIT = 100
2628
OPERATION_FIELDS = (
2729
"type",
2830
"id",
@@ -356,28 +358,34 @@ async def get_latest_block(self) -> Dict[str, Any]:
356358
self._logger.debug(block)
357359
return block
358360

359-
async def get_originations(self, addresses: Set[str], offset: int, first_level, last_level) -> List[OperationData]:
360-
raw_originations = await self._proxy.http_request(
361-
'get',
362-
url=f'{self._url}/v1/operations/originations',
363-
params={
364-
"originatedContract.in": ','.join(addresses),
365-
"offset": offset,
366-
"limit": self.request_limit,
367-
"level.gt": first_level,
368-
"level.le": last_level,
369-
"select": ','.join(ORIGINATION_OPERATION_FIELDS),
370-
"status": "applied",
371-
},
372-
)
361+
async def get_originations(self, addresses: Set[str], offset: int, first_level: int, last_level: int) -> List[OperationData]:
362+
raw_originations = []
363+
# NOTE: TzKT may hit URL length limit with hundreds of originations in a single request.
364+
# NOTE: Chunk of 100 addresses seems like a reasonable choice - URL of ~3971 characters.
365+
# NOTE: Other operation requests won't hit that limit.
366+
for addresses_chunk in split_by_chunks(list(addresses), TZKT_ORIGINATIONS_REQUEST_LIMIT):
367+
raw_originations += await self._proxy.http_request(
368+
'get',
369+
url=f'{self._url}/v1/operations/originations',
370+
params={
371+
"originatedContract.in": ','.join(addresses_chunk),
372+
"offset": offset,
373+
"limit": self.request_limit,
374+
"level.gt": first_level,
375+
"level.le": last_level,
376+
"select": ','.join(ORIGINATION_OPERATION_FIELDS),
377+
"status": "applied",
378+
},
379+
)
380+
373381
originations = []
374382
for op in raw_originations:
375383
# NOTE: `type` field needs to be set manually when requesting operations by specific type
376384
op['type'] = 'origination'
377385
originations.append(self.convert_operation(op))
378386
return originations
379387

380-
async def get_transactions(self, field: str, addresses: Set[str], offset: int, first_level, last_level) -> List[OperationData]:
388+
async def get_transactions(self, field: str, addresses: Set[str], offset: int, first_level: int, last_level: int) -> List[OperationData]:
381389
raw_transactions = await self._proxy.http_request(
382390
'get',
383391
url=f'{self._url}/v1/operations/transactions',

src/dipdup/utils.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import time
77
from contextlib import asynccontextmanager
88
from logging import Logger
9-
from typing import AsyncIterator, Optional
9+
from typing import Any, AsyncIterator, Iterator, List, Optional, Sequence
1010

1111
import aiohttp
1212
from tortoise import Tortoise
@@ -40,6 +40,13 @@ def pascal_to_snake(name: str) -> str:
4040
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()
4141

4242

43+
def split_by_chunks(input_: List[Any], size: int) -> Iterator[List[Any]]:
44+
i = 0
45+
while i < len(input_):
46+
yield input_[i : i + size]
47+
i += size
48+
49+
4350
@asynccontextmanager
4451
async def tortoise_wrapper(url: str, models: Optional[str] = None) -> AsyncIterator:
4552
"""Initialize Tortoise with internal and project models, close connections when done"""

0 commit comments

Comments
 (0)