Tu Primera Transacción
Las transacciones son la forma fundamental de cambiar datos en la blockchain de Aptos. Piensa en ellas como enviar un paquete: necesitas especificar qué estás enviando, a quién va dirigido, y luego rastrearlo hasta que se confirme la entrega. En términos de blockchain, las transacciones te permiten transferir monedas, llamar funciones de contratos inteligentes y actualizar el estado en cadena.
Este tutorial te guiará a través de la creación y envío de tu primera transacción en la blockchain de Aptos. Aprenderás cómo:
- Configurar tu entorno de desarrollo
- Crear cuentas de prueba y financiarlas
- Construir una transacción para transferir monedas
- Simular la transacción para estimar costos
- Firmar y enviar la transacción
- Verificar que la transacción se ejecutó exitosamente
1. Configuración de Tu Entorno
Sección titulada «1. Configuración de Tu Entorno»Antes de poder crear transacciones, necesitamos configurar nuestro entorno de desarrollo con las herramientas y SDKs necesarias.
-
Instalar el SDK de TypeScript
Instala el SDK de TypeScript usando tu gestor de paquetes 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 de proyecto
Crea un nuevo directorio para tu proyecto:
Ventana de terminal mkdir mi-primera-transaccioncd mi-primera-transaccion -
Crear un nuevo archivo
Crea un nuevo archivo llamado
transaction.ts
:Ventana de terminal touch transaction.tsVentana de terminal type nul > transaction.ts
Antes de poder crear transacciones, necesitamos configurar nuestro entorno de desarrollo con las herramientas y SDKs necesarias.
-
Instalar el SDK de Python
Instala el SDK de Python usando pip:
Ventana de terminal pip install aptos-sdk -
Crear un directorio de proyecto
Crea un nuevo directorio para tu proyecto:
Ventana de terminal mkdir mi-primera-transaccioncd mi-primera-transaccion -
Crear un nuevo archivo
Crea un nuevo archivo 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 provenir de una cuenta. Vamos a crear dos cuentas de prueba: una para enviar monedas (Alice) y otra para recibirlas (Bob).
-
Configurar el cliente
Primero, necesitamos inicializar el cliente de Aptos que se conectará a la blockchain. Abre
transaction.ts
en 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 (remitente) y Bob (receptor):// 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}`); -
Financiar las cuentas
Agrega este código después de generar las cuentas para obtener monedas de prueba del faucet:
// Financiar las cuentas con APT de prueba del faucet de devnetconsole.log("\n=== Financiando cuentas ===");await aptos.fundAccount({accountAddress: alice.accountAddress,amount: 100_000_000, // 1 APT = 100,000,000 octas});console.log("Cuentas financiadas exitosamente");// Verificar saldos inicialesconst aliceBalance = await aptos.getAccountAPTAmount({accountAddress: alice.accountAddress,});const bobBalance = await aptos.getAccountAPTAmount({accountAddress: bob.accountAddress,});console.log("\n=== Saldos Iniciales ===");console.log(`Alice: ${aliceBalance} octas`);console.log(`Bob: ${bobBalance} octas`); -
Ejecutar el código
Vamos a probar 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=== Financiando cuentas ===Cuentas financiadas exitosamente=== Saldos Iniciales ===Alice: 100000000 octasBob: 0 octas
En blockchain, todas las transacciones deben provenir de una cuenta. Vamos a crear dos cuentas de prueba: una para enviar monedas (Alice) y otra para recibirlas (Bob).
-
Configurar el cliente
Primero, necesitamos inicializar el cliente de Aptos que se conectará a la blockchain. Abre
transaction.py
en 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 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 (remitente) y Bob (receptor):# 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()}") -
Financiar las cuentas
Agrega este código después de generar las cuentas para obtener monedas de prueba del faucet:
# Financiar las cuentas con APT de prueba del faucet de devnetprint("\n=== Financiando 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 financiada exitosamente")# Verificar saldos inicialesalice_balance = await rest_client.account_balance(alice.address())bob_balance = await rest_client.account_balance(bob.address())print("\n=== Saldos Iniciales ===")print(f"Alice: {alice_balance} octas")print(f"Bob: {bob_balance} octas") -
Ejecutar el código
Vamos a probar 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=== Financiando cuentas ===Cuenta financiada exitosamente=== Saldos Iniciales ===Alice: 100000000 octasBob: 0 octas
3. Construyendo una Transacción
Sección titulada «3. Construyendo una Transacción»Ahora que tenemos cuentas financiadas, vamos a crear una transacción para transferir monedas de Alice a Bob. Esto es como llenar un formulario especificando qué quieres enviar y a quién.
-
Entender la estructura de transacción
Una transacción en Aptos tiene varios componentes clave:
- Remitente: La cuenta que inicia la transacción (Alice)
- Función: La función en cadena a llamar (en este caso, una transferencia de monedas)
- Argumentos: Datos necesarios para la función (dirección del destinatario y cantidad)
- Parámetros de gas: Cantidad máxima de gas y precio unitario de gas
- Tiempo de expiración: Cuando la transacción deja de ser válida si no se ejecuta
- Número de secuencia: Un contador que previene ataques de repetición
-
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 los detalles de la transacción desde la transacción rawconst rawTxn = transaction.rawTransaction;console.log(`Remitente: ${rawTxn.sender}`);console.log(`Número de Secuencia: ${rawTxn.sequence_number}`);console.log(`Cantidad Máxima de Gas: ${rawTxn.max_gas_amount}`);console.log(`Precio Unitario de Gas: ${rawTxn.gas_unit_price}`);console.log(`Timestamp de Expiración: ${new Date(Number(rawTxn.expiration_timestamp_secs) * 1000).toISOString()}`);
Ahora que tenemos cuentas financiadas, vamos a crear una transacción para transferir monedas de Alice a Bob. Esto es como llenar un formulario especificando qué quieres enviar y a quién.
-
Entender la estructura de transacción
Una transacción en Aptos tiene varios componentes clave:
- Remitente: La cuenta que inicia la transacción (Alice)
- Función: La función en cadena a llamar (en este caso, una transferencia de monedas)
- Argumentos: Datos necesarios para la función (dirección del destinatario y cantidad)
- Parámetros de gas: Cantidad máxima de gas y precio unitario de gas
- Tiempo de expiración: Cuando la transacción deja de ser válida si no se ejecuta
- Número de secuencia: Un contador que previene ataques de repetición
-
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 función de entrada# 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 destinatarioTransactionArgument(1000, Serializer.u64), # Cantidad a transferir (1000 octas)],)# Obtener el ID de cadena para la transacciónchain_id = await rest_client.chain_id()# Obtener el número de secuencia actual del remitenteaccount_data = await rest_client.account(alice.address())sequence_number = int(account_data["sequence_number"])# Crear la transacción raw con todos los campos requeridosraw_transaction = RawTransaction(sender=alice.address(), # Dirección del remitentesequence_number=sequence_number, # Número de secuencia para prevenir ataques de repeticiónpayload=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, # ID de cadena para asegurar la red correcta)print("Transacción construida exitosamente")print(f"Remitente: {raw_transaction.sender}")print(f"Número de Secuencia: {raw_transaction.sequence_number}")print(f"Cantidad Máxima de Gas: {raw_transaction.max_gas_amount}")print(f"Precio Unitario de Gas: {raw_transaction.gas_unit_price}")print(f"Timestamp de Expiración: {time.ctime(raw_transaction.expiration_timestamps_secs)}")
4. Simulando la Transacción
Sección titulada «4. Simulando la Transacción»Antes de enviar una transacción, es sabio simularla primero para estimar el costo de gas. Esto es como verificar los costos de envío antes de enviar 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 ${simulationResult.success ? "tendría éxito" : "fallaría"}`);
Antes de enviar una transacción, es sabio simularla primero para estimar el costo de gas. Esto es como verificar los costos de envío antes de enviar 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 no envía realmente 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 verificar erroressimulation_result = await rest_client.simulate_transaction(simulation_transaction, alice)# Extraer y mostrar los resultados de 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 {'tendría éxito' if success else 'fallaría'}")
5. Firmando y Enviando la Transacción
Sección titulada «5. Firmando y Enviando la Transacción»Ahora que hemos construido y simulado la transacción, necesitamos firmarla con la clave privada de Alice y enviarla a la blockchain.
-
Firmar la transacción
Firmar 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"); -
Enviar la transacción
Agrega este código después de firmar la transacción para enviar la transacción firmada a la blockchain:
// 4. Enviar la transacciónconsole.log("\n=== 4. Enviando 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 clave privada de Alice y enviarla a la blockchain.
-
Firmar la transacción
Firmar 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 transacción raw con la clave privada del remitente# Esto crea una firma criptográfica que prueba que el remitente autorizó esta transacciónsigned_transaction = await rest_client.create_bcs_signed_transaction(alice, # Cuenta con la clave privadaTransactionPayload(entry_function), # El payload de nuestra transacciónsequence_number=sequence_number # Usar el mismo número de secuencia que antes)print("Transacción firmada exitosamente")# No podemos extraer fácilmente la firma del objeto de transacción firmada,# pero podemos confirmar que fue creada -
Enviar la transacción
Agrega este código después de firmar la transacción para enviar la transacción firmada a la blockchain:
# 4. Enviar la transacciónprint("\n=== 4. Enviando la transacción ===")# Enviar la transacción firmada a la blockchain# Esto transmite la transacción a la red para procesamientotx_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 enviar una transacción, necesitamos esperar a que sea procesada por la blockchain. Esto es como esperar a que un paquete sea entregado.
-
Esperar completación de 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 completación de la transacción ===");const txnResult = await aptos.waitForTransaction({transactionHash: pendingTransaction.hash,});console.log(`Transacción completada con estado: ${txnResult.success ? "ÉXITO" : "FALLIDO"}`);// Si quieres ver más detalles sobre la transacción:console.log(`Estado VM: ${txnResult.vm_status}`);console.log(`Gas usado: ${txnResult.gas_used}`); -
Verificar los resultados
Agrega este código después de esperar la transacción para verificar los saldos y confirmar que la transferencia funcionó:
// Verificar saldos finalesconst aliceFinalBalance = await aptos.getAccountAPTAmount({accountAddress: alice.accountAddress,});const bobFinalBalance = await aptos.getAccountAPTAmount({accountAddress: bob.accountAddress,});console.log("\n=== Saldos Finales ===");console.log(`Alice: ${aliceFinalBalance} octas (gastó ${aliceBalance - aliceFinalBalance} octas en transferencia y gas)`);console.log(`Bob: ${bobFinalBalance} octas (recibió 1000 octas)`); -
Ejecutar 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=== Financiando cuentas ===Cuentas financiadas exitosamente=== Saldos Iniciales ===Alice: 100000000 octasBob: 0 octas=== 1. Construyendo la transacción ===Transacción construida exitosamenteRemitente: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaNúmero de Secuencia: 0Cantidad Máxima de Gas: 20000Precio Unitario de Gas: 100Timestamp de Expiración: 2025-03-05T22:59:21.000Z=== 2. Simulando la transacción ===Unidades de gas estimadas: 146Costo de gas estimado: 14600 octasLa transacción tendría éxito=== 3. Firmando la transacción ===Transacción firmada exitosamente=== 4. Enviando la transacción ===Transacción enviada con hash: 0x3a8a3e34a1c64ad9d7636a3a827b7ec3bb12d73825b36fa06d425c5a3b42cccc=== 5. Esperando completación de la transacción ===Transacción completada con estado: ÉXITOEstado VM: Ejecutado exitosamenteGas usado: 146=== Saldos Finales ===Alice: 99984400 octas (gastó 15600 octas en transferencia y gas)Bob: 1000 octas (recibió 1000 octas)
Después de enviar una transacción, necesitamos esperar a que sea procesada por la blockchain. Esto es como esperar a que un paquete sea entregado.
-
Esperar completación de la transacción
Agrega este código después de enviar la transacción:
# 5. Esperar a que la transacción se completeprint("\n=== 5. Esperando completación de la transacción ===")# Esperar a que la transacción sea procesada por la blockchain# Esto sondea la blockchain hasta que la transacción sea confirmadaawait rest_client.wait_for_transaction(tx_hash)# Obtener los detalles de la transacción para verificar 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: {'ÉXITO' if success else 'FALLIDO'}")print(f"Estado VM: {vm_status}")print(f"Gas usado: {gas_used}") -
Verificar los resultados
Agrega este código después de esperar la transacción para verificar los saldos y confirmar que la transferencia funcionó:
# Verificar saldos finalesalice_final_balance = await rest_client.account_balance(alice.address())bob_final_balance = await rest_client.account_balance(bob.address())print("\n=== Saldos 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)") -
Ejecutar 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=== Financiando cuentas ===Cuentas financiadas exitosamente=== Saldos Iniciales ===Alice: 100000000 octasBob: 0 octas=== 1. Construyendo la transacción ===Transacción construida exitosamenteRemitente: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaNúmero de Secuencia: 0Cantidad Máxima de Gas: 2000Precio Unitario de Gas: 100Timestamp de Expiración: Wed Mar 05 22:59:21 2025=== 2. Simulando la transacción ===Unidades de gas estimadas: 146Costo de gas estimado: 14600 octasLa transacción tendría éxito=== 3. Firmando la transacción ===Transacción firmada exitosamente=== 4. Enviando la transacción ====== 3. Firmando la transacción ===Transacción firmada exitosamente=== 4. Enviando la transacción ===Transacción enviada con hash: 0x3a8a3e34a1c64ad9d7636a3a827b7ec3bb12d73825b36fa06d425c5a3b42cccc=== 5. Esperando completación de la transacción ===Transacción completada con estado: ÉXITOEstado VM: Ejecutado exitosamenteGas usado: 146=== Saldos Finales ===Alice: 99984400 octas (gastó 15600 octas en transferencia y gas)Bob: 1000 octas (recibió 1000 octas)
7. (Opcional) Explora Tu Transacción En Cadena
Sección titulada «7. (Opcional) Explora Tu Transacción En Cadena»Ahora que has ejecutado exitosamente una transacción, puedes explorarla en el Explorador de Aptos. Esto te ayudará a entender cómo se registran las transacciones en la blockchain y qué información está disponible públicamente.
-
Copia el hash de tu transacción
Desde la salida de tu terminal, copia el hash de transacción que se imprimió después del envío. Se ve algo como esto:
Transacción enviada con hash: 0x3a8a3e34a1c64ad9d7636a3a827b7ec3bb12d73825b36fa06d425c5a3b42cccc -
Abre el Explorador de Aptos
Ve al Explorador de Aptos.
-
Asegúrate de estar en la red 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 el hash de tu transacción en la barra de búsqueda en el medio de la página.
-
Ve los detalles de la transacción
Espera a que aparezcan los resultados, luego haz clic en el hash de transacción para ver sus detalles.
Deberías ver información sobre tu transacción, incluyendo:
- Estado (debería ser “Success”)
- Timestamp
- Gas usado
- Direcciones del remitente y destinatario
- Cantidad transferida
-
Explora más
Desde la página de detalles de la transacción, puedes:
- Hacer clic en las direcciones del remitente o destinatario para ver los detalles de sus cuentas
- Ver los cambios exactos hechos al estado de la blockchain
- Ver el payload y argumentos de la transacción
8. Próximos Pasos
Sección titulada «8. Próximos Pasos»¡Felicitaciones! Has creado y ejecutado exitosamente tu primera transacción en la blockchain de Aptos. Aquí hay algunas sugerencias para qué explorar a continuación:
Aprende sobre transacciones más complejas:
- Firmas Multi-Agente - Transacciones que requieren múltiples firmantes
- Patrocinio de Transacciones - Hacer que otra cuenta pague las tarifas de gas
- Agrupación de Transacciones - Enviar múltiples transacciones eficientemente
Explora contratos inteligentes o conceptos básicos de cuentas:
- Tu Primer Módulo Move - Crea tu propio contrato inteligente
- Conceptos Básicos de Cuentas
¡Únete al Discord de Aptos y comparte lo que estás construyendo!
Muestra Completa de Código
Sección titulada «Muestra Completa de Código»Las muestras completas de código a continuación combinan todos los fragmentos que hemos cubierto en este tutorial:
import { Account, Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
async function main() { // Initialize the Aptos client const config = new AptosConfig({ network: Network.DEVNET }); const aptos = new Aptos(config);
console.log("Connected to Aptos devnet");
// More code will go here // Generate two accounts const alice = Account.generate(); const bob = Account.generate();
console.log("=== Addresses ==="); console.log(`Alice's address: ${alice.accountAddress}`); console.log(`Bob's address: ${bob.accountAddress}`);
// Fund the accounts with test APT from the devnet faucet console.log("\n=== Funding accounts ==="); 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 starts with 0 APT }); console.log("Accounts funded successfully");
// Check initial balances const aliceBalance = await aptos.getAccountAPTAmount({ accountAddress: alice.accountAddress, }); const bobBalance = await aptos.getAccountAPTAmount({ accountAddress: bob.accountAddress, });
console.log("\n=== Initial Balances ==="); console.log(`Alice: ${aliceBalance} octas`); console.log(`Bob: ${bobBalance} octas`);
// 1. Build the transaction console.log("\n=== 1. Building the transaction ==="); const transaction = await aptos.transaction.build.simple({ sender: alice.accountAddress, data: { function: "0x1::aptos_account::transfer", functionArguments: [bob.accountAddress, 1000], // Transfer 1000 octas }, }); console.log("Transaction built successfully"); // Use type assertion to bypass TypeScript's type checking const txnAny = transaction as any; console.log(`Sender: ${alice.accountAddress}`); // Use the known sender address 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. Simulate the transaction console.log("\n=== 2. Simulating the transaction ==="); const [simulationResult] = await aptos.transaction.simulate.simple({ signerPublicKey: alice.publicKey, transaction, });
console.log(`Estimated gas units: ${simulationResult.gas_used}`); console.log( `Estimated gas cost: ${ Number(simulationResult.gas_used) * Number(simulationResult.gas_unit_price) } octas` ); console.log( `Transaction would ${simulationResult.success ? "succeed" : "fail"}` );
// 3. Sign the transaction console.log("\n=== 3. Signing the transaction ==="); const senderAuthenticator = aptos.transaction.sign({ signer: alice, transaction, }); console.log("Transaction signed successfully"); // Use type assertion to bypass TypeScript's type checking 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. Submit the transaction console.log("\n=== 4. Submitting the transaction ==="); const pendingTransaction = await aptos.transaction.submit.simple({ transaction, senderAuthenticator, }); console.log(`Transaction submitted with hash: ${pendingTransaction.hash}`);
// 5. Wait for the transaction to complete console.log("\n=== 5. Waiting for transaction completion ==="); const txnResult = await aptos.waitForTransaction({ transactionHash: pendingTransaction.hash, }); console.log( `Transaction completed with status: ${ txnResult.success ? "SUCCESS" : "FAILURE" }` );
// If you want to see more details about the transaction: console.log(`VM Status: ${txnResult.vm_status}`); console.log(`Gas used: ${txnResult.gas_used}`);
// Check final balances const aliceFinalBalance = await aptos.getAccountAPTAmount({ accountAddress: alice.accountAddress, }); const bobFinalBalance = await aptos.getAccountAPTAmount({ accountAddress: bob.accountAddress, });
console.log("\n=== Final Balances ==="); console.log( `Alice: ${aliceFinalBalance} octas (spent ${ aliceBalance - aliceFinalBalance } octas on transfer and gas)` ); console.log(`Bob: ${bobFinalBalance} octas (received 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
# Network configurationNODE_URL = "https://fullnode.devnet.aptoslabs.com/v1"FAUCET_URL = "https://faucet.devnet.aptoslabs.com"
async def main(): # Initialize the clients rest_client = RestClient(NODE_URL) faucet_client = FaucetClient(FAUCET_URL, rest_client)
print("Connected to Aptos devnet")
# Generate two accounts alice = Account.generate() bob = Account.generate()
print("=== Addresses ===") print(f"Alice's address: {alice.address()}") print(f"Bob's address: {bob.address()}") # More code will go here # Fund the accounts with test APT from the devnet faucet print("\n=== Funding accounts ===") alice_amount = 100_000_000 # 1 APT = 100,000,000 octas bob_amount = 0 # Bob starts with 0 APT
await faucet_client.fund_account(alice.address(), alice_amount) await faucet_client.fund_account(bob.address(), bob_amount) print("Accounts funded successfully")
# Check initial balances alice_balance = await rest_client.account_balance(alice.address()) bob_balance = await rest_client.account_balance(bob.address())
print("\n=== Initial Balances ===") print(f"Alice: {alice_balance} octas") print(f"Bob: {bob_balance} octas")
# 1. Build the transaction print("\n=== 1. Building the transaction ===")
# Create the entry function payload # This specifies which function to call and with what arguments entry_function = EntryFunction.natural( "0x1::aptos_account", # Module address and name "transfer", # Function name [], # Type arguments (empty for this function) [ # Function arguments with their serialization type TransactionArgument(bob.address(), Serializer.struct), # Recipient address TransactionArgument(1000, Serializer.u64), # Amount to transfer (1000 octas) ], )
# Get the chain ID for the transaction chain_id = await rest_client.chain_id()
# Get the sender's current sequence number account_data = await rest_client.account(alice.address()) sequence_number = int(account_data["sequence_number"])
# Create the raw transaction with all required fields raw_transaction = RawTransaction( sender=alice.address(), # Sender's address sequence_number=sequence_number, # Sequence number to prevent replay attacks payload=TransactionPayload(entry_function), # The function to call max_gas_amount=2000, # Maximum gas units to use gas_unit_price=100, # Price per gas unit in octas expiration_timestamps_secs=int(time.time()) + 600, # Expires in 10 minutes chain_id=chain_id, # Chain ID to ensure correct network )
print("Transaction built successfully") 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. Simulate the transaction print("\n=== 2. Simulating the transaction ===")
# Create a BCS transaction for simulation # This doesn't actually submit the transaction to the blockchain simulation_transaction = await rest_client.create_bcs_transaction(alice, TransactionPayload(entry_function))
# Simulate the transaction to estimate gas costs and check for errors simulation_result = await rest_client.simulate_transaction(simulation_transaction, alice)
# Extract and display the simulation results 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"Estimated gas units: {gas_used}") print(f"Estimated gas cost: {gas_used * gas_unit_price} octas") print(f"Transaction would {'succeed' if success else 'fail'}")
# 3. Sign the transaction print("\n=== 3. Signing the transaction ===")
# Sign the raw transaction with the sender's private key # This creates a cryptographic signature that proves the sender authorized this transaction signed_transaction = await rest_client.create_bcs_signed_transaction( alice, # Account with the private key TransactionPayload(entry_function), # The payload from our transaction sequence_number=sequence_number # Use the same sequence number as before )
print("Transaction signed successfully") # We can't easily extract the signature from the signed transaction object, # but we can confirm it was created
# 4. Submit the transaction print("\n=== 4. Submitting the transaction ===")
# Submit the signed transaction to the blockchain # This broadcasts the transaction to the network for processing tx_hash = await rest_client.submit_bcs_transaction(signed_transaction)
print(f"Transaction submitted with hash: {tx_hash}")
# 5. Wait for the transaction to complete print("\n=== 5. Waiting for transaction completion ===")
# Wait for the transaction to be processed by the blockchain # This polls the blockchain until the transaction is confirmed await rest_client.wait_for_transaction(tx_hash)
# Get the transaction details to check its status 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"Transaction completed with status: {'SUCCESS' if success else 'FAILURE'}") print(f"VM Status: {vm_status}") print(f"Gas used: {gas_used}")
# Check final balances alice_final_balance = await rest_client.account_balance(alice.address()) bob_final_balance = await rest_client.account_balance(bob.address())
print("\n=== Final Balances ===") print(f"Alice: {alice_final_balance} octas (spent {alice_balance - alice_final_balance} octas on transfer and gas)") print(f"Bob: {bob_final_balance} octas (received 1000 octas)")if __name__ == "__main__": asyncio.run(main())