mirror of
https://github.com/stronk-dev/LivepeerEvents.git
synced 2025-07-05 02:35:09 +02:00
233 lines
6.8 KiB
JavaScript
233 lines
6.8 KiB
JavaScript
import express from "express";
|
|
import Event from '../models/event';
|
|
const fs = require('fs');
|
|
const apiRouter = express.Router();
|
|
import {
|
|
API_CMC, API_L1_HTTP, API_L2_HTTP, API_L2_WS
|
|
} from "../config";
|
|
|
|
// Get ETH price & LPT coin prices
|
|
const CoinMarketCap = require('coinmarketcap-api');
|
|
const cmcClient = new CoinMarketCap(API_CMC);
|
|
// Get gas price on ETH (L2 already gets exported by the O's themselves)
|
|
const { createAlchemyWeb3 } = require("@alch/alchemy-web3");
|
|
const web3layer1 = createAlchemyWeb3(API_L1_HTTP);
|
|
const web3layer2 = createAlchemyWeb3(API_L2_HTTP);
|
|
const web3layer2WS = createAlchemyWeb3(API_L2_WS);
|
|
|
|
// Update CMC related api calls every 5 minutes
|
|
const timeoutCMC = 300000;
|
|
let cmcPriceGet = 0;
|
|
let ethPrice = 0;
|
|
let lptPrice = 0;
|
|
let cmcQuotes = {};
|
|
let cmcCache = {};
|
|
|
|
// Update alchemy related API calls every 2 seconds
|
|
const timeoutAlchemy = 2000;
|
|
let l2Gwei = 0;
|
|
let l1Gwei = 0;
|
|
let l2block = 0;
|
|
let l1block = 0;
|
|
let arbGet = 0;
|
|
|
|
// Gas limits on common contract interactions
|
|
const redeemRewardGwei = 1053687;
|
|
const claimTicketGwei = 1333043;
|
|
const withdrawFeeGwei = 688913;
|
|
let redeemRewardCostL1 = 0;
|
|
let redeemRewardCostL2 = 0;
|
|
let claimTicketCostL1 = 0;
|
|
let claimTicketCostL2 = 0;
|
|
let withdrawFeeCostL1 = 0;
|
|
let withdrawFeeCostL2 = 0;
|
|
|
|
|
|
// Listen to smart contract emitters. Resync with DB every 5 minutes
|
|
const timeoutEvents = 300000;
|
|
let eventsCache = [];
|
|
let eventsGet = 0;
|
|
// https://arbiscan.io/address/0x35Bcf3c30594191d53231E4FF333E8A770453e40#events
|
|
const BondingManagerTargetJson = fs.readFileSync('src/abi/BondingManagerTarget.json');
|
|
const BondingManagerTargetAbi = JSON.parse(BondingManagerTargetJson);
|
|
const BondingManagerProxyAddr = "0x35Bcf3c30594191d53231E4FF333E8A770453e40";
|
|
const contractInstance = new web3layer2WS.eth.Contract(BondingManagerTargetAbi.abi, BondingManagerProxyAddr);
|
|
var BondingManagerProxyListener = contractInstance.events.allEvents(async (error, event) => {
|
|
try {
|
|
if (error) {
|
|
throw error
|
|
}
|
|
console.log('New event emitted on', BondingManagerProxyAddr);
|
|
// Push obj of event to cache and create a new entry for it in the DB
|
|
const eventObj = {
|
|
address: event.address,
|
|
transactionHash: event.transactionHash,
|
|
transactionUrl: "https://arbiscan.io/tx/" + event.transactionHash,
|
|
name: event.event,
|
|
data: event.returnValues
|
|
}
|
|
const dbObj = new Event(eventObj);
|
|
await dbObj.save();
|
|
eventsCache.push(eventObj);
|
|
}
|
|
catch (err) {
|
|
console.log("FATAL ERROR: ", err);
|
|
}
|
|
});
|
|
console.log("listening for events on", BondingManagerProxyAddr)
|
|
|
|
// Splits of the big CMC object into separate datas
|
|
const parseCmc = async function () {
|
|
try {
|
|
cmcCache = await cmcClient.getTickers({ limit: 200 });
|
|
for (var idx = 0; idx < cmcCache.data.length; idx++) {
|
|
const coinData = cmcCache.data[idx];
|
|
// Handle specific coins only for the grafana endpoint
|
|
if (coinData.symbol == "ETH") {
|
|
ethPrice = coinData.quote.USD.price;
|
|
} else if (coinData.symbol == "LPT") {
|
|
lptPrice = coinData.quote.USD.price;
|
|
}
|
|
// Sort by name->quotes for quotes endpoint
|
|
cmcQuotes[coinData.symbol] = coinData.quote.USD;
|
|
}
|
|
}
|
|
catch (err) {
|
|
res.status(400).send(err);
|
|
}
|
|
}
|
|
|
|
// Queries Alchemy for block info and fees
|
|
const parseL1Blockchain = async function () {
|
|
const l1Wei = await web3layer1.eth.getGasPrice();
|
|
l1block = await web3layer1.eth.getBlockNumber();
|
|
l1Gwei = l1Wei / 1000000000;
|
|
redeemRewardCostL1 = (redeemRewardGwei * l1Gwei) / 1000000000;
|
|
claimTicketCostL1 = (claimTicketGwei * l1Gwei) / 1000000000;
|
|
withdrawFeeCostL1 = (withdrawFeeGwei * l1Gwei) / 1000000000;
|
|
}
|
|
const parseL2Blockchain = async function () {
|
|
const l2Wei = await web3layer2.eth.getGasPrice();
|
|
l2block = await web3layer2.eth.getBlockNumber();
|
|
l2Gwei = l2Wei / 1000000000;
|
|
redeemRewardCostL2 = (redeemRewardGwei * l2Gwei) / 1000000000;
|
|
claimTicketCostL2 = (claimTicketGwei * l2Gwei) / 1000000000;
|
|
withdrawFeeCostL2 = (withdrawFeeGwei * l2Gwei) / 1000000000;
|
|
}
|
|
const parseEthBlockchain = async function () {
|
|
await Promise.all([parseL1Blockchain(), parseL2Blockchain()]);
|
|
}
|
|
|
|
// Export livepeer and eth coin prices and L1 Eth gas price
|
|
apiRouter.get("/grafana", async (req, res) => {
|
|
try {
|
|
const now = new Date().getTime();
|
|
// Update blockchain data if the cached data has expired
|
|
if (now - arbGet > timeoutAlchemy) {
|
|
await parseEthBlockchain();
|
|
arbGet = now;
|
|
}
|
|
// Update coin prices once their data has expired
|
|
if (now - cmcPriceGet > timeoutCMC) {
|
|
await parseCmc();
|
|
cmcPriceGet = now;
|
|
}
|
|
res.send({
|
|
timestamp: now,
|
|
cmcTime: cmcPriceGet,
|
|
blockchainTime: arbGet,
|
|
l1GasFeeInGwei: l1Gwei,
|
|
l2GasFeeInGwei: l2Gwei,
|
|
ethPriceInDollar: ethPrice,
|
|
lptPriceInDollar: lptPrice,
|
|
redeemRewardCostL1,
|
|
redeemRewardCostL2,
|
|
claimTicketCostL1,
|
|
claimTicketCostL2,
|
|
withdrawFeeCostL1,
|
|
withdrawFeeCostL2,
|
|
quotes: cmcQuotes
|
|
});
|
|
} catch (err) {
|
|
res.status(400).send(err);
|
|
}
|
|
});
|
|
|
|
apiRouter.get("/cmc", async (req, res) => {
|
|
try {
|
|
const now = new Date().getTime();
|
|
// Update cmc once their data has expired
|
|
if (now - cmcPriceGet > timeoutCMC) {
|
|
await parseCmc();
|
|
cmcPriceGet = now;
|
|
}
|
|
res.send(cmcCache);
|
|
} catch (err) {
|
|
res.status(400).send(err);
|
|
}
|
|
});
|
|
|
|
apiRouter.get("/blockchains", async (req, res) => {
|
|
try {
|
|
const now = new Date().getTime();
|
|
// Update blockchain data if the cached data has expired
|
|
if (now - arbGet > timeoutAlchemy) {
|
|
await parseEthBlockchain();
|
|
arbGet = now;
|
|
}
|
|
res.send({
|
|
timestamp: now,
|
|
l1block,
|
|
l2block,
|
|
blockchainTime: arbGet,
|
|
l1GasFeeInGwei: l1Gwei,
|
|
l2GasFeeInGwei: l2Gwei,
|
|
redeemRewardCostL1,
|
|
redeemRewardCostL2,
|
|
claimTicketCostL1,
|
|
claimTicketCostL2,
|
|
withdrawFeeCostL1,
|
|
withdrawFeeCostL2
|
|
});
|
|
} catch (err) {
|
|
res.status(400).send(err);
|
|
}
|
|
});
|
|
|
|
|
|
apiRouter.get("/quotes", async (req, res) => {
|
|
try {
|
|
const now = new Date().getTime();
|
|
// Update cmc once their data has expired
|
|
if (now - cmcPriceGet > timeoutCMC) {
|
|
cmcCache = await cmcClient.getTickers({ limit: 200 });
|
|
await parseCmc();
|
|
cmcPriceGet = now;
|
|
}
|
|
res.send(cmcQuotes);
|
|
} catch (err) {
|
|
res.status(400).send(err);
|
|
}
|
|
});
|
|
|
|
apiRouter.get("/getEvents", async (req, res) => {
|
|
try {
|
|
const now = new Date().getTime();
|
|
// Update cmc once their data has expired
|
|
if (now - eventsGet > timeoutEvents) {
|
|
eventsCache = await Event.find({}, {
|
|
address: 1,
|
|
transactionHash: 1,
|
|
transactionUrl: 1,
|
|
name: 1,
|
|
data: 1,
|
|
_id: 0});
|
|
eventsGet = now;
|
|
}
|
|
res.send(eventsCache);
|
|
} catch (err) {
|
|
res.status(400).send(err);
|
|
}
|
|
});
|
|
|
|
export default apiRouter; |