Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions apps/fortuna/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
*private-key*
.envrc
fortuna.db*
.env*

This file was deleted.

This file was deleted.

This file was deleted.

12 changes: 10 additions & 2 deletions apps/fortuna/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fortuna"
version = "8.1.0"
version = "8.2.0"
edition = "2021"

[lib]
Expand Down Expand Up @@ -46,8 +46,16 @@ chrono = { version = "0.4.38", features = [
backoff = { version = "0.4.0", features = ["futures", "tokio"] }
thiserror = "1.0.61"
futures-locks = "0.7.1"
sqlx = { version = "0.8", features = ["runtime-tokio", "sqlite", "chrono"] }
sqlx = { version = "0.8", features = [
"runtime-tokio",
"tls-rustls",
"sqlite",
"any",
"postgres",
"chrono",
] }
num-traits = "0.2.19"
dotenv = "0.15.0"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems abandoned (from sqlx docs), can you use dotenvy?


[dev-dependencies]
axum-test = "13.1.1"
35 changes: 19 additions & 16 deletions apps/fortuna/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,38 @@ Each blockchain is configured in `config.yaml`.

## Build & Test

We use sqlx query macros to check the SQL queries at compile time. This requires
a database to be available at build time. Create a `.env` file in the root of the project with the following content:
Fortuna uses Cargo for building and dependency management.
Simply run `cargo build` and `cargo test` to build and test the project.
To run Fortuna locally, see the [Local Development](#local-development) section below.

### Connect a database
Fortuna stores request history in a SQL database and serves it from its explorer API.
Any SQLite or Postgres database is supported. The database connection is sourced from the `DATABASE_URL` env var.
Create a `.env` file in the root of the project with a DB connection string.
```
DATABASE_URL="sqlite:fortuna.db?mode=rwc"
```
If not provided, Fortuna will create and use a SQLite file-based database at `./fortuna.db`, as in the example above.

### Database migrations
Fortuna will automatically apply the schema migrations in the `./migrations` directory when connecting to the database.
To manually administer the migrations, use the `sqlx` tool for cargo. The tool automatically uses the
database connection in the `.env` file.

Install sqlx for cargo with:
Install `sqlx`:
```bash
cargo install sqlx
```

Next, you need to create the database and apply the schema migrations. You can do this by running:

To create the database if needed and apply the migrations:
```bash
cargo sqlx migrate run # automatically picks up the .env file
cargo sqlx migrate run
```
This will create a SQLite database file called `fortuna.db` in the root of the project and apply the schema migrations to it.
This will allow `cargo check` to check the queries against the existing database.

Fortuna uses Cargo for building and dependency management.
Simply run `cargo build` and `cargo test` to build and test the project.

If you have changed any queries in the code, you need to update the .sqlx folder with the new queries:

To restore the database to a fresh state (drop, recreate, apply migrations):
```bash
cargo sqlx prepare
cargo sqlx database reset
```
Please add the changed files in the `.sqlx` folder to your git commit.

## Command-Line Interface

Expand Down Expand Up @@ -124,7 +127,7 @@ To start an instance of the webserver for local testing, you first need to perfo
1. Run `cargo run -- setup-provider` to register a randomness provider for this service. This command
will update the on-chain contracts such that the configured provider key is a randomness provider,
and its on-chain configuration matches `config.yaml`.

1. Review the [Connect a database](#connect-a-database) section above. The default configuration will create a file-based DB.
Once you've completed the setup, simply run the following command to start the service:

```bash
Expand Down
1 change: 0 additions & 1 deletion apps/fortuna/migrations/20250502164500_init.down.sql

This file was deleted.

26 changes: 0 additions & 26 deletions apps/fortuna/migrations/20250502164500_init.up.sql

This file was deleted.

4 changes: 0 additions & 4 deletions apps/fortuna/migrations/20250521203448_gas.down.sql

This file was deleted.

5 changes: 0 additions & 5 deletions apps/fortuna/migrations/20250521203448_gas.up.sql

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

1 change: 1 addition & 0 deletions apps/fortuna/migrations/20250707000000_init.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS request;
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
-- 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 TABLE request(
chain_id VARCHAR(20) NOT NULL,
network_id INTEGER NOT NULL,
provider VARCHAR(40) NOT NULL,
sequence INTEGER NOT NULL,
created_at INTEGER NOT NULL,
last_updated_at INTEGER NOT NULL,
state VARCHAR(10) NOT NULL,
request_block_number INTEGER NOT NULL,
request_tx_hash VARCHAR(64) NOT NULL,
user_random_number VARCHAR(64) NOT NULL,
sender VARCHAR(40) NOT NULL,
reveal_block_number INTEGER,
reveal_tx_hash VARCHAR(64),
provider_random_number VARCHAR(64),
info TEXT,
gas_used VARCHAR(100),
gas_limit VARCHAR(100) NOT NULL,
PRIMARY KEY (network_id, sequence, provider, request_tx_hash)
);

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);
Expand All @@ -20,3 +31,6 @@ CREATE INDEX request__sequence__state__created_at ON request(sequence, state, cr
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);

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;
10 changes: 10 additions & 0 deletions apps/fortuna/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ pub enum StateTag {
Failed,
}

impl std::fmt::Display for StateTag {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
StateTag::Pending => write!(f, "Pending"),
StateTag::Completed => write!(f, "Completed"),
StateTag::Failed => write!(f, "Failed"),
}
}
}

#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]
pub struct RequestLabel {
pub value: String,
Expand Down
2 changes: 1 addition & 1 deletion apps/fortuna/src/api/explorer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub struct ExplorerQueryParams {
#[derive(Debug, serde::Serialize, utoipa::ToSchema)]
pub struct ExplorerResponse {
pub requests: Vec<RequestStatus>,
pub total_results: u64,
pub total_results: i64,
}

/// Returns the logs of all requests captured by the keeper.
Expand Down
2 changes: 2 additions & 0 deletions apps/fortuna/src/command/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ pub async fn run_api(
}

pub async fn run(opts: &RunOptions) -> Result<()> {
// Load environment variables from a .env file if present
let _ = dotenv::dotenv()?;
let config = Config::load(&opts.config.config)?;
let secret = config.provider.secret.load()?.ok_or(anyhow!(
"Please specify a provider secret in the config file."
Expand Down
Loading
Loading