From dfda2367a2c4d6921f426f06313cf7721e5e56ab Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Mon, 13 Feb 2023 17:49:10 +0200 Subject: [PATCH] feat: add payment for stoeage --- README.md | 8 +++ models.py | 6 +- tasks.py | 22 +++++++ templates/nostrrelay/public.html | 107 +++++++++++++++++++++++-------- views_api.py | 22 +++++-- 5 files changed, 130 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index d98b0e2..42678f1 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,11 @@ UI for diagnostics and management (key alow/ban lists, rate limiting) coming soo 1. Enable extension 2. Enable relay + + +### Development + +Create Symbolic Link: +``` +ln -s /Users/my-user/git-repos/nostr-relay-extension/ /Users/my-user/git-repos/lnbits/lnbits/extensions/nostrrelay +``` \ No newline at end of file diff --git a/models.py b/models.py index 071c3fe..d83f4ef 100644 --- a/models.py +++ b/models.py @@ -307,10 +307,14 @@ class NostrFilter(BaseModel): return inner_joins, where, values -class RelayJoin(BaseModel): +class BuyOrder(BaseModel): + action: str relay_id: str pubkey: str + units_to_buy = 0 + def is_valid_action(self): + return self.action in ['join', 'storage'] class NostrAccount(BaseModel): pubkey: str diff --git a/tasks.py b/tasks.py index 11dbc50..db09d7b 100644 --- a/tasks.py +++ b/tasks.py @@ -31,6 +31,11 @@ async def on_invoice_paid(payment: Payment): await invoice_paid_to_join(relay_id, pubkey) return + if payment.extra.get("action") == "storage": + storage_to_buy = payment.extra.get("storage_to_buy") + await invoice_paid_for_storage(relay_id, pubkey, storage_to_buy) + return + async def invoice_paid_to_join(relay_id: str, pubkey: str): try: account = await get_account(relay_id, pubkey) @@ -44,5 +49,22 @@ async def invoice_paid_to_join(relay_id: str, pubkey: str): account.paid_to_join = True await update_account(relay_id, account) + except Exception as ex: + logger.warning(ex) + + +async def invoice_paid_for_storage(relay_id: str, pubkey: str, storage_to_buy: int): + try: + account = await get_account(relay_id, pubkey) + if not account: + await create_account(relay_id, NostrAccount(pubkey=pubkey, storage=storage_to_buy)) + return + + if account.blocked: + return + + account.storage = storage_to_buy + await update_account(relay_id, account) + except Exception as ex: logger.warning(ex) \ No newline at end of file diff --git a/templates/nostrrelay/public.html b/templates/nostrrelay/public.html index 6c08824..29207a5 100644 --- a/templates/nostrrelay/public.html +++ b/templates/nostrrelay/public.html @@ -12,7 +12,7 @@

- + Public Key: - Show Invoice - Cost to join: - - - - sats - +
+
+ Cost to join: +
+
+ + sats +
+
+ Pay to Join +
+
+ +
+
+ Storage cost: +
+
+ + sats per + + + +
+
+ +
+
+ + sats +
+
+ Buy storage space +
+
+
This is a free relay - +
- Copy invoice
@@ -66,7 +106,7 @@
@@ -163,11 +203,19 @@ return { relay: JSON.parse('{{relay | tojson | safe}}'), pubkey: '', - joinInvoice: '' + invoice: '', + unitsToBuy: 0 + } + }, + computed: { + storageCost: function () { + if (!this.relay || !this.relay.config.storageCostValue) return 0 + return this.unitsToBuy * this.relay.config.storageCostValue } }, methods: { - createJoinInvoice: async function () { + createInvoice: async function (action) { + if (!action) return if (!this.pubkey) { this.$q.notify({ timeout: 5000, @@ -177,17 +225,20 @@ return } try { + const reqData = { + action, + relay_id: this.relay.id, + pubkey: this.pubkey, + units_to_buy: this.unitsToBuy + } const {data} = await LNbits.api.request( 'PUT', - '/nostrrelay/api/v1/join', + '/nostrrelay/api/v1/pay', '', - { - relay_id: this.relay.id, - pubkey: this.pubkey - } + reqData ) console.log('### data.invoice', data.invoice) - this.joinInvoice = data.invoice + this.invoice = data.invoice } catch (error) { LNbits.utils.notifyApiError(error) } diff --git a/views_api.py b/views_api.py index d5f98c9..1260d23 100644 --- a/views_api.py +++ b/views_api.py @@ -27,7 +27,7 @@ from .crud import ( update_relay, ) from .helpers import normalize_public_key -from .models import NostrRelay, RelayJoin +from .models import BuyOrder, NostrRelay client_manager = NostrClientManager() @@ -154,9 +154,8 @@ async def api_delete_relay( ) -@nostrrelay_ext.put("/api/v1/join") -async def api_pay_to_join(data: RelayJoin): - +@nostrrelay_ext.put("/api/v1/pay") +async def api_pay_to_join(data: BuyOrder): try: pubkey = normalize_public_key(data.pubkey) relay = await get_relay_by_id(data.relay_id) @@ -166,18 +165,29 @@ async def api_pay_to_join(data: RelayJoin): detail="Relay not found", ) - if relay.is_free_to_join: + if data.action == 'join' and relay.is_free_to_join: raise ValueError("Relay is free to join") + storage_to_buy = 0 + if data.action == 'storage': + if relay.config.storage_cost_value == 0: + raise ValueError("Relay storage cost is zero. Cannot buy!") + if data.units_to_buy == 0: + raise ValueError("Must specify how much storage to buy!") + storage_to_buy = data.units_to_buy * relay.config.storage_cost_value * 1024 + if relay.config.storage_cost_unit == "MB": + storage_to_buy *= 1024 + _, payment_request = await create_invoice( wallet_id=relay.config.wallet, amount=int(relay.config.cost_to_join), memo=f"Pubkey '{data.pubkey}' wants to join {relay.id}", extra={ "tag": "nostrrely", - "action": "join", + "action": data.action, "relay_id": relay.id, "pubkey": pubkey, + "storage_to_buy": storage_to_buy }, ) print("### payment_request", payment_request)