{"id":14561818,"url":"https://github.com/sambacha/dune-snippets","last_synced_at":"2025-04-09T14:13:57.747Z","repository":{"id":45710479,"uuid":"259121765","full_name":"sambacha/dune-snippets","owner":"sambacha","description":"dune snippets is a collection of sql queries for duneanalytics.com / Google BigQuery ","archived":false,"fork":false,"pushed_at":"2024-04-16T15:41:36.000Z","size":25031,"stargazers_count":148,"open_issues_count":4,"forks_count":20,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-02T08:47:57.557Z","etag":null,"topics":["analytics","bigquery","crypto","defi","dune","eth","ethereum","orderbok","solidity","sql","tick-data"],"latest_commit_sha":null,"homepage":"","language":"PLpgSQL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sambacha.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-26T20:01:46.000Z","updated_at":"2025-03-29T20:58:34.000Z","dependencies_parsed_at":"2025-01-15T18:28:51.535Z","dependency_job_id":null,"html_url":"https://github.com/sambacha/dune-snippets","commit_stats":{"total_commits":80,"total_committers":7,"mean_commits":"11.428571428571429","dds":"0.23750000000000004","last_synced_commit":"1b7e4b015ffcbc7510fc659ffde83a59fe126e03"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Fdune-snippets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Fdune-snippets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Fdune-snippets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Fdune-snippets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sambacha","download_url":"https://codeload.github.com/sambacha/dune-snippets/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248054193,"owners_count":21039952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","bigquery","crypto","defi","dune","eth","ethereum","orderbok","solidity","sql","tick-data"],"created_at":"2024-09-07T02:01:00.041Z","updated_at":"2025-04-09T14:13:57.716Z","avatar_url":"https://github.com/sambacha.png","language":"PLpgSQL","funding_links":[],"categories":["analytics"],"sub_categories":[],"readme":" \u003cimg src=\"https://i.imgur.com/RURn3Pa.png\" align=\"center\" width=\"350\"\u003e\n\n## Dune Snippets\n\n\u003e**Warning**     \n\u003e Abstractions are now 'deprecated', We encourage users to start making the transition to v2 abstractions aka spellbook.\n\u003e [see https://github.com/duneanalytics/spellbook/pull/1424](https://github.com/duneanalytics/spellbook/pull/1424)\n\n\u003e pr/1424\n\u003e Move Dune's v1 abstractions into the archive folder deprecated-dune-v1-abstractions.\n\u003e Intermediate datasets created by v1 abstractions are still accessible on dune.com. We encourage users to start making the transition to v2 abstractions aka spellbook.\n\n\u003e Rename repo from abstractions to spellbook\n\n\n---\n\n\u003cbr /\u003e\n\n![Autoformat SQL](https://github.com/sambacha/dune-snippets/workflows/Autoformat%20SQL/badge.svg)\n\n\u003e Snippets of both Dune user submissions and my own. All queries are linted through a GitHub Actions CI workflow\n\n\u003cbr /\u003e\n\n[source from Dune Analytics HackMD](https://hackmd.io/k71ZUSTxQVKGqOcvR6OXnw)\n\n### Contents\n\n- [📑 Documentation](#---documentation) - [👇 Top links](#---top-links) - [📚 Need some help getting started with queries?](#---need-some-help-getting-started-with-queries-)\n  - [Dune Analytics TLDR](#dune-analytics-tldr)\n    - [1. Query human-readable smart contract data with PostgreSQL 🔍](#1-query-human-readable-smart-contract-data-with-postgresql---)\n    - [2. Visualize your findings 📊](#2-visualize-your-findings---)\n    - [3. Create dashboards and share them with public links 🌎](#3-create-dashboards-and-share-them-with-public-links---)\n    - [4. Explore analysis created by other community members. You can fork any query by the click of a button. 👨‍👩‍👦‍👦](#4-explore-analysis-created-by-other-community-members-you-can-fork-any-query-by-the-click-of-a-button------------)\n    - [👉 Create a user for free at [duneanalytics.com](https://www.duneanalytics.com/)](#----create-a-user-for-free-at--duneanalyticscom--https---wwwduneanalyticscom--)\n  - [Table of contents](#table-of-contents)\n- [🗂 Data tables](#---data-tables)\n  - [Decoded smart contract data](#decoded-smart-contract-data)\n  - [Abstractions/table views](#abstractions-table-views)\n    - [Raw Ethereum data](#raw-ethereum-data)\n  - [Centralised exchanges trading data](#centralised-exchanges-trading-data)\n- [👨‍🏫 Tips for querying the data](#------tips-for-querying-the-data)\n  - [Use view abstractions and tables](#use-view-abstractions-and-tables)\n  - [Using Inline Ethereum addresses](#using-inline-ethereum-addresses)\n  - [Quote camel case column and table names](#quote-camel-case-column-and-table-names)\n  - [Remove decimals](#remove-decimals)\n  - [Use `date_trunc` to get time](#use--date-trunc--to-get-time)\n  - [How to get USD price](#how-to-get-usd-price)\n  - [Token symbols](#token-symbols)\n- [🏷 Address Labels](#---address-labels)\n  - [🪧 What is a label?](#---what-is-a-label-)\n  - [🖼 What labels looks like](#---what-labels-looks-like)\n    - [Address label examples](#address-label-examples)\n  - [📥 Adding labels](#---adding-labels)\n    - [1. Directly to an address via our [labels page](https://duneanalytics.com/hagaetc/labels)](#1-directly-to-an-address-via-our--labels-page--https---duneanalyticscom-hagaetc-labels-)\n    - [2. Via a Dune query](#2-via-a-dune-query)\n  - [🗄 The labels table](#---the-labels-table)\n  - [🧑‍🔧 Using labels](#------using-labels)\n  - [📜 Usecase: I want to display labels for a list of addresses](#---usecase--i-want-to-display-labels-for-a-list-of-addresses)\n  - [🧼 Usecase: I want to filter my query by labels that exist.](#---usecase--i-want-to-filter-my-query-by-labels-that-exist)\n- [🧐 Understanding data decoding in Dune Analytics](#---understanding-data-decoding-in-dune-analytics)\n  - [What contracts have decoded data?](#what-contracts-have-decoded-data-)\n    - [Decoded data](#decoded-data)\n    - [Abstractions and views](#abstractions-and-views)\n    - [A few handy queries to explore decoded tables](#a-few-handy-queries-to-explore-decoded-tables)\n  - [Scalable decoding across contracts](#scalable-decoding-across-contracts)\n    - [Contracts with the same bytecode](#contracts-with-the-same-bytecode)\n    - [Interfaces](#interfaces)\n  - [How Dune handles Proxy contracts](#how-dune-handles-proxy-contracts)\n- [📬 Get any smart contract decoded](#---get-any-smart-contract-decoded) - [We have decoded data for the most popular smart contract projects. Head to duneanalytics.com/decode if you have a request for decoding of data.](#we-have-decoded-data-for-the-most-popular-smart-contract-projects-head-to-duneanalyticscom-decode-if-you-have-a-request-for-decoding-of-data)\n- [👩‍🏭 Change log](#------change-log) - [[August 2020](https://hackmd.io/YOP3YIgaRAejTPE190sOjw?view) - USD prices for more assets, token decimals on `prices.usd` table](#-august-2020--https---hackmdio-yop3yigaraejtpe190sojw-view----usd-prices-for-more-assets--token-decimals-on--pricesusd--table) - [[March 2020](https://hackmd.io/YOP3YIgaRAejTPE190sOjw?view#March-2020) - block_time denormalization, traces.success and more](#-march-2020--https---hackmdio-yop3yigaraejtpe190sojw-view-march-2020----block-time-denormalization--tracessuccess-and-more) - [[January 2020](https://hackmd.io/YOP3YIgaRAejTPE190sOjw?view) - ERC20 transfer table, Fallback decoding and more](#-january-2020--https---hackmdio-yop3yigaraejtpe190sojw-view----erc20-transfer-table--fallback-decoding-and-more) - [[October 2019](https://hackmd.io/YOP3YIgaRAejTPE190sOjw?view#October-2019) - New data structure](#-october-2019--https---hackmdio-yop3yigaraejtpe190sojw-view-october-2019----new-data-structure)\n- [👉 Some sample queries](#---some-sample-queries)\n  - [Growth rate](#growth-rate)\n  - [Users and amount over a trailing period](#users-and-amount-over-a-trailing-period)\n  - [Filter query by an address in the interface](#filter-query-by-an-address-in-the-interface)\n  - [Circulating supply over time of a token with mint/burn functions](#circulating-supply-over-time-of-a-token-with-mint-burn-functions)\n  - [Circulating supply over time with mint/burn from `0x000...` address](#circulating-supply-over-time-with-mint-burn-from--0x000--address)\n  - [USD value of token utilised for an event](#usd-value-of-token-utilised-for-an-event)\n  - [USD trading volume per token over time](#usd-trading-volume-per-token-over-time)\n  - [USD price for a token from Uniswap](#usd-price-for-a-token-from-uniswap)\n  - [Token (and USD value) per token over time for an address](#token--and-usd-value--per-token-over-time-for-an-address)\n- [🤕 Known issues](#---known-issues)\n  - [Function overloading](#function-overloading)\n\n[source from Dune Analytics HackMD](https://hackmd.io/k71ZUSTxQVKGqOcvR6OXnw)\n\n## 📑 Dune Documentation\n\nHere are some tips and tricks on how to get started with the data and interface.\n\n#### 👇 Top links\n\n- Create a user for free at [duneanalytics.com](https://www.duneanalytics.com/) 👍\n\n- Submit contracts for decoding at [duneanalytics.com/decode](https://www.duneanalytics.com/decode) 📥\n\n- Browse curated dashboards, queries and data tables for top projects [duneanalytics.com/projects](duneanalytics.com/projects) or [add a project](https://github.com/duneanalytics/projects) via a simple markdown file 🗂\n\n- Find and create data abstractions via our public [Github](http://github.com/duneanalytics/) 💻\n\n- Can't find what you're looking for? Ask our community on our [Discord server](https://discord.gg/ErrzwBz) or email us at support@duneanalytics.com 👩‍🔧\n\n#### 📚 Need some help getting started with queries?\n\n- See [this 20 min intro video](https://www.youtube.com/watch?v=AWlwO9T8dkY) on how to create queries on Dune 📹\n\n- Here's a good [getting started article](https://duneanalytics.com/blog/get-started-guide), even if you don't know SQL 🗒\n\nMany non-technical users have mastered Dune with no prior codeing experience. Dune is powered by the very common database PostgreSQL and you can find a ton of resources by searching online, both for getting started with SQL (udemy, codecademy etc.) and for any query specific question 🧠\n\n## Dune Analytics TLDR\n\n#### 1. Query human-readable smart contract data with PostgreSQL 🔍\n\n#### 2. Visualize your findings 📊\n\n#### 3. Create dashboards and share them with public links 🌎\n\n#### 4. Explore analysis created by other community members. You can fork any query by the click of a button. 👨‍👩‍👦‍👦\n\n#### 👉 Create a user for free at [duneanalytics.com](https://www.duneanalytics.com/)\n\n## Table of contents\n\n[TOC]\n\n# 🗂 Data tables\n\nYou can currently query data from **Ethereum mainnet** and **xdai**.\n\nTo query xDai data change the data source in the dropdown list above the data table list on the query page.\n\n- [Decoded smart contract data](#decoded-data)\n- [Abstractions/table views](#abstractions/table-views)\n- [Centralised exchanges trading data](#Centralised-exchanges-trading-data)\n- [Raw Ethereum data](#raw-ethereum-data)\n\nThe most commonly used tables are\n\n- **Event and call data** for each project where you typically get the action that occured in the smart contract. Simply search for project name to find the relevant tables.\n- **Abstractions/view tables** containing abstractions that makes various data very straight forward to query. Examples\n  - `dex.trades`\n  - `lending.borrow`, `lending.collateral_change`, `lending.repay`\n  - `stablecoin.transfer`, `stablecoin.mint`, `stablecoin.burn`\n  - See the full list and add your own via our [Github](https://github.com/duneanalytics/abstractions)\n- **prices.usd** which gives you USD price of various assets per minute. Typically joined on minute with the event data and multiplied by the on-chain value (trade, transfer etc).\n- **erc20.tokens** gives you contract address, symbol and number of decimals for popular tokens. Token value transfers are then divided by `10` to the power of `decimals` from this table.\n- **Ethereum transactions** to get ETH transfers. Typically join with event on `ethereum.transactions.hash = evt_tx_hash`.\n\n### Decoded smart contract data\n\nInstead of working with the traces, logs, and receipts, Dune decodes smart contract activity into nice human-readable tables. See the [this section for more info](#🧐-Understanding-data-decoding-in-Dune-Analytics).\n\nSubmit contracts for decoding at [duneanalytics.com/decode](duneanalytics.com/decode).\n\n### Abstractions/table views\n\nThese are the cleanest and easiest to use tables on Dune. We have abstractions for dex trades in the `dex.trades` table.\n\nYou can also search for `view` in our table list to find all the various views.\n\nTogether with various teams and community members we've created table views that make the blockchain data even easier to work with. This typically entails removing decimals for ETH and token transfers, adding human readable symbols, joining relevant tables together, adding USD value of events and more.\n\nYou can always see the underlying tables derived directly from the blockchain if you need more details or are curious about how the views are created: [check out our Github](https://github.com/duneanalytics/abstractions), you can even do a pull request to create your own abstractions.\n\n#### Raw Ethereum data\n\n- Blocks\n- Logs\n- Transactions\n- Receipts\n- Traces\n\nYou probably won't use this too much when doing analysis with Dune (see [decoded data](#decoded-data)), but it's always nice to have just in case.\n\nYou can [click here](https://ethereum.stackexchange.com/questions/268/ethereum-block-architecture) to learn more about Ethereum's data structure, but again it's not really needed for using Dune.\n\n### Centralised exchanges trading data\n\nToken volume is great, but more often than not you want to know the USD value of smart contract activity.\n\nYou can easily get and join that information with onchain data using the data we pull from the coincap API. See how to use it below.\n\n- `prices.usd` - assets on Ethereum\n  - contract_address\n  - price\n  - minute\n  - symbol (ticker)\n\nNote that `WETH` can be used for ETH price.\n\n- `prices.layer_1usd` - native layer 1 assets\n  - price\n  - minute\n  - symbol (ticker)\n\nPrice is the volume-weighted price based on real-time market data every minute, translated to USD.\n\nThe data is fetched from the [Coinpaprika API](https://coinpaprika.com/api/).\n\n# 👨‍🏫 Tips for querying the data\n\nYou can interact with the [data tables](#Data-tables) through our interface at [duneanalytics.com](https://www.duneanalytics.com/).\n\nTo create a new query you simply click Create -\u003e Query\n\n![](https://i.imgur.com/FVLbPef.png)\n\nOn your left you can select which database you want to use in the dropdown list and then see the data tables in the window. Just search for the project you are interested in working with.\n\n### Use view abstractions and tables\n\nThe easiest way to do great analysis with Dune Analytics is to use prepared views named `namespace.view_` or abstraction tables like `dex.trades`. All the view tables are cleaned and contains data and metadata (like human readable token symbols) that make them very straight forward to query.\n\n### Using Inline Ethereum addresses\n\nIn Dune Ethereum addresses are stored as postgres bytearrays which are encoded with the `\\x` prefix. This differs from the customary `0x` prefix. If you'd like to use an inline address, say to filter for a given token, you would do\n\n```sql\nWHERE token = '\\x6b175474e89094c44da98b954eedeac495271d0f'\n```\n\nwhich is simply short for\n\n```sql\nWHERE token = '\\x6b175474e89094c44da98b954eedeac495271d0f'::bytea\n```\n\n### Quote camel case column and table names\n\nColumn and table names are mostly taken directly from smart contract ABIs, with no modification. Since most smart contracts are written in Solidity, and written with a camelCased naming convention, so is many of Dune's table and column names. Postgres requires you to quote columns and tablenames that are case sensitive:\n\n```SQL\nSELECT “columnName”\nFROM projectname.”contractName_evt_EventName”\nLIMIT 10\n```\n\nIn Postgres, double quotes are reserved for tables and columns, whereas single quotes are reserved for values:\n\n```SQL\nSELECT “columnName”\nFROM projectname.”contratName_evt_eventName”\nWHERE contract_address = '\\x6B175474E89094C44Da98b954EedeAC495271d0F'\nLIMIT 10\n```\n\nSchemas are always lowercase in Dune.\n\n### Remove decimals\n\nEther transfers and most ERC-20 tokens have 18 decimal places. To get a more human readable number you need to remove all the decimals. The table `erc20.tokens` gives you contract address, symbol and number of decimals for popular tokens. Token value transfers are then divided by 10 to the power of decimals from this table:\n\n`transfer_value / 10^erc20.tokens.decimals`\n\n### Use `date_trunc` to get time\n\nWe've added `evt_block_time` to decoded event tables for your convenience. A neat way to use it is with the `date_trunc` function like this\n\n```SQL\nSELECT date_trunc('week', evt_block_time) AS time\n```\n\nHere you can use minute, day, week, month.\n\n### How to get USD price\n\nTo get the USD volume of onchain activity you typically want to join the smart contract event you are looking at with the usd price and join on minute. Also make sure that asset matches asset.\n\n```SQL\nLEFT JOIN prices.usd p\nON p.minute = date_trunc('minute', evt_block_time)\nAND event.\"asset\" = p.contract_address\n```\n\nThen you can simply multiply the value or amount from the smart contract event with the usd price in your `SELECT` statement: `* p.price`.\n\n### Token symbols\n\nYou often want to group your results by token address. For instance you want to see volume on a DEX grouped by token. However, a big list of token addresses are abstract and hard to digest.\n\nTherefore you often want to use the token symbol instead. Simply join the table `erc20.tokens` with your event table where asset = token address. You then select symbol in your select statement instead of token address.\n\n**NB** The `erc20.tokens` table cointains a selection of popular tokens. If you are working with more obscure tokens you should be careful with joining with this table because tokens that are not in the coincap table might be excluded from your results.\n\n# 🏷 Address Labels\n\nHave 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.\n\n**Address labels** is a new feature on Dune where you as a user can _add_, _update_ and _query_ labels for any address. All for free!\n\n### 🪧 What is a label?\n\nA 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_.\n\nBrowse addresses and and labels at the [**labels page**](https://duneanalytics.com/labels).\n\n### 🖼 What labels looks like\n\nCheck out [this dashboard](https://duneanalytics.com/hagaetc/labels) for examples on what can be created with labels.\n\n#### Address label examples\n\nThe address [0xD551234Ae421e3BCBA99A0Da6d736074f22192FF](https://duneanalytics.com/ethereum/address/0xD551234Ae421e3BCBA99A0Da6d736074f22192FF) can be labeled\n\n| type        | name     |\n| ----------- | -------- |\n| owner       | binance  |\n| wallet type | exchange |\n\nBecause the address is controlled by the exchange Binance.\n\nThe address [0xe65040f61701940b62e18da7a53126a58525588b](https://duneanalytics.com/ethereum/address/0xe65040f61701940b62e18da7a53126a58525588b) can be labeled\n\n| type       | name         |\n| ---------- | ------------ |\n| dapp usage | uniswap user |\n| activity   | dex trader   |\n\nBecause the address in the past interacted with Uniswap.\n\nYou are free to come up with both new types and label names, as labels on Dune are open ended and **crowdsourced** 🎉.\n\n### 📥 Adding labels\n\nThere are two ways to add labels:\n\n#### 1. Directly to an address via our [labels page](https://duneanalytics.com/hagaetc/labels)\n\nGood for specific labels like \"this is a binance wallet\"\n\n#### 2. Via a Dune query\n\nUse Dune queries to label addresses 🤯 A very powerful and scalable way to add labels like \"all these addresses used Uniswap\", and much much more.\n\nPlease see our [Github](https://github.com/duneanalytics/abstractions/tree/master/labels) for examples of labels created with queries and PR in your own!\n\nExamples of what you can do:\n\n- Label all addresses that used a certain dapp\n- Label all addresses that hold a certain amount of a token\n- Label all addresses that use a dapp more than X times per month\n- Label all addresses that sent money to Binance\n\nYou 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.\n\nNote that there might be a few minutes delay from adding the label on duneanalytics.com until you can query it in SQL.\n\n### 🗄 The labels table\n\nLabels are stored in the new `labels.labels` table which has the following schema:\n\n```sql\nCREATE TABLE IF NOT EXISTS labels.labels (\n    -- the id of the label is just an incrementing integer (not useful for querying)\n    id integer PRIMARY KEY,\n    -- the address this label describes\n    address bytea NOT NULL,\n    -- the actual label\n    name text NOT NULL,\n    -- the label type\n    type text NOT NULL,\n    -- the username of the Dune user who created this label\n    author text NOT NULL,\n    -- the source of this label, autopopulated by dune\n    source text NOT NULL,\n    -- the last time this label was changed\n    updated_at timestamptz NOT NULL\n);\n```\n\n### 🧑‍🔧 Using labels\n\nNote 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:\n\n`labels.get(address bytea, type text default null) RETURNS text[]`\n\nwhich we anticipate will be the primary way to use labels. See examples below.\n\nTypically 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')`.\n\nWe'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:\n\n[https://duneanalytics.com/ethereum/address/0xD551234Ae421e3BCBA99A0Da6d736074f22192FF](https://duneanalytics.com/ethereum/address/0xD551234Ae421e3BCBA99A0Da6d736074f22192FF)\n\n### 📜 Usecase: I want to display labels for a list of addresses\n\n\u003e We encourage you to run these queries in Dune while you read this\n\nSay you're looking at the top 10 traders of DAI across all dexes last 24 hours:\n\n```sql\nSELECT trader_a, SUM(token_a_amount)\nFROM dex.trades\nWHERE token_a_symbol = 'DAI'\nAND block_time \u003e now() - interval '24 hours'\nGROUP BY 1\nORDER BY 3 DESC\nLIMIT 10;\n```\n\nIf you want to have labels for these addresses simply alter the `trader_a` column to `labels.get(trader_a)`.\n\n\u003e Note: In the examples below `---` represents lines removed, and `+++` lines added.\n\n```sql\n--- SELECT trader_a, SUM(token_a_amount)\n+++ SELECT labels.get(trader_a), SUM(token_a_amount)\n    FROM dex.trades\n    WHERE token_a_symbol = 'DAI'\n    AND block_time \u003e now() - interval '24 hours'\n    GROUP BY 1\n    ORDER BY 3 DESC\n    LIMIT 10;\n```\n\nNow 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:\n\n```sql\n--- SELECT labels.get(trader_a), SUM(token_a_amount)\n+++ SELECT labels.get(trader_a, 'activity'), SUM(token_a_amount)\n    FROM dex.trades\n    WHERE token_a_symbol = 'DAI'\n    AND block_time \u003e now() - interval '24 hours'\n    GROUP BY 1\n    ORDER BY 3 DESC\n    LIMIT 10;\n```\n\nOf course you can also show the address, and filter for multiple label types\n\n```sql\n--- SELECT labels.get(trader_a, 'activity'), SUM(token_a_amount)\n+++ SELECT trader_a, labels.get(trader_a, 'activity', 'project', 'contract_name') as labels, SUM(token_a_amount)\n    FROM dex.trades\n    WHERE token_a_symbol = 'DAI'\n    AND block_time \u003e now() - interval '24 hours'\n--- GROUP BY 1\n+++ GROUP BY 1, 2\n    ORDER BY 3 DESC\n    LIMIT 10;\n```\n\nYou can also use `labels.url` to make the addresses clickable:\n\n```sql\n--- SELECT trader_a, labels.get(trader_a, 'activity') as labels, SUM(token_a_amount)\n+++ SELECT labels.url(trader_a), labels.get(trader_a, 'activity') as labels, SUM(token_a_amount)\n    FROM dex.trades\n    WHERE token_a_symbol = 'DAI'\n    AND block_time \u003e now() - interval '24 hours'\n--- GROUP BY 1\n+++ GROUP BY 1, 2\n    ORDER BY 3 DESC\n    LIMIT 10;\n```\n\nThis way people who look at your dashboard can easily contribute even better labels to it!\n\n### 🧼 Usecase: I want to filter my query by labels that exist.\n\nIn 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.\n\nAs 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:\n\n```sql\nSELECT \"to\"\nFROM uniswap_v2.\"Pair_evt_Swap\"\nWHERE EXISTS(\n            SELECT *\n            FROM labels.labels\n            WHERE address=\"to\"\n            AND type='dapp usage'\n            AND name='1inch user'\n            )\nLIMIT 10;\n```\n\nThe above query will give you 10 address that has swapped on Uniswap and traded on 1inch.\n\nOf 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:\n\n```sql\n--- SELECT \"to\"\n+++ SELECT \"to\", labels.get(\"to\")\n    FROM uniswap_v2.\"Pair_evt_Swap\"\n    WHERE EXISTS(SELECT * FROM labels.labels WHERE address=\"to\" AND type='dapp usage' AND name='1inch user')\n    LIMIT 10;\n```\n\nThere you have it: you see addresses that traded on both Uniswap and 1inch _and_ all associated address labels.\n\n# 🧐 Understanding data decoding in Dune Analytics\n\nThis section contains a quick primer on how you can explore what decoded data we have and the methods we use to decode the data.\n\nIn Dune, there are tables for each event and function defined in the smart contract ABI. Subsequently, every event or function call on that contract is decoded and inserted as rows into these tables.\n\nThe tables are named accordingly\n\nevents:`projectname.\"contractName_evt_eventName\"`\n\nfunction calls: `projectname.\"contractName_call_eventName\"`\n\nAs an example, decoded data for the `AddLiquidity`-event and `addLiquidity`-function of the uniswap exchange contract are found in tables\n\n`uniswap.\"Exchange_evt_AddLiquidity\"` and `uniswap.\"Exchange_call_addLiquidity\"`.\n\nUsing the event tables is usually sufficient, but in some cases you will want to use the `call` tables. For instance Maker DAO which don't give you too many events you can use tables like `maker.SaiTub_call_draw`.\n\n## What contracts have decoded data?\n\n### Decoded data\n\nBy querying `ethereum.contracts`, you can get an overview over which contracts are tracked by the Dune backend. The columns are\n\n```sql\nnamespace -- Project/product name\nname -- Contract name\nABI -- The ABI that will populate the relevant tables\naddress -- The contract address\ndynamic -- True if all contracts with the same bytecode are decoded automatically\nbytecode -- The bytecode for the decoded contract\n```\n\n### Abstractions and views\n\nOn top of the decoded tables we have a growing number of views that make it even easier to work with the data.\n\nViews are named `namespace.view_event` for instance. In general you can search for `view` in the table list to find the views we have.\n\n### A few handy queries to explore decoded tables\n\n**See all projects we have decoded data for**\n\n```sql\nSELECT DISTINCT namespace FROM ethereum.\"contracts\";\n```\n\n**Do we have decoded data for a specific contract?**\n\n```sql\nSELECT * FROM ethereum.\"contracts\"\nWHERE address = '\\xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';\n```\n\n**Contracts that are \"interface\"-decoded**\n\n```sql\nSELECT * FROM ethereum.\"contracts\" WHERE address IS NULL;\n```\n\nIf you are working with a an event or call table directly you can see if there are several instances of that contract with\n\n```sql\nSELECT DISTINCT contract_address FROM projectname.\"contractName_evt_eventName\";\n```\n\n## Scalable decoding across contracts\n\nMany dApps have numerous smart contracts that are more or less similar, we have two main ways of handling this in a scalable way:\n\n### Contracts with the same bytecode\n\nDune can dynamically add contracts to track by comparing the bytecode of deployed contracts to known bytecodes. If a known contract is \"dynamic\", events and calls to a newly deployed contract with matching bytecode will find it's way into the same tables as were defined by the base contract. Essentially this covers all factory-pattern contract architectures. As a result, `SELECT`-ing from a single table might yield data from multiple contracts. In decoded tables, the column `contract_address` tells you which smart contract the event or call is on. If you want to look at only a single contract you can filter by its address.\n\nFor example:\n\n```sql\nSELECT DISTINCT contract_address FROM uniswap.\"Exchange_evt_TokenPurchase\";\n```\n\nWill give you all the unique Uniswap exchanges with a Token Purchase event.\n\n### Interfaces\n\nWhen we're interested in a subset of events fired regardless of the origin contract, Dune uses interface-decoding. Notable examples include erc20 and erc721 transfer events. This method is reserved for special cases.\n\n## How Dune handles Proxy contracts\n\nSometimes users interact with dApps through proxy contracts. The proxy contract throws the event, but there's an underlying contract that contains and performs the action. In those cases, we apply the ABI of the proxied contract (sometimes called \"master copy\") to the proxy contract address. We also usually apply the name of the proxied contract to the relevant table.\n\n# 📬 Get any smart contract decoded\n\n#### We have decoded data for the most popular smart contract projects. Head to duneanalytics.com/decode if you have a request for decoding of data.\n\n# 👩‍🏭 Change log\n\n#### [August 2020](https://hackmd.io/YOP3YIgaRAejTPE190sOjw?view) - USD prices for more assets, token decimals on `prices.usd` table\n\n#### [March 2020](https://hackmd.io/YOP3YIgaRAejTPE190sOjw?view#March-2020) - block_time denormalization, traces.success and more\n\n#### [January 2020](https://hackmd.io/YOP3YIgaRAejTPE190sOjw?view) - ERC20 transfer table, Fallback decoding and more\n\n#### [October 2019](https://hackmd.io/YOP3YIgaRAejTPE190sOjw?view#October-2019) - New data structure\n\n# 👉 Some sample queries\n\n## Growth rate\n\nAssuming you have a query with a count of some event grouped by time (month for instance) you can add this snippet to you `select` statement to get growth rate.\n\n```SQL\n(count(distinct event) - lag(count(distinct event), 1)\nover (order by date_trunc('month', evt_block_time))) / lag(count(distinct action), 1)\nover (order by date_trunc('month', evt_block_time)) as \"Growth rate\"\n```\n\nMultiply the number by 100 to get percentage.\n\n## Users and amount over a trailing period\n\n```sql\nSELECT  date_trunc('day', evt_block_time),\n        COUNT (DISTINCT buyer),\n        SUM(eth_bought / 1e18)\nFROM uniswap.\"Exchange_evt_EthPurchase\" p\nWHERE evt_block_time \u003e now() - interval '7 days'\nGROUP BY 1\nORDER BY 1;\n```\n\n## Filter query by an address in the interface\n\nIf you use `{{}}` in a query an input field in the UI will appear and anyone looking at the query can easily input info in that field that will go into the query.\n\nThis is very useful when filtering for custom atributes like an Ethereum address or a token address.\n\nWhen you query in Dune you use `\\x...` while people commonly use `0x...` (see more details [here](https://hackmd.io/k71ZUSTxQVKGqOcvR6OXnw?view#Using-Inline-Ethereum-addresses)).\n\nUsing the below snippet will allow users to past addresses in the regular `0x...` format and then convert it to `\\x...` that will work in a query.\n\n```SQL\nWHERE contract_address = CONCAT('\\x', substring('{{Address}}' from 3))::bytea\n```\n\n[Here's](https://explore.duneanalytics.com/queries/10505/source?p_Address=0x37236cd05b34cc79d3715af2383e96dd7443dcf1#20880) an example of this being applied in a query.\n\n## Circulating supply over time of a token with mint/burn functions\n\n```SQL\nSELECT\nweek,\nSUM(transfer) over (order by week)\nFROM\n (\n    SELECT\n    date_trunc('week', evt_block_time) as week,\n    sum(amount/1e18) as transfer\n    FROM ptokens.\"pBTC_evt_Minted\" tr\n    GROUP BY 1\nUNION\n    SELECT\n    date_trunc('week', evt_block_time) as week,\n    sum(-amount/1e18) as transfer\n    FROM ptokens.\"pBTC_evt_Burned\" tr\n    GROUP BY 1\n) as net;\n```\n\n## Circulating supply over time with mint/burn from `0x000...` address\n\n```SQL\n\nSELECT\nweek,\nSUM(transfer) over (order by week)\nFROM\n (\n    SELECT\n    date_trunc('week', evt_block_time) as week,\n    sum(value/1e8) as transfer --Divide by relevant decimal number\n    FROM erc20.\"ERC20_evt_Transfer\"\n    WHERE contract_address = '\\x2260fac5e5542a773aa44fbcfedf7c193bc2c599' -- token contract address\n    AND \"from\" = '\\x0000000000000000000000000000000000000000'\n    GROUP BY 1\nUNION\n    SELECT\n    date_trunc('week', evt_block_time) as week,\n    sum(-value/1e8) as transfer --Divide by relevant decimal number\n    FROM erc20.\"ERC20_evt_Transfer\"\n    WHERE contract_address = '\\x2260fac5e5542a773aa44fbcfedf7c193bc2c599' -- token contract address\n    AND \"to\" = '\\x0000000000000000000000000000000000000000'\n    GROUP BY 1\n) as net;\n\n\n```\n\n## USD value of token utilised for an event\n\n```sql\nSELECT\ndate_trunc('week', evt_block_time),\nSUM(amount/1e18 * p.price) AS staked\nFROM numerai.\"SimpleGriefing_evt_StakeAdded\" s --Replace with relevant event\nLEFT JOIN prices.usd p ON p.minute = date_trunc('minute', evt_block_time)\nWHERE p.symbol = 'NMR' --Replace with relevant token\n-- WHERE p.contract_address = s.token_address --In case different tokens\nGROUP BY 1;\n```\n\n## USD trading volume per token over time\n\n```sql\nSELECT    price.symbol,\n          date_trunc('week', evt_block_time) AS time,\n          SUM([\"FilledAmount\"] /10^(erc.decimals) * price.price) AS usd_value\n   FROM [table].[\"fill_event\"] filled\n   LEFT JOIN prices.usd price ON date_trunc('minute', evt_block_time) = price.minute AND [tokenAddress] = price.contract_address\n   LEFT JOIN erc20.tokens erc ON erc.contract_address = \"takerAsset\"\n    WHERE evt_block_time \u003c date_trunc('week', current_date)::date\n   GROUP BY 1,\n            2;\n```\n\n## USD price for a token from Uniswap\n\nThe most common and easiest way to get token USD prices on Dune Analytics is with the `prices.usd` table. However, this data is fetched from centralised exchanges so for a long tail of tokens the best approach is to get prices from Uniswap.\n\nThis query uses WETH pairs, which is used to map to USD price. The query can be modified to work with any token that has a price in `prices.usd`\n\nYou can find this query on Dune [here](https://explore.duneanalytics.com/queries/11050/source?p_Token%20address=0xeb4c2781e4eba804ce9a9803c67d0893436bb27d).\n\n```SQL\nWITH weth_pairs AS ( -- Get exchange contract address and \"other token\" for WETH\n    SELECT cr.\"pair\" AS contract,\n        CASE WHEN cr.\"token0\" = '\\xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' then '0' ELSE '1' END  AS eth_token,\n        CASE WHEN cr.\"token1\" = '\\xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' then cr.\"token0\" ELSE cr.\"token1\" END  AS other_token\n    FROM uniswap_v2.\"Factory_evt_PairCreated\" cr\n    WHERE token0 = '\\xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' OR  token1 = '\\xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'\n    )\n\n, swap AS ( -- Get all trades on the pair last 14 days\n    SELECT\n        CASE WHEN eth_token = '0' then sw.\"amount0In\" + sw.\"amount0Out\" ELSE sw.\"amount1In\" + sw.\"amount1Out\"\n        END/1e18 AS eth_amt,\n        CASE WHEN eth_token = '1' then sw.\"amount0In\" + sw.\"amount0Out\" ELSE sw.\"amount1In\" + sw.\"amount1Out\"\n        END/power(10, tok.\"decimals\") AS other_amt, -- If the token is not in the erc20.tokens list you can manually divide by 10^decimals\n        tok.\"symbol\",\n        tok.\"contract_address\",\n        date_trunc('hour', sw.\"evt_block_time\") AS hour\n    FROM uniswap_v2.\"Pair_evt_Swap\" sw\n    JOIN weth_pairs ON sw.\"contract_address\" = weth_pairs.\"contract\"\n    JOIN erc20.\"tokens\" tok ON weth_pairs.\"other_token\" = tok.\"contract_address\"\n    WHERE other_token = '\\xeb4c2781e4eba804ce9a9803c67d0893436bb27d' --renBTC example\n    -- To allow users to submit token address in the Dune UI you can use the below line:\n    -- WHERE other_token = CONCAT('\\x', substring('{{Token address}}' from 3))::bytea -- Allow user to input 0x... format and convert to \\x... format\n    AND sw.evt_block_time \u003e= now() - interval '14 days'\n    )\n\n, eth_prcs AS (\n    SELECT avg(price) eth_prc, date_trunc('hour', minute) AS hour\n    FROM prices.layer1_usd_eth\n    WHERE minute \u003e= now() - interval '14 days'\n    group by 2\n    )\n\nSELECT\n    AVG((eth_amt/other_amt)*eth_prc) AS usd_price,\n    swap.\"symbol\" AS symbol,\n    swap.\"contract_address\" AS contract_address,\n    eth_prcs.\"hour\" AS hour\nFROM swap JOIN eth_prcs ON swap.\"hour\" = eth_prcs.\"hour\"\nGROUP BY 2,3,4\n;\n```\n\n## Token (and USD value) per token over time for an address\n\nNote that this query can get very heavy when there are many tokens and transfers over a long period of time.\n\n```SQL\nWITH transfers AS (\n\n    SELECT  day,\n            address,\n            token_address,\n            sum(amount) AS amount -- Net inflow or outflow per day\n    FROM\n\n    (\n        SELECT  date_trunc('day', evt_block_time) AS day,\n                \"to\" AS address,\n                tr.contract_address AS token_address,\n                value AS amount\n        FROM erc20.\"ERC20_evt_Transfer\" tr\n        WHERE \"to\" = '\\x70c730465dff5447a12bae37090446745c9edccc' --Filter for holding address\n        -- AND contract_address = '\\xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' -- Filter for token address if you only want to see a specific token\n\n        UNION ALL\n\n        SELECT  date_trunc('day', evt_block_time) AS day,\n                \"from\" AS address,\n                tr.contract_address AS token_address,\n                -value AS amount\n        FROM erc20.\"ERC20_evt_Transfer\" tr\n        WHERE \"from\" = '\\x70c730465dff5447a12bae37090446745c9edccc' --Filter for holding address\n        -- AND contract_address = '\\xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' -- Filter for token address if you only want to see a specific token\n    ) t\n   GROUP BY 1, 2, 3\n   )\n\n, balances_with_gap_days AS (\n    SELECT  t.day,\n            address,\n            t.token_address,\n            SUM(amount) OVER (PARTITION BY token_address, address ORDER BY t.day) AS balance, -- balance per day with a transfer\n            lead(day, 1, now()) OVER (PARTITION BY token_address, address ORDER BY t.day) AS next_day -- the day after a day with a transfer\n    FROM transfers t\n    )\n\n , days AS (\n    SELECT generate_series('2020-07-01'::timestamp, date_trunc('day', NOW()), '1 day') AS day -- Generate all days since the first contract\n    )\n\n, balance_all_days AS (\n    SELECT  d.day,\n            address,\n            erc.symbol,\n            b.token_address,\n            SUM(balance/10^decimals) AS balance\n    FROM balances_with_gap_days b\n    INNER JOIN days d ON b.day \u003c= d.day AND d.day \u003c b.next_day -- Yields an observation for every day after the first transfer until the next day with transfer\n    INNER JOIN erc20.tokens erc ON b.token_address = erc.contract_address\n    GROUP BY 1, 2, 3, 4\n    ORDER BY 1, 2, 3, 4\n    )\n\nSELECT  b.day,\n        b.symbol,\n        b.token_address,\n        SUM(balance) AS token_balance,\n        SUM(balance*p.price) AS balance_usd_value\nFROM balance_all_days b\nLEFT JOIN  (\n                SELECT  date_trunc('day', p.minute) as day,\n                        contract_address,\n                        symbol,\n                        decimals,\n                        AVG(p.price) as price\n                FROM prices.\"usd\" p\n                GROUP BY 1, 2, 3, 4\n            ) p ON b.day = p.day AND b.token_address = p.contract_address\nGROUP BY 1,2,3\nORDER BY 1,2,3\n;\n\n```\n\n# 🤕 Known issues\n\n### Function overloading\n\nWe have a known issue with _function overloading_. There are a few cases where smart contract developers use function overloading, i.e. specify two functions with the same name but different parameters. In these cases, we will currently only have _one_ of the implementations in our database. We’re working on a fix for this. One known case is the two approve implementations in the SAI contract.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsambacha%2Fdune-snippets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsambacha%2Fdune-snippets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsambacha%2Fdune-snippets/lists"}