Skip to main content
Jetton transfer is an operation specified in TEP 0074. Its implementation must comply with this standard, and Jetton wallet contracts must support the logic described there. The Jetton transfer message is also specified and must comply with the corresponding TL-B scheme. This scheme involves, among other things,
  • forward_ton_amount: the amount of nanotons to be sent to the destination address;
  • forward_payload: optional custom data that should be sent to the destination address.
If forward_ton_amount > 0, then forward_payload must comply with one of the standard formats. We present here only the simple comment format. First, you can use web services as TON MINTER and avoid writing code, just follow the guides. Second, you can use your favorite IDE. You may also need information on how to get the address of your Jetton wallet. Below there are two illustrative examples:
import { Address, beginCell, internal, toNano } from "@ton/core";
import { TonClient, WalletContractV4 } from "@ton/ton";
import { mnemonicToPrivateKey } from "@ton/crypto";

async function main() {
    const jettonWalletAddress = Address
        .parse('put your jetton wallet address');
    const destinationAddress = Address
        .parse('put destination wallet address');

    const forwardPayload = beginCell()
        .storeUint(0, 32) // 0 opcode means we have a comment
        .storeStringTail('for coffee')
        .endCell();

    const messageBody = beginCell()
        .storeUint(0x0f8a7ea5, 32) // opcode for jetton transfer
        .storeUint(0, 64) // query id
        .storeCoins(toNano(5)) // jetton amount, amount * 10^9
        .storeAddress(destinationAddress) // the address of the new jetton owner
        .storeAddress(destinationAddress) // response destination
        .storeBit(0) // no custom payload
        .storeCoins(toNano('0.02')) // forward amount - if >0, will send notification message
        .storeBit(1) // store forwardPayload as a reference
        .storeRef(forwardPayload)
        .endCell();

    const transferMessage = internal({
        to: jettonWalletAddress,
        value: toNano('0.1'),
        bounce: true,
        body: messageBody
    });

    // connect to your regular wallet
    const client = new TonClient({
    endpoint: 'https://toncenter.com/api/v2/jsonRPC',
    });
    const provider = client.provider(destinationAddress);

    const your_mnemonic = 'put your mnemonic here, ...';
    const keyPair = await mnemonicToPrivateKey(your_mnemonic.split(" "));
    const walletContract = WalletContractV4.create({
        workchain: 0,
        publicKey: keyPair.publicKey,
    });

    // send the transfer message through your wallet
    const seqno = await walletContract.getSeqno(provider);
    await walletContract.sendTransfer(provider, {
        seqno: seqno,
        secretKey: keyPair.secretKey,
        messages: [
            transferMessage,
        ],
        });
}
However, there is an SDK that allows you to avoid manually creating all the necessary messages. An example of how it can be used to send the transfer message is provided below:
import { Address, toNano } from '@ton/core';

import { AssetsSDK, createApi, createSender, importKey, PinataStorageParams } from '@ton-community/assets-sdk';

async function main() {
    const NETWORK = 'mainnet';
    const api = await createApi(NETWORK);

    const keyPair = await importKey(process.env.MNEMONIC!);
    const sender = await createSender('highload-v2', keyPair, api);

    const storage: PinataStorageParams = {
        pinataApiKey: process.env.PINATA_API_KEY!,
        pinataSecretKey: process.env.PINATA_SECRET!,
    };

    const sdk = AssetsSDK.create({
        api: api,
        storage: storage,
        sender: sender,
    });

    const JETTON_ADDRESS = Address.parse('MY_JETTON_ADDRESS');
    const jetton = await sdk.openJetton(JETTON_ADDRESS);

    const RECEIVER_ADDRESS = Address.parse('RECEIVER_ADDRESS');
    const myJettonWallet = await jetton.getWallet(sdk.sender!.address!);
    await myJettonWallet.send(sender, RECEIVER_ADDRESS, toNano(10));
}

void main();
I