iota_faucet/faucet/
mod.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5mod 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    /// Send `Coin<IOTA>` of the specified amount to the recipient
65    async fn send(
66        &self,
67        id: Uuid,
68        recipient: IotaAddress,
69        amounts: &[u64],
70    ) -> Result<FaucetReceipt, FaucetError>;
71
72    /// Send `Coin<IOTA>` of the specified amount to the recipient in a batch
73    /// request
74    async fn batch_send(
75        &self,
76        id: Uuid,
77        recipient: IotaAddress,
78        amounts: &[u64],
79    ) -> Result<BatchFaucetReceipt, FaucetError>;
80
81    /// Get the status of a batch_send request
82    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}