Example #1
0
async def get_confirmations(method, xpub):
    coin = settings.get_coin(method.currency, xpub)
    invoice_data = await coin.get_request(method.payment_address)
    return min(constants.MAX_CONFIRMATION_WATCH,
               invoice_data.get(
                   "confirmations",
                   0))  # don't store arbitrary number of confirmations
Example #2
0
async def test_create_invoice_and_pay(async_client, token: str, mocker):
    # get an existing wallet
    wallet = await models.Wallet.query.where(models.Wallet.name == "test5"
                                             ).gino.first()
    # create invoice
    r = await async_client.post("/invoices",
                                json={
                                    "store_id": 2,
                                    "price": 9.9
                                },
                                headers={"Authorization": f"Bearer {token}"})
    assert r.status_code == 200
    invoice_id = r.json()["id"]
    invoice = await models.Invoice.get(invoice_id)
    # get payment
    payment_method = await models.PaymentMethod.query.where(
        models.PaymentMethod.invoice_id == invoice_id).gino.first()
    payment_method.coin = settings.get_coin(payment_method.currency,
                                            xpub=wallet.xpub)
    assert not (await models.Invoice.get(invoice_id)).paid_currency
    # mock transaction complete
    mocker.patch.object(payment_method.coin,
                        "get_request",
                        return_value=get_future_return_value(
                            {"status": "complete"}))
    # process invoice
    await tasks.process_invoice(invoice, {}, [payment_method], notify=False)
    # validate invoice paid_currency
    assert (await models.Invoice.get(invoice_id)
            ).paid_currency == payment_method.currency
    await async_client.delete(f"/invoices/{invoice_id}",
                              headers={"Authorization": f"Bearer {token}"})
Example #3
0
async def get_wallet_history(model, response):
    coin = settings.get_coin(model.currency, model.xpub)
    txes = (await coin.history())["transactions"]
    for i in txes:
        response.append({
            "date": i["date"],
            "txid": i["txid"],
            "amount": i["bc_value"]
        })
Example #4
0
async def check_pending(currency):
    async for method, invoice, xpub in iterate_pending_invoices(currency):
        with log_errors():  # issues processing one item
            if invoice.status == InvoiceStatus.EXPIRED:
                continue
            coin = settings.get_coin(method.currency, xpub)
            if method.lightning:
                invoice_data = await coin.get_invoice(method.rhash)
            else:
                invoice_data = await coin.get_request(method.payment_address)
            await mark_invoice_paid(invoice, method, xpub,
                                    invoice_data["status"])
Example #5
0
async def sync_wallet(event, event_data):
    model = await utils.database.get_object(models.Wallet,
                                            event_data["id"],
                                            raise_exception=False)
    if not model:
        return
    coin = settings.get_coin(model.currency, model.xpub)
    balance = await coin.balance()
    logger.info(f"Wallet {model.id} synced, balance: {balance['confirmed']}")
    await utils.redis.publish_message(f"wallet:{model.id}", {
        "status": "success",
        "balance": str(balance["confirmed"])
    })  # convert for json serialization
Example #6
0
async def get_wallet_balances(user):
    show_currency = user.settings.balance_currency
    balances = Decimal()
    rates = {}
    async with utils.database.iterate_helper():
        async for wallet in models.Wallet.query.where(
                models.Wallet.user_id == user.id).gino.iterate():
            coin = settings.get_coin(wallet.currency, wallet.xpub)
            crypto_balance = await get_wallet_balance(coin)
            if wallet.currency in rates:  # pragma: no cover
                rate = rates[wallet.currency]
            else:
                rate = rates[wallet.currency] = await get_rate(
                    coin, show_currency)
            balances += crypto_balance * rate
    return currency_table.normalize(show_currency, balances)
Example #7
0
 async def validate(self, **kwargs):
     await super().validate(**kwargs)
     if "currency" in kwargs:
         coin = settings.get_coin(kwargs["currency"])
         if not await coin.validate_key(kwargs.get("xpub")):
             raise HTTPException(422, "Wallet key invalid")
Example #8
0
    async def add_fields(self):
        from api import utils

        self.balance = await utils.wallets.get_wallet_balance(
            settings.get_coin(self.currency, self.xpub))
Example #9
0
async def get_wallet_coin_by_id(model_id: int, user):
    wallet = await utils.database.get_object(models.Wallet, model_id, user)
    return settings.get_coin(wallet.currency, wallet.xpub)
Example #10
0
async def _create_payment_method(invoice,
                                 wallet,
                                 product,
                                 store,
                                 discounts,
                                 promocode,
                                 lightning=False):
    coin = settings.get_coin(wallet.currency, wallet.xpub)
    discount_id = None
    rate = await coin.rate(invoice.currency)
    if math.isnan(rate):
        rate = await coin.rate(store.default_currency)
    if math.isnan(rate):
        rate = await coin.rate("USD")
    if math.isnan(rate):
        rate = Decimal(1)  # no rate available, no conversion
    price = invoice.price
    if discounts:
        try:
            discount = max(
                filter(
                    lambda x: (not x.currencies or wallet.currency in
                               CommaSeparatedStrings(x.currencies)) and
                    (promocode == x.promocode or not x.promocode),
                    discounts,
                ),
                key=attrgetter("percent"),
            )
            logger.info(
                f"Payment method {wallet.currency} of invoice {invoice.id}: matched discount {discount.id}"
            )
            discount_id = discount.id
            price -= price * (Decimal(discount.percent) / Decimal(100))
        except ValueError:  # no matched discounts
            pass
    request_price = price * (
        (1 - (Decimal(store.checkout_settings.underpaid_percentage) / 100)))
    request_price = currency_table.normalize(wallet.currency,
                                             request_price / rate)
    price = currency_table.normalize(wallet.currency, price / rate)
    method = coin.add_request
    if lightning:  # pragma: no cover
        try:
            await coin.node_id  # check if works
            method = coin.add_invoice
        except errors.LightningUnsupportedError:
            return
    recommended_fee = (await coin.server.recommended_fee(
        store.checkout_settings.recommended_fee_target_blocks)
                       if not lightning else 0)
    recommended_fee = 0 if recommended_fee is None else recommended_fee  # if no rate available, disable it
    recommended_fee = round_up(Decimal(recommended_fee) / 1024,
                               2)  # convert to sat/byte, two decimal places
    data_got = await method(request_price,
                            description=product.name if product else "",
                            expire=invoice.expiration)
    address = data_got["address"] if not lightning else data_got["invoice"]
    url = data_got["URI"] if not lightning else data_got["invoice"]
    node_id = await coin.node_id if lightning else None
    rhash = data_got["rhash"] if lightning else None
    return await models.PaymentMethod.create(
        invoice_id=invoice.id,
        amount=price,
        rate=rate,
        discount=discount_id,
        currency=wallet.currency,
        payment_address=address,
        payment_url=url,
        rhash=rhash,
        lightning=lightning,
        node_id=node_id,
        recommended_fee=recommended_fee,
        confirmations=0,
    )
Example #11
0
 async def validate(self, **kwargs):
     await super().validate(**kwargs)
     currency = kwargs.get("currency", self.currency)
     coin = settings.get_coin(currency)
     if not await coin.validate_key(kwargs.get("xpub")):
         raise HTTPException(422, "Wallet key invalid")