En la sección anterior, aprendiste cómo leer datos de la red de Solana mediante la consulta de cuentas. Para escribir datos en la red de Solana se necesita una transacción. Una transacción contiene una o más instrucciones, y cada instrucción invoca un programa.
Los programas definen la lógica de negocio de cada instrucción. Cuando envías una transacción, el runtime de Solana ejecuta las instrucciones de la transacción en orden. Las transacciones son atómicas: o todas las instrucciones de la transacción se ejecutan correctamente, o la transacción completa falla.
Los ejemplos de esta sección muestran cómo:
- Transferir SOL entre cuentas
- Crear un nuevo token mint
Transferir SOL
El siguiente ejemplo transfiere SOL de una cuenta a otra. Solo el programa designado como propietario de una cuenta puede modificar los datos de esa cuenta o deducir lamports de su saldo. Las cuentas de billetera son propiedad del System Program, por lo que transferir SOL entre cuentas de billetera requiere una instrucción que invoque la instrucción transfer del System Program. La cuenta de origen también debe firmar la transacción.
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";import { getTransferSolInstruction } from "@solana-program/system";const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));const receiver = await generateKeyPairSigner();const transferInstruction = getTransferSolInstruction({source: client.payer,destination: receiver.address,amount: lamports(10_000_000n)});const result = await client.sendTransaction([transferInstruction]);console.log("Transaction Signature:", result.context.signature);const { value: senderBalance } = await client.rpc.getBalance(client.payer.address).send();const { value: receiverBalance } = await client.rpc.getBalance(receiver.address).send();console.log("Sender Balance:", senderBalance);console.log("Receiver Balance:", receiverBalance);
Crea un cliente de Kit para el validator de pruebas local. Este fragmento añade un firmante pagador, se conecta al endpoint RPC local, habilita los airdrops y financia al pagador con SOL de prueba para la transferencia.
const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));
Genera un firmante para el receptor. El remitente es client.payer, que fue
creado por generatedPayer() y financiado por airdropPayer().
const receiver = await generateKeyPairSigner();
El helper getTransferSolInstruction() crea una instrucción de System Program.
La instrucción transfiere SOL desde el firmante source hacia
la dirección destination por la cantidad especificada
de amount lamports.
const transferInstruction = getTransferSolInstruction({source: client.payer,destination: receiver.address,amount: lamports(10_000_000n)});
Llama a client.sendTransaction() con un array de instrucciones. El cliente de
Kit convierte las instrucciones en una sola transacción, firma con los firmantes
adjuntos a las instrucciones, envía la transacción y espera la confirmación.
const result = await client.sendTransaction([transferInstruction]);console.log("Transaction Signature:", result.context.signature);
Después de que la transacción sea confirmada, obtén ambos saldos usando
client.rpc.
const { value: senderBalance } = await client.rpc.getBalance(client.payer.address).send();const { value: receiverBalance } = await client.rpc.getBalance(receiver.address).send();
Crear un token
El siguiente ejemplo crea un nuevo mint de token usando el Token Extensions Program. Una mint account es la cuenta que define la configuración global de un token, como los decimales, el suministro, la autoridad de emisión y la autoridad de congelación.
Crear una mint account requiere dos instrucciones:
- Invocar el System Program para crear una nueva cuenta propiedad del Token Extensions Program.
- Invocar el Token Extensions Program para inicializar esa cuenta como un mint.
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";import { getCreateAccountInstruction } from "@solana-program/system";import {fetchMint,getInitializeMintInstruction,getMintSize,TOKEN_2022_PROGRAM_ADDRESS} from "@solana-program/token-2022";const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));const mint = await generateKeyPairSigner();const space = BigInt(getMintSize());const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();const createAccountInstruction = getCreateAccountInstruction({payer: client.payer,newAccount: mint,space,lamports: rent,programAddress: TOKEN_2022_PROGRAM_ADDRESS});const initializeMintInstruction = getInitializeMintInstruction({mint: mint.address,decimals: 2,mintAuthority: client.payer.address,freezeAuthority: client.payer.address,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS});const result = await client.sendTransaction([createAccountInstruction,initializeMintInstruction]);console.log("Mint Address:", mint.address);console.log("Transaction Signature:", result.context.signature);const mintAccount = await fetchMint(client.rpc, mint.address);console.log("Mint Account:", mintAccount);
Crea y financia un cliente Kit, luego genera un firmante para usar como dirección del nuevo mint account. El pagador del cliente financia la creación de la cuenta y paga la comisión de la transacción.
const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));const mint = await generateKeyPairSigner();
Calcula el tamaño del mint account en bytes, luego realiza una solicitud RPC para calcular los lamports necesarios para almacenar esos datos en la cuenta. Este saldo requerido se denomina rent.
const space = BigInt(getMintSize());const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();
La primera instrucción invoca el System Program. La instrucción usa el
payer para financiar una newAccount,
asigna el space del mint account, transfiere los
lamports de exención de rent, y asigna la propiedad al
programAddress.
const createAccountInstruction = getCreateAccountInstruction({payer: client.payer,newAccount: mint,space,lamports: rent,programAddress: TOKEN_2022_PROGRAM_ADDRESS});
La segunda instrucción invoca el Token Extensions Program. La instrucción
inicializa la dirección del mint con un valor de
decimals, una mintAuthority,
una freezeAuthority, y especifica el
tokenProgram que posee el mint account.
const initializeMintInstruction = getInitializeMintInstruction({mint: mint.address,decimals: 2,mintAuthority: client.payer.address,freezeAuthority: client.payer.address,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS});
Envía ambas instrucciones en una sola transacción. La instrucción de creación de cuenta debe ir antes de la instrucción de inicialización del mint porque el mint account debe existir antes de que el Token Extensions Program pueda escribir los datos del mint en la cuenta.
const result = await client.sendTransaction([createAccountInstruction,initializeMintInstruction]);
Una vez confirmada la transacción, obtén el mint account.
const mintAccount = await fetchMint(client.rpc, mint.address);console.log("Mint Account:", mintAccount);
Estos ejemplos usan generatedPayer() para crear un keypair desechable para
pruebas locales. Las aplicaciones en producción nunca deben almacenar claves
privadas en texto plano dentro del código — delega la firma a un backend de
gestión de claves. Consulta Firma en
Producción.
Is this page helpful?