/ python / README.md
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