Last active
June 17, 2025 15:00
-
-
Save StephenBrown2/0a01846c355ef5c56f94a1f129cc00a2 to your computer and use it in GitHub Desktop.
Real Estate in BTC UserScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Real Estate Priced in BTC | |
// @namespace http://tampermonkey.net/ | |
// @version 0.2 | |
// @updateURL https://gist.github.com/StephenBrown2/0a01846c355ef5c56f94a1f129cc00a2 | |
// @downloadURL https://gist.github.com/StephenBrown2/0a01846c355ef5c56f94a1f129cc00a2 | |
// @description Display all home prices in BTC. | |
// @author Phteven | |
// @match http*://www.zillow.com/* | |
// @match http*://www.redfin.com/* | |
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | |
// @grant none | |
// ==/UserScript== | |
async function getBTC() { | |
const url = "https://mempool.space/api/v1/prices"; | |
const btc = await fetch(url).then(function (response) { | |
return response.json(); | |
}).then(function (data) { | |
return data.USD; | |
}).catch(function (err) { | |
console.log('Fetch Error :-S', err); | |
}) | |
return btc; | |
} | |
async function getHistoricalBTC(date = new Date()) { | |
const url = `https://mempool.space/api/v1/historical-price?currency=USD×tamp=${Math.floor(date.getTime() / 1000)}`; | |
const btc = await fetch(url).then(function (response) { | |
return response.json(); | |
}).then(function (data) { | |
return data.prices[0].USD; | |
}).catch(function (err) { | |
console.log('Fetch Error :-S', err); | |
}); | |
return btc; | |
} | |
async function setRedfinLastSoldPrice() { | |
let lastSold = document.querySelector('div.ListingStatusBannerSection.remodel'); | |
if (!lastSold) { | |
console.log("Last sold element not found"); | |
return; | |
} | |
// Extract the date and price from the text "LAST SOLD ON MAR 1, 2024 FOR $384,900" | |
let dateMatch = lastSold.textContent.match(/ON (.+?) FOR/); | |
let priceMatch = lastSold.textContent.match(/FOR (\$[,\d]+)/); | |
let date = dateMatch ? dateMatch[1] : null; | |
let usdPrice = priceMatch ? priceMatch[1].replace(/[\$,]/g, '') : null; | |
usdPrice = usdPrice ? parseFloat(usdPrice) : null; | |
date = date ? new Date(date + " 12:00 PM") : null; | |
var btcPrice = await getHistoricalBTC(date); | |
if (btcPrice === 0) { | |
console.error("BTC price is zero, cannot calculate BTC value."); | |
return; | |
} | |
let BTC = (usdPrice / btcPrice).toFixed(8) + ' ₿'; | |
if (lastSold.hasChildNodes()) { | |
for (const node of lastSold.childNodes) { | |
if (node.nodeType === Node.TEXT_NODE) { | |
if (node.textContent.match(/FOR \$([,\d]+)/)) { | |
let span = document.createElement('span'); | |
span.title = priceMatch[1] + ' @ $' + btcPrice + '/BTC'; | |
span.textContent = ' FOR ' + BTC; | |
node.replaceWith(span); | |
} | |
} | |
} | |
} | |
} | |
function getAllPrices() { | |
// Combined query selector for all possible price elements | |
return document.querySelectorAll( | |
'div.stat-block .statsValue,' + // Redfin | |
'.bp-Homecard__Price--value,' + // Redfin Homepage Cards | |
'.price-text,' + // Zillow | |
'[data-testid="primary-zestimate"],' + // Zestimate | |
'.hs-fact-value,' + // Home Zestimate | |
'[data-test="property-card-price"],' + // Zillow Cards | |
'[data-testid="data-price-row"]', + // Zillow Favorite homes | |
'[data-testid="price"]' // Zillow photos view | |
); | |
} | |
// setBTC takes an element with a USD price, and btcPrice, | |
// and updates the element's innerHTML to show the BTC equivalent | |
// of the USD price | |
function setBTC(elem, btcPrice) { | |
if (!elem.textContent.includes('$')) { | |
return; | |
} | |
let usdPrice = Number(elem.textContent.replace(/[^0-9.-]+/g, "")); | |
let BTC = (usdPrice / btcPrice).toFixed(8) + ' ₿'; | |
const inner = '<span title="' + elem.textContent + ' @ $' + btcPrice + '/BTC">' + BTC + '</span>'; | |
elem.innerHTML = inner; | |
} | |
(async function() { | |
'use strict'; | |
var btcPrice = await getBTC(); | |
var runIt = async function() { | |
var prices = getAllPrices(); | |
for (const priceObj of prices) { | |
setBTC(priceObj, btcPrice); | |
} | |
await setRedfinLastSoldPrice(); | |
}; | |
window.onload = await runIt; | |
setInterval(runIt, 1000); | |
setInterval(async function() { btcPrice = await getBTC(); }, 60000); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment