Marketcap of SNS tokens

Seeking guidance on obtaining the market cap of a token. After exploring the ledger and governance canisters, I couldn’t locate a method providing the total circulating supply or related data. In the ledger canister, there’s the icrc1_total_supply method, but it seems to provide the total number of tokens, not specifically the circulating supply. Is my understanding correct?
and from where we can get marketcap?

1 Like

Yes, ICRC1_total_supply returns the total number of tokens on all accounts except for the minting account. The easiest way to cross-reference on the IC Data Dashboard is by referencing the Total Supply chart on the main SNS page and then clicking on the Ledger Canister ID → Run ICRC1_total_supply function.

For example, for ELNA, check the ELNA Total Supply chart on their SNS page and then click on their corresponding Ledger Canister under ELNA AI Canisters. On the ELNA AI Ledger Canister page, click on icrc1_total_supply. It should be the same number listed in the Total Supply chart.

The easiest way to check the market cap of SNS tokens is to use ICP Coins or ICPSwap Token List.

These SNS tokens are also on CoinmarketCap:

Thanks for the links and explaination but i was looking for the source of market supply. on dashboard i can see all the information but from where dashboard is getting the information. There must be some canister which have these information like treasury supply and how many tokens are in circulation etc.

An approach is to take the total supply minus tokens in wallets that tokens were initially minted to (before the first transfer. This includes treasury).

Using the IC Data Dashboard

For the PANDA token of ICPandaDAO, you would take the PANDA Total Supply on their main page and then subtract it with the total amount of PANDA before the first “Transfer”.

Looking at their first transactions, the first Transfer was at index 15:

Therefore, the number of tokens in wallets that were initially minted would include the current balances of these accounts listed from index 0 to 14.

You would then click on the current principal ID and check their current balance. For example, principal dwv6s-6aaaa-aaaaq-aacta-cai with subaccount 0818a39651f7c9fa5c8af7241c7032a876f98f12a6fb5082bc34a1dae87d37ad still has 5,000,000 PANDA.

Programmatically:

  • Total Supply - Call icrc1_total_supply (from the ledger canister)

  • The Principals and subaccount before the first transfer- Iterate through get_blocks (from the index canister) starting with start: 0 until the result no longer lists record { "op"; variant { Text = "mint" } };

In the to section, you will get an array of the Principal and subaccounts as blob representations. There are ways to convert the blob representation to a Principal. For example, the Motoko library Principal library.

  • Balance of Principals and subaccount before the first transfer - Call icrc1_balance_of (from the index canister) passing in the principal and subaccount to get the current balance of these wallets

IcpCoins, for example, calculates the circulating supply as following:

circulating_supply = total_supply - treasury_balance

The total_supply comes from calling the icrc1_total_supply() method from a SNS Ledger canister.

Now the treasury_balance is a bit more complex:

  1. you have to calculate the sub-account of the treasury using the following JS code (untested):
    const subAccount = new Uint8Array(sha256.create().update([0x12, ...new TextEncoder().encode("token-distribution"), ...SNS_governance_canister_principal.toUint8Array()]).array())
  2. call the SNS Ledger canister icrc1_balance_of() method passing the SNS governance canister principal and the sub-account calculated at the step 1 above

References:

  1. ic/rs/nervous_system/common/src/ledger.rs at 69cd381ecf8c183759f256861e6a817b124af5b8 · dfinity/ic · GitHub
  2. defi_aggregator/src/main.mo at 4659c3592ababa5e8c94257e26161773e43090df · Neutrinomic/defi_aggregator · GitHub
1 Like

thanks for detailed answer. i’m not able to reproduce it can you please help.
this is the code i’m trying to execute:

import { Principal } from "@dfinity/principal";
import { sha256 } from "js-sha256";

// governance canister id of GOLD DAO
const GOVERNANCE_CANISTER_ID = "tr3th-kiaaa-aaaaq-aab6q-cai";

const subAccount = new Uint8Array(
  sha256
    .create()
    .update([
      0x12,
      ...new TextEncoder().encode("token-distribution"),
      ...Principal.fromText(GOVERNANCE_CANISTER_ID).toUint8Array(),
    ])
    .array()
);

console.log("sub account: ", Principal.fromUint8Array(subAccount).toHex());

testing for GoldDAO (random SNS from dashboard, it shows treasury amount on dashboard).
this is the ledger canister of it: Canister: Gold DAO Ledger - ICP Dashboard

above function give me this subaccount id: “BA84E75F566A87AC0FCBB07AAC5518DFD36193C8050F34ED67B3F00123C4FD93” and this is the governance canister: tr3th-kiaaa-aaaaq-aab6q-cai

why i’m getting balance as 0.
i tried same with few other SNS also, same result getting 0 balance only.
looks like i’m making some minor error but not able to identify, can you please help. thanks.

Ah, try adding the nonce.

Try this code:

import { Principal } from "@dfinity/principal";
import { sha256 } from "js-sha256";

const GOVERNANCE_CANISTER_ID = "tr3th-kiaaa-aaaaq-aab6q-cai";

function toBytesUint64(num) {
  const buffer = new ArrayBuffer(8);
  const view = new DataView(buffer);
  view.setBigUint64(0, BigInt(num));
  return Array.from(new Uint8Array(buffer));
}

const subAccount = new Uint8Array(
  sha256
    .create()
    .update([
      0x12,
      ...new TextEncoder().encode("token-distribution"),
      ...Principal.fromText(GOVERNANCE_CANISTER_ID).toUint8Array(),
      ...toBytesUint64(0)
    ])
    .array()
);

console.log("sub account: ", Principal.fromUint8Array(subAccount).toHex());

Here is a test link to confirm: GoldDAO Subaccount - Replit

This returns subaccount 7776d299b4a804a14862b02bff7b74d1b956e431f5f832525d966d67ff3d7ce8 for canister tr3th-kiaaa-aaaaq-aab6q-cai (GoldDAO Governance Canister).

It should match the GLDGov Treasury account linked from GLDGov Treasury to here.

Hope that helps!

2 Likes

@jaesharma FYI, we recommend that SNS projects use this formula to calculate circulating supply. This formula aligns with CMC’sdefinition and if using it, projects should have no problem verifying their circulating supply with CMC. Verifying circulating supply is critical to a project’s CMC ranking.

Please let us know if you have any questions or help.

hey @jennifertran

Shouldn’t it be: circulating_supply = total_supply - treasury_balance - balance_in_neurons where balance in neurons is the sum of all neurons with dissolve delay > 0 ?

In theory, you can use this formula as well. It does add additional complexity to the formula.

The formula that we proposed above is a simple definition that captures CMC’s definition.

Fair enough, but for Dragginz we can’t use this as we’ve minted more tokens after the initial SNS.