-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat(dex): integrate Agra DEX (ethereum, hyperevm) #9839
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
cxheng315
wants to merge
9
commits into
duneanalytics:main
Choose a base branch
from
cxheng315:agra-dex-integration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
5d451ba
feat(dex): register agra_multichain source
cxheng315 69c3a91
feat(dex): add agra base trades for ethereum and hyperevm
cxheng315 e77c44f
test(dex): add agra schema tests and seeds
cxheng315 b64f4c7
feat(dex): add agra to dex_info
cxheng315 c0522b7
fix(dex): dedup agra matched orders and set start date
cxheng315 e2f23ef
test(dex): populate agra base trades seeds
cxheng315 70a6706
refactor(dex): extract shared agra_base_trades macro
cxheng315 bbfd7a2
feat(dex): add agra.trades project view
cxheng315 fdb1884
fix(dex): guard agra base trades against multi-token order fan-out
cxheng315 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
134 changes: 134 additions & 0 deletions
134
dbt_subprojects/dex/macros/models/_project/agra_base_trades.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| {% macro agra_base_trades( | ||
| blockchain, | ||
| start_date = '2026-03-01' | ||
| ) | ||
| %} | ||
|
|
||
| with orders as ( | ||
| select | ||
| evt_block_time as block_time | ||
| , evt_block_number as block_number | ||
| , evt_tx_hash as tx_hash | ||
| , evt_index | ||
| , contract_address as project_contract_address | ||
| , offerer | ||
| , recipient | ||
| , orderHash as order_hash | ||
| , offer | ||
| , consideration | ||
| from {{ source('agra_multichain', 'settlement_evt_orderfulfilled') }} | ||
| where chain = '{{ blockchain }}' | ||
| {% if is_incremental() %} | ||
| and {{ incremental_predicate('evt_block_time') }} | ||
| {% else %} | ||
| and evt_block_time >= timestamp '{{ start_date }}' | ||
| {% endif %} | ||
| ) | ||
|
|
||
| -- Order hashes settled via matchOrders. Such orders emit one OrderFulfilled per side, so the | ||
| -- taker's order leg (offerer = recipient) is the aggregate of the maker legs and is a duplicate. | ||
| , matched_hashes as ( | ||
| select evt_tx_hash as tx_hash, oh as order_hash | ||
| from {{ source('agra_multichain', 'settlement_evt_ordersmatched') }} | ||
| cross join unnest(orderHashes) as t(oh) | ||
| where chain = '{{ blockchain }}' | ||
| {% if is_incremental() %} | ||
| and {{ incremental_predicate('evt_block_time') }} | ||
| {% else %} | ||
| and evt_block_time >= timestamp '{{ start_date }}' | ||
| {% endif %} | ||
| group by 1, 2 | ||
| ) | ||
|
|
||
| -- token the taker RECEIVES (offerer gives) -> token_bought | ||
| , offer_tokens as ( | ||
| select | ||
| tx_hash | ||
| , evt_index | ||
| , from_hex(json_extract_scalar(o, '$.token')) as token | ||
| , cast(sum(cast(json_extract_scalar(o, '$.amount') as uint256)) as uint256) as amount | ||
| from orders | ||
| cross join unnest(offer) as t(o) | ||
| where json_extract_scalar(o, '$.itemType') = '1' -- ERC20 only | ||
| group by tx_hash, evt_index, from_hex(json_extract_scalar(o, '$.token')) | ||
| ) | ||
|
|
||
| -- CLOB settles one ERC20 per side; keep one deterministic row so a malformed | ||
| -- multi-token order can't break the tx_hash+evt_index unique key / incremental merge. | ||
| , offer_side as ( | ||
| select tx_hash, evt_index, token, amount | ||
| from ( | ||
| select | ||
| tx_hash | ||
| , evt_index | ||
| , token | ||
| , amount | ||
| , row_number() over (partition by tx_hash, evt_index order by amount desc, token) as rn | ||
| from offer_tokens | ||
| ) | ||
| where rn = 1 | ||
| ) | ||
|
|
||
| -- token the taker PAYS (offerer receives, incl. fees) -> token_sold | ||
| , consideration_tokens as ( | ||
| select | ||
| tx_hash | ||
| , evt_index | ||
| , from_hex(json_extract_scalar(c, '$.token')) as token | ||
| , cast(sum(cast(json_extract_scalar(c, '$.amount') as uint256)) as uint256) as amount | ||
| from orders | ||
| cross join unnest(consideration) as t(c) | ||
| where json_extract_scalar(c, '$.itemType') = '1' -- ERC20 only | ||
| group by tx_hash, evt_index, from_hex(json_extract_scalar(c, '$.token')) | ||
| ) | ||
|
|
||
| -- CLOB settles one ERC20 per side; keep one deterministic row so a malformed | ||
| -- multi-token order can't break the tx_hash+evt_index unique key / incremental merge. | ||
| , consideration_side as ( | ||
| select tx_hash, evt_index, token, amount | ||
| from ( | ||
| select | ||
| tx_hash | ||
| , evt_index | ||
| , token | ||
| , amount | ||
| , row_number() over (partition by tx_hash, evt_index order by amount desc, token) as rn | ||
| from consideration_tokens | ||
| ) | ||
| where rn = 1 | ||
| ) | ||
|
|
||
| select | ||
| '{{ blockchain }}' as blockchain | ||
| , 'agra' as project | ||
| , '1' as version | ||
| , cast(date_trunc('month', o.block_time) as date) as block_month | ||
| , cast(date_trunc('day', o.block_time) as date) as block_date | ||
| , o.block_time | ||
| , o.block_number | ||
| , ofr.amount as token_bought_amount_raw | ||
| , con.amount as token_sold_amount_raw | ||
| , ofr.token as token_bought_address | ||
| , con.token as token_sold_address | ||
| , o.recipient as taker | ||
| , o.offerer as maker | ||
| , o.project_contract_address | ||
| , o.tx_hash | ||
| , o.evt_index | ||
| -- Agra is a CLOB: exactly one ERC20 per side per order (a/b, c/b). A multi-token order | ||
| -- would be a contract failure and is intentionally not modeled; the guards above + the | ||
| -- tx_hash+evt_index unique key keep it from corrupting output. | ||
| from orders o | ||
| inner join offer_side ofr | ||
| on ofr.tx_hash = o.tx_hash | ||
| and ofr.evt_index = o.evt_index | ||
| inner join consideration_side con | ||
| on con.tx_hash = o.tx_hash | ||
| and con.evt_index = o.evt_index | ||
| left join matched_hashes m | ||
| on m.tx_hash = o.tx_hash | ||
| and m.order_hash = o.order_hash | ||
| -- drop the duplicated taker aggregate leg of matched orders; keep everything else | ||
| where m.order_hash is null or o.offerer <> o.recipient | ||
|
|
||
| {% endmacro %} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| {{ config( | ||
| schema = 'agra', | ||
| alias = 'trades', | ||
| materialized = 'view' | ||
| , post_hook='{{ hide_spells() }}' | ||
| ) | ||
| }} | ||
|
|
||
| {{ dex_project_trades('agra') }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
dbt_subprojects/dex/models/trades/ethereum/platforms/agra_ethereum_base_trades.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| {{ config( | ||
| schema = 'agra_ethereum' | ||
| , alias = 'base_trades' | ||
| , materialized = 'incremental' | ||
| , file_format = 'delta' | ||
| , incremental_strategy = 'merge' | ||
| , unique_key = ['tx_hash', 'evt_index'] | ||
| , incremental_predicates = [incremental_predicate('DBT_INTERNAL_DEST.block_time')] | ||
| ) | ||
| }} | ||
|
|
||
| {{ agra_base_trades(blockchain = 'ethereum') }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
dbt_subprojects/dex/models/trades/hyperevm/platforms/agra_hyperevm_base_trades.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| {{ config( | ||
| schema = 'agra_hyperevm' | ||
| , alias = 'base_trades' | ||
| , materialized = 'incremental' | ||
| , file_format = 'delta' | ||
| , incremental_strategy = 'merge' | ||
| , unique_key = ['tx_hash', 'evt_index'] | ||
| , incremental_predicates = [incremental_predicate('DBT_INTERNAL_DEST.block_time')] | ||
| ) | ||
| }} | ||
|
|
||
| {{ agra_base_trades(blockchain = 'hyperevm') }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 4 additions & 0 deletions
4
dbt_subprojects/dex/seeds/trades/agra_ethereum_base_trades_seed.csv
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| blockchain,project,version,block_date,tx_hash,evt_index,token_bought_address,token_sold_address,block_number,token_bought_amount_raw,token_sold_amount_raw | ||
| ethereum,agra,1,2026-06-26,0xf65db18c06700ca14f938c08dc98298aafa9e44d64d3165cc78e95ae8892deee,161,0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48,0xc9499006a149c553d18171747ed19aa7c6dd19e2,25400895,2998470,3000000 | ||
| ethereum,agra,1,2026-06-26,0xbc1f81e637e09c3b5b2eaff92a7b7090a37afad576099d36fb15510b09fb7e9e,67,0xc9499006a149c553d18171747ed19aa7c6dd19e2,0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48,25400893,2998470,2999999 | ||
| ethereum,agra,1,2026-06-25,0xa9c838147c9c34c37fa5dbb34b32439980df845933101d35574c4c988bb7e411,324,0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48,0xbf4e3fbe8b60062a00c7a6b1d97d0d49c2971a19,25394695,101181000,100000000 |
4 changes: 4 additions & 0 deletions
4
dbt_subprojects/dex/seeds/trades/agra_hyperevm_base_trades_seed.csv
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| blockchain,project,version,block_date,tx_hash,evt_index,token_bought_address,token_sold_address,block_number,token_bought_amount_raw,token_sold_amount_raw | ||
| hyperevm,agra,1,2026-03-13,0x788f742644007f6d4780d573e8fc4c13157d8d750ffb89d8aeb33cfb8e6121b4,0,0x5555555555555555555555555555555555555555,0x5748ae796ae46a4f1348a1693de4b50560485562,29637157,998583302299000000,981987710000000000 | ||
| hyperevm,agra,1,2026-03-13,0x61fa7014a33d33de87fa076bd887e9db6fd91172263301f86b6e7b80a59c223b,4,0x5555555555555555555555555555555555555555,0x5748ae796ae46a4f1348a1693de4b50560485562,29633718,18316689857700000,18012300000000000 | ||
| hyperevm,agra,1,2026-03-13,0x68f814e2bf69ff189e8f7ba372a350a96f7e7a7577807c5b6457cca3995e1de6,0,0x5555555555555555555555555555555555555555,0x5748ae796ae46a4f1348a1693de4b50560485562,29633687,998582310142300000,981987700000000000 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When an Agra
OrderFulfilledcontains more than one ERC20 offer or consideration item,offer_sideandconsideration_sideeach produce one row per token, but this join only usestx_hashandevt_index. A single event then expands into every offer-token × consideration-token combination while the model is keyed and tested only bytx_hash, evt_index, so multi-asset fills will either fail the unique test/merge or be arbitrarily de-duped downstream index_base_trades_macro.Useful? React with 👍 / 👎.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't happen for Agra. It's a CLOB — every order matches exactly one ERC20 against the quote token (a/b or c/b). A single order paying two tokens for one (
a + c / b) isn't a valid trade; it could only come from a contract failure. Confirmed across all production data so far (247 events: 235 ethereum, 12 hyperevm) — everyOrderFulfilledhas exactly one distinct ERC20 per side.And even if it did occur, a multi-asset fill isn't representable in
dex.tradesanyway (onetoken_bought_address/ onetoken_sold_addressper row, and no prices at the base layer to split a leg), so it's intentionally out of scope — consistent with the rest of the base-trades sector.That said, I added a deterministic guard so a malformed order can never silently break the
(tx_hash, evt_index)unique key or the incremental merge: each side collapses to one row per event viarow_number()(QUALIFYisn't supported in DuneSQL/Trino). It's a verified no-op on all current data — old-vs-new output is byte-identical (209 = 209 rows, empty symmetric difference) — and the unique key stays the tripwire if an anomalous order ever appears.