Skip to main content

Shrinemaps

A token's largest holders as a map of bubbles, linked where wallets belong together and grouped into clusters: wallets that are likely one hand. Put it on your own site with one iframe.

8.4%cluster: 14.1%same funderbundlerKOL5.2%Holder mapone bubble per holder, sized by its share of the supply

Add it to your page​

Paste the frame and put the token's mint in the address:

<iframe
src="https://maps.shrine.trade/embed/sol/<mint>"
title="Holder map"
width="100%"
height="600"
style="border:0"
loading="lazy"
allow="clipboard-write"
referrerpolicy="no-referrer"
sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox"
></iframe>

Or ask the API for the frame of a token, ready to paste:

const res = await fetch("https://sol.shrine.trade/api/maps/<mint>/embed");
const { url, page, iframe } = await res.json();
document.querySelector("#holders").innerHTML = iframe;
{
"mint": "<mint>",
"url": "https://maps.shrine.trade/embed/sol/<mint>",
"page": "https://maps.shrine.trade/sol/<mint>",
"iframe": "<iframe src=\"https://maps.shrine.trade/embed/sol/<mint>\" …></iframe>"
}

page is the same map as its own page on maps.shrine.trade, for a "full map" link. No key is needed for either.

OptionValues
?n=50, 100, 200How many of the largest holders the map shows at first. Default 100; the viewer can change it in the map.

Size. The map fills its frame: give it the full width of your column and at least 480 px of height; 600 suits a token page. It works on phones too.

Reading the map​

  • Bubbles. One per holder, sized by its share of the supply. Hover or tap one for the wallet, its share and how it is linked.
  • Links. A line joins two wallets that belong together: one sent the other its first SOL, both got their first SOL from the same address (a small funder dot between them), both bought in the launch slot with the dev, or both traded through a bundler (a red bundler dot).
  • Clusters. Wallets linked together share a colour and count as one cluster: likely one hand. The side panel lists the clusters with their combined share.
  • Known traders. KOLs show as their picture with their name and share.
  • Exchanges. An exchange funds everyone, so it is shown as a label, never as a link.
  • Live. The map refreshes every few seconds while it is open.

Holdings count the token's trades Shrine has seen: a token that launched before Shrine started is marked partial. Links fill in as more of the token's wallets are looked at, so a fresh token's map grows over its first minutes.

The advanced bundle detection embed comes with the Developer plan.

Talk to the map (optional)​

The map and your page can exchange a few messages with postMessage. It tells you only public facts: which token it shows, and which wallet someone clicked.

FromMessageMeaning
map{ type: "shrinemaps:ready" }The map has loaded.
map{ type: "shrinemaps:coin", mint, symbol }The token it shows, for your page's title.
your page{ type: "shrinemaps:host" }Your page opens wallets itself: the map's wallet button then reads "Open the wallet" and tells you which one.
map{ type: "shrinemaps:wallet", wallet }Someone asked to open this wallet.
const MAPS = "https://maps.shrine.trade";
const frame = document.querySelector(`iframe[src^="${MAPS}/embed/"]`);

window.addEventListener("message", (e) => {
if (e.origin !== MAPS || e.source !== frame.contentWindow) return;
const m = e.data;
if (m?.type === "shrinemaps:ready") frame.contentWindow.postMessage({ type: "shrinemaps:host" }, MAPS);
if (m?.type === "shrinemaps:coin") document.title = `${m.symbol} holders`;
if (m?.type === "shrinemaps:wallet") window.open(`https://solscan.io/account/${m.wallet}`, "_blank", "noopener");
});

Safe to embed​

  • Its own scripts only. The frame runs Shrinemaps' code and reads Shrine's data; it cannot change or navigate your page.
  • Your address stays yours. With referrerpolicy="no-referrer" the map never learns which page it is on.
  • Nothing to sign. No wallet connection, no account and no buttons that act for your visitors.