Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

166 faucet (outdated) #179

Closed
wants to merge 116 commits into from
Closed
Show file tree
Hide file tree
Changes from 114 commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
5976adf
Add project faucet (166-faucet)
vakond Aug 11, 2021
4dd17ee
Eth side wip (166-faucet)
vakond Aug 11, 2021
06a570c
Http server side wip (166-faucet)
vakond Aug 11, 2021
8af49c8
WIP (166-faucet)
vakond Aug 11, 2021
bf2d790
WIP (166-faucet)
vakond Aug 11, 2021
1fcb504
Merge branch 'develop' into 166-faucet
vakond Aug 11, 2021
6281f15
Refactoring (166-faucet)
vakond Aug 12, 2021
9333e36
Wrap into docker image (166-faucet)
vakond Aug 12, 2021
e04278b
Add readme file (166-faucet)
vakond Aug 12, 2021
9989491
Set Access-Control-Allow-Origin header of responses (166-faucet)
vakond Aug 12, 2021
19d81e4
Set Access-Control-Allow-Methods header of responses (166-faucet)
vakond Aug 12, 2021
b46f959
Set Access-Control-Allow-Headers header of responses (166-faucet)
vakond Aug 12, 2021
a147305
Input request as plain text (166-faucet)
vakond Aug 13, 2021
68e331f
Merge branch 'develop' into 166-faucet
vakond Aug 13, 2021
b8e6ebc
Explicit sender of transactions (166-faucet)
vakond Aug 13, 2021
438be07
Config keeps both admin key and address (166-faucet)
vakond Aug 13, 2021
7957fda
Use actix-web for incoming rpc (166-faucet)
vakond Aug 14, 2021
2743387
Refactoring (166-faucet)
vakond Aug 15, 2021
ced9cea
Remove explicit admin address (can be derived from privkey) (166-faucet)
vakond Aug 15, 2021
becd086
Improve error handling (166-faucet)
vakond Aug 15, 2021
d3efa29
Add logs (166-faucet)
vakond Aug 15, 2021
8475503
Add logs (166-faucet)
vakond Aug 16, 2021
78fefdb
Use ethers.rs version 0.2 (166-faucet)
vakond Aug 16, 2021
dbf6f4f
Refactoring (166-faucet)
vakond Aug 16, 2021
cb186b9
Refactoring (166-faucet)
vakond Aug 16, 2021
27d8cba
Use rust-web3 version 0.17 (166-faucet)
vakond Aug 16, 2021
cee8f80
eth_sendRawTransaction (166-faucet)
vakond Aug 16, 2021
b6b34b0
Pass recipient address as string not H160 (166-faucet)
vakond Aug 16, 2021
03518bd
Pass amount as U256 not u64 (166-faucet)
vakond Aug 16, 2021
60625f9
Pass wallet as Address (166-faucet)
vakond Aug 16, 2021
cc7732d
Refactoring (166-faucet)
vakond Aug 16, 2021
399b17c
Include crate web3 into the project (166-faucet)
vakond Aug 17, 2021
d2494f6
Improve error handling (166-faucet)
vakond Aug 17, 2021
4fb0c8d
Improve error handling (166-faucet)
vakond Aug 17, 2021
f1f18ce
Improve error handling (166-faucet)
vakond Aug 18, 2021
5cd48ec
Improve error handling (166-faucet)
vakond Aug 18, 2021
2a75e80
Improve error handling (166-faucet)
vakond Aug 18, 2021
9630a04
Log all eth_* requests (166-faucet)
vakond Aug 18, 2021
17f7110
Improve error handling (166-faucet)
vakond Aug 18, 2021
76daef5
Improve error handling (166-faucet)
vakond Aug 18, 2021
1b16af5
Add parameter --workers (166-faucet)
vakond Aug 18, 2021
8457526
Refactoring (166-faucet)
vakond Aug 18, 2021
6db96c7
Temporarily off Eth (166-faucet)
vakond Aug 20, 2021
1da072c
Setup CORS (166-faucet)
vakond Aug 20, 2021
e8f6b1b
Add logging (166-faucet)
vakond Aug 20, 2021
9fc1445
Adjust CORS settings (166-faucet)
vakond Aug 22, 2021
e0957bb
Show version in log (166-faucet)
vakond Aug 23, 2021
f348ec0
Show revision in log (166-faucet)
vakond Aug 23, 2021
da0c103
CORS in config file (166-faucet)
vakond Aug 23, 2021
4051061
Refactoring (166-faucet)
vakond Aug 24, 2021
486ebc2
Merge branch 'develop' into 166-faucet
vakond Aug 25, 2021
10e1ad1
Add module tokens (166-faucet)
vakond Aug 25, 2021
b029c93
Use default decimals=18 (166-faucet)
vakond Aug 25, 2021
0e2511f
Refactoring (166-faucet)
vakond Aug 25, 2021
97f8abc
Implement getting decimals from contracts (166-faucet)
vakond Aug 25, 2021
4ecd195
Use env vars for config (166-faucet)
vakond Aug 26, 2021
e00af6c
Refactoring (166-faucet)
vakond Aug 27, 2021
135b7d6
Add build of faucet (166-faucet)
vakond Aug 27, 2021
bf8d816
Debugging CI (166-faucet)
vakond Aug 27, 2021
b1972c5
Remove general settings (166-faucet)
vakond Aug 27, 2021
f54f2cc
Env vars for all settings (166-faucet)
vakond Aug 27, 2021
f8f4d3f
Delete docker directory (166-faucet)
vakond Aug 27, 2021
4a94a41
Show revision as unknown if no git metadata (166-faucet)
vakond Aug 27, 2021
ba074ae
Refactoring (166-faucet)
vakond Aug 28, 2021
2f3082a
Add unit test (166-faucet)
vakond Aug 29, 2021
c46febd
Refactoring (166-faucet)
vakond Aug 30, 2021
3e7b5b8
Add handler for eth token (166-faucet)
vakond Aug 30, 2021
af0f2f9
Add settings for eth token (166-faucet)
vakond Aug 31, 2021
10e1e4a
Merge branch 'develop' into 166-faucet
vakond Aug 31, 2021
70441d6
Refactoring (166-faucet)
vakond Aug 31, 2021
72dc802
Add max_limit (166-faucet)
vakond Aug 31, 2021
d31a7ae
Add connection to Solana (166-faucet)
vakond Aug 31, 2021
504196b
Try get_token_account (166-faucet)
vakond Aug 31, 2021
9604dff
Try create_associated_token_account (166-faucet)
vakond Aug 31, 2021
fb47f39
Add spl_token::instruction::transfer_checked (166-faucet)
vakond Aug 31, 2021
3533089
Bump version to 0.2.0 (166-faucet)
vakond Sep 1, 2021
3999a2a
Merge branch 'develop' into 166-faucet
vakond Sep 1, 2021
92b6b67
Use make_solana_program_address from cli (166-faucet)
vakond Sep 1, 2021
9e3b790
Add operator_key (166-faucet)
vakond Sep 1, 2021
dc3d7a3
Use operator_key (166-faucet)
vakond Sep 1, 2021
a49b92e
No need for private key of token owner (166-faucet)
vakond Sep 1, 2021
b4ca6b5
Refactoring (166-faucet)
vakond Sep 1, 2021
f3f413e
Get back standard gasPrice -> '0x...' (166-faucet)
vakond Sep 1, 2021
49a5e9c
Refactoring (166-faucet)
vakond Sep 2, 2021
612a6ab
Refactoring (166-faucet)
vakond Sep 2, 2021
24a43e3
Obfuscate private keys (166-faucet)
vakond Sep 2, 2021
b36d28a
Transfer checked (166-faucet)
vakond Sep 2, 2021
aac5b84
Create ether account if needed (166-faucet)
vakond Sep 2, 2021
81639e6
Refactoring (166-faucet)
vakond Sep 2, 2021
f8b21d8
Take decimals into consideration (166-faucet)
vakond Sep 2, 2021
a23c76a
Take decimals into consideration (166-faucet)
vakond Sep 2, 2021
28d08c8
Refactoring (166-faucet)
vakond Sep 2, 2021
5ecb5f4
Refactoring (166-faucet)
vakond Sep 3, 2021
60f8569
Use serde(deny_unknown_fields) (166-faucet)
vakond Sep 3, 2021
dd74dd4
Obfuscate also public addresses (166-faucet)
vakond Sep 3, 2021
d1c76bf
Refactoring (166-faucet)
vakond Sep 3, 2021
c0a6c28
Use tokio spawn_blocking instead of std thread spawn (166-faucet)
vakond Sep 3, 2021
e4d6b77
Fix amount scaling calculation (166-faucet)
vakond Sep 3, 2021
1092d92
Refactoring (166-faucet)
vakond Sep 6, 2021
eef35a1
Merge branch 'develop' into 166-faucet
vakond Sep 13, 2021
cdd3282
Can disable subservices (166-faucet)
vakond Sep 14, 2021
90607a5
Read keypair from another file (166-faucet)
vakond Sep 14, 2021
17e7d4a
Refactoring (166-faucet)
vakond Sep 14, 2021
82d208b
Refactoring (166-faucet)
vakond Sep 14, 2021
9a200af
Refactoring (166-faucet)
vakond Sep 14, 2021
e54bc23
Introduce config option token_mint (166-faucet)
vakond Sep 21, 2021
1cb6458
Introduce config option token_mint_decimals (166-faucet)
vakond Sep 21, 2021
ee0fc81
Use config option token_mint (166-faucet)
vakond Sep 21, 2021
0892648
Adjust comments (166-faucet)
vakond Sep 22, 2021
cb3d255
Refactoring (166-faucet)
vakond Sep 22, 2021
8f9ab39
Handle request stop (166-faucet)
vakond Sep 22, 2021
3e44ee2
Improve error handling (166-faucet)
vakond Sep 23, 2021
e415f15
Check tokens lazily (166-faucet)
vakond Sep 23, 2021
6f41ad2
Refactoring (166-faucet)
vakond Sep 23, 2021
f7242e6
Refactoring (166-faucet)
vakond Sep 23, 2021
78e272c
Use public version web3 0.17 (166-faucet)
vakond Sep 24, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ steps:
- label: ":docker: build proxy docker image"
trigger: "neon-proxy"
build:
branch: "${PROXY_BRANCH:-develop}"
branch: "166-faucet"
env:
EVM_LOADER_REVISION: "${BUILDKITE_COMMIT}"
EVM_LOADER_BRANCH: "${EVM_LOADER_BRANCH}"
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ node_modules
hfuzz_target
hfuzz_workspace
**/*.so
**/*.lock
6 changes: 5 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Install BPF SDK
FROM solanalabs/rust:1.53.0 AS builder
FROM solanalabs/rust:1.54.0 AS builder
RUN rustup component add clippy
WORKDIR /opt
RUN sh -c "$(curl -sSfL https://release.solana.com/v1.7.9/install)" && \
Expand All @@ -20,6 +20,9 @@ RUN cargo build --release
WORKDIR /opt/evm_loader/performance/sender
RUN cargo clippy
RUN cargo build --release
WORKDIR /opt/evm_loader/faucet
RUN cargo clippy --release
RUN cargo build --release

# Download and build spl-token
FROM builder AS spl-token-builder
Expand Down Expand Up @@ -62,6 +65,7 @@ COPY --from=solana /opt/solana/bin/solana /opt/solana/bin/solana-keygen /opt/sol
COPY --from=evm-loader-builder /opt/evm_loader/program/target/deploy/evm_loader.so /opt/
COPY --from=evm-loader-builder /opt/evm_loader/cli/target/release/neon-cli /opt/
COPY --from=evm-loader-builder /opt/evm_loader/performance/sender/target/release/sender /opt/
COPY --from=evm-loader-builder /opt/evm_loader/faucet/target/release/faucet /opt/
COPY --from=spl-token-builder /opt/spl-token /opt/
COPY --from=contracts /opt/ /opt/solidity/
COPY --from=contracts /usr/bin/solc /usr/bin/solc
Expand Down
37 changes: 37 additions & 0 deletions evm_loader/faucet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[package]
name = "faucet"
description = "Ethereum ERC20 Token Faucet Service"
authors = ["NeonLabs Maintainers <[email protected]>"]
repository = "https://github.com/neonlabsorg/neon-evm/evm_loader/faucet"
version = "0.2.2"
build = "build.rs"
edition = "2018"

[dependencies]
actix-cors = { version = "0.6.0-beta.2", default-features = false }
actix-web = { version = "4.0.0-beta.9", default-features = false }
color-eyre = "0.5"
derive-new = "0.5"
ed25519-dalek = "1.0"
evm-loader = { path = "../program", default_features = false, features = ["no-entrypoint"] }
hex = "0.4"
lazy_static = "1.4"
nix = "0.22"
num_cpus = "1.13"
secp256k1 = "0.20"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
solana-client = "=1.7.10"
solana-sdk = "=1.7.10"
spl-associated-token-account = { version = "1.0", default_features = false, features = ["no-entrypoint"] }
spl-token = { version = "3.2", default_features = false, features = ["no-entrypoint"] }
structopt = "0.3"
thiserror = "1.0"
tokio = { version = "1.10", default_features = false, features = ["rt"] }
toml = "0.5"
tracing = "0.1"
tracing-subscriber = "0.2"
web3 = { path = "web3" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we can't use web3 package from the rust repository?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was because of gasPrice. I started with the public version of web3, of course, but had to modify it to support non-standard result of the proxy's gasPrice at that time. Probably we should try to return to the public version of web3 crate.


[build-dependencies]
vergen = { version = "5.1", default-features = false, features = ["git"] }
3 changes: 3 additions & 0 deletions evm_loader/faucet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ERC20 Token Faucet (Airdrop)

ERC20 Token Faucet is a service which performs airdrop of tokens on user request.
5 changes: 5 additions & 0 deletions evm_loader/faucet/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use vergen::{vergen, Config};

fn main() {
vergen(Config::default()).ok();
}
1 change: 1 addition & 0 deletions evm_loader/faucet/erc20/ERC20.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenOwner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"_totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"remaining","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"}],"name":"safeAdd","outputs":[{"internalType":"uint256","name":"c","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"}],"name":"safeSub","outputs":[{"internalType":"uint256","name":"c","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
111 changes: 111 additions & 0 deletions evm_loader/faucet/erc20/ERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
// ----------------------------------------------------------------------------
// Safe maths
// ----------------------------------------------------------------------------
contract SafeMath {
function safeAdd(uint a, uint b) public pure returns (uint c) {
c = a + b;
require(c >= a);
}
function safeSub(uint a, uint b) public pure returns (uint c) {
require(b <= a);
c = a - b;
}
}
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
// ----------------------------------------------------------------------------
abstract contract ERC20Interface {
function totalSupply() virtual public view returns (uint);
function balanceOf(address tokenOwner) virtual public view returns (uint balance);
function allowance(address tokenOwner, address spender) virtual public view returns (uint remaining);
function transfer(address to, uint tokens) virtual public returns (bool success);
function approve(address spender, uint tokens) virtual public returns (bool success);
function transferFrom(address from, address to, uint tokens) virtual public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals
// assisted token transfers
// ----------------------------------------------------------------------------
contract TestToken is ERC20Interface, SafeMath {
string public symbol;
string public name;
uint8 public decimals;
uint public _totalSupply;
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
constructor() {
symbol = "TST";
name = "TestToken";
decimals = 18;
_totalSupply = 10000000000000000000000000000;
balances[msg.sender] = _totalSupply;
emit Transfer(address(0), msg.sender, _totalSupply);
}
// ------------------------------------------------------------------------
// Total supply
// ------------------------------------------------------------------------
function totalSupply() public override view returns (uint) {
return _totalSupply - balances[address(0)];
}
// ------------------------------------------------------------------------
// Get the token balance for account tokenOwner
// ------------------------------------------------------------------------
function balanceOf(address tokenOwner) public override view returns (uint balance) {
return balances[tokenOwner];
}
// ------------------------------------------------------------------------
// Transfer the balance from token owner's account to receiver account
// - Owner's account must have sufficient balance to transfer
// - 0 value transfers are allowed
// ------------------------------------------------------------------------
function transfer(address receiver, uint tokens) public override returns (bool success) {
balances[msg.sender] = safeSub(balances[msg.sender], tokens);
balances[receiver] = safeAdd(balances[receiver], tokens);
emit Transfer(msg.sender, receiver, tokens);
return true;
}
// ------------------------------------------------------------------------
// Token owner can approve for spender to transferFrom(...) tokens
// from the token owner's account
//
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
// recommends that there are no checks for the approval double-spend attack
// as this should be implemented in user interfaces
// ------------------------------------------------------------------------
function approve(address spender, uint tokens) public override returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
return true;
}
// ------------------------------------------------------------------------
// Transfer tokens from sender account to receiver account
//
// The calling account must already have sufficient tokens approve(...)-d
// for spending from sender account and
// - From account must have sufficient balance to transfer
// - Spender must have sufficient allowance to transfer
// - 0 value transfers are allowed
// ------------------------------------------------------------------------
function transferFrom(address sender, address receiver, uint tokens) public override returns (bool success) {
balances[sender] = safeSub(balances[sender], tokens);
allowed[sender][msg.sender] = safeSub(allowed[sender][msg.sender], tokens);
balances[receiver] = safeAdd(balances[receiver], tokens);
emit Transfer(sender, receiver, tokens);
return true;
}
// ------------------------------------------------------------------------
// Returns the amount of tokens approved by the owner that can be
// transferred to the spender's account
// ------------------------------------------------------------------------
function allowance(address tokenOwner, address spender) public override view returns (uint remaining) {
return allowed[tokenOwner][spender];
}
}
22 changes: 22 additions & 0 deletions evm_loader/faucet/faucet.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Neon Token Faucet Service Config

[rpc]
port = 3333
allowed_origins = ["http://localhost"]

[web3]
enable = true
rpc_url = "http://localhost:9090/solana"
private_key = "0x0000000000000000000000000000000000000000000000000000000000000Ace"
tokens = ["0x00000000000000000000000000000000CafeBabe",
"0x00000000000000000000000000000000DeadBeef"]
max_amount = 1000

[solana]
enable = true
url = "http://localhost:8899"
operator_keyfile = "operator_id.json"
evm_loader = "EvmLoaderId11111111111111111111111111111111"
token_mint = "TokenMintId11111111111111111111111111111111"
token_mint_decimals = 9
max_amount = 10
54 changes: 54 additions & 0 deletions evm_loader/faucet/src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//! Faucet options parser.

use crate::config;
use std::path::PathBuf;
use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(about = "NeonLabs Token Faucet Service")]
pub struct Application {
#[structopt(
parse(from_os_str),
short,
long,
default_value = &config::DEFAULT_CONFIG,
help = "Path to the config file"
)]
pub config: PathBuf,

#[structopt(subcommand)]
pub cmd: Command,
}

#[derive(StructOpt)]
pub enum Command {
#[structopt(about = "Shows config")]
Config {
#[structopt(
parse(from_os_str),
short,
long,
default_value = &config::DEFAULT_CONFIG,
help = "Path to the config file"
)]
file: PathBuf,
},

#[structopt(about = "Shows environment variables")]
Env {},

#[structopt(about = "Starts listening for requests")]
Run {
#[structopt(
long,
default_value = &config::AUTO,
help = "Number of listening workers"
)]
workers: String,
},
}

/// Constructs instance of Application.
pub fn application() -> Application {
Application::from_args()
}
Loading