> ## 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": "/ecosystem/wallet-apps/tonkeeper",
  "feedback": "Description of the issue"
}
```

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

</AgentInstructions>

# Tonkeeper

export const Image = ({src, darkSrc, alt = '', darkAlt, href, target, height = 342, width = 608, noZoom = false, center = false}) => {
  const isSVG = src.match(/\.svg(?:[#?].*?)?$/i) !== null;
  const shouldInvert = isSVG && !darkSrc;
  const shouldCreateLink = href !== undefined;
  const minPx = 9;
  const maxPx = 608;
  const expectedPx = `a number or a string with a number that is greater than ${minPx - 1} and less than or equal to ${maxPx}`;
  const createInvalidPropCallout = (title, received, expected) => {
    return <Danger>
        <span className="font-bold">
          Invalid <code>{title.toString()}</code> passed!
        </span>
        <br />
        <span className="font-bold">Received: </span>
        {received.toString()}
        <br />
        <span className="font-bold">Expected: </span>
        {expected.toString()}
        {}
      </Danger>;
  };
  const checkValidDimensionValue = value => {
    switch (typeof value) {
      case "string":
      case "number":
        const num = Number(value);
        return Number.isSafeInteger(num) && num >= minPx && num <= maxPx;
      default:
        return false;
    }
  };
  let callouts = [];
  if (height && !checkValidDimensionValue(height)) {
    callouts.push(createInvalidPropCallout("height", height, expectedPx));
  }
  if (width && !checkValidDimensionValue(width)) {
    callouts.push(createInvalidPropCallout("width", width, expectedPx));
  }
  if (callouts.length !== 0) {
    return callouts;
  }
  const heightPx = Number(height);
  const widthPx = Number(width);
  const shouldCenter = center === "true" || center === true ? true : false;
  const shouldNotZoom = noZoom === "true" || noZoom === true ? true : false;
  const images = <>
      <img className="block dark:hidden" src={src} alt={alt} {...height && ({
    height: heightPx
  })} {...width && ({
    width: widthPx
  })} {...(shouldCreateLink || shouldInvert || shouldNotZoom) && ({
    noZoom: "true"
  })} />
      <img className={`hidden dark:block ${shouldInvert ? "invert" : ""}`} src={darkSrc ?? src} alt={darkAlt ?? alt} {...height && ({
    height: heightPx
  })} {...width && ({
    width: widthPx
  })} {...(shouldCreateLink || shouldInvert || shouldNotZoom) && ({
    noZoom: "true"
  })} />
    </>;
  if (shouldCreateLink) {
    if (shouldCenter) {
      return <div style={{
        display: "flex",
        justifyContent: "center"
      }}>
          <a href={href} target={target ?? "_self"}>
            {images}
          </a>
        </div>;
    }
    return <a href={href} target={target ?? "_self"}>
        {images}
      </a>;
  }
  if (shouldCenter) {
    return <div style={{
      display: "flex",
      justifyContent: "center"
    }}>{images}</div>;
  }
  return images;
};

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>
    </>;
};

[Tonkeeper](https://tonkeeper.com/) is a self‑custodial mobile wallet available on [iOS](https://apps.apple.com/us/app/tonkeeper-ton-wallet/id1587742107) and [Android](https://play.google.com/store/apps/details?id=com.ton_keeper).
It supports regular [wallets](/standard/wallets/how-it-works), [Jettons](/standard/tokens/jettons/overview), [NFTs](/standard/tokens/nft/overview), and [TON Connect](/ecosystem/ton-connect). Its github repository can be found [here](https://github.com/tonkeeper).

<div style={{ display: "flex", justifyContent: "center" }}>
  <Image src="/resources/images/wallets/tonkeeper/main-int-light.png" darkSrc="/resources/images/wallets/tonkeeper/main-int-dark.png" width={228} height={342} alt="Tonkeeper main interface" />
</div>

* 🟡 **Account balance** displays the total amount of Toncoin and other tokens held on account.
* 🔴 **Account address** is shown as a base64-encoded string. It can be shared to receive TON, jettons, or NFTs.
* 🟢 **Send/Receive/Scan buttons** are used to transfer TON or jettons to another account, receive TON or jettons to the wallet, and scan QR codes to confirm transactions, respectively.

## Create a wallet

A wallet is required to do any transactions on a public global network. It is the primary way to interact with the blockchain. This step-by-step guide explains how to use Tonkeeper app to create a testnet wallet account.

Testnet is used instead of mainnet, because it is more suitable for development and experimentation, and test coins can be obtained for free on testnet. The procedure works the same way on mainnet, except funds will have to be procured in a different way.

Overall procedure is:

* Generate a mnemonic (a key). It uniquely determines wallet's address, but the wallet doesn't exist on blockchain yet, i.e. is in [`nonexist`](/foundations/status#status-variety) status.
* Send some funds to the wallet's account. Now it will be in [`uninit`](/foundations/status#status-variety) status, i.e. already with some balance on it, but without any code yet.
* Deploy wallet's code to this address. Some of these funds will be used to pay for the deploy process. Now the wallet is in [`active`](/foundations/status#status-variety) status, and can be used for any purpose.

<Aside type="danger" title="Funds at risk">
  Addresses of both mainnet and testnet accounts can be derived from the same mnemonic, i.e. the same key might be used for both wallets. Beware these accounts exist only in their corresponding networks.

  It's possible to forget switching to testnet, and accidentally spend real funds on mainnet.

  It's possible to accidentally transfer funds to a testnet wallet address on mainnet. These funds will be impossible to recover.

  Verify which network is used before any funds are sent.
</Aside>

### Generate a key

1. Install Tonkeeper on [iOS](https://apps.apple.com/us/app/tonkeeper-ton-wallet/id1587742107) or [Android](https://play.google.com/store/apps/details?id=com.ton_keeper).

2. Click <kbd>Create New Wallet</kbd>

   <div style={{ display: "flex", justifyContent: "center" }}>
     <Image src="/resources/images/wallets/tonkeeper/create-wallet-light.png" darkSrc="/resources/images/wallets/tonkeeper/create-wallet-dark.png" width={228} height={342} alt="Create a wallet" />
   </div>

3. Create a passcode and re-enter it. Passcode is used to encrypt the mnemonic.

   <div style={{ display: "flex", justifyContent: "center", gap: "16px" }}>
     <Image src="/resources/images/wallets/tonkeeper/passcode-light.png" darkSrc="/resources/images/wallets/tonkeeper/passcode-dark.png" width={228} height={342} alt="Create a passcode" />

     <Image src="/resources/images/wallets/tonkeeper/reenter-light.png" darkSrc="/resources/images/wallets/tonkeeper/reenter-dark.png" width={228} height={342} alt="Confirm the passcode" />
   </div>

4. Click <kbd>Back up your recovery phrase</kbd> and <kbd>Back Up Manually</kbd>.

   <div style={{ display: "flex", justifyContent: "center", gap: "16px" }}>
     <Image src="/resources/images/wallets/tonkeeper/backup-light.png" darkSrc="/resources/images/wallets/tonkeeper/backup-dark.png" width={228} height={300} alt="Back up" />

     <Image src="/resources/images/wallets/tonkeeper/backup-manually-light.png" darkSrc="/resources/images/wallets/tonkeeper/backup-manually-dark.png" width={228} height={342} alt="Confirm the passcode" />
   </div>

5. Save 24 words of the [mnemonic](/standard/wallets/mnemonics).

   <Aside type="danger" title="Funds at risk">
     Mnemonic is the text representation of wallet's secret key. Losing it is the same as losing access to the wallet.<br />
     Anyone who has access to the mnemonic can take control of the wallet and move funds. If compromise is suspected, create a new wallet and transfer all funds immediately. Prefer not to store recovery words digitally; write them down and keep them offline.
   </Aside>

   <div style={{ display: "flex", justifyContent: "center" }}>
     <Image src="/resources/images/wallets/tonkeeper/recovery-light.png" darkSrc="/resources/images/wallets/tonkeeper/recovery-dark.png" width={228} height={342} alt="Recovery phrase" />
   </div>

6. Pass the check that the mnemonic was saved.

   <div style={{ display: "flex", justifyContent: "center" }}>
     <Image src="/resources/images/wallets/tonkeeper/backup-check-light.png" darkSrc="/resources/images/wallets/tonkeeper/backup-check-dark.png" width={228} height={342} alt="Recovery phrase" />
   </div>

7. The main interface of the app should now appear.

### Switch to testnet

1. Click <kbd>wallet</kbd> to open the <kbd>Add Wallet</kbd> pop-up.

   <div style={{ display: "flex", justifyContent: "center" }}>
     <Image src="/resources/images/wallets/tonkeeper/add-testnet-wallet-light.png" darkSrc="/resources/images/wallets/tonkeeper/add-testnet-wallet-dark.png" width={228} height={342} alt="Add testnet" />
   </div>

2. In the "Add Wallet" window, scroll down to the "For developers" section. Click the "Testnet Account" card.

   <div style={{ display: "flex", justifyContent: "center" }}>
     <Image src="/resources/images/wallets/tonkeeper/for-devs-light.png" darkSrc="/resources/images/wallets/tonkeeper/for-devs-dark.png" width={228} height={342} alt="Testnet account" />
   </div>

3. Enter the recovery phrase that was provided when the wallet was created on Mainnet, then click <kbd>Confirm</kbd>.

   <div style={{ display: "flex", justifyContent: "center" }}>
     <Image src="/resources/images/wallets/tonkeeper/recovery-test-light.png" darkSrc="/resources/images/wallets/tonkeeper/recovery-test-dark.png" width={228} height={342} alt="Recovery phrase for testnet" />
   </div>

4. The main interface of the app should now appear, indicating that the testnet is used. Also address of the testnet wallet in the [user-friendly format](/foundations/addresses/formats#user-friendly-format) starts with `k` or `0`.

   <div style={{ display: "flex", justifyContent: "center" }}>
     <Image src="/resources/images/wallets/tonkeeper/main-int-test-light.png" darkSrc="/resources/images/wallets/tonkeeper/main-int-test-dark.png" width={228} height={342} alt="Main interface with testnet note" />
   </div>

### Add funds into the wallet

To get free coins on testnet, follow [the guide](/ecosystem/wallet-apps/get-coins).

#### Quick version

1. Message [`@testgiver_ton_bot`](https://t.me/testgiver_ton_bot) in [Telegram](https://telegram.org/).
2. Press the <kbd>Start</kbd> or send `/start` message.
3. Pass the captcha test.
4. Enter and send the testnet wallet address displayed by wallet.
5. Soon after the "Request added to the queue" response, 2 TON will be sent to the wallet.
6. There won't be any other message that the transfer happened. [Use an explorer](#check-the-account-state) to check the request status.
7. The account should be in the `uninit` status now.

<Image src="/resources/images/wallets/wallet-ton-org/address_uninit_light.png" darkSrc="/resources/images/wallets/wallet-ton-org/address_uninit_dark.png" alt="Account status: uninit" />

### Deploy the code

<Aside type="danger" title="Funds at risk">
  On-chain transfers are irreversible — verify the recipient and amount before confirming. Use testnet for practice; use mainnet only for real transfers.
</Aside>

To deploy the code, send any transaction from the wallet. The recipient can be any address, including the wallet itself.

1. Click <kbd>Send</kbd> on the main interface, enter wallet address in "Address or name", and the "Amount" of TON. Click <kbd>Continue</kbd>.

   <div style={{ display: "flex", justifyContent: "center" }}>
     <Image src="/resources/images/wallets/tonkeeper/send-light.png" darkSrc="/resources/images/wallets/tonkeeper/send-dark.png" width={228} height={342} alt="Send TON" />
   </div>

2. Verify the transaction details and swipe if correct. Otherwise, tap <kbd>`<`</kbd> in the top-left corner to edit.

   <div style={{ display: "flex", justifyContent: "center" }}>
     <Image src="/resources/images/wallets/tonkeeper/confirm-light.png" darkSrc="/resources/images/wallets/tonkeeper/confirm-dark.png" width={228} height={342} alt="Verify transaction" />
   </div>

3. After confirmation, enter the passcode. Then, the "History" page displays the sent transaction.

4. [Use an explorer](#check-the-account-state) to check wallet's status. It should be `active` now.

## Check the account state

Use a [blockchain explorer](/ecosystem/explorers/overview) to inspect the account. For **Testnet**, use [Tonviewer Testnet](https://testnet.tonviewer.com/).

1. Paste the wallet address into the search bar.<br /><Image src="/resources/images/wallets/wallet-ton-org/tonviewer_light.png" darkSrc="/resources/images/wallets/wallet-ton-org/tonviewer_dark.png" alt="Insert address in Tonviewer search" />

2. The account details will appear. In a newly created wallet, the status is `nonexist`, indicating the wallet is not deployed.<br /><Image src="/resources/images/wallets/wallet-ton-org/address_nonexist_light.png" darkSrc="/resources/images/wallets/wallet-ton-org/address_nonexist_dark.png" alt="Account status: nonexist" />

## Verify wallet's version

By default, Tonkeeper creates wallets with the [Wallet v5](/standard/wallets/v5) code deployed on them. To switch [wallet contract version](/standard/wallets/comparison) to [v4](/standard/wallets/v4):

1. On the main menu, tap the gear icon <kbd><Icon icon="gear" size={16} /></kbd> in the upper-right corner.

2. In "Settings", select <kbd>Wallet v4R2</kbd> and enter the passcode.

   <div style={{ display: "flex", justifyContent: "center" }}>
     <Image src="/resources/images/wallets/tonkeeper/v4r2-light.png" darkSrc="/resources/images/wallets/tonkeeper/v4r2-dark.png" width={228} height={342} alt="V4R2" />
   </div>

3. The wallet v4r2 is auto-generated and the app returns to the main menu.

   * If v5 is highlighted, v4 has no visual indicator.
   * To check, tap the wallet name — **wallet v4r2** — v5 is highlighted, while v4 is not.

<div style={{ display: "flex", justifyContent: "center" }}>
  <Image src="/resources/images/wallets/tonkeeper/wallet-v4r2-light.png" darkSrc="/resources/images/wallets/tonkeeper/wallet-v4r2-dark.png" width={228} height={342} alt="V4R2" />
</div>
