Skip to content

Commit

Permalink
Merge pull request #21 from taha-abbasi/develop
Browse files Browse the repository at this point in the history
Dynamic nonCirculatingSupplyAddressConfiguration based on Currency
  • Loading branch information
taha-abbasi authored Apr 1, 2023
2 parents 2a292f0 + d77a7da commit 523bb06
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 262 deletions.
42 changes: 31 additions & 11 deletions build/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getNonCirculatingSupplyAddressConfigurations = exports.getNetworkConfigurations = exports.nonCirculatingSupplyAddressesConfigInput = void 0;
exports.getNonCirculatingSupplyAddressConfigurations = exports.getNetworkConfigurations = exports.getNonCirculatingSupplyAddressesConfigInput = void 0;
// src/config.ts
const node_fetch_1 = __importDefault(require("node-fetch"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const mongodb_1 = require("mongodb");
const dotenv_1 = require("dotenv");
(0, dotenv_1.config)();
const API_URL = process.env.API_URL;
// const MONGODB_URI = "mongodb+srv://tokenSupply_app_dev_qa_uat:[email protected]/?retryWrites=true&w=majority";
const DATABASE_NAME = "ferrum-network-dev";
const DATABASE_NAME = process.env.DATABASE_NAME;
const DB_COLLECTION_NAME_NON_CIRCULATING_SUPPLY_ADDRESS = process.env.DB_COLLECTION_NAME_NON_CIRCULATING_SUPPLY_ADDRESS;
const DB_COLLECTION_NAME_CHAIN_NETWORK_MAP = process.env.DB_COLLECTION_NAME_CHAIN_NETWORK_MAP;
function getChainIdToNetworkMap() {
return __awaiter(this, void 0, void 0, function* () {
const MONGODB_URI = process.env.MONGODB_URI;
Expand All @@ -32,11 +31,11 @@ function getChainIdToNetworkMap() {
const client = new mongodb_1.MongoClient(MONGODB_URI);
yield client.connect();
const database = client.db(DATABASE_NAME);
const chainIdToNetworkMapCollection = database.collection("chainIdToNetworkMap");
const chainIdToNetworkMapCollection = database.collection(DB_COLLECTION_NAME_CHAIN_NETWORK_MAP);
const result = yield chainIdToNetworkMapCollection.findOne({ appName: "tokenSupply" });
yield client.close();
if (!result) {
throw new Error("chainIdToNetworkMap not found in the database.");
throw new Error(`${DB_COLLECTION_NAME_CHAIN_NETWORK_MAP} not found in the database.`);
}
const chainIdToNetworkMap = {};
for (const item of result.chainIdToNetworkMap) {
Expand Down Expand Up @@ -65,19 +64,40 @@ function getNetworkConfigurations(tokenContractAddress, chainId) {
};
}
}
return networks;
// Get the currencyId from the response data
const currencyId = data.body.currencyAddressesByNetworks[0].currency._id;
return { networks, currencyId };
});
}
exports.getNetworkConfigurations = getNetworkConfigurations;
exports.nonCirculatingSupplyAddressesConfigInput = JSON.parse(fs_1.default.readFileSync(path_1.default.join(__dirname, "../config/", "nonCirculatingSupplyAddressesConfig.json"), "utf-8"));
function getNonCirculatingSupplyAddressConfigurations(tokenContractAddress, chainId) {
function getNonCirculatingSupplyAddressesConfigInput(currencyId) {
return __awaiter(this, void 0, void 0, function* () {
const MONGODB_URI = process.env.MONGODB_URI;
if (!MONGODB_URI) {
throw new Error('MONGODB_URI is not defined in the environment variables');
}
const client = new mongodb_1.MongoClient(MONGODB_URI);
yield client.connect();
const database = client.db(DATABASE_NAME);
const collection = database.collection(DB_COLLECTION_NAME_NON_CIRCULATING_SUPPLY_ADDRESS);
const result = yield collection.findOne({ currency: new mongodb_1.ObjectId(currencyId) });
yield client.close();
if (!result) {
throw new Error(`No non-circulating supply addresses configuration found for currency with ID: ${currencyId}`);
}
return result.nonCirculatingSupplyAddresses;
});
}
exports.getNonCirculatingSupplyAddressesConfigInput = getNonCirculatingSupplyAddressesConfigInput;
function getNonCirculatingSupplyAddressConfigurations(tokenContractAddress, chainId, currencyId) {
return __awaiter(this, void 0, void 0, function* () {
const url = `${API_URL}?tokenContractAddress=${tokenContractAddress}&chainId=${chainId}&offset=0`;
const response = yield (0, node_fetch_1.default)(url);
const data = yield response.json();
const nonCirculatingSupplyAddresses = [];
const chainIdToNetworkMap = yield getChainIdToNetworkMap();
for (const item of exports.nonCirculatingSupplyAddressesConfigInput) {
const nonCirculatingSupplyAddressesConfigInput = yield getNonCirculatingSupplyAddressesConfigInput(currencyId);
for (const item of nonCirculatingSupplyAddressesConfigInput) {
const network = chainIdToNetworkMap[item.chainId];
let networkItemFromGatewayConfig = data.body.currencyAddressesByNetworks.find(i => i.network.chainId === item.chainId);
nonCirculatingSupplyAddresses.push({
Expand Down
63 changes: 7 additions & 56 deletions build/getSupplyAcrossNetworks.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.getTotalSupplyAcrossNetworks = exports.getNonCirculatingSupplyBalances = void 0;
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const web3_1 = __importDefault(require("web3"));
const erc20Abi_json_1 = __importDefault(require("./erc20Abi.json"));
const config_1 = require("./config");
const utils_1 = require("./utils");
function getNonCirculatingSupplyBalances(tokenContractAddress, chainId) {
const erc20Abi = erc20Abi_json_1.default;
function getNonCirculatingSupplyBalances(tokenContractAddress, chainId, currencyId) {
return __awaiter(this, void 0, void 0, function* () {
const nonCirculatingSupplyBalances = [];
let total = new bignumber_js_1.default(0);
for (const { chainId: currentChainId, address, jsonRpcUrl, tokenContractAddress: currentTokenContractAddress, name, } of yield (0, config_1.getNonCirculatingSupplyAddressConfigurations)(tokenContractAddress, chainId)) {
for (const { chainId: currentChainId, address, jsonRpcUrl, tokenContractAddress: currentTokenContractAddress, name, } of yield (0, config_1.getNonCirculatingSupplyAddressConfigurations)(tokenContractAddress, chainId, currencyId)) {
let balance;
if (currentChainId === "bnbBeaconChain") {
balance = new bignumber_js_1.default(yield (0, utils_1.getBep2TokenBalance)(address, jsonRpcUrl, currentTokenContractAddress));
Expand All @@ -46,33 +48,12 @@ function getNonCirculatingSupplyBalances(tokenContractAddress, chainId) {
}
exports.getNonCirculatingSupplyBalances = getNonCirculatingSupplyBalances;
const getTotalSupplyAcrossNetworks = (networks) => __awaiter(void 0, void 0, void 0, function* () {
const erc20ABI = [
// Some parts of the ABI have been removed for brevity
{
constant: true,
inputs: [],
name: "totalSupply",
outputs: [{ name: "", type: "uint256" }],
payable: false,
stateMutability: "view",
type: "function",
},
{
constant: true,
inputs: [],
name: "decimals",
outputs: [{ name: "", type: "uint8" }],
payable: false,
stateMutability: "view",
type: "function",
},
];
const supplyPerNetwork = {};
let totalSupply = new bignumber_js_1.default(0);
for (const network in networks) {
const config = networks[network];
const web3 = new web3_1.default(config.jsonRpcUrl);
const tokenContract = new web3.eth.Contract(erc20ABI, config.tokenContractAddress);
const tokenContract = new web3.eth.Contract(erc20Abi, config.tokenContractAddress);
try {
const [supply, decimals] = yield Promise.all([
tokenContract.methods.totalSupply().call(),
Expand All @@ -82,42 +63,12 @@ const getTotalSupplyAcrossNetworks = (networks) => __awaiter(void 0, void 0, voi
const decimalsBN = new bignumber_js_1.default(10).pow(decimals);
const supplyInEther = supplyBN.div(decimalsBN);
totalSupply = totalSupply.plus(supplyInEther);
supplyPerNetwork[network] = supplyInEther.toString();
supplyPerNetwork[network] = supplyInEther.toFixed(18);
}
catch (error) {
console.error(`Error getting total supply for ${network}:`, error.message);
}
}
return Object.assign(Object.assign({}, supplyPerNetwork), { total: totalSupply.toString() });
return Object.assign(Object.assign({}, supplyPerNetwork), { total: totalSupply.toFixed(18) });
});
exports.getTotalSupplyAcrossNetworks = getTotalSupplyAcrossNetworks;
const erc20ABI = [
// Add necessary parts of the ABI, such as "balanceOf"
{
constant: true,
inputs: [],
name: "totalSupply",
outputs: [{ name: "", type: "uint256" }],
payable: false,
stateMutability: "view",
type: "function",
},
{
constant: true,
inputs: [],
name: "decimals",
outputs: [{ name: "", type: "uint8" }],
payable: false,
stateMutability: "view",
type: "function",
},
{
constant: true,
inputs: [{ name: "_owner", type: "address" }],
name: "balanceOf",
outputs: [{ name: "balance", type: "uint256" }],
payable: false,
stateMutability: "view",
type: "function",
},
];
35 changes: 27 additions & 8 deletions build/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Expand All @@ -32,7 +43,7 @@ app.get("/totalSupplyAcrossNetworks", (0, cacheMiddleware_1.default)(cacheDurati
res.status(400).json({ error: 'Both tokenContractAddress and chainId must be provided as query parameters.' });
return;
}
const networks = yield (0, config_1.getNetworkConfigurations)(tokenContractAddress, Number(chainId));
const { networks, currencyId } = yield (0, config_1.getNetworkConfigurations)(tokenContractAddress, Number(chainId));
const totalSupplyData = yield (0, getSupplyAcrossNetworks_1.getTotalSupplyAcrossNetworks)(networks);
res.json(totalSupplyData);
}
Expand All @@ -47,7 +58,7 @@ app.get('/totalSupply', (0, cacheMiddleware_1.default)(cacheDuration), (req, res
res.status(400).json({ error: 'Both tokenContractAddress and chainId must be provided as query parameters.' });
return;
}
const networks = yield (0, config_1.getNetworkConfigurations)(tokenContractAddress, Number(chainId));
const { networks, currencyId } = yield (0, config_1.getNetworkConfigurations)(tokenContractAddress, Number(chainId));
const totalSupplyData = yield (0, getSupplyAcrossNetworks_1.getTotalSupplyAcrossNetworks)(networks);
res.send(totalSupplyData.total);
}
Expand All @@ -62,8 +73,14 @@ app.get("/nonCirculatingSupplyAddresses", (0, cacheMiddleware_1.default)(cacheDu
res.status(400).json({ error: 'Both tokenContractAddress and chainId must be provided as query parameters.' });
return;
}
const nonCirculatingSupplyAddressConfigurations = yield (0, config_1.getNonCirculatingSupplyAddressConfigurations)(tokenContractAddress, Number(chainId));
res.json(nonCirculatingSupplyAddressConfigurations);
const { networks, currencyId } = yield (0, config_1.getNetworkConfigurations)(tokenContractAddress, Number(chainId));
const nonCirculatingSupplyAddressConfigurations = yield (0, config_1.getNonCirculatingSupplyAddressConfigurations)(tokenContractAddress, Number(chainId), currencyId);
// Remove jsonRpcUrl from the response
const filteredResponse = nonCirculatingSupplyAddressConfigurations.map((_a) => {
var { jsonRpcUrl } = _a, rest = __rest(_a, ["jsonRpcUrl"]);
return rest;
});
res.json(filteredResponse);
}));
app.get('/nonCirculatingSupplyBalancesByAddress', (0, cacheMiddleware_1.default)(cacheDuration), (req, res) => __awaiter(void 0, void 0, void 0, function* () {
try {
Expand All @@ -72,7 +89,8 @@ app.get('/nonCirculatingSupplyBalancesByAddress', (0, cacheMiddleware_1.default)
res.status(400).json({ error: 'Both tokenContractAddress and chainId must be provided as query parameters.' });
return;
}
const nonCirculatingSupplyBalances = yield (0, getSupplyAcrossNetworks_1.getNonCirculatingSupplyBalances)(tokenContractAddress, Number(chainId));
const { networks, currencyId } = yield (0, config_1.getNetworkConfigurations)(tokenContractAddress, Number(chainId));
const nonCirculatingSupplyBalances = yield (0, getSupplyAcrossNetworks_1.getNonCirculatingSupplyBalances)(tokenContractAddress, Number(chainId), currencyId);
res.json(nonCirculatingSupplyBalances);
}
catch (error) {
Expand All @@ -87,7 +105,8 @@ app.get('/nonCirculatingSupplyBalance', (0, cacheMiddleware_1.default)(cacheDura
res.status(400).json({ error: 'Both tokenContractAddress and chainId must be provided as query parameters.' });
return;
}
const { balances } = yield (0, getSupplyAcrossNetworks_1.getNonCirculatingSupplyBalances)(tokenContractAddress, Number(chainId));
const { networks, currencyId } = yield (0, config_1.getNetworkConfigurations)(tokenContractAddress, Number(chainId));
const { balances } = yield (0, getSupplyAcrossNetworks_1.getNonCirculatingSupplyBalances)(tokenContractAddress, Number(chainId), currencyId);
const totalBalance = balances.reduce((sum, balance) => sum.plus(balance.balance), new bignumber_js_1.default(0));
res.send(totalBalance.toString());
}
Expand All @@ -103,10 +122,10 @@ app.get('/circulatingSupplyBalance', (0, cacheMiddleware_1.default)(cacheDuratio
res.status(400).json({ error: 'Both tokenContractAddress and chainId must be provided as query parameters.' });
return;
}
const networks = yield (0, config_1.getNetworkConfigurations)(tokenContractAddress, Number(chainId));
const { networks, currencyId } = yield (0, config_1.getNetworkConfigurations)(tokenContractAddress, Number(chainId));
const totalSupplyData = yield (0, getSupplyAcrossNetworks_1.getTotalSupplyAcrossNetworks)(networks);
const totalSupply = new bignumber_js_1.default(totalSupplyData.total);
const { balances } = yield (0, getSupplyAcrossNetworks_1.getNonCirculatingSupplyBalances)(tokenContractAddress, Number(chainId));
const { balances } = yield (0, getSupplyAcrossNetworks_1.getNonCirculatingSupplyBalances)(tokenContractAddress, Number(chainId), currencyId);
const nonCirculatingSupply = balances.reduce((sum, balance) => sum.plus(balance.balance), new bignumber_js_1.default(0));
const circulatingSupply = totalSupply.minus(nonCirculatingSupply);
res.send(circulatingSupply.toString());
Expand Down
47 changes: 0 additions & 47 deletions config/nonCirculatingSupplyAddressesConfig.json

This file was deleted.

1 change: 1 addition & 0 deletions src/cacheMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// src/cacheMiddleware.ts
import { Request, Response, NextFunction } from "express";
import NodeCache from "node-cache";

Expand Down
Loading

0 comments on commit 523bb06

Please sign in to comment.