Skip to main content

Transfers

This walkthrough covers how to send TON, batch messages, contract calls with payload, and deployment requests with StateInit through UKey Wallet TON Connect Provider.


Send tx

You can initiate a TON transfer by calling sendTransaction via the send method:

const callResult = await provider.send({
method: "sendTransaction",
id: Date.now().toString(),
requestParams: [
JSON.stringify({
valid_until: Math.floor(Date.now() / 1000) + 600, // 10 minutes validity period
messages: [
{
address: "0:8a1d3c5e7f90b2d4c6e8f00123456789abcdeffedcba9876543210fedcba1234", // Receiving address (original format)
amount: "1000000000", // sample amount in nanotons (1 TON = 10^9 nanotons)
},
],
}),
],
});

if ("callResult" in callResult) {
console.log("Transaction BOC payload:", callResult.callResult);
} else {
console.error("Transaction submission failed:", callResult.error.message);
}

Send multiple messages

A single TON transaction can contain up to 4 messages:

const callResult = await provider.send({
method: "sendTransaction",
id: Date.now().toString(),
requestParams: [
JSON.stringify({
valid_until: Math.floor(Date.now() / 1000) + 600,
messages: [
{
address: "0:8a1d3c5e7f90b2d4c6e8f00123456789abcdeffedcba9876543210fedcba1234",
amount: "500000000", // half TON
},
{
address: "0:8e4d3c2b1a098765f4e3d2c1b0a9876543210fedcba9876543210fedcba98765",
amount: "300000000", // 0.3 TON amount
},
],
}),
],
});

Send transaction with payload

Contract interaction usually requires carrying a payload in Base64 BOC format in the message:

import { beginCell } from "@ton/core";

// Create the comment cell
const comment = beginCell()
.storeUint(0, 32) // Note: Comment opcode
.storeStringTail("Greetings from dApp!")
.endCell();

const callResult = await provider.send({
method: "sendTransaction",
id: Date.now().toString(),
requestParams: [
JSON.stringify({
valid_until: Math.floor(Date.now() / 1000) + 600,
messages: [
{
address: "0:8a1d3c5e7f90b2d4c6e8f00123456789abcdeffedcba9876543210fedcba1234",
amount: "100000000",
payload: comment.toBoc().toString("base64"),
},
],
}),
],
});

Send transaction with StateInit

When deploying a contract or initializing account status, you can carry stateInit in the message:

const callResult = await provider.send({
method: "sendTransaction",
id: Date.now().toString(),
requestParams: [
JSON.stringify({
valid_until: Math.floor(Date.now() / 1000) + 600,
messages: [
{
address: "0:9d8c7b6a5948372615049382716f5e4d3c2b1a09876543210fedcba987654321",
amount: "50000000",
stateInit: stateInitBoc.toString("base64"), // Note: Base64 encoded StateInit
},
],
}),
],
});

Send transactions using the SDK

import { useTonConnectUI } from "@tonconnect/ui-react";

function TonTransferButton() {
const [tonConnectUI] = useTonConnectUI();

const handleSend = async () => {
const callResult = await tonConnectUI.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 600,
messages: [
{
address: "EQA...",
amount: "1000000000",
},
],
});
console.log("Serialized BOC:", callResult.boc);
};

return <button onClick={handleSend}>Send 1 TON</button>;
}

Addr Format

TON addresses are available in raw and user-friendly formats. The original format is often used in Provider requests, and the friendly format is usually used when displayed to users:

import { Address } from "@ton/core";

// Provider 内部使用的原始格式
const raw = "0:8a1d3c5e7f90b2d4c6e8f00123456789abcdeffedcba9876543210fedcba1234";

// 对用户更友好的 bounceable 格式
const friendly = Address.parse(raw).toString();
// For instance 'EQBx7qMv2Lk9sNp4Rz5hTc8Yw1Df6JaQ3'

// Non-bounce format
const nonBounceable = Address.parse(raw).toString({ bounceable: false });
// 参考结果可能像 'UQBm4xPv8nLs2kTr6qWc9Yd1fGh5Jz0Ra'

// Convert from friendly format to raw format
const addr = Address.parse("EQBx7qMv2Lk9sNp4Rz5hTc8Yw1Df6JaQ3");
const rawAddress = `${addr.workChain}:${addr.hash.toString("hex")}`;