Files

4.7 KiB

Context

The current SPL transfer flow separates responsibilities cleanly: SolanaBlockChain serializes unsigned low-level transactions, while SolanaWallet resolves mint and holding state, validates human-readable amounts, signs, and submits. The transaction serializer already supports legacy-message account ordering, compact-u16 encoding, recent blockhash metadata, and selecting either supported SPL token program.

Goals / Non-Goals

Goals:

  • Extend the existing API/implementation boundary with checked SPL-token burning.
  • Keep all state-dependent ownership and balance checks in the wallet and all wire serialization in the blockchain implementation.
  • Use identical behavior for the original SPL Token Program and Token-2022 except for the selected program address.
  • Preserve the existing submission-only signing flow.

Non-Goals:

  • Confirmation awaiting, retry, account closure, rent recovery, multisignatures, delegates, or permanent delegates.
  • Native or wrapped SOL burning, a burn-all convenience API, or integration with Evelyn and Discord.
  • New ValueTags, configuration, dependencies, tests, or changes to unrelated consumers.

Decisions

Mirror the existing transfer responsibility split

The wallet will reuse its existing mint-program detection, supply loading, holding lookup, decimal consistency checks, exact decimal conversion, and signAndSendTransaction() flow. The blockchain method accepts already-resolved raw units and program identity and only validates/serializes those low-level inputs.

Moving state lookup into the transaction builder was rejected because it would duplicate wallet policy and blur the existing API boundary. Building the transaction directly in the wallet was rejected because low-level Solana serialization belongs to SolanaBlockChain.

Encode one standard BurnChecked instruction

The unsigned legacy transaction will contain four account keys in privilege order: owner as writable signer/fee payer, token account and mint as writable unsigned accounts, and the selected token program as read-only unsigned. Its one compiled instruction will invoke program index 3 with account indexes token account, mint, owner and data consisting of the BurnChecked discriminator, little-endian unsigned-u64 amount bits, and unsigned-byte decimals. The message declares one required signature, zero read-only signed accounts, and one read-only unsigned account.

This follows the repository's current TransferChecked serializer instead of introducing a transaction framework or external dependency. Although Java long is signed, a validated unsigned-u64 BigInteger is serialized through its low 64 bits with longValue(), preserving the complete bit pattern.

Validate all local builder inputs before RPC access

The builder will parse and range-check the raw amount, range-check decimals, require a non-null supported enum program, and decode all supplied addresses before requesting a recent blockhash. This keeps invalid input deterministic and avoids unnecessary RPC traffic. The same shared address decoder used by existing transaction builders provides Base58 and 32-byte validation.

Treat complete-balance burn as an ordinary amount

Wallet balance validation rejects only raw amounts greater than the holding, so equality is deliberately allowed. No close instruction is appended; the token account remains open with a zero balance.

Delegate construction through the cache boundary

CachedSolanaBlockChain will forward the call directly because each build requires a fresh recent blockhash. Caching or deduplicating transaction construction could return stale blockhashes and is therefore unsafe.

Risks / Trade-offs

  • [Hand-written Solana wire encoding can be sensitive to account ordering and instruction discriminators] → Mirror the existing compiled-instruction serializer and use the standard BurnChecked layout with explicit constants.
  • [Unsigned-u64 values above signed-long maximum appear negative as Java longs] → Validate with BigInteger first and serialize the low 64-bit two's-complement representation in little-endian order.
  • [Submission success does not establish on-chain burn success] → Keep the API explicitly submission-only; callers may separately await the returned signature when their domain policy requires it.
  • [Mint and holding state can change between validation and execution] → Let Solana's checked instruction and runtime enforce final state; do not retry automatically.

Migration Plan

Add the API methods, implementations, and direct cached delegation in one source-compatible change. Existing callers need no migration because the new methods are additive. Rollback removes those additions; no data or configuration migration is involved.