Skip to content

Commit

Permalink
Merge pull request #9 from taha-abbasi/develop
Browse files Browse the repository at this point in the history
Added functionality to get balances for contracts across chains and standard and open staking contracts along with structural changes
  • Loading branch information
taha-abbasi authored May 5, 2023
2 parents bae48d3 + ca641c5 commit 4468399
Show file tree
Hide file tree
Showing 17 changed files with 5,989 additions and 229 deletions.
1,189 changes: 1,189 additions & 0 deletions ABI/crucibleRouterAbi.json

Large diffs are not rendered by default.

993 changes: 993 additions & 0 deletions ABI/openStakingContractAbi.json

Large diffs are not rendered by default.

1,131 changes: 1,131 additions & 0 deletions build/ABI/crucibleRouterAbi.json

Large diffs are not rendered by default.

953 changes: 953 additions & 0 deletions build/ABI/openStakingContractAbi.json

Large diffs are not rendered by default.

188 changes: 106 additions & 82 deletions build/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,69 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a, _b, _c;
Object.defineProperty(exports, "__esModule", { value: true });
const dotenv_1 = __importDefault(require("dotenv"));
const web3_1 = __importDefault(require("web3"));
const mongodb_1 = require("mongodb");
const bignumber_js_1 = require("bignumber.js");
const standardStakingContractAbi_json_1 = __importDefault(require("../ABI/standardStakingContractAbi.json"));
const tokenContractAbi_json_1 = __importDefault(require("../ABI/tokenContractAbi.json"));
const standardStaking_1 = require("./standardStaking");
const openStaking_1 = require("./openStaking");
dotenv_1.default.config();
const rpcUrl = process.env.RPC_URL || "";
const web3 = new web3_1.default(rpcUrl);
console.log("Web3 instance created.");
const tokenContractAddress = "0x9f6abbf0ba6b5bfa27f4deb6597cc6ec20573fda";
const tokenContract = new web3.eth.Contract(tokenContractAbi_json_1.default, tokenContractAddress);
console.log("Token contract instance created.");
function getTokenDecimals(tokenContractAddress) {
const DB_CONNECTION_STRING = (_a = process.env.DB_CONNECTION_STRING) !== null && _a !== void 0 ? _a : "";
const DB_NAME = (_b = process.env.DB_NAME) !== null && _b !== void 0 ? _b : "";
const DB_COLLECTION = (_c = process.env.DB_COLLECTION) !== null && _c !== void 0 ? _c : "";
if (!DB_CONNECTION_STRING || !DB_NAME || !DB_COLLECTION) {
throw new Error("DB_CONNECTION_STRING, DB_NAME, or DB_COLLECTION is not defined.");
}
const getWeb3Instance = (rpcUrl) => {
if (!rpcUrl) {
throw new Error("RPC URL is undefined.");
}
return new web3_1.default(rpcUrl);
};
// The data array containing staking contract and token contract addresses
const data = [
// {
// stakingPoolName: "GC - VIP Pool - FRM Arbitrum",
// stakingContractAddress: "0x2bE7904c81dd3535f31B2C7B524a6ed91FDb37EC",
// stakingPoolType: "standard",
// tokenContractAddress: "0x9f6abbf0ba6b5bfa27f4deb6597cc6ec20573fda",
// chainId: "42161",
// },
{
stakingPoolName: "cFRM Arbitrum Open Staking",
stakingContractAddress: "0xb4927895cbee88e651e0582893051b3b0f8d7db8",
stakingPoolType: "open",
tokenContractAddress: "0xe685d3cc0be48bd59082ede30c3b64cbfc0326e2",
chainId: "42161",
}
];
const getRpcUrl = (chainId, appName = "snapshot") => __awaiter(void 0, void 0, void 0, function* () {
const client = new mongodb_1.MongoClient(DB_CONNECTION_STRING);
try {
yield client.connect();
const db = client.db(DB_NAME);
const collection = db.collection(DB_COLLECTION);
const document = yield collection.findOne({ appName });
if (document) {
const chainIdToNetworkMap = document.chainIdToNetworkMap;
const rpcDetails = chainIdToNetworkMap.find((item) => item.chainId === chainId);
if (rpcDetails) {
return rpcDetails.jsonRpcUrl;
}
}
}
catch (error) {
console.error("Error fetching RPC URL:", error);
}
finally {
yield client.close();
}
return undefined;
});
function getTokenDecimals(tokenContractAddress, web3) {
return __awaiter(this, void 0, void 0, function* () {
console.log("Fetching token decimals...");
let decimals = 18;
Expand All @@ -40,84 +89,59 @@ function getTokenDecimals(tokenContractAddress) {
return decimals;
});
}
const stakingContractAddress = "0x2bE7904c81dd3535f31B2C7B524a6ed91FDb37EC";
const stakingContract = new web3.eth.Contract(standardStakingContractAbi_json_1.default, stakingContractAddress);
console.log("Staking contract instance created.");
function getUniqueStakers() {
return __awaiter(this, void 0, void 0, function* () {
console.log("Fetching unique stakers...");
const uniqueStakers = new Set();
const stakedEventFilter = {
fromBlock: 70124014,
toBlock: "latest",
address: stakingContractAddress,
topics: [stakingContract.events.Staked.signature],
};
(() => __awaiter(void 0, void 0, void 0, function* () {
let totalStakedBalances = {};
let finalResults = [];
for (const item of data) {
const stakingContractAddress = item.stakingContractAddress;
const tokenContractAddress = item.tokenContractAddress;
const chainId = item.chainId;
const rpcUrl = yield getRpcUrl(chainId);
try {
const logs = yield web3.eth.getPastLogs(stakedEventFilter);
logs.forEach((log) => {
const eventInterface = stakingContract.options.jsonInterface.find((i) => i.signature === log.topics[0]);
if (!eventInterface) {
console.error("Event interface not found for signature:", log.topics[0]);
return;
}
const inputs = eventInterface.inputs;
const event = web3.eth.abi.decodeLog(inputs, log.data, log.topics.slice(1));
const stakerAddress = event["staker_"];
uniqueStakers.add(stakerAddress);
});
console.log("Unique stakers fetched.");
}
catch (error) {
console.error("Error fetching unique stakers:", error);
}
return Array.from(uniqueStakers);
});
}
function getStakedBalances(stakers, decimals) {
return __awaiter(this, void 0, void 0, function* () {
console.log("Fetching staked balances...");
const stakedBalances = new Map();
for (const staker of stakers) {
try {
const balance = yield stakingContract.methods.stakeOf(staker).call();
const convertedBalance = new bignumber_js_1.BigNumber(balance).dividedBy(new bignumber_js_1.BigNumber(10).pow(decimals)).toString();
stakedBalances.set(staker, convertedBalance);
const web3Instance = getWeb3Instance(rpcUrl);
const decimals = yield getTokenDecimals(tokenContractAddress, web3Instance);
console.log("Token decimals:", decimals);
if (item.stakingPoolType === "standard") {
const stakers = yield (0, standardStaking_1.getUniqueStakers)(stakingContractAddress, web3Instance);
console.log("Unique staker addresses:", stakers);
const stakedBalances = yield (0, standardStaking_1.getStakedBalances)(stakers, decimals, stakingContractAddress, web3Instance);
console.log("Staked balances:", stakedBalances);
const stakingPoolName = item.stakingPoolName;
console.log("Staking pool name:", stakingPoolName);
const result = {
stakingPoolName: stakingPoolName,
stakedBalances: Object.fromEntries(stakedBalances),
};
console.log("Result:", JSON.stringify(result, null, 2));
// Update the totalStakedBalances object
stakedBalances.forEach((value, key) => {
if (totalStakedBalances[key]) {
const existingBalance = new bignumber_js_1.BigNumber(totalStakedBalances[key]);
const newBalance = existingBalance.plus(value);
totalStakedBalances[key] = newBalance.toString();
}
else {
totalStakedBalances[key] = value;
}
});
// Add the result to the finalResults array
finalResults.push(result);
}
catch (error) {
console.error(`Error fetching staked balance for ${staker}:`, error);
else if (item.stakingPoolType === "open") {
const uniqueStakers = yield (0, openStaking_1.getUniqueStakersFromOpenStaking)(web3Instance, stakingContractAddress, tokenContractAddress);
console.log("Unique staker addresses from open staking:", uniqueStakers);
const stakedBalances = yield (0, openStaking_1.getOpenStakingStakedBalances)(web3Instance, stakingContractAddress, tokenContractAddress, uniqueStakers, decimals);
console.log("Staked balances from open staking:", stakedBalances);
// Rest of the logic to store and display results for open staking
}
}
console.log("Staked balances fetched.");
return stakedBalances;
});
}
function getStakingPoolName() {
return __awaiter(this, void 0, void 0, function* () {
console.log("Fetching staking pool name...");
let poolName = "";
try {
poolName = yield stakingContract.methods.name().call();
// Add logic for other staking pool types here if needed
}
catch (error) {
console.error("Error fetching staking pool name:", error);
console.error("Error processing data item:", error);
continue;
}
console.log("Staking pool name fetched.");
return poolName;
});
}
(() => __awaiter(void 0, void 0, void 0, function* () {
const decimals = yield getTokenDecimals(tokenContractAddress);
console.log("Token decimals:", decimals);
const stakers = yield getUniqueStakers();
console.log("Unique staker addresses:", stakers);
const stakedBalances = yield getStakedBalances(stakers, decimals);
console.log("Staked balances:", stakedBalances);
const stakingPoolName = yield getStakingPoolName();
console.log("Staking pool name:", stakingPoolName);
const result = {
stakingPoolName: stakingPoolName,
stakedBalances: Object.fromEntries(stakedBalances),
};
console.log("Result:", JSON.stringify(result, null, 2));
}
// Add the total staked balances to the finalResults array
finalResults.push({ stakingPoolName: "totalStakedBalances", stakedBalances: totalStakedBalances });
console.log("Final Results:", JSON.stringify(finalResults, null, 2));
}))();
76 changes: 76 additions & 0 deletions build/src/openStaking.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"use strict";
// src/openStaking.ts
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getOpenStakingStakedBalances = exports.getUniqueStakersFromOpenStaking = void 0;
const bignumber_js_1 = require("bignumber.js");
const tokenContractAbi_json_1 = __importDefault(require("../ABI/tokenContractAbi.json"));
const openStakingContractAbi_json_1 = __importDefault(require("../ABI/openStakingContractAbi.json"));
function getUniqueStakersFromOpenStaking(web3Instance, stakingContractAddress, tokenContractAddress) {
return __awaiter(this, void 0, void 0, function* () {
console.log("Fetching Unique Stakers from Open Staking Contract...");
const tokenContract = new web3Instance.eth.Contract(tokenContractAbi_json_1.default, tokenContractAddress);
const transferEventSignature = tokenContract.events.Transfer.signature;
const transferEventFilter = {
fromBlock: 66553295,
toBlock: "latest",
address: tokenContractAddress,
topics: [transferEventSignature, null, web3Instance.eth.abi.encodeParameter("address", stakingContractAddress)],
};
const uniqueStakers = new Set();
try {
const logs = yield web3Instance.eth.getPastLogs(transferEventFilter);
console.log("Fetched logs:", logs);
logs.forEach((log) => {
console.log("Log:", log);
const eventInterface = tokenContract.options.jsonInterface.find((i) => i.signature === log.topics[0]);
if (!eventInterface) {
console.error("Event interface not found for signature:", log.topics[0]);
return;
}
const inputs = eventInterface.inputs;
const event = web3Instance.eth.abi.decodeLog(inputs, log.data, log.topics.slice(1));
console.log("Decoded event:", event);
// Check if the destination address matches the staking contract address
if (event.dst.toLowerCase() === stakingContractAddress.toLowerCase()) {
uniqueStakers.add(event.src);
}
});
}
catch (error) {
console.error("Error fetching ERC20 transfers to Staking Contract:", error);
}
return uniqueStakers;
});
}
exports.getUniqueStakersFromOpenStaking = getUniqueStakersFromOpenStaking;
function getOpenStakingStakedBalances(web3Instance, stakingContractAddress, tokenContractAddress, uniqueStakers, decimals) {
return __awaiter(this, void 0, void 0, function* () {
console.log("Fetching staked balances from Open Staking Contract...");
const stakingContract = new web3Instance.eth.Contract(openStakingContractAbi_json_1.default, stakingContractAddress);
const stakedBalances = {};
try {
for (const stakerAddress of uniqueStakers) {
const stakedBalanceRaw = yield stakingContract.methods.stakeOf(tokenContractAddress, stakerAddress).call();
const stakedBalance = new bignumber_js_1.BigNumber(stakedBalanceRaw).dividedBy(new bignumber_js_1.BigNumber(10).pow(decimals)).toString();
stakedBalances[stakerAddress] = stakedBalance;
}
}
catch (error) {
console.error("Error fetching staked balances from Open Staking Contract:", error);
}
return stakedBalances;
});
}
exports.getOpenStakingStakedBalances = getOpenStakingStakedBalances;
75 changes: 75 additions & 0 deletions build/src/standardStaking.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"use strict";
// src/standardStaking.ts
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStakedBalances = exports.getUniqueStakers = void 0;
const standardStakingContractAbi_json_1 = __importDefault(require("../ABI/standardStakingContractAbi.json"));
const bignumber_js_1 = require("bignumber.js");
function getUniqueStakers(stakingContractAddress, web3Instance) {
return __awaiter(this, void 0, void 0, function* () {
console.log("Fetching unique stakers...");
const uniqueStakers = new Set();
const stakingContract = new web3Instance.eth.Contract(standardStakingContractAbi_json_1.default, stakingContractAddress);
const stakedEventFilter = {
fromBlock: 66553295,
toBlock: "latest",
address: stakingContractAddress,
topics: [stakingContract.events.Staked.signature],
};
try {
const logs = yield web3Instance.eth.getPastLogs(stakedEventFilter);
console.log("Fetched logs:", logs);
logs.forEach((log) => {
const eventInterface = stakingContract.options.jsonInterface.find((i) => i.signature === log.topics[0]);
if (!eventInterface) {
console.error("Event interface not found for signature:", log.topics[0]);
return;
}
const inputs = eventInterface.inputs;
const event = web3Instance.eth.abi.decodeLog(inputs, log.data, log.topics.slice(1));
console.log("Decoded event:", event);
const stakerAddress = event["staker_"];
uniqueStakers.add(stakerAddress);
});
console.log("Unique stakers fetched.");
}
catch (error) {
console.error("Error fetching unique stakers:", error);
}
return Array.from(uniqueStakers);
});
}
exports.getUniqueStakers = getUniqueStakers;
function getStakedBalances(stakers, decimals, stakingContractAddress, web3Instance) {
return __awaiter(this, void 0, void 0, function* () {
console.log("Fetching staked balances...");
const stakedBalances = new Map();
const stakingContract = new web3Instance.eth.Contract(standardStakingContractAbi_json_1.default, stakingContractAddress);
for (const staker of stakers) {
try {
const balance = yield stakingContract.methods.stakeOf(staker).call();
const convertedBalance = new bignumber_js_1.BigNumber(balance)
.dividedBy(new bignumber_js_1.BigNumber(10).pow(decimals))
.toString();
stakedBalances.set(staker, convertedBalance);
}
catch (error) {
console.error(`Error fetching staked balance for ${staker}:`, error);
}
}
console.log("Staked balances fetched.");
return stakedBalances;
});
}
exports.getStakedBalances = getStakedBalances;
Loading

0 comments on commit 4468399

Please sign in to comment.