From f2a63ce54efe18c11e1ef3f183d019fc38fd4325 Mon Sep 17 00:00:00 2001 From: hoangdv2429 Date: Wed, 17 Jan 2024 00:11:28 +0700 Subject: [PATCH 1/9] add customer_usage --- main.ts | 104 +++++++++++++++++++++++++++++++++++++++++++---------- queries.ts | 29 +++++++++++++-- 2 files changed, 111 insertions(+), 22 deletions(-) diff --git a/main.ts b/main.ts index c7b6058..ed32cbb 100644 --- a/main.ts +++ b/main.ts @@ -2,11 +2,14 @@ import { CosmWasmClient } from "npm:@cosmjs/cosmwasm-stargate"; import { Coin } from "npm:@cosmjs/stargate"; import { Decimal } from "npm:@cosmjs/math"; import { toUtf8 } from "npm:@cosmjs/encoding"; -import { HttpBatchClient, Tendermint34Client } from "npm:@cosmjs/tendermint-rpc"; +import { + HttpBatchClient, + Tendermint34Client, +} from "npm:@cosmjs/tendermint-rpc"; import * as promclient from "npm:prom-client"; import express from "npm:express@4.18.2"; import settings from "./settings.ts"; -import { communityPoolFunds, totalSupply } from "./queries.ts"; +import { communityPoolFunds, contractBalance, totalSupply } from "./queries.ts"; function printableCoin(coin: Coin): string { if (coin.denom?.startsWith("u")) { @@ -17,6 +20,17 @@ function printableCoin(coin: Coin): string { } } +// mapping of channel IDs to customer +const channelDescriptions = { + "channel-11": "gelotto-proxy", + "channel-16": "example-proxy-1", +}; + +function mapChannelToDescription(channelId: string): string { + // Default to a unknown if the channel is not found + return channelDescriptions[channelId] || "unknown-proxy"; +} + export interface Account { readonly name: string; readonly address: string; @@ -32,7 +46,6 @@ function errorLog(msg: string) { } if (import.meta.main) { - const app = express(); const balances = new Map(); @@ -43,16 +56,32 @@ if (import.meta.main) { labelNames: ["account", "rpcEndpoint", "chainId"] as const, }); + const customerUsageGauge = new promclient.Gauge({ + name: "customer_usage", + help: "Usage data per customer chain", + labelNames: [ + "channel", + "rpcEndpoint", + "chainId", + "description", + "address", + ] as const, + }); + // Updates all gauges with the current balances const gaugify = () => { for (const [key, val] of balances.entries()) { - balancesGauge.set({ account: key, rpcEndpoint, chainId }, parseInt(val, 10) / 1_000_000); + balancesGauge.set( + { account: key, rpcEndpoint, chainId }, + parseInt(val, 10) / 1_000_000 + ); } }; // deno-lint-ignore no-explicit-any app.get("/metrics", (_req: any, res: any) => { gaugify(); + updateContractState(); res.set("Content-Type", promclient.register.contentType); promclient.register.metrics().then((metrics) => res.end(metrics)); @@ -60,7 +89,7 @@ if (import.meta.main) { const rpcEndpoint = Deno.env.get("RPC_ENDPOINT"); if (!rpcEndpoint) { - console.error('RPC_ENDPOINT environment variable is not defined'); + console.error("RPC_ENDPOINT environment variable is not defined"); Deno.exit(1); // Exit the process with a non-zero code to indicate failure } const httpBatch = new HttpBatchClient(rpcEndpoint); @@ -75,37 +104,74 @@ if (import.meta.main) { const updateAccounts = () => { // debugLog("Getting balances ..."); for (const account of accounts) { - client.getBalance(account.address, account.denom).then((balance) => { - debugLog(`${account.name}: ${printableCoin(balance)}`); - balances.set(account.name, balance.amount); - }, (err) => errorLog(err.toString())); + client.getBalance(account.address, account.denom).then( + (balance) => { + debugLog(`${account.name}: ${printableCoin(balance)}`); + balances.set(account.name, balance.amount); + }, + (err) => errorLog(err.toString()) + ); } }; const updateTotalSupply = () => { - totalSupply(tmClient, "unois").then((balance) => { - const exportAccountName = "total supply"; - debugLog(`${exportAccountName}: ${printableCoin(balance)}`); - balances.set(exportAccountName, balance.amount); - }, (err) => errorLog(err.toString())); + totalSupply(tmClient, "unois").then( + (balance) => { + const exportAccountName = "total supply"; + debugLog(`${exportAccountName}: ${printableCoin(balance)}`); + balances.set(exportAccountName, balance.amount); + }, + (err) => errorLog(err.toString()) + ); }; const updateCommunityPool = () => { - communityPoolFunds(tmClient, "unois").then((balance) => { - const exportAccountName = "community pool"; - debugLog(`${exportAccountName}: ${printableCoin(balance)}`); - balances.set(exportAccountName, balance.amount); - }, (err) => errorLog(err.toString())); + communityPoolFunds(tmClient, "unois").then( + (balance) => { + const exportAccountName = "community pool"; + debugLog(`${exportAccountName}: ${printableCoin(balance)}`); + balances.set(exportAccountName, balance.amount); + }, + (err) => errorLog(err.toString()) + ); + }; + + const updateContractState = async () => { + try { + const contractState = await contractBalance( + tmClient, + "nois1xwde9rzqk5u36fke0r9ddmtwvh43n4fv53c5vc462wz8xlnqjhls6d90xc" + ); + + // array of customer data + for (const customer of contractState.customers) { + const description = mapChannelToDescription(customer.channel_id); // Implement this mapping function + customerUsageGauge.set( + { + channel: customer.channel_id, + rpcEndpoint: rpcEndpoint, + chainId: chainId, + description: description, + address: customer.payment, + }, + customer.requested_beacons + ); + } + } catch (err) { + errorLog(err.toString()); + } }; // Initial call updateAccounts(); updateTotalSupply(); updateCommunityPool(); + updateContractState(); setInterval(updateAccounts, 10_000); setInterval(updateTotalSupply, 45_000); setInterval(updateCommunityPool, 100_000); + setInterval(updateContractState, 60_000); const port = 3000; app.listen(port, function () { diff --git a/queries.ts b/queries.ts index fd5a5f2..53a04ac 100644 --- a/queries.ts +++ b/queries.ts @@ -7,8 +7,12 @@ import { setupBankExtension, setupDistributionExtension, } from "npm:@cosmjs/stargate"; +import { setupWasmExtension } from "npm:@cosmjs/cosmwasm-stargate"; -export async function totalSupply(tmClient: TendermintClient, searchDenom: string): Promise { +export async function totalSupply( + tmClient: TendermintClient, + searchDenom: string +): Promise { const queryClient = QueryClient.withExtensions(tmClient, setupBankExtension); return await queryClient.bank.supplyOf(searchDenom); } @@ -16,9 +20,12 @@ export async function totalSupply(tmClient: TendermintClient, searchDenom: strin /* Queries the community pool funds in full unois. */ export async function communityPoolFunds( tmClient: TendermintClient, - searchDenom: string, + searchDenom: string ): Promise { - const queryClient = QueryClient.withExtensions(tmClient, setupDistributionExtension); + const queryClient = QueryClient.withExtensions( + tmClient, + setupDistributionExtension + ); const resp = await queryClient.distribution.communityPool(); const unois = resp.pool.find((coin) => coin.denom === searchDenom); if (!unois) { @@ -28,3 +35,19 @@ export async function communityPoolFunds( return coin(amount, searchDenom); } } + +export async function contractBalance( + tmClient: TendermintClient, + contractAddress: string, +) { + const queryClient = QueryClient.withExtensions(tmClient, setupWasmExtension); + let res: any; + try { + res = await queryClient.wasm.queryContractSmart(contractAddress, { + customers: {}, + }); + } catch (error) { + console.error(error); + } + return res; +} From e66dff3c0a664b4f09eca780503600be2ea65048 Mon Sep 17 00:00:00 2001 From: hoangdv2429 Date: Thu, 18 Jan 2024 18:06:55 +0700 Subject: [PATCH 2/9] names correction --- main.ts | 12 ++++++------ queries.ts | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/main.ts b/main.ts index ed32cbb..353ef55 100644 --- a/main.ts +++ b/main.ts @@ -9,7 +9,7 @@ import { import * as promclient from "npm:prom-client"; import express from "npm:express@4.18.2"; import settings from "./settings.ts"; -import { communityPoolFunds, contractBalance, totalSupply } from "./queries.ts"; +import { communityPoolFunds, getContractUsage, totalSupply } from "./queries.ts"; function printableCoin(coin: Coin): string { if (coin.denom?.startsWith("u")) { @@ -81,7 +81,7 @@ if (import.meta.main) { // deno-lint-ignore no-explicit-any app.get("/metrics", (_req: any, res: any) => { gaugify(); - updateContractState(); + updateContractUsage(); res.set("Content-Type", promclient.register.contentType); promclient.register.metrics().then((metrics) => res.end(metrics)); @@ -136,9 +136,9 @@ if (import.meta.main) { ); }; - const updateContractState = async () => { + const updateContractUsage = async () => { try { - const contractState = await contractBalance( + const contractState = await getContractUsage( tmClient, "nois1xwde9rzqk5u36fke0r9ddmtwvh43n4fv53c5vc462wz8xlnqjhls6d90xc" ); @@ -166,12 +166,12 @@ if (import.meta.main) { updateAccounts(); updateTotalSupply(); updateCommunityPool(); - updateContractState(); + updateContractUsage(); setInterval(updateAccounts, 10_000); setInterval(updateTotalSupply, 45_000); setInterval(updateCommunityPool, 100_000); - setInterval(updateContractState, 60_000); + setInterval(updateContractUsage, 60_000); const port = 3000; app.listen(port, function () { diff --git a/queries.ts b/queries.ts index 53a04ac..e9b5e1d 100644 --- a/queries.ts +++ b/queries.ts @@ -36,7 +36,7 @@ export async function communityPoolFunds( } } -export async function contractBalance( +export async function getContractUsage( tmClient: TendermintClient, contractAddress: string, ) { From 1ece90ca9ef0963f88f1574c1e235bddbd3b36c5 Mon Sep 17 00:00:00 2001 From: hoangdv2429 Date: Thu, 18 Jan 2024 18:11:19 +0700 Subject: [PATCH 3/9] revert --- main.ts | 36 ++++++++++++------------------------ queries.ts | 10 ++-------- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/main.ts b/main.ts index 353ef55..a5a0994 100644 --- a/main.ts +++ b/main.ts @@ -2,10 +2,7 @@ import { CosmWasmClient } from "npm:@cosmjs/cosmwasm-stargate"; import { Coin } from "npm:@cosmjs/stargate"; import { Decimal } from "npm:@cosmjs/math"; import { toUtf8 } from "npm:@cosmjs/encoding"; -import { - HttpBatchClient, - Tendermint34Client, -} from "npm:@cosmjs/tendermint-rpc"; +import { HttpBatchClient, Tendermint34Client } from "npm:@cosmjs/tendermint-rpc"; import * as promclient from "npm:prom-client"; import express from "npm:express@4.18.2"; import settings from "./settings.ts"; @@ -71,10 +68,7 @@ if (import.meta.main) { // Updates all gauges with the current balances const gaugify = () => { for (const [key, val] of balances.entries()) { - balancesGauge.set( - { account: key, rpcEndpoint, chainId }, - parseInt(val, 10) / 1_000_000 - ); + balancesGauge.set({ account: key, rpcEndpoint, chainId }, parseInt(val, 10) / 1_000_000); } }; @@ -89,7 +83,7 @@ if (import.meta.main) { const rpcEndpoint = Deno.env.get("RPC_ENDPOINT"); if (!rpcEndpoint) { - console.error("RPC_ENDPOINT environment variable is not defined"); + console.error('RPC_ENDPOINT environment variable is not defined'); Deno.exit(1); // Exit the process with a non-zero code to indicate failure } const httpBatch = new HttpBatchClient(rpcEndpoint); @@ -104,25 +98,19 @@ if (import.meta.main) { const updateAccounts = () => { // debugLog("Getting balances ..."); for (const account of accounts) { - client.getBalance(account.address, account.denom).then( - (balance) => { - debugLog(`${account.name}: ${printableCoin(balance)}`); - balances.set(account.name, balance.amount); - }, - (err) => errorLog(err.toString()) - ); + client.getBalance(account.address, account.denom).then((balance) => { + debugLog(`${account.name}: ${printableCoin(balance)}`); + balances.set(account.name, balance.amount); + }, (err) => errorLog(err.toString())); } }; const updateTotalSupply = () => { - totalSupply(tmClient, "unois").then( - (balance) => { - const exportAccountName = "total supply"; - debugLog(`${exportAccountName}: ${printableCoin(balance)}`); - balances.set(exportAccountName, balance.amount); - }, - (err) => errorLog(err.toString()) - ); + totalSupply(tmClient, "unois").then((balance) => { + const exportAccountName = "total supply"; + debugLog(`${exportAccountName}: ${printableCoin(balance)}`); + balances.set(exportAccountName, balance.amount); + }, (err) => errorLog(err.toString())); }; const updateCommunityPool = () => { diff --git a/queries.ts b/queries.ts index e9b5e1d..0c69bcf 100644 --- a/queries.ts +++ b/queries.ts @@ -9,10 +9,7 @@ import { } from "npm:@cosmjs/stargate"; import { setupWasmExtension } from "npm:@cosmjs/cosmwasm-stargate"; -export async function totalSupply( - tmClient: TendermintClient, - searchDenom: string -): Promise { +export async function totalSupply(tmClient: TendermintClient, searchDenom: string): Promise { const queryClient = QueryClient.withExtensions(tmClient, setupBankExtension); return await queryClient.bank.supplyOf(searchDenom); } @@ -22,10 +19,7 @@ export async function communityPoolFunds( tmClient: TendermintClient, searchDenom: string ): Promise { - const queryClient = QueryClient.withExtensions( - tmClient, - setupDistributionExtension - ); + const queryClient = QueryClient.withExtensions(tmClient, setupDistributionExtension); const resp = await queryClient.distribution.communityPool(); const unois = resp.pool.find((coin) => coin.denom === searchDenom); if (!unois) { From c5007b0d234f3c4797a13b616f5402dcf0fb00b7 Mon Sep 17 00:00:00 2001 From: hoangdv2429 Date: Thu, 18 Jan 2024 20:41:17 +0700 Subject: [PATCH 4/9] add deployer address to chain setting --- main.ts | 2 +- settings.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/main.ts b/main.ts index a5a0994..01e59ab 100644 --- a/main.ts +++ b/main.ts @@ -128,7 +128,7 @@ if (import.meta.main) { try { const contractState = await getContractUsage( tmClient, - "nois1xwde9rzqk5u36fke0r9ddmtwvh43n4fv53c5vc462wz8xlnqjhls6d90xc" + settings[chainId].deployerAddr ); // array of customer data diff --git a/settings.ts b/settings.ts index 52fdc56..2db51c9 100644 --- a/settings.ts +++ b/settings.ts @@ -2,6 +2,7 @@ import { Account } from "./main.ts"; export interface ChainSettings { accounts: Account[]; + deployerAddr: string; } const settings: Record = { @@ -33,6 +34,7 @@ const settings: Record = { denom: "unois", }, ], + deployerAddr: "nois1acyc05v6fgcdgj88nmz2t40aex9nlnptqpwp5hf8hwg7rhce9uuqgqz5wp" }, "nois-testnet-005": { accounts: [ @@ -52,6 +54,7 @@ const settings: Record = { denom: "unois", }, ], + deployerAddr: "nois1xwde9rzqk5u36fke0r9ddmtwvh43n4fv53c5vc462wz8xlnqjhls6d90xc" }, }; From 597ddd5dac3ebb9b9ccc86c6264f09dcbf7861aa Mon Sep 17 00:00:00 2001 From: hoangdv2429 Date: Thu, 18 Jan 2024 20:53:32 +0700 Subject: [PATCH 5/9] move channels description to setting --- main.ts | 13 ++++--------- settings.ts | 12 +++++++++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/main.ts b/main.ts index 01e59ab..6c76ca6 100644 --- a/main.ts +++ b/main.ts @@ -17,15 +17,10 @@ function printableCoin(coin: Coin): string { } } -// mapping of channel IDs to customer -const channelDescriptions = { - "channel-11": "gelotto-proxy", - "channel-16": "example-proxy-1", -}; -function mapChannelToDescription(channelId: string): string { +function mapChannelToDescription(chainId: string,channelId: string): string { // Default to a unknown if the channel is not found - return channelDescriptions[channelId] || "unknown-proxy"; + return settings[chainId].mappingChannels[channelId] || "unknown-proxy"; } export interface Account { @@ -128,12 +123,12 @@ if (import.meta.main) { try { const contractState = await getContractUsage( tmClient, - settings[chainId].deployerAddr + settings[chainId].gatewayAddr ); // array of customer data for (const customer of contractState.customers) { - const description = mapChannelToDescription(customer.channel_id); // Implement this mapping function + const description = mapChannelToDescription(chainId, customer.channel_id); // Implement this mapping function customerUsageGauge.set( { channel: customer.channel_id, diff --git a/settings.ts b/settings.ts index 2db51c9..3a00b95 100644 --- a/settings.ts +++ b/settings.ts @@ -2,7 +2,8 @@ import { Account } from "./main.ts"; export interface ChainSettings { accounts: Account[]; - deployerAddr: string; + gatewayAddr: string; + mappingChannels: Record } const settings: Record = { @@ -34,7 +35,11 @@ const settings: Record = { denom: "unois", }, ], - deployerAddr: "nois1acyc05v6fgcdgj88nmz2t40aex9nlnptqpwp5hf8hwg7rhce9uuqgqz5wp" + gatewayAddr: "nois1acyc05v6fgcdgj88nmz2t40aex9nlnptqpwp5hf8hwg7rhce9uuqgqz5wp", + mappingChannels: { + "channel-11": "gelotto-proxy", + "channel-16": "example-proxy-1", + } }, "nois-testnet-005": { accounts: [ @@ -54,7 +59,8 @@ const settings: Record = { denom: "unois", }, ], - deployerAddr: "nois1xwde9rzqk5u36fke0r9ddmtwvh43n4fv53c5vc462wz8xlnqjhls6d90xc" + gatewayAddr: "nois1xwde9rzqk5u36fke0r9ddmtwvh43n4fv53c5vc462wz8xlnqjhls6d90xc", + mappingChannels: {} }, }; From 17ca9ee37424e070ea409e42f36ca0f8c3808799 Mon Sep 17 00:00:00 2001 From: Kais baccour <31540265+kaisbaccour@users.noreply.github.com> Date: Thu, 18 Jan 2024 15:16:32 +0100 Subject: [PATCH 6/9] Update settings.ts --- settings.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/settings.ts b/settings.ts index 3a00b95..b914ce4 100644 --- a/settings.ts +++ b/settings.ts @@ -38,7 +38,12 @@ const settings: Record = { gatewayAddr: "nois1acyc05v6fgcdgj88nmz2t40aex9nlnptqpwp5hf8hwg7rhce9uuqgqz5wp", mappingChannels: { "channel-11": "gelotto-proxy", - "channel-16": "example-proxy-1", + "channel-2": "juno-nois-team", + "channel-20": "injective-governance", + "channel-22": "architech", + "channel-35": "aura-team", + "channel-38": "stargaze-governance", + "channel-38": "osmosis-nois-team", } }, "nois-testnet-005": { @@ -60,7 +65,10 @@ const settings: Record = { }, ], gatewayAddr: "nois1xwde9rzqk5u36fke0r9ddmtwvh43n4fv53c5vc462wz8xlnqjhls6d90xc", - mappingChannels: {} + mappingChannels: { + "channel-17": "juno-nois-team", + "channel-36": "injective-nois-team", + } }, }; From 5e2e6fc43d4c6feae9008689e388da6b3a067d41 Mon Sep 17 00:00:00 2001 From: Kais baccour <31540265+kaisbaccour@users.noreply.github.com> Date: Thu, 18 Jan 2024 15:27:16 +0100 Subject: [PATCH 7/9] Update settings.ts --- settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.ts b/settings.ts index b914ce4..d5cfff6 100644 --- a/settings.ts +++ b/settings.ts @@ -43,7 +43,7 @@ const settings: Record = { "channel-22": "architech", "channel-35": "aura-team", "channel-38": "stargaze-governance", - "channel-38": "osmosis-nois-team", + "channel-41": "osmosis-nois-team", } }, "nois-testnet-005": { From 1c5bed357244902e9413861f559c0e7bd602c8e6 Mon Sep 17 00:00:00 2001 From: hoangdv2429 Date: Thu, 18 Jan 2024 21:28:21 +0700 Subject: [PATCH 8/9] right channel --- settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.ts b/settings.ts index b914ce4..d5cfff6 100644 --- a/settings.ts +++ b/settings.ts @@ -43,7 +43,7 @@ const settings: Record = { "channel-22": "architech", "channel-35": "aura-team", "channel-38": "stargaze-governance", - "channel-38": "osmosis-nois-team", + "channel-41": "osmosis-nois-team", } }, "nois-testnet-005": { From 27410ac6db781751e613e0f21dfe20540ccf9873 Mon Sep 17 00:00:00 2001 From: hoangdv2429 Date: Thu, 18 Jan 2024 22:18:13 +0700 Subject: [PATCH 9/9] add mapping channels --- main.ts | 15 ++++++++++----- queries.ts | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/main.ts b/main.ts index 6c76ca6..7da5fef 100644 --- a/main.ts +++ b/main.ts @@ -6,7 +6,7 @@ import { HttpBatchClient, Tendermint34Client } from "npm:@cosmjs/tendermint-rpc" import * as promclient from "npm:prom-client"; import express from "npm:express@4.18.2"; import settings from "./settings.ts"; -import { communityPoolFunds, getContractUsage, totalSupply } from "./queries.ts"; +import { communityPoolFunds, getContractUsage, getIbcChannels, totalSupply } from "./queries.ts"; function printableCoin(coin: Coin): string { if (coin.denom?.startsWith("u")) { @@ -18,7 +18,7 @@ function printableCoin(coin: Coin): string { } -function mapChannelToDescription(chainId: string,channelId: string): string { +function mapChannelToDescription(chainId: string, channelId: string): string { // Default to a unknown if the channel is not found return settings[chainId].mappingChannels[channelId] || "unknown-proxy"; } @@ -125,17 +125,22 @@ if (import.meta.main) { tmClient, settings[chainId].gatewayAddr ); - + + // get an array of channels infos + const channelsInfo = await getIbcChannels(tmClient); + // array of customer data for (const customer of contractState.customers) { - const description = mapChannelToDescription(chainId, customer.channel_id); // Implement this mapping function + const description = mapChannelToDescription(chainId, customer.channel_id); + const connection = channelsInfo.filter(channel => channel.channelId === customer.channel_id); + customerUsageGauge.set( { channel: customer.channel_id, rpcEndpoint: rpcEndpoint, chainId: chainId, description: description, - address: customer.payment, + address: connection[0].counterparty?.portId?.slice(5) }, customer.requested_beacons ); diff --git a/queries.ts b/queries.ts index 0c69bcf..4a7a14f 100644 --- a/queries.ts +++ b/queries.ts @@ -6,6 +6,7 @@ import { QueryClient, setupBankExtension, setupDistributionExtension, + setupIbcExtension } from "npm:@cosmjs/stargate"; import { setupWasmExtension } from "npm:@cosmjs/cosmwasm-stargate"; @@ -45,3 +46,16 @@ export async function getContractUsage( } return res; } + +export async function getIbcChannels( + tmClient: TendermintClient +) { + const queryClient = QueryClient.withExtensions(tmClient, setupIbcExtension); + let res, filteredChannels; + try { + res = await queryClient.ibc.channel.channels(); + } catch (error) { + console.error(error); + } + return res.channels; +}