diff --git a/models/silver/validator/run_models/silver__run_stake_accounts_snapshot.sql b/models/silver/validator/run_models/silver__run_stake_accounts_snapshot.sql new file mode 100644 index 00000000..428f1ef1 --- /dev/null +++ b/models/silver/validator/run_models/silver__run_stake_accounts_snapshot.sql @@ -0,0 +1,82 @@ +{{ config( + materialized = 'incremental', + unique_key = 'test_timestamp', + tags = ['scheduled_non_core'] +) }} + +WITH table_epoch AS ( + SELECT + MAX(epoch) AS current_table_epoch + FROM + {{ ref('gov__fact_stake_accounts') }} +), + +epoch_call as ( + SELECT + live.udf_api( + 'POST', + '{service}/{Authentication}', + OBJECT_CONSTRUCT( + 'Content-Type', + 'application/json' + ), + OBJECT_CONSTRUCT( + 'id', + current_timestamp, + 'jsonrpc', + '2.0', + 'method', + 'getEpochInfo', + 'params', + [] + ), + 'Vault/prod/solana/quicknode/mainnet' + ) AS data + ), + +sol_epoch AS ( + SELECT + DATA:data:result:epoch::INT AS current_sol_epoch + FROM + epoch_call +), + +run_model AS ( + SELECT + table_epoch.current_table_epoch, + sol_epoch.current_sol_epoch, + github_actions.workflow_dispatches( + 'FlipsideCrypto', + 'solana_models', + 'dbt_run_streamline_stake_accounts_snapshot.yml', + NULL + ) AS run_stake_accounts_snapshot + FROM + table_epoch, + sol_epoch + WHERE + sol_epoch.current_sol_epoch > table_epoch.current_table_epoch +) + + +SELECT + dummy, + COALESCE( + current_sol_epoch, + 0 + ) AS current_sol_epoch, + COALESCE( + current_table_epoch, + 0 + ) AS current_table_epoch, + COALESCE( + run_stake_accounts_snapshot, + OBJECT_CONSTRUCT( + 'status', + 'skipped' + ) + ) AS run_stake_accounts_snapshot, + SYSDATE() AS test_timestamp +FROM + (SELECT 1 AS dummy) + LEFT JOIN run_model ON 1 = 1 \ No newline at end of file diff --git a/tests/test_silver__snapshot_stake_accounts_recency.sql b/tests/test_silver__snapshot_stake_accounts_recency.sql new file mode 100644 index 00000000..3fcdd86f --- /dev/null +++ b/tests/test_silver__snapshot_stake_accounts_recency.sql @@ -0,0 +1,58 @@ +{{ config( + tags = ["test_daily"] +) }} + +WITH max_block AS ( + SELECT + MAX(block_id) AS max_block_id + FROM + {{ ref('silver__blocks') }} +), +--We can't do a direct join because the blocks at the start of an epoch could be skipped and thus would not be in the blocks table +epoch_range AS ( + SELECT + e.epoch, + e.start_block, + e.end_block + FROM + {{ ref('silver__epoch') }} e + JOIN + max_block mb + ON + mb.max_block_id BETWEEN e.start_block AND e.end_block +), + +closest_block AS ( + SELECT + e.epoch, + MIN(b.block_id) AS closest_block_id, + MIN(b.block_timestamp) AS start_block_timestamp + FROM + epoch_range e + LEFT JOIN + {{ ref('silver__blocks') }} b + ON + b.block_id >= e.start_block + AND b.block_id <= e.end_block + GROUP BY + e.epoch +), + +recent_epoch_stake_account AS ( + SELECT + MAX(epoch_recorded) AS existing_max_epoch + FROM + {{ ref('silver__snapshot_stake_accounts_2') }} +) +-- Will alert (return records) if Solanas current epoch is older then 24 hours AND the stake_accounts_snapshot table doesnt have records yet for that epoch +SELECT + * +FROM + closest_block a +LEFT JOIN + recent_epoch_stake_account b +ON + a.epoch = b.existing_max_epoch +WHERE + b.existing_max_epoch IS NULL + AND a.start_block_timestamp <= (SYSDATE() - INTERVAL '24 HOUR')