> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ton.org/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.ton.org/feedback

```json
{
  "path": "/standard/wallets/interact",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# How to interact with wallet

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

Creating a wallet involves several steps

* Generate a mnemonic; wallet will be still in [`nonexist`](/foundations/status#status-variety) status.
* Derive the public key and the wallet address out of it.
* Put some funds to the address; wallet account will move to [`uninit`](/foundations/status#status-variety) status.
* Deploy code of wallet contract to that address; account will move to [`active`](/foundations/status#status-variety) status.

## Derive wallet address

The following algorithm is used by wallet apps, and has to be replicated if the same wallet address should be generated programmatically.

A wallet account's address is [derived](/foundations/addresses/derive) from [`StateInit`](/foundations/messages/deploy) that stores in its `data` field two values:

* `public_key`, dependent on the [mnemonic](/standard/wallets/mnemonics);
* `wallet_id`, a special [salt-like](https://en.wikipedia.org/wiki/Salt_\(cryptography\)) field, dependent on the wallet contract type and the `network_id`.

<Aside type="note">
  Sometimes `wallet_id` is also called `subwallet_id` in some of the libraries and documentation. They mean the same thing.
</Aside>

This means that the mnemonic alone does not determine an address uniquely: `wallet_id` has to be known to compute the address.

### Default `wallet_id` values

| Network | [V4R2](/standard/wallets/v4) | [V5](/standard/wallets/v5) |
| ------- | ---------------------------- | -------------------------- |
| Mainnet | `0x29a9a317` (698983191)     | `0x7FFFFF11` (2147483409)  |
| Testnet | `0x29a9a317` (698983191)     | `0x7FFFFFFD` (2147483645)  |

For Wallet V4R2 `wallet_id` is defined as first 4 bytes from TON mainnet blockchain initial state hash. There is no specific logic why this number was chosen, community needed some default value and this one works well enough.

For Wallet V5, `wallet_id` is different between Mainnet and Testnet for security reasons. There will be different wallet addresses for different networks with the same mnemonic. This prevents replaying transactions from testnet on mainnet, and ensuing loss of funds. The `wallet_id` value is obtained from

* `network_id`: `-239` for mainnet, `-3` for testnet,
* `wallet_version`: currently always `0`,
* `subwallet_number`: `0` by default,
* `workchain`: `0` for basechain

by the following algorithm:

```ts theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
type WalletIdV5 = {
    // currently always 0
    readonly walletVersion: number;
    // -239 for mainnet, -3 for testnet
    readonly networkGlobalId: number;
    // 0 for basechain
    readonly workchain: number;
    // 0 for the first wallet with this mnemonic
    readonly subwalletNumber: number;
}

export function storeWalletIdV5(walletId: WalletIdV5) {
    return (builder: Builder) => {
        builder.storeInt(walletId.networkGlobalId, 32);
        builder.storeInt(walletId.workchain, 8);
        builder.storeUint(walletId.walletVersion, 8);
        builder.storeUint(walletId.subwalletNumber, 32);
    }
}
```

<Aside type="note">
  Algorithm here is presented for educational purposes, in most cases there is no need to reimplement it. Use the existing implementation from TON SDKs instead.
</Aside>

### Examples

The following examples use wrappers for wallet contracts from the [`@ton/ton`](https://github.com/ton-org/ton) TypeScript SDK.

#### Wallet V4R2

```ts expandable theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
import { mnemonicToPrivateKey } from '@ton/crypto';
import { WalletContractV4 } from '@ton/ton';

// 12‑ or 24‑word mnemonic (space‑separated)
const mnemonic = 'bread table ...';

// async function for await
const main = async () => {
    const keyPair = await mnemonicToPrivateKey(
        mnemonic.split(' ')
    );
    const walletContractV4 = WalletContractV4.create({
        workchain: 0,
        publicKey: keyPair.publicKey,
        // this magic number is default wallet_id for V4R2 wallet contract
        walletId: 0x29a9a317,
    });
    console.log(walletContractV4.address);
}

void main();
```

#### Wallet V5

```ts expandable theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
import { mnemonicToPrivateKey } from '@ton/crypto';
import { WalletContractV5R1 } from '@ton/ton';

// 12‑ or 24‑word mnemonic (space‑separated).
const mnemonic = 'foo bar baz ...';

// async function for await
const main = async () => {
    const keyPair = await mnemonicToPrivateKey(
        mnemonic.split(' '),
    );

    // testnet
    const testnetV5Wallet = WalletContractV5R1.create({
        walletId: {
            networkGlobalId: -3,
        },
        publicKey: keyPair.publicKey,
        workchain: 0,
    });

    console.log(testnetV5Wallet.address);

    // mainnet
    const mainnetV5Wallet = WalletContractV5R1.create({
        walletId: {
            networkGlobalId: -239,
        },
        publicKey: keyPair.publicKey,
        workchain: 0,
    });

    console.log(mainnetV5Wallet.address);
};

void main();
```

This wallet contract instance can be used to [send messages](/standard/wallets/v5-api) to the blockchain.

## Comments

Wallet apps can attach short human-readable notes — commonly called *comments* — to outgoing internal messages. On-chain they are just message bodies with a specific layout that ecosystem agreed to interpret as text.

### Comment format

* The first 32 bits of the incoming message body must be the opcode `0x00000000`. This value signals that the rest of the payload should be treated as a comment.
* The remaining bytes are UTF-8 encoded text. Wallet apps should tolerate invalid or empty strings — many senders emit messages without a comment or with zero-length payloads.
* When parsing, always inspect the opcode before assuming a text comment. If the opcode differs, fall back to handling other contract-specific payloads.

Because comments ride inside ordinary internal messages, the format works identically for:

* native Toncoin transfers between wallets;
* [Jetton transfers](/standard/tokens/jettons/api#forward-payload-formats), where the wallet forwards an internal message to the token wallet along with the comment payload;
* [NFT transfers](/standard/tokens/nft/api#forward-payload-formats), where the comment travels in the same forwarding message that moves the ownership record.

### Attaching a comment when sending

To include a comment in an outgoing transfer, construct an internal message body that starts with `0x00000000` and append the UTF-8 bytes of the note YOU want to share. Most wallet libraries expose helpers for this, but the underlying steps are:

1. Allocate a cell.
2. Store the 32-bit zero opcode.
3. Store the text as a [byte string](/standard/tokens/metadata#snake-data-encoding) (UTF-8 encoded).
4. Send the internal message along with the desired Toncoin, [Jettons](/standard/tokens/jettons/how-it-works), or [NFT](/standard/tokens/nft/how-it-works) payload.

Receivers that follow the convention will display the decoded text to the user. Contracts that do not recognize the opcode will simply ignore it or treat the message body as opaque data, so comments are backward-compatible with existing transfers.

### Example: Sending a comment with `@ton/core`

```ts theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
import { Cell, beginCell } from '@ton/core';

function createCommentCell(comment: string): Cell {
    return beginCell()
        // opcode for comment
        .storeUint(0, 32)
        // UTF-8 encoded text in snake encoding
        .storeStringTail(comment)
        .endCell();
}
```
