Inital/setup (#1)

* initial commit

* arb set up
This commit is contained in:
Austin 2022-06-16 18:19:56 -04:00 committed by GitHub
parent a031180c61
commit 6f43a4df08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
110 changed files with 2033 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 @@
# arbitrum-models
## Profile Set Up
#### Use the following within profiles.yml
----
```yml
arbitrum:
target: dev
outputs:
dev:
type: snowflake
account: <ACCOUNT>
role: <ROLE>
user: <USERNAME>
password: <PASSWORD>
region: <REGION>
database: ARBITRUM_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: ARBITRUM
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: "arbitrum_models"
version: "1.0.0"
config-version: 2
# This setting configures which "profile" dbt uses for this project.
profile: "arbitrum"
# 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 == 'ARBITRUM' %}
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 arbitrum._internal.create_prod_clone(
'arbitrum',
'arbitrum_dev',
'internal_dev'
);
{% endset %}
{% do run_query(clone_query) %}
{% endmacro %}

View File

@ -0,0 +1,76 @@
{% 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 t*/
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_ARBITRUM`});
snowflake.execute({sqlText: `REVOKE OWNERSHIP ON FUTURE PROCEDURES IN SCHEMA ${DESTINATION_DB_NAME}.${schema} FROM ROLE DBT_CLOUD_ARBITRUM`});
snowflake.execute({sqlText: `REVOKE OWNERSHIP ON FUTURE TABLES IN SCHEMA ${DESTINATION_DB_NAME}.${schema} FROM ROLE DBT_CLOUD_ARBITRUM`});
snowflake.execute({sqlText: `REVOKE OWNERSHIP ON FUTURE VIEWS IN SCHEMA ${DESTINATION_DB_NAME}.${schema} FROM ROLE DBT_CLOUD_ARBITRUM`});
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,20 @@
{{ config (
materialized = 'view'
) }}
SELECT
record_id,
offset_id,
block_id,
block_timestamp,
network,
chain_id,
tx_count,
header,
ingested_at,
_inserted_timestamp
FROM
{{ source(
'prod',
'arbitrum_blocks'
) }}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
{% docs arb_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 arb_blocks_table_doc %}
This table contains block level data for the Arbitrum 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 arb_difficulty %}
The effort required to mine the block.
{% enddocs %}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
{% docs arb_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 arb_receipts_root %}
The root of the state trie.
{% enddocs %}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
{% docs arb_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 arb_event_index %}
Event number within a transaction.
{% enddocs %}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
{% docs arb_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 arb_logs_contract_address %}
The address interacted with for a given event.
{% enddocs %}

View File

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

View File

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

View File

@ -0,0 +1,5 @@
{% docs arb_logs_table_doc %}
This table contains flattened event logs from transactions on the Arbitrum 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 arb_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 arb_origin_from %}
The from address of this transaction.
{% enddocs %}

View File

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

View File

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

View File

@ -0,0 +1,76 @@
{% docs __overview__ %}
# Welcome to the Flipside Crypto Arbitrum 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 Arbitrum 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/arbitrum-models)
### **Quick Links to Table Documentation**
- [fact_blocks]()
- [fact_event_logs]()
- [fact_traces]()
- [fact_transactions]()
## **Data Model Overview**
The Arbitrum 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 `arbitrum.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/arbitrum-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 arb_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 arb_block_timestamp %}
The date and time at which the block was produced.
{% enddocs %}

View File

@ -0,0 +1,5 @@
{% docs arb_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 arb_from_address %}
The sending address of this transaction.
{% enddocs %}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
{% docs arb_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 arb_traces_gas %}
The gas supplied for this trace.
{% enddocs %}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
{% docs arb_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 arb_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 arb_traces_type %}
The type of internal transaction. Common trace types are `CALL`, `DELEGATECALL`, and `STATICCALL`.
{% enddocs %}

View File

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

View File

@ -0,0 +1,5 @@
{% docs arb_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 arb_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 arb_tx_fee %}
Amount paid to validate the transaction in ETH.
{% enddocs %}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
{% docs arb_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 arb_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 arb_tx_json %}
This JSON column contains the transaction details, including event logs.
{% enddocs %}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
{% docs arb_tx_table_doc %}
This table contains transaction level data for the Arbitrum Blockchain. Each transaction will have a unique transaction hash, along with transactions fees and a ETH value transferred when applicable. Transactions may be native ETH 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 arb_value %}
The value transacted in ETH.
{% 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("arb_blocks_table_doc") }}'
columns:
- name: BLOCK_NUMBER
description: '{{ doc("arb_block_number") }}'
- name: BLOCK_TIMESTAMP
description: '{{ doc("arb_block_timestamp") }}'
- name: NETWORK
description: '{{ doc("arb_network") }}'
- name: BLOCKCHAIN
description: '{{ doc("arb_blockchain") }}'
- name: TX_COUNT
description: '{{ doc("arb_tx_count") }}'
- name: DIFFICULTY
description: '{{ doc("arb_difficulty") }}'
- name: TOTAL_DIFFICULTY
description: '{{ doc("arb_total_difficulty") }}'
- name: EXTRA_DATA
description: '{{ doc("arb_extra_data") }}'
- name: GAS_LIMIT
description: '{{ doc("arb_gas_limit") }}'
- name: GAS_USED
description: '{{ doc("arb_gas_used") }}'
- name: HASH
description: '{{ doc("arb_blocks_hash") }}'
- name: PARENT_HASH
description: '{{ doc("arb_parent_hash") }}'
- name: RECEIPTS_ROOT
description: '{{ doc("arb_receipts_root") }}'
- name: SHA3_UNCLES
description: '{{ doc("arb_sha3_uncles") }}'
- name: SIZE
description: '{{ doc("arb_size") }}'
- name: UNCLE_BLOCKS
description: '{{ doc("arb_uncle_blocks") }}'
- name: BLOCK_HEADER_JSON
description: '{{ doc("arb_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("arb_logs_table_doc") }}'
columns:
- name: BLOCK_NUMBER
description: '{{ doc("arb_block_number") }}'
- name: BLOCK_TIMESTAMP
description: '{{ doc("arb_block_timestamp") }}'
- name: TX_HASH
description: '{{ doc("arb_logs_tx_hash") }}'
- name: EVENT_INDEX
description: '{{ doc("arb_event_index") }}'
- name: CONTRACT_ADDRESS
description: '{{ doc("arb_logs_contract_address") }}'
- name: CONTRACT_NAME
description: '{{ doc("arb_logs_contract_name") }}'
- name: EVENT_NAME
description: '{{ doc("arb_event_name") }}'
- name: EVENT_INPUTS
description: '{{ doc("arb_event_inputs") }}'
- name: TOPICS
description: '{{ doc("arb_topics") }}'
- name: DATA
description: '{{ doc("arb_logs_data") }}'
- name: EVENT_REMOVED
description: '{{ doc("arb_event_removed") }}'
- name: _LOG_ID
description: '{{ doc("arb_log_id_events") }}'
- name: TX_STATUS
description: '{{ doc("arb_tx_status") }}'
- name: ORIGIN_FUNCTION_SIGNATURE
description: '{{ doc("arb_origin_sig") }}'
- name: ORIGIN_FROM_ADDRESS
description: '{{ doc("arb_origin_from") }}'
- name: ORIGIN_TO_ADDRESS
description: '{{ doc("arb_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,
eth_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("arb_traces_table_doc") }}'
columns:
- name: BLOCK_NUMBER
description: '{{ doc("arb_traces_block_no") }}'
- name: BLOCK_TIMESTAMP
description: '{{ doc("arb_traces_blocktime") }}'
- name: TX_HASH
description: '{{ doc("arb_traces_tx_hash") }}'
- name: FROM_ADDRESS
description: '{{ doc("arb_traces_from") }}'
- name: TO_ADDRESS
description: '{{ doc("arb_traces_to") }}'
- name: ETH_VALUE
description: '{{ doc("arb_traces_value") }}'
- name: GAS
description: '{{ doc("arb_traces_gas") }}'
- name: GAS_USED
description: '{{ doc("arb_traces_gas_used") }}'
- name: INPUT
description: '{{ doc("arb_traces_input") }}'
- name: OUTPUT
description: '{{ doc("arb_traces_output") }}'
- name: TYPE
description: '{{ doc("arb_traces_type") }}'
- name: IDENTIFIER
description: '{{ doc("arb_traces_identifier") }}'
- name: DATA
description: '{{ doc("arb_traces_call_data") }}'
- name: TX_STATUS
description: '{{ doc("arb_tx_status") }}'
- name: SUB_TRACES
description: '{{ doc("arb_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,
eth_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("arb_tx_table_doc") }}'
columns:
- name: BLOCK_NUMBER
description: '{{ doc("arb_block_number") }}'
- name: BLOCK_TIMESTAMP
description: '{{ doc("arb_block_timestamp") }}'
- name: BLOCK_HASH
description: '{{ doc("arb_tx_block_hash") }}'
- name: TX_HASH
description: '{{ doc("arb_tx_hash") }}'
- name: NONCE
description: '{{ doc("arb_tx_nonce") }}'
- name: POSITION
description: '{{ doc("arb_tx_position") }}'
- name: FROM_ADDRESS
description: '{{ doc("arb_from_address") }}'
- name: TO_ADDRESS
description: '{{ doc("arb_to_address") }}'
- name: ETH_VALUE
description: '{{ doc("arb_value") }}'
- name: TX_FEE
description: '{{ doc("arb_tx_fee") }}'
- name: GAS_PRICE
description: '{{ doc("arb_tx_gas_price") }}'
- name: GAS_LIMIT
description: '{{ doc("arb_tx_gas_limit") }}'
- name: GAS_USED
description: '{{ doc("arb_tx_gas_used") }}'
- name: CUMULATIVE_GAS_USED
description: '{{ doc("arb_cumulative_gas_used") }}'
- name: STATUS
description: '{{ doc("arb_tx_status") }}'
- name: TX_JSON
description: '{{ doc("arb_tx_json") }}'
- name: INPUT_DATA
description: '{{ doc("arb_tx_input_data") }}'
- name: ORIGIN_FUNCTION_SIGNATURE
description: '{{ doc("arb_tx_origin_sig") }}'

View File

@ -0,0 +1,75 @@
{{ config(
materialized = 'incremental',
unique_key = "block_number",
cluster_by = ['block_timestamp::DATE']
) }}
WITH base_tables AS (
SELECT
record_id,
offset_id,
block_id,
block_timestamp,
network,
chain_id,
tx_count,
header,
ingested_at,
_inserted_timestamp
FROM
{{ ref('bronze__blocks') }}
{% if is_incremental() %}
WHERE
_inserted_timestamp >= (
SELECT
MAX(
_inserted_timestamp
)
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: 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,
_inserted_timestamp
FROM
base_tables qualify(ROW_NUMBER() over(PARTITION BY block_id
ORDER BY
_inserted_timestamp DESC)) = 1

View File

@ -0,0 +1,113 @@
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: 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,111 @@
{{ config(
materialized = 'incremental',
unique_key = "_log_id",
cluster_by = ['block_timestamp::DATE']
) }}
WITH base_txs AS (
SELECT
record_id,
tx_id,
tx_block_index,
offset_id,
block_id,
block_timestamp,
network,
chain_id,
tx,
ingested_at,
_inserted_timestamp
FROM
{{ ref('bronze__transactions') }}
{% if is_incremental() %}
WHERE
_inserted_timestamp >= (
SELECT
MAX(
_inserted_timestamp
)
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,
_inserted_timestamp :: TIMESTAMP AS _inserted_timestamp,
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,
_inserted_timestamp,
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,
_inserted_timestamp
FROM
logs qualify(ROW_NUMBER() over(PARTITION BY _log_id
ORDER BY
_inserted_timestamp DESC)) = 1

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