distributions
Process
Independent verification
require('dotenv').config();
const { parse } = require('csv-parse/sync');
const crypto = require('crypto');
const seedrandom = require('seedrandom');
// Replace this with your own Dune API key
const meta = {
'x-dune-api-key': {{apiKey}}
}
const header = new Headers(meta);
// Replace these with the metadata for the Brown Hole round you want to validate
const roundId = {{roundId}};
const roundStart = '{{roundStart}}';
const roundEnd = '{{roundEnd}}';
const prizeDescription = '{{prizeDescription}}';
const params = {
'query_parameters': {
'starttime': roundStart,
'endtime': roundEnd
}
};
const body = JSON.stringify(params);
async function executeDuneQuery() {
const executeUrl = 'https://api.dune.com/api/v1/query/3447423/execute';
try {
const execute = await fetch(executeUrl, {
method: 'POST',
headers: header,
body: body
});
const executeResponse = await execute.json();
console.log('Dune query submitted:', executeResponse.execution_id);
await pollForCompletion(executeResponse.execution_id);
} catch(error) {
console.log('Error: ', error);
}
}
async function pollForCompletion(executionId) {
const statusUrl = `https://api.dune.com/api/v1/execution/${executionId}/status`;
try {
let completed = false;
while (!completed) {
const response = await fetch(statusUrl, {
method: 'GET',
headers: header
});
const statusResponse = await response.json();
if (statusResponse.state === 'QUERY_STATE_COMPLETED') {
completed = true;
console.log('Dune query completed.');
await getDuneResults(executionId);
} else {
console.log('Dune query still executing, waiting...');
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait for 5 seconds before polling again
}
}
} catch (error) {
console.error('Error polling for completion:', error);
}
}
async function getDuneResults(executionId) {
const resultsUrl = `https://api.dune.com/api/v1/execution/${executionId}/results/csv`;
try {
const dataResponse = await fetch(resultsUrl, {
method: 'GET',
headers: header
});
const data = await dataResponse.text();
await flattenPoints(data);
} catch (error) {
console.log('Error getting results:', error);
}
}
async function flattenPoints(data) {
const records = parse(data, {
columns: true,
skip_empty_lines: true
});
let flatList = [];
let eligibleWallets = [];
records.forEach(record => {
eligibleWallets.push(record.wallet);
for (let i = 0; i < parseInt(record.points, 10); i++) {
flatList.push(record.wallet);
}
});
const flatListString = flatList.join('\n');
const concatenatedString = `${roundId}\n${prizeDescription}\n${roundStart}\n${roundEnd}\n${eligibleWallets}`;
const hash = crypto.createHash('sha256').update(concatenatedString).digest('hex');
console.log('Hashed round data:', hash);
const rng = seedrandom(hash);
const randomValue = rng();
console.log('Random number generated using hash as seed:', randomValue);
const randomIndex = Math.floor(randomValue * flatList.length);
console.log('Index corresponding to random number:', randomIndex);
const winningAddress = flatList[randomIndex];
console.log(`Winning address at chosen index: ${winningAddress}`);
console.log('--------------------');
console.log(`${winningAddress} wins ${prizeDescription} for Brown Hole round ${roundId} based on points tallied between ${roundStart} and ${roundEnd}`);
}
executeDuneQuery();Last updated