Skip to content

Commit 6ca1d4d

Browse files
committed
Revert "feat(LRAPI): add 1inch classic swap rpc (#2222)"
This reverts commit 8f83308
1 parent 53b6d2b commit 6ca1d4d

File tree

23 files changed

+72
-1409
lines changed

23 files changed

+72
-1409
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ members = [
3939
"mm2src/proxy_signature",
4040
"mm2src/rpc_task",
4141
"mm2src/trezor",
42-
"mm2src/trading_api",
4342
]
4443

4544
exclude = [

mm2src/coins/eth.rs

+23-18
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,20 @@ pub type Web3RpcFut<T> = Box<dyn Future<Item = T, Error = MmError<Web3RpcError>>
524524
pub type Web3RpcResult<T> = Result<T, MmError<Web3RpcError>>;
525525
type EthPrivKeyPolicy = PrivKeyPolicy<KeyPair>;
526526

527+
#[macro_export]
528+
macro_rules! wei_from_gwei_decimal {
529+
($big_decimal: expr) => {
530+
$crate::eth::wei_from_big_decimal($big_decimal, $crate::eth::ETH_GWEI_DECIMALS)
531+
};
532+
}
533+
534+
#[macro_export]
535+
macro_rules! wei_to_gwei_decimal {
536+
($gwei: expr) => {
537+
$crate::eth::u256_to_big_decimal($gwei, $crate::eth::ETH_GWEI_DECIMALS)
538+
};
539+
}
540+
527541
#[derive(Clone, Debug)]
528542
pub(crate) struct LegacyGasPrice {
529543
pub(crate) gas_price: U256,
@@ -568,11 +582,11 @@ impl TryFrom<PayForGasParams> for PayForGasOption {
568582
fn try_from(param: PayForGasParams) -> Result<Self, Self::Error> {
569583
match param {
570584
PayForGasParams::Legacy(legacy) => Ok(Self::Legacy(LegacyGasPrice {
571-
gas_price: wei_from_gwei_decimal(&legacy.gas_price)?,
585+
gas_price: wei_from_gwei_decimal!(&legacy.gas_price)?,
572586
})),
573587
PayForGasParams::Eip1559(eip1559) => Ok(Self::Eip1559(Eip1559FeePerGas {
574-
max_fee_per_gas: wei_from_gwei_decimal(&eip1559.max_fee_per_gas)?,
575-
max_priority_fee_per_gas: wei_from_gwei_decimal(&eip1559.max_priority_fee_per_gas)?,
588+
max_fee_per_gas: wei_from_gwei_decimal!(&eip1559.max_fee_per_gas)?,
589+
max_priority_fee_per_gas: wei_from_gwei_decimal!(&eip1559.max_priority_fee_per_gas)?,
576590
})),
577591
}
578592
}
@@ -1068,9 +1082,6 @@ impl EthCoinImpl {
10681082
let guard = self.erc20_tokens_infos.lock().unwrap();
10691083
(*guard).clone()
10701084
}
1071-
1072-
#[inline(always)]
1073-
pub fn chain_id(&self) -> u64 { self.chain_id }
10741085
}
10751086

10761087
async fn get_raw_transaction_impl(coin: EthCoin, req: RawTransactionRequest) -> RawTransactionResult {
@@ -1193,8 +1204,8 @@ pub async fn withdraw_erc1155(ctx: MmArc, withdraw_type: WithdrawErc1155) -> Wit
11931204
let fee_details = EthTxFeeDetails::new(gas, pay_for_gas_option, fee_coin)?;
11941205

11951206
Ok(TransactionNftDetails {
1196-
tx_hex: BytesJson::from(signed_bytes.to_vec()), // TODO: should we return tx_hex 0x-prefixed (everywhere)?
1197-
tx_hash: format!("{:02x}", signed.tx_hash_as_bytes()), // TODO: add 0x hash (use unified hash format for eth wherever it is returned)
1207+
tx_hex: BytesJson::from(signed_bytes.to_vec()),
1208+
tx_hash: format!("{:02x}", signed.tx_hash_as_bytes()),
11981209
from: vec![eth_coin.my_address()?],
11991210
to: vec![withdraw_type.to],
12001211
contract_type: ContractType::Erc1155,
@@ -1285,7 +1296,7 @@ pub async fn withdraw_erc721(ctx: MmArc, withdraw_type: WithdrawErc721) -> Withd
12851296

12861297
Ok(TransactionNftDetails {
12871298
tx_hex: BytesJson::from(signed_bytes.to_vec()),
1288-
tx_hash: format!("{:02x}", signed.tx_hash_as_bytes()), // TODO: add 0x hash (use unified hash format for eth wherever it is returned)
1299+
tx_hash: format!("{:02x}", signed.tx_hash_as_bytes()),
12891300
from: vec![eth_coin.my_address()?],
12901301
to: vec![withdraw_type.to],
12911302
contract_type: ContractType::Erc721,
@@ -2445,7 +2456,7 @@ impl MarketCoinOps for EthCoin {
24452456
let fut = async move {
24462457
coin.send_raw_transaction(bytes.into())
24472458
.await
2448-
.map(|res| format!("{:02x}", res)) // TODO: add 0x hash (use unified hash format for eth wherever it is returned)
2459+
.map(|res| format!("{:02x}", res))
24492460
.map_err(|e| ERRL!("{}", e))
24502461
};
24512462

@@ -4751,7 +4762,7 @@ impl EthCoin {
47514762
self.call(request, Some(BlockId::Number(BlockNumber::Latest))).await
47524763
}
47534764

4754-
pub fn allowance(&self, spender: Address) -> Web3RpcFut<U256> {
4765+
fn allowance(&self, spender: Address) -> Web3RpcFut<U256> {
47554766
let coin = self.clone();
47564767
let fut = async move {
47574768
match coin.coin_type {
@@ -4816,7 +4827,7 @@ impl EthCoin {
48164827
Box::new(fut.boxed().compat())
48174828
}
48184829

4819-
pub fn approve(&self, spender: Address, amount: U256) -> EthTxFut {
4830+
fn approve(&self, spender: Address, amount: U256) -> EthTxFut {
48204831
let coin = self.clone();
48214832
let fut = async move {
48224833
let token_addr = match coin.coin_type {
@@ -6183,12 +6194,6 @@ pub fn wei_from_big_decimal(amount: &BigDecimal, decimals: u8) -> NumConversResu
61836194
U256::from_dec_str(&amount).map_to_mm(|e| NumConversError::new(format!("{:?}", e)))
61846195
}
61856196

6186-
pub fn wei_from_gwei_decimal(bigdec: &BigDecimal) -> NumConversResult<U256> {
6187-
wei_from_big_decimal(bigdec, ETH_GWEI_DECIMALS)
6188-
}
6189-
6190-
pub fn wei_to_gwei_decimal(wei: U256) -> NumConversResult<BigDecimal> { u256_to_big_decimal(wei, ETH_GWEI_DECIMALS) }
6191-
61926197
impl Transaction for SignedEthTx {
61936198
fn tx_hex(&self) -> Vec<u8> { rlp::encode(self).to_vec() }
61946199

mm2src/coins/eth/eip1559_gas_fee.rs

+26-26
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Provides estimations of base and priority fee per gas or fetch estimations from a gas api provider
22
33
use super::web3_transport::FeeHistoryResult;
4-
use super::{wei_from_gwei_decimal, wei_to_gwei_decimal, Web3RpcError, Web3RpcResult};
5-
use crate::{EthCoin, NumConversError};
4+
use super::{Web3RpcError, Web3RpcResult};
5+
use crate::{wei_from_gwei_decimal, wei_to_gwei_decimal, EthCoin, NumConversError};
66
use ethereum_types::U256;
77
use mm2_err_handle::mm_error::MmError;
88
use mm2_err_handle::or_mm_error::OrMmError;
@@ -104,24 +104,24 @@ impl TryFrom<InfuraFeePerGas> for FeePerGasEstimated {
104104

105105
fn try_from(infura_fees: InfuraFeePerGas) -> Result<Self, Self::Error> {
106106
Ok(Self {
107-
base_fee: wei_from_gwei_decimal(&infura_fees.estimated_base_fee)?,
107+
base_fee: wei_from_gwei_decimal!(&infura_fees.estimated_base_fee)?,
108108
low: FeePerGasLevel {
109-
max_fee_per_gas: wei_from_gwei_decimal(&infura_fees.low.suggested_max_fee_per_gas)?,
110-
max_priority_fee_per_gas: wei_from_gwei_decimal(&infura_fees.low.suggested_max_priority_fee_per_gas)?,
109+
max_fee_per_gas: wei_from_gwei_decimal!(&infura_fees.low.suggested_max_fee_per_gas)?,
110+
max_priority_fee_per_gas: wei_from_gwei_decimal!(&infura_fees.low.suggested_max_priority_fee_per_gas)?,
111111
min_wait_time: Some(infura_fees.low.min_wait_time_estimate),
112112
max_wait_time: Some(infura_fees.low.max_wait_time_estimate),
113113
},
114114
medium: FeePerGasLevel {
115-
max_fee_per_gas: wei_from_gwei_decimal(&infura_fees.medium.suggested_max_fee_per_gas)?,
116-
max_priority_fee_per_gas: wei_from_gwei_decimal(
117-
&infura_fees.medium.suggested_max_priority_fee_per_gas,
115+
max_fee_per_gas: wei_from_gwei_decimal!(&infura_fees.medium.suggested_max_fee_per_gas)?,
116+
max_priority_fee_per_gas: wei_from_gwei_decimal!(
117+
&infura_fees.medium.suggested_max_priority_fee_per_gas
118118
)?,
119119
min_wait_time: Some(infura_fees.medium.min_wait_time_estimate),
120120
max_wait_time: Some(infura_fees.medium.max_wait_time_estimate),
121121
},
122122
high: FeePerGasLevel {
123-
max_fee_per_gas: wei_from_gwei_decimal(&infura_fees.high.suggested_max_fee_per_gas)?,
124-
max_priority_fee_per_gas: wei_from_gwei_decimal(&infura_fees.high.suggested_max_priority_fee_per_gas)?,
123+
max_fee_per_gas: wei_from_gwei_decimal!(&infura_fees.high.suggested_max_fee_per_gas)?,
124+
max_priority_fee_per_gas: wei_from_gwei_decimal!(&infura_fees.high.suggested_max_priority_fee_per_gas)?,
125125
min_wait_time: Some(infura_fees.high.min_wait_time_estimate),
126126
max_wait_time: Some(infura_fees.high.max_wait_time_estimate),
127127
},
@@ -143,33 +143,33 @@ impl TryFrom<BlocknativeBlockPricesResponse> for FeePerGasEstimated {
143143
return Ok(FeePerGasEstimated::default());
144144
}
145145
Ok(Self {
146-
base_fee: wei_from_gwei_decimal(&block_prices.block_prices[0].base_fee_per_gas)?,
146+
base_fee: wei_from_gwei_decimal!(&block_prices.block_prices[0].base_fee_per_gas)?,
147147
low: FeePerGasLevel {
148-
max_fee_per_gas: wei_from_gwei_decimal(
149-
&block_prices.block_prices[0].estimated_prices[2].max_fee_per_gas,
148+
max_fee_per_gas: wei_from_gwei_decimal!(
149+
&block_prices.block_prices[0].estimated_prices[2].max_fee_per_gas
150150
)?,
151-
max_priority_fee_per_gas: wei_from_gwei_decimal(
152-
&block_prices.block_prices[0].estimated_prices[2].max_priority_fee_per_gas,
151+
max_priority_fee_per_gas: wei_from_gwei_decimal!(
152+
&block_prices.block_prices[0].estimated_prices[2].max_priority_fee_per_gas
153153
)?,
154154
min_wait_time: None,
155155
max_wait_time: None,
156156
},
157157
medium: FeePerGasLevel {
158-
max_fee_per_gas: wei_from_gwei_decimal(
159-
&block_prices.block_prices[0].estimated_prices[1].max_fee_per_gas,
158+
max_fee_per_gas: wei_from_gwei_decimal!(
159+
&block_prices.block_prices[0].estimated_prices[1].max_fee_per_gas
160160
)?,
161-
max_priority_fee_per_gas: wei_from_gwei_decimal(
162-
&block_prices.block_prices[0].estimated_prices[1].max_priority_fee_per_gas,
161+
max_priority_fee_per_gas: wei_from_gwei_decimal!(
162+
&block_prices.block_prices[0].estimated_prices[1].max_priority_fee_per_gas
163163
)?,
164164
min_wait_time: None,
165165
max_wait_time: None,
166166
},
167167
high: FeePerGasLevel {
168-
max_fee_per_gas: wei_from_gwei_decimal(
169-
&block_prices.block_prices[0].estimated_prices[0].max_fee_per_gas,
168+
max_fee_per_gas: wei_from_gwei_decimal!(
169+
&block_prices.block_prices[0].estimated_prices[0].max_fee_per_gas
170170
)?,
171-
max_priority_fee_per_gas: wei_from_gwei_decimal(
172-
&block_prices.block_prices[0].estimated_prices[0].max_priority_fee_per_gas,
171+
max_priority_fee_per_gas: wei_from_gwei_decimal!(
172+
&block_prices.block_prices[0].estimated_prices[0].max_priority_fee_per_gas
173173
)?,
174174
min_wait_time: None,
175175
max_wait_time: None,
@@ -260,7 +260,7 @@ impl FeePerGasSimpleEstimator {
260260
let max_priority_fee_per_gas = Self::percentile_of(&level_rewards, Self::PRIORITY_FEE_PERCENTILES[level_index]);
261261
// Convert the priority fee to BigDecimal gwei, falling back to 0 on error.
262262
let max_priority_fee_per_gas_gwei =
263-
wei_to_gwei_decimal(max_priority_fee_per_gas).unwrap_or_else(|_| BigDecimal::from(0));
263+
wei_to_gwei_decimal!(max_priority_fee_per_gas).unwrap_or_else(|_| BigDecimal::from(0));
264264

265265
// Calculate the max fee per gas by adjusting the base fee and adding the priority fee.
266266
let adjust_max_fee =
@@ -273,7 +273,7 @@ impl FeePerGasSimpleEstimator {
273273

274274
Ok(FeePerGasLevel {
275275
max_priority_fee_per_gas,
276-
max_fee_per_gas: wei_from_gwei_decimal(&max_fee_per_gas_dec)?,
276+
max_fee_per_gas: wei_from_gwei_decimal!(&max_fee_per_gas_dec)?,
277277
// TODO: Consider adding default wait times if applicable (and mark them as uncertain).
278278
min_wait_time: None,
279279
max_wait_time: None,
@@ -290,7 +290,7 @@ impl FeePerGasSimpleEstimator {
290290
.first()
291291
.cloned()
292292
.unwrap_or_else(|| U256::from(0));
293-
let latest_base_fee_dec = wei_to_gwei_decimal(latest_base_fee).unwrap_or_else(|_| BigDecimal::from(0));
293+
let latest_base_fee_dec = wei_to_gwei_decimal!(latest_base_fee).unwrap_or_else(|_| BigDecimal::from(0));
294294

295295
// The predicted base fee is not used for calculating eip1559 values here and is provided for other purposes
296296
// (f.e if the caller would like to do own estimates of max fee and max priority fee)

mm2src/coins/eth/eth_rpc.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,8 @@ impl EthCoin {
241241
.and_then(|t| serde_json::from_value(t).map_err(Into::into))
242242
}
243243

244-
/// Get chain id from network
245-
pub(crate) async fn network_chain_id(&self) -> Result<U256, web3::Error> {
244+
/// Get chain id
245+
pub(crate) async fn chain_id(&self) -> Result<U256, web3::Error> {
246246
self.try_rpc_send("eth_chainId", vec![])
247247
.await
248248
.and_then(|t| serde_json::from_value(t).map_err(Into::into))

mm2src/coins/lp_coins.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,9 @@ pub mod coins_tests;
220220
pub mod eth;
221221
use eth::erc20::get_erc20_ticker_by_contract_address;
222222
use eth::eth_swap_v2::{PaymentStatusErr, PrepareTxDataError, ValidatePaymentV2Err};
223+
use eth::GetValidEthWithdrawAddError;
223224
use eth::{eth_coin_from_conf_and_request, get_eth_address, EthCoin, EthGasDetailsErr, EthTxFeeDetails,
224-
GetEthAddressError, GetValidEthWithdrawAddError, SignedEthTx};
225+
GetEthAddressError, SignedEthTx};
225226

226227
pub mod hd_wallet;
227228
use hd_wallet::{AccountUpdatingError, AddressDerivingError, HDAccountOps, HDAddressId, HDAddressOps, HDCoinAddress,
@@ -660,10 +661,6 @@ impl TransactionErr {
660661
}
661662
}
662663

663-
impl std::fmt::Display for TransactionErr {
664-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.get_plain_text_format()) }
665-
}
666-
667664
#[derive(Debug, PartialEq)]
668665
pub enum FoundSwapTxSpend {
669666
Spent(TransactionEnum),

mm2src/coins/rpc_command/get_estimated_fees.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! RPCs to start/stop gas fee estimator and get estimated base and priority fee per gas
22
3-
use crate::eth::{wei_to_gwei_decimal, EthCoin, EthCoinType, FeeEstimatorContext, FeeEstimatorState, FeePerGasEstimated};
4-
use crate::{lp_coinfind_or_err, AsyncMutex, CoinFindError, MmCoinEnum, NumConversError};
3+
use crate::eth::{EthCoin, EthCoinType, FeeEstimatorContext, FeeEstimatorState, FeePerGasEstimated};
4+
use crate::{lp_coinfind_or_err, wei_to_gwei_decimal, AsyncMutex, CoinFindError, MmCoinEnum, NumConversError};
55
use common::executor::{spawn_abortable, Timer};
66
use common::log::debug;
77
use common::{HttpStatusCode, StatusCode};
@@ -66,22 +66,22 @@ impl TryFrom<FeePerGasEstimated> for FeePerGasEstimatedExt {
6666

6767
fn try_from(fees: FeePerGasEstimated) -> Result<Self, Self::Error> {
6868
Ok(Self {
69-
base_fee: wei_to_gwei_decimal(fees.base_fee)?,
69+
base_fee: wei_to_gwei_decimal!(fees.base_fee)?,
7070
low: FeePerGasLevel {
71-
max_fee_per_gas: wei_to_gwei_decimal(fees.low.max_fee_per_gas)?,
72-
max_priority_fee_per_gas: wei_to_gwei_decimal(fees.low.max_priority_fee_per_gas)?,
71+
max_fee_per_gas: wei_to_gwei_decimal!(fees.low.max_fee_per_gas)?,
72+
max_priority_fee_per_gas: wei_to_gwei_decimal!(fees.low.max_priority_fee_per_gas)?,
7373
min_wait_time: fees.low.min_wait_time,
7474
max_wait_time: fees.low.max_wait_time,
7575
},
7676
medium: FeePerGasLevel {
77-
max_fee_per_gas: wei_to_gwei_decimal(fees.medium.max_fee_per_gas)?,
78-
max_priority_fee_per_gas: wei_to_gwei_decimal(fees.medium.max_priority_fee_per_gas)?,
77+
max_fee_per_gas: wei_to_gwei_decimal!(fees.medium.max_fee_per_gas)?,
78+
max_priority_fee_per_gas: wei_to_gwei_decimal!(fees.medium.max_priority_fee_per_gas)?,
7979
min_wait_time: fees.medium.min_wait_time,
8080
max_wait_time: fees.medium.max_wait_time,
8181
},
8282
high: FeePerGasLevel {
83-
max_fee_per_gas: wei_to_gwei_decimal(fees.high.max_fee_per_gas)?,
84-
max_priority_fee_per_gas: wei_to_gwei_decimal(fees.high.max_priority_fee_per_gas)?,
83+
max_fee_per_gas: wei_to_gwei_decimal!(fees.high.max_fee_per_gas)?,
84+
max_priority_fee_per_gas: wei_to_gwei_decimal!(fees.high.max_priority_fee_per_gas)?,
8585
min_wait_time: fees.high.min_wait_time,
8686
max_wait_time: fees.high.max_wait_time,
8787
},

mm2src/common/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ lazy_static = "1.4"
3535
log = "0.4.17"
3636
parking_lot = { version = "0.12.0", features = ["nightly"] }
3737
parking_lot_core = { version = "0.6", features = ["nightly"] }
38-
paste = "1.0"
3938
primitive-types = "0.11.1"
4039
rand = { version = "0.7", features = ["std", "small_rng"] }
4140
rustc-hash = "2.0"

mm2src/common/common.rs

-32
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ use futures01::{future, Future};
150150
use http::header::CONTENT_TYPE;
151151
use http::Response;
152152
use parking_lot::{Mutex as PaMutex, MutexGuard as PaMutexGuard};
153-
pub use paste::paste;
154153
use rand::RngCore;
155154
use rand::{rngs::SmallRng, SeedableRng};
156155
use serde::{de, ser};
@@ -1138,37 +1137,6 @@ pub fn http_uri_to_ws_address(uri: http::Uri) -> String {
11381137
format!("{}{}{}{}", address_prefix, host_address, port, path)
11391138
}
11401139

1141-
/// If 0x prefix exists in an str strip it or return the str as-is
1142-
#[macro_export]
1143-
macro_rules! str_strip_0x {
1144-
($s: expr) => {
1145-
$s.strip_prefix("0x").unwrap_or($s)
1146-
};
1147-
}
1148-
1149-
/// If value is 'some' push key and value (as string) into an array containing (key, value) elements
1150-
#[macro_export]
1151-
macro_rules! push_if_some {
1152-
($arr: expr, $k: expr, $v: expr) => {
1153-
if let Some(v) = $v {
1154-
$arr.push(($k, v.to_string()))
1155-
}
1156-
};
1157-
}
1158-
1159-
/// Define 'with_...' method to set a parameter with an optional value in a builder
1160-
#[macro_export]
1161-
macro_rules! def_with_opt_param {
1162-
($var: ident, $var_type: ty) => {
1163-
$crate::paste! {
1164-
pub fn [<with_ $var>](&mut self, $var: Option<$var_type>) -> &mut Self {
1165-
self.$var = $var;
1166-
self
1167-
}
1168-
}
1169-
};
1170-
}
1171-
11721140
#[test]
11731141
fn test_http_uri_to_ws_address() {
11741142
let uri = "https://cosmos-rpc.polkachu.com".parse::<http::Uri>().unwrap();

mm2src/mm2_main/Cargo.toml

-3
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,10 @@ mm2_net = { path = "../mm2_net" }
7272
mm2_number = { path = "../mm2_number" }
7373
mm2_rpc = { path = "../mm2_rpc", features = ["rpc_facilities"]}
7474
mm2_state_machine = { path = "../mm2_state_machine" }
75-
trading_api = { path = "../trading_api" }
7675
num-traits = "0.2"
7776
parity-util-mem = "0.11"
7877
parking_lot = { version = "0.12.0", features = ["nightly"] }
7978
primitives = { path = "../mm2_bitcoin/primitives" }
80-
primitive-types = "0.11.1"
8179
prost = "0.12"
8280
rand = { version = "0.7", features = ["std", "small_rng"] }
8381
rand6 = { version = "0.6", package = "rand" }
@@ -129,7 +127,6 @@ coins = { path = "../coins", features = ["for-tests"] }
129127
coins_activation = { path = "../coins_activation", features = ["for-tests"] }
130128
common = { path = "../common", features = ["for-tests"] }
131129
mm2_test_helpers = { path = "../mm2_test_helpers" }
132-
trading_api = { path = "../trading_api", features = ["mocktopus"] }
133130
mocktopus = "0.8.0"
134131
testcontainers = "0.15.0"
135132
web3 = { git = "https://github.com/KomodoPlatform/rust-web3", tag = "v0.20.0", default-features = false, features = ["http-rustls-tls"] }

mm2src/mm2_main/src/ext_api.rs

-3
This file was deleted.

0 commit comments

Comments
 (0)