Labels

Have you ever made a query on Dune where you get a list of addresses, only to stop and wonder what’s behind these beautiful, random hexadecimal encoded strings? So have we.

Address labels is a feature on Dune where you as a user can add, update and query labels for any address.

What is a label?

A label is a piece of metadata about an address, a tag or metadata if you will. It comes in the form of a key-value pair. The key is the label type, and the value the label name.

Browse addresses and and labels at the labels page.

What labels looks like

Check out this dashboard for examples on what can be created with labels.

Address label examples

The address 0xD551234Ae421e3BCBA99A0Da6d736074f22192FF can be labeled like this:

type

name

owner

binance

wallet type

exchange

The address is controlled by the exchange Binance.

The address 0xe65040f61701940b62e18da7a53126a58525588b can be labeled like this:

type

name

dapp usage

uniswap user

activity

dex trader

The address in the past interacted with Uniswap.

You are free to come up with both new types and label names, as labels on Dune are open ended and crowd sourced.

Adding labels

There are two ways to add labels:

1. Directly to an address via our labels page

Good for specific labels like “this is a binance wallet”.

2. Via a Dune query

Use Dune queries to label addresses. A very powerful and scalable way to add labels like “all these addresses used Uniswap”, and much much more.

Please see our Github for examples of labels created with queries and PR in your own!

Examples of what you can do:

  • Label all addresses that used a certain dapp

  • Label all addresses that hold a certain amount of a token

  • Label all addresses that use a dapp more than X times per month

  • Label all addresses that sent money to Binance

You could also do more novel and involved things around user patterns like who did arbitrage trades or profited from flash loans and so much more.

Note that there might be a few minutes delay from adding the label on duneanalytics.com until you can query it in SQL.

The labels table

Labels are stored in the new labels.labels table which has the following schema:

column name

data type

description

id

int

incrementing integer

address

bytea

the address of a contract or wallet this label describes

label

text

the label

type

text

label type

author

text

the username of the user who created this label

source

text

the source of this label, autopopulated by dune

updated_at

timestamptz

the last time this label was changed

Using labels

Note that this table holds multiple rows per address, and therefore joins against it can be tricky to get right. For that reason we’ve made the convenient function:

labels.get(address bytea, type text default null) RETURNS text[]

which we anticipate will be the primary way to use labels. See examples below.

Typically if you do a query that returns address you can use labels.get(address) to get all labels for that address independent of label type. If you want to see labels of the type owner you can do labels.get(address, 'owner'). You can also pass this function several label types you want included like: labels.get(address, 'owner', 'project').

We’ve also added the function labels.url(address bytea). Pass that function an address from your query and your results table will contain a clickable link to for instance:

https://duneanalytics.com/ethereum/address/0xD551234Ae421e3BCBA99A0Da6d736074f22192FF

Usecase: I want to display labels for a list of addresses

We encourage you to run these queries in Dune while you read this

Say you’re looking at the top 10 traders of DAI across all dexes last 24 hours:

SELECT trader_a, SUM(token_a_amount)
FROM dex.trades
WHERE token_a_symbol = 'DAI'
AND block_time > now() - interval '24 hours'
GROUP BY 1
ORDER BY 3 DESC
LIMIT 10;

If you want to have labels for these addresses simply alter the trader_a column to labels.get(trader_a).

Note: In the examples below --- represents lines removed, and +++ lines added.

SELECT trader_a, labels.get(trader_a) as label, SUM(token_a_amount)
FROM dex.trades
WHERE token_a_symbol = 'DAI'
AND block_time > now() - interval '24 hours'
and not labels.get(trader_a) isnull
GROUP BY 1
ORDER BY 2 DESC
LIMIT 100;

Now you’ve replaced the addresses with lists of all labels for trader_a. Sometimes you’re only interested in a subset of labels: labels.get accepts an optional list of type names which filter the type of labels you get. Say you’re only interested in ‘activity’ labels:

SELECT trader_a, labels.get(trader_a, 'activity') as label, SUM(token_a_amount)
FROM dex.trades
WHERE token_a_symbol = 'DAI'
AND block_time > now() - interval '24 hours'
and not labels.get(trader_a) isnull
GROUP BY 1
ORDER BY 2 DESC
LIMIT 100;

Of course you can also show the address, and filter for multiple label types

SELECT trader_a, labels.get(trader_a, 'activity', 'project', 'contract_name') as label, SUM(token_a_amount)
FROM dex.trades
WHERE token_a_symbol = 'DAI'
AND block_time > now() - interval '24 hours'
and not labels.get(trader_a) isnull
GROUP BY 1
ORDER BY 2 DESC
LIMIT 100;

You can also use labels.url to make the addresses clickable:

SELECT labels.url(trader_a), labels.get(trader_a, 'activity') as labels, SUM(token_a_amount)
FROM dex.trades
WHERE token_a_symbol = 'DAI'
AND block_time > now() - interval '24 hours'
GROUP BY 1, 2
ORDER BY 3 DESC
LIMIT 10;

This way people who look at your dashboard can easily contribute even better labels to it!

Usecase: I want to filter my query by labels that exist.

In this usecase you wouldn’t want to use labels.get, because it can be slow to operate with. Instead you’ll use the fantastic EXISTS function in SQL.

As an example: you’re querying Uniswap, but are interested in the behavior of users who have traded previously on 1inch. Here’s how you’d go about that:

SELECT "to"
FROM uniswap_v2."Pair_evt_Swap"
WHERE EXISTS(
SELECT *
FROM labels.labels
WHERE address="to"
AND type='dapp usage'
AND name='1inch user'
)
LIMIT 10;

The above query will give you 10 address that has swapped on Uniswap and traded on 1inch.

Of course, you can use the two patterns in conjunction! If you are interested for labels on those addresses, go ahead and use labels.get in addition to the WHERE EXISTS pattern:

--- SELECT "to"
+++ SELECT "to", labels.get("to")
FROM uniswap_v2."Pair_evt_Swap"
WHERE EXISTS(SELECT * FROM labels.labels WHERE address="to" AND type='dapp usage' AND name='1inch user')
LIMIT 10;

There you have it: you see addresses that traded on both Uniswap and 1inch and all associated address labels.