diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 637633c..f9e4d5e 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -20,7 +20,7 @@ - [Search Gifts](client/marketplace/search-gifts.md) - Ads - [Overview](client/ads/overview.md) - - [Top Up TON](client/ads/topup-ton.md) + - [Top Up GRAM](client/ads/topup-gram.md) - [Recharge Ads](client/ads/recharge-ads.md) - Anonymous Numbers - [Overview](client/anonymous-numbers/overview.md) diff --git a/docs/advanced/troubleshooting.md b/docs/advanced/troubleshooting.md index 4878d77..1eed9fb 100644 --- a/docs/advanced/troubleshooting.md +++ b/docs/advanced/troubleshooting.md @@ -43,7 +43,7 @@ Symptoms: Actions: -- keep TON reserve for fees, +- keep GRAM (ex 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. diff --git a/docs/client/ads/overview.md b/docs/client/ads/overview.md index a6659da..118a4ec 100644 --- a/docs/client/ads/overview.md +++ b/docs/client/ads/overview.md @@ -2,10 +2,10 @@ Ads flow is split into two methods: -- [Top Up TON](topup-ton.md) +- [Top Up GRAM](topup-gram.md) - [Recharge Ads](recharge-ads.md) -Use the first method to send TON to a Telegram user. +Use the first method to send GRAM (ex TON) to a Telegram user. Use the second method to fund your own Telegram Ads account. ## Common errors diff --git a/docs/client/ads/topup-gram.md b/docs/client/ads/topup-gram.md new file mode 100644 index 0000000..ff4ce96 --- /dev/null +++ b/docs/client/ads/topup-gram.md @@ -0,0 +1,38 @@ +# Top Up GRAM + +Use this method to send GRAM (ex TON) to a user's Telegram balance. + +## Method + +```python +await client.topup_gram( + username: str, + amount: int, + show_sender: bool = True, +) -> AdsTopupResult +``` + +## Parameters + +- `username`: recipient Telegram username — `@username`, `username`, or `https://t.me/username` +- `amount`: integer from `1` to `1_000_000_000` +- `show_sender`: controls sender visibility + +**`amount` must be an integer in the allowed range.** + +## Return + +- `AdsTopupResult(transaction_id, username, amount)` + +## Typical errors + +- `ConfigurationError`: invalid amount +- `UserNotFoundError`: recipient not found on Fragment +- `WalletError`: insufficient GRAM (ex TON) balance + +## Example + +```python +result: AdsTopupResult = await client.topup_gram("@username", amount=10, show_sender=True) +print(result.transaction_id) +``` diff --git a/docs/client/ads/topup-ton.md b/docs/client/ads/topup-ton.md deleted file mode 100644 index 657152f..0000000 --- a/docs/client/ads/topup-ton.md +++ /dev/null @@ -1,32 +0,0 @@ -# Top Up TON - -Use this method to send TON to a user's Telegram balance. - -## Method - -```python -await client.topup_ton( - username: str, - amount: int, - show_sender: bool = True, -) -> AdsTopupResult -``` - -## Parameters - -- `username`: recipient Telegram username -- `amount`: integer from `1` to `1_000_000_000` -- `show_sender`: controls sender visibility - -**Important:** `amount` must be an integer in the allowed range. - -## Return - -- `AdsTopupResult(transaction_id, username, amount)` - -## Example - -```python -result: AdsTopupResult = await client.topup_ton("@username", amount=10, show_sender=True) -print(result.transaction_id) -``` diff --git a/docs/client/overview.md b/docs/client/overview.md index 9fbeac2..56143c2 100644 --- a/docs/client/overview.md +++ b/docs/client/overview.md @@ -19,7 +19,7 @@ Main async methods on `FragmentClient`: - `purchase_premium(...)` - `giveaway_stars(...)` - `giveaway_premium(...)` -- `topup_ton(...)` +- `topup_gram(...)` - `recharge_ads(...)` - `get_wallet()` - `get_login_code(...)` diff --git a/docs/client/premium/giveaway.md b/docs/client/premium/giveaway.md index 3c88c05..1f9c246 100644 --- a/docs/client/premium/giveaway.md +++ b/docs/client/premium/giveaway.md @@ -9,7 +9,7 @@ await client.giveaway_premium( channel: str, winners: int, months: int = 3, - payment_method: PaymentMethod = "ton", + payment_method: PaymentMethod = PaymentMethod.GRAM, ) -> PremiumGiveawayResult ``` @@ -18,7 +18,7 @@ await client.giveaway_premium( - `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"` +- `payment_method`: `PaymentMethod.GRAM` (default), `PaymentMethod.USDT_GRAM`, or any other `PaymentMethod` value **`winners` must be a positive integer, and large values can increase total cost significantly.** diff --git a/docs/client/premium/purchase.md b/docs/client/premium/purchase.md index 2fdcdbd..72cee14 100644 --- a/docs/client/premium/purchase.md +++ b/docs/client/premium/purchase.md @@ -9,7 +9,7 @@ await client.purchase_premium( username: str, months: int, show_sender: bool = True, - payment_method: PaymentMethod = "ton", + payment_method: PaymentMethod = PaymentMethod.GRAM, ) -> PremiumResult ``` @@ -18,7 +18,7 @@ await client.purchase_premium( - `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"` +- `payment_method`: `PaymentMethod.GRAM` (default), `PaymentMethod.USDT_GRAM`, or any other `PaymentMethod` value **`months` only supports `3`, `6`, or `12`.** @@ -36,6 +36,6 @@ await client.purchase_premium( ## Example ```python -result: PremiumResult = await client.purchase_premium("@username", months=6, payment_method="ton") +result: PremiumResult = await client.purchase_premium("@username", months=6, payment_method=PaymentMethod.GRAM) print(result.transaction_id) ``` diff --git a/docs/client/stars/giveaway.md b/docs/client/stars/giveaway.md index 5d783c0..fc2e3c1 100644 --- a/docs/client/stars/giveaway.md +++ b/docs/client/stars/giveaway.md @@ -9,16 +9,16 @@ await client.giveaway_stars( channel: str, winners: int, amount: int, - payment_method: PaymentMethod = "ton", + payment_method: PaymentMethod = PaymentMethod.GRAM, ) -> StarsGiveawayResult ``` ## Parameters - `channel`: accepts `@channel`, `channel`, or `https://t.me/channel` -- `winners`: integer from `1` to `5` +- `winners`: integer from `1` to `15` - `amount`: integer from `500` to `1_000_000` (per winner) -- `payment_method`: `"ton"` or `"usdt_ton"` +- `payment_method`: `PaymentMethod.GRAM` (default), `PaymentMethod.USDT_GRAM`, or any other `PaymentMethod` value **Each winner receives the full `amount` value.** diff --git a/docs/client/stars/purchase.md b/docs/client/stars/purchase.md index 7a55435..34494e6 100644 --- a/docs/client/stars/purchase.md +++ b/docs/client/stars/purchase.md @@ -9,18 +9,18 @@ await client.purchase_stars( username: str, amount: int, show_sender: bool = True, - payment_method: PaymentMethod = "ton", + payment_method: PaymentMethod = PaymentMethod.GRAM, ) -> StarsResult ``` ## Parameters - `username`: accepts `@username`, `username`, or `https://t.me/username` -- `amount`: integer from `50` to `1_000_000` +- `amount`: integer from `50` to `10_000_000` - `show_sender`: controls sender visibility on recipient side -- `payment_method`: `"ton"` or `"usdt_ton"` +- `payment_method`: `PaymentMethod.GRAM` (default), `PaymentMethod.USDT_GRAM`, or any other `PaymentMethod` value -**Amount must be between `50` and `1_000_000`.** +**Amount must be between `50` and `10_000_000`.** ## Return @@ -36,6 +36,6 @@ await client.purchase_stars( ## Example ```python -result: StarsResult = await client.purchase_stars("@username", amount=500, payment_method="ton") +result: StarsResult = await client.purchase_stars("@username", amount=500, payment_method=PaymentMethod.GRAM) print(result.amount) ``` diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md index 933cc08..2282f36 100644 --- a/docs/getting-started/configuration.md +++ b/docs/getting-started/configuration.md @@ -8,19 +8,21 @@ FragmentClient( api_key: str, cookies: dict[str, Any] | str, wallet_version: str = "V5R1", + api_provider: str = "tonapi", timeout: float = 30.0, ) ``` ## Parameters -- `seed`: wallet mnemonic (**12, 18, or 24 words**) -- `api_key`: Tonapi key from https://tonconsole.com +- `seed`: wallet mnemonic (**12 or 24 words**) +- `api_key`: API key — from [tonconsole.com](https://tonconsole.com) (tonapi) or [@toncenter](https://t.me/toncenter) - `cookies`: Fragment cookies as a dictionary or JSON string -- `wallet_version`: `"V4R2"` or `"V5R1"` +- `wallet_version`: `"V4R2"`, `"V5R1"`, `"HighloadV2"`, or `"HighloadV3R1"` +- `api_provider`: blockchain API provider — `"tonapi"` (default) or `"toncenter"` - `timeout`: request timeout in seconds -**If `api_key` is too short or cookies are incomplete, initialization fails immediately.** +**If `api_key` or cookies are missing, initialization fails immediately.** ## Required cookies @@ -34,26 +36,34 @@ FragmentClient( ```python from pyfragment import FragmentClient -client = FragmentClient( +async with FragmentClient( seed="word1 word2 ... word24", - api_key="YOUR_TONAPI_KEY", + api_key="YOUR_API_KEY", cookies={ "stel_ssid": "...", "stel_dt": "...", "stel_token": "...", "stel_ton_token": "...", }, -) -``` - -Use it inside async context manager: - -```python -async with client: +) as client: wallet = await client.get_wallet() ``` -You can also create the client directly inside `async with` if you prefer one-block setup. +## Switching API provider + +By default, the library uses [tonconsole.com](https://tonconsole.com) (tonapi). To use [toncenter](https://t.me/toncenter) instead, pass `api_provider="toncenter"`: + +```python +async with FragmentClient( + seed="...", + api_key="YOUR_TONCENTER_API_KEY", + cookies={...}, + api_provider="toncenter", +) as client: + ... +``` + +Both providers work identically — the correct `tonutils` client is selected automatically based on `api_provider`. ## Validation behavior @@ -62,8 +72,7 @@ At initialization, library validates: - seed format, - cookie shape and required keys, - supported wallet version, +- supported API provider, - 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 index 97abbc1..13c742d 100644 --- a/docs/getting-started/credentials-and-cookies.md +++ b/docs/getting-started/credentials-and-cookies.md @@ -8,7 +8,7 @@ Generate an API key at https://tonconsole.com. ## Seed phrase -Use your TON wallet mnemonic. +Use your GRAM (ex TON) wallet mnemonic. - **Keep it private.** - **Never log it or commit it to git.** diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index fa8d816..139b895 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -6,21 +6,33 @@ Use this minimal example to verify that your credentials, cookies, and wallet se import asyncio from pyfragment import FragmentClient +from pyfragment.enums import PaymentMethod async def main() -> None: async with FragmentClient( seed="word1 word2 ... word24", - api_key="YOUR_TONAPI_KEY", + api_key="YOUR_API_KEY", # tonconsole.com (tonapi, default) or t.me/toncenter cookies={ "stel_ssid": "...", "stel_dt": "...", "stel_token": "...", "stel_ton_token": "...", }, + wallet_version="V5R1", # or "V4R2", "HighloadV2", "HighloadV3R1" + api_provider="tonapi", # or "toncenter" ) as client: wallet = await client.get_wallet() - print(wallet) + print(f"GRAM: {wallet.gram_balance} | USDT: {wallet.usdt_balance}") + + recipient = "https://t.me/username" # also: @username, username + + 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}") + + premium = await client.purchase_premium(recipient, months=6, payment_method=PaymentMethod.GRAM) + print(f"Sent Premium {premium.amount}m to {premium.username} | tx: {premium.transaction_id}") + asyncio.run(main()) ``` diff --git a/docs/reference/errors.md b/docs/reference/errors.md index 80a7e2d..c7fe129 100644 --- a/docs/reference/errors.md +++ b/docs/reference/errors.md @@ -11,6 +11,7 @@ Good error handling is the difference between a stable integration and random pr - `FragmentAPIError` - `FragmentPageError` - `UserNotFoundError` + - `AlreadySubscribedError` - `AnonymousNumberError` - `TransactionError` - `ParseError` @@ -44,7 +45,9 @@ except FragmentError: ## Method-to-error mapping -- Stars/Premium purchase and giveaway: `ConfigurationError`, `UserNotFoundError`, `WalletError`, `VerificationError` +- Stars purchase: `ConfigurationError`, `UserNotFoundError`, `WalletError`, `VerificationError` +- Premium purchase: `ConfigurationError`, `UserNotFoundError`, `AlreadySubscribedError`, `WalletError`, `VerificationError` +- Stars/Premium giveaway: `ConfigurationError`, `UserNotFoundError`, `WalletError`, `VerificationError` - Ads operations: `ConfigurationError`, `UserNotFoundError`, `WalletError`, `VerificationError` - Cookies/auth setup: `CookieError`, `ConfigurationError`, `FragmentPageError` diff --git a/docs/reference/literals.md b/docs/reference/literals.md index 01eee5e..48dfcd2 100644 --- a/docs/reference/literals.md +++ b/docs/reference/literals.md @@ -2,22 +2,52 @@ These literals describe accepted string values for key method parameters. +## ApiProvider + +```python +from pyfragment.enums import ApiProvider + +ApiProvider.TONAPI # tonconsole.com — default +ApiProvider.TONCENTER # t.me/toncenter +``` + +Pass as string to `FragmentClient(api_provider=...)`: + +```python +FragmentClient(..., api_provider="tonapi") # default +FragmentClient(..., api_provider="toncenter") +``` + ## PaymentMethod ```python -PaymentMethod = Literal["ton", "usdt_ton"] +from pyfragment.enums import PaymentMethod + +PaymentMethod.GRAM # GRAM (ex TON) — default +PaymentMethod.USDT_GRAM # USDT on GRAM (ex TON) +PaymentMethod.USDT_ETH # USDT on Ethereum +PaymentMethod.USDT_POL # USDT on Polygon +PaymentMethod.USDC_ETH # USDC on Ethereum +PaymentMethod.USDC_BASE # USDC on Base +PaymentMethod.USDC_POL # USDC on Polygon ``` ## WalletVersion ```python -WalletVersion = Literal["V4R2", "V5R1"] +from pyfragment.enums import WalletVersion + +WalletVersion.V5R1 # default +WalletVersion.V4R2 +WalletVersion.HighloadV2 +WalletVersion.HighloadV3R1 ``` -These literals are exported from `pyfragment` (top-level), `pyfragment.models`, and `pyfragment.models.enums`. +All enums are exported from both `pyfragment` (top-level) and `pyfragment.enums`. ## Usage notes +- Use `ApiProvider` when configuring the blockchain API provider in `FragmentClient`. - Use `PaymentMethod` for purchase and giveaway operations. - Use `WalletVersion` when configuring `FragmentClient`. diff --git a/docs/reference/models.md b/docs/reference/models.md index 622b0d4..3d7c740 100644 --- a/docs/reference/models.md +++ b/docs/reference/models.md @@ -11,7 +11,7 @@ Exported result models: - `AdsRechargeResult(transaction_id, amount)` - `StarsGiveawayResult(transaction_id, channel, winners, amount)` - `PremiumGiveawayResult(transaction_id, channel, winners, amount)` -- `WalletInfo(address, state, ton_balance, usdt_balance)` +- `WalletInfo(address, state, gram_balance, usdt_balance)` - `LoginCodeResult(number, code, active_sessions)` - `TerminateSessionsResult(number, message)` - `UsernamesResult(items, next_offset_id)` @@ -26,7 +26,7 @@ Most high-level methods return one of these dataclasses. - `purchase_premium()`: `PremiumResult` - `giveaway_stars()`: `StarsGiveawayResult` - `giveaway_premium()`: `PremiumGiveawayResult` -- `topup_ton()`: `AdsTopupResult` +- `topup_gram()`: `AdsTopupResult` - `recharge_ads()`: `AdsRechargeResult` - `get_wallet()`: `WalletInfo` - `get_login_code()`: `LoginCodeResult`