Counted working

This commit is contained in:
Ben Arc 2021-04-05 01:48:35 +01:00
parent 744662fb63
commit f5d06653a6
5 changed files with 103 additions and 50 deletions

View file

@ -50,14 +50,16 @@ async def create_charge(user: str, description: Optional[str] = None, onchainwal
) )
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", """,
(charge_id, user, description, onchainwallet, onchainaddress, lnbitswallet, payment_request, payment_hash, webhook, time, amount, 0, False), (charge_id, user, description, onchainwallet, onchainaddress, lnbitswallet,
payment_request, payment_hash, webhook, time, amount, 0, False),
) )
return await get_charge(charge_id) return await get_charge(charge_id)
async def update_charge(charge_id: str, **kwargs) -> Optional[Charges]: async def update_charge(charge_id: str, **kwargs) -> Optional[Charges]:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
await db.execute(f"UPDATE charges SET {q} WHERE id = ?", (*kwargs.values(), wallet_id)) await db.execute(f"UPDATE charges SET {q} WHERE id = ?", (*kwargs.values(), charge_id))
row = await db.fetchone("SELECT * FROM charges WHERE id = ?", (wallet_id,)) row = await db.fetchone("SELECT * FROM charges WHERE id = ?", (charge_id,))
return Charges.from_row(row) if row else None return Charges.from_row(row) if row else None
@ -74,6 +76,7 @@ async def get_charges(user: str) -> List[Charges]:
async def delete_charge(charge_id: str) -> None: async def delete_charge(charge_id: str) -> None:
await db.execute("DELETE FROM charges WHERE id = ?", (charge_id,)) await db.execute("DELETE FROM charges WHERE id = ?", (charge_id,))
async def check_address_balance(charge_id: str) -> List[Charges]: async def check_address_balance(charge_id: str) -> List[Charges]:
charge = await get_charge(charge_id) charge = await get_charge(charge_id)
if charge.onchainaddress: if charge.onchainaddress:
@ -83,14 +86,14 @@ async def check_address_balance(charge_id: str) -> List[Charges]:
r = await client.get(mempool.endpoint + "/api/address/" + charge.onchainaddress) r = await client.get(mempool.endpoint + "/api/address/" + charge.onchainaddress)
respAmount = r.json()['chain_stats']['funded_txo_sum'] respAmount = r.json()['chain_stats']['funded_txo_sum']
if (charge.balance + respAmount) >= charge.balance: if (charge.balance + respAmount) >= charge.balance:
return await update_charge(charge_id = charge_id, balance = (charge.balance + respAmount), paid = True) return await update_charge(charge_id=charge_id, balance=(charge.balance + respAmount), paid=True)
else: else:
return await update_charge(charge_id = charge_id, balance = (charge.balance + respAmount), paid = False) return await update_charge(charge_id=charge_id, balance=(charge.balance + respAmount), paid=False)
except Exception: except Exception:
pass pass
if charge.lnbitswallet: if charge.lnbitswallet:
invoice_status = await check_invoice_status(charge.lnbitswallet, charge.payment_hash) invoice_status = await check_invoice_status(charge.lnbitswallet, charge.payment_hash)
if invoice_status.paid: if invoice_status.paid:
return await update_charge(charge_id = charge_id, balance = charge.balance, paid = True) return await update_charge(charge_id=charge_id, balance=charge.balance, paid=True)
row = await db.fetchone("SELECT * FROM charges WHERE id = ?", (charge_id,)) row = await db.fetchone("SELECT * FROM charges WHERE id = ?", (charge_id,))
return Charges.from_row(row) if row else None return Charges.from_row(row) if row else None

View file

@ -1,6 +1,7 @@
from sqlite3 import Row from sqlite3 import Row
from typing import NamedTuple from typing import NamedTuple
class Charges(NamedTuple): class Charges(NamedTuple):
id: str id: str
user: str user: str
@ -18,5 +19,5 @@ class Charges(NamedTuple):
timestamp: int timestamp: int
@classmethod @classmethod
def from_row(cls, row: Row) -> "Payments": def from_row(cls, row: Row) -> "Charges":
return cls(**dict(row)) return cls(**dict(row))

View file

@ -41,30 +41,82 @@
</q-card-section> </q-card-section>
</q-card> </q-card>
</q-expansion-item> </q-expansion-item>
<q-expansion-item group="api" dense expand-separator label="Get a pay link"> <q-expansion-item group="api" dense expand-separator label="Update charge">
<q-card> <q-card>
<q-card-section> <q-card-section>
<code <code
><span class="text-blue">GET</span> ><span class="text-blue">PUT</span>
/pay/api/v1/links/&lt;pay_id&gt;</code /satspay/api/v1/charge/&lt;charge_id&gt;</code
> >
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5> <h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"X-Api-Key": &lt;invoice_key&gt;}</code><br /> <code>{"X-Api-Key": &lt;admin_key&gt;}</code><br />
<h5 class="text-caption q-mt-sm q-mb-none"> <h5 class="text-caption q-mt-sm q-mb-none">
Body (application/json) Body (application/json)
</h5> </h5>
<h5 class="text-caption q-mt-sm q-mb-none"> <h5 class="text-caption q-mt-sm q-mb-none">
Returns 201 CREATED (application/json) Returns 200 OK (application/json)
</h5> </h5>
<code>{"lnurl": &lt;string&gt;}</code> <code>[&lt;charge_object&gt;, ...]</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5> <h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code <code
>curl -X GET {{ request.url_root }}pay/api/v1/links/&lt;pay_id&gt; >curl -X POST {{ request.url_root }}api/v1/charge/&lt;charge_id&gt;
-d '{"onchainwallet": &lt;string, watchonly_wallet_id&gt;,
"description": &lt;string&gt;, "webhook":&lt;string&gt;, "time":
&lt;integer&gt;, "amount": &lt;integer&gt;, "lnbitswallet":
&lt;string, lnbits_wallet_id&gt;}' -H "Content-type:
application/json" -H "X-Api-Key: {{g.user.wallets[0].adminkey }}"
</code>
</q-card-section>
</q-card>
</q-expansion-item>
<q-expansion-item group="api" dense expand-separator label="Get charge">
<q-card>
<q-card-section>
<code
><span class="text-blue">GET</span>
/satspay/api/v1/charge/&lt;charge_id&gt;</code
>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"X-Api-Key": &lt;admin_key&gt;}</code><br />
<h5 class="text-caption q-mt-sm q-mb-none">
Body (application/json)
</h5>
<h5 class="text-caption q-mt-sm q-mb-none">
Returns 200 OK (application/json)
</h5>
<code>[&lt;charge_object&gt;, ...]</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code
>curl -X GET {{ request.url_root }}api/v1/charge/&lt;charge_id&gt;
-H "X-Api-Key: {{ g.user.wallets[0].inkey }}" -H "X-Api-Key: {{ g.user.wallets[0].inkey }}"
</code> </code>
</q-card-section> </q-card-section>
</q-card> </q-card>
</q-expansion-item> </q-expansion-item>
<q-expansion-item group="api" dense expand-separator label="Get charges">
<q-card>
<q-card-section>
<code
><span class="text-blue">GET</span> /satspay/api/v1/charges</code
>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"X-Api-Key": &lt;admin_key&gt;}</code><br />
<h5 class="text-caption q-mt-sm q-mb-none">
Body (application/json)
</h5>
<h5 class="text-caption q-mt-sm q-mb-none">
Returns 200 OK (application/json)
</h5>
<code>[&lt;charge_object&gt;, ...]</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code
>curl -X GET {{ request.url_root }}api/v1/charges -H "X-Api-Key: {{
g.user.wallets[0].inkey }}"
</code>
</q-card-section>
</q-card>
</q-expansion-item>
<q-expansion-item <q-expansion-item
group="api" group="api"
dense dense

View file

@ -297,10 +297,10 @@
} }
obj.displayUrl = ['/satspay/', obj.id].join('') obj.displayUrl = ['/satspay/', obj.id].join('')
return obj return obj
} }
new Vue({ new Vue({
el: '#vue', el: '#vue',
mixins: [windowMixin], mixins: [windowMixin],
@ -312,6 +312,7 @@
checker: null, checker: null,
walletLinks: [], walletLinks: [],
ChargeLinks: [], ChargeLinks: [],
ChargeLinksObj: [],
onchainwallet: '', onchainwallet: '',
currentaddress: "", currentaddress: "",
Addresses: { Addresses: {
@ -324,12 +325,7 @@
ChargesTable: { ChargesTable: {
columns: [ columns: [
{
name: 'timeleft',
align: 'left',
label: 'Time left',
field: 'countdown'
},
{ {
name: 'id', name: 'id',
align: 'left', align: 'left',
@ -342,6 +338,12 @@
label: 'Title', label: 'Title',
field: 'description' field: 'description'
}, },
{
name: 'timeleft',
align: 'left',
label: 'Time left',
field: 'date'
},
{ {
name: 'amount', name: 'amount',
align: 'left', align: 'left',
@ -354,6 +356,12 @@
label: 'Balance', label: 'Balance',
field: 'balance' field: 'balance'
}, },
{
name: 'time to pay',
align: 'left',
label: 'Time to Pay',
field: 'time'
},
{ {
name: 'onchain address', name: 'onchain address',
align: 'left', align: 'left',
@ -366,12 +374,6 @@
label: 'LNbits wallet', label: 'LNbits wallet',
field: 'lnbitswallet' field: 'lnbitswallet'
}, },
{
name: 'time to pay',
align: 'left',
label: 'Time to Pay',
field: 'time'
},
], ],
pagination: { pagination: {
rowsPerPage: 10 rowsPerPage: 10
@ -391,19 +393,12 @@
} }
} }
}, },
computed: {
updateCountdowns() {
console.log("whatever")
Object.mapWalletLink(this.data).forEach(row => {
let datem = moment(row.time).format('YYYY-MM-DD HH:mm');
row.countdown = countdown(new Date(datem).getTime()).toString();
})
}
},
methods: { methods: {
updateCountdowns: function () {
setInterval(function(){
}, 1000)
},
getWalletLinks: function () { getWalletLinks: function () {
var self = this var self = this
@ -494,7 +489,7 @@
}, },
sendFormDataCharge: function () { sendFormDataCharge: function () {
var self = this var self = this
var wallet = self.g.user.wallets[0].inkey var wallet = self.g.user.wallets[0].adminkey
var data = self.formDialogCharge.data var data = self.formDialogCharge.data
console.log(data) console.log(data)
data.amount = parseInt(data.amount) data.amount = parseInt(data.amount)
@ -515,7 +510,7 @@
.request( .request(
'PUT', 'PUT',
'/satspay/api/v1/Charge/' + data.id, '/satspay/api/v1/Charge/' + data.id,
wallet.inkey, data) wallet.adminkey, data)
.then(function (response) { .then(function (response) {
self.Charge = _.reject(self.Charge, function (obj) { self.Charge = _.reject(self.Charge, function (obj) {
return obj.id === data.id return obj.id === data.id
@ -654,8 +649,8 @@
} }
}, 5000); }, 5000);
getCharges() getCharges()
var updateCountdowns = this.updateCountdowns
updateCountdowns()
} }
}) })
</script> </script>

View file

@ -10,6 +10,7 @@ from lnbits.decorators import api_check_wallet_key, api_validate_post_request
from lnbits.extensions.satspay import satspay_ext from lnbits.extensions.satspay import satspay_ext
from .crud import ( from .crud import (
create_charge, create_charge,
update_charge,
get_charge, get_charge,
get_charges, get_charges,
delete_charge, delete_charge,
@ -38,7 +39,7 @@ async def api_charge_create_or_update(charge_id=None):
charge = await create_charge(user=g.wallet.user, **g.data) charge = await create_charge(user=g.wallet.user, **g.data)
return jsonify(charge._asdict()), HTTPStatus.CREATED return jsonify(charge._asdict()), HTTPStatus.CREATED
else: else:
charge = await update_charge(user=g.wallet.user, **g.data) charge = await update_charge(charge_id=charge_id, **g.data)
return jsonify(charge._asdict()), HTTPStatus.OK return jsonify(charge._asdict()), HTTPStatus.OK
@ -59,12 +60,13 @@ async def api_charges_retrieve():
@satspay_ext.route("/api/v1/charge/<charge_id>", methods=["GET"]) @satspay_ext.route("/api/v1/charge/<charge_id>", methods=["GET"])
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_charge_retrieve(charge_id): async def api_charge_retrieve(charge_id):
charge = get_charge(charge_id) charge = await get_charge(charge_id)
print(charge)
if not charge: if not charge:
return jsonify({"message": "charge does not exist"}), HTTPStatus.NOT_FOUND return jsonify({"message": "charge does not exist"}), HTTPStatus.NOT_FOUND
return jsonify({charge}), HTTPStatus.OK return jsonify(charge._asdict()), HTTPStatus.OK
@satspay_ext.route("/api/v1/charge/<charge_id>", methods=["DELETE"]) @satspay_ext.route("/api/v1/charge/<charge_id>", methods=["DELETE"])