1mod simple_faucet;
6mod write_ahead_log;
7
8use std::{net::Ipv4Addr, path::PathBuf, sync::Arc};
9
10use async_trait::async_trait;
11use clap::Parser;
12use iota_types::base_types::{IotaAddress, ObjectID, TransactionDigest};
13use serde::{Deserialize, Serialize};
14use uuid::Uuid;
15
16pub use self::simple_faucet::SimpleFaucet;
17use crate::FaucetError;
18
19#[derive(Serialize, Deserialize, Debug, Clone)]
20pub struct FaucetReceipt {
21 pub sent: Vec<CoinInfo>,
22}
23
24#[derive(Serialize, Deserialize, Debug, Clone)]
25pub struct BatchFaucetReceipt {
26 pub task: String,
27}
28
29#[derive(Serialize, Deserialize, Debug, Clone)]
30#[serde(rename_all = "camelCase")]
31pub struct CoinInfo {
32 pub amount: u64,
33 pub id: ObjectID,
34 pub transfer_tx_digest: TransactionDigest,
35}
36
37#[derive(Serialize, Deserialize, Debug, Clone)]
38pub struct BatchSendStatus {
39 pub status: BatchSendStatusType,
40 pub transferred_gas_objects: Option<FaucetReceipt>,
41}
42
43#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
44#[serde(rename_all = "UPPERCASE")]
45pub enum BatchSendStatusType {
46 INPROGRESS,
47 SUCCEEDED,
48 DISCARDED,
49}
50
51pub struct AppState<F = Arc<SimpleFaucet>> {
52 pub faucet: F,
53 pub config: FaucetConfig,
54}
55
56impl<F> AppState<F> {
57 pub fn new(faucet: F, config: FaucetConfig) -> Self {
58 Self { faucet, config }
59 }
60}
61
62#[async_trait]
63pub trait Faucet {
64 async fn send(
66 &self,
67 id: Uuid,
68 recipient: IotaAddress,
69 amounts: &[u64],
70 ) -> Result<FaucetReceipt, FaucetError>;
71
72 async fn batch_send(
75 &self,
76 id: Uuid,
77 recipient: IotaAddress,
78 amounts: &[u64],
79 ) -> Result<BatchFaucetReceipt, FaucetError>;
80
81 async fn get_batch_send_status(&self, task_id: Uuid) -> Result<BatchSendStatus, FaucetError>;
83}
84
85pub const DEFAULT_AMOUNT: u64 = 1_000_000_000;
86pub const DEFAULT_NUM_OF_COINS: usize = 1;
87
88#[derive(Parser, Clone)]
89#[command(
90 name = "IOTA Faucet",
91 about = "Faucet for requesting test tokens on IOTA"
92)]
93pub struct FaucetConfig {
94 #[arg(long, default_value_t = 5003)]
95 pub port: u16,
96
97 #[arg(long, default_value = "127.0.0.1")]
98 pub host_ip: Ipv4Addr,
99
100 #[arg(long, default_value_t = DEFAULT_AMOUNT)]
101 pub amount: u64,
102
103 #[arg(long, default_value_t = DEFAULT_NUM_OF_COINS)]
104 pub num_coins: usize,
105
106 #[arg(long, default_value_t = 10)]
107 pub request_buffer_size: usize,
108
109 #[arg(long, default_value_t = 10)]
110 pub max_request_per_second: u64,
111
112 #[arg(long, default_value_t = 60)]
113 pub wallet_client_timeout_secs: u64,
114
115 #[arg(long)]
116 pub write_ahead_log: PathBuf,
117
118 #[arg(long, default_value_t = 300)]
119 pub wal_retry_interval: u64,
120
121 #[arg(long, default_value_t = 10000)]
122 pub max_request_queue_length: u64,
123
124 #[arg(long, default_value_t = 500)]
125 pub batch_request_size: u64,
126
127 #[arg(long, default_value_t = 300)]
128 pub ttl_expiration: u64,
129
130 #[arg(long, action = clap::ArgAction::Set, default_value_t = false)]
131 pub batch_enabled: bool,
132}
133
134impl Default for FaucetConfig {
135 fn default() -> Self {
136 Self {
137 port: 5003,
138 host_ip: Ipv4Addr::new(127, 0, 0, 1),
139 amount: DEFAULT_AMOUNT,
140 num_coins: DEFAULT_NUM_OF_COINS,
141 request_buffer_size: 10,
142 max_request_per_second: 10,
143 wallet_client_timeout_secs: 60,
144 write_ahead_log: Default::default(),
145 wal_retry_interval: 300,
146 max_request_queue_length: 10000,
147 batch_request_size: 500,
148 ttl_expiration: 300,
149 batch_enabled: false,
150 }
151 }
152}