David/referral test new (#162)
* working on test for referral * refactored logic in tests to helper functions * added getbalance helper * added more helper functions to test for referral * gotta be able to submit to rpc now * adding provider instead * referral tests are not passing, may be because we need for stats to be updated * balance doesnt decrease * will look into deposits in the meantime * finding some first bugs * seems to have fixed a bunch of stuff * feedback, lint, and make it compile --------- Co-authored-by: Bryan Stitt <bryan@llamanodes.com>
This commit is contained in:
parent
2418d1ab77
commit
8d31680ff1
@ -413,8 +413,8 @@ impl BufferedRpcQueryStats {
|
|||||||
deltas.balance_spent_including_free_credits = self.sum_credits_used;
|
deltas.balance_spent_including_free_credits = self.sum_credits_used;
|
||||||
deltas.balance_spent_excluding_free_credits = self.sum_credits_used;
|
deltas.balance_spent_excluding_free_credits = self.sum_credits_used;
|
||||||
} else {
|
} else {
|
||||||
deltas.balance_spent_including_free_credits = user_balance;
|
deltas.balance_spent_including_free_credits = self.sum_credits_used;
|
||||||
deltas.balance_spent_excluding_free_credits = self.sum_credits_used;
|
deltas.balance_spent_excluding_free_credits = user_balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((deltas, Some((referral_entity, referrer_code_entity))))
|
Ok((deltas, Some((referral_entity, referrer_code_entity))))
|
||||||
@ -428,8 +428,8 @@ impl BufferedRpcQueryStats {
|
|||||||
deltas.balance_spent_including_free_credits = self.sum_credits_used;
|
deltas.balance_spent_including_free_credits = self.sum_credits_used;
|
||||||
deltas.balance_spent_excluding_free_credits = self.sum_credits_used;
|
deltas.balance_spent_excluding_free_credits = self.sum_credits_used;
|
||||||
} else {
|
} else {
|
||||||
deltas.balance_spent_including_free_credits = user_balance;
|
deltas.balance_spent_including_free_credits = self.sum_credits_used;
|
||||||
deltas.balance_spent_excluding_free_credits = self.sum_credits_used;
|
deltas.balance_spent_excluding_free_credits = user_balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((deltas, None))
|
Ok((deltas, None))
|
||||||
@ -575,7 +575,6 @@ impl BufferedRpcQueryStats {
|
|||||||
deltas: &Deltas,
|
deltas: &Deltas,
|
||||||
db_conn: &DatabaseConnection,
|
db_conn: &DatabaseConnection,
|
||||||
sender_rpc_entity: &rpc_key::Model,
|
sender_rpc_entity: &rpc_key::Model,
|
||||||
referral_objects: &Option<(referee::Model, referrer::Model)>,
|
|
||||||
rpc_secret_key_cache: &RpcSecretKeyCache,
|
rpc_secret_key_cache: &RpcSecretKeyCache,
|
||||||
user_balance_cache: &UserBalanceCache,
|
user_balance_cache: &UserBalanceCache,
|
||||||
) -> Web3ProxyResult<()> {
|
) -> Web3ProxyResult<()> {
|
||||||
@ -710,7 +709,6 @@ impl BufferedRpcQueryStats {
|
|||||||
&deltas,
|
&deltas,
|
||||||
db_conn,
|
db_conn,
|
||||||
&sender_rpc_entity,
|
&sender_rpc_entity,
|
||||||
&referral_objects,
|
|
||||||
rpc_secret_key_cache,
|
rpc_secret_key_cache,
|
||||||
user_balance_cache,
|
user_balance_cache,
|
||||||
)
|
)
|
||||||
|
46
web3_proxy/tests/common/admin_increases_balance.rs
Normal file
46
web3_proxy/tests/common/admin_increases_balance.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use crate::TestApp;
|
||||||
|
use ethers::prelude::{LocalWallet, Signer};
|
||||||
|
use rust_decimal::Decimal;
|
||||||
|
use tracing::info;
|
||||||
|
use web3_proxy::frontend::admin::AdminIncreaseBalancePost;
|
||||||
|
use web3_proxy::frontend::users::authentication::LoginPostResponse;
|
||||||
|
|
||||||
|
/// Helper function to increase the balance of a user, from an admin
|
||||||
|
#[allow(unused)]
|
||||||
|
pub async fn admin_increase_balance(
|
||||||
|
x: &TestApp,
|
||||||
|
r: &reqwest::Client,
|
||||||
|
admin_login_response: &LoginPostResponse,
|
||||||
|
target_wallet: &LocalWallet,
|
||||||
|
amount: Decimal,
|
||||||
|
) -> serde_json::Value {
|
||||||
|
let increase_balance_post_url = format!("{}admin/increase_balance", x.proxy_provider.url());
|
||||||
|
info!("Increasing balance");
|
||||||
|
// Login the user
|
||||||
|
// Use the bearer token of admin to increase user balance
|
||||||
|
let increase_balance_data = AdminIncreaseBalancePost {
|
||||||
|
user_address: target_wallet.address(), // set user address to increase balance
|
||||||
|
amount, // set amount to increase
|
||||||
|
note: Some("Test increasing balance".to_string()),
|
||||||
|
};
|
||||||
|
info!(?increase_balance_post_url);
|
||||||
|
info!(?increase_balance_data);
|
||||||
|
info!(?admin_login_response.bearer_token);
|
||||||
|
|
||||||
|
let increase_balance_response = r
|
||||||
|
.post(increase_balance_post_url)
|
||||||
|
.json(&increase_balance_data)
|
||||||
|
.bearer_auth(admin_login_response.bearer_token)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?increase_balance_response, "http response");
|
||||||
|
|
||||||
|
let increase_balance_response = increase_balance_response
|
||||||
|
.json::<serde_json::Value>()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?increase_balance_response, "json response");
|
||||||
|
|
||||||
|
increase_balance_response
|
||||||
|
}
|
101
web3_proxy/tests/common/create_admin.rs
Normal file
101
web3_proxy/tests/common/create_admin.rs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
use crate::TestApp;
|
||||||
|
use ethers::prelude::{LocalWallet, Signer};
|
||||||
|
use ethers::types::Signature;
|
||||||
|
use tracing::info;
|
||||||
|
use web3_proxy::frontend::users::authentication::{LoginPostResponse, PostLogin};
|
||||||
|
use web3_proxy::sub_commands::ChangeAdminStatusSubCommand;
|
||||||
|
|
||||||
|
/// Helper function to create admin
|
||||||
|
|
||||||
|
/// Create user as admin
|
||||||
|
#[allow(unused)]
|
||||||
|
pub async fn create_user_as_admin(
|
||||||
|
x: &TestApp,
|
||||||
|
r: &reqwest::Client,
|
||||||
|
admin_wallet: &LocalWallet,
|
||||||
|
) -> LoginPostResponse {
|
||||||
|
// Create the account
|
||||||
|
let login_post_url = format!("{}user/login", x.proxy_provider.url());
|
||||||
|
let admin_login_get_url = format!(
|
||||||
|
"{}user/login/{:?}",
|
||||||
|
x.proxy_provider.url(),
|
||||||
|
admin_wallet.address()
|
||||||
|
);
|
||||||
|
let admin_login_message = r.get(admin_login_get_url).send().await.unwrap();
|
||||||
|
let admin_login_message = admin_login_message.text().await.unwrap();
|
||||||
|
|
||||||
|
// Sign the message and POST it to login as admin
|
||||||
|
let admin_signed: Signature = admin_wallet
|
||||||
|
.sign_message(&admin_login_message)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?admin_signed);
|
||||||
|
|
||||||
|
let admin_post_login_data = PostLogin {
|
||||||
|
msg: admin_login_message,
|
||||||
|
sig: admin_signed.to_string(),
|
||||||
|
referral_code: None,
|
||||||
|
};
|
||||||
|
info!(?admin_post_login_data);
|
||||||
|
|
||||||
|
let admin_login_response = r
|
||||||
|
.post(&login_post_url)
|
||||||
|
.json(&admin_post_login_data)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.json::<LoginPostResponse>()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?admin_login_response);
|
||||||
|
|
||||||
|
// Upgrade the account to admin
|
||||||
|
info!("Make the user an admin ...");
|
||||||
|
// Change Admin SubCommand struct
|
||||||
|
let admin_status_changer = ChangeAdminStatusSubCommand {
|
||||||
|
address: format!("{:?}", admin_wallet.address()),
|
||||||
|
should_be_admin: true,
|
||||||
|
};
|
||||||
|
info!(?admin_status_changer);
|
||||||
|
|
||||||
|
info!("Changing the status of the admin_wallet to be an admin");
|
||||||
|
// Pass on the database into it ...
|
||||||
|
admin_status_changer.main(x.db_conn()).await.unwrap();
|
||||||
|
|
||||||
|
// Now log him in again, because he was just signed out
|
||||||
|
// Login the admin again, because he was just signed out
|
||||||
|
let admin_login_get_url = format!(
|
||||||
|
"{}user/login/{:?}",
|
||||||
|
x.proxy_provider.url(),
|
||||||
|
admin_wallet.address()
|
||||||
|
);
|
||||||
|
let admin_login_message = r.get(admin_login_get_url).send().await.unwrap();
|
||||||
|
let admin_login_message = admin_login_message.text().await.unwrap();
|
||||||
|
|
||||||
|
// Sign the message and POST it to login as admin
|
||||||
|
let admin_signed: Signature = admin_wallet
|
||||||
|
.sign_message(&admin_login_message)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?admin_signed);
|
||||||
|
|
||||||
|
let admin_post_login_data = PostLogin {
|
||||||
|
msg: admin_login_message,
|
||||||
|
sig: admin_signed.to_string(),
|
||||||
|
referral_code: None,
|
||||||
|
};
|
||||||
|
info!(?admin_post_login_data);
|
||||||
|
|
||||||
|
let admin_login_response = r
|
||||||
|
.post(&login_post_url)
|
||||||
|
.json(&admin_post_login_data)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.json::<LoginPostResponse>()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?admin_login_response);
|
||||||
|
|
||||||
|
admin_login_response
|
||||||
|
}
|
47
web3_proxy/tests/common/create_user.rs
Normal file
47
web3_proxy/tests/common/create_user.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use crate::TestApp;
|
||||||
|
use ethers::prelude::{LocalWallet, Signer};
|
||||||
|
use ethers::types::Signature;
|
||||||
|
use tracing::info;
|
||||||
|
use web3_proxy::frontend::users::authentication::{LoginPostResponse, PostLogin};
|
||||||
|
|
||||||
|
/// Helper function to create an "ordinary" user
|
||||||
|
#[allow(unused)]
|
||||||
|
pub async fn create_user(
|
||||||
|
x: &TestApp,
|
||||||
|
r: &reqwest::Client,
|
||||||
|
user_wallet: &LocalWallet,
|
||||||
|
referral_code: Option<String>,
|
||||||
|
) -> (LoginPostResponse) {
|
||||||
|
let login_post_url = format!("{}user/login", x.proxy_provider.url());
|
||||||
|
let user_login_get_url = format!(
|
||||||
|
"{}user/login/{:?}",
|
||||||
|
x.proxy_provider.url(),
|
||||||
|
user_wallet.address()
|
||||||
|
);
|
||||||
|
let user_login_message = r.get(user_login_get_url).send().await.unwrap();
|
||||||
|
let user_login_message = user_login_message.text().await.unwrap();
|
||||||
|
|
||||||
|
// Sign the message and POST it to login as the user
|
||||||
|
let user_signed: Signature = user_wallet.sign_message(&user_login_message).await.unwrap();
|
||||||
|
info!(?user_signed);
|
||||||
|
|
||||||
|
let user_post_login_data = PostLogin {
|
||||||
|
msg: user_login_message,
|
||||||
|
sig: user_signed.to_string(),
|
||||||
|
referral_code,
|
||||||
|
};
|
||||||
|
info!(?user_post_login_data);
|
||||||
|
|
||||||
|
let user_login_response = r
|
||||||
|
.post(&login_post_url)
|
||||||
|
.json(&user_post_login_data)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.json::<LoginPostResponse>()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?user_login_response);
|
||||||
|
|
||||||
|
user_login_response
|
||||||
|
}
|
55
web3_proxy/tests/common/get_rpc_key.rs
Normal file
55
web3_proxy/tests/common/get_rpc_key.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use crate::TestApp;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tracing::info;
|
||||||
|
use ulid::Ulid;
|
||||||
|
use web3_proxy::frontend::users::authentication::LoginPostResponse;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct RpcKeyResponse {
|
||||||
|
pub user_id: u64,
|
||||||
|
pub user_rpc_keys: std::collections::HashMap<String, RpcKey>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct RpcKey {
|
||||||
|
pub active: bool,
|
||||||
|
pub allowed_ips: Option<serde_json::Value>,
|
||||||
|
pub allowed_origins: Option<serde_json::Value>,
|
||||||
|
pub allowed_referers: Option<serde_json::Value>,
|
||||||
|
pub allowed_user_agents: Option<serde_json::Value>,
|
||||||
|
pub description: Option<serde_json::Value>,
|
||||||
|
pub id: u64,
|
||||||
|
pub log_revert_chance: f64,
|
||||||
|
pub private_txs: bool,
|
||||||
|
pub role: String,
|
||||||
|
pub secret_key: Ulid,
|
||||||
|
pub user_id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function to get the user's balance
|
||||||
|
#[allow(unused)]
|
||||||
|
pub async fn user_get_first_rpc_key(
|
||||||
|
x: &TestApp,
|
||||||
|
r: &reqwest::Client,
|
||||||
|
login_response: &LoginPostResponse,
|
||||||
|
) -> RpcKey {
|
||||||
|
let get_keys = format!("{}user/keys", x.proxy_provider.url());
|
||||||
|
|
||||||
|
info!("Get balance");
|
||||||
|
let rpc_key_response = r
|
||||||
|
.get(get_keys)
|
||||||
|
.bearer_auth(login_response.bearer_token)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?rpc_key_response);
|
||||||
|
|
||||||
|
let rpc_key_response = rpc_key_response.json::<serde_json::Value>().await.unwrap();
|
||||||
|
info!(?rpc_key_response);
|
||||||
|
|
||||||
|
info!("Rpc Key");
|
||||||
|
let rpc_key: RpcKeyResponse = serde_json::from_value(rpc_key_response).unwrap();
|
||||||
|
info!(?rpc_key);
|
||||||
|
|
||||||
|
rpc_key.user_rpc_keys.into_iter().next().unwrap().1
|
||||||
|
}
|
26
web3_proxy/tests/common/get_user_balance.rs
Normal file
26
web3_proxy/tests/common/get_user_balance.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use crate::TestApp;
|
||||||
|
use tracing::info;
|
||||||
|
use web3_proxy::frontend::users::authentication::LoginPostResponse;
|
||||||
|
|
||||||
|
/// Helper function to get the user's balance
|
||||||
|
#[allow(unused)]
|
||||||
|
pub async fn user_get_balance(
|
||||||
|
x: &TestApp,
|
||||||
|
r: &reqwest::Client,
|
||||||
|
login_response: &LoginPostResponse,
|
||||||
|
) -> (serde_json::Value) {
|
||||||
|
let get_user_balance = format!("{}user/balance", x.proxy_provider.url());
|
||||||
|
info!("Get balance");
|
||||||
|
let balance_response = r
|
||||||
|
.get(get_user_balance)
|
||||||
|
.bearer_auth(login_response.bearer_token)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?balance_response);
|
||||||
|
|
||||||
|
let balance_response = balance_response.json::<serde_json::Value>().await.unwrap();
|
||||||
|
info!(?balance_response);
|
||||||
|
|
||||||
|
balance_response
|
||||||
|
}
|
@ -1,3 +1,9 @@
|
|||||||
|
pub mod admin_increases_balance;
|
||||||
pub mod app;
|
pub mod app;
|
||||||
|
pub mod create_admin;
|
||||||
|
pub mod create_user;
|
||||||
|
pub mod get_rpc_key;
|
||||||
|
pub mod get_user_balance;
|
||||||
|
pub mod referral;
|
||||||
|
|
||||||
pub use self::app::TestApp;
|
pub use self::app::TestApp;
|
||||||
|
124
web3_proxy/tests/common/referral.rs
Normal file
124
web3_proxy/tests/common/referral.rs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/// Helper for referral functions
|
||||||
|
/// Includes
|
||||||
|
/// - get referral link
|
||||||
|
/// - getting code for referral (shared and used)
|
||||||
|
use crate::TestApp;
|
||||||
|
use tracing::info;
|
||||||
|
use ulid::Ulid;
|
||||||
|
use web3_proxy::frontend::users::authentication::LoginPostResponse;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct UserSharedReferralInfo {
|
||||||
|
pub user: User,
|
||||||
|
pub referrals: Vec<Referral>,
|
||||||
|
pub used_referral_code: Ulid,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct UserUsedReferralInfo {
|
||||||
|
pub user: User,
|
||||||
|
pub referrals: Vec<Referral>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct User {
|
||||||
|
pub address: String,
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub email: Option<String>,
|
||||||
|
pub id: u64,
|
||||||
|
pub user_tier_id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Referral {
|
||||||
|
pub credits_applied_for_referee: bool,
|
||||||
|
pub credits_applied_for_referrer: String,
|
||||||
|
pub referral_start_date: String,
|
||||||
|
pub referred_address: Option<String>,
|
||||||
|
pub used_referral_code: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function to create an "ordinary" user
|
||||||
|
#[allow(unused)]
|
||||||
|
pub async fn get_referral_code(
|
||||||
|
x: &TestApp,
|
||||||
|
r: &reqwest::Client,
|
||||||
|
login_response: &LoginPostResponse,
|
||||||
|
) -> String {
|
||||||
|
let get_referral_link = format!("{}user/referral", x.proxy_provider.url());
|
||||||
|
|
||||||
|
// The referrer makes sure that the user is registered as a referred used
|
||||||
|
let referral_link = r
|
||||||
|
.get(&get_referral_link)
|
||||||
|
.bearer_auth(login_response.bearer_token)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?referral_link);
|
||||||
|
let referral_link = referral_link.json::<serde_json::Value>().await.unwrap();
|
||||||
|
info!("Referrer get link");
|
||||||
|
info!(?referral_link);
|
||||||
|
let referral_link = referral_link["referral_code"].as_str().unwrap().to_string();
|
||||||
|
info!(?referral_link);
|
||||||
|
|
||||||
|
referral_link
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub async fn get_shared_referral_codes(
|
||||||
|
x: &TestApp,
|
||||||
|
r: &reqwest::Client,
|
||||||
|
login_response: &LoginPostResponse,
|
||||||
|
) -> UserSharedReferralInfo {
|
||||||
|
let check_shared_referral_link =
|
||||||
|
format!("{}user/referral/stats/shared-codes", x.proxy_provider.url());
|
||||||
|
info!("Get balance");
|
||||||
|
let shared_referral_codes = r
|
||||||
|
.get(check_shared_referral_link)
|
||||||
|
.bearer_auth(login_response.bearer_token)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?shared_referral_codes);
|
||||||
|
|
||||||
|
let shared_referral_codes = shared_referral_codes
|
||||||
|
.json::<serde_json::Value>()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?shared_referral_codes);
|
||||||
|
|
||||||
|
let user_referral_info: UserSharedReferralInfo =
|
||||||
|
serde_json::from_value(shared_referral_codes).unwrap();
|
||||||
|
|
||||||
|
user_referral_info
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub async fn get_used_referral_codes(
|
||||||
|
x: &TestApp,
|
||||||
|
r: &reqwest::Client,
|
||||||
|
login_response: &LoginPostResponse,
|
||||||
|
) -> UserUsedReferralInfo {
|
||||||
|
let check_used_referral_link =
|
||||||
|
format!("{}user/referral/stats/used-codes", x.proxy_provider.url());
|
||||||
|
info!("Get balance");
|
||||||
|
let used_referral_codes = r
|
||||||
|
.get(check_used_referral_link)
|
||||||
|
.bearer_auth(login_response.bearer_token)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?used_referral_codes);
|
||||||
|
|
||||||
|
let used_referral_codes = used_referral_codes
|
||||||
|
.json::<serde_json::Value>()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
info!(?used_referral_codes);
|
||||||
|
|
||||||
|
let user_referral_info: UserUsedReferralInfo =
|
||||||
|
serde_json::from_value(used_referral_codes).unwrap();
|
||||||
|
user_referral_info
|
||||||
|
}
|
@ -3,14 +3,13 @@ mod common;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::common::admin_increases_balance::admin_increase_balance;
|
||||||
|
use crate::common::create_admin::create_user_as_admin;
|
||||||
|
use crate::common::create_user::create_user;
|
||||||
|
use crate::common::get_user_balance::user_get_balance;
|
||||||
use crate::common::TestApp;
|
use crate::common::TestApp;
|
||||||
use ethers::prelude::Signer;
|
|
||||||
use ethers::types::Signature;
|
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
use web3_proxy::frontend::admin::AdminIncreaseBalancePost;
|
|
||||||
use web3_proxy::frontend::users::authentication::{LoginPostResponse, PostLogin};
|
|
||||||
use web3_proxy::sub_commands::ChangeAdminStatusSubCommand;
|
|
||||||
|
|
||||||
// #[cfg_attr(not(feature = "tests-needing-docker"), ignore)]
|
// #[cfg_attr(not(feature = "tests-needing-docker"), ignore)]
|
||||||
#[ignore = "under construction"]
|
#[ignore = "under construction"]
|
||||||
@ -32,157 +31,34 @@ async fn test_admin_grant_credits() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Setup variables that will be used
|
// Setup variables that will be used
|
||||||
let login_post_url = format!("{}user/login", x.proxy_provider.url());
|
let user_wallet = x.wallet(0);
|
||||||
let increase_balance_post_url = format!("{}admin/increase_balance", x.proxy_provider.url());
|
|
||||||
|
|
||||||
let admin_wallet = x.wallet(1);
|
let admin_wallet = x.wallet(1);
|
||||||
let user_wallet = x.wallet(2);
|
info!(?admin_wallet);
|
||||||
|
|
||||||
// Login the admin to create their account. they aren't an admin yet
|
let user_login_response = create_user(&x, &r, &user_wallet, None).await;
|
||||||
let admin_login_get_url = format!(
|
let admin_login_response = create_user_as_admin(&x, &r, &admin_wallet).await;
|
||||||
"{}user/login/{:?}",
|
|
||||||
x.proxy_provider.url(),
|
|
||||||
admin_wallet.address()
|
|
||||||
);
|
|
||||||
let admin_login_message = r.get(admin_login_get_url).send().await.unwrap();
|
|
||||||
let admin_login_message = admin_login_message.text().await.unwrap();
|
|
||||||
|
|
||||||
// Sign the message and POST it to login as admin
|
|
||||||
let admin_signed: Signature = admin_wallet
|
|
||||||
.sign_message(&admin_login_message)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
info!(?admin_signed);
|
|
||||||
|
|
||||||
let admin_post_login_data = PostLogin {
|
|
||||||
msg: admin_login_message,
|
|
||||||
sig: admin_signed.to_string(),
|
|
||||||
referral_code: None,
|
|
||||||
};
|
|
||||||
info!(?admin_post_login_data);
|
|
||||||
|
|
||||||
let admin_login_response = r
|
|
||||||
.post(&login_post_url)
|
|
||||||
.json(&admin_post_login_data)
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.json::<LoginPostResponse>()
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
info!(?admin_login_response);
|
info!(?admin_login_response);
|
||||||
|
|
||||||
// Also login the user (to create the user)
|
let increase_balance_response = admin_increase_balance(
|
||||||
let user_login_get_url = format!(
|
&x,
|
||||||
"{}user/login/{:?}",
|
&r,
|
||||||
x.proxy_provider.url(),
|
&admin_login_response,
|
||||||
user_wallet.address()
|
&user_wallet,
|
||||||
);
|
Decimal::from(100),
|
||||||
let user_login_message = r.get(user_login_get_url).send().await.unwrap();
|
)
|
||||||
let user_login_message = user_login_message.text().await.unwrap();
|
.await;
|
||||||
|
|
||||||
// Sign the message and POST it to login as the user
|
|
||||||
let user_signed: Signature = user_wallet.sign_message(&user_login_message).await.unwrap();
|
|
||||||
info!(?user_signed);
|
|
||||||
|
|
||||||
let user_post_login_data = PostLogin {
|
|
||||||
msg: user_login_message,
|
|
||||||
sig: user_signed.to_string(),
|
|
||||||
referral_code: None,
|
|
||||||
};
|
|
||||||
info!(?user_post_login_data);
|
|
||||||
|
|
||||||
let user_login_response = r
|
|
||||||
.post(&login_post_url)
|
|
||||||
.json(&user_post_login_data)
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.json::<LoginPostResponse>()
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
info!(?user_login_response);
|
|
||||||
|
|
||||||
info!("Make the user an admin ...");
|
|
||||||
// Change Admin SubCommand struct
|
|
||||||
let admin_status_changer = ChangeAdminStatusSubCommand {
|
|
||||||
address: format!("{:?}", admin_wallet.address()),
|
|
||||||
should_be_admin: true,
|
|
||||||
};
|
|
||||||
info!(?admin_status_changer);
|
|
||||||
|
|
||||||
info!("Changing the status of the admin_wallet to be an admin");
|
|
||||||
// Pass on the database into it ...
|
|
||||||
admin_status_changer.main(x.db_conn()).await.unwrap();
|
|
||||||
|
|
||||||
// Login the admin again, because he was just signed out
|
|
||||||
let admin_login_get_url = format!(
|
|
||||||
"{}user/login/{:?}",
|
|
||||||
x.proxy_provider.url(),
|
|
||||||
admin_wallet.address()
|
|
||||||
);
|
|
||||||
let admin_login_message = r.get(admin_login_get_url).send().await.unwrap();
|
|
||||||
let admin_login_message = admin_login_message.text().await.unwrap();
|
|
||||||
|
|
||||||
// Sign the message and POST it to login as admin
|
|
||||||
let admin_signed: Signature = admin_wallet
|
|
||||||
.sign_message(&admin_login_message)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
info!(?admin_signed);
|
|
||||||
|
|
||||||
let admin_post_login_data = PostLogin {
|
|
||||||
msg: admin_login_message,
|
|
||||||
sig: admin_signed.to_string(),
|
|
||||||
referral_code: None,
|
|
||||||
};
|
|
||||||
info!(?admin_post_login_data);
|
|
||||||
|
|
||||||
let admin_login_response = r
|
|
||||||
.post(&login_post_url)
|
|
||||||
.json(&admin_post_login_data)
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.json::<LoginPostResponse>()
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
info!(?admin_login_response);
|
|
||||||
|
|
||||||
info!("Increasing balance");
|
|
||||||
// Login the user
|
|
||||||
// Use the bearer token of admin to increase user balance
|
|
||||||
let increase_balance_data = AdminIncreaseBalancePost {
|
|
||||||
user_address: user_wallet.address(), // set user address to increase balance
|
|
||||||
amount: Decimal::from(100), // set amount to increase
|
|
||||||
note: Some("Test increasing balance".to_string()),
|
|
||||||
};
|
|
||||||
info!(?increase_balance_post_url);
|
|
||||||
info!(?increase_balance_data);
|
|
||||||
info!(?admin_login_response.bearer_token);
|
|
||||||
|
|
||||||
let increase_balance_response = r
|
|
||||||
.post(increase_balance_post_url)
|
|
||||||
.json(&increase_balance_data)
|
|
||||||
.bearer_auth(admin_login_response.bearer_token)
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
info!(?increase_balance_response, "http response");
|
|
||||||
|
|
||||||
let increase_balance_response = increase_balance_response
|
|
||||||
.json::<serde_json::Value>()
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
info!(?increase_balance_response, "json response");
|
|
||||||
|
|
||||||
// Check if the response is as expected
|
|
||||||
// TODO: assert_eq!(increase_balance_response["user"], user_wallet.address());
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Decimal::from_str(increase_balance_response["amount"].as_str().unwrap()).unwrap(),
|
Decimal::from_str(increase_balance_response["amount"].as_str().unwrap()).unwrap(),
|
||||||
Decimal::from(100)
|
Decimal::from(100)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let user_balance_response = user_get_balance(&x, &r, &user_login_response).await;
|
||||||
|
assert_eq!(
|
||||||
|
Decimal::from_str(user_balance_response["balance"].as_str().unwrap()).unwrap(),
|
||||||
|
Decimal::from(100)
|
||||||
|
);
|
||||||
|
|
||||||
x.wait().await;
|
x.wait().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,25 @@
|
|||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
|
use crate::common::admin_increases_balance::admin_increase_balance;
|
||||||
|
use crate::common::create_admin::create_user_as_admin;
|
||||||
|
use crate::common::create_user::create_user;
|
||||||
|
use crate::common::get_rpc_key::{user_get_first_rpc_key, RpcKey};
|
||||||
|
use crate::common::get_user_balance::user_get_balance;
|
||||||
|
use crate::common::referral::{
|
||||||
|
get_referral_code, get_shared_referral_codes, get_used_referral_codes, UserSharedReferralInfo,
|
||||||
|
UserUsedReferralInfo,
|
||||||
|
};
|
||||||
use crate::common::TestApp;
|
use crate::common::TestApp;
|
||||||
|
use ethers::prelude::{Http, Provider};
|
||||||
use ethers::{signers::Signer, types::Signature};
|
use ethers::{signers::Signer, types::Signature};
|
||||||
|
use rust_decimal::Decimal;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::time::Duration;
|
||||||
use tracing::{debug, info, trace};
|
use tracing::{debug, info, trace};
|
||||||
use ulid::Ulid;
|
use ulid::Ulid;
|
||||||
use web3_proxy::frontend::users::authentication::PostLogin;
|
use web3_proxy::frontend::users::authentication::PostLogin;
|
||||||
|
use web3_proxy::rpcs::blockchain::ArcBlock;
|
||||||
|
|
||||||
/// TODO: use this type in the frontend
|
/// TODO: use this type in the frontend
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
@ -73,11 +87,229 @@ async fn test_log_in_and_out() {
|
|||||||
assert_eq!(logout_response, "goodbye");
|
assert_eq!(logout_response, "goodbye");
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[cfg_attr(not(feature = "tests-needing-docker"), ignore)]
|
#[cfg_attr(not(feature = "tests-needing-docker"), ignore)]
|
||||||
#[ignore = "under construction"]
|
|
||||||
#[test_log::test(tokio::test)]
|
#[test_log::test(tokio::test)]
|
||||||
async fn test_referral_bonus() {
|
async fn test_user_balance_decreases() {
|
||||||
|
info!("Starting balance decreases with usage test");
|
||||||
let x = TestApp::spawn(true).await;
|
let x = TestApp::spawn(true).await;
|
||||||
|
let r = reqwest::Client::builder()
|
||||||
|
.timeout(Duration::from_secs(20))
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
todo!();
|
let user_wallet = x.wallet(0);
|
||||||
|
let admin_wallet = x.wallet(1);
|
||||||
|
|
||||||
|
// Create three users, one referrer, one admin who bumps both their balances
|
||||||
|
let admin_login_response = create_user_as_admin(&x, &r, &admin_wallet).await;
|
||||||
|
let user_login_response = create_user(&x, &r, &user_wallet, None).await;
|
||||||
|
|
||||||
|
// Get the rpc keys for this user
|
||||||
|
let rpc_keys: RpcKey = user_get_first_rpc_key(&x, &r, &user_login_response).await;
|
||||||
|
let proxy_endpoint = format!("{}rpc/{}", x.proxy_provider.url(), rpc_keys.secret_key);
|
||||||
|
let proxy_provider = Provider::<Http>::try_from(proxy_endpoint).unwrap();
|
||||||
|
|
||||||
|
// Make somre requests while in the free tier, so we can test bookkeeping here
|
||||||
|
for _ in 1..10_000 {
|
||||||
|
let _ = proxy_provider
|
||||||
|
.request::<_, Option<ArcBlock>>("eth_getBlockByNumber", ("latest", false))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush all stats here
|
||||||
|
let (influx_count, mysql_count) = x.flush_stats().await.unwrap();
|
||||||
|
assert_eq!(influx_count, 0);
|
||||||
|
assert!(mysql_count > 0);
|
||||||
|
|
||||||
|
// Bump both user's wallet to $20
|
||||||
|
admin_increase_balance(
|
||||||
|
&x,
|
||||||
|
&r,
|
||||||
|
&admin_login_response,
|
||||||
|
&user_wallet,
|
||||||
|
Decimal::from(20),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let user_balance_response = user_get_balance(&x, &r, &user_login_response).await;
|
||||||
|
let user_balance_pre =
|
||||||
|
Decimal::from_str(user_balance_response["balance"].as_str().unwrap()).unwrap();
|
||||||
|
assert_eq!(user_balance_pre, Decimal::from(20));
|
||||||
|
|
||||||
|
for _ in 1..10_000 {
|
||||||
|
let _ = proxy_provider
|
||||||
|
.request::<_, Option<ArcBlock>>("eth_getBlockByNumber", ("latest", false))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush all stats here
|
||||||
|
let (influx_count, mysql_count) = x.flush_stats().await.unwrap();
|
||||||
|
assert_eq!(influx_count, 0);
|
||||||
|
assert!(mysql_count > 0);
|
||||||
|
|
||||||
|
// Deposits should not be affected, and should be equal to what was initially provided
|
||||||
|
let total_deposits =
|
||||||
|
Decimal::from_str(user_balance_response["total_deposits"].as_str().unwrap()).unwrap();
|
||||||
|
assert_eq!(total_deposits, Decimal::from(20));
|
||||||
|
|
||||||
|
// Get the full balance endpoint
|
||||||
|
let user_balance_response = user_get_balance(&x, &r, &user_login_response).await;
|
||||||
|
let user_balance_post =
|
||||||
|
Decimal::from_str(user_balance_response["balance"].as_str().unwrap()).unwrap();
|
||||||
|
assert!(user_balance_post < user_balance_pre);
|
||||||
|
|
||||||
|
// Balance should be total deposits - usage while in the paid tier
|
||||||
|
let total_spent_outside_free_tier = Decimal::from_str(
|
||||||
|
user_balance_response["total_spent_outside_free_tier"]
|
||||||
|
.as_str()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
total_deposits - total_spent_outside_free_tier,
|
||||||
|
user_balance_post
|
||||||
|
);
|
||||||
|
|
||||||
|
// This should never be negative
|
||||||
|
let user_balance_total_spent =
|
||||||
|
Decimal::from_str(user_balance_response["total_spent"].as_str().unwrap()).unwrap();
|
||||||
|
assert!(user_balance_total_spent > Decimal::from(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(feature = "tests-needing-docker"), ignore)]
|
||||||
|
#[test_log::test(tokio::test)]
|
||||||
|
async fn test_referral_bonus_non_concurrent() {
|
||||||
|
info!("Starting referral bonus test");
|
||||||
|
let x = TestApp::spawn(true).await;
|
||||||
|
let r = reqwest::Client::builder()
|
||||||
|
.timeout(Duration::from_secs(20))
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let user_wallet = x.wallet(0);
|
||||||
|
let referrer_wallet = x.wallet(1);
|
||||||
|
let admin_wallet = x.wallet(2);
|
||||||
|
|
||||||
|
// Create three users, one referrer, one admin who bumps both their balances
|
||||||
|
let referrer_login_response = create_user(&x, &r, &referrer_wallet, None).await;
|
||||||
|
let admin_login_response = create_user_as_admin(&x, &r, &admin_wallet).await;
|
||||||
|
// Get the first user's referral link
|
||||||
|
let referral_link = get_referral_code(&x, &r, &referrer_login_response).await;
|
||||||
|
|
||||||
|
let user_login_response = create_user(&x, &r, &user_wallet, Some(referral_link.clone())).await;
|
||||||
|
|
||||||
|
// Bump both user's wallet to $20
|
||||||
|
admin_increase_balance(
|
||||||
|
&x,
|
||||||
|
&r,
|
||||||
|
&admin_login_response,
|
||||||
|
&user_wallet,
|
||||||
|
Decimal::from(20),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
admin_increase_balance(
|
||||||
|
&x,
|
||||||
|
&r,
|
||||||
|
&admin_login_response,
|
||||||
|
&referrer_wallet,
|
||||||
|
Decimal::from(20),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// Get balance before for both users
|
||||||
|
let user_balance_response = user_get_balance(&x, &r, &user_login_response).await;
|
||||||
|
let user_balance_pre =
|
||||||
|
Decimal::from_str(user_balance_response["balance"].as_str().unwrap()).unwrap();
|
||||||
|
let referrer_balance_response = user_get_balance(&x, &r, &referrer_login_response).await;
|
||||||
|
let referrer_balance_pre =
|
||||||
|
Decimal::from_str(referrer_balance_response["balance"].as_str().unwrap()).unwrap();
|
||||||
|
|
||||||
|
// Make sure they both have balance now
|
||||||
|
assert_eq!(user_balance_pre, Decimal::from(20));
|
||||||
|
assert_eq!(referrer_balance_pre, Decimal::from(20));
|
||||||
|
|
||||||
|
// Setup variables that will be used
|
||||||
|
let shared_referral_code: UserSharedReferralInfo =
|
||||||
|
get_shared_referral_codes(&x, &r, &referrer_login_response).await;
|
||||||
|
let used_referral_code: UserUsedReferralInfo =
|
||||||
|
get_used_referral_codes(&x, &r, &user_login_response).await;
|
||||||
|
|
||||||
|
// assert that the used referral code is used
|
||||||
|
assert_eq!(
|
||||||
|
format!("{:?}", user_wallet.address()),
|
||||||
|
shared_referral_code
|
||||||
|
.clone()
|
||||||
|
.referrals
|
||||||
|
.get(0)
|
||||||
|
.unwrap()
|
||||||
|
.referred_address
|
||||||
|
.clone()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
referral_link.clone(),
|
||||||
|
used_referral_code
|
||||||
|
.clone()
|
||||||
|
.referrals
|
||||||
|
.get(0)
|
||||||
|
.unwrap()
|
||||||
|
.used_referral_code
|
||||||
|
.clone()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make a for-loop just spam it a bit
|
||||||
|
// Make a JSON request
|
||||||
|
let rpc_keys: RpcKey = user_get_first_rpc_key(&x, &r, &user_login_response).await;
|
||||||
|
info!("Rpc key is: {:?}", rpc_keys);
|
||||||
|
|
||||||
|
let proxy_endpoint = format!("{}rpc/{}", x.proxy_provider.url(), rpc_keys.secret_key);
|
||||||
|
let proxy_provider = Provider::<Http>::try_from(proxy_endpoint).unwrap();
|
||||||
|
|
||||||
|
for _ in 1..20_000 {
|
||||||
|
let _proxy_result = proxy_provider
|
||||||
|
.request::<_, Option<ArcBlock>>("eth_getBlockByNumber", ("latest", false))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush all stats here
|
||||||
|
let (influx_count, mysql_count) = x.flush_stats().await.unwrap();
|
||||||
|
assert_eq!(influx_count, 0);
|
||||||
|
assert!(mysql_count > 0);
|
||||||
|
|
||||||
|
// Check that at least something was earned:
|
||||||
|
let shared_referral_code: UserSharedReferralInfo =
|
||||||
|
get_shared_referral_codes(&x, &r, &referrer_login_response).await;
|
||||||
|
info!("Referral code");
|
||||||
|
info!("{:?}", shared_referral_code.referrals.get(0).unwrap());
|
||||||
|
|
||||||
|
// We make sure that the referrer has $10 + 10% of the used balance
|
||||||
|
// The admin provides credits for both
|
||||||
|
let user_balance_response = user_get_balance(&x, &r, &user_login_response).await;
|
||||||
|
let user_balance_post =
|
||||||
|
Decimal::from_str(user_balance_response["balance"].as_str().unwrap()).unwrap();
|
||||||
|
let referrer_balance_response = user_get_balance(&x, &r, &referrer_login_response).await;
|
||||||
|
let referrer_balance_post =
|
||||||
|
Decimal::from_str(referrer_balance_response["balance"].as_str().unwrap()).unwrap();
|
||||||
|
|
||||||
|
let difference = user_balance_pre - user_balance_post;
|
||||||
|
|
||||||
|
// Make sure that the pre and post balance is not the same (i.e. some change has occurred)
|
||||||
|
assert_ne!(
|
||||||
|
user_balance_pre, user_balance_post,
|
||||||
|
"Pre and post balnace is equivalent"
|
||||||
|
);
|
||||||
|
assert!(user_balance_pre > user_balance_post);
|
||||||
|
assert!(referrer_balance_pre < referrer_balance_post);
|
||||||
|
|
||||||
|
// Finally, make sure that referrer has received 10$ of balances
|
||||||
|
assert_eq!(
|
||||||
|
referrer_balance_pre + difference / Decimal::from(10),
|
||||||
|
referrer_balance_post
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user