Solana/SPL Token/Minting Tokens and Querying Balances
In this lesson, we'll talk about minting tokens.
Minting Tokens and Querying Balances
You can easily mint additional tokens for any user with a simple piece of code. Note: only the token creator has the authority to mint new tokens!
The amount minted via the spl_mint() method must take into account the decimal places. For example, if decimals=9, then 1000000000 represents 1 full token.
Likewise, when querying your token balance using the spl_balance() method, the function returns an array: the first element is the token amount you hold, and the second is the token's decimal precision.
import pxsol
ada = pxsol.wallet.Wallet(pxsol.core.PriKey.int_decode(1))
spl = pxsol.core.PubKey.base58_decode('2CMXJX8arHRsiiZadVheRLTd6uhP7DpbaJ9hRiRMSGcF')
ada.spl_mint(spl, ada.pubkey, 100000000 * 10 ** 9)
print(ada.spl_balance(spl)) # [100000000000000000, 9]
Associated Token Account
Just like the Thai Baht Coin program we previously wrote, your tokens are essentially stored in a PDA account. This account is commonly referred to as an Associated Token Account (ATA), a special account for holding and managing SPL tokens on behalf of a user.
- Each ATA uniquely corresponds to a wallet address and a token's mint address.
- It is programmatically generated following deterministic rules, ensuring the same wallet-token pair always derives the same ATA address.
- It stores the token balance of a user.
When you use the spl_mint() method from Pxsol to mint tokens, Pxsol will automatically create an ATA for the recipient if it doesn't already exist.
Let's use the RPC interface to query the data stored in an ATA and inspect the result.
import base64
import pxsol
ada = pxsol.wallet.Wallet(pxsol.core.PriKey.int_decode(1))
spl = pxsol.core.PubKey.base58_decode('2CMXJX8arHRsiiZadVheRLTd6uhP7DpbaJ9hRiRMSGcF')
ata = ada.spl_account(spl)
info = pxsol.rpc.get_account_info(ata.base58(), {})
data = base64.b64decode(info['data'][0])
print(data.hex())
The returned data is 170 bytes in length. Here's a breakdown of the contents:
11c447d79a76ef38a896d72fe54b373bab14dcba868425645a1670180e656780 Token Mint Address
4cb5abf6ad79fbf5abbccafcc269d85cd2651ed4b885b5869f241aedf0a5ba29 User Wallet Address
00008a5d78456301 Balance in little-endian, equals 100000000 * 10 ** 9
00000000 Delegate flag: 0 = no delegate set
0000000000000000000000000000000000000000000000000000000000000000 Delegate Address
01 Account state (1 = initialized)
00000000 Native token flag: 0 = non-native (expected)
0000000000000000 Rent exemption amount (if native)
0000000000000000 Delegated amount
00000000 Close authority flag
0000000000000000000000000000000000000000000000000000000000000000 Close authority address
02 Account type (2 = token account)
0700 Token extension (7 = immutable ownership)
0000 Token extension (padding, unused)
You can refer to the following source links to deepen your understanding of associated token accounts:
In most scenarios, we only care about the first three fields: the token mint address, the user's wallet address, and the token balance.
Exercise
Q: Is Bob allowed to mint new tokens? Try it with code.
A: No, he can't.
import pxsol
bob = pxsol.wallet.Wallet(pxsol.core.PriKey.int_decode(2))
spl = pxsol.core.PubKey.base58_decode('2CMXJX8arHRsiiZadVheRLTd6uhP7DpbaJ9hRiRMSGcF')
bob.spl_mint(spl, bob.pubkey, 100000000 * 10 ** 9)
# Exception: {
# 'code': -32002,
# 'message': 'Transaction simulation failed: Attempt to debit an account but found no record of a prior credit.',
# 'data': {
# 'accounts': None,
# 'err': 'AccountNotFound',
# 'innerInstructions': None,
# 'logs': [],
# 'replacementBlockhash': None,
# 'returnData': None,
# 'unitsConsumed': 0
# }
# }