Public
Edited
Sep 21, 2023
Insert cell
Insert cell
Insert cell
Insert cell
endpointUrl = {
return "https://lotus.miner.report/mainnet_api/0/node/rpc/v0"
// return "https://lotus.jimpick.com/mainnet_api/0/node/rpc/v0"
// return "https://api.node.glif.io/rpc/v0" - Doesn't work
// return "https://api.chain.love/rpc/v0"
}
Insert cell
await client.version()
Insert cell
chainHead = await client.chainHead()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
filteredMinerPeerIds.length
Insert cell
maxElapsed = 10 * 60 * 1000
Insert cell
Insert cell
minerInfoSubsetLatest
Insert cell
Insert cell
minerPeerIds = Object.entries(minerInfoSubsetLatest.miners).map(([miner, info]) => ({ miner, peerId: info.peerId })).filter(info => info.peerId).sort(({ miner: minerA }, { miner: minerB }) => Number(minerA.slice(1)) - Number(minerB.slice(1)))
Insert cell
Insert cell
Insert cell
// legacyAnnotationsMainnet
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dhtAddrsLatestReport = (await fetch(`${dhtAddrsLatestBucketUrl}/dht-addrs-latest.json`)).json()
Insert cell
minTimestamp = dateFns.subDays(new Date(), 7)
Insert cell
latestDhtAddrsMiners = {
const minerSet = new Set()
for (const miner in dhtAddrsLatestReport.miners) {
const timestamp = d3.isoParse(dhtAddrsLatestReport.miners[miner].timestamp)
if (timestamp > minTimestamp) minerSet.add(miner)
}
return minerSet
}
Insert cell
subsetToScan
Insert cell
filteredMinerPeerIds = d3.shuffle(minerPeerIds.filter(({ miner }) => {
/* if (subsetToScan === 'No fail') {
return !legacyAnnotationsMainnet[miner].startsWith('fail,')
} else
if (subsetToScan === 'Fail only') {
return legacyAnnotationsMainnet[miner].startsWith('fail,')
} else */ if (subsetToScan === 'All recents') {
return dailyCountsReport.miners[miner] || multidayCountsReport.miners[miner] || latestDhtAddrsMiners.has(miner)
} else if (subsetToScan === 'No recents') {
return !(dailyCountsReport.miners[miner] || multidayCountsReport.miners[miner] || latestDhtAddrsMiners.has(miner))
} else {
return true
}
}))
Insert cell
workingMiner = minerPeerIds.find(({ miner }) => miner === 'f02620')
Insert cell
dhtFindPeerFirst = client.netFindPeer(workingMiner.peerId)
Insert cell
async function* dhtFindPeerStream() {
const concurrency = 15
const callDhtFindPeerStream = transform(concurrency, async ({ miner, peerId }) => {
try {
const { Addrs: multiaddrs } = (await client.netFindPeer(peerId))

return {
miner,
peerId,
multiaddrs: multiaddrs.sort()
}
} catch (e) {
console.info('DHT lookup error', miner, e.message)
return {}
}
})
const startTime = new Date()
let counter = 0
let hits = 0
let errors = 0
let lastMiner
for await (const dhtLookup of callDhtFindPeerStream(filteredMinerPeerIds)) {
const now = new Date()
if (now - startTime > maxElapsed) {
yield {
done: true,
timeout: true,
counter,
hits,
errors
}
return
}
if (dhtLookup.miner) {
lastMiner = dhtLookup.miner
hits++
yield {
counter,
hits,
errors,
...dhtLookup
}
} else {
errors++
yield {
counter,
hits,
errors,
lastMiner
}
}
counter++
}
yield {
done: true,
counter,
hits,
errors
}
}
Insert cell
filteredMinerPeerIds.length
Insert cell
// dhtFindPeerStream()
Insert cell
minerDhtAddrs = {
if (start === 0) {
yield {
state: 'paused'
}
return
}
yield {
state: 'starting'
}
let records = []
let totalErrors = 0
let lastCounter = 0
const startTime = new Date()
for await (const {counter, hits, errors, ...record} of dhtFindPeerStream()) {
totalErrors = errors
lastCounter = counter
if (record.miner) {
records.push(record)
}
yield {
state: "streaming",
elapsed: ((new Date()) - startTime) / 1000,
scannedPeers: counter,
totalPeers: filteredMinerPeerIds.length,
recordsLength: records.length,
errors
}
}
const endTime = new Date()
yield {
state: "done",
elapsed: (endTime - startTime) / 1000,
scannedPeers: lastCounter,
totalPeers: filteredMinerPeerIds.length,
records: records.sort(sortMinerRecords),
startTime,
endTime,
errors: totalErrors
}
}
Insert cell
minerDhtAddrs.state === 'done' && md`Miner | Multiaddrs
---|---
${minerDhtAddrs.records.slice(0, maxRows).map(({ miner, multiaddrs }) => {
const multiaddrsFormatted = multiaddrs ? multiaddrs.join(' ') : ''
let lines = `${miner} | ${multiaddrsFormatted}\n`
return lines
})}
`
Insert cell
maxRows = 100
Insert cell
Insert cell
LotusRPC = (await import('@filecoin-shipyard/lotus-client-rpc')).LotusRPC
Insert cell
BrowserProvider = (await import('@filecoin-shipyard/lotus-client-provider-browser')).BrowserProvider
Insert cell
schema = (await import('@filecoin-shipyard/lotus-client-schema')).mainnet.fullNode
Insert cell
Insert cell
Object.keys(schema.methods)
Insert cell
Insert cell
client = {
const provider = new BrowserProvider(endpointUrl)
return new LotusRPC(provider, { schema })
}
Insert cell
Insert cell
transform = (await import('streaming-iterables@7.1.0')).transform
Insert cell
import { epochToDate } from '@jbenet/filecoin-chain-time-calculator'
Insert cell
Insert cell
Insert cell
import {sortMinerRecords} from '@jimpick/provider-quest-utils'
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