예제 #1
0
def push_balance(link_id):
    """
    swagger: swagger/core/push-balance.yml
    """
    payload = request.get_json() or {}
    password = payload.get('password')

    wallet = PushWallet.get_or_none(link_id=link_id)
    if not wallet:
        return jsonify({'error': 'Link does not exist'}), HTTPStatus.NOT_FOUND

    if not wallet.auth(password):
        return jsonify({'error':
                        'Incorrect password'}), HTTPStatus.UNAUTHORIZED

    # зарефакторить
    virtual_balance = None if wallet.virtual_balance == '0' else wallet.virtual_balance
    if virtual_balance is not None and not wallet.seen:
        if wallet.sent_from:
            from_w = PushWallet.get(link_id=wallet.sent_from)
            result = send_coins(from_w,
                                wallet.address,
                                amount=to_bip(wallet.virtual_balance),
                                wait=False)
            if result is not True:
                return jsonify({'error':
                                result}), HTTPStatus.INTERNAL_SERVER_ERROR
            wallet.virtual_balance = '0'
            wallet.save()
        else:
            cmp = PushCampaign.get_or_none(id=wallet.campaign_id)
            cmp_wallet = PushWallet.get(link_id=cmp.wallet_link_id)
            result = send_coins(cmp_wallet,
                                wallet.address,
                                amount=to_bip(wallet.virtual_balance),
                                wait=False)
            if result is not True:
                return jsonify({'error':
                                result}), HTTPStatus.INTERNAL_SERVER_ERROR
            wallet.virtual_balance = '0'
            recipient = Recipient.get(wallet_link_id=wallet.link_id)
            recipient.linked_at = datetime.utcnow()
            recipient.save()
            wallet.save()

    if not wallet.seen:
        wallet.seen = True
        wallet.save()
    balance = get_address_balance(wallet.address, virtual=virtual_balance)
    response = {'address': wallet.address, **balance}
    return jsonify(response)
예제 #2
0
def gratz_buy(wallet, product, confirm=True, contact=None, price_fiat=None):
    logging.info(f'Buy gratz product id {product}')
    response = gratz_order_create(product)
    if isinstance(response, str):
        return response
    logging.info(f'  order create response {response}')

    price_bip = response['price_bip']
    if not confirm:
        return {'price_bip': price_bip}
    result = send_coins(wallet,
                        to=response['address'],
                        amount=price_bip,
                        wait=True)
    if isinstance(result, str):
        return result

    order = OrderHistory.create(provider='gratz',
                                product_id=product,
                                price_pip=str(to_pip(price_bip)),
                                address_from=wallet.address,
                                address_to=response['address'],
                                contact=contact)
    result = gratz_order_confirm(response['order_id'])
    logging.info(f'  order confirmation response {result}')

    cat, shop, value = get_full_product_name(product)
    order_name = f'Product ID: {product} (Category: {cat}, Shop: {shop}, value: {value})'
    schedule_gratz_notification(order.id, result, order_name)

    if not result.get('success'):
        return f"Gratz Provider Error: {result['error']}"
    return result
예제 #3
0
def gratz_buy(wallet, product, confirm=True, contact=None):
    logging.info(f'Buy gratz product id {product}')
    response = gratz_order_create(product)
    if isinstance(response, str):
        return response
    logging.info(f'  order create response {response}')

    price_bip = response['price_bip']
    if not confirm:
        return {'price_bip': price_bip}
    result = send_coins(wallet,
                        to=response['address'],
                        amount=price_bip,
                        wait=True)
    if isinstance(result, str):
        return result

    OrderHistory.create(provider='gratz',
                        product_id=product,
                        price_pip=str(to_pip(price_bip)),
                        address_from=wallet.address,
                        address_to=response['address'],
                        contact=contact)
    result = gratz_order_confirm(response['order_id'])
    logging.info(f'  order confirmation response {result}')

    if not result.get('success'):
        return f"Gratz Provider Error: {result['error']}"
    return result
예제 #4
0
def campaign_close(campaign_id):
    decimal.getcontext().rounding = decimal.ROUND_DOWN
    campaign = PushCampaign.get_or_none(id=campaign_id)
    if not campaign:
        return jsonify({'error': 'Campaign not found'}), HTTP_404_NOT_FOUND

    # временно
    # if campaign.status != 'completed':
    #     return jsonify({
    #         'error': f"Can stop only 'completed' campaign. Current status: {campaign.status}"}), HTTP_400_BAD_REQUEST

    confirm = bool(int(request.args.get('confirm', "0")))

    wallet = PushWallet.get(link_id=campaign.wallet_link_id)
    amount_left = round(Decimal(get_balance(wallet.address, bip=True) - 0.01), 4)
    return_address = get_first_transaction(wallet.address)

    if confirm:
        campaign.status = 'closed'
        campaign.save()
        if amount_left > 0:
            result = send_coins(wallet, return_address, amount_left, wait=True)
            # тут скорее всего есть баг - нужно еще виртуальные балансы обнулять
            # иначе с рассылки придет челик, проверит баланс, применит виртуальный
            # и продукт встретит его пятисоткой потому что на балансе кампании 0
            if result is not True:
                return jsonify({'error': result}), HTTP_500_INTERNAL_SERVER_ERROR

    return jsonify({
        'amount_left': float(amount_left) if amount_left >= 0 else 0,
        'return_address': return_address
    })
예제 #5
0
def giftery_buy(wallet: PushWallet, product: int, price_fiat: int, contact: str = None, confirm: bool = True):
    price_bip = 0 if DEV else rub_to_bip(price_fiat)

    if not confirm:
        return {'price_bip': price_bip}

    client = GifteryAPIClient(test=DEV)

    if not DEV:
        balance = client.get_balance()
        if balance < float(price_fiat):
            return 'No balance on merchant account.'

    if not is_email(contact):
        contact = '*****@*****.**'

    try:
        order_id = client.make_order({
            'product_id': product,
            'face': price_fiat,
            'email_to': contact,
            'from': '*****@*****.**',
        })
    except GifteryAPIException as e:
        logging.info(f'GIFTERY EXCEPTION: {e}')
        return 'Product sold out :('

    if not DEV:
        result = send_coins(wallet, to=BIP_WALLET, amount=price_bip, wait=True)
        if isinstance(result, str):
            return result

    code = None
    try:
        code = client.get_code({'queue_id': order_id})
    except GifteryAPIException as e:
        logging.info(f'GIFTERY EXCEPTION {e}')

    OrderHistory.create(
        provider='giftery',
        product_id=product,
        price_pip=price_bip,
        address_from=wallet.address,
        address_to=BIP_WALLET
    )

    return {
        'certificate': current_app.config['BASE_URL'] + url_for('upload.giftery-pdf', order_id=order_id),
        'order_id': order_id,
        'code': code
    }
예제 #6
0
def flatfm_top_up(wallet: PushWallet, amount, profile):
    profile = profile.strip()
    r = requests.post(f'{FLATFM_BASE_URL}/users/wallet/address',
                      json={'user_id': profile})
    response = r.json()
    if 'address' not in response:
        return response.get('error', {}).get(
            'reason', f'Flat.audio profile "{profile}" not found')

    result = send_coins(wallet, response['address'], amount, wait=True)
    if isinstance(result, str):
        return result

    return True
예제 #7
0
def push_resend(
        wallet,
        new_password=None, sender=None, recipient=None, amount=None,
        virtual=None):
    if not amount:
        return 'Amount should be >0'
    virtual_balance = str(to_pip(amount)) if virtual else None
    new_wallet = generate_and_save_wallet(
        sender=sender, recipient=recipient, new_password=new_password,
        virtual_balance=virtual_balance, sent_from=wallet.link_id)
    if not virtual:
        result = send_coins(wallet, new_wallet.address, amount, wait=True)
        if isinstance(result, str):
            return result
    return {'new_link_id': new_wallet.link_id}
예제 #8
0
def bipgame_top_up(wallet: PushWallet, amount):
    gift_code = uuid()
    h = hashlib.sha256()
    h.update(gift_code.encode('utf-8'))
    payload = f'push:{h.hexdigest()}'

    amount_fact = amount - float(estimate_payload_fee(payload, bip=True))
    if amount_fact <= 0:
        return 'Amount is too low'

    result = send_coins(wallet,
                        BIPGAME_ADDRESS,
                        amount_fact,
                        payload=payload,
                        wait=True)
    if isinstance(result, str):
        return result

    return {'link': f'https://bipgame.io/public/push?gift={gift_code}'}
예제 #9
0
def timeloop_top_up(wallet: PushWallet, amount):
    gift_code = uuid()
    h = hashlib.sha256()
    h.update(gift_code.encode('utf-8'))
    payload = h.hexdigest()

    amount_fact = amount - float(estimate_payload_fee(payload, bip=True))
    if amount_fact <= 0:
        return 'Amount is too low'

    result = send_coins(wallet,
                        TIMELOOP_ADDRESS,
                        amount_fact,
                        payload=payload,
                        wait=True)
    if isinstance(result, str):
        return result

    return {'link': f'https://timeloop.games/?gift={gift_code}'}
예제 #10
0
def gift_buy(wallet, product, confirm=True):
    response = gift_order_create(product)
    if isinstance(response, str):
        return response
    price_bip = response['price_bip']

    if not confirm:
        return {'price_bip': price_bip}

    OrderHistory.create(
        provider='gift',
        product_id=product,
        price_pip=str(to_pip(price_bip)),
        address_from=wallet.address,
        address_to=response['address'])

    result = send_coins(wallet, to=response['address'], amount=price_bip, wait=True)
    if isinstance(result, str):
        return result

    return gift_order_confirm(response['order_id'])
예제 #11
0
def unu_top_up(wallet: PushWallet, amount, email=None):
    email = email.strip()
    if not email:
        return 'Email not specified'

    r = requests.post(UNU_BASE_URL,
                      data={
                          'api_key': UNU_API_KEY,
                          'action': 'get_minter_wallet',
                          'email': email
                      })
    r.raise_for_status()
    response = r.json()

    if response['errors']:
        return response['errors']

    result = send_coins(wallet, response['wallet'], amount, wait=True)
    if isinstance(result, str):
        return result

    return True
예제 #12
0
def campaign_close(campaign_id):
    """
    swagger: swagger/sharing/campaign-close.yml
    """
    payload = request.get_json() or {}
    password = payload.get('password')
    confirm = bool(int(request.args.get('confirm', "0")))

    campaign = PushCampaign.get_or_none(id=campaign_id)
    if not campaign:
        return jsonify({'error': 'Campaign not found'}), HTTPStatus.NOT_FOUND
    if not campaign.auth(password):
        return jsonify({'error':
                        'Incorrect password'}), HTTPStatus.UNAUTHORIZED

    decimal.getcontext().rounding = decimal.ROUND_DOWN
    wallet = PushWallet.get(link_id=campaign.wallet_link_id)
    amount_left = round(Decimal(get_balance(wallet.address, bip=True) - 0.01),
                        4)
    return_address = get_first_transaction(wallet.address)

    if confirm:
        campaign.status = 'closed'
        campaign.save()
        if amount_left > 0:
            result = send_coins(wallet, return_address, amount_left, wait=True)
            # тут скорее всего есть баг - нужно еще виртуальные балансы обнулять
            # иначе с рассылки придет челик, проверит баланс, увидит виртуальный
            # и продукт встретит его пятисоткой потому что на балансе кампании 0
            if result is not True:
                return jsonify({'error':
                                result}), HTTPStatus.INTERNAL_SERVER_ERROR

    return jsonify({
        'amount_left': float(amount_left) if amount_left >= 0 else 0,
        'return_address': return_address
    })