diff --git a/macros/models/_sector/nft/nft_mints.sql b/macros/models/_sector/nft/nft_mints.sql new file mode 100644 index 00000000000..9c1b7f99e87 --- /dev/null +++ b/macros/models/_sector/nft/nft_mints.sql @@ -0,0 +1,190 @@ +{% macro nft_mints( + blockchain, + src_contracts, + src_traces, + src_transactions, + src_erc20_evt_transfer, + nft_transfers, + nft_aggregators, + tokens_nft, + default_currency_symbol, + default_currency_contract, + addresses_defi = null +)%} + +with + +namespaces as ( + select + address, + min_by(namespace, created_at) as namespace + from {{ src_contracts }} + group by 1 +), + +nfts_per_tx as ( + select + tx_hash, + sum(cast(amount as double)) as nfts_minted_in_tx -- for some erc1155 uint256 is not enough + from {{ nft_transfers }} + where "from" = 0x0000000000000000000000000000000000000000 + {% if is_incremental () %} + and {{ incremental_predicate('block_time') }} + {% endif %} + group by 1 +), + +nft_mints as ( + select + nft_mints.block_time as block_time, + cast(date_trunc('day', nft_mints.block_time) as date) as block_date, + cast(date_trunc('month', nft_mints.block_time) as date) as block_month, + nft_mints.block_number, + nft_mints.token_id, + nft_mints.token_standard, + case + when nft_mints.amount = uint256 '1' then 'Single Item Mint' + else 'Bundle Mint' + end as trade_type, + nft_mints.amount as number_of_items, + 'Mint' as trade_category, + 'Mint' as evt_type, + nft_mints."from" as seller, -- needed? always burn address + nft_mints.to as buyer, + nft_mints.amount / case when nft_count.nfts_minted_in_tx = 0 then 1 else nft_count.nfts_minted_in_tx end as mint_ratio, + nft_mints.contract_address as nft_contract_address, + nft_mints.tx_hash, + nft_mints.evt_index, + tx.to as project_contract_address, + tx."from" as tx_from, + tx.to as tx_to + from {{ nft_transfers }} nft_mints + join nfts_per_tx nft_count on nft_count.tx_hash = nft_mints.tx_hash + join {{ src_transactions }} tx on nft_mints.block_time = tx.block_time and nft_mints.tx_hash = tx.hash + {% if is_incremental () %} + and {{ incremental_predicate('tx.block_time') }} + {% endif %} + where 1 = 1 + and nft_mints."from" = 0x0000000000000000000000000000000000000000 + {% if is_incremental () %} + and {{ incremental_predicate('nft_mints.block_time') }} + {% endif %} +), + +nft_mint_with_native as ( + select + nft_mints.block_time, + nft_mints.tx_hash, + nft_mints.token_id, + {{ default_currency_contract }} as contract_address, + '{{ default_currency_symbol }}' as symbol, + sum(coalesce(cast(trc.value as double), 0) * nft_mints.mint_ratio) as amount_raw, + sum((coalesce(cast(trc.value as double), 0) / power(10, 18)) * nft_mints.mint_ratio) as amount_original, + sum((coalesce(cast(trc.value as double), 0) / power(10, 18)) * nft_mints.mint_ratio * pu_native.price) as amount_usd + from nft_mints + join {{ src_traces }} trc on nft_mints.block_time = trc.block_time + and nft_mints.tx_hash = trc.tx_hash + and nft_mints.buyer = trc."from" + {% if is_incremental () %} + and {{ incremental_predicate('trc.block_time') }} + {% endif %} + left join {{ source('prices', 'usd') }} pu_native on pu_native.blockchain = '{{blockchain}}' + and pu_native.minute = date_trunc('minute', trc.block_time) + and pu_native.contract_address = {{ default_currency_contract }} + {% if is_incremental () %} + and {{ incremental_predicate('pu_native.minute') }} + {% endif %} + where 1 = 1 + and (trc.call_type not in ('delegatecall', 'callcode', 'staticcall') or trc.call_type is null) + and cast(trc.value as double) > 0 + and trc.success + group by 1,2,3 +), + +nft_mint_with_erc20 as ( + select + nft_mints.block_time, + nft_mints.tx_hash, + nft_mints.token_id, + erc20.contract_address, + pu_erc20.symbol, + sum(coalesce(cast(erc20.value as double), 0) * nft_mints.mint_ratio) as amount_raw, + sum((coalesce(cast(erc20.value as double), 0) / power(10, 18)) * nft_mints.mint_ratio) as amount_original, + sum((coalesce(cast(erc20.value as double), 0) / power(10, 18)) * nft_mints.mint_ratio * pu_erc20.price) as amount_usd + from nft_mints + join {{ src_erc20_evt_transfer }} erc20 on nft_mints.block_time = erc20.evt_block_time + and nft_mints.tx_hash = erc20.evt_tx_hash + and nft_mints.buyer = erc20."from" + {% if is_incremental () %} + and {{ incremental_predicate('erc20.evt_block_time') }} + {% endif %} + left join {{ source('prices', 'usd') }} pu_erc20 on pu_erc20.blockchain = '{{blockchain}}' + and pu_erc20.minute = date_trunc('minute', erc20.evt_block_time) + and erc20.contract_address = pu_erc20.contract_address + {% if is_incremental () %} + and {{ incremental_predicate('pu_erc20.minute') }} + {% endif %} + where 1 = 1 + and cast(erc20.value as double) > 0 + group by 1,2,3,4,5 +) + +select + '{{blockchain}}' as blockchain, + coalesce(ec.namespace, 'Unknown') as project, + coalesce(tok.name, 'Unknown') as collection, + '' as version, + nft_mints.block_time, + nft_mints.block_date, + nft_mints.block_month, + nft_mints.block_number, + nft_mints.token_id, + nft_mints.token_standard, + nft_mints.trade_type, + nft_mints.number_of_items, + nft_mints.trade_category, + nft_mints.evt_type, + nft_mints.seller, + nft_mints.buyer, + nft_mints.nft_contract_address, + nft_mints.tx_hash, + nft_mints.evt_index, + nft_mints.project_contract_address, + nft_mints.tx_from, + nft_mints.tx_to, + coalesce(mint_erc20.amount_raw, mint_native.amount_raw, 0) as amount_raw, + coalesce(mint_erc20.amount_original, mint_native.amount_original, 0) as amount_original, + coalesce(mint_erc20.amount_usd, mint_native.amount_usd, 0) as amount_usd, + coalesce(mint_erc20.symbol, mint_native.symbol, '{{ default_currency_symbol }}') as currency_symbol, + coalesce(mint_erc20.contract_address, mint_native.contract_address, {{ default_currency_contract }}) as currency_contract, + agg.name as aggregator_name, + agg.contract_address as aggregator_address, + cast(0 as uint256) as platform_fee_amount_raw, + cast(0 as double) as platform_fee_amount, + cast(0 as double) as platform_fee_amount_usd, + cast(0 as double) as platform_fee_percentage, + cast(null as varbinary) as royalty_fee_receive_address, + '0' as royalty_fee_currency_symbol, + cast(0 as uint256) as royalty_fee_amount_raw, + cast(0 as double) as royalty_fee_amount, + cast(0 as double) as royalty_fee_amount_usd, + cast(0 as double) as royalty_fee_percentage +from nft_mints + left join nft_mint_with_native mint_native on nft_mints.block_time = mint_native.block_time + and nft_mints.tx_hash = mint_native.tx_hash + and nft_mints.token_id = mint_native.token_id + left join nft_mint_with_erc20 mint_erc20 on nft_mints.block_time = mint_erc20.block_time + and nft_mints.tx_hash = mint_erc20.tx_hash + and nft_mints.token_id = mint_erc20.token_id + left join {{ nft_aggregators }} agg on nft_mints.tx_to = agg.contract_address + left join {{ tokens_nft }} tok on nft_mints.nft_contract_address = tok.contract_address + left join namespaces ec on nft_mints.tx_to = ec.address +where 1 = 1 + {% if addresses_defi %} + and nft_mints.nft_contract_address not in (select address from {{ addresses_defi }}) + {% endif %} + {% if is_incremental () %} + and {{ incremental_predicate('nft_mints.block_time') }} + {% endif %} + +{% endmacro %} diff --git a/models/_sector/nft/mints/_schema.yml b/models/_sector/nft/mints/_schema.yml index b2b3e05264d..16998f6fbf7 100644 --- a/models/_sector/nft/mints/_schema.yml +++ b/models/_sector/nft/mints/_schema.yml @@ -4,20 +4,22 @@ models: - name: nft_mints meta: - blockchain: ethereum, solana, bnb, optimism, arbitrum, polygon + blockchain: ethereum, solana, bnb, optimism, arbitrum, polygon, celo sector: nft - contributors: soispoke, hildobby, ilemi, 0xRob, cat, umer_h_adil + contributors: soispoke, hildobby, ilemi, 0xRob, cat, umer_h_adil, tomfutago config: - tags: ['nft', 'opensea', 'looksrare', 'x2y2', 'magiceden', 'sudoswap', 'foundation', 'element', 'zora', 'ethereum', 'bnb', 'solana', 'events', 'polygon', 'optimism', 'arbitrum', 'rarible', 'aavegotchi', 'oneplanet', 'fractal'] + tags: ['nft', 'opensea', 'looksrare', 'x2y2', 'magiceden', 'sudoswap', 'foundation', 'element', 'zora', 'ethereum', 'bnb', 'solana', 'events', 'polygon', 'optimism', 'arbitrum', 'celo', 'rarible', 'aavegotchi', 'oneplanet', 'fractal'] description: > NFT mints tests: - dbt_utils.unique_combination_of_columns: combination_of_columns: + - blockchain - tx_hash - evt_index - token_id - number_of_items + - currency_contract columns: - &blockchain name: blockchain diff --git a/models/_sector/nft/mints/native/_schema.yml b/models/_sector/nft/mints/native/_schema.yml index 5e2980e1513..8f44304bd7b 100644 --- a/models/_sector/nft/mints/native/_schema.yml +++ b/models/_sector/nft/mints/native/_schema.yml @@ -6,7 +6,7 @@ models: meta: blockchain: ethereum sector: nft - contributors: umer_h_adil, hildobby + contributors: umer_h_adil, hildobby, tomfutago config: tags: [ 'nft','ethereum' ] description: > @@ -18,6 +18,7 @@ models: - evt_index - token_id - number_of_items + - currency_contract columns: - &tx_hash name: tx_hash @@ -39,6 +40,11 @@ models: description: "number_of_items" tests: - not_null + - ¤cy_contract + name: currency_contract + description: "currency contract" + tests: + - not_null - &amount_usd name: amount_usd description: "USD value of the trade at time of execution" @@ -68,3 +74,28 @@ models: - *token_id - *number_of_items - *amount_usd + + - name: nft_celo_native_mints + meta: + blockchain: celo + sector: nft + contributors: tomfutago + config: + tags: [ 'nft','celo' ] + description: > + NFT native (i.e., non-platform) mints + tests: + - dbt_utils.unique_combination_of_columns: + combination_of_columns: + - tx_hash + - evt_index + - token_id + - number_of_items + - currency_contract + columns: + - *tx_hash + - *evt_index + - *token_id + - *number_of_items + - *currency_contract + - *amount_usd diff --git a/models/_sector/nft/mints/native/nft_celo_native_mints.sql b/models/_sector/nft/mints/native/nft_celo_native_mints.sql new file mode 100644 index 00000000000..515495e2d40 --- /dev/null +++ b/models/_sector/nft/mints/native/nft_celo_native_mints.sql @@ -0,0 +1,29 @@ +{{ + config( + tags = ['dunesql'], + schema = 'nft_celo', + alias = alias('native_mints'), + partition_by = ['block_month'], + materialized = 'incremental', + file_format = 'delta', + incremental_strategy = 'merge', + unique_key = ['tx_hash','evt_index','token_id','number_of_items','currency_contract'] + ) +}} + +{% set blockchain = 'celo' %} + +{{ + nft_mints( + blockchain = blockchain, + src_contracts = source(blockchain, 'contracts'), + src_traces = source(blockchain, 'traces'), + src_transactions = source(blockchain, 'transactions'), + src_erc20_evt_transfer = source('erc20_' ~ blockchain, 'evt_transfer'), + nft_transfers = ref('nft_' ~ blockchain ~ '_transfers'), + nft_aggregators = ref('nft_' ~ blockchain ~ '_aggregators'), + tokens_nft = ref('tokens_' ~ blockchain ~ '_nft'), + default_currency_symbol = 'CELO', + default_currency_contract = '0x471EcE3750Da237f93B8E339c536989b8978a438' + ) +}} diff --git a/models/_sector/nft/mints/native/nft_ethereum_native_mints.sql b/models/_sector/nft/mints/native/nft_ethereum_native_mints.sql index 173f92678ed..fee330f22de 100644 --- a/models/_sector/nft/mints/native/nft_ethereum_native_mints.sql +++ b/models/_sector/nft/mints/native/nft_ethereum_native_mints.sql @@ -1,181 +1,30 @@ -{{ config( +{{ + config( tags = ['dunesql'], schema = 'nft_ethereum', alias = alias('native_mints'), partition_by = ['block_month'], - materialized = 'incremental', - file_format = 'delta', - incremental_strategy = 'merge', - unique_key = ['tx_hash','evt_index','token_id','number_of_items'] - ) + materialized = 'incremental', + file_format = 'delta', + incremental_strategy = 'merge', + unique_key = ['tx_hash','evt_index','token_id','number_of_items','currency_contract'] + ) }} -WITH namespaces AS ( - SELECT address - , min_by(namespace, created_at) AS namespace - FROM {{ source('ethereum','contracts') }} - GROUP BY address - ) +{% set blockchain = 'ethereum' %} -, nfts_per_tx_tmp AS ( - SELECT tx_hash - , sum(amount) AS nfts_minted_in_tx - FROM {{ ref('nft_ethereum_transfers') }} - {% if is_incremental() %} - WHERE block_time >= date_trunc('day', now() - interval '7' Day) - {% endif %} - GROUP BY tx_hash +{{ + nft_mints( + blockchain = blockchain, + src_contracts = source(blockchain, 'contracts'), + src_traces = source(blockchain, 'traces'), + src_transactions = source(blockchain, 'transactions'), + src_erc20_evt_transfer = source('erc20_' ~ blockchain, 'evt_transfer'), + nft_transfers = ref('nft_' ~ blockchain ~ '_transfers'), + nft_aggregators = ref('nft_' ~ blockchain ~ '_aggregators'), + tokens_nft = ref('tokens_' ~ blockchain ~ '_nft'), + default_currency_symbol = 'ETH', + default_currency_contract = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + addresses_defi = ref('addresses_' ~ blockchain ~ '_defi') ) - -, nfts_per_tx as ( - SELECT - tx_hash - , case when nfts_minted_in_tx = UINT256 '0' THEN UINT256 '1' ELSE nfts_minted_in_tx END as nfts_minted_in_tx - FROM - nfts_per_tx_tmp -) -SELECT -blockchain -, project -, version -, block_time -, block_date -, block_month -, block_number -, token_id -, collection -, token_standard -, trade_type -, number_of_items -, trade_category -, evt_type -, seller -, buyer -, amount_raw -, amount_original -, amount_usd -, currency_symbol -, currency_contract -, nft_contract_address -, project_contract_address -, aggregator_name -, aggregator_address -, tx_hash -, tx_from -, tx_to -, platform_fee_amount_raw -, platform_fee_amount -, platform_fee_amount_usd -, platform_fee_percentage -, royalty_fee_receive_address -, royalty_fee_currency_symbol -, royalty_fee_amount_raw -, royalty_fee_amount -, royalty_fee_amount_usd -, royalty_fee_percentage -, evt_index -FROM -( -SELECT - *, - ROW_NUMBER() OVER (PARTITION BY tx_hash, evt_index, token_id, number_of_items ORDER BY amount_usd DESC NULLS LAST) as rank_index -FROM -( -SELECT distinct 'ethereum' AS blockchain -, COALESCE(ec.namespace, 'Unknown') AS project -, '' AS version -, nft_mints.block_time AS block_time -, CAST(date_trunc('day', nft_mints.block_time) as date) AS block_date -, CAST(date_trunc('month', nft_mints.block_time) as date) AS block_month -, nft_mints.block_number AS block_number -, nft_mints.token_id AS token_id -, tok.name AS collection -, nft_mints.token_standard -, CASE WHEN nft_mints.amount= UINT256 '1' THEN 'Single Item Mint' - ELSE 'Bundle Mint' - END AS trade_type -, nft_mints.amount AS number_of_items -, 'Mint' AS trade_category -, 'Mint' AS evt_type -, nft_mints."from" AS seller -, nft_mints.to AS buyer -, CAST(COALESCE(SUM(CAST(et.value as DOUBLE)), SUM(CAST(erc20s.value as DOUBLE)), 0)*(nft_mints.amount/nft_count.nfts_minted_in_tx) AS UINT256) AS amount_raw -, COALESCE(SUM(CAST(et.value as DOUBLE))/POWER(10, 18), SUM(CAST(erc20s.value as DOUBLE))/POWER(10, pu_erc20s.decimals))*(nft_mints.amount/nft_count.nfts_minted_in_tx) AS amount_original -, COALESCE(pu_eth.price*SUM(CAST(et.value as DOUBLE))/POWER(10, 18), pu_erc20s.price*SUM(CAST(erc20s.value as DOUBLE))/POWER(10, pu_erc20s.decimals))*(nft_mints.amount/nft_count.nfts_minted_in_tx) AS amount_usd -, CASE WHEN et.success THEN 'ETH' ELSE pu_erc20s.symbol END AS currency_symbol -, CASE WHEN et.success THEN 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 ELSE erc20s.contract_address END AS currency_contract -, nft_mints.contract_address AS nft_contract_address -, etxs.to AS project_contract_address -, agg.name AS aggregator_name -, agg.contract_address AS aggregator_address -, nft_mints.tx_hash AS tx_hash -, etxs."from" AS tx_from -, etxs.to AS tx_to -, CAST(0 AS UINT256) AS platform_fee_amount_raw -, CAST(0 AS DOUBLE) AS platform_fee_amount -, CAST(0 AS DOUBLE) AS platform_fee_amount_usd -, CAST(0 AS DOUBLE) AS platform_fee_percentage -, CAST(NULL as VARBINARY) AS royalty_fee_receive_address -, '0' AS royalty_fee_currency_symbol -, CAST(0 AS UINT256) AS royalty_fee_amount_raw -, CAST(0 AS DOUBLE) AS royalty_fee_amount -, CAST(0 AS DOUBLE) AS royalty_fee_amount_usd -, CAST(0 AS DOUBLE) AS royalty_fee_percentage -, nft_mints.evt_index -FROM {{ ref('nft_ethereum_transfers') }} nft_mints -LEFT JOIN nfts_per_tx nft_count ON nft_count.tx_hash=nft_mints.tx_hash -LEFT JOIN {{ source('ethereum','traces') }} et ON et.block_time=nft_mints.block_time - AND et.tx_hash=nft_mints.tx_hash - AND et."from"=nft_mints.to - AND (et.call_type NOT IN ('delegatecall', 'callcode', 'staticcall') OR et.call_type IS NULL) - AND et.success - AND CAST(et.value as DOUBLE) > 0 - {% if is_incremental() %} - AND et.block_time >= date_trunc('day', now() - interval '7' Day) - {% endif %} -LEFT JOIN {{ source('prices','usd') }} pu_eth ON pu_eth.blockchain='ethereum' - AND pu_eth.minute=date_trunc('minute', et.block_time) - AND pu_eth.contract_address= 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 - {% if is_incremental() %} - AND pu_eth.minute >= date_trunc('day', now() - interval '7' Day) - {% endif %} -LEFT JOIN {{ source('erc20_ethereum','evt_transfer') }} erc20s ON erc20s.evt_block_time=nft_mints.block_time - AND erc20s."from"=nft_mints.to - AND erc20s.evt_tx_hash = nft_mints.tx_hash - AND (et.value IS NULL OR CAST(et.value as double) = 0) - {% if is_incremental() %} - AND erc20s.evt_block_time >= date_trunc('day', now() - interval '7' Day) - {% endif %} -LEFT JOIN {{ source('prices','usd') }} pu_erc20s ON pu_erc20s.blockchain='ethereum' - AND pu_erc20s.minute=date_trunc('minute', erc20s.evt_block_time) - AND erc20s.contract_address=pu_erc20s.contract_address - {% if is_incremental() %} - AND pu_erc20s.minute >= date_trunc('day', now() - interval '7' Day) - {% endif %} -LEFT JOIN {{ source('ethereum','transactions') }} etxs ON etxs.block_time=nft_mints.block_time - AND etxs.hash=nft_mints.tx_hash - {% if is_incremental() %} - AND etxs.block_time >= date_trunc('day', now() - interval '7' Day) - {% endif %} -LEFT JOIN {{ ref('nft_ethereum_aggregators') }} agg ON etxs.to=agg.contract_address -LEFT JOIN {{ ref('tokens_ethereum_nft') }} tok ON tok.contract_address=nft_mints.contract_address -LEFT JOIN namespaces ec ON etxs.to=ec.address -{% if is_incremental() %} -LEFT JOIN {{this}} anti_txs ON anti_txs.block_time=nft_mints.block_time - AND anti_txs.tx_hash=nft_mints.tx_hash -WHERE anti_txs.tx_hash IS NULL -{% else %} -WHERE 1=1 -{% endif %} -AND nft_mints."from"= 0x0000000000000000000000000000000000000000 -AND nft_mints.contract_address NOT IN (SELECT address FROM {{ ref('addresses_ethereum_defi') }}) -{% if is_incremental() %} -AND nft_mints.block_time >= date_trunc('day', now() - interval '7' Day) -{% endif %} -GROUP BY nft_mints.block_time, nft_mints.block_number, nft_mints.token_id, nft_mints.token_standard -, nft_mints.amount, nft_mints."from", nft_mints.to, nft_mints.contract_address, etxs.to, nft_mints.evt_index -, nft_mints.tx_hash, etxs."from", ec.namespace, tok.name, pu_erc20s.decimals, pu_eth.price, pu_erc20s.price -, agg.name, agg.contract_address, nft_count.nfts_minted_in_tx, pu_erc20s.symbol, erc20s.contract_address, et.success -) tmp -) tmp_2 -WHERE rank_index = 1 +}} diff --git a/models/_sector/nft/mints/nft_mints.sql b/models/_sector/nft/mints/nft_mints.sql index 9d68a9219e2..409aa61dfca 100644 --- a/models/_sector/nft/mints/nft_mints.sql +++ b/models/_sector/nft/mints/nft_mints.sql @@ -6,27 +6,29 @@ materialized = 'incremental', file_format = 'delta', incremental_strategy = 'merge', - unique_key = ['tx_hash','evt_index','token_id','number_of_items'], - post_hook='{{ expose_spells(\'["ethereum","bnb","optimism","arbitrum"]\', + unique_key = ['blockchain','tx_hash','evt_index','token_id','currency_contract'], + post_hook='{{ expose_spells(\'["ethereum","bnb","optimism","arbitrum","celo"]\', "sector", "nft", - \'["soispoke","umer_h_adil","hildobby","0xRob", "chuxin"]\') }}') + \'["soispoke","umer_h_adil","hildobby","0xRob","chuxin","tomfutago"]\') }}') }} {% set native_mints = [ ref('nft_ethereum_native_mints') -,ref('nft_optimism_native_mints') +,ref('nft_celo_native_mints') ] %} +--,ref('nft_optimism_native_mints') -- temporarily removed as currency_contract column is nullable in the model atm {% set project_mints = [ ref('nftb_bnb_events') ,ref('opensea_v1_ethereum_events') -,ref('magiceden_solana_events') ,ref('stealcam_arbitrum_events') ] %} +--,ref('magiceden_solana_events') -- temp removed - reason as above + WITH project_mints as ( {% for project_mint in project_mints %} @@ -48,7 +50,7 @@ WITH project_mints as seller, buyer, amount_original, - amount_raw, + cast(amount_raw as double) as amount_raw, currency_symbol, currency_contract, nft_contract_address,