-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.js
120 lines (112 loc) · 3.02 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* global Arweave */
import './vendor/arweave.js'
import pTimeout from './vendor/p-timeout.js'
const IP_ADDRESS_REGEX = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/
const ONE_MINUTE = 60_000
const MEASUREMENT_DELAY = ONE_MINUTE
const UPDATE_NODES_DELAY = 10 * ONE_MINUTE
const RANDOM_TRANSACTION_IDS = [
'sHqUBKFeS42-CMCvNqPR31yEP63qSJG3ImshfwzJJF8',
'vexijI_Ij0GfvWW1wvewlz255_v1Ni7dk9LuQdbi6yw',
'797MuCtgdgiDrglJWczz2lMZkFkXInC88Htqv-JuOUQ',
'XO6w3W8dYZnioq-phAbq8SG1Px5kci_j3RmcChS05VY',
's2aJ5tzVEcSxITsq2G5cZnAhBDplCSkARJEOuNMZ31o'
]
const RETRIEVE_TIMEOUT = 10_000
const getNodes = async () => {
// TODO: Find a publicly documented API
const docs = []
let maxPage = Infinity
for (let page = 0; page < maxPage; page++) {
const res = await fetch(
`https://api.viewblock.io/arweave/nodes?page=${page + 1}&network=mainnet`,
{
headers: {
Origin: 'https://viewblock.io'
}
}
)
const body = await res.json()
if (maxPage === Infinity) {
maxPage = body.pages
}
docs.push(...body.docs)
}
const nodes = [
{
host: 'arweave.net',
port: 443,
protocol: 'https'
},
...docs
.map(doc => doc.id)
.filter(Boolean)
.map(addr => {
const [host, port] = addr.split(':')
const protocol = IP_ADDRESS_REGEX.test(host) ? 'http' : 'https'
return {
host,
port: port
? Number(port)
: protocol === 'http' ? 80 : 443,
protocol
}
})
]
console.log(`Found ${nodes.length} nodes`)
return nodes
}
const measure = async node => {
const arweave = Arweave.init(node)
const txId = RANDOM_TRANSACTION_IDS[Math.floor(Math.random() * RANDOM_TRANSACTION_IDS.length)]
try {
await pTimeout(
arweave.chunks.downloadChunkedData(txId),
{ milliseconds: RETRIEVE_TIMEOUT }
)
} catch (err) {
console.error(err)
return false
}
return true
}
const submit = async measurement => {
const res = await fetch('https://api.checker.network/arweave/measurement', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(measurement)
})
if (!res.ok) {
throw new Error(`Failed to submit measurement (status=${res.status})`, {
cause: new Error(await res.text().catch(() => null))
})
}
}
let nodes = await getNodes()
;(async () => {
while (true) {
await new Promise(resolve => setTimeout(resolve, UPDATE_NODES_DELAY))
try {
nodes = await getNodes()
} catch (err) {
console.error('Error updating nodes')
console.error(err)
}
}
})()
while (true) {
const measurement = await measure(
nodes[Math.floor(Math.random() * nodes.length)]
)
console.log('measurement:', measurement)
try {
await submit(measurement)
} catch (err) {
console.error('Error submitting measurement')
console.error(err)
}
console.log(`Waiting ${MEASUREMENT_DELAY / 1_000} seconds...`)
await new Promise(resolve => setTimeout(resolve, MEASUREMENT_DELAY))
}