Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DeployAccount Method to account/account.go for Issue #381 #445

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions account/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -824,3 +824,49 @@ func FmtCalldataCairo2(fnCalls []rpc.FunctionCall) []*felt.Felt {

return execCallData
}

type DeployOptions struct {
ClassHash *felt.Felt
MaxFee *felt.Felt
DeploytWaitTime time.Duration
ConstructorCalldata []*felt.Felt
}
Gabulhas marked this conversation as resolved.
Show resolved Hide resolved

func (account *Account) DeployAccount(options DeployOptions) (*rpc.AddDeployAccountTransactionResponse, error) {
Gabulhas marked this conversation as resolved.
Show resolved Hide resolved

pub, err := utils.HexToFelt(account.publicKey)
if err != nil {
return nil, err
}

// Create transaction data
tx := rpc.DeployAccountTxn{
Nonce: &felt.Zero,
MaxFee: options.MaxFee,
Type: rpc.TransactionType_DeployAccount,
Version: rpc.TransactionV1,
Signature: []*felt.Felt{},
ClassHash: options.ClassHash,
ContractAddressSalt: pub,
ConstructorCalldata: options.ConstructorCalldata,
}

precomputedAddress, err := account.PrecomputeAddress(&felt.Zero, pub, options.ClassHash, tx.ConstructorCalldata)
if err != nil {
return nil, err
}

err = account.SignDeployAccountTransaction(context.Background(), &tx, precomputedAddress)
if err != nil {
return nil, err
}

resp, err := account.AddDeployAccountTransaction(context.Background(), tx)
Gabulhas marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}

account.WaitForTransactionReceipt(context.Background(), resp.TransactionHash, options.DeploytWaitTime)
Gabulhas marked this conversation as resolved.
Show resolved Hide resolved

return resp, nil
}
45 changes: 45 additions & 0 deletions account/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,50 @@ func TestAddDeclareTxn(t *testing.T) {
}
}

func TestDeployAccountDevnet(t *testing.T) {
Gabulhas marked this conversation as resolved.
Show resolved Hide resolved
if testEnv != "devnet" {
t.Skip("Skipping test as it requires a devnet environment")
}
client, err := rpc.NewClient(base + "/rpc")
require.NoError(t, err, "Error in rpc.NewClient")
provider := rpc.NewProvider(client)

devnet, acnts, err := newDevnet(t, base)
require.NoError(t, err, "Error setting up Devnet")
fakeUser := acnts[0]
fakeUserAddr := utils.TestHexToFelt(t, fakeUser.Address)
fakeUserPub := utils.TestHexToFelt(t, fakeUser.PublicKey)

// Set up ks
ks := account.NewMemKeystore()
fakePrivKeyBI, ok := new(big.Int).SetString(fakeUser.PrivateKey, 0)
require.True(t, ok)
ks.Put(fakeUser.PublicKey, fakePrivKeyBI)

acnt, err := account.NewAccount(provider, fakeUserAddr, fakeUser.PublicKey, ks)
require.NoError(t, err)

classHash := utils.TestHexToFelt(t, "0x7b3e05f48f0c69e4a65ce5e076a66271a527aff2c34ce1083ec6e1526997a69") // preDeployed classhash
require.NoError(t, err)

precomputedAddress, err := acnt.PrecomputeAddress(&felt.Zero, fakeUserPub, classHash, []*felt.Felt{fakeUserPub})

_, err = devnet.Mint(precomputedAddress, new(big.Int).SetUint64(10000000000000000000))

require.NoError(t, err)

deployOptions := account.DeployOptions{
ClassHash: classHash,
MaxFee: new(felt.Felt).SetUint64(0),
Gabulhas marked this conversation as resolved.
Show resolved Hide resolved
DeploytWaitTime: 2 * time.Second,
ConstructorCalldata: []*felt.Felt{},
Gabulhas marked this conversation as resolved.
Show resolved Hide resolved
}
resp, err := acnt.DeployAccount(deployOptions)
require.NoError(t, err, "DeployAccount gave an Error")
require.NotNil(t, resp, "DeployAccount resp not nil")
}


// newDevnet creates a new devnet with the given URL.
//
// Parameters:
Expand All @@ -964,6 +1008,7 @@ func TestAddDeclareTxn(t *testing.T) {
// - *devnet.DevNet: a pointer to a devnet object
// - []devnet.TestAccount: a slice of test accounts
// - error: an error, if any

func newDevnet(t *testing.T, url string) (*devnet.DevNet, []devnet.TestAccount, error) {
devnet := devnet.NewDevNet(url)
acnts, err := devnet.Accounts()
Expand Down
1 change: 0 additions & 1 deletion examples/deployAccount/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

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

Steps:
Expand Down
49 changes: 21 additions & 28 deletions examples/deployAccount/main.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package main
Gabulhas marked this conversation as resolved.
Show resolved Hide resolved

import (
"bufio"
"context"
"fmt"
"os"
"time"

"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/starknet.go/account"
Expand Down Expand Up @@ -59,39 +61,30 @@ func main() {
panic(err)
}

// Create transaction data
tx := rpc.DeployAccountTxn{
Nonce: &felt.Zero, // Contract accounts start with nonce zero.
MaxFee: new(felt.Felt).SetUint64(4724395326064),
Type: rpc.TransactionType_DeployAccount,
Version: rpc.TransactionV1,
Signature: []*felt.Felt{},
ClassHash: classHash,
ContractAddressSalt: pub,
ConstructorCalldata: []*felt.Felt{pub},
}

precomputedAddress, err := acnt.PrecomputeAddress(&felt.Zero, pub, classHash, tx.ConstructorCalldata)
fmt.Println("precomputedAddress:", precomputedAddress)
precomputedAddress, err := acnt.PrecomputeAddress(&felt.Zero, pub, classHash, []*felt.Felt{pub})

// At this point you need to add funds to precomputed address to use it.
var input string
fmt.Printf("\nIn order to deploy your account (address %s), you need to fund the acccount (using a faucet), and then press `enter` to continue : \n", precomputedAddress.String())

fmt.Println("The `precomputedAddress` account needs to have enough ETH to perform a transaction.")
fmt.Println("Use the starknet faucet to send ETH to your `precomputedAddress`")
fmt.Println("When your account has been funded by the faucet, press any key, then `enter` to continue : ")
fmt.Scan(&input)

// Sign the transaction
err = acnt.SignDeployAccountTransaction(context.Background(), &tx, precomputedAddress)
reader := bufio.NewReader(os.Stdin)
_, err = reader.ReadString('\n')
if err != nil {
panic(err)
fmt.Printf("Error: %v\n", err)
return
}

// Send transaction to the network
resp, err := acnt.AddDeployAccountTransaction(context.Background(), rpc.BroadcastDeployAccountTxn{DeployAccountTxn: tx})
fmt.Println("Waiting for deployment")
deployOptions := account.DeployOptions{
Gabulhas marked this conversation as resolved.
Show resolved Hide resolved
ClassHash: classHash,
MaxFee: new(felt.Felt).SetUint64(4724395326064),
DeploytWaitTime: 2 * time.Second,
}

// Deploy the account
resp, err := acnt.DeployAccount(deployOptions)

if err != nil {
panic(fmt.Sprint("Error returned from AddDeployAccountTransaction: ", err))
panic(fmt.Sprint("Error returned from DeployAccount: ", err))
}
fmt.Println("AddDeployAccountTransaction response:", resp)
fmt.Println("Deployed with response response:", resp)

}