Add files to connect monad into balancerv3 dex#9302
Add files to connect monad into balancerv3 dex#9302jeff-dude merged 14 commits intoduneanalytics:mainfrom
Conversation
…els_balancer_v3_pools_monad.sql Co-authored-by: jeff-dude <102681548+jeff-dude@users.noreply.github.com>
…ancer_v3_monad_trades.sql Co-authored-by: jeff-dude <102681548+jeff-dude@users.noreply.github.com>
📝 WalkthroughWalkthroughThis pull request introduces Monad blockchain support to the Balancer DEX models in dbt. It adds new model definitions, SQL implementations, and source configurations for Balancer v3 pools labels, pool fees, and trade data on the Monad network, while updating existing aggregation models to include these new data sources. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
|
Thanks for the suggestions, pushing fixes |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
dbt_subprojects/dex/models/_projects/balancer/trades/monad/balancer_v3_monad_trades.sql (1)
51-57: Consider adding block_date to join/filter for partition pruning.The join with
dexs_baseand the WHERE clause filter onblockchain,project, andversion, but not onblock_date. For large tables, including the partition column improves query performance.This is a performance optimization, not a blocking issue.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@dbt_subprojects/dex/models/_projects/balancer/trades/monad/balancer_v3_monad_trades.sql` around lines 51 - 57, The query should include the partition column block_date in the join and/or WHERE so partition pruning can occur; update the JOIN between dexs (from {{ ref('dex_trades') }}) and dexs_base to also match on dexs.block_date = dexs_base.block_date and add a WHERE filter referencing dexs.block_date (or a block_date range) alongside blockchain/project/version to constrain scanned partitions and improve performance.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@dbt_subprojects/dex/models/_projects/balancer/labels/monad/labels_balancer_v3_pools_monad.sql`:
- Around line 7-158: The final SELECT uses bytearray_substring(pool_id, 1, 20)
AS address without grouping or aggregating it and also contains bare column
references; fix by computing address earlier and/or including it in the GROUP BY
and fully qualifying columns. Concretely: in the derived subquery that is
aliased as s (the SELECT from settings / s1), add address:
bytearray_substring(s1.pool_id,1,20) AS address, and then change the outer
SELECT to reference s.address and fully qualify all columns (e.g.,
s.pool_symbol, s.pool_type, s.token_symbol, s.norm_weight, s.pool_id) and
include s.address in the GROUP BY (or aggregate it consistently). Update any
other bare column usages to use their table alias (settings, s1, pools, etc.).
In
`@dbt_subprojects/dex/models/_projects/balancer/trades/monad/balancer_monad_trades.sql`:
- Around line 12-49: The selected columns in the loop are currently unqualified;
update the inner FROM to use an explicit table alias (e.g., FROM {{ dex_model }}
AS t) and prefix every selected column with that alias (t.blockchain, t.project,
t.version, t.block_month, etc.) inside the SELECT within the balancer_models
loop so all columns are fully qualified per the DuneSQL guideline.
---
Nitpick comments:
In
`@dbt_subprojects/dex/models/_projects/balancer/trades/monad/balancer_v3_monad_trades.sql`:
- Around line 51-57: The query should include the partition column block_date in
the join and/or WHERE so partition pruning can occur; update the JOIN between
dexs (from {{ ref('dex_trades') }}) and dexs_base to also match on
dexs.block_date = dexs_base.block_date and add a WHERE filter referencing
dexs.block_date (or a block_date range) alongside blockchain/project/version to
constrain scanned partitions and improve performance.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
dbt_subprojects/dex/seeds/trades/balancer_monad_base_trades_seed.csvis excluded by!**/*.csv
📒 Files selected for processing (15)
dbt_subprojects/dex/models/_projects/balancer/labels/_schema.ymldbt_subprojects/dex/models/_projects/balancer/labels/labels_balancer_v3_pools.sqldbt_subprojects/dex/models/_projects/balancer/labels/monad/labels_balancer_v3_pools_monad.sqldbt_subprojects/dex/models/_projects/balancer/pools/_schema.ymldbt_subprojects/dex/models/_projects/balancer/pools/balancer_pools_fees.sqldbt_subprojects/dex/models/_projects/balancer/pools/monad/balancer_v3_monad_pools_fees.sqldbt_subprojects/dex/models/_projects/balancer/trades/balancer_trades.sqldbt_subprojects/dex/models/_projects/balancer/trades/monad/_schema.ymldbt_subprojects/dex/models/_projects/balancer/trades/monad/balancer_monad_trades.sqldbt_subprojects/dex/models/_projects/balancer/trades/monad/balancer_v3_monad_trades.sqldbt_subprojects/dex/models/trades/monad/_schema.ymldbt_subprojects/dex/models/trades/monad/dex_monad_base_trades.sqldbt_subprojects/dex/models/trades/monad/platforms/balancer_v3_monad_base_trades.sqlsources/_subprojects_outputs/dex/_sources.ymlsources/balancer/monad/balancer_monad_sources.yml
| WITH token_data AS ( | ||
| SELECT | ||
| pool, | ||
| ARRAY_AGG(FROM_HEX(json_extract_scalar(token, '$.token')) ORDER BY token_index) AS tokens | ||
| FROM ( | ||
| SELECT | ||
| pool, | ||
| tokenConfig, | ||
| SEQUENCE(1, CARDINALITY(tokenConfig)) AS token_index_array | ||
| FROM {{ source('balancer_v3_monad', 'Vault_evt_PoolRegistered') }} | ||
| ) AS pool_data | ||
| CROSS JOIN UNNEST(tokenConfig, token_index_array) AS t(token, token_index) | ||
| GROUP BY 1 | ||
| ), | ||
|
|
||
| pools AS ( | ||
| SELECT | ||
| pool_id, | ||
| zip.tokens AS token_address, | ||
| zip.weights / POWER(10, 18) AS normalized_weight, | ||
| symbol, | ||
| pool_type | ||
| FROM ( | ||
| SELECT | ||
| c.pool AS pool_id, | ||
| t.tokens, | ||
| w.weights, | ||
| cc.symbol, | ||
| 'weighted' AS pool_type | ||
| FROM token_data c | ||
| INNER JOIN {{ source('balancer_v3_monad', 'WeightedPoolFactory_call_create') }} cc | ||
| ON c.pool = cc.output_pool | ||
| CROSS JOIN UNNEST(c.tokens) WITH ORDINALITY t(tokens, pos) | ||
| CROSS JOIN UNNEST(cc.normalizedWeights) WITH ORDINALITY w(weights, pos) | ||
| WHERE t.pos = w.pos | ||
|
|
||
| UNION ALL | ||
|
|
||
| SELECT | ||
| c.pool AS pool_id, | ||
| t.tokens, | ||
| 0 AS weights, | ||
| cc.symbol, | ||
| 'stable' AS pool_type | ||
| FROM token_data c | ||
| INNER JOIN {{ source('balancer_v3_monad', 'StablePoolFactory_call_create') }} cc | ||
| ON c.pool = cc.output_pool | ||
| CROSS JOIN UNNEST(c.tokens) AS t(tokens) | ||
|
|
||
| UNION ALL | ||
|
|
||
| SELECT | ||
| c.pool AS pool_id, | ||
| t.tokens, | ||
| 0 AS weights, | ||
| cc.symbol, | ||
| 'stable' AS pool_type | ||
| FROM token_data c | ||
| INNER JOIN {{ source('balancer_v3_monad', 'StableSurgePoolFactory_call_create') }} cc | ||
| ON c.pool = cc.output_pool | ||
| CROSS JOIN UNNEST(c.tokens) AS t(tokens) | ||
|
|
||
| UNION ALL | ||
|
|
||
| SELECT | ||
| c.pool AS pool_id, | ||
| t.tokens, | ||
| 0 AS weights, | ||
| cast(null as varchar) AS symbol, | ||
| 'LBP' AS pool_type | ||
| FROM token_data c | ||
| INNER JOIN {{ source('balancer_v3_monad', 'LBPoolFactory_call_create') }} cc | ||
| ON c.pool = cc.output_pool | ||
| CROSS JOIN UNNEST(c.tokens) AS t(tokens) | ||
|
|
||
| UNION ALL | ||
|
|
||
| SELECT | ||
| c.pool AS pool_id, | ||
| t.tokens AS token_address, | ||
| 0 AS normalized_weight, | ||
| cc.symbol, | ||
| 'ECLP' AS pool_type | ||
| FROM token_data c | ||
| INNER JOIN {{ source('balancer_v3_monad', 'GyroECLPPoolFactory_call_create') }} cc | ||
| ON c.pool = cc.output_pool | ||
| CROSS JOIN UNNEST(c.tokens) AS t(tokens) | ||
| ) zip | ||
| ), | ||
|
|
||
| pool_token_symbols AS ( | ||
| SELECT | ||
| p.pool_id, | ||
| p.pool_type, | ||
| coalesce(t.symbol, '?') AS token_symbol | ||
| FROM pools p | ||
| LEFT JOIN {{ source('tokens', 'erc20') }} t ON p.token_address = t.contract_address | ||
| AND t.blockchain = 'monad' | ||
| ), | ||
|
|
||
| pool_symbols_derived AS ( | ||
| SELECT | ||
| pool_id, | ||
| pool_type, | ||
| lower(array_join(array_agg(token_symbol ORDER BY token_symbol), '/')) AS derived_pool_symbol | ||
| FROM pool_token_symbols | ||
| WHERE pool_type = 'LBP' | ||
| GROUP BY pool_id, pool_type | ||
| ), | ||
|
|
||
| settings AS ( | ||
| SELECT | ||
| p.pool_id, | ||
| coalesce(t.symbol, '?') AS token_symbol, | ||
| p.normalized_weight, | ||
| coalesce(p.symbol, ps.derived_pool_symbol) AS pool_symbol, | ||
| p.pool_type | ||
| FROM pools p | ||
| LEFT JOIN {{ source('tokens', 'erc20') }} t ON p.token_address = t.contract_address | ||
| AND t.blockchain = 'monad' | ||
| LEFT JOIN pool_symbols_derived ps ON p.pool_id = ps.pool_id AND p.pool_type = ps.pool_type | ||
| ) | ||
|
|
||
| SELECT | ||
| 'monad' AS blockchain, | ||
| bytearray_substring(pool_id, 1, 20) AS address, | ||
| CASE WHEN pool_type IN ('stable', 'LBP', 'ECLP') | ||
| THEN lower(pool_symbol) | ||
| ELSE lower(concat(array_join(array_agg(token_symbol ORDER BY token_symbol), '/'), ' ', | ||
| array_join(array_agg(cast(norm_weight AS varchar) ORDER BY token_symbol), '/'))) | ||
| END AS name, | ||
| pool_type, | ||
| 'balancer_v3_pool' AS category, | ||
| 'balancerlabs' AS contributor, | ||
| 'query' AS source, | ||
| TIMESTAMP'2024-12-01 00:00' AS created_at, | ||
| now() AS updated_at, | ||
| 'balancer_v3_pools_monad' AS model_name, | ||
| 'identifier' AS label_type | ||
|
|
||
| FROM ( | ||
| SELECT | ||
| s1.pool_id, | ||
| token_symbol, | ||
| pool_symbol, | ||
| cast(100 * normalized_weight AS integer) AS norm_weight, | ||
| pool_type | ||
| FROM settings s1 | ||
| GROUP BY s1.pool_id, token_symbol, pool_symbol, normalized_weight, pool_type | ||
| ) s | ||
| GROUP BY pool_id, pool_symbol, pool_type | ||
| ORDER BY 1 No newline at end of file |
There was a problem hiding this comment.
Fix aggregation error: address expression isn’t in GROUP BY (will fail compilation).
In the final SELECT, bytearray_substring(pool_id, 1, 20) AS address is selected but not aggregated and not included in the GROUP BY (Line 132 vs Line 157). Trino/DuneSQL will reject this.
Also, this new model uses many bare column references without table aliases; please align it to the project SQL guideline (explicit aliases + prefixed columns) before merging.
Proposed fix (minimal) to make GROUP BY valid
SELECT
'monad' AS blockchain,
- bytearray_substring(pool_id, 1, 20) AS address,
+ bytearray_substring(pool_id, 1, 20) AS address,
CASE WHEN pool_type IN ('stable', 'LBP', 'ECLP')
THEN lower(pool_symbol)
ELSE lower(concat(array_join(array_agg(token_symbol ORDER BY token_symbol), '/'), ' ',
array_join(array_agg(cast(norm_weight AS varchar) ORDER BY token_symbol), '/')))
END AS name,
pool_type,
'balancer_v3_pool' AS category,
'balancerlabs' AS contributor,
'query' AS source,
TIMESTAMP'2024-12-01 00:00' AS created_at,
now() AS updated_at,
'balancer_v3_pools_monad' AS model_name,
'identifier' AS label_type
@@
) s
-GROUP BY pool_id, pool_symbol, pool_type
+GROUP BY
+ pool_id,
+ bytearray_substring(pool_id, 1, 20),
+ pool_symbol,
+ pool_type
ORDER BY 1As per coding guidelines, “Always use explicit table aliases — prefix all columns (t.column, p.column), never use bare column names in DuneSQL/Trino SQL”.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@dbt_subprojects/dex/models/_projects/balancer/labels/monad/labels_balancer_v3_pools_monad.sql`
around lines 7 - 158, The final SELECT uses bytearray_substring(pool_id, 1, 20)
AS address without grouping or aggregating it and also contains bare column
references; fix by computing address earlier and/or including it in the GROUP BY
and fully qualifying columns. Concretely: in the derived subquery that is
aliased as s (the SELECT from settings / s1), add address:
bytearray_substring(s1.pool_id,1,20) AS address, and then change the outer
SELECT to reference s.address and fully qualify all columns (e.g.,
s.pool_symbol, s.pool_type, s.token_symbol, s.norm_weight, s.pool_id) and
include s.address in the GROUP BY (or aggregate it consistently). Update any
other bare column usages to use their table alias (settings, s1, pools, etc.).
| SELECT * | ||
| FROM ( | ||
| {% for dex_model in balancer_models %} | ||
| SELECT | ||
| blockchain, | ||
| project, | ||
| version, | ||
| block_month, | ||
| block_date, | ||
| block_time, | ||
| block_number, | ||
| token_bought_symbol, | ||
| token_sold_symbol, | ||
| token_pair, | ||
| token_bought_amount, | ||
| token_sold_amount, | ||
| token_bought_amount_raw, | ||
| token_sold_amount_raw, | ||
| amount_usd, | ||
| token_bought_address, | ||
| token_sold_address, | ||
| taker, | ||
| maker, | ||
| pool_id, | ||
| swap_fee, | ||
| project_contract_address, | ||
| pool_symbol, | ||
| pool_type, | ||
| tx_hash, | ||
| tx_from, | ||
| tx_to, | ||
| evt_index | ||
| FROM {{ dex_model }} | ||
| {% if not loop.last %} | ||
| UNION ALL | ||
| {% endif %} | ||
| {% endfor %} | ||
| ) |
There was a problem hiding this comment.
New SQL model: add a table alias and prefix selected columns (guideline requirement).
Right now the SELECT projects bare column names from {{ dex_model }}; please alias the FROM and prefix (t.blockchain, etc.) to match the repo’s DuneSQL guideline.
Proposed fix (mechanical aliasing)
SELECT *
FROM (
{% for dex_model in balancer_models %}
SELECT
- blockchain,
- project,
- version,
- block_month,
- block_date,
- block_time,
- block_number,
- token_bought_symbol,
- token_sold_symbol,
- token_pair,
- token_bought_amount,
- token_sold_amount,
- token_bought_amount_raw,
- token_sold_amount_raw,
- amount_usd,
- token_bought_address,
- token_sold_address,
- taker,
- maker,
- pool_id,
- swap_fee,
- project_contract_address,
- pool_symbol,
- pool_type,
- tx_hash,
- tx_from,
- tx_to,
- evt_index
- FROM {{ dex_model }}
+ t.blockchain,
+ t.project,
+ t.version,
+ t.block_month,
+ t.block_date,
+ t.block_time,
+ t.block_number,
+ t.token_bought_symbol,
+ t.token_sold_symbol,
+ t.token_pair,
+ t.token_bought_amount,
+ t.token_sold_amount,
+ t.token_bought_amount_raw,
+ t.token_sold_amount_raw,
+ t.amount_usd,
+ t.token_bought_address,
+ t.token_sold_address,
+ t.taker,
+ t.maker,
+ t.pool_id,
+ t.swap_fee,
+ t.project_contract_address,
+ t.pool_symbol,
+ t.pool_type,
+ t.tx_hash,
+ t.tx_from,
+ t.tx_to,
+ t.evt_index
+ FROM {{ dex_model }} t
{% if not loop.last %}
UNION ALL
{% endif %}
{% endfor %}
)As per coding guidelines, “Always use explicit table aliases — prefix all columns (t.column, p.column), never use bare column names in DuneSQL/Trino SQL”.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@dbt_subprojects/dex/models/_projects/balancer/trades/monad/balancer_monad_trades.sql`
around lines 12 - 49, The selected columns in the loop are currently
unqualified; update the inner FROM to use an explicit table alias (e.g., FROM {{
dex_model }} AS t) and prefix every selected column with that alias
(t.blockchain, t.project, t.version, t.block_month, etc.) inside the SELECT
within the balancer_models loop so all columns are fully qualified per the
DuneSQL guideline.
Thank you for contributing to Spellbook 🪄
Please open the PR in draft and mark as ready when you want to request a review.
Description:
Add files to connect monad into Balancer V3
quick links for more information: