main.rs 4.82 KB
Newer Older
1
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
2
// This file is part of ink!.
3
//
4
// ink! is free software: you can redistribute it and/or modify
5 6 7 8
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
9
// ink! is distributed in the hope that it will be useful,
10 11 12 13 14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
15
// along with ink!.  If not, see <http://www.gnu.org/licenses/>.
16 17 18 19 20 21 22

mod cmd;

use structopt::{
    clap::AppSettings,
    StructOpt,
};
Andrew Jones's avatar
Andrew Jones committed
23
use url::Url;
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

#[derive(Debug, StructOpt)]
#[structopt(bin_name = "cargo")]
pub(crate) enum Opts {
    #[structopt(
        name = "contract",
        raw(
            setting = "AppSettings::UnifiedHelpMessage",
            setting = "AppSettings::DeriveDisplayOrder",
            setting = "AppSettings::DontCollapseArgsInUsage"
        )
    )]
    /// Utilities to develop Wasm smart contracts.
    Contract(ContractArgs),
}

#[derive(Debug, StructOpt)]
pub(crate) struct ContractArgs {
    #[structopt(subcommand)]
    cmd: Command,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum AbstractionLayer {
    Core,
    Model,
    Lang,
}

53 54 55 56
use std::{
    path::PathBuf,
    result::Result as StdResult,
};
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

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) struct InvalidAbstractionLayer;

impl std::fmt::Display for InvalidAbstractionLayer {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "expected `core`, `model` or `lang`")
    }
}

impl std::str::FromStr for AbstractionLayer {
    type Err = InvalidAbstractionLayer;

    fn from_str(input: &str) -> StdResult<Self, Self::Err> {
        match input {
            "core" => Ok(AbstractionLayer::Core),
            "model" => Ok(AbstractionLayer::Model),
            "lang" => Ok(AbstractionLayer::Lang),
            _ => Err(InvalidAbstractionLayer),
        }
    }
}

#[derive(Debug, StructOpt)]
enum Command {
    /// Setup and create a new smart contract.
    #[structopt(name = "new")]
    New {
        /// The abstraction layer to use: `core`, `model` or `lang`
        #[structopt(short = "l", long = "layer", default_value = "lang")]
        layer: AbstractionLayer,
        /// The name of the newly created smart contract.
        name: String,
90 91 92
        /// The optional target directory for the contract project
        #[structopt(short, long, parse(from_os_str))]
        target_dir: Option<PathBuf>,
93 94 95 96
    },
    /// Builds the smart contract.
    #[structopt(name = "build")]
    Build {},
97 98 99
    /// Generate abi artifacts
    #[structopt(name = "generate-abi")]
    GenerateAbi {},
100 101 102 103 104 105
    /// Test the smart contract off-chain.
    #[structopt(name = "test")]
    Test {},
    /// Deploy the smart contract on-chain. (Also for testing purposes.)
    #[structopt(name = "deploy")]
    Deploy {
Andrew Jones's avatar
Andrew Jones committed
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
        /// Websockets url of a substrate node
        #[structopt(
            name = "url",
            long,
            parse(try_from_str),
            default_value = "ws://localhost:9944"
        )]
        url: Url,
        /// Secret key URI for the account deploying the contract.
        #[structopt(name = "suri", long, short)]
        suri: String,
        /// Password for the secret key
        #[structopt(name = "password", long, short)]
        password: Option<String>,
        #[structopt(name = "gas", long, default_value = "500000")]
        /// Maximum amount of gas to be used in this deployment
        gas: u64,
        /// Path to wasm contract code, defaults to ./target/<name>-pruned.wasm
        #[structopt(parse(from_os_str))]
        wasm_path: Option<std::path::PathBuf>,
126 127 128
    },
}

129
fn main() {
Andrew Jones's avatar
Andrew Jones committed
130 131
    env_logger::init();

132
    let Opts::Contract(args) = Opts::from_args();
133 134 135 136 137 138 139
    match exec(args.cmd) {
        Ok(msg) => println!("\t{}", msg),
        Err(err) => eprintln!("error: {}", err),
    }
}

fn exec(cmd: Command) -> cmd::Result<String> {
140
    use crate::cmd::CommandError;
141
    match &cmd {
142 143 144 145 146 147
        Command::New {
            layer,
            name,
            target_dir,
        } => cmd::execute_new(*layer, name, target_dir.as_ref()),
        Command::Build {} => cmd::execute_build(None),
148
        Command::GenerateAbi {} => cmd::execute_generate_abi(None),
149
        Command::Test {} => Err(CommandError::UnimplementedCommand),
Andrew Jones's avatar
Andrew Jones committed
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
        Command::Deploy {
            url,
            suri,
            password,
            gas,
            wasm_path,
        } => {
            cmd::execute_deploy(
                url.clone(),
                suri,
                password.as_ref().map(String::as_ref),
                *gas,
                wasm_path.as_ref(),
            )
        }
165 166
    }
}