PagamentiPagamenti avanzati

Permessi di spesa

I Token Programs di Solana supportano la delega—concedere a un altro account il permesso di trasferire token dal tuo token account fino a un limite specificato. Questo abilita casi d'uso come pagamenti automatizzati, servizi di deposito a garanzia e elaborazione di pagamenti da parte di terzi senza rinunciare alla custodia dei tuoi fondi.

Come funziona la delega

Quando approvi un delegato, stai autorizzando un account specifico a trasferire token per tuo conto:

  • Il proprietario mantiene la custodia: possiedi ancora i token e puoi trasferirli o revocare in qualsiasi momento
  • Spesa limitata: il delegato può trasferire solo fino all'importo approvato
  • Un solo delegato per account: ogni token account può avere un solo delegato attivo
  • La nuova approvazione sostituisce la precedente: approvare un nuovo delegato revoca automaticamente quello precedente

La delega è non-custodial. Il delegato può spendere token fino al limite, ma non può accedere o svuotare l'account oltre l'importo approvato. Il proprietario può revocare in qualsiasi momento.

Casi d'uso aziendali

Caso d'usoCome aiuta la delega
Processori di pagamentoIl commerciante concede al processore il permesso di regolare le transazioni
Buste paga automatizzateLa tesoreria approva il servizio di gestione stipendi per erogare i salari
Servizi di deposito a garanziaL'acquirente delega all'agente di deposito a garanzia per il rilascio condizionale
Piattaforme di tradingL'utente approva l'exchange per eseguire operazioni per suo conto
Emissione di carteL'utente approva l'emittente della carta per addebitare gli acquisti sul suo token account

Approvare un delegato

Concedi a un altro account il permesso di spendere token dal tuo account:

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

Parametri:

  • source: Il token account che concede il permesso
  • delegate: L'account che avrà il permesso di spesa
  • owner: Proprietario attuale del token account (deve firmare la transazione)
  • amount: Numero massimo di token che il delegato può trasferire
  • decimals: Decimali del token per la validazione (previene errori decimali)

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.

Revocare un delegato

Rimuovi tutti i permessi di spesa dal delegato corrente:

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

La revoca rimuove tutti i permessi del delegato—non esiste una revoca parziale. Se devi ridurre il limite, approva lo stesso delegato con un importo inferiore.

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.

Trasferire come delegato

Quando agisci come delegato, usa un trasferimento standard ma firma con il keypair del delegato invece che con quello del proprietario:

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

Il trasferimento avrà successo se:

  • L'account sorgente ha un saldo sufficiente
  • Il delegato firma la transazione

Ogni trasferimento riduce l'allowance rimanente. Quando l'allowance raggiunge zero, il delegato non può più trasferire 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.

Verificare lo stato della delega

Interroga un token account per vedere il suo delegato attuale e l'allowance rimanente:

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.

Considerazioni sulla sicurezza

Per i proprietari degli account:

  • Approva solo delegati fidati
  • Imposta il limite di spesa minimo necessario
  • Revoca le deleghe quando non sono più necessarie
  • Monitora i tuoi account per trasferimenti inattesi

Per i fornitori di servizi (delegati):

  • Comunica chiaramente il limite di spesa richiesto agli utenti
  • Implementa una corretta gestione delle chiavi per il tuo account delegato
  • Monitora il consumo dell'allowance per richiedere una nuova approvazione prima che i limiti si esauriscano

Delega vs. custodia

AspettoDelegaCustodia completa
Proprietà tokenL'utente mantieneL'utente trasferisce al custode
Controllo spesaLimitato all'importo approvatoAccesso completo ai fondi trasferiti
RevocaIstantanea, dal proprietarioRichiede cooperazione del custode
Esposizione al rischioLimitata all'importo approvatoIntero saldo
Fiducia richiestaLimitataElevata

La delega fornisce una via di mezzo, consentendo pagamenti automatizzati limitando al contempo l'esposizione al rischio all'importo approvato.

Risorse correlate

RisorsaDescrizione
Approve DelegateCome concedere a un altro account il permesso di spendere dal tuo token account.
Revoke DelegateCome rimuovere un delegato esistente e revocare i suoi permessi di spesa.
Transfer TokenCome trasferire token tra token account.

Is this page helpful?

Indice

Modifica Pagina

Gestito da

© 2026 Solana Foundation.
Tutti i diritti riservati.
Rimani Connesso