-
Notifications
You must be signed in to change notification settings - Fork 1
Wallet
Tonnet Browser includes a built-in W5 (v5r1) wallet for TON. Keys are encrypted on disk via the OS keychain, and the secret key is zeroed from memory after each signing operation.
<userData>/wallet-key.dat
Where <userData> is the Electron user data directory:
- Linux:
~/.config/<app> - macOS:
~/Library/Application Support/<app> - Windows:
%APPDATA%\<app>
The wallet file uses one of three formats, detected automatically on read:
| Format | Detection | Description |
|---|---|---|
| Unencrypted legacy | File is exactly 32 bytes | Raw Ed25519 seed, no encryption |
| Encrypted hex seed | Starts with SENC marker, plaintext is hex string |
safeStorage-encrypted 32-byte seed |
| Encrypted JSON mnemonic | Starts with SENC marker, plaintext is JSON |
safeStorage-encrypted 24-word mnemonic (current format) |
Uses Electron safeStorage API:
- macOS: system Keychain
- Windows: DPAPI (bound to user account)
- Linux: gnome-keyring, kwallet, or
basic_textfallback
The SENC (4-byte ASCII) marker is prepended to all encrypted data on disk.
When the Linux backend is basic_text (no keyring daemon), the wallet still works but weakEncryption: true is set in the wallet state. Auto-migration of legacy seeds is suppressed on this backend.
On every read, if the file is an unencrypted 32-byte seed and a proper keychain backend is available, the data is immediately re-encrypted in place (format 1 to format 2). No migration runs from hex seed to JSON mnemonic.
- Generates a 24-word mnemonic via
mnemonicNew(24)from@ton/crypto - Derives Ed25519 keypair via
mnemonicToPrivateKey(mnemonic) - Stores
{ type: 'mnemonic', mnemonic }as encrypted JSON - Creates
WalletContractV5R1with workchain 0 - Mnemonic array is zeroed after storage (
fill('') + length = 0)
- Validates the phrase with
mnemonicValidate(words) - Wipes in-memory keys (
fill(0)) - Deletes existing wallet file
- Writes new mnemonic encrypted
- Zeros the input words array
- Derives new
WalletContractV5R1
Returns the 24-word mnemonic from the encrypted file. Only works for JSON mnemonic format (format 3). Legacy seed-only wallets cannot export a mnemonic.
- Unsubscribes account and transaction feeds
- Zeroes
secretKeyandpublicKeybuffers withfill(0) - Cancels auto-lock timer
- Deletes wallet file from disk (ignores if already absent)
Default: 5 minutes. Configurable from 0 (disabled) to 1440 minutes.
On expiry:
-
cachedSecretKeyis zeroed withfill(0)and set tonull - Public key remains in memory (address and state queries still work)
- Next signing operation triggers re-decryption from disk
The timer resets on every successful key load or generation.
After every BOC signing operation, the secret key is immediately zeroed and cleared from memory. The secret key exists in memory only for the duration of a single signing call. The next transaction requires re-decryption from disk.
-
Seqno sync: fetches on-chain seqno via
wallet.getSeqno. Usesmax(local, onChain)to prevent replay. Undeployed contracts default to seqno 0. - BOC build: concurrent sends are serialized through a sign lock. For seqno 0 (first transaction), the contract init code is included and validity is extended to 1 hour. Otherwise validity is 300 seconds.
-
Broadcast: sends via
lite.sendAndWatchwith 120-second confirmation window. On timeout, falls back tolite.sendMessage(fire-and-forget). - Local seqno is incremented immediately after signing, before broadcast confirms.
Two real-time subscriptions via the bridge:
-
subscribe.accountState: pushes balance, last transaction, and seqno changes -
subscribe.transactions: pushes new transaction objects
Both subscriptions are re-established automatically after WebSocket reconnect.
On wallet load, getBalance() is retried up to 10 times with exponential backoff (500ms to 5s). This warms the shard-specific ADNL path, since the bridge readiness probe only validates the masterchain liteserver. If all attempts fail, balance defaults to 0 and startup proceeds.
tonnet.resistance.dog · GitHub · MIT License
Tonnet Browser
Getting Started
Reference
Development