diff --git a/dashboard/modules/base_mainnet/perp_stats.py b/dashboard/modules/base_mainnet/perp_stats.py index 7237cd31..d0209495 100644 --- a/dashboard/modules/base_mainnet/perp_stats.py +++ b/dashboard/modules/base_mainnet/perp_stats.py @@ -43,10 +43,25 @@ def fetch_data(filters): db, ) + df_buyback = pd.read_sql_query( + f""" + SELECT + ts, + snx_amount, + usd_amount, + cumulative_snx_amount, + cumulative_usd_amount + FROM base_mainnet.fct_buyback_{resolution} + WHERE ts >= '{start_date}' and ts <= '{end_date}' + """, + db, + ) + db.close() return { "stats": df_stats, + "buyback": df_buyback, } @@ -94,6 +109,21 @@ def make_charts(data): ["liquidation_rewards"], "Liquidation Rewards", ), + "buyback": chart_bars( + data["buyback"], + "ts", + ["snx_amount"], + "SNX Buyback", + y_format="#", + ), + "cumulative_buyback": chart_lines( + data["buyback"], + "ts", + ["cumulative_snx_amount"], + "Cumulative SNX Buyback", + y_format="#", + smooth=True, + ), } @@ -128,12 +158,14 @@ def main(): st.plotly_chart(charts["cumulative_fees"], use_container_width=True) st.plotly_chart(charts["account_liquidations"], use_container_width=True) st.plotly_chart(charts["liquidation_rewards"], use_container_width=True) + st.plotly_chart(charts["cumulative_buyback"], use_container_width=True) pass with col2: st.plotly_chart(charts["volume"], use_container_width=True) st.plotly_chart(charts["fees"], use_container_width=True) st.plotly_chart(charts["trades"], use_container_width=True) + st.plotly_chart(charts["buyback"], use_container_width=True) pass ## export diff --git a/extractors/src/clean.py b/extractors/src/clean.py index 4cf0c40c..d021e64f 100644 --- a/extractors/src/clean.py +++ b/extractors/src/clean.py @@ -75,7 +75,7 @@ def clean_data(chain_name, contract, function_name, write=True): contract, function_name, decode_hex(f"0x{x[10:]}") ) ) - if x + if x is not None else None ) ) @@ -92,7 +92,7 @@ def clean_data(chain_name, contract, function_name, write=True): contract, function_name, decode_hex(x), is_input=False ) ) - if x + if x is not None else None ) ) diff --git a/indexers/base-mainnet/abi/BuybackSnx.json b/indexers/base-mainnet/abi/BuybackSnx.json new file mode 100644 index 00000000..a902afe8 --- /dev/null +++ b/indexers/base-mainnet/abi/BuybackSnx.json @@ -0,0 +1,181 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_premium", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snxFeeShare", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_oracleManager", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_snxNodeId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_snxToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_usdToken", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "OverflowInt256ToUint256", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "buyer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "snx", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "usd", + "type": "uint256" + } + ], + "name": "BuybackProcessed", + "type": "event" + }, + { + "inputs": [], + "name": "DEAD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPremium", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSnxFeeShare", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSnxNodeId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "snxAmount", + "type": "uint256" + } + ], + "name": "processBuyback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "marketId", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "quoteFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/indexers/base-mainnet/squidgen.yaml b/indexers/base-mainnet/squidgen.yaml index 177bac3a..ef7f82c0 100644 --- a/indexers/base-mainnet/squidgen.yaml +++ b/indexers/base-mainnet/squidgen.yaml @@ -36,3 +36,13 @@ contracts: abi: ./abi/SpotMarketProxy.json events: true functions: false + - name: BuybackSnxLegacy + address: "0x53f1E640C058337a12D036265681bC172e6fB962" + abi: ./abi/BuybackSnx.json + events: true + functions: false + - name: BuybackSnx + address: "0x632cAa10A56343C5e6C0c066735840c096291B18" + abi: ./abi/BuybackSnx.json + events: true + functions: false diff --git a/indexers/base-sepolia/abi/BuybackSnx.json b/indexers/base-sepolia/abi/BuybackSnx.json new file mode 100644 index 00000000..a902afe8 --- /dev/null +++ b/indexers/base-sepolia/abi/BuybackSnx.json @@ -0,0 +1,181 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_premium", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snxFeeShare", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_oracleManager", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_snxNodeId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_snxToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_usdToken", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "OverflowInt256ToUint256", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "buyer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "snx", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "usd", + "type": "uint256" + } + ], + "name": "BuybackProcessed", + "type": "event" + }, + { + "inputs": [], + "name": "DEAD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPremium", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSnxFeeShare", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSnxNodeId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "snxAmount", + "type": "uint256" + } + ], + "name": "processBuyback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "marketId", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "quoteFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/indexers/base-sepolia/squidgen.yaml b/indexers/base-sepolia/squidgen.yaml index 35c9cea9..b4a6b5ca 100644 --- a/indexers/base-sepolia/squidgen.yaml +++ b/indexers/base-sepolia/squidgen.yaml @@ -36,3 +36,8 @@ contracts: abi: ./abi/SpotMarketProxy.json events: true functions: false + - name: BuybackSnx + address: "0x1Cd30a3CCd177F37Bd7199723B4497d31A7209e4" + abi: ./abi/BuybackSnx.json + events: true + functions: false diff --git a/postgres/initdb/create_databases.sql b/postgres/initdb/create_databases.sql index 9ccd683e..8520032a 100644 --- a/postgres/initdb/create_databases.sql +++ b/postgres/initdb/create_databases.sql @@ -10,5 +10,6 @@ CREATE database analytics; CREATE USER analytics WITH password 'analytics'; GRANT pg_read_all_data TO analytics; -- add the parquet extension +\c analytics CREATE extension IF NOT EXISTS parquet_fdw; CREATE server parquet_server foreign DATA wrapper parquet_fdw; diff --git a/transformers/synthetix/dbt_project.yml b/transformers/synthetix/dbt_project.yml index 2a088399..b1646446 100644 --- a/transformers/synthetix/dbt_project.yml +++ b/transformers/synthetix/dbt_project.yml @@ -27,6 +27,8 @@ models: enabled: "{{ target.name in ('base_sepolia', 'optimism_mainnet', 'base_mainnet') }}" perp: enabled: "{{ target.name in ('base_sepolia', 'base_mainnet') }}" + buyback: + enabled: "{{ target.name in ('base_mainnet') }}" marts: core: enabled: "{{ target.name in ('base_sepolia', 'optimism_mainnet', 'base_mainnet') }}" @@ -36,3 +38,5 @@ models: enabled: "{{ target.name in ('base_sepolia', 'base_mainnet') }}" perp_stats: enabled: "{{ target.name in ('base_sepolia', 'base_mainnet') }}" + buyback: + enabled: "{{ target.name in ('base_mainnet') }}" diff --git a/transformers/synthetix/models/marts/buyback/fct_buyback.sql b/transformers/synthetix/models/marts/buyback/fct_buyback.sql new file mode 100644 index 00000000..bfc17305 --- /dev/null +++ b/transformers/synthetix/models/marts/buyback/fct_buyback.sql @@ -0,0 +1,9 @@ +SELECT + id, + block_timestamp AS ts, + buyer, + {{ convert_wei('snx') }} AS snx, + {{ convert_wei('usd') }} AS usd, + {{ convert_wei('usd') }} / {{ convert_wei('snx') }} AS snx_price +FROM + {{ ref('buyback_processed') }} diff --git a/transformers/synthetix/models/marts/buyback/fct_buyback_daily.sql b/transformers/synthetix/models/marts/buyback/fct_buyback_daily.sql new file mode 100644 index 00000000..c941ad82 --- /dev/null +++ b/transformers/synthetix/models/marts/buyback/fct_buyback_daily.sql @@ -0,0 +1,27 @@ +WITH agg AS ( + SELECT + DATE_TRUNC( + 'day', + ts + ) AS ts, + SUM(snx) AS snx_amount, + SUM(usd) AS usd_amount + FROM + {{ ref('fct_buyback') }} + GROUP BY + 1 +) -- add cumulative amounts +SELECT + ts, + snx_amount, + usd_amount, + SUM(snx_amount) over ( + ORDER BY + ts + ) AS cumulative_snx_amount, + SUM(usd_amount) over ( + ORDER BY + ts + ) AS cumulative_usd_amount +FROM + agg diff --git a/transformers/synthetix/models/marts/buyback/fct_buyback_hourly.sql b/transformers/synthetix/models/marts/buyback/fct_buyback_hourly.sql new file mode 100644 index 00000000..a7f7b9b2 --- /dev/null +++ b/transformers/synthetix/models/marts/buyback/fct_buyback_hourly.sql @@ -0,0 +1,27 @@ +WITH agg AS ( + SELECT + DATE_TRUNC( + 'hour', + ts + ) AS ts, + SUM(snx) AS snx_amount, + SUM(usd) AS usd_amount + FROM + {{ ref('fct_buyback') }} + GROUP BY + 1 +) -- add cumulative amounts +SELECT + ts, + snx_amount, + usd_amount, + SUM(snx_amount) over ( + ORDER BY + ts + ) AS cumulative_snx_amount, + SUM(usd_amount) over ( + ORDER BY + ts + ) AS cumulative_usd_amount +FROM + agg diff --git a/transformers/synthetix/models/raw/buyback/buyback_processed.sql b/transformers/synthetix/models/raw/buyback/buyback_processed.sql new file mode 100644 index 00000000..e8e7f047 --- /dev/null +++ b/transformers/synthetix/models/raw/buyback/buyback_processed.sql @@ -0,0 +1,37 @@ +WITH legacy_events AS ( + {{ get_event_data( + 'buyback_snx_legacy', + 'buyback_processed' + ) }} +), +current_events AS ( + {{ get_event_data( + 'buyback_snx', + 'buyback_processed' + ) }} +) +SELECT + id, + block_number, + block_timestamp, + transaction_hash, + event_name, + contract, + buyer, + snx, + usd +FROM + legacy_events +UNION ALL +SELECT + id, + block_number, + block_timestamp, + transaction_hash, + event_name, + contract, + buyer, + snx, + usd +FROM + current_events diff --git a/transformers/synthetix/models/raw/sources.yml b/transformers/synthetix/models/raw/sources.yml index 8acfedac..3484c2da 100644 --- a/transformers/synthetix/models/raw/sources.yml +++ b/transformers/synthetix/models/raw/sources.yml @@ -47,6 +47,8 @@ sources: - name: core_proxy_event_market_usd_deposited - name: core_proxy_event_market_usd_withdrawn + - name: buyback_snx_event_buyback_processed + - name: core_get_vault_collateral - name: core_get_vault_debt - name: blocks_parquet @@ -97,6 +99,9 @@ sources: - name: core_proxy_event_market_usd_deposited - name: core_proxy_event_market_usd_withdrawn + - name: buyback_snx_legacy_event_buyback_processed + - name: buyback_snx_event_buyback_processed + - name: core_get_vault_collateral - name: core_get_vault_debt - name: blocks_parquet