Send a payment nobody else can read.
Solana Token-2022 confidential transfers, run by @softseco/confidential-transfers inside this page. Nothing to install and no wallet extension: the page makes throwaway devnet keys and keeps them in this browser.
-
1
Get devnet SOL
Your throwaway wallet pays fees and rent. The whole run costs about 0.03 SOL. Devnet SOL is free and worth nothing.
The call
await rpc.requestAirdrop(you.address, lamports(1_000_000_000n)).send(); // faucet refused? get devnet SOL at faucet.solana.com -
2
Create a confidential test dollar
A Token-2022 mint with the confidential-transfer extension and a designated auditor key. You hold the mint authority, so you give yourself 1,000 public test dollars.
The SDK call
// the mint carries ConfidentialTransferMint { auditorElgamalPubkey } const auditorKeypair = await deriveAuditorElgamalKeypair(auditor); const auditorElgamalPubkey = getAuditorElgamalPubkey(auditorKeypair); // then your token account is configured for confidential transfers await configureAccount({ rpc, rpcSubscriptions, payer: you, owner: you, mint }); -
3
Move 100 into your confidential balance
A deposit moves public tokens into a pending confidential balance; applying it makes them spendable. From here on the chain holds only ciphertext for your confidential balance.
The SDK call
await deposit({ rpc, rpcSubscriptions, payer: you, owner: you, mint, amount: 100_000_000n, decimals: 6 }); await applyPendingBalance({ rpc, rpcSubscriptions, payer: you, owner: you, mint }); -
4
Send a confidential transfer
The amount is encrypted three times — to you, to Bob and to the auditor — and zero-knowledge proofs show it is valid without revealing it. Bob needs no SOL: you pay the fees.
The SDK call
const { signatures } = await transfer({ rpc, rpcSubscriptions, payer: you, owner: you, mint, destinationOwner: bob.address, amount: 25_000_000n, auditorElgamalPubkey, }); -
5
See who can read it
Three keys can open the amount. Everyone else sees the addresses and a ciphertext.
The SDK call
await decryptBalance({ rpc, owner: you, mint }); // you await decryptBalance({ rpc, owner: bob, mint }); // Bob await decryptTransferAmountAsAuditor({ rpc, signature, auditorKeypair }); // the auditor -
6
Withdraw back to public
Bob moves what he received from his confidential balance to his public balance, proving he has enough without showing how much he had.
The SDK call
await withdraw({ rpc, rpcSubscriptions, payer: you, owner: bob, mint, amount: 25_000_000n, decimals: 6 }); -
Part 2 · Rules
Private amounts, rules still enforced
The same transfer, on a token with Sentinel as its transfer hook. Token-2022 calls Sentinel on every transfer, confidential ones included, and Sentinel can refuse.
-
7
Put a compliance rule on a new token
A second confidential test dollar with the same auditor, plus a transfer hook. Its policy turns the blocklist on, and a new wallet, Mallory, goes on the list. You get 100 of it in your confidential balance.
The calls
// the mint: TransferHook { programId: SENTINEL } + ConfidentialTransferMint { auditor } // the rules, with @softseco/sentinel from Node await sentinel.initializeExtraAccountMetaList(mint); await sentinel.initializePolicy({ mint, allowlist: false, blocklist: true, maxTransferAmount: 0 }); await sentinel.addToBlocklist(mint, mallory.address); // this page sends the same three instructions, built with @solana/kit -
8
Pay Mallory, then Bob
Sentinel cannot see the amount, but it can see who gets paid. The payment to Mallory is refused by the chain. The same payment to Bob goes through, still encrypted, and the auditor can still read it.
The SDK call
// the same call as in step 4; the SDK finds the hook's accounts itself await transfer({ rpc, rpcSubscriptions, payer: you, owner: you, mint, destinationOwner: mallory.address, amount: 25_000_000n, auditorElgamalPubkey }); // refused: RecipientBlocked await transfer({ rpc, rpcSubscriptions, payer: you, owner: you, mint, destinationOwner: bob.address, amount: 25_000_000n, auditorElgamalPubkey }); // delivered
That was a private payment on a public chain.
Configure, deposit, apply, transfer, decrypt, withdraw, and a rule the chain enforced on a payment nobody else could read. Every step was a real devnet transaction. The same SDK and Sentinel power PAPER on devnet, where identity is also checked at mint and redeem.
Building payments, payroll or treasury on Solana? Tell us what broke: open an issue or write to hello@softseco.com.