Skip to content

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.BroadcastInvokeTxnV3
Parameters:
  • senderAddress - The address of the account sending the transaction
  • nonce - The account's nonce
  • calldata - The data expected by the account's execute function (typically includes the called contract address and a function selector)
  • resourceBounds - Resource bounds for the transaction execution
  • opts - Optional settings for the transaction (can be nil for defaults)
Returns:
  • *rpc.BroadcastInvokeTxnV3 - A broadcast invoke transaction with default values for signature, paymaster data, etc. Needs to be signed before being sent.
Usage Example:
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)
Parameters:
  • senderAddress - The address of the account sending the transaction
  • casmClass - The CASM class of the contract to be declared
  • contractClass - The contract class to be declared
  • nonce - The account's nonce
  • resourceBounds - Resource bounds for the transaction execution
  • opts - Optional settings for the transaction (can be nil for defaults)
Returns:
  • *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
Usage Example:
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.BroadcastDeployAccountTxnV3
Parameters:
  • nonce - The account's nonce
  • contractAddressSalt - A value used to randomize the deployed contract address
  • constructorCalldata - The parameters for the constructor function
  • classHash - The hash of the contract class to deploy
  • resourceBounds - Resource bounds for the transaction execution
  • opts - Optional settings for the transaction (can be nil for defaults)
Returns:
  • *rpc.BroadcastDeployAccountTxnV3 - A broadcast deploy account transaction with default values for signature, paymaster data, etc. Needs to be signed before being sent.
Usage Example:
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)
Parameters:
  • classHash - The class hash of the contract to deploy
  • constructorCalldata - The calldata to pass to the constructor of the contract
  • opts - The options for the UDC deployment (can be nil for defaults)
Returns:
  • 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
Usage Example:
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.Felt
Parameters:
  • classHash - The class hash of the contract to deploy
  • salt - The salt to be used for the UDC deployment
  • constructorCalldata - The calldata to pass to the constructor of the contract
  • udcVersion - The UDC version to be used
  • originAccAddress - The address of the account that will deploy the contract. Must be nil if deploying origin-independently
Returns:
  • *felt.Felt - The precomputed address for the UDC deployment
Usage Example:
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.ResourceBoundsMapping
Parameters:
  • feeEstimation - The fee estimation to convert
  • multiplier - 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)
Returns:
  • *rpc.ResourceBoundsMapping - Resource bounds with applied multipliers
Usage Example:
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)
Parameters:
  • resBounds - The resource bounds to calculate the fee for
  • multiplier - Multiplier for max amount and max price per unit. Recommended to be 1.5, but at least greater than 0
Returns:
  • *felt.Felt - The overall fee in FRI
  • error - An error if any
Usage Example:
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.FunctionCall
Parameters:
  • invokeFuncCalls - The invoke function calls to convert
Returns:
  • []rpc.FunctionCall - A new slice of function calls
Usage Example:
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