Ape Framework Documentation

repository·main·Indexed 21 days ago

https://github.com/apeworx/ape

A modular Web3 development tool for compiling, testing, and interacting with smart contracts using Python. It features a unified CLI, a plugin system for blockchain network and language interoperability, and comprehensive managers for accounts, chains, networks, and compilers. The framework includes tools like the Ape console, a pytest plugin for contract testing, and utilities for managing project configurations and blockchain state.

Tokens
57.8K
Snippets
240
Records
290
Agent score
77%

What's inside Ape Framework

  1. Overview of the Ape Pytest Plugin

    main
    The ape_test core plugin is the component responsible for invoking tests within the Ape ecosystem. It is designed to integrate with pytest by handling the plugin registration process externally to avoid race conditions in the global plugin registration context. This ensures that critical components like providers and accounts are correctly registered and available when pytest is invoked.
  2. Understand Ape plugin types

    main

    Ape's architecture is built on plugins that extend different capabilities. Common plugin types include:

    • CompilerAPI: Supports various languages (e.g., Vyper, Solidity).
    • ProviderAPI: Connects to blockchains (e.g., Alchemy, Geth, Hardhat).
    • EcosystemAPI: Manages networks (e.g., Ethereum, Fantom, Starknet).
    • CLI plugins: Extend the click-based command line interface.
  3. Work with contract instances using ape.contracts

    main

    The ape.contracts module provides the core abstractions for interacting with smart contracts in Ape.

    • ContractInstance: Represents a specific deployed contract at a specific address on a network. Use this to call functions, send transactions, and access contract state.
    • ContractTypeWrapper: A wrapper used to handle contract types and metadata.
    • ContractContainer: A collection or registry of contract definitions/artifacts.
    • ContractEvent: Represents an event emitted by a contract, allowing for structured access to event logs and arguments.
  4. Understand the Ape Plugin System

    main

    Ape uses a modular plugin system to provide an interoperable experience across different Web3 technologies, including various contract languages and blockchain networks.

    • Installing Plugins: You can extend Ape's functionality by installing plugins. Note that installing 3rd-party plugins (those not originating from the ApeWorX GitHub Organization) will trigger a warning; use them at your own risk.
    • Developing Plugins: Developers can create their own plugins to add support for new features or networks.
  5. Use the JSON Compiler for interfaces and pre-existing contracts

    main

    Ape includes a JSON compiler that allows you to use .json files as contract interfaces or pre-compiled contract types. This is useful for:

    1. Interfaces: Including an ABI in your contracts/ folder to create a contract wrapper around an existing address.
    2. Pre-existing Contract Types: Including JSON contract types compiled elsewhere.
    3. Raw Compiler Output: Including binary artifacts compiled elsewhere.

    To use a JSON interface, place the file (e.g., MyInterface.json) in your contracts folder and access it via project.MyInterface.

    from ape import project
    
    # Comes from a file named `MyInterface.json` in the contracts/ folder.
    my_interface = project.MyInterface
    address = "0x1234556b5Ed9202110D7Ecd637A4581db8b9879F"
    
    # Instantiate a deployed contract using the local interface.
    contract = my_interface.at(address)
    
    # Call a method named `my_method` found in the local contract ABI.
    contract.my_method()
  6. Use the Ape Namespace in the console

    main

    When you launch the console, several root objects are automatically available in your namespace. You can use these objects directly to interact with your project components:

    NameClass
    accountsAccountManager
    networksNetworkManager
    chainChainManager
    projectProjectManager
    queryQueryManager
    convertconvert
    apeape

    Example usage:

    # Access the current network manager
    networks
    
    # Access the head timestamp of the current chain
    chain.blocks.head.timestamp
    In [1]: chain.blocks.head.timestamp
    Out[1]: 1647323479
  7. Use the accounts fixture for testing

    main

    The accounts fixture provides access to automatically funded test accounts. You can access them by index or by address.

    Accessing Accounts

    • By Index: accounts[0], accounts[1], etc.
    • By Address (Impersonation): If using a provider like Foundry, you can access an account via its address: accounts["0x... "]. Alternatively, use accounts.impersonate_account("0x...") for better readability.

    Configuration

    You can configure test accounts in ape-config.yaml using the test key:

    test:
      mnemonic: test test test test test test test test test test test junk
      number_of_accounts: 5
      balance: 100_000 ETH
      hd_path: "m/44'/60'/0'/0/{}" # Optional: custom derivation path

    Best Practice

    For cleaner tests, wrap the accounts fixture into your own named fixtures (e.g., owner, receiver).

    def test_my_method(accounts):
        owner = accounts[0]
        receiver = accounts[1]
    
    # Recommended pattern
    @pytest.fixture
    def owner(accounts):
        return accounts[0]
    
    @pytest.fixture
    def receiver(accounts):
        return accounts[1]
    
    def test_my_method(owner, receiver):
        ...
    
    # Impersonation pattern
    @pytest.fixture
    def vitalik(accounts):
        return accounts.impersonate_account("0xab5801a7d398351b8be11c439e05c5b3259aec9b")
  8. View dev messages in stacktraces

    main

    If you are using a provider that supports tracing and a compiler that detects dev messages, Ape will display these messages in the stacktrace even if the contract did not include a formal revert message. This allows developers to save gas while still receiving useful debugging information.

    Vyper example: assert msg.sender == self.owner # dev: !authorized

    Solidity example: require(msg.sender == owner); // @dev !authorized

  9. How Ape retrieves contract creation metadata

    main

    Ape uses a fallback system to retrieve metadata. If all methods fail, creation_metadata returns None.

    1. In-Session Deployments: Metadata for contracts deployed in the current session is captured in memory automatically.
    2. Otterscan API Integration: Uses the ots_getContractCreator RPC endpoint for nodes with Otterscan extensions. This provides the most complete data, including factory details.
    3. Archive Node Deployment Detection: Uses eth_getCode and block tracing (debug_traceBlockByNumber or trace_replayBlockTransactions) to reconstruct deployment via binary search. Requires an archive node.
    4. Explorer API Fallback: Queries blockchain explorers via plugins like ape-etherscan. This is the most compatible method but may lack factory information and depends on third-party APIs.
  10. How proxy contract detection works in Ape

    main

    Ape automatically detects proxy contracts to ensure that interactions use the target implementation's interface rather than the proxy's interface. When you initialize a contract at a proxy address, Ape attempts to resolve the implementation address and returns the corresponding interface, allowing you to call implementation methods directly.

    Supported proxy types in ape-ethereum include:

    • Minimal: EIP-1167
    • Standard: EIP-1967
    • Beacon: EIP-1967
    • UUPS: EIP-1822
    • Vyper: vyper <0.2.9 create_forwarder_to()
    • Clones: 0xsplits clones
    • Safe: Formerly Gnosis Safe
    • OpenZeppelin: OZ Upgradable
    • Delegate: EIP-897
    • ZeroAge: A minimal proxy
    • SoladyPush0: Uses PUSH0
    from ape import Contract
    
    # Automatic proxy detection (default behavior)
    my_contract = Contract("0x...")
    
    # Even if the address is a proxy, you can call implementation methods
    my_contract.my_method(sender=account)
  11. How to select a network in Ape

    main

    To interact with a specific blockchain, you must specify a "network choice" triplet. This triplet follows the format: <ecosystem-name>:<network-name>:<provider-name>.

    • ecosystem-name: The ecosystem plugin (e.g., ethereum, polygon, fantom).
    • network-name: The specific network (e.g., mainnet, sepolia, local).
    • provider-name: The provider plugin (e.g., node, foundry, alchemy).

    You can specify this triplet using the --network flag in CLI commands. You can also use shorthand by omitting values to use defaults (default ecosystem is ethereum and default network is local). For example, --network ::foundry is shorthand for ethereum:local:foundry.

    To see all available networks, run ape networks list.

    # Using the --network flag with common commands
    ape test --network ethereum:local:foundry
    ape console --network arbitrum:testnet:alchemy
    
    # Using shorthand (defaults to ethereum:local)
    ape run <custom-cmd> --network ::foundry
  12. How Ape manages dependency storage

    main

    Ape downloads and caches all dependencies in the .ape/packages directory. This directory is organized into three specific sub-folders:

    1. projects/: Contains the raw source files for each dependency, organized by <name>/<version-id>. This is where local project compilation looks for source files referenced in import statements.
    2. manifests/: Caches dependency manifests. When a dependency is compiled, its contract types are stored here in JSON format.
    3. api/: Caches API data (from dependencies: config or ape pm install commands) to allow dependency management from any location in the file system.