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
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate log;
extern crate glob;
extern crate web3;
extern crate ethabi;

pub mod blockchain;
pub mod project_generator;
pub mod compiler;
pub mod config;
pub mod deployment;
mod utils;

use std::process::{ExitStatus, Output};
use std::path::PathBuf;
use std::collections::HashMap;
use blockchain::connector as connector;
use web3::types::Address;

#[derive(Debug)]
pub struct Vibranium {
  project_path: PathBuf,
  pub config: config::Config,
}

impl Vibranium {
  pub fn new(project_path: PathBuf) -> Vibranium {
    Vibranium {
      config: config::Config::new(project_path.clone()),
      project_path,
    }
  }

  pub fn start_node(&self, config: blockchain::NodeConfig) -> Result<ExitStatus, blockchain::error::NodeError> {
    let generator = project_generator::ProjectGenerator::new(&self.config);
    generator
      .check_vibranium_dir_exists()
      .map_err(|error| blockchain::error::NodeError::Other(error.to_string()))
      .and_then(|_| {
        let node = blockchain::Node::new(&self.config);
        node.start(config)
          .map(|mut process| process.wait().map_err(blockchain::error::NodeError::Io))
          .and_then(|status| status)
      })
  }

  pub fn init_project(&self) -> Result<(), project_generator::error::ProjectGenerationError> {
    let generator = project_generator::ProjectGenerator::new(&self.config);
    generator.generate_project(&self.project_path)
  }

  pub fn reset_project(&self, reset_options: project_generator::ResetOptions) -> Result<(), project_generator::error::ProjectGenerationError> {
    let generator = project_generator::ProjectGenerator::new(&self.config);
    generator
      .reset_project(&self.project_path, reset_options)
      .and_then(|_| generator.generate_project(&self.project_path))
  }

  pub fn set_config(&self, option: String, value: toml::Value) -> Result<(), config::error::ConfigError> {
    let generator = project_generator::ProjectGenerator::new(&self.config);
    generator
      .check_vibranium_dir_exists()
      .map_err(|error| config::error::ConfigError::Other(error.to_string()))
      .and_then(|_| self.config.write(option, value))
  }

  pub fn unset_config(&self, option: String) -> Result<(), config::error::ConfigError> {
    let generator = project_generator::ProjectGenerator::new(&self.config);
    generator
      .check_vibranium_dir_exists()
      .map_err(|error| config::error::ConfigError::Other(error.to_string()))
      .and_then(|_| self.config.remove(option))
  }

  pub fn compile(&self, config: compiler::CompilerConfig) -> Result<Output, compiler::error::CompilerError> {
    let compiler = compiler::Compiler::new(&self.config);
    let generator = project_generator::ProjectGenerator::new(&self.config);

    generator
      .check_vibranium_dir_exists()
      .map_err(compiler::error::CompilerError::VibraniumDirectoryNotFound)
      .and_then(|_| {
        compiler.compile(config).map(|process| {
          process.wait_with_output().map_err(compiler::error::CompilerError::Io)
        })
      })
      .and_then(|output| output)
      .and_then(|output| {
        if !output.stderr.is_empty() {
          Err(compiler::error::CompilerError::Other(String::from_utf8_lossy(&output.stderr).to_string()))
        } else {
          Ok(output)
        }
      })
  }

  pub fn get_blockchain_connector(&self) -> Result<(web3::transports::EventLoopHandle, connector::BlockchainConnector), blockchain::error::ConnectionError> {
    let generator = project_generator::ProjectGenerator::new(&self.config);

    generator
      .check_vibranium_dir_exists()
      .map_err(|err| blockchain::error::ConnectionError::Other(err.to_string()))
      .and_then(|_| {
        let project_config = self.config.read().map_err(|err| blockchain::error::ConnectionError::Other(err.to_string()))?;
        let blockchain_config = project_config.blockchain.ok_or(blockchain::error::ConnectionError::MissingConnectorConfig)?;
        let connector_config = blockchain_config.connector.ok_or(blockchain::error::ConnectionError::MissingConnectorConfig)?;
        let (eloop, adapter) = connector::web3_adapter::Web3Adapter::new(connector_config)?;
        let blockchain_connector = connector::BlockchainConnector::new(adapter);
        Ok((eloop, blockchain_connector))
      })
  }

  pub fn deploy(&self) -> Result<HashMap<String, (String, Address)>, deployment::error::DeploymentError> {
    let (_eloop, connector) = self.get_blockchain_connector().map_err(deployment::error::DeploymentError::Connection)?;
    let deployer = deployment::Deployer::new(&self.config, &connector);
    deployer.deploy()
  }
}