DEV Community

Cover image for How to compile, deploy and interact with smart contracts using Apeworx(ape) and VS Code.
Muwawu Moses
Muwawu Moses

Posted on • Edited on

How to compile, deploy and interact with smart contracts using Apeworx(ape) and VS Code.

Today, we are going to write our smart contracts using Vyper and the Apeworx framework. We are going to connect to the ethereum network using Sepolia via Alchemy.

Prerequisites

  • python version later than 3.8
  • pip installed
  • metamask wallet already set up

Procedure

First, we are going to set up the development environment. Remember, when using windows, it's recommended to use WSL2 for development purposes. I am using Ubuntu for this tutorial.

  • Let's create a project folder named testing. mkdir testing
  • Then, navigate through the folder: cd testing
  • Create a virtual environment named .venv python3 -m venv .venvand then, run code . to open vs code. In the VS code terminal, activate the virtual environment by running source .venv/bin/activate

Next, we are going to install apeworx and all dependencies through a single command: pip install eth-ape'[recommended-plugins]'.

After a successful installation, we are now going to connect our project to the metamask wallet through creation of what is called an account.

  • Run ape accounts import meta_wallet In the above command, we have named our account 'meta_wallet'(you can name it anything you want). You'll then be prompted to enter private key and create a passphrase to encrypt your account.
Enter Private Key: 
Create Passphrase to encrypt account: 
Repeat for confirmation: 
Enter fullscreen mode Exit fullscreen mode

To enter private key, go to your metamask wallet and copy a private key and securely save it somewhere. Paste it into the terminal and please note that you won't be able to see it so, don't paste more than once.
For a passphrase, create something that you won't forget.
To confirm if your account has been imported, run ape accounts list.

One more last thing to do for a successful set up is adding the Alchemy-api-key to our settings.
Run code ~/.bashrc to open the bashrc file. In this file, add the following line of code("YOUR_ALCHEMY_API_KEY" with the actual api key from alchemy) to the bottom end of it: `export WEB3_ALCHEMY_API_KEY="YOUR_ALCHEMY_API_KEY"

Another option is to run export WEB3_ALCHEMY_API_KEY=<your_api_key> in your terminal

Lastly, run source ~/.bashrc so as to save the above changes
`
Note: If you are running your program on a testnet, please make sure that your alchemy ethereum app is a testnet not a mainnet.

Good that we are now done with the set up process, let's go for the actual business.
We shall start by initializing a project by running ape init.
This creates creates a project structure including; .build(for storage of artifacts), scripts folder, tests folder, contracts folder, and the ape-config.yaml file.

Add the following code to the ape-config.yaml file:

# ape-config.yaml
name: my-contract


ethereum:
  default_network: sepolia
  sepolia:
    default_provider: alchemy

default_ecosystem: ethereum
Enter fullscreen mode Exit fullscreen mode

First, in the contracts folder, let's create a new file named Greeting.vy and add the following code.

#pragma version >0.3.10

greeting: public(String[120])

@deploy
def __init__(_word: String[120]):
    self.greeting = _word

@external
def set_string(_word: String[120]):
    self.greeting = _word
Enter fullscreen mode Exit fullscreen mode

Explanation

The set_string function is for setting a string that doesn't exceed 120 characters and the greeting variable is an automatic get()function since it's marked public.

Next is to compile our code: ape compile.
Please note that after running the above command, a new file named __local__.json is automatically created in the .build folder. This file contains the abi and bytcode of the contract.

contract deployment

So, our next task is to create a another file named deploy.py in the scripts folder:

from ape import accounts, project

def main():
    # Use an existing account or create a new one
    deployer = accounts.load("meta_wallet")

    # we are initializing our contract with following string
    _hello = "Good Morning, Uganda!"

    # Deploy the Greeting Contract
    greeting_contract = deployer.deploy(project.Greeting, _hello)

    print(f"Greeting Contract deployed at: {greeting_contract.address}")
Enter fullscreen mode Exit fullscreen mode

Run ape run deploy --network ethereum:sepolia:alchemy .
Congratulations if your deployment was a successful one.

calling a function

We can interact with the contract using ape:

# scripts/interact.py
from ape import project, accounts

def main():
    # Use your preferred account, e.g., the default one
    contract_address = "<copy_and_paste_here_contract_address>"

    contract = project.Greeting.at(contract_address)  # `Greeting` is contract name

    # view string
    result = contract.greeting()

    print(f"Result: {result}")

Enter fullscreen mode Exit fullscreen mode

Run: ape run interact --network ethereum:sepolia:alchemy

Calling the set_string() function

# scripts/set_string.py
from ape import networks, accounts, project

def update_string_in_contract(new_string: str, contract_address: str, network_name: str, account_alias: str):
    """
    Function to update a string value in a smart contract on the specified network.

    :param new_string: The new string value to set in the contract.
    :param contract_address: The address of the smart contract.
    :param network_name: The network where the contract is deployed (e.g., 'arbitrum:sepolia:alchemy').
    :param account_alias: The alias of the account to use for the transaction (e.g., 'meta_wallet').
    :return: Transaction receipt or an error message.
    """
    try:
        with networks.parse_network_choice(network_name) as net:
            # Load the contract
            contract = project.Greeting.at(contract_address)

            # Prepare and send the transaction
            account = accounts.load(account_alias)
            tx = contract.set_string(new_string, sender=account)

            # Poll for the transaction receipt using `tx.txn_hash`
            receipt = net.provider.get_receipt(tx.txn_hash)

            if receipt.failed:
                return "Transaction failed"

            return {"result": "String updated successfully", "transaction_hash": tx.txn_hash}
    except Exception as e:
        return f"An error occurred: {str(e)}"

# Example usage
if __name__ == "__main__":
    new_string = "Unity is strength. Unity is Power. Unity is Humanity."
    contract_address = '<your_contract_address>'
    network_name = 'arbitrum:sepolia:alchemy'
    account_alias = 'meta_wallet'

    result = update_string_in_contract(new_string, contract_address, network_name, account_alias)
    print(result)

Enter fullscreen mode Exit fullscreen mode

Wow! we have had our smart contract compiled, deployed and interacted with all in vs code. If you found this article helpful, don't hesitate to give me a like and please follow for more. Thank You!

Top comments (0)