1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use std::path::PathBuf;

use crate::local_node::LocalNodeCliConfig;
use locutus_stdlib::prelude::Version;

#[derive(clap::Parser, Clone)]
#[clap(name = "Locutus Development Tool")]
#[clap(author = "The Freenet Project Inc.")]
#[clap(version = "0.0.3")]
pub struct Config {
    #[clap(subcommand)]
    pub sub_command: SubCommand,
    #[clap(flatten)]
    pub additional: BaseConfig,
}

#[derive(clap::ValueEnum, Clone, Copy, Debug)]
pub enum OperationMode {
    /// Run the node in local-only mode. Useful for development pourpouses.
    Local,
    /// Standard operation mode.
    Network,
}

#[derive(clap::Parser, Clone)]
pub struct BaseConfig {
    /// Overrides the default data directory where Locutus contract files are stored.
    pub(crate) contract_data_dir: Option<PathBuf>,
    /// Node operation mode.
    #[clap(value_enum, default_value_t=OperationMode::Local)]
    pub(crate) mode: OperationMode,
}

#[derive(clap::Subcommand, Clone)]
pub enum SubCommand {
    RunLocal(LocalNodeCliConfig),
    Build(BuildToolCliConfig),
    New(NewPackageCliConfig),
    Publish(PutConfig),
    Execute(RunCliConfig),
}

/// Node CLI
///
/// This tool allows the execution of commands against the local node
/// and is intended to be used for development and automated workflows.
#[derive(clap::Parser, Clone)]
pub struct RunCliConfig {
    /// Command to execute.
    #[clap(subcommand)]
    pub command: NodeCommand,
}

#[derive(clap::Subcommand, Clone)]
pub enum NodeCommand {
    Put(PutConfig),
    Update(UpdateConfig),
}

/// Updates a contract in the network.
#[derive(clap::Parser, Clone)]
pub struct UpdateConfig {
    /// Contract id of the contract being updated in Base58 format.
    pub(crate) key: String,
    /// A path to the update/delta being pushed to the contract.
    pub(crate) delta: PathBuf,
    /// Whether this contract will be updated in the network or is just a dry run
    /// to be executed in local mode only. By default puts are performed in local.
    pub(crate) release: bool,
}

/// Publishes a new contract to the network.
#[derive(clap::Parser, Clone)]
pub struct PutConfig {
    /// A path to the compiled WASM code file.
    #[clap(long)]
    pub(crate) code: PathBuf,
    /// A path to the file parameters for the contract. If not specified, the contract
    /// will be published with empty parameters.
    #[clap(long)]
    pub(crate) parameters: Option<PathBuf>,
    /// A path to the initial state for the contract being published.
    #[clap(long)]
    pub(crate) state: PathBuf,
    /// Whether this contract will be released into the network or is just a dry run
    /// to be executed in local mode only. By default puts are performed in local.
    #[clap(long)]
    pub(crate) release: bool,
    /// A path to a JSON file listing the related contracts.
    #[clap(long)]
    pub(crate) related_contracts: Option<PathBuf>,
}

/// Builds and packages a contract.
///
/// This tool will build the WASM contract and publish it to the network.
#[derive(clap::Parser, Clone)]
pub struct BuildToolCliConfig {
    /// Compile the contract with WASI extension enabled (useful for debugging).
    #[clap(long)]
    pub(crate) wasi: bool,

    /// Compile the contract with a specific version.
    #[clap(long, value_parser = parse_version, default_value_t=Version::new(0, 0, 1))]
    pub(crate) version: Version,
}

impl Default for BuildToolCliConfig {
    fn default() -> Self {
        Self {
            wasi: false,
            version: Version::new(0, 0, 1),
        }
    }
}

fn parse_version(src: &str) -> Result<Version, String> {
    Version::parse(src).map_err(|e| e.to_string())
}

/// Create a new Locutus contract and/or app.
#[derive(clap::Parser, Clone)]
pub struct NewPackageCliConfig {
    #[clap(id = "type", value_enum)]
    pub(crate) kind: ContractKind,
}

#[derive(clap::ValueEnum, Clone)]
pub(crate) enum ContractKind {
    /// A web app container contract.
    WebApp,
    /// An standard contract.
    Contract,
}