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:
- Rename the ".env.template" file located at the root of the "examples" folder to ".env"
- Uncomment, and assign your Sepolia testnet endpoint to the
RPC_PROVIDER_URL
variable in the ".env" file - Make sure you are in the "deployAccount" directory
- Execute
go run main.go
- Fund the precomputed address using a starknet faucet, eg https://starknet-faucet.vercel.app/
- 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
- First, we initialize a new Starknet client with your node URL
- Create a new account instance using your private key
- Deploy the account to the network
- 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