From 09804a72c1054f09ea30a4184f1c57ba4f7ad1f9 Mon Sep 17 00:00:00 2001 From: Felix Henneke Date: Tue, 16 Jan 2024 10:17:26 +0100 Subject: [PATCH] Add test for order quotes (#331) This PR adds a test for the quote rewards query. The tables `orders`, `order_quotes`, `trades` were added to the test database. A new unit test using this data was added. It covers: - market orders (normal reward) - partially fillable orders (no reward) - in market limit orders (reward) --- .../queries/batch_rewards_test_db.sql | 56 ++++++++-------- tests/queries/quote_rewards_test_db.sql | 67 +++++++++++++++++++ tests/queries/test_batch_rewards.py | 4 +- tests/queries/test_quote_rewards.py | 39 +++++++++++ 4 files changed, 138 insertions(+), 28 deletions(-) rename populate_cip_20.sql => tests/queries/batch_rewards_test_db.sql (59%) create mode 100644 tests/queries/quote_rewards_test_db.sql create mode 100644 tests/queries/test_quote_rewards.py diff --git a/populate_cip_20.sql b/tests/queries/batch_rewards_test_db.sql similarity index 59% rename from populate_cip_20.sql rename to tests/queries/batch_rewards_test_db.sql index 2b309ed0..c984e1d4 100644 --- a/populate_cip_20.sql +++ b/tests/queries/batch_rewards_test_db.sql @@ -34,11 +34,12 @@ CREATE TABLE IF NOT EXISTS auction_participants CREATE TABLE IF NOT EXISTS settlement_scores ( - auction_id bigint PRIMARY KEY, - block_deadline bigint NOT NULL, - winner bytea NOT NULL, - winning_score numeric(78, 0) NOT NULL, - reference_score numeric(78, 0) NOT NULL + auction_id bigint PRIMARY KEY, + winner bytea NOT NULL, + winning_score numeric(78, 0) NOT NULL, + reference_score numeric(78, 0) NOT NULL, + block_deadline bigint NOT NULL, + simulation_block bigint NOT NULL ); -- Populated after block finalization via transactionReceipt. @@ -61,14 +62,15 @@ TRUNCATE auction_participants; TRUNCATE settlement_scores; TRUNCATE settlement_observations; + INSERT INTO settlements (block_number, log_index, solver, tx_hash, tx_from, tx_nonce) -VALUES (1, 0, '\x5111111111111111111111111111111111111111'::bytea, '\x7111'::bytea, '\x5111111111111111111111111111111111111111'::bytea, 1), - (2, 0, '\x5222222222222222222222222222222222222222'::bytea, '\x7222'::bytea, '\x5222222222222222222222222222222222222222'::bytea, 1), - (5, 0, '\x5111111111111111111111111111111111111111'::bytea, '\x7333'::bytea, '\x5111111111111111111111111111111111111111'::bytea, 2), +VALUES (1, 10, '\x5111111111111111111111111111111111111111'::bytea, '\x7111'::bytea, '\x5111111111111111111111111111111111111111'::bytea, 1), + (2, 10, '\x5222222222222222222222222222222222222222'::bytea, '\x7222'::bytea, '\x5222222222222222222222222222222222222222'::bytea, 1), + (5, 10, '\x5111111111111111111111111111111111111111'::bytea, '\x7333'::bytea, '\x5111111111111111111111111111111111111111'::bytea, 2), -- would the following entry be in the data base? (submitted too late) -- YES - (20, 0, '\x5111111111111111111111111111111111111111'::bytea, '\x7444'::bytea, '\x5111111111111111111111111111111111111111'::bytea, 3), - (25, 0, '\x5111111111111111111111111111111111111111'::bytea, '\x7555'::bytea, '\x5111111111111111111111111111111111111111'::bytea, 4), - (26, 0, '\x5111111111111111111111111111111111111111'::bytea, '\x7666'::bytea, '\x5111111111111111111111111111111111111111'::bytea, 6); + (20, 10, '\x5111111111111111111111111111111111111111'::bytea, '\x7444'::bytea, '\x5111111111111111111111111111111111111111'::bytea, 3), + (25, 10, '\x5111111111111111111111111111111111111111'::bytea, '\x7555'::bytea, '\x5111111111111111111111111111111111111111'::bytea, 4), + (26, 10, '\x5111111111111111111111111111111111111111'::bytea, '\x7666'::bytea, '\x5111111111111111111111111111111111111111'::bytea, 6); INSERT INTO auction_transaction (auction_id, tx_from, tx_nonce) VALUES (1, '\x5111111111111111111111111111111111111111'::bytea, 1), @@ -104,23 +106,23 @@ VALUES (1, '\x5222222222222222222222222222222222222222'::bytea), (10, '\x5444444444444444444444444444444444444444'::bytea), (10, '\x5333333333333333333333333333333333333333'::bytea); -INSERT INTO settlement_scores (auction_id, block_deadline, winning_score, reference_score, winner) -VALUES (1, 10, 5000000000000000000, 4000000000000000000, '\x5111111111111111111111111111111111111111'::bytea), - (2, 11, 6000000000000000000, 3000000000000000000, '\x5222222222222222222222222222222222222222'::bytea), - (3, 12, 21000000000000000000, 3000000000000000000, '\x5111111111111111111111111111111111111111'::bytea), - (5, 14, 5000000000000000000, 3000000000000000000, '\x5111111111111111111111111111111111111111'::bytea), -- jump in auction id - (6, 15, 10000000000000000000, 9000000000000000000, '\x5111111111111111111111111111111111111111'::bytea), -- settled too late - (7, 30, 5000000000000000000, 0, '\x5111111111111111111111111111111111111111'::bytea), -- no competition - (8, 35, 5000000000000000000, 0, '\x5111111111111111111111111111111111111111'::bytea), -- no competition, failed transaction - (9, 36, 5000000000000000000, 1000000000000000000, '\x5111111111111111111111111111111111111111'::bytea), -- score larger than quality - (10, 37, 5000000000000000000, 4000000000000000000, '\x5333333333333333333333333333333333333333'::bytea); -- participant with net negative payment +INSERT INTO settlement_scores (auction_id, winning_score, reference_score, winner, block_deadline, simulation_block) +VALUES (1, 5000000000000000000, 4000000000000000000, '\x5111111111111111111111111111111111111111'::bytea, 10, 0), + (2, 6000000000000000000, 3000000000000000000, '\x5222222222222222222222222222222222222222'::bytea, 11, 1), + (3, 21000000000000000000, 3000000000000000000, '\x5111111111111111111111111111111111111111'::bytea, 12, 2), + (5, 5000000000000000000, 3000000000000000000, '\x5111111111111111111111111111111111111111'::bytea, 14, 4), -- jump in auction id + (6, 10000000000000000000, 9000000000000000000, '\x5111111111111111111111111111111111111111'::bytea, 15, 5), -- settled too late + (7, 5000000000000000000, 0, '\x5111111111111111111111111111111111111111'::bytea, 30, 6), -- no competition + (8, 5000000000000000000, 0, '\x5111111111111111111111111111111111111111'::bytea, 35, 7), -- no competition, failed transaction + (9, 5000000000000000000, 1000000000000000000, '\x5111111111111111111111111111111111111111'::bytea, 36, 8), -- score larger than quality + (10, 5000000000000000000, 4000000000000000000, '\x5333333333333333333333333333333333333333'::bytea, 37, 9); -- participant with net negative payment INSERT INTO settlement_observations (block_number, log_index, gas_used, effective_gas_price, surplus, fee) -VALUES (1, 0, 100000, 2000000000, 6000000000000000000, 200000000000000), - (2, 0, 150000, 3000000000, 12000000000000000000, 400000000000000), - (5, 0, 100000, 2000000000, 5000000000000000000, 250000000000000), +VALUES (1, 10, 100000, 2000000000, 6000000000000000000, 200000000000000), + (2, 10, 150000, 3000000000, 12000000000000000000, 400000000000000), + (5, 10, 100000, 2000000000, 5000000000000000000, 250000000000000), -- Depends on backend (setting surplus and fee to zero). -- I would prefer to use the real numbers. What is backend gonna do. - (20, 0, 100000, 2000000000, 0, 0), -- would that entry be in the data base? (submitted too late) - (25, 0, 100000, 2000000000, 6000000000000000000, 200000000000000), - (26, 0, 100000, 2000000000, 0, 400000000000000); + (20, 10, 100000, 2000000000, 0, 0), -- would that entry be in the data base? (submitted too late) + (25, 10, 100000, 2000000000, 6000000000000000000, 200000000000000), + (26, 10, 100000, 2000000000, 0, 400000000000000); diff --git a/tests/queries/quote_rewards_test_db.sql b/tests/queries/quote_rewards_test_db.sql new file mode 100644 index 00000000..6121228c --- /dev/null +++ b/tests/queries/quote_rewards_test_db.sql @@ -0,0 +1,67 @@ +DROP TABLE IF EXISTS orders; +DROP TYPE IF EXISTS OrderKind; +DROP TABLE IF EXISTS order_quotes; +DROP TABLE IF EXISTS trades; + + +-- orders table +CREATE TYPE OrderKind AS ENUM ('buy', 'sell'); + +CREATE TABLE IF NOT EXISTS orders +( + uid bytea PRIMARY KEY, + sell_amount numeric(78,0) NOT NULL, + buy_amount numeric(78,0) NOT NULL, + fee_amount numeric(78,0) NOT NULL, + kind OrderKind NOT NULL, + partially_fillable boolean NOT NULL +); + +CREATE TABLE IF NOT EXISTS order_quotes +( + order_uid bytea PRIMARY KEY, + sell_amount numeric(78, 0) NOT NULL, + buy_amount numeric(78, 0) NOT NULL, + solver bytea NOT NULL +); + +CREATE TABLE IF NOT EXISTS trades +( + block_number bigint NOT NULL, + log_index bigint NOT NULL, + order_uid bytea NOT NULL, + sell_amount numeric(78, 0) NOT NULL, + buy_amount numeric(78, 0) NOT NULL, + + PRIMARY KEY (block_number, log_index) +); + + +TRUNCATE orders; +TRUNCATE order_quotes; +TRUNCATE trades; + + +INSERT INTO orders (uid, sell_amount, buy_amount, fee_amount, kind, partially_fillable) +VALUES ('\x01'::bytea, 95000000, 94000000000000000000, 5000000, 'sell', 'f'), -- normal sell market order +('\x02'::bytea, 101000000, 100000000000000000000, 5000000, 'buy', 'f'), -- normal buy market order +('\x03'::bytea, 100000000, 100000000000000000000, 0, 'sell', 't'), -- partially fillable sell limit order +('\x04'::bytea, 100000000, 100000000000000000000, 0, 'buy', 't'), -- partially fillable buy limit order +('\x05'::bytea, 100000000, 94000000000000000000, 0, 'sell', 'f'), -- in market sell limit order +('\x06'::bytea, 106000000, 100000000000000000000, 0, 'buy', 'f'); -- in market buy limit order + +INSERT INTO order_quotes (order_uid, sell_amount, buy_amount, solver) +VALUES ('\x01'::bytea, 95000000, 95000000000000000000, '\x01'::bytea), +('\x02'::bytea, 101000000, 100000000000000000000, '\x02'::bytea), +('\x03'::bytea, 100000000, 95000000000000000000, '\x03'::bytea), +('\x04'::bytea, 105000000, 100000000000000000000, '\x03'::bytea), +('\x05'::bytea, 100000000, 95000000000000000000, '\x03'::bytea), +('\x06'::bytea, 105000000, 100000000000000000000, '\x03'::bytea); + +INSERT INTO trades (block_number, log_index, order_uid, sell_amount, buy_amount) +VALUES (1, 0, '\x01'::bytea, 100000000, 95000000000000000000), +(2, 0, '\x02'::bytea, 106000000, 100000000000000000000), +(3, 0, '\x03'::bytea, 100000000, 101000000000000000000), +(4, 0, '\x04'::bytea, 99000000, 100000000000000000000), +(5, 0, '\x05'::bytea, 100000000, 95000000000000000000), +(6, 0, '\x06'::bytea, 105000000, 100000000000000000000); diff --git a/tests/queries/test_batch_rewards.py b/tests/queries/test_batch_rewards.py index a5feb01f..fc6f3fb2 100644 --- a/tests/queries/test_batch_rewards.py +++ b/tests/queries/test_batch_rewards.py @@ -10,7 +10,9 @@ class TestBatchRewards(unittest.TestCase): def setUp(self) -> None: db_url = "postgres:postgres@localhost:5432/postgres" self.fetcher = MultiInstanceDBFetcher([db_url]) - with open("./populate_cip_20.sql", "r", encoding="utf-8") as file: + with open( + "./tests/queries/batch_rewards_test_db.sql", "r", encoding="utf-8" + ) as file: self.fetcher.connections[0].execute(file.read()) def test_get_batch_rewards(self): diff --git a/tests/queries/test_quote_rewards.py b/tests/queries/test_quote_rewards.py new file mode 100644 index 00000000..8bad030b --- /dev/null +++ b/tests/queries/test_quote_rewards.py @@ -0,0 +1,39 @@ +import unittest + +import pandas.testing +from pandas import DataFrame + +from src.pg_client import MultiInstanceDBFetcher + + +class TestQuoteRewards(unittest.TestCase): + def setUp(self) -> None: + db_url = "postgres:postgres@localhost:5432/postgres" + self.fetcher = MultiInstanceDBFetcher([db_url]) + with open( + "./tests/queries/quote_rewards_test_db.sql", "r", encoding="utf-8" + ) as file: + self.fetcher.connections[0].execute(file.read()) + + def test_get_quote_rewards(self): + start_block, end_block = "0", "100" + quote_rewards = self.fetcher.get_quote_rewards(start_block, end_block) + expected = DataFrame( + { + "solver": [ + "0x01", + "0x02", + "0x03", + ], + "num_quotes": [ + 1, + 1, + 2, + ], + } + ) + self.assertIsNone(pandas.testing.assert_frame_equal(expected, quote_rewards)) + + +if __name__ == "__main__": + unittest.main()