Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[+] Multi client for async tron #140

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 55 additions & 7 deletions tronpy/providers/async_http.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import asyncio
import os
from typing import Any, Union
import random
import sys
from typing import Any, List, Union
from urllib.parse import urljoin

import httpx
Expand All @@ -9,6 +12,14 @@

DEFAULT_TIMEOUT = 10.0
DEFAULT_API_KEY = "f92221d5-7056-4366-b96f-65d3662ec2d9"
DEFAULT_API_KEYS = [
"f92221d5-7056-4366-b96f-65d3662ec2d9",
"1e0a625f-cfa5-43ee-ba41-a09db1aae55f",
"f399168e-2259-481c-90fc-6b3d984c5463",
"da63253b-aa9c-46e7-a4e8-22d259a8026d",
"88c10958-af7b-4d5a-8eef-6e84bf5fb809",
"169bb4b3-cbe8-449a-984e-80e9adacac55",
]


class AsyncHTTPProvider:
Expand All @@ -24,7 +35,7 @@ def __init__(
endpoint_uri: Union[str, dict] = None,
timeout: float = DEFAULT_TIMEOUT,
client: httpx.AsyncClient = None,
api_key: str = DEFAULT_API_KEY,
api_key: Union[str, List[str]] = DEFAULT_API_KEY,
jw_token: str = None,
):
super().__init__()
Expand All @@ -38,21 +49,58 @@ def __init__(
else:
raise TypeError(f"unknown endpoint uri {endpoint_uri}")

headers = {"User-Agent": f"Tronpy/{VERSION}", "Tron-Pro-Api-Key": api_key}
if jw_token is not None:
headers["Authorization"] = f"Bearer {jw_token}"
if "trongrid" in self.endpoint_uri:
self.use_api_key = True
if isinstance(api_key, (str,)):
self._api_keys = [api_key]
elif isinstance(api_key, (list,)) and api_key:
self._api_keys = api_key
else:
self._api_keys = DEFAULT_API_KEYS.copy()

self._default_api_keys = self._api_keys.copy()
else:
self.use_api_key = False
self.jw_token = jw_token

if client is None:
self.client = httpx.AsyncClient(headers=headers, timeout=Timeout(timeout))
self.client = httpx.AsyncClient(timeout=Timeout(timeout))
else:
self.client = client

self.timeout = timeout
"""Request timeout in second."""

async def make_request(self, method: str, params: Any = None) -> dict:
headers = {}
if self.use_api_key:
headers["Tron-Pro-Api-Key"] = self.random_api_key
headers["User-Agent"] = f"Tronpy/{VERSION}"

if self.jw_token is not None:
headers["Authorization"] = f"Bearer {self.jw_token}"

if params is None:
params = {}
url = urljoin(self.endpoint_uri, method)
resp = await self.client.post(url, json=params)
resp = await self.client.post(headers=headers, url=url, json=params)

if self.use_api_key:
if resp.status_code == 403 and b"Exceed the user daily usage" in resp.content:
print("W:", resp.json().get("Error", "rate limit!"), file=sys.stderr)
await self._handle_rate_limit(headers["Tron-Pro-Api-Key"])
return await self.make_request(method, params)

resp.raise_for_status()
return resp.json()

@property
def random_api_key(self):
return random.choice(self._api_keys)

async def _handle_rate_limit(self, used_key):
if len(self._api_keys) > 1:
self._api_keys.remove(used_key)
else:
print("W: Please add as-many API-Keys in HTTPProvider", file=sys.stderr)
await asyncio.sleep(0.9)