Fetching latest headlines…

Dev

Who actually holds Litecoin? A rich list and holder distribution in 30 lines of Python

Dev.toUnited States · NORTH AMERICA

"Who holds the coins" sounds like a simple question. Answering it yourself is not. You need the whole UTXO set (every unspent output on the chain), grouped by address, refreshed as blocks arrive. For...

3 views0 likes0 comments

"Who holds the coins" sounds like a simple question. Answering it yourself is not. You need the whole UTXO set (every unspent output on the chain), grouped by address, refreshed as blocks arrive. For Litecoin that is about 54 million outputs. For Bitcoin it is more.

I run full nodes and a UTXO index for several chains, so I put those numbers behind a plain JSON API. This post uses it to answer the question for Litecoin. Everything below is real output from today.

One call

curl -H "X-API-Key: $OLENZA_KEY" https://explorer.olenza.io/api/v1/ltc/stats

The answer has several parts. Two of them matter here:

  • distribution: how many addresses fall into each balance band, and how many coins those bands hold.
  • richlist: the largest addresses, with each one's share of all coins.

Every part says which block it was computed at (as_of.height), so you know how fresh it is. Amounts are strings in the smallest unit (litoshi, 10⁻⁸ LTC). They are strings so that big totals don't lose precision in JavaScript.

The script

import json, os, urllib.request

KEY = os.environ["OLENZA_KEY"]

def get(path):
    req = urllib.request.Request("https://explorer.olenza.io/api/v1/" + path,
                                 headers={"X-API-Key": KEY, "User-Agent": "holders-example/1.0"})
    return json.load(urllib.request.urlopen(req))

stats = get("ltc/stats")
dist = stats["distribution"]["data"]
dec = 10 ** dist["decimals"]
total = int(dist["total_value"])

print(f"{dist['nonzero_addresses']:,} addresses hold coins")
for b in dist["bands"]:
    share = int(b["value"]) / total
    print(f"{b['label']:>14}  {b['addresses']:>10,} addresses  {share:6.1%} of coins")

top = stats["richlist"]["data"]["top"]
top10 = sum(t["share"] for t in top[:10])
print(f"\ntop 10 addresses: {top10:.1%} of all coins")
for t in top[:3]:
    print(f"#{t['rank']} {t['address']}  {int(t['value']) / dec:,.0f} LTC")

What it prints

9,116,927 addresses hold coins
       < 0.001   4,293,546 addresses    0.0% of coins
  0.001 – 0.01   1,274,631 addresses    0.0% of coins
    0.01 – 0.1   1,274,578 addresses    0.1% of coins
       0.1 – 1   1,295,021 addresses    0.6% of coins
        1 – 10     721,005 addresses    2.9% of coins
      10 – 100     216,437 addresses    8.1% of coins
      100 – 1k      36,795 addresses   12.2% of coins
      1k – 10k       4,266 addresses   14.4% of coins
    10k – 100k         535 addresses   18.3% of coins
        ≥ 100k         113 addresses   43.4% of coins

top 10 addresses: 14.0% of all coins
#1 MQd1fJwqBJvwLuyhr17PhEFx1swiqDbPQS  2,412,949 LTC
#2 ltc1qr07zu594qf63xm7l7x6pu3a2v39m2z6hh5pp4t  2,205,009 LTC
#3 ltc1qe8akpjkr822kvexkgqcc5msew0uwj8xv0ygp5l  1,102,168 LTC

113 addresses hold 43% of all Litecoin. Almost half of all addresses hold less than 0.001 LTC each.

Reading it honestly

An address is not a person. The biggest addresses are almost always exchanges, holding coins for many customers. One person can also spread coins over hundreds of addresses. So this is a picture of how coins sit on the chain, not of who is rich.

Two Litecoin details are handled for you:

  • MWEB. Coins moved into MimbleWimble Extension Blocks sit in one output that no one owns, and the holders behind it are private by design. That output is reported on its own under special, not ranked as the "largest holder".
  • Old pay-to-pubkey outputs are counted under the normal address of the same key, so one owner is not split in two.

Other chains and other questions

The same /stats call works for Bitcoin, Dogecoin, Bitcoin Cash and eCash. It also returns coin age (hodl: how long coins have been sitting unmoved), daily fees, and which mining pools found recent blocks. Ethereum has its own version, with ETH and token holders.

If you just want to look rather than code, the same data is on a page: explorer.olenza.io/ltc/stats.

A free key is at account.olenza.io. The same key also works for raw node RPC on nine chains, which I wrote about in my previous post.

Comments (0)

Sign in to join the discussion

Be the first to comment!