README.md
1 # 💰 Beaglegaze Python Sample 2 3 This Python sample demonstrates how to integrate Beaglegaze's blockchain-powered fee collection into your Python libraries. The example shows a monetized library where function calls automatically trigger micro-payments through a smart contract. 4 5 ## 📋 What's Included 6 7 - `demo.py` - Main demonstration of a monetized library with pay-per-call functionality 8 - `fund.py` - Script to fund the smart contract with ETH for testing 9 - `requirements.txt` - Python dependencies (references local beaglegaze-python-sdk) 10 - `contracts/` - Smart contract ABI and binary files 11 12 ## 🔧 Prerequisites 13 14 1. **Python 3.8+** with pip 15 2. **Docker** for running the local Ethereum testnet 16 3. **Git** for cloning repositories 17 4. **Beaglegaze Python SDK** (needs to be cloned separately - see setup steps) 18 19 ## 🚀 Quick Start 20 21 ### Step 0: Clone Required Repositories 22 23 First, ensure you have both the examples and the Python SDK: 24 25 ```bash 26 # Clone the examples repository (if not already done) 27 git clone https://github.com/beaglegaze/beaglegaze-examples.git 28 cd beaglegaze-examples 29 30 # Clone the Python SDK (required dependency) 31 git clone https://github.com/beaglegaze/beaglegaze-python-sdk.git 32 ``` 33 34 **Important:** The Python sample expects the SDK to be located at `../../beaglegaze-python-sdk` relative to the `python/` directory. Your directory structure should look like: 35 36 ``` 37 your-workspace/ 38 ├── beaglegaze-examples/ 39 │ └── python/ 40 │ ├── demo.py 41 │ ├── fund.py 42 │ └── requirements.txt 43 └── beaglegaze-python-sdk/ 44 ├── setup.py 45 └── beaglegaze/ 46 ``` 47 48 ### Step 1: Set Up the Ethereum Testnet 49 50 First, start a local Hardhat testnet with the deployed smart contract: 51 52 ```bash 53 # From the root of beaglegaze-examples repository 54 docker buildx build -t hardhat-testnet deploy/hardhat-testnet/. 55 docker run -d -p 8545:8545 --rm --name hardhat-testnet hardhat-testnet 56 ``` 57 58 The testnet will deploy the contract at address: `0x289B72CEeaB48832261626D62E3daA87Fd90B024` 59 60 ### Step 2: Install Dependencies 61 62 ```bash 63 cd beaglegaze-examples/python 64 python -m venv .venv 65 source .venv/bin/activate # On Windows: .venv\Scripts\activate 66 pip install -r requirements.txt 67 ``` 68 69 **Note:** The `requirements.txt` file installs the beaglegaze SDK from the local clone using `-e ../../beaglegaze-python-sdk`. If you get import errors, verify that: 70 1. The beaglegaze-python-sdk directory exists at the correct relative path 71 2. Your virtual environment is activated 72 3. The SDK was installed successfully (you should see it listed in `pip list`) 73 74 ### Step 3: Try the Demo (Will Fail Initially) 75 76 Run the demo without funding first to see the expected failure: 77 78 ```bash 79 python demo.py 80 ``` 81 82 **Expected output:** 83 ``` 84 --- Calling monetized function --- 85 86 Call 1: 87 Processing batch with sum 10000... 88 Error: Insufficient client funding 89 ``` 90 91 ### Step 4: Fund the Smart Contract 92 93 Fund the contract with ETH so the client can make paid function calls: 94 95 ```bash 96 python fund.py 97 ``` 98 99 This script sends 0.1 ETH to the smart contract on behalf of the client account. 100 101 ### Step 5: Run the Demo Successfully 102 103 Now run the demo again: 104 105 ```bash 106 python demo.py 107 ``` 108 109 **Expected output:** 110 ``` 111 --- Calling monetized function --- 112 113 Call 1: 114 Executing important_function with args=(0,) and kwargs={} 115 116 Call 2: 117 Executing important_function with args=(1,) and kwargs={} 118 119 Call 3: 120 Executing important_function with args=(2,) and kwargs={} 121 122 Call 4: 123 Executing important_function with args=(3,) and kwargs={} 124 125 Call 5: 126 Executing important_function with args=(4,) and kwargs={} 127 128 --- Demo complete --- 129 ``` 130 131 ## 📖 How It Works 132 133 ### The Monetized Library 134 135 The `MonetizedLibrary` class in `demo.py` demonstrates how to integrate Beaglegaze: 136 137 ```python 138 class MonetizedLibrary: 139 def __init__(self, network_url: str, client_private_key: str): 140 # Set up async batch processor 141 async_processor = AsyncBatchProcessor(BatchMode.OFF) 142 143 # Create smart contract instance 144 smart_contract = SmartContract( 145 "0x289B72CEeaB48832261626D62E3daA87Fd90B024", # Contract address 146 network_url, 147 client_private_key, 148 10 # batch size 149 ) 150 151 # Set up contract consumer and global processor 152 contract_consumer = ContractConsumer(smart_contract) 153 async_processor.add_observer(contract_consumer) 154 set_processor(async_processor) 155 156 @pay_per_call(price=10000) # 10,000 wei per call 157 def important_function(self, *args, **kwargs): 158 """This function costs 10,000 wei per call.""" 159 print(f"Executing important_function with args={args} and kwargs={kwargs}") 160 return "Success" 161 ``` 162 163 ### Key Components 164 165 - **`@pay_per_call(price=10000)`**: Decorator that makes the function cost 10,000 wei per call 166 - **`AsyncBatchProcessor`**: Handles asynchronous fee collection 167 - **`SmartContract`**: Interface to the Ethereum smart contract 168 - **`ContractConsumer`**: Processes fee collection events 169 170 ### Configuration 171 172 The demo uses these default values: 173 - **Network URL**: `http://localhost:8545` (local Hardhat testnet) 174 - **Client Private Key**: `0xcccc...cccc` (pre-funded test account) 175 - **Contract Address**: `0x289B72CEeaB48832261626D62E3daA87Fd90B024` 176 - **Price per call**: 10,000 wei 177 178 ## 🔍 Understanding the Workflow 179 180 1. **Client Setup**: The library initializes with a client private key and connects to the smart contract 181 2. **Fee Collection**: When `important_function()` is called, the `@pay_per_call` decorator triggers a fee collection event 182 3. **Asynchronous Processing**: The `AsyncBatchProcessor` batches multiple calls for efficiency 183 4. **Smart Contract Interaction**: The `ContractConsumer` processes the batch and deducts fees from the client's pre-funded account 184 185 ## 🎯 Customizing for Your Library 186 187 To integrate Beaglegaze into your own Python library: 188 189 1. **Add the decorator** to functions you want to monetize: 190 ```python 191 @pay_per_call(price=50000) # Set your price in wei 192 def your_expensive_function(self): 193 # Your implementation here 194 pass 195 ``` 196 197 2. **Initialize the processor** in your library's constructor: 198 ```python 199 def __init__(self, client_private_key: str): 200 # Set up the same components as in the demo 201 async_processor = AsyncBatchProcessor(BatchMode.OFF) 202 smart_contract = SmartContract(contract_address, network_url, client_private_key, batch_size) 203 contract_consumer = ContractConsumer(smart_contract) 204 async_processor.add_observer(contract_consumer) 205 set_processor(async_processor) 206 ``` 207 208 3. **Deploy your smart contract** or use an existing one for your service 209 210 ## 📚 Additional Resources 211 212 - [Beaglegaze Examples Repository](https://github.com/beaglegaze/beaglegaze-examples) 213 - [Java SDK Documentation](../java/README.md) 214 - [Smart Contract Documentation](../../beaglegaze-web3/README.md) 215 216 ## ⚠️ Important Notes 217 218 - Due to asynchronous processing, not every method invocation is immediately charged 219 - Some calls may execute even with insufficient funding, but the library will eventually block when funds are depleted 220 - Always test with a local testnet before deploying to mainnet 221 - Ensure clients understand the fee structure of your library 222 223 ## 🐛 Troubleshooting 224 225 **"Insufficient client funding" error:** 226 - Run `python fund.py` to add more ETH to the client account 227 - Check that the Hardhat testnet is running on port 8545 228 229 **Import errors:** 230 - Ensure the beaglegaze-python-sdk is properly installed: `pip install -e ../../beaglegaze-python-sdk` 231 - Check that the beaglegaze-python-sdk directory exists at the correct relative path 232 - Verify your virtual environment is activated: `which python` should point to your venv 233 234 **Connection errors:** 235 - Verify the Hardhat testnet is running: `docker ps` 236 - Ensure no firewall is blocking port 8545