支払い高度な支払い

支出権限

Solanaのトークンプログラムは委任をサポートしています。これは、指定された上限まで、あなたのトークンアカウントからトークンを転送する権限を別のアカウントに付与するものです。これにより、資金の管理権を手放すことなく、自動支払い、エスクローサービス、サードパーティ決済処理などのユースケースが可能になります。

委任の仕組み

委任先を承認すると、特定のアカウントにあなたの代わりにトークンを転送する権限を与えることになります。

  • 所有者が管理権を保持: トークンの所有権は引き続きあなたにあり、いつでも転送または取り消しが可能です
  • 支出上限の設定: 委任先は承認された金額までしか転送できません
  • アカウントごとに1つの委任先: 各トークンアカウントは、アクティブな委任先を1つだけ持つことができます
  • 新しい承認で古い承認を置き換え: 新しい委任先を承認すると、以前の委任先は自動的に取り消されます

委任は非カストディアルです。委任先は上限までトークンを使用できますが、承認された金額を超えてアカウントにアクセスしたり、資金を引き出したりすることはできません。所有者はいつでも取り消すことができます。

ビジネスユースケース

ユースケース委任の活用方法
決済処理業者加盟店が決済処理業者に取引決済の権限を付与
自動給与支払い財務部門が給与サービスに給与支払いの権限を承認
エスクローサービス購入者がエスクローエージェントに条件付きリリースの権限を委任
取引プラットフォームユーザーが取引所に代理取引の実行を承認
カード発行ユーザーがカード発行会社に、トークンアカウントへの購入請求を承認

委任先の承認

あなたのアカウントからトークンを使用する権限を別のアカウントに付与します:

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

パラメータ:

  • source: 権限を付与するトークンアカウント
  • delegate: 使用権限を持つアカウント
  • owner: トークンアカウントの現在の所有者(トランザクションに署名する必要があります)
  • amount: デリゲートが転送できる最大トークン数
  • decimals: 検証用のトークンの小数点以下桁数(小数点エラーを防ぎます)

デモ

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.

委任者の取り消し

現在の委任者からすべての使用権限を削除します。

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

取り消しは委任者の権限をすべて削除します。部分的な取り消しはできません。制限を減らす必要がある場合は、同じ委任者に対してより低い金額で承認してください。

デモ

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.

委任者としての転送

委任者として動作する場合は、標準的な転送を使用しますが、所有者ではなく委任者のkeypairで署名します。

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 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.

デリゲーションステータスの確認

トークンアカウントを照会して、現在のデリゲートと残りの許可量を確認します:

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

デモ

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.

セキュリティに関する考慮事項

アカウント所有者向け:

  • 信頼できるデリゲートのみを承認する
  • 必要最小限の支出制限を設定する
  • 不要になったデリゲーションは取り消す
  • 予期しない転送がないかアカウントを監視する

サービスプロバイダー(デリゲート)向け:

  • 要求する支出制限をユーザーに明確に伝える
  • デリゲートアカウントの適切な鍵管理を実装する
  • 許可量の消費を追跡し、制限に達する前に再承認を要求する

デリゲーションと保管の比較

項目デリゲーション完全な保管
トークンの所有権ユーザーが保持ユーザーがカストディアンに譲渡
支出管理承認額に上限あり譲渡された資金への完全なアクセス
取り消し所有者による即時実行カストディアンの協力が必要
リスクエクスポージャー承認額に限定残高全体
必要な信頼限定的高い

デリゲーションは中間的な選択肢を提供し、自動支払いを可能にしながらリスクエクスポージャーを承認額に制限します。

関連リソース

リソース説明
デリゲートの承認別のアカウントにトークンアカウントからの支出権限を付与する方法。
デリゲートの取り消し既存のデリゲートを削除し、その支出権限を取り消す方法。
トークンの転送トークンアカウント間でトークンを転送する方法。

Is this page helpful?

管理運営

© 2026 Solana Foundation.
無断転載を禁じます。
つながろう