Skip to main content

faportalsmp

Asynchronous Python library for the Portals Gift Marketplace API.

A maintained fork of aportalsmp — trade Telegram gifts (NFTs), place and manage offers, run giveaways, read your account, and deposit & withdraw GRAM.

pip install faportalsmp

Imported as aportalsmp:

import aportalsmp as portals

Quick start

import asyncio
import aportalsmp as portals

AUTH = "tma query_id=...&user=...&auth_date=...&hash=..."  # see Authentication

async def main():
    floors = await portals.giftsFloors(authData=AUTH)
    print("Plush Pepe floor:", floors.floor("plushpepe"))

    listings = await portals.search(gift_name="Plush Pepe", sort="price_asc", limit=5, authData=AUTH)
    for gift in listings:
        print(gift.name, gift.model, gift.price)

    balances = await portals.myBalances(authData=AUTH)
    print("Balance:", balances.balance, "GRAM")

asyncio.run(main())

Authentication

Every request needs authData — a Telegram Mini App initData string prefixed with tma . Generate it from a Telegram user session with update_auth():

from aportalsmp import update_auth

# with api_id / api_hash (creates a .session file)
authData = await update_auth(api_id=12345, api_hash="abc...", session_name="account")

# or from an existing Pyrogram/Kurigram session string
authData = await update_auth(session_string="BQ...")

Wallet — GRAM deposits & withdrawals

GRAM is the native coin (moved on the TON network). Amounts and balances are in GRAM; addresses and the on-chain transfer use the TON network.

Balance, limits & history

bal    = await portals.myBalances(authData=AUTH)     # .balance, .frozen_funds
limits = await portals.walletLimits(authData=AUTH)   # .min_deposit, .min_withdraw, .max_withdraw, .daily_limit
hist   = await portals.walletHistory(offset=0, limit=20, authData=AUTH)

Deposit GRAM

A deposit is a native GRAM transfer to the Portals deposit wallet carrying a text comment equal to the deposit id — that's how the marketplace credits your balance.

Intent — send it yourself (from any wallet/bot):

info = await portals.deposit(authData=AUTH)
print(info.address)   # where to send GRAM
print(info.comment)   # text comment to attach (the deposit id)
print(info.amount)    # expected amount, if provided

Auto-send — the library signs & broadcasts for you (needs a wallet mnemonic):

info = await portals.deposit(
    amount=0.5,
    mnemonic="word1 word2 ... word24",   # used only to sign, never transmitted
    wallet_version="v4r2",                # v4r2 (default), v3r2, v3r1, v5r1
    authData=AUTH,
)
print(info.sent_tx)   # {'status': 'sent', 'amount': 0.5, 'to': ..., 'comment': ...}

statuses = await portals.depositStatus(ids=info.id, authData=AUTH)

Withdraw GRAM

withdrawal_id = await portals.withdrawGram(amount=1.0, wallet="UQ...external_address", authData=AUTH)
statuses = await portals.withdrawStatus(ids=withdrawal_id, authData=AUTH)

withdrawPortals and withdrawTon are kept as aliases of withdrawGram.


Gifts

Function Purpose
giftsFloors(authData) Floor prices for every collection (by short name)
filterFloors(gift_name, authData) Model / backdrop / symbol floors for a collection
collections(limit, authData) Collections with floor, supply, volume
search(...) Search listings with filters & sorting
marketActivity(...) Recent buys / listings / offers / price updates
myPortalsGifts(offset, limit, listed, authData) Your owned gifts
myActivity(offset, limit, authData) Your activity
buy(nft_id, price, authData) Buy a listing
sale(nft_id, price, authData) / bulkList(nfts, authData) List gift(s) for sale
changePrice(nft_id, price, authData) Re-price a listing
transferGifts(nft_ids, username, anonymous, authData) Transfer gifts to a user
withdrawGifts(nft_ids, authData) Withdraw gifts out of the marketplace
getGiveaways / giveawayInfo / joinGiveaway Giveaways
gifts = await portals.search(
    gift_name="Plush Pepe",
    model="Sad Cat",
    backdrop=["Onyx Black", "Midnight Blue"],
    sort="price_asc", min_price=0, max_price=5000, limit=20,
    authData=AUTH,
)
if gifts:
    result = await portals.buy(nft_id=gifts[0].id, price=gifts[0].price, authData=AUTH)

Gift names resolve leniently — "plush pepe", "Durov's Cap" and "Durov’s Cap" all work.


Offers

await portals.makeOffer(nft_id="...", offer_price=10, expiration_days=7, authData=AUTH)
await portals.editOffer(offer_id="...", new_price=12, authData=AUTH)
await portals.cancelOffer(offer_id="...", authData=AUTH)

await portals.collectionOffer(gift_name="Plush Pepe", amount=100, max_nfts=3, authData=AUTH)
top = await portals.topOffer(gift_name="Plush Pepe", authData=AUTH)

received = await portals.myReceivedOffers(authData=AUTH)
placed   = await portals.myPlacedOffers(authData=AUTH)

Keeping the gift list fresh

Collection IDs live in aportalsmp/utils/collections_ids.py and are generated from the public /collections endpoint. When new gifts drop, regenerate them:

python scripts/update_collections.py

Data objects

Every response is wrapped in a lightweight object with typed properties and a .toDict() escape hatch:

PortalsGift, CollectionOffer, GiftOffer, Points, Stats, Balances, DepositInfo, DepositStatus, WithdrawStatus, WalletLimits, WalletHistory, Filters, GiftsFloors, Collections, Activity, MyActivity, SaleResult, Giveaway, GiveawayRequirements, …


Errors

All errors subclass Exception and live in aportalsmp:

authDataError, offerError, accountError, requestError, connectionError, floorsError, giftsError, tradingError.

from aportalsmp import requestError

try:
    await portals.buy(nft_id="...", price=1.0, authData=AUTH)
except requestError as e:
    print("API error:", e)

Disclaimer

Unofficial library — not affiliated with Portals. Trading and GRAM transfers move real assets; test with small amounts first and keep your mnemonics safe. Use at your own risk.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

faportalsmp-2.0.0.tar.gz (31.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

faportalsmp-2.0.0-py3-none-any.whl (27.9 kB view details)

Uploaded Python 3

File details

Details for the file faportalsmp-2.0.0.tar.gz.

File metadata

  • Download URL: faportalsmp-2.0.0.tar.gz
  • Upload date:
  • Size: 31.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for faportalsmp-2.0.0.tar.gz
Algorithm Hash digest
SHA256 a98684a225547a92f18b978400f599b9f2739022d4994d9e386dbbd3939f245f
MD5 61c6a738c2d3bac8452b29e4de15b54a
BLAKE2b-256 08be5675b664de6db6b53f886f4dba6c707d3e67c8ee7e938098522e3ddc2eff

See more details on using hashes here.

File details

Details for the file faportalsmp-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: faportalsmp-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 27.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for faportalsmp-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 846c239345db52098cd3f35b1f85f03119db6f0335ea8fe0b1641337cff199b5
MD5 31fd0ec61ea5241f73663c7259ba6e58
BLAKE2b-256 054c1047b998352343455257b68fa8bd9e83836ef4f525a05aa6f2e69851a2c2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page