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'uso | Come aiuta la delega |
|---|---|
| Processori di pagamento | Il commerciante concede al processore il permesso di regolare le transazioni |
| Buste paga automatizzate | La tesoreria approva il servizio di gestione stipendi per erogare i salari |
| Servizi di deposito a garanzia | L'acquirente delega all'agente di deposito a garanzia per il rilascio condizionale |
| Piattaforme di trading | L'utente approva l'exchange per eseguire operazioni per suo conto |
| Emissione di carte | L'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 accountmint: usdcMintAddress, // USDC mintdelegate: delegateAddress, // Account receiving permissionowner: ownerKeypair, // You (must sign)amount: 1_000_000_000n, // 1,000 USDC in base unitsdecimals: 6});
Parametri:
source: Il token account che concede il permessodelegate: L'account che avrà il permesso di spesaowner: Proprietario attuale del token account (deve firmare la transazione)amount: Numero massimo di token che il delegato può trasferiredecimals: Decimali del token per la validazione (previene errori decimali)
Demo
// Generate keypairs for sender and delegateconst 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 tokensconst { client, mint, senderAta } = await demoSetup(sender);console.log("\nMint Address:", mint.address);console.log("Sender ATA:", senderAta);// =============================================================================// Approve Delegate// =============================================================================// Create instruction to approve delegateconst approveInstruction = getApproveCheckedInstruction({source: senderAta,mint: mint.address,delegate: delegate.address,owner: sender,amount: 1_000_000n, // 1.0 tokens with 6 decimalsdecimals: 6});// Send approve transactionconst 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 setconst tokenData = await fetchToken(client.runtime.rpc, senderAta);console.log("\nSender Token Account Data:", tokenData.data);// =============================================================================// Demo Setup Helper Function// =============================================================================
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 accountowner: 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
// Generate keypairs for sender and delegateconst 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 tokensconst { 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 delegateconst approveInstruction = getApproveCheckedInstruction({source: senderAta,mint: mint.address,delegate: delegate.address,owner: sender,amount: 1_000_000n, // 1.0 tokens with 6 decimalsdecimals: 6});// Send approve transactionconst 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 setconst tokenDataAfterApprove = await fetchToken(client.runtime.rpc, senderAta);console.log("\nSender Token Account Data:", tokenDataAfterApprove.data);// =============================================================================// Transaction 2: Revoke Delegate// =============================================================================// Create instruction to revoke delegateconst revokeInstruction = getRevokeInstruction({source: senderAta,owner: sender});// Send revoke transactionconst 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 revokedconst tokenDataAfterRevoke = await fetchToken(client.runtime.rpc, senderAta);console.log("\nSender Token Account Data:", tokenDataAfterRevoke.data);// =============================================================================// Demo Setup Helper Function// =============================================================================
Trasferire come delegato
Quando agisci come delegato, usa un trasferimento standard ma firma con il keypair del delegato invece che con quello del proprietario:
import { getTransferCheckedInstruction } from "@solana-program/token";const transferInstruction = getTransferCheckedInstruction({source: ownerTokenAccount, // The account you have permission to spend frommint: usdcMintAddress,destination: recipientTokenAccount,authority: delegateKeypair, // You (the delegate) sign, not the owneramount: 100_000_000n, // 100 USDCdecimals: 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
// Generate keypairs for sender, delegate, and recipientconst 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 tokensconst { 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 delegateconst approveInstruction = getApproveCheckedInstruction({source: senderAta,mint: mint.address,delegate: delegate.address,owner: sender,amount: 1_000_000n, // 1.0 tokens with 6 decimalsdecimals: 6});// Send approve transactionconst 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 ownerconst transferInstruction = getTransferCheckedInstruction({source: senderAta,mint: mint.address,destination: recipientAta,authority: delegate, // Delegate signs this transactionamount: 500_000n, // 0.5 tokens with 6 decimalsdecimals: 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 signsinstructions: [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// =============================================================================
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
// 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 delegateconst tokenWithDelegate = await fetchToken(client.runtime.rpc, ataWithDelegate);console.log("Token Account with Delegate:", tokenWithDelegate);// Fetch token account without delegateconst tokenWithoutDelegate = await fetchToken(client.runtime.rpc,ataWithoutDelegate);console.log("\nToken Account without Delegate:", tokenWithoutDelegate);// =============================================================================// Demo Setup Helper Function// =============================================================================
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
| Aspetto | Delega | Custodia completa |
|---|---|---|
| Proprietà token | L'utente mantiene | L'utente trasferisce al custode |
| Controllo spesa | Limitato all'importo approvato | Accesso completo ai fondi trasferiti |
| Revoca | Istantanea, dal proprietario | Richiede cooperazione del custode |
| Esposizione al rischio | Limitata all'importo approvato | Intero saldo |
| Fiducia richiesta | Limitata | Elevata |
La delega fornisce una via di mezzo, consentendo pagamenti automatizzati limitando al contempo l'esposizione al rischio all'importo approvato.
Risorse correlate
| Risorsa | Descrizione |
|---|---|
| Approve Delegate | Come concedere a un altro account il permesso di spendere dal tuo token account. |
| Revoke Delegate | Come rimuovere un delegato esistente e revocare i suoi permessi di spesa. |
| Transfer Token | Come trasferire token tra token account. |
Is this page helpful?