From 19e82706bdc5a1d306ac742ddb729f5bd027f5bb Mon Sep 17 00:00:00 2001 From: soispoke <66172107+soispoke@users.noreply.github.com> Date: Mon, 20 Jun 2022 12:14:55 +0200 Subject: [PATCH] Fix incremental run time issues (#1193) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In a previous PR, the aim was to standardize the incremental strategy across spells: https://github.com/duneanalytics/abstractions/commit/9ae14c5289a85605314bcd6fd49efcb05567eecc
 
We were using the « merge » strategy, which allows to update fields if the underlying data changed for the whole table, and append new data. While I remain convinced the merge strategy is the best one to ensure data quality, this unfortunately came at a cost: Quarter hourly jobs could not run under 15 minutes, which caused jobs to queue up. 

To mitigate this, I propose to use the « default » incremental strategy, that just appends new data incrementally (without updating the whole dataset if needed). The big advantage is that tables are updated around twice as fast as the merge strategy. To mitigate the fact that existing data can’t be updated, I added uniqueness tests to all incremental tables so we can regularly make sure there are no duplicates/data quality is good. I've checked that: * [x] I tested the query on dune.com after compiling the model with dbt compile (compiled queries are written to the target directory) * [x] I used "refs" to reference other models in this repo and "sources" to reference raw or decoded tables * [x] the directory tree matches the pattern /sector/blockchain/ e.g. /tokens/ethereum * [x] if adding a new model, I added a test * [x] the filename is unique and ends with .sql * [x] each file has only one view, table or function defined * [x] column names are `lowercase_snake_cased` --- spellbook/macros/alter_table_properties.sql | 36 +++++++++- spellbook/macros/optimize_tables.sql | 16 ++++- .../models/magiceden/magiceden_schema.yml | 4 +- .../models/magiceden/magiceden_trades.sql | 17 ++--- .../solana/magiceden_solana_schema.yml | 2 - spellbook/models/nft/nft_trades.sql | 10 +-- .../ethereum/opensea_ethereum_schema.yml | 2 - .../ethereum/opensea_ethereum_trades.sql | 6 +- spellbook/models/opensea/opensea_schema.yml | 2 + spellbook/models/opensea/opensea_trades.sql | 10 +-- .../transfers_ethereum_erc1155_agg_day.sql | 7 +- .../transfers_ethereum_erc1155_agg_hour.sql | 7 +- .../transfers_ethereum_erc20_agg_day.sql | 7 +- .../transfers_ethereum_erc20_agg_hour.sql | 7 +- .../transfers_ethereum_erc721_agg_day.sql | 9 +-- .../transfers_ethereum_erc721_agg_hour.sql | 9 +-- .../ethereum/uniswap_ethereum_schema.yml | 4 +- .../ethereum/uniswap_ethereum_trades.sql | 11 +-- spellbook/models/uniswap/uniswap_trades.sql | 13 ++++ spellbook/models/uniswap/uniswap_trades.yml | 69 +++++++++++++++++++ 20 files changed, 163 insertions(+), 85 deletions(-) create mode 100644 spellbook/models/uniswap/uniswap_trades.sql create mode 100644 spellbook/models/uniswap/uniswap_trades.yml diff --git a/spellbook/macros/alter_table_properties.sql b/spellbook/macros/alter_table_properties.sql index d8fa8a54355..cadb93cbf36 100644 --- a/spellbook/macros/alter_table_properties.sql +++ b/spellbook/macros/alter_table_properties.sql @@ -55,6 +55,33 @@ ALTER VIEW balances_ethereum.erc721_latest SET TBLPROPERTIES('dune.public'='true 'dune.data_explorer.contributors'='["hildobby","soispoke","dot2dotseurat"]'); {% endset %} +{% set balances_ethereum_erc1155_day %} +ALTER VIEW balances_ethereum.erc1155_day SET TBLPROPERTIES('dune.public'='true', + 'dune.data_explorer.blockchains'='["ethereum"]', + 'dune.data_explorer.category'='abstraction', + 'dune.data_explorer.abstraction.type'='sector', + 'dune.data_explorer.abstraction.name'='balances', + 'dune.data_explorer.contributors'='["soispoke"]'); +{% endset %} + +{% set balances_ethereum_erc1155_hour %} +ALTER VIEW balances_ethereum.erc1155_hour SET TBLPROPERTIES('dune.public'='true', + 'dune.data_explorer.blockchains'='["ethereum"]', + 'dune.data_explorer.category'='abstraction', + 'dune.data_explorer.abstraction.type'='sector', + 'dune.data_explorer.abstraction.name'='balances', + 'dune.data_explorer.contributors'='["soispoke"]'); +{% endset %} + +{% set balances_ethereum_erc1155_latest %} +ALTER VIEW balances_ethereum.erc1155_latest SET TBLPROPERTIES('dune.public'='true', + 'dune.data_explorer.blockchains'='["ethereum"]', + 'dune.data_explorer.category'='abstraction', + 'dune.data_explorer.abstraction.type'='sector', + 'dune.data_explorer.abstraction.name'='balances', + 'dune.data_explorer.contributors'='["soispoke"]'); +{% endset %} + {% set magiceden_trades %} ALTER TABLE magiceden.trades SET TBLPROPERTIES('dune.public'='true', 'dune.data_explorer.blockchains'='["solana"]', @@ -136,8 +163,8 @@ ALTER VIEW tokens_ethereum.nft SET TBLPROPERTIES('dune.public'='true', 'dune.data_explorer.contributors'='["dot2dotseurat","soispoke"]'); {% endset %} -{% set uniswap_ethereum_trades %} -ALTER TABLE uniswap_ethereum.trades SET TBLPROPERTIES('dune.public'='true', +{% set uniswap_trades %} +ALTER TABLE uniswap.trades SET TBLPROPERTIES('dune.public'='true', 'dune.data_explorer.blockchains'='["ethereum"]', 'dune.data_explorer.category'='abstraction', 'dune.data_explorer.abstraction.type'='project', @@ -151,6 +178,9 @@ ALTER TABLE uniswap_ethereum.trades SET TBLPROPERTIES('dune.public'='true', {% do run_query(balances_ethereum_erc721_day) %} {% do run_query(balances_ethereum_erc721_hour) %} {% do run_query(balances_ethereum_erc721_latest) %} +{% do run_query(balances_ethereum_erc1155_day) %} +{% do run_query(balances_ethereum_erc1155_hour) %} +{% do run_query(balances_ethereum_erc1155_latest) %} {% do run_query(magiceden_trades) %} {% do run_query(nft_trades) %} {% do run_query(opensea_active_traders_day) %} @@ -160,7 +190,7 @@ ALTER TABLE uniswap_ethereum.trades SET TBLPROPERTIES('dune.public'='true', {% do run_query(tokens_ethereum_erc20) %} {% do run_query(transfers_ethereum_erc20) %} {% do run_query(tokens_ethereum_nft) %} -{% do run_query(uniswap_ethereum_trades) %} +{% do run_query(uniswap_trades) %} {% do log("Tables generated", info=True) %} {%- else -%} diff --git a/spellbook/macros/optimize_tables.sql b/spellbook/macros/optimize_tables.sql index 433dd5cae9a..acd8f6952b0 100644 --- a/spellbook/macros/optimize_tables.sql +++ b/spellbook/macros/optimize_tables.sql @@ -16,6 +16,14 @@ OPTIMIZE transfers_ethereum.erc721_agg_hour; OPTIMIZE transfers_ethereum.erc721_agg_day; {% endset %} +{% set transfers_ethereum_erc1155_agg_hour %} +OPTIMIZE transfers_ethereum.erc1155_agg_hour; +{% endset %} + +{% set transfers_ethereum_erc1155_agg_day %} +OPTIMIZE transfers_ethereum.erc1155_agg_day; +{% endset %} + {% set opensea_trades %} OPTIMIZE opensea.trades; {% endset %} @@ -24,8 +32,8 @@ OPTIMIZE opensea.trades; OPTIMIZE magiceden.trades; {% endset %} -{% set uniswap_ethereum_trades %} -OPTIMIZE uniswap_ethereum.trades; +{% set uniswap_trades %} +OPTIMIZE uniswap.trades; {% endset %} {% set nft_trades %} @@ -37,9 +45,11 @@ OPTIMIZE nft.trades; {% do run_query(transfers_ethereum_erc20_agg_day) %} {% do run_query(transfers_ethereum_erc721_agg_hour) %} {% do run_query(transfers_ethereum_erc721_agg_day) %} +{% do run_query(transfers_ethereum_erc1155_agg_hour) %} +{% do run_query(transfers_ethereum_erc1155_agg_day) %} {% do run_query(opensea_trades) %} {% do run_query(magiceden_trades) %} -{% do run_query(uniswap_ethereum_trades) %} +{% do run_query(uniswap_trades) %} {% do run_query(nft_trades) %} {% do log("Tables Optimized", info=True) %} diff --git a/spellbook/models/magiceden/magiceden_schema.yml b/spellbook/models/magiceden/magiceden_schema.yml index e2f0e04a729..080cf431046 100644 --- a/spellbook/models/magiceden/magiceden_schema.yml +++ b/spellbook/models/magiceden/magiceden_schema.yml @@ -31,4 +31,6 @@ models: - name: amount_usd description: "USD value of the trade at time of execution" - name: unique_trade_id - description: "Unique trade ID (derived from signatures[0] and id in solana transactions)" \ No newline at end of file + description: "Unique trade ID (derived from signatures[0] and id in solana transactions)" + tests: + - unique \ No newline at end of file diff --git a/spellbook/models/magiceden/magiceden_trades.sql b/spellbook/models/magiceden/magiceden_trades.sql index a5b639d043b..0f0b4d63501 100644 --- a/spellbook/models/magiceden/magiceden_trades.sql +++ b/spellbook/models/magiceden/magiceden_trades.sql @@ -1,16 +1,13 @@ -{{ config( - alias='trades', - materialized ='incremental', - file_format ='delta', - incremental_strategy='merge', - unique_key='unique_trade_id' - ) + {{ + config( + alias='trades', materialize = 'incremental') }} -SELECT blockchain, 'magiceden' as project, '' as version, tx_hash, block_time, amount_usd, amount, token_symbol, token_address, unique_trade_id FROM +SELECT blockchain, 'magiceden' as project, '' as version, tx_hash, block_time, amount_usd, amount, token_symbol, token_address, unique_trade_id +FROM ( - SELECT blockchain, tx_hash, block_time, amount_usd, amount, token_symbol, token_address, unique_trade_id - FROM {{ ref('magiceden_solana_trades') }} +SELECT blockchain, tx_hash, block_time, amount_usd, amount, token_symbol, token_address, unique_trade_id +FROM {{ ref('magiceden_solana_trades') }} ) {% if is_incremental() %} -- this filter will only be applied on an incremental run diff --git a/spellbook/models/magiceden/solana/magiceden_solana_schema.yml b/spellbook/models/magiceden/solana/magiceden_solana_schema.yml index 8170106a963..ebe8db35c66 100644 --- a/spellbook/models/magiceden/solana/magiceden_solana_schema.yml +++ b/spellbook/models/magiceden/solana/magiceden_solana_schema.yml @@ -13,8 +13,6 @@ models: columns: - name: unique_trade_id description: "Unique trade id, combination of signatures[0] and id" - tests: - - unique - &blockchain name: blockchain description: "Blockchain" diff --git a/spellbook/models/nft/nft_trades.sql b/spellbook/models/nft/nft_trades.sql index 05dd8fdef5d..ac6c0f42112 100644 --- a/spellbook/models/nft/nft_trades.sql +++ b/spellbook/models/nft/nft_trades.sql @@ -1,10 +1,6 @@ -{{ config( - alias='trades', - materialized ='incremental', - file_format ='delta', - incremental_strategy='merge', - unique_key='unique_trade_id' - ) + {{ + config( + alias='trades', materialize = 'incremental') }} SELECT blockchain, project, version, tx_hash, block_time, amount_usd, amount, token_symbol, token_address, unique_trade_id FROM diff --git a/spellbook/models/opensea/ethereum/opensea_ethereum_schema.yml b/spellbook/models/opensea/ethereum/opensea_ethereum_schema.yml index 9f77e31145d..5d8b4904987 100644 --- a/spellbook/models/opensea/ethereum/opensea_ethereum_schema.yml +++ b/spellbook/models/opensea/ethereum/opensea_ethereum_schema.yml @@ -13,8 +13,6 @@ models: columns: - name: unique_trade_id description: "Unique trade id, combination of tx_hash and trade_id" - tests: - - unique - &blockchain name: blockchain description: "Blockchain" diff --git a/spellbook/models/opensea/ethereum/opensea_ethereum_trades.sql b/spellbook/models/opensea/ethereum/opensea_ethereum_trades.sql index 90079b0cdb7..509bc93b749 100644 --- a/spellbook/models/opensea/ethereum/opensea_ethereum_trades.sql +++ b/spellbook/models/opensea/ethereum/opensea_ethereum_trades.sql @@ -1,8 +1,4 @@ - {{ - config( - alias='trades' - ) -}} + {{ config(alias='trades') }} SELECT evt_tx_hash || '-' || evt_index::string as unique_trade_id, diff --git a/spellbook/models/opensea/opensea_schema.yml b/spellbook/models/opensea/opensea_schema.yml index 85453e79582..5270f2f175c 100644 --- a/spellbook/models/opensea/opensea_schema.yml +++ b/spellbook/models/opensea/opensea_schema.yml @@ -26,6 +26,8 @@ models: description: "USD value of the trade at time of execution" - name: unique_trade_id description: "Unique trade ID" + tests: + - unique - name: opensea_volume_day meta: diff --git a/spellbook/models/opensea/opensea_trades.sql b/spellbook/models/opensea/opensea_trades.sql index e911d576d2d..20dc37afde9 100644 --- a/spellbook/models/opensea/opensea_trades.sql +++ b/spellbook/models/opensea/opensea_trades.sql @@ -1,10 +1,6 @@ -{{ config( - alias='trades', - materialized ='incremental', - file_format ='delta', - incremental_strategy='merge', - unique_key='unique_trade_id' - ) + {{ + config( + alias='trades', materialize = 'incremental') }} SELECT blockchain, 'opensea' as project, 'v1' as version, tx_hash, block_time, amount_usd, amount, token_symbol, token_address, unique_trade_id FROM diff --git a/spellbook/models/transfers/ethereum/erc1155/transfers_ethereum_erc1155_agg_day.sql b/spellbook/models/transfers/ethereum/erc1155/transfers_ethereum_erc1155_agg_day.sql index 32575a5599e..e2188c0a4d1 100644 --- a/spellbook/models/transfers/ethereum/erc1155/transfers_ethereum_erc1155_agg_day.sql +++ b/spellbook/models/transfers/ethereum/erc1155/transfers_ethereum_erc1155_agg_day.sql @@ -1,9 +1,6 @@ {{ config( alias ='erc1155_agg_day', - materialized ='incremental', - file_format ='delta', - incremental_strategy='merge', - unique_key='unique_transfer_id' + materialized ='incremental' ) }} @@ -18,7 +15,7 @@ select FROM {{ ref('transfers_ethereum_erc1155') }} {% if is_incremental() %} -- this filter will only be applied on an incremental run -where evt_block_time > now() - interval 2 days +where date_trunc('day', evt_block_time) > now() - interval 2 days {% endif %} group by date_trunc('day', evt_block_time), wallet_address, token_address, tokenId, unique_tx_id \ No newline at end of file diff --git a/spellbook/models/transfers/ethereum/erc1155/transfers_ethereum_erc1155_agg_hour.sql b/spellbook/models/transfers/ethereum/erc1155/transfers_ethereum_erc1155_agg_hour.sql index c77c5bf4478..45811c0ffa2 100644 --- a/spellbook/models/transfers/ethereum/erc1155/transfers_ethereum_erc1155_agg_hour.sql +++ b/spellbook/models/transfers/ethereum/erc1155/transfers_ethereum_erc1155_agg_hour.sql @@ -1,9 +1,6 @@ {{ config( alias ='erc1155_agg_hour', - materialized ='incremental', - file_format ='delta', - incremental_strategy='merge', - unique_key='unique_transfer_id' + materialized ='incremental' ) }} @@ -18,7 +15,7 @@ select FROM {{ ref('transfers_ethereum_erc1155') }} {% if is_incremental() %} -- this filter will only be applied on an incremental run -where evt_block_time > now() - interval 2 days +where date_trunc('hour', evt_block_time) > now() - interval 2 days {% endif %} group by date_trunc('hour', evt_block_time), wallet_address, token_address, tokenId, unique_tx_id \ No newline at end of file diff --git a/spellbook/models/transfers/ethereum/erc20/transfers_ethereum_erc20_agg_day.sql b/spellbook/models/transfers/ethereum/erc20/transfers_ethereum_erc20_agg_day.sql index fba899f2759..7ad9177ceac 100644 --- a/spellbook/models/transfers/ethereum/erc20/transfers_ethereum_erc20_agg_day.sql +++ b/spellbook/models/transfers/ethereum/erc20/transfers_ethereum_erc20_agg_day.sql @@ -1,9 +1,6 @@ {{ config( alias ='erc20_agg_day', - materialized ='incremental', - file_format ='delta', - incremental_strategy='merge', - unique_key='unique_transfer_id' + materialized ='incremental' ) }} @@ -20,7 +17,7 @@ from {{ ref('transfers_ethereum_erc20') }} tr left join {{ ref('tokens_ethereum_erc20') }} t on t.contract_address = tr.token_address {% if is_incremental() %} -- this filter will only be applied on an incremental run -where tr.evt_block_time > now() - interval 2 days +where date_trunc('day', tr.evt_block_time) > now() - interval 2 days {% endif %} group by date_trunc('day', tr.evt_block_time), tr.wallet_address, tr.token_address, t.symbol,unique_tx_id \ No newline at end of file diff --git a/spellbook/models/transfers/ethereum/erc20/transfers_ethereum_erc20_agg_hour.sql b/spellbook/models/transfers/ethereum/erc20/transfers_ethereum_erc20_agg_hour.sql index 31b43551875..4028b504505 100644 --- a/spellbook/models/transfers/ethereum/erc20/transfers_ethereum_erc20_agg_hour.sql +++ b/spellbook/models/transfers/ethereum/erc20/transfers_ethereum_erc20_agg_hour.sql @@ -1,9 +1,6 @@ {{ config( alias ='erc20_agg_hour', - materialized ='incremental', - file_format ='delta', - incremental_strategy='merge', - unique_key='unique_transfer_id' + materialized ='incremental' ) }} @@ -20,7 +17,7 @@ from {{ ref('transfers_ethereum_erc20') }} tr left join {{ ref('tokens_ethereum_erc20') }} t on t.contract_address = tr.token_address {% if is_incremental() %} -- this filter will only be applied on an incremental run -where tr.evt_block_time > now() - interval 2 days +where date_trunc('hour', tr.evt_block_time) > now() - interval 2 days {% endif %} group by date_trunc('hour', tr.evt_block_time), tr.wallet_address, tr.token_address, t.symbol,unique_tx_id diff --git a/spellbook/models/transfers/ethereum/erc721/transfers_ethereum_erc721_agg_day.sql b/spellbook/models/transfers/ethereum/erc721/transfers_ethereum_erc721_agg_day.sql index 2bdfc2d15a3..70c5ecf393e 100644 --- a/spellbook/models/transfers/ethereum/erc721/transfers_ethereum_erc721_agg_day.sql +++ b/spellbook/models/transfers/ethereum/erc721/transfers_ethereum_erc721_agg_day.sql @@ -1,9 +1,6 @@ {{ config( - alias ='erc721_agg_day', - materialized ='incremental', - file_format ='delta', - incremental_strategy='merge', - unique_key='unique_transfer_id' + alias ='erc721_agg_day', + materialized ='incremental' ) }} @@ -17,7 +14,7 @@ select from {{ ref('transfers_ethereum_erc721') }} {% if is_incremental() %} -- this filter will only be applied on an incremental run -where evt_block_time > now() - interval 2 days +where date_trunc('day', evt_block_time) > now() - interval 2 days {% endif %} group by date_trunc('day', evt_block_time), wallet_address, token_address, tokenId,unique_tx_id diff --git a/spellbook/models/transfers/ethereum/erc721/transfers_ethereum_erc721_agg_hour.sql b/spellbook/models/transfers/ethereum/erc721/transfers_ethereum_erc721_agg_hour.sql index c67fdd6583c..ac95f4bc69d 100644 --- a/spellbook/models/transfers/ethereum/erc721/transfers_ethereum_erc721_agg_hour.sql +++ b/spellbook/models/transfers/ethereum/erc721/transfers_ethereum_erc721_agg_hour.sql @@ -1,9 +1,6 @@ {{ config( - alias ='erc721_agg_hour', - materialized ='incremental', - file_format ='delta', - incremental_strategy='merge', - unique_key='unique_transfer_id' + alias ='erc721_agg_hour', + materialized ='incremental' ) }} @@ -17,7 +14,7 @@ select from {{ ref('transfers_ethereum_erc721') }} {% if is_incremental() %} -- this filter will only be applied on an incremental run -where evt_block_time > now() - interval 2 days +where date_trunc('hour', evt_block_time) > now() - interval 2 days {% endif %} group by date_trunc('hour', evt_block_time), wallet_address, token_address, tokenId,unique_tx_id diff --git a/spellbook/models/uniswap/ethereum/uniswap_ethereum_schema.yml b/spellbook/models/uniswap/ethereum/uniswap_ethereum_schema.yml index 500e52334df..900d5e18e08 100644 --- a/spellbook/models/uniswap/ethereum/uniswap_ethereum_schema.yml +++ b/spellbook/models/uniswap/ethereum/uniswap_ethereum_schema.yml @@ -64,9 +64,7 @@ models: description: "Receive this transaction" - &unique_trade_id name: unique_trade_id - description: "Unique trade ID (derived from tx_hash and evt_index for ethereum dex trades)" - tests: - - unique + description: "Unique trade ID (derived from tx_hash and evt_index for ethereum dex trades)" - name: uniswap_v2_ethereum_trades meta: diff --git a/spellbook/models/uniswap/ethereum/uniswap_ethereum_trades.sql b/spellbook/models/uniswap/ethereum/uniswap_ethereum_trades.sql index cc130980374..51a8900828e 100644 --- a/spellbook/models/uniswap/ethereum/uniswap_ethereum_trades.sql +++ b/spellbook/models/uniswap/ethereum/uniswap_ethereum_trades.sql @@ -1,11 +1,6 @@ {{ config( - alias='trades', - materialized ='incremental', - file_format ='delta', - incremental_strategy='merge', - unique_key='unique_trade_id' - ) + alias='trades') }} SELECT blockchain, project, version, block_time, token_a_symbol, token_b_symbol, @@ -14,7 +9,3 @@ SELECT blockchain, project, version, block_time, token_a_symbol, token_b_symbol, FROM (SELECT * FROM {{ ref('uniswap_v2_ethereum_trades') }} UNION ALL SELECT * FROM {{ ref('uniswap_v3_ethereum_trades') }}) -{% if is_incremental() %} --- this filter will only be applied on an incremental run -WHERE block_time > now() - interval 2 days -{% endif %} diff --git a/spellbook/models/uniswap/uniswap_trades.sql b/spellbook/models/uniswap/uniswap_trades.sql new file mode 100644 index 00000000000..8571a925842 --- /dev/null +++ b/spellbook/models/uniswap/uniswap_trades.sql @@ -0,0 +1,13 @@ + {{ + config( + alias='trades', materialize = 'incremental') +}} + +SELECT blockchain, project, version, block_time, token_a_symbol, token_b_symbol, + token_a_amount, token_b_amount, trader_a, trader_b, usd_amount, token_a_address, + token_b_address, exchange_contract_address, tx_hash, tx_from, tx_to, unique_trade_id +FROM (SELECT * FROM {{ ref('uniswap_ethereum_trades') }}) +{% if is_incremental() %} +-- this filter will only be applied on an incremental run +WHERE block_time > now() - interval 2 days +{% endif %} diff --git a/spellbook/models/uniswap/uniswap_trades.yml b/spellbook/models/uniswap/uniswap_trades.yml new file mode 100644 index 00000000000..5affa3cb79d --- /dev/null +++ b/spellbook/models/uniswap/uniswap_trades.yml @@ -0,0 +1,69 @@ +version: 2 + +models: + - name: uniswap_trades + meta: + blockchain: ethereum + project: uniswap + contributors: masquot, soispoke + config: + tags: ['ethereum','uniswap','trades'] + description: > + Uniswap V1 trades + columns: + - &blockchain + name: blockchain + description: "Blockchain" + - &project + name: project + description: "Project name" + - &version + name: version + description: "Version" + - &block_time + name: block_time + description: "UTC event block time" + - &token_a_symbol + name: token_a_symbol + description: "Symbol for first token traded" + - &token_b_symbol + name: token_b_symbol + description: "Symbol for second token traded" + - &token_a_amount + name: token_a_amount + description: "Value of the trade at time of execution in the original currency for the first token" + - &token_b_amount + name: token_b_amount + description: "Value of the trade at time of execution in the original currency for the second token" + - &trader_a + name: trader_a + description: "Address of trader A" + - &trader_b + name: trader_b + description: "Address of trader B" + - &amount_usd + name: amount_usd + description: "USD value of the trade at time of execution" + - &token_a_address + name: token_a_address + description: "Contract address of first token traded" + - &token_b_address + name: token_b_address + description: "Contract address of second token traded" + - &exchange_contract_address + name: exchange_contract_address + description: "Exchange contract address" + - &tx_hash + name: tx_hash + description: "Transaction hash" + - &tx_from + name: tx_from + description: "Initiated this transaction" + - &tx_to + name: tx_to + description: "Receive this transaction" + - &unique_trade_id + name: unique_trade_id + description: "Unique trade ID (derived from tx_hash and evt_index for ethereum dex trades)" + tests: + - unique