"""Free quote by default; one paid page only with --pay and an explicit budget. Install: pip install 'x402[httpx,evm]==2.25.0' """ import argparse import json import os from decimal import Decimal from pathlib import Path from urllib.parse import urlparse import httpx ORIGIN = 'https://agentleadrelay.com' RECIPIENT = '0xe619d127d21a1a8c177110311cb9b791d1d6928f' USDC = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' def validate_offer(offer, quote, budget, paid_url): if offer.x402_version != 2 or offer.resource is None or offer.resource.url != paid_url: raise ValueError('Unexpected payment version or resource') amount = int(quote['price_atomic']) if amount <= 0 or Decimal(amount) / 1000000 > budget: raise ValueError('Quote exceeds the authorized budget') valid = [a for a in offer.accepts if a.scheme == 'exact' and a.network == 'eip155:8453' and a.asset.lower() == USDC and a.pay_to.lower() == RECIPIENT and int(a.amount) == amount] if len(valid) != 1: raise ValueError('Payment challenge does not match the quote, asset, network and recipient') return offer.model_copy(update={'accepts': valid}) def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--municipality', default='Porto') parser.add_argument('--category', default='software_data') parser.add_argument('--keyword', default='') parser.add_argument('--min-funding', default='50000') parser.add_argument('--limit', type=int, default=10) parser.add_argument('--pay', action='store_true') parser.add_argument('--max-usdc', default='0') parser.add_argument('--output', default='bsp-search-result.json') args = parser.parse_args() budget = Decimal(args.max_usdc) if not budget.is_finite() or budget < 0: parser.error('Budget must be a finite nonnegative amount') with httpx.Client(timeout=90, follow_redirects=False) as http: response = http.get(ORIGIN + '/search/quote', params={'municipality': args.municipality, 'category': args.category, 'keyword': args.keyword, 'min_funding_eur': args.min_funding, 'limit': args.limit}) response.raise_for_status() quote = response.json() print(json.dumps(quote, indent=2, ensure_ascii=False)) if not args.pay or quote['status'] == 'NO_MATCH': return if Decimal(quote['price_usdc']) > budget or budget == 0: raise SystemExit('No purchase: quote exceeds the authorized budget.') paid_url = quote['paid_url'] parsed = urlparse(paid_url) if parsed.scheme != 'https' or parsed.netloc != 'agentleadrelay.com' or not parsed.path.startswith('/search/') or not parsed.path.endswith('/results') or parsed.query: raise SystemExit('No purchase: unexpected paid URL.') # No wallet is accessed until the explicit --pay branch. from eth_account import Account from x402 import x402ClientSync from x402.http import x402HTTPClientSync from x402.mechanisms.evm.exact import ExactEvmScheme client = x402ClientSync() transport = x402HTTPClientSync(client) challenge = http.get(paid_url) if challenge.status_code != 402: raise SystemExit('No purchase: expected a 402 challenge.') offer = transport.get_payment_required_response(challenge.headers.get) offer = validate_offer(offer, quote, budget, paid_url) key = os.environ.get('BSP_WALLET_PRIVATE_KEY') if not key: raise SystemExit('No purchase: configure BSP_WALLET_PRIVATE_KEY locally; never send it to the service.') client.register('eip155:8453', ExactEvmScheme(Account.from_key(key))) payload = client.create_payment_payload(offer) headers = transport.encode_payment_signature_header(payload) headers['X-Discovery-Source'] = 'developer-example' # Send the authorization once. Never automatically retry after this point. try: paid = http.get(paid_url, headers=headers) except httpx.HTTPError: raise SystemExit('Payment outcome unknown. Reconcile the wallet transaction before trying again.') try: receipt = transport.get_payment_settle_response(paid.headers.get) except ValueError: raise SystemExit('Settlement receipt missing. Payment outcome unknown; reconcile before trying again.') if paid.status_code != 200 or receipt is None or not receipt.success: raise SystemExit('Purchase not confirmed. Reconcile the settlement before trying again.') data = paid.json() if data.get('count') != quote['page_count'] or data.get('price_usdc') != quote['price_usdc'] or data.get('freshness', {}).get('snapshot_sha256') != quote['snapshot_sha256']: raise SystemExit('Payment settled but the result differs from the quote. Contact hello@agentleadrelay.com; do not repurchase.') Path(args.output).write_text(json.dumps({'quote':quote, 'result':data, 'receipt':receipt.model_dump(mode='json')}, ensure_ascii=False, indent=2)) print(f"Saved {data['count']} company records and the settlement receipt to {args.output}") if __name__ == '__main__': main()