SDK de Go - Construir Transacciones
Las transacciones te permiten cambiar datos en la cadena o activar eventos. Generalmente, las transacciones siguen 5 pasos desde la construcción hasta la ejecución en la cadena: construir, simular, firmar, enviar y esperar.
-
Construir
Construir una transacción es cómo especificas:
- La cuenta
Sender
.
Esta cuenta normalmente paga las comisiones de gas por esta transacción. Ver Transacciones Patrocinadas para aprender cómo hacer que otra cuenta pague por las comisiones de transacción. - La
Function
siendo llamada en la cadena.
Este es el identificador para la función de entrada del contrato inteligente en la cadena que se activará cuando ejecutes esta transacción. - Los
ArgTypes
yArgs
.
Esto es cualquier dato que la función necesita para ejecutarse.
Esto se puede hacer para una sola cuenta así:
// 1. Construir transacciónaccountBytes, err := bcs.Serialize(&bob.Address)if err != nil {panic("Failed to serialize bob's address:" + err.Error())}amountBytes, err := bcs.SerializeU64(TransferAmount)if err != nil {panic("Failed to serialize transfer amount:" + err.Error())}rawTxn, err := client.BuildTransaction(alice.AccountAddress(), aptos.TransactionPayload{Payload: &aptos.EntryFunction{Module: aptos.ModuleId{Address: aptos.AccountOne,Name: "aptos_account",},Function: "transfer",ArgTypes: []aptos.TypeTag{},Args: [][]byte{accountBytes,amountBytes,},}},)Opciones de Construcción
Sección titulada «Opciones de Construcción»Puedes personalizar la forma en que tu transacción se ejecuta pasando
options
al construir. Algunas de las opciones más comúnmente usadas son:MaxGasAmount
- Esto limita la cantidad de gas que estás dispuesto a pagar para ejecutar esta transacción.GasUnitPrice
- Puedes especificar un precio por gas mayor que el mínimo para ser ejecutado con mayor prioridad por la red de Aptos.ExpirationSeconds
- Esto da un tiempo concreto en que la transacción debe ejecutarse o será cancelada.
El SDK proporciona valores por defecto sensatos para estos valores si no se especifican explícitamente.
- La cuenta
-
Simular (Opcional)
Cada transacción en la cadena de Aptos tiene una comisión de gas asociada con cuánto trabajo las máquinas de la red tienen que hacer al ejecutar la transacción. Para estimar el costo asociado con eso, puedes simular transacciones antes de comprometerlas.
Puedes ejecutar la simulación usando
aptos.SimulateTransaction
así:// 2. Simular transacción (opcional)// Esto es útil para entender cuánto costará la transacción// y para asegurar que la transacción es válida antes de enviarla a la red// Esto es opcional, pero recomendadosimulationResult, err := client.SimulateTransaction(rawTxn, alice)// If the fee looks ok, continue to signing! -
Firmar
Una vez que la transacción está construida y los costos parecen razonables, puedes firmar la transacción con
rawTransaction.SignedTransaction()
. La firma debe venir de la cuentasender
.// 3. Firmar transacciónsignedTxn, err := rawTxn.SignedTransaction(alice) -
Enviar
Ahora que la transacción está firmada, puedes enviarla a la red usando
client.SubmitTransaction()
así:// 4. Enviar transacciónsubmitResult, err := client.SubmitTransaction(signedTxn) -
Esperar
Finalmente, puedes esperar el resultado de la transacción usando
client.WaitForTransaction()
y especificando el hash de la transacción que acabas de enviar así:// 5. Esperar la transacción para completartxnHash := submitResult.Hash_, err = client.WaitForTransaction(txnHash)
Ejemplo Completo en Go
Sección titulada «Ejemplo Completo en Go»// transfer_coin es un ejemplo de cómo hacer una transacción de transferencia de moneda en la forma más simple posiblepackage main
import ( "fmt"
"github.com/aptos-labs/aptos-go-sdk" "github.com/aptos-labs/aptos-go-sdk/bcs")
const FundAmount = 100_000_000const TransferAmount = 1_000
// example Este ejemplo muestra cómo hacer una transacción de transferencia de APT en la forma más simple posiblefunc example(networkConfig aptos.NetworkConfig) { // Crear un cliente para Aptos client, err := aptos.NewClient(networkConfig) if err != nil { panic("Failed to create client:" + err.Error()) }
// Crear cuentas localmente para alice y bob alice, err := aptos.NewEd25519Account() if err != nil { panic("Failed to create alice:" + err.Error()) } bob, err := aptos.NewEd25519Account() if err != nil { panic("Failed to create bob:" + err.Error()) }
fmt.Printf("\n=== Addresses ===\n") fmt.Printf("Alice: %s\n", alice.Address.String()) fmt.Printf("Bob:%s\n", bob.Address.String())
// Fundear el remitente con el faucet para crearlo en la cadena err = client.Fund(alice.Address, FundAmount) if err != nil { panic("Failed to fund alice:" + err.Error()) }
aliceBalance, err := client.AccountAPTBalance(alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } bobBalance, err := client.AccountAPTBalance(bob.Address) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } fmt.Printf("\n=== Initial Balances ===\n") fmt.Printf("Alice: %d\n", aliceBalance) fmt.Printf("Bob:%d\n", bobBalance)
// 1. Construir transacción accountBytes, err := bcs.Serialize(&bob.Address) if err != nil { panic("Failed to serialize bob's address:" + err.Error()) }
amountBytes, err := bcs.SerializeU64(TransferAmount) if err != nil { panic("Failed to serialize transfer amount:" + err.Error()) } rawTxn, err := client.BuildTransaction(alice.AccountAddress(), aptos.TransactionPayload{ Payload: &aptos.EntryFunction{ Module: aptos.ModuleId{ Address: aptos.AccountOne, Name: "aptos_account", }, Function: "transfer", ArgTypes: []aptos.TypeTag{}, Args: [][]byte{ accountBytes, amountBytes, }, }}, )
if err != nil { panic("Failed to build transaction:" + err.Error()) }
// 2. Simular transacción (opcional) // Esto es útil para entender cuánto costará la transacción // y para asegurar que la transacción es válida antes de enviarla a la red // Esto es opcional, pero recomendado simulationResult, err := client.SimulateTransaction(rawTxn, alice) if err != nil { panic("Failed to simulate transaction:" + err.Error()) } fmt.Printf("\n=== Simulation ===\n") fmt.Printf("Gas unit price: %d\n", simulationResult[0].GasUnitPrice) fmt.Printf("Gas used: %d\n", simulationResult[0].GasUsed) fmt.Printf("Total gas fee: %d\n", simulationResult[0].GasUsed*simulationResult[0].GasUnitPrice) fmt.Printf("Status: %s\n", simulationResult[0].VmStatus)
// 3. Firmar transacción signedTxn, err := rawTxn.SignedTransaction(alice) if err != nil { panic("Failed to sign transaction:" + err.Error()) }
// 4. Enviar transacción submitResult, err := client.SubmitTransaction(signedTxn) if err != nil { panic("Failed to submit transaction:" + err.Error()) } txnHash := submitResult.Hash
// 5. Esperar la transacción para completar _, err = client.WaitForTransaction(txnHash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) }
// Check balances aliceBalance, err = client.AccountAPTBalance(alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } bobBalance, err = client.AccountAPTBalance(bob.Address) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } fmt.Printf("\n=== Intermediate Balances ===\n") fmt.Printf("Alice: %d\n", aliceBalance) fmt.Printf("Bob:%d\n", bobBalance)
// Ahora hazlo de nuevo, pero con un método diferente resp, err := client.BuildSignAndSubmitTransaction(alice, aptos.TransactionPayload{ Payload: &aptos.EntryFunction{ Module: aptos.ModuleId{ Address: aptos.AccountOne, Name: "aptos_account", }, Function: "transfer", ArgTypes: []aptos.TypeTag{}, Args: [][]byte{ accountBytes, amountBytes, }, }}, ) if err != nil { panic("Failed to sign transaction:" + err.Error()) }
_, err = client.WaitForTransaction(resp.Hash) if err != nil { panic("Failed to wait for transaction:" + err.Error()) }
aliceBalance, err = client.AccountAPTBalance(alice.Address) if err != nil { panic("Failed to retrieve alice balance:" + err.Error()) } bobBalance, err = client.AccountAPTBalance(bob.Address) if err != nil { panic("Failed to retrieve bob balance:" + err.Error()) } fmt.Printf("\n=== Final Balances ===\n") fmt.Printf("Alice: %d\n", aliceBalance) fmt.Printf("Bob:%d\n", bobBalance)}
func main() { example(aptos.DevnetConfig)}
Resumen
Sección titulada «Resumen»Construir y enviar transacciones en la cadena implica los siguientes 5 pasos:
- Construir la transacción.
- Simular el costo. (Opcional)
- Firmar la transacción (si los costos simulados parecen razonables).
- Enviar la transacción a la red.
- Esperar para que la cadena valide y actualice.
Explorar Características Avanzadas de Transacciones
Sección titulada «Explorar Características Avanzadas de Transacciones»Las transacciones tienen un par de características adicionales que les permiten adaptarse a tus necesidades, que puedes aprender aquí:
- Firmas Multi-Agente - Permitir el uso de múltiples cuentas para una sola transacción.
- Transacciones Patrocinadas - Hacer que otra cuenta pague las comisiones de gas por esta transacción.
- Envío de Transacciones por Lote - Cómo enviar múltiples transacciones rápidamente desde una sola cuenta.
- Serialización Canónica Binaria (BCS) - El formato utilizado para serializar datos para transacciones de Aptos.