SINAI STANDARD

ConfidentialTransferManager

Manage Token-2022 Confidential Transfers — privacy-preserving encrypted balances and transfers with auditor access

Overview

ConfidentialTransferManager wraps Token-2022's native Confidential Transfer extension. No custom on-chain program is needed — all operations use the standard Token-2022 program directly.

Balances are encrypted on-chain using ElGamal encryption. Only the account owner (and an optional auditor) can decrypt them. Transfers use zero-knowledge proofs to validate correctness without revealing amounts.

Import

import {
  ConfidentialTransferManager,
  generateElGamalKeypair,
  createAuditorKeypair,
} from "@sinai-standard/sdk";
 
const ctm = new ConfidentialTransferManager(connection, payer, mint);

Constructor

ParameterTypeDescription
connectionConnectionSolana RPC connection
payerKeypairFee payer for transactions
mintPublicKeyToken mint address

Methods

initializeMintForConfidential(mintKeypair, decimals, authority?, auditorElGamalPubkey?)

Creates a new Token-2022 mint with the ConfidentialTransferMint extension enabled. Auto-approves new accounts by default.

ParameterTypeDescription
mintKeypairKeypairKeypair for the new mint account
decimalsnumberToken decimal places
authorityPublicKey (optional)Mint authority (defaults to payer)
auditorElGamalPubkeyUint8Array (optional)Auditor's ElGamal public key for regulatory decryption
const mintKeypair = Keypair.generate();
const auditor = createAuditorKeypair();
 
await ctm.initializeMintForConfidential(
  mintKeypair,
  6,
  issuer.publicKey,
  auditor.publicKey // Auditor can decrypt all transfers
);

configureAccount(owner, account, elGamalPubkey)

Enables confidential transfers on a token account by initializing the ConfidentialTransferAccount extension with the owner's ElGamal public key.

ParameterTypeDescription
ownerKeypairAccount owner
accountPublicKeyToken account address
elGamalPubkeyUint8ArrayOwner's ElGamal public key
const ownerKeys = generateElGamalKeypair();
await ctm.configureAccount(owner, ownerTokenAccount, ownerKeys.publicKey);

deposit(owner, account, amount, decimals)

Moves tokens from the public balance into the confidential (pending) balance. Call applyPendingBalance() afterward to make funds available for confidential transfers.

ParameterTypeDescription
ownerKeypairAccount owner
accountPublicKeyToken account address
amountnumber | bigintAmount to deposit
decimalsnumberToken decimal places
await ctm.deposit(owner, ownerTokenAccount, 1_000_000, 6);
await ctm.applyPendingBalance(owner, ownerTokenAccount);

withdraw(owner, account, amount, decimals, newDecryptableBalance?, proofInstructionOffset?)

Withdraws from the confidential balance back to the public balance. Requires a ZK range proof.

ParameterTypeDescription
ownerKeypairAccount owner
accountPublicKeyToken account address
amountnumber | bigintAmount to withdraw
decimalsnumberToken decimal places
newDecryptableBalanceUint8Array (optional)Updated decryptable balance ciphertext
proofInstructionOffsetnumber (optional)Offset to ZK proof instruction
await ctm.withdraw(owner, ownerTokenAccount, 500_000, 6);

confidentialTransfer(owner, sourceAccount, destAccount, amount, decimals, newSourceDecryptableBalance?, proofInstructionOffset?)

Performs an encrypted transfer between two confidential-enabled accounts. The transfer amount is hidden on-chain — only the sender, receiver, and auditor can see it.

ParameterTypeDescription
ownerKeypairSource account owner
sourceAccountPublicKeySource token account
destAccountPublicKeyDestination token account
amountnumber | bigintAmount to transfer
decimalsnumberToken decimal places
newSourceDecryptableBalanceUint8Array (optional)Updated source decryptable balance
proofInstructionOffsetnumber (optional)Offset to ZK proof instruction
await ctm.confidentialTransfer(
  sender,
  senderTokenAccount,
  receiverTokenAccount,
  100_000,
  6
);

applyPendingBalance(owner, account, newDecryptableBalance?, expectedPendingCreditCounter?)

Applies pending incoming confidential balance to the available balance. Must be called after receiving a confidential transfer or deposit before funds can be used.

ParameterTypeDescription
ownerKeypairAccount owner
accountPublicKeyToken account address
newDecryptableBalanceUint8Array (optional)Updated decryptable balance
expectedPendingCreditCounterbigint (optional)Expected pending credit counter
// After receiving a deposit or transfer
await ctm.applyPendingBalance(owner, ownerTokenAccount);

getConfidentialBalance(account)

Reads the confidential balance state for a token account. Returns credit counters as balance activity indicators. Full decryption of encrypted balances requires the account owner's ElGamal secret key.

const balance = await ctm.getConfidentialBalance(ownerTokenAccount);
console.log("Pending:", balance.pending);
console.log("Available:", balance.available);

ElGamal Key Helpers

generateElGamalKeypair()

Generates an ElGamal keypair for use with confidential transfers. The 32-byte public key serves as the ElGamal public key for the Token-2022 extension.

import { generateElGamalKeypair } from "@sinai-standard/sdk";
 
const keys = generateElGamalKeypair();
// keys.publicKey  — 32-byte Uint8Array
// keys.secretKey  — 64-byte Uint8Array

createAuditorKeypair()

Creates an auditor ElGamal keypair. The auditor can decrypt all confidential transfers for compliance and regulatory purposes.

import { createAuditorKeypair } from "@sinai-standard/sdk";
 
const auditor = createAuditorKeypair();
// Store auditor.secretKey securely — it can decrypt all transfer amounts

Balance Lifecycle

Public Balance ──deposit()──▶ Pending Balance ──applyPendingBalance()──▶ Available Balance
       ▲                                                                        │
       └────────────────────withdraw()◀─────────────────────────────────────────┘

                                   confidentialTransfer()


                                    Dest Pending Balance
  1. Deposit — moves public tokens into pending confidential balance
  2. Apply — makes pending balance available for confidential transfers
  3. Transfer — sends encrypted amount to destination's pending balance
  4. Withdraw — moves confidential balance back to public balance