# Create a New Bot This is a step-by-step guide on creating a new bot and releasing it to be used with cHaOSneT. The creation of this bot will be through the Silverback SDK, which can be found at [https://github.com/ApeWorX/silverback](https://github.com/ApeWorX/silverback). You can use the hosted base image which can be used to build a docker container of the bot. In this example, we will create an NFT bot to mint and distribute NFTs to active addresses in each block. The complete code for this bot can be found at [https://github.com/ApeAcademy/Spamalot](https://github.com/ApeAcademy/Spamalot) ## File Structure We will create a file structure for our bot to keep it organized. ``` {bot-family}/ # Contains all bots under "family" (Protocol, etc.) ├── {bot-name}.json # Contains task definition for simulation └── {bot-name}/ # Contains all files for testing and building bot ├── ape-config.yaml # Ape configuration file (development only) ├── contracts # Smart contracts directory (if needed) │ └── *.{vy,sol} # Any mock contracts needed for bot operation ├── scripts # Scripts directory (contains production script and data) │ └── bot.py # Main script for running the bot (in container) └── tests # Test suite (assumes `--network :mainnet-fork:foundry`) ├── conftest.py # Pytest configuration file (should set up `bot` fixture) └── test_*.py # Test files to test bot functionality ``` ## Steps 1. **Initialize with Silverback** 2. **Create Data Structure** 3. **App Initialization** 4. **New Block Event / Event Log** ## Step 1. Initiate with Silverback To create a cHaOsNeT bot, you must use the Silverback SDK in conjunction with cHaOsNeT to continuously monitor and respond to on-chain events occuring in the Simulation. Instructions for installing the Silverback SDK can be found at [https://github.com/ApeWorX/silverback](https://github.com/ApeWorX/silverback). We are going to be creating our NFT bot in a file named `bot.py` and initialize Silverback using: ```python from silverback import SilverbackApp # App Initialization app = SilverbackApp() ``` ## Step 2. Create a Data Structure and Constants We will then need to create data structures and set constants for our bot, like block intervals, tracked addresses, and NFT contracts. ```python from typing import Set from ape import chain, project from ape.logging import logger from taskiq import Context, TaskiqDepends # Constants BLOCK_INTERVAL = 100 # Adjust this to the desired block interval for NFT minting # Data Structures tracked_addresses: Set[str] = set() # NFT Contract NFT_CONTRACT = project.erc721 # Replace this with the correct path to your NFT contract found in the `contracts/` directory ``` ## Step 4. App Initialization The SilverbackApp class handles state and configuration, so we need to initialize the state and deploy the contract. ```python @app.on__startup() def initialize(context: Context = TaskiqDepends()): """ Startup function to deploy the NFT contract and initialize the state. """ logger.info("Deploying NFT contract") nft_contract = NFT_CONTRACT.deploy(sender=app.signer) # Ensure you have the correct deploy method in your contract context.state.nft_contract = nft_contract context.state.tracked_addresses = tracked_addresses ``` ## Step 4. New Block Events/Event Logs Then, we define the logic that we want to handle each new event detected by the client. This can be either block or event handlers. For our use, we want to track active addresses based on every `n` blocks (`BLOCK_INTERVAl`) and track it in `tracked_addresses`. ```python @app.on_(chain.blocks) async def track_active_addresses(block, context: Context = TaskiqDepends()): """ Handler that tracks active addresses from transactions in each block. """ if block.number % BLOCK_INTERVAL == 0: context.state.tracked_addresses.clear() # Reset the set every `n` blocks # Track active addresses transactions = block.transactions for tx in transactions: context.state.tracked_addresses.add(tx.sender) ``` Then we want to mint NFTs to those active addresses found. ```python @app.on_(chain.blocks) async def mint_and_distribute_nfts(block, context: Context = TaskiqDepends()): """ Handler that mints and distributes NFTs to active addresses every `n` blocks. """ if block.number % BLOCK_INTERVAL == 0 and context.state.tracked_addresses: logger.info("Minting and distributing NFTs to active addresses") for address in context.state.tracked_addresses: try: # Adjust based on your contract's API context.state.nft_contract.mint(address, sender=app.signer) logger.info(f"NFT minted and sent to {address}") except Exception as e: logger.error(f"Error minting NFT for {address}: {e}") ```