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

fix(tpu-v2): provide ethcoin support in tpu kickstart process #2300

Open
wants to merge 10 commits into
base: fix-tpu-v2-wait-for-payment-spend
Choose a base branch
from
3 changes: 1 addition & 2 deletions mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1313,8 +1313,7 @@ pub fn init_geth_node() {
thread::sleep(Duration::from_millis(100));
}

let dex_fee_addr = addr_from_raw_pubkey(&DEX_FEE_ADDR_RAW_PUBKEY).unwrap();
let dex_fee_addr = Token::Address(dex_fee_addr);
let dex_fee_addr = Token::Address(GETH_ACCOUNT);
let params = ethabi::encode(&[dex_fee_addr]);
let taker_swap_v2_data = format!("{}{}", TAKER_SWAP_V2_BYTES, hex::encode(params));

Expand Down
146 changes: 136 additions & 10 deletions mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ use coins::{CoinProtocol, CoinWithDerivationMethod, CommonSwapOpsV2, ConfirmPaym
use common::{block_on, block_on_f01, now_sec};
use crypto::Secp256k1Secret;
use ethereum_types::U256;
#[cfg(any(feature = "sepolia-maker-swap-v2-tests", feature = "sepolia-taker-swap-v2-tests"))]
use mm2_core::mm_ctx::MmArc;
use mm2_number::{BigDecimal, BigUint};
use mm2_test_helpers::for_tests::{account_balance, disable_coin, enable_erc20_token_v2, enable_eth_with_tokens_v2,
erc20_dev_conf, eth_dev_conf, get_new_address, get_token_info, nft_dev_conf,
MarketMakerIt, Mm2TestConf};
use mm2_test_helpers::for_tests::{account_balance, active_swaps, coins_needed_for_kickstart, disable_coin,
enable_erc20_token_v2, enable_eth_coin_v2, enable_eth_with_tokens_v2,
erc20_dev_conf, eth1_dev_conf, eth_dev_conf, get_locked_amount, get_new_address,
get_token_info, mm_dump, my_swap_status, nft_dev_conf, start_swaps, MarketMakerIt,
Mm2TestConf, SwapV2TestContracts, TestNode};
#[cfg(any(feature = "sepolia-maker-swap-v2-tests", feature = "sepolia-taker-swap-v2-tests"))]
use mm2_test_helpers::for_tests::{eth_sepolia_conf, sepolia_erc20_dev_conf};
use mm2_test_helpers::structs::{Bip44Chain, EnableCoinBalanceMap, EthWithTokensActivationResult, HDAccountAddressId,
Expand All @@ -43,6 +44,7 @@ use serde_json::Value as Json;
use std::str::FromStr;
use std::thread;
use std::time::Duration;
use uuid::Uuid;
use web3::contract::{Contract, Options};
use web3::ethabi::Token;
#[cfg(any(feature = "sepolia-maker-swap-v2-tests", feature = "sepolia-taker-swap-v2-tests"))]
Expand All @@ -55,6 +57,7 @@ const SEPOLIA_MAKER_PRIV: &str = "6e2f3a6223b928a05a3a3622b0c3f3573d03663b704a61
const SEPOLIA_TAKER_PRIV: &str = "e0be82dca60ff7e4c6d6db339ac9e1ae249af081dba2110bddd281e711608f16";
const NFT_ETH: &str = "NFT_ETH";
const ETH: &str = "ETH";
const ETH1: &str = "ETH1";

#[cfg(any(feature = "sepolia-maker-swap-v2-tests", feature = "sepolia-taker-swap-v2-tests"))]
const ERC20: &str = "ERC20DEV";
Expand Down Expand Up @@ -1427,15 +1430,16 @@ impl SwapAddresses {
}
}

#[allow(dead_code)]
/// Needed for eth or erc20 v2 activation in Geth tests
fn eth_coin_v2_activation_with_random_privkey(
ctx: &MmArc,
ticker: &str,
conf: &Json,
swap_addr: SwapAddresses,
erc20: bool,
) -> EthCoin {
let build_policy = EthPrivKeyBuildPolicy::IguanaPrivKey(random_secp256k1_secret());
) -> (EthCoin, Secp256k1Secret) {
let priv_key = random_secp256k1_secret();
let build_policy = EthPrivKeyBuildPolicy::IguanaPrivKey(priv_key);
let node = EthNode {
url: GETH_RPC_URL.to_string(),
komodo_proxy: false,
Expand All @@ -1455,7 +1459,7 @@ fn eth_coin_v2_activation_with_random_privkey(
gap_limit: None,
};
let coin = block_on(eth_coin_from_conf_and_request_v2(
&MM_CTX1,
ctx,
ticker,
conf,
platform_request,
Expand All @@ -1471,9 +1475,9 @@ fn eth_coin_v2_activation_with_random_privkey(
token_addr: erc20_contract(),
};
let coin = block_on(coin.set_coin_type(coin_type));
return coin;
return (coin, priv_key);
}
coin
(coin, priv_key)
}

#[cfg(feature = "sepolia-taker-swap-v2-tests")]
Expand Down Expand Up @@ -2749,3 +2753,125 @@ fn test_enable_custom_erc20_with_duplicate_contract_in_config() {
// Disable the custom token, this to check that it was enabled correctly
block_on(disable_coin(&mm_hd, &config_ticker, true));
}

#[test]
fn test_v2_eth_eth_kickstart() {
// Initialize swap addresses and configurations
let swap_addresses = SwapAddresses::init();
let contracts = SwapV2TestContracts {
maker_swap_v2_contract: eth_addr_to_hex(&swap_addresses.swap_v2_contracts.maker_swap_v2_contract),
taker_swap_v2_contract: eth_addr_to_hex(&swap_addresses.swap_v2_contracts.taker_swap_v2_contract),
nft_maker_swap_v2_contract: eth_addr_to_hex(&swap_addresses.swap_v2_contracts.nft_maker_swap_v2_contract),
};
let swap_contract_address = eth_addr_to_hex(&swap_addresses.swap_contract_address);
let node = TestNode {
url: GETH_RPC_URL.to_string(),
};

// Helper function for activating coins
let enable_coins = |mm: &MarketMakerIt, coins: &[&str]| {
for &coin in coins {
log!(
"{:?}",
block_on(enable_eth_coin_v2(
mm,
coin,
&swap_contract_address,
contracts.clone(),
None,
&[node.clone()]
))
);
}
};

// start Bob and Alice
let (_, bob_priv_key) =
eth_coin_v2_activation_with_random_privkey(&MM_CTX, ETH, &eth_dev_conf(), swap_addresses, false);
let (_, alice_priv_key) =
eth_coin_v2_activation_with_random_privkey(&MM_CTX1, ETH1, &eth1_dev_conf(), swap_addresses, false);
let coins = json!([eth_dev_conf(), eth1_dev_conf()]);

let mut bob_conf = Mm2TestConf::seednode_trade_v2(&format!("0x{}", hex::encode(bob_priv_key)), &coins);
let mut mm_bob = MarketMakerIt::start(bob_conf.conf.clone(), bob_conf.rpc_password.clone(), None).unwrap();
let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path);
log!("Bob log path: {}", mm_bob.log_path.display());

let mut alice_conf =
Mm2TestConf::light_node_trade_v2(&format!("0x{}", hex::encode(alice_priv_key)), &coins, &[&mm_bob
.ip
.to_string()]);
let mut mm_alice = MarketMakerIt::start(alice_conf.conf.clone(), alice_conf.rpc_password.clone(), None).unwrap();
let (_alice_dump_log, _alice_dump_dashboard) = mm_dump(&mm_alice.log_path);
log!("Alice log path: {}", mm_alice.log_path.display());

// Enable ETH and ETH1 for both Bob and Alice
enable_coins(&mm_bob, &[ETH, ETH1]);
enable_coins(&mm_alice, &[ETH, ETH1]);

let uuids = block_on(start_swaps(&mut mm_bob, &mut mm_alice, &[(ETH, ETH1)], 1.0, 1.0, 77.));
log!("{:?}", uuids);
let parsed_uuids: Vec<Uuid> = uuids.iter().map(|u| u.parse().unwrap()).collect();

for uuid in uuids.iter() {
log_swap_status_before_stop(&mm_bob, uuid, "Maker");
log_swap_status_before_stop(&mm_alice, uuid, "Taker");
}
Comment on lines +2812 to +2819
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: uuids is just a single item in a vector. you might want to extract it.


block_on(mm_bob.stop()).unwrap();
block_on(mm_alice.stop()).unwrap();

// Restart Bob and Alice
bob_conf.conf["dbdir"] = mm_bob.folder.join("DB").to_str().unwrap().into();
bob_conf.conf["log"] = mm_bob.folder.join("mm2_dup.log").to_str().unwrap().into();
Comment on lines +2824 to +2826
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: or you might just use MarketMakerIt::seednode_trade_v2


let mm_bob = MarketMakerIt::start(bob_conf.conf, bob_conf.rpc_password, None).unwrap();
let (_bob_dump_log, _bob_dump_dashboard) = mm_dump(&mm_bob.log_path);
log!("Bob log path: {}", mm_bob.log_path.display());

alice_conf.conf["dbdir"] = mm_alice.folder.join("DB").to_str().unwrap().into();
alice_conf.conf["log"] = mm_alice.folder.join("mm2_dup.log").to_str().unwrap().into();
alice_conf.conf["seednodes"] = vec![mm_bob.ip.to_string()].into();
Comment on lines +2832 to +2834
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: or MarketMakerIt::light_node_trade_v2

Copy link
Collaborator

Choose a reason for hiding this comment

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

btw, why create a different mm2_dup.log? u could not call mm_dump if u want.


let mm_alice = MarketMakerIt::start(alice_conf.conf, alice_conf.rpc_password, None).unwrap();
let (_alice_dump_log, _alice_dump_dashboard) = mm_dump(&mm_alice.log_path);
log!("Alice log path: {}", mm_alice.log_path.display());

verify_coins_needed_for_kickstart(&mm_bob, &[ETH, ETH1]);
verify_coins_needed_for_kickstart(&mm_alice, &[ETH, ETH1]);

enable_coins(&mm_bob, &[ETH, ETH1]);
enable_coins(&mm_alice, &[ETH, ETH1]);

// give swaps 1 second to restart
thread::sleep(Duration::from_secs(1));

verify_active_swaps(&mm_bob, &parsed_uuids);
verify_active_swaps(&mm_alice, &parsed_uuids);

// coins must be virtually locked after kickstart until swap transactions are sent
verify_locked_amount(&mm_alice, "Taker", ETH1);
verify_locked_amount(&mm_bob, "Maker", ETH);
}

fn log_swap_status_before_stop(mm: &MarketMakerIt, uuid: &str, role: &str) {
let status = block_on(my_swap_status(mm, uuid));
log!("{} swap {} status before stop: {:?}", role, uuid, status);
}

fn verify_coins_needed_for_kickstart(mm: &MarketMakerIt, expected_coins: &[&str]) {
let mut coins_needed = block_on(coins_needed_for_kickstart(mm));
coins_needed.sort();
assert_eq!(coins_needed, expected_coins);
}

fn verify_active_swaps(mm: &MarketMakerIt, expected_uuids: &[Uuid]) {
let active_swaps = block_on(active_swaps(mm));
assert_eq!(active_swaps.uuids, expected_uuids);
}

fn verify_locked_amount(mm: &MarketMakerIt, role: &str, coin: &str) {
let locked = block_on(get_locked_amount(mm, coin));
log!("{} {} locked amount: {:?}", role, coin, locked.locked_amount);
assert_eq!(locked.coin, coin);
}
55 changes: 54 additions & 1 deletion mm2src/mm2_test_helpers/src/for_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,8 +820,16 @@ pub fn eth_testnet_conf_trezor() -> Json {

/// ETH configuration used for dockerized Geth dev node
pub fn eth_dev_conf() -> Json {
eth_conf("ETH")
}

pub fn eth1_dev_conf() -> Json {
eth_conf("ETH1")
}

fn eth_conf(coin: &str) -> Json {
json!({
"coin": "ETH",
"coin": coin,
"name": "ethereum",
"mm2": 1,
"chain_id": 1337,
Expand Down Expand Up @@ -2041,6 +2049,51 @@ pub async fn enable_eth_coin(
json::from_str(&enable.1).unwrap()
}

#[derive(Clone)]
pub struct SwapV2TestContracts {
pub maker_swap_v2_contract: String,
pub taker_swap_v2_contract: String,
pub nft_maker_swap_v2_contract: String,
}

#[derive(Clone)]
pub struct TestNode {
pub url: String,
}

pub async fn enable_eth_coin_v2(
mm: &MarketMakerIt,
ticker: &str,
swap_contract_address: &str,
swap_v2_contracts: SwapV2TestContracts,
fallback_swap_contract: Option<&str>,
nodes: &[TestNode],
) -> Json {
let enable = mm
.rpc(&json!({
"userpass": mm.userpass,
"method": "enable_eth_with_tokens",
"mmrpc": "2.0",
"params": {
"ticker": ticker,
"mm2": 1,
"swap_contract_address": swap_contract_address,
"swap_v2_contracts": {
"maker_swap_v2_contract": swap_v2_contracts.maker_swap_v2_contract,
"taker_swap_v2_contract": swap_v2_contracts.taker_swap_v2_contract,
"nft_maker_swap_v2_contract": swap_v2_contracts.nft_maker_swap_v2_contract
},
"fallback_swap_contract": fallback_swap_contract,
"nodes": nodes.iter().map(|node| json!({ "url": node.url })).collect::<Vec<_>>(),
"erc20_tokens_requests": []
}
}))
.await
.unwrap();
assert_eq!(enable.0, StatusCode::OK, "'enable_eth_with_tokens' failed: {}", enable.1);
json::from_str(&enable.1).unwrap()
}

pub async fn enable_slp(mm: &MarketMakerIt, coin: &str) -> Json {
let enable = mm
.rpc(&json!({
Expand Down
Loading