The supra-python-sdk provides a seamless interface for interacting with the Supra-L1 network. It offers comprehensive support for move-vm operations and transactions, enabling developers to both query on-chain data and submit move-vm based transactions with ease.
- Python 3.12+ support
python -m pip install supra-sdkThe SDK is tested against Supra node supra_node_v11.7.2 (Mainnet and Testnet) and supra_node_v12.0.0.rc7 (Devnet).
It calls /rpc/v3 only.
These need a node from supra_node_v12.0.0. On a supra_node_v11.7.2 node they behave as described:
| Method or parameter | On a supra_node_v11.7.2 node |
|---|---|
account_history, iter_account_history |
The node answers HTTP 404 with an empty body, raised as ApiNotFoundError with the message Not Found. |
The settlement value of transaction_type (account_coin_transactions, account_fa_transactions and their iterators) |
The node rejects it as an unknown type. |
version(): the release field |
The key is absent from the response of every v11 release and of supra_node_v12.0.0.rc1 to rc6; it is present from supra_node_v12.0.0.rc7. |
sequence_number=0 for a sender without an account (SupraClient.create_fee_payer_transaction) |
The SDK builds and returns the signed transaction, and the node refuses its submission (HTTP 400, "Transaction validation failed: Failed to read the AccountResource"). |
Other behaviour that differs by node release is described in the sections below and in the docstrings:
- Where an account holds SUPRA, and which method lists its movements: SUPRA as a fungible asset
and Listing an account's SUPRA movements. A chain created with features 64
and 65 on (Devnet on
supra_node_v12.0.0) has noCoinStore<SupraCoin>. - How a feed ends (the
Nonecursor, and the cursor"0"of a v11.7.x node on an empty page): SUPRA as a fungible asset,account_coin_transactionsandaccount_history. - The error for a missing account:
ApiNotFoundError(404) on a v12 node,ApiError(400) on an earlier node; see theApiNotFoundErrordocstring and Errors, timeouts and retries.
Check examples section.
A response with a status other than 200 raises ApiError (from supra_sdk.clients), whose message is the node's
error message, status_code the HTTP status, headers the response headers and body the response body. These
statuses raise a subclass of ApiError:
| Status | Class | Extra attribute |
|---|---|---|
| 404 | ApiNotFoundError |
|
| 408 | ApiRequestTimeoutError |
|
| 410 | ApiGoneError |
oldest_block, from the x-supra-oldest-block header |
| 429 | ApiRateLimitError |
retry_after_seconds, from the body or the Retry-After header |
| 503 | ApiServiceUnavailableError |
view() raises UnexpectedResponseError, which is also a KeyError, when a 200 response is not a JSON object with
the result field. faucet() returns None (or raises FaucetRequestNotAcceptedError while waiting) when the
200 response is "TryLater", and raises UnexpectedResponseError when the 200 body is not JSON or its Accepted
field is missing, empty or not a string. A request that exceeds the timeout raises ClientTimeoutError,
which is a httpx.TimeoutException and carries the request as request.
Each phase of a request (connecting, waiting for a pooled connection, writing, reading) is limited to 60 seconds;
timeout changes the limit. GET requests are repeated after a 408, 429 or 503 response or a timeout only when
retry is set. POST requests and the faucet request are never repeated.
from supra_sdk.clients import RetryPolicy
from supra_sdk.clients.rest import SupraClient, SupraClientConfig
client = SupraClient(
"https://rpc-testnet.supra.com",
SupraClientConfig(timeout=30, retry=RetryPolicy(attempts=3, max_delay_seconds=10)),
)SUPRA exists in two forms: a CoinStore balance and a balance in the account's primary fungible store (metadata
address 0xa). A Devnet created with SUPRA as a fungible asset from genesis funds accounts in the fungible store only.
Accounts that still hold a CoinStore balance keep it there until they migrate it.
account_supra_balance/account_coin_balanceread0x1::coin::balance: theCoinStorebalance plus the paired fungible asset balance, so the sum is the same in either form. The fungible asset part is included only while the coin-to-fungible-asset migration feature is enabled and the coin has a paired fungible asset.account_fa_balancereads the fungible store alone (0x1::primary_fungible_store::balance), and is 0 for an account that has only aCoinStorebalance.transfer_fungible_assetdebits the sender's fungible store only.transfer_supra_coinmoves SUPRA held in either form.migrate_coin_to_fungible_storemoves aCoinStorebalance into the fungible store. It is meaningful only for accounts that still hold aCoinStorebalance, and cannot be undone. The framework of v11.7.x nodes writes acoin::MigrationFlagat the store; the v12 framework writes none, and a converted account is one withoutCoinStore<CoinType>.account_fa_transactionslists the transactions of an account's primary fungible store, a page at a time. On Devnet an account's SUPRA movements are listed here and not byaccount_coin_transactions. The returned cursor isNoneat the end of the feed on v11.7.x and v12 nodes (the method reads a v11.7.x node's"0"on an empty page as the end). Stop when the cursor isNone, not on an empty page or on"0": a page filtered bytransaction_typecan be empty and still carry a cursor to continue from, and"0"can be the position of a genesis row.iter_account_fa_transactionstakes the same arguments and follows the cursor until the feed ends.
balance = await client.account_fa_balance(alice.address())
await client.transfer_fungible_asset(alice, bob.address(), 1_000)
transactions, cursor = await client.account_fa_transactions(bob.address())All of them default to SUPRA and take a metadata_address for another fungible asset (migrate_coin_to_fungible_store
takes a coin_type). See examples/fungible_asset.py.
For the function specific documentation, check out the supra-python-sdk reference documentation.
Which method lists them depends on where the account holds SUPRA:
- Coin layout (Mainnet and Testnet accounts created before governance enables feature 64 or 65): SUPRA is in the
account's
CoinStore<SupraCoin>, andaccount_coin_transactionslists its movements. - Primary-store layout: SUPRA is in the account's primary fungible store, and
account_coin_transactionslists none of its movements. While feature 64 or 65 is enabled, registering SUPRA creates the primary store instead of aCoinStore<SupraCoin>, so new accounts hold SUPRA there; so does an account that migrated its SUPRA. On a chain created with features 64 and 65 on, such as Devnet onsupra_node_v12.0.0, no account has aCoinStore<SupraCoin>. Useaccount_historywith the categoryfa(nodes fromsupra_node_v12.0.0) oraccount_fa_transactions. SUPRA transfers emit0x1::fungible_asset::WithdrawandDepositevents, whosestorefield names the fungible store, not the account, and no0x1::coinevents.
history = await client.account_history(address, categories=["fa"])
print(history.entries, history.cursor, history.indexed_from, history.oldest_block)
async for entry in client.iter_account_history(address, categories=["sent", "fa"]):
print(entry["categories"], entry["transaction"]["hash"])
async for transaction in client.iter_account_fa_transactions(address):
print(transaction["hash"])If you found a bug or would like to request a feature, please file an issue. If, based on the discussion on an issue, you would like to offer a code change, please make a pull request.