def update_currency(user: ExchangeUser, currency: str): # We can do this because only 1 currency right now user_limit = UserLimit.objects.filter(user=user).first() if user_limit: if user_limit.fiat_currency != currency: old_currency = user_limit.fiat_currency user_limit.fiat_currency = currency user_limit.usage = RateManagement.convert_currency( user_limit.usage, old_currency, currency) user_limit.limit = RateManagement.convert_currency( user_limit.limit, old_currency, currency) user_limit.save()
def check_cod_limit(user, local_amount, fiat_currency): limit = { FIAT_CURRENCY.USD: { 'min': Decimal('2000'), 'max': Decimal('3000'), }, FIAT_CURRENCY.HKD: { 'min': Decimal('15000'), 'max': Decimal('25000'), }, } data = limit.get(fiat_currency) if data: exchange_user = user.exchange_user if exchange_user.currency != fiat_currency: check_amount = RateManagement.convert_currency( local_amount, exchange_user.currency, fiat_currency) if not (data['min'] <= check_amount <= data['max']): raise CoinUserOverLimitException now = get_now() order = Order.objects.filter( direction=DIRECTION.buy, order_type=ORDER_TYPE.cod, created_at__day=now.day, created_at__month=now.month, created_at__year=now.year, ).first() if order: raise CoinUserOverLimitException else: raise InvalidDataException
def increase_limit(user, amount, currency, direction, fiat_local_amount, fiat_local_currency): # Convert local currency to user currency update_amount = fiat_local_amount if user.currency != fiat_local_currency: update_amount = RateManagement.convert_currency( update_amount, fiat_local_currency, user.currency) UserLimit.objects.filter(user=user, direction=DIRECTION_ALL, fiat_currency=user.currency) \ .update(usage=F('usage') + update_amount, updated_at=get_now()) Pool.objects.filter(direction=direction, currency=currency).update( usage=F('usage') + amount, updated_at=get_now())
def check_user_limit(user, local_price, fiat_currency): # Get user limit to check try: exchange_user = user.exchange_user check_amount = local_price if exchange_user.currency != fiat_currency: check_amount = RateManagement.convert_currency( local_price, exchange_user.currency, fiat_currency) user_limit = UserLimit.objects.get( user=exchange_user, direction=DIRECTION_ALL, fiat_currency=exchange_user.currency) if user_limit.usage + check_amount > user_limit.limit: raise CoinUserOverLimitException except UserLimit.DoesNotExist as e: logging.exception(e) raise InvalidDataException
def decrease_limit(user, amount, currency, direction, fiat_local_amount, fiat_local_currency): # Convert local currency to user currency update_amount = fiat_local_amount if user.currency != fiat_local_currency: update_amount = RateManagement.convert_currency( update_amount, fiat_local_currency, user.currency) user_limit = UserLimit.objects.get(user=user, direction=DIRECTION_ALL, fiat_currency=user.currency) if user_limit.usage < update_amount: user_limit.usage = 0 else: user_limit.usage = F('usage') - update_amount user_limit.save() pool = Pool.objects.get(direction=direction, currency=currency) if pool.usage < amount: pool.usage = 0 else: pool.usage = F('usage') - amount pool.save()
def get_quote(user, params) -> QuoteSerializer: input_serializer = QuoteInputSerializer( data={ 'amount': params.get('amount'), 'currency': params.get('currency'), 'fiat_currency': params.get('fiat_currency', FIAT_CURRENCY.USD), 'pool_check': params.get('check', False), 'user_check': params.get('user_check', False), 'direction': params.get('direction', DIRECTION.buy), }) if input_serializer.is_valid(raise_exception=True): safe_data = input_serializer.validated_data direction = safe_data['direction'] currency = safe_data['currency'] amount = safe_data['amount'] price = QuoteManagement.get_price(direction, safe_data) raw_fiat_amount = amount * price fiat_local_currency = safe_data['fiat_currency'] if safe_data['user_check']: # request.user # User logged in if user and user.is_authenticated: if fiat_local_currency != user.exchange_user.currency: raw_fiat_local_amount = RateManagement.convert_currency( raw_fiat_amount, fiat_local_currency, user.exchange_user.currency) else: raw_fiat_local_amount = RateManagement.convert_to_local_currency( raw_fiat_amount, fiat_local_currency) QuoteManagement.check_user_limit( user, raw_fiat_local_amount, user.exchange_user.currency) else: raise NotAuthenticated if safe_data['pool_check']: QuoteManagement.check_pool(direction, amount, currency) if direction == DIRECTION.buy: fiat_amount, fiat_amount_fee = markup_fee( raw_fiat_amount, FEE_COIN_ORDER_BANK) else: fiat_amount, fiat_amount_fee = markup_fee( raw_fiat_amount, FEE_COIN_SELLING_ORDER_BANK) fiat_local_amount = RateManagement.convert_to_local_currency( fiat_amount, fiat_local_currency) fee_local = RateManagement.convert_to_local_currency( fiat_amount_fee, fiat_local_currency) if direction == DIRECTION.buy: fiat_amount_cod, fiat_amount_fee_cod = markup_fee( raw_fiat_amount, FEE_COIN_ORDER_COD) fiat_local_amount_cod = RateManagement.convert_to_local_currency( fiat_amount_cod, fiat_local_currency) fee_local_cod = RateManagement.convert_to_local_currency( fiat_amount_fee_cod, fiat_local_currency) else: fiat_amount_cod, fiat_amount_fee_cod = markup_fee( raw_fiat_amount, FEE_COIN_SELLING_ORDER_COD) fiat_local_amount_cod = RateManagement.convert_to_local_currency( fiat_amount_cod, fiat_local_currency) fee_local_cod = RateManagement.convert_to_local_currency( fiat_amount_fee_cod, fiat_local_currency) serializer = QuoteSerializer( data={ 'fiat_amount': round_currency(fiat_amount), 'fiat_currency': FIAT_CURRENCY.USD, 'fiat_local_amount': round_currency(fiat_local_amount), 'fiat_local_currency': fiat_local_currency, 'fiat_amount_cod': round_currency(fiat_amount_cod), 'fiat_local_amount_cod': round_currency( fiat_local_amount_cod), 'fee': round_currency(fiat_amount_fee), 'fee_cod': round_currency(fiat_amount_fee_cod), 'fee_local': round_currency(fee_local), 'fee_local_cod': round_currency(fee_local_cod), 'raw_fiat_amount': round_currency(raw_fiat_amount), 'price': round_currency(price), 'amount': round_crypto_currency(amount), 'currency': safe_data['currency'], 'direction': safe_data['direction'] }) serializer.is_valid(raise_exception=True) return serializer
def get_quote_reverse(user, params) -> QuoteReverseSerializer: input_serializer = QuoteReverseInputSerializer( data={ 'fiat_amount': params.get('fiat_amount'), 'currency': params.get('currency'), 'fiat_currency': params.get('fiat_currency', FIAT_CURRENCY.USD), 'pool_check': params.get('check', False), 'user_check': params.get('user_check', False), 'direction': params.get('direction', DIRECTION.buy), 'order_type': params.get('type', ORDER_TYPE.bank) }) order_type = input_serializer.initial_data['order_type'] if order_type not in ORDER_TYPE: raise ValidationError if input_serializer.is_valid(raise_exception=True): safe_data = input_serializer.validated_data direction = safe_data['direction'] currency = safe_data['currency'] fiat_local_amount = safe_data['fiat_amount'] fiat_local_currency = safe_data['fiat_currency'] fiat_amount = RateManagement.convert_from_local_currency( fiat_local_amount, fiat_local_currency) if direction == DIRECTION.buy: if order_type == ORDER_TYPE.bank: raw_fiat_amount, fiat_amount_fee = remove_markup_fee( fiat_amount, FEE_COIN_ORDER_BANK) else: raw_fiat_amount, fiat_amount_fee = remove_markup_fee( fiat_amount, FEE_COIN_ORDER_COD) else: if order_type == ORDER_TYPE.bank: raw_fiat_amount, fiat_amount_fee = remove_markup_fee( fiat_amount, FEE_COIN_SELLING_ORDER_BANK) else: raw_fiat_amount, fiat_amount_fee = remove_markup_fee( fiat_amount, FEE_COIN_SELLING_ORDER_COD) price = QuoteManagement.get_price(direction, safe_data) amount = raw_fiat_amount / price if safe_data['user_check']: # request.user # User logged in if user and user.is_authenticated: if fiat_local_currency != user.exchange_user.currency: raw_fiat_local_amount = RateManagement.convert_currency( raw_fiat_amount, fiat_local_currency, user.exchange_user.currency) else: raw_fiat_local_amount = RateManagement.convert_to_local_currency( raw_fiat_amount, fiat_local_currency) QuoteManagement.check_user_limit( user, raw_fiat_local_amount, user.exchange_user.currency) else: raise NotAuthenticated if safe_data['pool_check']: QuoteManagement.check_pool(direction, amount, currency) fiat_local_amount = RateManagement.convert_to_local_currency( fiat_amount, fiat_local_currency) serializer = QuoteReverseSerializer( data={ 'fiat_amount': round_currency(fiat_amount), 'fiat_currency': FIAT_CURRENCY.USD, 'fiat_local_amount': round_currency(fiat_local_amount), 'fiat_local_currency': fiat_local_currency, 'raw_fiat_amount': round_currency(raw_fiat_amount), 'price': round_currency(price), 'amount': round_crypto_currency(amount), 'currency': safe_data['currency'], 'direction': safe_data['direction'] }) serializer.is_valid(raise_exception=True) return serializer
def create_promotion(order: Order): referrer = order.user.referral user = order.user # Pre-check if user already has bonus if PromotionOrder.objects.filter(user=user, referrer=False).first(): return referrer_promotion = PromotionUser.objects.filter( user=referrer).first() currency = referrer.currency if referrer_promotion: currency = referrer_promotion.currency user_promotion = PromotionUser.objects.filter(user=user).first() # Referral referrer_rule = PromotionRule.objects.filter(country=referrer.country, currency=currency, active=True).first() if referrer_rule: if not referrer_promotion: referrer_promotion = PromotionUser.objects.create( user=referrer, currency=currency, referral_count=0, ) else: # Don't need do anymore if violating below rules if referrer_promotion.referral_count >= referrer_rule.first_referral_count > 0: return if not user_promotion: user_promotion = PromotionUser.objects.create( user=user, currency=user.currency, referral_amount=Decimal('0')) first_referral_count = referrer_promotion.referral_count org_amount = RateManagement.convert_currency( user_promotion.referral_amount, user.currency, referrer_promotion.currency) check_amount = RateManagement.convert_currency( order.fiat_local_amount, order.fiat_local_currency, referrer_promotion.currency) referrer_promotion.referral_count = F('referral_count') + 1 referrer_promotion.save() user_promotion.referral_amount = F( 'referral_amount') + check_amount user_promotion.save() if referrer_rule.first_referral_referrer_bonus > 0 and \ ((referrer_rule.first_referral_count < 0 or first_referral_count + 1 <= referrer_rule.first_referral_count) and org_amount + check_amount >= referrer_rule.first_referral_amount): PromotionOrder.objects.create( order=order, user=referrer, amount=referrer_rule.first_referral_referrer_bonus, currency=referrer_rule.currency, status=REFERRAL_STATUS.pending, referrer=True, note=PROMOTION.referrer) if referrer_rule.first_referral_referee_bonus > 0 and \ org_amount + check_amount >= referrer_rule.first_referral_amount: PromotionOrder.objects.create( order=order, user=user, amount=RateManagement.convert_currency( referrer_rule.first_referral_referee_bonus, referrer_rule.currency, user.currency), currency=user.currency, status=REFERRAL_STATUS.pending, referrer=False, note=PROMOTION.referee)