diff --git a/apps/fortuna/.gitignore b/apps/fortuna/.gitignore index 7e54106f12..9fb1d0163d 100644 --- a/apps/fortuna/.gitignore +++ b/apps/fortuna/.gitignore @@ -2,3 +2,5 @@ *config.yaml *secret* *private-key* +.envrc +fortuna.db diff --git a/apps/fortuna/.sqlx/query-392da9e5fdd212a4a665c86e5fc6d4f619355294490248e656ad0fc97a252471.json b/apps/fortuna/.sqlx/query-392da9e5fdd212a4a665c86e5fc6d4f619355294490248e656ad0fc97a252471.json deleted file mode 100644 index 4f145288ec..0000000000 --- a/apps/fortuna/.sqlx/query-392da9e5fdd212a4a665c86e5fc6d4f619355294490248e656ad0fc97a252471.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT * FROM request WHERE created_at >= ? AND created_at <= ? ORDER BY created_at DESC LIMIT ? OFFSET ?", - "describe": { - "columns": [ - { - "name": "chain_id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "network_id", - "ordinal": 1, - "type_info": "Integer" - }, - { - "name": "provider", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "sequence", - "ordinal": 3, - "type_info": "Integer" - }, - { - "name": "created_at", - "ordinal": 4, - "type_info": "Datetime" - }, - { - "name": "last_updated_at", - "ordinal": 5, - "type_info": "Datetime" - }, - { - "name": "state", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "request_block_number", - "ordinal": 7, - "type_info": "Integer" - }, - { - "name": "request_tx_hash", - "ordinal": 8, - "type_info": "Text" - }, - { - "name": "user_random_number", - "ordinal": 9, - "type_info": "Text" - }, - { - "name": "sender", - "ordinal": 10, - "type_info": "Text" - }, - { - "name": "reveal_block_number", - "ordinal": 11, - "type_info": "Integer" - }, - { - "name": "reveal_tx_hash", - "ordinal": 12, - "type_info": "Text" - }, - { - "name": "provider_random_number", - "ordinal": 13, - "type_info": "Text" - }, - { - "name": "info", - "ordinal": 14, - "type_info": "Text" - }, - { - "name": "gas_used", - "ordinal": 15, - "type_info": "Text" - }, - { - "name": "gas_limit", - "ordinal": 16, - "type_info": "Text" - } - ], - "parameters": { - "Right": 4 - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - true, - true, - true, - true, - true, - false - ] - }, - "hash": "392da9e5fdd212a4a665c86e5fc6d4f619355294490248e656ad0fc97a252471" -} diff --git a/apps/fortuna/.sqlx/query-78be8c62d5eb764995221f927b0f166e38d6fba8eb8fddb07f50c572fd27b4e2.json b/apps/fortuna/.sqlx/query-78be8c62d5eb764995221f927b0f166e38d6fba8eb8fddb07f50c572fd27b4e2.json deleted file mode 100644 index 1ba9d570d2..0000000000 --- a/apps/fortuna/.sqlx/query-78be8c62d5eb764995221f927b0f166e38d6fba8eb8fddb07f50c572fd27b4e2.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT * FROM request WHERE network_id = ? AND created_at >= ? AND created_at <= ? ORDER BY created_at DESC LIMIT ? OFFSET ?", - "describe": { - "columns": [ - { - "name": "chain_id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "network_id", - "ordinal": 1, - "type_info": "Integer" - }, - { - "name": "provider", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "sequence", - "ordinal": 3, - "type_info": "Integer" - }, - { - "name": "created_at", - "ordinal": 4, - "type_info": "Datetime" - }, - { - "name": "last_updated_at", - "ordinal": 5, - "type_info": "Datetime" - }, - { - "name": "state", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "request_block_number", - "ordinal": 7, - "type_info": "Integer" - }, - { - "name": "request_tx_hash", - "ordinal": 8, - "type_info": "Text" - }, - { - "name": "user_random_number", - "ordinal": 9, - "type_info": "Text" - }, - { - "name": "sender", - "ordinal": 10, - "type_info": "Text" - }, - { - "name": "reveal_block_number", - "ordinal": 11, - "type_info": "Integer" - }, - { - "name": "reveal_tx_hash", - "ordinal": 12, - "type_info": "Text" - }, - { - "name": "provider_random_number", - "ordinal": 13, - "type_info": "Text" - }, - { - "name": "info", - "ordinal": 14, - "type_info": "Text" - }, - { - "name": "gas_used", - "ordinal": 15, - "type_info": "Text" - }, - { - "name": "gas_limit", - "ordinal": 16, - "type_info": "Text" - } - ], - "parameters": { - "Right": 5 - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - true, - true, - true, - true, - true, - false - ] - }, - "hash": "78be8c62d5eb764995221f927b0f166e38d6fba8eb8fddb07f50c572fd27b4e2" -} diff --git a/apps/fortuna/.sqlx/query-8cd10cd5839b81bd9538aeb10fdfd27c6e36baf5d90a4fb9e61718f021812710.json b/apps/fortuna/.sqlx/query-8cd10cd5839b81bd9538aeb10fdfd27c6e36baf5d90a4fb9e61718f021812710.json deleted file mode 100644 index 05031bec35..0000000000 --- a/apps/fortuna/.sqlx/query-8cd10cd5839b81bd9538aeb10fdfd27c6e36baf5d90a4fb9e61718f021812710.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT * FROM request WHERE sender = ?", - "describe": { - "columns": [ - { - "name": "chain_id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "network_id", - "ordinal": 1, - "type_info": "Integer" - }, - { - "name": "provider", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "sequence", - "ordinal": 3, - "type_info": "Integer" - }, - { - "name": "created_at", - "ordinal": 4, - "type_info": "Datetime" - }, - { - "name": "last_updated_at", - "ordinal": 5, - "type_info": "Datetime" - }, - { - "name": "state", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "request_block_number", - "ordinal": 7, - "type_info": "Integer" - }, - { - "name": "request_tx_hash", - "ordinal": 8, - "type_info": "Text" - }, - { - "name": "user_random_number", - "ordinal": 9, - "type_info": "Text" - }, - { - "name": "sender", - "ordinal": 10, - "type_info": "Text" - }, - { - "name": "reveal_block_number", - "ordinal": 11, - "type_info": "Integer" - }, - { - "name": "reveal_tx_hash", - "ordinal": 12, - "type_info": "Text" - }, - { - "name": "provider_random_number", - "ordinal": 13, - "type_info": "Text" - }, - { - "name": "info", - "ordinal": 14, - "type_info": "Text" - }, - { - "name": "gas_used", - "ordinal": 15, - "type_info": "Text" - }, - { - "name": "gas_limit", - "ordinal": 16, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - true, - true, - true, - true, - true, - false - ] - }, - "hash": "8cd10cd5839b81bd9538aeb10fdfd27c6e36baf5d90a4fb9e61718f021812710" -} diff --git a/apps/fortuna/.sqlx/query-905dbc91cd5319537c5c194277d531689ac5c1338396414467496d0f50ddc3f0.json b/apps/fortuna/.sqlx/query-905dbc91cd5319537c5c194277d531689ac5c1338396414467496d0f50ddc3f0.json deleted file mode 100644 index 0bc128fb33..0000000000 --- a/apps/fortuna/.sqlx/query-905dbc91cd5319537c5c194277d531689ac5c1338396414467496d0f50ddc3f0.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT * FROM request WHERE sequence = ?", - "describe": { - "columns": [ - { - "name": "chain_id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "network_id", - "ordinal": 1, - "type_info": "Integer" - }, - { - "name": "provider", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "sequence", - "ordinal": 3, - "type_info": "Integer" - }, - { - "name": "created_at", - "ordinal": 4, - "type_info": "Datetime" - }, - { - "name": "last_updated_at", - "ordinal": 5, - "type_info": "Datetime" - }, - { - "name": "state", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "request_block_number", - "ordinal": 7, - "type_info": "Integer" - }, - { - "name": "request_tx_hash", - "ordinal": 8, - "type_info": "Text" - }, - { - "name": "user_random_number", - "ordinal": 9, - "type_info": "Text" - }, - { - "name": "sender", - "ordinal": 10, - "type_info": "Text" - }, - { - "name": "reveal_block_number", - "ordinal": 11, - "type_info": "Integer" - }, - { - "name": "reveal_tx_hash", - "ordinal": 12, - "type_info": "Text" - }, - { - "name": "provider_random_number", - "ordinal": 13, - "type_info": "Text" - }, - { - "name": "info", - "ordinal": 14, - "type_info": "Text" - }, - { - "name": "gas_used", - "ordinal": 15, - "type_info": "Text" - }, - { - "name": "gas_limit", - "ordinal": 16, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - true, - true, - true, - true, - true, - false - ] - }, - "hash": "905dbc91cd5319537c5c194277d531689ac5c1338396414467496d0f50ddc3f0" -} diff --git a/apps/fortuna/.sqlx/query-a62e094cee65ae58bd12ce7d3e7df44f5aca31520d1ceced83f492945e850764.json b/apps/fortuna/.sqlx/query-a62e094cee65ae58bd12ce7d3e7df44f5aca31520d1ceced83f492945e850764.json deleted file mode 100644 index 39ff0484e7..0000000000 --- a/apps/fortuna/.sqlx/query-a62e094cee65ae58bd12ce7d3e7df44f5aca31520d1ceced83f492945e850764.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT * FROM request WHERE request_tx_hash = ? OR reveal_tx_hash = ?", - "describe": { - "columns": [ - { - "name": "chain_id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "network_id", - "ordinal": 1, - "type_info": "Integer" - }, - { - "name": "provider", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "sequence", - "ordinal": 3, - "type_info": "Integer" - }, - { - "name": "created_at", - "ordinal": 4, - "type_info": "Datetime" - }, - { - "name": "last_updated_at", - "ordinal": 5, - "type_info": "Datetime" - }, - { - "name": "state", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "request_block_number", - "ordinal": 7, - "type_info": "Integer" - }, - { - "name": "request_tx_hash", - "ordinal": 8, - "type_info": "Text" - }, - { - "name": "user_random_number", - "ordinal": 9, - "type_info": "Text" - }, - { - "name": "sender", - "ordinal": 10, - "type_info": "Text" - }, - { - "name": "reveal_block_number", - "ordinal": 11, - "type_info": "Integer" - }, - { - "name": "reveal_tx_hash", - "ordinal": 12, - "type_info": "Text" - }, - { - "name": "provider_random_number", - "ordinal": 13, - "type_info": "Text" - }, - { - "name": "info", - "ordinal": 14, - "type_info": "Text" - }, - { - "name": "gas_used", - "ordinal": 15, - "type_info": "Text" - }, - { - "name": "gas_limit", - "ordinal": 16, - "type_info": "Text" - } - ], - "parameters": { - "Right": 2 - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - true, - true, - true, - true, - true, - false - ] - }, - "hash": "a62e094cee65ae58bd12ce7d3e7df44f5aca31520d1ceced83f492945e850764" -} diff --git a/apps/fortuna/.sqlx/query-c9e3089b1ffd52d20cfcd89e71e051c0f351643dce9be4b84b6343909c816c22.json b/apps/fortuna/.sqlx/query-c9e3089b1ffd52d20cfcd89e71e051c0f351643dce9be4b84b6343909c816c22.json deleted file mode 100644 index 6129528669..0000000000 --- a/apps/fortuna/.sqlx/query-c9e3089b1ffd52d20cfcd89e71e051c0f351643dce9be4b84b6343909c816c22.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT * FROM request WHERE sequence = ? AND network_id = ?", - "describe": { - "columns": [ - { - "name": "chain_id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "network_id", - "ordinal": 1, - "type_info": "Integer" - }, - { - "name": "provider", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "sequence", - "ordinal": 3, - "type_info": "Integer" - }, - { - "name": "created_at", - "ordinal": 4, - "type_info": "Datetime" - }, - { - "name": "last_updated_at", - "ordinal": 5, - "type_info": "Datetime" - }, - { - "name": "state", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "request_block_number", - "ordinal": 7, - "type_info": "Integer" - }, - { - "name": "request_tx_hash", - "ordinal": 8, - "type_info": "Text" - }, - { - "name": "user_random_number", - "ordinal": 9, - "type_info": "Text" - }, - { - "name": "sender", - "ordinal": 10, - "type_info": "Text" - }, - { - "name": "reveal_block_number", - "ordinal": 11, - "type_info": "Integer" - }, - { - "name": "reveal_tx_hash", - "ordinal": 12, - "type_info": "Text" - }, - { - "name": "provider_random_number", - "ordinal": 13, - "type_info": "Text" - }, - { - "name": "info", - "ordinal": 14, - "type_info": "Text" - }, - { - "name": "gas_used", - "ordinal": 15, - "type_info": "Text" - }, - { - "name": "gas_limit", - "ordinal": 16, - "type_info": "Text" - } - ], - "parameters": { - "Right": 2 - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - true, - true, - true, - true, - true, - false - ] - }, - "hash": "c9e3089b1ffd52d20cfcd89e71e051c0f351643dce9be4b84b6343909c816c22" -} diff --git a/apps/fortuna/.sqlx/query-f58bdd3e0ecb30f35356c22e9ab1b3802f8eebda455efabc18d30f02d23787b7.json b/apps/fortuna/.sqlx/query-f58bdd3e0ecb30f35356c22e9ab1b3802f8eebda455efabc18d30f02d23787b7.json deleted file mode 100644 index 32cbf3b9c5..0000000000 --- a/apps/fortuna/.sqlx/query-f58bdd3e0ecb30f35356c22e9ab1b3802f8eebda455efabc18d30f02d23787b7.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT * FROM request WHERE sender = ? AND network_id = ?", - "describe": { - "columns": [ - { - "name": "chain_id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "network_id", - "ordinal": 1, - "type_info": "Integer" - }, - { - "name": "provider", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "sequence", - "ordinal": 3, - "type_info": "Integer" - }, - { - "name": "created_at", - "ordinal": 4, - "type_info": "Datetime" - }, - { - "name": "last_updated_at", - "ordinal": 5, - "type_info": "Datetime" - }, - { - "name": "state", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "request_block_number", - "ordinal": 7, - "type_info": "Integer" - }, - { - "name": "request_tx_hash", - "ordinal": 8, - "type_info": "Text" - }, - { - "name": "user_random_number", - "ordinal": 9, - "type_info": "Text" - }, - { - "name": "sender", - "ordinal": 10, - "type_info": "Text" - }, - { - "name": "reveal_block_number", - "ordinal": 11, - "type_info": "Integer" - }, - { - "name": "reveal_tx_hash", - "ordinal": 12, - "type_info": "Text" - }, - { - "name": "provider_random_number", - "ordinal": 13, - "type_info": "Text" - }, - { - "name": "info", - "ordinal": 14, - "type_info": "Text" - }, - { - "name": "gas_used", - "ordinal": 15, - "type_info": "Text" - }, - { - "name": "gas_limit", - "ordinal": 16, - "type_info": "Text" - } - ], - "parameters": { - "Right": 2 - }, - "nullable": [ - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - false, - true, - true, - true, - true, - true, - false - ] - }, - "hash": "f58bdd3e0ecb30f35356c22e9ab1b3802f8eebda455efabc18d30f02d23787b7" -} diff --git a/apps/fortuna/README.md b/apps/fortuna/README.md index dc2316ba52..416aa5e486 100644 --- a/apps/fortuna/README.md +++ b/apps/fortuna/README.md @@ -57,3 +57,12 @@ RUST_LOG=INFO cargo run -- run ``` This command will start the webservice on `localhost:34000`. + +## Nix + +If you are a nix user, you can use the included [Nix flake](./flake.nix) and +[direnv config](./envrc) which will configure your environment for you +automatically. If you use this configuration you will have a `cli` script in +your dev shell which provides easy access to some common tasks, such as `cli +start` to start the server in watch mode, `cli test` to run unit, code format, +and lint checks, and `cli fix` to run auto-fixes for formatting and lint issues. diff --git a/apps/fortuna/flake.lock b/apps/fortuna/flake.lock new file mode 100644 index 0000000000..59e9f60266 --- /dev/null +++ b/apps/fortuna/flake.lock @@ -0,0 +1,149 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "mkCli": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1722285416, + "narHash": "sha256-Yb1NV8zVt9gMnlEni8IFLtLhGkqPDYAoZxi7ZxiZq0A=", + "owner": "cprussin", + "repo": "mkCli", + "rev": "983799699e84d2cb428b65b8f628663bfc82fbb2", + "type": "github" + }, + "original": { + "owner": "cprussin", + "repo": "mkCli", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1718310279, + "narHash": "sha256-OfRCrNPMLlElYIUAWIOGAvJ5XDT/WpOXj6Ymfttj6Lk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5dde575c3c4afb618781387b0db6d1c08a206c92", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1748799545, + "narHash": "sha256-IcYNrKd4yztiJv2B3EKy70qf1vNBKxnXhf4j0ntMSAM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "83ae70ea0415026d51d4a12bb82c962a2eaab5b0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "mkCli": "mkCli", + "nixpkgs": "nixpkgs_2", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1748746145, + "narHash": "sha256-bwkCAK9pOyI2Ww4Q4oO1Ynv7O9aZPrsIAMMASmhVGp4=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "12a0d94a2f2b06714f747ab97b2fa546f46b460c", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/apps/fortuna/flake.nix b/apps/fortuna/flake.nix new file mode 100644 index 0000000000..583ba71598 --- /dev/null +++ b/apps/fortuna/flake.nix @@ -0,0 +1,63 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs"; + flake-utils.url = "github:numtide/flake-utils"; + mkCli.url = "github:cprussin/mkCli"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { + nixpkgs, + flake-utils, + mkCli, + rust-overlay, + ... + }: ( + flake-utils.lib.eachDefaultSystem + ( + system: let + cli-overlay = nixpkgs.lib.composeExtensions mkCli.overlays.default (_: prev: let + cargo = "cargo --color=always"; + in { + cli = prev.lib.mkCli "cli" { + _noAll = true; + start = "${cargo} sqlx migrate run && ${cargo} sqlx prepare && RUST_LOG=info ${cargo} watch -x 'run -- run'"; + test = { + format = "${cargo} fmt --check"; + lint = "${cargo} sqlx migrate run && ${cargo} sqlx prepare && ${cargo} clippy --color always"; + unit = "${cargo} sqlx migrate run && ${cargo} sqlx prepare && ${cargo} test -- --color always"; + }; + fix = { + format = "${cargo} fmt"; + lint = "${cargo} sqlx migrate run && ${cargo} sqlx prepare && ${cargo} clippy -- --color always --fix"; + }; + }; + }); + + pkgs = import nixpkgs { + inherit system; + overlays = [cli-overlay rust-overlay.overlays.default]; + config = {}; + }; + in { + devShells.default = pkgs.mkShell { + buildInputs = [ + pkgs.cli + pkgs.git + pkgs.openssl + pkgs.pkg-config + pkgs.rust-analyzer + pkgs.rust-bin.stable."1.82.0".default + pkgs.sqlx-cli + pkgs.foundry + pkgs.sqlite + pkgs.cargo-watch + ]; + }; + } + ) + ); +} diff --git a/apps/fortuna/migrations/20250605004757_add_indices_for_advanced_search.down.sql b/apps/fortuna/migrations/20250605004757_add_indices_for_advanced_search.down.sql new file mode 100644 index 0000000000..d7287b5c61 --- /dev/null +++ b/apps/fortuna/migrations/20250605004757_add_indices_for_advanced_search.down.sql @@ -0,0 +1,22 @@ +-- Add down migration script here + +DROP INDEX request__network_id__state__created_at; +DROP INDEX request__network_id__created_at; +DROP INDEX request__sender__network_id__state__created_at; +DROP INDEX request__sender__network_id__created_at; +DROP INDEX request__sender__state__created_at; +DROP INDEX request__sender__created_at; +DROP INDEX request__sequence__network_id__state__created_at; +DROP INDEX request__sequence__network_id__created_at; +DROP INDEX request__sequence__state__created_at; +DROP INDEX request__sequence__created_at; +DROP INDEX request__state__created_at; +DROP INDEX request__created_at; + + +CREATE INDEX idx_request_sequence ON request (sequence); +CREATE INDEX idx_request_network_id_created_at ON request (network_id, created_at); +CREATE INDEX idx_request_created_at ON request (created_at); +CREATE INDEX idx_request_request_tx_hash ON request (request_tx_hash) WHERE request_tx_hash IS NOT NULL; +CREATE INDEX idx_request_reveal_tx_hash ON request (reveal_tx_hash) WHERE reveal_tx_hash IS NOT NULL; +CREATE INDEX idx_request_sender ON request (sender) WHERE sender IS NOT NULL; diff --git a/apps/fortuna/migrations/20250605004757_add_indices_for_advanced_search.up.sql b/apps/fortuna/migrations/20250605004757_add_indices_for_advanced_search.up.sql new file mode 100644 index 0000000000..7b087384b4 --- /dev/null +++ b/apps/fortuna/migrations/20250605004757_add_indices_for_advanced_search.up.sql @@ -0,0 +1,22 @@ +-- Add up migration script here + +DROP INDEX idx_request_sequence; +DROP INDEX idx_request_network_id_created_at; +DROP INDEX idx_request_created_at; +DROP INDEX idx_request_request_tx_hash; +DROP INDEX idx_request_reveal_tx_hash; +DROP INDEX idx_request_sender; + + +CREATE INDEX request__network_id__state__created_at ON request(network_id, state, created_at); +CREATE INDEX request__network_id__created_at ON request(network_id, created_at); +CREATE INDEX request__sender__network_id__state__created_at ON request(sender, network_id, state, created_at); +CREATE INDEX request__sender__network_id__created_at ON request(sender, network_id, created_at); +CREATE INDEX request__sender__state__created_at ON request(sender, state, created_at); +CREATE INDEX request__sender__created_at ON request(sender, created_at); +CREATE INDEX request__sequence__network_id__state__created_at ON request(sequence, network_id, state, created_at); +CREATE INDEX request__sequence__network_id__created_at ON request(sequence, network_id, created_at); +CREATE INDEX request__sequence__state__created_at ON request(sequence, state, created_at); +CREATE INDEX request__sequence__created_at ON request(sequence, created_at); +CREATE INDEX request__state__created_at ON request(state, created_at); +CREATE INDEX request__created_at ON request(created_at); diff --git a/apps/fortuna/migrations/20250605165549_re-add_tx_hash_indices.down.sql b/apps/fortuna/migrations/20250605165549_re-add_tx_hash_indices.down.sql new file mode 100644 index 0000000000..a57615dc2c --- /dev/null +++ b/apps/fortuna/migrations/20250605165549_re-add_tx_hash_indices.down.sql @@ -0,0 +1,4 @@ +-- Add down migration script here + +DROP INDEX request__request_tx_hash; +DROP INDEX request__reveal_tx_hash; diff --git a/apps/fortuna/migrations/20250605165549_re-add_tx_hash_indices.up.sql b/apps/fortuna/migrations/20250605165549_re-add_tx_hash_indices.up.sql new file mode 100644 index 0000000000..619dbdbdd2 --- /dev/null +++ b/apps/fortuna/migrations/20250605165549_re-add_tx_hash_indices.up.sql @@ -0,0 +1,4 @@ +-- Add up migration script here + +CREATE INDEX request__request_tx_hash ON request (request_tx_hash) WHERE request_tx_hash IS NOT NULL; +CREATE INDEX request__reveal_tx_hash ON request (reveal_tx_hash) WHERE reveal_tx_hash IS NOT NULL; diff --git a/apps/fortuna/src/api.rs b/apps/fortuna/src/api.rs index f960bad0ba..6ee7fd5d92 100644 --- a/apps/fortuna/src/api.rs +++ b/apps/fortuna/src/api.rs @@ -35,6 +35,13 @@ mod revelation; pub type ChainId = String; pub type NetworkId = u64; +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema, sqlx::Type)] +pub enum StateTag { + Pending, + Completed, + Failed, +} + #[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] pub struct RequestLabel { pub value: String, diff --git a/apps/fortuna/src/api/explorer.rs b/apps/fortuna/src/api/explorer.rs index dc7c0efa04..7e643d589a 100644 --- a/apps/fortuna/src/api/explorer.rs +++ b/apps/fortuna/src/api/explorer.rs @@ -1,6 +1,6 @@ use { crate::{ - api::{ApiBlockChainState, NetworkId, RestError}, + api::{ApiBlockChainState, NetworkId, RestError, StateTag}, history::RequestStatus, }, axum::{ @@ -8,8 +8,6 @@ use { Json, }, chrono::{DateTime, Utc}, - ethers::types::{Address, TxHash}, - std::str::FromStr, utoipa::IntoParams, }; @@ -27,6 +25,8 @@ pub struct ExplorerQueryParams { /// The network ID to filter the results by. #[param(value_type = Option)] pub network_id: Option, + /// The state to filter the results by. + pub state: Option, /// The maximum number of logs to return. Max value is 1000. #[param(default = 1000)] pub limit: Option, @@ -35,8 +35,6 @@ pub struct ExplorerQueryParams { pub offset: Option, } -const LOG_RETURN_LIMIT: u64 = 1000; - /// Returns the logs of all requests captured by the keeper. /// /// This endpoint allows you to filter the logs by a specific network ID, a query string (which can be a transaction hash, sender address, or sequence number), and a time range. @@ -65,51 +63,35 @@ pub async fn explorer( return Err(RestError::InvalidChainId); } } + let mut query = state.history.query(); + if let Some(search) = query_params.query { + query = query + .search(search) + .map_err(|_| RestError::InvalidQueryString)?; + } + if let Some(network_id) = query_params.network_id { + query = query.network_id(network_id); + } + if let Some(state) = query_params.state { + query = query.state(state); + } if let Some(limit) = query_params.limit { - if limit > LOG_RETURN_LIMIT || limit == 0 { - return Err(RestError::InvalidQueryString); - } + query = query + .limit(limit) + .map_err(|_| RestError::InvalidQueryString)?; } - if let Some(query) = query_params.query { - if let Ok(tx_hash) = TxHash::from_str(&query) { - return Ok(Json( - state - .history - .get_requests_by_tx_hash(tx_hash) - .await - .map_err(|_| RestError::TemporarilyUnavailable)?, - )); - } - if let Ok(sender) = Address::from_str(&query) { - return Ok(Json( - state - .history - .get_requests_by_sender(sender, query_params.network_id) - .await - .map_err(|_| RestError::TemporarilyUnavailable)?, - )); - } - if let Ok(sequence_number) = u64::from_str(&query) { - return Ok(Json( - state - .history - .get_requests_by_sequence(sequence_number, query_params.network_id) - .await - .map_err(|_| RestError::TemporarilyUnavailable)?, - )); - } - return Err(RestError::InvalidQueryString); + if let Some(offset) = query_params.offset { + query = query.offset(offset); + } + if let Some(min_timestamp) = query_params.min_timestamp { + query = query.min_timestamp(min_timestamp); + } + if let Some(max_timestamp) = query_params.max_timestamp { + query = query.max_timestamp(max_timestamp); } Ok(Json( - state - .history - .get_requests_by_time( - query_params.network_id, - query_params.limit.unwrap_or(LOG_RETURN_LIMIT), - query_params.offset.unwrap_or(0), - query_params.min_timestamp, - query_params.max_timestamp, - ) + query + .execute() .await .map_err(|_| RestError::TemporarilyUnavailable)?, )) diff --git a/apps/fortuna/src/command/run.rs b/apps/fortuna/src/command/run.rs index cd2fd65d7b..33a10c6ef1 100644 --- a/apps/fortuna/src/command/run.rs +++ b/apps/fortuna/src/command/run.rs @@ -44,6 +44,7 @@ pub async fn run_api( crate::history::RequestEntryState, crate::api::Blob, crate::api::BinaryEncoding, + crate::api::StateTag, ) ), tags( diff --git a/apps/fortuna/src/history.rs b/apps/fortuna/src/history.rs index 7c462b6e0c..e1160f21c1 100644 --- a/apps/fortuna/src/history.rs +++ b/apps/fortuna/src/history.rs @@ -1,5 +1,5 @@ use { - crate::api::{ChainId, NetworkId}, + crate::api::{ChainId, NetworkId, StateTag}, anyhow::Result, chrono::{DateTime, NaiveDateTime}, ethers::{ @@ -10,12 +10,14 @@ use { }, serde::Serialize, serde_with::serde_as, - sqlx::{migrate, Pool, Sqlite, SqlitePool}, - std::sync::Arc, + sqlx::{migrate, FromRow, Pool, QueryBuilder, Sqlite, SqlitePool}, + std::{str::FromStr, sync::Arc}, tokio::{spawn, sync::mpsc}, utoipa::ToSchema, }; +const LOG_RETURN_LIMIT: u64 = 1000; + #[serde_as] #[derive(Clone, Debug, Serialize, ToSchema, PartialEq)] #[serde(tag = "state", rename_all = "kebab-case")] @@ -97,7 +99,7 @@ impl RequestStatus { } } -#[derive(Clone, Debug, Serialize, ToSchema, PartialEq)] +#[derive(Clone, Debug, Serialize, ToSchema, PartialEq, FromRow)] struct RequestRow { chain_id: String, network_id: i64, @@ -335,136 +337,165 @@ impl History { } } - pub async fn get_requests_by_tx_hash(&self, tx_hash: TxHash) -> Result> { - let tx_hash: String = tx_hash.encode_hex(); - let rows = sqlx::query_as!( - RequestRow, - "SELECT * FROM request WHERE request_tx_hash = ? OR reveal_tx_hash = ?", - tx_hash, - tx_hash - ) - .fetch_all(&self.pool) - .await - .map_err(|e| { - tracing::error!("Failed to fetch request by tx hash: {}", e); - e - })?; - Ok(rows.into_iter().filter_map(|row| row.into()).collect()) + pub fn query(&self) -> RequestQueryBuilder { + RequestQueryBuilder::new(&self.pool) } +} - pub async fn get_requests_by_sender( - &self, - sender: Address, - network_id: Option, - ) -> Result> { - let sender: String = sender.encode_hex(); - let rows = match network_id { - Some(network_id) => { - let network_id = network_id as i64; - sqlx::query_as!( - RequestRow, - "SELECT * FROM request WHERE sender = ? AND network_id = ?", - sender, - network_id, - ) - .fetch_all(&self.pool) - .await - } - None => { - sqlx::query_as!(RequestRow, "SELECT * FROM request WHERE sender = ?", sender,) - .fetch_all(&self.pool) - .await - } +#[derive(Debug, Clone)] +pub struct RequestQueryBuilder<'a> { + pool: &'a Pool, + search: Option, + network_id: Option, + state: Option, + limit: i64, + offset: i64, + min_timestamp: DateTime, + max_timestamp: DateTime, +} + +impl<'a> RequestQueryBuilder<'a> { + fn new(pool: &'a Pool) -> Self { + Self { + pool, + search: None, + network_id: None, + state: None, + limit: LOG_RETURN_LIMIT as i64, + offset: 0, + // UTC_MIN and UTC_MAX are not valid timestamps in SQLite + // So we need small and large enough timestamps to replace them + min_timestamp: "2012-12-12T12:12:12Z" + .parse::>() + .unwrap(), + max_timestamp: "2050-12-12T12:12:12Z" + .parse::>() + .unwrap(), } - .map_err(|e| { - tracing::error!("Failed to fetch request by sender: {}", e); - e - })?; - Ok(rows.into_iter().filter_map(|row| row.into()).collect()) } - pub async fn get_requests_by_sequence( - &self, - sequence: u64, - network_id: Option, - ) -> Result> { - let sequence = sequence as i64; - let rows = match network_id { - Some(network_id) => { - let network_id = network_id as i64; - sqlx::query_as!( - RequestRow, - "SELECT * FROM request WHERE sequence = ? AND network_id = ?", - sequence, - network_id, - ) - .fetch_all(&self.pool) - .await - } - None => { - sqlx::query_as!( - RequestRow, - "SELECT * FROM request WHERE sequence = ?", - sequence, - ) - .fetch_all(&self.pool) - .await - } + pub fn search(mut self, search: String) -> Result { + if let Ok(tx_hash) = TxHash::from_str(&search) { + Ok(SearchField::TxHash(tx_hash)) + } else if let Ok(sender) = Address::from_str(&search) { + Ok(SearchField::Sender(sender)) + } else if let Ok(sequence_number) = u64::from_str(&search) { + Ok(SearchField::SequenceNumber(sequence_number as i64)) + } else { + Err(RequestQueryBuilderError::InvalidSearch) } - .map_err(|e| { - tracing::error!("Failed to fetch request by sequence: {}", e); - e - })?; - Ok(rows.into_iter().filter_map(|row| row.into()).collect()) + .map(|search_field| { + self.search = Some(search_field); + self + }) } - pub async fn get_requests_by_time( - &self, - network_id: Option, - limit: u64, - offset: u64, - min_timestamp: Option>, - max_timestamp: Option>, - ) -> Result> { - // UTC_MIN and UTC_MAX are not valid timestamps in SQLite - // So we need small and large enough timestamps to replace them - let min_timestamp = min_timestamp.unwrap_or( - "2012-12-12T12:12:12Z" - .parse::>() - .unwrap(), - ); - let max_timestamp = max_timestamp.unwrap_or( - "2050-12-12T12:12:12Z" - .parse::>() - .unwrap(), - ); - let limit = limit as i64; - let offset = offset as i64; - let rows = match network_id { - Some(network_id) => { - let network_id = network_id as i64; - sqlx::query_as!(RequestRow, "SELECT * FROM request WHERE network_id = ? AND created_at >= ? AND created_at <= ? ORDER BY created_at DESC LIMIT ? OFFSET ?", - network_id, - min_timestamp, - max_timestamp, - limit, - offset).fetch_all(&self.pool).await + pub fn network_id(mut self, network_id: NetworkId) -> Self { + self.network_id = Some(network_id as i64); + self + } + + pub fn state(mut self, state: StateTag) -> Self { + self.state = Some(state); + self + } + + pub fn limit(mut self, limit: u64) -> Result { + if limit > LOG_RETURN_LIMIT { + Err(RequestQueryBuilderError::LimitTooLarge) + } else if limit == 0 { + Err(RequestQueryBuilderError::ZeroLimit) + } else { + self.limit = limit as i64; + Ok(self) + } + } + + pub fn offset(mut self, offset: u64) -> Self { + self.offset = offset as i64; + self + } + + pub fn min_timestamp(mut self, min_timestamp: DateTime) -> Self { + self.min_timestamp = min_timestamp; + self + } + + pub fn max_timestamp(mut self, max_timestamp: DateTime) -> Self { + self.max_timestamp = max_timestamp; + self + } + + pub async fn execute(&self) -> Result> { + let mut query_builder = + QueryBuilder::new("SELECT * FROM request WHERE created_at BETWEEN "); + query_builder.push_bind(self.min_timestamp); + query_builder.push(" AND "); + query_builder.push_bind(self.max_timestamp); + + match &self.search { + Some(SearchField::TxHash(tx_hash)) => { + let tx_hash: String = tx_hash.encode_hex(); + query_builder.push(" AND (request_tx_hash = "); + query_builder.push_bind(tx_hash.clone()); + query_builder.push(" OR reveal_tx_hash = "); + query_builder.push_bind(tx_hash); + query_builder.push(")"); + } + Some(SearchField::Sender(sender)) => { + let sender: String = sender.encode_hex(); + query_builder.push(" AND sender = "); + query_builder.push_bind(sender); } - None => { - sqlx::query_as!(RequestRow, "SELECT * FROM request WHERE created_at >= ? AND created_at <= ? ORDER BY created_at DESC LIMIT ? OFFSET ?", - min_timestamp, - max_timestamp, - limit, - offset).fetch_all(&self.pool).await + Some(SearchField::SequenceNumber(sequence_number)) => { + query_builder.push(" AND sequence = "); + query_builder.push_bind(sequence_number); } - }.map_err(|e| { + None => (), + } + + if let Some(network_id) = &self.network_id { + query_builder.push(" AND network_id = "); + query_builder.push_bind(network_id); + } + + if let Some(state) = &self.state { + query_builder.push(" AND state = "); + query_builder.push_bind(state); + } + + query_builder.push(" ORDER BY created_at DESC LIMIT "); + query_builder.push_bind(self.limit); + query_builder.push(" OFFSET "); + query_builder.push_bind(self.offset); + + let rows = query_builder + .build_query_as::() + .fetch_all(self.pool) + .await; + + if let Err(e) = &rows { tracing::error!("Failed to fetch request by time: {}", e); - e - })?; - Ok(rows.into_iter().filter_map(|row| row.into()).collect()) + } + + Ok(rows?.into_iter().filter_map(|row| row.into()).collect()) } } +#[derive(Debug)] +pub enum RequestQueryBuilderError { + LimitTooLarge, + ZeroLimit, + InvalidSearch, +} + +#[derive(Debug, Clone)] +enum SearchField { + TxHash(TxHash), + Sender(Address), + SequenceNumber(i64), +} + #[cfg(test)] mod test { use {super::*, chrono::Duration, tokio::time::sleep}; @@ -505,37 +536,193 @@ mod test { History::update_request_status(&history.pool, status.clone()).await; let logs = history - .get_requests_by_sequence(status.sequence, Some(status.network_id)) + .query() + .search(status.sequence.to_string()) + .unwrap() + .network_id(status.network_id) + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(status.sequence.to_string()) + .unwrap() + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(status.sequence.to_string()) + .unwrap() + .state(StateTag::Completed) + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(status.request_tx_hash.encode_hex()) + .unwrap() + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(format!( + "0x{}", + status.request_tx_hash.encode_hex::() + )) + .unwrap() + .execute() .await .unwrap(); assert_eq!(logs, vec![status.clone()]); let logs = history - .get_requests_by_sequence(status.sequence, None) + .query() + .search(status.request_tx_hash.encode_hex::().to_uppercase()) + .unwrap() + .execute() .await .unwrap(); assert_eq!(logs, vec![status.clone()]); let logs = history - .get_requests_by_tx_hash(status.request_tx_hash) + .query() + .search(format!( + "0x{}", + status.request_tx_hash.encode_hex::().to_uppercase() + )) + .unwrap() + .execute() .await .unwrap(); assert_eq!(logs, vec![status.clone()]); let logs = history - .get_requests_by_tx_hash(reveal_tx_hash) + .query() + .search(status.request_tx_hash.encode_hex()) + .unwrap() + .state(StateTag::Completed) + .execute() .await .unwrap(); assert_eq!(logs, vec![status.clone()]); let logs = history - .get_requests_by_sender(status.sender, Some(status.network_id)) + .query() + .search(reveal_tx_hash.encode_hex()) + .unwrap() + .execute() .await .unwrap(); assert_eq!(logs, vec![status.clone()]); let logs = history - .get_requests_by_sender(status.sender, None) + .query() + .search(format!("0x{}", reveal_tx_hash.encode_hex::())) + .unwrap() + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(reveal_tx_hash.encode_hex::().to_uppercase()) + .unwrap() + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(format!( + "0x{}", + reveal_tx_hash.encode_hex::().to_uppercase() + )) + .unwrap() + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(reveal_tx_hash.encode_hex()) + .unwrap() + .state(StateTag::Completed) + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(status.sender.encode_hex()) + .unwrap() + .network_id(status.network_id) + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(format!("0x{}", status.sender.encode_hex::())) + .unwrap() + .network_id(status.network_id) + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(status.sender.encode_hex::().to_uppercase()) + .unwrap() + .network_id(status.network_id) + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(format!( + "0x{}", + status.sender.encode_hex::().to_uppercase() + )) + .unwrap() + .network_id(status.network_id) + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(status.sender.encode_hex()) + .unwrap() + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![status.clone()]); + + let logs = history + .query() + .search(status.sender.encode_hex()) + .unwrap() + .state(StateTag::Completed) + .execute() .await .unwrap(); assert_eq!(logs, vec![status.clone()]); @@ -566,7 +753,10 @@ mod test { History::update_request_status(&history.pool, failed_status).await; let logs = history - .get_requests_by_tx_hash(reveal_tx_hash) + .query() + .search(reveal_tx_hash.encode_hex()) + .unwrap() + .execute() .await .unwrap(); assert_eq!(logs, vec![status.clone()]); @@ -583,7 +773,10 @@ mod test { }; History::update_request_status(&history.pool, status.clone()).await; let logs = history - .get_requests_by_tx_hash(status.request_tx_hash) + .query() + .search(status.request_tx_hash.encode_hex()) + .unwrap() + .execute() .await .unwrap(); assert_eq!(logs, vec![status.clone()]); @@ -617,31 +810,56 @@ mod test { History::update_request_status(&history.pool, status.clone()).await; let logs = history - .get_requests_by_sequence(status.sequence, Some(123)) + .query() + .search(status.sequence.to_string()) + .unwrap() + .network_id(123) + .execute() + .await + .unwrap(); + assert_eq!(logs, vec![]); + + let logs = history + .query() + .search((status.sequence + 1).to_string()) + .unwrap() + .execute() .await .unwrap(); assert_eq!(logs, vec![]); let logs = history - .get_requests_by_sequence(status.sequence + 1, None) + .query() + .search(TxHash::zero().encode_hex()) + .unwrap() + .execute() .await .unwrap(); assert_eq!(logs, vec![]); let logs = history - .get_requests_by_tx_hash(TxHash::zero()) + .query() + .search(Address::zero().encode_hex()) + .unwrap() + .network_id(status.network_id) + .execute() .await .unwrap(); assert_eq!(logs, vec![]); let logs = history - .get_requests_by_sender(Address::zero(), Some(status.network_id)) + .query() + .search(Address::zero().encode_hex()) + .unwrap() + .execute() .await .unwrap(); assert_eq!(logs, vec![]); let logs = history - .get_requests_by_sender(Address::zero(), None) + .query() + .state(StateTag::Completed) + .execute() .await .unwrap(); assert_eq!(logs, vec![]); @@ -654,49 +872,41 @@ mod test { History::update_request_status(&history.pool, status.clone()).await; for network_id in [None, Some(121)] { // min = created_at = max - let logs = history - .get_requests_by_time( - network_id, - 10, - 0, - Some(status.created_at), - Some(status.created_at), - ) + let mut query = history.query().limit(10).unwrap(); + + if let Some(network_id) = network_id { + query = query.network_id(network_id); + } + + let logs = query + .clone() + .min_timestamp(status.created_at) + .max_timestamp(status.created_at) + .execute() .await .unwrap(); assert_eq!(logs, vec![status.clone()]); // min = created_at + 1 - let logs = history - .get_requests_by_time( - network_id, - 10, - 0, - Some(status.created_at + Duration::seconds(1)), - None, - ) + let logs = query + .clone() + .min_timestamp(status.created_at + Duration::seconds(1)) + .execute() .await .unwrap(); assert_eq!(logs, vec![]); // max = created_at - 1 - let logs = history - .get_requests_by_time( - network_id, - 10, - 0, - None, - Some(status.created_at - Duration::seconds(1)), - ) + let logs = query + .clone() + .max_timestamp(status.created_at - Duration::seconds(1)) + .execute() .await .unwrap(); assert_eq!(logs, vec![]); // no min or max - let logs = history - .get_requests_by_time(network_id, 10, 0, None, None) - .await - .unwrap(); + let logs = query.execute().await.unwrap(); assert_eq!(logs, vec![status.clone()]); } } @@ -709,7 +919,11 @@ mod test { // wait for the writer thread to write to the db sleep(std::time::Duration::from_secs(1)).await; let logs = history - .get_requests_by_sequence(1, Some(121)) + .query() + .search(1.to_string()) + .unwrap() + .network_id(121) + .execute() .await .unwrap(); assert_eq!(logs, vec![status]); diff --git a/flake.nix b/flake.nix index 5bea18b610..ee38c3c970 100644 --- a/flake.nix +++ b/flake.nix @@ -48,7 +48,6 @@ in { devShells.default = pkgs.mkShell { buildInputs = [ - pkgs.cargo pkgs.cli pkgs.git pkgs.libusb1