import requests import datetime from bs4 import BeautifulSoup import sys # This python script scrapes Ocean.xyz and creates a csv of the payouts to a given BTC address. # # This will be useful for anyone mining on Ocean.xyz who wants to keep track of their earnings in BTC or USD # # Example output: # Please enter the address you're using to mine on Ocean.xyz: <3QomtEj5nfzEkxPXoVD3hvxgJDzA6M6evt> # Row, Block_Height, Date, BTCUSD, BTC_Earned, USD_Earned, BTC_Fee, USD_Fee # 1, 829513, 02-08-2024, $44335.00, 0.43437323, $19257.94, 0.00000000, 0.0 # 2, 829267, 02-06-2024, $42658.30, 0.35614859, $15192.69, 0.00000000, 0.0 # 3, 828232, 01-31-2024, $42937.72, 0.13227494, $5679.58, 0.00000000, 0.0 # 4, 827750, 01-28-2024, $42126.55, 0.03297256, $1389.02, 0.00000000, 0.0 # # How it does it: # 1. it visits Ocean.xyz and grabs your "Latest Earnings" # 2. it takes the hash from the earning to mempool.space to get the date of the earning # 3. it takes the date to coinbase's api to get the BTCUSD # 4. it does the math to calculate $ earned & $ fee paid # 5. it formats this into a nice CSV for you to import into Excel/Quickbooks/etc. # # Is there value here for you? # Value 4 Value: btc99k@strike.me # def fetch_block_details(block_hash: str): url = f"https://mempool.space/api/block/{block_hash}" response = requests.get(url) if response.status_code == 200: data = response.json() height = data.get('height') timestamp = data.get('timestamp') datetime_obj = datetime.datetime.utcfromtimestamp(timestamp) formatted_date = datetime_obj.strftime("%m-%d-%Y") return height, formatted_date else: return None, None def get_bitcoin_price_on_date(mmddyyyy_str: str): month, day, year = mmddyyyy_str.split("-") date_formatted = f"{year}-{month}-{day}" url = f"https://api.coinbase.com/v2/prices/BTC-USD/spot?date={date_formatted}" try: response = requests.get(url) if response.status_code == 200: data = response.json() # The price is in the 'data' field, under 'amount' btc_price = data['data']['amount'] return float(btc_price) else: return "Error: Unable to fetch Bitcoin price data" except Exception as e: return f"Error: {str(e)}" def output_for_address(ocean_addr: str, maximum_page_number: int = 20, oldest_to_newest: bool = True): page_index = 0 output_data = [] while page_index < maximum_page_number: url = f"https://ocean.xyz/template/workers/earnings/rows?user={ocean_addr}&epage={page_index+1}&page={page_index}&sortParam=" page_index = page_index + 1 print(f"Working on page {page_index}") # Fetch the webpage response = requests.get(url) html = response.text # Parse the HTML soup = BeautifulSoup(html, 'html.parser') rows = soup.find_all("tr", class_="table-row") if not rows: break for row in soup.find_all("tr", class_="table-row"): cells = row.find_all("td", class_="table-cell") block_hash = cells[0].get_text(strip=True).split()[0] btc_earned = cells[2].get_text(strip=True).split()[0] btc_fee = cells[3].get_text(strip=True).split()[0] height, mmdddyyyy_str = fetch_block_details(block_hash) btcusd = get_bitcoin_price_on_date(mmdddyyyy_str) usd_earned = float(btc_earned) * float(btcusd) usd_fee_paid = float(btc_fee) * float(btcusd) output = (f"{height}, " f"{mmdddyyyy_str}, " f"${btcusd:.2f}, " f"{btc_earned}, " f"${usd_earned:0.2f}, " f"{btc_fee}, " f"{usd_fee_paid}") output_data.append(output) if oldest_to_newest: output_data.reverse() output_row_number = 1 print("Row", "Block_Height", "Date", "BTCUSD", "BTC_Earned", "USD_Earned", "BTC_Fee", "USD_Fee", sep=", ") for one_row in output_data: print(output_row_number, one_row, sep=", ") output_row_number += 1 if __name__ == "__main__": old_first = True pages = 10 if len(sys.argv) > 1: btc_address = sys.argv[1] else: btc_address = input("Please enter the address you're using to mine on Ocean.xyz: ") # # I'm not really documenting it, but you can pass in the # of pages to fetch in the 2nd argument # if len(sys.argv) > 2: pages = int(sys.argv[2]) # # I'm not really documenting it, but you can pass "false" as arg #3 if you want it sorted newest-to-oldest" # if len(sys.argv) > 3: old_first = False if sys.argv[3].lower() == "false" else True if len(btc_address): print("") output_for_address(ocean_addr=btc_address, maximum_page_number=pages, oldest_to_newest=old_first) print("") else: print("\nNext time, enter a BTC address on the command line, or at the prompt. \nHappy Hashing!")