make format && generate keys with schnorr

This commit is contained in:
Tiago Vasconcelos 2022-12-20 16:11:56 +00:00
parent 9b69851155
commit 70a051a413
7 changed files with 105 additions and 159 deletions

View File

@ -59,17 +59,13 @@ async def update_shop_product(product_id: str, **kwargs) -> Optional[Stalls]:
f"UPDATE shop.products SET {q} WHERE id = ?",
(*kwargs.values(), product_id),
)
row = await db.fetchone(
"SELECT * FROM shop.products WHERE id = ?", (product_id,)
)
row = await db.fetchone("SELECT * FROM shop.products WHERE id = ?", (product_id,))
return Products(**row) if row else None
async def get_shop_product(product_id: str) -> Optional[Products]:
row = await db.fetchone(
"SELECT * FROM shop.products WHERE id = ?", (product_id,)
)
row = await db.fetchone("SELECT * FROM shop.products WHERE id = ?", (product_id,))
return Products(**row) if row else None
@ -132,9 +128,7 @@ async def get_shop_zone(zone_id: str) -> Optional[Zones]:
async def get_shop_zones(user: str) -> List[Zones]:
rows = await db.fetchall(
'SELECT * FROM shop.zones WHERE "user" = ?', (user,)
)
rows = await db.fetchall('SELECT * FROM shop.zones WHERE "user" = ?', (user,))
return [Zones(**row) for row in rows]
@ -182,16 +176,12 @@ async def update_shop_stall(stall_id: str, **kwargs) -> Optional[Stalls]:
f"UPDATE shop.stalls SET {q} WHERE id = ?",
(*kwargs.values(), stall_id),
)
row = await db.fetchone(
"SELECT * FROM shop.stalls WHERE id = ?", (stall_id,)
)
row = await db.fetchone("SELECT * FROM shop.stalls WHERE id = ?", (stall_id,))
return Stalls(**row) if row else None
async def get_shop_stall(stall_id: str) -> Optional[Stalls]:
row = await db.fetchone(
"SELECT * FROM shop.stalls WHERE id = ?", (stall_id,)
)
row = await db.fetchone("SELECT * FROM shop.stalls WHERE id = ?", (stall_id,))
return Stalls(**row) if row else None
@ -203,9 +193,7 @@ async def get_shop_stalls(wallet_ids: Union[str, List[str]]) -> List[Stalls]:
return [Stalls(**row) for row in rows]
async def get_shop_stalls_by_ids(
stall_ids: Union[str, List[str]]
) -> List[Stalls]:
async def get_shop_stalls_by_ids(stall_ids: Union[str, List[str]]) -> List[Stalls]:
q = ",".join(["?"] * len(stall_ids))
rows = await db.fetchall(
f"SELECT * FROM shop.stalls WHERE id IN ({q})", (*stall_ids,)
@ -250,9 +238,7 @@ async def create_shop_order(data: createOrder, invoiceid: str) -> Orders:
# return link
async def create_shop_order_details(
order_id: str, data: List[createOrderDetails]
):
async def create_shop_order_details(order_id: str, data: List[createOrderDetails]):
for item in data:
item_id = urlsafe_short_hash()
await db.execute(
@ -280,9 +266,7 @@ async def get_shop_order_details(order_id: str) -> List[OrderDetail]:
async def get_shop_order(order_id: str) -> Optional[Orders]:
row = await db.fetchone(
"SELECT * FROM shop.orders WHERE id = ?", (order_id,)
)
row = await db.fetchone("SELECT * FROM shop.orders WHERE id = ?", (order_id,))
return Orders(**row) if row else None
@ -362,9 +346,7 @@ async def get_shop_markets(user: str) -> List[Market]:
async def get_shop_market(market_id: str) -> Optional[Market]:
row = await db.fetchone(
"SELECT * FROM shop.markets WHERE id = ?", (market_id,)
)
row = await db.fetchone("SELECT * FROM shop.markets WHERE id = ?", (market_id,))
return Market(**row) if row else None
@ -397,9 +379,7 @@ async def create_shop_market(data: CreateMarket):
return market
async def create_shop_market_stalls(
market_id: str, data: List[CreateMarketStalls]
):
async def create_shop_market_stalls(market_id: str, data: List[CreateMarketStalls]):
for stallid in data:
id = urlsafe_short_hash()

View File

@ -14,17 +14,18 @@
<li>Create Shipping Zones you're willing to ship to</li>
<li>Create a Stall to list yiur products on</li>
<li>Create products to put on the Stall</li>
<li>
Take orders
</li>
<li>
Includes chat support!
</li>
<li>Take orders</li>
<li>Includes chat support!</li>
</ol>
The first LNbits shop idea 'Diagon Alley' helped create Nostr, and soon this shop extension will have the option to work on Nostr 'Diagon Alley' mode, by the merchant, shop, and buyer all having keys, and data being routed through Nostr relays.
The first LNbits shop idea 'Diagon Alley' helped create Nostr, and soon
this shop extension will have the option to work on Nostr 'Diagon Alley'
mode, by the merchant, shop, and buyer all having keys, and data being
routed through Nostr relays.
<br />
<small>
Created by, <a href="https://github.com/talvasconcelos">Tal Vasconcelos</a>, <a href="https://github.com/benarc">Ben Arc</a></small
Created by,
<a href="https://github.com/talvasconcelos">Tal Vasconcelos</a>,
<a href="https://github.com/benarc">Ben Arc</a></small
>
<!-- </p> -->
</q-card-section>

View File

@ -253,7 +253,7 @@
>
</q-select>
<q-input
v-if="diagonalley"
v-if="diagonalley"
v-if="keys"
filled
dense
@ -261,8 +261,7 @@
label="Public Key"
></q-input>
<q-input
v-if="diagonalley"
v-if="diagonalley"
v-if="keys"
filled
dense
@ -291,7 +290,7 @@
label="Shipping Zones"
></q-select>
<q-select
v-if="diagonalley"
v-if="diagonalley"
:options="relayOptions"
filled
dense
@ -300,14 +299,14 @@
label="Relays"
></q-select>
<q-input
v-if="diagonalley"
v-if="diagonalley"
filled
dense
v-model.trim="stallDialog.data.crelays"
label="Custom relays (seperate by comma)"
></q-input>
<q-input
v-if="diagonalley"
v-if="diagonalley"
filled
dense
v-model.trim="stallDialog.data.nostrShops"
@ -399,9 +398,7 @@
<q-separator inset></q-separator>
<q-card-section>
<div class="text-h6">Shop</div>
<div class="text-subtitle2">
Make a shop of multiple stalls.
</div>
<div class="text-subtitle2">Make a shop of multiple stalls.</div>
</q-card-section>
<q-card-section>
@ -929,7 +926,7 @@
</q-card-section>
</q-card>
<!-- CHAT BOX -->
<q-card style="max-height: 600px">
<q-card>
<q-card-section>
<h6 class="text-subtitle1 q-my-none">Messages</h6>
</q-card-section>
@ -946,45 +943,45 @@
></q-select>
</q-card-section>
<q-card-section>
<div class="chat-container q-pa-md" ref="chatCard">
<div class="chat-box">
<!-- <p v-if="Object.keys(messages).length === 0">No messages yet</p> -->
<div class="chat-messages">
<q-chat-message
:key="index"
v-for="(message, index) in orderMessages"
:name="message.pubkey == keys.pubkey ? 'me' : 'customer'"
:text="[message.msg]"
:sent="message.pubkey == keys.pubkey ? true : false"
:bg-color="message.pubkey == keys.pubkey ? 'white' : 'light-green-2'"
/>
</div>
</div>
<q-card-section>
<q-form @submit="sendMessage" class="full-width chat-input">
<q-input
ref="newMessage"
v-model="newMessage"
placeholder="Message"
class="full-width"
dense
outlined
>
<template>
<q-btn
round
dense
flat
type="submit"
icon="send"
color="primary"
<div class="chat-container" ref="chatCard">
<div class="chat-box">
<!-- <p v-if="Object.keys(messages).length === 0">No messages yet</p> -->
<div class="chat-messages">
<q-chat-message
:key="index"
v-for="(message, index) in orderMessages"
:name="message.pubkey == keys.pubkey ? 'me' : 'customer'"
:text="[message.msg]"
:sent="message.pubkey == keys.pubkey ? true : false"
:bg-color="message.pubkey == keys.pubkey ? 'white' : 'light-green-2'"
/>
</template>
</q-input>
</q-form>
</div>
</div>
<q-card-section>
<q-form @submit="sendMessage" class="full-width chat-input">
<q-input
ref="newMessage"
v-model="newMessage"
placeholder="Message"
class="full-width"
dense
outlined
>
<template>
<q-btn
round
dense
flat
type="submit"
icon="send"
color="primary"
/>
</template>
</q-input>
</q-form>
</q-card-section>
</div>
</q-card-section>
</div>
</q-card-section>
</q-card>
<!-- <q-card>
<q-card-section>
@ -1112,12 +1109,15 @@
</div>
{% endblock %} {% block scripts %} {{ window_vars(user) }}
<script src="https://cdn.jsdelivr.net/npm/pica@6.1.1/dist/pica.min.js"></script>
<script src="https://github.com/paulmillr/noble-secp256k1/releases/download/1.7.0/noble-secp256k1.js"></script>
<script>
Vue.component(VueQrcode.name, VueQrcode)
const pica = window.pica()
const secp = window.nobleSecp256k1
function imgSizeFit(img, maxWidth = 1024, maxHeight = 768) {
let ratio = Math.min(
@ -1504,31 +1504,17 @@
window.URL.revokeObjectURL(url)
},
generateKeys() {
LNbits.api
.request(
'GET',
'/shop/api/v1/keys',
this.g.user.wallets[0].adminkey
)
.then(response => {
if (response.data) {
this.keys = response.data
this.stallDialog.data.publickey = this.keys.pubkey
this.stallDialog.data.privatekey = this.keys.privkey
this.$q.localStorage.set(
`lnbits.shop.${this.g.user.id}`,
this.keys
)
}
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
const privkey = secp.utils.bytesToHex(secp.utils.randomPrivateKey())
const pubkey = secp.utils.bytesToHex(secp.schnorr.getPublicKey(privKey))
this.keys = {privKey, pubKey}
this.stallDialog.data.publickey = this.keys.pubkey
this.stallDialog.data.privatekey = this.keys.privkey
this.$q.localStorage.set(`lnbits.shop.${this.g.user.id}`, this.keys)
console.log({privKey, pubKey})
},
restoreKeys() {
let keys = this.$q.localStorage.getItem(
`lnbits.shop.${this.g.user.id}`
)
let keys = this.$q.localStorage.getItem(`lnbits.shop.${this.g.user.id}`)
if (keys) {
this.keys = keys
this.stallDialog.data.publickey = this.keys.pubkey
@ -1858,11 +1844,7 @@
var self = this
LNbits.api
.request(
'GET',
'/shop/api/v1/zones',
this.g.user.wallets[0].inkey
)
.request('GET', '/shop/api/v1/zones', this.g.user.wallets[0].inkey)
.then(function (response) {
if (response.data) {
self.zones = response.data.map(mapZone)
@ -1967,11 +1949,7 @@
////////////////////////////////////////
getMarkets() {
LNbits.api
.request(
'GET',
'/shop/api/v1/markets',
this.g.user.wallets[0].inkey
)
.request('GET', '/shop/api/v1/markets', this.g.user.wallets[0].inkey)
.then(response => {
if (response.data) {
this.markets = response.data.map(mapMarkets)
@ -2171,17 +2149,17 @@
this.g.user.wallets[0].adminkey
)
.then(res => {
if (!res.data?.length) return
this.messages = _.groupBy(res.data, 'id_conversation')
this.checkUnreadMessages()
})
.catch(error => {
console.error(error)
LNbits.utils.notifyApiError(error)
})
},
updateLastSeenMsg(id) {
let data = this.$q.localStorage.getItem(
`lnbits.shop.${this.g.user.id}`
)
let data = this.$q.localStorage.getItem(`lnbits.shop.${this.g.user.id}`)
let chat = {
...data.chat,
[`${id}`]: {
@ -2256,9 +2234,7 @@
} else {
ws_scheme = 'ws://'
}
ws = new WebSocket(
ws_scheme + location.host + '/shop/ws/' + room_name
)
ws = new WebSocket(ws_scheme + location.host + '/shop/ws/' + room_name)
function checkWebSocket(event) {
if (ws.readyState === WebSocket.CLOSED) {
@ -2296,9 +2272,7 @@
await this.getOrders()
this.getMarkets()
await this.getAllMessages()
let keys = this.$q.localStorage.getItem(
`lnbits.shop.${this.g.user.id}`
)
let keys = this.$q.localStorage.getItem(`lnbits.shop.${this.g.user.id}`)
if (keys) {
this.keys = keys
}
@ -2319,7 +2293,8 @@
position: relative;
display: grid;
grid-template-rows: 1fr auto;
height: calc(100vh - 140px);
/*height: calc(100vh - 200px);*/
height: 50vh;
}
.chat-box {
@ -2327,6 +2302,7 @@
flex-direction: column-reverse;
padding: 1rem;
overflow-y: auto;
margin-left: auto;
}
.chat-messages {

View File

@ -2,7 +2,7 @@
<div class="row q-col-gutter-md flex">
<div class="col-12 col-md-7 col-lg-6 q-gutter-y-md">
<q-card>
<div class="chat-container q-pa-md">
<div class="chat-container">
<div class="chat-box">
<!-- <p v-if="Object.keys(messages).length === 0">No messages yet</p> -->
<div class="chat-messages">
@ -102,7 +102,11 @@
<q-card-section>
<q-separator></q-separator>
<q-list>
<q-expansion-item v-if="diagonalley" group="extras" icon="vpn_key" label="Keys"
<q-expansion-item
v-if="diagonalley"
group="extras"
icon="vpn_key"
label="Keys"
><p>
Bellow are the keys needed to contact the merchant. They are
stored in the browser!
@ -197,7 +201,7 @@
</div>
<!-- RESTORE KEYS DIALOG -->
<q-dialog
v-if="diagonalley"
v-if="diagonalley"
v-model="keysDialog.show"
position="top"
@hide="clearRestoreKeyDialog"
@ -398,9 +402,7 @@
} else {
ws_scheme = 'ws://'
}
ws = new WebSocket(
ws_scheme + location.host + '/shop/ws/' + room_name
)
ws = new WebSocket(ws_scheme + location.host + '/shop/ws/' + room_name)
function checkWebSocket(event) {
if (ws.readyState === WebSocket.CLOSED) {
@ -448,8 +450,7 @@
}
})
let data =
this.$q.localStorage.getItem(`lnbits.shop.data`) || false
let data = this.$q.localStorage.getItem(`lnbits.shop.data`) || false
if (data) {
this.user = data
@ -486,7 +487,8 @@
position: relative;
display: grid;
grid-template-rows: 1fr auto;
height: calc(100vh - 133px);
/*height: calc(100vh - 200px);*/
height: 50vh;
}
.chat-box {
@ -494,6 +496,7 @@
flex-direction: column-reverse;
padding: 1rem;
overflow-y: auto;
margin-left: auto;
}
.chat-messages {

View File

@ -163,7 +163,7 @@
label="Name *optional"
></q-input>
<q-input
v-if="diagonalley"
v-if="diagonalley"
filled
dense
v-model.trim="checkoutDialog.data.pubkey"
@ -280,7 +280,7 @@
stall: null,
products: [],
searchText: null,
diagonalley:false,
diagonalley: false,
cart: {
total: 0,
size: 0,

View File

@ -78,9 +78,7 @@ async def display(request: Request, market_id):
stalls = await get_shop_market_stalls(market_id)
stalls_ids = [stall.id for stall in stalls]
products = [
product.dict() for product in await get_shop_products(stalls_ids)
]
products = [product.dict() for product in await get_shop_products(stalls_ids)]
return shop_renderer().TemplateResponse(
"shop/market.html",

View File

@ -346,9 +346,7 @@ async def api_shop_order_shipped(
order_id,
),
)
order = await db.fetchone(
"SELECT * FROM shop.orders WHERE id = ?", (order_id,)
)
order = await db.fetchone("SELECT * FROM shop.orders WHERE id = ?", (order_id,))
return order
@ -361,15 +359,11 @@ async def api_shop_stall_products(
stall_id, wallet: WalletTypeInfo = Depends(get_key_type)
):
rows = await db.fetchone(
"SELECT * FROM shop.stalls WHERE id = ?", (stall_id,)
)
rows = await db.fetchone("SELECT * FROM shop.stalls WHERE id = ?", (stall_id,))
if not rows:
return {"message": "Stall does not exist."}
products = db.fetchone(
"SELECT * FROM shop.products WHERE wallet = ?", (rows[1],)
)
products = db.fetchone("SELECT * FROM shop.products WHERE wallet = ?", (rows[1],))
if not products:
return {"message": "No products"}
@ -441,10 +435,7 @@ async def api_shop_stall_checkshipped(
async def api_shop_markets(wallet: WalletTypeInfo = Depends(get_key_type)):
# await get_shop_market_stalls(market_id="FzpWnMyHQMcRppiGVua4eY")
try:
return [
market.dict()
for market in await get_shop_markets(wallet.wallet.user)
]
return [market.dict() for market in await get_shop_markets(wallet.wallet.user)]
except:
return {"message": "We could not retrieve the markets."}
@ -498,10 +489,7 @@ async def api_shop_generate_keys():
async def api_get_merchant_messages(
orders: str = Query(...), wallet: WalletTypeInfo = Depends(require_admin_key)
):
return [
msg.dict() for msg in await get_shop_chat_by_merchant(orders.split(","))
]
return [msg.dict() for msg in await get_shop_chat_by_merchant(orders.split(","))]
@shop_ext.get("/api/v1/chat/messages/{room_name}")