Compare commits

...

9 Commits

Author SHA1 Message Date
tommy a6ac1cf5e7 one more removal 2022-08-08 15:20:14 +02:00
tommy 0ba2a3b724 update text to reflect the correct opts args 2022-08-08 15:18:54 +02:00
tommy 96d5fd7612 update the version 2022-08-08 15:15:52 +02:00
tommy a1b7b43da2 Resolve PR comments 2022-08-08 15:11:24 +02:00
tommy 123cbf7aff add change log entry 2022-08-05 15:42:40 +02:00
tommy c4d12e7a8e cargo fmt - and the project to cargo.toml 2022-08-05 15:34:24 +02:00
tommy bf22a13b8f Revert "Validator Command Binary - Draft"
This reverts commit 3429e0a8e9.
2022-08-05 12:19:12 +02:00
tommy 8f5dd00027 minor changes 2022-08-04 13:41:53 +02:00
tommy 84c43ebf54 Draft - Validator CLI
- validator  binary - to enable easy to use commands on the network
- contains all operations (vesting / normal)
2022-08-04 13:38:59 +02:00
39 changed files with 1512 additions and 1 deletions
+1
View File
@@ -25,6 +25,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- validator-client: add `denom` argument and add simple test for querying an account balance
- gateway, validator-api: Checks for coconut credential double spending attempts, taking the coconut bandwidth contract as source of truth ([#1457])
- coconut-bandwidth-contract: Record the state of a coconut credential; create specific proposal for releasing funds ([#1457])
- add validator-client script rust binary /tools/validator-client-scripts
### Fixed
Generated
+32
View File
@@ -5397,6 +5397,15 @@ dependencies = [
"tokio",
]
[[package]]
name = "streaming-stats"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0d670ce4e348a2081843569e0f79b21c99c91bb9028b3b3ecb0f050306de547"
dependencies = [
"num-traits",
]
[[package]]
name = "stringprep"
version = "0.1.2"
@@ -6284,6 +6293,29 @@ dependencies = [
"vesting-contract-common",
]
[[package]]
name = "validator-client-scripts"
version = "0.1.0"
dependencies = [
"base64",
"bip39",
"bs58",
"clap 3.2.8",
"csv",
"dotenv",
"log",
"mixnet-contract-common",
"network-defaults",
"pretty_env_logger",
"serde",
"serde_json",
"streaming-stats",
"tokio",
"url",
"validator-client",
"vesting-contract-common",
]
[[package]]
name = "valuable"
version = "0.1.0"
+2 -1
View File
@@ -68,7 +68,8 @@ members = [
"service-providers/network-statistics",
"validator-api",
"validator-api/validator-api-requests",
"tools/ts-rs-cli"
"tools/ts-rs-cli",
"tools/validator-client-scripts"
]
default-members = [
+3
View File
@@ -69,6 +69,9 @@ build-wallet:
build-connect:
cargo build --manifest-path nym-connect/Cargo.toml --workspace
build-validator-scripts:
cargo build --release --manifest-path tools/validator-client-scripts/Cargo.toml
fmt-main:
cargo fmt --all
+23
View File
@@ -0,0 +1,23 @@
[package]
name = "validator-client-scripts"
version = "1.0.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
base64 = "0.13.0"
bs58 = "0.4"
clap = { version = "3.2.8", features = ["derive"] }
dotenv = "0.15.0"
log = "0.4"
pretty_env_logger = "0.4"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1.11", features = [ "net", "rt-multi-thread", "macros", "signal"] }
bip39 = "1.0.1"
validator-client = { path = "../../common/client-libs/validator-client", features = ["nymd-client"] }
network-defaults = { path = "../../common/network-defaults" }
mixnet-contract-common ={ path = "../../common/cosmwasm-smart-contracts/mixnet-contract" }
vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" }
+32
View File
@@ -0,0 +1,32 @@
# NYM - CLI TOOL
## Overview
Set of simple CLI commands to perform basic actions, such as upload contract, bond mixnode, etc.
Note: to work it requires rust 1.60+
## The binary
- Build the binary
- cargo build --release --bin validator-client-scripts
- this will compile the binary to "your/main/nym/path/target/release"
- the binary is named ./validator-client-scripts
## Executing commands
-./validator-client-scripts --help
- will produce a list of it's capabilites
The binary takes optional args which are as follows -> OPTIONS:
```
--config-env-file <CONFIG_ENV_FILE>
--mixnet-contract <MIXNET_CONTRACT>
--mnemonic <MNEMONIC>
--nymd-url <NYMD_URL>
--vesting-contract <VESTING_CONTRACT>
```
If you specify --config-env-file it will read the values from the envs/directory:
`./validator-client-scripts --config-env-file env/qa.env .....` and you don't need to supply the
mixnet-contract nor the vesting-contract argument
An example of a command is as follows:
```
Disclaimer the amount is in UNYMs
./validator-client-scripts --config-env-file ../../envs/qa.env --nymd-url https://qa-validator.nymtech.net --mnemonic "INPUT YOUR MNEMONIC" send --amount 100000000 --recipient <NYM_ADDRESS>
```
@@ -0,0 +1,20 @@
CONFIGURED=true
RUST_LOG=info
RUST_BACKTRACE=1
BECH32_PREFIX=n
MIX_DENOM=unym
MIX_DENOM_DISPLAY=nym
STAKE_DENOM=unyx
STAKE_DENOM_DISPLAY=nyx
DENOMS_EXPONENT=6
MIXNET_CONTRACT_ADDRESS=n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g
VESTING_CONTRACT_ADDRESS=n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw
BANDWIDTH_CLAIM_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
MULTISIG_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://127.0.0.1:8090"
NYMD_VALIDATOR="https://rpc.nyx.nodes.guru/"
API_VALIDATOR="https://validator.nymtech.net/api/"
@@ -0,0 +1,20 @@
CONFIGURED=true
RUST_LOG=info
RUST_BACKTRACE=1
BECH32_PREFIX=n
MIX_DENOM=unym
MIX_DENOM_DISPLAY=nym
STAKE_DENOM=unyx
STAKE_DENOM_DISPLAY=nyx
DENOMS_EXPONENT=6
MIXNET_CONTRACT_ADDRESS=n1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrsd3qaep
VESTING_CONTRACT_ADDRESS=n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav
BANDWIDTH_CLAIM_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n1ghd753shjuwexxywmgs4xz7x2q732vcn7ty4yw
MULTISIG_CONTRACT_ADDRESS=n17p9rzwnnfxcjp32un9ug7yhhzgtkhvl988qccs
REWARDING_VALIDATOR_ADDRESS=n1tfzd4qz3a45u8p4mr5zmzv66457uwjgcl05jdq
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
NYMD_VALIDATOR="https://qa-validator.nymtech.net"
API_VALIDATOR="https://qa-validator-api.nymtech.net/api"
@@ -0,0 +1,78 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::{info, warn};
use mixnet_contract_common::Coin;
use network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT};
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub host: String,
#[clap(long)]
pub signature: String,
#[clap(long)]
pub mix_port: Option<u16>,
#[clap(long)]
pub clients_port: Option<u16>,
#[clap(long)]
pub location: Option<String>,
#[clap(long)]
pub sphinx_key: String,
#[clap(long)]
pub identity_key: String,
#[clap(long)]
pub version: String,
#[clap(
long,
help = "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')"
)]
pub amount: u128,
#[clap(long)]
pub gas: Option<u64>,
#[clap(short, long)]
pub force: bool,
}
pub(crate) async fn bond_gateway(client: Client, args: Args, denom: &str) {
info!("Starting gateway bonding!");
// if we're trying to bond less than 1 token
if args.amount < 1_000_000 && !args.force {
warn!("You're trying to bond only {}{} which is less than 1 full token. Are you sure that's what you want? If so, run with `--force` or `-f` flag", args.amount, denom);
return;
}
let gateway = mixnet_contract_common::Gateway {
host: args.host,
mix_port: args.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT),
clients_port: args.clients_port.unwrap_or(DEFAULT_CLIENT_LISTENING_PORT),
location: args
.location
.unwrap_or_else(|| "secret gateway location".to_owned()),
sphinx_key: args.sphinx_key,
identity_key: args.identity_key,
version: args.version,
};
let coin = Coin::new(args.amount, denom);
let res = client
.bond_gateway(gateway, args.signature, coin.into(), None)
.await
.expect("failed to bond gateway!");
info!("Bonding result: {:?}", res)
}
@@ -0,0 +1,84 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::{info, warn};
use mixnet_contract_common::Coin;
use network_defaults::{
DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT,
};
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub host: String,
#[clap(long)]
pub signature: String,
#[clap(long)]
pub mix_port: Option<u16>,
#[clap(long)]
pub verloc_port: Option<u16>,
#[clap(long)]
pub http_api_port: Option<u16>,
#[clap(long)]
pub sphinx_key: String,
#[clap(long)]
pub identity_key: String,
#[clap(long)]
pub version: String,
#[clap(long)]
pub profit_margin_percent: Option<u8>,
#[clap(
long,
help = "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')"
)]
pub amount: u128,
#[clap(long)]
pub gas: Option<u64>,
#[clap(short, long)]
pub force: bool,
}
pub(crate) async fn bond_mixnode(client: Client, args: Args, denom: &str) {
info!("Starting mixnode bonding!");
// if we're trying to bond less than 1 token
if args.amount < 1_000_000 && !args.force {
warn!("You're trying to bond only {}{} which is less than 1 full token. Are you sure that's what you want? If so, run with `--force` or `-f` flag", args.amount, denom);
return;
}
let mixnode = mixnet_contract_common::MixNode {
host: args.host,
mix_port: args.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT),
verloc_port: args.verloc_port.unwrap_or(DEFAULT_VERLOC_LISTENING_PORT),
http_api_port: args
.http_api_port
.unwrap_or(DEFAULT_HTTP_API_LISTENING_PORT),
sphinx_key: args.sphinx_key,
identity_key: args.identity_key,
version: args.version,
profit_margin_percent: args.profit_margin_percent.unwrap_or(10),
};
let coin = Coin::new(args.amount, denom);
let res = client
.bond_mixnode(mixnode, args.signature, coin.into(), None)
.await
.expect("failed to bond mixnode!");
info!("Bonding result: {:?}", res)
}
@@ -0,0 +1,26 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
#[clap(long)]
pub identity: String,
}
pub(crate) async fn claim_delegator_reward(client: Client, args: Args) {
info!("Claim delegator reward");
let res = client
.execute_claim_delegator_reward(args.identity, None)
.await
.expect("failed to claim delegator-reward");
info!("Claiming delegator reward: {:?}", res)
}
@@ -0,0 +1,23 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn claim_operator_reward(client: Client) {
info!("Claim operator reward");
let res = client
.execute_claim_operator_reward(None)
.await
.expect("failed to claim operator reward");
info!("Claiming operator reward: {:?}", res)
}
@@ -0,0 +1,26 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
#[clap(long)]
pub identity: String,
}
pub(crate) async fn compound_delegator_reward(client: Client, args: Args) {
info!("compound delegator reward");
let res = client
.execute_compound_delegator_reward(args.identity, None)
.await
.expect("failed to claim delegator-reward");
info!("Claiming delegator reward: {:?}", res)
}
@@ -0,0 +1,23 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn compound_operator_reward(client: Client, _args: Args) {
info!("compounding operator reward");
let res = client
.execute_compound_operator_reward(None)
.await
.expect("failed to compound operator-reward");
info!("Claiming compound operator reward: {:?}", res)
}
@@ -0,0 +1,24 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::Parser;
use validator_client::nymd::wallet::DirectSecp256k1HdWallet;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
// allowed values are 12, 18 or 24
pub word_count: Option<usize>,
}
pub(crate) fn create_account(args: Args, prefix: &str) {
let word_count = args.word_count.unwrap_or(24);
let mnemonic = bip39::Mnemonic::generate(word_count).expect("failed to generate mnemonic!");
let wallet =
DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic).expect("failed to build wallet!");
// Output address and mnemonics into separate lines for easier parsing
println!("{}", wallet.mnemonic());
println!("{}", wallet.try_derive_accounts().unwrap()[0].address());
}
@@ -0,0 +1,17 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::Parser;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(short, long)]
pub key: String,
}
pub(crate) fn decode_mixnode_key(args: Args) {
let b64_decoded = base64::decode(args.key).expect("failed to decode base64 string");
let b58_encoded = bs58::encode(&b64_decoded).into_string();
println!("{}", b58_encoded)
}
@@ -0,0 +1,32 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
use mixnet_contract_common::Coin;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
#[clap(long)]
pub identity_key: String,
#[clap(long)]
pub amount: u128,
}
pub(crate) async fn delegate_to_mixnode(client: Client, args: Args, denom: &str) {
info!("Starting delegation to mixnode");
let coin = Coin::new(args.amount, denom);
let res = client
.delegate_to_mixnode(&*args.identity_key, coin.into(), None)
.await
.expect("failed to delegate to mixnode!");
info!("delegating to mixnode: {:?}", res);
}
@@ -0,0 +1,74 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
use mixnet_contract_common::InstantiateMsg;
use validator_client::nymd::cosmwasm_client::types::{ContractCodeId, InstantiateOptions};
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub code_id: ContractCodeId,
#[clap(long)]
pub memo: Option<String>,
#[clap(long)]
pub label: Option<String>,
#[clap(long)]
pub init_message: Option<String>,
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn init(client: Client, args: Args, denom: &str) {
info!("Starting contract instantiation!");
let memo = args
.memo
.unwrap_or_else(|| "contract instantiation".to_owned());
let label = args
.label
.unwrap_or_else(|| "Nym mixnet smart contract".to_owned());
// by default we make ourselves an admin, let me know if you don't like that behaviour
let opts = Some(InstantiateOptions {
funds: vec![],
admin: Some(client.address().clone()),
});
// the EmptyMsg{} argument is equivalent to `--init-message='{}'`
let res = if let Some(raw_msg) = args.init_message {
let msg: serde_json::Value =
serde_json::from_str(&raw_msg).expect("failed to parse init message");
client
.instantiate(args.code_id, &msg, label, memo, opts, None)
.await
.expect("failed to instantiate the contract!")
} else {
let address = client.address().to_string();
client
.instantiate(
args.code_id,
&InstantiateMsg {
rewarding_validator_address: address,
mixnet_denom: denom.to_string(),
},
label,
memo,
opts,
None,
)
.await
.expect("failed to instantiate the contract!")
};
info!("Init result: {:?}", res);
println!("{}", res.contract_address)
}
@@ -0,0 +1,47 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
use validator_client::nymd::cosmwasm_client::types::{ContractCodeId, EmptyMsg};
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub code_id: ContractCodeId,
#[clap(long)]
pub memo: Option<String>,
#[clap(long)]
pub init_message: Option<String>,
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn migrate(client: Client, args: Args) {
println!("Starting contract migration!");
let memo = args.memo.unwrap_or_else(|| "contract migration".to_owned());
let contract_address = client.mixnet_contract_address();
// the EmptyMsg{} argument is equivalent to `--init-message='{}'`
let res = if let Some(raw_msg) = args.init_message {
let msg: serde_json::Value =
serde_json::from_str(&raw_msg).expect("failed to parse init message");
client
.migrate(contract_address, args.code_id, &msg, memo, None)
.await
.expect("failed to instantiate the contract!")
} else {
client
.migrate(contract_address, args.code_id, &EmptyMsg {}, memo, None)
.await
.expect("failed to instantiate the contract!")
};
info!("Migrate result: {:?}", res);
}
@@ -0,0 +1,32 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub(crate) mod bond_gateway;
pub(crate) mod bond_mixnode;
pub(crate) mod claim_delegator_reward;
pub(crate) mod claim_operator_reward;
pub(crate) mod compound_delegator_reward;
pub(crate) mod compound_operator_reward;
pub(crate) mod create_account;
pub(crate) mod decode_mixnode_key;
pub(crate) mod delegate_to_mixnode;
pub(crate) mod init_contract;
pub(crate) mod migrate_contract;
pub(crate) mod send;
pub(crate) mod unbond_gateway;
pub(crate) mod unbond_mixnode;
pub(crate) mod undelegate_from_mixnode;
pub(crate) mod update_profit_percent;
pub(crate) mod upload_contract;
pub(crate) mod vesting_bond_gateway;
pub(crate) mod vesting_bond_mixnode;
pub(crate) mod vesting_claim_delegator_reward;
pub(crate) mod vesting_claim_operator_reward;
pub(crate) mod vesting_compound_delegator_reward;
pub(crate) mod vesting_compound_operator_reward;
pub(crate) mod vesting_create_schedule;
pub(crate) mod vesting_delegate_to_mixnode;
pub(crate) mod vesting_unbond_gateway;
pub(crate) mod vesting_unbond_mixnode;
pub(crate) mod vesting_undelegate_from_mixnode;
pub(crate) mod vesting_update_profit_percent;
@@ -0,0 +1,54 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::str::FromStr;
use crate::Client;
use clap::Parser;
use log::{info, warn};
use validator_client::nymd::{AccountId, CosmosCoin, Denom};
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub recipient: AccountId,
#[clap(
long,
help = "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')"
)]
pub amount: u64,
#[clap(long)]
pub memo: Option<String>,
#[clap(long)]
pub gas: Option<u64>,
#[clap(short, long)]
pub force: bool,
}
pub(crate) async fn send(client: Client, args: Args, denom: &str) {
info!("Starting token sending!");
let memo = args.memo.unwrap_or_else(|| "Sending tokens".to_owned());
// if we're trying to bond less than 1 token
if args.amount < 1_000_000 && !args.force {
warn!("You're trying to send only {}{} which is less than 1 full token. Are you sure that's what you want? If so, run with `--force` or `-f` flag", args.amount, denom);
return;
}
let coin = CosmosCoin {
denom: Denom::from_str(denom).unwrap(),
amount: args.amount.into(),
};
let res = client
.send(&args.recipient, vec![coin.into()], memo, None)
.await
.expect("failed to send tokens!");
info!("Sending result: {:?}", res)
}
@@ -0,0 +1,23 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn unbond_gateway(client: Client) {
info!("Starting gateway unbonding!");
let res = client
.unbond_gateway(None)
.await
.expect("failed to unbond gateway!");
info!("Unbonding result: {:?}", res)
}
@@ -0,0 +1,23 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn unbond_mixnode(client: Client) {
info!("Starting mixnode unbonding!");
let res = client
.unbond_mixnode(None)
.await
.expect("failed to unbond mixnode!");
info!("Unbonding result: {:?}", res)
}
@@ -0,0 +1,26 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub identity_key: String,
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn undelegate_from_mixnode(client: Client, args: Args) {
info!("removing stake from mix-node");
let res = client
.remove_mixnode_delegation(&*args.identity_key, None)
.await
.expect("failed to remove stake from mixnode!");
info!("removing stake from mixnode: {:?}", res)
}
@@ -0,0 +1,27 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub profit_percent: u8,
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn update_profit_percent(client: Client, args: Args) {
info!("Update mix node profit percent - get those rewards!");
//profit percent between 1-100
let res = client
.update_mixnode_config(args.profit_percent, None)
.await
.expect("updating mix-node profit percent");
info!("profit percentage updated: {:?}", res)
}
@@ -0,0 +1,40 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
use std::io::Read;
use std::path::PathBuf;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub wasm_path: PathBuf,
#[clap(long)]
pub memo: Option<String>,
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn upload(client: Client, args: Args) {
info!("Starting contract upload!");
let mut file = std::fs::File::open(args.wasm_path).expect("failed to open the wasm blob");
let mut data = Vec::new();
file.read_to_end(&mut data).unwrap();
let memo = args.memo.unwrap_or_else(|| "contract upload".to_owned());
let res = client
.upload(data, memo, None)
.await
.expect("failed to upload the contract!");
info!("Upload result: {:?}", res);
println!("{}", res.code_id)
}
@@ -0,0 +1,79 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::{info, warn};
use mixnet_contract_common::{Coin, Gateway};
use network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT};
use validator_client::nymd::VestingSigningClient;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub host: String,
#[clap(long)]
pub signature: String,
#[clap(long)]
pub mix_port: Option<u16>,
#[clap(long)]
pub clients_port: Option<u16>,
#[clap(long)]
pub location: Option<String>,
#[clap(long)]
pub sphinx_key: String,
#[clap(long)]
pub identity_key: String,
#[clap(long)]
pub version: String,
#[clap(
long,
help = "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')"
)]
pub amount: u128,
#[clap(long)]
pub gas: Option<u64>,
#[clap(short, long)]
pub force: bool,
}
pub(crate) async fn vesting_bond_gateway(client: Client, args: Args, denom: &str) {
info!("Starting vesting gateway bonding!");
// if we're trying to bond less than 1 token
if args.amount < 1_000_000 && !args.force {
warn!("You're trying to bond only {}{} which is less than 1 full token. Are you sure that's what you want? If so, run with `--force` or `-f` flag", args.amount, denom);
return;
}
let gateway = Gateway {
host: args.host,
mix_port: args.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT),
clients_port: args.clients_port.unwrap_or(DEFAULT_CLIENT_LISTENING_PORT),
location: args
.location
.unwrap_or_else(|| "secret gateway location".to_owned()),
sphinx_key: args.sphinx_key,
identity_key: args.identity_key,
version: args.version,
};
let coin = Coin::new(args.amount, denom);
let res = client
.vesting_bond_gateway(gateway, &*args.signature, coin.into(), None)
.await
.expect("failed to bond gateway!");
info!("Vesting bonding gateway result: {:?}", res)
}
@@ -0,0 +1,86 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::{info, warn};
use mixnet_contract_common::Coin;
use mixnet_contract_common::MixNode;
use network_defaults::{
DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT,
};
use validator_client::nymd::VestingSigningClient;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub host: String,
#[clap(long)]
pub signature: String,
#[clap(long)]
pub mix_port: Option<u16>,
#[clap(long)]
pub verloc_port: Option<u16>,
#[clap(long)]
pub http_api_port: Option<u16>,
#[clap(long)]
pub sphinx_key: String,
#[clap(long)]
pub identity_key: String,
#[clap(long)]
pub version: String,
#[clap(long)]
pub profit_margin_percent: Option<u8>,
#[clap(
long,
help = "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')"
)]
pub amount: u128,
#[clap(long)]
pub gas: Option<u64>,
#[clap(short, long)]
pub force: bool,
}
pub(crate) async fn vesting_bond_mixnode(client: Client, args: Args, denom: &str) {
info!("Starting vesting mixnode bonding!");
// if we're trying to bond less than 1 token
if args.amount < 1_000_000 && !args.force {
warn!("You're trying to bond only {}{} which is less than 1 full token. Are you sure that's what you want? If so, run with `--force` or `-f` flag", args.amount, denom);
return;
}
let mixnode = MixNode {
host: args.host,
mix_port: args.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT),
verloc_port: args.verloc_port.unwrap_or(DEFAULT_VERLOC_LISTENING_PORT),
http_api_port: args
.http_api_port
.unwrap_or(DEFAULT_HTTP_API_LISTENING_PORT),
sphinx_key: args.sphinx_key,
identity_key: args.identity_key,
version: args.version,
profit_margin_percent: args.profit_margin_percent.unwrap_or(10),
};
let coin = Coin::new(args.amount, denom);
let res = client
.vesting_bond_mixnode(mixnode, &*args.signature, coin.into(), None)
.await
.expect("failed to bond vesting mixnode!");
info!("Bonding vesting result: {:?}", res)
}
@@ -0,0 +1,26 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
#[clap(long)]
pub identity: String,
}
pub(crate) async fn vesting_claim_delegator_reward(client: Client, args: Args) {
info!("Claim vesting delegator reward");
let res = client
.execute_vesting_claim_delegator_reward(args.identity, None)
.await
.expect("failed to claim vesting delegator-reward");
info!("Claiming vesting delegator reward: {:?}", res)
}
@@ -0,0 +1,23 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn vesting_claim_operator_reward(client: Client) {
info!("Claim vesting operator reward");
let res = client
.execute_vesting_claim_operator_reward(None)
.await
.expect("failed to claim vesting operator reward");
info!("Claiming vesting operator reward: {:?}", res)
}
@@ -0,0 +1,26 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
#[clap(long)]
pub identity: String,
}
pub(crate) async fn vesting_compound_delegator_reward(client: Client, args: Args) {
info!("Claim vesting delegator reward");
let res = client
.execute_vesting_compound_delegator_reward(args.identity, None)
.await
.expect("failed to claim vesting delegator-reward");
info!("Claiming vesting delegator reward: {:?}", res)
}
@@ -0,0 +1,23 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn vesting_compound_operator_reward(client: Client, _args: Args) {
info!("compounding vesting operator reward");
let res = client
.execute_vesting_compound_operator_reward(None)
.await
.expect("failed to compound operator-reward");
info!("Claiming compound operator reward: {:?}", res)
}
@@ -0,0 +1,76 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{AccountId, Client};
use clap::Parser;
use log::info;
use mixnet_contract_common::Coin;
use std::str::FromStr;
use validator_client::nymd::{CosmosCoin, Denom, VestingSigningClient};
use vesting_contract_common::messages::VestingSpecification;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub periods_seconds: Option<u64>,
#[clap(long)]
pub number_of_periods: Option<u64>,
#[clap(long)]
pub start_time: Option<u64>,
#[clap(long)]
pub address: String,
#[clap(long)]
pub amount: u64,
#[clap(long)]
pub staking_address: Option<String>,
}
pub(crate) async fn vesting_create_schedule(client: Client, args: Args, denom: &str) {
info!("Creating vesting schedule!");
let vesting = VestingSpecification::new(
args.start_time,
args.periods_seconds,
args.number_of_periods,
);
let coin = Coin::new(args.amount.into(), denom);
let res = client
.create_periodic_vesting_account(
&*args.address,
args.staking_address,
Some(vesting),
coin.into(),
None,
)
.await
.expect("creating vesting schedule for the user!");
//send 1 coin
let coin_amount: u64 = 100_000;
let coin = CosmosCoin {
denom: Denom::from_str(denom).unwrap(),
amount: coin_amount.into(),
};
let send_coin_response = client
.send(
&AccountId::from_str(&*args.address).unwrap(),
vec![coin.into()],
"payment made :)",
None,
)
.await
.unwrap();
info!("Vesting result: {:?}", res);
info!("Coin send result: {:?}", send_coin_response);
}
@@ -0,0 +1,33 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
use mixnet_contract_common::Coin;
use validator_client::nymd::VestingSigningClient;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
#[clap(long)]
pub identity_key: String,
#[clap(long)]
pub amount: u128,
}
pub(crate) async fn vesting_delegate_to_mixnode(client: Client, args: Args, denom: &str) {
info!("Starting vesting delegation to mixnode");
let coin = Coin::new(args.amount, denom);
let res = client
.vesting_delegate_to_mixnode(&*args.identity_key, coin.into(), None)
.await
.expect("failed to delegate to mixnode!");
info!("vesting delegating to mixnode: {:?}", res);
}
@@ -0,0 +1,23 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn vesting_unbond_gateway(client: Client) {
info!("Starting vesting gateway unbonding!");
let res = client
.unbond_gateway(None)
.await
.expect("failed to unbond vesting gateway!");
info!("Unbonding vesting result: {:?}", res)
}
@@ -0,0 +1,24 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
use validator_client::nymd::VestingSigningClient;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn vesting_unbond_mixnode(client: Client) {
info!("Starting vesting mixnode unbonding!");
let res = client
.vesting_unbond_mixnode(None)
.await
.expect("failed to unbond vesting mixnode!");
info!("Unbonding vesting result: {:?}", res)
}
@@ -0,0 +1,27 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
use validator_client::nymd::VestingSigningClient;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub identity_key: String,
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn vesting_undelegate_from_mixnode(client: Client, args: Args) {
info!("removing stake from vesting mix-node");
let res = client
.vesting_undelegate_from_mixnode(&*args.identity_key, None)
.await
.expect("failed to remove stake from vesting account on mixnode!");
info!("removing stake from vesting mixnode: {:?}", res)
}
@@ -0,0 +1,28 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::Client;
use clap::Parser;
use log::info;
use validator_client::nymd::VestingSigningClient;
#[derive(Debug, Parser)]
pub(crate) struct Args {
#[clap(long)]
pub profit_percent: u8,
#[clap(long)]
pub gas: Option<u64>,
}
pub(crate) async fn vesting_update_profit_percent(client: Client, args: Args) {
info!("Update vesting mix node profit percent - get those rewards!");
//profit percent between 1-100
let res = client
.vesting_update_mixnode_config(args.profit_percent, None)
.await
.expect("updating vesting mix-node profit percent");
info!("profit percentage updated: {:?}", res)
}
+226
View File
@@ -0,0 +1,226 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::commands::bond_gateway::bond_gateway;
use crate::commands::bond_mixnode::bond_mixnode;
use crate::commands::claim_delegator_reward::claim_delegator_reward;
use crate::commands::claim_operator_reward::claim_operator_reward;
use crate::commands::compound_delegator_reward::compound_delegator_reward;
use crate::commands::compound_operator_reward::compound_operator_reward;
use crate::commands::create_account::create_account;
use crate::commands::decode_mixnode_key::decode_mixnode_key;
use crate::commands::delegate_to_mixnode::delegate_to_mixnode;
use crate::commands::init_contract::init;
use crate::commands::migrate_contract::migrate;
use crate::commands::send::send;
use crate::commands::unbond_gateway::unbond_gateway;
use crate::commands::unbond_mixnode::unbond_mixnode;
use crate::commands::undelegate_from_mixnode::undelegate_from_mixnode;
use crate::commands::update_profit_percent::update_profit_percent;
use crate::commands::upload_contract::upload;
use crate::commands::vesting_bond_gateway::vesting_bond_gateway;
use crate::commands::vesting_bond_mixnode::vesting_bond_mixnode;
use crate::commands::vesting_claim_delegator_reward::vesting_claim_delegator_reward;
use crate::commands::vesting_claim_operator_reward::vesting_claim_operator_reward;
use crate::commands::vesting_compound_delegator_reward::vesting_compound_delegator_reward;
use crate::commands::vesting_compound_operator_reward::vesting_compound_operator_reward;
use crate::commands::vesting_create_schedule::vesting_create_schedule;
use crate::commands::vesting_delegate_to_mixnode::vesting_delegate_to_mixnode;
use crate::commands::vesting_unbond_gateway::vesting_unbond_gateway;
use crate::commands::vesting_unbond_mixnode::vesting_unbond_mixnode;
use crate::commands::vesting_undelegate_from_mixnode::vesting_undelegate_from_mixnode;
use crate::commands::vesting_update_profit_percent::vesting_update_profit_percent;
use clap::Parser;
use log::{error, warn};
use network_defaults::{
setup_env,
var_names::{BECH32_PREFIX, MIX_DENOM},
NymNetworkDetails,
};
use validator_client::nymd::{self, AccountId, NymdClient, SigningNymdClient};
mod commands;
// we're always going to be using the signing client
pub(crate) type Client = validator_client::nymd::NymdClient<SigningNymdClient>;
#[derive(Debug, Parser)]
pub(crate) enum Command {
BondGateway(commands::bond_gateway::Args),
BondMixnode(commands::bond_mixnode::Args),
ClaimOperatorReward(commands::claim_operator_reward::Args),
ClaimDelegatorReward(commands::claim_delegator_reward::Args),
CompoundOperatorReward(commands::compound_operator_reward::Args),
CompoundDelegatorReward(commands::compound_delegator_reward::Args),
Init(commands::init_contract::Args),
Migrate(commands::migrate_contract::Args),
Upload(commands::upload_contract::Args),
UnbondMixnode(commands::unbond_mixnode::Args),
UnbondGateway(commands::unbond_gateway::Args),
DelegateToMixnode(commands::delegate_to_mixnode::Args),
UnDelegateFomMixnode(commands::undelegate_from_mixnode::Args),
Send(commands::send::Args),
CreateAccount(commands::create_account::Args),
UpdateProfitPercent(commands::update_profit_percent::Args),
DecodeMixnodeKey(commands::decode_mixnode_key::Args),
VestingUpdateProfitPercent(commands::vesting_update_profit_percent::Args),
VestingBondGateway(commands::vesting_bond_gateway::Args),
VestingBondMixnode(commands::vesting_bond_mixnode::Args),
VestingClaimDelegatorRewards(commands::vesting_claim_delegator_reward::Args),
VestingClaimOperatorRewards(commands::vesting_claim_operator_reward::Args),
VestingCompoundOperatorRewards(commands::vesting_compound_operator_reward::Args),
VestingCompoundDelegatorRewards(commands::vesting_compound_delegator_reward::Args),
VestingCreateSchedule(commands::vesting_create_schedule::Args),
VestingDelegateToMixnode(commands::vesting_delegate_to_mixnode::Args),
VestingUnbondGateway(commands::vesting_unbond_gateway::Args),
VestingUnbondMixnode(commands::vesting_unbond_mixnode::Args),
VestingUndelegateFromMixnode(commands::vesting_undelegate_from_mixnode::Args),
}
#[derive(Debug, Parser)]
#[clap(name = "validator-client-scripts")]
pub(crate) struct Args {
#[clap(long)]
pub(crate) config_env_file: Option<std::path::PathBuf>,
#[clap(long)]
pub(crate) nymd_url: Option<String>,
#[clap(long)]
pub(crate) mnemonic: Option<bip39::Mnemonic>,
// it can only be `None` in the case of contract upload or init
#[clap(long)]
pub(crate) mixnet_contract: Option<AccountId>,
// it can only be `None` in the case of contract upload or init
#[clap(long)]
pub(crate) vesting_contract: Option<AccountId>,
#[clap(subcommand)]
pub(crate) command: Command,
}
async fn execute(args: Args) {
let prefix = std::env::var(BECH32_PREFIX).expect("prefix not set");
let denom = std::env::var(MIX_DENOM).expect("denom not set");
// doesn't require the client
if let Command::CreateAccount(args) = args.command {
return create_account(args, &prefix);
}
if let Command::DecodeMixnodeKey(args) = args.command {
return decode_mixnode_key(args);
}
let client = create_client(&args);
// require the client
match args.command {
Command::BondGateway(args) => bond_gateway(client, args, &denom).await,
Command::BondMixnode(args) => bond_mixnode(client, args, &denom).await,
Command::ClaimOperatorReward(_args) => claim_operator_reward(client).await,
Command::ClaimDelegatorReward(args) => claim_delegator_reward(client, args).await,
Command::CompoundDelegatorReward(args) => compound_delegator_reward(client, args).await,
Command::CompoundOperatorReward(args) => compound_operator_reward(client, args).await,
Command::Init(args) => init(client, args, &denom).await,
Command::Migrate(args) => migrate(client, args).await,
Command::Upload(args) => upload(client, args).await,
Command::UnbondMixnode(_) => unbond_mixnode(client).await,
Command::UnbondGateway(_) => unbond_gateway(client).await,
Command::Send(args) => send(client, args, &denom).await,
Command::DelegateToMixnode(args) => delegate_to_mixnode(client, args, &denom).await,
Command::UnDelegateFomMixnode(args) => undelegate_from_mixnode(client, args).await,
Command::UpdateProfitPercent(args) => update_profit_percent(client, args).await,
Command::VestingUpdateProfitPercent(args) => {
vesting_update_profit_percent(client, args).await
}
Command::VestingBondGateway(args) => vesting_bond_gateway(client, args, &denom).await,
Command::VestingBondMixnode(args) => vesting_bond_mixnode(client, args, &denom).await,
Command::VestingClaimDelegatorRewards(args) => {
vesting_claim_delegator_reward(client, args).await
}
Command::VestingClaimOperatorRewards(_args) => vesting_claim_operator_reward(client).await,
Command::VestingCompoundDelegatorRewards(args) => {
vesting_compound_delegator_reward(client, args).await
}
Command::VestingCompoundOperatorRewards(args) => {
vesting_compound_operator_reward(client, args).await
}
Command::VestingCreateSchedule(args) => vesting_create_schedule(client, args, &denom).await,
Command::VestingDelegateToMixnode(args) => {
vesting_delegate_to_mixnode(client, args, &denom).await
}
Command::VestingUnbondGateway(_args) => vesting_unbond_gateway(client).await,
Command::VestingUnbondMixnode(_args) => vesting_unbond_mixnode(client).await,
Command::VestingUndelegateFromMixnode(args) => {
vesting_undelegate_from_mixnode(client, args).await
}
_ => unreachable!(),
}
}
fn setup_logging() {
let mut log_builder = pretty_env_logger::formatted_timed_builder();
if let Ok(s) = ::std::env::var("RUST_LOG") {
log_builder.parse_filters(&s);
} else {
// default to 'Info'
log_builder.filter(None, log::LevelFilter::Info);
}
log_builder
.filter_module("hyper", log::LevelFilter::Warn)
.filter_module("tokio_reactor", log::LevelFilter::Warn)
.filter_module("reqwest", log::LevelFilter::Warn)
.filter_module("mio", log::LevelFilter::Warn)
.filter_module("want", log::LevelFilter::Warn)
.filter_module("sled", log::LevelFilter::Warn)
.filter_module("tungstenite", log::LevelFilter::Warn)
.filter_module("tokio_tungstenite", log::LevelFilter::Warn)
.init();
}
fn create_client(args: &Args) -> Client {
let network_details = NymNetworkDetails::new_from_env();
let client_config = nymd::Config::try_from_nym_network_details(&network_details)
.expect("failed to construct valid validator client config with the provided network");
NymdClient::connect_with_mnemonic(
client_config,
args.nymd_url
.as_ref()
.expect("nymd url was not provided")
.as_str(),
args.mnemonic
.as_ref()
.expect("mnemonic was not provided")
.clone(),
None,
)
.expect("failed to create the client")
}
async fn wait_for_interrupt() {
if let Err(e) = tokio::signal::ctrl_c().await {
error!(
"There was an error while capturing SIGINT - {:?}. We will terminate regardless",
e
);
}
println!(
"Received SIGINT - the process will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)."
);
}
#[tokio::main]
async fn main() {
setup_logging();
let args = Args::parse();
setup_env(args.config_env_file.clone());
tokio::select! {
_ = wait_for_interrupt() => warn!("Received interrupt - the specified command might have not completed!"),
_ = execute(args) => (),
}
}