You've already forked AstralRinth
forked from didirus/AstralRinth
Enforce 2dp on payout withdrawals (#4829)
* fix mural withdraw amount * Enforce 2dp on all payout logic
This commit is contained in:
@@ -20,10 +20,11 @@ use chrono::{DateTime, Datelike, Duration, NaiveTime, TimeZone, Utc};
|
||||
use dashmap::DashMap;
|
||||
use eyre::{Result, eyre};
|
||||
use futures::TryStreamExt;
|
||||
use modrinth_util::decimal::Decimal2dp;
|
||||
use muralpay::MuralPay;
|
||||
use reqwest::Method;
|
||||
use rust_decimal::prelude::ToPrimitive;
|
||||
use rust_decimal::{Decimal, dec};
|
||||
use rust_decimal::{Decimal, RoundingStrategy, dec};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
@@ -618,7 +619,7 @@ impl PayoutsQueue {
|
||||
&self,
|
||||
request: &PayoutMethodRequest,
|
||||
method_id: &str,
|
||||
amount: Decimal,
|
||||
amount: Decimal2dp,
|
||||
) -> Result<PayoutFees, ApiError> {
|
||||
const MURAL_FEE: Decimal = dec!(0.01);
|
||||
|
||||
@@ -641,8 +642,9 @@ impl PayoutsQueue {
|
||||
..
|
||||
},
|
||||
} => PayoutFees {
|
||||
method_fee: dec!(0),
|
||||
platform_fee: amount * MURAL_FEE,
|
||||
method_fee: Decimal2dp::ZERO,
|
||||
platform_fee: amount
|
||||
.mul_round(MURAL_FEE, RoundingStrategy::AwayFromZero),
|
||||
exchange_rate: None,
|
||||
},
|
||||
PayoutMethodRequest::MuralPay {
|
||||
@@ -667,8 +669,14 @@ impl PayoutsQueue {
|
||||
fee_total,
|
||||
..
|
||||
} => PayoutFees {
|
||||
method_fee: fee_total.token_amount,
|
||||
platform_fee: amount * MURAL_FEE,
|
||||
method_fee: Decimal2dp::rounded(
|
||||
fee_total.token_amount,
|
||||
RoundingStrategy::AwayFromZero,
|
||||
),
|
||||
platform_fee: amount.mul_round(
|
||||
MURAL_FEE,
|
||||
RoundingStrategy::AwayFromZero,
|
||||
),
|
||||
exchange_rate: Some(exchange_rate),
|
||||
},
|
||||
muralpay::TokenPayoutFee::Error { message, .. } => {
|
||||
@@ -680,16 +688,22 @@ impl PayoutsQueue {
|
||||
}
|
||||
PayoutMethodRequest::PayPal | PayoutMethodRequest::Venmo => {
|
||||
let method = get_method.await?;
|
||||
let fee = method.fee.compute_fee(amount);
|
||||
let fee = Decimal2dp::rounded(
|
||||
method.fee.compute_fee(amount),
|
||||
RoundingStrategy::AwayFromZero,
|
||||
);
|
||||
PayoutFees {
|
||||
method_fee: fee,
|
||||
platform_fee: dec!(0),
|
||||
platform_fee: Decimal2dp::ZERO,
|
||||
exchange_rate: None,
|
||||
}
|
||||
}
|
||||
PayoutMethodRequest::Tremendous { method_details } => {
|
||||
let method = get_method.await?;
|
||||
let fee = method.fee.compute_fee(amount);
|
||||
let fee = Decimal2dp::rounded(
|
||||
method.fee.compute_fee(amount),
|
||||
RoundingStrategy::AwayFromZero,
|
||||
);
|
||||
|
||||
let forex: TremendousForexResponse = self
|
||||
.make_tremendous_request(Method::GET, "forex", None::<()>)
|
||||
@@ -718,7 +732,7 @@ impl PayoutsQueue {
|
||||
// we send the request to Tremendous. Afterwards, the method
|
||||
// (Tremendous) will take 0% off the top of our $10.
|
||||
PayoutFees {
|
||||
method_fee: dec!(0),
|
||||
method_fee: Decimal2dp::ZERO,
|
||||
platform_fee: fee,
|
||||
exchange_rate,
|
||||
}
|
||||
@@ -736,19 +750,19 @@ pub struct PayoutFees {
|
||||
/// For example, if a user withdraws $10.00 and the method takes a
|
||||
/// 10% cut, then we submit a payout request of $10.00 to the method,
|
||||
/// and only $9.00 will be sent to the recipient.
|
||||
pub method_fee: Decimal,
|
||||
pub method_fee: Decimal2dp,
|
||||
/// Fee which we keep and don't pass to the underlying method.
|
||||
///
|
||||
/// For example, if a user withdraws $10.00 and the method takes a
|
||||
/// 10% cut, then we submit a payout request of $9.00, and the $1.00 stays
|
||||
/// in our account.
|
||||
pub platform_fee: Decimal,
|
||||
pub platform_fee: Decimal2dp,
|
||||
/// How much is 1 USD worth in the target currency?
|
||||
pub exchange_rate: Option<Decimal>,
|
||||
}
|
||||
|
||||
impl PayoutFees {
|
||||
pub fn total_fee(&self) -> Decimal {
|
||||
pub fn total_fee(&self) -> Decimal2dp {
|
||||
self.method_fee + self.platform_fee
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use ariadne::ids::UserId;
|
||||
use chrono::Utc;
|
||||
use eyre::{Result, eyre};
|
||||
use futures::{StreamExt, TryFutureExt, stream::FuturesUnordered};
|
||||
use modrinth_util::decimal::Decimal2dp;
|
||||
use muralpay::{MuralError, MuralPay, TokenFeeRequest};
|
||||
use rust_decimal::{Decimal, prelude::ToPrimitive};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -35,7 +36,7 @@ pub enum MuralPayoutRequest {
|
||||
impl PayoutsQueue {
|
||||
pub async fn compute_muralpay_fees(
|
||||
&self,
|
||||
amount: Decimal,
|
||||
amount: Decimal2dp,
|
||||
fiat_and_rail_code: muralpay::FiatAndRailCode,
|
||||
) -> Result<muralpay::TokenPayoutFee, ApiError> {
|
||||
let muralpay = self.muralpay.load();
|
||||
@@ -48,7 +49,7 @@ impl PayoutsQueue {
|
||||
.get_fees_for_token_amount(&[TokenFeeRequest {
|
||||
amount: muralpay::TokenAmount {
|
||||
token_symbol: muralpay::USDC.into(),
|
||||
token_amount: amount,
|
||||
token_amount: amount.get(),
|
||||
},
|
||||
fiat_and_rail_code,
|
||||
}])
|
||||
@@ -65,7 +66,7 @@ impl PayoutsQueue {
|
||||
&self,
|
||||
payout_id: DBPayoutId,
|
||||
user_id: UserId,
|
||||
gross_amount: Decimal,
|
||||
gross_amount: Decimal2dp,
|
||||
fees: PayoutFees,
|
||||
payout_details: MuralPayoutRequest,
|
||||
recipient_info: muralpay::PayoutRecipientInfo,
|
||||
@@ -107,9 +108,9 @@ impl PayoutsQueue {
|
||||
|
||||
let recipient_address = recipient_info.physical_address();
|
||||
let recipient_email = recipient_info.email().to_string();
|
||||
let gross_amount_cents = gross_amount * Decimal::from(100);
|
||||
let net_amount_cents = net_amount * Decimal::from(100);
|
||||
let fees_cents = fees.total_fee() * Decimal::from(100);
|
||||
let gross_amount_cents = gross_amount.get() * Decimal::from(100);
|
||||
let net_amount_cents = net_amount.get() * Decimal::from(100);
|
||||
let fees_cents = fees.total_fee().get() * Decimal::from(100);
|
||||
let address_line_3 = format!(
|
||||
"{}, {}, {}",
|
||||
recipient_address.city,
|
||||
@@ -153,7 +154,7 @@ impl PayoutsQueue {
|
||||
|
||||
let payout = muralpay::CreatePayout {
|
||||
amount: muralpay::TokenAmount {
|
||||
token_amount: sent_to_method,
|
||||
token_amount: sent_to_method.get(),
|
||||
token_symbol: muralpay::USDC.into(),
|
||||
},
|
||||
payout_details,
|
||||
|
||||
Reference in New Issue
Block a user