Skip to content

Commit

Permalink
feat: gather subnets metadata (#886)
Browse files Browse the repository at this point in the history
* feat: gather subnets metadata

Signed-off-by: David Dal Busco <[email protected]>

* feat: gather statistics

Signed-off-by: David Dal Busco <[email protected]>

* feat: merge also specified subnets

Signed-off-by: David Dal Busco <[email protected]>

* feat: fetch specialization

Signed-off-by: David Dal Busco <[email protected]>

---------

Signed-off-by: David Dal Busco <[email protected]>
  • Loading branch information
peterpeterparker authored Dec 5, 2024
1 parent 8e1018c commit 7e59d15
Show file tree
Hide file tree
Showing 4 changed files with 289 additions and 69 deletions.
22 changes: 11 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
"@dfinity/agent": "^2.1.3",
"@dfinity/auth-client": "^2.1.3",
"@dfinity/candid": "^2.1.3",
"@dfinity/cmc": "^4.0.2",
"@dfinity/cmc": "^4.0.2-next-2024-12-04",
"@dfinity/ic-management": "^6.0.1",
"@dfinity/identity": "^2.1.3",
"@dfinity/ledger-icp": "^2.6.4",
Expand Down
81 changes: 73 additions & 8 deletions scripts/cmc.subnets.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node

import { CMCCanister } from '@dfinity/cmc';
import { jsonReplacer } from '@dfinity/utils';
import { jsonReplacer, nonNullish } from '@dfinity/utils';
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { icAnonymousAgent } from './actor.mjs';
Expand All @@ -13,7 +13,12 @@ if (!existsSync(DATA_FOLDER)) {
mkdirSync(DATA_FOLDER, { recursive: true });
}

const listSubnets = async () => {
/**
* The list of subnets used by the CMC to create canisters randomly if no parameters are provided when creating a canister.
* Which means that these are subnets that can also be used if a developer wants to specify a particular subnet.
* @returns {Promise<Principal[]>}
*/
const listSubnetIds = async () => {
const agent = await icAnonymousAgent();

const { getDefaultSubnets } = CMCCanister.create({
Expand All @@ -24,14 +29,74 @@ const listSubnets = async () => {
return await getDefaultSubnets({ certified: true });
};

const writeSubnets = (subnets) => {
const subnetsList = subnets.map((principal) => ({
subnetId: principal.toText()
}));
/**
* The list of subnets supported by the CMC to create canisters only if specified,
* i.e., those subnets are not used when creating a canister in a random subnet.
* @returns {Promise<SubnetTypesToSubnetsResponse>}
*/
const listSpecifiedSubnetIds = async () => {
const agent = await icAnonymousAgent();

const { getSubnetTypesToSubnets } = CMCCanister.create({
agent,
canisterId: CMC_ID
});

writeFileSync(join(DATA_FOLDER, 'subnets.json'), JSON.stringify(subnetsList, jsonReplacer, 8));
return await getSubnetTypesToSubnets({ certified: true });
};

const subnets = await listSubnets();
/**
* The Dashboard API provides some information about the subnets, like their type and also statistics.
* @returns {Promise<any>}
*/
const listSubnets = async () => {
const response = await fetch('https://ic-api.internetcomputer.org/api/v3/subnets');

if (!response.ok) {
throw new Error('Fetching the Dashboard API failed!');
}

return await response.json();
};

const writeSubnets = (subnets) => {
writeFileSync(join(DATA_FOLDER, 'subnets.json'), JSON.stringify(subnets, jsonReplacer, 8));
};

// CMC.get_default_subnets
const subnetIds = await listSubnetIds();

// CMC.get_subnet_types_to_subnets
const { data: specifiedSubnetIds } = await listSpecifiedSubnetIds();

// Metadata from the dashboard API
const { subnets: subnetsMetadata } = await listSubnets();

const subnets = [
...subnetIds.map((subnetId) => ({ subnetId })),
...specifiedSubnetIds.flatMap(([specialization, subnetIds]) =>
subnetIds.map((subnetId) => ({ subnetId, specialization }))
)
].map(({ subnetId: sId, specialization }) => {
const subnetId = sId.toText();
const metadata = subnetsMetadata.find(({ subnet_id }) => subnet_id === subnetId);

return {
subnetId,
...(nonNullish(specialization) && { specialization }),
...(nonNullish(metadata) && {
// The dashboard was instructed long ago to display verified_application as application
type: metadata.subnet_type === 'verified_application' ? 'application' : metadata.subnet_type,
canisters: {
stopped: metadata.stopped_canisters,
running: metadata.running_canisters
},
nodes: {
up: metadata.up_nodes,
total: metadata.total_nodes
}
})
};
});

writeSubnets(subnets);
Loading

0 comments on commit 7e59d15

Please sign in to comment.