diff --git a/spellbook/macros/alter_table_properties.sql b/spellbook/macros/alter_table_properties.sql index 34f3d1ec03f..fefe6fe1928 100644 --- a/spellbook/macros/alter_table_properties.sql +++ b/spellbook/macros/alter_table_properties.sql @@ -244,6 +244,15 @@ ALTER VIEW magiceden.mints SET TBLPROPERTIES('dune.public'='true', 'dune.data_explorer.contributors'='["soispoke"]'); {% endset %} +{% set magiceden_fees %} +ALTER VIEW magiceden.fees SET TBLPROPERTIES('dune.public'='true', + 'dune.data_explorer.blockchains'='["solana"]', + 'dune.data_explorer.category'='abstraction', + 'dune.data_explorer.abstraction.type'='project', + 'dune.data_explorer.abstraction.name'='magiceden', + 'dune.data_explorer.contributors'='["soispoke"]'); +{% endset %} + {% set nft_events %} ALTER TABLE nft.events SET TBLPROPERTIES('dune.public'='true', 'dune.data_explorer.blockchains'='["ethereum","solana"]', @@ -415,6 +424,7 @@ ALTER VIEW ens.view_renewals SET TBLPROPERTIES('dune.public'='true', {% do run_query(magiceden_events) %} {% do run_query(magiceden_trades) %} {% do run_query(magiceden_mints) %} +{% do run_query(magiceden_fees) %} {% do run_query(nft_events) %} {% do run_query(nft_trades) %} {% do run_query(nft_mints) %} diff --git a/spellbook/models/magiceden/magiceden_events.sql b/spellbook/models/magiceden/magiceden_events.sql index 9322fad3f18..0580ec81fe9 100644 --- a/spellbook/models/magiceden/magiceden_events.sql +++ b/spellbook/models/magiceden/magiceden_events.sql @@ -11,16 +11,16 @@ SELECT blockchain, project, version, block_time, -NULL::string as token_id, +token_id, NULL::string as collection, amount_usd, token_standard, -NULL::string as trade_type, -NULL::string as number_of_items, +trade_type, +number_of_items, NULL::string as trade_category, evt_type, -NULL::string as seller, -NULL::string as buyer, +seller, +buyer, amount_original, amount_raw, currency_symbol, @@ -33,20 +33,20 @@ tx_hash, block_number, NULL::string as tx_from, NULL::string as tx_to, -NULL::double as platform_fee_amount_raw, -NULL::double as platform_fee_amount, -NULL::double as platform_fee_amount_usd, -NULL::string as platform_fee_percentage, -NULL::double as royalty_fee_amount_raw, -NULL::double as royalty_fee_amount, -NULL::double as royalty_fee_amount_usd, -NULL::string as royalty_fee_percentage, -NULL::double as royalty_fee_receive_address, -NULL::double as royalty_fee_currency_symbol, +platform_fee_amount_raw, +platform_fee_amount, +platform_fee_amount_usd, +platform_fee_percentage, +royalty_fee_amount_raw, +royalty_fee_amount, +royalty_fee_amount_usd, +royalty_fee_percentage, +NULL::string as royalty_fee_receive_address, +royalty_fee_currency_symbol, unique_trade_id FROM {{ ref('magiceden_solana_events') }} {% if is_incremental() %} -- this filter will only be applied on an incremental run -WHERE block_time > now() - interval 2 days +WHERE block_time >= (select max(block_time) from {{ this }}) {% endif %} \ No newline at end of file diff --git a/spellbook/models/magiceden/magiceden_fees.sql b/spellbook/models/magiceden/magiceden_fees.sql new file mode 100644 index 00000000000..52e463b90a2 --- /dev/null +++ b/spellbook/models/magiceden/magiceden_fees.sql @@ -0,0 +1,38 @@ + {{ + config( + alias='fees') +}} + +SELECT blockchain, +project, +version, +block_time, +token_id, +NULL::string as collection, +platform_fee_amount_raw, +platform_fee_amount, +platform_fee_amount_usd, +platform_fee_percentage, +royalty_fee_amount_raw, +royalty_fee_amount, +royalty_fee_amount_usd, +royalty_fee_percentage, +NULL::string as royalty_fee_receive_address, +royalty_fee_currency_symbol, +token_standard, +trade_type, +number_of_items, +NULL::string as trade_category, +evt_type, +seller, +buyer, +NULL::string as nft_contract_address, +project_contract_address, +NULL::string as aggregator_name, +NULL::string as aggregator_address, +block_number, +tx_hash, +NULL::string as tx_from, +NULL::string as tx_to, +unique_trade_id +FROM {{ ref('magiceden_solana_events') }} \ No newline at end of file diff --git a/spellbook/models/magiceden/magiceden_mints.sql b/spellbook/models/magiceden/magiceden_mints.sql index 4b5fd6a5c22..708be5f62dd 100644 --- a/spellbook/models/magiceden/magiceden_mints.sql +++ b/spellbook/models/magiceden/magiceden_mints.sql @@ -7,16 +7,16 @@ SELECT blockchain, project, version, block_time, -NULL::string as token_id, +token_id, NULL::string as collection, amount_usd, token_standard, -NULL::string as trade_type, -NULL::string as number_of_items, +trade_type, +number_of_items, NULL::string as trade_category, evt_type, -NULL::string as seller, -NULL::string as buyer, +seller, +buyer, amount_original, amount_raw, currency_symbol, diff --git a/spellbook/models/magiceden/magiceden_schema.yml b/spellbook/models/magiceden/magiceden_schema.yml index 43a86554acb..3d40c347c60 100644 --- a/spellbook/models/magiceden/magiceden_schema.yml +++ b/spellbook/models/magiceden/magiceden_schema.yml @@ -197,4 +197,51 @@ models: - *block_number - *tx_from - *tx_to - - *unique_trade_id \ No newline at end of file + - *unique_trade_id + + + - name: magiceden_fees + meta: + blockchain: solana + project: magiceden + contributors: soispoke + config: + tags: ['magiceden','solana','fees'] + description: > + MagicEden fees on Solana + columns: + - *blockchain + - *project + - *version + - *block_time + - *token_id + - *collection + - *platform_fee_amount_raw + - *platform_fee_amount + - *platform_fee_amount_usd + - *platform_fee_percentage + - *royalty_fee_amount_raw + - *royalty_fee_amount + - *royalty_fee_amount_usd + - *royalty_fee_percentage + - *royalty_fee_receive_address + - *royalty_fee_currency_symbol + - *token_standard + - *trade_type + - *number_of_items + - *trade_category + - *evt_type + - *seller + - *buyer + - *currency_symbol + - *currency_contract + - *nft_contract_address + - *project_contract_address + - *aggregator_name + - *aggregator_address + - *tx_hash + - *block_number + - *tx_from + - *tx_to + - name: unique_trade_id + description: "Unique trade ID" \ No newline at end of file diff --git a/spellbook/models/magiceden/magiceden_trades.sql b/spellbook/models/magiceden/magiceden_trades.sql index a57a600709a..20038f515eb 100644 --- a/spellbook/models/magiceden/magiceden_trades.sql +++ b/spellbook/models/magiceden/magiceden_trades.sql @@ -7,16 +7,16 @@ SELECT blockchain, project, version, block_time, -NULL::string as token_id, +token_id, NULL::string as collection, amount_usd, token_standard, NULL::string as trade_type, -NULL::string as number_of_items, +number_of_items, NULL::string as trade_category, evt_type, -NULL::string as seller, -NULL::string as buyer, +seller, +buyer, amount_original, amount_raw, currency_symbol, diff --git a/spellbook/models/magiceden/solana/magiceden_solana_events.sql b/spellbook/models/magiceden/solana/magiceden_solana_events.sql index aaa34f6e73b..8ec6e54481e 100644 --- a/spellbook/models/magiceden/solana/magiceden_solana_events.sql +++ b/spellbook/models/magiceden/solana/magiceden_solana_events.sql @@ -7,20 +7,11 @@ ) }} -{% set v1_key = "MEisE1HzehtrDpAAT8PnLHjpSSkRYakotTuJRPjTpo8" %} -{% set v2_key = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K" %} -{% set launchpad_v1_key = "CMX5tvuWs2rBUL3vqVWiARfcDoCKjdeSinCsZdxJmYoF" %} -{% set launchpad_v2_key = "CMY8R8yghKfFnHKCWjzrArUpYH4PbJ56aWBr4kCP4DMk" %} -{% set launchpad_v3_key = "CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb" %} - SELECT 'solana' as blockchain, 'magiceden' as project, - CASE WHEN (array_contains(account_keys, '{{v1_key}}')) THEN 'v1' - WHEN (array_contains(account_keys, '{{v2_key}}')) THEN 'v2' - WHEN (array_contains(account_keys, '{{launchpad_v1_key}}')) THEN 'launchpad_v1' - WHEN (array_contains(account_keys, '{{launchpad_v2_key}}')) THEN 'launchpad_v2' - WHEN (array_contains(account_keys, '{{launchpad_v3_key}}')) THEN 'launchpad_v3' + CASE WHEN (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K')) THEN 'v2' + WHEN (array_contains(account_keys, 'CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb')) THEN 'launchpad_v3' END as version, signatures[0] as tx_hash, block_time, @@ -31,30 +22,85 @@ SELECT p.symbol as currency_symbol, p.contract_address as currency_contract, 'metaplex' as token_standard, - CASE WHEN (array_contains(account_keys, '{{v1_key}}')) THEN '{{v1_key}}' - WHEN (array_contains(account_keys, '{{v2_key}}')) THEN '{{v2_key}}' - END as project_contract_address, - CASE WHEN (array_contains(account_keys, '{{v1_key}}')) - OR (array_contains(account_keys, '{{v2_key}}')) THEN 'Trade' - WHEN (array_contains(account_keys, '{{launchpad_v1_key}}')) - OR (array_contains(account_keys, '{{launchpad_v2_key}}')) - OR (array_contains(account_keys, '{{launchpad_v3_key}}')) THEN 'Mint' - ELSE 'Transaction' END as evt_type, - signatures[0] || '-' || id || '-' || instructions[0]::string as unique_trade_id + CASE WHEN (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K')) THEN 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K' + WHEN (array_contains(account_keys, 'CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb')) THEN 'CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb' + END as project_contract_address, + CASE WHEN (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K')) + AND array_contains(log_messages, 'Program log: Instruction: ExecuteSale') + AND array_contains(log_messages, 'Program log: Instruction: Buy') THEN 'Trade' + WHEN (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K')) + AND array_contains(log_messages, 'Program log: Instruction: Sell') THEN 'List' + WHEN (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K')) + AND array_contains(log_messages, 'Program log: Instruction: Buy') THEN 'Bid' + WHEN (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K')) + AND array_contains(log_messages, 'Program log: Instruction: CancelBuy') THEN 'Cancel Bid' + WHEN (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K')) + AND array_contains(log_messages, 'Program log: Instruction: CancelSell') THEN 'Cancel Listing' + WHEN (array_contains(account_keys, 'CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb')) + AND array_contains(log_messages, 'Program log: Instruction: SetAuthority') THEN 'Mint' + ELSE 'Other' END as evt_type, + CASE WHEN (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K')) + AND array_contains(log_messages, 'Program log: Instruction: ExecuteSale') + AND array_contains(log_messages, 'Program log: Instruction: Buy') THEN instructions[1].account_arguments[2]::string + WHEN (array_contains(account_keys, 'CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb')) + AND array_contains(log_messages, 'Program log: Instruction: SetAuthority') THEN COALESCE(instructions[6].account_arguments[9], instructions[5].account_arguments[9], + instructions[4].account_arguments[9], instructions[2].account_arguments[7], instructions[1].account_arguments[10], instructions[0].account_arguments[10])::string + END AS token_id, + NULL::string as collection, + CASE WHEN (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K')) + AND array_contains(log_messages, 'Program log: Instruction: ExecuteSale') + AND array_contains(log_messages, 'Program log: Instruction: Buy') THEN 'Single Item Trade' ELSE NULL::string + END as trade_type, + '1' as number_of_items, + NULL::string as trade_category, + signer as buyer, + CASE WHEN (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K')) + AND array_contains(log_messages, 'Program log: Instruction: ExecuteSale') + AND array_contains(log_messages, 'Program log: Instruction: Buy') THEN instructions[2].account_arguments[1]::string + WHEN (array_contains(account_keys, 'CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb')) THEN '' END as seller, + NULL::string as nft_contract_address, + NULL::string as aggregator_name, + NULL::string as aggregator_address, + NULL::string as tx_from, + NULL::string as tx_to, + 2*(abs(post_balances[0] - pre_balances[0])::string)/100 as platform_fee_amount_raw, + 2*(abs(post_balances[0] / 1e9 - pre_balances[0] / 1e9))/100 as platform_fee_amount, + 2*(abs(post_balances[0] / 1e9 - pre_balances[0] / 1e9) * p.price)/100 as platform_fee_amount_usd, + '2' as platform_fee_percentage, + abs(post_balances[11] - pre_balances[11]) + abs(post_balances[12] - pre_balances[12]) + + abs(post_balances[13] - pre_balances[13]) + abs(post_balances[14] - pre_balances[14]) + abs(post_balances[15] - pre_balances[15]) as royalty_fee_amount_raw, + abs(post_balances[11] / 1e9 - pre_balances[11] / 1e9) + abs(post_balances[12] / 1e9 - pre_balances[12] / 1e9) + + abs(post_balances[13] / 1e9 - pre_balances[13] / 1e9) + abs(post_balances[14] / 1e9 - pre_balances[14] / 1e9) + abs(post_balances[15] / 1e9 - pre_balances[15] / 1e9) + as royalty_fee_amount, + (abs(post_balances[11] / 1e9 - pre_balances[11] / 1e9) + abs(post_balances[12] / 1e9 - pre_balances[12] / 1e9) + + abs(post_balances[13] / 1e9 - pre_balances[13] / 1e9) + abs(post_balances[14] / 1e9 - pre_balances[14] / 1e9) + abs(post_balances[15] / 1e9 - pre_balances[15] / 1e9)) * + p.price as royalty_fee_amount_usd, + ROUND(((abs(post_balances[10] / 1e9 - pre_balances[10] / 1e9) + +abs(post_balances[11] / 1e9 - pre_balances[11] / 1e9) + +abs(post_balances[12] / 1e9 - pre_balances[12] / 1e9) + +abs(post_balances[13] / 1e9 - pre_balances[13] / 1e9) + +abs(post_balances[14] / 1e9 - pre_balances[14] / 1e9) + +abs(post_balances[15] / 1e9 - pre_balances[15] / 1e9)) / ((abs(post_balances[0] / 1e9 - pre_balances[0] / 1e9)-0.00204928)) * 100),2) as royalty_fee_percentage, + NULL::double as royalty_fee_receive_address, + CASE WHEN (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K')) + AND array_contains(log_messages, 'Program log: Instruction: ExecuteSale') + AND array_contains(log_messages, 'Program log: Instruction: Buy') THEN 'SOL' + ELSE NULL::string END as royalty_fee_currency_symbol, + signatures[0] || '-' || id || '-' || instructions[0]::string as unique_trade_id, + instructions, + signatures, + log_messages FROM {{ source('solana','transactions') }} -LEFT JOIN {{ source('prices', 'usd') }} p +LEFT JOIN prices.usd p ON p.minute = date_trunc('minute', block_time) AND p.symbol = 'SOL' -WHERE ( -array_contains(account_keys, '{{v1_key}}') -- magic eden v2 -OR array_contains(account_keys, '{{v2_key}}') -OR array_contains(account_keys, '{{launchpad_v1_key}}') -OR array_contains(account_keys, '{{launchpad_v2_key}}') -OR array_contains(account_keys, '{{launchpad_v3_key}}')) -AND block_date > '2022-01-07' +WHERE (array_contains(account_keys, 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K') -- magic eden v2 +OR array_contains(account_keys, 'CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb')) +AND success = 'True' +AND block_date > '2022-01-05' AND block_slot > 114980355 {% if is_incremental() %} -- this filter will only be applied on an incremental run -AND block_date > now() - interval 2 days +AND block_date >= (select max(block_time) from {{ this }}) {% endif %} \ No newline at end of file diff --git a/spellbook/models/magiceden/solana/magiceden_solana_schema.yml b/spellbook/models/magiceden/solana/magiceden_solana_schema.yml index 8915f12f01d..1ffb47ac54a 100644 --- a/spellbook/models/magiceden/solana/magiceden_solana_schema.yml +++ b/spellbook/models/magiceden/solana/magiceden_solana_schema.yml @@ -20,6 +20,9 @@ models: - &block_time name: block_time description: "UTC event block time" + - &token_id + name: token_id + description: "NFT Token ID. In Solana case, we display the token address" - ¤cy_symbol name: currency_symbol description: "Currency Symbol of the trade value" @@ -29,18 +32,57 @@ models: - &token_standard name: token_standard description: "Token standard (Metaplex for Solana NFTs)" + - &trade_type + name: trade_type + description: "Identify whether it was a single NFT trade or multiple NFTs traded" - &amount_original name: amount_original description: "Value of the trade at time of execution in the original currency" - &amount_usd name: amount_usd description: "USD value of the trade at time of execution" + - &number_of_items + name: number_of_items + description: "Number of items traded" - &project_contract_address name: project_contract_address description: "Contract address used by the v1 project" - &evt_type name: evt_type - description: "Event type (Trade, Mint, Burn, Transaction)" + description: "Event type (Trade, Mint, Burn, Bid, List)" + - &seller + name: seller + description: "Seller wallet address" + - &buyer + name: buyer + description: "Buyer wallet address" + - &platform_fee_amount_raw + name: platform_fee_amount_raw + description: "Raw numerical amount for platform fees" + - &platform_fee_amount + name: platform_fee_amount + description: "Platform fee amount in original token currency (properly formatted in decimals)" + - &platform_fee_amount_usd + name: platform_fee_amount_usd + description: "Platform fee amount in USD" + - &platform_fee_percentage + name: platform_fee_amount_usd + description: "Platform fee in % of the amount paid for a given trade" + - &royalty_fee_amount_raw + name: royalty_fee_amount_raw + description: "Raw numerical amount for royalty fees" + - &royalty_fee_amount + name: royalty_fee_amount + description: "Royalty fee amount in original token currency (properly formatted in decimals)" + - &royalty_fee_amount_usd + name: royalty_fee_amount_usd + description: "Royalty fee amount in USD" + - &royalty_fee_percentage + name: royalty_fee_percentage + description: "Royalty fee in % of the amount paid for a given trade" + - &royalty_fee_currency_symbol + name: royalty_fee_currency_symbol + description: "Symbol of the token in which fees are paid out" - &unique_trade_id name: unique_trade_id description: "Unique trade id, combination of signatures[0] and id" @@ -60,13 +102,18 @@ models: - *blockchain - *tx_hash - *block_time + - *token_id - *currency_symbol - *currency_contract - *token_standard - *amount_original - *amount_usd - *project_contract_address + - *trade_type - *evt_type + - *seller + - *buyer + - *number_of_items - *unique_trade_id - name: magiceden_solana_mints @@ -82,11 +129,16 @@ models: - *blockchain - *tx_hash - *block_time + - *token_id - *currency_symbol - *currency_contract - *token_standard - *amount_original - *amount_usd - *project_contract_address + - *trade_type - *evt_type + - *seller + - *buyer + - *number_of_items - *unique_trade_id \ No newline at end of file