import os from flask import Flask, request, jsonify from ravencoin.rpc import RavenProxy from dotenv import load_dotenv import re from flask_limiter import Limiter from flask_limiter.util import get_remote_address import redis # Load environment variables load_dotenv() # Load environment variables from .env file api_key = os.getenv('RVN_API_KEY') if not api_key: raise ValueError("API Key not found in environment variables") print(f"API Key loaded: {api_key}") app = Flask(__name__) # Set up Redis for rate limiting redis_url = os.getenv('REDIS_URL', 'redis://localhost:6379/0') # Default Redis URL r = redis.from_url(redis_url) # Initialize Flask-Limiter with Redis storage limiter = Limiter(get_remote_address, app=app, storage_uri=redis_url) # Initialize Ravencoin RPC Proxy rpc_user = os.getenv('RVN_RPC_USER') rpc_password = os.getenv('RVN_RPC_PASSWORD') rpc_port = int(os.getenv('RVN_RPC_PORT', 8766)) # Default to 8766 if not provided rvn = RavenProxy(service_port=rpc_port, username=rpc_user, password=rpc_password) def is_valid_rvn_address(address): """Validate the provided Ravencoin address.""" return bool(re.match(r'^[Rr][a-km-zA-HJ-NP-Z1-9]{25,34}$', address)) @app.route('/', methods=['POST']) @limiter.limit("10 per minute") # Rate limit for RVN payments def reward_player(): req_data = request.get_json() provided_api_key = request.headers.get('X-API-KEY') # Check for valid API key if provided_api_key != api_key: return jsonify({'error': 'Unauthorized'}), 403 # Check for missing fields in the request if 'player_address' not in req_data or 'asset_name' not in req_data: return jsonify({'error': 'Missing player_address or asset_name'}), 400 player_address = req_data['player_address'] asset_name = req_data['asset_name'] # Get amount from request or use default amount = req_data.get('amount', 100) # Use provided amount or default to 100 # Validate the provided Ravencoin address if not is_valid_rvn_address(player_address): return jsonify({'error': 'Invalid Ravencoin address'}), 400 try: # Log the transaction attempt print(f"Attempting to send {amount} of {asset_name} to {player_address}") # Handle RVN vs Asset payments differently if asset_name.upper() == 'RVN': # For RVN payments, use amount directly as RVN (no satoshi conversion) rvn_amount = float(amount) print(f"Processing RVN payment: {rvn_amount} RVN to {player_address}") # Get network info for minimum fee requirements try: network_info = rvn.getnetworkinfo() min_relay_fee = network_info.get('relayfee', 0.00001) print(f"Node minimum relay fee: {min_relay_fee}") # Ensure amount meets minimum requirements if rvn_amount < min_relay_fee: print(f"Amount {rvn_amount} below minimum {min_relay_fee}, adjusting to minimum") rvn_amount = max(min_relay_fee * 10, 0.001) # Use 10x minimum or 0.001, whichever is higher except Exception as e: print(f"Could not get network info: {e}") # Use a safe minimum if we can't get network info if rvn_amount < 0.001: print(f"Using fallback minimum: adjusting {rvn_amount} to 0.001 RVN") rvn_amount = 0.001 print(f"Final RVN amount: {rvn_amount}") txid = rvn.sendtoaddress(player_address, rvn_amount) else: # For assets, use transfer method print(f"Sending {amount} units of asset {asset_name}") txid = rvn.transfer(asset_name, amount, player_address) # If txid is in bytes, convert it to a hex string if isinstance(txid, bytes): txid = txid.hex() print(f"Transaction successful! TXID: {txid}") return jsonify({'txid': txid}), 200 except Exception as e: # Return error message if something goes wrong error_msg = str(e) print(f"Transaction failed: {error_msg}") return jsonify({'error': error_msg}), 500 if __name__ == '__main__': app.run(host='0.0.0.0', port=30992, debug=True)