How to use the Starknet Plugin

written by
Dalena Dang
Date Last Updated
March 30, 2023
Download Project Files

This is an update to the previous video where we showed you how to install and use the Starknet plugin.

This video will focus on the new changes to the starknet plugin.

Welcome to our video on How to use the Starknet Plugin version 0.5.0. Today, I am going to be going over what you can do with the ape-starknet plugin. This will include account management, declaring and deploying contracts, contract interaction, and testing.

This is an update to the previous video, where we showed you how to install and use the Starknet plugin. This video will focus on the new changes to the Starknet plugin. The best place for you to find the most current up-to-date information will be through the Github repository and the README documentation. 

The scripts that will be used can be found in the README and the demo github repo.

Section 1


Now, let’s start with account management. In this section, we will go over local accounts as well as testnet and mainnet accounts. We will cover importing, creating, deploying, listing, and deleting accounts through the ape console, as well as using accounts to auto-sign messages. 

Currently, you can access local test accounts out of the box from script or console. There are 10 test accounts that you can access. You can view these test accounts by launching the starknet-devnet process manually and it will show the address, public, and private keys for the test accounts for that session:


Remember that you should not be using the local accounts when testing on testnet or mainnet because it may lead to a loss of funds. You will most likely only be using these local accounts while testing and using testnet or mainnet accounts in your scripts.

Importing Accounts

In order to access a live network like testnet or mainnet, you will need to import or create an account first. You can import any existing, deployed account from the Starknet network. You can also import accounts from your Argent-X or Braavos wallet. 

To import an account from an Argent-X wallet, you would run:

 ape starknet accounts import ALIAS --address ADDRESS --network starknet --clash-hash argentx

You will need your private key in order to import the wallet. It will also ask you to set a passphrase that you will use to access your account. You can set a passphrase if you would like, however the plugin also accepts empty passphrases. The class hash for Argent-X wallets is already set in the plugin but you can change the import with whichever class hash is appropriate. Setting the network flag to starknet will add all the networks at once. 

Once you have successfully imported your account, you can begin to use it in your scripts and testing. To access these accounts from script you can run:

from ape import accounts		
account = accounts.load(“ALIAS”)	

In Starknet, the balance of an account is the amount it holds of the fee token.

Creating Accounts

To create an account, you can run the create command:

ape starknet accounts create ALIAS

By default, new accounts will use the Open Zeppelin account contract implementation, however you can change the class using the --class-hash option. 

NOTE: You may also need to change the constructor-calldata flag when using a different account contract type.

The create command will create a public and private key combination and store a local keyfile for the account but does not deploy the account automatically. This is because the account needs funding to pay for its deployment.

Deploying Accounts

There are multiple ways we can fund and deploy the account. You can visit the Starknet Faucet or the Starknet L2 bridge to transfer funds to your newly created account before deploying. Remember that you cannot use an Ethereum account to directly fund a Starknet account, but you may use the Starknet Bridge to send L1 ETH to an L2 account. Links to the Faucet and the Bridge can also be found in the official Starknet Guide.

Otherwise, you can use another account with funds to fund the deployment of a newly created account using the --funder tag option:

ape starknet accounts deploy NEW-ACCOUNT --network testnet --funder EXISTING-FUNDED-ALIAS

Listing Accounts

The Starknet plugin also allows you to see all your accounts and their deployment addresses using:

ape starknet accounts list

This will show your alias, public key, class hash, and contract address. This will also let you know if the account has been deployed yet on any network.

Deleting an Account

To delete accounts you can run:

ape starknet accounts delete ALIAS --network testnet, testnet2

The delete command differs based on its values of the --network and --address option: 

  • To delete all deployments on a given network, use the –network option without the --address option
  • To delete all deployments matching an address (regardless of network), use --address option without the –network option
  • To delete a deployment on a network with a particular address, use both --network and --address options 
  • Exclude both options to delete the whole account

NOTE: You can also specify multiple networks, similar to the import command.

Auto-Sign Message

Using the Starknet plugin, you can also auto-sign messages using keyring. While sometimes necessary, it is generally considered bad practice; an example would be during testnet automated deployments. To do this, you should use the set_autosign() method available on the keyfile accounts:

import keyring	
from ape import accounts

# Use keyring package to store secrets
password = keyring.get_password("starknet-testnet-automations", "ci-shared-account")
testnet_account = accounts.load("starknet-testnet-account")
testnet_account.set_autosign(True, passphrase=password)

# Won't prompt for signing or unlocking

Section 2

Contract Dependencies

Now let’s briefly go over contracts. If you have dependencies, such as the OpenZeppelin Cairo Contracts package, you can add them to a configuration file, ape-config.yaml:

  - name: OpenZeppelinCairo
    github: OpenZeppelin/cairo-contracts
    version: 0.6.0
    contracts_folder: src

    - OpenZeppelinCairo@0.6.0

Then in your Cairo contracts, you can import from these dependencies like you see here in the MyToken.cairo contract:

from openzeppelin.token.erc20.library import ERC20

Then when you run ape compile, Ape will download the dependency, if needed, and include it when compiling.

Declaring and Deploying Contracts

In Starknet, you can declare contract types by publishing them to the chain. This allows other contracts to create instances of them using the deploy system call. 

To declare a contract using ape-starknet, you can do the following in either script or console. 

You can load an account from testnet, mainnet, or load a local account from the starknet-devnet accounts using:

from ape import accounts

account = accounts.load(“ALIAS”) # testnet or mainnet account
account = accounts.containers[‘starknet’].test_accounts[0] # local account

Then you can declare your contract using:


Once you have declared your contract, you can begin to deploy it. All contracts must be declared before they are deployed and it is recommended that you only declare a contract once. However you can deploy a contract as many times as needed.

NOTE: The deploy method in the ape-starknet plugin makes an invoke-function call against the Starknet public Universal Deployer Contract (UDC).

This will only work if the contract has been declared previously, you do not need to provide the class hash as Ape will look it up:

from ape import project
declaration = project.MyContract.deploy(sender=account)

If you want to deploy using project.MyContracy.deploy() you must include a sender as a keyword-argument (kwarg) or else the contract will not be able to deploy properly. This is a change from the previous version because DeployTransactions used to be anonymous. Now we call InvokeTransaction on the UDC to deploy for us, which requires a sender. 

Another way of deploying a contract is by using a factory contract. In this example, the factory takes the class of the contract it is able to deploy. However, factory contracts can be implemented many ways, depending on the needs of the project: 

# Factory Contract Example

%lang starknet

from starkware.cairo.common.alloc import alloc
from starkware.starknet.common.syscalls import deploy
from starkware.cairo.common.cairo_builtins import HashBuiltin
from starkware.cairo.common.bool import FALSE, TRUE

func class_hash() -> (class_hash: felt) {

func salt() -> (value: felt) {

func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(cls_hash: felt) {
    return ();

func deploy_my_contract{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
    let (cls_hash) =;
    let (current_salt) =;
    let (ctor_calldata) = alloc();
    let (contract_addr) = deploy(
    salt.write(value=current_salt + 1);
    return ();

To deploy a contract using a factory contract:

# This contracts accepts a class hash of a declared contract and then deploys it
factory = project.MyFactory.deploy(declaration.class_hash, sender=account)
factory_deployment = factory.deploy_my_contract(sender=account)

Now let’s run this deploy script in the terminal using:

ape run deploy --network starknet:local

Section 3


In this next section, we will go over Contract Interactions using the ape-starknet plugin.

After deploying a contract, you can interact with them. Deploy methods return a contract instance from which you can call methods.

In this instance, we are using a test account and have declared and deployed the contract so that we can see how we can interact with our contract. 

We can use a mutable method and include a sender to delegate transactions like how I have done here:

# Interact with deployed contract
# Use a mutable method and include sender to delegate the transaction
receipt = contract.increase_balance(account.address, 123, sender=account)

We can also use view methods from a contract:

# Use a view method
value = contract.get_balance(account)

And we can access return data from a mutable method’s receipt:

# Access return data from mutable method receipt
result = receipt.return_value

NOTE: To pass in arrays as arguments,you have to include the array size beforehand:

contract.store_sum(3, [1, 2, 3], sender=account)

The Ape Framework uses method argument length to select the correct method to call from your Python code and Cairo uses pointers for arrays. Pointers are memory addresses so arrays always have an arr_len input before it to know how many field elements or felt values to grab at that memory address. The Starknet plugin is smart enough to pass len(array) as the argument for you so the number you input for arr_len does not matter however it is needed as a placeholder for method selection in the Ape framework.

Section 4


Now we will go over the testing capabilities of the Starknet plugin. 

For testing, you can use starknet-devnet accounts. This is an example of one way you may want to access a devnet account. In our, we first set up our account container and first test account:

import pytest
import ape

def devnet_accounts():
    with ape.networks.starknet.local.use_provider("starknet"):
        return ape.accounts.containers["starknet"]

def account(devnet_accounts):
    return devnet_accounts.test_accounts[0]

Then, in our file, we begin to test our accounts including creating and using ephemeral accounts. Any accounts deployed in the testing session are not saved to disk and are ephemeral:

import pytest

def ephemeral_account(devnet_accounts):
    new_account = devnet_accounts.create_account("demo-fund")
    # funder = account.load("argent")
    funder = devnet_accounts.test_accounts[2]
    funder.transfer(new_account, "0.02 ETH")
    return devnet_accounts.load("demo-fund")

def test_ephemeral_balance(ephemeral_account):
    balance = ephemeral_account.balance
    assert balance > 0

You can also use this script in the fixture ephemeral_account, if you need to manually fund and deploy your accounts in testnet or mainnet, using an existing imported and created account.

We can also test our contract methods in our file

import pytest

def contract(project, account):
    contract = project.MyContract.deploy(sender=account)
    return contract

def test_increase_balance(contract, account):
    initial_balance = contract.get_balance(account)
    contract.increase_balance(account.address, 100, sender=account)
    assert contract.get_balance(account) == initial_balance + 100

Paying Fees

Starknet fees are currently paid in ETH, which is an ERC-20 on the Starknet chain. To check your account balance (in ETH) you can use the balance property on the account:

from ape import account
acct = accounts.load("ALIAS")

To pay fees, you can either manually set the max_fee kwarg on the invoke-transaction:

contract.increase_balance(123, max_fee=2900000000000)

NOTE: By not setting the max_fee, it will automatically get set to the value returned from the provider estimate_gas_cost() call. You do NOT need to call estimate_gas_call() explicitly.

Thank you for watching this video on learning how to use Ape-Starknet. If you have any questions, please feel free to join our Discord and ask.