Skip to content

Commit 448dc4e

Browse files
jeff-dudecursoragenttomfutago
authored
feat(dex): integrate Cronos DEXes (VVS Finance, Cronaswap, Ferro) (#9844)
* feat(dex): integrate Cronos DEXes (VVS Finance, Cronaswap, Ferro) Add Cronos chain to dex.trades with platform base trade models for: - VVS Finance v2 (UniswapV2 fork) and v3 (UniswapV3 fork) - Cronaswap v1 and v2 (UniswapV2 forks) - Ferro (Saddle/StableSwap fork) Includes cronos raw base sources, decoded dex sources, chain-level union models (dex_cronos_base_trades / trades / token_volumes_daily), seed scaffolding, dex.info entries, and registers cronos in dex.trades. Co-authored-by: jeff-dude <jeff-dude@users.noreply.github.com> * fix(dex): correct cronos decoded source names and consolidate cronaswap Point VVS v2/v3 models at the actual decoded tables (namespace is vvsfinance, not vvs_finance; VVSPair/VVSV3Pool/VVSFactory/VVSV3Factory event tables). Collapse cronaswap into a single non-versioned model: on-chain and CronaSwap docs show one AMM factory (0x73a48f...); the 'V2' was MasterChefV2 yield farming, not a DEX version. * test(dex): seed cronos dex base_trades from on-chain ground truth Populate VVS (v2+v3), Cronaswap, and Ferro base_trades seeds with real swaps whose expected bought/sold tokens and raw amounts are derived independently from the pool's ERC20 Transfer events (not the DEX swap decoding), so the check_dex_base_trades_seed test validates model logic against on-chain truth. VVS v2 and Cronaswap rows will fail until their fleet-wide decode backfills complete. * chore(dex): align VVS Cronos model names * Add not_null tests on merge keys for Cronos base_trades models Applied via @cursor push command * fix(dex): wire cronos into dex.token_volumes_daily global union Co-authored-by: jeff-dude <jeff-dude@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: jeff-dude <jeff-dude@users.noreply.github.com> Co-authored-by: tomfutago <35136350+tomfutago@users.noreply.github.com>
1 parent 0768a0b commit 448dc4e

17 files changed

Lines changed: 485 additions & 1 deletion

dbt_subprojects/dex/models/dex_info.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,7 @@ FROM (VALUES
258258
, ('bitget_dex_aggregator', 'Bitget Wallet Aggregator', 'Aggregator', 'BitgetWalletAggregator')
259259
, ('tessera_v', 'Tessera-V', 'Direct', 'tessera_v')
260260
, ('bulba', 'Bulba', 'Direct', 'bulba')
261+
, ('vvs_finance', 'VVS Finance', 'Direct', 'VVS_finance')
262+
, ('cronaswap', 'CronaSwap', 'Direct', 'CronaSwap_org')
263+
, ('ferro', 'Ferro', 'Direct', 'FerroProtocol')
261264
) AS temp_table (project, name, marketplace_type, x_username)

dbt_subprojects/dex/models/trades/_schema.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ models:
44
- name: dex_trades
55
meta:
66
docs_slug: /curated/dex-trades/evm/dex-trades
7-
blockchain: arbitrum, avalanche_c, base, bnb, celo, ethereum, fantom, gnosis, kaia, optimism, polygon, scroll, zksync, linea, blast, sei, ronin, flare, boba, sonic, corn, berachain, sophon
7+
blockchain: arbitrum, avalanche_c, base, bnb, celo, cronos, ethereum, fantom, gnosis, kaia, optimism, polygon, scroll, zksync, linea, blast, sei, ronin, flare, boba, sonic, corn, berachain, sophon
88
sector: dex
99
short_description: "Detailed data on trades executed via decentralized exchanges (DEXs), containing one or many trades per transaction across all EVM chains."
1010
contributors: 0xRob, hosuke, jeff-dude, tomfutago, viniabussafi
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
version: 2
2+
3+
models:
4+
- name: dex_cronos_trades
5+
data_tests:
6+
- check_columns_dex_trades
7+
- dbt_utils.unique_combination_of_columns:
8+
arguments:
9+
combination_of_columns:
10+
- blockchain
11+
- project
12+
- version
13+
- tx_hash
14+
- evt_index
15+
- dbt_utils.accepted_range:
16+
arguments:
17+
column_name: amount_usd
18+
max_value: 1000000000 # $1b is an arbitrary number, intended to flag outlier amounts early
19+
20+
- name: dex_cronos_base_trades
21+
22+
- name: vvs_finance_v2_cronos_base_trades
23+
meta:
24+
blockchain: cronos
25+
sector: dex
26+
project: vvs_finance
27+
contributors: jeff-dude
28+
config:
29+
tags: ["cronos", "dex", "trades", "vvs_finance", "v2"]
30+
description: "VVS Finance v2 Cronos base trades"
31+
data_tests:
32+
- dbt_utils.unique_combination_of_columns:
33+
arguments:
34+
combination_of_columns:
35+
- tx_hash
36+
- evt_index
37+
- check_dex_base_trades_seed:
38+
arguments:
39+
seed_file: ref('vvs_finance_cronos_base_trades_seed')
40+
filter:
41+
version: 2
42+
columns:
43+
- name: tx_hash
44+
data_tests:
45+
- not_null
46+
- name: evt_index
47+
data_tests:
48+
- not_null
49+
50+
- name: vvs_finance_v3_cronos_base_trades
51+
meta:
52+
blockchain: cronos
53+
sector: dex
54+
project: vvs_finance
55+
contributors: jeff-dude
56+
config:
57+
tags: ["cronos", "dex", "trades", "vvs_finance", "v3"]
58+
description: "VVS Finance v3 Cronos base trades"
59+
data_tests:
60+
- dbt_utils.unique_combination_of_columns:
61+
arguments:
62+
combination_of_columns:
63+
- tx_hash
64+
- evt_index
65+
- check_dex_base_trades_seed:
66+
arguments:
67+
seed_file: ref('vvs_finance_cronos_base_trades_seed')
68+
filter:
69+
version: 3
70+
columns:
71+
- name: tx_hash
72+
data_tests:
73+
- not_null
74+
- name: evt_index
75+
data_tests:
76+
- not_null
77+
78+
- name: cronaswap_cronos_base_trades
79+
meta:
80+
blockchain: cronos
81+
sector: dex
82+
project: cronaswap
83+
contributors: jeff-dude
84+
config:
85+
tags: ["cronos", "dex", "trades", "cronaswap"]
86+
description: "Cronaswap cronos base trades"
87+
data_tests:
88+
- dbt_utils.unique_combination_of_columns:
89+
arguments:
90+
combination_of_columns:
91+
- tx_hash
92+
- evt_index
93+
- check_dex_base_trades_seed:
94+
arguments:
95+
seed_file: ref('cronaswap_cronos_base_trades_seed')
96+
filter:
97+
version: 1
98+
columns:
99+
- name: tx_hash
100+
data_tests:
101+
- not_null
102+
- name: evt_index
103+
data_tests:
104+
- not_null
105+
106+
- name: ferro_cronos_base_trades
107+
meta:
108+
blockchain: cronos
109+
sector: dex
110+
project: ferro
111+
contributors: jeff-dude
112+
config:
113+
tags: ["cronos", "dex", "trades", "ferro"]
114+
description: "Ferro cronos base trades"
115+
data_tests:
116+
- dbt_utils.unique_combination_of_columns:
117+
arguments:
118+
combination_of_columns:
119+
- tx_hash
120+
- evt_index
121+
- check_dex_base_trades_seed:
122+
arguments:
123+
seed_file: ref('ferro_cronos_base_trades_seed')
124+
columns:
125+
- name: tx_hash
126+
data_tests:
127+
- not_null
128+
- name: evt_index
129+
data_tests:
130+
- not_null
131+
132+
- name: dex_cronos_token_volumes_daily
133+
data_tests:
134+
- dbt_utils.unique_combination_of_columns:
135+
arguments:
136+
combination_of_columns:
137+
- blockchain
138+
- token_address
139+
- block_date
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{{ config(
2+
schema = 'dex_cronos'
3+
, alias = 'base_trades'
4+
, partition_by = ['block_month']
5+
, materialized = 'incremental'
6+
, file_format = 'delta'
7+
, incremental_strategy = 'merge'
8+
, unique_key = ['blockchain', 'project', 'version', 'tx_hash', 'evt_index']
9+
, incremental_predicates = [incremental_predicate('DBT_INTERNAL_DEST.block_time')]
10+
)
11+
}}
12+
13+
{% set base_models = [
14+
ref('vvs_finance_v2_cronos_base_trades'),
15+
ref('vvs_finance_v3_cronos_base_trades'),
16+
ref('cronaswap_cronos_base_trades'),
17+
ref('ferro_cronos_base_trades'),
18+
] %}
19+
20+
{{ dex_base_trades_macro(
21+
blockchain = 'cronos',
22+
base_models = base_models
23+
) }}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{{ config(
2+
schema = 'dex_cronos'
3+
, alias = 'token_volumes_daily'
4+
, partition_by = ['block_month']
5+
, materialized = 'incremental'
6+
, file_format = 'delta'
7+
, incremental_strategy = 'merge'
8+
, unique_key = ['blockchain', 'token_address', 'block_date']
9+
, incremental_predicates = [incremental_predicate('DBT_INTERNAL_DEST.block_date')]
10+
)
11+
}}
12+
13+
14+
WITH daily_token_volumes AS (
15+
{{
16+
dex_token_volumes_daily(
17+
blockchain = 'cronos'
18+
, dev_dates = var('dev_dates', false)
19+
)
20+
}}
21+
)
22+
23+
SELECT *
24+
FROM daily_token_volumes
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{{ config(
2+
schema = 'dex_cronos'
3+
, alias = 'trades'
4+
, partition_by = ['block_month']
5+
, materialized = 'incremental'
6+
, file_format = 'delta'
7+
, incremental_strategy = 'merge'
8+
, unique_key = ['blockchain', 'project', 'version', 'tx_hash', 'evt_index', 'block_month']
9+
, incremental_predicates = [incremental_predicate('DBT_INTERNAL_DEST.block_time')]
10+
, merge_skip_unchanged = true
11+
)
12+
}}
13+
14+
WITH dexs AS (
15+
{{
16+
enrich_dex_trades(
17+
base_trades = ref('dex_cronos_base_trades')
18+
, filter = "1=1"
19+
, tokens_erc20_model = source('tokens', 'erc20')
20+
, blockchain = 'cronos'
21+
)
22+
}}
23+
)
24+
25+
SELECT
26+
blockchain
27+
, project
28+
, version
29+
, block_month
30+
, block_date
31+
, block_time
32+
, block_number
33+
, token_bought_symbol
34+
, token_sold_symbol
35+
, token_pair
36+
, token_bought_amount
37+
, token_sold_amount
38+
, token_bought_amount_raw
39+
, token_sold_amount_raw
40+
, amount_usd
41+
, token_bought_address
42+
, token_sold_address
43+
, taker
44+
, maker
45+
, project_contract_address
46+
, tx_hash
47+
, tx_from
48+
, tx_to
49+
, evt_index
50+
, current_timestamp AS _updated_at
51+
FROM
52+
dexs
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{{ config(
2+
schema = 'cronaswap_cronos'
3+
, alias = 'base_trades'
4+
, materialized = 'incremental'
5+
, file_format = 'delta'
6+
, incremental_strategy = 'merge'
7+
, unique_key = ['tx_hash', 'evt_index']
8+
, incremental_predicates = [incremental_predicate('DBT_INTERNAL_DEST.block_time')]
9+
)
10+
}}
11+
12+
{{
13+
uniswap_compatible_v2_trades(
14+
blockchain = 'cronos'
15+
, project = 'cronaswap'
16+
, version = '1'
17+
, Pair_evt_Swap = source('cronaswap_cronos', 'CronaSwapPair_evt_Swap')
18+
, Factory_evt_PairCreated = source('cronaswap_cronos', 'CronaSwapFactory_evt_PairCreated')
19+
)
20+
}}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
{{ config(
2+
schema = 'ferro_cronos'
3+
, alias = 'base_trades'
4+
, partition_by = ['block_month']
5+
, materialized = 'incremental'
6+
, file_format = 'delta'
7+
, incremental_strategy = 'merge'
8+
, unique_key = ['tx_hash', 'evt_index']
9+
, incremental_predicates = [incremental_predicate('DBT_INTERNAL_DEST.block_time')]
10+
)
11+
}}
12+
13+
-- Ferro is a Saddle/StableSwap fork. The TokenSwap event only exposes the pool-local
14+
-- token indexes (soldId / boughtId), so we resolve them to token addresses using the
15+
-- pooledTokens array emitted by the SwapDeployer at pool creation time.
16+
WITH pool_tokens AS (
17+
SELECT
18+
swapAddress AS pool_address
19+
, token_address
20+
, CAST(token_index - 1 AS int256) AS token_id -- pooledTokens ordinality is 1-based, TokenSwap ids are 0-based
21+
FROM
22+
{{ source('ferro_cronos', 'SwapDeployer_evt_NewSwapPool') }}
23+
CROSS JOIN UNNEST(pooledTokens) WITH ORDINALITY AS t(token_address, token_index)
24+
)
25+
26+
, token_swaps AS (
27+
SELECT
28+
t.evt_block_number AS block_number
29+
, t.evt_block_time AS block_time
30+
, t.tokensBought AS token_bought_amount_raw
31+
, t.tokensSold AS token_sold_amount_raw
32+
, CAST(t.boughtId AS int256) AS bought_id
33+
, CAST(t.soldId AS int256) AS sold_id
34+
, t.buyer AS taker
35+
, CAST(NULL AS varbinary) AS maker
36+
, t.contract_address AS project_contract_address
37+
, t.evt_tx_hash AS tx_hash
38+
, t.evt_index
39+
FROM
40+
{{ source('ferro_cronos', 'Swap_evt_TokenSwap') }} t
41+
{% if is_incremental() %}
42+
WHERE
43+
{{ incremental_predicate('t.evt_block_time') }}
44+
{% endif %}
45+
)
46+
47+
, dexs AS (
48+
SELECT
49+
s.block_number
50+
, s.block_time
51+
, s.token_bought_amount_raw
52+
, s.token_sold_amount_raw
53+
, pt_bought.token_address AS token_bought_address
54+
, pt_sold.token_address AS token_sold_address
55+
, s.taker
56+
, s.maker
57+
, s.project_contract_address
58+
, s.tx_hash
59+
, s.evt_index
60+
FROM
61+
token_swaps s
62+
INNER JOIN pool_tokens pt_bought
63+
ON s.project_contract_address = pt_bought.pool_address
64+
AND s.bought_id = pt_bought.token_id
65+
INNER JOIN pool_tokens pt_sold
66+
ON s.project_contract_address = pt_sold.pool_address
67+
AND s.sold_id = pt_sold.token_id
68+
)
69+
70+
SELECT
71+
'cronos' AS blockchain
72+
, 'ferro' AS project
73+
, '1' AS version
74+
, CAST(date_trunc('month', dexs.block_time) AS date) AS block_month
75+
, CAST(date_trunc('day', dexs.block_time) AS date) AS block_date
76+
, dexs.block_time
77+
, dexs.block_number
78+
, dexs.token_bought_amount_raw
79+
, dexs.token_sold_amount_raw
80+
, dexs.token_bought_address
81+
, dexs.token_sold_address
82+
, dexs.taker
83+
, dexs.maker
84+
, dexs.project_contract_address
85+
, dexs.tx_hash
86+
, dexs.evt_index
87+
FROM
88+
dexs
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{{ config(
2+
schema = 'vvs_finance_v2_cronos'
3+
, alias = 'base_trades'
4+
, materialized = 'incremental'
5+
, file_format = 'delta'
6+
, incremental_strategy = 'merge'
7+
, unique_key = ['tx_hash', 'evt_index']
8+
, incremental_predicates = [incremental_predicate('DBT_INTERNAL_DEST.block_time')]
9+
)
10+
}}
11+
12+
{{
13+
uniswap_compatible_v2_trades(
14+
blockchain = 'cronos'
15+
, project = 'vvs_finance'
16+
, version = '2'
17+
, Pair_evt_Swap = source('vvsfinance_cronos', 'VVSPair_evt_Swap')
18+
, Factory_evt_PairCreated = source('vvsfinance_cronos', 'VVSFactory_evt_PairCreated')
19+
)
20+
}}

0 commit comments

Comments
 (0)