Skip to content

Commit

Permalink
Fixing cargo.lock conflicts + merging next
Browse files Browse the repository at this point in the history
  • Loading branch information
phklive committed Mar 29, 2024
2 parents 8113178 + d8edb09 commit fdd5f0b
Show file tree
Hide file tree
Showing 15 changed files with 1,496 additions and 30 deletions.
843 changes: 813 additions & 30 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ members = [
"store",
"utils",
"test-macro",
"faucet"
]

resolver = "2"
Expand Down
27 changes: 27 additions & 0 deletions faucet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[package]
name = "miden-node-faucet"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
# Makes `make-genesis` subcommand run faster. Is only suitable for testing.
testing = ["miden-client/testing"]

[dependencies]
actix-web = "4"
actix-files = "0.6.5"
actix-cors = "0.7.0"
derive_more = "0.99.17"
figment = { version = "0.10", features = ["toml", "env"] }
miden-lib = { workspace = true }
miden-client = { version = "0.1.0", features = ["concurrent"] }
miden-node-proto = { path = "../proto", version = "0.2" }
miden-node-utils = { path = "../utils", version = "0.2" }
miden-objects = { workspace = true }
serde = { version = "1.0", features = ["derive"] }
clap = { version = "4.5.1", features = ["derive"] }
async-mutex = "1.4.0"
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
3 changes: 3 additions & 0 deletions faucet/miden-faucet.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
endpoint = { protocol = "http", host = "localhost", port = 8080 }
rpc_url = "http://localhost:57291"
database_filepath = "miden-faucet.sqlite3"
54 changes: 54 additions & 0 deletions faucet/src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use std::path::PathBuf;

use clap::{Parser, Subcommand};

use crate::config;

#[derive(Parser, Debug)]
#[clap(name = "Miden Faucet")]
#[clap(about = "A command line tool for the Miden faucet", long_about = None)]
pub struct Cli {
#[clap(subcommand)]
pub command: Commands,
}

#[derive(Subcommand, Debug)]
pub enum Commands {
/// Initialise a new Miden faucet from arguments
Init(InitArgs),

/// Imports an existing Miden faucet from specified file
Import(ImportArgs),
}

#[derive(Parser, Debug)]
pub struct InitArgs {
#[clap(short, long)]
pub token_symbol: String,

#[clap(short, long)]
pub decimals: u8,

#[clap(short, long)]
pub max_supply: u64,

/// Amount of assets to be dispersed by the faucet on each request
#[clap(short, long)]
pub asset_amount: u64,

#[clap(short, long, value_name = "FILE", default_value = config::CONFIG_FILENAME)]
pub config: PathBuf,
}

#[derive(Parser, Debug)]
pub struct ImportArgs {
#[clap(short, long)]
pub faucet_path: PathBuf,

/// Amount of assets to be dispersed by the faucet on each request
#[clap(short, long)]
pub asset_amount: u64,

#[clap(short, long, value_name = "FILE", default_value = config::CONFIG_FILENAME)]
pub config: PathBuf,
}
37 changes: 37 additions & 0 deletions faucet/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::fmt::{Display, Formatter};

use miden_node_utils::config::Endpoint;
use serde::{Deserialize, Serialize};

pub const CONFIG_FILENAME: &str = "miden-faucet.toml";

// Faucet config
// ================================================================================================

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)]
pub struct FaucetConfig {
/// Endpoint of the faucet
pub endpoint: Endpoint,
/// rpc gRPC endpoint in the format `http://<host>[:<port>]`.
pub rpc_url: String,
/// Location to store database files
pub database_filepath: String,
}

impl FaucetConfig {
pub fn as_url(&self) -> String {
self.endpoint.to_string()
}
}

impl Display for FaucetConfig {
fn fmt(
&self,
f: &mut Formatter<'_>,
) -> std::fmt::Result {
f.write_fmt(format_args!(
"{{ endpoint: \"{}\", store_url: \"{}\", block_producer_url: \"{}\" }}",
self.endpoint, self.database_filepath, self.rpc_url
))
}
}
32 changes: 32 additions & 0 deletions faucet/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use actix_web::{
error,
http::{header::ContentType, StatusCode},
HttpResponse,
};
use derive_more::Display;

#[derive(Debug, Display)]
pub enum FaucetError {
BadRequest(String),
InternalServerError(String),
}

impl error::ResponseError for FaucetError {
fn error_response(&self) -> HttpResponse<actix_web::body::BoxBody> {
let message = match self {
FaucetError::BadRequest(msg) => msg,
FaucetError::InternalServerError(msg) => msg,
};

HttpResponse::build(self.status_code())
.insert_header(ContentType::html())
.body(message.to_owned())
}

fn status_code(&self) -> actix_web::http::StatusCode {
match *self {
FaucetError::InternalServerError(_) => StatusCode::INTERNAL_SERVER_ERROR,
FaucetError::BadRequest(_) => StatusCode::BAD_REQUEST,
}
}
}
102 changes: 102 additions & 0 deletions faucet/src/handlers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use actix_web::{get, http::header, post, web, HttpResponse, Result};
use miden_client::client::transactions::TransactionTemplate;
use miden_objects::{
accounts::AccountId, assets::FungibleAsset, notes::NoteId, utils::serde::Serializable,
};
use serde::{Deserialize, Serialize};
use tracing::info;

use crate::{errors::FaucetError, FaucetState};

#[derive(Deserialize)]
struct FaucetRequest {
account_id: String,
}

#[derive(Serialize)]
struct FaucetMetadataReponse {
id: String,
asset_amount: u64,
}

#[get("/get_metadata")]
pub async fn get_metadata(state: web::Data<FaucetState>) -> HttpResponse {
let response = FaucetMetadataReponse {
id: state.id.to_string(),
asset_amount: state.asset_amount,
};

HttpResponse::Ok().json(response)
}

#[post("/get_tokens")]
pub async fn get_tokens(
req: web::Json<FaucetRequest>,
state: web::Data<FaucetState>,
) -> Result<HttpResponse> {
info!("Received a request with account_id: {}", req.account_id);

let client = state.client.clone();

// Receive and hex user account id
let target_account_id = AccountId::from_hex(req.account_id.as_str())
.map_err(|err| FaucetError::BadRequest(err.to_string()))?;

// Instantiate asset
let asset =
FungibleAsset::new(state.id, state.asset_amount).expect("Failed to instantiate asset.");

// Instantiate transaction template
let tx_template = TransactionTemplate::MintFungibleAsset {
asset,
target_account_id,
};

// Run transaction executor & execute transaction
let tx_result = client
.lock()
.await
.new_transaction(tx_template)
.map_err(|err| FaucetError::InternalServerError(err.to_string()))?;

// Get note id
let note_id: NoteId = tx_result
.created_notes()
.first()
.ok_or_else(|| {
FaucetError::InternalServerError("Failed to access generated note.".to_string())
})?
.id();

// Run transaction prover & send transaction to node
{
let mut client_guard = client.lock().await;
client_guard
.send_transaction(tx_result)
.await
.map_err(|err| FaucetError::InternalServerError(err.to_string()))?;
}

// Get note from client store
let input_note = state
.client
.clone()
.lock()
.await
.get_input_note(note_id)
.map_err(|err| FaucetError::InternalServerError(err.to_string()))?;

// Serialize note for transport
let bytes = input_note.to_bytes();

// Send generated note to user
Ok(HttpResponse::Ok()
.content_type("application/octet-stream")
.append_header(header::ContentDisposition {
disposition: actix_web::http::header::DispositionType::Attachment,
parameters: vec![actix_web::http::header::DispositionParam::Filename(
"note.mno".to_string(),
)],
})
.body(bytes))
}
Loading

0 comments on commit fdd5f0b

Please sign in to comment.