Transaction Builders
Utility functions for building and managing Starknet transactions.
Transaction Building Functions
BuildInvokeTxn
Creates a new invoke transaction (v3) for the Starknet network.
func BuildInvokeTxn(
senderAddress *felt.Felt,
nonce *felt.Felt,
calldata []*felt.Felt,
resourceBounds *rpc.ResourceBoundsMapping,
opts *TxnOptions,
) *rpc.BroadcastInvokeTxnV3senderAddress- The address of the account sending the transactionnonce- The account's noncecalldata- The data expected by the account'sexecutefunction (typically includes the called contract address and a function selector)resourceBounds- Resource bounds for the transaction executionopts- Optional settings for the transaction (can be nil for defaults)
*rpc.BroadcastInvokeTxnV3- A broadcast invoke transaction with default values for signature, paymaster data, etc. Needs to be signed before being sent.
package main
import (
"context"
"fmt"
"log"
"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/starknet.go/account"
"github.com/NethermindEth/starknet.go/rpc"
"github.com/NethermindEth/starknet.go/utils"
)
func main() {
// Initialize provider and account
provider, err := rpc.NewProvider("https://starknet-sepolia.public.blastapi.io/rpc/v0_8")
if err != nil {
log.Fatal(err)
}
// Account address and private key
accountAddress, _ := utils.HexToFelt("0x...")
privateKey, _ := utils.HexToFelt("0x...")
// Get nonce
nonce, err := provider.Nonce(context.Background(), rpc.BlockID{Tag: "latest"}, accountAddress)
if err != nil {
log.Fatal(err)
}
// Prepare calldata for transfer
recipient, _ := utils.HexToFelt("0x...")
amount := utils.Uint64ToFelt(1000000000000000000) // 1 ETH in Wei
calldata := []*felt.Felt{recipient, amount, new(felt.Felt).SetUint64(0)}
// Estimate fees and create resource bounds
feeEstimate, err := provider.EstimateFee(
context.Background(),
[]rpc.BroadcastTransaction{/* your transaction */},
[]rpc.SimulationFlag{},
rpc.BlockID{Tag: "latest"},
)
if err != nil {
log.Fatal(err)
}
resourceBounds := utils.FeeEstToResBoundsMap(feeEstimate[0], 1.5)
// Build invoke transaction
invokeTx := utils.BuildInvokeTxn(
accountAddress,
nonce,
calldata,
resourceBounds,
nil, // Use default options
)
fmt.Printf("Built invoke transaction: %+v\n", invokeTx)
}BuildDeclareTxn
Creates a new declare transaction (v3) for the Starknet network. A declare transaction is used to declare a new contract class on the network.
func BuildDeclareTxn(
senderAddress *felt.Felt,
casmClass *contracts.CasmClass,
contractClass *contracts.ContractClass,
nonce *felt.Felt,
resourceBounds *rpc.ResourceBoundsMapping,
opts *TxnOptions,
) (*rpc.BroadcastDeclareTxnV3, error)senderAddress- The address of the account sending the transactioncasmClass- The CASM class of the contract to be declaredcontractClass- The contract class to be declarednonce- The account's nonceresourceBounds- Resource bounds for the transaction executionopts- Optional settings for the transaction (can be nil for defaults)
*rpc.BroadcastDeclareTxnV3- A broadcast declare transaction with default values for signature, paymaster data, etc. Needs to be signed before being sent.error- Error if the transaction cannot be built
package main
import (
"context"
"fmt"
"log"
"github.com/NethermindEth/starknet.go/contracts"
"github.com/NethermindEth/starknet.go/rpc"
"github.com/NethermindEth/starknet.go/utils"
)
func main() {
// Initialize provider
provider, err := rpc.NewProvider("https://starknet-sepolia.public.blastapi.io/rpc/v0_8")
if err != nil {
log.Fatal(err)
}
// Load contract class and CASM class
contractClass, err := utils.UnmarshalJSONFileToType[contracts.ContractClass]("contract.json", "")
if err != nil {
log.Fatal(err)
}
casmClass, err := utils.UnmarshalJSONFileToType[contracts.CasmClass]("contract.casm.json", "")
if err != nil {
log.Fatal(err)
}
// Account details
accountAddress, _ := utils.HexToFelt("0x...")
nonce, err := provider.Nonce(context.Background(), rpc.BlockID{Tag: "latest"}, accountAddress)
if err != nil {
log.Fatal(err)
}
// Estimate fees and create resource bounds
// ... (similar to BuildInvokeTxn example)
resourceBounds := utils.FeeEstToResBoundsMap(feeEstimate[0], 1.5)
// Build declare transaction
declareTx, err := utils.BuildDeclareTxn(
accountAddress,
casmClass,
contractClass,
nonce,
resourceBounds,
nil, // Use default options
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Built declare transaction: %+v\n", declareTx)
}BuildDeployAccountTxn
Creates a new deploy account transaction (v3) for the Starknet network. A deploy account transaction is used to deploy a new account contract on the network.
func BuildDeployAccountTxn(
nonce *felt.Felt,
contractAddressSalt *felt.Felt,
constructorCalldata []*felt.Felt,
classHash *felt.Felt,
resourceBounds *rpc.ResourceBoundsMapping,
opts *TxnOptions,
) *rpc.BroadcastDeployAccountTxnV3nonce- The account's noncecontractAddressSalt- A value used to randomize the deployed contract addressconstructorCalldata- The parameters for the constructor functionclassHash- The hash of the contract class to deployresourceBounds- Resource bounds for the transaction executionopts- Optional settings for the transaction (can be nil for defaults)
*rpc.BroadcastDeployAccountTxnV3- A broadcast deploy account transaction with default values for signature, paymaster data, etc. Needs to be signed before being sent.
package main
import (
"fmt"
"log"
"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/starknet.go/rpc"
"github.com/NethermindEth/starknet.go/utils"
)
func main() {
// Account class hash (e.g., OpenZeppelin account)
classHash, _ := utils.HexToFelt("0x...")
// Generate random salt
salt, err := new(felt.Felt).SetRandom()
if err != nil {
log.Fatal(err)
}
// Public key for the account
publicKey, _ := utils.HexToFelt("0x...")
constructorCalldata := []*felt.Felt{publicKey}
// Resource bounds (from fee estimation)
resourceBounds := &rpc.ResourceBoundsMapping{
L1Gas: rpc.ResourceBounds{MaxAmount: "0x1000", MaxPricePerUnit: "0x5f5e100"},
L1DataGas: rpc.ResourceBounds{MaxAmount: "0x1000", MaxPricePerUnit: "0x5f5e100"},
L2Gas: rpc.ResourceBounds{MaxAmount: "0x1000", MaxPricePerUnit: "0x5f5e100"},
}
// Build deploy account transaction
deployTx := utils.BuildDeployAccountTxn(
&felt.Zero, // Nonce is 0 for new accounts
salt,
constructorCalldata,
classHash,
resourceBounds,
nil, // Use default options
)
fmt.Printf("Built deploy account transaction: %+v\n", deployTx)
}Universal Deployer Contract (UDC) Functions
BuildUDCCalldata
Builds the INVOKE transaction function call to deploy a contract using the Universal Deployer Contract (UDC).
func BuildUDCCalldata(
classHash *felt.Felt,
constructorCalldata []*felt.Felt,
opts *UDCOptions,
) (rpc.InvokeFunctionCall, *felt.Felt, error)classHash- The class hash of the contract to deployconstructorCalldata- The calldata to pass to the constructor of the contractopts- The options for the UDC deployment (can be nil for defaults)
rpc.InvokeFunctionCall- The INVOKE transaction function call to deploy the contract, including the UDC address and the calldata*felt.Felt- The salt used for the UDC deployment (either the provided one or a random one)error- An error if any
package main
import (
"fmt"
"log"
"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/starknet.go/utils"
)
func main() {
// Class hash of the contract to deploy
classHash, _ := utils.HexToFelt("0x...")
// Constructor calldata
constructorCalldata := []*felt.Felt{
utils.Uint64ToFelt(100),
utils.Uint64ToFelt(200),
}
// UDC options
opts := &utils.UDCOptions{
UDCVersion: utils.UDCCairoV2,
OriginIndependent: true,
Salt: nil, // Will generate random salt
}
// Build UDC calldata
invokeCall, salt, err := utils.BuildUDCCalldata(classHash, constructorCalldata, opts)
if err != nil {
log.Fatal(err)
}
fmt.Printf("UDC Address: %s\n", invokeCall.ContractAddress)
fmt.Printf("Function: %s\n", invokeCall.FunctionName)
fmt.Printf("Salt used: %s\n", salt)
fmt.Printf("Calldata length: %d\n", len(invokeCall.CallData))
}PrecomputeAddressForUDC
Precomputes the address for a UDC deployment.
func PrecomputeAddressForUDC(
classHash *felt.Felt,
salt *felt.Felt,
constructorCalldata []*felt.Felt,
udcVersion UDCVersion,
originAccAddress *felt.Felt,
) *felt.FeltclassHash- The class hash of the contract to deploysalt- The salt to be used for the UDC deploymentconstructorCalldata- The calldata to pass to the constructor of the contractudcVersion- The UDC version to be usedoriginAccAddress- The address of the account that will deploy the contract. Must be nil if deploying origin-independently
*felt.Felt- The precomputed address for the UDC deployment
package main
import (
"fmt"
"log"
"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/starknet.go/utils"
)
func main() {
classHash, _ := utils.HexToFelt("0x...")
salt, _ := utils.HexToFelt("0x123")
constructorCalldata := []*felt.Felt{
utils.Uint64ToFelt(100),
}
// Origin-independent deployment
address := utils.PrecomputeAddressForUDC(
classHash,
salt,
constructorCalldata,
utils.UDCCairoV2,
nil, // nil for origin-independent
)
fmt.Printf("Precomputed address: %s\n", address)
// Origin-dependent deployment
accountAddress, _ := utils.HexToFelt("0x...")
addressDependent := utils.PrecomputeAddressForUDC(
classHash,
salt,
constructorCalldata,
utils.UDCCairoV2,
accountAddress,
)
fmt.Printf("Precomputed address (origin-dependent): %s\n", addressDependent)
}Fee Estimation Utilities
FeeEstToResBoundsMap
Converts a FeeEstimation to ResourceBoundsMapping with applied multipliers.
func FeeEstToResBoundsMap(
feeEstimation rpc.FeeEstimation,
multiplier float64,
) *rpc.ResourceBoundsMappingfeeEstimation- The fee estimation to convertmultiplier- Multiplier for max amount and max price per unit. Recommended to be 1.5, but at least greater than 0. If multiplier < 0, all resource bounds will be set to 0. If resource bounds overflow, they will be set to the max allowed value (U64 or U128)
*rpc.ResourceBoundsMapping- Resource bounds with applied multipliers
package main
import (
"context"
"fmt"
"log"
"github.com/NethermindEth/starknet.go/rpc"
"github.com/NethermindEth/starknet.go/utils"
)
func main() {
provider, err := rpc.NewProvider("https://starknet-sepolia.public.blastapi.io/rpc/v0_8")
if err != nil {
log.Fatal(err)
}
// Estimate fees for a transaction
estimates, err := provider.EstimateFee(
context.Background(),
[]rpc.BroadcastTransaction{/* your transaction */},
[]rpc.SimulationFlag{},
rpc.BlockID{Tag: "latest"},
)
if err != nil {
log.Fatal(err)
}
// Convert to resource bounds with 1.5x multiplier
resourceBounds := utils.FeeEstToResBoundsMap(estimates[0], 1.5)
fmt.Printf("L1 Gas: max_amount=%s, max_price_per_unit=%s\n",
resourceBounds.L1Gas.MaxAmount,
resourceBounds.L1Gas.MaxPricePerUnit)
fmt.Printf("L1 Data Gas: max_amount=%s, max_price_per_unit=%s\n",
resourceBounds.L1DataGas.MaxAmount,
resourceBounds.L1DataGas.MaxPricePerUnit)
fmt.Printf("L2 Gas: max_amount=%s, max_price_per_unit=%s\n",
resourceBounds.L2Gas.MaxAmount,
resourceBounds.L2Gas.MaxPricePerUnit)
}ResBoundsMapToOverallFee
Calculates the overall fee for a ResourceBoundsMapping with applied multipliers.
func ResBoundsMapToOverallFee(
resBounds *rpc.ResourceBoundsMapping,
multiplier float64,
) (*felt.Felt, error)resBounds- The resource bounds to calculate the fee formultiplier- Multiplier for max amount and max price per unit. Recommended to be 1.5, but at least greater than 0
*felt.Felt- The overall fee in FRIerror- An error if any
package main
import (
"fmt"
"log"
"github.com/NethermindEth/starknet.go/rpc"
"github.com/NethermindEth/starknet.go/utils"
)
func main() {
resourceBounds := &rpc.ResourceBoundsMapping{
L1Gas: rpc.ResourceBounds{
MaxAmount: "0x1000",
MaxPricePerUnit: "0x5f5e100",
},
L1DataGas: rpc.ResourceBounds{
MaxAmount: "0x1000",
MaxPricePerUnit: "0x5f5e100",
},
L2Gas: rpc.ResourceBounds{
MaxAmount: "0x1000",
MaxPricePerUnit: "0x5f5e100",
},
}
// Calculate overall fee with 1.5x multiplier
overallFee, err := utils.ResBoundsMapToOverallFee(resourceBounds, 1.5)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Overall fee: %s FRI\n", overallFee)
// Convert to STRK for display
strkAmount := utils.FRIToSTRK(overallFee)
fmt.Printf("Overall fee: %.6f STRK\n", strkAmount)
}Function Call Conversion
InvokeFuncCallsToFunctionCalls
Converts a slice of InvokeFunctionCall to a slice of FunctionCall.
func InvokeFuncCallsToFunctionCalls(invokeFuncCalls []rpc.InvokeFunctionCall) []rpc.FunctionCallinvokeFuncCalls- The invoke function calls to convert
[]rpc.FunctionCall- A new slice of function calls
package main
import (
"fmt"
"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/starknet.go/rpc"
"github.com/NethermindEth/starknet.go/utils"
)
func main() {
contractAddress, _ := utils.HexToFelt("0x...")
invokeCalls := []rpc.InvokeFunctionCall{
{
ContractAddress: contractAddress,
FunctionName: "transfer",
CallData: []*felt.Felt{
utils.HexToFelt("0x..."), // recipient
utils.Uint64ToFelt(1000), // amount
},
},
}
// Convert to FunctionCall format
functionCalls := utils.InvokeFuncCallsToFunctionCalls(invokeCalls)
fmt.Printf("Converted %d function calls\n", len(functionCalls))
fmt.Printf("Entry point selector: %s\n", functionCalls[0].EntryPointSelector)
}Related
- Types - TxnOptions and UDCOptions documentation
- Unit Conversions - FRI/STRK and Wei/ETH conversions
- RPC Methods - Methods for submitting transactions

