Пример #1
0
def make_deposit_transfer(transfer_amount,
                          token,
                          receive_account,
                          transfer_mode=None,
                          automatically_resolve_complete=True,
                          uuid=None,
                          fiat_ramp=None):
    """
    This is used for a user depositing funds to their Sempo wallet. Only interacts with Sempo float.
    :param transfer_amount:
    :param token:
    :param receive_account:
    :param transfer_mode:
    :param automatically_resolve_complete:
    :param uuid:
    :param fiat_ramp: A FiatRamp Object to tie to credit transfer
    :return:
    """

    transfer = CreditTransfer(amount=transfer_amount,
                              token=token,
                              recipient_user=receive_account,
                              transfer_type=TransferTypeEnum.DEPOSIT, uuid=uuid, fiat_ramp=fiat_ramp)

    transfer.transfer_mode = transfer_mode

    if automatically_resolve_complete:
        transfer.resolve_as_completed()
        pusher.push_admin_credit_transfer(transfer)

    return transfer
Пример #2
0
def make_withdrawal_transfer(transfer_amount,
                             token,
                             send_account,
                             transfer_mode=None,
                             require_sender_approved=True,
                             require_sufficient_balance=True,
                             automatically_resolve_complete=True,
                             uuid=None):
    """
    This is used for a user withdrawing funds from their Sempo wallet. Only interacts with Sempo float.
    :param transfer_amount:
    :param token:
    :param send_account:
    :param transfer_mode:
    :param require_sender_approved:
    :param require_sufficient_balance:
    :param automatically_resolve_complete:
    :param uuid:
    :return:
    """

    transfer = CreditTransfer(transfer_amount,
                              token,
                              sender_user=send_account,
                              uuid=uuid,
                              transfer_type=TransferTypeEnum.WITHDRAWAL)

    transfer.transfer_mode = transfer_mode

    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_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)

    return transfer
Пример #3
0
def create_transfer(amount,
                    sender_user,
                    recipient_user,
                    token,
                    subtype=TransferSubTypeEnum.STANDARD,
                    transfer_usages=None,
                    created_offset=0,
                    transfer_mode=None):
    transfer = CreditTransfer(amount=amount,
                              sender_user=sender_user,
                              recipient_user=recipient_user,
                              token=token,
                              uuid=str(uuid4()))

    db.session.add(transfer)
    # Mimics before_request hook
    g.pending_transactions = []

    if transfer_usages:
        transfer.transfer_usages = transfer_usages

    transfer.resolve_as_complete_and_trigger_blockchain()

    transfer.transfer_type = TransferTypeEnum.PAYMENT
    transfer.transfer_subtype = subtype
    transfer.transfer_mode = transfer_mode

    transfer.created = datetime.utcnow() - timedelta(days=created_offset)

    # Commit to prevent memory errors with large numbers of txns counts
    db.session.commit()

    # Mimic after request hook midway through process
    for transaction, queue in g.pending_transactions:
        transaction.send_blockchain_payload_to_worker(queue=queue)

    return transfer
Пример #4
0
def make_payment_transfer(transfer_amount,
                          token=None,
                          send_user=None,
                          send_transfer_account=None,
                          receive_user=None,
                          receive_transfer_account=None,
                          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_subtype: TransferSubTypeEnum=TransferSubTypeEnum.STANDARD,
                          is_ghost_transfer=False,
                          queue='high-priority'):
    """
    This is used for internal transfers between Sempo wallets.
    :param transfer_amount:
    :param token:
    :param send_user:
    :param send_transfer_account:
    :param receive_user:
    :param receive_transfer_account:
    :param transfer_use:
    :param transfer_mode:
    :param require_sender_approved:
    :param require_recipient_approved:
    :param require_sufficient_balance:
    :param automatically_resolve_complete:
    :param uuid:
    :param transfer_subtype: accepts TransferSubType str.
    :param is_ghost_transfer: if an account is created for recipient just to exchange, it's not real
    :return:
    """

    if transfer_subtype is TransferSubTypeEnum.DISBURSEMENT:
        require_sender_approved = False
        require_recipient_approved = False
        require_sufficient_balance = False
        # primary NGO wallet to disburse from
        send_transfer_account = receive_user.default_organisation.queried_org_level_transfer_account

    if transfer_subtype is TransferSubTypeEnum.RECLAMATION:
        require_sender_approved = False
        # primary NGO wallet to reclaim to
        receive_transfer_account = send_user.default_organisation.queried_org_level_transfer_account

    if transfer_subtype is TransferSubTypeEnum.INCENTIVE:
        send_transfer_account = receive_transfer_account.get_float_transfer_account()

    transfer = CreditTransfer(transfer_amount,
                              token=token,
                              sender_user=send_user,
                              sender_transfer_account=send_transfer_account,
                              recipient_user=receive_user,
                              recipient_transfer_account=receive_transfer_account,
                              uuid=uuid,
                              transfer_type=TransferTypeEnum.PAYMENT,
                              transfer_subtype=transfer_subtype,
                              is_ghost_transfer=is_ghost_transfer)

    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 = TransferUsage.query.get(int(use_id))
                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_transfer_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_user)
        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_transfer_account)
        transfer.resolve_as_rejected(message)
        raise InsufficientBalanceError(message)

    if automatically_resolve_complete:
        transfer.resolve_as_completed(queue=queue)
        pusher.push_admin_credit_transfer(transfer)

    if make_cashout_incentive_transaction:
        try:
            # todo: check limits apply
            incentive_amount = round(transfer_amount * current_app.config['CASHOUT_INCENTIVE_PERCENT'] / 100)

            make_payment_transfer(
                incentive_amount,
                receive_user=receive_user,
                transfer_subtype=TransferSubTypeEnum.INCENTIVE
            )

        except Exception as e:
            print(e)
            sentry_sdk.capture_exception(e)

    return transfer