mirror of
https://github.com/bohd4nx/FragmentAPI.git
synced 2026-07-25 06:14:29 +00:00
@@ -16,7 +16,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/setup-python@v6
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: "3.10"
|
python-version: "3.11"
|
||||||
cache: pip
|
cache: pip
|
||||||
|
|
||||||
- run: pip install ".[dev]"
|
- run: pip install ".[dev]"
|
||||||
@@ -30,7 +30,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14"]
|
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
# Contributing to pyfragment
|
|
||||||
|
|
||||||
## Development setup
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/bohd4nx/pyfragment.git
|
|
||||||
cd pyfragment
|
|
||||||
pip install -e ".[dev]"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running checks
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Lint and format
|
|
||||||
ruff check . --fix && ruff format .
|
|
||||||
|
|
||||||
# Type check
|
|
||||||
mypy . --explicit-package-bases
|
|
||||||
|
|
||||||
# Tests
|
|
||||||
pytest
|
|
||||||
```
|
|
||||||
|
|
||||||
All three must pass before opening a PR.
|
|
||||||
|
|
||||||
## Project structure
|
|
||||||
|
|
||||||
```
|
|
||||||
pyfragment/
|
|
||||||
client.py — FragmentClient (public entry point)
|
|
||||||
enums.py — ApiProvider, PaymentMethod, WalletVersion
|
|
||||||
exceptions.py — exception hierarchy
|
|
||||||
core/ — constants, validation helpers
|
|
||||||
domains/ — one package per feature domain
|
|
||||||
ads/ — recharge_ads, topup_gram
|
|
||||||
anonymous_numbers/— get_login_code, toggle_login_codes, terminate_sessions
|
|
||||||
giveaways/ — giveaway_stars, giveaway_premium
|
|
||||||
marketplace/ — search_usernames, search_numbers, search_gifts
|
|
||||||
purchases/ — purchase_stars, purchase_premium
|
|
||||||
services/ — shared infrastructure services
|
|
||||||
cookies/ — browser cookie extraction (models + service)
|
|
||||||
tonapi/ — wallet info, transaction signing (tonapi/toncenter)
|
|
||||||
tests/ — unit tests (pytest)
|
|
||||||
examples/ — runnable usage examples (excluded from CI)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Conventions
|
|
||||||
|
|
||||||
- All public async methods live on `FragmentClient` and delegate to a domain service.
|
|
||||||
- Domain functions receive a `FragmentClient` instance, never raw httpx clients.
|
|
||||||
- Patch targets in tests use the module where the name is **defined**, e.g. `pyfragment.services.tonapi.transaction._make_ton_client`.
|
|
||||||
- Versioning follows [CalVer](https://calver.org/): `YYYY.MINOR.MICRO`. Bump in `pyproject.toml`; tag as `vYYYY.MINOR.MICRO`.
|
|
||||||
|
|
||||||
## Pull requests
|
|
||||||
|
|
||||||
- Keep PRs focused — one feature or fix per PR.
|
|
||||||
- Update `CHANGELOG.md` under `[Unreleased]`.
|
|
||||||
- Add or update tests for any changed behaviour.
|
|
||||||
@@ -9,18 +9,14 @@
|
|||||||
[](https://github.com/bohd4nx/pyfragment/actions)
|
[](https://github.com/bohd4nx/pyfragment/actions)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|
||||||
Async Python client for the **[Fragment](https://fragment.com)** marketplace API.
|
Async Python client for the **[Fragment.com](https://fragment.com)** marketplace API.
|
||||||
Buy Stars & Premium, run giveaways, top up GRAM (ex TON) and Ads balances,
|
|
||||||
manage anonymous numbers, and search Fragment listings.
|
|
||||||
|
|
||||||
**[Documentation](https://bohd4nx.gitbook.io/pyfragment/)** · **[Examples](https://github.com/bohd4nx/pyfragment/tree/master/examples)** · **[Changelog](CHANGELOG.md)** · **[Donate GRAM](https://app.tonkeeper.com/transfer/UQCppfw5DxWgdVHf3zkmZS8k1mt9oAUYxQLwq2fz3nhO8No5)**
|
**[Documentation](https://bohd4nx.gitbook.io/pyfragment/)** · **[Examples](https://github.com/bohd4nx/pyfragment/tree/master/examples)**
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
> **Disclaimer:** This project is not affiliated with [Fragment](https://fragment.com) or [Telegram](https://telegram.org).
|
> **Disclaimer:** This project is not affiliated with [Fragment](https://fragment.com) or [Telegram](https://telegram.org).
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -46,120 +42,24 @@ from pyfragment.enums import PaymentMethod
|
|||||||
async def main() -> None:
|
async def main() -> None:
|
||||||
async with FragmentClient(
|
async with FragmentClient(
|
||||||
seed="word1 word2 ... word24",
|
seed="word1 word2 ... word24",
|
||||||
api_key="YOUR_API_KEY", # tonconsole.com (tonapi, default) or t.me/toncenter
|
api_key="YOUR_API_KEY",
|
||||||
cookies={
|
cookies={"stel_ssid": "...", "stel_dt": "...", "stel_token": "...", "stel_ton_token": "..."},
|
||||||
"stel_ssid": "...",
|
|
||||||
"stel_dt": "...",
|
|
||||||
"stel_token": "...",
|
|
||||||
"stel_ton_token": "...",
|
|
||||||
},
|
|
||||||
wallet_version="V5R1", # or "V4R2", "HighloadV2", "HighloadV3R1"
|
|
||||||
api_provider="tonapi", # or "toncenter"
|
|
||||||
) as client:
|
) as client:
|
||||||
wallet = await client.get_wallet()
|
wallet = await client.get_wallet()
|
||||||
print(f"GRAM: {wallet.gram_balance} | USDT: {wallet.usdt_balance}")
|
print(f"GRAM: {wallet.gram_balance} | USDT: {wallet.usdt_balance}")
|
||||||
|
|
||||||
recipient = "https://t.me/username" # also: @username, username
|
stars = await client.purchase_stars("@username", amount=500, payment_method=PaymentMethod.USDT_GRAM)
|
||||||
|
|
||||||
stars = await client.purchase_stars(recipient, amount=500, payment_method=PaymentMethod.USDT_GRAM)
|
|
||||||
print(f"Sent {stars.amount} Stars to {stars.username} | tx: {stars.transaction_id}")
|
print(f"Sent {stars.amount} Stars to {stars.username} | tx: {stars.transaction_id}")
|
||||||
|
|
||||||
premium = await client.purchase_premium(recipient, months=6, payment_method=PaymentMethod.GRAM)
|
premium = await client.purchase_premium("@username", months=6, payment_method=PaymentMethod.GRAM)
|
||||||
print(f"Sent Premium {premium.amount}m to {premium.username} | tx: {premium.transaction_id}")
|
print(f"Sent Premium {premium.amount}m to {premium.username} | tx: {premium.transaction_id}")
|
||||||
|
|
||||||
|
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
| Parameter | Type | Default | Description |
|
|
||||||
| ---------------- | ------------- | ---------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| `seed` | `str` | — | 12- or 24-word GRAM (ex TON) wallet mnemonic |
|
|
||||||
| `api_key` | `str` | — | API key for the chosen provider (see `api_provider`) |
|
|
||||||
| `cookies` | `dict \| str` | — | Fragment session cookies |
|
|
||||||
| `wallet_version` | `str` | `"V5R1"` | `"V4R2"` or `"V5R1"` — also accepts `WalletVersion` literal |
|
|
||||||
| `api_provider` | `str` | `"tonapi"` | `"tonapi"` ([tonconsole.com](https://tonconsole.com)) or `"toncenter"` ([t.me/toncenter](https://t.me/toncenter)) |
|
|
||||||
| `timeout` | `float` | `30.0` | HTTP request timeout in seconds |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Credentials
|
|
||||||
|
|
||||||
### Fragment cookies
|
|
||||||
|
|
||||||
Log in to [fragment.com](https://fragment.com) and connect your GRAM (ex TON) wallet.
|
|
||||||
|
|
||||||
**Automatically** (recommended) — reads directly from your browser, no extension needed:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install "pyfragment[browser]"
|
|
||||||
```
|
|
||||||
|
|
||||||
```python
|
|
||||||
from pyfragment import get_cookies_from_browser
|
|
||||||
|
|
||||||
result = get_cookies_from_browser("chrome") # firefox, edge, brave, ...
|
|
||||||
# result.cookies — dict[str, str] ready to pass to FragmentClient
|
|
||||||
# result.expires — ISO 8601 expiry of stel_ssid, or None for session cookies
|
|
||||||
```
|
|
||||||
|
|
||||||
**Manually** — use [Cookie Editor](https://chromewebstore.google.com/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm) and export: `stel_ssid`, `stel_dt`, `stel_token`, `stel_ton_token`. Pass as a `dict` or JSON string.
|
|
||||||
|
|
||||||
Refresh cookies when you get authentication errors.
|
|
||||||
|
|
||||||
### Tonapi key
|
|
||||||
|
|
||||||
Generate at [tonconsole.com](https://tonconsole.com).
|
|
||||||
|
|
||||||
### Seed phrase
|
|
||||||
|
|
||||||
12- or 24-word mnemonic from your GRAM (ex TON) wallet (**Tonkeeper → Settings → Backup**). Never share it.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Logging
|
|
||||||
|
|
||||||
`pyfragment` uses the standard `logging` module under the `pyfragment` namespace and is silent by default:
|
|
||||||
|
|
||||||
```python
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
|
||||||
logging.getLogger("pyfragment").setLevel(logging.DEBUG) # for detailed request logs
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Error Handling
|
|
||||||
|
|
||||||
All exceptions inherit from `FragmentError`:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from pyfragment import (
|
|
||||||
ConfigurationError, # invalid arguments (amount, months, payment_method…)
|
|
||||||
UserNotFoundError, # recipient not found on Fragment
|
|
||||||
WalletError, # insufficient GRAM (ex TON) or USDT balance
|
|
||||||
TransactionError, # broadcast failed, duplicate seqno, invalid payload
|
|
||||||
FragmentAPIError, # Fragment API returned an error response
|
|
||||||
FragmentPageError, # page fetch or hash extraction failed
|
|
||||||
AnonymousNumberError, # number not owned, wrong state, login code issues
|
|
||||||
CookieError, # missing or malformed session cookies
|
|
||||||
ParseError, # failed to decode Fragment payload
|
|
||||||
VerificationError, # on-chain verification step failed
|
|
||||||
OperationError, # generic operation-level failure
|
|
||||||
UnexpectedError, # unexpected API response structure
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
Made with ❤️ by [@bohd4nx](https://t.me/bohd4nx) · [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md)
|
[Changelog](CHANGELOG.md) · [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md)
|
||||||
|
|
||||||
**Star ⭐ if you found it useful**
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
-19
@@ -1,19 +0,0 @@
|
|||||||
# Security Policy
|
|
||||||
|
|
||||||
## Reporting a vulnerability
|
|
||||||
|
|
||||||
Please **do not** open a public GitHub issue for security vulnerabilities.
|
|
||||||
|
|
||||||
Report them privately via GitHub's [Security Advisory](https://github.com/bohd4nx/pyfragment/security/advisories/new) feature, or contact the maintainer directly at [@bohd4nx](https://t.me/bohd4nx) on Telegram.
|
|
||||||
|
|
||||||
Include:
|
|
||||||
|
|
||||||
- A description of the vulnerability and its potential impact.
|
|
||||||
- Steps to reproduce or a proof-of-concept.
|
|
||||||
- Affected versions.
|
|
||||||
|
|
||||||
You will receive a response within 72 hours. Once the fix is released, the advisory will be published.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This library handles sensitive credentials (GRAM (ex TON) seed phrases, Fragment session cookies, Tonapi keys). Please treat any finding that could expose or misuse these credentials as high severity.
|
|
||||||
@@ -8,7 +8,7 @@ from typing import Any, cast
|
|||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from pyfragment.core.constants import DEFAULT_TIMEOUT, FRAGMENT_BASE_URL
|
from pyfragment.core.constants import DEFAULT_TIMEOUT, FRAGMENT_BASE_URL
|
||||||
from pyfragment.exceptions import FragmentPageError, ParseError, VerificationError
|
from pyfragment.exceptions import FragmentPageError, ParseError
|
||||||
|
|
||||||
|
|
||||||
async def get_fragment_hash(
|
async def get_fragment_hash(
|
||||||
@@ -73,17 +73,3 @@ async def fragment_request(
|
|||||||
)
|
)
|
||||||
return parse_json_response(resp, data.get("method", "request"))
|
return parse_json_response(resp, data.get("method", "request"))
|
||||||
raise FragmentPageError(FragmentPageError.BAD_STATUS.format(status=429, url=f"{FRAGMENT_BASE_URL}/api"))
|
raise FragmentPageError(FragmentPageError.BAD_STATUS.format(status=429, url=f"{FRAGMENT_BASE_URL}/api"))
|
||||||
|
|
||||||
|
|
||||||
async def execute_transaction_request(
|
|
||||||
session: httpx.AsyncClient,
|
|
||||||
headers: dict[str, str],
|
|
||||||
tx_data: dict[str, Any],
|
|
||||||
fragment_hash: str,
|
|
||||||
) -> dict[str, Any]:
|
|
||||||
transaction = await fragment_request(session, fragment_hash, headers, tx_data)
|
|
||||||
|
|
||||||
if transaction.get("need_verify"):
|
|
||||||
raise VerificationError(VerificationError.KYC_REQUIRED)
|
|
||||||
|
|
||||||
return transaction
|
|
||||||
|
|||||||
+1
-9
@@ -1,18 +1,10 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import sys
|
from enum import StrEnum
|
||||||
from enum import Enum
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from tonutils.contracts.wallet import WalletHighloadV2, WalletHighloadV3R1, WalletV4R2, WalletV5R1
|
from tonutils.contracts.wallet import WalletHighloadV2, WalletHighloadV3R1, WalletV4R2, WalletV5R1
|
||||||
|
|
||||||
if sys.version_info >= (3, 11):
|
|
||||||
from enum import StrEnum
|
|
||||||
else:
|
|
||||||
|
|
||||||
class StrEnum(str, Enum): # noqa: F811
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class PaymentMethod(StrEnum):
|
class PaymentMethod(StrEnum):
|
||||||
GRAM = "ton"
|
GRAM = "ton"
|
||||||
|
|||||||
@@ -36,10 +36,6 @@ class ConfigurationError(ClientError):
|
|||||||
f"Invalid Stars amount: must be an integer between {STARS_PURCHASE_MIN:,} and {STARS_PURCHASE_MAX:,}."
|
f"Invalid Stars amount: must be an integer between {STARS_PURCHASE_MIN:,} and {STARS_PURCHASE_MAX:,}."
|
||||||
)
|
)
|
||||||
INVALID_GRAM_AMOUNT = f"Invalid GRAM (ex TON) amount: must be an integer between {GRAM_TOPUP_MIN:,} and {GRAM_TOPUP_MAX:,}."
|
INVALID_GRAM_AMOUNT = f"Invalid GRAM (ex TON) amount: must be an integer between {GRAM_TOPUP_MIN:,} and {GRAM_TOPUP_MAX:,}."
|
||||||
INVALID_USERNAME = (
|
|
||||||
"Invalid username '{username}'. "
|
|
||||||
"Must be 5-32 characters and contain only letters (A-Z, a-z), digits (0-9), or underscores (_)."
|
|
||||||
)
|
|
||||||
INVALID_WINNERS_STARS = (
|
INVALID_WINNERS_STARS = (
|
||||||
f"Invalid winners count: must be an integer between {STARS_WINNERS_MIN:,} and {STARS_WINNERS_MAX:,}."
|
f"Invalid winners count: must be an integer between {STARS_WINNERS_MIN:,} and {STARS_WINNERS_MAX:,}."
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import importlib
|
import importlib
|
||||||
from datetime import datetime, timezone
|
from datetime import UTC, datetime
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pyfragment.core.constants import FRAGMENT_BASE_URL, FRAGMENT_DOMAIN, REQUIRED_COOKIE_KEYS
|
from pyfragment.core.constants import FRAGMENT_BASE_URL, FRAGMENT_DOMAIN, REQUIRED_COOKIE_KEYS
|
||||||
@@ -42,11 +42,11 @@ def get_cookies_from_browser(browser: str = "chrome") -> CookieResult:
|
|||||||
if cookie.get("name") == "stel_ssid":
|
if cookie.get("name") == "stel_ssid":
|
||||||
raw = cookie.get("expires")
|
raw = cookie.get("expires")
|
||||||
if isinstance(raw, (int, float)):
|
if isinstance(raw, (int, float)):
|
||||||
expires_iso = datetime.fromtimestamp(raw, tz=timezone.utc).isoformat()
|
expires_iso = datetime.fromtimestamp(raw, tz=UTC).isoformat()
|
||||||
elif isinstance(raw, str) and raw:
|
elif isinstance(raw, str) and raw:
|
||||||
for fmt in ("%Y-%m-%dT%H:%M:%S.%fZ", "%Y-%m-%dT%H:%M:%SZ"):
|
for fmt in ("%Y-%m-%dT%H:%M:%S.%fZ", "%Y-%m-%dT%H:%M:%SZ"):
|
||||||
try:
|
try:
|
||||||
expires_iso = datetime.strptime(raw, fmt).replace(tzinfo=timezone.utc).isoformat()
|
expires_iso = datetime.strptime(raw, fmt).replace(tzinfo=UTC).isoformat()
|
||||||
break
|
break
|
||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
@@ -54,7 +54,7 @@ def get_cookies_from_browser(browser: str = "chrome") -> CookieResult:
|
|||||||
|
|
||||||
if expires_iso:
|
if expires_iso:
|
||||||
expires_dt = datetime.fromisoformat(expires_iso)
|
expires_dt = datetime.fromisoformat(expires_iso)
|
||||||
if expires_dt < datetime.now(timezone.utc):
|
if expires_dt < datetime.now(UTC):
|
||||||
raise CookieError(CookieError.EXPIRED.format(expires=expires_iso))
|
raise CookieError(CookieError.EXPIRED.format(expires=expires_iso))
|
||||||
|
|
||||||
return CookieResult(cookies={k: cookie_map[k] for k in REQUIRED_COOKIE_KEYS}, expires=expires_iso)
|
return CookieResult(cookies={k: cookie_map[k] for k in REQUIRED_COOKIE_KEYS}, expires=expires_iso)
|
||||||
|
|||||||
+5
-27
@@ -5,51 +5,33 @@ build-backend = "hatchling.build"
|
|||||||
[project]
|
[project]
|
||||||
name = "pyfragment"
|
name = "pyfragment"
|
||||||
version = "2026.3.2"
|
version = "2026.3.2"
|
||||||
description = "Async Python client for the Fragment API. Buy Stars and Premium, top up GRAM (ex TON) and Ads balances, run giveaways, manage anonymous numbers, and search Fragment listings."
|
description = "Async Python client for the Fragment.com marketplace API."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = { text = "MIT" }
|
license = { text = "MIT" }
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.11"
|
||||||
authors = [{ name = "bohd4nx" }]
|
authors = [{ name = "bohd4nx" }]
|
||||||
keywords = [
|
keywords = [
|
||||||
"fragment",
|
"fragment",
|
||||||
"fragment-api",
|
|
||||||
"telegram",
|
"telegram",
|
||||||
"telegram-api",
|
|
||||||
"telegram-stars",
|
"telegram-stars",
|
||||||
"telegram-premium",
|
"telegram-premium",
|
||||||
"telegram-giveaway",
|
|
||||||
"telegram-ads",
|
|
||||||
"ton",
|
"ton",
|
||||||
"ton-blockchain",
|
|
||||||
"tonapi",
|
"tonapi",
|
||||||
"anonymous-numbers",
|
"anonymous-numbers",
|
||||||
"username-auctions",
|
|
||||||
"gift-marketplace",
|
|
||||||
"crypto-payments",
|
|
||||||
"nft-marketplace",
|
|
||||||
"web3",
|
|
||||||
"python-client",
|
|
||||||
"typed",
|
|
||||||
"asyncio",
|
"asyncio",
|
||||||
]
|
]
|
||||||
classifiers = [
|
classifiers = [
|
||||||
"Development Status :: 5 - Production/Stable",
|
"Development Status :: 5 - Production/Stable",
|
||||||
"Intended Audience :: Developers",
|
"Intended Audience :: Developers",
|
||||||
"License :: OSI Approved :: MIT License",
|
"License :: OSI Approved :: MIT License",
|
||||||
"Natural Language :: English",
|
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
"Programming Language :: Python",
|
|
||||||
"Programming Language :: Python :: 3 :: Only",
|
"Programming Language :: Python :: 3 :: Only",
|
||||||
"Programming Language :: Python :: 3.10",
|
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
"Programming Language :: Python :: 3.12",
|
"Programming Language :: Python :: 3.12",
|
||||||
"Programming Language :: Python :: 3.13",
|
"Programming Language :: Python :: 3.13",
|
||||||
"Programming Language :: Python :: 3.14",
|
"Programming Language :: Python :: 3.14",
|
||||||
"Framework :: AsyncIO",
|
"Framework :: AsyncIO",
|
||||||
"Topic :: Software Development :: Libraries",
|
|
||||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
"Topic :: Internet",
|
|
||||||
"Topic :: Internet :: WWW/HTTP",
|
|
||||||
"Typing :: Typed",
|
"Typing :: Typed",
|
||||||
]
|
]
|
||||||
dependencies = ["httpx>=0.25", "tonutils>=2.0.1"]
|
dependencies = ["httpx>=0.25", "tonutils>=2.0.1"]
|
||||||
@@ -59,7 +41,6 @@ dev = ["pytest", "pytest-asyncio", "pytest-mock", "mypy", "ruff"]
|
|||||||
browser = ["rookiepy>=0.5.6"]
|
browser = ["rookiepy>=0.5.6"]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Homepage = "https://github.com/bohd4nx/pyfragment"
|
|
||||||
Repository = "https://github.com/bohd4nx/pyfragment"
|
Repository = "https://github.com/bohd4nx/pyfragment"
|
||||||
Documentation = "https://bohd4nx.gitbook.io/pyfragment/"
|
Documentation = "https://bohd4nx.gitbook.io/pyfragment/"
|
||||||
Issues = "https://github.com/bohd4nx/pyfragment/issues"
|
Issues = "https://github.com/bohd4nx/pyfragment/issues"
|
||||||
@@ -76,20 +57,17 @@ addopts = "-v --tb=short"
|
|||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
line-length = 128
|
line-length = 128
|
||||||
target-version = "py310"
|
target-version = "py311"
|
||||||
|
|
||||||
[tool.ruff.lint]
|
[tool.ruff.lint]
|
||||||
# E — pycodestyle errors, F — pyflakes, W — warnings, I — isort, UP — pyupgrade
|
|
||||||
select = ["E", "F", "W", "I", "UP"]
|
select = ["E", "F", "W", "I", "UP"]
|
||||||
# E501 — line too long (covered by line-length above)
|
ignore = ["E501"]
|
||||||
# UP017 — use datetime.UTC (only available in Python 3.11+, we support 3.10)
|
|
||||||
ignore = ["E501", "UP017"]
|
|
||||||
|
|
||||||
[tool.ruff.lint.per-file-ignores]
|
[tool.ruff.lint.per-file-ignores]
|
||||||
"tests/*" = ["E402"]
|
"tests/*" = ["E402"]
|
||||||
|
|
||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
python_version = "3.10"
|
python_version = "3.11"
|
||||||
strict = true
|
strict = true
|
||||||
exclude = ["^examples/", "^logs/", "^tests/"]
|
exclude = ["^examples/", "^logs/", "^tests/"]
|
||||||
|
|
||||||
|
|||||||
@@ -36,10 +36,6 @@ FAKE_BALANCE_NANOGRAM: int = 1_500_000_000 # 1.5 GRAM (ex TON)
|
|||||||
# recharge_ads
|
# recharge_ads
|
||||||
FAKE_ADS_ACCOUNT: str = "@mychannel"
|
FAKE_ADS_ACCOUNT: str = "@mychannel"
|
||||||
|
|
||||||
# Revenue withdrawals
|
|
||||||
FAKE_WITHDRAWAL_WALLET: str = "EQDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
FAKE_REVENUE_TX: str = "revenue_tx_abc123"
|
|
||||||
|
|
||||||
# Anonymous number
|
# Anonymous number
|
||||||
FAKE_HTML_WITH_CODE: str = """
|
FAKE_HTML_WITH_CODE: str = """
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
Reference in New Issue
Block a user