
Cómo empezar a desarrollar con Solana Web3.js 2.0 SDK
Tabla de contenido
Antes de comenzar, queremos agradecer a Evan y Nick por revisar este artículo. Apreciamos mucho sus valiosos comentarios y aportes.
Introducción
El SDK Solana Web3.js es una potente biblioteca de TypeScript y JavaScript para desarrollar aplicaciones de Solana en Node.js, la web y plataformas React Native. El 7 de noviembre de 2024, Anza presentó la esperada actualización 2.0 del SDK, con numerosas funciones y mejoras modernas de JavaScript. Entre las novedades principales se incluyen tipos estándar de JS para bigints y criptografía, además de paquetes más pequeños. Esto representa una mejora importante para los desarrolladores.
Si has estado usando @solana/web3.js, tendrás que migrar tu software al nuevo paquete v2.0 o especificar explícitamente la versión para fijarla en v1.x.
En este artículo, exploraremos las últimas novedades de Web3.js 2.0 SDK, te guiaremos por el proceso de migración y proporcionaremos un ejemplo para ayudarte a comenzar.
Este artículo supone que comprendes bien los conceptos fundamentales de Solana, como el envío de transacciones, el modelo de cuentas de Solana, los blockhashes y las comisiones de prioridad, y que tienes experiencia con TypeScript o JavaScript. Se recomienda conocer la versión anterior de Web3.js SDK, pero no es obligatorio. ¡Comencemos!
¿Qué novedades incluye Web3.js 2.0?
Veamos rápidamente qué ofrece el nuevo Web3.js 2.0 SDK:
1. Mejoras de rendimiento
Operaciones criptográficas más rápidas: la generación de pares de claves, la firma de transacciones y la verificación de mensajes son hasta 10 veces más rápidas gracias al uso de API criptográficas nativas en entornos JavaScript modernos, como Node.js y los navegadores actuales.
2. Aplicaciones más pequeñas y eficientes
Web3.js 2.0 admite tree shaking por completo, por lo que puedes incluir solo las partes de la biblioteca que utilizas y minimizar el tamaño de tu paquete. Además, el nuevo SDK no tiene dependencias externas, lo que garantiza una compilación ligera y segura.
3. Mayor flexibilidad
Ahora los desarrolladores pueden crear soluciones personalizadas mediante:
- La definición de instancias RPC con métodos personalizados
- El uso de transportes de red o firmantes de transacciones especializados
- La composición de primitivas personalizadas para redes, confirmaciones de transacciones y códecs
Los nuevos clientes TypeScript para programas on-chain ahora se alojan en la organización @solana-program de GitHub. Estos clientes se generan automáticamente con Codama, lo que permite a los desarrolladores generar con rapidez clientes para programas personalizados.
¿Ya deberías migrar a Web3.js v2?
A febrero de 2025:
- Si estás creando una nueva aplicación de Solana en JS/TS y usas programas existentes, como el programa del sistema, el programa de tokens, el programa de tokens asociados y otros programas comunes, ya puedes usar web3.js v2.
- Si estás creando aplicaciones on-chain personalizadas con Anchor, quizá prefieras esperar: Anchor todavía no admite web3.js v2 de forma nativa. Puedes esperar una futura actualización de Anchor. Como alternativa, usa Codama para crear un cliente TypeScript para tus aplicaciones on-chain, aunque esto requiere un poco más de trabajo.
Migración desde web3.js versión 1
Si has usado web3.js v1, aquí tienes un breve resumen de las diferencias importantes:
Pares de claves
En todos los lugares donde usarías Keypair, ahora debes usar un KeyPairSigner. Keypair.generate() ahora es generateKeyPairSigner(). Además, keypair ahora se escribe keyPair en todas partes, siguiendo el camelCase normal de JS/TS.
Las claves secretas ahora se llaman privateKey y están disponibles en keyPairSigner.privateKey. Por lo general, en web3.js v2 se usa KeyPairSigner donde se usaba una secretKey en web3.js v1.
Direcciones/claves públicas
Los lugares que usaban una PublicKey en web3.js v1 simplemente usan una dirección en web3.js v2. Por ejemplo, los KeyPairSigner tienen una propiedad keypairSigner.address, que es su clave pública. Puedes convertir una clave pública en formato de cadena a una dirección con la función address.
Cantidades de SOL y tokens
Las cantidades usan el tipo nativo de JS BigInt. Por lo tanto, debes agregar n al final de los números, de modo que uno sea 1n en lugar de 1.
Fábricas
Muchas funciones son configurables. Por eso, en lugar de tener una implementación predefinida (por ejemplo, doThing()), existe una fábrica (llamada doThingFactory()) que puedes usar para crear tu propia función doThing(). Por ejemplo:
- Para enviar y confirmar transacciones, ejecutas
sendAndConfirmTransactionFactory()una vez con tus opciones preferidas y recibes una funciónsendAndConfirmTransaction()personalizada. Después, puedes usarsendAndConfirmTransaction()cada vez que necesites enviar y confirmar una transacción. - Para recibir un airdrop en devnet o localnet, ejecutas
airdropFactory()una vez y recibes una funciónairdrop()personalizada que puedes usar cuando quieras un airdrop.
Cómo enviar transacciones con Web3.js 2.0
Helius publicó recientemente Kite, un framework de TypeScript para web3.js v2 que incluye funciones de una sola llamada para las tareas más comunes de Solana.
Desarrollaremos un programa del lado del cliente con Web3.js 2.0 para transferir lamports a otra billetera. Este programa mostrará técnicas para mejorar la tasa de éxito de las transacciones y acelerar los tiempos de confirmación.
Seguiremos estas prácticas recomendadas para enviar transacciones:
- Obtener el blockhash más reciente con un nivel de compromiso confirmed
- Establecer las comisiones de prioridad según lo recomendado por la Priority Fee API de Helius
- Optimizar las unidades de cómputo
- Enviar la transacción con maxRetries establecido en 0 y skipPreflight en true
Este enfoque garantiza un rendimiento y una fiabilidad óptimos, incluso durante la congestión de la red.
Requisitos previos
- Instala Node.js
- Usa un IDE compatible (por ejemplo, VS Code o Cursor)
Instalación
Comienza por crear un proyecto básico de Node.js para estructurar tu aplicación.
Ejecuta el siguiente comando para crear un archivo package.json que gestione tus dependencias y los metadatos del proyecto:
npm init -yCrea un directorio src y, dentro de él, agrega un archivo index.ts donde estará el código principal:
mkdir src
touch src/index.tsA continuación, usa npm para instalar las dependencias necesarias para trabajar con Solana Web3.js 2.0 SDK:
npm install @solana/web3.js@2 @solana-program/system @solana-program/compute-budget esrunEsta es una descripción de cada paquete:
@solana/web3.js: Solana Web3.js 2.0 SDK es esencial para crear y gestionar transacciones de Solana@solana-program/system: proporciona acceso al programa del sistema de Solana y permite operaciones como transferencias de lamports@solana-program/compute-budget: se usa para establecer comisiones de prioridad y optimizar las unidades de cómputo de las transaccionesesrunes una forma sencilla de ejecutar aplicaciones TypeScript desde la línea de comandos sin necesitar configuración ni funciones contenedoras.
Definir las direcciones de transferencia
En index.ts, definamos las direcciones de origen y destino para transferir lamports. Usaremos la función address() para generar la clave pública de destino a partir de la cadena proporcionada.
Para el origen, derivaremos el KeyPair mediante su secretKey.
import { address, createKeyPairSignerFromBytes, getBase58Encoder } from "@solana/web3.js";
const destinationAddress = address("public-key-to-send-lamports-to");
const secretKey = "add-your-private-key";
const sourceKeypair = await createKeyPairSignerFromBytes(getBase58Encoder().encode(secretKey));
Configurar las conexiones RPC
A continuación, podemos configurar las conexiones RPC correspondientes. La función createSolanaRpc establece la comunicación con el servidor RPC mediante un transporte HTTP predeterminado, suficiente para la mayoría de los casos de uso.
De forma similar, usamos createSolanaRpcSubscriptions para establecer una conexión WebSocket. rpc_url y wss_url están en el panel de Helius. Solo tienes que registrarte o iniciar sesión e ir a la sección “Endpoints”.
La función sendAndConfirmTransactionFactory crea un emisor de transacciones reutilizable. Este emisor necesita una conexión RPC para enviar transacciones y una suscripción RPC para supervisar su estado.
import {
// ...
createSolanaRpcSubscriptions,
createSolanaRpc,
sendAndConfirmTransactionFactory,
} from "@solana/web3.js";
const rpc_url = "https://mainnet.helius-rpc.com/?api-key=<your-key>";
const wss_url = "wss://mainnet.helius-rpc.com/?api-key=<your-key>";
const rpc = createSolanaRpc(rpc_url);
const rpcSubscriptions = createSolanaRpcSubscriptions(wss_url);
const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
rpc,
rpcSubscriptions,
});Crear una instrucción de transferencia
Incluir un blockhash reciente evita duplicaciones y asigna una vida útil a las transacciones. Cada transacción debe incluir un blockhash válido para que se acepte su ejecución. Para esta transacción, obtendremos el blockhash más reciente con el nivel de compromiso confirmed.
A continuación, usaremos getTransferSolInstruction() para crear una instrucción de transferencia predefinida que proporciona el programa del sistema. Esto requiere especificar la cantidad y el origen
, además del destino. El origen siempre debe ser un Signer, mientras que el destino debe ser una dirección pública.
import {
// ...
lamports,
} from "@solana/web3.js";
import { getTransferSolInstruction } from "@solana-program/system";
/**
* STEP 1: CREATE THE TRANSFER TRANSACTION
*/
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const instruction = getTransferSolInstruction({
amount: lamports(1n),
destination: destinationAddress,
source: sourceKeypair,
});
Crear el mensaje de transacción
Después, crearemos el mensaje de transacción. Ahora todos los mensajes de transacción reconocen su versión, lo que elimina la necesidad de gestionar tipos diferentes (por ejemplo, Transaction frente a VersionedTransaction).
Estableceremos el origen como pagador de la comisión, incluiremos el blockhash y agregaremos la instrucción para transferir lamports.
import {
// ...
pipe,
createTransactionMessage,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstruction,
} from "@solana/web3.js";
// ...
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(message) => setTransactionMessageFeePayer(sourceKeypair.address, message),
(message) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, message),
(message) => appendTransactionMessageInstruction(instruction, message),
);
console.log("Transaction message created");
La función pipe, común en la programación funcional, crea una secuencia de funciones en la que la salida de una se convierte en la entrada de la siguiente. Aquí crea un mensaje de transacción paso a paso y aplica transformaciones como establecer el pagador de la comisión y la vida útil, además de agregar instrucciones.
Inicializar el mensaje de transacción:
createTransactionMessage({ version: 0 }) comienza con un mensaje de transacción básico.
Establecer el pagador de la comisión:
message => setTransactionMessageFeePayer(fromKeypair.address, message) agrega la dirección del pagador de la comisión.
Establecer la vida útil mediante el blockhash
message => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, message) usa el blockhash más reciente para garantizar que la transacción sea válida durante un periodo determinado.
Agregar la instrucción de transferencia
message => appendTransactionMessageInstruction(instruction, message) agrega la acción (por ejemplo, transferir lamports) al mensaje.
Cada función flecha message => (...) modifica el mensaje actualizado y lo pasa al siguiente paso, con lo que produce un mensaje de transacción nuevo y completamente construido.
Firmar la transacción
Firmaremos la transacción con el firmante especificado, el Keypair de origen.
import {
// ...
signTransactionMessageWithSigners,
} from "@solana/web3.js";
// ...
/**
* STEP 2: SIGN THE TRANSACTION
*/
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
console.log("Transaction signed");
Estimar las comisiones de prioridad
En este paso, podemos proceder a enviar y confirmar la transacción. Sin embargo, conviene optimizarla estableciendo comisiones de prioridad y ajustando las unidades de cómputo. Estas optimizaciones ayudan a mejorar la tasa de éxito de las transacciones y reducen los tiempos de confirmación, especialmente durante la congestión de la red.
Para establecer las comisiones de prioridad, usaremos la Priority Fee API de Helius. Esto requiere la transacción serializada en formato Base64. Aunque la API también admite la codificación Base58, el SDK actual proporciona directamente la transacción en formato Base64, lo que simplifica el proceso.
import {
// ...
getBase64EncodedWireTransaction,
} from "@solana/web3.js";
/**
* STEP 3: GET PRIORITY FEE FROM SIGNED TRANSACTION
*/
const base64EncodedWireTransaction = getBase64EncodedWireTransaction(signedTransaction);
const response = await fetch(rpc_url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "helius-example",
method: "getPriorityFeeEstimate",
params: [
{
transaction: base64EncodedWireTransaction,
options: {
transactionEncoding: "base64",
priorityLevel: "High",
},
},
],
}),
});
const { result } = await response.json();
const priorityFee = result.priorityFeeEstimate;
console.log("Setting priority fee to ", priorityFee);
Establecer priorityLevel en High suele ser suficiente. Sin embargo, implementar estrategias avanzadas para las comisiones de prioridad, como usar transacciones serializadas y claves de cuenta, puede mejorar significativamente la tasa de éxito de las transacciones durante la congestión de la red.
Optimizar las unidades de cómputo
A continuación, estimaremos las unidades de cómputo reales que consume el mensaje de transacción.
Después, agregamos un margen del 10 % multiplicando este valor por 1.1. Este margen contempla las unidades de cómputo que usan las comisiones de prioridad y las instrucciones adicionales de unidades de cómputo, que incorporaremos más adelante.
Algunas instrucciones, como transferir lamports, pueden tener una estimación menor de unidades de cómputo. Para garantizar que haya suficientes recursos, agregamos una protección que establece un mínimo de 1000 unidades de cómputo si la estimación queda por debajo de este umbral.
import {
// ...
getComputeUnitEstimateForTransactionMessageFactory,
} from "@solana/web3.js";
/**
* STEP 4: OPTIMIZE COMPUTE UNITS
*/
const getComputeUnitEstimateForTransactionMessage = getComputeUnitEstimateForTransactionMessageFactory({
rpc,
});
// Request an estimate of the actual compute units this message will consume.
let computeUnitsEstimate = await getComputeUnitEstimateForTransactionMessage(transactionMessage);
computeUnitsEstimate = computeUnitsEstimate < 1000 ? 1000 : Math.ceil(computeUnitsEstimate * 1.1);
console.log("Setting compute units to ", computeUnitsEstimate);
Reconstruir y firmar la transacción
Ahora tenemos las comisiones de prioridad y las unidades de cómputo necesarias para esta transacción. Como la transacción ya se firmó, no podemos agregar nuevas instrucciones directamente. En su lugar, reconstruiremos todo el mensaje de transacción con un blockhash nuevo.
Los blockhashes solo son válidos durante aproximadamente 1 o 2 minutos, y obtener las comisiones de prioridad y las unidades de cómputo lleva cierto tiempo. Para evitar que el blockhash caduque mientras enviamos la transacción, es más seguro obtener uno nuevo al reconstruirla.
En esta transacción reconstruida, incluiremos dos instrucciones adicionales:
- Una instrucción para establecer las comisiones de prioridad; y
- Otra instrucción para establecer las unidades de cómputo
Por último, firmaremos esta transacción actualizada para prepararla para el envío:
import {
// ...
appendTransactionMessageInstructions,
} from "@solana/web3.js";
import { getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction } from "@solana-program/compute-budget";
/**
* STEP 5: REBUILD AND SIGN FINAL TRANSACTION
*/
const { value: finalLatestBlockhash } = await rpc.getLatestBlockhash().send();
const finalTransactionMessage = appendTransactionMessageInstructions(
[
getSetComputeUnitPriceInstruction({ microLamports: priorityFee }),
getSetComputeUnitLimitInstruction({ units: computeUnitsEstimate }),
],
transactionMessage,
);
setTransactionMessageLifetimeUsingBlockhash(finalLatestBlockhash, finalTransactionMessage);
const finalSignedTransaction = await signTransactionMessageWithSigners(finalTransactionMessage);
console.log("Rebuilt the transaction and signed it");
Enviar y confirmar la transacción
A continuación, la transacción firmada se envía y confirma con la función sendAndConfirmTransaction.
El nivel de compromiso se establece en confirmed, de forma coherente con el blockhash obtenido antes, mientras que maxRetries se establece en 0. La opción skipPreflight se establece en true, lo que omite las comprobaciones de preflight para acelerar la ejecución. Sin embargo, solo debes usarla cuando tengas la certeza de que la firma de tu transacción está verificada y no hay otros errores.
sendAndConfirmTransaction se creó antes proporcionando tanto la URL RPC como la URL de suscripción RPC. Usar la URL de suscripción RPC permite comprobar el estado de la transacción sin necesidad de hacer sondeos manuales.
En la sección de gestión de errores, el código comprueba si ocurrieron errores durante las comprobaciones de preflight. Como establecimos skipPreflight en true, esta comprobación es redundante. Sin embargo, será útil si no lo estableces en true.
import {
getSignatureFromTransaction,
isSolanaError,
SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
} from "@solana/web3.js";
import { getSystemErrorMessage, isSystemError } from "@solana-program/system";
/**
* STEP 6: SEND AND CONFIRM THE FINAL TRANSACTION
*/
console.log("Sending and confirming transaction");
await sendAndConfirmTransaction(finalSignedTransaction, {
commitment: "confirmed",
maxRetries: 0n,
skipPreflight: true,
});
console.log("Transfer confirmed: ", getSignatureFromTransaction(finalSignedTransaction));
Ejecutar el código
Por último, podemos ejecutar el código:
npx esrun send-transaction.ts
Conclusión
El lanzamiento de Solana Web3.js 2.0 SDK es una actualización transformadora que permite a los desarrolladores crear aplicaciones más rápidas, eficientes y escalables en Solana. Al adoptar estándares modernos de JavaScript e introducir funciones como API criptográficas nativas, compatibilidad con tree shaking y clientes TypeScript generados automáticamente, el SDK mejora de forma significativa la experiencia del desarrollador y el rendimiento de las aplicaciones.
El código completo del ejemplo de programación está en GitHub.
Si llegaste hasta aquí, ¡gracias, anon! Ingresa tu dirección de correo electrónico a continuación para no perderte ninguna novedad de Solana. ¿Listo para profundizar? Explora los artículos más recientes en el blog de Helius y continúa hoy tu recorrido por Solana.
Recursos
Artículos relacionados
Suscríbete a Helius
Mantente al día con las novedades del desarrollo en Solana y recibe actualizaciones cuando publiquemos


