2017-08-01 02:36:48 -07:00
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use futures::{future, Future};
|
2017-08-03 15:48:12 -07:00
|
|
|
use tokio_core::reactor::{Handle};
|
2017-08-13 04:09:50 -07:00
|
|
|
use web3::Transport;
|
2017-08-01 02:36:48 -07:00
|
|
|
use web3::transports::ipc::Ipc;
|
|
|
|
use web3::types::TransactionRequest;
|
2017-08-02 03:45:15 -07:00
|
|
|
use error::{Error, ErrorKind, ResultExt};
|
2017-08-01 02:36:48 -07:00
|
|
|
use config::Config;
|
2017-08-13 03:21:51 -07:00
|
|
|
use database::Database;
|
2017-08-12 11:03:48 -07:00
|
|
|
use contracts::{EthereumBridge, KovanBridge};
|
2017-08-02 03:45:15 -07:00
|
|
|
use api;
|
2017-08-01 02:36:48 -07:00
|
|
|
|
2017-08-04 08:57:09 -07:00
|
|
|
pub enum Deployed {
|
2017-08-13 07:13:03 -07:00
|
|
|
/// No existing database found. Deployed new contracts.
|
2017-08-04 08:57:09 -07:00
|
|
|
New(Database),
|
2017-08-13 07:13:03 -07:00
|
|
|
/// Reusing existing contracts.
|
|
|
|
Existing(Database),
|
2017-08-04 08:57:09 -07:00
|
|
|
}
|
|
|
|
|
2017-08-01 02:36:48 -07:00
|
|
|
pub struct App<T> where T: Transport {
|
2017-08-12 07:57:07 -07:00
|
|
|
pub config: Config,
|
|
|
|
pub database_path: PathBuf,
|
|
|
|
pub connections: Connections<T>,
|
2017-08-01 02:36:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Connections<T> where T: Transport {
|
2017-08-12 07:57:07 -07:00
|
|
|
pub mainnet: T,
|
|
|
|
pub testnet: T,
|
2017-08-01 02:36:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Connections<Ipc> {
|
2017-08-02 03:45:15 -07:00
|
|
|
pub fn new_ipc<P: AsRef<Path>>(handle: &Handle, mainnet: P, testnet: P) -> Result<Self, Error> {
|
|
|
|
let mainnet = Ipc::with_event_loop(mainnet, handle).chain_err(|| "Cannot connect to mainnet node ipc")?;
|
|
|
|
let testnet = Ipc::with_event_loop(testnet, handle).chain_err(|| "Cannot connect to testnet node ipc")?;
|
|
|
|
|
2017-08-01 02:36:48 -07:00
|
|
|
let result = Connections {
|
2017-08-02 03:45:15 -07:00
|
|
|
mainnet,
|
|
|
|
testnet,
|
2017-08-01 02:36:48 -07:00
|
|
|
};
|
|
|
|
Ok(result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl App<Ipc> {
|
2017-08-03 15:48:12 -07:00
|
|
|
pub fn new_ipc<P: AsRef<Path>>(config: Config, database_path: P, handle: &Handle) -> Result<Self, Error> {
|
|
|
|
let connections = Connections::new_ipc(handle, &config.mainnet.ipc, &config.testnet.ipc)?;
|
2017-08-01 02:36:48 -07:00
|
|
|
let result = App {
|
|
|
|
config,
|
|
|
|
database_path: database_path.as_ref().to_path_buf(),
|
|
|
|
connections,
|
|
|
|
};
|
|
|
|
Ok(result)
|
|
|
|
}
|
2017-08-12 07:57:07 -07:00
|
|
|
}
|
2017-08-01 02:36:48 -07:00
|
|
|
|
2017-08-12 07:57:07 -07:00
|
|
|
impl<T: Transport> App<T> {
|
2017-08-04 08:57:09 -07:00
|
|
|
pub fn ensure_deployed<'a>(&'a self) -> Box<Future<Item = Deployed, Error = Error> + 'a> {
|
2017-08-01 02:36:48 -07:00
|
|
|
let database_path = self.database_path.clone();
|
2017-08-02 03:45:15 -07:00
|
|
|
match Database::load(&database_path).map_err(ErrorKind::from) {
|
2017-08-13 07:13:03 -07:00
|
|
|
Ok(database) => future::result(Ok(Deployed::Existing(database))).boxed(),
|
2017-08-04 08:57:09 -07:00
|
|
|
Err(ErrorKind::MissingFile(_)) => Box::new(self.deploy().map(Deployed::New)),
|
2017-08-01 02:36:48 -07:00
|
|
|
Err(err) => future::result(Err(err.into())).boxed(),
|
|
|
|
}
|
2017-08-04 08:57:09 -07:00
|
|
|
|
2017-08-01 02:36:48 -07:00
|
|
|
}
|
|
|
|
|
2017-08-02 03:45:15 -07:00
|
|
|
pub fn deploy<'a>(&'a self) -> Box<Future<Item = Database, Error = Error> + 'a> {
|
2017-08-01 02:36:48 -07:00
|
|
|
let main_tx_request = TransactionRequest {
|
2017-08-03 15:48:12 -07:00
|
|
|
from: self.config.mainnet.account,
|
2017-08-01 02:36:48 -07:00
|
|
|
to: None,
|
2017-08-12 11:03:48 -07:00
|
|
|
gas: Some(self.config.mainnet.txs.deploy.gas.into()),
|
|
|
|
gas_price: Some(self.config.mainnet.txs.deploy.gas_price.into()),
|
|
|
|
value: Some(self.config.mainnet.txs.deploy.value.into()),
|
2017-08-01 02:36:48 -07:00
|
|
|
data: Some(include_bytes!("../contracts/EthereumBridge.bin").to_vec().into()),
|
|
|
|
nonce: None,
|
|
|
|
condition: None,
|
|
|
|
};
|
|
|
|
|
|
|
|
let test_tx_request = TransactionRequest {
|
2017-08-03 15:48:12 -07:00
|
|
|
from: self.config.testnet.account,
|
2017-08-01 02:36:48 -07:00
|
|
|
to: None,
|
2017-08-12 11:03:48 -07:00
|
|
|
gas: Some(self.config.testnet.txs.deploy.gas.into()),
|
|
|
|
gas_price: Some(self.config.testnet.txs.deploy.gas_price.into()),
|
|
|
|
value: Some(self.config.testnet.txs.deploy.value.into()),
|
2017-08-01 02:36:48 -07:00
|
|
|
data: Some(include_bytes!("../contracts/KovanBridge.bin").to_vec().into()),
|
|
|
|
nonce: None,
|
|
|
|
condition: None,
|
|
|
|
};
|
|
|
|
|
2017-08-02 03:45:15 -07:00
|
|
|
let main_future = api::send_transaction_with_confirmation(&self.connections.mainnet, main_tx_request, self.config.mainnet.poll_interval, self.config.mainnet.required_confirmations);
|
|
|
|
let test_future = api::send_transaction_with_confirmation(&self.connections.testnet, test_tx_request, self.config.testnet.poll_interval, self.config.testnet.required_confirmations);
|
2017-08-01 02:36:48 -07:00
|
|
|
|
|
|
|
let deploy = main_future.join(test_future)
|
|
|
|
.map(|(main_receipt, test_receipt)| {
|
|
|
|
Database {
|
2017-08-13 03:21:51 -07:00
|
|
|
mainnet_contract_address: main_receipt.contract_address.expect("contract creation receipt must have an address; qed"),
|
|
|
|
testnet_contract_address: test_receipt.contract_address.expect("contract creation receipt must have an address; qed"),
|
|
|
|
mainnet_deploy: main_receipt.block_number.low_u64(),
|
|
|
|
testnet_deploy: test_receipt.block_number.low_u64(),
|
|
|
|
checked_deposit_relay: main_receipt.block_number.low_u64(),
|
|
|
|
checked_withdraw_relay: test_receipt.block_number.low_u64(),
|
|
|
|
checked_withdraw_confirm: test_receipt.block_number.low_u64(),
|
2017-08-01 02:36:48 -07:00
|
|
|
}
|
|
|
|
})
|
2017-08-02 03:45:15 -07:00
|
|
|
.map_err(ErrorKind::Web3)
|
2017-08-03 15:48:12 -07:00
|
|
|
.map_err(Error::from)
|
|
|
|
.map_err(|e| e.chain_err(|| "Failed to deploy contracts"));
|
2017-08-01 02:36:48 -07:00
|
|
|
|
|
|
|
Box::new(deploy)
|
|
|
|
}
|
2017-08-12 07:57:07 -07:00
|
|
|
|
|
|
|
pub fn mainnet_bridge(&self) -> EthereumBridge {
|
|
|
|
EthereumBridge(&self.config.mainnet.contract.abi)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn testnet_bridge(&self) -> KovanBridge {
|
|
|
|
KovanBridge(&self.config.mainnet.contract.abi)
|
|
|
|
}
|
2017-08-01 02:36:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|