|
1 | | -from typing import Optional |
| 1 | +from abc import ABC |
| 2 | +from dataclasses import dataclass |
| 3 | +from typing import Optional, Generator |
2 | 4 |
|
3 | 5 | from requests import Response, request |
4 | 6 |
|
| 7 | +from open_sea_v1.responses import OpenSeaAPIResponse |
5 | 8 |
|
6 | | -class OpenSeaClient: |
| 9 | +@dataclass |
| 10 | +class _ClientParams: |
| 11 | + """Common OpenSea Endpoint parameters to pass in.""" |
| 12 | + offset: int = 0 |
| 13 | + limit: int = 20 |
| 14 | + max_pages: Optional[int] = None |
| 15 | + api_key: Optional[str] = None |
7 | 16 |
|
8 | | - api_key = None |
9 | | - _response: Optional[Response] = None |
| 17 | + |
| 18 | +class BaseOpenSeaClient(ABC): |
| 19 | + client_params: _ClientParams |
| 20 | + processed_pages: int = 0 |
| 21 | + response = None |
| 22 | + parsed_http_response = None |
| 23 | + url = None |
| 24 | + _http_response = None |
10 | 25 |
|
11 | 26 | @property |
12 | 27 | def http_headers(self) -> dict: |
13 | | - return { |
14 | | - "headers": |
15 | | - {"X-API-Key" : self.api_key} if self.api_key else dict(), |
16 | | - } |
| 28 | + params = {'headers': dict()} |
| 29 | + if self.client_params.api_key: |
| 30 | + params['headers'] = {'X-API-Key': self.client_params.api_key} |
| 31 | + return params |
17 | 32 |
|
18 | | - def _get_request(self, url: str, method: str = 'GET', **kwargs) -> Response: |
19 | | - """ |
20 | | - Automatically passes in API key in HTTP _get_request headers. |
21 | | - """ |
22 | | - if 'api_key' in kwargs: |
23 | | - self.api_key = kwargs.pop('api_key') |
| 33 | + def _get_request(self, **kwargs) -> Response: |
24 | 34 | updated_kwargs = kwargs | self.http_headers |
25 | | - return request(method, url, **updated_kwargs) |
26 | | - |
27 | | - @property |
28 | | - def http_response(self): |
29 | | - self._assert_get_request_was_called_before_accessing_this_property() |
30 | | - return self._response |
31 | | - |
32 | | - def _assert_get_request_was_called_before_accessing_this_property(self): |
33 | | - if self._response is None: |
34 | | - raise AttributeError('You must call self.request prior to accessing self.response') |
35 | | - |
36 | | - # def collections(self, *, asset_owner: Optional[str] = None, offset: int, limit: int) -> OpenseaCollections: |
37 | | - # """ |
38 | | - # Use this endpoint to fetch collections and dapps that OpenSea shows on opensea.io, |
39 | | - # along with dapps and smart contracts that a particular user cares about. |
40 | | - # |
41 | | - # :param asset_owner: A wallet address. If specified, will return collections where |
42 | | - # the owner owns at least one asset belonging to smart contracts in the collection. |
43 | | - # The number of assets the account owns is shown as owned_asset_count for each collection. |
44 | | - # :param offset: For pagination. Number of contracts offset from the beginning of the result list. |
45 | | - # :param limit: For pagination. Maximum number of contracts to return. |
46 | | - # :return: Parsed JSON |
47 | | - # """ |
48 | | - # if offset != 0: |
49 | | - # raise NotImplementedError( |
50 | | - # "Sorry, tested offset parameter is not implemented yet. " |
51 | | - # "Feel free to PR after looking at the tests and trying to understand" |
52 | | - # " why current implementation doesn't allow pagination to work..." |
53 | | - # ) |
54 | | - # resp = self._collections(asset_owner=asset_owner, offset=offset, limit=limit) |
55 | | - # return resp.json()['collections'] |
56 | | - # |
57 | | - # def _collections(self, **_request_params) -> Response: |
58 | | - # """Returns HTTPResponse object.""" |
59 | | - # url = OpenseaApiEndpoints.COLLECTIONS.value |
60 | | - # return self._get_request("GET", url, _request_params=_request_params) |
61 | | - # |
62 | | - # def asset(self, asset_contract_address: str, token_id: str, account_address: Optional[str] = None) -> OpenseaAsset: |
63 | | - # """ |
64 | | - # :param asset_contract_address: Address of the contract for this NFT |
65 | | - # :param token_id: Token ID for this item |
66 | | - # :param account_address: Address of an owner of the token. If you include this, the http_response will include an ownership object that includes the number of tokens owned by the address provided instead of the top_ownerships object included in the standard http_response, which provides the number of tokens owned by each of the 10 addresses with the greatest supply of the token. |
67 | | - # :return: Parsed JSON. |
68 | | - # """ |
69 | | - # resp = self._asset( |
70 | | - # asset_contract_address=asset_contract_address, |
71 | | - # token_id=token_id, |
72 | | - # account_address=account_address, |
73 | | - # ) |
74 | | - # return resp.response() |
75 | | - |
| 35 | + return request('GET', self.url, **updated_kwargs) |
| 36 | + |
| 37 | + def get_pages(self) -> Generator[list[list[OpenSeaAPIResponse]], None, None]: |
| 38 | + self._http_response = None |
| 39 | + while self.remaining_pages(): |
| 40 | + self._http_response = self._get_request() |
| 41 | + yield self.parsed_http_response |
| 42 | + self.client_params.offset += self.client_params.limit |
| 43 | + self.processed_pages += 1 |
| 44 | + |
| 45 | + def remaining_pages(self) -> bool: |
| 46 | + if self._http_response is None: |
| 47 | + return True |
| 48 | + if self.client_params.max_pages is not None and self.processed_pages <= self.client_params.max_pages: |
| 49 | + return True |
| 50 | + if len(self.response) >= self.client_params.offset: |
| 51 | + return True |
| 52 | + return False |
0 commit comments