diff --git a/crud.py b/crud.py new file mode 100644 index 0000000..8f41bff --- /dev/null +++ b/crud.py @@ -0,0 +1,42 @@ +import json +from typing import Optional + +from lnbits.helpers import urlsafe_short_hash + +from . import db +from .models import Merchant, PartialMerchant + + +async def create_merchant(user_id: str, m: PartialMerchant) -> Merchant: + merchant_id = urlsafe_short_hash() + await db.execute( + """ + INSERT INTO nostrmarket.merchants (user_id, id, private_key, public_key, meta) + VALUES (?, ?, ?, ?, ?) + """, + (user_id, merchant_id, m.private_key, m.public_key, json.dumps(dict(m.config))), + ) + merchant = await get_merchant(user_id, merchant_id) + assert merchant, "Created merchant cannot be retrieved" + return merchant + + +async def get_merchant(user_id: str, merchant_id: str) -> Optional[Merchant]: + row = await db.fetchone( + """SELECT * FROM nostrmarket.merchants WHERE user_id = ? AND id = ?""", + ( + user_id, + merchant_id, + ), + ) + + return Merchant.from_row(row) if row else None + + +async def get_merchant_for_user(user_id: str) -> Optional[Merchant]: + row = await db.fetchone( + """SELECT * FROM nostrmarket.merchants WHERE user_id = ? """, + (user_id,), + ) + + return Merchant.from_row(row) if row else None diff --git a/migrations.py b/migrations.py index 02565f7..0880b62 100644 --- a/migrations.py +++ b/migrations.py @@ -7,9 +7,10 @@ async def m001_initial(db): """ CREATE TABLE nostrmarket.merchants ( user_id TEXT NOT NULL, + id TEXT PRIMARY KEY, private_key TEXT NOT NULL, public_key TEXT NOT NULL, - config TEXT NOT NULL + meta TEXT NOT NULL DEFAULT '{}' ); """ ) diff --git a/models.py b/models.py new file mode 100644 index 0000000..e6a4e5e --- /dev/null +++ b/models.py @@ -0,0 +1,25 @@ +import json +from sqlite3 import Row +from typing import Optional + +from pydantic import BaseModel + + +class MerchantConfig(BaseModel): + name: Optional[str] + + +class PartialMerchant(BaseModel): + private_key: str + public_key: str + config: MerchantConfig = MerchantConfig() + + +class Merchant(PartialMerchant): + id: str + + @classmethod + def from_row(cls, row: Row) -> "Merchant": + merchant = cls(**dict(row)) + merchant.config = MerchantConfig(**json.loads(row["meta"])) + return merchant diff --git a/static/js/index.js b/static/js/index.js index 71d65d5..a5adbd6 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -1,15 +1,52 @@ -const stalls = async () => { +const merchant = async () => { Vue.component(VueQrcode.name, VueQrcode) await stallDetails('static/components/stall-details/stall-details.html') + const nostr = window.NostrTools + new Vue({ el: '#vue', mixins: [windowMixin], data: function () { - return {} + return { + merchant: null + } + }, + methods: { + generateKeys: async function () { + const privkey = nostr.generatePrivateKey() + const pubkey = nostr.getPublicKey(privkey) + + const data = {private_key: privkey, public_key: pubkey, config: {}} + try { + const resp = await LNbits.api.request( + 'POST', + '/nostrmarket/api/v1/merchant', + this.g.user.wallets[0].adminkey, + data + ) + } catch (error) { + LNbits.utils.notifyApiError(error) + } + }, + getMerchant: async function () { + try { + const {data} = await LNbits.api.request( + 'get', + '/nostrmarket/api/v1/merchant', + this.g.user.wallets[0].adminkey + ) + this.merchant = data + } catch (error) { + LNbits.utils.notifyApiError(error) + } + } + }, + created: async function () { + await this.getMerchant() } }) } -stalls() +merchant() diff --git a/templates/nostrmarket/index.html b/templates/nostrmarket/index.html index 410fbf4..37710a5 100644 --- a/templates/nostrmarket/index.html +++ b/templates/nostrmarket/index.html @@ -2,7 +2,7 @@ %} {% block page %}