Refactor FragmentAPI to pyfragment

- Renamed the package from `fragmentapi` to `pyfragment` across all modules and tests.
- Removed the old wallet utility functions and replaced them with new implementations.
- Updated the `pyproject.toml` to reflect the new package name and repository links.
- Adjusted all import statements in tests to use the new package name.
- Implemented new methods for gifting Telegram Premium, Stars, and topping up TON balance.
- Added exception handling for various error scenarios in the API interactions.
- Created new utility functions for handling HTTP requests and decoding payloads.
- Established a clear structure for types and constants used throughout the library.
This commit is contained in:
bohd4nx
2026-03-15 22:07:01 +02:00
parent 7f269d9a87
commit 8135a9da7e
29 changed files with 68 additions and 68 deletions
+6 -6
View File
@@ -1,5 +1,5 @@
name: Bug report
description: Report an issue or unexpected behavior in FragmentAPI.
description: Report an issue or unexpected behavior in pyfragment.
labels:
- bug
body:
@@ -7,7 +7,7 @@ body:
attributes:
label: Checklist
options:
- label: I am sure the error is coming from FragmentAPI code
- label: I am sure the error is coming from pyfragment code
required: true
- label: I have searched the issue tracker for similar bug reports, including closed ones
required: true
@@ -35,8 +35,8 @@ body:
- type: input
attributes:
label: FragmentAPI version
description: Run `pip show fragmentapi` inside your virtualenv
label: pyfragment version
description: Run `pip show pyfragment` inside your virtualenv
placeholder: e.g. 2026.1.0
validations:
required: true
@@ -74,7 +74,7 @@ body:
description: Provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) if applicable.
placeholder: |
import asyncio
from fragmentapi import FragmentClient
from pyfragment import FragmentClient
async def main():
client = FragmentClient(...)
@@ -91,7 +91,7 @@ body:
Traceback (most recent call last):
File "main.py", line 7, in main
...
fragmentapi.types.ParseError: ...
pyfragment.types.ParseError: ...
render: sh
- type: textarea
+1 -1
View File
@@ -1,5 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: Ask a question or start a discussion
url: https://github.com/bohd4nx/FragmentAPI/discussions
url: https://github.com/bohd4nx/pyfragment/discussions
about: General questions, ideas, and community help go here — not in the issue tracker.
+2 -2
View File
@@ -1,11 +1,11 @@
name: Feature request
description: Suggest an improvement or new feature for FragmentAPI.
description: Suggest an improvement or new feature for pyfragment.
labels:
- enhancement
body:
- type: dropdown
attributes:
label: FragmentAPI version
label: pyfragment version
description: Which version are you running?
options:
- latest
+1 -1
View File
@@ -23,7 +23,7 @@ Describe the tests you ran to verify the change and list any relevant details.
**Test configuration:**
* OS:
* Python version:
* FragmentAPI version:
* pyfragment version:
## Checklist
+1 -1
View File
@@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/fragmentapi/
url: https://pypi.org/project/pyfragment/
permissions:
id-token: write
+10 -10
View File
@@ -7,14 +7,14 @@
<b>Python library for the Fragment.com API — gift Telegram Stars, Premium, and top up TON Ads balance.</b>
</p>
[![PyPI version](https://img.shields.io/pypi/v/fragmentapi?style=flat&color=blue)](https://pypi.org/project/fragmentapi/)
[![PyPI downloads](https://img.shields.io/pypi/dm/fragmentapi?style=flat&color=brightgreen)](https://pypi.org/project/fragmentapi/)
[![PyPI version](https://img.shields.io/pypi/v/pyfragment?style=flat&color=blue)](https://pypi.org/project/pyfragment/)
[![PyPI downloads](https://img.shields.io/pypi/dm/pyfragment?style=flat&color=brightgreen)](https://pypi.org/project/pyfragment/)
[![Python](https://img.shields.io/badge/Python-3.12+-3776AB?style=flat&logo=python&logoColor=white)](https://python.org)
[![License](https://img.shields.io/github/license/bohd4nx/FragmentAPI?style=flat&color=lightgrey)](LICENSE)
[![Stars](https://img.shields.io/github/stars/bohd4nx/FragmentAPI?style=flat&color=yellow)](https://github.com/bohd4nx/FragmentAPI/stargazers)
[![CI](https://img.shields.io/github/actions/workflow/status/bohd4nx/FragmentAPI/tests.yml?style=flat&label=tests&logo=github)](https://github.com/bohd4nx/FragmentAPI/actions)
[![License](https://img.shields.io/github/license/bohd4nx/pyfragment?style=flat&color=lightgrey)](LICENSE)
[![Stars](https://img.shields.io/github/stars/bohd4nx/pyfragment?style=flat&color=yellow)](https://github.com/bohd4nx/pyfragment/stargazers)
[![CI](https://img.shields.io/github/actions/workflow/status/bohd4nx/pyfragment/tests.yml?style=flat&label=tests&logo=github)](https://github.com/bohd4nx/pyfragment/actions)
[Report Bug](https://github.com/bohd4nx/FragmentAPI/issues) · [Request Feature](https://github.com/bohd4nx/FragmentAPI/issues) · [**Donate TON**](https://app.tonkeeper.com/transfer/UQCppfw5DxWgdVHf3zkmZS8k1mt9oAUYxQLwq2fz3nhO8No5)
[Report Bug](https://github.com/bohd4nx/pyfragment/issues) · [Request Feature](https://github.com/bohd4nx/pyfragment/issues) · [**Donate TON**](https://app.tonkeeper.com/transfer/UQCppfw5DxWgdVHf3zkmZS8k1mt9oAUYxQLwq2fz3nhO8No5)
</div>
@@ -33,7 +33,7 @@
## 📦 Installation
```bash
pip install fragmentapi
pip install pyfragment
```
Requires **Python 3.12+**.
@@ -44,7 +44,7 @@ Requires **Python 3.12+**.
```python
import asyncio
from fragmentapi import FragmentClient
from pyfragment import FragmentClient
client = FragmentClient(
seed="word1 word2 ... word24",
@@ -146,10 +146,10 @@ Go to **Settings → Backup** → copy the 24 words.
## 🗂️ Error Handling
All exceptions inherit from `FragmentError` — see [`fragmentapi/types/exceptions.py`](fragmentapi/types/exceptions.py) for the full list.
All exceptions inherit from `FragmentError` — see [`pyfragment/types/exceptions.py`](pyfragment/types/exceptions.py) for the full list.
```python
from fragmentapi import FragmentClient, UserNotFoundError, ConfigurationError, WalletError
from pyfragment import FragmentClient, UserNotFoundError, ConfigurationError, WalletError
try:
result = await client.gift_stars("@unknown", amount=100)
+1 -1
View File
@@ -7,7 +7,7 @@ wallet_version defaults to "V5R1" — change to "V4R2" for older wallets.
import asyncio
from fragmentapi import FragmentClient
from pyfragment import FragmentClient
SEED = "word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12 word13 word14 word15 word16 word17 word18 word19 word20 word21 word22 word23 word24"
API_KEY = "YOUR_TONAPI_KEY"
+1 -1
View File
@@ -7,7 +7,7 @@ Set show_sender=False to send anonymously.
import asyncio
from fragmentapi import ConfigurationError, FragmentClient, UserNotFoundError
from pyfragment import ConfigurationError, FragmentClient, UserNotFoundError
SEED = "word1 word2 ... word24"
API_KEY = "YOUR_TONAPI_KEY"
+1 -1
View File
@@ -7,7 +7,7 @@ Set show_sender=False to send anonymously.
import asyncio
from fragmentapi import ConfigurationError, FragmentClient, UserNotFoundError
from pyfragment import ConfigurationError, FragmentClient, UserNotFoundError
SEED = "word1 word2 ... word24"
API_KEY = "YOUR_TONAPI_KEY"
+1 -1
View File
@@ -7,7 +7,7 @@ Your wallet must hold at least the topup amount + ~0.056 TON for gas.
import asyncio
from fragmentapi import ConfigurationError, FragmentClient, UserNotFoundError, WalletError
from pyfragment import ConfigurationError, FragmentClient, UserNotFoundError, WalletError
SEED = "word1 word2 ... word24"
API_KEY = "YOUR_TONAPI_KEY"
-5
View File
@@ -1,5 +0,0 @@
from fragmentapi.methods.premium import gift_premium
from fragmentapi.methods.stars import gift_stars
from fragmentapi.methods.ton import topup_ton
__all__ = ["gift_premium", "gift_stars", "topup_ton"]
@@ -3,8 +3,8 @@
# This source code is licensed under the MIT License found in the
# LICENSE file in the root directory of this source tree.
from fragmentapi.client import FragmentClient
from fragmentapi.types import (
from pyfragment.client import FragmentClient
from pyfragment.types import (
AdsTopupResult,
ClientError,
ConfigurationError,
@@ -1,9 +1,9 @@
import json
from fragmentapi.methods.premium import gift_premium
from fragmentapi.methods.stars import gift_stars
from fragmentapi.methods.ton import topup_ton
from fragmentapi.types import (
from pyfragment.methods.premium import gift_premium
from pyfragment.methods.stars import gift_stars
from pyfragment.methods.ton import topup_ton
from pyfragment.types import (
REQUIRED_COOKIE_KEYS,
SUPPORTED_WALLET_VERSIONS,
AdsTopupResult,
+5
View File
@@ -0,0 +1,5 @@
from pyfragment.methods.premium import gift_premium
from pyfragment.methods.stars import gift_stars
from pyfragment.methods.ton import topup_ton
__all__ = ["gift_premium", "gift_stars", "topup_ton"]
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING
import httpx
from fragmentapi.types import (
from pyfragment.types import (
BASE_HEADERS,
DEVICE,
PREMIUM_PAGE,
@@ -15,7 +15,7 @@ from fragmentapi.types import (
UnexpectedError,
UserNotFoundError,
)
from fragmentapi.utils import (
from pyfragment.utils import (
execute_transaction_request,
fragment_post,
get_account_info,
@@ -24,7 +24,7 @@ from fragmentapi.utils import (
)
if TYPE_CHECKING:
from fragmentapi.client import FragmentClient
from pyfragment.client import FragmentClient
# Page-specific headers
HEADERS: dict[str, str] = {
@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
import httpx
from fragmentapi.types import (
from pyfragment.types import (
BASE_HEADERS,
DEVICE,
STARS_PAGE,
@@ -14,7 +14,7 @@ from fragmentapi.types import (
UnexpectedError,
UserNotFoundError,
)
from fragmentapi.utils import (
from pyfragment.utils import (
execute_transaction_request,
fragment_post,
get_account_info,
@@ -23,7 +23,7 @@ from fragmentapi.utils import (
)
if TYPE_CHECKING:
from fragmentapi.client import FragmentClient
from pyfragment.client import FragmentClient
# Page-specific headers
HEADERS: dict[str, str] = {
@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
import httpx
from fragmentapi.types import (
from pyfragment.types import (
BASE_HEADERS,
DEVICE,
TON_PAGE,
@@ -14,7 +14,7 @@ from fragmentapi.types import (
UnexpectedError,
UserNotFoundError,
)
from fragmentapi.utils import (
from pyfragment.utils import (
execute_transaction_request,
fragment_post,
get_account_info,
@@ -23,7 +23,7 @@ from fragmentapi.utils import (
)
if TYPE_CHECKING:
from fragmentapi.client import FragmentClient
from pyfragment.client import FragmentClient
# Page-specific headers
HEADERS: dict[str, str] = {
@@ -1,4 +1,4 @@
from fragmentapi.types.constants import (
from pyfragment.types.constants import (
BASE_HEADERS,
DEVICE,
MIN_TON_BALANCE,
@@ -10,7 +10,7 @@ from fragmentapi.types.constants import (
WALLET_CLASSES,
WalletVersion,
)
from fragmentapi.types.exceptions import (
from pyfragment.types.exceptions import (
ClientError,
ConfigurationError,
CookieError,
@@ -25,7 +25,7 @@ from fragmentapi.types.exceptions import (
VerificationError,
WalletError,
)
from fragmentapi.types.results import AdsTopupResult, PremiumResult, StarsResult
from pyfragment.types.results import AdsTopupResult, PremiumResult, StarsResult
__all__ = [
# constants
@@ -1,5 +1,5 @@
class FragmentError(Exception):
"""Base exception for all fragmentapi library errors."""
"""Base exception for all pyfragment library errors."""
class ClientError(FragmentError):
@@ -1,11 +1,11 @@
from fragmentapi.utils.decoder import clean_decode
from fragmentapi.utils.http import (
from pyfragment.utils.decoder import clean_decode
from pyfragment.utils.http import (
execute_transaction_request,
fragment_post,
get_fragment_hash,
parse_json_response,
)
from fragmentapi.utils.wallet import get_account_info, process_transaction
from pyfragment.utils.wallet import get_account_info, process_transaction
__all__ = [
"clean_decode",
@@ -2,7 +2,7 @@ import base64
from pytoniq_core import Cell
from fragmentapi.types import ParseError
from pyfragment.types import ParseError
def clean_decode(payload: str) -> str:
@@ -3,7 +3,7 @@ from typing import Any
import httpx
from fragmentapi.types import FragmentPageError, ParseError, VerificationError
from pyfragment.types import FragmentPageError, ParseError, VerificationError
async def get_fragment_hash(
@@ -4,11 +4,11 @@ from typing import TYPE_CHECKING, Any
from tonutils.clients import TonapiClient
from tonutils.types import NetworkGlobalID
from fragmentapi.types import MIN_TON_BALANCE, WALLET_CLASSES, TransactionError, WalletError
from fragmentapi.utils.decoder import clean_decode
from pyfragment.types import MIN_TON_BALANCE, WALLET_CLASSES, TransactionError, WalletError
from pyfragment.utils.decoder import clean_decode
if TYPE_CHECKING:
from fragmentapi.client import FragmentClient
from pyfragment.client import FragmentClient
def _init_ton_client(client: "FragmentClient") -> TonapiClient:
+5 -5
View File
@@ -3,7 +3,7 @@ requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "fragmentapi"
name = "pyfragment"
version = "2026.1.0"
description = "Python library for the Fragment.com API — gift Telegram Stars, Premium, and top up TON Ads balance."
readme = "README.md"
@@ -39,12 +39,12 @@ dev = [
]
[project.urls]
Homepage = "https://github.com/bohd4nx/FragmentAPI"
Repository = "https://github.com/bohd4nx/FragmentAPI"
Issues = "https://github.com/bohd4nx/FragmentAPI/issues"
Homepage = "https://github.com/bohd4nx/pyfragment"
Repository = "https://github.com/bohd4nx/pyfragment"
Issues = "https://github.com/bohd4nx/pyfragment/issues"
[tool.hatch.build.targets.wheel]
packages = ["fragmentapi"]
packages = ["pyfragment"]
[tool.pytest.ini_options]
testpaths = ["tests"]
+2 -2
View File
@@ -4,8 +4,8 @@ import re
import pytest
from fragmentapi.types import ParseError
from fragmentapi.utils.decoder import clean_decode
from pyfragment.types import ParseError
from pyfragment.utils.decoder import clean_decode
PAYLOADS = [
pytest.param(
+2 -2
View File
@@ -4,8 +4,8 @@ import json
import pytest
from fragmentapi import FragmentClient
from fragmentapi.types import ConfigurationError, CookieError
from pyfragment import FragmentClient
from pyfragment.types import ConfigurationError, CookieError
VALID_SEED = "abandon " * 23 + "about"
VALID_API_KEY = "test_api_key"
+2 -2
View File
@@ -5,8 +5,8 @@ import re
import pytest
from fragmentapi.types import BASE_HEADERS, STARS_PAGE
from fragmentapi.utils import get_fragment_hash
from pyfragment.types import BASE_HEADERS, STARS_PAGE
from pyfragment.utils import get_fragment_hash
@pytest.mark.asyncio