19 minutos de lectura
Esta guía está disponible en las versiones de Solana Web3.js (versión heredada 1.x) y Solana Kit (v. 2.x). Selecciona la pestaña correspondiente para ver los fragmentos de código y las instrucciones de la biblioteca que prefieras:
- Kit Solana
- Solana Web3.js (versión anterior)
Resumen
El envío de tokens de la biblioteca de programas de Solana (SPL) es un mecanismo fundamental para el desarrollo en Solana. Tanto si estás realizando un airdrop de tokens de la lista blanca a tu comunidad, como si estás enviando NFT de forma masiva a otra cartera o gestionando flujos de tokens entre cuentas de depósito en garantía, inevitablemente necesitarás poder transferir tokens SPL. La transferencia de tokens SPL es ligeramente diferente al envío de SOL, por lo que es esencial comprender cómo funciona a medida que avanzas en tu trayectoria de desarrollo en Solana.
Tus funciones
En esta guía, utilizarás TypeScript para escribir un script que transfiera un token SPL de una cuenta a otra en la red de desarrollo de Solana.
Si quieres saber cómo transferir tokens SPL y SOL en un programa utilizando el marco Anchor, echa un vistazo a nuestra guía: «Cómo transferir SOL y tokens SPL utilizando Anchor» .
¿Prefieres un tutorial en vídeo? Sigue los pasos de Sahil y aprende a transferir tokens SPL en Solana Devnet.
Lo que necesitarás
Resumen de las cuentas de tokens SPL
Antes de empezar, conviene comprender cómo funcionan algunos componentes de la cuenta del Programa de tokens de Solana: los ID de acuñación y las cuentas de tokens asociadas.
Identificadores de Mint
Cada token SPL tiene un ID de acuñación único que permite distinguirlo de cualquier otro tipo de token. Por ejemplo, el ID de acuñación del token SPL $USDC es EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v y el del token SPL $SAMO es 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU.
Cabe destacar que cada NFT tiene una dirección de acuñación única (lo que, en parte, lo convierte en no fungible). Por ejemplo, el Famous Fox n.º 4679 tiene un ID de acuñación de GS2AtoEoL9DgaYg9xC7cUumftB7vb2CPMrczZCKgJv1Y y el Famous Fox n.º 6562 tiene un ID de acuñación de 7FTdQdMqkk5Xc2oFsYR88BuJt2yyCPReTpqr3viH6b6C. Como verás en un momento, esta es una diferencia significativa entre los dos tokens.
Si quieres saber más sobre la emisión de tokens SPL, echa un vistazo a nuestras guías sobre Cómo crear un token SPL fungible con el nuevo estándar de tokens Metaplex y Cómo acuñar un NFT en Solana.
Cuentas de tokens asociadas
El Programa de Tokens de Solana genera «una clave de cuenta de token a partir de la dirección de la cuenta principal del sistema del usuario y de una dirección de acuñación de tokens, lo que permite al usuario crear una cuenta de token principal para cada token que posea» (Fuente: spl.solana.com). A esa cuenta se la denomina «Cuenta de Token Asociada» o «ATA». En la práctica, una ATA es una cuenta única vinculada a un usuario y a una acuñación de tokens específica. Por ejemplo, supongamos que soy el titular de la cuenta «DEMO...1234». Puedo tener muchas ATA: una por cada emisión de token que posea (por ejemplo, una ATA única para cada $USDC, $SAMO, etc., tal y como se ilustra a continuación).

Las transferencias de tokens siempre deben realizarse entre dos cuentas ATA asociadas a la misma dirección de emisión. Esto significa que no podemos enviar $USDC desde mi cuenta ATA a tu cuenta ATA de $SAMO (véase el ejemplo a continuación).

Como verás en nuestro código dentro de un momento, no todas las cuentas disponen ya de un ATA para cada casa de moneda. Si un usuario no ha interactuado antes con un token, el remitente debe «crearlo» y depositar la cuota necesaria para que la cuenta permanezca activa.
Este concepto puede resultar complicado al principio, pero es importante, ¡así que tómate tu tiempo para asegurarte de que lo entiendes bien! A mí me resulta útil echar un vistazo a mi monedero en Solana Explorer, en la página de detalles de los tokens: https://explorer.solana.com/address/YOUR_WALLET_ADDRESS/tokens?display=detail. Allí podrás ver cada uno de tus ATA, su ID de cuenta y el ID de acuñación asociado:

Si quieres profundizar un poco más en la biblioteca del Programa de tokens SPL de Solana, visita spl.solana.com.
¿Listo para empezar a programar? ¡Yo también!
Configura tu proyecto
- Kit Solana
- Solana Web3.js (versión anterior)
Crea un nuevo directorio de proyecto en tu terminal con:
mkdir spl-transfer-kit
cd spl-transfer-kit
Crea un archivo para tu aplicación, app.ts:
echo > app.ts
Inicializa tu proyecto con el indicador «yes» para utilizar los valores predeterminados en tu nuevo paquete:
yarn init --yes
#o
npm init --yes
Crea un archivo tsconfig.json con resolución de módulos moderna:
tsc --init
Actualiza tu archivo tsconfig.json con el siguiente contenido:
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"noEmit": true,
"target": "ESNext"
}
}
Instalar las dependencias de Solana Kit
Para este ejercicio, tendremos que añadir Solana Kit y la biblioteca del programa Token. Escribe lo siguiente en tu terminal:
yarn add @solana/kit @solana-program/token
#o
npm install @solana/kit @solana-program/token
Crea un nuevo directorio de proyecto en tu terminal con:
mkdir spl-transfer
cd spl-transfer
Crea un archivo para tu aplicación, app.ts:
echo > app.ts
Inicializa tu proyecto con el indicador «yes» para utilizar los valores predeterminados en tu nuevo paquete:
yarn init --yes
#o
npm init --yes
Crea un archivo tsconfig.json con la importación de .json habilitada:
tsc -init --resolveJsonModule true
Instalar la dependencia de Solana Web3
Para este ejercicio, tendremos que añadir las bibliotecas Solana Web3 y SPL Token. Escribe lo siguiente en tu terminal:
yarn add @solana/web3.js@1 @solana/spl-token
#o
npm install @solana/web3.js@1 @solana/spl-token
Crea un monedero y recibe SOL mediante airdrop
- Kit Solana
- Solana Web3.js (versión anterior)
Lo primero que tendremos que hacer es crear una cuenta con un monedero y recargarla. Utilizaremos la práctica herramienta que aparece a continuación para generar automáticamente un nuevo monedero y recibir un airdrop de 1 SOL en él.
Nota: Enviar solicitudes de airdrop con demasiada frecuencia puede provocar un error 429 (demasiadas solicitudes).
Una vez que hayas generado correctamente tu par de claves, verás que aparecen dos nuevas constantes: secreto y FROM_KEYPAIR, un par de claves. El secreto es una matriz de 32 bytes que se utiliza para generar las claves pública y privada. La FROM_KEYPAIR es una instancia de Keypair que se utiliza para firmar transacciones (hemos repartido algunos SOL de la red de desarrollo para cubrir las comisiones de gas). Asegúrate de añadirla a tu código debajo de las demás constantes si aún no lo has hecho.
Debajo de las importaciones, pega tu nueva matriz secreta:
const secreto = [0,...,0]; // 👈 Sustituye por tu clave secreta
Lo primero que tendremos que hacer es crear una cuenta con un monedero y recargarla. Utilizaremos la práctica herramienta que aparece a continuación para generar automáticamente un nuevo monedero y recibir un airdrop de 1 SOL en él. (También puedes hacerlo con el Keypair.generate() y requestAirdrop() funciones, si prefieres un enfoque más manual).
Nota: Enviar solicitudes de airdrop con demasiada frecuencia puede provocar un error 429 (demasiadas solicitudes).
Una vez que hayas generado correctamente tu par de claves, verás que aparecen dos nuevas constantes: secreto y FROM_KEYPAIR, un par de claves. El secreto es una matriz de 32 bytes que se utiliza para generar las claves pública y privada. La FROM_KEYPAIR es una instancia de Keypair que se utiliza para firmar transacciones (hemos repartido algunos SOL de la red de desarrollo para cubrir las comisiones de gas). Asegúrate de añadirla a tu código debajo de las demás constantes si aún no lo has hecho.
Debajo de tus importaciones, pega tu nuevo secreto y añade:
import { Keypair } from "@solana/web3.js";
const secret = [0,...,0]; // 👈 Replace with your secret
const FROM_KEYPAIR = Keypair.fromSecretKey(new Uint8Array(secret));
console.log(`My public key is: ${FROM_KEYPAIR.publicKey.toString()}.`);
Emitir o distribuir mediante airdrop algunos tokens SPL
Para completar esta guía, necesitarás algunas fichas SPL en Devnet. Hay varias formas de conseguir fichas SPL de Devnet; a continuación te indicamos algunas.
- Crea tus propios tokens fungibles (Guía: Cómo crear un token SPL fungible con el nuevo estándar de tokens Metaplex).
- Crea uno o varios NFT con Candy Machine (Guía: Cómo implementar una colección de NFT en Solana utilizando Sugar (Candy Machine)).
- Solicita un airdrop de tokens $DUMMY desde un «faucet» de tokens SPL.*
- Si ya tienes tokens SPL de Devnet en otra cartera, puedes enviarlos utilizando Phantom u otra interfaz de cartera.*
Antes de continuar, deberías poder acceder a Solana Explorer y comprobar que tu monedero tiene un saldo en SOL y al menos un token SPL en la red de desarrollo (https://explorer.solana.com/address/YOUR_WALLET_ADDRESS/tokens?cluster=devnet). Debería tener un aspecto similar a este:

Empecemos.
Configura tu aplicación
Importar las dependencias necesarias
- Kit Solana
- Solana Web3.js (versión anterior)
Abre el archivo app.ts y pega las siguientes importaciones en la línea 1:
import {
createSolanaRpc,
createSolanaRpcSubscriptions,
address,
pipe,
createTransactionMessage,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstruction,
signTransactionMessageWithSigners,
sendAndConfirmTransactionFactory,
airdropFactory,
lamports,
getSignatureFromTransaction,
createKeyPairFromBytes,
createSignerFromKeyPair
} from '@solana/kit';
import {
TOKEN_PROGRAM_ADDRESS,
fetchToken,
getTransferInstruction,
findAssociatedTokenPda,
getCreateAssociatedTokenIdempotentInstruction
} from '@solana-program/token';
Además del monedero que hemos creado en el paso anterior, vamos a importar métodos y clases esenciales de Solana Kit y de la biblioteca de programas Token.
Abre el archivo app.ts y pega las siguientes importaciones en la línea 1:
import { getOrCreateAssociatedTokenAccount, createTransferInstruction } from "@solana/spl-token";
import { Connection, Keypair, ParsedAccountData, PublicKey, sendAndConfirmTransaction, Transaction } from "@solana/web3.js";
Además del monedero que hemos creado en el paso anterior, también vamos a importar algunos métodos y clases esenciales de la biblioteca Solana Web3.
Configura tu punto de acceso de Quicknode
- Kit Solana
- Solana Web3.js (versión anterior)
Para desarrollar en Solana, necesitarás un punto final de API para conectarte a la red. Puedes utilizar nodos públicos o implementar y gestionar tu propia infraestructura; sin embargo, si quieres tiempos de respuesta 8 veces más rápidos, puedes dejarnos a nosotros el trabajo pesado. Descubre por qué más del 50 % de los proyectos en Solana eligen Quicknode y regístrate aquí para crear una cuenta. Vamos a utilizar un nodo de Solana Devnet.
Copia el enlace del proveedor HTTP:

En el archivo app.ts, debajo de las declaraciones de importación, declara tu RPC y establece la conexión con Solana:
const QUICKNODE_RPC = 'https://example.solana-devnet.quiknode.pro/0123456/';
const QUICKNODE_RPC_SUBSCRIPTIONS = 'wss://example.solana-devnet.quiknode.pro/0123456/';
const rpc = createSolanaRpc(QUICKNODE_RPC);
const rpcSubscriptions = createSolanaRpcSubscriptions(QUICKNODE_RPC_SUBSCRIPTIONS);
const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
Asegúrate de sustituir el QUICKNODE_RPC y QUICKNODE_RPC_SUBSCRIPTIONS con tus URL de punto final de Quicknode reales (enlaces https y wss del panel de control de Quicknode).
Para desarrollar en Solana, necesitarás un punto final de API para conectarte a la red. Puedes utilizar nodos públicos o implementar y gestionar tu propia infraestructura; sin embargo, si quieres tiempos de respuesta 8 veces más rápidos, puedes dejarnos a nosotros el trabajo pesado. Descubre por qué más del 50 % de los proyectos en Solana eligen Quicknode y regístrate aquí para crear una cuenta. Vamos a utilizar un nodo de Solana Devnet.
Copia el enlace del proveedor HTTP:

En el archivo app.ts, debajo de las declaraciones de importación, declara tu RPC y establece la conexión con Solana:
const QUICKNODE_RPC = 'https://example.solana-devnet.quiknode.pro/0123456/';
const SOLANA_CONNECTION = new Connection(QUICKNODE_RPC);
Declarar variables
- Kit Solana
- Solana Web3.js (versión anterior)
Vas a tener que declarar algunas variables para ejecutar tu script: tu cuenta de destino (el titular al que deseas transferir los tokens), la dirección de acuñación del token que vas a transferir y el número de tokens que vas a transferir. Añade las siguientes declaraciones debajo de tu configuración RPC:
const CARTERA_DE_DESTINO = dirección('DemoKMZWkk483hX4mUrcJoo3zVvsKhm8XXs28TuwZw9H');
const MINT_ADDRESS = dirección('DoJuta7joTSuuoozqQtjtnASRYiVsT435gh4srh5LLGK'); //¡Debes cambiar este valor!
const TRANSFER_AMOUNT = 1n; // Uso de BigInt para importes precisos de tokens
Sustituir MINT_ADDRESS con la dirección de acuñación del token que quieres enviar. Si no conoces la dirección de acuñación de tu token, puedes ir a https://explorer.solana.com/address/YOUR_WALLET_ADDRESS/tokens?cluster=devnet y haz clic en el Copiar icono para obtener tu dirección de Mint. Pégala en el MINT_ADDRESS variable.

Nota: También puedes actualizar tu DESTINATION_WALLET y el TRANSFER_AMOUNT si lo deseas, aunque ambos valores servirán para este ejemplo.
Vas a tener que declarar algunas variables para ejecutar tu script: tu cuenta de destino (el titular al que deseas transferir los tokens), la dirección de acuñación del token que vas a transferir y el número de tokens que vas a transferir. Añade las siguientes declaraciones a continuación SOLANA_CONNECTION:
const CARTERA_DE_DESTINO = 'DemoKMZWkk483hX4mUrcJoo3zVvsKhm8XXs28TuwZw9H';
const DIRECCIÓN_DE_EMISIÓN = 'DoJuta7joTSuuoozqQtjtnASRYiVsT435gh4srh5LLGK'; //¡Debes cambiar este valor!
const TRANSFER_AMOUNT = 1;
Sustituir MINT_ADDRESS con la dirección de acuñación del token que quieres enviar. Si no conoces la dirección de acuñación de tu token, puedes ir a https://explorer.solana.com/address/YOUR_WALLET_ADDRESS/tokens?cluster=devnet y haz clic en el Copiar icono para obtener tu dirección de Mint. Pégala en el MINT_ADDRESS variable.

Nota: También puedes actualizar tu DESTINATION_WALLET y el TRANSFER_AMOUNT si lo deseas, aunque ambos valores servirán para este ejemplo.
Obtener el número de decimales
- Kit Solana
- Solana Web3.js (versión anterior)
Si ya has creado alguna vez un token SPL fungible, sabrás que los decimales son importantes. Dado que la cadena representa el suministro de tokens como un valor entero, debemos convertir la cantidad de tokens en función del número de decimales asignados en los metadatos del token (por ejemplo, si una emisión tiene tres decimales, debemos enviar 1.000 unidades para transferir efectivamente un token [1.000 / 10**3]).
Para obtener los decimales, llamaremos a «getAccountInfo» en nuestra instancia de RPC y analizaremos los datos de la cuenta de Mint. Añade esta función debajo de tus declaraciones:
async function getNumberDecimals(mintAddress) {
// getAccountInfo defaults to binary, using `jsonParsed` lets us read parsed.info.decimals without manual byte offsets.
const accountInfo = await rpc.getAccountInfo(mintAddress, { encoding: 'jsonParsed' }).send();
const data = accountInfo.value?.data;
if (!data || !('parsed' in data) || !data.parsed?.info) {
throw new Error('Failed to find mint account');
}
return (data.parsed.info as { decimals: number }).decimals;
}
Técnicamente, no es necesario si conoces el número de decimales de tu emisión de tokens (puedes encontrarlo en la página del token en Solana Explorer). No obstante, nos gusta incluirlo, ya que te permite adaptar tu código a diferentes emisiones sin tener que modificar ninguna otra variable.
¡Vamos a lo divertido!
Si ya has creado alguna vez un token SPL fungible, sabrás que los decimales son importantes. Dado que la cadena representa el suministro de tokens como un valor entero, debemos convertir la cantidad de tokens en función del número de decimales asignados en los metadatos del token (por ejemplo, si una emisión tiene tres decimales, debemos enviar 1.000 unidades para transferir efectivamente un token [1.000 / 10**3]).
Para obtener los decimales, llamaremos a getParsedAccountInfo en SOLANA_CONNECTION y le pasaremos el token MINT_ADDRESS. Dado que el método puede devolver varios tipos, debemos declarar nuestro tipo como ParsedAccountData para analizar los datos de forma eficaz. Añade esta función debajo de tus declaraciones:
async function getNumberDecimals(mintAddress: string):Promise<number> {
const info = await SOLANA_CONNECTION.getParsedAccountInfo(new PublicKey(MINT_ADDRESS));
const result = (info.value?.data as ParsedAccountData).parsed.info.decimals as number;
return result;
}
Técnicamente, no es necesario si conoces el número de decimales de tu emisión de tokens (puedes encontrarlo en la página del token en Solana Explorer). No obstante, nos gusta incluirlo, ya que te permite adaptar tu código a diferentes emisiones sin tener que modificar ninguna otra variable.
¡Vamos a lo divertido!
Crear función de transferencia
- Kit Solana
- Solana Web3.js (versión anterior)
Crea una nueva función asíncrona, ` sendTokens`:
asíncrono función sendTokens() {
}
En primer lugar, tenemos que crear nuestro firmante de pares de claves a partir del array «secret» y recargarlo con SOL. Dentro de la función «sendTokens», añade el paso 1:
console.log(`Sending ${TRANSFER_AMOUNT} ${MINT_ADDRESS} to ${DESTINATION_WALLET}.`)
//Step 1
console.log(`1 - Creating keypair and funding with SOL`);
const keyPair = await createKeyPairFromBytes(new Uint8Array(secret));
const FROM_KEYPAIR = await createSignerFromKeyPair(keyPair);
// Fund the keypair with SOL for transaction fees
// (you can skip this step if you already have devnet SOL in your FROM_KEYPAIR)
await airdropFactory({ rpc, rpcSubscriptions })({
recipientAddress: FROM_KEYPAIR.address,
lamports: lamports(1_000_000_000n), // 1 SOL
commitment: 'confirmed',
});
console.log(` From wallet: ${FROM_KEYPAIR.address}`);
Nota: En un entorno de producción, se utilizaría
generateKeyPairFromBytes(new Uint8Array(secret))utilizando tu clave secreta real en lugar de generar una nueva.
A continuación, calcularemos las cuentas de tokens asociadas («ATA») para nuestras cuentas de origen y destino. Recuerda que cada cuenta debe tener una ATA que asocie un monedero con una emisión; una ATA solo puede contener tokens de una única emisión; y la emisión de las cuentas de tokens asociadas tanto del remitente como del destinatario debe ser la misma. Añade el paso 2:
//Step 2
console.log(`2 - Deriving Associated Token Accounts`);
const [sourceTokenAccount] = await findAssociatedTokenPda({
owner: FROM_KEYPAIR.address,
mint: MINT_ADDRESS,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
});
const [destinationTokenAccount] = await findAssociatedTokenPda({
owner: DESTINATION_WALLET,
mint: MINT_ADDRESS,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
});
console.log(` Source Token Account: ${sourceTokenAccount}`);
console.log(` Destination Token Account: ${destinationTokenAccount}`);
A continuación, debemos comprobar si la cuenta del token de destino existe y crearla si es necesario. Añadir el paso 3:
console.log(`3 - Checking Destination Token Account`);
let needsDestinationAccount = false;
try {
await rpc.getAccountInfo(destinationTokenAccount).send();
} catch (error) {
needsDestinationAccount = true;
}
if (needsDestinationAccount) {
console.log(` Destination token account does not exist, will create it`);
} else {
console.log(` Destination token account exists`);
}
Obtengamos el número de decimales para calcular correctamente la cantidad. Añade el paso 4:
//Step 4
console.log(`4 - Fetching Number of Decimals for Mint: ${MINT_ADDRESS}`);
const numberDecimals = await getNumberDecimals(MINT_ADDRESS);
console.log(` Number of Decimals: ${numberDecimals}`);
const transferAmountWithDecimals = TRANSFER_AMOUNT * BigInt(Math.pow(10, numberDecimals));
Por último, tenemos que compilar y enviar nuestra transacción utilizando el enfoque funcional de Solana Kit. Añade el paso 5:
//Step 5
console.log(`5 - Creating and Sending Transaction`);
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(FROM_KEYPAIR, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => {
// Add create ATA instruction if needed
if (needsDestinationAccount) {
return appendTransactionMessageInstruction(
getCreateAssociatedTokenIdempotentInstruction({
payer: FROM_KEYPAIR,
ata: destinationTokenAccount,
owner: DESTINATION_WALLET,
mint: MINT_ADDRESS,
}),
tx
);
}
return tx;
},
(tx) => appendTransactionMessageInstruction(
getTransferInstruction({
source: sourceTokenAccount,
destination: destinationTokenAccount,
authority: FROM_KEYPAIR,
amount: transferAmountWithDecimals,
}),
tx
)
);
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
await sendAndConfirmTransaction(signedTransaction, { commitment: 'confirmed' });
const signature = await getSignatureFromTransaction(signedTransaction);
console.log(
'\x1b[32m', //Green Text
` Transaction Success!🎉`,
`\n https://explorer.solana.com/tx/${signature}?cluster=devnet`
);
Crea una nueva función asíncrona, ` sendTokens`:
asíncrono función sendTokens() {
}
En primer lugar, tendremos que obtener las cuentas de tokens asociadas («ATA») para nuestras cuentas de origen y destino. Recuerda que cada cuenta debe tener una ATA que asocie un monedero con una emisión; una ATA solo puede contener tokens de una única emisión; y la emisión de las cuentas de tokens asociadas tanto del remitente como del destinatario debe ser la misma.
Utilizaremos getOrCreateAssociatedTokenAccount para obtener el ATA (o crearlo si no existe) de cada parte de esta transacción. Dado que es posible que tengamos que crear una cuenta asociada para estas transacciones, es posible que nuestro pagador tenga que depositar una pequeña cantidad de SOL en el nuevo ATA para cubrir el alquiler. Dentro de `sendTokens`, añade el paso 1 a tu código para recuperar nuestra cuenta de origen (técnicamente, como sabemos que ya tenemos tokens SPL —ya tenemos una ATA—, también podríamos utilizar `getAssociatedTokenAddress`):
console.log(`Sending ${TRANSFER_AMOUNT} ${(MINT_ADDRESS)} from ${(FROM_KEYPAIR.publicKey.toString())} to ${(DESTINATION_WALLET)}.`)
//Step 1
console.log(`1 - Getting Source Token Account`);
let sourceAccount = await getOrCreateAssociatedTokenAccount(
SOLANA_CONNECTION,
FROM_KEYPAIR,
new PublicKey(MINT_ADDRESS),
FROM_KEYPAIR.publicKey
);
console.log(` Source Account: ${sourceAccount.address.toString()}`);
Haremos lo mismo con nuestra cuenta de destino. Añade el paso 2 que aparece a continuación para obtener o crear nuestra cuenta de destino (el ATA del destinatario al que se enviarán los tokens):
//Step 2
console.log(`2 - Getting Destination Token Account`);
let destinationAccount = await getOrCreateAssociatedTokenAccount(
SOLANA_CONNECTION,
FROM_KEYPAIR,
new PublicKey(MINT_ADDRESS),
new PublicKey(DESTINATION_WALLET)
);
console.log(` Destination Account: ${destinationAccount.address.toString()}`);
Solo nos falta un dato más para completar nuestra transacción. ¿Te acuerdas de la función `getNumberDecimals ` que creamos? Vamos a llamarla y a guardar el valor devuelto en una constante, ` numberDecimals`:
//Step 3
console.log(`3 - Fetching Number of Decimals for Mint: ${MINT_ADDRESS}`);
const numberDecimals = await getNumberDecimals(MINT_ADDRESS);
console.log(` Number of Decimals: ${numberDecimals}`);
Por último, tenemos que compilar y enviar nuestra transacción. Añade el siguiente código de compilación debajo del paso 3:
//Paso 4
console.log(`4 - Creación y envío de transacciones`);
const tx = new Transaction();
tx.añadir(createTransferInstruction(
cuentaDeOrigen.dirección,
cuentaDestino.dirección,
PAR DE CLAVES DE ORIGEN.clave_pública,
IMPORTE_DE_LA_TRANSFERENCIA * Math.pow(10, númeroDecimales)
))
- Kit Solana
- Solana Web3.js (versión anterior)
Lo que estamos haciendo aquí es indicar a nuestra aplicación que transfiera tokens por valor de TRANSFER_AMOUNT (ten en cuenta que debemos multiplicar por 10 elevado a numberDecimals) desde la cuenta sourceTokenAccount a la cuenta destinationTokenAccount.
El enfoque de Solana Kit utiliza un estilo de programación funcional con el tubo función para crear la transacción paso a paso. Esto proporciona una mayor seguridad de tipos y hace que el proceso de creación de la transacción sea más explícito. También nos encargamos de crear el ATA de destino si no existe dentro de la misma transacción mediante la instrucción idempotente, que no dará error si la cuenta ya existe.
No te fijes en ese «console.log»: solo es un truco para que el resultado aparezca en verde.
Lo que estamos haciendo aquí es indicar a nuestra aplicación que transfiera tokens por valor de TRANSFER_AMOUNT (ten en cuenta que debemos multiplicar por 10 elevado a numberDecimals) desde la cuenta de origen (sourceAccount) que hemos obtenido hasta la cuenta de destino (destinationAccount) que también hemos obtenido.
Para seguir las mejores prácticas, deberíamos obtener un hash de bloque reciente antes de enviar nuestra transacción. Añade este fragmento de código al final del paso 4 de tu función `sendTokens`:
const latestBlockHash = await SOLANA_CONNECTION.getLatestBlockhash('confirmed');
tx.recentBlockhash = await latestBlockHash.blockhash;
const signature = await sendAndConfirmTransaction(SOLANA_CONNECTION,tx,[FROM_KEYPAIR]);
console.log(
'\x1b[32m', //Green Text
` Transaction Success!🎉`,
`\n https://explorer.solana.com/tx/${signature}?cluster=devnet`
);
No te fijes en ese «console.log»: solo es un truco para que el resultado aparezca en verde.
🏃♂️ Ejecuta tu código
- Kit Solana
- Solana Web3.js (versión anterior)
Por último, al final de tu código, llama a sendTokens:
sendTokens().catch(console.error);
En tu terminal, ejecuta el código escribiendo:
ts-node app.ts
¡Enhorabuena! Si has seguido los pasos anteriores, deberías ver algo como esto:

Por último, al final de tu código, llama a sendTokens:
sendTokens();
En tu terminal, ejecuta el código escribiendo:
ts-node app.ts
¡Enhorabuena! Si has seguido los pasos anteriores, deberías ver algo como esto:

Próximos pasos y resumen
¡Genial! ¡Ya sabes cómo transferir tokens SPL de un usuario a otro! ¿Quieres ir un paso más allá? Aquí tienes un par de ideas para llevar esto un poco más lejos:
-
¿Puedes escribir un script que transfiera todos tus NFT a otra cartera? (Pista: quizá te convenga informarte primero sobre cómo recuperar todos los tokens de la cartera de un usuario ).
-
¿Podrías escribir un script para distribuir tokens SPL mediante airdrop a varias carteras que puedan o no tener un ATA asociado a tu acuñación? (Pista: echa un vistazo a nuestra guía sobre cómo enviar distribuciones masivas de SOL para inspirarte).
Si lo pruebas o tienes alguna pregunta que hacernos, ¡dínoslo! ¡Síguenos en Discord y Twitter!
¡Nos encanta recibir comentarios!
Si tienes algún comentario o sugerencia sobre nuevos temas, no dudes en hacérnoslo saber. Nos encantaría saber tu opinión.
