示例#1
0
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()
示例#2
0
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()
示例#3
0
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
示例#4
0
    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
示例#5
0
    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
示例#6
0
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
示例#7
0
    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
示例#8
0
    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
示例#9
0
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
示例#10
0
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