Skip to content

Commit 47e711f

Browse files
authored
T 13866 looksrare transactions on v2 (#1241)
Brief comments on the purpose of your changes: This PR adds the LooksRare platform (Ethereum) on Dune v2. It includes LooksRare transactions, mints, burns, and fees tables Using the merge into strategy, I made rows are unique. I also added a test against Dune v1 nft.trades_v2_beta table I made sure the new tables have the appropriate metadata and can be exposed on the Dune App + are integrated to get included in nft.transactions/trades/mints/burns. *For Dune Engine V2* I've checked that: * [x] I tested the query on dune.com after compiling the model with dbt compile (compiled queries are written to the target directory) * [x] I used "refs" to reference other models in this repo and "sources" to reference raw or decoded tables * [x] if adding a new model, I added a test * [x] the filename is unique and ends with .sql * [x] each sql file is a select statement and has only one view, table or function defined * [x] column names are `lowercase_snake_cased` When you are ready for a review, tag duneanalytics/data-experience. We will re-open your forked pull request as an internal pull request. Then your spells will run in dbt and the logs will be avaiable in Github Actions DBT Slim CI. This job will only run the models and tests changed by your PR compared to the production project.
1 parent b573cb4 commit 47e711f

17 files changed

Lines changed: 1695 additions & 11 deletions

spellbook/dbt_project.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ models:
4848
solana:
4949
+schema: opensea_solana
5050
+materialized: view
51+
looksrare:
52+
+schema: looksrare
53+
+materialized: view
54+
ethereum:
55+
+schema: looksrare_ethereum
56+
+materialized: view
5157
magiceden:
5258
+schema: magiceden
5359
+materialized: view

spellbook/macros/alter_table_properties.sql

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,51 @@ ALTER VIEW opensea.fees SET TBLPROPERTIES('dune.public'='true',
127127
'dune.data_explorer.contributors'='["soispoke"]');
128128
{% endset %}
129129

130+
{% set looksrare_ethereum_events %}
131+
ALTER TABLE looksrare_ethereum.events SET TBLPROPERTIES('dune.public'='true',
132+
'dune.data_explorer.blockchains'='["ethereum"]',
133+
'dune.data_explorer.category'='abstraction',
134+
'dune.data_explorer.abstraction.type'='project',
135+
'dune.data_explorer.abstraction.name'='looksrare',
136+
'dune.data_explorer.contributors'='["soispoke"]');
137+
{% endset %}
138+
139+
{% set looksrare_ethereum_trades %}
140+
ALTER VIEW looksrare_ethereum.trades SET TBLPROPERTIES('dune.public'='true',
141+
'dune.data_explorer.blockchains'='["ethereum"]',
142+
'dune.data_explorer.category'='abstraction',
143+
'dune.data_explorer.abstraction.type'='project',
144+
'dune.data_explorer.abstraction.name'='looksrare',
145+
'dune.data_explorer.contributors'='["soispoke"]');
146+
{% endset %}
147+
148+
{% set looksrare_ethereum_mints %}
149+
ALTER VIEW looksrare_ethereum.mints SET TBLPROPERTIES('dune.public'='true',
150+
'dune.data_explorer.blockchains'='["ethereum"]',
151+
'dune.data_explorer.category'='abstraction',
152+
'dune.data_explorer.abstraction.type'='project',
153+
'dune.data_explorer.abstraction.name'='looksrare',
154+
'dune.data_explorer.contributors'='["soispoke"]');
155+
{% endset %}
156+
157+
{% set looksrare_ethereum_burns %}
158+
ALTER VIEW looksrare_ethereum.burns SET TBLPROPERTIES('dune.public'='true',
159+
'dune.data_explorer.blockchains'='["ethereum"]',
160+
'dune.data_explorer.category'='abstraction',
161+
'dune.data_explorer.abstraction.type'='project',
162+
'dune.data_explorer.abstraction.name'='looksrare',
163+
'dune.data_explorer.contributors'='["soispoke"]');
164+
{% endset %}
165+
166+
{% set looksrare_ethereum_fees %}
167+
ALTER VIEW looksrare_ethereum.fees SET TBLPROPERTIES('dune.public'='true',
168+
'dune.data_explorer.blockchains'='["ethereum"]',
169+
'dune.data_explorer.category'='abstraction',
170+
'dune.data_explorer.abstraction.type'='project',
171+
'dune.data_explorer.abstraction.name'='looksrare',
172+
'dune.data_explorer.contributors'='["soispoke"]');
173+
{% endset %}
174+
130175

131176
{% set magiceden_events %}
132177
ALTER TABLE magiceden.events SET TBLPROPERTIES('dune.public'='true',
@@ -304,6 +349,11 @@ ALTER VIEW ens.view_renewals SET TBLPROPERTIES('dune.public'='true',
304349
{% do run_query(opensea_mints) %}
305350
{% do run_query(opensea_burns) %}
306351
{% do run_query(opensea_fees) %}
352+
{% do run_query(looksrare_ethereum_events) %}
353+
{% do run_query(looksrare_ethereum_trades) %}
354+
{% do run_query(looksrare_ethereum_mints) %}
355+
{% do run_query(looksrare_ethereum_burns) %}
356+
{% do run_query(looksrare_ethereum_fees) %}
307357
{% do run_query(magiceden_events) %}
308358
{% do run_query(magiceden_trades) %}
309359
{% do run_query(magiceden_mints) %}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{{
2+
config(
3+
alias='burns')
4+
}}
5+
6+
SELECT blockchain,
7+
project,
8+
version,
9+
block_time,
10+
token_id,
11+
collection,
12+
amount_usd,
13+
token_standard,
14+
trade_type,
15+
number_of_items,
16+
trade_category,
17+
evt_type,
18+
seller,
19+
buyer,
20+
amount_original,
21+
amount_raw,
22+
currency_symbol,
23+
currency_contract,
24+
nft_contract_address,
25+
project_contract_address,
26+
aggregator_name,
27+
aggregator_address,
28+
tx_hash,
29+
tx_from,
30+
tx_to,
31+
unique_trade_id
32+
FROM ({{ ref('looksrare_ethereum_events') }})
33+
WHERE evt_type = 'Burn'
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
{{ config(
2+
alias ='events',
3+
materialized ='incremental',
4+
file_format ='delta',
5+
incremental_strategy='merge',
6+
unique_key='unique_trade_id'
7+
)
8+
}}
9+
10+
WITH looks_rare AS (
11+
SELECT
12+
ask.evt_block_time AS block_time,
13+
ask.tokenId::string AS token_id,
14+
ask.amount AS number_of_items,
15+
taker AS seller,
16+
maker AS buyer,
17+
price AS price,
18+
roy.amount AS royalty_fee,
19+
roy.royaltyRecipient AS royalty_fee_receive_address,
20+
roy.currency AS royalty_fee_currency_symbol,
21+
CASE -- REPLACE `ETH` WITH `WETH` for ERC20 lookup later
22+
WHEN ask.currency = '0x0000000000000000000000000000000000000000' THEN '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
23+
ELSE ask.currency
24+
END AS currency_contract,
25+
ask.currency AS currency_contract_original,
26+
ask.collection AS nft_contract_address,
27+
ask.contract_address AS contract_address,
28+
ask.evt_tx_hash AS tx_hash,
29+
ask.evt_block_number AS block_number,
30+
ask.evt_index AS evt_index,
31+
roy.evt_index as roy_event_index,
32+
CASE -- CATEGORIZE Collection Wide Offers Accepted
33+
WHEN strategy = '0x86f909f70813cdb1bc733f4d97dc6b03b8e7e8f3' THEN 'Collection Offer Accepted'
34+
ELSE 'Offer Accepted'
35+
END AS category
36+
FROM {{ source('looksrare_ethereum','looksrareexchange_evt_takerask') }} ask
37+
LEFT JOIN {{ source('looksrare_ethereum','looksrareexchange_evt_royaltypayment') }} roy ON roy.evt_tx_hash = ask.evt_tx_hash
38+
AND ask.evt_index - 2 = roy.evt_index
39+
{% if is_incremental() %} -- this filter will only be applied on an incremental run
40+
WHERE ask.evt_block_time >= (select max(block_time) from {{ this }})
41+
{% endif %}
42+
UNION
43+
SELECT
44+
bid.evt_block_time AS block_time,
45+
bid.tokenId::string AS token_id,
46+
bid.amount AS number_of_items,
47+
maker AS seller,
48+
taker AS buyer,
49+
price AS price,
50+
roy.amount AS royalty_fee,
51+
roy.royaltyRecipient AS royalty_fee_receive_address,
52+
roy.currency AS royalty_fee_currency_symbol,
53+
CASE -- REPLACE `ETH` WITH `WETH` for ERC20 lookup later
54+
WHEN bid.currency = '0x0000000000000000000000000000000000000000' THEN '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
55+
ELSE bid.currency
56+
END AS currency_contract,
57+
bid.currency AS currency_contract_original,
58+
bid.collection AS nft_contract_address,
59+
bid.contract_address AS contract_address,
60+
bid.evt_tx_hash AS tx_hash,
61+
bid.evt_block_number AS block_number,
62+
bid.evt_index AS evt_index,
63+
roy.evt_index as roy_event_index,
64+
'Buy' as category
65+
FROM {{ source('looksrare_ethereum','looksrareexchange_evt_takerbid') }} bid
66+
LEFT JOIN {{ source('looksrare_ethereum','looksrareexchange_evt_royaltypayment') }} roy ON roy.evt_tx_hash = bid.evt_tx_hash
67+
AND roy.evt_index = bid.evt_index - 4
68+
{% if is_incremental() %} -- this filter will only be applied on an incremental run
69+
WHERE bid.evt_block_time >= (select max(block_time) from {{ this }})
70+
{% endif %}
71+
),
72+
73+
-- Get ERC721 AND ERC1155 transfer data for every trade TRANSACTION
74+
erc_transfers as
75+
(SELECT evt_tx_hash,
76+
contract_address,
77+
id::string as token_id_erc,
78+
cardinality(collect_list(value)) as count_erc,
79+
value as value_unique,
80+
CASE WHEN erc1155.from = '0x0000000000000000000000000000000000000000' THEN 'Mint'
81+
WHEN erc1155.to = '0x0000000000000000000000000000000000000000'
82+
OR erc1155.to = '0x000000000000000000000000000000000000dead' THEN 'Burn'
83+
ELSE 'Trade' END AS evt_type,
84+
evt_index
85+
FROM {{ source('erc1155_ethereum','evt_transfersingle') }} erc1155
86+
WHERE erc1155.evt_block_time > '2022-01-01'
87+
GROUP BY evt_tx_hash,value,id,evt_index, erc1155.from, erc1155.to, erc1155.contract_address
88+
UNION
89+
SELECT evt_tx_hash,
90+
contract_address,
91+
tokenId::string as token_id_erc,
92+
COUNT(tokenId) as count_erc,
93+
NULL as value_unique,
94+
CASE WHEN erc721.from = '0x0000000000000000000000000000000000000000' THEN 'Mint'
95+
WHEN erc721.to = '0x0000000000000000000000000000000000000000'
96+
OR erc721.to = '0x000000000000000000000000000000000000dead' THEN 'Burn'
97+
ELSE 'Trade' END AS evt_type,
98+
evt_index
99+
FROM {{ source('erc721_ethereum','evt_transfer') }} erc721
100+
WHERE erc721.evt_block_time > '2022-01-01'
101+
GROUP BY evt_tx_hash,tokenId,evt_index, erc721.from, erc721.to, erc721.contract_address)
102+
103+
SELECT DISTINCT
104+
'ethereum' as blockchain,
105+
'looksrare' as project,
106+
'v1' as version,
107+
looks_rare.block_time,
108+
token_id,
109+
tokens.name AS collection,
110+
looks_rare.price / power(10,erc20.decimals) * p.price AS amount_usd,
111+
tokens.standard AS token_standard,
112+
CASE
113+
WHEN agg.name is NULL AND erc.value_unique = 1 OR erc.count_erc = 1 THEN 'Single Item Trade'
114+
WHEN agg.name is NULL AND erc.value_unique > 1 OR erc.count_erc > 1 THEN 'Bundle Trade'
115+
ELSE 'Single Item Trade' END AS trade_type,
116+
-- Count number of items traded for different trade types and erc standards
117+
CASE WHEN agg.name is NULL AND erc.value_unique > 1 THEN erc.value_unique
118+
WHEN agg.name is NULL AND erc.value_unique is NULL AND erc.count_erc > 1 THEN erc.count_erc
119+
WHEN tokens.standard = 'erc1155' THEN erc.value_unique
120+
WHEN tokens.standard = 'erc721' THEN erc.count_erc
121+
ELSE (SELECT
122+
count(1)::bigint cnt
123+
FROM {{ source('erc721_ethereum','evt_transfer') }} erc721
124+
WHERE erc721.evt_tx_hash = tx_hash
125+
) +
126+
(SELECT
127+
count(1)::bigint cnt
128+
FROM {{ source('erc1155_ethereum','evt_transfersingle') }} erc1155
129+
WHERE erc1155.evt_tx_hash = tx_hash
130+
) END AS number_of_items,
131+
looks_rare.category as trade_category,
132+
evt_type,
133+
seller,
134+
buyer,
135+
looks_rare.price / power(10,erc20.decimals) AS amount_original,
136+
looks_rare.price AS amount_raw,
137+
CASE WHEN looks_rare.currency_contract_original = '0x0000000000000000000000000000000000000000' THEN 'ETH' ELSE erc20.symbol END AS currency_symbol,
138+
currency_contract,
139+
COALESCE(erc.contract_address, nft_contract_address) AS nft_contract_address,
140+
looks_rare.contract_address AS project_contract_address,
141+
agg.name AS aggregator_name,
142+
agg.contract_address AS aggregator_address,
143+
tx_hash,
144+
tx.from AS tx_from,
145+
tx.to AS tx_to,
146+
ROUND((2*(looks_rare.price)/100),7) as platform_fee_amount_raw,
147+
ROUND((2*(looks_rare.price / power(10,erc20.decimals))/100),7) platform_fee_amount,
148+
ROUND((2*(looks_rare.price / power(10,erc20.decimals) * p.price)/100),7) as platform_fee_amount_usd,
149+
'2' as platform_fee_percentage,
150+
royalty_fee as royalty_fee_amount_raw,
151+
royalty_fee / power(10,erc20.decimals) as royalty_fee_amount,
152+
royalty_fee * p.price/ power(10,erc20.decimals) as royalty_fee_amount_usd,
153+
royalty_fee / looks_rare.price * 100 as royalty_fee_percentage,
154+
royalty_fee_receive_address,
155+
royalty_fee_currency_symbol,
156+
tx_hash || '-' || token_id || '-' || seller || '-' || looks_rare.evt_index::string || '-' || evt_type as unique_trade_id
157+
FROM looks_rare
158+
INNER JOIN {{ source('ethereum','transactions') }} tx ON tx_hash = tx.hash
159+
AND tx.block_time > '2022-01-01'
160+
LEFT JOIN erc_transfers erc ON erc.evt_tx_hash = tx_hash AND erc.token_id_erc = token_id
161+
LEFT JOIN {{ ref('tokens_ethereum_nft') }} tokens ON tokens.contract_address = nft_contract_address
162+
LEFT JOIN {{ ref('nft_ethereum_aggregators') }} agg ON agg.contract_address = tx.to
163+
LEFT JOIN {{ source('prices', 'usd') }} p ON p.minute = date_trunc('minute', looks_rare.block_time)
164+
AND p.contract_address = currency_contract
165+
AND p.blockchain ='ethereum'
166+
LEFT JOIN {{ ref('tokens_ethereum_erc20') }} erc20 ON erc20.contract_address = currency_contract
167+
{% if is_incremental() %}
168+
-- this filter will only be applied on an incremental run
169+
WHERE looks_rare.block_time >= (select max(block_time) from {{ this }})
170+
{% endif %}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{{
2+
config(
3+
alias='fees')
4+
}}
5+
6+
SELECT blockchain,
7+
project,
8+
version,
9+
block_time,
10+
token_id,
11+
collection,
12+
platform_fee_amount_raw,
13+
platform_fee_amount,
14+
platform_fee_amount_usd,
15+
platform_fee_percentage,
16+
royalty_fee_amount_raw,
17+
royalty_fee_amount,
18+
royalty_fee_amount_usd,
19+
royalty_fee_percentage,
20+
royalty_fee_receive_address,
21+
royalty_fee_currency_symbol,
22+
token_standard,
23+
trade_type,
24+
number_of_items,
25+
trade_category,
26+
evt_type,
27+
seller,
28+
buyer,
29+
nft_contract_address,
30+
project_contract_address,
31+
aggregator_name,
32+
aggregator_address,
33+
tx_hash,
34+
tx_from,
35+
tx_to,
36+
unique_trade_id
37+
FROM ({{ ref('looksrare_ethereum_events') }})
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{{
2+
config(
3+
alias='mints')
4+
}}
5+
6+
SELECT blockchain,
7+
project,
8+
version,
9+
block_time,
10+
token_id,
11+
collection,
12+
amount_usd,
13+
token_standard,
14+
trade_type,
15+
number_of_items,
16+
trade_category,
17+
evt_type,
18+
seller,
19+
buyer,
20+
amount_original,
21+
amount_raw,
22+
currency_symbol,
23+
currency_contract,
24+
nft_contract_address,
25+
project_contract_address,
26+
aggregator_name,
27+
aggregator_address,
28+
tx_hash,
29+
tx_from,
30+
tx_to,
31+
unique_trade_id
32+
FROM ({{ ref('looksrare_ethereum_events') }})
33+
WHERE evt_type = 'Mint'

0 commit comments

Comments
 (0)