Skip to content

Deploy Account

This guide demonstrates how to deploy a new account on Starknet using Starknet.go.

Prerequisites

  • Go 1.18 or higher
  • Starknet.go installed
  • A Starknet node URL (voyager rpc)

Overview

This example uses a pre-existing class on the Sepolia network to deploy a new account contract. To successfully run this example, you will need: 1) a Sepolia endpoint, and 2) some Sepolia ETH to fund the precomputed address.

Steps:

  1. Rename the ".env.template" file located at the root of the "examples" folder to ".env"
  2. Uncomment, and assign your Sepolia testnet endpoint to the RPC_PROVIDER_URL variable in the ".env" file
  3. Make sure you are in the "deployAccount" directory
  4. Execute go run main.go
  5. Fund the precomputed address using a starknet faucet, eg https://starknet-faucet.vercel.app/
  6. Press any key, then enter

At this point your account should be deployed on testnet, and you can use a block explorer like Voyager to view your transaction using the transaction hash.

Code Example

main.go
package main
 
import (
	"context"
	"fmt"
 
	"github.com/NethermindEth/juno/core/felt"
	"github.com/NethermindEth/starknet.go/account"
	"github.com/NethermindEth/starknet.go/rpc"
	"github.com/NethermindEth/starknet.go/utils"
 
	setup "github.com/NethermindEth/starknet.go/examples/internal"
)
 
var (
	// OpenZeppelin Account Class Hash in Sepolia
	predeployedClassHash = "0x61dac032f228abef9c6626f995015233097ae253a7f72d68552db02f2971b8f"
)
 
// main initializes the client, sets up the temporary account, precomputes the address of the new account,
// estimates deployment fees, and prepares for the account deployment transaction.
//
// It loads environment variables, initializes a Starknet RPC client, generates random cryptographic keys,
// sets up an account with the generated keys, precomputes the address of a new account, estimates deployment fees,
// and prepares for the account deployment transaction.
func main() {
	// Load variables from '.env' file
	rpcProviderUrl := setup.GetRpcProviderUrl()
 
	// Initialise the client.
	client, err := rpc.NewProvider(rpcProviderUrl)
	if err != nil {
		panic(err)
	}
 
	// Get random keys for being able to sign the deploy transaction.
	// These keys will always be used to sign transactions in the new account.
	ks, pub, privKey := account.GetRandomKeys()
	fmt.Printf("Generated public key: %v\n", pub)
	fmt.Printf("Generated private key: %v\n", privKey)
 
	// Set up the account passing random values to 'accountAddress' and 'cairoVersion' variables,
	// as for this case we only need the 'ks' to sign the deploy transaction.
	accnt, err := account.NewAccount(client, pub, pub.String(), ks, 2)
	if err != nil {
		panic(err)
	}
 
	classHash, err := utils.HexToFelt(predeployedClassHash)
	if err != nil {
		panic(err)
	}
 
	// Build and estimate fees for the deploy account transaction, and precompute the address of the new account.
	// In our case, the OZ account constructor requires the public key of the account as calldata, so we pass it as calldata.
	// The multiplier for the fee estimation is 1.5, as we want to be sure that the transaction will be accepted.
	deployAccountTxn, precomputedAddress, err := accnt.BuildAndEstimateDeployAccountTxn(context.Background(), pub, classHash, []*felt.Felt{pub}, 1.5)
	if err != nil {
		panic(err)
	}
 
	fmt.Println("PrecomputedAddress:", setup.PadZerosInFelt(precomputedAddress))
 
	// Convert the estimated fee to STRK. The multiplier is 1, as we already estimated the fee in BuildAndEstimateDeployAccountTxn multiplying by 1.5.
	overallFee, err := utils.ResBoundsMapToOverallFee(deployAccountTxn.ResourceBounds, 1)
	if err != nil {
		panic(err)
	}
	feeInSTRK := utils.FRIToSTRK(overallFee)
 
	// At this point you need to add funds to precomputed address to use it.
	var input string
 
	fmt.Println("\nThe `precomputedAddress` account needs to have enough STRK to perform a transaction.")
	fmt.Printf("You can use the starknet faucet or send STRK to your `precomputedAddress`. You need approximately %f STRK. \n", feeInSTRK)
	fmt.Println("When your account has been funded, press any key, then `enter` to continue: ")
	fmt.Scan(&input)
 
	// Send transaction to the network
	resp, err := accnt.SendTransaction(context.Background(), deployAccountTxn)
	if err != nil {
		fmt.Println("Error returned from SendTransaction: ")
		panic(err)
	}
 
	fmt.Println("BroadcastDeployAccountTxn successfully submitted! Wait a few minutes to see it in Voyager.")
	fmt.Printf("Transaction hash: %v \n", resp.TransactionHash)
	fmt.Printf("Contract address: %v \n", setup.PadZerosInFelt(resp.ContractAddress))
}

Explanation

  1. First, we initialize a new Starknet client with your node URL
  2. Create a new account instance using your private key
  3. Deploy the account to the network
  4. The transaction hash is returned upon successful deployment

Best Practices

  • Always store private keys securely
  • Use environment variables for sensitive information
  • Handle errors appropriately
  • Consider using a testnet for development

Common Issues

  • Invalid private key format
  • Insufficient funds for deployment
  • Network connectivity issues
  • Transaction timeout