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")}`;