Tu Primera Transacción
Las transacciones son la forma fundamental de cambiar la data en la blockchain de Aptos. Piénsalo como enviar un paquete: necesitas especificar qué envías, a quién va dirigido, y luego rastrearlo hasta que se confirme el delivery. En términos de blockchain, las transacciones te permiten transferir coins, llamar funciones de smart contracts y actualizar el estado on-chain.
Este tutorial te guiará para crear y hacer submit de tu primera transacción en la blockchain de Aptos. Aprenderás cómo:
- Configurar tu entorno de desarrollo
- Crear cuentas de prueba y fondearlas
- Construir una transacción para transferir coins
- Simular la transacción para estimar costos
- Firmar y hacer submit de la transacción
- Verificar que la transacción se ejecutó exitosamente
1. Configurando tu Entorno
Sección titulada «1. Configurando tu Entorno»Antes de que podamos crear transacciones, necesitamos configurar nuestro entorno de desarrollo con las herramientas y SDKs necesarios.
-
Instalar el SDK de TypeScript
Instala el SDK de TypeScript usando tu package manager preferido:
Ventana de terminal npm install @aptos-labs/ts-sdkVentana de terminal yarn add @aptos-labs/ts-sdkVentana de terminal pnpm add @aptos-labs/ts-sdk -
Crear un directorio para el proyecto
Crea un directorio nuevo para tu proyecto:
Ventana de terminal mkdir my-first-transactioncd my-first-transaction -
Crear un archivo nuevo
Crea un archivo nuevo llamado
transaction.ts:Ventana de terminal touch transaction.tsVentana de terminal type nul > transaction.ts
Antes de que podamos crear transacciones, necesitamos configurar nuestro entorno de desarrollo con las herramientas y SDKs necesarios.
-
Instalar el SDK de Python
Instala el SDK de Python usando pip:
Ventana de terminal pip install aptos-sdk -
Crear un directorio para el proyecto
Crea un directorio nuevo para tu proyecto:
Ventana de terminal mkdir my-first-transactioncd my-first-transaction -
Crear un archivo nuevo
Crea un archivo nuevo llamado
transaction.py:Ventana de terminal touch transaction.pyVentana de terminal type nul > transaction.py
2. Creando Cuentas de Prueba
Sección titulada «2. Creando Cuentas de Prueba»En blockchain, todas las transacciones deben venir de una cuenta (account). Vamos a crear dos cuentas de prueba: una para enviar coins (Alice) y otra para recibirlos (Bob).
-
Configurar el cliente
Primero, necesitamos inicializar el cliente de Aptos que se conectará a la blockchain. Abre
transaction.tsen tu editor y agrega:import {Account,Aptos,AptosConfig,Network,} from "@aptos-labs/ts-sdk";async function main() {// Inicializar el cliente de Aptosconst config = new AptosConfig({ network: Network.DEVNET });const aptos = new Aptos(config);console.log("Conectado a Aptos devnet");// Más código irá aquí}main().catch(console.error); -
Generar cuentas
Agrega este código dentro de tu función
main()para crear dos cuentas: Alice (sender) y Bob (receiver):// Generar dos cuentasconst alice = Account.generate();const bob = Account.generate();console.log("=== Direcciones ===");console.log(`Dirección de Alice: ${alice.accountAddress}`);console.log(`Dirección de Bob: ${bob.accountAddress}`); -
Fondear las cuentas
Agrega este código después de generar las cuentas para obtener coins de prueba desde el faucet:
// Fondear las cuentas con APT de prueba del faucet de devnetconsole.log("\n=== Fondeando cuentas ===");await aptos.fundAccount({accountAddress: alice.accountAddress,amount: 100_000_000, // 1 APT = 100,000,000 octas});console.log("Cuentas fondeadas exitosamente");// Revisar balances inicialesconst aliceBalance = await aptos.getAccountAPTAmount({accountAddress: alice.accountAddress,});const bobBalance = await aptos.getAccountAPTAmount({accountAddress: bob.accountAddress,});console.log("\n=== Balances Iniciales ===");console.log(`Alice: ${aliceBalance} octas`);console.log(`Bob: ${bobBalance} octas`); -
Correr el código
Probemos nuestro código hasta ahora:
Ventana de terminal npx ts-node transaction.tsDeberías ver una salida similar a:
Conectado a Aptos devnet=== Direcciones ===Dirección de Alice: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaDirección de Bob: 0x7af2d6c93a2feafc9b69b5e8ad9d6b513b260f62f23f3a384a3a2e4a84694a9b=== Fondeando cuentas ===Cuentas fondeadas exitosamente=== Balances Iniciales ===Alice: 100000000 octasBob: 0 octas
En blockchain, todas las transacciones deben venir de una cuenta (account). Vamos a crear dos cuentas de prueba: una para enviar coins (Alice) y otra para recibirlos (Bob).
-
Configurar el cliente
Primero, necesitamos inicializar el cliente de Aptos que se conectará a la blockchain. Abre
transaction.pyen tu editor y agrega:import asynciofrom aptos_sdk.account import Accountfrom aptos_sdk.async_client import FaucetClient, RestClientfrom aptos_sdk.transactions import EntryFunction, TransactionPayload, TransactionArgument, RawTransactionfrom aptos_sdk.bcs import Serializerimport time# Configuración de la redNODE_URL = "https://fullnode.devnet.aptoslabs.com/v1"FAUCET_URL = "https://faucet.devnet.aptoslabs.com"async def main():# Inicializar los clientesrest_client = RestClient(NODE_URL)faucet_client = FaucetClient(FAUCET_URL, rest_client)print("Conectado a Aptos devnet")# Más código irá aquíif __name__ == "__main__":asyncio.run(main()) -
Generar cuentas
Agrega este código dentro de tu función
main()para crear dos cuentas: Alice (sender) y Bob (receiver):# Generar dos cuentasalice = Account.generate()bob = Account.generate()print("=== Direcciones ===")print(f"Dirección de Alice: {alice.address()}")print(f"Dirección de Bob: {bob.address()}") -
Fondear las cuentas
Agrega este código después de generar las cuentas para obtener coins de prueba desde el faucet:
# Fondear las cuentas con APT de prueba del faucet de devnetprint("\n=== Fondeando cuentas ===")alice_amount = 100_000_000 # 1 APT = 100,000,000 octasbob_amount = 0 # Bob comienza con 0 APTawait faucet_client.fund_account(alice.address(), alice_amount)print("Cuenta fondeada exitosamente")# Revisar balances inicialesalice_balance = await rest_client.account_balance(alice.address())bob_balance = await rest_client.account_balance(bob.address())print("\n=== Balances Iniciales ===")print(f"Alice: {alice_balance} octas")print(f"Bob: {bob_balance} octas") -
Correr el código
Probemos nuestro código hasta ahora:
Ventana de terminal python transaction.pyDeberías ver una salida similar a:
Conectado a Aptos devnet=== Direcciones ===Dirección de Alice: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaDirección de Bob: 0x7af2d6c93a2feafc9b69b5e8ad9d6b513b260f62f23f3a384a3a2e4a84694a9b=== Fondeando cuentas ===Cuenta fondeada exitosamente=== Balances Iniciales ===Alice: 100000000 octasBob: 0 octas
3. Construyendo una Transacción
Sección titulada «3. Construyendo una Transacción»Ahora que tenemos cuentas fondeadas, vamos a crear una transacción para transferir coins de Alice a Bob. Esto es como llenar un formulario especificando qué quieres enviar y a quién.
-
Entender la estructura de la transacción
Una transacción en Aptos tiene varios componentes clave:
- Sender: La cuenta que inicia la transacción (Alice)
- Function: La función on-chain a llamar (en este caso, una transferencia de coins)
- Arguments: Data necesaria por la función (dirección del recipiente y monto)
- Gas parameters: Cantidad máxima de gas (max gas amount) y precio por unidad de gas (gas unit price)
- Expiration time: Cuándo la transacción deja de ser válida si no se ha ejecutado
- Sequence number: Un contador que previene ataques de replay
-
Construir la transacción
Vamos a agregar código para construir una transacción que transfiere 1000 octas de Alice a Bob:
Agrega este código a tu función
main():// 1. Construir la transacciónconsole.log("\n=== 1. Construyendo la transacción ===");const transaction = await aptos.transaction.build.simple({sender: alice.accountAddress,data: {function: "0x1::aptos_account::transfer",functionArguments: [bob.accountAddress, 1000], // Transferir 1000 octas},});console.log("Transacción construida exitosamente");// Acceder a detalles de la transacción desde la raw transactionconst rawTxn = transaction.rawTransaction;console.log(`Sender: ${rawTxn.sender}`);console.log(`Sequence Number: ${rawTxn.sequence_number}`);console.log(`Max Gas Amount: ${rawTxn.max_gas_amount}`);console.log(`Gas Unit Price: ${rawTxn.gas_unit_price}`);console.log(`Expiration Timestamp: ${new Date(Number(rawTxn.expiration_timestamp_secs) * 1000).toISOString()}`);
Ahora que tenemos cuentas fondeadas, vamos a crear una transacción para transferir coins de Alice a Bob. Esto es como llenar un formulario especificando qué quieres enviar y a quién.
-
Entender la estructura de la transacción
Una transacción en Aptos tiene varios componentes clave:
- Sender: La cuenta que inicia la transacción (Alice)
- Function: La función on-chain a llamar (en este caso, una transferencia de coins)
- Arguments: Data necesaria por la función (dirección del recipiente y monto)
- Gas parameters: Cantidad máxima de gas (max gas amount) y precio por unidad de gas (gas unit price)
- Expiration time: Cuándo la transacción deja de ser válida si no se ha ejecutado
- Sequence number: Un contador que previene ataques de replay
-
Construir la transacción
Agrega el siguiente código a tu función
main()para construir una transacción que transfiere 1000 octas de Alice a Bob:# 1. Construir la transacciónprint("\n=== 1. Construyendo la transacción ===")# Crear el payload de la entry function# Esto especifica qué función llamar y con qué argumentosentry_function = EntryFunction.natural("0x1::aptos_account", # Dirección y nombre del módulo"transfer", # Nombre de la función[], # Argumentos de tipo (vacío para esta función)[# Argumentos de función con su tipo de serializaciónTransactionArgument(bob.address(), Serializer.struct), # Dirección del recipienteTransactionArgument(1000, Serializer.u64), # Monto a transferir (1000 octas)],)# Obtener el chain ID para la transacciónchain_id = await rest_client.chain_id()# Obtener el sequence number actual del senderaccount_data = await rest_client.account(alice.address())sequence_number = int(account_data["sequence_number"])# Crear la raw transaction con todos los campos requeridosraw_transaction = RawTransaction(sender=alice.address(), # Dirección del sendersequence_number=sequence_number, # Sequence number para prevenir ataques de replaypayload=TransactionPayload(entry_function), # La función a llamarmax_gas_amount=2000, # Unidades máximas de gas a usargas_unit_price=100, # Precio por unidad de gas en octasexpiration_timestamps_secs=int(time.time()) + 600, # Expira en 10 minutoschain_id=chain_id, # Chain ID para asegurar la red correcta)print("Transacción construida exitosamente")print(f"Sender: {raw_transaction.sender}")print(f"Sequence Number: {raw_transaction.sequence_number}")print(f"Max Gas Amount: {raw_transaction.max_gas_amount}")print(f"Gas Unit Price: {raw_transaction.gas_unit_price}")print(f"Expiration Timestamp: {time.ctime(raw_transaction.expiration_timestamps_secs)}")
4. Simulando la Transacción
Sección titulada «4. Simulando la Transacción»Antes de hacer submit de una transacción, es una buena práctica simularla primero para estimar el costo del gas. Esto es como revisar los costos de envío antes de mandar un paquete.
-
Simular la transacción
Agrega este código después de construir la transacción:
// 2. Simular la transacciónconsole.log("\n=== 2. Simulando la transacción ===");const [simulationResult] = await aptos.transaction.simulate.simple({signerPublicKey: alice.publicKey,transaction,});const gasUsed = parseInt(simulationResult.gas_used);const gasUnitPrice = parseInt(simulationResult.gas_unit_price);console.log(`Unidades de gas estimadas: ${gasUsed}`);console.log(`Costo de gas estimado: ${gasUsed * gasUnitPrice} octas`);console.log(`La transacción sería ${simulationResult.success ? "exitosa" : "fallida"}`);
Antes de hacer submit de una transacción, es una buena práctica simularla primero para estimar el costo del gas. Esto es como revisar los costos de envío antes de mandar un paquete.
-
Simular la transacción
Agrega este código después de construir la transacción:
# 2. Simular la transacciónprint("\n=== 2. Simulando la transacción ===")# Crear una transacción BCS para simulación# Esto realmente no hace submit de la transacción a la blockchainsimulation_transaction = await rest_client.create_bcs_transaction(alice, TransactionPayload(entry_function))# Simular la transacción para estimar costos de gas y revisar erroressimulation_result = await rest_client.simulate_transaction(simulation_transaction, alice)# Extraer y mostrar los resultados de la simulacióngas_used = int(simulation_result[0]['gas_used'])gas_unit_price = int(simulation_result[0]['gas_unit_price'])success = simulation_result[0]['success']print(f"Unidades de gas estimadas: {gas_used}")print(f"Costo de gas estimado: {gas_used * gas_unit_price} octas")print(f"La transacción sería {'exitosa' if success else 'fallida'}")
5. Firmando y haciendo Submit de la Transacción
Sección titulada «5. Firmando y haciendo Submit de la Transacción»Ahora que hemos construido y simulado la transacción, necesitamos firmarla con la private key de Alice y hacerle submit a la blockchain.
-
Firmar la transacción
La firma prueba que Alice autorizó esta transacción:
Agrega este código después de simular la transacción:
// 3. Firmar la transacciónconsole.log("\n=== 3. Firmando la transacción ===");const senderAuthenticator = aptos.transaction.sign({signer: alice,transaction,});console.log("Transacción firmada exitosamente"); -
Hacer submit de la transacción
Agrega este código después de firmar la transacción para enviar la transacción firmada a la blockchain:
// 4. Hacer submit de la transacciónconsole.log("\n=== 4. Haciendo submit de la transacción ===");const pendingTransaction = await aptos.transaction.submit.simple({transaction,senderAuthenticator,});console.log(`Transacción enviada con hash: ${pendingTransaction.hash}`);
Ahora que hemos construido y simulado la transacción, necesitamos firmarla con la private key de Alice y hacerle submit a la blockchain.
-
Firmar la transacción
La firma prueba que Alice autorizó esta transacción:
Agrega este código después de simular la transacción:
# 3. Firmar la transacciónprint("\n=== 3. Firmando la transacción ===")# Firmar la raw transaction con la private key del sender# Esto crea una firma criptográfica que prueba que el sender autorizó esta transacciónsigned_transaction = await rest_client.create_bcs_signed_transaction(alice, # Cuenta con la private keyTransactionPayload(entry_function), # El payload de nuestra transacciónsequence_number=sequence_number # Usar el mismo sequence number de antes)print("Transacción firmada exitosamente")# No podemos extraer fácilmente la firma del objeto signed transaction,# pero podemos confirmar que fue creada -
Hacer submit de la transacción
Agrega este código después de firmar la transacción para enviar la transacción firmada a la blockchain:
# 4. Hacer submit de la transacciónprint("\n=== 4. Haciendo submit de la transacción ===")# Hacer submit de la transacción firmada a la blockchain# Esto transmite la transacción a la red para ser procesadatx_hash = await rest_client.submit_bcs_transaction(signed_transaction)print(f"Transacción enviada con hash: {tx_hash}")
6. Esperando Confirmación
Sección titulada «6. Esperando Confirmación»Después de hacer submit de una transacción, necesitamos esperar a que sea procesada por la blockchain. Esto es como esperar a que te entreguen el paquete.
-
Esperar a que se complete la transacción
Agrega este código después de enviar la transacción:
// 5. Esperar a que la transacción se completeconsole.log("\n=== 5. Esperando a que se complete la transacción ===");const txnResult = await aptos.waitForTransaction({transactionHash: pendingTransaction.hash,});console.log(`Transacción completada con estado: ${txnResult.success ? "SUCCESS" : "FAILURE"}`);// Si quieres ver más detalles sobre la transacción:console.log(`VM Status: ${txnResult.vm_status}`);console.log(`Gas used: ${txnResult.gas_used}`); -
Verificar los resultados
Agrega este código después de esperar a la transacción para revisar los balances y confirmar que la transferencia funcionó:
// Revisar balances finalesconst aliceFinalBalance = await aptos.getAccountAPTAmount({accountAddress: alice.accountAddress,});const bobFinalBalance = await aptos.getAccountAPTAmount({accountAddress: bob.accountAddress,});console.log("\n=== Balances Finales ===");console.log(`Alice: ${aliceFinalBalance} octas (gastó ${aliceBalance - aliceFinalBalance} octas en transferencia y gas)`);console.log(`Bob: ${bobFinalBalance} octas (recibió 1000 octas)`); -
Correr el código completo
Ventana de terminal npx ts-node transaction.tsDeberías ver una salida similar a:
Conectado a Aptos devnet=== Direcciones ===Dirección de Alice: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaDirección de Bob: 0x7af2d6c93a2feafc9b69b5e8ad9d6b513b260f62f23f3a384a3a2e4a84694a9b=== Fondeando cuentas ===Cuentas fondeadas exitosamente=== Balances Iniciales ===Alice: 100000000 octasBob: 0 octas=== 1. Construyendo la transacción ===Transacción construida exitosamenteSender: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaSequence Number: 0Max Gas Amount: 20000Gas Unit Price: 100Expiration Timestamp: 2025-03-05T22:59:21.000Z=== 2. Simulando la transacción ===Unidades de gas estimadas: 146Costo de gas estimado: 14600 octasLa transacción sería exitosa=== 3. Firmando la transacción ===Transacción firmada exitosamente=== 4. Haciendo submit de la transacción ===Transacción enviada con hash: 0x3a8a3e34a1c64ad9d7636a3a827b7ec3bb12d73825b36fa06d425c5a3b42cccc=== 5. Esperando a que se complete la transacción ===Transacción completada con estado: SUCCESSVM Status: Executed successfullyGas used: 146=== Balances Finales ===Alice: 99984400 octas (gastó 15600 octas en transferencia y gas)Bob: 1000 octas (recibió 1000 octas)
Después de hacer submit de una transacción, necesitamos esperar a que sea procesada por la blockchain. Esto es como esperar a que te entreguen el paquete.
-
Esperar a que se complete la transacción
Agrega este código después de enviar la transacción:
# 5. Esperar a que se complete la transacciónprint("\n=== 5. Esperando a que se complete la transacción ===");# Esperar a que la transacción sea procesada por la blockchain# Esto hace polling a la blockchain hasta que la transacción sea confirmadaawait rest_client.wait_for_transaction(tx_hash)# Obtener los detalles de la transacción para revisar su estadotransaction_details = await rest_client.transaction_by_hash(tx_hash)success = transaction_details["success"]vm_status = transaction_details["vm_status"]gas_used = transaction_details["gas_used"]print(f"Transacción completada con estado: {'SUCCESS' if success else 'FAILURE'}")print(f"VM Status: {vm_status}")print(f"Gas used: {gas_used}") -
Verificar los resultados
Agrega este código después de esperar a la transacción para revisar los balances y confirmar que la transferencia funcionó:
# Revisar balances finalesalice_final_balance = await rest_client.account_balance(alice.address())bob_final_balance = await rest_client.account_balance(bob.address())print("\n=== Balances Finales ===")print(f"Alice: {alice_final_balance} octas (gastó {alice_balance - alice_final_balance} octas en transferencia y gas)")print(f"Bob: {bob_final_balance} octas (recibió 1000 octas)") -
Correr el código completo
Ventana de terminal python transaction.pyDeberías ver una salida similar a:
Conectado a Aptos devnet=== Direcciones ===Dirección de Alice: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaDirección de Bob: 0x7af2d6c93a2feafc9b69b5e8ad9d6b513b260f62f23f3a384a3a2e4a84694a9b=== Fondeando cuentas ===Cuenta fondeada exitosamente=== Balances Iniciales ===Alice: 100000000 octasBob: 0 octas=== 1. Construyendo la transacción ===Transacción construida exitosamenteSender: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaSequence Number: 0Max Gas Amount: 2000Gas Unit Price: 100Expiration Timestamp: Wed Mar 05 22:59:21 2025=== 2. Simulando la transacción ===Unidades de gas estimadas: 146Costo de gas estimado: 14600 octasLa transacción sería exitosa=== 3. Firmando la transacción ===Transacción firmada exitosamente=== 4. Haciendo submit de la transacción ===Transacción enviada con hash: 0x3a8a3e34a1c64ad9d7636a3a827b7ec3bb12d73825b36fa06d425c5a3b42cccc=== 5. Esperando a que se complete la transacción ===Transacción completada con estado: SUCCESSVM Status: Executed successfullyGas used: 146=== Balances Finales ===Alice: 99984400 octas (gastó 15600 octas en transferencia y gas)Bob: 1000 octas (recibió 1000 octas)
7. (Opcional) Explora tu Transacción On-Chain
Sección titulada «7. (Opcional) Explora tu Transacción On-Chain»Ahora que has ejecutado exitosamente una transacción, puedes explorarla en el Aptos Explorer. Esto te ayudará a entender cómo se registran las transacciones en la blockchain y qué información está disponible públicamente.
-
Copia tu transaction hash
Desde la salida de tu terminal, copia el hash de la transacción que se imprimió después del submit. Se ve algo así:
Transacción enviada con hash: 0x3a8a3e34a1c64ad9d7636a3a827b7ec3bb12d73825b36fa06d425c5a3b42cccc -
Abre el Aptos Explorer
Ve al Aptos Explorer.
-
Asegúrate de estar en Devnet
Busca “Devnet” en la esquina superior derecha, o cambia de red haciendo clic en el dropdown y seleccionando Devnet.

-
Busca tu transacción
Pega tu transaction hash en la barra de búsqueda en el medio de la página.
-
Mira los detalles de la transacción
Espera a que aparezcan los resultados, luego haz clic en el transaction hash para ver sus detalles.
Deberías ver información sobre tu transacción, incluyendo:
- Estado (debería ser “Success”)
- Timestamp
- Gas used
- Direcciones del sender y el recipiente
- Monto transferido
-
Explora más a fondo
Desde la página de detalles de la transacción, puedes:
- Hacer clic en las direcciones del sender o recipiente para ver los detalles de su cuenta
- Ver los cambios exactos hechos al estado de la blockchain
- Ver el payload de la transacción y los argumentos
8. Siguientes Pasos
Sección titulada «8. Siguientes Pasos»¡Felicitaciones! Has creado y ejecutado exitosamente tu primera transacción en la blockchain de Aptos. Aquí hay algunas sugerencias para explorar a continuación:
Aprende sobre transacciones más complejas:
- Firmas Multi-Agent - Transacciones que requieren múltiples signers
- Transacciones Patrocinadas - Hacer que otra cuenta pague los gas fees
- Batching de Transacciones - Enviar múltiples transacciones eficientemente
Explora smart contracts o conceptos básicos de cuentas:
- Tu Primer Módulo Move - Crea tu propio smart contract
- Conceptos Básicos de Cuentas
¡Únete al Discord de Aptos y comparte lo que estás construyendo!
Full Code Sample
Sección titulada «Full Code Sample»Los ejemplos de código completo abajo combinan todos los snippets que hemos cubierto en este tutorial:
import { Account, Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
async function main() { // Inicializar el cliente de Aptos const config = new AptosConfig({ network: Network.DEVNET }); const aptos = new Aptos(config);
console.log("Conectado a Aptos devnet");
// Más código irá aquí // Generar dos cuentas const alice = Account.generate(); const bob = Account.generate();
console.log("=== Direcciones ==="); console.log(`Dirección de Alice: ${alice.accountAddress}`); console.log(`Dirección de Bob: ${bob.accountAddress}`);
// Fondear las cuentas con APT de prueba del faucet de devnet console.log("\n=== Fondeando cuentas ==="); await aptos.fundAccount({ accountAddress: alice.accountAddress, amount: 100_000_000, // 1 APT = 100,000,000 octas }); await aptos.fundAccount({ accountAddress: bob.accountAddress, amount: 0, // Bob empieza con 0 APT }); console.log("Cuentas fondeadas exitosamente");
// Revisar balances iniciales const aliceBalance = await aptos.getAccountAPTAmount({ accountAddress: alice.accountAddress, }); const bobBalance = await aptos.getAccountAPTAmount({ accountAddress: bob.accountAddress, });
console.log("\n=== Balances Iniciales ==="); console.log(`Alice: ${aliceBalance} octas`); console.log(`Bob: ${bobBalance} octas`);
// 1. Construir la transacción console.log("\n=== 1. Construyendo la transacción ==="); const transaction = await aptos.transaction.build.simple({ sender: alice.accountAddress, data: { function: "0x1::aptos_account::transfer", functionArguments: [bob.accountAddress, 1000], // Transferir 1000 octas }, }); console.log("Transacción construida exitosamente"); // Usar aserción de tipo para saltar el chequeo de tipos de TypeScript const txnAny = transaction as any; console.log(`Sender: ${alice.accountAddress}`); // Usar la dirección de sender conocida console.log(`Sequence Number: ${txnAny.sequenceNumber || "N/A"}`); console.log(`Max Gas Amount: ${txnAny.maxGasAmount || "N/A"}`); console.log(`Gas Unit Price: ${txnAny.gasUnitPrice || "N/A"}`); console.log( `Expiration Timestamp: ${new Date( Number(txnAny.expirationTimestampSecs || 0) * 1000 ).toISOString()}` );
// 2. Simular la transacción console.log("\n=== 2. Simulando la transacción ==="); const [simulationResult] = await aptos.transaction.simulate.simple({ signerPublicKey: alice.publicKey, transaction, });
console.log(`Unidades de gas estimadas: ${simulationResult.gas_used}`); console.log( `Costo de gas estimado: ${ Number(simulationResult.gas_used) * Number(simulationResult.gas_unit_price) } octas` ); console.log( `La transacción sería ${simulationResult.success ? "exitosa" : "fallida"}` );
// 3. Firmar la transacción console.log("\n=== 3. Firmando la transacción ==="); const senderAuthenticator = aptos.transaction.sign({ signer: alice, transaction, }); console.log("Transacción firmada exitosamente"); // Usar aserción de tipo para saltar el chequeo de tipos de TypeScript const authAny = senderAuthenticator as any; const signatureStr = typeof authAny.signature === 'string' ? authAny.signature : JSON.stringify(authAny.signature || ''); console.log(`Signature: ${signatureStr.slice(0, 20)}...`);
// 4. Hacer submit de la transacción console.log("\n=== 4. Haciendo submit de la transacción ==="); const pendingTransaction = await aptos.transaction.submit.simple({ transaction, senderAuthenticator, }); console.log(`Transacción enviada con hash: ${pendingTransaction.hash}`);
// 5. Esperar a que la transacción se complete console.log("\n=== 5. Esperando a que se complete la transacción ==="); const txnResult = await aptos.waitForTransaction({ transactionHash: pendingTransaction.hash, }); console.log( `Transacción completada con estado: ${ txnResult.success ? "SUCCESS" : "FAILURE" }` );
// Si quieres ver más detalles sobre la transacción: console.log(`VM Status: ${txnResult.vm_status}`); console.log(`Gas used: ${txnResult.gas_used}`);
// Revisar balances finales const aliceFinalBalance = await aptos.getAccountAPTAmount({ accountAddress: alice.accountAddress, }); const bobFinalBalance = await aptos.getAccountAPTAmount({ accountAddress: bob.accountAddress, });
console.log("\n=== Balances Finales ==="); console.log( `Alice: ${aliceFinalBalance} octas (gastó ${ aliceBalance - aliceFinalBalance } octas en transferencia y gas)` ); console.log(`Bob: ${bobFinalBalance} octas (recibió 1000 octas)`);}
main().catch(console.error);import asynciofrom aptos_sdk.account import Accountfrom aptos_sdk.async_client import FaucetClient, RestClientfrom aptos_sdk.transactions import EntryFunction, TransactionPayload, TransactionArgument, RawTransactionfrom aptos_sdk.bcs import Serializerimport time
# Configuración de la redNODE_URL = "https://fullnode.devnet.aptoslabs.com/v1"FAUCET_URL = "https://faucet.devnet.aptoslabs.com"
async def main(): # Inicializar los clientes rest_client = RestClient(NODE_URL) faucet_client = FaucetClient(FAUCET_URL, rest_client)
print("Conectado a Aptos devnet")
# Generar dos cuentas alice = Account.generate() bob = Account.generate()
print("=== Direcciones ==="); print(f"Dirección de Alice: {alice.address()}") print(f"Dirección de Bob: {bob.address()}") # Más código irá aquí # Fondear las cuentas con APT de prueba del faucet de devnet print("\n=== Fondeando cuentas ==="); alice_amount = 100_000_000 # 1 APT = 100,000,000 octas bob_amount = 0 # Bob empieza con 0 APT
await faucet_client.fund_account(alice.address(), alice_amount) await faucet_client.fund_account(bob.address(), bob_amount) print("Cuentas fondeadas exitosamente");
# Revisar balances iniciales alice_balance = await rest_client.account_balance(alice.address()) bob_balance = await rest_client.account_balance(bob.address())
print("\n=== Balances Iniciales ==="); print(f"Alice: {alice_balance} octas") print(f"Bob: {bob_balance} octas")
# 1. Construir la transacción print("\n=== 1. Construyendo la transacción ===")
# Crear el payload de la entry function # Esto especifica qué función llamar y con qué argumentos entry_function = EntryFunction.natural( "0x1::aptos_account", # Dirección y nombre del módulo "transfer", # Nombre de la función [], # Argumentos de tipo (vacío para esta función) [ # Argumentos de función con su tipo de serialización TransactionArgument(bob.address(), Serializer.struct), # Dirección del recipiente TransactionArgument(1000, Serializer.u64), # Monto a transferir (1000 octas) ], )
# Obtener el chain ID para la transacción chain_id = await rest_client.chain_id()
# Obtener el sequence number actual del sender account_data = await rest_client.account(alice.address()) sequence_number = int(account_data["sequence_number"])
# Crear la raw transaction con todos los campos requeridos raw_transaction = RawTransaction( sender=alice.address(), # Dirección del sender sequence_number=sequence_number, # Sequence number para prevenir ataques de replay payload=TransactionPayload(entry_function), # La función a llamar max_gas_amount=2000, # Unidades máximas de gas a usar gas_unit_price=100, # Precio por unidad de gas en octas expiration_timestamps_secs=int(time.time()) + 600, # Expira en 10 minutos chain_id=chain_id, # Chain ID para asegurar la red correcta )
print("Transacción construida exitosamente") print(f"Sender: {raw_transaction.sender}") print(f"Sequence Number: {raw_transaction.sequence_number}") print(f"Max Gas Amount: {raw_transaction.max_gas_amount}") print(f"Gas Unit Price: {raw_transaction.gas_unit_price}") print(f"Expiration Timestamp: {time.ctime(raw_transaction.expiration_timestamps_secs)}")
# 2. Simular la transacción print("\n=== 2. Simulando la transacción ===")
# Crear una transacción BCS para simulación # Esto realmente no hace submit de la transacción a la blockchain simulation_transaction = await rest_client.create_bcs_transaction(alice, TransactionPayload(entry_function))
# Simular la transacción para estimar costos de gas y revisar errores simulation_result = await rest_client.simulate_transaction(simulation_transaction, alice)
# Extraer y mostrar los resultados de la simulación gas_used = int(simulation_result[0]['gas_used']) gas_unit_price = int(simulation_result[0]['gas_unit_price']) success = simulation_result[0]['success']
print(f"Unidades de gas estimadas: {gas_used}") print(f"Costo de gas estimado: {gas_used * gas_unit_price} octas") print(f"La transacción sería {'exitosa' if success else 'fallida'}")
# 3. Firmar la transacción print("\n=== 3. Firmando la transacción ===")
# Firmar la raw transaction con la private key del sender # Esto crea una firma criptográfica que prueba que el sender autorizó esta transacción signed_transaction = await rest_client.create_bcs_signed_transaction( alice, # Cuenta con la private key TransactionPayload(entry_function), # El payload de nuestra transacción sequence_number=sequence_number # Usar el mismo sequence number de antes )
print("Transacción firmada exitosamente") # No podemos extraer fácilmente la firma del objeto signed transaction, # pero podemos confirmar que fue creada
# 4. Hacer submit de la transacción print("\n=== 4. Haciendo submit de la transacción ===");
# Hacer submit de la transacción firmada a la blockchain # Esto transmite la transacción a la red para ser procesada tx_hash = await rest_client.submit_bcs_transaction(signed_transaction)
print(f"Transacción enviada con hash: {tx_hash}")
# 5. Esperar a que se complete la transacción print("\n=== 5. Esperando a que se complete la transacción ===");
# Esperar a que la transacción sea procesada por la blockchain # Esto hace polling a la blockchain hasta que la transacción sea confirmada await rest_client.wait_for_transaction(tx_hash)
# Obtener los detalles de la transacción para revisar su estado transaction_details = await rest_client.transaction_by_hash(tx_hash) success = transaction_details["success"] vm_status = transaction_details["vm_status"] gas_used = transaction_details["gas_used"]
print(f"Transacción completada con estado: {'SUCCESS' if success else 'FAILURE'}") print(f"VM Status: {vm_status}") print(f"Gas used: {gas_used}")
# Revisar balances finales alice_final_balance = await rest_client.account_balance(alice.address()) bob_final_balance = await rest_client.account_balance(bob.address())
print("\n=== Balances Finales ==="); print(f"Alice: {alice_final_balance} octas (gastó {alice_balance - alice_final_balance} octas en transferencia y gas)") print(f"Bob: {bob_final_balance} octas (recibió 1000 octas)")if __name__ == "__main__": asyncio.run(main())