Confidential transfers require
dynamic-wallet-sdk version 0.7.0 or later.Overview
Solana’s Token-2022 Confidential Balances extension, also called the confidential transfer extension, keeps token balances and transfer amounts encrypted on chain. Wallet and token account addresses stay public. A token account with the extension enabled holds three balances:
Incoming funds always land in the pending balance. Before you can spend them, you apply the pending balance, which moves it to the available balance. Solana keeps the two apart so that anyone sending you tokens cannot interfere with a transaction you are preparing.
DynamicSvmWalletClient builds, signs, and optionally broadcasts each operation for a Dynamic wallet. The operation names match the Token-2022 instructions, and each one is a single Solana transaction.
amount is a string in the token’s base units, so "1000000" is one token for a mint with 6 decimals. decimals must match the mint.
How it works
Each call tosign_confidential_transfer runs the same steps:
- Read. The SDK reads the token account and the latest blockhash from your Solana RPC endpoint, because the secure enclave that builds the transaction cannot reach the network.
- Build. The enclave builds one unsigned transaction. It holds the Token-2022 instruction and the zero-knowledge proofs that the ZK ElGamal Proof program verifies on chain, and it uses the wallet’s confidential seed to derive the ElGamal keypair and AES key.
- Check. The SDK verifies the transaction before signing. It refuses to sign unless the transaction is a version 1 transaction, uses only the Token-2022, associated token account, System, ZK ElGamal Proof, and Compute Budget programs, has the wallet as its only signer and fee payer, and contains exactly one confidential instruction that matches the operation, mint, token account, destination, amount, and decimals you passed.
- Sign. The SDK signs the transaction with the wallet’s key share in a single signing session.
- Broadcast. If you set
broadcast=True, the SDK submits the transaction and waits for theconfirmedcommitment level.
serializedTransactions (the signed transaction as base64), signatures (its base58 signature), and transactionIds when you broadcast.
Prerequisites
-
The SDK and
solders, which derives token account addresses: -
A Solana wallet funded with SOL. The wallet pays the transaction fee, and
configureAccountalso pays the rent to create and grow the token account. See create a Solana wallet. -
A Token-2022 mint with the Confidential Transfer extension enabled. See Solana’s issuer guide. If the mint does not auto-approve new accounts, its confidential transfer authority must approve each token account after
configureAccount. The SDK does not send that instruction. -
A public balance of the token in the wallet’s associated token account before you
deposit. -
A recipient for
transferwhose token account for the mint has already runconfigureAccount. The transfer fails if the destination token account does not have confidential transfers enabled.
Quick Start
This script creates a wallet and its confidential seed, then runs every operation and reads the decrypted balances. It pauses so that you can fund the new wallet.main(), in the async with block after the steps above. That is where client, wallet_id, address, token_account, and run are defined.
rpc_url falls back to the default_rpc_url you pass to the client constructor. It must use https. The SDK accepts http only for localhost, 127.0.0.1, and ::1.
Operations
Configure a token account
configureAccount enables confidential transfers on the wallet’s associated token account, and creates the account first if it does not exist. Run it for every token account that will send or receive confidential funds, including the recipient’s.
Deposit, apply, transfer, and withdraw
All five operations use the samesign_confidential_transfer call with a different operation name, as in the script above.
- The recipient of a
transferreceives it as a pending balance. The recipient runsapplyPendingBalancebefore they can transfer or withdraw those funds. - Each operation reads the current token account state, so wait for one to confirm before you start the next. With
broadcast=Truethe call returns only after the transaction reachesconfirmed. - Pass the
passwordyou set when you created the wallet. If you hold the wallet’s key shares yourself, pass them askey_sharesinstead. For a wallet that requires multi-factor authentication, passmfa_token.
Read decrypted balances
The pending and available balances are ciphertexts that only the owner’s keys can read.get_confidential_balance decrypts both inside the enclave and returns them as decimal strings in base units. It reads the token account at the confirmed commitment level, so the result includes any operation you have already confirmed.
getTokenAccountBalance JSON-RPC method.
Sign without broadcasting
Leave outbroadcast to get the signed transaction back without submitting it. Submit it yourself, and wait for confirmation before the next operation.
Supply account state yourself
By default the SDK fetches account state and the blockhash fromrpc_url. If you already have them, set account_state, destination_account_state, recent_blockhash, and last_valid_block_height on the options and omit rpc_url. A call that broadcasts still needs an RPC URL. account_state is a dictionary with the keys data, lamports, and owner, where data is the base64 account data and lamports and owner are strings.
Error handling
SDK errors raiseDynamicSDKError.
rpc_url or setting default_rpc_url on the client, and a transaction the SDK refuses to sign because it does not match the request. In the second case, check mint, token_account, amount, and decimals.
Next steps
- Sign SVM transactions
- Create a Solana wallet
- Confidential Balances in the Solana documentation