Initial/setup (#1)

* stash

* clean up mistakes

* clean up docs

* dbt docs
This commit is contained in:
Austin 2022-06-07 19:13:08 -04:00 committed by GitHub
parent 66e65359ad
commit dc4fb4acc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
110 changed files with 2040 additions and 1 deletions

16
.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
target/
dbt_modules/
# newer versions of dbt use this directory instead of dbt_modules for test dependencies
dbt_packages/
logs/
.venv/
.python-version
# Visual Studio Code files
*/.vscode
*.code-workspace
.history/
**/.DS_Store
.vscode/

View File

@ -1 +1,45 @@
# polygon-models
## Profile Set Up
#### Use the following within profiles.yml
----
```yml
polygon:
target: dev
outputs:
dev:
type: snowflake
account: <ACCOUNT>
role: <ROLE>
user: <USERNAME>
password: <PASSWORD>
region: <REGION>
database: POLYGON_DEV
warehouse: <WAREHOUSE>
schema: silver
threads: 12
client_session_keep_alive: False
query_tag: <TAG>
prod:
type: snowflake
account: <ACCOUNT>
role: <ROLE>
user: <USERNAME>
password: <PASSWORD>
region: <REGION>
database: POLYGON
warehouse: <WAREHOUSE>
schema: silver
threads: 12
client_session_keep_alive: False
query_tag: <TAG>
```
### Resources:
- Learn more about dbt [in the docs](https://docs.getdbt.com/docs/introduction)
- Check out [Discourse](https://discourse.getdbt.com/) for commonly asked questions and answers
- Join the [chat](https://community.getdbt.com/) on Slack for live discussions and support
- Find [dbt events](https://events.getdbt.com) near you
- Check out [the blog](https://blog.getdbt.com/) for the latest news on dbt's development and best practices

0
analysis/.gitkeep Normal file
View File

0
data/.gitkeep Normal file
View File

39
dbt_project.yml Normal file
View File

@ -0,0 +1,39 @@
# Name your project! Project names should contain only lowercase characters
# and underscores. A good package name should reflect your organization's
# name or the intended use of these models
name: "polygon_models"
version: "1.0.0"
config-version: 2
# This setting configures which "profile" dbt uses for this project.
profile: "polygon"
# These configurations specify where dbt should look for different types of files.
# The `source-paths` config, for example, states that models in this project can be
# found in the "models/" directory. You probably won't need to change these!
model-paths: ["models"]
analysis-paths: ["analysis"]
test-paths: ["tests"]
seed-paths: ["data"]
macro-paths: ["macros"]
snapshot-paths: ["snapshots"]
target-path: "target" # directory which will store compiled SQL files
clean-targets: # directories to be removed by `dbt clean`
- "target"
- "dbt_modules"
- "dbt_packages"
on-run-start:
- "{{ create_sps() }}"
- "{{ create_udfs() }}"
# Configuring models
# Full documentation: https://docs.getdbt.com/docs/configuring-models
# In this example config, we tell dbt to build all models in the example/ directory
# as tables. These settings can be overridden in the individual model files
# using the `{{ config(...) }}` macro.
vars:
"dbt_date:time_zone": GMT

1
docs/catalog.json Normal file

File diff suppressed because one or more lines are too long

102
docs/index.html Normal file

File diff suppressed because one or more lines are too long

1
docs/manifest.json Normal file

File diff suppressed because one or more lines are too long

0
macros/.gitkeep Normal file
View File

6
macros/create_sps.sql Normal file
View File

@ -0,0 +1,6 @@
{% macro create_sps() %}
{% if target.database == 'POLYGON' %}
CREATE schema IF NOT EXISTS _internal;
{{ sp_create_prod_clone('_internal') }};
{% endif %}
{% endmacro %}

11
macros/create_udfs.sql Normal file
View File

@ -0,0 +1,11 @@
{% macro create_udfs() %}
{% set sql %}
CREATE schema if NOT EXISTS silver;
{{ create_js_hex_to_int() }};
{{ create_udf_hex_to_int(
schema = "public"
) }}
{% endset %}
{% do run_query(sql) %}
{% endmacro %}

View File

@ -0,0 +1,11 @@
{% macro generate_schema_name(custom_schema_name=none, node=none) -%}
{% set node_name = node.name %}
{% set split_name = node_name.split('__') %}
{{ split_name[0] | trim }}
{%- endmacro %}
{% macro generate_alias_name(custom_alias_name=none, node=none) -%}
{% set node_name = node.name %}
{% set split_name = node_name.split('__') %}
{{ split_name[1] | trim }}
{%- endmacro %}

6
macros/js_hextoint.sql Normal file
View File

@ -0,0 +1,6 @@
{% macro create_js_hex_to_int() %}
CREATE
OR REPLACE FUNCTION {{ target.schema }}.js_hex_to_int (
s STRING
) returns DOUBLE LANGUAGE javascript AS 'if (S !== null) { yourNumber = parseInt(S, 16); } return yourNumber'
{% endmacro %}

21
macros/python/udfs.sql Normal file
View File

@ -0,0 +1,21 @@
{% macro create_udf_hex_to_int(schema) %}
create or replace function {{ schema }}.udf_hex_to_int(hex string)
returns string
language python
runtime_version = '3.8'
handler = 'hex_to_int'
as
$$
def hex_to_int(hex) -> str:
"""
Converts hex (of any size) to int (as a string). Snowflake and java script can only handle up to 64-bit (38 digits of precision)
select hex_to_int('200000000000000000000000000000211');
>> 680564733841876926926749214863536423441
select hex_to_int('0x200000000000000000000000000000211');
>> 680564733841876926926749214863536423441
select hex_to_int(NULL);
>> NULL
"""
return str(int(hex, 16)) if hex else None
$$;
{% endmacro %}

View File

@ -0,0 +1,10 @@
{% macro run_sp_create_prod_clone() %}
{% set clone_query %}
call polygon._internal.create_prod_clone(
'polygon',
'polygon_dev',
'internal_dev'
);
{% endset %}
{% do run_query(clone_query) %}
{% endmacro %}

View File

@ -0,0 +1,72 @@
{% macro sp_create_prod_clone(target_schema) -%}
CREATE
OR REPLACE PROCEDURE {{ target_schema }}.create_prod_clone(
source_db_name STRING,
destination_db_name STRING,
role_name STRING
) returns BOOLEAN LANGUAGE javascript EXECUTE AS caller AS $$ snowflake.execute(
{ sqlText: `BEGIN TRANSACTION;` }
);
try { snowflake.execute(
{ sqlText: `DROP DATABASE IF EXISTS ${DESTINATION_DB_NAME}` }
);
snowflake.execute(
{ sqlText: `CREATE DATABASE ${DESTINATION_DB_NAME} CLONE ${SOURCE_DB_NAME}` }
);
snowflake.execute(
{ sqlText: `DROP SCHEMA ${DESTINATION_DB_NAME}._INTERNAL` }
);
/* this only needs to be in prod */
var existing_schemas = snowflake.execute(
{ sqlText: `SELECT table_schema FROM ${DESTINATION_DB_NAME}.INFORMATION_SCHEMA.TABLE_PRIVILEGES WHERE grantor IS NOT NULL GROUP BY 1 UNION SELECT 'PUBLIC';` }
);
WHILE (existing_schemas.next()) { var schema = existing_schemas.getColumnValue(1) snowflake.execute(
{ sqlText: `GRANT OWNERSHIP ON SCHEMA ${DESTINATION_DB_NAME}.${schema} TO ROLE ${ROLE_NAME} COPY CURRENT GRANTS;` }
);
snowflake.execute(
{ sqlText: `REVOKE OWNERSHIP ON FUTURE FUNCTIONS IN SCHEMA ${DESTINATION_DB_NAME}.${schema} FROM ROLE DBT_CLOUD_POLYGON` }
);
snowflake.execute(
{ sqlText: `REVOKE OWNERSHIP ON FUTURE PROCEDURES IN SCHEMA ${DESTINATION_DB_NAME}.${schema} FROM ROLE DBT_CLOUD_POLYGON` }
);
snowflake.execute(
{ sqlText: `REVOKE OWNERSHIP ON FUTURE TABLES IN SCHEMA ${DESTINATION_DB_NAME}.${schema} FROM ROLE DBT_CLOUD_POLYGON` }
);
snowflake.execute(
{ sqlText: `REVOKE OWNERSHIP ON FUTURE VIEWS IN SCHEMA ${DESTINATION_DB_NAME}.${schema} FROM ROLE DBT_CLOUD_POLYGON` }
);
snowflake.execute(
{ sqlText: `GRANT OWNERSHIP ON FUTURE FUNCTIONS IN SCHEMA ${DESTINATION_DB_NAME}.${schema} TO ROLE ${ROLE_NAME};` }
);
snowflake.execute(
{ sqlText: `GRANT OWNERSHIP ON FUTURE PROCEDURES IN SCHEMA ${DESTINATION_DB_NAME}.${schema} TO ROLE ${ROLE_NAME};` }
);
snowflake.execute(
{ sqlText: `GRANT OWNERSHIP ON FUTURE TABLES IN SCHEMA ${DESTINATION_DB_NAME}.${schema} TO ROLE ${ROLE_NAME};` }
);
snowflake.execute(
{ sqlText: `GRANT OWNERSHIP ON FUTURE VIEWS IN SCHEMA ${DESTINATION_DB_NAME}.${schema} TO ROLE ${ROLE_NAME};` }
);} var existing_tables = snowflake.execute(
{ sqlText: `SELECT table_schema, table_name FROM ${DESTINATION_DB_NAME}.INFORMATION_SCHEMA.TABLE_PRIVILEGES WHERE grantor IS NOT NULL GROUP BY 1,2;` }
);
WHILE (existing_tables.next()) { var schema = existing_tables.getColumnValue(1) var table_name = existing_tables.getColumnValue(2) snowflake.execute(
{ sqlText: `GRANT OWNERSHIP ON TABLE ${DESTINATION_DB_NAME}.${schema}.${table_name} TO ROLE ${ROLE_NAME} COPY CURRENT GRANTS;` }
);} var existing_functions = snowflake.execute(
{ sqlText: `SELECT function_schema, function_name, concat('(',array_to_string(regexp_substr_all(argument_signature, 'VARCHAR|NUMBER|FLOAT|ARRAY|VARIANT|OBJECT|DOUBLE'),','),')') as argument_signature FROM ${DESTINATION_DB_NAME}.INFORMATION_SCHEMA.FUNCTIONS;` }
);
WHILE (existing_functions.next()) { var schema = existing_functions.getColumnValue(1) var function_name = existing_functions.getColumnValue(2) var argument_signature = existing_functions.getColumnValue(3) snowflake.execute(
{ sqlText: `GRANT OWNERSHIP ON FUNCTION ${DESTINATION_DB_NAME}.${schema}.${function_name}${argument_signature} to role ${ROLE_NAME} REVOKE CURRENT GRANTS;` }
);} var existing_procedures = snowflake.execute(
{ sqlText: `SELECT procedure_schema, procedure_name, concat('(',array_to_string(regexp_substr_all(argument_signature, 'VARCHAR|NUMBER|FLOAT|ARRAY|VARIANT|OBJECT|DOUBLE'),','),')') as argument_signature FROM ${DESTINATION_DB_NAME}.INFORMATION_SCHEMA.PROCEDURES;` }
);
WHILE (existing_procedures.next()) { var schema = existing_procedures.getColumnValue(1) var procedure_name = existing_procedures.getColumnValue(2) var argument_signature = existing_procedures.getColumnValue(3) snowflake.execute(
{ sqlText: `GRANT OWNERSHIP ON PROCEDURE ${DESTINATION_DB_NAME}.${schema}.${procedure_name}${argument_signature} to role ${ROLE_NAME} REVOKE CURRENT GRANTS;` }
);} snowflake.execute(
{ sqlText: `GRANT OWNERSHIP ON DATABASE ${DESTINATION_DB_NAME} TO ROLE ${ROLE_NAME};` }
) snowflake.execute(
{ sqlText: `COMMIT;` }
);} catch (err) { snowflake.execute(
{ sqlText: `ROLLBACK;` }
);
throw(err);} RETURN TRUE $$
{%- endmacro %}

View File

@ -0,0 +1,34 @@
{% test sequence_gaps(
model,
partition_by,
column_name
) %}
{%- set partition_sql = partition_by | join(", ") -%}
{%- set previous_column = "prev_" ~ column_name -%}
WITH source AS (
SELECT
{{ partition_sql + "," if partition_sql }}
{{ column_name }},
LAG(
{{ column_name }},
1
) over (
{{ "PARTITION BY " ~ partition_sql if partition_sql }}
ORDER BY
{{ column_name }} ASC
) AS {{ previous_column }}
FROM
{{ model }}
)
SELECT
{{ partition_sql + "," if partition_sql }}
{{ previous_column }},
{{ column_name }},
{{ column_name }} - {{ previous_column }}
- 1 AS gap
FROM
source
WHERE
{{ column_name }} - {{ previous_column }} <> 1
ORDER BY
gap DESC {% endtest %}

33
macros/tests/tx_gaps.sql Normal file
View File

@ -0,0 +1,33 @@
{% macro tx_gaps(
model
) %}
WITH block_base AS (
SELECT
block_number,
tx_count
FROM
{{ ref('silver__blocks') }}
),
model_name AS (
SELECT
block_number,
COUNT(
DISTINCT tx_hash
) AS model_tx_count
FROM
{{ model }}
GROUP BY
block_number
)
SELECT
block_base.block_number,
tx_count,
model_name.block_number,
model_tx_count
FROM
block_base
LEFT JOIN model_name
ON block_base.block_number = model_name.block_number
WHERE
tx_count <> model_tx_count
{% endmacro %}

View File

@ -0,0 +1,22 @@
{{ config (
materialized = 'view'
) }}
SELECT
record_id,
offset_id,
block_id,
block_timestamp,
network,
chain_id,
tx_count,
header,
ingested_at
FROM
{{ source(
'prod',
'polygon_blocks'
) }}
qualify(ROW_NUMBER() over(PARTITION BY block_id
ORDER BY
ingested_at DESC)) = 1

View File

@ -0,0 +1,20 @@
{{ config (
materialized = 'view'
) }}
SELECT
record_id,
tx_id,
tx_block_index,
offset_id,
block_id,
block_timestamp,
network,
chain_id,
tx,
ingested_at
FROM
{{ source(
'prod',
'polygon_txs'
) }}

View File

@ -0,0 +1,5 @@
{% docs poly_block_header_json %}
This JSON column contains the block header details.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_blockchain %}
The blockchain on which transactions are being confirmed.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_blocks_hash %}
The hash of the block header for a given block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_blocks_nonce %}
Block nonce is a value used during mining to demonstrate proof of work for a given block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_blocks_table_doc %}
This table contains block level data for the Polygon Blockchain. This table can be used to analyze trends at a block level, for example gas fees vs. total transactions over time. For more information on EVM transactions, please see [Etherscan Resources](https://etherscan.io/directory/Learning_Resources/Ethereum) or [The Ethereum Organization](https://ethereum.org/en/developers/docs/blocks/)
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_difficulty %}
The effort required to mine the block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_extra_data %}
Any data included by the validator for a given block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_gas_limit %}
Total gas limit provided by all transactions in the block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_gas_used %}
Total gas used in the block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_miner %}
Miner who successfully added a given block to the blockchain.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_network %}
The network on the blockchain used by a transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_parent_hash %}
The hash of the block from which a given block is generated. Also known as the parent block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_receipts_root %}
The root of the state trie.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_sha3_uncles %}
The mechanism which Ethereum Javascript RLP encodes an empty string.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_size %}
Block size, which is determined by a given block's gas limit.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_total_difficulty %}
Total difficulty of the chain at a given block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_count %}
Total number of transactions within a block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_uncle_blocks %}
Uncle blocks occur when two blocks are mined and broadcasted at the same time, with the same block number. The block validated across the most nodes will be added to the primary chain, and the other one becomes an uncle block. Miners do receive rewards for uncle blocks.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_event_index %}
Event number within a transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_event_inputs %}
The decoded event inputs for a given event.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_event_name %}
The decoded event name for a given event.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_event_removed %}
Whether the event has been removed from the transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_origin_sig %}
The function signature of this transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_log_id_events %}
This is the primary key for this table. This is a concatenation of the transaction hash and the event index at which the event occurred.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_logs_contract_address %}
The address interacted with for a given event.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_logs_contract_name %}
The name of the contract or token, where possible.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_logs_data %}
The un-decoded event data.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_logs_table_doc %}
This table contains flattened event logs from transactions on the Polygon Blockchain. Transactions may have multiple events, which are denoted by the event index for a transaction hash. Therefore, this table is unique on the combination of transaction hash and event index. Event names are decoded in this table where possible. The event inputs column will contain the log details in JSON format. Specific fields can be pulled from this column using the following sample format: ```event_inputs:<FILED_NAME>::<DATA TYPE> as <FIELD_NAME>```.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_logs_tx_hash %}
Transaction hash is a unique 66-character identifier that is generated when a transaction is executed. This field will not be unique in this table, as a given transaction can include multiple events.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_origin_from %}
The from address of this transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_origin_to %}
The to address of this transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_topics %}
The un-decoded event input topics.
{% enddocs %}

View File

@ -0,0 +1,76 @@
{% docs __overview__ %}
# Welcome to the Flipside Crypto Polygon Models Documentation!
## **What is Flipside?**
[Flipside Crypto](https://flipsidecrypto.xyz/earn) provides Community Enabled Crypto Analytics, allowing our users to create and share data insights on the crypto projects they care most about.
**Flipside Crypto puts pre-modeled and labeled blockchain data in the hands of communities.**
Through dashboard and visualization tools, as well as auto-generated API endpoints, data analysts can easily create queries that answer any question via a tool called [Velocity](https://app.flipsidecrypto.com/velocity?nav=Discover).
**Community members earn bounties for answering questions with data.**
Bounties provide incentive and direction, so crypto projects can quickly source the data insights they need in order to grow.
**Flipside works directly with leading crypto projects to reward on-demand analytics through structured bounty programs.**
Questions sourced directly from the community provide insight into what communities care about as well as analytics needed to drive ecosystem engagement and growth.
## **What does this documentation cover?**
The documentation included here details the design of the Polygon tables and views available via [Flipside Crypto.](https://flipsidecrypto.xyz/earn) For more information on how these models are built, please see [the github repository.](https://github.com/FlipsideCrypto/polygon-models)
### **Quick Links to Table Documentation**
- [fact_blocks]()
- [fact_event_logs]()
- [fact_traces]()
- [fact_transactions]()
## **Data Model Overview**
The Polygon models are built a few different ways, but the core fact table are built using three layers of sql models: **bronze, silver, and gold (or core).**
- Bronze: Data is loaded in from the source as a view
- Silver: All necessary parsing, filtering, de-duping, and other transformations are done here
- Gold (or core): Final views and tables that are available in Velocity
The dimension tables are sourced from a variety of on-chain and off-chain sources.
Convenience views (denoted ez_) are a combination of different fact and dimension tables.
A user-defined-function (UDF) is available to decode hex encoded values to integers in this database. You can call this UDF by using `polygon.public.udf_hex_to_int(FIELD)`.
## **Using dbt docs**
### Navigation
You can use the ```Project``` and ```Database``` navigation tabs on the left side of the window to explore the models in the project.
### Database Tab
This view shows relations (tables and views) grouped into database schemas. Note that ephemeral models are *not* shown in this interface, as they do not exist in the database.
### Graph Exploration
You can click the blue icon on the bottom-right corner of the page to view the lineage graph of your models.
On model pages, you'll see the immediate parents and children of the model you're exploring. By clicking the Expand button at the top-right of this lineage pane, you'll be able to see all of the models that are used to build, or are built from, the model you're exploring.
Once expanded, you'll be able to use the ```--models``` and ```--exclude``` model selection syntax to filter the models in the graph. For more information on model selection, check out the [dbt docs](https://docs.getdbt.com/docs/model-selection-syntax).
Note that you can also right-click on models to interactively filter and explore the graph.
### **More information**
- [Flipside](https://flipsidecrypto.xyz/earn)
- [Velocity](https://app.flipsidecrypto.com/velocity?nav=Discover)
- [Tutorials](https://docs.flipsidecrypto.com/our-data/tutorials)
- [Github](https://github.com/FlipsideCrypto/polygon-models)
- [Query Editor Shortcuts](https://docs.flipsidecrypto.com/velocity/query-editor-shortcuts)
- [What is dbt?](https://docs.getdbt.com/docs/introduction)
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_block_number %}
Also known as block height. The block number, which indicates the length of the blockchain, increases after the addition of each new block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_block_timestamp %}
The date and time at which the block was produced.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_decimals %}
The number of decimal places this contract needs adjusted where token values exist. For example, use the decimal field to correctly transform raw amounts in ```fact_token_transfers```.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_from_address %}
The sending address of this transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_ingested_at %}
Internal column.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_to_address %}
The receiving address of this transaction. This can be a contract address.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_block_no %}
The block number of this transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_blocktime %}
The block timestamp of this transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_call_data %}
The raw JSON data for this trace.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_from %}
The sending address of this trace. This is not necessarily the from address of the transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_gas %}
The gas supplied for this trace.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_gas_used %}
The gas used for this trace.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_identifier %}
This field represents the position and type of the trace within the transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_input %}
The input data for this trace.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_output %}
The output data for this trace.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_sub %}
The amount of nested sub traces for this trace.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_table_doc %}
This table contains flattened trace data for internal contract calls on the Polygon Blockchain. Hex encoded fields can be decoded to integers by using `polygon.public.udf_hex_to_int()`.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_to %}
The receiving address of this trace. This is not necessarily the to address of the transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_tx_hash %}
The transaction hash for the trace. Please note, this is not necessarily unique in this table as transactions frequently have multiple traces.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_type %}
The type of internal transaction. Common trace types are `CALL`, `DELEGATECALL`, and `STATICCALL`.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_traces_value %}
The amount of MATIC transferred in this trace.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_cumulative_gas_used %}
The total amount of gas used when this transaction was executed in the block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_block_hash %}
Block hash is a unique 66-character identifier that is generate when a block is produced.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_fee %}
Amount paid to validate the transaction in MATIC.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_gas_limit %}
Maximum amount of gas allocated for the transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_gas_price %}
Cost per unit of gas in Gwei.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_gas_used %}
Gas used by transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_hash %}
Transaction hash is a unique 66-character identifier that is generated when a transaction is executed.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_input_data %}
This column contains additional data for this transaction, and is commonly used as part of a contract interaction or as a message to the recipient.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_json %}
This JSON column contains the transaction details, including event logs.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_nonce %}
The number of transactions sent from a given address.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_origin_sig %}
The function signature of the contract call.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_position %}
The position of the transaction within the block.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_status %}
Status of the transaction.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_tx_table_doc %}
This table contains transaction level data for the Polygon Blockchain. Each transaction will have a unique transaction hash, along with transactions fees and a MATIC value transferred when applicable. Transactions may be native MATIC transfers or interactions with contract addresses. For more information, please see [The Ethereum Organization - Transactions](https://ethereum.org/en/developers/docs/transactions/)
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs poly_value %}
The value transacted in Matic.
{% enddocs %}

View File

@ -0,0 +1,26 @@
{{ config(
materialized = 'view',
persist_docs ={ "relation": true,
"columns": true }
) }}
SELECT
block_number,
block_timestamp,
network,
blockchain,
tx_count,
difficulty,
total_difficulty,
extra_data,
gas_limit,
gas_used,
HASH,
parent_hash,
receipts_root,
sha3_uncles,
SIZE,
uncle_blocks,
block_header_json
FROM
{{ ref('silver__blocks') }}

View File

@ -0,0 +1,40 @@
version: 2
models:
- name: core__fact_blocks
description: '{{ doc("poly_blocks_table_doc") }}'
columns:
- name: BLOCK_NUMBER
description: '{{ doc("poly_block_number") }}'
- name: BLOCK_TIMESTAMP
description: '{{ doc("poly_block_timestamp") }}'
- name: NETWORK
description: '{{ doc("poly_network") }}'
- name: BLOCKCHAIN
description: '{{ doc("poly_blockchain") }}'
- name: TX_COUNT
description: '{{ doc("poly_tx_count") }}'
- name: DIFFICULTY
description: '{{ doc("poly_difficulty") }}'
- name: TOTAL_DIFFICULTY
description: '{{ doc("poly_total_difficulty") }}'
- name: EXTRA_DATA
description: '{{ doc("poly_extra_data") }}'
- name: GAS_LIMIT
description: '{{ doc("poly_gas_limit") }}'
- name: GAS_USED
description: '{{ doc("poly_gas_used") }}'
- name: HASH
description: '{{ doc("poly_blocks_hash") }}'
- name: PARENT_HASH
description: '{{ doc("poly_parent_hash") }}'
- name: RECEIPTS_ROOT
description: '{{ doc("poly_receipts_root") }}'
- name: SHA3_UNCLES
description: '{{ doc("poly_sha3_uncles") }}'
- name: SIZE
description: '{{ doc("poly_size") }}'
- name: UNCLE_BLOCKS
description: '{{ doc("poly_uncle_blocks") }}'
- name: BLOCK_HEADER_JSON
description: '{{ doc("poly_block_header_json") }}'

View File

@ -0,0 +1,25 @@
{{ config(
materialized = 'view',
persist_docs ={ "relation": true,
"columns": true }
) }}
SELECT
block_number,
block_timestamp,
tx_hash,
origin_function_signature,
origin_from_address,
origin_to_address,
event_index,
contract_address,
contract_name,
event_name,
event_inputs,
topics,
DATA,
event_removed,
tx_status,
_log_id
FROM
{{ ref('silver__logs') }}

View File

@ -0,0 +1,38 @@
version: 2
models:
- name: core__fact_event_logs
description: '{{ doc("poly_logs_table_doc") }}'
columns:
- name: BLOCK_NUMBER
description: '{{ doc("poly_block_number") }}'
- name: BLOCK_TIMESTAMP
description: '{{ doc("poly_block_timestamp") }}'
- name: TX_HASH
description: '{{ doc("poly_logs_tx_hash") }}'
- name: EVENT_INDEX
description: '{{ doc("poly_event_index") }}'
- name: CONTRACT_ADDRESS
description: '{{ doc("poly_logs_contract_address") }}'
- name: CONTRACT_NAME
description: '{{ doc("poly_logs_contract_name") }}'
- name: EVENT_NAME
description: '{{ doc("poly_event_name") }}'
- name: EVENT_INPUTS
description: '{{ doc("poly_event_inputs") }}'
- name: TOPICS
description: '{{ doc("poly_topics") }}'
- name: DATA
description: '{{ doc("poly_logs_data") }}'
- name: EVENT_REMOVED
description: '{{ doc("poly_event_removed") }}'
- name: _LOG_ID
description: '{{ doc("poly_log_id_events") }}'
- name: TX_STATUS
description: '{{ doc("poly_tx_status") }}'
- name: ORIGIN_FUNCTION_SIGNATURE
description: '{{ doc("poly_origin_sig") }}'
- name: ORIGIN_FROM_ADDRESS
description: '{{ doc("poly_origin_from") }}'
- name: ORIGIN_TO_ADDRESS
description: '{{ doc("poly_origin_to") }}'

View File

@ -0,0 +1,24 @@
{{ config(
materialized = 'view',
persist_docs ={ "relation": true,
"columns": true }
) }}
SELECT
tx_hash,
block_number,
block_timestamp,
from_address,
to_address,
matic_value,
gas,
gas_used,
input,
output,
TYPE,
identifier,
DATA,
tx_status,
sub_traces
FROM
{{ ref('silver__traces') }}

View File

@ -0,0 +1,40 @@
version: 2
models:
- name: core__fact_traces
description: '{{ doc("poly_traces_table_doc") }}'
columns:
- name: BLOCK_NUMBER
description: '{{ doc("poly_traces_block_no") }}'
- name: BLOCK_TIMESTAMP
description: '{{ doc("poly_traces_blocktime") }}'
- name: TX_HASH
description: '{{ doc("poly_traces_tx_hash") }}'
- name: FROM_ADDRESS
description: '{{ doc("poly_traces_from") }}'
- name: TO_ADDRESS
description: '{{ doc("poly_traces_to") }}'
- name: MATIC_VALUE
description: '{{ doc("poly_traces_value") }}'
- name: GAS
description: '{{ doc("poly_traces_gas") }}'
- name: GAS_USED
description: '{{ doc("poly_traces_gas_used") }}'
- name: INPUT
description: '{{ doc("poly_traces_input") }}'
- name: OUTPUT
description: '{{ doc("poly_traces_output") }}'
- name: TYPE
description: '{{ doc("poly_traces_type") }}'
- name: IDENTIFIER
description: '{{ doc("poly_traces_identifier") }}'
- name: DATA
description: '{{ doc("poly_traces_call_data") }}'
- name: TX_STATUS
description: '{{ doc("poly_tx_status") }}'
- name: SUB_TRACES
description: '{{ doc("poly_traces_sub") }}'

View File

@ -0,0 +1,27 @@
{{ config(
materialized = 'view',
persist_docs ={ "relation": true,
"columns": true }
) }}
SELECT
block_number,
block_timestamp,
block_hash,
tx_hash,
nonce,
POSITION,
origin_function_signature,
from_address,
to_address,
matic_value,
tx_fee,
gas_price,
gas_limit,
gas_used,
cumulative_Gas_Used,
input_data,
status,
tx_json
FROM
{{ ref('silver__transactions') }}

View File

@ -0,0 +1,42 @@
version: 2
models:
- name: core__fact_transactions
description: '{{ doc("poly_tx_table_doc") }}'
columns:
- name: BLOCK_NUMBER
description: '{{ doc("poly_block_number") }}'
- name: BLOCK_TIMESTAMP
description: '{{ doc("poly_block_timestamp") }}'
- name: BLOCK_HASH
description: '{{ doc("poly_tx_block_hash") }}'
- name: TX_HASH
description: '{{ doc("poly_tx_hash") }}'
- name: NONCE
description: '{{ doc("poly_tx_nonce") }}'
- name: POSITION
description: '{{ doc("poly_tx_position") }}'
- name: FROM_ADDRESS
description: '{{ doc("poly_from_address") }}'
- name: TO_ADDRESS
description: '{{ doc("poly_to_address") }}'
- name: MATIC_VALUE
description: '{{ doc("poly_value") }}'
- name: TX_FEE
description: '{{ doc("poly_tx_fee") }}'
- name: GAS_PRICE
description: '{{ doc("poly_tx_gas_price") }}'
- name: GAS_LIMIT
description: '{{ doc("poly_tx_gas_limit") }}'
- name: GAS_USED
description: '{{ doc("poly_tx_gas_used") }}'
- name: CUMULATIVE_GAS_USED
description: '{{ doc("poly_cumulative_gas_used") }}'
- name: STATUS
description: '{{ doc("poly_tx_status") }}'
- name: TX_JSON
description: '{{ doc("poly_tx_json") }}'
- name: INPUT_DATA
description: '{{ doc("poly_tx_input_data") }}'
- name: ORIGIN_FUNCTION_SIGNATURE
description: '{{ doc("poly_tx_origin_sig") }}'

View File

@ -0,0 +1,75 @@
{{ config(
materialized = 'incremental',
unique_key = "block_number",
cluster_by = ['ingested_at::DATE']
) }}
WITH base_tables AS (
SELECT
record_id,
offset_id,
block_id,
block_timestamp,
network,
chain_id,
tx_count,
header,
ingested_at
FROM
{{ ref('bronze__blocks') }}
{% if is_incremental() %}
WHERE
ingested_at >= (
SELECT
MAX(
ingested_at
)
FROM
{{ this }}
)
{% endif %}
)
SELECT
block_id :: INTEGER AS block_number,
block_timestamp :: TIMESTAMP AS block_timestamp,
network :: STRING AS network,
chain_id :: STRING AS blockchain,
tx_count :: INTEGER AS tx_count,
udf_hex_to_int(
header :difficulty :: STRING
) :: INTEGER AS difficulty,
udf_hex_to_int(
header :totalDifficulty :: STRING
) :: INTEGER AS total_difficulty,
header: extraData :: STRING AS extra_data,
udf_hex_to_int(
header :gasLimit :: STRING
) :: INTEGER AS gas_limit,
udf_hex_to_int(
header :gasUsed :: STRING
) :: INTEGER AS gas_used,
header: "hash" :: STRING AS HASH,
header: parentHash :: STRING AS parent_hash,
header: miner :: STRING AS miner,
header: nonce :: STRING AS nonce,
header: receiptsRoot :: STRING AS receipts_root,
header: sha3Uncles :: STRING AS sha3_uncles,
udf_hex_to_int(
header: "size" :: STRING
) :: INTEGER AS SIZE,
CASE
WHEN header: uncles [1] :: STRING IS NOT NULL THEN CONCAT(
header: uncles [0] :: STRING,
', ',
header: uncles [1] :: STRING
)
ELSE header: uncles [0] :: STRING
END AS uncle_blocks,
ingested_at :: TIMESTAMP AS ingested_at,
header :: OBJECT AS block_header_json
FROM
base_tables qualify(ROW_NUMBER() over(PARTITION BY block_id
ORDER BY
ingested_at DESC)) = 1

View File

@ -0,0 +1,123 @@
version: 2
models:
- name: silver__blocks
tests:
- dbt_utils.unique_combination_of_columns:
combination_of_columns:
- BLOCK_NUMBER
- sequence_gaps:
column_name: BLOCK_NUMBER
where: BLOCK_TIMESTAMP < CURRENT_DATE - 1
columns:
- name: BLOCK_NUMBER
tests:
- not_null
- dbt_expectations.expect_column_values_to_be_in_type_list:
column_type_list:
- NUMBER
- FLOAT
- name: BLOCK_TIMESTAMP
tests:
- not_null
- dbt_expectations.expect_row_values_to_have_recent_data:
datepart: day
interval: 1
- dbt_expectations.expect_column_values_to_be_in_type_list:
column_type_list:
- TIMESTAMP_NTZ
- name: NETWORK
tests:
- not_null
- dbt_expectations.expect_column_values_to_be_in_type_list:
column_type_list:
- STRING
- VARCHAR
- name: BLOCKCHAIN
tests:
- not_null
- dbt_expectations.expect_column_values_to_be_in_type_list:
column_type_list:
- STRING
- VARCHAR
- name: TX_COUNT
tests:
- not_null
- dbt_expectations.expect_column_values_to_be_in_type_list:
column_type_list:
- NUMBER
- FLOAT
- name: DIFFICULTY
tests:
- not_null
- dbt_expectations.expect_column_values_to_be_in_type_list:
column_type_list:
- NUMBER
- FLOAT
- name: TOTAL_DIFFICULTY
tests:
- not_null
- dbt_expectations.expect_column_values_to_be_in_type_list:
column_type_list:
- NUMBER
- FLOAT
- name: EXTRA_DATA
tests:
- not_null
- name: GAS_LIMIT
tests:
- not_null
- dbt_expectations.expect_column_values_to_be_in_type_list:
column_type_list:
- NUMBER
- FLOAT
- name: GAS_USED
tests:
- not_null
- dbt_expectations.expect_column_values_to_be_in_type_list:
column_type_list:
- NUMBER
- FLOAT
- name: HASH
tests:
- not_null
- dbt_expectations.expect_column_values_to_match_regex:
regex: 0[xX][0-9a-fA-F]+
- name: PARENT_HASH
tests:
- not_null
- dbt_expectations.expect_column_values_to_match_regex:
regex: 0[xX][0-9a-fA-F]+
- name: MINER
tests:
- not_null
- dbt_expectations.expect_column_values_to_match_regex:
regex: 0[xX][0-9a-fA-F]+
- name: NONCE
tests:
- not_null
- dbt_expectations.expect_column_values_to_match_regex:
regex: 0[xX][0-9a-fA-F]+
- name: RECEIPTS_ROOT
tests:
- not_null
- dbt_expectations.expect_column_values_to_match_regex:
regex: 0[xX][0-9a-fA-F]+
- name: SHA3_UNCLES
tests:
- not_null
- dbt_expectations.expect_column_values_to_match_regex:
regex: 0[xX][0-9a-fA-F]+
- name: SIZE
tests:
- not_null
- dbt_expectations.expect_column_values_to_be_in_type_list:
column_type_list:
- NUMBER
- name: BLOCK_HEADER_JSON
tests:
- not_null
- dbt_expectations.expect_column_values_to_be_in_type_list:
column_type_list:
- OBJECT

View File

@ -0,0 +1,108 @@
{{ config(
materialized = 'incremental',
unique_key = "_log_id",
cluster_by = ['ingested_at::DATE'],
post_hook = "ALTER TABLE {{ this }} ADD SEARCH OPTIMIZATION"
) }}
WITH base_txs AS (
SELECT
record_id,
tx_id,
tx_block_index,
offset_id,
block_id,
block_timestamp,
network,
chain_id,
tx,
ingested_at
FROM
{{ ref('bronze__transactions') }}
{% if is_incremental() %}
WHERE
ingested_at >= (
SELECT
MAX(
ingested_at
)
FROM
{{ this }}
)
{% endif %}
),
logs_raw AS (
SELECT
block_id,
block_timestamp,
tx_id AS tx_hash,
tx :receipt :logs AS full_logs,
ingested_at :: TIMESTAMP AS ingested_at,
CASE
WHEN tx :receipt :status :: STRING = '0x1' THEN 'SUCCESS'
ELSE 'FAIL'
END AS tx_status,
SUBSTR(
tx :input :: STRING,
1,
10
) AS origin_function_signature,
tx :from :: STRING AS origin_from_address,
tx :to :: STRING AS origin_to_address
FROM
base_txs
),
logs AS (
SELECT
block_id,
block_timestamp,
tx_hash,
origin_function_signature,
origin_from_address,
origin_to_address,
tx_status,
ingested_at,
udf_hex_to_int(
VALUE :logIndex :: STRING
) :: INTEGER AS event_index,
VALUE :address :: STRING AS contract_address,
VALUE :decoded :contractName :: STRING AS contract_name,
VALUE :decoded :eventName :: STRING AS event_name,
VALUE :decoded :inputs :: OBJECT AS event_inputs,
VALUE :topics AS topics,
VALUE :data :: STRING AS DATA,
VALUE :removed :: STRING AS event_removed
FROM
logs_raw,
LATERAL FLATTEN (
input => full_logs
)
)
SELECT
concat_ws(
'-',
tx_hash,
event_index
) AS _log_id,
block_id AS block_number,
block_timestamp,
tx_hash,
origin_function_signature,
origin_from_address,
origin_to_address,
ingested_at,
event_index,
contract_address,
contract_name,
event_name,
event_inputs,
topics,
DATA,
event_removed,
tx_status
FROM
logs qualify(ROW_NUMBER() over(PARTITION BY _log_id
ORDER BY
ingested_at DESC)) = 1

Some files were not shown because too many files have changed in this diff Show More