Skip to content
This repository has been archived by the owner on Jul 22, 2020. It is now read-only.

Commit

Permalink
feat: remove command-line solana dep, use web3js fr uptime instead
Browse files Browse the repository at this point in the history
  • Loading branch information
sunnygleason committed Aug 30, 2019
1 parent d796d77 commit 5d2a509
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 72 deletions.
126 changes: 60 additions & 66 deletions api/uptime-crawler.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
import * as solanaWeb3 from '@solana/web3.js';
import _ from 'lodash';
import YAML from 'yaml';
import redis from 'redis';
import {promisify} from 'util';
import {exec} from 'child_process';
import {sync as commandExistsSync} from 'command-exists';

import config from './config';

const FULLNODE_URL = process.env.FULLNODE_URL || 'http://localhost:8899';

const REFRESH_INTERVAL = 10 * 60 * 1000; // 10min

if (!commandExistsSync('solana')) {
throw 'solana command not found!';
}

function getClient() {
let props = config.redis.path
? {path: config.redis.path}
Expand All @@ -27,72 +20,73 @@ function getClient() {
const client = getClient();
const setAsync = promisify(client.set).bind(client);

function getVoteAccountUptime(x) {
const t1 = new Date().getTime();
// FIXME: this should be a genesis block API call (eventually), see:
// https://github.com/solana-labs/solana/blob/master/cli/src/wallet.rs#L680
// https://github.com/solana-labs/solana/blob/master/sdk/src/timing.rs#L14
const SLOTS_PER_EPOCH = 8192;

const p = new Promise((resolve, reject) => {
if (!x.votePubkey || x.votePubkey.length !== 44) {
reject(`invalid pubkey: ${x}`);
return;
}
let command = `solana -u ${FULLNODE_URL} show-vote-account ${x.votePubkey}`;
exec(command, (err, stdout, stderr) => {
const t2 = new Date().getTime();

if (err) {
// node couldn't execute the command
console.log('err', err, stderr);
reject(err);
return;
}

const result = YAML.parse(stdout);

const uptime = _.reduce(
result['epoch voting history'],
(a, v) => {
a.unshift({
epoch: v.epoch,
credits_earned: v['credits earned'],
slots_in_epoch: v['slots in epoch'],
percentage: (
(v['credits earned'] * 1.0) /
(v['slots in epoch'] * 1.0)
).toFixed(6),
});
return a;
},
[],
);

const uptimeValue = {
nodePubkey: result['node id'],
authorizedVoterPubkey: result['authorized voter pubkey'],
uptime: uptime,
lat: t2 - t1,
ts: t1,
};

resolve(uptimeValue);
});
});

return p;
async function getVoteAccountUptime(connection, x) {
const t1 = new Date().getTime();
let voteAccount = await connection.getAccountInfo(
new solanaWeb3.PublicKey(x.votePubkey),
);
const t2 = new Date().getTime();

let voteState = solanaWeb3.VoteAccount.fromAccountData(voteAccount.data);
if (voteState) {
const uptime = _.reduce(
voteState.epochCredits,
(a, v) => {
let credits = v.credits - v.prevCredits;

a.unshift({
epoch: v.epoch,
credits_earned: credits,
slots_in_epoch: SLOTS_PER_EPOCH,
percentage: ((credits * 1.0) / (SLOTS_PER_EPOCH * 1.0)).toFixed(6),
});

return a;
},
[],
);

const uptimeValue = {
nodePubkey: voteState.nodePubkey.toString(),
authorizedVoterPubkey: voteState.authorizedVoterPubkey.toString(),
uptime: uptime,
lat: t2 - t1,
ts: t1,
};

return uptimeValue;
} else {
console.log('eep, no vote state: ', x.votePubkey);
return null;
}
}

async function refreshUptime() {
console.log('uptime updater: updating...');
const connection = new solanaWeb3.Connection(FULLNODE_URL);
let voting = await connection.getVoteAccounts();

const allTasks = _.map(voting.current.concat(...voting.delinquent), v => {
return getVoteAccountUptime(v);
});

Promise.all(allTasks).then(async results => {
try {
const connection = new solanaWeb3.Connection(FULLNODE_URL);
let voting = await connection.getVoteAccounts();

const resultsAsync = _.map(
voting.current.concat(...voting.delinquent),
v => {
return getVoteAccountUptime(connection, v);
},
);

let results = await Promise.all(resultsAsync);
results = _.filter(results, x => x);
await setAsync('!uptime', JSON.stringify(results));

console.log('uptime updater: updated successfully.');
});
} catch (err) {
console.log('ERROR updating uptime: ' + err);
}
}

console.log('uptime updater process running...');
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"babel-plugin-transform-runtime": "^6.23.0",
"base-58": "^0.0.1",
"classnames": "^2.2.6",
"command-exists": "^1.2.8",
"copy-to-clipboard": "^3.2.0",
"cors": "^2.8.5",
"date-fns": "^2.0.1",
Expand Down
5 changes: 0 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4453,11 +4453,6 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"

command-exists@^1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.8.tgz#715acefdd1223b9c9b37110a149c6392c2852291"
integrity sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw==

commander@2, commander@^2.11.0, commander@^2.12.2, commander@^2.20.0:
version "2.20.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
Expand Down

0 comments on commit 5d2a509

Please sign in to comment.