mirror of
https://github.com/FlipsideCrypto/solana-models.git
synced 2026-02-06 16:16:47 +00:00
An 1605/nft mints refactor (#102)
* refactor nft mints model * An 1949/bt (#95) * date limit some program * block timestamp * fixes * fix * An 1937/blocks txs2 (#94) * blocks * transactions and deduping wip * silver reorganization * remove tx count from blocks * wip * load blocks backfill incrementally * wip * wip * wip * remove unused comments * fix ref to wrong table * update to tests * test fixes * moved yawww bids * merge main & fix refs Co-authored-by: Desmond Hui <desmond@flipsidecrypto.com> * description updates (#96) * fix missing incremental block (#97) * reduce batch load size (#98) * Adjust tx2 incremental load size (#99) * reduce batch load size * revert change * revert change * minor cleanup and add model output comparison test * move models to nft folder * add test case * update/add descriptions and tests * adjust unique key * adjust unique key, add columns to output * add alias for new tx_id name from underlying model * add index + inner_index to output and unique key * remove inner index test * fix unique key Co-authored-by: Jessica Huhnke <91915469+jhuhnke@users.noreply.github.com>
This commit is contained in:
parent
b57c7144e3
commit
af2ce900af
22
data/testing__nft_mints.csv
Normal file
22
data/testing__nft_mints.csv
Normal file
@ -0,0 +1,22 @@
|
||||
mint,purchaser,mint_currency,mint_price
|
||||
zsFUFcetxjLCeUaNjsQE57b3c3awU79sVeTZQrsoSq6,748yt6s4kkhFWWLmG5kzBXhsr6hsuCnuTW4hKZ7H8B6C,So11111111111111111111111111111111111111111,1.25847032
|
||||
8XQqL7wwKrGftLaSnd8Km9WnA6bwT1B1w2NXrxQfxU6t,AnW2XvmP5QmS4Vm2DxcjJ3YzRW7utZg83TAwdPvbQ57e,So11111111111111111111111111111111111111111,0.0119712
|
||||
8miSwDxQNV9W7LHPRzXEMXwk4oYHU29fxFi5LAaS3Zoo,9FGsCoLTUKYo8GbfpEN4G91UemB7nmy83JXXQN6tV8QH,So11111111111111111111111111111111111111111,0.00847032
|
||||
CArsPMgQyevzmE4SYDjVaeWvoNwEMsE4cwbCyXrPGtE5,G4A3sTtsk2megbv8q7XpFKio3JgB1jbPXq6KJzQoyF5y,So11111111111111111111111111111111111111111,0.01727472
|
||||
YcDLuwoqB8yWcfnwNDrjoSo4iuVmTCz27ZXsh6w12mo,8VDvnZ31y9RqiZj8m3i4oPaShmY7CqgHu6tNoyEphSSE,So11111111111111111111111111111111111111111,0.00847032
|
||||
6HBSxEKHJzS19aKhFhzWeYRM9QezKk1QGKug3QLFw8AU,3BNjZikUrvdvsHeTjCUrr8bLEtPVBP2oZnSAxtbcQh9a,So11111111111111111111111111111111111111111,0.0105096
|
||||
3ry2VrRvehb6Z7roeXaAzzQuqheeM2wyWHTmgMUtZZSk,3BNjZikUrvdvsHeTjCUrr8bLEtPVBP2oZnSAxtbcQh9a,So11111111111111111111111111111111111111111,0.0105096
|
||||
FUHUjD4z1YDDRGqZAL4n89HsuDEFhVLcoz47LJirCnBm,5PJh6ywVqXTUcwrJyF6nbkgqmmoXEJSXa7rhh3MWQZ7p,So11111111111111111111111111111111111111111,0.0091176
|
||||
FaC8SaDj6crwZA5JyucbKuTDbbTLbCSVpGbLVSXxaxJ4,5PJh6ywVqXTUcwrJyF6nbkgqmmoXEJSXa7rhh3MWQZ7p,So11111111111111111111111111111111111111111,0.0091176
|
||||
BxGPRSEzHwEzX73Ep67a9u5xFc2BSuXSrAevqNMkzN8Z,5PJh6ywVqXTUcwrJyF6nbkgqmmoXEJSXa7rhh3MWQZ7p,So11111111111111111111111111111111111111111,0.0091176
|
||||
HrbK1X3ooR2fBujtDSWeKQtbj1fUtptrEb7mWvsxeQQk,5PJh6ywVqXTUcwrJyF6nbkgqmmoXEJSXa7rhh3MWQZ7p,So11111111111111111111111111111111111111111,0.0091176
|
||||
CmejwsHB1hcQPbY7y4EjYD5gxWJEXn9G4PkXLpLoTus1,5PJh6ywVqXTUcwrJyF6nbkgqmmoXEJSXa7rhh3MWQZ7p,So11111111111111111111111111111111111111111,0.0091176
|
||||
JBzLjej5DEtVupwVtn6y1mnG4HFEkm5PVxQYFNYMJzhc,GPzYDMBnzCNJm7bx9EUVAN6NDYZPYC73YGm9Jypi7LFY,So11111111111111111111111111111111111111111,0.00847032
|
||||
JBzLjej5DEtVupwVtn6y1mnG4HFEkm5PVxQYFNYMJzhc,GPzYDMBnzCNJm7bx9EUVAN6NDYZPYC73YGm9Jypi7LFY,GzpRsvnKXKz586kRLkjdppR4dUCFwHa2qaszKkPUQx6g,80000
|
||||
J5EFUxYPxAyx5oCUUgmCrESHjhmXuzrYsscoxRvVW5Vz,ELdfaUoVQ6uP49t1ZuuMajoadjMVLNVDfQQiuxChS4p5,So11111111111111111111111111111111111111111,0.00937512
|
||||
DCahWcCagbsW8HAqu4QMDaQZn212MrA7aN4yLNKYn3tY,7eAf79f5qpBCPMsZggwoieBGUHiGwhTxCtviXzsNJ33k,So11111111111111111111111111111111111111111,2.00847032
|
||||
58MAJPUgfSyehsKggYEeWjpNZaKw5qxnLNZ4EKeRicmq,8B3NLjV9waB1HAtN5ksz4ymYhjjAwjT9NXFXvCen2UVy,So11111111111111111111111111111111111111111,0.00847032
|
||||
Dq6H4jMXQkHEf3q3BocptwF7Nh6V9FZwABXuVRgRXtts,93oV7JEMxrzqZzcdqWtwoy2cfpmobBpWqcQwXLdnCRgh,So11111111111111111111111111111111111111111,0.00847032
|
||||
Ar9mEJ7qJ1uAgkWduKGo3UYVbPMdKrmWxs5z2wgZgbgN,3hNzvJcbjdhwt14cWkJMYUYFvNbVxLoS8cmrkqfAFVeM,So11111111111111111111111111111111111111111,0.00561672
|
||||
Ar9mEJ7qJ1uAgkWduKGo3UYVbPMdKrmWxs5z2wgZgbgN,3hNzvJcbjdhwt14cWkJMYUYFvNbVxLoS8cmrkqfAFVeM,GENEtH5amGSi8kHAtQoezp1XEXwZJ8vcuePYnXdKrMYz,10
|
||||
Ar9mEJ7qJ1uAgkWduKGo3UYVbPMdKrmWxs5z2wgZgbgN,GenoS3ck8xbDvYEZ8RxMG3Ln2qcyoAN8CTeZuaWgAoEA,So11111111111111111111111111111111111111111,0.0028536
|
||||
|
29
macros/tests/compare_model_subset.sql
Normal file
29
macros/tests/compare_model_subset.sql
Normal file
@ -0,0 +1,29 @@
|
||||
{% test compare_model_subset(model, compare_model, compare_columns, model_condition) %}
|
||||
|
||||
{% set compare_cols_csv = compare_columns | join(', ') %}
|
||||
|
||||
with a as (
|
||||
select {{compare_cols_csv}} from {{ model }}
|
||||
{{ model_condition }}
|
||||
),
|
||||
b as (
|
||||
select {{compare_cols_csv}} from {{ compare_model }}
|
||||
),
|
||||
a_minus_b as (
|
||||
select * from a
|
||||
{{ dbt_utils.except() }}
|
||||
select * from b
|
||||
),
|
||||
b_minus_a as (
|
||||
select * from b
|
||||
{{ dbt_utils.except() }}
|
||||
select * from a
|
||||
),
|
||||
unioned as (
|
||||
select 'in_actual_not_in_expected' as which_diff, a_minus_b.* from a_minus_b
|
||||
union all
|
||||
select 'in_expected_not_in_actual' as which_diff, b_minus_a.* from b_minus_a
|
||||
)
|
||||
select * from unioned
|
||||
|
||||
{% endtest %}
|
||||
@ -5,7 +5,7 @@
|
||||
SELECT
|
||||
block_timestamp,
|
||||
block_id,
|
||||
tx_id,
|
||||
initialization_tx_id as tx_id,
|
||||
succeeded,
|
||||
program_id,
|
||||
purchaser,
|
||||
|
||||
5
models/descriptions/decimal.md
Normal file
5
models/descriptions/decimal.md
Normal file
@ -0,0 +1,5 @@
|
||||
{% docs decimal %}
|
||||
|
||||
Number of decimals in the token value, need to divide amount by 10^decimal
|
||||
|
||||
{% enddocs %}
|
||||
@ -1,5 +1,5 @@
|
||||
{% docs event_index %}
|
||||
|
||||
Location of the event within the instructions of a transaction
|
||||
Location of the instruction (event) within a transaction
|
||||
|
||||
{% enddocs %}
|
||||
5
models/descriptions/mint_amount.md
Normal file
5
models/descriptions/mint_amount.md
Normal file
@ -0,0 +1,5 @@
|
||||
{% docs mint_amount %}
|
||||
|
||||
Number of tokens minted
|
||||
|
||||
{% enddocs %}
|
||||
5
models/descriptions/mint_payer.md
Normal file
5
models/descriptions/mint_payer.md
Normal file
@ -0,0 +1,5 @@
|
||||
{% docs mint_payer %}
|
||||
|
||||
Wallet address associated with paying for the mint
|
||||
|
||||
{% enddocs %}
|
||||
52
models/silver/nfts/silver__nft_mint_price.sql
Normal file
52
models/silver/nfts/silver__nft_mint_price.sql
Normal file
@ -0,0 +1,52 @@
|
||||
{{ config(
|
||||
materialized = 'view'
|
||||
) }}
|
||||
|
||||
with base as (
|
||||
select
|
||||
block_timestamp,
|
||||
tx_ids,
|
||||
program_id,
|
||||
payer,
|
||||
mint,
|
||||
mint_currency,
|
||||
mint_price,
|
||||
_inserted_timestamp,
|
||||
1 as ranking
|
||||
from
|
||||
{{ ref('silver__nft_mint_price_candy_machine') }}
|
||||
union
|
||||
select
|
||||
block_timestamp,
|
||||
tx_ids,
|
||||
program_id,
|
||||
payer,
|
||||
mint,
|
||||
mint_currency,
|
||||
mint_price,
|
||||
_inserted_timestamp,
|
||||
2 as ranking
|
||||
from
|
||||
{{ ref('silver__nft_mint_price_other') }}
|
||||
where
|
||||
mint_price is not null
|
||||
union
|
||||
select
|
||||
block_timestamp,
|
||||
tx_ids,
|
||||
program_id,
|
||||
payer,
|
||||
mint,
|
||||
mint_currency,
|
||||
mint_price,
|
||||
_inserted_timestamp,
|
||||
99 as ranking
|
||||
from
|
||||
{{ ref('silver__nft_mint_price_generic') }}
|
||||
where
|
||||
mint_price is not null
|
||||
)
|
||||
select
|
||||
*
|
||||
from base
|
||||
qualify(row_number() over (partition by mint, payer, mint_currency order by ranking)) = 1
|
||||
50
models/silver/nfts/silver__nft_mint_price.yml
Normal file
50
models/silver/nfts/silver__nft_mint_price.yml
Normal file
@ -0,0 +1,50 @@
|
||||
version: 2
|
||||
models:
|
||||
- name: silver__nft_mint_price
|
||||
description: intermediary model for getting an nft's mint price
|
||||
tests:
|
||||
- dbt_utils.unique_combination_of_columns:
|
||||
combination_of_columns:
|
||||
- MINT
|
||||
- PAYER
|
||||
- MINT_CURRENCY
|
||||
columns:
|
||||
- name: BLOCK_TIMESTAMP
|
||||
description: "block timestamp of the latest transaction with a mint price"
|
||||
tests:
|
||||
- not_null
|
||||
- dbt_expectations.expect_row_values_to_have_recent_data:
|
||||
datepart: day
|
||||
interval: 3
|
||||
- name: TX_IDS
|
||||
description: "set of transaction ids that has an associated mint price"
|
||||
tests:
|
||||
- not_null
|
||||
- name: MINT
|
||||
description: "{{ doc('mint') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: PAYER
|
||||
description: "{{ doc('mint_payer') }}"
|
||||
tests:
|
||||
- not_null:
|
||||
where: mint_price is not null
|
||||
- name: MINT_CURRENCY
|
||||
description: "{{ doc('mint_currency') }}"
|
||||
tests:
|
||||
- not_null:
|
||||
where: mint_price is not null
|
||||
- name: PROGRAM_ID
|
||||
description: "{{ doc('program_id') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: MINT_PRICE
|
||||
description: "{{ doc('mint_price') }}"
|
||||
- name: RANKING
|
||||
description: ranking order for which model to take mint price from first
|
||||
tests:
|
||||
- not_null
|
||||
- name: _INSERTED_TIMESTAMP
|
||||
description: "{{ doc('_inserted_timestamp') }}"
|
||||
tests:
|
||||
- not_null
|
||||
100
models/silver/nfts/silver__nft_mint_price_candy_machine.sql
Normal file
100
models/silver/nfts/silver__nft_mint_price_candy_machine.sql
Normal file
@ -0,0 +1,100 @@
|
||||
{{ config(
|
||||
materialized = 'incremental',
|
||||
unique_key = "CONCAT_WS('-', mint, payer, mint_currency)",
|
||||
incremental_strategy = 'delete+insert',
|
||||
cluster_by = ['block_timestamp::DATE','_inserted_timestamp::DATE'],
|
||||
) }}
|
||||
|
||||
WITH base_candy_machine_events AS (
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
{{ ref('silver__events') }}
|
||||
WHERE
|
||||
program_id = 'cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ'
|
||||
AND
|
||||
succeeded
|
||||
|
||||
{% if is_incremental() %}
|
||||
AND
|
||||
_inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
base_ptb AS (
|
||||
SELECT
|
||||
DISTINCT mint AS mint_paid,
|
||||
account,
|
||||
DECIMAL
|
||||
FROM
|
||||
{{ ref('silver___post_token_balances') }}
|
||||
|
||||
{% if is_incremental() %}
|
||||
WHERE
|
||||
_inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
candy_machine AS (
|
||||
SELECT
|
||||
e.block_timestamp,
|
||||
e.tx_id,
|
||||
e.index,
|
||||
i.index as inner_index,
|
||||
e.program_id,
|
||||
instruction :accounts [5] :: STRING AS mint,
|
||||
instruction :accounts [2] :: STRING AS payer,
|
||||
COALESCE(
|
||||
i.value :parsed :info :lamports :: INTEGER,
|
||||
i.value :parsed :info :amount :: INTEGER
|
||||
) AS transfer_amount,
|
||||
CASE
|
||||
WHEN i.value :parsed :info :lamports is not null THEN NULL
|
||||
ELSE i.value :parsed :info :source
|
||||
END as token_account,
|
||||
e._inserted_timestamp
|
||||
FROM
|
||||
base_candy_machine_events e
|
||||
LEFT JOIN TABLE(FLATTEN(inner_instruction :instructions)) i
|
||||
group by 1,2,3,4,5,6,7,8,9,10
|
||||
),
|
||||
pre_final as (
|
||||
select
|
||||
e.*,
|
||||
COALESCE(
|
||||
p.mint_paid,
|
||||
'So11111111111111111111111111111111111111111'
|
||||
) AS mint_currency,
|
||||
COALESCE(p.decimal, 9) as decimal
|
||||
from candy_machine e
|
||||
LEFT OUTER JOIN base_ptb p on e.token_account = p.account
|
||||
)
|
||||
SELECT
|
||||
p.mint,
|
||||
p.payer,
|
||||
mint_currency,
|
||||
decimal,
|
||||
p.program_id,
|
||||
SUM(p.transfer_amount / pow(10, decimal)) AS mint_price,
|
||||
array_unique_agg(tx_id) as tx_ids,
|
||||
max(block_timestamp) as block_timestamp,
|
||||
max(_inserted_timestamp) as _inserted_timestamp
|
||||
FROM
|
||||
pre_final p
|
||||
WHERE
|
||||
p.mint not in ('Sysvar1nstructions1111111111111111111111111','SysvarRent111111111111111111111111111111111') -- not mint events
|
||||
GROUP BY
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
51
models/silver/nfts/silver__nft_mint_price_candy_machine.yml
Normal file
51
models/silver/nfts/silver__nft_mint_price_candy_machine.yml
Normal file
@ -0,0 +1,51 @@
|
||||
version: 2
|
||||
models:
|
||||
- name: silver__nft_mint_price_candy_machine
|
||||
description: intermediary model for getting an nft's mint price
|
||||
tests:
|
||||
- dbt_utils.unique_combination_of_columns:
|
||||
combination_of_columns:
|
||||
- MINT
|
||||
- PAYER
|
||||
- MINT_CURRENCY
|
||||
where: mint <> 'GqzH4GRCqqsNXAvx9FSK7n3pMqRCjnyns7pqe94yAV1M'
|
||||
columns:
|
||||
- name: BLOCK_TIMESTAMP
|
||||
description: "block timestamp of the latest transaction with a mint price"
|
||||
tests:
|
||||
- not_null
|
||||
- dbt_expectations.expect_row_values_to_have_recent_data:
|
||||
datepart: day
|
||||
interval: 3
|
||||
- name: TX_IDS
|
||||
description: "set of transaction ids that has an associated mint price"
|
||||
tests:
|
||||
- not_null
|
||||
- name: MINT
|
||||
description: "{{ doc('mint') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: PAYER
|
||||
description: "{{ doc('mint_payer') }}"
|
||||
tests:
|
||||
- not_null:
|
||||
where: mint_price is not null
|
||||
- name: MINT_CURRENCY
|
||||
description: "{{ doc('mint_currency') }}"
|
||||
tests:
|
||||
- not_null:
|
||||
where: mint_price is not null
|
||||
- name: DECIMAL
|
||||
description: "{{ doc('decimal') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: PROGRAM_ID
|
||||
description: "{{ doc('program_id') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: MINT_PRICE
|
||||
description: "{{ doc('mint_price') }}"
|
||||
- name: _INSERTED_TIMESTAMP
|
||||
description: "{{ doc('_inserted_timestamp') }}"
|
||||
tests:
|
||||
- not_null
|
||||
171
models/silver/nfts/silver__nft_mint_price_generic.sql
Normal file
171
models/silver/nfts/silver__nft_mint_price_generic.sql
Normal file
@ -0,0 +1,171 @@
|
||||
{{ config(
|
||||
materialized = 'incremental',
|
||||
unique_key = "CONCAT_WS('-', mint, payer, mint_currency)",
|
||||
incremental_strategy = 'delete+insert',
|
||||
cluster_by = ['block_timestamp::DATE','_inserted_timestamp::DATE'],
|
||||
) }}
|
||||
|
||||
WITH base_events AS (
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
{{ ref('silver__events') }}
|
||||
WHERE succeeded
|
||||
|
||||
{% if is_incremental() %}
|
||||
AND
|
||||
_inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
base_ptb AS (
|
||||
SELECT
|
||||
distinct mint AS mint_paid,
|
||||
account,
|
||||
DECIMAL
|
||||
FROM
|
||||
{{ ref('silver___post_token_balances') }}
|
||||
|
||||
{% if is_incremental() %}
|
||||
WHERE
|
||||
_inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
metaplex_events AS (
|
||||
SELECT
|
||||
block_id,
|
||||
block_timestamp,
|
||||
tx_id,
|
||||
e.succeeded,
|
||||
e.program_id,
|
||||
e.index,
|
||||
e.instruction :accounts AS accounts,
|
||||
ARRAY_SIZE(accounts) AS num_accounts,
|
||||
e.inner_instruction,
|
||||
_inserted_timestamp
|
||||
FROM
|
||||
base_events e,
|
||||
TABLE(FLATTEN(inner_instruction :instructions)) i
|
||||
WHERE
|
||||
program_id = 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'
|
||||
AND succeeded
|
||||
AND (
|
||||
(ARRAY_SIZE(accounts) = 7
|
||||
AND accounts [5] = '11111111111111111111111111111111'
|
||||
AND accounts [6] = 'SysvarRent111111111111111111111111111111111')
|
||||
OR (ARRAY_SIZE(accounts) = 9
|
||||
AND accounts [7] = '11111111111111111111111111111111'
|
||||
AND accounts [8] = 'SysvarRent111111111111111111111111111111111')
|
||||
OR (ARRAY_SIZE(accounts) = 14
|
||||
AND accounts [11] = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
|
||||
AND accounts [12] = '11111111111111111111111111111111'
|
||||
AND accounts [13] = 'SysvarRent111111111111111111111111111111111')
|
||||
OR (ARRAY_SIZE(accounts) = 17
|
||||
AND accounts [13] = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
|
||||
AND accounts [14] = 'vau1zxA2LbssAUEF7Gpw91zMM1LvXrvpzJtmZ58rPsn'
|
||||
AND accounts [15] = '11111111111111111111111111111111'
|
||||
AND accounts [16] = 'SysvarRent111111111111111111111111111111111'))
|
||||
UNION
|
||||
SELECT
|
||||
block_id,
|
||||
block_timestamp,
|
||||
tx_id,
|
||||
e.succeeded,
|
||||
e.program_id,
|
||||
e.index,
|
||||
i.value :accounts AS accounts,
|
||||
ARRAY_SIZE(accounts) AS num_accounts,
|
||||
e.inner_instruction,
|
||||
_inserted_timestamp
|
||||
FROM
|
||||
base_events e,
|
||||
TABLE(FLATTEN(inner_instruction :instructions)) i
|
||||
WHERE
|
||||
i.value :programId :: STRING = 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'
|
||||
AND succeeded
|
||||
AND (
|
||||
(ARRAY_SIZE(accounts) = 7
|
||||
AND accounts [5] = '11111111111111111111111111111111'
|
||||
AND accounts [6] = 'SysvarRent111111111111111111111111111111111')
|
||||
OR (ARRAY_SIZE(accounts) = 9
|
||||
AND accounts [7] = '11111111111111111111111111111111'
|
||||
AND accounts [8] = 'SysvarRent111111111111111111111111111111111')
|
||||
OR (ARRAY_SIZE(accounts) = 14
|
||||
AND accounts [11] = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
|
||||
AND accounts [12] = '11111111111111111111111111111111'
|
||||
AND accounts [13] = 'SysvarRent111111111111111111111111111111111')
|
||||
OR (ARRAY_SIZE(accounts) = 17
|
||||
AND accounts [13] = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
|
||||
AND accounts [14] = 'vau1zxA2LbssAUEF7Gpw91zMM1LvXrvpzJtmZ58rPsn'
|
||||
AND accounts [15] = '11111111111111111111111111111111'
|
||||
AND accounts [16] = 'SysvarRent111111111111111111111111111111111'))
|
||||
),
|
||||
mint_price_events AS (
|
||||
SELECT
|
||||
me.block_timestamp,
|
||||
me.tx_id,
|
||||
me.index,
|
||||
i.index as inner_index,
|
||||
'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s' as program_id,
|
||||
CASE
|
||||
WHEN num_accounts in (14,17) THEN me.accounts [3] :: STRING
|
||||
ELSE me.accounts [1] :: STRING
|
||||
END AS mint,
|
||||
CASE
|
||||
WHEN num_accounts in (14,17) THEN me.accounts [6] :: STRING
|
||||
WHEN num_accounts = 9 THEN me.accounts [4] :: STRING
|
||||
ELSE me.accounts [3] :: STRING
|
||||
END AS payer,
|
||||
COALESCE(
|
||||
i.value :parsed :info :lamports :: INTEGER,
|
||||
i.value :parsed :info :amount :: INTEGER
|
||||
) AS transfer_amount,
|
||||
CASE
|
||||
WHEN i.value :parsed :info :lamports is not null THEN NULL
|
||||
ELSE i.value :parsed :info :source
|
||||
END as token_account,
|
||||
me._inserted_timestamp
|
||||
FROM
|
||||
metaplex_events me
|
||||
LEFT JOIN TABLE(FLATTEN(inner_instruction :instructions)) i
|
||||
group by 1,2,3,4,5,6,7,8,9,10
|
||||
),
|
||||
pre_final as (
|
||||
select
|
||||
e.*,
|
||||
COALESCE(
|
||||
p.mint_paid,
|
||||
'So11111111111111111111111111111111111111111'
|
||||
) AS mint_currency,
|
||||
COALESCE(p.decimal, 9) as decimal
|
||||
from mint_price_events e
|
||||
LEFT OUTER JOIN base_ptb p on e.token_account = p.account
|
||||
)
|
||||
SELECT
|
||||
p.mint,
|
||||
p.payer,
|
||||
mint_currency,
|
||||
decimal,
|
||||
p.program_id,
|
||||
SUM(p.transfer_amount / pow(10, decimal)) AS mint_price,
|
||||
array_unique_agg(tx_id) as tx_ids,
|
||||
max(block_timestamp) as block_timestamp,
|
||||
max(_inserted_timestamp) as _inserted_timestamp
|
||||
FROM
|
||||
pre_final p
|
||||
GROUP BY
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
@ -1,56 +1,49 @@
|
||||
version: 2
|
||||
models:
|
||||
- name: silver__nft_mints_tmp
|
||||
- name: silver__nft_mint_price_generic
|
||||
description: intermediary model for getting an nft's mint price
|
||||
tests:
|
||||
- dbt_utils.unique_combination_of_columns:
|
||||
combination_of_columns:
|
||||
- TX_ID
|
||||
- MINT
|
||||
- PAYER
|
||||
- MINT_CURRENCY
|
||||
columns:
|
||||
- name: BLOCK_TIMESTAMP
|
||||
description: "{{ doc('block_timestamp') }}"
|
||||
description: "block timestamp of the latest transaction with a mint price"
|
||||
tests:
|
||||
- not_null
|
||||
- dbt_expectations.expect_row_values_to_have_recent_data:
|
||||
datepart: day
|
||||
interval: 3
|
||||
- name: BLOCK_ID
|
||||
description: "{{ doc('block_id') }}"
|
||||
- name: TX_IDS
|
||||
description: "set of transaction ids that has an associated mint price"
|
||||
tests:
|
||||
- not_null
|
||||
- name: TX_ID
|
||||
description: "{{ doc('tx_id') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: SUCCEEDED
|
||||
description: "{{ doc('tx_succeeded') }}"
|
||||
tests:
|
||||
- dbt_expectations.expect_column_to_exist
|
||||
- name: PROGRAM_ID
|
||||
description: "{{ doc('program_id') }}"
|
||||
- name: MINT
|
||||
description: "{{ doc('mint') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: PURCHASER
|
||||
description: "{{ doc('purchaser') }}"
|
||||
- name: PAYER
|
||||
description: "{{ doc('mint_payer') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- not_null:
|
||||
where: mint_price is not null
|
||||
- name: MINT_CURRENCY
|
||||
description: "{{ doc('mint_currency') }}"
|
||||
tests:
|
||||
- not_null:
|
||||
where: mint_price is not null
|
||||
- name: DECIMAL
|
||||
description: "{{ doc('decimal') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: MINT
|
||||
description: "{{ doc('mint') }}"
|
||||
- name: PROGRAM_ID
|
||||
description: "{{ doc('program_id') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: MINT_PRICE
|
||||
description: "{{ doc('mint_price') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: INGESTED_AT
|
||||
description: " {{ doc('ingested_at') }} "
|
||||
tests:
|
||||
- not_null
|
||||
- name: _INSERTED_TIMESTAMP
|
||||
description: "{{ doc('_inserted_timestamp') }}"
|
||||
tests:
|
||||
186
models/silver/nfts/silver__nft_mint_price_other.sql
Normal file
186
models/silver/nfts/silver__nft_mint_price_other.sql
Normal file
@ -0,0 +1,186 @@
|
||||
{{ config(
|
||||
materialized = 'incremental',
|
||||
unique_key = "CONCAT_WS('-', mint, payer, mint_currency)",
|
||||
incremental_strategy = 'delete+insert',
|
||||
cluster_by = ['block_timestamp::DATE','_inserted_timestamp::DATE'],
|
||||
) }}
|
||||
|
||||
WITH base_events AS (
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
{{ ref('silver__events') }}
|
||||
WHERE succeeded
|
||||
{% if is_incremental() %}
|
||||
AND
|
||||
_inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
base_ptb AS (
|
||||
SELECT
|
||||
DISTINCT mint AS mint_paid,
|
||||
account,
|
||||
DECIMAL
|
||||
FROM
|
||||
{{ ref('silver___post_token_balances') }}
|
||||
|
||||
{% if is_incremental() %}
|
||||
WHERE
|
||||
_inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
--unknown program...
|
||||
hweq_fallback AS (
|
||||
SELECT
|
||||
e.block_timestamp,
|
||||
e.tx_id,
|
||||
e.index,
|
||||
i.index as inner_index,
|
||||
e.program_id,
|
||||
instruction :accounts [2] :: STRING AS mint,
|
||||
instruction :accounts [0] :: STRING AS payer,
|
||||
COALESCE(
|
||||
i.value :parsed :info :lamports :: INTEGER,
|
||||
i.value :parsed :info :amount :: INTEGER
|
||||
) AS transfer_amount,
|
||||
CASE
|
||||
WHEN i.value :parsed :info :lamports is not null THEN NULL
|
||||
ELSE i.value :parsed :info :source
|
||||
END as token_account,
|
||||
e._inserted_timestamp
|
||||
FROM
|
||||
base_events e
|
||||
LEFT JOIN TABLE(FLATTEN(inner_instruction :instructions)) i
|
||||
WHERE
|
||||
program_id = 'HWeQ1ntizxmbMwVHemf9zncf2h6RTTfLiuzbjD9wAN9e'
|
||||
AND ARRAY_SIZE(
|
||||
instruction :accounts
|
||||
) > 7
|
||||
group by 1,2,3,4,5,6,7,8,9,10
|
||||
),
|
||||
--unknown program...
|
||||
multi_mints_fallback AS (
|
||||
SELECT
|
||||
e.block_timestamp,
|
||||
e.tx_id,
|
||||
e.index,
|
||||
i.index as inner_index,
|
||||
e.program_id,
|
||||
instruction :accounts [17] :: STRING AS mint,
|
||||
instruction :accounts [2] :: STRING AS payer,
|
||||
COALESCE(
|
||||
i.value :parsed :info :lamports :: INTEGER,
|
||||
i.value :parsed :info :amount :: INTEGER
|
||||
) AS transfer_amount,
|
||||
CASE
|
||||
WHEN i.value :parsed :info :lamports is not null THEN NULL
|
||||
ELSE i.value :parsed :info :source
|
||||
END as token_account,
|
||||
e._inserted_timestamp
|
||||
FROM
|
||||
base_events e
|
||||
LEFT JOIN TABLE(FLATTEN(inner_instruction :instructions)) i
|
||||
WHERE
|
||||
program_id = '5WTCguyGQDrFosVn8M9JynwdoRpQJUPuzaembMwug35r'
|
||||
AND instruction :data :: STRING LIKE '2z8AjPpeqe%'
|
||||
AND mint is not null
|
||||
AND inner_index < 17
|
||||
group by 1,2,3,4,5,6,7,8,9,10
|
||||
UNION
|
||||
SELECT
|
||||
e.block_timestamp,
|
||||
e.tx_id,
|
||||
e.index,
|
||||
i.index as inner_index,
|
||||
e.program_id,
|
||||
instruction :accounts [21] :: STRING AS mint,
|
||||
instruction :accounts [2] :: STRING AS payer,
|
||||
COALESCE(
|
||||
i.value :parsed :info :lamports :: INTEGER,
|
||||
i.value :parsed :info :amount :: INTEGER
|
||||
) AS transfer_amount,
|
||||
CASE
|
||||
WHEN i.value :parsed :info :lamports is not null THEN NULL
|
||||
ELSE i.value :parsed :info :source
|
||||
END as token_account,
|
||||
e._inserted_timestamp
|
||||
FROM
|
||||
base_events e
|
||||
LEFT JOIN TABLE(FLATTEN(inner_instruction :instructions)) i
|
||||
WHERE
|
||||
program_id = '5WTCguyGQDrFosVn8M9JynwdoRpQJUPuzaembMwug35r'
|
||||
AND instruction :data :: STRING LIKE '2z8AjPpeqe%'
|
||||
AND mint is not null
|
||||
AND inner_index >= 17
|
||||
group by 1,2,3,4,5,6,7,8,9,10
|
||||
),
|
||||
hweq_pre_final as (
|
||||
select
|
||||
e.*,
|
||||
COALESCE(
|
||||
p.mint_paid,
|
||||
'So11111111111111111111111111111111111111111'
|
||||
) AS mint_currency,
|
||||
COALESCE(p.decimal, 9) as decimal
|
||||
from hweq_fallback e
|
||||
LEFT OUTER JOIN base_ptb p on e.token_account = p.account
|
||||
),
|
||||
multi_mints_pre_final as (
|
||||
select
|
||||
e.*,
|
||||
COALESCE(
|
||||
p.mint_paid,
|
||||
'So11111111111111111111111111111111111111111'
|
||||
) AS mint_currency,
|
||||
COALESCE(p.decimal, 9) as decimal
|
||||
from multi_mints_fallback e
|
||||
LEFT OUTER JOIN base_ptb p on e.token_account = p.account
|
||||
)
|
||||
SELECT
|
||||
p.mint,
|
||||
p.payer,
|
||||
mint_currency,
|
||||
decimal,
|
||||
p.program_id,
|
||||
SUM(p.transfer_amount / pow(10, decimal)) AS mint_price,
|
||||
array_unique_agg(tx_id) as tx_ids,
|
||||
max(block_timestamp) as block_timestamp,
|
||||
max(_inserted_timestamp) as _inserted_timestamp
|
||||
FROM
|
||||
hweq_pre_final p
|
||||
GROUP BY
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
UNION
|
||||
SELECT
|
||||
p.mint,
|
||||
p.payer,
|
||||
mint_currency,
|
||||
decimal,
|
||||
p.program_id,
|
||||
SUM(p.transfer_amount / pow(10, decimal)) AS mint_price,
|
||||
array_unique_agg(tx_id) as tx_ids,
|
||||
max(block_timestamp) as block_timestamp,
|
||||
max(_inserted_timestamp) as _inserted_timestamp
|
||||
FROM
|
||||
multi_mints_pre_final p
|
||||
GROUP BY
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
48
models/silver/nfts/silver__nft_mint_price_other.yml
Normal file
48
models/silver/nfts/silver__nft_mint_price_other.yml
Normal file
@ -0,0 +1,48 @@
|
||||
version: 2
|
||||
models:
|
||||
- name: silver__nft_mint_price_other
|
||||
description: intermediary model for getting an nft's mint price
|
||||
tests:
|
||||
- dbt_utils.unique_combination_of_columns:
|
||||
combination_of_columns:
|
||||
- MINT
|
||||
- PAYER
|
||||
- MINT_CURRENCY
|
||||
where: mint <> 'GqzH4GRCqqsNXAvx9FSK7n3pMqRCjnyns7pqe94yAV1M' # seems like a special token, actually minted twice?
|
||||
columns:
|
||||
- name: BLOCK_TIMESTAMP
|
||||
description: "block timestamp of the latest transaction with a mint price"
|
||||
tests:
|
||||
- not_null
|
||||
- name: TX_IDS
|
||||
description: "set of transaction ids that has an associated mint price"
|
||||
tests:
|
||||
- not_null
|
||||
- name: MINT
|
||||
description: "{{ doc('mint') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: PAYER
|
||||
description: "{{ doc('mint_payer') }}"
|
||||
tests:
|
||||
- not_null:
|
||||
where: mint_price is not null
|
||||
- name: MINT_CURRENCY
|
||||
description: "{{ doc('mint_currency') }}"
|
||||
tests:
|
||||
- not_null:
|
||||
where: mint_price is not null
|
||||
- name: DECIMAL
|
||||
description: "{{ doc('decimal') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: PROGRAM_ID
|
||||
description: "{{ doc('program_id') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: MINT_PRICE
|
||||
description: "{{ doc('mint_price') }}"
|
||||
- name: _INSERTED_TIMESTAMP
|
||||
description: "{{ doc('_inserted_timestamp') }}"
|
||||
tests:
|
||||
- not_null
|
||||
@ -1,115 +1,112 @@
|
||||
{{ config(
|
||||
materialized = 'incremental',
|
||||
unique_key = "CONCAT_WS('-', tx_id, mint, mint_currency)",
|
||||
unique_key = "CONCAT_WS('-', initialization_tx_id, mint, purchaser, mint_currency)",
|
||||
incremental_strategy = 'delete+insert',
|
||||
cluster_by = ['block_timestamp::DATE'],
|
||||
) }}
|
||||
|
||||
WITH b AS (
|
||||
WITH base_mint_actions AS (
|
||||
|
||||
SELECT
|
||||
tx_id
|
||||
*
|
||||
FROM
|
||||
{{ ref('silver__events') }}
|
||||
e
|
||||
{{ ref('silver__mint_actions') }}
|
||||
{% if is_incremental() %}
|
||||
WHERE
|
||||
_inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
base_mint_price AS (
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
{{ ref('silver__nft_mint_price') }}
|
||||
{% if is_incremental() %}
|
||||
WHERE
|
||||
_inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
initialization AS (
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
base_mint_actions
|
||||
WHERE
|
||||
event_type IN (
|
||||
'mintTo',
|
||||
'initializeMint'
|
||||
'initializeMint',
|
||||
'initializeMint2'
|
||||
)
|
||||
AND succeeded
|
||||
|
||||
{% if is_incremental() %}
|
||||
AND e._inserted_timestamp >= (
|
||||
),
|
||||
first_mint AS (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
*
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
EXCEPT
|
||||
SELECT
|
||||
tx_id
|
||||
FROM
|
||||
{{ ref('silver__nft_mints_tmp') }}
|
||||
m
|
||||
|
||||
{% if is_incremental() %}
|
||||
WHERE m._inserted_timestamp >= (
|
||||
base_mint_actions
|
||||
WHERE
|
||||
event_type NOT IN (
|
||||
'initializeMint',
|
||||
'initializeMint2'
|
||||
)
|
||||
AND succeeded qualify(ROW_NUMBER() over (PARTITION BY mint
|
||||
ORDER BY
|
||||
block_timestamp)) = 1
|
||||
),
|
||||
pre_final AS (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
i.block_id,
|
||||
i.block_timestamp,
|
||||
i.tx_id,
|
||||
i.succeeded,
|
||||
i.mint,
|
||||
i.decimal,
|
||||
f.mint_amount,
|
||||
i._inserted_timestamp
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
initialization i
|
||||
LEFT OUTER JOIN first_mint f
|
||||
ON i.mint = f.mint
|
||||
),
|
||||
b AS (
|
||||
SELECT
|
||||
*,
|
||||
CASE
|
||||
WHEN DECIMAL = 0
|
||||
AND mint_amount = 1 THEN 'nft'
|
||||
WHEN DECIMAL <> 0
|
||||
OR mint_amount > 1 THEN 'token'
|
||||
ELSE 'unknown'
|
||||
END AS mint_type
|
||||
FROM
|
||||
pre_final
|
||||
)
|
||||
SELECT
|
||||
block_timestamp,
|
||||
block_id,
|
||||
tx_id,
|
||||
succeeded,
|
||||
program_id,
|
||||
purchaser,
|
||||
mint_currency,
|
||||
mint,
|
||||
mint_price,
|
||||
ingested_at,
|
||||
_inserted_timestamp
|
||||
b.block_id,
|
||||
b.block_timestamp,
|
||||
b.succeeded,
|
||||
b.tx_id as initialization_tx_id,
|
||||
mp.program_id,
|
||||
mp.payer as purchaser,
|
||||
b.mint,
|
||||
mp.mint_currency,
|
||||
mp.mint_price,
|
||||
b._inserted_timestamp
|
||||
FROM
|
||||
{{ ref('silver__nft_mints_tmp') }}
|
||||
e
|
||||
{% if is_incremental() %}
|
||||
WHERE e._inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
UNION
|
||||
SELECT
|
||||
e.block_timestamp,
|
||||
e.block_id,
|
||||
e.tx_id,
|
||||
e.succeeded,
|
||||
e.program_id,
|
||||
COALESCE(
|
||||
instruction :parsed :info :mintAuthority :: STRING,
|
||||
instruction :parsed :info :multisigMintAuthority :: STRING
|
||||
) AS purchaser,
|
||||
NULL AS mint_currency,
|
||||
instruction :parsed :info :mint :: STRING AS mint,
|
||||
NULL AS mint_price,
|
||||
e.ingested_at,
|
||||
e._inserted_timestamp
|
||||
FROM
|
||||
{{ ref('silver__events') }}
|
||||
e
|
||||
INNER JOIN b
|
||||
ON b.tx_id = e.tx_id
|
||||
b
|
||||
LEFT OUTER JOIN base_mint_price mp
|
||||
ON b.mint = mp.mint
|
||||
WHERE
|
||||
event_type IN (
|
||||
'mintTo',
|
||||
'initializeMint'
|
||||
b.mint_type IN (
|
||||
'nft',
|
||||
'unknown'
|
||||
)
|
||||
|
||||
{% if is_incremental() %}
|
||||
AND e._inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
GROUP BY
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11
|
||||
|
||||
@ -4,9 +4,25 @@ models:
|
||||
tests:
|
||||
- dbt_utils.unique_combination_of_columns:
|
||||
combination_of_columns:
|
||||
- TX_ID
|
||||
- INITIALIZATION_TX_ID
|
||||
- MINT
|
||||
- PURCHASER
|
||||
- MINT_CURRENCY
|
||||
- compare_model_subset:
|
||||
name: silver__nft_mints_business_logic_test
|
||||
compare_model: ref('testing__nft_mints')
|
||||
compare_columns:
|
||||
- mint
|
||||
- purchaser
|
||||
- mint_currency
|
||||
- round(mint_price,8)
|
||||
model_condition: "where mint in ('zsFUFcetxjLCeUaNjsQE57b3c3awU79sVeTZQrsoSq6','8XQqL7wwKrGftLaSnd8Km9WnA6bwT1B1w2NXrxQfxU6t',
|
||||
'8miSwDxQNV9W7LHPRzXEMXwk4oYHU29fxFi5LAaS3Zoo','CArsPMgQyevzmE4SYDjVaeWvoNwEMsE4cwbCyXrPGtE5','YcDLuwoqB8yWcfnwNDrjoSo4iuVmTCz27ZXsh6w12mo',
|
||||
'6HBSxEKHJzS19aKhFhzWeYRM9QezKk1QGKug3QLFw8AU','3ry2VrRvehb6Z7roeXaAzzQuqheeM2wyWHTmgMUtZZSk','FUHUjD4z1YDDRGqZAL4n89HsuDEFhVLcoz47LJirCnBm',
|
||||
'FaC8SaDj6crwZA5JyucbKuTDbbTLbCSVpGbLVSXxaxJ4','BxGPRSEzHwEzX73Ep67a9u5xFc2BSuXSrAevqNMkzN8Z','HrbK1X3ooR2fBujtDSWeKQtbj1fUtptrEb7mWvsxeQQk',
|
||||
'CmejwsHB1hcQPbY7y4EjYD5gxWJEXn9G4PkXLpLoTus1','JBzLjej5DEtVupwVtn6y1mnG4HFEkm5PVxQYFNYMJzhc','J5EFUxYPxAyx5oCUUgmCrESHjhmXuzrYsscoxRvVW5Vz',
|
||||
'DCahWcCagbsW8HAqu4QMDaQZn212MrA7aN4yLNKYn3tY','58MAJPUgfSyehsKggYEeWjpNZaKw5qxnLNZ4EKeRicmq','Dq6H4jMXQkHEf3q3BocptwF7Nh6V9FZwABXuVRgRXtts',
|
||||
'Ar9mEJ7qJ1uAgkWduKGo3UYVbPMdKrmWxs5z2wgZgbgN')"
|
||||
columns:
|
||||
- name: BLOCK_TIMESTAMP
|
||||
description: "{{ doc('block_timestamp') }}"
|
||||
@ -19,7 +35,7 @@ models:
|
||||
description: "{{ doc('block_id') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: TX_ID
|
||||
- name: INITIALIZATION_TX_ID
|
||||
description: "{{ doc('tx_id') }}"
|
||||
tests:
|
||||
- not_null
|
||||
@ -30,16 +46,18 @@ models:
|
||||
- name: PROGRAM_ID
|
||||
description: "{{ doc('program_id') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- not_null:
|
||||
where: mint_price is not null
|
||||
- name: PURCHASER
|
||||
description: "{{ doc('purchaser') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- not_null:
|
||||
where: mint_price is not null
|
||||
- name: MINT_CURRENCY
|
||||
description: "{{ doc('mint_currency') }}"
|
||||
tests:
|
||||
- not_null:
|
||||
enabled: FALSE
|
||||
where: mint_price is not null
|
||||
- name: MINT
|
||||
description: "{{ doc('mint') }}"
|
||||
tests:
|
||||
@ -49,10 +67,6 @@ models:
|
||||
tests:
|
||||
- not_null:
|
||||
enabled: FALSE
|
||||
- name: INGESTED_AT
|
||||
description: " {{ doc('ingested_at') }} "
|
||||
tests:
|
||||
- not_null
|
||||
- name: _INSERTED_TIMESTAMP
|
||||
description: "{{ doc('_inserted_timestamp') }}"
|
||||
tests:
|
||||
|
||||
@ -1,307 +0,0 @@
|
||||
{{ config(
|
||||
materialized = 'incremental',
|
||||
unique_key = "CONCAT_WS('-', tx_id, mint, mint_currency)",
|
||||
incremental_strategy = 'delete+insert',
|
||||
cluster_by = ['block_timestamp::DATE'],
|
||||
) }}
|
||||
|
||||
WITH mint_tx_tmp AS (
|
||||
|
||||
SELECT
|
||||
t.tx_id,
|
||||
t.signers [0] :: STRING AS signer,
|
||||
CASE
|
||||
WHEN ARRAY_SIZE(
|
||||
t.signers
|
||||
) > 1 THEN t.signers [1] :: STRING
|
||||
ELSE NULL
|
||||
END AS potential_nft_mint,
|
||||
t.succeeded,
|
||||
silver.udf_get_all_inner_instruction_events(
|
||||
inner_instruction :instructions
|
||||
) AS inner_instruction_events
|
||||
FROM
|
||||
{{ ref('silver__events') }}
|
||||
e
|
||||
INNER JOIN {{ ref('silver__transactions') }}
|
||||
t
|
||||
ON t.tx_id = e.tx_id
|
||||
WHERE
|
||||
(event_type IN ('mintTo', 'initializeMint')
|
||||
OR (program_id = 'CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb'
|
||||
AND (ARRAY_CONTAINS('mintTo' :: variant, inner_instruction_events)
|
||||
OR ARRAY_CONTAINS('initializeMint' :: variant, inner_instruction_events))))
|
||||
|
||||
{% if is_incremental() %}
|
||||
AND e._inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
AND t._inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
mint_tx AS (
|
||||
SELECT
|
||||
DISTINCT tx_id,
|
||||
signer,
|
||||
potential_nft_mint,
|
||||
succeeded
|
||||
FROM
|
||||
mint_tx_tmp
|
||||
),
|
||||
txs_tmp AS (
|
||||
SELECT
|
||||
e.block_timestamp,
|
||||
e.block_id,
|
||||
t.tx_id,
|
||||
t.succeeded AS succeeded,
|
||||
t.signer,
|
||||
t.potential_nft_mint,
|
||||
program_id,
|
||||
e.index,
|
||||
i.index AS inner_index,
|
||||
COALESCE(
|
||||
i.value :parsed :info :lamports :: INTEGER,
|
||||
i.value :parsed :info :amount :: INTEGER
|
||||
) AS sales_amount,
|
||||
LAST_VALUE(
|
||||
i.value :parsed :info :mint :: STRING ignore nulls
|
||||
) over (
|
||||
PARTITION BY t.tx_id,
|
||||
e.index
|
||||
ORDER BY
|
||||
inner_index
|
||||
) AS nft,
|
||||
LAST_VALUE(
|
||||
i.value :parsed :info :multisigAuthority :: STRING ignore nulls
|
||||
) over (
|
||||
PARTITION BY t.tx_id,
|
||||
e.index
|
||||
ORDER BY
|
||||
inner_index
|
||||
) AS wallet,
|
||||
i.value :parsed :info :authority :: STRING AS authority,
|
||||
i.value :parsed :info :source :: STRING AS source,
|
||||
i.value: parsed :info :destination :: STRING AS destination,
|
||||
CASE
|
||||
-- marindate specific
|
||||
WHEN e.inner_instruction :instructions [0] :programId :: STRING = 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s' THEN e.instruction :accounts [3] :: STRING
|
||||
ELSE NULL
|
||||
END AS update_authority,
|
||||
e.ingested_at,
|
||||
e._inserted_timestamp
|
||||
FROM
|
||||
{{ ref('silver__events') }}
|
||||
e
|
||||
INNER JOIN mint_tx t
|
||||
ON t.tx_id = e.tx_id
|
||||
LEFT OUTER JOIN TABLE(FLATTEN(inner_instruction :instructions)) i
|
||||
WHERE
|
||||
e.event_type IS NULL
|
||||
AND (
|
||||
ARRAY_CONTAINS(
|
||||
'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s' :: variant,
|
||||
e.instruction :accounts :: ARRAY
|
||||
)
|
||||
OR e.inner_instruction :instructions [0] :programId :: STRING = 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'
|
||||
OR e.program_id IN (
|
||||
'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s',
|
||||
'CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb'
|
||||
)
|
||||
)
|
||||
AND t.succeeded = TRUE
|
||||
|
||||
{% if is_incremental() %}
|
||||
AND e._inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
txs AS (
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
txs_tmp
|
||||
WHERE
|
||||
(
|
||||
program_id NOT IN (
|
||||
'342zaQ1jgejKvPMqcnZejuZ845NtnfkpGvo9j15gDmEL',
|
||||
'TTTi5K2DS4qD95yyvvWht53qFWT8ff1Hp3xKsrp1QQf'
|
||||
)
|
||||
OR (
|
||||
program_id IN (
|
||||
'342zaQ1jgejKvPMqcnZejuZ845NtnfkpGvo9j15gDmEL',
|
||||
'TTTi5K2DS4qD95yyvvWht53qFWT8ff1Hp3xKsrp1QQf'
|
||||
)
|
||||
AND wallet IS NULL
|
||||
)
|
||||
)
|
||||
),
|
||||
transfers AS (
|
||||
SELECT
|
||||
tr.*
|
||||
FROM
|
||||
{{ ref('silver__transfers') }}
|
||||
tr
|
||||
INNER JOIN mint_tx t
|
||||
ON t.tx_id = tr.tx_id
|
||||
|
||||
{% if is_incremental() %}
|
||||
WHERE
|
||||
tr._inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
mint_currency AS (
|
||||
SELECT
|
||||
DISTINCT t.tx_id,
|
||||
p.mint AS mint_paid,
|
||||
p.account,
|
||||
p.decimal
|
||||
FROM
|
||||
txs t
|
||||
INNER JOIN {{ ref('silver___post_token_balances') }}
|
||||
p
|
||||
ON t.tx_id = p.tx_id
|
||||
WHERE
|
||||
source = p.account
|
||||
|
||||
{% if is_incremental() %}
|
||||
AND p._inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
),
|
||||
pre_final AS (
|
||||
SELECT
|
||||
block_timestamp,
|
||||
block_id,
|
||||
t.tx_id,
|
||||
succeeded,
|
||||
program_id,
|
||||
CASE
|
||||
WHEN program_id = 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s' THEN COALESCE(
|
||||
signer,
|
||||
wallet
|
||||
)
|
||||
ELSE COALESCE(
|
||||
wallet,
|
||||
signer
|
||||
)
|
||||
END AS purchaser,
|
||||
CASE
|
||||
WHEN update_authority = '6jG2QcwaJPFS8Y9SzgH2kfKPj6ERhLi9RVtH8kRahj4j' THEN -- marinade nfts are "free"
|
||||
0
|
||||
ELSE SUM(sales_amount / pow(10, COALESCE(p.decimal, 9)))
|
||||
END AS mint_price,
|
||||
COALESCE(
|
||||
p.mint_paid,
|
||||
'So11111111111111111111111111111111111111111'
|
||||
) AS mint_currency,
|
||||
COALESCE(
|
||||
nft,
|
||||
potential_nft_mint
|
||||
) AS mint,
|
||||
ingested_at,
|
||||
_inserted_timestamp
|
||||
FROM
|
||||
txs t
|
||||
LEFT OUTER JOIN mint_currency p
|
||||
ON p.tx_id = t.tx_id
|
||||
AND p.account = t.source
|
||||
WHERE
|
||||
sales_amount IS NOT NULL
|
||||
AND destination IS NOT NULL
|
||||
GROUP BY
|
||||
block_timestamp,
|
||||
block_id,
|
||||
t.tx_id,
|
||||
program_id,
|
||||
purchaser,
|
||||
succeeded,
|
||||
mint_currency,
|
||||
mint,
|
||||
update_authority,
|
||||
ingested_at,
|
||||
_inserted_timestamp
|
||||
),
|
||||
pre_pre_final AS (
|
||||
SELECT
|
||||
pf.block_timestamp,
|
||||
pf.block_id,
|
||||
pf.tx_id,
|
||||
pf.program_id,
|
||||
pf.purchaser,
|
||||
pf.succeeded,
|
||||
CASE
|
||||
WHEN tr.tx_id IS NOT NULL
|
||||
AND mint_currency = 'So11111111111111111111111111111111111111111' THEN mint_price + tr.amount
|
||||
ELSE mint_price
|
||||
END AS mint_price,
|
||||
pf.mint_currency,
|
||||
pf.mint,
|
||||
pf.ingested_at,
|
||||
pf._inserted_timestamp
|
||||
FROM
|
||||
pre_final pf
|
||||
LEFT OUTER JOIN transfers tr
|
||||
ON tr.tx_id = pf.tx_id
|
||||
AND tr.tx_from = pf.purchaser
|
||||
AND pf.program_id = 'CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb'
|
||||
)
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
pre_pre_final
|
||||
WHERE
|
||||
program_id <> 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'
|
||||
UNION
|
||||
SELECT
|
||||
block_timestamp,
|
||||
block_id,
|
||||
tx_id,
|
||||
program_id,
|
||||
purchaser,
|
||||
succeeded,
|
||||
SUM(mint_price) over (
|
||||
PARTITION BY tx_id,
|
||||
purchaser,
|
||||
mint,
|
||||
mint_currency
|
||||
) AS mint_price,
|
||||
mint_currency,
|
||||
mint,
|
||||
ingested_at,
|
||||
_inserted_timestamp
|
||||
FROM
|
||||
pre_pre_final
|
||||
WHERE
|
||||
program_id = 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'
|
||||
AND tx_id NOT IN (
|
||||
SELECT
|
||||
DISTINCT tx_id
|
||||
FROM
|
||||
pre_pre_final
|
||||
WHERE
|
||||
program_id <> 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'
|
||||
)
|
||||
AND mint IS NOT NULL qualify(ROW_NUMBER() over (PARTITION BY tx_id, purchaser, mint, mint_currency
|
||||
ORDER BY
|
||||
block_id)) = 1
|
||||
74
models/silver/silver__mint_actions.sql
Normal file
74
models/silver/silver__mint_actions.sql
Normal file
@ -0,0 +1,74 @@
|
||||
{{ config(
|
||||
materialized = 'incremental',
|
||||
unique_key = "CONCAT_WS('-', tx_id, event_type, mint)",
|
||||
incremental_strategy = 'delete+insert',
|
||||
cluster_by = ['block_timestamp::DATE','_inserted_timestamp::DATE'],
|
||||
) }}
|
||||
|
||||
WITH base_events AS (
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
{{ ref('silver__events') }}
|
||||
|
||||
{% if is_incremental() %}
|
||||
WHERE
|
||||
_inserted_timestamp >= (
|
||||
SELECT
|
||||
MAX(_inserted_timestamp)
|
||||
FROM
|
||||
{{ this }}
|
||||
)
|
||||
{% endif %}
|
||||
)
|
||||
SELECT
|
||||
block_id,
|
||||
block_timestamp,
|
||||
tx_id,
|
||||
succeeded,
|
||||
index,
|
||||
null as inner_index,
|
||||
event_type,
|
||||
instruction :parsed :info :mint :: STRING AS mint,
|
||||
instruction :parsed :info :decimals :: INTEGER AS DECIMAL,
|
||||
COALESCE(
|
||||
instruction :parsed :info :amount :: INTEGER,
|
||||
instruction :parsed :info :tokenAmount: amount :: INTEGER
|
||||
) AS mint_amount,
|
||||
_inserted_timestamp
|
||||
FROM
|
||||
base_events
|
||||
WHERE
|
||||
event_type IN (
|
||||
'mintTo',
|
||||
'initializeMint',
|
||||
'mintToChecked',
|
||||
'initializeMint2'
|
||||
)
|
||||
UNION
|
||||
SELECT
|
||||
block_id,
|
||||
block_timestamp,
|
||||
tx_id,
|
||||
succeeded,
|
||||
e.index,
|
||||
i.index as inner_index,
|
||||
i.value :parsed :type :: STRING AS event_type,
|
||||
i.value :parsed :info :mint :: STRING AS mint,
|
||||
i.value :parsed :info :decimals :: INTEGER AS DECIMAL,
|
||||
COALESCE(
|
||||
i.value :parsed :info :amount :: INTEGER,
|
||||
i.value :parsed :info :tokenAmount: amount :: INTEGER
|
||||
) AS mint_amount,
|
||||
_inserted_timestamp
|
||||
FROM
|
||||
base_events e,
|
||||
TABLE(FLATTEN(inner_instruction :instructions)) i
|
||||
WHERE
|
||||
i.value :parsed :type :: STRING IN (
|
||||
'mintTo',
|
||||
'initializeMint',
|
||||
'mintToChecked',
|
||||
'initializeMint2'
|
||||
)
|
||||
60
models/silver/silver__mint_actions.yml
Normal file
60
models/silver/silver__mint_actions.yml
Normal file
@ -0,0 +1,60 @@
|
||||
version: 2
|
||||
models:
|
||||
- name: silver__mint_actions
|
||||
description: table holding mint initialization or token minting events
|
||||
tests:
|
||||
- dbt_utils.unique_combination_of_columns:
|
||||
combination_of_columns:
|
||||
- TX_ID
|
||||
- INDEX
|
||||
- INNER_INDEX
|
||||
- EVENT_TYPE
|
||||
- MINT
|
||||
columns:
|
||||
- name: BLOCK_TIMESTAMP
|
||||
description: "{{ doc('block_timestamp') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- dbt_expectations.expect_row_values_to_have_recent_data:
|
||||
datepart: day
|
||||
interval: 3
|
||||
- name: BLOCK_ID
|
||||
description: "{{ doc('block_id') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: TX_ID
|
||||
description: "{{ doc('tx_id') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: SUCCEEDED
|
||||
description: "{{ doc('tx_succeeded') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: INDEX
|
||||
description: "{{ doc('event_index') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: INNER_INDEX
|
||||
description: Location of the inner instruction within an instruction
|
||||
- name: EVENT_TYPE
|
||||
description: "{{ doc('event_type') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: MINT
|
||||
description: "{{ doc('mint') }}"
|
||||
tests:
|
||||
- not_null
|
||||
- name: DECIMAL
|
||||
description: "{{ doc('decimal') }}"
|
||||
tests:
|
||||
- not_null:
|
||||
where: event_type in ('initializeMint','initializeMint2')
|
||||
- name: MINT_AMOUNT
|
||||
description: "{{ doc('mint_amount') }}"
|
||||
tests:
|
||||
- not_null:
|
||||
where: event_type in ('mintTo','mintToChecked')
|
||||
- name: _INSERTED_TIMESTAMP
|
||||
description: "{{ doc('_inserted_timestamp') }}"
|
||||
tests:
|
||||
- not_null
|
||||
Loading…
Reference in New Issue
Block a user