Documentation Index
Fetch the complete documentation index at: https://companyname-a7d5b98e-feature-fumodocs.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
sendTransaction asks the wallet to sign and broadcast one or more outgoing messages from the connected account. The request supports two payload shapes — raw messages for full control, or structured items to let the wallet build the BoC.
Request shape
interface SendTransactionRequest {
validUntil: number; // unix seconds; reject if older
network?: string; // NETWORK_ID; '-239' mainnet, '-3' testnet, any other valid TON global_id allowed
from?: string; // optional sender address; restricts which account signs
messages?: RawMessage[]; // raw mode (mutually exclusive with `items`)
items?: StructuredItem[]; // structured mode (mutually exclusive with `messages`)
}
network should be set explicitly. If the dApp’s network and the wallet’s network differ, the wallet refuses the request.
Raw messages[]
Use raw messages when you need full control over the cell — custom op codes, contract calls, or backward compatibility with wallets that do not advertise itemTypes.
Each message is { address, amount, payload?, stateInit?, extraCurrency? }. address must be TEP-2 user-friendly form (not raw workchain:hex).
Plain TON transfers omit payload or use an empty body.
Raw messages (no payload for a simple transfer):
import { comment } from '@ton/ton'
await tonConnectUi.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 600,
network: '-239',
messages: [{ address: 'EQD4oN...wz7A', amount: '5000000', payload: comment('Hello, world!') }],
});
Jetton transfer
For jettons you send to the user’s jetton wallet contract with a TEP-74 transfer#0f8a7ea5 body.
import { Address, beginCell, toNano } from '@ton/core';
import { TonClient } from '@ton/ton';
import { TonConnectUI } from '@tonconnect/ui';
const tonConnectUi = new TonConnectUI({
manifestUrl: 'https://your-dapp.example/tonconnect-manifest.json',
});
const JETTON_MASTER = 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs';
const RECIPIENT = 'Ef8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAU';
const account = tonConnectUi.account;
if (!account?.address) {
throw new Error('Connect the wallet first');
}
const SENDER = account.address;
const client = new TonClient({
endpoint: 'https://toncenter.com/api/v2/jsonRPC',
});
async function resolveJettonWalletAddress(master: string, owner: string): Promise<string> {
const result = await client.runMethod(
Address.parse(master),
'get_wallet_address',
[{ type: 'slice', cell: beginCell().storeAddress(Address.parse(owner)).endCell() }]
);
const walletAddress = result.stack.readAddress();
return walletAddress.toString({ urlSafe: true, bounceable: true });
}
const jettonAmount = toNano('1');
const forwardTonAmount = 1n; // 1 nanoTON
const userJettonWallet = await resolveJettonWalletAddress(JETTON_MASTER, SENDER);
const transferBody = beginCell()
.storeUint(0x0f8a7ea5, 32) // transfer op
.storeUint(0n, 64) // query_id
.storeCoins(jettonAmount)
.storeAddress(Address.parse(RECIPIENT))
.storeAddress(Address.parse(SENDER)) // response_destination
.storeBit(0) // custom_payload: none
.storeCoins(forwardTonAmount)
.storeBit(0) // forward_payload: inline empty
.endCell()
.toBoc()
.toString('base64');
await tonConnectUi.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 600,
network: '-239',
messages: [
{
address: userJettonWallet, // user-friendly (base64url) format
amount: toNano('0.05').toString(), // TON attached for jetton-wallet execution
payload: transferBody,
},
],
});
NFT transfer
For NFTs you send to the NFT item contract with TEP-62 transfer#5fcc3d14. Build the body as a base64 BoC and attach it as payload:
import { Address, beginCell, toNano } from '@ton/core';
const nftItem = Address.parse('EQAcoW...qD8qM3T'); // NFT item contract, full friendly address
const newOwner = Address.parse('EQD4oN...wz7A');
const responseDestination = Address.parse('UQAs9V...g5kX'); // connected wallet, excess return
const nftTransferBody = beginCell()
.storeUint(0x5fcc3d14, 32)
.storeUint(0n, 64) // query_id
.storeAddress(newOwner)
.storeAddress(responseDestination)
.storeBit(0) // no custom_payload
.storeCoins(toNano('0.01')) // forward_amount to new owner
.storeBit(0) // forward_payload: empty (Either left)
.endCell()
.toBoc()
.toString('base64');
await tonConnectUi.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 600,
network: '-239',
messages: [
{
address: nftItem.toString({ urlSafe: true, bounceable: true }),
amount: toNano('0.05').toString(),
payload: nftTransferBody,
},
],
});
Structured items[]
Structured items describe what to do — send TON, transfer a jetton, transfer an NFT. The wallet resolves jetton wallet addresses, builds transfer cells, and estimates gas. Use this path only when you know the target wallet advertises support (see Choosing items vs messages and Filter wallets by required features).
Three item types: ton, jetton, nft.
ton — transfer TON
interface TonItem {
type: 'ton';
address: string; // destination, friendly format
amount: string; // nanoTON as decimal string
payload?: string; // optional one-cell BoC, base64
stateInit?: string; // optional one-cell BoC, base64
extraCurrency?: { [k: number]: string };
}
Same TON-with-comment transfer as the raw version above, expressed as a structured item:
import { comment } from '@ton/ton';
await tonConnectUi.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 600,
network: '-239',
items: [
{
type: 'ton',
address: 'EQD4oN...wz7A', // recipient, full TEP-2 friendly address
amount: '5000000',
payload: comment('Hello, world!'),
},
],
});
jetton — transfer fungible tokens
interface JettonItem {
type: 'jetton';
master: string; // jetton master contract address
destination: string; // recipient address
amount: string; // jetton amount in elementary units
attachAmount?: string; // TON to attach for fees; wallet estimates if omitted
responseDestination?: string; // where to send excess; defaults to sender
customPayload?: string; // raw one-cell BoC, base64
forwardAmount?: string; // nanoTON to forward to destination
forwardPayload?: string; // raw one-cell BoC, base64
queryId?: string;
}
await tonConnectUi.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 600,
network: '-239',
items: [
{
type: 'jetton',
master: 'EQCxE6...Id_sDs', // jetton master, full friendly address
amount: '1000000',
destination: 'EQD4oN...wz7A',
},
],
});
nft — transfer an NFT
interface NftItem {
type: 'nft';
nftAddress: string;
newOwner: string;
attachAmount?: string;
responseDestination?: string;
customPayload?: string;
forwardAmount?: string;
forwardPayload?: string;
queryId?: string;
}
await tonConnectUi.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 600,
network: '-239',
items: [
{
type: 'nft',
nftAddress: 'EQAcoW...qD8qM3T', // NFT item contract, full friendly address
newOwner: 'EQD4oN...wz7A',
},
],
});
Mixing types in one transaction
await tonConnectUi.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 600,
network: '-239',
items: [
{ type: 'ton', address: '...', amount: '5000000' },
{
type: 'jetton',
master: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs',
amount: '50000',
destination: 'Ef8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAU',
}
]
});
To restrict the picker to wallets that support specific item types, see Filter wallets by required features.
Multi-message batches
Wallets accept up to maxMessages messages per request (declared in the wallet’s SendTransaction feature). Exceeding the limit throws before the wallet is opened.
Submission is grouped, execution is not atomic across recipients:
- The wallet signs and broadcasts one external message containing all requested internal messages.
- Recipient contracts execute independently; one message can fail or bounce while others succeed.
- Recipient execution order and final outcomes can diverge from the input list.
Treat batch results as partial by default and verify each target account on-chain.
Choosing items vs messages
Prefer messages today unless you control the wallet list. Many wallets still do not advertise structured SendTransaction capabilities (itemTypes for ton / jetton / nft), so items flows often fail or fall back unpredictably across the full registry.
If you build on items (simpler jetton and NFT flows, no jetton-wallet resolution in the dApp), restrict the connect UI to wallets that declare the features you need. See Filter wallets by required features.
Prefer messages when | Prefer items when (with wallet filtering) |
|---|
| Default path for maximum compatibility | The wallet advertises the needed itemTypes |
| Custom op codes or non-standard payloads | Standard TON / jetton / NFT transfers only |
| You already resolve jetton wallet addresses | You want the wallet to build TEP-74 / TEP-62 bodies |
| You cannot filter the wallet picker | You filter wallets — Filter wallets by required features |
Response
interface SendTransactionResponse {
boc: string; // base64 BoC of the broadcast external message
traceId?: string; // UUID for end-to-end analytics correlation
}
const result = await tonConnectUi.sendTransaction(request);
console.log(result.boc); // base64 BoC of the broadcast external message
Use the returned BoC to look up the transaction on-chain.
Errors
| Code | Name | Description |
|---|
| 0 | UNKNOWN_ERROR | Unknown error. |
| 1 | BAD_REQUEST_ERROR | Bad request. |
| 100 | UNKNOWN_APP_ERROR | Unknown app. |
| 300 | USER_REJECTS_ERROR | User declined the request. |
| 400 | METHOD_NOT_SUPPORTED | Method not supported. |
See also