Transacciones Patrocinadas
Normalmente, la cuenta que ejecuta una transacción paga las comisiones de gas. Puedes permitir que otra cuenta cubra esos cargos patrocinando una transacción.
Esto puede usarse para ayudar a gestionar comisiones desde una cuenta central al trabajar con contratos inteligentes complicados.
Cómo Patrocinar una Transacción
Sección titulada «Cómo Patrocinar una Transacción»-
Construye la transacción con el parámetro withFeePayer: true.
const transaction = await aptos.transaction.build.simple({sender: sender.accountAddress,withFeePayer: true,data: {// Todas las transacciones en Aptos se implementan vía contratos inteligentes.function: "0x1::aptos_account::transfer",functionArguments: [destination.accountAddress, 100],},}); -
Firma la transacción con AMBOS, el remitente y el feePayer.
- Firma con la cuenta remitente usando
.sign
. - Firma con la cuenta patrocinadora usando
.signAsFeePayer
.
const senderAuthenticator = aptos.transaction.sign({signer: sender,transaction,});const feePayerAuthenticator = aptos.transaction.signAsFeePayer({signer: feePayer,transaction}) - Firma con la cuenta remitente usando
-
(Opcional) Simula la transacción patrocinada
Puedes simular la transacción patrocinada para previsualizar el resultado antes de enviarla de la siguiente manera:
const [userTransactionResponse] = await aptos.transaction.simulate.simple({signerPublicKey: sender.publicKey,transaction,});Por defecto, el
feePayerAddress
de latransaction
se establece en0x0
, lo que hace que la simulación de la transacción omita el pago de la comisión de gas. Esto te permite simular la transacción sin especificar un fee payer. Ten en cuenta quesignerPublicKey
es opcional y puede omitirse si deseas omitir la verificación de la clave de autenticación del remitente.También puedes simular la transacción con un fee payer específico estableciendo el
feePayerAddress
en el objetotransaction
así:transaction.feePayerAddress = feePayer.accountAddress;const [userTransactionResponse] = await aptos.transaction.simulate.simple({signerPublicKey: sender.publicKey,feePayerPublicKey: feePayer.publicKey,transaction,});Esta configuración verificará que
feePayer
tenga saldo suficiente para cubrir la comisión de gas de la transacción. De manera similar,feePayerPublicKey
es opcional y puede omitirse si deseas omitir la verificación de la clave de autenticación del fee payer. -
Envía la transacción combinando ambas firmas.
// 4. Enviarconst committedTransaction = await aptos.transaction.submit.simple({transaction,senderAuthenticator: senderAuthenticator,feePayerAuthenticator: feePayerAuthenticator,}); -
Espera a que la transacción se ejecute.
// 5. Esperar resultadosconst executedTransaction = await aptos.waitForTransaction({ transactionHash: committedTransaction.hash });
Ejemplo de Código de Transacción Patrocinada en TypeScript
Sección titulada «Ejemplo de Código de Transacción Patrocinada en TypeScript»/** * Este ejemplo muestra cómo usar el SDK de Aptos para enviar una transacción con patrocinador. */
import { Account, Aptos, AptosConfig, Network,} from "@aptos-labs/ts-sdk";
async function example() { console.log("Este ejemplo enviará una transacción patrocinada de Alice a Carol.");
// 0. Configura el cliente y las cuentas de prueba const config = new AptosConfig({ network: Network.DEVNET }); const aptos = new Aptos(config);
let alice = Account.generate(); let bob = Account.generate(); let carol = Account.generate();
console.log("=== Direcciones ===\n"); console.log(`La dirección de Alice es: ${alice.accountAddress}`); console.log(`La dirección de Bob es: ${bob.accountAddress}`); console.log(`La dirección de Carol es: ${carol.accountAddress}`);
console.log("\n=== Financiando cuentas ===\n"); await aptos.fundAccount({ accountAddress: alice.accountAddress, amount: 500_000_000, }); await aptos.fundAccount({ accountAddress: bob.accountAddress, amount: 500_000_000, }); await aptos.fundAccount({ accountAddress: carol.accountAddress, amount: 100, }); console.log("¡Cuentas financiadas!")
// 1. Construir console.log("\n=== 1. Construyendo la transacción ===\n"); const transaction = await aptos.transaction.build.simple({ sender: alice.accountAddress, withFeePayer: true, data: { // Todas las transacciones en Aptos se implementan vía contratos inteligentes. function: "0x1::aptos_account::transfer", functionArguments: [carol.accountAddress, 100], }, }); console.log("¡Transacción construida!")
// 2. Firmar console.log("\n=== 2. Firmando transacción ===\n"); const aliceSenderAuthenticator = aptos.transaction.sign({ signer: alice, transaction, }); const bobSenderAuthenticator = aptos.transaction.signAsFeePayer({ signer: bob, transaction }) console.log("¡Transacción firmada!")
// 3. Simular (Opcional) console.log("\n === 3. Simulando Respuesta (Opcional) === \n") const [userTransactionResponse] = await aptos.transaction.simulate.simple({ signerPublicKey: alice.publicKey, feePayerPublicKey: bob.publicKey, transaction, }); console.log(userTransactionResponse)
// 4. Enviar console.log("\n=== 4. Enviando transacción ===\n"); const committedTransaction = await aptos.transaction.submit.simple({ transaction, senderAuthenticator: aliceSenderAuthenticator, feePayerAuthenticator: bobSenderAuthenticator, }); console.log("Hash de la transacción enviada:", committedTransaction.hash);
// 5. Esperar resultados console.log("\n=== 5. Esperando resultado de la transacción ===\n"); const executedTransaction = await aptos.waitForTransaction({ transactionHash: committedTransaction.hash }); console.log(executedTransaction)};
example();
Errores Comunes
Sección titulada «Errores Comunes»INSUFFICIENT_BALANCE_FOR_TRANSACTION_FEE
:
- Esto puede ser causado por usar accidentalmente
.sign
en vez de.signAsFeePayer
al firmar la transacción antes de enviarla en la cadena. - Patrocinar una transacción requiere que la cuenta patrocinadora tenga suficientes fondos para cubrir la comisión máxima de gas posible. Esto suele ser órdenes de magnitud mayor que las comisiones de gas esperadas o reales requeridas para que una transacción se ejecute. En este caso, aumenta los fondos en la cuenta por encima de
max_gas_amount
multiplicado por elgas_unit_price
en la transacción simulada. Estos deben multiplicarse porque el gas no tiene unidades, por lo que debe multiplicarse por la tasa de conversión de gas a octas. Puedes aprender más sobre gas aquí.