From 4c1f4a52f64487bd90d97f0d3fc9ce331d379613 Mon Sep 17 00:00:00 2001 From: Harry Solovay Date: Thu, 3 Oct 2024 10:28:18 -0400 Subject: [PATCH 01/10] begin --- CONTRIBUTING.md | 28 +++++ README.md | 112 +++++------------- .../fetch_genesis_block_identifier.rs | 7 +- 3 files changed, 57 insertions(+), 90 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c6e424b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,28 @@ +# Contributing + +## Testing + +Running the tests requires having Archive database available [see: +[Quick Start with Mainnet](#quick-start-with-mainnet)]. Once the setup is complete you can run tests +using: + +```bash +just test +``` + +### Managing PostgreSQL + +- **Stop PostgreSQL**: To stop the PostgreSQL instance: + + ```bash + just pg-down + ``` + +- **Restart PostgreSQL**: To restart without reinitializing the database (useful if the database is + already set up): + + ```bash + just pg-up + ``` + +> You only need to reinitialize the database if you want the latest data dump. diff --git a/README.md b/README.md index 9b59b58..e8664a1 100644 --- a/README.md +++ b/README.md @@ -1,110 +1,52 @@ # Mina Mesh -[![checks](https://github.com/MinaFoundation/MinaMesh/actions/workflows/checks.yaml/badge.svg)](https://github.com/MinaFoundation/MinaMesh/actions/workflows/checks.yaml) - -## Overview - Mina Mesh is an implementation of the [Coinbase Mesh specification](https://docs.cdp.coinbase.com/mesh/docs/welcome) for the [Mina blockchain](https://minaprotocol.com/). -## Building - -To build the project: - -```bash -cargo build -``` - -The binary will be available at: +> Note: Mina Mesh is WIP and should not yet be used in production. -```bash -target/debug/mina_mesh -``` - -## Running - -Mina Mesh requires access to a PostgreSQL Archive database and a Mina GraphQL endpoint. By default, -the configuration points to the mainnet, making it easy to get started. You can override the -configuration by either passing arguments or setting environment variables via a `.env` file (an -example is provided as `.env.example`). +## Installation -### Quick Start with Mainnet +```sh +# Install the mina-mesh executable +cargo install mina-mesh -1. **Set up the PostgreSQL Archive Database** - -Use the predefined `just` commands to set up and start the PostgreSQL database: - -```bash -just setup-archive-db +# Confirm installation successful +mina-mesh --help ``` -> Note: This process sets up the PostgreSQL docker using the latest mainnet archive database. - -2. **Run the Mina Mesh Server** +## Fetch Genesis Block Identifier -To start the server with default settings (mainnet configuration): +Before running the server, we must first write genesis block identifier information to our `.env` +file. -```bash -target/debug/mina_mesh serve +```sh +mina-mesh fetch-genesis-block-identifier >> .env ``` -The server will listen on `0.0.0.0:3000` by default. +> Note: this command utilizes a default GraphQL endpoint +> ("https://mainnet.minaprotocol.network/graphql"). You can override this default by specifying a +> `PROXY_URL` in your `.env` file. -### Playground Mode +## Instantiate the Server -You can enable a playground mode, which provides a simplified testing interface, by adding the -`--playground` flag: +Mina Mesh depends on a Postgres connection string for an archive database. -```bash -cargo run -- serve --playground -``` - -When enabled, you can access the playground at the root URL (`/`). - -### Configuration +Ensure that you also specify an archive `DATABASE_URL` in your `.env`. -Mina Mesh can be configured through command-line options or by using environment variables. For -convenience, you can use a `.env` file. To get started, copy the provided `.env.example`: - -```bash -cp .env.example .env +```sh +mina-mesh serve --playground ``` -Then modify the `.env` file to suit your environment. The available configurations include: - -- **Mina GraphQL Endpoint**: `MINA_PROXY_URL` (default: - `https://mainnet.minaprotocol.network/graphql`) -- **PostgreSQL Archive Database URL**: `MINA_ARCHIVE_DATABASE_URL` (default: - `postgres://mina:whatever@localhost:5432/archive`) -- **Genesis Block Identifier**: `MINA_GENESIS_BLOCK_IDENTIFIER_HEIGHT`, - `MINA_GENESIS_BLOCK_IDENTIFIER_STATE_HASH` - -> You can also pass these options as arguments to `mina_mesh serve` to override the defaults. +> Note: you may want to exclude the `--playground` flag in production. This will disable the +> playground, which renders when the server's root `/` route receives a GET request. -## Testing +Alternatively, you can supply the archive database URL via the command line. -Running the tests requires having Archive database available [see: -[Quick Start with Mainnet](#quick-start-with-mainnet)]. Once the setup is complete you can run tests -using: - -```bash -just test +```sh +mina-mesh serve --playground --database-url postgres://mina:whatever@localhost:5432/archive ``` -### Managing PostgreSQL - -- **Stop PostgreSQL**: To stop the PostgreSQL instance: - - ```bash - just pg-down - ``` - -- **Restart PostgreSQL**: To restart without reinitializing the database (useful if the database is - already set up): - - ```bash - just pg-up - ``` - -> You only need to reinitialize the database if you want the latest data dump. +Then visit [`http://0.0.0.0:3000`](http://0.0.0.0:3000) for an interactive playground with which you +can explore and test endpoints. diff --git a/src/commands/fetch_genesis_block_identifier.rs b/src/commands/fetch_genesis_block_identifier.rs index 11b1bf2..7eacce3 100644 --- a/src/commands/fetch_genesis_block_identifier.rs +++ b/src/commands/fetch_genesis_block_identifier.rs @@ -8,16 +8,13 @@ use crate::graphql::QueryGenesisBlockIdentifier; #[command(about = "Retrieve the genesis block identifier via a proxy node GraphQL endpoint.")] pub struct FetchGenesisBlockIdentifierCommand { #[arg(long, short = 'n', default_value = "https://mainnet.minaprotocol.network/graphql")] - proxy_node_graphql_endpoint: String, + proxy_url: String, } impl FetchGenesisBlockIdentifierCommand { pub async fn run(&self) -> Result<()> { let client = reqwest::Client::new(); - let result = client - .post(self.proxy_node_graphql_endpoint.to_owned()) - .run_graphql(QueryGenesisBlockIdentifier::build(())) - .await?; + let result = client.post(self.proxy_url.to_owned()).run_graphql(QueryGenesisBlockIdentifier::build(())).await?; if let Some(inner) = result.data { let genesis_block_hash = inner.genesis_block.state_hash.0; let genesis_block_index = inner.genesis_block.protocol_state.consensus_state.block_height.0; From 8b7189ccd44c26b992530c125787315604879a6e Mon Sep 17 00:00:00 2001 From: Harry Solovay Date: Thu, 3 Oct 2024 10:30:05 -0400 Subject: [PATCH 02/10] continue --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e8664a1..7d68af6 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ Mina Mesh is an implementation of the ## Installation +Ensure you have the Rust toolchain installed. If you do not, see +[installation instructions here](https://www.rust-lang.org/tools/install). + ```sh # Install the mina-mesh executable cargo install mina-mesh From 314c3e16ba0b67dbd212f267d576f105fdcfa7e9 Mon Sep 17 00:00:00 2001 From: Harry Solovay Date: Thu, 3 Oct 2024 10:40:07 -0400 Subject: [PATCH 03/10] more --- CODE_OF_CONDUCT.md | 117 +++++++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 100 ++++++++++++++++++++++++++++++++++---- README.md | 25 +++++++--- 3 files changed, 228 insertions(+), 14 deletions(-) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..872c154 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,117 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a +harassment-free experience for everyone, regardless of age, body size, visible or invisible +disability, ethnicity, sex characteristics, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or +sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and +healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the + experience +- Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without their + explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior +and will take appropriate and fair corrective action in response to any behavior that they deem +inappropriate, threatening, offensive, or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject comments, commits, +code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and +will communicate reasons for moderation decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when an individual is +officially representing the community in public spaces. Examples of representing our community +include using an official email address, posting via an official social media account, or acting as +an appointed representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community +leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and +investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter of any +incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining the consequences for +any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or +unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing clarity around the +nature of the violation and an explanation of why the behavior was inappropriate. A public apology +may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of actions. + +**Consequence**: A warning with consequences for continued behavior. No interaction with the people +involved, including unsolicited interaction with those enforcing the Code of Conduct, for a +specified period of time. This includes avoiding interactions in community spaces as well as +external channels like social media. Violating these terms may lead to a temporary or permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including sustained inappropriate +behavior. + +**Consequence**: A temporary ban from any sort of interaction or public communication with the +community for a specified period of time. No public or private interaction with the people involved, +including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this +period. Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community standards, including +sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement +of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c6e424b..d84cbfa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,16 +1,88 @@ # Contributing -## Testing +When contributing to this repository, please check our open issues and whether there is already an +issue related to your idea. Please first discuss the change you wish to make in a GitHub issue and +wait for a reply from the maintainers of this repository before making a change. -Running the tests requires having Archive database available [see: -[Quick Start with Mainnet](#quick-start-with-mainnet)]. Once the setup is complete you can run tests -using: +We have a [code of conduct](CODE_OF_CONDUCT.md); please follow it in all your interactions relating +to the project. -```bash -just test -``` +## Environment setup + +To develop on your machine, install the following (and please submit issues if errors crop up) + +- [Rust](https://www.rust-lang.org/tools/install) +- [Docker](https://docs.docker.com/get-docker/) +- [dprint](https://dprint.dev/) +- [Just](https://github.com/casey/just) +- [sql-formatter](https://github.com/sql-formatter-org/sql-formatter) +- [insta](https://insta.rs/) + +## Pull requests + +**For a pull request to be merged it must at least:** + +:white_check_mark:   Pass CI + +:white_check_mark:   Have one approving review + +:white_check_mark:   Have the PR title follow +[conventional commit](https://www.conventionalcommits.org/) + +**Ideally, a good pull request should:** + +:clock3:   Take less than 15 minutes to review + +:open_book:   Have a meaningful description (describes the problem being solved) + +:one:   Introduce one feature or solve one bug at a time, for which an open issue already +exists. In case of a project wide refactoring, a larger PR is to be expected, but the reviewer +should be more carefully guided through it + +:jigsaw:   Issues that seem too big for a PR that can be reviewed in 15 minutes or PRs that +need to touch other issues should be discussed and probably split differently before starting any +development + +:dart:   Handle renaming, moving files, linting and formatting separately (not alongside +features or bug fixes) + +:test_tube:   Add tests for new functionality + +**Draft pull requests for early feedback are welcome and do not need to adhere to any guidelines.** + +When reviewing a pull request, the end-goal is to suggest useful changes to the author. Reviews +should finish with approval unless there are issues that would result in: + +:x:   Buggy behavior + +:x:   Undue maintenance burden -### Managing PostgreSQL +:x:   Measurable performance issues + +:x:   Feature reduction (i.e. it removes some aspect of functionality that a significant +minority of users rely on) + +:x:   Uselessness (i.e. it does not strictly add a feature or fix a known issue) + +:x:   Disabling a compiler feature to introduce code that wouldn't compile + +## Releases + +Declaring formal releases remains the prerogative of the project maintainer(s). + +## License + +By contributing to project, you agree that your contributions will be licensed under its +[Apache license](LICENSE). + +## Changes to this arrangement + +This is an experiment and feedback is welcome! This document may also be subject to pull-requests or +changes by contributors where you believe you have something valuable to add or change. + +## Testing + +### Ensure Test DB Accessible - **Stop PostgreSQL**: To stop the PostgreSQL instance: @@ -26,3 +98,15 @@ just test ``` > You only need to reinitialize the database if you want the latest data dump. + +### Run Tests + +```bash +cargo test +``` + +### Update Snapshots + +``` +cargo insta review +``` diff --git a/README.md b/README.md index 7d68af6..17bea7c 100644 --- a/README.md +++ b/README.md @@ -15,22 +15,22 @@ Ensure you have the Rust toolchain installed. If you do not, see # Install the mina-mesh executable cargo install mina-mesh -# Confirm installation successful +# Confirm the installation was successful mina-mesh --help ``` ## Fetch Genesis Block Identifier -Before running the server, we must first write genesis block identifier information to our `.env` -file. +The server depends on two environment variables (the genesis block identifier hash and index). We +can retrieve these using the `fetch-genesis-block-identifier` command. ```sh mina-mesh fetch-genesis-block-identifier >> .env ``` -> Note: this command utilizes a default GraphQL endpoint -> ("https://mainnet.minaprotocol.network/graphql"). You can override this default by specifying a -> `PROXY_URL` in your `.env` file. +> Note: all commands utilize a default GraphQL endpoint +> ("https://mainnet.minaprotocol.network/graphql"). You can override this default by specifying the +> `PROXY_URL`. ## Instantiate the Server @@ -53,3 +53,16 @@ mina-mesh serve --playground --database-url postgres://mina:whatever@localhost:5 Then visit [`http://0.0.0.0:3000`](http://0.0.0.0:3000) for an interactive playground with which you can explore and test endpoints. + +## Code of Conduct + +Everyone interacting in this repo is expected to follow the [code of conduct](CODE_OF_CONDUCT.md). + +## Contributing + +Contributions are welcome and appreciated! Check out the [contributing guide](CONTRIBUTING.md) +before you dive in. + +## License + +Mina Mesh is [Apache licensed](LICENSE). From 2994eb9d4cbb4cfd1589f6717e9be03b142f9c81 Mon Sep 17 00:00:00 2001 From: Harry Solovay Date: Thu, 3 Oct 2024 10:45:05 -0400 Subject: [PATCH 04/10] continued --- README.md | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 17bea7c..06a6d6d 100644 --- a/README.md +++ b/README.md @@ -19,25 +19,30 @@ cargo install mina-mesh mina-mesh --help ``` -## Fetch Genesis Block Identifier +## Environment -The server depends on two environment variables (the genesis block identifier hash and index). We -can retrieve these using the `fetch-genesis-block-identifier` command. +The server depends on several environment variables. + +### Mina Proxy (GraphQL) URL + +All commands utilize a default GraphQL endpoint `https://mainnet.minaprotocol.network/graphql`. This +can be overridden via `PROXY_URL`. + +### Archive DB Connection String + +Mina Mesh depends on a Postgres connection string for an archive database. This is specified as +`DATABASE_URL`. + +### Genesis Block Identifier Hash and Index + +We can retrieve these using the `fetch-genesis-block-identifier` command. ```sh mina-mesh fetch-genesis-block-identifier >> .env ``` -> Note: all commands utilize a default GraphQL endpoint -> ("https://mainnet.minaprotocol.network/graphql"). You can override this default by specifying the -> `PROXY_URL`. - ## Instantiate the Server -Mina Mesh depends on a Postgres connection string for an archive database. - -Ensure that you also specify an archive `DATABASE_URL` in your `.env`. - ```sh mina-mesh serve --playground ``` @@ -45,12 +50,6 @@ mina-mesh serve --playground > Note: you may want to exclude the `--playground` flag in production. This will disable the > playground, which renders when the server's root `/` route receives a GET request. -Alternatively, you can supply the archive database URL via the command line. - -```sh -mina-mesh serve --playground --database-url postgres://mina:whatever@localhost:5432/archive -``` - Then visit [`http://0.0.0.0:3000`](http://0.0.0.0:3000) for an interactive playground with which you can explore and test endpoints. From 7651dcc3dba141b8df8cbe87507fc1709e6fd5ac Mon Sep 17 00:00:00 2001 From: Harry Solovay Date: Thu, 3 Oct 2024 10:49:33 -0400 Subject: [PATCH 05/10] continued --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 06a6d6d..44f0b54 100644 --- a/README.md +++ b/README.md @@ -23,18 +23,21 @@ mina-mesh --help The server depends on several environment variables. -### Mina Proxy (GraphQL) URL +### `MINAMESH_PROXY_URL`: Mina Proxy (GraphQL) URL -All commands utilize a default GraphQL endpoint `https://mainnet.minaprotocol.network/graphql`. This -can be overridden via `PROXY_URL`. +All commands utilize a Mina proxy (GraphQL) endpoint. The default is +`https://mainnet.minaprotocol.network/graphql`. -### Archive DB Connection String +### `MINAMESH_DATABASE_URL`: Mina Archive Connection String -Mina Mesh depends on a Postgres connection string for an archive database. This is specified as -`DATABASE_URL`. +Mina Mesh depends on a connection (and therefore connection string) to a Mina archive database. ### Genesis Block Identifier Hash and Index +#### `MINAMESH_GENESIS_BLOCK_IDENTIFIER_HEIGHT` + +### `MINAMESH_GENESIS_BLOCK_IDENTIFIER_STATE_HASH` + We can retrieve these using the `fetch-genesis-block-identifier` command. ```sh From b166394a213c17577a89557057daebaa51eaf714 Mon Sep 17 00:00:00 2001 From: Harry Solovay Date: Thu, 3 Oct 2024 10:51:38 -0400 Subject: [PATCH 06/10] continued --- README.md | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 44f0b54..0556d8a 100644 --- a/README.md +++ b/README.md @@ -23,26 +23,15 @@ mina-mesh --help The server depends on several environment variables. -### `MINAMESH_PROXY_URL`: Mina Proxy (GraphQL) URL - -All commands utilize a Mina proxy (GraphQL) endpoint. The default is -`https://mainnet.minaprotocol.network/graphql`. - -### `MINAMESH_DATABASE_URL`: Mina Archive Connection String - -Mina Mesh depends on a connection (and therefore connection string) to a Mina archive database. - -### Genesis Block Identifier Hash and Index - -#### `MINAMESH_GENESIS_BLOCK_IDENTIFIER_HEIGHT` - -### `MINAMESH_GENESIS_BLOCK_IDENTIFIER_STATE_HASH` - -We can retrieve these using the `fetch-genesis-block-identifier` command. - -```sh -mina-mesh fetch-genesis-block-identifier >> .env -``` +- `MINAMESH_PROXY_URL`: a Mina proxy (GraphQL) endpoint. The default is + `https://mainnet.minaprotocol.network/graphql`. +- `MINAMESH_DATABASE_URL`: a connection string referencing a Mina archive database. +- `MINAMESH_GENESIS_BLOCK_IDENTIFIER_HEIGHT` and `MINAMESH_GENESIS_BLOCK_IDENTIFIER_STATE_HASH`: we + can retrieve these using the `fetch-genesis-block-identifier` command. + + ```sh + mina-mesh fetch-genesis-block-identifier >> .env + ``` ## Instantiate the Server From 56ba99ec066eb850faeb3fa955669cfb4840460d Mon Sep 17 00:00:00 2001 From: Harry Solovay Date: Thu, 3 Oct 2024 10:53:58 -0400 Subject: [PATCH 07/10] continued --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0556d8a..aca1198 100644 --- a/README.md +++ b/README.md @@ -39,11 +39,11 @@ The server depends on several environment variables. mina-mesh serve --playground ``` -> Note: you may want to exclude the `--playground` flag in production. This will disable the -> playground, which renders when the server's root `/` route receives a GET request. +> Note: the presence of the `--playground` flag enables the serving of an OpenAPI playground in +> response to `GET /`. To disable this endpoint, omit the `--playground` flag. -Then visit [`http://0.0.0.0:3000`](http://0.0.0.0:3000) for an interactive playground with which you -can explore and test endpoints. +Visit [`http://0.0.0.0:3000`](http://0.0.0.0:3000) for an interactive playground with which you can +explore and test endpoints. ## Code of Conduct From 6ae99949e386f37c5e17bcb043a93978b3cec510 Mon Sep 17 00:00:00 2001 From: Harry Solovay Date: Thu, 3 Oct 2024 11:42:43 -0400 Subject: [PATCH 08/10] fix env var / args handling --- .env.example | 5 +- .github/workflows/checks.yaml | 1 + .vscode/launch.json | 17 ++----- README.md | 2 +- .../fetch_genesis_block_identifier.rs | 8 +-- src/config.rs | 50 +++++++------------ src/util.rs | 4 ++ tests/account_balance.rs | 2 +- tests/block.rs | 4 +- tests/network_list.rs | 2 +- 10 files changed, 40 insertions(+), 55 deletions(-) diff --git a/.env.example b/.env.example index 2335ae7..2097017 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,6 @@ -DATABASE_URL=postgres://mina:whatever@localhost:5432/archive +MINAMESH_ARCHIVE_DATABASE_URL=postgres://mina:whatever@localhost:5432/archive +MINAMESH_GENESIS_BLOCK_IDENTIFIER_STATE_HASH=3NK4BpDSekaqsG6tx8Nse2zJchRft2JpnbvMiog55WCr5xJZaKeP +MINAMESH_GENESIS_BLOCK_IDENTIFIER_HEIGHT=359605 + RUST_LOG=debug,error,mina_mesh=info RUST_ENV=production diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 731d913..4a5dc91 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -56,6 +56,7 @@ jobs: key: ${{ runner.os }}-test-${{ hashFiles('**/Cargo.lock') }} - name: Setup run: | + cp .env.example .env just get-mainnet-archive-db just pg just wait-for-pg diff --git a/.vscode/launch.json b/.vscode/launch.json index a1209aa..884d3ca 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,24 +4,17 @@ { "type": "lldb", "request": "launch", - "name": "Debug unit tests in library", + "name": "Debug Cargo tests", "cargo": { - "args": [ - "test", - "--no-run", - "--lib", - "--package=${workspaceFolderBasename}" - ], - "filter": { - "name": "${workspaceFolderBasename}", - "kind": "lib" - } + "args": ["test", "--no-run", "--lib"] }, "args": ["--nocapture"], "cwd": "${workspaceFolder}", "env": { "RUST_LOG": "debug" - } + }, + "envFile": "${workspaceFolder}/.env", + "console": "integratedTerminal" } ] } diff --git a/README.md b/README.md index aca1198..86f0dd6 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ The server depends on several environment variables. - `MINAMESH_PROXY_URL`: a Mina proxy (GraphQL) endpoint. The default is `https://mainnet.minaprotocol.network/graphql`. -- `MINAMESH_DATABASE_URL`: a connection string referencing a Mina archive database. +- `MINAMESH_ARCHIVE_DATABASE_URL`: a connection string referencing a Mina archive database. - `MINAMESH_GENESIS_BLOCK_IDENTIFIER_HEIGHT` and `MINAMESH_GENESIS_BLOCK_IDENTIFIER_STATE_HASH`: we can retrieve these using the `fetch-genesis-block-identifier` command. diff --git a/src/commands/fetch_genesis_block_identifier.rs b/src/commands/fetch_genesis_block_identifier.rs index 7eacce3..f2e13d0 100644 --- a/src/commands/fetch_genesis_block_identifier.rs +++ b/src/commands/fetch_genesis_block_identifier.rs @@ -2,12 +2,12 @@ use anyhow::{bail, Result}; use clap::Args; use cynic::{http::ReqwestExt, QueryBuilder}; -use crate::graphql::QueryGenesisBlockIdentifier; +use crate::{graphql::QueryGenesisBlockIdentifier, util::default_mina_proxy_url}; #[derive(Debug, Args)] #[command(about = "Retrieve the genesis block identifier via a proxy node GraphQL endpoint.")] pub struct FetchGenesisBlockIdentifierCommand { - #[arg(long, short = 'n', default_value = "https://mainnet.minaprotocol.network/graphql")] + #[arg(long, env = "MINAMESH_PROXY_URL", default_value_t = default_mina_proxy_url())] proxy_url: String, } @@ -18,8 +18,8 @@ impl FetchGenesisBlockIdentifierCommand { if let Some(inner) = result.data { let genesis_block_hash = inner.genesis_block.state_hash.0; let genesis_block_index = inner.genesis_block.protocol_state.consensus_state.block_height.0; - println!("MINAMESH_GENESIS_BLOCK_HASH = {}", genesis_block_hash); - println!("MINAMESH_GENESIS_BLOCK_INDEX = {}", genesis_block_index); + println!("MINAMESH_GENESIS_BLOCK_IDENTIFIER_STATE_HASH = {genesis_block_hash}"); + println!("MINAMESH_GENESIS_BLOCK_IDENTIFIER_HEIGHT = {genesis_block_index}"); } else { bail!("No genesis block identifier found in the response"); } diff --git a/src/config.rs b/src/config.rs index 2a7de9e..0aac911 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,23 +1,34 @@ use anyhow::Result; -use clap::Args; +use clap::{Args, Parser}; use mesh::models::BlockIdentifier; use sqlx::PgPool; -use crate::{graphql::GraphQLClient, MinaMesh}; +use crate::{graphql::GraphQLClient, util::default_mina_proxy_url, MinaMesh}; #[derive(Debug, Args)] pub struct MinaMeshConfig { - #[arg(long, env = "MINA_PROXY_URL", default_value_t = mina_proxy_url())] + #[arg(long, env = "MINAMESH_PROXY_URL", default_value_t = default_mina_proxy_url())] pub proxy_url: String, - #[arg(long, env = "MINA_ARCHIVE_DATABASE_URL", default_value_t = database_url())] + #[arg(long, env = "MINAMESH_ARCHIVE_DATABASE_URL")] pub archive_database_url: String, - #[arg(long, env = "MINA_GENESIS_BLOCK_IDENTIFIER_HEIGHT", default_value_t = genesis_block_identifier_height())] + #[arg(long, env = "MINAMESH_GENESIS_BLOCK_IDENTIFIER_HEIGHT")] pub genesis_block_identifier_height: i64, - #[arg(long, env = "MINA_GENESIS_BLOCK_IDENTIFIER_STATE_HASH", default_value_t = genesis_block_identifier_state_hash())] + #[arg(long, env = "MINAMESH_GENESIS_BLOCK_IDENTIFIER_STATE_HASH")] pub genesis_block_identifier_state_hash: String, } impl MinaMeshConfig { + pub fn from_env() -> Self { + dotenv::dotenv().ok(); + return MinaMeshConfigParser::parse().config; + + #[derive(Parser)] + struct MinaMeshConfigParser { + #[command(flatten)] + config: MinaMeshConfig, + } + } + pub async fn to_mina_mesh(self) -> Result { Ok(MinaMesh { graphql_client: GraphQLClient::new(self.proxy_url.to_owned()), @@ -29,30 +40,3 @@ impl MinaMeshConfig { }) } } - -impl Default for MinaMeshConfig { - fn default() -> Self { - Self { - proxy_url: mina_proxy_url(), - archive_database_url: database_url(), - genesis_block_identifier_height: genesis_block_identifier_height(), - genesis_block_identifier_state_hash: genesis_block_identifier_state_hash(), - } - } -} - -fn mina_proxy_url() -> String { - "https://mainnet.minaprotocol.network/graphql".to_string() -} - -fn database_url() -> String { - "postgres://mina:whatever@localhost:5432/archive".to_string() -} - -fn genesis_block_identifier_height() -> i64 { - 359605 -} - -fn genesis_block_identifier_state_hash() -> String { - "3NK4BpDSekaqsG6tx8Nse2zJchRft2JpnbvMiog55WCr5xJZaKeP".to_string() -} diff --git a/src/util.rs b/src/util.rs index 27a233b..3b001cd 100644 --- a/src/util.rs +++ b/src/util.rs @@ -47,3 +47,7 @@ impl ToString for Wrapper<&PartialBlockIdentifier> { } } } + +pub fn default_mina_proxy_url() -> String { + "https://mainnet.minaprotocol.network/graphql".to_string() +} diff --git a/tests/account_balance.rs b/tests/account_balance.rs index 687da1e..f475c23 100644 --- a/tests/account_balance.rs +++ b/tests/account_balance.rs @@ -8,7 +8,7 @@ use mina_mesh::{ #[tokio::test] async fn responses() -> Result<()> { - let mina_mesh = MinaMeshConfig::default().to_mina_mesh().await?; + let mina_mesh = MinaMeshConfig::from_env().to_mina_mesh().await?; let futures: Vec<_> = [ // cspell:disable "B62qmjJeM4Fd4FVghfhgwoE1fkEexK2Rre8WYKMnbxVwB5vtKUwvgMv", diff --git a/tests/block.rs b/tests/block.rs index c154a2e..67eac9f 100644 --- a/tests/block.rs +++ b/tests/block.rs @@ -6,7 +6,7 @@ use mina_mesh::{BlockMetadata, MinaMeshConfig, PartialBlockIdentifier}; #[tokio::test] async fn specified() -> Result<()> { - let mina_mesh = MinaMeshConfig::default().to_mina_mesh().await?; + let mina_mesh = MinaMeshConfig::from_env().to_mina_mesh().await?; let mut metadata_futures = specified_identifiers().iter().map(|item| mina_mesh.block_metadata(item)).collect::>(); let mut maybe_prev: Option> = None; @@ -38,7 +38,7 @@ fn specified_identifiers() -> &'static [PartialBlockIdentifier; 3] { #[tokio::test] async fn unspecified() -> Result<()> { - let mina_mesh = MinaMeshConfig::default().to_mina_mesh().await?; + let mina_mesh = MinaMeshConfig::from_env().to_mina_mesh().await?; let result = mina_mesh.block_metadata(&PartialBlockIdentifier { hash: None, index: None }).await; assert!(result.is_ok()); Ok(()) diff --git a/tests/network_list.rs b/tests/network_list.rs index 63d5712..324b87c 100644 --- a/tests/network_list.rs +++ b/tests/network_list.rs @@ -5,7 +5,7 @@ use mina_mesh::MinaMeshConfig; #[tokio::test] async fn mainnet_test() -> Result<()> { // Create a MinaMesh instance using the default configuration - let mina_mesh = MinaMeshConfig::default().to_mina_mesh().await?; + let mina_mesh = MinaMeshConfig::from_env().to_mina_mesh().await?; // Call the network_list function let result = mina_mesh.network_list().await?; From 4677ce14d76052d462801a5231ccc70c8205c9b3 Mon Sep 17 00:00:00 2001 From: Harry Solovay Date: Thu, 3 Oct 2024 11:44:25 -0400 Subject: [PATCH 09/10] add word --- words.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/words.txt b/words.txt index 87f4cf8..3f75934 100644 --- a/words.txt +++ b/words.txt @@ -1,3 +1,5 @@ +MINAMESH +RUSTFLAGS codegen coinbases darklight @@ -17,11 +19,11 @@ insta isready joaosreis johnmarcou +katyo keypair lookback microschemas mina -MINAMESH navroot nocapture openapi @@ -29,7 +31,6 @@ preprocess querygen reqwest retriable -RUSTFLAGS rustfmt schnorr secp From f86e4e48797f235b49b6fc0390c20b162baa43ee Mon Sep 17 00:00:00 2001 From: Harry Solovay Date: Thu, 3 Oct 2024 11:52:59 -0400 Subject: [PATCH 10/10] cleanup --- .vscode/launch.json | 20 ------------------- tests/block.rs | 9 ++++++--- tests/network_list.rs | 12 ++--------- .../snapshots/network_list__mainnet_test.snap | 14 +++++++------ 4 files changed, 16 insertions(+), 39 deletions(-) delete mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 884d3ca..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "type": "lldb", - "request": "launch", - "name": "Debug Cargo tests", - "cargo": { - "args": ["test", "--no-run", "--lib"] - }, - "args": ["--nocapture"], - "cwd": "${workspaceFolder}", - "env": { - "RUST_LOG": "debug" - }, - "envFile": "${workspaceFolder}/.env", - "console": "integratedTerminal" - } - ] -} diff --git a/tests/block.rs b/tests/block.rs index 67eac9f..2d309e4 100644 --- a/tests/block.rs +++ b/tests/block.rs @@ -38,8 +38,11 @@ fn specified_identifiers() -> &'static [PartialBlockIdentifier; 3] { #[tokio::test] async fn unspecified() -> Result<()> { - let mina_mesh = MinaMeshConfig::from_env().to_mina_mesh().await?; - let result = mina_mesh.block_metadata(&PartialBlockIdentifier { hash: None, index: None }).await; - assert!(result.is_ok()); + let response = MinaMeshConfig::from_env() + .to_mina_mesh() + .await? + .block_metadata(&PartialBlockIdentifier { hash: None, index: None }) + .await; + assert!(response.is_ok()); Ok(()) } diff --git a/tests/network_list.rs b/tests/network_list.rs index 324b87c..fac082d 100644 --- a/tests/network_list.rs +++ b/tests/network_list.rs @@ -4,15 +4,7 @@ use mina_mesh::MinaMeshConfig; #[tokio::test] async fn mainnet_test() -> Result<()> { - // Create a MinaMesh instance using the default configuration - let mina_mesh = MinaMeshConfig::from_env().to_mina_mesh().await?; - - // Call the network_list function - let result = mina_mesh.network_list().await?; - - assert!(!result.network_identifiers.is_empty()); - - let network_identifier = &result.network_identifiers[0]; - assert_debug_snapshot!(network_identifier); + let response = MinaMeshConfig::from_env().to_mina_mesh().await?.network_list().await?; + assert_debug_snapshot!(&response.network_identifiers); Ok(()) } diff --git a/tests/snapshots/network_list__mainnet_test.snap b/tests/snapshots/network_list__mainnet_test.snap index c73de61..2807195 100644 --- a/tests/snapshots/network_list__mainnet_test.snap +++ b/tests/snapshots/network_list__mainnet_test.snap @@ -1,9 +1,11 @@ --- source: tests/network_list.rs -expression: network_identifier +expression: "&response.network_identifiers" --- -NetworkIdentifier { - blockchain: "mina", - network: "mainnet", - sub_network_identifier: None, -} +[ + NetworkIdentifier { + blockchain: "mina", + network: "mainnet", + sub_network_identifier: None, + }, +]