This file records user-visible changes to Wallet Engine.
create_encrypted_commentandresolve_encrypted_comment_recipientnow treatrecipient_public_keyas a hint for an undeployed recipient. They always read the recipient account state: an active wallet'sget_public_keyanswer is used and a supplied key is ignored, while a nonexistent or uninitialized account uses the supplied key after verifying that it derives the recipient address. A key derived from the address is only the wallet's initial key, so for a wallet that had rotated its key, a supplied key encrypted comments to a replaced key. Supplying a key no longer skips HTTP, andresolve_encrypted_comment_recipientwith a key now takes the single-flight slot.
- Added
detect_mnemonic_schemes, which reports every scheme under which entered recovery words validate:rotation(importable), plus detection-onlyton(passwordless legacy TON mnemonic) andbip39(24-word Multichain mnemonic). Applications use it to explain why an import was rejected; the engine still derives keys only from Rotation mnemonics. - Added
WalletClient::send_bocand platform bindings for durable submission of an already signed external BOC. It validates fresh metadata, shares the transfer journal and single-flight slot, and returns the standardSendResultfor normal pending resolution. - Added
WalletLifecycle::derive_ton_connect_sessionand theTonConnectDerivedSessionobject for MTProto-relayed TON Connect sessions whose X25519 key pair is derived from the wallet's current signing key, the dApp client id, and a server nonce. The object exposes only the session public key and the signing public key, opens the server challenge, validates relayed requests, and encrypts rawnonce || boxreplies with caller-supplied ids; it persists nothing. AppendedSecretAccessReason::DeriveTonConnectSessionKeyandWalletLifecycleError::InvalidTonConnectSessionInput. - Added
WalletClient::resolve_encrypted_comment_recipientand platform bindings. It returns the recipient public keycreate_encrypted_commentwould encrypt for, verifying a supplied key locally and otherwise reading the recipient account state and itsget_public_key, without any protected-secret access, so applications can learn whether a comment can be encrypted before asking for authentication. AppendedWalletClientError::EncryptedCommentLookupFailed. - Added TON Connect
signData(text,binary,cell) to derived sessions. Their connect event now advertisesSignDatabesideSendTransaction, anddecrypt_requestreturns the newTonConnectIncomingRequest::SignDatawith aTonConnectSignDataRequest(TonConnectSignDataPayload) validated against the session wallet.WalletLifecycle::sign_ton_connect_datasigns aTonConnectSignDataSignRequestwith the current signing key and returnsTonConnectSignedData, whichTonConnectDerivedSession::encrypt_sign_data_successanswers with after verifying it with the session's signing key. The domain must be the manifest host, not a URL.encrypt_connect_eventrequireston_addrto advertise the session's signing public key. AppendedSecretAccessReason::SignTonConnectData. - Added recovery of replaced signing keys to
WalletClient::decrypt_comment, so it also decrypts comments sent to signing keys that a key rotation replaced. It tries the current signing key and then the anchor key without any HTTP request; when neither matches on a rotated wallet, it reads the wallet'schange_wallet_keyactions from Toncenter/api/v3/actions(indexer v1.3 or later), recovers each earlier signing key from the encrypted old key its rotation published, and tries those. The protected secret is still read once per call. The public history is cached in memory while it contains the rotation that installed the current signing key, and recovered keys are never returned or stored.EncryptedCommentLookupFailedalso means that the history does not include the current signing key yet and the call can be retried;EncryptedCommentUnavailablemeans that no key of the wallet decrypts the body. The public API is unchanged.
- Breaking:
TonConnectIncomingRequestgainedSignData, andSecretAccessReasongainedDeriveTonConnectSessionKeyandSignTonConnectData. Exhaustive Swiftswitchand Kotlinwhenover them must handle the new cases; native bridge sessions never produceSignData. - Breaking: Moved
prepare_key_rotationfromWalletLifecycletoWalletClient. The request no longer contains a wallet descriptor orseqno; the client uses fresh account state, fetching the getter only for an active contract and using zero plus anchor-basedStateInitbefore deployment. - Breaking: Key-rotation requests (
ChangePublicKeyRequestEandChangePublicKeyRequestI) now carry a second reference after the rotation-proof signature,encryptedOldPrivateKey = sha256(newPrivateKey ‖ "keyChangeSaltV1") XOR oldPrivateKeyover 32-byte Ed25519 seeds, and target the Wallet rev00 revision with bytecode hashe30911420bef1191c09dce58b9df2b4ca4c2d9c383cc3b6a91170349ffa70e2c. That revision publishes the value in a key-changed external-out log (opcode0xEBA19948). Signed rotation BOCs differ from earlier releases. The testnet config param-123and the localnet fixturetests/support/wallet_tg_rev00.codehold this revision. create_encrypted_commentnow encrypts with the wallet's current signing key, the key itsget_public_keyreports, instead of the anchor key. Recipients are unaffected; the sender's own comments sent before a later rotation are decrypted through the key-change history like received ones.
- Wallet rev00 key rotation can be prepared repeatedly. Later rotations are authorized by the current signing half while preserving the anchor half and wallet address.
- Key rotation no longer interprets Toncenter's failed
seqnogetter stack for an undeployed account. It derives sequence number zero from account state and prepares a deployable rotation BOC withStateInit. create_encrypted_commentno longer reports a failed, rate-limited, or cancelled recipient key lookup asEncryptedCommentUnavailable, which told applications the recipient cannot receive encrypted comments; it returnsEncryptedCommentLookupFailed. It reads the recipient account state beforeget_public_key, so an undeployed or frozen wallet is reported as unavailable, and it rejects a getter result with a failed TVM exit code instead of reading its stack as a key.- TON Connect
ton_proofreplies now writeproof.timestampas a JSON number in every session, native bridge and derived alike.@tonconnect/sdkreplaces a proof whose timestamp is a string with an error, so connecting with a proof to a strict dApp failed;ton-connect-corestill accepts a canonical decimal string when it reads a proof. - TON Connect
sendTransactionandsignMessagemessages now use the bounce flag of the destination's user-friendly address, as the TON Connect specification requires, instead of always being non-bounceable. - TON Connect cell
BoCs deeper than 1024 cells, the TVM's maximum cell depth, are now rejected as invalid before the cell tree is built. A few thousand nested cells in asignDatacell or asendTransactionpayload overflowed a 512 KiB thread stack and aborted the process. An indexedBoCwhose header claims more index entries than it carries is rejected before its index is allocated. ton://transferbinpayloads and every otherBocread from text (UniFFI arguments, JSON) now pass the same envelope and depth validation as TON Connect cellBoCs beforeton_coreparses them. A 32-characterbinclaiming 2^32-1 cells madeton_corerequest about 1.2 TB and abort the process on Linux and Windows, a reference past the last cell panicked, and a few thousand nested cells overflowed the stack.- TON Connect cell
BoCs and every engineBocnow reject exotic cells whose layout TON refuses: a pruned branch whose size, level mask or stored depth does not match its data, and library, Merkle proof or Merkle update cells of the wrong size or reference count. A pruned branch shorter than its level mask madeton_corepanic when it hashed the cell, which left asendTransactionpreview's slot taken, so every later preview on that client failed as already in progress. prepare_key_rotationon a nonexistent or uninitialized account now returnsKeyRotationUnavailablefor a post-rotation 24-word phrase, as transfers already did. It signed with words 13-24 while the attachedStateInitdeploys the anchor key, so the contract rejected the request.decrypt_commentno longer fails withEncryptedCommentUnavailablefor a comment encrypted to the current signing key of a rotated wallet. It decrypted only with the anchor key, while senders encrypt to the key the wallet'sget_public_keyreturns, which is the current signing key.
- Added
WalletLifecycle::prepare_key_rotationand platform bindings. It creates the second 12-word half, both contract signatures, and the signed key-change BOC. - Added Windows x86-64 MSVC release archives with the static library, DLL, import library, and C++ wrapper.
- Breaking: Wallet derivation and signing now use the embedded Wallet rev00 contract instead of the experimental Wallet V5 placeholder, including its contract code, subwallet IDs, state layout, and external and internal request encoding.
- Post-rotation Wallet rev00 requests now use the signing half of the recovery phrase while the account address and
StateInitremain anchored to the first half. Deployment from a post-rotation phrase is rejected until the account is active on-chain.
- Added
WalletStatuslessHostandWalletClient::new_statusless, including generated platform bindings, for relays and protocol proxies that return only a provider body or an opaque host error. - Added a runnable TypeScript provider-transport example covering both metadata-rich HTTP and body-only relay integrations.
- Post-rotation Wallet rev00 requests now use the signing half of the recovery phrase while the account address and
StateInitremain anchored to the first half. - Strict
ton://transfer/parsing now rejects control characters, ambiguous normalized paths and authorities, and noncanonical raw recipient or jetton-master addresses. - TON Connect device information now accepts the legacy
"SendTransaction"feature alongside its detailed descriptor while continuing to reject exact duplicates. - Status-less provider transports now recognize Toncenter error envelopes with explicit body codes, including rate limits and authentication failures.
- Added
parse_ton_address,convert_ton_address, andis_valid_ton_addressfor TON address parsing, validation, and conversion. - Added
mnemonic_wordlist, which returns the BIP-39 English word list in its original order. - Added transaction fees, transfer statuses, plaintext comments, and encrypted-comment BOCs to activity items.
- Added NFT collection descriptors with the collection address, name, description, image, and provider metadata.
- Added
create_encrypted_commentanddecrypt_commentwith protected-key access through the platform host. - Added
.tonDNS wallet-record resolution.ProviderConfig.dns_root_addressoverrides the default root for the selected network. - Added strict
ton://transfer/parsing for Gram and jetton transfers, exact amounts, text or BOC payloads, and expiration.
- Breaking: Wallet creation and import now use TEP-0003 Rotation mnemonics.
- New wallets return a 12-word phrase before the first key rotation.
- Wallet import accepts 12-word pre-rotation phrases and 24-word post-rotation phrases.
- Wallet import now rejects TON mnemonics and plain Multichain mnemonics.
- C++ typed binding errors now return the Rust
Displaymessage fromwhat(). - The TUI recovery grid now uses the actual recovery-phrase length.
Test third version
Test second version
Test first version