diff --git a/examples/simpleInvoke/README.md b/examples/simpleInvoke/README.md new file mode 100644 index 00000000..b715fb2e --- /dev/null +++ b/examples/simpleInvoke/README.md @@ -0,0 +1,9 @@ +Note: To run this example, you need a testnet endpoint. + +Steps to run this example on mainnet: + +1. rename ".env.template" to ".env.testnet" +2. uncomment, and set INTEGRATION_BASE to the testnet url //You can get it from here www.alchemy.com/starknet +3. make sure you are in the "simpleInvoke" directory +4. execute `go mod tidy` +5. execute `go run main.go` diff --git a/examples/simpleInvoke/go.mod b/examples/simpleInvoke/go.mod new file mode 100644 index 00000000..96d7a8ee --- /dev/null +++ b/examples/simpleInvoke/go.mod @@ -0,0 +1,33 @@ +module account + +go 1.20 + +require ( + github.com/NethermindEth/juno v0.3.1 + github.com/NethermindEth/starknet.go v0.4.6-0.20231005024141-742a82479868 + github.com/ethereum/go-ethereum v1.10.26 + github.com/joho/godotenv v1.4.0 +) + +require ( + github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/bits-and-blooms/bitset v1.7.0 // indirect + github.com/consensys/gnark-crypto v0.11.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/fxamacker/cbor/v2 v2.4.0 // indirect + github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-stack/stack v1.8.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/stretchr/testify v1.8.1 // indirect + github.com/test-go/testify v1.1.4 // indirect + github.com/tklauser/go-sysconf v0.3.5 // indirect + github.com/tklauser/numcpus v0.2.2 // indirect + github.com/x448/float16 v0.8.4 // indirect + golang.org/x/crypto v0.2.0 // indirect + golang.org/x/sys v0.3.0 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/examples/simpleInvoke/go.work b/examples/simpleInvoke/go.work new file mode 100644 index 00000000..b32bc53a --- /dev/null +++ b/examples/simpleInvoke/go.work @@ -0,0 +1,6 @@ +go 1.18 + +use ( + . + ../.. +) diff --git a/examples/simpleInvoke/main.go b/examples/simpleInvoke/main.go new file mode 100644 index 00000000..4703acde --- /dev/null +++ b/examples/simpleInvoke/main.go @@ -0,0 +1,120 @@ +package main + +import ( + "context" + "fmt" + "math/big" + "os" + + "github.com/NethermindEth/starknet.go/account" + "github.com/NethermindEth/starknet.go/rpc" + "github.com/NethermindEth/starknet.go/utils" + ethrpc "github.com/ethereum/go-ethereum/rpc" + "github.com/joho/godotenv" +) + +// NOTE : Please add in your keys only for testing purposes, incase of a leak you would potentially lose your funds. +var ( + name string = "testnet" //env."name" + account_addr string = "0x06f36e8a0fc06518125bbb1c63553e8a7d8597d437f9d56d891b8c7d3c977716" //Replace it with your account address + privateKey string = "0x0687bf84896ee63f52d69e6de1b41492abeadc0dc3cb7bd351d0a52116915937" //Replace it with your account private key + public_key string = "0x58b0824ee8480133cad03533c8930eda6888b3c5170db2f6e4f51b519141963" //Replace it with your account public key + someContract string = "0x4c1337d55351eac9a0b74f3b8f0d3928e2bb781e5084686a892e66d49d510d" //Replace it with the contract that you want to invoke + contractMethod string = "increase_value" //Replace it with the function name that you want to invoke +) + +func main() { + //Loading the env + godotenv.Load(fmt.Sprintf(".env.%s", name)) + base := os.Getenv("INTEGRATION_BASE") //please modify the .env.testnet and replace the INTEGRATION_BASE with an starknet goerli RPC. + fmt.Println("Starting simpleInvoke example") + + //Initialising the connection + c, err := ethrpc.DialContext(context.Background(), base) + if err != nil { + fmt.Println("Failed to connect to the client, did you specify the url in the .env.testnet?") + panic(err) + } + + //Initialising the provider + clientv02 := rpc.NewProvider(c) + + //Here we are converting the account address to felt + account_address, err := utils.HexToFelt(account_addr) + if err != nil { + panic(err.Error()) + } + //Initializing the account memkeyStore + ks := account.NewMemKeystore() + fakePrivKeyBI, ok := new(big.Int).SetString(privateKey, 0) + if !ok { + panic(err.Error()) + } + ks.Put(public_key, fakePrivKeyBI) + + fmt.Println("Established connection with the client") + + //Here we are setting the maxFee + maxfee, err := utils.HexToFelt("0x9184e72a000") + if err != nil { + panic(err.Error()) + } + + //Initializing the account + accnt, err := account.NewAccount(clientv02, account_address, public_key, ks) + if err != nil { + panic(err.Error()) + } + + //Getting the nonce from the account, and then converting it into felt + nonce_string, _ := accnt.Nonce(context.Background(), rpc.BlockID{Tag: "latest"}, accnt.AccountAddress) + nonce, err := utils.HexToFelt(*nonce_string) + if err != nil { + panic(err.Error()) + } + + //Building the InvokeTx struct + InvokeTx := rpc.InvokeTxnV1{ + MaxFee: maxfee, + Version: rpc.TransactionV1, + Nonce: nonce, + Type: rpc.TransactionType_Invoke, + SenderAddress: accnt.AccountAddress, + } + + //Converting the contractaddress from hex to felt + contractAddress, err := utils.HexToFelt(someContract) + if err != nil { + panic(err.Error()) + } + + //Building the functioncall struct, where : + FnCall := rpc.FunctionCall{ + ContractAddress: contractAddress, //contractAddress is the contract that we wanna call + EntryPointSelector: utils.GetSelectorFromNameFelt(contractMethod), //this is the function that we wanna call + } + + //Mentioning the contract version + CairoContractVersion := 2 + + //Building the Calldata with the help of FmtCalldata where we pass in the FnCall struct along with the Cairo version + InvokeTx.Calldata, err = accnt.FmtCalldata([]rpc.FunctionCall{FnCall}, CairoContractVersion) + if err != nil { + panic(err.Error()) + } + + //Signing of the the transaction that is done by the account + err = accnt.SignInvokeTransaction(context.Background(), &InvokeTx) + if err != nil { + panic(err.Error()) + } + + //After the signing we finally call the AddInvokeTransaction in order to invoke the contract function + resp, err := accnt.AddInvokeTransaction(context.Background(), InvokeTx) + if err != nil { + panic(err.Error()) + } + //This returns us with the transaction hash + fmt.Println("Response : ", resp.TransactionHash) + +}