Saltearse al contenido

SDK de Go - Transacciones en Lote

El SDK de Go tiene una forma integrada de enviar muchas transacciones concurrentemente y ordenarlas. Esto puede ser una herramienta conveniente cuando intentas ejecutar múltiples transacciones rápidamente desde la misma cuenta.

Esto se puede hacer con client.BuildSignAndSubmitTransactions como se puede ver en el ejemplo de abajo.

// sending_concurrent_transactions muestra cómo enviar transacciones en serie o concurrentemente en una sola cuenta
package main
import (
"github.com/aptos-labs/aptos-go-sdk"
"github.com/aptos-labs/aptos-go-sdk/api"
"time"
)
func setup(networkConfig aptos.NetworkConfig) (*aptos.Client, aptos.TransactionSigner) {
client, err := aptos.NewClient(networkConfig)
if err != nil {
panic("Failed to create client:" + err.Error())
}
sender, err := aptos.NewEd25519Account()
if err != nil {
panic("Failed to create sender:" + err.Error())
}
err = client.Fund(sender.Address, 100_000_000)
if err != nil {
panic("Failed to fund sender:" + err.Error())
}
return client, sender
}
func payload() aptos.TransactionPayload {
receiver := aptos.AccountAddress{}
err := receiver.ParseStringRelaxed("0xBEEF")
if err != nil {
panic("Failed to parse address:" + err.Error())
}
amount := uint64(100)
p, err := aptos.CoinTransferPayload(nil, receiver, amount)
if err != nil {
panic("Failed to serialize arguments:" + err.Error())
}
return aptos.TransactionPayload{Payload: p}
}
func sendManyTransactionsSerially(networkConfig aptos.NetworkConfig, numTransactions uint64) {
client, sender := setup(networkConfig)
responses := make([]*api.SubmitTransactionResponse, numTransactions)
payload := payload()
senderAddress := sender.AccountAddress()
sequenceNumber := uint64(0)
for i := uint64(0); i < numTransactions; i++ {
rawTxn, err := client.BuildTransaction(senderAddress, payload, aptos.SequenceNumber(sequenceNumber))
if err != nil {
panic("Failed to build transaction:" + err.Error())
}
signedTxn, err := rawTxn.SignedTransaction(sender)
if err != nil {
panic("Failed to sign transaction:" + err.Error())
}
submitResult, err := client.SubmitTransaction(signedTxn)
if err != nil {
panic("Failed to submit transaction:" + err.Error())
}
responses[i] = submitResult
sequenceNumber++
}
// Esperar en la última transacción
response, err := client.WaitForTransaction(responses[numTransactions-1].Hash)
if err != nil {
panic("Failed to wait for transaction:" + err.Error())
}
if response.Success == false {
panic("Transaction failed due to " + response.VmStatus)
}
}
func sendManyTransactionsConcurrently(networkConfig aptos.NetworkConfig, numTransactions uint64) {
client, sender := setup(networkConfig)
payload := payload()
// iniciar goroutine de envío
payloads := make(chan aptos.TransactionBuildPayload, 50)
results := make(chan aptos.TransactionSubmissionResponse, 50)
go client.BuildSignAndSubmitTransactions(sender, payloads, results)
// Enviar transacciones a la goroutine
go func() {
for i := uint64(0); i < numTransactions; i++ {
payloads <- aptos.TransactionBuildPayload{
Id: i,
Type: aptos.TransactionSubmissionTypeSingle,
Inner: payload,
}
}
close(payloads)
}()
// Esperar a que todas las transacciones sean procesadas
for result := range results {
if result.Err != nil {
panic("Failed to submit and wait for transaction:" + result.Err.Error())
}
}
}
// example Este ejemplo te muestra cómo mejorar el rendimiento del envío de transacciones
//
// La velocidad se puede mejorar manejando localmente el número de secuencia, precio del gas y otros factores
func example(networkConfig aptos.NetworkConfig, numTransactions uint64) {
println("Sending", numTransactions, "transactions Serially")
startSerial := time.Now()
sendManyTransactionsSerially(networkConfig, numTransactions)
endSerial := time.Now()
println("Serial:", time.Duration.Milliseconds(endSerial.Sub(startSerial)), "ms")
println("Sending", numTransactions, "transactions Concurrently")
startConcurrent := time.Now()
sendManyTransactionsConcurrently(networkConfig, numTransactions)
endConcurrent := time.Now()
println("Concurrent:", time.Duration.Milliseconds(endConcurrent.Sub(startConcurrent)), "ms")
println("Concurrent is", time.Duration.Milliseconds(endSerial.Sub(startSerial)-endConcurrent.Sub(startConcurrent)), "ms faster than Serial")
}
func main() {
example(aptos.DevnetConfig, 100)
}