#!/usr/bin/env python3 """ Send POL transaction on Polygon network. Usage: uv run python send_pol.py --to 0xRecipient --amount 0.1 --key 0xPrivateKey uv run python send_pol.py --to 0xRecipient --amount 0.1 # uses SENDER_PRIVATE_KEY from .env """ import argparse import os import sys from decimal import Decimal from dotenv import load_dotenv from web3 import Web3 from web3.middleware import ExtraDataToPOAMiddleware load_dotenv() POLYGON_RPC_URL = os.getenv("POLYGON_RPC_URL", "https://polygon-bor-rpc.publicnode.com") POLYGON_CHAIN_ID = int(os.getenv("POLYGON_CHAIN_ID", "137")) def send_pol(to_address: str, amount_pol: Decimal, private_key: str) -> str: w3 = Web3(Web3.HTTPProvider(POLYGON_RPC_URL)) w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0) if not w3.is_connected(): print(f"Error: cannot connect to RPC {POLYGON_RPC_URL}", file=sys.stderr) sys.exit(1) account = w3.eth.account.from_key(private_key) sender = account.address to_checksum = Web3.to_checksum_address(to_address) amount_wei = w3.to_wei(amount_pol, "ether") balance_wei = w3.eth.get_balance(sender) balance_pol = w3.from_wei(balance_wei, "ether") print(f"Sender: {sender}") print(f"Balance: {balance_pol} POL") print(f"Recipient: {to_checksum}") print(f"Amount: {amount_pol} POL ({amount_wei} wei)") gas_price = w3.eth.gas_price gas_limit = 21000 fee_wei = gas_price * gas_limit fee_pol = w3.from_wei(fee_wei, "ether") print(f"Gas price: {w3.from_wei(gas_price, 'gwei'):.2f} Gwei (fee ≈ {fee_pol:.6f} POL)") if balance_wei < amount_wei + fee_wei: print( f"Error: insufficient balance. Need {w3.from_wei(amount_wei + fee_wei, 'ether')} POL, have {balance_pol} POL", file=sys.stderr, ) sys.exit(1) nonce = w3.eth.get_transaction_count(sender) tx = { "to": to_checksum, "value": amount_wei, "gas": gas_limit, "gasPrice": gas_price, "nonce": nonce, "chainId": POLYGON_CHAIN_ID, } signed = w3.eth.account.sign_transaction(tx, private_key) tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction) tx_hash_hex = tx_hash.hex() print(f"\nTransaction sent: {tx_hash_hex}") print(f"Tracker: https://polygonscan.com/tx/{tx_hash_hex}") print("Waiting for receipt...", end=" ", flush=True) receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=120) if receipt["status"] == 1: print(f"confirmed in block {receipt['blockNumber']}") else: print("REVERTED", file=sys.stderr) sys.exit(1) return tx_hash_hex def main(): parser = argparse.ArgumentParser(description="Send POL on Polygon") parser.add_argument("--to", required=True, help="Recipient address (0x...)") parser.add_argument("--amount", required=True, type=Decimal, help="Amount in POL") parser.add_argument( "--key", default=None, help="Sender private key (0x...). Falls back to SENDER_PRIVATE_KEY env var.", ) args = parser.parse_args() private_key = args.key or os.getenv("SENDER_PRIVATE_KEY") if not private_key: print( "Error: provide --key or set SENDER_PRIVATE_KEY in .env", file=sys.stderr, ) sys.exit(1) send_pol(args.to, args.amount, private_key) if __name__ == "__main__": main()