def push_user_transfer_confirmation(receive_user, transfer_random_key): try: pusher_client.trigger( 'private-user-{}-{}'.format(current_app.config['DEPLOYMENT_NAME'], receive_user.id), 'payment_confirmed', {'transfer_random_key': transfer_random_key}) except Exception as e: print(e) sentry.captureException()
def push_admin_credit_transfer(transfer): new_transfer = credit_transfer_schema.dump(transfer).data try: pusher_client.trigger(current_app.config['PUSHER_ENV_CHANNEL'], 'credit_transfer', {'credit_transfer': new_transfer}) except Exception as e: print(e) sentry.captureException()
def save_photo_and_check_for_duplicate(url, new_filename, image_id): save_to_s3_from_url(url, new_filename) try: rekognition_task = celery_app.signature( 'worker.celery_tasks.check_for_duplicate_person', args=(new_filename, image_id)) rekognition_task.delay() except Exception as e: print(e) sentry.captureException() pass
def location(self, location): self._location = location if location is not None and location is not '': try: task = {'user_id': self.id, 'address': location} geolocate_task = celery_app.signature( 'worker.celery_tasks.geolocate_address', args=(task, )) geolocate_task.delay() except Exception as e: print(e) sentry.captureException() pass
def ip(self, ip): self._ip = ip if ip is not None: try: task = {'ip_address_id': self.id, 'ip': ip} ip_location_task = celery_app.signature( 'worker.celery_tasks.ip_location', args=(task, )) ip_location_task.delay() except Exception as e: print(e) sentry.captureException() pass
def get_usd_to_satoshi_rate(): blockchain_task = celery_app.signature( 'worker.celery_tasks.get_usd_to_satoshi_rate') result = blockchain_task.apply_async() try: conversion_rate = result.wait(timeout=3, propagate=True, interval=0.5) except Exception as e: print(e) sentry.captureException() raise BlockchainError("Blockchain Error") finally: result.forget() return conversion_rate
def send_blockchain_payload_to_worker(self, is_retry=False): if self.transfer_type == TransferTypeEnum.DISBURSEMENT: if self.recipient_user and self.recipient_user.transfer_card: self.recipient_user.transfer_card.update_transfer_card() master_wallet_approval_status = self.recipient_transfer_account.master_wallet_approval_status elapsed_time('4.3.2: Approval Status calculated') if master_wallet_approval_status in ['NO_REQUEST', 'FAILED']: account_to_approve_pk = self.recipient_transfer_account.blockchain_address.encoded_private_key else: account_to_approve_pk = None blockchain_payload = { 'type': 'DISBURSEMENT', 'credit_transfer_id': self.id, 'transfer_amount': self.transfer_amount, 'recipient': self.recipient_transfer_account.blockchain_address.address, 'account_to_approve_pk': account_to_approve_pk, 'master_wallet_approval_status': master_wallet_approval_status, 'uncompleted_tasks': list(self.uncompleted_blockchain_tasks), 'is_retry': is_retry } elapsed_time('4.3.3: Payload made') elif self.transfer_type == TransferTypeEnum.PAYMENT: if self.recipient_transfer_account: recipient = self.recipient_transfer_account.blockchain_address.address else: recipient = self.recipient_blockchain_address.address try: master_wallet_approval_status = self.recipient_transfer_account.master_wallet_approval_status except AttributeError: master_wallet_approval_status = 'NOT_REQUIRED' if master_wallet_approval_status in ['NO_REQUEST', 'FAILED']: account_to_approve_pk = self.recipient_transfer_account.blockchain_address.encoded_private_key else: account_to_approve_pk = None blockchain_payload = { 'type': 'PAYMENT', 'credit_transfer_id': self.id, 'transfer_amount': self.transfer_amount, 'sender': self.sender_transfer_account.blockchain_address.address, 'recipient': recipient, 'account_to_approve_pk': account_to_approve_pk, 'master_wallet_approval_status': master_wallet_approval_status, 'uncompleted_tasks': list(self.uncompleted_blockchain_tasks), 'is_retry': is_retry } elif self.transfer_type == TransferTypeEnum.WITHDRAWAL: master_wallet_approval_status = self.sender_transfer_account.master_wallet_approval_status if master_wallet_approval_status == 'NO_REQUEST': account_to_approve_pk = self.sender_transfer_account.blockchain_address.encoded_private_key else: account_to_approve_pk = None blockchain_payload = { 'type': 'WITHDRAWAL', 'credit_transfer_id': self.id, 'transfer_amount': self.transfer_amount, 'sender': self.sender_transfer_account.blockchain_address.address, 'recipient': current_app.config['ETH_OWNER_ADDRESS'], 'account_to_approve_pk': account_to_approve_pk, 'master_wallet_approval_status': master_wallet_approval_status, 'uncompleted_tasks': list(self.uncompleted_blockchain_tasks), 'is_retry': is_retry } else: raise InvalidTransferTypeException("Invalid Transfer Type") if not is_retry or len(blockchain_payload['uncompleted_tasks']) > 0: try: blockchain_task = celery_app.signature( 'worker.celery_tasks.make_blockchain_transaction', kwargs={'blockchain_payload': blockchain_payload}) blockchain_task.delay() except Exception as e: print(e) sentry.captureException() pass
def post(self): # get the post data post_data = request.get_json() user = None email = post_data.get('username') or post_data.get('email') password = post_data.get('password') tfa_token = post_data.get('tfa_token') # First try to match email if email: user = User.query.filter_by(email=email).first() #Now try to match the public serial number (comes in under the phone) if not user: public_serial_number_or_phone = post_data.get('phone') user = User.query.filter_by( public_serial_number=public_serial_number_or_phone).first() #Now try to match the phone if not user: phone = proccess_phone_number(post_data.get('phone')) if phone: user = User.query.filter_by(phone=phone).first() if not (email or post_data.get('phone')): responseObject = { 'status': 'fail', 'message': 'No username supplied' } return make_response(jsonify(responseObject)), 401 if post_data.get( 'phone' ) and user and user.one_time_code and not user.is_activated: if user.one_time_code == password: responseObject = { 'status': 'success', 'pin_must_be_set': True, 'message': 'Please set your pin.' } return make_response(jsonify(responseObject)), 200 try: if not user or not user.verify_password(post_data.get('password')): responseObject = { 'status': 'fail', 'message': 'Invalid username or password' } return make_response(jsonify(responseObject)), 401 if not user.is_activated: responseObject = { 'status': 'fail', 'is_activated': False, 'message': 'Account has not been activated. Please check your emails.' } return make_response(jsonify(responseObject)), 401 if post_data.get('deviceInfo'): save_device_info(post_data.get('deviceInfo'), user) db.session.commit() auth_token = user.encode_auth_token() if not auth_token: responseObject = { 'status': 'fail', 'message': 'Invalid username or password' } return make_response(jsonify(responseObject)), 401 # Possible Outcomes: # TFA required, but not set up # TFA enabled, and user does not have valid TFA token # TFA enabled, and user has valid TFA token # TFA not required tfa_response_oject = tfa_logic(user, tfa_token) if tfa_response_oject: tfa_response_oject['auth_token'] = auth_token.decode() return make_response(jsonify(tfa_response_oject)), 401 #Update the last_seen TS for this user user.update_last_seen_ts() responseObject = create_user_response_object( user, auth_token, 'Successfully logged in.') return make_response(jsonify(responseObject)), 200 except Exception as e: sentry.captureException() raise e
def make_payment_transfer(transfer_amount, send_account, receive_account, transfer_use=None, transfer_mode=None, require_sender_approved=True, require_recipient_approved=True, require_sufficient_balance=True, automatically_resolve_complete=True, uuid=None): transfer = create_and_commit_transfer(transfer_amount, send_account=send_account, receive_account=receive_account, uuid=uuid) make_cashout_incentive_transaction = False if transfer_use is not None: usages = [] try: use_ids = transfer_use.split(',') # passed as '3,4' etc. except AttributeError: use_ids = transfer_use for use_id in use_ids: if use_id != 'null': use = models.TransferUsage.query.filter_by(id=use_id).first() if use: usages.append(use.name) if use.is_cashout: make_cashout_incentive_transaction = True else: usages.append('Other') transfer.transfer_use = usages transfer.transfer_mode = transfer_mode transfer.uuid = uuid if require_sender_approved and not transfer.check_sender_is_approved(): message = "Sender {} is not approved".format(send_account) transfer.resolve_as_rejected(message) raise AccountNotApprovedError(message, is_sender=True) if require_recipient_approved and not transfer.check_recipient_is_approved( ): message = "Recipient {} is not approved".format(receive_account) transfer.resolve_as_rejected(message) raise AccountNotApprovedError(message, is_sender=False) if require_sufficient_balance and not transfer.check_sender_has_sufficient_balance( ): message = "Sender {} has insufficient balance".format(send_account) transfer.resolve_as_rejected(message) raise InsufficientBalanceError(message) if automatically_resolve_complete: transfer.resolve_as_completed() pusher.push_admin_credit_transfer(transfer) if make_cashout_incentive_transaction: try: incentive_amount = round( transfer_amount * current_app.config['CASHOUT_INCENTIVE_PERCENT'] / 100) make_disbursement_transfer(incentive_amount, receive_account) except Exception as e: print(e) sentry.captureException() return transfer
def master_wallet_funds_available(allowed_cache_age_seconds=60): """ IF refreshing cash THEN: return: [current blockchain balance] - [all transfers with blockchain state pending or unknown] save to cache: [funds available at last cache], [ID of highest transfer used in cache], [cache creation datetime] ELSE return: [funds available at last cache] - [all non-failed transfers since cache created] :param allowed_cache_age_seconds: how long between checking the blockchain for external funds added or removed :return: amount of funds available """ refresh_cache = False funds_available_cache = red.get('funds_available_cache') try: parsed_cache = json.loads(funds_available_cache) last_updated_datetime = datetime.datetime.fromtimestamp( float(parsed_cache['last_updated'])) earliest_allowed = datetime.datetime.utcnow() - datetime.timedelta( seconds=allowed_cache_age_seconds) if last_updated_datetime < earliest_allowed: refresh_cache = True except Exception as e: refresh_cache = True if refresh_cache: blockchain_task = celery_app.signature( 'worker.celery_tasks.get_master_balance') result = blockchain_task.apply_async() try: master_wallet_balance = result.wait(timeout=6, propagate=True, interval=0.5) except Exception as e: print(e) sentry.captureException() raise BlockchainError("Blockchain Error") finally: result.forget() highest_transfer_id_checked = 0 required_blockchain_statuses = ['PENDING', 'UNKNOWN'] else: cached_funds_available = parsed_cache['cached_funds_available'] highest_transfer_id_checked = parsed_cache[ 'highest_transfer_id_checked'] required_blockchain_statuses = ['PENDING', 'UNKNOWN', 'COMPLETE'] new_dibursements = (models.CreditTransfer.query.filter( models.CreditTransfer.transfer_type == models.TransferTypeEnum.DISBURSEMENT).filter( models.CreditTransfer.transfer_status == models.TransferStatusEnum.COMPLETE).filter( models.CreditTransfer.id > highest_transfer_id_checked ).filter( models.CreditTransfer.created > datetime.datetime.utcnow() - datetime.timedelta(hours=36)).all()) local_disbursement_value = 0 for disbursement in new_dibursements: status = disbursement.blockchain_status if status in required_blockchain_statuses: local_disbursement_value += disbursement.transfer_amount if refresh_cache: balance = master_wallet_balance - local_disbursement_value if len(new_dibursements) > 0: highest_transfer_id_checked = new_dibursements[-1].id else: all_transfers = models.CreditTransfer.query.all() if len(all_transfers) > 0: highest_transfer_id_checked = all_transfers[-1].id else: highest_transfer_id_checked = 0 cache_data = { 'cached_funds_available': balance, 'highest_transfer_id_checked': highest_transfer_id_checked, 'last_updated': datetime.datetime.utcnow().timestamp() } red.set('funds_available_cache', json.dumps(cache_data)) balance = master_wallet_balance - local_disbursement_value return balance else: balance = cached_funds_available - local_disbursement_value return balance