-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixing cargo.lock conflicts + merging next
- Loading branch information
Showing
15 changed files
with
1,496 additions
and
30 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ members = [ | |
"store", | ||
"utils", | ||
"test-macro", | ||
"faucet" | ||
] | ||
|
||
resolver = "2" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | ||
} |
Oops, something went wrong.