Thanh toánThanh toán nâng cao

Quyền chi tiêu

Các Token Program của Solana hỗ trợ ủy quyền—cấp cho một tài khoản khác quyền chuyển token từ token account của bạn trong giới hạn được chỉ định. Điều này cho phép các trường hợp sử dụng như thanh toán tự động, dịch vụ ký quỹ và xử lý thanh toán qua bên thứ ba mà không cần từ bỏ quyền giữ quỹ của bạn.

Cách thức hoạt động của ủy quyền

Khi bạn phê duyệt một đại diện ủy quyền, bạn đang cho phép một tài khoản cụ thể chuyển token thay mặt bạn:

  • Chủ sở hữu vẫn giữ quyền kiểm soát: Bạn vẫn sở hữu token và có thể chuyển hoặc thu hồi bất cứ lúc nào
  • Giới hạn chi tiêu: Đại diện ủy quyền chỉ có thể chuyển tối đa số lượng đã được phê duyệt
  • Một đại diện ủy quyền cho mỗi tài khoản: Mỗi token account chỉ có thể có một đại diện ủy quyền đang hoạt động
  • Phê duyệt mới thay thế phê duyệt cũ: Phê duyệt đại diện ủy quyền mới sẽ tự động thu hồi đại diện trước đó

Ủy quyền không phải là hình thức giữ hộ. Đại diện ủy quyền có thể chi tiêu token trong giới hạn, nhưng không thể truy cập hoặc rút cạn tài khoản vượt quá số lượng đã được phê duyệt. Chủ sở hữu có thể thu hồi bất cứ lúc nào.

Các trường hợp sử dụng trong kinh doanh

Trường hợp sử dụngCách ủy quyền hỗ trợ
Bộ xử lý thanh toánNgười bán cấp quyền cho bộ xử lý để thanh toán giao dịch
Bảng lương tự độngKho bạc phê duyệt dịch vụ bảng lương để chi trả lương
Dịch vụ ký quỹNgười mua ủy quyền cho đại lý ký quỹ để giải ngân có điều kiện
Nền tảng giao dịchNgười dùng phê duyệt sàn giao dịch để thực hiện giao dịch thay mặt họ
Phát hành thẻNgười dùng phê duyệt nhà phát hành thẻ để tính phí mua hàng vào token account của họ

Phê duyệt đại diện ủy quyền

Cấp quyền cho tài khoản khác để chi tiêu token từ tài khoản của bạn:

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

Tham số:

  • source: Token account cấp quyền
  • delegate: Tài khoản sẽ có quyền chi tiêu
  • owner: Chủ sở hữu hiện tại của token account (phải ký giao dịch)
  • amount: Số lượng token tối đa mà delegate có thể chuyển
  • decimals: Số chữ số thập phân của token để xác thực (ngăn ngừa lỗi thập phân)

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.

Thu hồi quyền của người được ủy quyền

Xóa tất cả quyền chi tiêu khỏi người được ủy quyền hiện tại:

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

Thu hồi sẽ xóa tất cả quyền của người được ủy quyền—không có thu hồi một phần. Nếu bạn cần giảm hạn mức, hãy phê duyệt lại cùng người được ủy quyền với số lượng thấp hơn.

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.

Chuyển token với tư cách người được ủy quyền

Khi hoạt động với tư cách người được ủy quyền, sử dụng lệnh chuyển tiêu chuẩn nhưng ký bằng keypair của người được ủy quyền thay vì chủ sở hữu:

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

Giao dịch chuyển sẽ thành công nếu:

  • Tài khoản nguồn có đủ số dư
  • Người được ủy quyền ký giao dịch

Mỗi lần chuyển sẽ giảm hạn mức còn lại. Khi hạn mức về không, người được ủy quyền không thể chuyển token nữa.

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.

Kiểm tra trạng thái ủy quyền

Truy vấn token account để xem delegate hiện tại và hạn mức còn lại:

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.

Các vấn đề bảo mật cần lưu ý

Đối với chủ sở hữu tài khoản:

  • Chỉ phê duyệt các delegate đáng tin cậy
  • Đặt hạn mức chi tiêu tối thiểu cần thiết
  • Thu hồi ủy quyền khi không còn cần thiết nữa
  • Giám sát tài khoản của bạn để phát hiện các giao dịch chuyển không mong muốn

Đối với nhà cung cấp dịch vụ (delegate):

  • Thông báo rõ ràng hạn mức chi tiêu được yêu cầu cho người dùng
  • Triển khai quản lý khóa phù hợp cho tài khoản delegate của bạn
  • Theo dõi mức tiêu thụ hạn mức để yêu cầu phê duyệt lại trước khi hết hạn mức

Ủy quyền so với giữ hộ

Khía cạnhỦy quyềnGiữ hộ toàn phần
Quyền sở hữu tokenNgười dùng giữ quyềnNgười dùng chuyển cho bên giữ hộ
Kiểm soát chi tiêuGiới hạn ở số tiền được phê duyệtToàn quyền truy cập vào số tiền đã chuyển
Thu hồiNgay lập tức, bởi chủ sở hữuYêu cầu sự hợp tác của bên giữ hộ
Rủi roGiới hạn ở số tiền được phê duyệtToàn bộ số dư
Mức độ tin tưởng cầnHạn chếCao

Ủy quyền cung cấp một giải pháp trung gian—cho phép thanh toán tự động trong khi giới hạn rủi ro ở mức số tiền được phê duyệt.

Tài nguyên liên quan

Tài nguyênMô tả
Approve DelegateCách cấp quyền cho tài khoản khác để chi tiêu từ token account của bạn.
Revoke DelegateCách xóa delegate hiện có và thu hồi quyền chi tiêu của nó.
Transfer TokenCách chuyển token giữa các token account.

Is this page helpful?

Quản lý bởi

© 2026 Solana Foundation.
Đã đăng ký bản quyền.
Kết nối