mirror of
https://github.com/lnbits/lnbits.git
synced 2025-09-25 11:14:02 +02:00
prettier and black
This commit is contained in:
@@ -4,7 +4,8 @@ from lnbits.db import Database
|
|||||||
db = Database("ext_watchonly")
|
db = Database("ext_watchonly")
|
||||||
|
|
||||||
|
|
||||||
watchonly_ext: Blueprint = Blueprint("watchonly", __name__, static_folder="static", template_folder="templates")
|
watchonly_ext: Blueprint = Blueprint(
|
||||||
|
"watchonly", __name__, static_folder="static", template_folder="templates")
|
||||||
|
|
||||||
|
|
||||||
from .views_api import * # noqa
|
from .views_api import * # noqa
|
||||||
|
@@ -24,7 +24,6 @@ from binascii import unhexlify, hexlify, a2b_base64, b2a_base64
|
|||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##########################WALLETS####################
|
##########################WALLETS####################
|
||||||
|
|
||||||
async def create_watch_wallet(*, user: str, masterpub: str, title: str) -> Wallets:
|
async def create_watch_wallet(*, user: str, masterpub: str, title: str) -> Wallets:
|
||||||
@@ -43,7 +42,7 @@ async def create_watch_wallet(*, user: str, masterpub: str, title: str) -> Walle
|
|||||||
""",
|
""",
|
||||||
(wallet_id, user, masterpub, title, 0, 0),
|
(wallet_id, user, masterpub, title, 0, 0),
|
||||||
)
|
)
|
||||||
# weallet_id = db.cursor.lastrowid
|
# weallet_id = db.cursor.lastrowid
|
||||||
|
|
||||||
return await get_watch_wallet(wallet_id)
|
return await get_watch_wallet(wallet_id)
|
||||||
|
|
||||||
@@ -57,6 +56,7 @@ async def get_watch_wallets(user: str) -> List[Wallets]:
|
|||||||
rows = await db.fetchall("SELECT * FROM wallets WHERE user = ?", (user,))
|
rows = await db.fetchall("SELECT * FROM wallets WHERE user = ?", (user,))
|
||||||
return [Wallets(**row) for row in rows]
|
return [Wallets(**row) for row in rows]
|
||||||
|
|
||||||
|
|
||||||
async def update_watch_wallet(wallet_id: str, **kwargs) -> Optional[Wallets]:
|
async def update_watch_wallet(wallet_id: str, **kwargs) -> Optional[Wallets]:
|
||||||
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
|
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
|
||||||
|
|
||||||
@@ -70,13 +70,14 @@ async def delete_watch_wallet(wallet_id: str) -> None:
|
|||||||
|
|
||||||
########################ADDRESSES#######################
|
########################ADDRESSES#######################
|
||||||
|
|
||||||
|
|
||||||
async def get_derive_address(wallet_id: str, num: int):
|
async def get_derive_address(wallet_id: str, num: int):
|
||||||
|
|
||||||
wallet = await get_watch_wallet(wallet_id)
|
wallet = await get_watch_wallet(wallet_id)
|
||||||
key = wallet[2]
|
key = wallet[2]
|
||||||
k = bip32.HDKey.from_base58(key)
|
k = bip32.HDKey.from_base58(key)
|
||||||
child = k.derive([0, num])
|
child = k.derive([0, num])
|
||||||
|
|
||||||
if key[0:4] == "xpub":
|
if key[0:4] == "xpub":
|
||||||
address = script.p2pkh(child).address()
|
address = script.p2pkh(child).address()
|
||||||
elif key[0:4] == "zpub":
|
elif key[0:4] == "zpub":
|
||||||
@@ -86,12 +87,13 @@ async def get_derive_address(wallet_id: str, num: int):
|
|||||||
|
|
||||||
return address
|
return address
|
||||||
|
|
||||||
|
|
||||||
async def get_fresh_address(wallet_id: str) -> Addresses:
|
async def get_fresh_address(wallet_id: str) -> Addresses:
|
||||||
wallet = await get_watch_wallet(wallet_id)
|
wallet = await get_watch_wallet(wallet_id)
|
||||||
|
|
||||||
address = await get_derive_address(wallet_id, wallet[4] + 1)
|
address = await get_derive_address(wallet_id, wallet[4] + 1)
|
||||||
|
|
||||||
await update_watch_wallet(wallet_id = wallet_id, address_no = wallet[4] + 1)
|
await update_watch_wallet(wallet_id=wallet_id, address_no=wallet[4] + 1)
|
||||||
masterpub_id = urlsafe_short_hash()
|
masterpub_id = urlsafe_short_hash()
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"""
|
"""
|
||||||
@@ -113,12 +115,14 @@ async def get_address(address: str) -> Addresses:
|
|||||||
row = await db.fetchone("SELECT * FROM addresses WHERE address = ?", (address,))
|
row = await db.fetchone("SELECT * FROM addresses WHERE address = ?", (address,))
|
||||||
return Addresses.from_row(row) if row else None
|
return Addresses.from_row(row) if row else None
|
||||||
|
|
||||||
|
|
||||||
async def get_addresses(wallet_id: str) -> List[Addresses]:
|
async def get_addresses(wallet_id: str) -> List[Addresses]:
|
||||||
rows = await db.fetchall("SELECT * FROM addresses WHERE wallet = ?", (wallet_id,))
|
rows = await db.fetchall("SELECT * FROM addresses WHERE wallet = ?", (wallet_id,))
|
||||||
return [Addresses(**row) for row in rows]
|
return [Addresses(**row) for row in rows]
|
||||||
|
|
||||||
######################MEMPOOL#######################
|
######################MEMPOOL#######################
|
||||||
|
|
||||||
|
|
||||||
async def create_mempool(user: str) -> Mempool:
|
async def create_mempool(user: str) -> Mempool:
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"""
|
"""
|
||||||
@@ -133,6 +137,7 @@ async def create_mempool(user: str) -> Mempool:
|
|||||||
row = await db.fetchone("SELECT * FROM mempool WHERE user = ?", (user,))
|
row = await db.fetchone("SELECT * FROM mempool WHERE user = ?", (user,))
|
||||||
return Mempool.from_row(row) if row else None
|
return Mempool.from_row(row) if row else None
|
||||||
|
|
||||||
|
|
||||||
async def update_mempool(user: str, **kwargs) -> Optional[Mempool]:
|
async def update_mempool(user: str, **kwargs) -> Optional[Mempool]:
|
||||||
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
|
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
|
||||||
|
|
||||||
|
@@ -25,7 +25,7 @@ async def m001_initial(db):
|
|||||||
);
|
);
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TABLE IF NOT EXISTS mempool (
|
CREATE TABLE IF NOT EXISTS mempool (
|
||||||
@@ -33,4 +33,4 @@ async def m001_initial(db):
|
|||||||
endpoint TEXT NOT NULL
|
endpoint TEXT NOT NULL
|
||||||
);
|
);
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
from sqlite3 import Row
|
from sqlite3 import Row
|
||||||
from typing import NamedTuple
|
from typing import NamedTuple
|
||||||
|
|
||||||
|
|
||||||
class Wallets(NamedTuple):
|
class Wallets(NamedTuple):
|
||||||
id: str
|
id: str
|
||||||
user: str
|
user: str
|
||||||
@@ -17,11 +18,12 @@ class Wallets(NamedTuple):
|
|||||||
class Mempool(NamedTuple):
|
class Mempool(NamedTuple):
|
||||||
user: str
|
user: str
|
||||||
endpoint: str
|
endpoint: str
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_row(cls, row: Row) -> "Mempool":
|
def from_row(cls, row: Row) -> "Mempool":
|
||||||
return cls(**dict(row))
|
return cls(**dict(row))
|
||||||
|
|
||||||
|
|
||||||
class Addresses(NamedTuple):
|
class Addresses(NamedTuple):
|
||||||
id: str
|
id: str
|
||||||
address: str
|
address: str
|
||||||
@@ -30,4 +32,4 @@ class Addresses(NamedTuple):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_row(cls, row: Row) -> "Addresses":
|
def from_row(cls, row: Row) -> "Addresses":
|
||||||
return cls(**dict(row))
|
return cls(**dict(row))
|
||||||
|
@@ -1,196 +1,244 @@
|
|||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<p>Watch Only extension uses mempool.space<br />
|
<p>
|
||||||
For use with "account Extended Public Key" <a href="https://iancoleman.io/bip39/">https://iancoleman.io/bip39/</a>
|
Watch Only extension uses mempool.space<br />
|
||||||
<small>
|
For use with "account Extended Public Key"
|
||||||
<br />Created by, <a target="_blank" href="https://github.com/arcbtc">Ben Arc</a> (using, <a target="_blank" href="https://github.com/diybitcoinhardware/embit">Embit</a></small
|
<a href="https://iancoleman.io/bip39/">https://iancoleman.io/bip39/</a>
|
||||||
>)
|
<small>
|
||||||
</p>
|
<br />Created by,
|
||||||
</q-card-section>
|
<a target="_blank" href="https://github.com/arcbtc">Ben Arc</a> (using,
|
||||||
|
<a target="_blank" href="https://github.com/diybitcoinhardware/embit"
|
||||||
|
>Embit</a
|
||||||
|
></small
|
||||||
|
>)
|
||||||
|
</p>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<q-expansion-item
|
|
||||||
group="extras"
|
|
||||||
icon="swap_vertical_circle"
|
|
||||||
label="API info"
|
|
||||||
:content-inset-level="0.5"
|
|
||||||
>
|
|
||||||
<q-expansion-item group="api" dense expand-separator label="List wallets">
|
|
||||||
<q-card>
|
|
||||||
<q-card-section>
|
|
||||||
<code><span class="text-blue">GET</span> /watchonly/api/v1/wallet</code>
|
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
|
|
||||||
<code>{"X-Api-Key": <invoice_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>[<wallets_object>, ...]</code>
|
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
|
||||||
<code
|
|
||||||
>curl -X GET {{ request.url_root }}api/v1/wallet -H "X-Api-Key: {{
|
|
||||||
g.user.wallets[0].inkey }}"
|
|
||||||
</code>
|
|
||||||
</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
</q-expansion-item>
|
|
||||||
<q-expansion-item group="api" dense expand-separator label="Get wallet details">
|
|
||||||
<q-card>
|
|
||||||
<q-card-section>
|
|
||||||
<code
|
|
||||||
><span class="text-blue">GET</span>
|
|
||||||
/watchonly/api/v1/wallet/<wallet_id></code
|
|
||||||
>
|
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
|
|
||||||
<code>{"X-Api-Key": <invoice_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 201 CREATED (application/json)
|
|
||||||
</h5>
|
|
||||||
<code>[<wallet_object>, ...]</code>
|
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
|
||||||
<code
|
|
||||||
>curl -X GET {{ request.url_root }}api/v1/wallet/<wallet_id> -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="extras"
|
||||||
dense
|
icon="swap_vertical_circle"
|
||||||
expand-separator
|
label="API info"
|
||||||
label="Create wallet"
|
:content-inset-level="0.5"
|
||||||
>
|
>
|
||||||
<q-card>
|
<q-expansion-item group="api" dense expand-separator label="List wallets">
|
||||||
<q-card-section>
|
<q-card>
|
||||||
<code><span class="text-green">POST</span> /watchonly/api/v1/wallet</code>
|
<q-card-section>
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
|
<code
|
||||||
<code>{"X-Api-Key": <admin_key>}</code><br />
|
><span class="text-blue">GET</span> /watchonly/api/v1/wallet</code
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Body (application/json)</h5>
|
>
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">
|
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
|
||||||
Returns 201 CREATED (application/json)
|
<code>{"X-Api-Key": <invoice_key>}</code><br />
|
||||||
</h5>
|
<h5 class="text-caption q-mt-sm q-mb-none">
|
||||||
<code>[<wallet_object>, ...]</code>
|
Body (application/json)
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
</h5>
|
||||||
<code
|
<h5 class="text-caption q-mt-sm q-mb-none">
|
||||||
>curl -X POST {{ request.url_root }}api/v1/wallet -d
|
Returns 200 OK (application/json)
|
||||||
'{"title": <string>, "masterpub": <string>}' -H
|
</h5>
|
||||||
"Content-type: application/json" -H "X-Api-Key: {{
|
<code>[<wallets_object>, ...]</code>
|
||||||
g.user.wallets[0].adminkey }}"
|
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
||||||
</code>
|
<code
|
||||||
</q-card-section>
|
>curl -X GET {{ request.url_root }}api/v1/wallet -H "X-Api-Key: {{
|
||||||
</q-card>
|
g.user.wallets[0].inkey }}"
|
||||||
|
</code>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</q-expansion-item>
|
||||||
|
<q-expansion-item
|
||||||
|
group="api"
|
||||||
|
dense
|
||||||
|
expand-separator
|
||||||
|
label="Get wallet details"
|
||||||
|
>
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<code
|
||||||
|
><span class="text-blue">GET</span>
|
||||||
|
/watchonly/api/v1/wallet/<wallet_id></code
|
||||||
|
>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
|
||||||
|
<code>{"X-Api-Key": <invoice_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 201 CREATED (application/json)
|
||||||
|
</h5>
|
||||||
|
<code>[<wallet_object>, ...]</code>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
||||||
|
<code
|
||||||
|
>curl -X GET {{ request.url_root }}api/v1/wallet/<wallet_id>
|
||||||
|
-H "X-Api-Key: {{ g.user.wallets[0].inkey }}"
|
||||||
|
</code>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</q-expansion-item>
|
||||||
|
<q-expansion-item group="api" dense expand-separator label="Create wallet">
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<code
|
||||||
|
><span class="text-green">POST</span> /watchonly/api/v1/wallet</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 201 CREATED (application/json)
|
||||||
|
</h5>
|
||||||
|
<code>[<wallet_object>, ...]</code>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
||||||
|
<code
|
||||||
|
>curl -X POST {{ request.url_root }}api/v1/wallet -d '{"title":
|
||||||
|
<string>, "masterpub": <string>}' -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="Delete wallet"
|
||||||
|
class="q-pb-md"
|
||||||
|
>
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<code
|
||||||
|
><span class="text-pink">DELETE</span>
|
||||||
|
/watchonly/api/v1/wallet/<wallet_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">Returns 204 NO CONTENT</h5>
|
||||||
|
<code></code>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
||||||
|
<code
|
||||||
|
>curl -X DELETE {{ request.url_root
|
||||||
|
}}api/v1/wallet/<wallet_id> -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="List addresses">
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<code
|
||||||
|
><span class="text-blue">GET</span>
|
||||||
|
/watchonly/api/v1/addresses/<wallet_id></code
|
||||||
|
>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
|
||||||
|
<code>{"X-Api-Key": <invoice_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>[<address_object>, ...]</code>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
||||||
|
<code
|
||||||
|
>curl -X GET {{ request.url_root
|
||||||
|
}}api/v1/addresses/<wallet_id> -H "X-Api-Key: {{
|
||||||
|
g.user.wallets[0].inkey }}"
|
||||||
|
</code>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</q-expansion-item>
|
||||||
|
|
||||||
|
<q-expansion-item
|
||||||
|
group="api"
|
||||||
|
dense
|
||||||
|
expand-separator
|
||||||
|
label="Get fresh address"
|
||||||
|
class="q-pb-md"
|
||||||
|
>
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<code
|
||||||
|
><span class="text-blue">GET</span>
|
||||||
|
/watchonly/api/v1/address/<wallet_id></code
|
||||||
|
>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
|
||||||
|
<code>{"X-Api-Key": <invoice_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>[<address_object>, ...]</code>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
||||||
|
<code
|
||||||
|
>curl -X GET {{ request.url_root }}api/v1/address/<wallet_id>
|
||||||
|
-H "X-Api-Key: {{ g.user.wallets[0].inkey }}"
|
||||||
|
</code>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</q-expansion-item>
|
||||||
|
|
||||||
|
<q-expansion-item
|
||||||
|
group="api"
|
||||||
|
dense
|
||||||
|
expand-separator
|
||||||
|
label="Get mempool.space details"
|
||||||
|
>
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<code
|
||||||
|
><span class="text-blue">GET</span> /watchonly/api/v1/mempool</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>[<mempool_object>, ...]</code>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
||||||
|
<code
|
||||||
|
>curl -X GET {{ request.url_root }}api/v1/mempool -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="Update mempool.space"
|
||||||
|
class="q-pb-md"
|
||||||
|
>
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<code
|
||||||
|
><span class="text-green">POST</span>
|
||||||
|
/watchonly/api/v1/mempool</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 201 CREATED (application/json)
|
||||||
|
</h5>
|
||||||
|
<code>[<mempool_object>, ...]</code>
|
||||||
|
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
||||||
|
<code
|
||||||
|
>curl -X PUT {{ request.url_root }}api/v1/mempool -d '{"endpoint":
|
||||||
|
<string>}' -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>
|
</q-expansion-item>
|
||||||
<q-expansion-item
|
</q-card>
|
||||||
group="api"
|
|
||||||
dense
|
|
||||||
expand-separator
|
|
||||||
label="Delete wallet"
|
|
||||||
class="q-pb-md"
|
|
||||||
>
|
|
||||||
<q-card>
|
|
||||||
<q-card-section>
|
|
||||||
<code
|
|
||||||
><span class="text-pink">DELETE</span>
|
|
||||||
/watchonly/api/v1/wallet/<wallet_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">Returns 204 NO CONTENT</h5>
|
|
||||||
<code></code>
|
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
|
||||||
<code
|
|
||||||
>curl -X DELETE {{ request.url_root }}api/v1/wallet/<wallet_id>
|
|
||||||
-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="List addresses">
|
|
||||||
<q-card>
|
|
||||||
<q-card-section>
|
|
||||||
<code><span class="text-blue">GET</span> /watchonly/api/v1/addresses/<wallet_id></code>
|
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
|
|
||||||
<code>{"X-Api-Key": <invoice_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>[<address_object>, ...]</code>
|
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
|
||||||
<code
|
|
||||||
>curl -X GET {{ request.url_root }}api/v1/addresses/<wallet_id> -H "X-Api-Key: {{
|
|
||||||
g.user.wallets[0].inkey }}"
|
|
||||||
</code>
|
|
||||||
</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
</q-expansion-item>
|
|
||||||
|
|
||||||
<q-expansion-item group="api" dense expand-separator label="Get fresh address" class="q-pb-md">
|
|
||||||
<q-card>
|
|
||||||
<q-card-section>
|
|
||||||
<code><span class="text-blue">GET</span> /watchonly/api/v1/address/<wallet_id></code>
|
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
|
|
||||||
<code>{"X-Api-Key": <invoice_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>[<address_object>, ...]</code>
|
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
|
||||||
<code
|
|
||||||
>curl -X GET {{ request.url_root }}api/v1/address/<wallet_id> -H "X-Api-Key: {{
|
|
||||||
g.user.wallets[0].inkey }}"
|
|
||||||
</code>
|
|
||||||
</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
</q-expansion-item>
|
|
||||||
|
|
||||||
|
|
||||||
<q-expansion-item group="api" dense expand-separator label="Get mempool.space details">
|
|
||||||
<q-card>
|
|
||||||
<q-card-section>
|
|
||||||
<code><span class="text-blue">GET</span> /watchonly/api/v1/mempool</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>[<mempool_object>, ...]</code>
|
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
|
||||||
<code
|
|
||||||
>curl -X GET {{ request.url_root }}api/v1/mempool -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="Update mempool.space" class="q-pb-md">
|
|
||||||
<q-card>
|
|
||||||
<q-card-section>
|
|
||||||
<code><span class="text-green">POST</span> /watchonly/api/v1/mempool</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 201 CREATED (application/json)
|
|
||||||
</h5>
|
|
||||||
<code>[<mempool_object>, ...]</code>
|
|
||||||
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
|
|
||||||
<code
|
|
||||||
>curl -X PUT {{ request.url_root }}api/v1/mempool -d
|
|
||||||
'{"endpoint": <string>}' -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>
|
|
||||||
|
@@ -4,38 +4,26 @@
|
|||||||
<div class="col-12 col-md-7 q-gutter-y-md">
|
<div class="col-12 col-md-7 q-gutter-y-md">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
{% raw %}
|
{% raw %}
|
||||||
<q-btn unelevated color="deep-purple" @click="formDialog.show = true"
|
<q-btn unelevated color="deep-purple" @click="formDialog.show = true">New wallet </q-btn>
|
||||||
>New wallet </q-btn
|
<q-btn unelevated color="deep-purple" icon="edit">
|
||||||
>
|
<div class="cursor-pointer">
|
||||||
<q-btn unelevated color="deep-purple"
|
<q-tooltip>
|
||||||
icon="edit">
|
Point to another Mempool
|
||||||
<div class="cursor-pointer">
|
</q-tooltip>
|
||||||
<q-tooltip>
|
{{ this.mempool.endpoint }}
|
||||||
Point to another Mempool
|
<q-popup-edit v-model="mempool.endpoint">
|
||||||
</q-tooltip>
|
<q-input color="accent" v-model="mempool.endpoint">
|
||||||
{{ this.mempool.endpoint }}
|
</q-input>
|
||||||
<q-popup-edit v-model="mempool.endpoint">
|
<center>
|
||||||
<q-input color="accent" v-model="mempool.endpoint">
|
<q-btn flat dense @click="updateMempool()" v-close-popup>set</q-btn>
|
||||||
</q-input>
|
<q-btn flat dense v-close-popup>cancel</q-btn>
|
||||||
<center><q-btn
|
|
||||||
flat
|
|
||||||
dense
|
|
||||||
@click="updateMempool()"
|
|
||||||
v-close-popup
|
|
||||||
>set</q-btn>
|
|
||||||
<q-btn
|
|
||||||
flat
|
|
||||||
dense
|
|
||||||
v-close-popup
|
|
||||||
>cancel</q-btn>
|
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
</q-popup-edit>
|
</q-popup-edit>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</q-btn
|
</q-btn>
|
||||||
>
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
|
||||||
@@ -46,23 +34,16 @@
|
|||||||
<h5 class="text-subtitle1 q-my-none">Wallets</h5>
|
<h5 class="text-subtitle1 q-my-none">Wallets</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<q-input borderless dense debounce="300" v-model="filter" placeholder="Search">
|
<q-input borderless dense debounce="300" v-model="filter" placeholder="Search">
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-icon name="search"></q-icon>
|
<q-icon name="search"></q-icon>
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<q-table
|
<q-table flat dense :data="walletLinks" row-key="id" :columns="WalletsTable.columns"
|
||||||
flat
|
:pagination.sync="WalletsTable.pagination" :filter="filter">
|
||||||
dense
|
|
||||||
:data="walletLinks"
|
|
||||||
row-key="id"
|
|
||||||
:columns="WalletsTable.columns"
|
|
||||||
:pagination.sync="WalletsTable.pagination"
|
|
||||||
:filter="filter"
|
|
||||||
>
|
|
||||||
<template v-slot:header="props">
|
<template v-slot:header="props">
|
||||||
<q-tr :props="props">
|
<q-tr :props="props">
|
||||||
<q-th auto-width></q-th>
|
<q-th auto-width></q-th>
|
||||||
@@ -75,32 +56,19 @@
|
|||||||
<template v-slot:body="props">
|
<template v-slot:body="props">
|
||||||
<q-tr :props="props">
|
<q-tr :props="props">
|
||||||
|
|
||||||
<q-td auto-width>
|
<q-td auto-width>
|
||||||
|
|
||||||
<q-btn
|
<q-btn unelevated dense size="xs" icon="dns" :color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
|
||||||
unelevated
|
@click="openQrCodeDialog(props.row.id)">
|
||||||
dense
|
|
||||||
size="xs"
|
<q-tooltip>
|
||||||
icon="dns"
|
Adresses
|
||||||
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
|
</q-tooltip>
|
||||||
@click="openQrCodeDialog(props.row.id)"
|
</q-btn>
|
||||||
>
|
<q-btn flat dense size="xs" @click="deleteWalletLink(props.row.id)" icon="cancel" color="pink"></q-btn>
|
||||||
|
|
||||||
<q-tooltip>
|
|
||||||
Adresses
|
|
||||||
</q-tooltip>
|
|
||||||
</q-btn>
|
|
||||||
<q-btn
|
|
||||||
flat
|
|
||||||
dense
|
|
||||||
size="xs"
|
|
||||||
@click="deleteWalletLink(props.row.id)"
|
|
||||||
icon="cancel"
|
|
||||||
color="pink"
|
|
||||||
></q-btn>
|
|
||||||
|
|
||||||
|
|
||||||
</q-td>
|
</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>
|
||||||
{{ col.value }}
|
{{ col.value }}
|
||||||
@@ -126,7 +94,7 @@
|
|||||||
<q-card-section class="q-pa-none">
|
<q-card-section class="q-pa-none">
|
||||||
<q-separator></q-separator>
|
<q-separator></q-separator>
|
||||||
<q-list>
|
<q-list>
|
||||||
{% include "watchonly/_api_docs.html" %}
|
{% include "watchonly/_api_docs.html" %}
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
@@ -135,35 +103,16 @@
|
|||||||
<q-dialog v-model="formDialog.show" position="top" @hide="closeFormDialog">
|
<q-dialog v-model="formDialog.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="sendFormData" class="q-gutter-md">
|
<q-form @submit="sendFormData" class="q-gutter-md">
|
||||||
<q-input
|
<q-input filled dense v-model.trim="formDialog.data.title" type="text" label="Title"></q-input>
|
||||||
filled
|
|
||||||
dense
|
<q-input filled type="textarea" v-model="formDialog.data.masterpub" height="50px" autogrow
|
||||||
v-model.trim="formDialog.data.title"
|
label="Account Extended Public Key; xpub, ypub, zpub"></q-input>
|
||||||
type="text"
|
|
||||||
label="Title"
|
|
||||||
></q-input>
|
|
||||||
<q-input
|
|
||||||
filled
|
|
||||||
type="textarea"
|
|
||||||
v-model="formDialog.data.masterpub"
|
|
||||||
height="50px"
|
|
||||||
autogrow
|
|
||||||
label="Account Extended Public Key; xpub, ypub, zpub"
|
|
||||||
></q-input>
|
|
||||||
|
|
||||||
<div class="row q-mt-lg">
|
<div class="row q-mt-lg">
|
||||||
<q-btn
|
<q-btn unelevated color="deep-purple" :disable="
|
||||||
unelevated
|
|
||||||
color="deep-purple"
|
|
||||||
:disable="
|
|
||||||
formDialog.data.masterpub == null ||
|
formDialog.data.masterpub == null ||
|
||||||
formDialog.data.title == null"
|
formDialog.data.title == null" type="submit">Create Watch-only Wallet</q-btn>
|
||||||
type="submit"
|
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn>
|
||||||
>Create Watch-only Wallet</q-btn
|
|
||||||
>
|
|
||||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
|
|
||||||
>Cancel</q-btn
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
</q-form>
|
</q-form>
|
||||||
</q-card>
|
</q-card>
|
||||||
@@ -172,78 +121,52 @@
|
|||||||
<q-dialog v-model="Addresses.show" position="top">
|
<q-dialog v-model="Addresses.show" position="top">
|
||||||
<q-card v-if="Addresses.data" class="q-pa-lg lnbits__dialog-card">
|
<q-card v-if="Addresses.data" class="q-pa-lg lnbits__dialog-card">
|
||||||
{% raw %}
|
{% raw %}
|
||||||
<h5 class="text-subtitle1 q-my-none">Addresses</h5>
|
<h5 class="text-subtitle1 q-my-none">Addresses</h5>
|
||||||
<q-separator></q-separator><br/>
|
<q-separator></q-separator><br />
|
||||||
<p><strong>Current:</strong>
|
<p><strong>Current:</strong>
|
||||||
{{ currentaddress }}
|
{{ currentaddress }}
|
||||||
<q-btn
|
<q-btn flat dense size="ms" icon="visibility" type="a" :href="mempool.endpoint + '/address/' + currentaddress"
|
||||||
flat
|
target="_blank"></q-btn>
|
||||||
dense
|
|
||||||
size="ms"
|
</p>
|
||||||
icon="visibility"
|
|
||||||
type="a"
|
|
||||||
:href="mempool.endpoint + '/address/' + currentaddress"
|
|
||||||
target="_blank"
|
|
||||||
></q-btn>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
<q-responsive :ratio="1" class="q-mx-xl q-mb-md">
|
<q-responsive :ratio="1" class="q-mx-xl q-mb-md">
|
||||||
<qrcode
|
<qrcode :value="currentaddress" :options="{width: 800}" class="rounded-borders"></qrcode>
|
||||||
:value="currentaddress"
|
|
||||||
:options="{width: 800}"
|
|
||||||
class="rounded-borders"
|
|
||||||
></qrcode>
|
|
||||||
</q-responsive>
|
</q-responsive>
|
||||||
<p style="word-break: break-all;">
|
<p style="word-break: break-all;">
|
||||||
|
|
||||||
<q-scroll-area style="height: 200px; max-width: 100%;">
|
<q-scroll-area style="height: 200px; max-width: 100%;">
|
||||||
<q-list bordered v-for="data in Addresses.data.slice().reverse()">
|
<q-list bordered v-for="data in Addresses.data.slice().reverse()">
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-item-section>{{ data.address }}</q-item-section>
|
<q-item-section>{{ data.address }}</q-item-section>
|
||||||
<q-btn
|
<q-btn flat dense size="ms" icon="visibility" type="a"
|
||||||
flat
|
:href="mempool.endpoint + '/address/' + data.address" target="_blank"></q-btn>
|
||||||
dense
|
</q-item>
|
||||||
size="ms"
|
</q-list>
|
||||||
icon="visibility"
|
</q-scroll-area>
|
||||||
type="a"
|
|
||||||
:href="mempool.endpoint + '/address/' + data.address"
|
|
||||||
target="_blank"
|
|
||||||
></q-btn>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-scroll-area>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="row q-mt-lg q-gutter-sm">
|
<div class="row q-mt-lg q-gutter-sm">
|
||||||
<q-btn
|
<q-btn outline color="grey" @click="getFreshAddress(current)" class="q-ml-sm">Get fresh address</q-btn>
|
||||||
outline
|
|
||||||
color="grey"
|
|
||||||
@click="getFreshAddress(current)"
|
|
||||||
class="q-ml-sm"
|
|
||||||
>Get fresh address</q-btn
|
|
||||||
>
|
|
||||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
|
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
|
||||||
</div>
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
{% endraw %}
|
{% endraw %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %} {% block scripts %} {{ window_vars(user) }}
|
{% endblock %} {% block scripts %} {{ window_vars(user) }}
|
||||||
<script src="{{ url_for('static', filename='vendor/vue-qrcode@1.0.2/vue-qrcode.min.js') }}"></script>
|
<script src="{{ url_for('static', filename='vendor/vue-qrcode@1.0.2/vue-qrcode.min.js') }}"></script>
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
Vue.component(VueQrcode.name, VueQrcode)
|
Vue.component(VueQrcode.name, VueQrcode)
|
||||||
|
|
||||||
Vue.filter('reverse', function(value) {
|
Vue.filter('reverse', function (value) {
|
||||||
// slice to make a copy of array, then reverse the copy
|
// slice to make a copy of array, then reverse the copy
|
||||||
return value.slice().reverse();
|
return value.slice().reverse();
|
||||||
});
|
});
|
||||||
var locationPath = [
|
var locationPath = [
|
||||||
window.location.protocol,
|
window.location.protocol,
|
||||||
'//',
|
'//',
|
||||||
@@ -283,12 +206,12 @@
|
|||||||
show: false,
|
show: false,
|
||||||
data: null
|
data: null
|
||||||
},
|
},
|
||||||
mempool:{
|
mempool: {
|
||||||
endpoint:""
|
endpoint: ""
|
||||||
},
|
},
|
||||||
WalletsTable: {
|
WalletsTable: {
|
||||||
columns: [
|
columns: [
|
||||||
{name: 'id', align: 'left', label: 'ID', field: 'id'},
|
{ name: 'id', align: 'left', label: 'ID', field: 'id' },
|
||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
@@ -319,46 +242,46 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
getAddressDetails: function (address){
|
getAddressDetails: function (address) {
|
||||||
LNbits.api
|
LNbits.api
|
||||||
.request(
|
.request(
|
||||||
'GET',
|
'GET',
|
||||||
'/watchonly/api/v1/mempool/' + address,
|
'/watchonly/api/v1/mempool/' + address,
|
||||||
this.g.user.wallets[0].inkey
|
this.g.user.wallets[0].inkey
|
||||||
)
|
)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
|
|
||||||
return reponse.data
|
return reponse.data
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
|
|
||||||
LNbits.utils.notifyApiError(error)
|
LNbits.utils.notifyApiError(error)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getAddresses: function (walletID) {
|
getAddresses: function (walletID) {
|
||||||
var self = this
|
var self = this
|
||||||
LNbits.api
|
LNbits.api
|
||||||
.request(
|
.request(
|
||||||
'GET',
|
'GET',
|
||||||
'/watchonly/api/v1/addresses/' + walletID,
|
'/watchonly/api/v1/addresses/' + walletID,
|
||||||
this.g.user.wallets[0].inkey
|
this.g.user.wallets[0].inkey
|
||||||
)
|
)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
self.Addresses.data = response.data
|
self.Addresses.data = response.data
|
||||||
self.currentaddress = self.Addresses.data[self.Addresses.data.length - 1].address
|
self.currentaddress = self.Addresses.data[self.Addresses.data.length - 1].address
|
||||||
self.AddressesLinks = response.data.map(function (obj) {
|
self.AddressesLinks = response.data.map(function (obj) {
|
||||||
console.log(obj)
|
console.log(obj)
|
||||||
|
|
||||||
return mapAddresses(obj)
|
|
||||||
|
|
||||||
})
|
return mapAddresses(obj)
|
||||||
})
|
|
||||||
.catch(function (error) {
|
})
|
||||||
|
})
|
||||||
LNbits.utils.notifyApiError(error)
|
.catch(function (error) {
|
||||||
})
|
|
||||||
|
LNbits.utils.notifyApiError(error)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
getFreshAddress: function (walletID) {
|
getFreshAddress: function (walletID) {
|
||||||
var self = this
|
var self = this
|
||||||
|
|
||||||
LNbits.api
|
LNbits.api
|
||||||
@@ -368,8 +291,8 @@
|
|||||||
this.g.user.wallets[0].inkey
|
this.g.user.wallets[0].inkey
|
||||||
)
|
)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
self.Addresses.data = response.data
|
self.Addresses.data = response.data
|
||||||
self.currentaddress = self.Addresses.data[self.Addresses.data.length - 1].address
|
self.currentaddress = self.Addresses.data[self.Addresses.data.length - 1].address
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getMempool: function () {
|
getMempool: function () {
|
||||||
@@ -415,11 +338,11 @@
|
|||||||
this.g.user.wallets[0].inkey
|
this.g.user.wallets[0].inkey
|
||||||
)
|
)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
console.log(response)
|
console.log(response)
|
||||||
|
|
||||||
self.walletLinks = response.data.map(function (obj) {
|
self.walletLinks = response.data.map(function (obj) {
|
||||||
self.getAddresses(obj.id)
|
self.getAddresses(obj.id)
|
||||||
return mapWalletLink(obj)
|
return mapWalletLink(obj)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
@@ -427,7 +350,7 @@
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
closeFormDialog: function () {
|
closeFormDialog: function () {
|
||||||
this.formDialog.data = {
|
this.formDialog.data = {
|
||||||
is_unique: false
|
is_unique: false
|
||||||
@@ -461,7 +384,7 @@
|
|||||||
},
|
},
|
||||||
deleteWalletLink: function (linkId) {
|
deleteWalletLink: function (linkId) {
|
||||||
var self = this
|
var self = this
|
||||||
var link = _.findWhere(this.walletLinks, {id: linkId})
|
var link = _.findWhere(this.walletLinks, { id: linkId })
|
||||||
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?')
|
||||||
.onOk(function () {
|
.onOk(function () {
|
||||||
@@ -471,10 +394,11 @@
|
|||||||
'/watchonly/api/v1/wallet/' + linkId,
|
'/watchonly/api/v1/wallet/' + linkId,
|
||||||
self.g.user.wallets[0].adminkey
|
self.g.user.wallets[0].adminkey
|
||||||
)
|
)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
self.walletLinks = _.reject(self.walletLinks, function (obj) {
|
self.walletLinks = _.reject(self.walletLinks, function (obj) {
|
||||||
return obj.id === linkId
|
return obj.id === linkId
|
||||||
})})
|
})
|
||||||
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
LNbits.utils.notifyApiError(error)
|
LNbits.utils.notifyApiError(error)
|
||||||
})
|
})
|
||||||
@@ -491,10 +415,8 @@
|
|||||||
getMempool()
|
getMempool()
|
||||||
var getWalletLinks = this.getWalletLinks
|
var getWalletLinks = this.getWalletLinks
|
||||||
getWalletLinks()
|
getWalletLinks()
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -15,6 +15,7 @@ async def index():
|
|||||||
|
|
||||||
@watchonly_ext.route("/<charge_id>")
|
@watchonly_ext.route("/<charge_id>")
|
||||||
async def display(charge_id):
|
async def display(charge_id):
|
||||||
link = get_payment(charge_id) or abort(HTTPStatus.NOT_FOUND, "Charge link does not exist.")
|
link = get_payment(charge_id) or abort(
|
||||||
|
HTTPStatus.NOT_FOUND, "Charge link does not exist.")
|
||||||
|
|
||||||
return await render_template("watchonly/display.html", link=link)
|
return await render_template("watchonly/display.html", link=link)
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
from quart import g, jsonify, url_for, request
|
from quart import g, jsonify, url_for, request
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
import httpx, json
|
import httpx
|
||||||
|
import json
|
||||||
|
|
||||||
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
|
||||||
@@ -22,6 +23,7 @@ from .crud import (
|
|||||||
|
|
||||||
###################WALLETS#############################
|
###################WALLETS#############################
|
||||||
|
|
||||||
|
|
||||||
@watchonly_ext.route("/api/v1/wallet", methods=["GET"])
|
@watchonly_ext.route("/api/v1/wallet", methods=["GET"])
|
||||||
@api_check_wallet_key("invoice")
|
@api_check_wallet_key("invoice")
|
||||||
async def api_wallets_retrieve():
|
async def api_wallets_retrieve():
|
||||||
@@ -33,11 +35,12 @@ async def api_wallets_retrieve():
|
|||||||
except:
|
except:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
@watchonly_ext.route("/api/v1/wallet/<wallet_id>", methods=["GET"])
|
@watchonly_ext.route("/api/v1/wallet/<wallet_id>", methods=["GET"])
|
||||||
@api_check_wallet_key("invoice")
|
@api_check_wallet_key("invoice")
|
||||||
async def api_wallet_retrieve(wallet_id):
|
async def api_wallet_retrieve(wallet_id):
|
||||||
wallet = await get_watch_wallet(wallet_id)
|
wallet = await get_watch_wallet(wallet_id)
|
||||||
|
|
||||||
if not wallet:
|
if not wallet:
|
||||||
return jsonify({"message": "wallet does not exist"}), HTTPStatus.NOT_FOUND
|
return jsonify({"message": "wallet does not exist"}), HTTPStatus.NOT_FOUND
|
||||||
|
|
||||||
@@ -54,7 +57,7 @@ async def api_wallet_retrieve(wallet_id):
|
|||||||
)
|
)
|
||||||
async def api_wallet_create_or_update(wallet_id=None):
|
async def api_wallet_create_or_update(wallet_id=None):
|
||||||
wallet = await create_watch_wallet(user=g.wallet.user, masterpub=g.data["masterpub"], title=g.data["title"])
|
wallet = await create_watch_wallet(user=g.wallet.user, masterpub=g.data["masterpub"], title=g.data["title"])
|
||||||
mempool = await get_mempool(g.wallet.user)
|
mempool = await get_mempool(g.wallet.user)
|
||||||
if not mempool:
|
if not mempool:
|
||||||
create_mempool(user=g.wallet.user)
|
create_mempool(user=g.wallet.user)
|
||||||
return jsonify(wallet._asdict()), HTTPStatus.CREATED
|
return jsonify(wallet._asdict()), HTTPStatus.CREATED
|
||||||
@@ -78,9 +81,9 @@ async def api_wallet_delete(wallet_id):
|
|||||||
@watchonly_ext.route("/api/v1/address/<wallet_id>", methods=["GET"])
|
@watchonly_ext.route("/api/v1/address/<wallet_id>", methods=["GET"])
|
||||||
@api_check_wallet_key("invoice")
|
@api_check_wallet_key("invoice")
|
||||||
async def api_fresh_address(wallet_id):
|
async def api_fresh_address(wallet_id):
|
||||||
await get_fresh_address(wallet_id)
|
await get_fresh_address(wallet_id)
|
||||||
|
|
||||||
addresses = await get_addresses(wallet_id)
|
addresses = await get_addresses(wallet_id)
|
||||||
|
|
||||||
return jsonify([address._asdict() for address in addresses]), HTTPStatus.OK
|
return jsonify([address._asdict() for address in addresses]), HTTPStatus.OK
|
||||||
|
|
||||||
@@ -90,16 +93,16 @@ async def api_fresh_address(wallet_id):
|
|||||||
async def api_get_addresses(wallet_id):
|
async def api_get_addresses(wallet_id):
|
||||||
print(wallet_id)
|
print(wallet_id)
|
||||||
|
|
||||||
wallet = await get_watch_wallet(wallet_id)
|
wallet = await get_watch_wallet(wallet_id)
|
||||||
|
|
||||||
if not wallet:
|
if not wallet:
|
||||||
return jsonify({"message": "wallet does not exist"}), HTTPStatus.NOT_FOUND
|
return jsonify({"message": "wallet does not exist"}), HTTPStatus.NOT_FOUND
|
||||||
|
|
||||||
addresses = await get_addresses(wallet_id)
|
addresses = await get_addresses(wallet_id)
|
||||||
|
|
||||||
if not addresses:
|
if not addresses:
|
||||||
await get_fresh_address(wallet_id)
|
await get_fresh_address(wallet_id)
|
||||||
addresses = await get_addresses(wallet_id)
|
addresses = await get_addresses(wallet_id)
|
||||||
|
|
||||||
return jsonify([address._asdict() for address in addresses]), HTTPStatus.OK
|
return jsonify([address._asdict() for address in addresses]), HTTPStatus.OK
|
||||||
|
|
||||||
@@ -115,17 +118,13 @@ async def api_get_addresses(wallet_id):
|
|||||||
)
|
)
|
||||||
async def api_update_mempool():
|
async def api_update_mempool():
|
||||||
mempool = await update_mempool(user=g.wallet.user, **g.data)
|
mempool = await update_mempool(user=g.wallet.user, **g.data)
|
||||||
return jsonify(mempool._asdict()), HTTPStatus.OK
|
return jsonify(mempool._asdict()), HTTPStatus.OK
|
||||||
|
|
||||||
|
|
||||||
@watchonly_ext.route("/api/v1/mempool", methods=["GET"])
|
@watchonly_ext.route("/api/v1/mempool", methods=["GET"])
|
||||||
@api_check_wallet_key("admin")
|
@api_check_wallet_key("admin")
|
||||||
async def api_get_mempool():
|
async def api_get_mempool():
|
||||||
mempool = await get_mempool(g.wallet.user)
|
mempool = await get_mempool(g.wallet.user)
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user