Published
Edited
Apr 2, 2022
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
allFundedWithMinerId = (await fetch(minersAndFundersUrl)).json()
Insert cell
Insert cell
roots = allFundedWithMinerId.filter(({ funded_from }) => !funded_from).sort(sortIdRecords)
Insert cell
Inputs.table(roots, { columns: [ "id", "address" ] })
Insert cell
Insert cell
joinedAllFundedWithMinerId = allFundedWithMinerId
.map(record => ({
...record,
funded_from: record.funded_from || 'root'
}))
.concat([{
id: "root",
address: "root",
funded_from: null,
miner_id: null
}])
Insert cell
Insert cell
reachable = {
const addressIndex = d3.index(joinedAllFundedWithMinerId, d => d.id)
const fundedFromIndex = d3.group(joinedAllFundedWithMinerId, d => d.funded_from)
const start = addressIndex.get('root')
const reachable = []
function walk (from) {
reachable.push(from)
// console.log('Walking', from.id)
const fundedNodes = fundedFromIndex.get(from.address)
// console.log('Funded Nodes', fundedNodes)
if (fundedNodes) {
for (const funded of fundedNodes) {
walk(funded)
}
}
}

walk(start)

return reachable
}
Insert cell
stratify = d3.stratify()
.id(d => d["address"])
.parentId(d => d["funded_from"])
Insert cell
reachableTree = stratify(reachable)
Insert cell
/* Too big!! graph(reachableTree, {label: d => d.data.id + (d.data.miner_id ? ` (SP: ${d.data.miner_id})` : '') }) */
Insert cell
Insert cell
Insert cell
leavesWithPower = reachable.filter(({ miner_id }) => minerPowerDailyAverageReport.miners[miner_id] && minerPowerDailyAverageReport.miners[miner_id].qualityAdjPower)
Insert cell
reachableWithPower = {
const addressIndex = d3.index(reachable, d => d.address)
const filtered = new Map()
function walkUp (node) {
// console.log('WalkUp', node)
filtered.set(node.id, {
...node,
qualityAdjPower: minerPowerDailyAverageReport.miners[node.miner_id] &&
minerPowerDailyAverageReport.miners[node.miner_id].qualityAdjPower
})
if (node.funded_from) {
// console.log('funded_from', node.funded_from, addressIndex)
walkUp(addressIndex.get(node.funded_from))
}
}

for (const leaf of leavesWithPower) {
walkUp(leaf)
}

return [...filtered.values()].sort(sortIdRecords)
}
Insert cell
reachableWithPowerTree = stratify(reachableWithPower)
Insert cell
shortCircuit1 = true
Insert cell
!shortCircuit1 && graph(reachableWithPowerTree, {label: d => d.data.id + (d.data.miner_id ? ` (SP: ${d.data.miner_id} - ${bytes(d.data.qualityAdjPower, { mode: 'binary' })})` : '') })
Insert cell
Insert cell
reachableWithPowerAndRegions = reachableWithPower.map(record => {
const newRecord = record
if (record.miner_id) {
const regions = minerRegionsCSPReport.minerRegions.filter(({ miner }) => miner === record.miner_id)
if (regions.length > 0) {
newRecord.regions = regions.map(({ region }) => region)
}
}
return newRecord
})
Insert cell
button(reachableWithPowerAndRegions, 'funder-tree-base.json')
Insert cell
reachableWithPowerAndRegionsTree = stratify(reachableWithPowerAndRegions)
Insert cell
shortCircuit2 = true
Insert cell
!shortCircuit2 && graph(reachableWithPowerAndRegionsTree, {
label: d =>
(d.data.miner_id ?
`SP: ${d.data.miner_id} - ${bytes(d.data.qualityAdjPower, { mode: 'binary' })}` : d.data.id) +
(d.data.regions ?
` - ${d.data.regions.join(', ')}` : '')
})
Insert cell
Insert cell
Insert cell
async function *getTreeWithDelegatesStream (tree) {
const providerLeaves = []
for (const provider of tree.leaves()) {
if (!provider.data.regions) {
providerLeaves.push(provider)
}
}
let count = 0
for (const provider of providerLeaves) {
const delegateId = await matchDelegate(provider)
console.log(`Delegate: ${provider.data.id} => ${delegateId}`)
provider.data.delegateId = delegateId
yield {
done: false,
processed: ++count,
total: providerLeaves.length
}
}
yield {
done: true,
tree
}
}
Insert cell
viewof start = Inputs.button('Start')
Insert cell
funderTreeWithDelegatesProgress = start && getTreeWithDelegatesStream(reachableWithPowerAndRegionsTree)
Insert cell
funderTreeWithDelegates = funderTreeWithDelegatesProgress && funderTreeWithDelegatesProgress.done ? funderTreeWithDelegatesProgress.tree : null
Insert cell
## Synthetic Provider Regions
Insert cell
providerCSPRegions = d3.group(minerRegionsCSPReport.minerRegions, d => d.miner)
Insert cell
syntheticProviderCSPRegions = {
if (!funderTreeWithDelegates) return
const providerRegionsWithDelegates = []
for (const provider of funderTreeWithDelegates.leaves()) {
const { miner_id: providerId, delegateId } = provider.data
const targetId = delegateId || providerId
const targetRegions = providerCSPRegions.get(targetId)
if (targetRegions) {
for (const region of targetRegions) {
const outputRegion = {
provider: providerId,
region: region.region,
numRegions: region.numRegions
}
if (delegateId) {
outputRegion.delegate = delegateId
}
providerRegionsWithDelegates.push(outputRegion)
}
}
}
return providerRegionsWithDelegates.sort(sortProviderRecords)
}
Insert cell
syntheticProviderCSPRegions && button(syntheticProviderCSPRegions, `synthetic-provider-country-state-province-${minerRegionsCSPReport.epoch}.json`)
Insert cell
providerRegions = d3.group(minerRegionsReport.minerRegions, d => d.miner)
Insert cell
syntheticProviderRegions = {
if (!funderTreeWithDelegates) return
const providerRegionsWithDelegates = []
for (const provider of funderTreeWithDelegates.leaves()) {
const { miner_id: providerId, delegateId } = provider.data
const targetId = delegateId || providerId
const targetRegions = providerRegions.get(targetId)
if (targetRegions) {
for (const region of targetRegions) {
const outputRegion = {
provider: providerId,
region: region.region,
numRegions: region.numRegions
}
if (delegateId) {
outputRegion.delegate = delegateId
}
providerRegionsWithDelegates.push(outputRegion)
}
}
}
return providerRegionsWithDelegates.sort(sortProviderRecords)
}
Insert cell
syntheticProviderRegions && button(syntheticProviderRegions, `synthetic-provider-regions-${minerRegionsReport.epoch}.json`)
Insert cell
## Synthetic Provider Locations
Insert cell
providerCSPLocations = d3.group(minerLocationsCSPReport.minerLocations, d => d.miner)
Insert cell
syntheticProviderCSPLocations = {
if (!funderTreeWithDelegates) return
const providerLocationsWithDelegates = []
for (const provider of funderTreeWithDelegates.leaves()) {
const { miner_id: providerId, delegateId } = provider.data
const targetId = delegateId || providerId
const targetLocations = providerCSPLocations.get(targetId)
if (targetLocations) {
for (const location of targetLocations) {
const { miner, ...rest } = location
const outputLocation = {
provider: providerId,
...rest
}
if (delegateId) {
outputLocation.delegate = delegateId
}
providerLocationsWithDelegates.push(outputLocation)
}
}
}
return providerLocationsWithDelegates.sort(sortProviderRecords)
}
Insert cell
syntheticProviderCSPLocations && button(syntheticProviderCSPLocations, `synthetic-provider-country-state-province-locations-${minerLocationsCSPReport.epoch}.json`)
Insert cell
providerLocations = d3.group(minerLocationsReport.minerLocations, d => d.miner)
Insert cell
syntheticProviderLocations = {
if (!funderTreeWithDelegates) return
const providerLocationsWithDelegates = []
for (const provider of funderTreeWithDelegates.leaves()) {
const { miner_id: providerId, delegateId } = provider.data
const targetId = delegateId || providerId
const targetLocations = providerLocations.get(targetId)
if (targetLocations) {
for (const location of targetLocations) {
const { miner, ...rest } = location
const outputLocation = {
provider: providerId,
...rest
}
if (delegateId) {
outputLocation.delegate = delegateId
}
providerLocationsWithDelegates.push(outputLocation)
}
}
}
return providerLocationsWithDelegates.sort(sortProviderRecords)
}
Insert cell
syntheticProviderLocations && button(syntheticProviderLocations, `synthetic-provider-locations-${minerLocationsReport.epoch}.json`)
Insert cell
Insert cell
Insert cell
minerPowerDailyAverageReport = (await fetch(`${minerPowerDailyAverageLatestBucketUrl}/miner-power-daily-average-latest.json`)).json()
Insert cell
Insert cell
geoIpLookupsBucketUrl
Insert cell
minerRegionsReport = (await fetch(`${geoIpLookupsBucketUrl}/miner-regions-latest.json`)).json()
Insert cell
minerRegionsCSPReport = (await fetch(`${geoIpLookupsBucketUrl}/provider-country-state-province-latest.json`)).json()
Insert cell
minerLocationsReport = (await fetch(`${geoIpLookupsBucketUrl}/miner-locations-latest.json`)).json()
Insert cell
minerLocationsCSPReport = (await fetch(`${geoIpLookupsBucketUrl}/provider-country-state-province-locations-latest.json`)).json()
Insert cell
sortIdRecords = ({ id: minerA }, { id: minerB }) => Number(minerA.slice(1)) - Number(minerB.slice(1))
Insert cell
sortProviderRecords = ({ provider: providerA }, { provider: providerB }) => Number(providerA.slice(1)) - Number(providerB.slice(1))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more