Test balance and referral accounting (#111)
* removed bloom filter temporarily, added some fixes with decimals in payment.rs * balance accounting for a single user (paid and free tier) seems to be ok * fixed some balance accounting * compute_cost reduced back to 0
This commit is contained in:
parent
c37b320286
commit
3f76b08364
@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize};
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: i32,
|
||||
#[sea_orm(unique)]
|
||||
pub tx_hash: String,
|
||||
pub chain_id: u64,
|
||||
#[sea_orm(column_type = "Decimal(Some((20, 10)))")]
|
||||
|
@ -26,7 +26,7 @@ impl MigrationTrait for Migration {
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(IncreaseOnChainBalanceReceipt::ChainId)
|
||||
.big_integer()
|
||||
.big_unsigned()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
@ -37,7 +37,6 @@ impl MigrationTrait for Migration {
|
||||
.col(
|
||||
ColumnDef::new(IncreaseOnChainBalanceReceipt::DepositToUserId)
|
||||
.big_unsigned()
|
||||
.unique_key()
|
||||
.not_null(),
|
||||
)
|
||||
.foreign_key(
|
||||
|
130
scripts/101-balance-referral-stats.sh
Normal file
130
scripts/101-balance-referral-stats.sh
Normal file
@ -0,0 +1,130 @@
|
||||
##################
|
||||
# Run the server
|
||||
##################
|
||||
|
||||
# Keep the proxyd instance running the background (and test that it works)
|
||||
cargo run --release -- proxyd
|
||||
|
||||
# Check if the instance is running
|
||||
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"web3_clientVersion","id":1}' 127.0.0.1:8544
|
||||
|
||||
##################
|
||||
# Login 2 users
|
||||
##################
|
||||
http://127.0.0.1:8544/user/login/0xeB3E928A2E54BE013EF8241d4C9EaF4DfAE94D5a
|
||||
https://www.myetherwallet.com/wallet/sign
|
||||
|
||||
# Use this site to sign a message
|
||||
curl -X POST http://127.0.0.1:8544/user/login \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"address": "0xeb3e928a2e54be013ef8241d4c9eaf4dfae94d5a",
|
||||
"msg": "0x6c6c616d616e6f6465732e636f6d2077616e747320796f7520746f207369676e20696e207769746820796f757220457468657265756d206163636f756e743a0a3078654233453932384132453534424530313345463832343164344339456146344466414539344435610a0af09fa699f09fa699f09fa699f09fa699f09fa6990a0a5552493a2068747470733a2f2f6c6c616d616e6f6465732e636f6d2f0a56657273696f6e3a20310a436861696e2049443a20310a4e6f6e63653a20303148324435424e47584d423539394e3952314a3148575a444e0a4973737565642041743a20323032332d30362d30385430393a32383a31362e36363939335a0a45787069726174696f6e2054696d653a20323032332d30362d30385430393a34383a31362e36363939335a",
|
||||
"sig": "cb85bccbc12619a5b492817ae26f1daea1aff921c5a404c190c5cd371afda9cc299f2685e97c7ca996ab8c2cbb74b8e115a24251bd09a393b628490df65793161b",
|
||||
"version": "3",
|
||||
"signer": "MEW"
|
||||
}'
|
||||
|
||||
# Keys are:
|
||||
# Bearer: 01H2D5CAQJF7P80222P4ZAFQ26
|
||||
# RPC: 01H2D5CAP1KF2NKRS30SGATDSD
|
||||
|
||||
# Now log in the other user using a referral code
|
||||
# Retrieve the referral link
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5CAQJF7P80222P4ZAFQ26" \
|
||||
-X GET "127.0.0.1:8544/user/referral"
|
||||
|
||||
# Referral Code: 01H2D5CMPQKG36WTW1TM21SG28
|
||||
|
||||
|
||||
http://127.0.0.1:8544/user/login/0x762390ae7a3c4D987062a398C1eA8767029AB08E
|
||||
https://www.myetherwallet.com/wallet/sign
|
||||
curl -X POST http://127.0.0.1:8544/user/login \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"address": "0x762390ae7a3c4d987062a398c1ea8767029ab08e",
|
||||
"msg": "0x6c6c616d616e6f6465732e636f6d2077616e747320796f7520746f207369676e20696e207769746820796f757220457468657265756d206163636f756e743a0a3078373632333930616537613363344439383730363261333938433165413837363730323941423038450a0af09fa699f09fa699f09fa699f09fa699f09fa6990a0a5552493a2068747470733a2f2f6c6c616d616e6f6465732e636f6d2f0a56657273696f6e3a20310a436861696e2049443a20310a4e6f6e63653a20303148324435435a314150414e5a505950594d5735415945474d0a4973737565642041743a20323032332d30362d30385430393a32383a35392e3137383533385a0a45787069726174696f6e2054696d653a20323032332d30362d30385430393a34383a35392e3137383533385a",
|
||||
"sig": "af69a53b860bd327c6bb1299439aec70c330aaf9e26cd92c02f4bc2b48b4ebe74fd61b4388ba6ac6a6b83a5e313560d8bbd7877d9eeb416504a3dadca50113621c",
|
||||
"version": "3",
|
||||
"signer": "MEW",
|
||||
"referral_code": "01H2D5CMPQKG36WTW1TM21SG28"
|
||||
}'
|
||||
|
||||
# Keys are:
|
||||
# Bearer: 01H2D5DN564M4Q2T6PETEZY83Q
|
||||
# RPC: 01H2D5DN4D423VR2KFWBZE46TR
|
||||
|
||||
# Check if the referral entry has been made in the database: checked
|
||||
|
||||
# Make a deposit transaction for both parties, and mark them (it does not matter who calls the endpoints)
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5DN564M4Q2T6PETEZY83Q" \
|
||||
-X GET "127.0.0.1:8544/user/balance/0x749788a5766577431a0a4fc8721fd7cb981f55222e073ed17976f0aba5e8818a"
|
||||
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5DN564M4Q2T6PETEZY83Q" \
|
||||
-X GET "127.0.0.1:8544/user/balance/0xd56dee328dfa3bea26c3762834081881e5eff62e77a2b45e72d98016daaeffba"
|
||||
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5DN564M4Q2T6PETEZY83Q" \
|
||||
-X GET "127.0.0.1:8544/user/balance/0xda41f748106d2d1f1bf395e65d07bd9fc507c1eb4fd50c87d8ca1f34cfd536b0"
|
||||
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5DN564M4Q2T6PETEZY83Q" \
|
||||
-X GET "127.0.0.1:8544/user/balance/0x12b38f3456ccb687ead8386c33071bedc23360931b9be672bb444b7ee1927bbe"
|
||||
# This throws an error, because the amount that's provided is 10^(18+12). With USDC (18 decimal points), this would be above 1BN dollars.
|
||||
# I suppose we won't accept shitcoins anytime soone.
|
||||
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5DN564M4Q2T6PETEZY83Q" \
|
||||
-X GET "127.0.0.1:8544/user/balance/0x81022efe36564d737af223e06b9a6c62f29ad7ce2f85dd99f1ea2f2e9a73306e"
|
||||
|
||||
|
||||
# Check the balance for both users now
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5DN564M4Q2T6PETEZY83Q" \
|
||||
-X GET "127.0.0.1:8544/user/balance"
|
||||
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5CAQJF7P80222P4ZAFQ26" \
|
||||
-X GET "127.0.0.1:8544/user/balance"
|
||||
|
||||
# Now we check if the referrals are triggered ...
|
||||
|
||||
# Referred user makes some requests
|
||||
for i in {1..10000}
|
||||
do
|
||||
curl \
|
||||
-X POST "127.0.0.1:8544/rpc/01H2D5CAP1KF2NKRS30SGATDSD" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}'
|
||||
done
|
||||
|
||||
# Let's also make simultaneous requests
|
||||
for i in {1..10000}
|
||||
do
|
||||
curl \
|
||||
-X POST "127.0.0.1:8544/rpc/01H2D5DN4D423VR2KFWBZE46TR" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}'
|
||||
done
|
||||
|
||||
|
||||
# Get some data on the referral items
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5DN564M4Q2T6PETEZY83Q" \
|
||||
-X GET "127.0.0.1:8544/user/referral/stats/used-codes"
|
||||
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5CAQJF7P80222P4ZAFQ26" \
|
||||
-X GET "127.0.0.1:8544/user/referral/stats/used-codes"
|
||||
|
||||
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5DN564M4Q2T6PETEZY83Q" \
|
||||
-X GET "127.0.0.1:8544/user/referral/stats/shared-codes"
|
||||
|
||||
curl \
|
||||
-H "Authorization: Bearer 01H2D5CAQJF7P80222P4ZAFQ26" \
|
||||
-X GET "127.0.0.1:8544/user/referral/stats/shared-codes"
|
@ -168,19 +168,32 @@ pub async fn user_balance_post(
|
||||
let payment_factory_contract =
|
||||
PaymentFactory::new(payment_factory_address, app.internal_provider().clone());
|
||||
|
||||
// check bloom filter to be sure this transaction contains any relevant logs
|
||||
if let Some(ValueOrArray::Value(Some(x))) = payment_factory_contract
|
||||
.payment_received_filter()
|
||||
.filter
|
||||
.topics[0]
|
||||
{
|
||||
let bloom_input = BloomInput::Hash(x.as_fixed_bytes());
|
||||
debug!(
|
||||
"Payment Factor Filter is: {:?}",
|
||||
payment_factory_contract.payment_received_filter()
|
||||
);
|
||||
|
||||
// do a quick check that this transaction contains the required log
|
||||
if !transaction_receipt.logs_bloom.contains_input(bloom_input) {
|
||||
return Err(Web3ProxyError::BadRequest("no matching logs found".into()));
|
||||
}
|
||||
}
|
||||
// check bloom filter to be sure this transaction contains any relevant logs
|
||||
// TODO: This does not work properly right now, get back this eventually
|
||||
// if let Some(ValueOrArray::Value(Some(x))) = payment_factory_contract
|
||||
// .payment_received_filter()
|
||||
// .filter
|
||||
// .topics[0]
|
||||
// {
|
||||
// debug!("Bloom input bytes is: {:?}", x);
|
||||
// debug!("Bloom input bytes is: {:?}", x..as_fixed_bytes());
|
||||
// debug!("Bloom input as hex is: {:?}", hex!(x));
|
||||
// let bloom_input = BloomInput::Raw(hex!(x));
|
||||
// debug!(
|
||||
// "Transaction receipt logs_bloom: {:?}",
|
||||
// transaction_receipt.logs_bloom
|
||||
// );
|
||||
//
|
||||
// // do a quick check that this transaction contains the required log
|
||||
// if !transaction_receipt.logs_bloom.contains_input(x) {
|
||||
// return Err(Web3ProxyError::BadRequest("no matching logs found".into()));
|
||||
// }
|
||||
// }
|
||||
|
||||
// the transaction might contain multiple relevant logs. collect them all
|
||||
let mut response_data = vec![];
|
||||
@ -195,7 +208,6 @@ pub async fn user_balance_post(
|
||||
}
|
||||
|
||||
// Create a new transaction that will be used for joint transaction
|
||||
let txn = db_conn.begin().await?;
|
||||
if let Ok(event) = payment_factory_contract
|
||||
.decode_event::<payment_factory::PaymentReceivedFilter>(
|
||||
"PaymentReceived",
|
||||
@ -224,26 +236,29 @@ pub async fn user_balance_post(
|
||||
// hopefully u32 is always enough, because the Decimal crate doesn't accept a larger scale
|
||||
// <https://eips.ethereum.org/EIPS/eip-20> uses uint8, but i've seen pretty much every int in practice
|
||||
let payment_token_decimals = payment_token.decimals().call().await?.as_u32();
|
||||
|
||||
let decimal_shift = Decimal::from(10).pow(payment_token_decimals as u64);
|
||||
|
||||
let mut payment_token_amount = Decimal::from_str_exact(&payment_token_wei.to_string())?;
|
||||
// Setting the scale already does the decimal shift, no need to divide a second time
|
||||
payment_token_amount.set_scale(payment_token_decimals)?;
|
||||
payment_token_amount /= decimal_shift;
|
||||
|
||||
info!(
|
||||
"Found deposit transaction for: {:?} {:?} {:?}",
|
||||
recipient_account, payment_token_address, payment_token_amount
|
||||
"Found deposit transaction for: {:?} {:?} {:?} {:?}",
|
||||
&recipient_account.to_fixed_bytes(),
|
||||
recipient_account,
|
||||
payment_token_address,
|
||||
payment_token_amount
|
||||
);
|
||||
|
||||
let recipient = match user::Entity::find()
|
||||
.filter(user::Column::Address.eq(recipient_account.encode_hex()))
|
||||
.filter(user::Column::Address.eq(recipient_account.to_fixed_bytes().as_slice()))
|
||||
.one(&db_conn)
|
||||
.await?
|
||||
{
|
||||
Some(x) => x,
|
||||
None => todo!("make their account"),
|
||||
};
|
||||
Some(x) => Ok(x),
|
||||
None => {
|
||||
// todo!("make their account");
|
||||
Err(Web3ProxyError::AccessDenied)
|
||||
}
|
||||
}?;
|
||||
|
||||
// For now we only accept stablecoins
|
||||
// And we hardcode the peg (later we would have to depeg this, for example
|
||||
@ -261,6 +276,7 @@ pub async fn user_balance_post(
|
||||
user_id: sea_orm::Set(recipient.id),
|
||||
..Default::default()
|
||||
};
|
||||
info!("Trying to insert into balance entry: {:?}", balance_entry);
|
||||
balance::Entity::insert(balance_entry)
|
||||
.on_conflict(
|
||||
OnConflict::new()
|
||||
@ -283,6 +299,7 @@ pub async fn user_balance_post(
|
||||
deposit_to_user_id: sea_orm::ActiveValue::Set(recipient.id),
|
||||
..Default::default()
|
||||
};
|
||||
info!("Trying to insert receipt {:?}", receipt);
|
||||
|
||||
receipt.save(&txn).await?;
|
||||
|
||||
|
@ -17,7 +17,7 @@ use derive_more::From;
|
||||
use entities::sea_orm_active_enums::TrackingLevel;
|
||||
use entities::{balance, referee, referrer, rpc_accounting_v2, rpc_key};
|
||||
use influxdb2::models::DataPoint;
|
||||
use log::trace;
|
||||
use log::{debug, trace};
|
||||
use migration::sea_orm::prelude::Decimal;
|
||||
use migration::sea_orm::{
|
||||
self, ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, TransactionTrait,
|
||||
@ -184,12 +184,14 @@ impl RpcQueryStats {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct Deltas {
|
||||
balance_used_outside_free_tier: Decimal,
|
||||
balance_used_including_free_tier: Decimal,
|
||||
sender_bonus_applied: bool,
|
||||
referrer_deposit_delta: Decimal,
|
||||
sender_bonus_balance_deposited: Decimal,
|
||||
balance_spent_including_free_credits: Decimal,
|
||||
balance_spent_excluding_free_credits: Decimal,
|
||||
apply_usage_bonus_to_request_sender: bool,
|
||||
usage_bonus_to_request_sender_through_referral: Decimal,
|
||||
|
||||
bonus_to_referrer: Decimal,
|
||||
}
|
||||
|
||||
/// A stat that we aggregate and then store in a database.
|
||||
@ -375,29 +377,42 @@ impl BufferedRpcQueryStats {
|
||||
referral_objects: Option<(referee::Model, referrer::Model)>,
|
||||
) -> Web3ProxyResult<(Deltas, Option<(referee::Model, referrer::Model)>)> {
|
||||
// Calculate Balance Only
|
||||
let mut deltas = Deltas {
|
||||
balance_used_outside_free_tier: Default::default(),
|
||||
balance_used_including_free_tier: Default::default(),
|
||||
sender_bonus_applied: false,
|
||||
referrer_deposit_delta: Default::default(),
|
||||
sender_bonus_balance_deposited: Default::default(),
|
||||
};
|
||||
let mut deltas = Deltas::default();
|
||||
|
||||
// Calculate a bunch using referrals as well
|
||||
if let Some((referral_entity, referrer_code_entity)) = referral_objects {
|
||||
deltas.sender_bonus_applied = referral_entity.credits_applied_for_referee;
|
||||
deltas.apply_usage_bonus_to_request_sender =
|
||||
referral_entity.credits_applied_for_referee;
|
||||
|
||||
// Calculate if we are above the usage threshold, and apply a bonus
|
||||
// Optimally we would read this from the balance, but if we do it like this, we only have to lock a single table (much safer w.r.t. deadlocks)
|
||||
// referral_entity.credits_applied_for_referrer * (Decimal::from(10) checks (atomically using this table only), whether the user has brought in >$100 to the referer
|
||||
// In this case, the sender receives $100 as a bonus / gift
|
||||
// Apply a 10$ bonus onto the user, if the user has spent 100$
|
||||
debug!(
|
||||
"Were credits applied so far? {:?} {:?}",
|
||||
referral_entity.credits_applied_for_referee,
|
||||
!referral_entity.credits_applied_for_referee
|
||||
);
|
||||
debug!(
|
||||
"Credits applied for referrer so far? {:?}",
|
||||
referral_entity.credits_applied_for_referrer
|
||||
);
|
||||
debug!("Sum credits used? {:?}", self.sum_credits_used);
|
||||
debug!(
|
||||
"Hello: {:?}",
|
||||
(referral_entity.credits_applied_for_referrer * (Decimal::from(10))
|
||||
+ self.sum_credits_used)
|
||||
>= Decimal::from(100)
|
||||
);
|
||||
if !referral_entity.credits_applied_for_referee
|
||||
&& (referral_entity.credits_applied_for_referrer * (Decimal::from(10))
|
||||
+ self.sum_credits_used)
|
||||
>= Decimal::from(100)
|
||||
{
|
||||
deltas.sender_bonus_balance_deposited += Decimal::from(10);
|
||||
deltas.sender_bonus_applied = true;
|
||||
debug!("Adding sender bonus balance");
|
||||
deltas.usage_bonus_to_request_sender_through_referral = Decimal::from(10);
|
||||
deltas.apply_usage_bonus_to_request_sender = true;
|
||||
}
|
||||
|
||||
// Calculate how much the referrer should get, limited to the last 12 months
|
||||
@ -407,24 +422,41 @@ impl BufferedRpcQueryStats {
|
||||
+ Months::new(12);
|
||||
|
||||
if now <= valid_until {
|
||||
deltas.referrer_deposit_delta += self.sum_credits_used / Decimal::new(10, 0);
|
||||
deltas.bonus_to_referrer += self.sum_credits_used / Decimal::new(10, 0);
|
||||
}
|
||||
|
||||
return Ok((deltas, Some((referral_entity, referrer_code_entity))));
|
||||
}
|
||||
// Duplicate code, I should fix this later ...
|
||||
let user_balance = (sender_balance.total_deposits
|
||||
- sender_balance.total_spent_outside_free_tier
|
||||
+ deltas.usage_bonus_to_request_sender_through_referral);
|
||||
|
||||
let user_balance = sender_balance.total_deposits + deltas.sender_bonus_balance_deposited
|
||||
- sender_balance.total_spent_outside_free_tier;
|
||||
// Split up the component of into how much of the paid component was used, and how much of the free component was used (anything after "balance")
|
||||
if user_balance >= Decimal::from(0) {
|
||||
deltas.balance_used_outside_free_tier = self.sum_credits_used;
|
||||
// Split up the component of into how much of the paid component was used, and how much of the free component was used (anything after "balance")
|
||||
if user_balance - self.sum_credits_used >= Decimal::from(0) {
|
||||
deltas.balance_spent_including_free_credits = self.sum_credits_used;
|
||||
deltas.balance_spent_excluding_free_credits = self.sum_credits_used;
|
||||
} else {
|
||||
deltas.balance_spent_including_free_credits = user_balance;
|
||||
deltas.balance_spent_excluding_free_credits = self.sum_credits_used;
|
||||
}
|
||||
|
||||
|
||||
Ok((deltas, Some((referral_entity, referrer_code_entity))))
|
||||
} else {
|
||||
deltas.balance_used_outside_free_tier =
|
||||
user_balance + deltas.sender_bonus_balance_deposited;
|
||||
deltas.balance_used_including_free_tier = self.sum_credits_used;
|
||||
}
|
||||
let user_balance = (sender_balance.total_deposits
|
||||
- sender_balance.total_spent_outside_free_tier
|
||||
+ deltas.usage_bonus_to_request_sender_through_referral);
|
||||
|
||||
Ok((deltas, None))
|
||||
// Split up the component of into how much of the paid component was used, and how much of the free component was used (anything after "balance")
|
||||
if user_balance - self.sum_credits_used >= Decimal::from(0) {
|
||||
deltas.balance_spent_including_free_credits = self.sum_credits_used;
|
||||
deltas.balance_spent_excluding_free_credits = self.sum_credits_used;
|
||||
} else {
|
||||
deltas.balance_spent_including_free_credits = user_balance;
|
||||
deltas.balance_spent_excluding_free_credits = self.sum_credits_used;
|
||||
}
|
||||
|
||||
Ok((deltas, None))
|
||||
}
|
||||
}
|
||||
|
||||
/// Save all referral-based objects in the database
|
||||
@ -435,33 +467,42 @@ impl BufferedRpcQueryStats {
|
||||
sender_rpc_entity: &rpc_key::Model,
|
||||
referral_objects: &Option<(referee::Model, referrer::Model)>,
|
||||
) -> Web3ProxyResult<()> {
|
||||
// Do the user updates
|
||||
// Do the sender balance updates
|
||||
let user_balance = balance::ActiveModel {
|
||||
id: sea_orm::NotSet,
|
||||
total_deposits: sea_orm::Set(deltas.sender_bonus_balance_deposited),
|
||||
total_spent_including_free_tier: sea_orm::Set(deltas.balance_used_including_free_tier),
|
||||
total_spent_outside_free_tier: sea_orm::Set(deltas.balance_used_outside_free_tier),
|
||||
total_deposits: sea_orm::Set(deltas.usage_bonus_to_request_sender_through_referral),
|
||||
total_spent_including_free_tier: sea_orm::Set(
|
||||
deltas.balance_spent_including_free_credits,
|
||||
),
|
||||
total_spent_outside_free_tier: sea_orm::Set(
|
||||
deltas.balance_spent_excluding_free_credits,
|
||||
),
|
||||
user_id: sea_orm::Set(sender_rpc_entity.user_id),
|
||||
};
|
||||
|
||||
// In any case, add to the balance
|
||||
debug!(
|
||||
"Delta is: {:?} from credits used {:?}",
|
||||
deltas, self.sum_credits_used
|
||||
);
|
||||
let _ = balance::Entity::insert(user_balance)
|
||||
.on_conflict(
|
||||
OnConflict::new()
|
||||
.values([
|
||||
(
|
||||
balance::Column::TotalDeposits,
|
||||
Expr::col(balance::Column::TotalDeposits)
|
||||
.add(deltas.sender_bonus_balance_deposited),
|
||||
),
|
||||
(
|
||||
balance::Column::TotalSpentIncludingFreeTier,
|
||||
Expr::col(balance::Column::TotalSpentIncludingFreeTier)
|
||||
.add(deltas.balance_used_including_free_tier),
|
||||
.add(deltas.balance_spent_including_free_credits),
|
||||
),
|
||||
(
|
||||
balance::Column::TotalSpentOutsideFreeTier,
|
||||
Expr::col(balance::Column::TotalSpentOutsideFreeTier)
|
||||
.add(deltas.balance_used_outside_free_tier),
|
||||
.add(deltas.balance_spent_excluding_free_credits),
|
||||
),
|
||||
(
|
||||
balance::Column::TotalDeposits,
|
||||
Expr::col(balance::Column::TotalDeposits)
|
||||
.add(deltas.usage_bonus_to_request_sender_through_referral),
|
||||
),
|
||||
])
|
||||
.to_owned(),
|
||||
@ -471,57 +512,78 @@ impl BufferedRpcQueryStats {
|
||||
|
||||
// Do the referrer_entry updates
|
||||
if let Some((referral_entity, referrer_code_entity)) = referral_objects {
|
||||
if deltas.referrer_deposit_delta > Decimal::from(0) {
|
||||
let referee_entry = referee::ActiveModel {
|
||||
id: sea_orm::Unchanged(referral_entity.id),
|
||||
referral_start_date: sea_orm::Unchanged(referral_entity.referral_start_date),
|
||||
used_referral_code: sea_orm::Unchanged(referral_entity.used_referral_code),
|
||||
user_id: sea_orm::Unchanged(referral_entity.user_id),
|
||||
debug!("Positive referrer deposit delta");
|
||||
let referee_entry = referee::ActiveModel {
|
||||
id: sea_orm::Unchanged(referral_entity.id),
|
||||
credits_applied_for_referee: sea_orm::Set(
|
||||
deltas.apply_usage_bonus_to_request_sender,
|
||||
),
|
||||
credits_applied_for_referrer: sea_orm::Set(deltas.bonus_to_referrer),
|
||||
|
||||
credits_applied_for_referee: sea_orm::Set(deltas.sender_bonus_applied),
|
||||
credits_applied_for_referrer: sea_orm::Set(deltas.referrer_deposit_delta),
|
||||
};
|
||||
referee::Entity::insert(referee_entry)
|
||||
referral_start_date: sea_orm::Unchanged(referral_entity.referral_start_date),
|
||||
used_referral_code: sea_orm::Unchanged(referral_entity.used_referral_code),
|
||||
user_id: sea_orm::Unchanged(referral_entity.user_id),
|
||||
};
|
||||
|
||||
// If there was a referral, first of all check if credits should be applied to the sender itself (once he spent 100$)
|
||||
// If these two values are not equal, that means that we have not applied the bonus just yet.
|
||||
// In that case, we can apply the bonus just now.
|
||||
if referral_entity.credits_applied_for_referee
|
||||
!= deltas.apply_usage_bonus_to_request_sender
|
||||
{
|
||||
referee::Entity::insert(referee_entry.clone())
|
||||
.on_conflict(
|
||||
OnConflict::new()
|
||||
.values([
|
||||
(
|
||||
referee::Column::CreditsAppliedForReferee,
|
||||
// Make it a "Set"
|
||||
Expr::col(referee::Column::CreditsAppliedForReferee)
|
||||
.eq(deltas.sender_bonus_applied),
|
||||
),
|
||||
(
|
||||
referee::Column::CreditsAppliedForReferrer,
|
||||
Expr::col(referee::Column::CreditsAppliedForReferrer)
|
||||
.add(deltas.referrer_deposit_delta),
|
||||
),
|
||||
])
|
||||
.values([(
|
||||
// TODO Make it a "Set", add is hacky (but works ..)
|
||||
referee::Column::CreditsAppliedForReferee,
|
||||
Expr::col(referee::Column::CreditsAppliedForReferee)
|
||||
.add(deltas.apply_usage_bonus_to_request_sender),
|
||||
)])
|
||||
.to_owned(),
|
||||
)
|
||||
.exec(txn)
|
||||
.await?;
|
||||
|
||||
let user_balance = balance::ActiveModel {
|
||||
id: sea_orm::NotSet,
|
||||
total_deposits: sea_orm::Set(deltas.referrer_deposit_delta),
|
||||
user_id: sea_orm::Set(referral_entity.user_id),
|
||||
..Default::default()
|
||||
};
|
||||
// Also add a bonus to the sender (But this should already have been done with the above code!!)
|
||||
}
|
||||
|
||||
let _ = balance::Entity::insert(user_balance)
|
||||
// If the bonus to the referrer is non-empty, also apply that
|
||||
if deltas.bonus_to_referrer > Decimal::from(0) {
|
||||
referee::Entity::insert(referee_entry)
|
||||
.on_conflict(
|
||||
OnConflict::new()
|
||||
.values([(
|
||||
balance::Column::TotalDeposits,
|
||||
Expr::col(balance::Column::TotalDeposits)
|
||||
.add(deltas.referrer_deposit_delta),
|
||||
// TODO Make it a "Set", add is hacky (but works ..)
|
||||
referee::Column::CreditsAppliedForReferrer,
|
||||
Expr::col(referee::Column::CreditsAppliedForReferrer)
|
||||
.add(deltas.bonus_to_referrer),
|
||||
)])
|
||||
.to_owned(),
|
||||
)
|
||||
.exec(txn)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// Finally, add to the balance of the referrer
|
||||
let user_balance = balance::ActiveModel {
|
||||
id: sea_orm::NotSet,
|
||||
total_deposits: sea_orm::Set(deltas.bonus_to_referrer),
|
||||
user_id: sea_orm::Set(referrer_code_entity.user_id),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let _ = balance::Entity::insert(user_balance)
|
||||
.on_conflict(
|
||||
OnConflict::new()
|
||||
.values([(
|
||||
balance::Column::TotalDeposits,
|
||||
Expr::col(balance::Column::TotalDeposits).add(deltas.bonus_to_referrer),
|
||||
)])
|
||||
.to_owned(),
|
||||
)
|
||||
.exec(txn)
|
||||
.await?;
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
@ -560,8 +622,8 @@ impl BufferedRpcQueryStats {
|
||||
let balance_before = *latest_balance;
|
||||
// Now modify the balance
|
||||
// TODO: Double check this (perhaps while testing...)
|
||||
*latest_balance = *latest_balance - deltas.balance_used_outside_free_tier
|
||||
+ deltas.sender_bonus_balance_deposited;
|
||||
*latest_balance = *latest_balance - deltas.balance_spent_including_free_credits
|
||||
+ deltas.usage_bonus_to_request_sender_through_referral;
|
||||
if *latest_balance < Decimal::from(0) {
|
||||
*latest_balance = Decimal::from(0);
|
||||
}
|
||||
@ -823,7 +885,7 @@ impl RpcQueryStats {
|
||||
method: Option<&str>,
|
||||
) -> Decimal {
|
||||
// for now, always return 0 for cost
|
||||
0.into()
|
||||
Decimal::new(0, 1)
|
||||
|
||||
/*
|
||||
// some methods should be free. there might be cases where method isn't set (though they should be uncommon)
|
||||
|
@ -136,14 +136,14 @@ impl StatBuffer {
|
||||
}
|
||||
}
|
||||
_ = db_save_interval.tick() => {
|
||||
// info!("DB save internal tick");
|
||||
info!("DB save internal tick");
|
||||
let count = self.save_relational_stats().await;
|
||||
if count > 0 {
|
||||
trace!("Saved {} stats to the relational db", count);
|
||||
}
|
||||
}
|
||||
_ = tsdb_save_interval.tick() => {
|
||||
// info!("TSDB save internal tick");
|
||||
info!("TSDB save internal tick");
|
||||
let count = self.save_tsdb_stats(&bucket).await;
|
||||
if count > 0 {
|
||||
trace!("Saved {} stats to the tsdb", count);
|
||||
|
Loading…
Reference in New Issue
Block a user