PembayaranPembayaran lanjutan

Izin pengeluaran

Program Token Solana mendukung delegasi—memberikan izin kepada akun lain untuk mentransfer token dari token account Anda hingga batas yang ditentukan. Ini memungkinkan kasus penggunaan seperti pembayaran otomatis, layanan escrow, dan pemrosesan pembayaran pihak ketiga tanpa melepaskan kepemilikan dana Anda.

Cara kerja delegasi

Ketika Anda menyetujui delegasi, Anda mengotorisasi akun tertentu untuk mentransfer token atas nama Anda:

  • Pemilik tetap memegang kendali: Anda masih memiliki token dan dapat mentransfer atau mencabut kapan saja
  • Pengeluaran terbatas: Delegasi hanya dapat mentransfer hingga jumlah yang disetujui
  • Satu delegasi per akun: Setiap token account hanya dapat memiliki satu delegasi aktif
  • Persetujuan baru menggantikan yang lama: Menyetujui delegasi baru secara otomatis mencabut yang sebelumnya

Delegasi bersifat non-custodial. Delegasi dapat menggunakan token hingga batas yang ditentukan, tetapi tidak dapat mengakses atau menguras akun melebihi jumlah yang disetujui. Pemilik dapat mencabut kapan saja.

Kasus penggunaan bisnis

Kasus penggunaanBagaimana delegasi membantu
Pemroses pembayaranMerchant memberikan izin kepada pemroses untuk menyelesaikan transaksi
Payroll otomatisTreasury menyetujui layanan payroll untuk mencairkan gaji
Layanan escrowPembeli mendelegasikan kepada agen escrow untuk pelepasan bersyarat
Platform tradingPengguna menyetujui exchange untuk mengeksekusi trading atas nama mereka
Penerbitan kartuPengguna menyetujui penerbit kartu untuk menagih pembelian ke token account mereka

Menyetujui delegasi

Berikan izin kepada akun lain untuk membelanjakan token dari akun Anda:

import { getApproveCheckedInstruction } from "@solana-program/token";
// Approve delegate to spend up to 1,000 USDC (6 decimals)
const approveInstruction = getApproveCheckedInstruction({
source: tokenAccountAddress, // Your token account
mint: usdcMintAddress, // USDC mint
delegate: delegateAddress, // Account receiving permission
owner: ownerKeypair, // You (must sign)
amount: 1_000_000_000n, // 1,000 USDC in base units
decimals: 6
});

Parameter:

  • source: Token account yang memberikan izin
  • delegate: Akun yang akan memiliki izin pembelanjaan
  • owner: Pemilik token account saat ini (harus menandatangani transaksi)
  • amount: Jumlah maksimum token yang dapat ditransfer oleh delegasi
  • decimals: Desimal token untuk validasi (mencegah kesalahan desimal)

Demo

Approve Delegate
// Generate keypairs for sender and delegate
const sender = (await generateKeypair()).signer;
const delegate = (await generateKeypair()).signer;
console.log("Sender Address:", sender.address);
console.log("Delegate Address:", delegate.address);
// Demo Setup: Create client, mint account, token account, and fund with initial tokens
const { client, mint, senderAta } = await demoSetup(sender);
console.log("\nMint Address:", mint.address);
console.log("Sender ATA:", senderAta);
// =============================================================================
// Approve Delegate
// =============================================================================
// Create instruction to approve delegate
const approveInstruction = getApproveCheckedInstruction({
source: senderAta,
mint: mint.address,
delegate: delegate.address,
owner: sender,
amount: 1_000_000n, // 1.0 tokens with 6 decimals
decimals: 6
});
// Send approve transaction
const signature = await client.transaction.prepareAndSend({
authority: sender,
instructions: [approveInstruction]
});
console.log("\n=== Approve Delegate ===");
console.log("Transaction Signature:", signature);
// Fetch token account data to show delegate is set
const tokenData = await fetchToken(client.runtime.rpc, senderAta);
console.log("\nSender Token Account Data:", tokenData.data);
// =============================================================================
// Demo Setup Helper Function
// =============================================================================
Console
Click to execute the code.

Mencabut delegasi

Hapus semua izin pengeluaran dari delegasi saat ini:

import { getRevokeInstruction } from "@solana-program/token";
const revokeInstruction = getRevokeInstruction({
source: tokenAccountAddress, // Your token account
owner: ownerKeypair // You (must sign)
});

Revoke menghapus semua izin delegasi—tidak ada pencabutan sebagian. Jika Anda perlu mengurangi batas, setujui delegasi yang sama dengan jumlah yang lebih rendah.

Demo

Revoke Delegate
// Generate keypairs for sender and delegate
const sender = (await generateKeypair()).signer;
const delegate = (await generateKeypair()).signer;
console.log("Sender Address:", sender.address);
console.log("Delegate Address:", delegate.address);
// Demo Setup: Create client, mint account, token account, and fund with initial tokens
const { client, mint, senderAta } = await demoSetup(sender);
console.log("\nMint Address:", mint.address);
console.log("Sender ATA:", senderAta);
// =============================================================================
// Transaction 1: Approve Delegate
// =============================================================================
// Create instruction to approve delegate
const approveInstruction = getApproveCheckedInstruction({
source: senderAta,
mint: mint.address,
delegate: delegate.address,
owner: sender,
amount: 1_000_000n, // 1.0 tokens with 6 decimals
decimals: 6
});
// Send approve transaction
const approveSignature = await client.transaction.prepareAndSend({
authority: sender,
instructions: [approveInstruction]
});
console.log("\n=== Transaction 1: Approve Delegate ===");
console.log("Transaction Signature:", approveSignature);
// Fetch token account data to show delegate is set
const tokenDataAfterApprove = await fetchToken(client.runtime.rpc, senderAta);
console.log("\nSender Token Account Data:", tokenDataAfterApprove.data);
// =============================================================================
// Transaction 2: Revoke Delegate
// =============================================================================
// Create instruction to revoke delegate
const revokeInstruction = getRevokeInstruction({
source: senderAta,
owner: sender
});
// Send revoke transaction
const revokeSignature = await client.transaction.prepareAndSend({
authority: sender,
instructions: [revokeInstruction]
});
console.log("\n=== Transaction 2: Revoke Delegate ===");
console.log("Transaction Signature:", revokeSignature);
// Fetch token account data to show delegate is revoked
const tokenDataAfterRevoke = await fetchToken(client.runtime.rpc, senderAta);
console.log("\nSender Token Account Data:", tokenDataAfterRevoke.data);
// =============================================================================
// Demo Setup Helper Function
// =============================================================================
Console
Click to execute the code.

Transfer sebagai delegasi

Saat bertindak sebagai delegasi, gunakan transfer standar tetapi tanda tangani dengan keypair delegasi, bukan pemilik:

Transfer as Delegate
import { getTransferCheckedInstruction } from "@solana-program/token";
const transferInstruction = getTransferCheckedInstruction({
source: ownerTokenAccount, // The account you have permission to spend from
mint: usdcMintAddress,
destination: recipientTokenAccount,
authority: delegateKeypair, // You (the delegate) sign, not the owner
amount: 100_000_000n, // 100 USDC
decimals: 6
});

Transfer akan berhasil jika:

  • Akun sumber memiliki saldo yang cukup
  • Delegasi menandatangani transaksi

Setiap transfer mengurangi sisa allowance. Ketika allowance mencapai nol, delegasi tidak dapat lagi mentransfer token.

Demo

Transfer as Delegate
// Generate keypairs for sender, delegate, and recipient
const sender = (await generateKeypair()).signer;
const delegate = (await generateKeypair()).signer;
const recipient = (await generateKeypair()).signer;
console.log("Sender Address:", sender.address);
console.log("Delegate Address:", delegate.address);
console.log("Recipient Address:", recipient.address);
// Demo Setup: Create client, mint account, token accounts, and fund with initial tokens
const { client, mint, senderAta, recipientAta } = await demoSetup(
sender,
delegate,
recipient
);
console.log("\nMint Address:", mint.address);
console.log("Sender ATA:", senderAta);
console.log("Recipient ATA:", recipientAta);
// =============================================================================
// Transaction 1: Approve Delegate
// =============================================================================
// Create instruction to approve delegate
const approveInstruction = getApproveCheckedInstruction({
source: senderAta,
mint: mint.address,
delegate: delegate.address,
owner: sender,
amount: 1_000_000n, // 1.0 tokens with 6 decimals
decimals: 6
});
// Send approve transaction
const approveSignature = await client.transaction.prepareAndSend({
authority: sender,
instructions: [approveInstruction]
});
console.log("\n=== Transaction 1: Approve Delegate ===");
console.log("Delegate Address:", delegate.address);
console.log("Transaction Signature:", approveSignature);
// =============================================================================
// Fetch Token Account Data to Demonstrate Delegate is Set
// =============================================================================
const tokenAccountData = await fetchToken(client.runtime.rpc, senderAta);
console.log("\nSender Token Account Data:", tokenAccountData.data);
// =============================================================================
// Transaction 2: Transfer Using Delegate
// =============================================================================
// Create instruction to transfer tokens using delegate
// Note: delegate is the authority here, not the owner
const transferInstruction = getTransferCheckedInstruction({
source: senderAta,
mint: mint.address,
destination: recipientAta,
authority: delegate, // Delegate signs this transaction
amount: 500_000n, // 0.5 tokens with 6 decimals
decimals: 6
});
// Send transfer transaction
// Delegate pays for the transaction and authorizes the transfer (sender not needed)
const transferSignature = await client.transaction.prepareAndSend({
authority: delegate, // Delegate pays fee and signs
instructions: [transferInstruction]
});
// =============================================================================
// Fetch Final Token Account Balances
// =============================================================================
const finalSenderToken = await fetchToken(client.runtime.rpc, senderAta);
const finalRecipientToken = await fetchToken(client.runtime.rpc, recipientAta);
console.log("\n=== Transaction 2: Transfer Using Delegate ===");
console.log("Transaction Signature:", transferSignature);
console.log("\nSender Token Account Data:", finalSenderToken.data);
console.log("\nRecipient Token Account Data:", finalRecipientToken.data);
// =============================================================================
// Demo Setup Helper Function
// =============================================================================
Console
Click to execute the code.

Memeriksa status delegasi

Query token account untuk melihat delegasi saat ini dan sisa allowance:

import { fetchToken } from "@solana-program/token";
const tokenAccount = await fetchToken(rpc, tokenAccountAddress);
if (tokenAccount.data.delegate) {
console.log("Delegate:", tokenAccount.data.delegate);
console.log("Remaining allowance:", tokenAccount.data.delegatedAmount);
} else {
console.log("No delegate set");
}

Demo

Check Delegation Status
// Demo Setup: Create client, mint, two token accounts (one with delegate, one without)
const { client, ataWithDelegate, ataWithoutDelegate } = await demoSetup();
// =============================================================================
// Fetch Token Accounts
// =============================================================================
// Fetch token account with delegate
const tokenWithDelegate = await fetchToken(client.runtime.rpc, ataWithDelegate);
console.log("Token Account with Delegate:", tokenWithDelegate);
// Fetch token account without delegate
const tokenWithoutDelegate = await fetchToken(
client.runtime.rpc,
ataWithoutDelegate
);
console.log("\nToken Account without Delegate:", tokenWithoutDelegate);
// =============================================================================
// Demo Setup Helper Function
// =============================================================================
Console
Click to execute the code.

Pertimbangan keamanan

Untuk pemilik akun:

  • Hanya setujui delegasi yang terpercaya
  • Tetapkan batas pengeluaran minimum yang diperlukan
  • Cabut delegasi ketika tidak lagi diperlukan
  • Pantau akun Anda untuk transfer yang tidak terduga

Untuk penyedia layanan (delegasi):

  • Komunikasikan dengan jelas batas pengeluaran yang diminta kepada pengguna
  • Terapkan manajemen kunci yang tepat untuk akun delegasi Anda
  • Lacak konsumsi allowance untuk meminta persetujuan ulang sebelum batas habis

Delegasi vs. kustodi

AspekDelegasiKustodi penuh
Kepemilikan tokenPengguna tetap memilikiPengguna mentransfer ke kustodian
Kontrol pengeluaranDibatasi pada jumlah yang disetujuiAkses penuh ke dana yang ditransfer
PencabutanInstan, oleh pemilikMemerlukan kerja sama kustodian
Eksposur risikoTerbatas pada jumlah yang disetujuiSeluruh saldo
Kepercayaan yang diperlukanTerbatasTinggi

Delegasi menyediakan jalan tengah—memungkinkan pembayaran otomatis sambil membatasi eksposur risiko pada jumlah yang disetujui.

Sumber daya terkait

Sumber dayaDeskripsi
Approve delegateCara memberikan izin kepada akun lain untuk membelanjakan dari token account Anda.
Revoke delegateCara menghapus delegasi yang ada dan mencabut izin pembelanjaannya.
Transfer tokenCara mentransfer token antar token account.

Is this page helpful?

Daftar Isi

Edit Halaman

Dikelola oleh

© 2026 Yayasan Solana.
Semua hak dilindungi.
Terhubung