tonutils library. It covers key operations such as:
- Creating and deploying wallets
- Importing wallets from mnemonic or private key
- Reading on-chain wallet information
- Sending transactions (TON, NFTs, jettons)
- Performing batch and sequential transfers
- Sending gasless (relayed) jetton transfers
- Encrypting and decrypting on-chain messages
Supported Wallets
The library supports multiple wallet versions and types, all importable fromtonutils.contracts:
Create Wallet
To create a new wallet, use the.create() classmethod of the wallet class you select. It returns a 4-tuple: the wallet instance, its public key, private key, and a freshly generated mnemonic phrase. Each wallet class takes an optional config= argument (WalletV4Config, WalletV5Config, etc. from ton_core), where you can customize subwallet_id to derive multiple wallets from the same mnemonic.
To use a different wallet version, swap the class and its config together: for example
WalletV5R1 with WalletV5Config, or WalletHighloadV3R1 with WalletHighloadV3Config. Configs are imported from ton_core.Import Wallet
You can import a wallet either from a mnemonic phrase or directly from a private key.from_mnemonic() returns the same 4-tuple as .create(); from_private_key() returns only the wallet instance.
From Mnemonic
Mnemonics can be 24 words (TON-native) or 12/18/24 words (BIP-39 import).From Private Key
PrivateKey from ton_core accepts the key in multiple formats: raw bytes, a hex string, a base64 string, or an integer.
Deploy Wallet
Wallets deploy automatically on their first outgoing transaction. To deploy explicitly, reconstruct the wallet from a mnemonic and send a small amount to its own address — after the transaction, the wallet transitions fromuninit to active status.
wallet.transfer(...) returns an ExternalMessage. Its normalized_hash is computed locally before sending — it is not the on-chain transaction hash. Use it to track whether the message was accepted on-chain via explorers or API queries.Wallet Information
To inspect a wallet without signing anything, initialize it from an address with.from_address() (read-only mode). Call await wallet.refresh() to fetch the latest on-chain state before reading properties.
Transfers
Send TON
Usewallet.transfer() to send TON with an optional text comment.
destination— recipient address (Address).amount— amount in nanotons; useto_nano()to convert from TON (int).body— optional text comment, visible in explorers and the recipient wallet (strorCell).
Send NFT
NFT transfers useNFTTransferBuilder with wallet.transfer_message(). The sending wallet must be the current owner of the NFT.
destination— new owner address (Address).nft_address— NFT item contract address (Address).forward_payload— optional message forwarded to the new owner, visible in the notification (strorCell).forward_amount— nanotons sent to the new owner with theownership_assignednotification (TEP-62); must be greater than 0 to trigger the notification (int).amount— TON attached to the NFT item for gas fees; 0.05 TON is typically sufficient, increase it ifforward_amountis higher (int).
Send Jetton
Jetton transfers useJettonTransferBuilder with wallet.transfer_message(). The wallet must hold a jetton balance in its jetton wallet.
destination— recipient address that receives the jettons (Address).jetton_amount— amount in base units, respecting the token’s decimals (int).jetton_master_address— jetton master contract address identifying the token (Address).forward_payload— optional message forwarded to the recipient, visible in the notification (strorCell).forward_amount— nanotons sent to the recipient with thetransfer_notification(TEP-74); must be greater than 0 to trigger the notification (int).amount— TON attached to the jetton wallet for gas fees; 0.05 TON is typically sufficient (int).
Jetton amounts respect the token’s decimals, which are not always 9. For USDT-like jettons with 6 decimals, convert with
to_nano(1, decimals=6).Batch Transfers
Send multiple transfers in a single transaction by passing a list of builders towallet.batch_transfer_message(). You can mix TONTransferBuilder, NFTTransferBuilder, and JettonTransferBuilder in one batch.
Message limits per wallet version are listed in Supported Wallets; exceeding the limit raises an error.
Sequential Transfers
Standard wallets reject a transaction whose seqno has already been used. If you send several transfers in quick succession, the second one can reuse the same on-chain seqno and fail. Wrap the wallet inSeqnoGuard to send safely in sequence — it waits for the on-chain seqno to advance after each send before allowing the next.
Gasless Transfers
Gasless transfers let a wallet send jettons without holding TON for gas: a relay pays the TON fees, and its commission is deducted from the sender’s jetton balance. The flow is two steps —gasless_estimate() to build and price the transfer, then gasless_send() to sign and relay it.
Gasless transfers require TonapiClient on mainnet and are only available for WalletV5 (WalletV5R1 and WalletV5Beta).
A Tonapi API key is required — get one at tonconsole.com. Always review
estimate.commission, estimate.valid_until, and the emulation result before calling gasless_send(); once sent, the transaction is irreversible.Encrypted Messages
The library supports end-to-end encrypted comments using elliptic curve Diffie-Hellman (ECDH): only the sender and the recipient can decrypt the message.Encrypt
Fetch the recipient’s public key withget_public_key_get_method(), encrypt the text with TextCipher.encrypt(), and send the resulting body with a regular transfer. The recipient’s wallet must be deployed (active state) and expose the get_public_key get-method.
payload— plaintext message to encrypt (str).sender_address— sender’s address, used as a salt for message-key derivation and verification; the recipient must pass the same address to decrypt (Address).our_private_key— sender’s private key for ECDH (PrivateKey).their_public_key— recipient’s public key for ECDH (PublicKey).
Decrypt
Decrypt an incoming encrypted comment withTextCipher.decrypt(). The sender’s public key is recovered from the encrypted payload (it is stored XORed with the recipient’s public key), so only the sender’s address and the recipient’s private key are needed.
payload— encrypted message asbytes, hex string, base64 string (cipher text only), or aCellcontaining the opcode0x2167DA4Band cipher text.sender_address— original sender’s address, used for verification (Address).our_private_key— recipient’s private key for ECDH decryption (PrivateKey).
Wallet Examples
Full runnable wallet example scripts on GitHub.