El método RPC getFeeForMessage de Solana devuelve la tarifa base de red en lamports para un mensaje compilado específico en un blockhash dado. Esta tarifa incluye un componente fijo por firma y un componente por unidad de cómputo basado en el límite de unidades de cómputo solicitado por el mensaje. El método devuelve null cuando el blockhash está expirado o es desconocido, por lo que las estimaciones deben tomarse cerca del momento de envío. La tarifa total de la transacción es la suma de esta tarifa base y una tarifa prioritaria elegida por el cliente (límite de unidades de cómputo multiplicado por el precio por unidad de cómputo). Esta guía explica la fórmula de tarifas, demuestra getFeeForMessage con Node.js y proporciona un método reproducible para medir tarifas contra tu propio endpoint.
Estructura de tarifas de Solana y el rol de getFeeForMessage
Las tarifas de transacción en Solana constan de dos partes: una tarifa base y una tarifa prioritaria. La tarifa base la determina la red e incluye un componente fijo de lamports por firma más un componente por unidad de cómputo calculado a la tasa de lamports por unidad de cómputo del clúster. La tarifa prioritaria es opcional y la elige el cliente; se calcula como el límite de unidades de cómputo multiplicado por el precio por unidad de cómputo. Según la documentación de tarifas de Solana, estos componentes se combinan para formar la tarifa total que paga una transacción.
El método RPC getFeeForMessage devuelve la tarifa base en lamports que la red cobraría por un mensaje compilado específico en un blockhash reciente. No incluye la tarifa prioritaria, que es una elección del lado del cliente. Este método es esencial para estimar el costo impuesto por la red antes del envío, especialmente cuando el límite de unidades de cómputo solicitado por el mensaje afecta la tarifa base. Para una visión más amplia de los métodos RPC de Solana, consulta la guía de la API de Solana.
- Tarifa base = tarifa fija por firma + (límite de unidades de cómputo × lamports por unidad de cómputo).
- Tarifa prioritaria = límite de unidades de cómputo × precio por unidad de cómputo (establecida por el cliente).
- getFeeForMessage devuelve solo la tarifa base para un mensaje y blockhash dados.
- El método devuelve null si el blockhash no es reciente o es desconocido.
Cómo evalúa getFeeForMessage un mensaje compilado
getFeeForMessage acepta dos parámetros: un mensaje compilado codificado en base64 y un nivel de compromiso. El mensaje compilado debe estar en el formato que espera el runtime de Solana, típicamente producido al serializar un objeto MessageV0 o un Message heredado. El método evalúa el mensaje contra un blockhash reciente para determinar la tarifa base. Si el blockhash no se encuentra o no es reciente, el método devuelve null, lo que indica que la tarifa no se puede estimar para ese mensaje en ese blockhash.
La tarifa devuelta está en lamports y refleja los parámetros de tarifas actuales de la red. Dado que la tarifa base depende del límite de unidades de cómputo solicitado por el mensaje, cualquier cambio en setComputeUnitLimit alterará el resultado. Por lo tanto, debes llamar a getFeeForMessage sobre el mensaje exacto que pretendes enviar, o al menos uno con el mismo límite de unidades de cómputo y la misma cantidad de firmas. Para obtener detalles sobre la validez del blockhash, consulta la referencia de getLatestBlockhash.
- Parámetro 1: mensaje compilado codificado en base64.
- Parámetro 2: nivel de compromiso (por ejemplo, 'processed', 'confirmed', 'finalized').
- Devuelve: tarifa en lamports, o null si el blockhash es obsoleto o desconocido.
- El límite de unidades de cómputo del mensaje influye directamente en la tarifa base.
Relación entre getFeeForMessage y la frescura del blockhash
getFeeForMessage se evalúa contra un blockhash específico incrustado en el mensaje. Si ese blockhash está expirado o es desconocido para el clúster, el método devuelve null. Esto significa que las estimaciones de tarifas solo son válidas durante una ventana corta, típicamente hasta que el blockhash expira, lo que ocurre alrededor de 150 bloques (aproximadamente 60-90 segundos) en Solana mainnet-beta. Para obtener un blockhash fresco, usa getLatestBlockhash, que también devuelve lastValidBlockHeight para el momento de envío de la transacción.
Debido a esta dependencia, debes llamar a getFeeForMessage inmediatamente antes de firmar y enviar la transacción. Si te demoras, el blockhash puede expirar y la estimación de la tarifa se vuelve inválida. Para estrategias que manejan la expiración del blockhash, incluidos los nonces duraderos, consulta Expiración de blockhash y nonces duraderos en Solana.
- getFeeForMessage devuelve null si el blockhash no es reciente.
- La validez del blockhash es típicamente de ~150 bloques (~60-90 segundos).
- Siempre obtén un blockhash fresco y estima las tarifas justo antes del envío.
- Usa getLatestBlockhash para obtener tanto el blockhash como lastValidBlockHeight.
Composición de la tarifa total de transacción: tarifa base más tarifa prioritaria
La tarifa total que paga una transacción es la suma de la tarifa base devuelta por getFeeForMessage y la tarifa prioritaria elegida por el cliente. La tarifa prioritaria se calcula como el límite de unidades de cómputo multiplicado por el precio por unidad de cómputo (en micro-lamports por unidad de cómputo). Esta tarifa prioritaria no está incluida en getFeeForMessage; debe agregarse por separado. La fórmula es: tarifa total = getFeeForMessage(message, commitment) + (computeUnitLimit × computeUnitPrice).
La tarifa prioritaria es un valor determinado por el mercado que estableces para incentivar la inclusión oportuna. No es un valor determinado por la red. Para obtener orientación sobre cómo estimar tarifas prioritarias usando getRecentPrioritizationFees, consulta Estimación de tarifas prioritarias en Solana y setComputeUnitPrice y Estimador local de tarifas getRecentPrioritizationFees de Solana.
- Tarifa total = tarifa base (de getFeeForMessage) + tarifa prioritaria (elegida por el cliente).
- Tarifa prioritaria = límite de unidades de cómputo × precio por unidad de cómputo.
- getFeeForMessage nunca incluye la tarifa prioritaria.
- Las tarifas prioritarias son opcionales pero pueden mejorar los tiempos de inclusión de la transacción.
Diferencias entre getFeeForMessage y getRecentPrioritizationFees
getFeeForMessage y getRecentPrioritizationFees cumplen propósitos diferentes. getFeeForMessage devuelve la tarifa base de red para un mensaje específico, incluido el componente por unidad de cómputo basado en el límite solicitado por el mensaje. getRecentPrioritizationFees, en cambio, devuelve una muestra de las tarifas prioritarias que otras transacciones pagaron recientemente, expresadas en micro-lamports por unidad de cómputo. No incluye la tarifa base y no es específica de tu mensaje.
Esta distinción es crucial: getFeeForMessage te dice lo que cobrará la red, mientras que getRecentPrioritizationFees te ayuda a elegir una tarifa prioritaria competitiva. Para cadenas basadas en cuentas como Ethereum, la estimación de tarifas suele usar eth_feeHistory, pero el modelo de Solana separa las tarifas base y prioritaria. Comprender ambos métodos te permite calcular el costo total exacto. Para más información sobre niveles de compromiso, consulta Niveles de compromiso y confirmación de transacciones en Solana.
- getFeeForMessage: tarifa base para un mensaje específico (determinada por la red).
- getRecentPrioritizationFees: muestra de tarifas prioritarias recientes (datos de mercado).
- La tarifa base incluye el componente por unidad de cómputo; la tarifa prioritaria es aparte.
- Usa ambos para estimar el costo total con precisión.
Ejemplo ejecutable en Node.js: estimación de la tarifa base y la tarifa total
El siguiente script de Node.js usa @solana/web3.js para construir un mensaje con un límite de unidades de cómputo explícito, llamar a getFeeForMessage y luego agregar una tarifa prioritaria elegida para calcular el total. También demuestra el resultado null al usar un blockhash obsoleto. Asegúrate de tener un endpoint RPC de Solana; puedes usar un endpoint público o uno dedicado de la red Solana de OnFinality.
El script primero obtiene un blockhash reciente, compila un MessageV0 con un límite de unidades de cómputo de 200,000 y llama a getFeeForMessage. Luego calcula la tarifa prioritaria usando un precio por unidad de cómputo de 1,000 micro-lamports (1 micro-lamport = 0.000001 lamports). Finalmente, simula un blockhash obsoleto usando un blockhash antiguo para mostrar el retorno null.
const { Connection, MessageV0, PublicKey, SystemProgram, TransactionMessage, ComputeBudgetProgram } = require('@solana/web3.js');
async function estimateFees() {
const connection = new Connection('https://your-solana-rpc-endpoint', 'confirmed');
const payer = new PublicKey('YourPayerPublicKey');
const recipient = new PublicKey('RecipientPublicKey');
// Fetch a recent blockhash
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
// Build a message with an explicit compute-unit limit
const computeUnitLimit = 200000;
const computeUnitPrice = 1000; // micro-lamports per compute unit
const instructions = [
ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnitLimit }),
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: computeUnitPrice }),
SystemProgram.transfer({ fromPubkey: payer, toPubkey: recipient, lamports: 1000000 })
];
const messageV0 = new TransactionMessage({
payerKey: payer,
recentBlockhash: blockhash,
instructions,
}).compileToV0Message();
// Serialize and encode to base64
const serializedMessage = messageV0.serialize();
const base64Message = Buffer.from(serializedMessage).toString('base64');
// Call getFeeForMessage
const feeResponse = await connection.getFeeForMessage(messageV0, 'confirmed');
const baseFee = feeResponse.value;
console.log('Base fee (lamports):', baseFee);
// Calculate priority fee
const priorityFee = computeUnitLimit * computeUnitPrice / 1e6; // convert micro-lamports to lamports
console.log('Priority fee (lamports):', priorityFee);
// Total fee
const totalFee = baseFee + priorityFee;
console.log('Total fee (lamports):', totalFee);
// Demonstrate null with stale blockhash
const staleBlockhash = '11111111111111111111111111111111'; // invalid blockhash
const staleMessage = new TransactionMessage({
payerKey: payer,
recentBlockhash: staleBlockhash,
instructions,
}).compileToV0Message();
const staleFeeResponse = await connection.getFeeForMessage(staleMessage, 'confirmed');
console.log('Stale blockhash fee (should be null):', staleFeeResponse.value);
}
estimateFees().catch(console.error);Método de medición reproducible y tabla de resultados
Para verificar el comportamiento de las tarifas en tu propio endpoint, ejecuta el script anterior con diferentes configuraciones de mensaje. Varía la cantidad de firmas (agregando firmantes) y el límite de unidades de cómputo, luego registra la tarifa base devuelta por getFeeForMessage. Registra también tu tarifa prioritaria elegida y el total calculado. Este método es reproducible y te ayuda a comprender cómo cada parámetro afecta la tarifa.
Usa la siguiente tabla para registrar tus mediciones. Complétala con datos de tus propias ejecuciones. Ten en cuenta que la tarifa base puede variar ligeramente según los parámetros del clúster, y la tarifa prioritaria es completamente tu elección. Para un endpoint RPC listo para producción, considera el servicio de API de OnFinality o revisa los precios de RPC para ver las opciones.
- Cantidad de firmas: número de firmas requeridas en el mensaje.
- Límite de unidades de cómputo: el límite establecido mediante ComputeBudgetProgram.setComputeUnitLimit.
- Resultado de getFeeForMessage: tarifa base en lamports (o null si es obsoleto).
- Tarifa prioritaria elegida: límite de unidades de cómputo × precio por unidad de cómputo (en lamports).
- Tarifa total: tarifa base + tarifa prioritaria.
| Signature Count | Compute-Unit Limit | getFeeForMessage (lamports) | Chosen Priority Fee (lamports) | Total Fee (lamports) |
|-----------------|--------------------|-----------------------------|--------------------------------|----------------------|
| 1 | 200,000 | | | |
| 2 | 200,000 | | | |
| 1 | 400,000 | | | |
| 1 | 200,000 (stale) | null | | |Limitaciones y compensaciones en la estimación de tarifas
La tarifa exacta es un parámetro del clúster que puede cambiar con el tiempo. La tasa de lamports por unidad de cómputo y la tarifa fija por firma las establece el clúster y pueden ajustarse mediante gobernanza. Por lo tanto, getFeeForMessage devuelve la tarifa según los parámetros actuales, pero estos pueden cambiar. Trata siempre el valor devuelto como una estimación, no como una garantía.
getFeeForMessage devuelve null cerca de la expiración del blockhash, lo que significa que no puedes confiar en una estimación en caché. Debes obtener un blockhash fresco y volver a estimar si el anterior expira. Además, la tarifa prioritaria es una elección del cliente, no un valor de la red; no está incluida en getFeeForMessage y debe agregarse manualmente. Esta separación te da control, pero requiere una composición cuidadosa. Para más información sobre los niveles de compromiso y su impacto en la frescura de los datos, consulta Niveles de compromiso y confirmación de transacciones en Solana.
- Los parámetros de tarifas del clúster pueden cambiar; las estimaciones no están garantizadas.
- getFeeForMessage devuelve null para blockhashes obsoletos o desconocidos.
- La tarifa prioritaria la elige el cliente y no está incluida en la tarifa base.
- Vuelve a estimar siempre las tarifas inmediatamente antes del envío.
Solución de problemas comunes de getFeeForMessage
Si getFeeForMessage devuelve null, la causa más probable es un blockhash expirado o desconocido. Asegúrate de usar un blockhash reciente de getLatestBlockhash y de llamar a getFeeForMessage con prontitud. Si el problema persiste, verifica que el mensaje esté correctamente compilado y serializado; un formato de mensaje inválido también puede causar errores. Comprueba que tu endpoint RPC esté sincronizado y responda.
Otro problema común es la discrepancia entre el mensaje usado para la estimación y el que realmente se envía. Si cambias el límite de unidades de cómputo o agregas instrucciones después de estimar, la tarifa base puede diferir. Estima siempre sobre el mensaje final. Si recibes un error en lugar de null, inspecciona el mensaje de error para obtener pistas; puede indicar un parámetro inválido o un problema de red. Para la confiabilidad del endpoint, considera usar un proveedor dedicado como la red Solana de OnFinality.
- Resultado null: blockhash obsoleto; obtén uno nuevo y reintenta.
- Error: verifica la serialización del mensaje y la salud del endpoint RPC.
- Discrepancia de tarifa: asegúrate de que el mensaje estimado coincida con el enviado.
- Usa un endpoint RPC confiable para evitar tiempos de espera o problemas de sincronización.
Próximos pasos: integrar la estimación de tarifas en tu flujo de trabajo
Para construir un flujo de trabajo robusto de estimación de tarifas, combina getFeeForMessage con getRecentPrioritizationFees para elegir una tarifa prioritaria competitiva. Obtén un blockhash fresco, compila tu mensaje con el límite de unidades de cómputo deseado, llama a getFeeForMessage y luego agrega tu tarifa prioritaria elegida. Monitorea la tarifa total y ajusta la tarifa prioritaria según las condiciones de la red. Para profundizar en estrategias de tarifas prioritarias, consulta Estimación de tarifas prioritarias en Solana y setComputeUnitPrice.
Explora más guías y tutoriales de RPC de Solana en el centro de aprendizaje de OnFinality. Si necesitas un endpoint RPC de alto rendimiento para producción, revisa los precios de RPC o comienza con el servicio de API de OnFinality. Para obtener una lista completa de los métodos RPC de Solana, consulta la guía de la API de Solana.
- Combina getFeeForMessage con getRecentPrioritizationFees para el costo total.
- Usa siempre un blockhash fresco y estima justo antes del envío.
- Ajusta las tarifas prioritarias dinámicamente según la congestión de la red.
- Aprovecha una infraestructura RPC confiable para una estimación de tarifas consistente.