mirror of
https://github.com/lnbits/lnbits.git
synced 2025-08-08 09:11:56 +02:00
Big, broken refactor payments/addresses to charges
This commit is contained in:
@@ -2,7 +2,7 @@ from typing import List, Optional, Union
|
|||||||
|
|
||||||
#from lnbits.db import open_ext_db
|
#from lnbits.db import open_ext_db
|
||||||
from . import db
|
from . import db
|
||||||
from .models import Wallets, Payments, Addresses, Mempool
|
from .models import Wallets, charges, Addresses, Mempool
|
||||||
|
|
||||||
from lnbits.helpers import urlsafe_short_hash
|
from lnbits.helpers import urlsafe_short_hash
|
||||||
|
|
||||||
@@ -20,46 +20,7 @@ from embit import script
|
|||||||
from embit import ec
|
from embit import ec
|
||||||
from embit.networks import NETWORKS
|
from embit.networks import NETWORKS
|
||||||
from binascii import unhexlify, hexlify, a2b_base64, b2a_base64
|
from binascii import unhexlify, hexlify, a2b_base64, b2a_base64
|
||||||
|
import requests
|
||||||
########################ADDRESSES#######################
|
|
||||||
|
|
||||||
async def get_derive_address(wallet_id: str, num: int):
|
|
||||||
|
|
||||||
wallet = await get_watch_wallet(wallet_id)
|
|
||||||
k = bip32.HDKey.from_base58(str(wallet[2]))
|
|
||||||
child = k.derive([0, num])
|
|
||||||
address = script.p2wpkh(child).address()
|
|
||||||
|
|
||||||
return address
|
|
||||||
|
|
||||||
async def get_fresh_address(wallet_id: str) -> Addresses:
|
|
||||||
wallet = await get_watch_wallet(wallet_id)
|
|
||||||
|
|
||||||
address = await get_derive_address(wallet_id, wallet[4] + 1)
|
|
||||||
|
|
||||||
await update_watch_wallet(wallet_id = wallet_id, address_no = wallet[4] + 1)
|
|
||||||
await db.execute(
|
|
||||||
"""
|
|
||||||
INSERT INTO addresses (
|
|
||||||
address,
|
|
||||||
wallet,
|
|
||||||
amount
|
|
||||||
)
|
|
||||||
VALUES (?, ?, ?)
|
|
||||||
""",
|
|
||||||
(address, wallet_id, 0),
|
|
||||||
)
|
|
||||||
|
|
||||||
return await get_address(address)
|
|
||||||
|
|
||||||
|
|
||||||
async def get_address(address: str) -> Addresses:
|
|
||||||
row = await db.fetchone("SELECT * FROM addresses WHERE address = ?", (address,))
|
|
||||||
return Addresses.from_row(row) if row else None
|
|
||||||
|
|
||||||
async def get_addresses(wallet_id: str) -> List[Addresses]:
|
|
||||||
rows = await db.fetchall("SELECT * FROM addresses WHERE wallet = ?", (wallet_id,))
|
|
||||||
return [Addresses(**row) for row in rows]
|
|
||||||
|
|
||||||
|
|
||||||
##########################WALLETS####################
|
##########################WALLETS####################
|
||||||
@@ -74,7 +35,7 @@ async def create_watch_wallet(*, user: str, masterpub: str, title: str) -> Walle
|
|||||||
masterpub,
|
masterpub,
|
||||||
title,
|
title,
|
||||||
address_no,
|
address_no,
|
||||||
amount
|
balance
|
||||||
)
|
)
|
||||||
VALUES (?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
@@ -106,43 +67,56 @@ async def delete_watch_wallet(wallet_id: str) -> None:
|
|||||||
await db.execute("DELETE FROM wallets WHERE id = ?", (wallet_id,))
|
await db.execute("DELETE FROM wallets WHERE id = ?", (wallet_id,))
|
||||||
|
|
||||||
|
|
||||||
###############PAYMENTS##########################
|
###############charges##########################
|
||||||
|
|
||||||
async def create_payment(*, walletid: str, user: str, title: str, time: str, amount: int) -> Payments:
|
async def create_charge(*, walletid: str, user: str, title: str, time: str, amount: int) -> charges:
|
||||||
|
|
||||||
address = await get_fresh_address(walletid)
|
address = await get_fresh_address(walletid)
|
||||||
payment_id = urlsafe_short_hash()
|
charge_id = urlsafe_short_hash()
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO payments (
|
INSERT INTO charges (
|
||||||
id,
|
id,
|
||||||
user,
|
user,
|
||||||
title,
|
title,
|
||||||
wallet,
|
wallet,
|
||||||
address,
|
address,
|
||||||
time_to_pay,
|
time_to_pay,
|
||||||
amount
|
amount,
|
||||||
|
balance
|
||||||
)
|
)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(payment_id, user, title, walletid, address.address, time, amount),
|
(charge_id, user, title, walletid, address.address, time, amount, 0),
|
||||||
)
|
)
|
||||||
return await get_payment(payment_id)
|
return await get_charge(charge_id)
|
||||||
|
|
||||||
|
|
||||||
async def get_payment(payment_id: str) -> Payments:
|
async def get_charge(charge_id: str) -> charges:
|
||||||
row = await db.fetchone("SELECT * FROM payments WHERE id = ?", (payment_id,))
|
row = await db.fetchone("SELECT * FROM charges WHERE id = ?", (charge_id,))
|
||||||
return Payments.from_row(row) if row else None
|
return charges.from_row(row) if row else None
|
||||||
|
|
||||||
|
|
||||||
async def get_payments(user: str) -> List[Payments]:
|
async def get_charges(user: str) -> List[charges]:
|
||||||
rows = await db.fetchall("SELECT * FROM payments WHERE user = ?", (user,))
|
rows = await db.fetchall("SELECT * FROM charges WHERE user = ?", (user,))
|
||||||
return [Payments.from_row(row) for row in rows]
|
for row in rows:
|
||||||
|
await check_address_balance(row.address)
|
||||||
|
rows = await db.fetchall("SELECT * FROM charges WHERE user = ?", (user,))
|
||||||
|
return [charges.from_row(row) for row in rows]
|
||||||
|
|
||||||
|
|
||||||
async def delete_payment(payment_id: str) -> None:
|
async def delete_charge(charge_id: str) -> None:
|
||||||
await db.execute("DELETE FROM payments WHERE id = ?", (payment_id,))
|
await db.execute("DELETE FROM charges WHERE id = ?", (charge_id,))
|
||||||
|
|
||||||
|
async def check_address_balance(address: str) -> List[Addresses]:
|
||||||
|
address_data = await get_address(address)
|
||||||
|
mempool = await get_mempool(address_data.user)
|
||||||
|
r = requests.get(mempool.endpoint + "/api/address/" + address)
|
||||||
|
amount_paid = r.json()['chain_stats']['funded_txo_sum'] - r.json()['chain_stats']['spent_txo_sum']
|
||||||
|
print(amount_paid)
|
||||||
|
await db.execute("UPDATE addresses SET amount_paid = ? WHERE address = ?", (amount_paid, address))
|
||||||
|
row = await db.fetchone("SELECT * FROM addresses WHERE address = ?", (address,))
|
||||||
|
return Addresses.from_row(row) if row else None
|
||||||
|
|
||||||
######################MEMPOOL#######################
|
######################MEMPOOL#######################
|
||||||
|
|
||||||
|
@@ -10,24 +10,14 @@ async def m001_initial(db):
|
|||||||
masterpub TEXT NOT NULL,
|
masterpub TEXT NOT NULL,
|
||||||
title TEXT NOT NULL,
|
title TEXT NOT NULL,
|
||||||
address_no INTEGER NOT NULL DEFAULT 0,
|
address_no INTEGER NOT NULL DEFAULT 0,
|
||||||
amount INTEGER NOT NULL
|
balance INTEGER NOT NULL
|
||||||
);
|
);
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TABLE IF NOT EXISTS addresses (
|
CREATE TABLE IF NOT EXISTS charges (
|
||||||
address TEXT NOT NULL PRIMARY KEY,
|
|
||||||
wallet TEXT NOT NULL,
|
|
||||||
amount INTEGER NOT NULL
|
|
||||||
);
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
await db.execute(
|
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS payments (
|
|
||||||
id TEXT NOT NULL PRIMARY KEY,
|
id TEXT NOT NULL PRIMARY KEY,
|
||||||
user TEXT,
|
user TEXT,
|
||||||
title TEXT,
|
title TEXT,
|
||||||
@@ -35,7 +25,7 @@ async def m001_initial(db):
|
|||||||
address TEXT NOT NULL,
|
address TEXT NOT NULL,
|
||||||
time_to_pay INTEGER NOT NULL,
|
time_to_pay INTEGER NOT NULL,
|
||||||
amount INTEGER NOT NULL,
|
amount INTEGER NOT NULL,
|
||||||
amount_paid INTEGER DEFAULT 0,
|
balance INTEGER DEFAULT 0,
|
||||||
time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now'))
|
time TIMESTAMP NOT NULL DEFAULT (strftime('%s', 'now'))
|
||||||
);
|
);
|
||||||
"""
|
"""
|
||||||
|
@@ -7,13 +7,13 @@ class Wallets(NamedTuple):
|
|||||||
masterpub: str
|
masterpub: str
|
||||||
title: str
|
title: str
|
||||||
address_no: int
|
address_no: int
|
||||||
amount: int
|
balance: int
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_row(cls, row: Row) -> "Wallets":
|
def from_row(cls, row: Row) -> "Wallets":
|
||||||
return cls(**dict(row))
|
return cls(**dict(row))
|
||||||
|
|
||||||
class Payments(NamedTuple):
|
class Charges(NamedTuple):
|
||||||
id: str
|
id: str
|
||||||
user: str
|
user: str
|
||||||
wallet: str
|
wallet: str
|
||||||
@@ -21,22 +21,13 @@ class Payments(NamedTuple):
|
|||||||
address: str
|
address: str
|
||||||
time_to_pay: str
|
time_to_pay: str
|
||||||
amount: int
|
amount: int
|
||||||
amount_paid: int
|
balance: int
|
||||||
time: int
|
time: int
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_row(cls, row: Row) -> "Payments":
|
def from_row(cls, row: Row) -> "Payments":
|
||||||
return cls(**dict(row))
|
return cls(**dict(row))
|
||||||
|
|
||||||
class Addresses(NamedTuple):
|
|
||||||
address: str
|
|
||||||
wallet: str
|
|
||||||
amount: int
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_row(cls, row: Row) -> "Addresses":
|
|
||||||
return cls(**dict(row))
|
|
||||||
|
|
||||||
class Mempool(NamedTuple):
|
class Mempool(NamedTuple):
|
||||||
user: str
|
user: str
|
||||||
endpoint: str
|
endpoint: str
|
||||||
|
@@ -89,11 +89,11 @@
|
|||||||
size="xs"
|
size="xs"
|
||||||
icon="toll"
|
icon="toll"
|
||||||
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
|
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
|
||||||
@click="formDialogPayment.show = true, formDialogPayment.data.walletid = props.row.id"
|
@click="formDialogCharge.show = true, formDialogCharge.data.walletid = props.row.id"
|
||||||
>
|
>
|
||||||
|
|
||||||
<q-tooltip>
|
<q-tooltip>
|
||||||
Payment link
|
Charge link
|
||||||
</q-tooltip>
|
</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<q-btn
|
<q-btn
|
||||||
@@ -163,10 +163,10 @@
|
|||||||
<q-table
|
<q-table
|
||||||
flat
|
flat
|
||||||
dense
|
dense
|
||||||
:data="paymentLinks"
|
:data="ChargeLinks"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
:columns="PaymentsTable.columns"
|
:columns="ChargesTable.columns"
|
||||||
:pagination.sync="PaymentsTable.pagination"
|
:pagination.sync="ChargesTable.pagination"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
>
|
>
|
||||||
|
|
||||||
@@ -190,6 +190,33 @@
|
|||||||
<q-tr :props="props">
|
<q-tr :props="props">
|
||||||
|
|
||||||
<q-td auto-width>
|
<q-td auto-width>
|
||||||
|
|
||||||
|
<q-icon v-if="props.row.timeleft < 1 && props.row.amount_paid < props.row.amount"
|
||||||
|
#unelevated
|
||||||
|
dense
|
||||||
|
size="xs"
|
||||||
|
name="error"
|
||||||
|
:color="($q.dark.isActive) ? 'red' : 'red'"
|
||||||
|
></q-icon>
|
||||||
|
|
||||||
|
<q-icon v-else-if="props.row.amount_paid > props.row.amount"
|
||||||
|
#unelevated
|
||||||
|
dense
|
||||||
|
size="xs"
|
||||||
|
name="check"
|
||||||
|
:color="($q.dark.isActive) ? 'green' : 'green'"
|
||||||
|
></q-icon>
|
||||||
|
|
||||||
|
<q-icon v-else="props.row.amount_paid < props.row.amount && props.row.timeleft > 1"
|
||||||
|
#unelevated
|
||||||
|
dense
|
||||||
|
size="xs"
|
||||||
|
name="cached"
|
||||||
|
:color="($q.dark.isActive) ? 'blue' : 'blue'"
|
||||||
|
></q-icon>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<q-btn
|
<q-btn
|
||||||
flat
|
flat
|
||||||
dense
|
dense
|
||||||
@@ -208,7 +235,6 @@
|
|||||||
></q-btn>
|
></q-btn>
|
||||||
|
|
||||||
|
|
||||||
</q-td>
|
|
||||||
</q-td>
|
</q-td>
|
||||||
<q-td v-for="col in props.cols" :key="col.name" :props="props" auto-width>
|
<q-td v-for="col in props.cols" :key="col.name" :props="props" auto-width>
|
||||||
<div v-if="col.name == 'id'"></div>
|
<div v-if="col.name == 'id'"></div>
|
||||||
@@ -217,7 +243,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</q-td>
|
</q-td>
|
||||||
|
|
||||||
|
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
{% endraw %}
|
{% endraw %}
|
||||||
@@ -299,14 +324,14 @@
|
|||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
|
|
||||||
<q-dialog v-model="formDialogPayment.show" position="top" @hide="closeFormDialog">
|
<q-dialog v-model="formDialogCharge.show" position="top" @hide="closeFormDialog">
|
||||||
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
||||||
<q-form @submit="sendFormDataPayment" class="q-gutter-md">
|
<q-form @submit="sendFormDataCharge" class="q-gutter-md">
|
||||||
|
|
||||||
<q-input
|
<q-input
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
v-model.trim="formDialogPayment.data.title"
|
v-model.trim="formDialogCharge.data.title"
|
||||||
type="text"
|
type="text"
|
||||||
label="Title"
|
label="Title"
|
||||||
></q-input>
|
></q-input>
|
||||||
@@ -314,7 +339,7 @@
|
|||||||
<q-input
|
<q-input
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
v-model.trim="formDialogPayment.data.amount"
|
v-model.trim="formDialogCharge.data.amount"
|
||||||
type="number"
|
type="number"
|
||||||
label="Amount (sats)"
|
label="Amount (sats)"
|
||||||
></q-input>
|
></q-input>
|
||||||
@@ -322,14 +347,14 @@
|
|||||||
<q-input
|
<q-input
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
v-model.trim="formDialogPayment.data.time"
|
v-model.trim="formDialogCharge.data.time"
|
||||||
type="number"
|
type="number"
|
||||||
label="Time (secs)"
|
label="Time (secs)"
|
||||||
> </q-input>
|
> </q-input>
|
||||||
|
|
||||||
<div class="row q-mt-lg">
|
<div class="row q-mt-lg">
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="formDialogPayment.data.id"
|
v-if="formDialogCharge.data.id"
|
||||||
unelevated
|
unelevated
|
||||||
color="deep-purple"
|
color="deep-purple"
|
||||||
type="submit"
|
type="submit"
|
||||||
@@ -340,8 +365,8 @@
|
|||||||
unelevated
|
unelevated
|
||||||
color="deep-purple"
|
color="deep-purple"
|
||||||
:disable="
|
:disable="
|
||||||
formDialogPayment.data.time == null ||
|
formDialogCharge.data.time == null ||
|
||||||
formDialogPayment.data.amount == null"
|
formDialogCharge.data.amount == null"
|
||||||
type="submit"
|
type="submit"
|
||||||
>Create Paylink</q-btn
|
>Create Paylink</q-btn
|
||||||
>
|
>
|
||||||
@@ -444,7 +469,7 @@
|
|||||||
)
|
)
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
var mapPayment = function (obj) {
|
var mapCharge = function (obj) {
|
||||||
obj._data = _.clone(obj)
|
obj._data = _.clone(obj)
|
||||||
obj.date = Quasar.utils.date.formatDate(
|
obj.date = Quasar.utils.date.formatDate(
|
||||||
new Date(obj.time * 1000),
|
new Date(obj.time * 1000),
|
||||||
@@ -463,7 +488,7 @@
|
|||||||
balance: null,
|
balance: null,
|
||||||
checker: null,
|
checker: null,
|
||||||
walletLinks: [],
|
walletLinks: [],
|
||||||
paymentLinks: [],
|
ChargeLinks: [],
|
||||||
currentaddress: "",
|
currentaddress: "",
|
||||||
Addresses: {
|
Addresses: {
|
||||||
show: false,
|
show: false,
|
||||||
@@ -498,7 +523,7 @@
|
|||||||
rowsPerPage: 10
|
rowsPerPage: 10
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PaymentsTable: {
|
ChargesTable: {
|
||||||
columns: [
|
columns: [
|
||||||
{name: 'id', align: 'left', label: 'ID', field: 'id'},
|
{name: 'id', align: 'left', label: 'ID', field: 'id'},
|
||||||
{
|
{
|
||||||
@@ -510,14 +535,14 @@
|
|||||||
{
|
{
|
||||||
name: 'amount',
|
name: 'amount',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: 'Amount',
|
label: 'Amount to pay',
|
||||||
field: 'amount'
|
field: 'amount'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'balance',
|
name: 'balance',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: 'Paid',
|
label: 'Balance',
|
||||||
field: 'getAddressBalance("1wizSAYSbuyXbt9d8JV8ytm5acqq2TorC")'
|
field: 'amount_paid'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'address',
|
name: 'address',
|
||||||
@@ -528,13 +553,13 @@
|
|||||||
{
|
{
|
||||||
name: 'time to pay',
|
name: 'time to pay',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: 'Time to Pay (secs)',
|
label: 'Time to Pay',
|
||||||
field: 'time_to_pay'
|
field: 'time_to_pay'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'timeleft',
|
name: 'timeleft',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: 'Time left (secs)',
|
label: 'Time left',
|
||||||
field: 'timeleft'
|
field: 'timeleft'
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -542,30 +567,11 @@
|
|||||||
rowsPerPage: 10
|
rowsPerPage: 10
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AddressTable: {
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
name: 'address',
|
|
||||||
align: 'left',
|
|
||||||
label: 'Address',
|
|
||||||
field: 'address'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'amount',
|
|
||||||
align: 'left',
|
|
||||||
label: 'Amount',
|
|
||||||
field: 'amount'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
pagination: {
|
|
||||||
rowsPerPage: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formDialog: {
|
formDialog: {
|
||||||
show: false,
|
show: false,
|
||||||
data: {}
|
data: {}
|
||||||
},
|
},
|
||||||
formDialogPayment: {
|
formDialogCharge: {
|
||||||
show: false,
|
show: false,
|
||||||
data: {}
|
data: {}
|
||||||
},
|
},
|
||||||
@@ -579,45 +585,7 @@
|
|||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
|
|
||||||
getAddresses: function (walletID) {
|
chargeRedirect: function (address){
|
||||||
var self = this
|
|
||||||
|
|
||||||
LNbits.api
|
|
||||||
.request(
|
|
||||||
'GET',
|
|
||||||
'/watchonly/api/v1/addresses/' + walletID,
|
|
||||||
this.g.user.wallets[0].inkey
|
|
||||||
)
|
|
||||||
.then(function (response) {
|
|
||||||
|
|
||||||
self.Addresses.data = response.data
|
|
||||||
self.currentaddress = self.Addresses.data[self.Addresses.data.length - 1].address
|
|
||||||
console.log(self.currentaddress)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
.catch(function (error) {
|
|
||||||
LNbits.utils.notifyApiError(error)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getFreshAddress: function (walletID) {
|
|
||||||
var self = this
|
|
||||||
|
|
||||||
LNbits.api
|
|
||||||
.request(
|
|
||||||
'GET',
|
|
||||||
'/watchonly/api/v1/address/' + walletID,
|
|
||||||
this.g.user.wallets[0].inkey
|
|
||||||
)
|
|
||||||
.then(function (response) {
|
|
||||||
console.log(response.data)
|
|
||||||
self.Addresses.data = response.data
|
|
||||||
self.currentaddress = self.Addresses.data[self.Addresses.data.length - 1].address
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
addressRedirect: function (address){
|
|
||||||
window.location.href = this.mempool.endpoint + "/address/" + address;
|
window.location.href = this.mempool.endpoint + "/address/" + address;
|
||||||
},
|
},
|
||||||
getMempool: function () {
|
getMempool: function () {
|
||||||
@@ -703,14 +671,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getPayments: function () {
|
getCharges: function () {
|
||||||
var self = this
|
var self = this
|
||||||
var getAddressBalance = this.getAddressBalance
|
var getAddressBalance = this.getAddressBalance
|
||||||
|
|
||||||
LNbits.api
|
LNbits.api
|
||||||
.request(
|
.request(
|
||||||
'GET',
|
'GET',
|
||||||
'/watchonly/api/v1/payment',
|
'/watchonly/api/v1/ChargeLinks',
|
||||||
this.g.user.wallets[0].inkey
|
this.g.user.wallets[0].inkey
|
||||||
)
|
)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
@@ -724,67 +692,64 @@
|
|||||||
else{
|
else{
|
||||||
response.data[i].timeleft = timeleft
|
response.data[i].timeleft = timeleft
|
||||||
}
|
}
|
||||||
getAddressBalance("1wizSAYSbuyXbt9d8JV8ytm5acqq2TorC")
|
|
||||||
console.log(this.balance)
|
|
||||||
response.data[i].balance = this.balance
|
|
||||||
|
|
||||||
}
|
}
|
||||||
self.paymentLinks = response.data.map(function (obj) {
|
self.ChargeLinks = response.data.map(function (obj) {
|
||||||
return mapPayment(obj)
|
return mapCharge(obj)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
LNbits.utils.notifyApiError(error)
|
LNbits.utils.notifyApiError(error)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
sendFormDataPayment: function () {
|
sendFormDataCharge: function () {
|
||||||
var self = this
|
var self = this
|
||||||
var wallet = self.g.user.wallets[0]
|
var wallet = self.g.user.wallets[0]
|
||||||
var data = self.formDialogPayment.data
|
var data = self.formDialogCharge.data
|
||||||
data.amount = parseInt(data.amount)
|
data.amount = parseInt(data.amount)
|
||||||
data.time = parseInt(data.time)
|
data.time = parseInt(data.time)
|
||||||
if (data.id) {
|
if (data.id) {
|
||||||
this.updatePayment(wallet, data)
|
this.updateCharge(wallet, data)
|
||||||
} else {
|
} else {
|
||||||
this.createPayment(wallet, data)
|
this.createCharge(wallet, data)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updatePayment: function (wallet, data) {
|
updateCharge: function (wallet, data) {
|
||||||
var self = this
|
var self = this
|
||||||
|
|
||||||
LNbits.api
|
LNbits.api
|
||||||
.request(
|
.request(
|
||||||
'PUT',
|
'PUT',
|
||||||
'/watchonly/api/v1/payment/' + data.id,
|
'/watchonly/api/v1/Charge/' + data.id,
|
||||||
wallet.inkey, data)
|
wallet.inkey, data)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
self.payment = _.reject(self.payment, function (obj) {
|
self.Charge = _.reject(self.Charge, function (obj) {
|
||||||
return obj.id === data.id
|
return obj.id === data.id
|
||||||
})
|
})
|
||||||
self.payment.push(mapPayment(response.data))
|
self.Charge.push(mapCharge(response.data))
|
||||||
self.formDialogPayLink.show = false
|
self.formDialogPayLink.show = false
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
LNbits.utils.notifyApiError(error)
|
LNbits.utils.notifyApiError(error)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
createPayment: function (wallet, data) {
|
createCharge: function (wallet, data) {
|
||||||
var self = this
|
var self = this
|
||||||
|
|
||||||
LNbits.api
|
LNbits.api
|
||||||
.request('POST', '/watchonly/api/v1/payment', wallet.inkey, data)
|
.request('POST', '/watchonly/api/v1/Charge', wallet.inkey, data)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
self.paymentLinks.push(mapPayment(response.data))
|
self.ChargeLinks.push(mapCharge(response.data))
|
||||||
self.formDialogPayment.show = false
|
self.formDialogCharge.show = false
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
LNbits.utils.notifyApiError(error)
|
LNbits.utils.notifyApiError(error)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
deletePayment: function (linkId) {
|
deleteCharge: function (linkId) {
|
||||||
var self = this
|
var self = this
|
||||||
var link = _.findWhere(this.payment, {id: linkId})
|
var link = _.findWhere(this.Charge, {id: linkId})
|
||||||
console.log(self.g.user.wallets[0].adminkey)
|
console.log(self.g.user.wallets[0].adminkey)
|
||||||
LNbits.utils
|
LNbits.utils
|
||||||
.confirmDialog('Are you sure you want to delete this pay link?')
|
.confirmDialog('Are you sure you want to delete this pay link?')
|
||||||
@@ -792,11 +757,11 @@
|
|||||||
LNbits.api
|
LNbits.api
|
||||||
.request(
|
.request(
|
||||||
'DELETE',
|
'DELETE',
|
||||||
'/watchonly/api/v1/payment/' + linkId,
|
'/watchonly/api/v1/Charge/' + linkId,
|
||||||
self.g.user.wallets[0].inkey
|
self.g.user.wallets[0].inkey
|
||||||
)
|
)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
self.payment = _.reject(self.payment, function (obj) {
|
self.Charge = _.reject(self.Charge, function (obj) {
|
||||||
return obj.id === linkId
|
return obj.id === linkId
|
||||||
})})
|
})})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
@@ -804,24 +769,7 @@
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getAddressBalance: function (address) {
|
|
||||||
var self = this
|
|
||||||
|
|
||||||
LNbits.api
|
|
||||||
.request(
|
|
||||||
'GET',
|
|
||||||
'/watchonly/api/v1/mempool/' + address,
|
|
||||||
this.g.user.wallets[0].inkey
|
|
||||||
)
|
|
||||||
.then(function (response) {
|
|
||||||
this.balance = response.data.balance
|
|
||||||
console.log(this.balance)
|
|
||||||
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
LNbits.utils.notifyApiError(error)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
updateWalletLink: function (wallet, data) {
|
updateWalletLink: function (wallet, data) {
|
||||||
var self = this
|
var self = this
|
||||||
|
|
||||||
@@ -886,8 +834,8 @@
|
|||||||
if (this.g.user.wallets.length) {
|
if (this.g.user.wallets.length) {
|
||||||
var getWalletLinks = this.getWalletLinks
|
var getWalletLinks = this.getWalletLinks
|
||||||
getWalletLinks()
|
getWalletLinks()
|
||||||
var getPayments = this.getPayments
|
var getCharges = this.getCharges
|
||||||
getPayments()
|
getCharges()
|
||||||
var getMempool = this.getMempool
|
var getMempool = this.getMempool
|
||||||
getMempool()
|
getMempool()
|
||||||
|
|
||||||
|
@@ -14,7 +14,7 @@ async def index():
|
|||||||
return await render_template("watchonly/index.html", user=g.user)
|
return await render_template("watchonly/index.html", user=g.user)
|
||||||
|
|
||||||
|
|
||||||
@watchonly_ext.route("/<payment_id>")
|
@watchonly_ext.route("/<charge_id>")
|
||||||
async def display(payment_id):
|
async def display(payment_id):
|
||||||
link = get_payment(payment_id) or abort(HTTPStatus.NOT_FOUND, "Pay link does not exist.")
|
link = get_payment(payment_id) or abort(HTTPStatus.NOT_FOUND, "Pay link does not exist.")
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ import hashlib
|
|||||||
from quart import g, jsonify, request, url_for
|
from quart import g, jsonify, request, url_for
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
import httpx
|
import httpx
|
||||||
import requests
|
|
||||||
|
|
||||||
from lnbits.core.crud import get_user
|
from lnbits.core.crud import get_user
|
||||||
from lnbits.decorators import api_check_wallet_key, api_validate_post_request
|
from lnbits.decorators import api_check_wallet_key, api_validate_post_request
|
||||||
@@ -14,10 +14,10 @@ from .crud import (
|
|||||||
get_watch_wallets,
|
get_watch_wallets,
|
||||||
update_watch_wallet,
|
update_watch_wallet,
|
||||||
delete_watch_wallet,
|
delete_watch_wallet,
|
||||||
create_payment,
|
create_charge,
|
||||||
get_payment,
|
get_charge,
|
||||||
get_payments,
|
get_charges,
|
||||||
delete_payment,
|
delete_charge,
|
||||||
create_mempool,
|
create_mempool,
|
||||||
update_mempool,
|
update_mempool,
|
||||||
get_mempool,
|
get_mempool,
|
||||||
@@ -85,67 +85,35 @@ async def api_wallet_delete(wallet_id):
|
|||||||
return jsonify({"deleted": "true"}), HTTPStatus.NO_CONTENT
|
return jsonify({"deleted": "true"}), HTTPStatus.NO_CONTENT
|
||||||
|
|
||||||
|
|
||||||
#############################ADDRESSES##########################
|
#############################CHARGES##########################
|
||||||
|
|
||||||
@watchonly_ext.route("/api/v1/address/<wallet_id>", methods=["GET"])
|
@watchonly_ext.route("/api/v1/charges", methods=["GET"])
|
||||||
@api_check_wallet_key("invoice")
|
@api_check_wallet_key("invoice")
|
||||||
async def api_fresh_address(wallet_id):
|
async def api_charges_retrieve():
|
||||||
await get_fresh_address(wallet_id)
|
|
||||||
|
|
||||||
addresses = await get_addresses(wallet_id)
|
charges = await get_charges(g.wallet.user)
|
||||||
|
if not charges:
|
||||||
return jsonify([address._asdict() for address in addresses]), HTTPStatus.OK
|
|
||||||
|
|
||||||
|
|
||||||
@watchonly_ext.route("/api/v1/addresses/<wallet_id>", methods=["GET"])
|
|
||||||
@api_check_wallet_key("invoice")
|
|
||||||
async def api_get_addresses(wallet_id):
|
|
||||||
print(wallet_id)
|
|
||||||
|
|
||||||
wallet = await get_watch_wallet(wallet_id)
|
|
||||||
|
|
||||||
if not wallet:
|
|
||||||
return jsonify({"message": "wallet does not exist"}), HTTPStatus.NOT_FOUND
|
|
||||||
|
|
||||||
addresses = await get_addresses(wallet_id)
|
|
||||||
|
|
||||||
if not addresses:
|
|
||||||
await get_fresh_address(wallet_id)
|
|
||||||
addresses = await get_addresses(wallet_id)
|
|
||||||
|
|
||||||
return jsonify([address._asdict() for address in addresses]), HTTPStatus.OK
|
|
||||||
|
|
||||||
|
|
||||||
#############################PAYEMENTS##########################
|
|
||||||
|
|
||||||
@watchonly_ext.route("/api/v1/payment", methods=["GET"])
|
|
||||||
@api_check_wallet_key("invoice")
|
|
||||||
async def api_payments_retrieve():
|
|
||||||
|
|
||||||
payments = await get_payments(g.wallet.user)
|
|
||||||
print(payments)
|
|
||||||
if not payments:
|
|
||||||
return (
|
return (
|
||||||
jsonify(""),
|
jsonify(""),
|
||||||
HTTPStatus.OK
|
HTTPStatus.OK
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return jsonify([payment._asdict() for payment in payments]), HTTPStatus.OK
|
return jsonify([charge._asdict() for charge in charges]), HTTPStatus.OK
|
||||||
|
|
||||||
|
|
||||||
@watchonly_ext.route("/api/v1/payment/<payment_id>", methods=["GET"])
|
@watchonly_ext.route("/api/v1/charge/<charge_id>", methods=["GET"])
|
||||||
@api_check_wallet_key("invoice")
|
@api_check_wallet_key("invoice")
|
||||||
async def api_payment_retrieve(payment_id):
|
async def api_charge_retrieve(charge_id):
|
||||||
payment = get_payment(payment_id)
|
charge = get_charge(charge_id)
|
||||||
|
|
||||||
if not payment:
|
if not charge:
|
||||||
return jsonify({"message": "payment does not exist"}), HTTPStatus.NOT_FOUND
|
return jsonify({"message": "charge does not exist"}), HTTPStatus.NOT_FOUND
|
||||||
|
|
||||||
return jsonify({payment}), HTTPStatus.OK
|
return jsonify({charge}), HTTPStatus.OK
|
||||||
|
|
||||||
|
|
||||||
@watchonly_ext.route("/api/v1/payment", methods=["POST"])
|
@watchonly_ext.route("/api/v1/charge", methods=["POST"])
|
||||||
@watchonly_ext.route("/api/v1/payment/<payment_id>", methods=["PUT"])
|
@watchonly_ext.route("/api/v1/charge/<charge_id>", methods=["PUT"])
|
||||||
@api_check_wallet_key("invoice")
|
@api_check_wallet_key("invoice")
|
||||||
@api_validate_post_request(
|
@api_validate_post_request(
|
||||||
schema={
|
schema={
|
||||||
@@ -155,26 +123,26 @@ async def api_payment_retrieve(payment_id):
|
|||||||
"amount": {"type": "integer", "min": 1, "required": True},
|
"amount": {"type": "integer", "min": 1, "required": True},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
async def api_payment_create_or_update(payment_id=None):
|
async def api_charge_create_or_update(charge_id=None):
|
||||||
|
|
||||||
if not payment_id:
|
if not charge_id:
|
||||||
payment = await create_payment(user = g.wallet.user, **g.data)
|
charge = await create_charge(user = g.wallet.user, **g.data)
|
||||||
return jsonify(payment), HTTPStatus.CREATED
|
return jsonify(charge), HTTPStatus.CREATED
|
||||||
|
|
||||||
else:
|
else:
|
||||||
payment = await update_payment(user = g.wallet.user, **g.data)
|
charge = await update_charge(user = g.wallet.user, **g.data)
|
||||||
return jsonify(payment), HTTPStatus.OK
|
return jsonify(charge), HTTPStatus.OK
|
||||||
|
|
||||||
|
|
||||||
@watchonly_ext.route("/api/v1/payment/<payment_id>", methods=["DELETE"])
|
@watchonly_ext.route("/api/v1/charge/<charge_id>", methods=["DELETE"])
|
||||||
@api_check_wallet_key("invoice")
|
@api_check_wallet_key("invoice")
|
||||||
async def api_payment_delete(payment_id):
|
async def api_charge_delete(charge_id):
|
||||||
payment = await get_watch_wallet(payment_id)
|
charge = await get_watch_wallet(charge_id)
|
||||||
|
|
||||||
if not payment:
|
if not charge:
|
||||||
return jsonify({"message": "Wallet link does not exist."}), HTTPStatus.NOT_FOUND
|
return jsonify({"message": "Wallet link does not exist."}), HTTPStatus.NOT_FOUND
|
||||||
|
|
||||||
await delete_watch_wallet(payment_id)
|
await delete_watch_wallet(charge_id)
|
||||||
|
|
||||||
return "", HTTPStatus.NO_CONTENT
|
return "", HTTPStatus.NO_CONTENT
|
||||||
|
|
||||||
@@ -198,13 +166,3 @@ async def api_get_mempool():
|
|||||||
if not mempool:
|
if not mempool:
|
||||||
mempool = await create_mempool(user=g.wallet.user)
|
mempool = await create_mempool(user=g.wallet.user)
|
||||||
return jsonify(mempool._asdict()), HTTPStatus.OK
|
return jsonify(mempool._asdict()), HTTPStatus.OK
|
||||||
|
|
||||||
@watchonly_ext.route("/api/v1/mempool/<address>", methods=["GET"])
|
|
||||||
@api_check_wallet_key("invoice")
|
|
||||||
async def api_get_mempool_address_balance(address):
|
|
||||||
mempool = await get_mempool(g.wallet.user)
|
|
||||||
print(mempool.endpoint)
|
|
||||||
r = requests.get(mempool.endpoint + "/api/address/" + address)
|
|
||||||
balance = r.json()['chain_stats']['funded_txo_sum'] - r.json()['chain_stats']['spent_txo_sum']
|
|
||||||
|
|
||||||
return jsonify({"balance":balance}), HTTPStatus.OK
|
|
Reference in New Issue
Block a user