SendTransaction
Sends a pre-built and signed V3 transaction to the network. This is a low-level method that provides a unified way to send Invoke, Declare, and Deploy Account transactions. Most users should use the higher-level methods like BuildAndSendInvokeTxn or BuildAndSendDeclareTxn instead.
Method Signature
func (account *Account) SendTransaction(
ctx context.Context,
txn rpc.BroadcastTxn,
) (rpc.TransactionResponse, error)Source: transaction.go
Parameters
ctx(context.Context): Context for cancellation and timeouttxn(rpc.BroadcastTxn): Pre-built V3 transaction (BroadcastInvokeTxnV3, BroadcastDeclareTxnV3, or BroadcastDeployAccountTxnV3)
Returns
rpc.TransactionResponse: Response containing transaction hash and optional class hash or contract addresserror: Error if sending fails or transaction type is unsupported
TransactionResponse Structure
Source: types_transaction_response.go
The returned response contains:
type TransactionResponse struct {
Hash *felt.Felt `json:"transaction_hash"`
ClassHash *felt.Felt `json:"class_hash,omitempty"`
ContractAddress *felt.Felt `json:"contract_address,omitempty"`
}Hash(*felt.Felt): Transaction hash (present for all transaction types)ClassHash(*felt.Felt): Class hash (present only for declare transactions)ContractAddress(*felt.Felt): Contract address (present only for deploy account transactions)
Usage Example
package main
import (
"context"
"fmt"
"log"
"math/big"
"os"
"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/starknet.go/account"
"github.com/NethermindEth/starknet.go/rpc"
"github.com/NethermindEth/starknet.go/utils"
"github.com/joho/godotenv"
)
func main() {
ctx := context.Background()
if err := godotenv.Load(); err != nil {
log.Fatal("Failed to load .env file:", err)
}
rpcURL := os.Getenv("STARKNET_RPC_URL")
if rpcURL == "" {
log.Fatal("STARKNET_RPC_URL not set in .env file")
}
provider, err := rpc.NewProvider(ctx, rpcURL)
if err != nil {
log.Fatal("Failed to create provider:", err)
}
accountAddress := os.Getenv("ACCOUNT_ADDRESS")
publicKey := os.Getenv("ACCOUNT_PUBLIC_KEY")
privateKey := os.Getenv("ACCOUNT_PRIVATE_KEY")
if accountAddress == "" || publicKey == "" || privateKey == "" {
log.Fatal("ACCOUNT_ADDRESS, ACCOUNT_PUBLIC_KEY, or ACCOUNT_PRIVATE_KEY not set")
}
ks := account.NewMemKeystore()
privKeyBI, ok := new(big.Int).SetString(privateKey, 0)
if !ok {
log.Fatal("Failed to parse private key")
}
ks.Put(publicKey, privKeyBI)
accountAddressFelt, err := utils.HexToFelt(accountAddress)
if err != nil {
log.Fatal("Failed to parse account address:", err)
}
accnt, err := account.NewAccount(
provider,
accountAddressFelt,
publicKey,
ks,
account.CairoV2,
)
if err != nil {
log.Fatal("Failed to create account:", err)
}
nonce, err := accnt.Nonce(ctx)
if err != nil {
log.Fatal("Failed to get nonce:", err)
}
strkContract, _ := utils.HexToFelt("0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d")
amount := new(felt.Felt).SetUint64(1)
u256Amount, _ := utils.HexToU256Felt(amount.String())
fnCall := rpc.FunctionCall{
ContractAddress: strkContract,
EntryPointSelector: utils.GetSelectorFromNameFelt("transfer"),
Calldata: append([]*felt.Felt{accountAddressFelt}, u256Amount...),
}
calldata, err := accnt.FmtCalldata([]rpc.FunctionCall{fnCall})
if err != nil {
log.Fatal("Failed to format calldata:", err)
}
invokeTx := utils.BuildInvokeTxn(
accnt.Address,
nonce,
calldata,
&rpc.ResourceBoundsMapping{
L1Gas: rpc.ResourceBounds{
MaxAmount: "0x0",
MaxPricePerUnit: "0x0",
},
L1DataGas: rpc.ResourceBounds{
MaxAmount: "0x0",
MaxPricePerUnit: "0x0",
},
L2Gas: rpc.ResourceBounds{
MaxAmount: "0x0",
MaxPricePerUnit: "0x0",
},
},
nil,
)
err = accnt.SignInvokeTransaction(ctx, invokeTx)
if err != nil {
log.Fatal("Failed to sign for estimation:", err)
}
feeRes, err := accnt.Provider.EstimateFee(
ctx,
[]rpc.BroadcastTxn{invokeTx},
[]rpc.SimulationFlag{},
rpc.WithBlockTag("pre_confirmed"),
)
if err != nil {
log.Fatal("Failed to estimate fee:", err)
}
invokeTx.ResourceBounds = utils.FeeEstToResBoundsMap(feeRes[0], 1.5)
err = accnt.SignInvokeTransaction(ctx, invokeTx)
if err != nil {
log.Fatal("Failed to sign final transaction:", err)
}
response, err := accnt.SendTransaction(ctx, invokeTx)
if err != nil {
log.Fatal("Failed to send transaction:", err)
}
fmt.Printf("Transaction Hash: %s\n", response.Hash.String())
}Error Handling
response, err := acc.SendTransaction(ctx, txn)
if err != nil {
switch {
case errors.Is(err, account.ErrUnsupportedTransactionType):
log.Println("Transaction must be a V3 transaction")
case errors.Is(err, rpc.ErrInsufficientAccountBalance):
log.Println("Insufficient balance to pay transaction fees")
default:
log.Printf("Failed to send transaction: %v", err)
}
return
}Common Use Cases
- Send pre-built deploy account transactions after funding the precomputed address
- Send manually constructed and signed transactions for advanced workflows
- Low-level transaction sending when you need complete control over transaction construction
- Usually handled automatically by BuildAndSendInvokeTxn and BuildAndSendDeclareTxn
- Advanced users building custom transaction flows with manual signing

