Counted working
This commit is contained in:
parent
744662fb63
commit
f5d06653a6
5 changed files with 103 additions and 50 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
@ -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/<pay_id></code
|
/satspay/api/v1/charge/<charge_id></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": <invoice_key>}</code><br />
|
<code>{"X-Api-Key": <admin_key>}</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": <string>}</code>
|
<code>[<charge_object>, ...]</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/<pay_id>
|
>curl -X POST {{ request.url_root }}api/v1/charge/<charge_id>
|
||||||
|
-d '{"onchainwallet": <string, watchonly_wallet_id>,
|
||||||
|
"description": <string>, "webhook":<string>, "time":
|
||||||
|
<integer>, "amount": <integer>, "lnbitswallet":
|
||||||
|
<string, lnbits_wallet_id>}' -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/<charge_id></code
|
||||||
|
>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
|
||||||
|
<code>{"X-Api-Key": <admin_key>}</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>[<charge_object>, ...]</code>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
||||||
|
<code
|
||||||
|
>curl -X GET {{ request.url_root }}api/v1/charge/<charge_id>
|
||||||
-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": <admin_key>}</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>[<charge_object>, ...]</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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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"])
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue