commit 81247b3d36c08ca14cbde29e3696b16c37678d54 Author: bohd4nx Date: Thu May 21 16:36:13 2026 +0300 docs: rewrite structure and humanize GitBook docs diff --git a/.github/workflows/gitbook-sync.yml b/.github/workflows/gitbook-sync.yml new file mode 100644 index 0000000..11b6117 --- /dev/null +++ b/.github/workflows/gitbook-sync.yml @@ -0,0 +1,23 @@ +name: Docs Branch Check + +on: + push: + branches: [docs] + pull_request: + branches: [docs] + +jobs: + docs-tree: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Ensure docs structure exists + run: | + test -f docs/README.md + test -f docs/SUMMARY.md + test -d docs/getting-started + test -d docs/client + test -d docs/reference + test -d docs/advanced diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..78c7d64 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# pyfragment docs branch + +This branch is dedicated to GitBook content. + +- Main docs source: docs/ +- Navigation: docs/SUMMARY.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..06d44df --- /dev/null +++ b/docs/README.md @@ -0,0 +1,41 @@ +# pyfragment Documentation + +`pyfragment` is an async Python client for [Fragment](https://fragment.com). + +If you are integrating Fragment into a bot or backend, this docs set is meant to be practical, not theoretical. + +**Recommended reading order:** + +1. Install the package +2. Configure `FragmentClient` +3. Set up credentials and cookies +4. Run the quick start +5. Move to feature-specific flows + +## Who this is for + +- Python developers integrating Fragment into bots, services, and automation. +- Teams that need predictable typed results and explicit error behavior. + +**Important:** this library is not affiliated with Fragment or Telegram. + +## Where to begin + +1. [Installation](getting-started/installation.md) +2. [Library and Configuration](getting-started/configuration.md) +3. [Credentials and Cookies](getting-started/credentials-and-cookies.md) +4. [Quick Start](getting-started/quickstart.md) + +## Feature entry points + +- Stars: [Purchase](client/stars/purchase.md), [Giveaway](client/stars/giveaway.md) +- Premium: [Purchase](client/premium/purchase.md), [Giveaway](client/premium/giveaway.md) +- Marketplace: [Overview](client/marketplace/overview.md), Ads: [Ads](client/ads.md) +- Management: [Anonymous Numbers](client/anonymous-numbers.md) + +## Additional references + +- [Error Handling](reference/errors.md) +- [Result Models](reference/models.md) +- [Literal Types](reference/literals.md) +- [Troubleshooting](advanced/troubleshooting.md) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md new file mode 100644 index 0000000..cc50e94 --- /dev/null +++ b/docs/SUMMARY.md @@ -0,0 +1,31 @@ +# Table of contents + +- [Start Here](getting-started/installation.md) +- Getting Started + - [Installation](getting-started/installation.md) + - [Library and Configuration](getting-started/configuration.md) + - [Credentials and Cookies](getting-started/credentials-and-cookies.md) + - [Quick Start](getting-started/quickstart.md) +- [Error Handling](reference/errors.md) +- Client API + - [Overview](client/overview.md) + - Stars + - [Purchase](client/stars/purchase.md) + - [Giveaway](client/stars/giveaway.md) + - Premium + - [Purchase](client/premium/purchase.md) + - [Giveaway](client/premium/giveaway.md) + - [Ads](client/ads.md) + - [Anonymous Numbers](client/anonymous-numbers.md) + - Marketplace + - [Overview](client/marketplace/overview.md) + - [Search Usernames](client/marketplace/search-usernames.md) + - [Search Numbers](client/marketplace/search-numbers.md) + - [Search Gifts](client/marketplace/search-gifts.md) + - [Raw API Calls](client/raw-call.md) +- Reference + - [Result Models](reference/models.md) + - [Literal Types](reference/literals.md) +- Advanced + - [Cookie Extraction Details](advanced/cookies.md) + - [Troubleshooting](advanced/troubleshooting.md) diff --git a/docs/advanced/cookies.md b/docs/advanced/cookies.md new file mode 100644 index 0000000..a567103 --- /dev/null +++ b/docs/advanced/cookies.md @@ -0,0 +1,24 @@ +# Cookie Extraction Details + +`get_cookies_from_browser(browser)` reads Fragment cookies from local browser storage (via `rookiepy`). + +This is the fastest way to start when you do not want manual cookie export. + +Supported browsers are defined in constants and include: + +- chrome, firefox, edge, brave, +- arc, opera, opera_gx, +- safari, vivaldi, +- chromium variants. + +Validation includes: + +- required key presence, +- non-empty values, +- optional expiration check for `stel_ssid`. + +**If any required cookie is empty or missing, extraction is treated as failed.** + +If extraction fails, `CookieError` is raised with actionable details. + +Use [Credentials and Cookies](../getting-started/credentials-and-cookies.md) for setup-first instructions. diff --git a/docs/advanced/troubleshooting.md b/docs/advanced/troubleshooting.md new file mode 100644 index 0000000..4878d77 --- /dev/null +++ b/docs/advanced/troubleshooting.md @@ -0,0 +1,59 @@ +# Troubleshooting + +When something breaks, start here. Most issues are caused by cookies, session state, or wallet balance. + +## Auth/session errors + +Symptoms: + +- Fragment page hash cannot be extracted, +- bad status loading Fragment pages, +- missing request IDs. + +Actions: + +- re-login on fragment.com, +- refresh cookies, +- ensure all `stel_*` keys are present. +- verify constructor payload in [Library and Configuration](../getting-started/configuration.md). + +**Re-login + fresh cookies solves the majority of auth errors.** + +## Cookie extraction errors + +Symptoms: + +- browser not supported, +- cannot read browser profile, +- required cookies not found. + +Actions: + +- install `pyfragment[browser]`, +- close locked browser profiles, +- use manual cookies if needed. + +## Balance/transaction failures + +Symptoms: + +- low TON/USDT balance errors, +- broadcast failures, +- duplicate seqno retries. + +Actions: + +- keep TON reserve for fees, +- ensure USDT is on the **Fragment-linked wallet**, +- retry after short delay when seqno collisions happen. +- check operation constraints in Stars/Premium/Ads method pages. + +## SSL-related broadcast failures + +If you get SSL-related transaction errors: + +```bash +pip install --upgrade certifi +``` + +On macOS, also run Python's `Install Certificates.command` if needed. diff --git a/docs/client/ads.md b/docs/client/ads.md new file mode 100644 index 0000000..cf951a2 --- /dev/null +++ b/docs/client/ads.md @@ -0,0 +1,55 @@ +# Ads + +Ads methods cover two different actions: + +- sending TON to a user, +- recharging your own Telegram Ads account. + +## topup_ton + +```python +await client.topup_ton( + username: str, + amount: int, + show_sender: bool = True, +) -> AdsTopupResult +``` + +Rules: + +- `username`: recipient Telegram username +- `amount`: integer from `1` to `1_000_000_000` +- `show_sender`: sender visibility + +**Important:** `amount` must be an integer in allowed range. + +## recharge_ads + +```python +await client.recharge_ads( + account: str, + amount: int, +) -> AdsRechargeResult +``` + +Rules: + +- `account`: channel/bot username linked to your ads account +- `amount`: integer from `1` to `1_000_000_000` + +## Returns + +- `AdsTopupResult(transaction_id, username, amount)` +- `AdsRechargeResult(transaction_id, amount)` + +## Common errors + +- `ConfigurationError` +- `UserNotFoundError` (topup recipient) +- `WalletError` +- `VerificationError` + +## Related flows + +- [Stars Purchase](stars/purchase.md) +- [Premium Purchase](premium/purchase.md) diff --git a/docs/client/anonymous-numbers.md b/docs/client/anonymous-numbers.md new file mode 100644 index 0000000..465ad27 --- /dev/null +++ b/docs/client/anonymous-numbers.md @@ -0,0 +1,45 @@ +# Anonymous Numbers + +These methods help you manage login behavior and active sessions for anonymous numbers owned by your current account. + +## get_login_code + +```python +await client.get_login_code(number: str) -> LoginCodeResult +``` + +Returns: + +- `number` +- `code` (`None` if no pending code) +- `active_sessions` + +## toggle_login_codes + +```python +await client.toggle_login_codes(number: str, can_receive: bool) -> None +``` + +Use `can_receive=True` to allow incoming login codes, or `False` to block them. + +## terminate_sessions + +```python +await client.terminate_sessions(number: str) -> TerminateSessionsResult +``` + +Returns: + +- `number` +- `message` + +## Common errors + +- `AnonymousNumberError.NOT_OWNED` +- `AnonymousNumberError.TERMINATE_FAILED` + +## Practical note + +These methods operate only on numbers owned by the currently authorized Fragment account. + +**If a number is not yours, requests will fail with `AnonymousNumberError`.** diff --git a/docs/client/marketplace/overview.md b/docs/client/marketplace/overview.md new file mode 100644 index 0000000..976fd1b --- /dev/null +++ b/docs/client/marketplace/overview.md @@ -0,0 +1,31 @@ +# Marketplace Overview + +Marketplace methods are exposed directly on `FragmentClient` and via `client.marketplace` service. + +If you only need one thing: pick the method by asset type (username, number, gift), then paginate until `next_offset_id` or `next_offset` becomes `None`. + +Available methods: + +- [Search Usernames](search-usernames.md) +- [Search Numbers](search-numbers.md) +- [Search Gifts](search-gifts.md) + +## Shared behavior + +- All methods are async. +- All methods call Fragment `searchAuctions` under the hood. +- `sort` and `filter` are optional passthrough strings. + +**These values are passed to Fragment as-is.** If Fragment changes accepted values, behavior can change too. + +Common values used by Fragment pages: + +- `sort`: `price_desc`, `price_asc`, `listed`, `ending` +- `filter`: empty string, `auction`, `sale`, `sold` + +## Pagination model + +- Usernames and Numbers return `next_offset_id` (string) +- Gifts return `next_offset` (integer) + +Use these fields to request next pages. diff --git a/docs/client/marketplace/search-gifts.md b/docs/client/marketplace/search-gifts.md new file mode 100644 index 0000000..9e309d3 --- /dev/null +++ b/docs/client/marketplace/search-gifts.md @@ -0,0 +1,75 @@ +# Search Gifts + +This endpoint is the most flexible marketplace search and supports collection, traits, and pagination. + +## Method + +```python +await client.search_gifts( + query: str = "", + collection: str | None = None, + sort: str | None = None, + filter: str | None = None, + view: str | None = None, + attr: dict[str, list[str]] | None = None, + offset: int | None = None, +) -> GiftsResult +``` + +## Parameters + +- `query`: search text (empty string for broad listing) +- `collection`: collection slug (for example `plushpepe`, `swisswatch`) +- `sort`: optional sort key passed to Fragment +- `filter`: optional listing filter passed to Fragment +- `view`: optional UI/view mode passed to Fragment +- `attr`: optional trait filters where key is trait name and value is list of allowed values +- `offset`: page offset for next page + +**`attr` is ideal for narrowing results by visual or rarity traits.** + +## Sorting values + +Common values accepted by Fragment: + +- `price_desc` +- `price_asc` +- `listed` +- `ending` + +## Filter values + +Common values accepted by Fragment: + +- empty string +- `auction` +- `sale` +- `sold` + +## Attribute filter format + +`attr` is encoded into request fields in this form: + +- `attr[trait_name] = ["value1", "value2"]` + +Example: + +```python +attr={ + "model": ["gold", "silver"], + "rarity": ["rare"], +} +``` + +In requests, each trait is sent as `attr[trait]` with a list of values. + +## Return type + +`GiftsResult` contains: + +- `items: list[dict[str, Any]]` +- `next_offset: int | None` + +## Pagination + +If `next_offset` is not `None`, pass it back as `offset` to load the next page. diff --git a/docs/client/marketplace/search-numbers.md b/docs/client/marketplace/search-numbers.md new file mode 100644 index 0000000..c5f902a --- /dev/null +++ b/docs/client/marketplace/search-numbers.md @@ -0,0 +1,54 @@ +# Search Numbers + +Use this endpoint to search anonymous Telegram number listings. + +## Method + +```python +await client.search_numbers( + query: str = "", + sort: str | None = None, + filter: str | None = None, + offset_id: str | None = None, +) -> NumbersResult +``` + +## Parameters + +- `query`: digits or text to match number listings +- `sort`: optional sort key passed to Fragment +- `filter`: optional listing filter passed to Fragment +- `offset_id`: page cursor for next page + +`query` can be partial digits (for example `"888"`) when you need pattern-based discovery. + +## Sorting values + +Common values accepted by Fragment: + +- `price_desc` +- `price_asc` +- `listed` +- `ending` + +## Filter values + +Common values accepted by Fragment: + +- empty string +- `auction` +- `sale` +- `sold` + +## Return type + +`NumbersResult` contains: + +- `items: list[dict[str, Any]]` +- `next_offset_id: str | None` + +## Pagination + +If `next_offset_id` is not `None`, pass it back as `offset_id` to load the next page. + +Keep requesting pages until `next_offset_id` becomes `None`. diff --git a/docs/client/marketplace/search-usernames.md b/docs/client/marketplace/search-usernames.md new file mode 100644 index 0000000..a34066b --- /dev/null +++ b/docs/client/marketplace/search-usernames.md @@ -0,0 +1,54 @@ +# Search Usernames + +Use this endpoint to discover Telegram usernames listed on Fragment. + +## Method + +```python +await client.search_usernames( + query: str = "", + sort: str | None = None, + filter: str | None = None, + offset_id: str | None = None, +) -> UsernamesResult +``` + +## Parameters + +- `query`: search text (empty string means broad listing) +- `sort`: optional sort key passed to Fragment +- `filter`: optional listing filter passed to Fragment +- `offset_id`: page cursor for next page + +For broad browsing, use empty `query` and set sorting only. + +## Sorting values + +Common values accepted by Fragment: + +- `price_desc` +- `price_asc` +- `listed` +- `ending` + +## Filter values + +Common values accepted by Fragment: + +- empty string +- `auction` +- `sale` +- `sold` + +## Return type + +`UsernamesResult` contains: + +- `items: list[dict[str, Any]]` +- `next_offset_id: str | None` + +## Pagination + +If `next_offset_id` is not `None`, pass it back as `offset_id` to load the next page. + +This is cursor pagination, so do not try to calculate offsets manually. diff --git a/docs/client/overview.md b/docs/client/overview.md new file mode 100644 index 0000000..58aba74 --- /dev/null +++ b/docs/client/overview.md @@ -0,0 +1,42 @@ +# Client Overview + +`FragmentClient` is the main API surface. + +You can call methods directly on the client or use grouped services. + +Grouped service wrappers: + +- `client.purchases` +- `client.giveaways` +- `client.ads` +- `client.anonymous_numbers` +- `client.marketplace` +- `client.tonapi` + +Main async methods on `FragmentClient`: + +- `purchase_stars(...)` +- `purchase_premium(...)` +- `giveaway_stars(...)` +- `giveaway_premium(...)` +- `topup_ton(...)` +- `recharge_ads(...)` +- `get_wallet()` +- `get_login_code(...)` +- `toggle_login_codes(...)` +- `terminate_sessions(...)` +- `search_usernames(...)` +- `search_numbers(...)` +- `search_gifts(...)` +- `call(...)` + +All methods are async and should be used inside `async with FragmentClient(...) as client:`. + +## Flow map + +- Stars: [Purchase](stars/purchase.md), [Giveaway](stars/giveaway.md) +- Premium: [Purchase](premium/purchase.md), [Giveaway](premium/giveaway.md) +- Ads: [Ads operations](ads.md) +- Utility operations: [Anonymous Numbers](anonymous-numbers.md), [Marketplace](marketplace/overview.md), [Raw API Calls](raw-call.md) + +**If you are new to the library, start with Stars Purchase or Wallet read (`get_wallet`) first.** diff --git a/docs/client/premium/giveaway.md b/docs/client/premium/giveaway.md new file mode 100644 index 0000000..ec67c0a --- /dev/null +++ b/docs/client/premium/giveaway.md @@ -0,0 +1,34 @@ +# Premium Giveaway + +Use this method to run a Telegram Premium giveaway for your channel. + +## Method + +```python +await client.giveaway_premium( + channel: str, + winners: int, + months: int = 3, + payment_method: PaymentMethod = "ton", +) -> PremiumGiveawayResult +``` + +## Parameters + +- `channel`: accepts `@channel`, `channel`, or `https://t.me/channel` +- `winners`: integer from `1` to `24_000` +- `months`: one of `3`, `6`, `12` +- `payment_method`: `"ton"` or `"usdt_ton"` + +**`winners` must be a positive integer, and large values can increase total cost significantly.** + +## Return + +- `PremiumGiveawayResult(transaction_id, channel, winners, amount)` + +## Typical errors + +- `ConfigurationError` +- `UserNotFoundError` +- `WalletError` +- `VerificationError` diff --git a/docs/client/premium/purchase.md b/docs/client/premium/purchase.md new file mode 100644 index 0000000..49ed3ee --- /dev/null +++ b/docs/client/premium/purchase.md @@ -0,0 +1,34 @@ +# Premium Purchase + +Use this method to gift Telegram Premium to a specific user. + +## Method + +```python +await client.purchase_premium( + username: str, + months: int, + show_sender: bool = True, + payment_method: PaymentMethod = "ton", +) -> PremiumResult +``` + +## Parameters + +- `username`: accepts `@username`, `username`, or `https://t.me/username` +- `months`: one of `3`, `6`, `12` +- `show_sender`: controls sender visibility on recipient side +- `payment_method`: `"ton"` or `"usdt_ton"` + +**`months` only supports `3`, `6`, or `12`.** + +## Return + +- `PremiumResult(transaction_id, username, amount)` + +## Typical errors + +- `ConfigurationError` +- `UserNotFoundError` +- `WalletError` +- `VerificationError` diff --git a/docs/client/raw-call.md b/docs/client/raw-call.md new file mode 100644 index 0000000..0159ac0 --- /dev/null +++ b/docs/client/raw-call.md @@ -0,0 +1,32 @@ +# Raw API Calls + +Use `client.call()` when you need a Fragment API method that does not yet have a dedicated wrapper. + +```python +result = await client.call( + "searchPremiumGiftRecipient", + {"query": "@username", "months": 3}, + page_url="https://fragment.com/premium/gift", +) +``` + +Signature: + +```python +await client.call( + method: str, + data: dict[str, Any] | None = None, + *, + page_url: str = "https://fragment.com", +) -> dict[str, Any] +``` + +Use this carefully: + +- request/response shape is Fragment-defined, +- undocumented methods can change without notice, +- you are responsible for validating returned fields. + +## Recommended approach + +Use dedicated wrappers first, and fallback to `call()` only for missing API surface. diff --git a/docs/client/stars/giveaway.md b/docs/client/stars/giveaway.md new file mode 100644 index 0000000..c3cea9a --- /dev/null +++ b/docs/client/stars/giveaway.md @@ -0,0 +1,34 @@ +# Stars Giveaway + +Use this method to run a Stars giveaway for a channel audience. + +## Method + +```python +await client.giveaway_stars( + channel: str, + winners: int, + amount: int, + payment_method: PaymentMethod = "ton", +) -> StarsGiveawayResult +``` + +## Parameters + +- `channel`: accepts `@channel`, `channel`, or `https://t.me/channel` +- `winners`: integer from `1` to `5` +- `amount`: integer from `500` to `1_000_000` (per winner) +- `payment_method`: `"ton"` or `"usdt_ton"` + +**Each winner receives the full `amount` value.** + +## Return + +- `StarsGiveawayResult(transaction_id, channel, winners, amount)` + +## Typical errors + +- `ConfigurationError` +- `UserNotFoundError` +- `WalletError` +- `VerificationError` diff --git a/docs/client/stars/purchase.md b/docs/client/stars/purchase.md new file mode 100644 index 0000000..d8bd3d5 --- /dev/null +++ b/docs/client/stars/purchase.md @@ -0,0 +1,34 @@ +# Stars Purchase + +Use this method to send Telegram Stars directly to a user. + +## Method + +```python +await client.purchase_stars( + username: str, + amount: int, + show_sender: bool = True, + payment_method: PaymentMethod = "ton", +) -> StarsResult +``` + +## Parameters + +- `username`: accepts `@username`, `username`, or `https://t.me/username` +- `amount`: integer from `50` to `1_000_000` +- `show_sender`: controls sender visibility on recipient side +- `payment_method`: `"ton"` or `"usdt_ton"` + +**Amount must be between `50` and `1_000_000`.** + +## Return + +- `StarsResult(transaction_id, username, amount)` + +## Typical errors + +- `ConfigurationError`: invalid amount or payment method +- `UserNotFoundError`: target user not found +- `WalletError`: insufficient balance or wallet-side issue +- `VerificationError`: verification/KYC required for operation diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md new file mode 100644 index 0000000..933cc08 --- /dev/null +++ b/docs/getting-started/configuration.md @@ -0,0 +1,69 @@ +# Library and Configuration + +Main entry point of the library is `FragmentClient`. + +```python +FragmentClient( + seed: str, + api_key: str, + cookies: dict[str, Any] | str, + wallet_version: str = "V5R1", + timeout: float = 30.0, +) +``` + +## Parameters + +- `seed`: wallet mnemonic (**12, 18, or 24 words**) +- `api_key`: Tonapi key from https://tonconsole.com +- `cookies`: Fragment cookies as a dictionary or JSON string +- `wallet_version`: `"V4R2"` or `"V5R1"` +- `timeout`: request timeout in seconds + +**If `api_key` is too short or cookies are incomplete, initialization fails immediately.** + +## Required cookies + +- `stel_ssid` +- `stel_dt` +- `stel_token` +- `stel_ton_token` + +## Minimal initialization pattern + +```python +from pyfragment import FragmentClient + +client = FragmentClient( + seed="word1 word2 ... word24", + api_key="YOUR_TONAPI_KEY", + cookies={ + "stel_ssid": "...", + "stel_dt": "...", + "stel_token": "...", + "stel_ton_token": "...", + }, +) +``` + +Use it inside async context manager: + +```python +async with client: + wallet = await client.get_wallet() +``` + +You can also create the client directly inside `async with` if you prefer one-block setup. + +## Validation behavior + +At initialization, library validates: + +- seed format, +- cookie shape and required keys, +- supported wallet version, +- parseability of cookie JSON strings. + +Constructor-level issues are raised as `ConfigurationError` or `CookieError`. + +**Tip:** keep validation failures visible in logs during initial integration. They save a lot of debugging time. diff --git a/docs/getting-started/credentials-and-cookies.md b/docs/getting-started/credentials-and-cookies.md new file mode 100644 index 0000000..97abbc1 --- /dev/null +++ b/docs/getting-started/credentials-and-cookies.md @@ -0,0 +1,56 @@ +# Credentials and Cookies + +This page covers the three things you need before making real requests: Tonapi key, wallet seed, and Fragment cookies. + +## Tonapi key + +Generate an API key at https://tonconsole.com. + +## Seed phrase + +Use your TON wallet mnemonic. + +- **Keep it private.** +- **Never log it or commit it to git.** + +## Fragment cookies + +You must be logged in to Fragment. + +### Option 1: automatic extraction + +```python +from pyfragment import get_cookies_from_browser + +cookie_result = get_cookies_from_browser("chrome") +cookies = cookie_result.cookies +``` + +`cookie_result` is `CookieResult`: + +- `cookies`: `dict[str, str]` +- `expires`: ISO string or `None` + +### Option 2: manual export + +Export the four required Fragment cookies and pass them directly as dict or JSON string. + +Required keys: + +- `stel_ssid` +- `stel_dt` +- `stel_token` +- `stel_ton_token` + +## Common auth failures + +- expired session cookies, +- not logged in on fragment.com, +- missing `stel_*` keys, +- stale cookies from another browser/profile. + +When this happens, re-login on fragment.com and refresh cookies first. It solves most auth issues. + +## Next step + +Proceed to [Quick Start](quickstart.md). diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md new file mode 100644 index 0000000..37aa91f --- /dev/null +++ b/docs/getting-started/installation.md @@ -0,0 +1,35 @@ +# Installation + +You can be up and running in under a minute. + +## Requirements + +- Python 3.10+ + +## Install from PyPI + +```bash +pip install pyfragment +``` + +## Install latest dev branch + +```bash +pip install git+https://github.com/bohd4nx/pyfragment.git@dev +``` + +## Optional browser cookie extraction support + +If you want automatic cookie extraction from local browser profiles: + +```bash +pip install "pyfragment[browser]" +``` + +This installs `rookiepy`, used by `get_cookies_from_browser()`. + +**Use this extra if you do not want to copy cookies manually.** + +## Next step + +After installation, continue with [Library and Configuration](configuration.md). diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md new file mode 100644 index 0000000..9bebcb1 --- /dev/null +++ b/docs/getting-started/quickstart.md @@ -0,0 +1,36 @@ +# Quick Start + +Use this minimal example to verify that your credentials, cookies, and wallet setup are correct. + +```python +import asyncio + +from pyfragment import FragmentClient + + +async def main() -> None: + async with FragmentClient( + seed="word1 word2 ... word24", + api_key="YOUR_TONAPI_KEY", + cookies={ + "stel_ssid": "...", + "stel_dt": "...", + "stel_token": "...", + "stel_ton_token": "...", + }, + ) as client: + wallet = await client.get_wallet() + print(wallet) + +asyncio.run(main()) +``` + +If this script returns wallet data, your setup is healthy. + +Then move to feature pages: + +- Stars: [Purchase](../client/stars/purchase.md), [Giveaway](../client/stars/giveaway.md) +- Premium: [Purchase](../client/premium/purchase.md), [Giveaway](../client/premium/giveaway.md) +- [Ads](../client/ads.md) +- [Anonymous Numbers](../client/anonymous-numbers.md) +- [Marketplace](../client/marketplace/overview.md) diff --git a/docs/reference/errors.md b/docs/reference/errors.md new file mode 100644 index 0000000..80a7e2d --- /dev/null +++ b/docs/reference/errors.md @@ -0,0 +1,53 @@ +# Error Handling + +Good error handling is the difference between a stable integration and random production failures. + +## Exception hierarchy + +- `FragmentError` + - `ClientError` + - `ConfigurationError` + - `CookieError` + - `FragmentAPIError` + - `FragmentPageError` + - `UserNotFoundError` + - `AnonymousNumberError` + - `TransactionError` + - `ParseError` + - `VerificationError` + - `OperationError` + - `WalletError` + - `UnexpectedError` + +## Recommended handling pattern + +```python +from pyfragment import ConfigurationError, FragmentError, UserNotFoundError, WalletError + +try: + result = await client.purchase_stars("@username", amount=500) +except UserNotFoundError: + # recipient does not exist on Fragment + ... +except WalletError: + # insufficient balance or wallet-side issue + ... +except ConfigurationError: + # invalid local input + ... +except FragmentError: + # any other library-level failure + ... +``` + +**Catch specific errors first, then fallback to `FragmentError`.** + +## Method-to-error mapping + +- Stars/Premium purchase and giveaway: `ConfigurationError`, `UserNotFoundError`, `WalletError`, `VerificationError` +- Ads operations: `ConfigurationError`, `UserNotFoundError`, `WalletError`, `VerificationError` +- Cookies/auth setup: `CookieError`, `ConfigurationError`, `FragmentPageError` + +## Canonical messages + +See `pyfragment/exceptions.py` for source-of-truth message templates. diff --git a/docs/reference/literals.md b/docs/reference/literals.md new file mode 100644 index 0000000..4e87206 --- /dev/null +++ b/docs/reference/literals.md @@ -0,0 +1,24 @@ +# Literal Types + +These literals describe accepted string values for key method parameters. + +## PaymentMethod + +```python +PaymentMethod = Literal["ton", "usdt_ton"] +``` + +## WalletVersion + +```python +WalletVersion = Literal["V4R2", "V5R1"] +``` + +These literals are exported from `pyfragment.models.enums` and `pyfragment.models`. + +## Usage notes + +- Use `PaymentMethod` for purchase and giveaway operations. +- Use `WalletVersion` when configuring `FragmentClient`. + +**Passing unsupported values raises `ConfigurationError`.** diff --git a/docs/reference/models.md b/docs/reference/models.md new file mode 100644 index 0000000..a634f37 --- /dev/null +++ b/docs/reference/models.md @@ -0,0 +1,31 @@ +# Result Models + +Every high-level method returns a typed model, so you can rely on predictable fields instead of raw payload parsing. + +Exported result models: + +- `CookieResult(cookies, expires)` +- `StarsResult(transaction_id, username, amount)` +- `PremiumResult(transaction_id, username, amount)` +- `AdsTopupResult(transaction_id, username, amount)` +- `AdsRechargeResult(transaction_id, amount)` +- `StarsGiveawayResult(transaction_id, channel, winners, amount)` +- `PremiumGiveawayResult(transaction_id, channel, winners, amount)` +- `WalletInfo(address, state, ton_balance, usdt_balance)` +- `LoginCodeResult(number, code, active_sessions)` +- `TerminateSessionsResult(number, message)` +- `UsernamesResult(items, next_offset_id)` +- `NumbersResult(items, next_offset_id)` +- `GiftsResult(items, next_offset)` + +Most high-level methods return one of these dataclasses. + +## Where they are used + +- Stars/Premium purchase: `StarsResult`, `PremiumResult` +- Stars/Premium giveaway: `StarsGiveawayResult`, `PremiumGiveawayResult` +- Ads: `AdsTopupResult`, `AdsRechargeResult` +- Wallet and utility: `WalletInfo`, `LoginCodeResult`, `TerminateSessionsResult` +- Marketplace search: `UsernamesResult`, `NumbersResult`, `GiftsResult` + +**Use these models directly in your app layer and avoid passing raw dictionaries around.**