feat: add support for NIP22
This commit is contained in:
parent
868e02d3c2
commit
f5c873ec4d
4 changed files with 158 additions and 3 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
from typing import Any, Awaitable, Callable, List, Optional
|
from typing import Any, Awaitable, Callable, List, Optional, Tuple
|
||||||
|
|
||||||
from fastapi import WebSocket
|
from fastapi import WebSocket
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
@ -167,6 +167,12 @@ class NostrClientConnection:
|
||||||
await self._send_msg(resp_nip20)
|
await self._send_msg(resp_nip20)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
in_range, message = self._created_at_in_range(e.created_at)
|
||||||
|
if not in_range:
|
||||||
|
resp_nip20 += [False, message]
|
||||||
|
await self._send_msg(resp_nip20)
|
||||||
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if e.is_replaceable_event():
|
if e.is_replaceable_event():
|
||||||
await delete_events(
|
await delete_events(
|
||||||
|
|
@ -186,6 +192,7 @@ class NostrClientConnection:
|
||||||
resp_nip20 += [event != None, message]
|
resp_nip20 += [event != None, message]
|
||||||
|
|
||||||
await self._send_msg(resp_nip20)
|
await self._send_msg(resp_nip20)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def client_config(self) -> ClientConfig:
|
def client_config(self) -> ClientConfig:
|
||||||
|
|
@ -241,3 +248,13 @@ class NostrClientConnection:
|
||||||
self._event_count_per_timestamp = 0
|
self._event_count_per_timestamp = 0
|
||||||
|
|
||||||
return self._event_count_per_timestamp > self.client_config.max_events_per_second
|
return self._event_count_per_timestamp > self.client_config.max_events_per_second
|
||||||
|
|
||||||
|
def _created_at_in_range(self, created_at: int) -> Tuple[bool, str]:
|
||||||
|
current_time = round(time.time())
|
||||||
|
if self.client_config.created_at_in_past != 0:
|
||||||
|
if created_at < (current_time - self.client_config.created_at_in_past):
|
||||||
|
return False, "created_at is too much into the past"
|
||||||
|
if self.client_config.created_at_in_future != 0:
|
||||||
|
if created_at > (current_time + self.client_config.created_at_in_future):
|
||||||
|
return False, "created_at is too much into the future"
|
||||||
|
return True, ""
|
||||||
23
models.py
23
models.py
|
|
@ -12,6 +12,17 @@ class ClientConfig(BaseModel):
|
||||||
max_client_filters = Field(0, alias="maxClientFilters")
|
max_client_filters = Field(0, alias="maxClientFilters")
|
||||||
limit_per_filter = Field(1000, alias="limitPerFilter")
|
limit_per_filter = Field(1000, alias="limitPerFilter")
|
||||||
max_events_per_second = Field(0, alias="maxEventsPerSecond")
|
max_events_per_second = Field(0, alias="maxEventsPerSecond")
|
||||||
|
|
||||||
|
created_at_days_past = Field(0, alias="createdAtDaysPast")
|
||||||
|
created_at_hours_past = Field(0, alias="createdAtHoursPast")
|
||||||
|
created_at_minutes_past = Field(0, alias="createdAtMinutesPast")
|
||||||
|
created_at_seconds_past = Field(0, alias="createdAtSecondsPast")
|
||||||
|
|
||||||
|
created_at_days_future = Field(0, alias="createdAtDaysFuture")
|
||||||
|
created_at_hours_future = Field(0, alias="createdAtHoursFuture")
|
||||||
|
created_at_minutes_future = Field(0, alias="createdAtMinutesFuture")
|
||||||
|
created_at_seconds_future = Field(0, alias="createdAtSecondsFuture")
|
||||||
|
|
||||||
allowed_public_keys = Field([], alias="allowedPublicKeys")
|
allowed_public_keys = Field([], alias="allowedPublicKeys")
|
||||||
blocked_public_keys = Field([], alias="blockedPublicKeys")
|
blocked_public_keys = Field([], alias="blockedPublicKeys")
|
||||||
|
|
||||||
|
|
@ -23,7 +34,15 @@ class ClientConfig(BaseModel):
|
||||||
return True
|
return True
|
||||||
# todo: check payment
|
# todo: check payment
|
||||||
return p in self.allowed_public_keys
|
return p in self.allowed_public_keys
|
||||||
|
|
||||||
|
@property
|
||||||
|
def created_at_in_past(self) -> int:
|
||||||
|
return self.created_at_days_past * 86400 + self.created_at_hours_past * 3600 + self.created_at_minutes_past * 60 + self.created_at_seconds_past
|
||||||
|
|
||||||
|
@property
|
||||||
|
def created_at_in_future(self) -> int:
|
||||||
|
return self.created_at_days_future * 86400 + self.created_at_hours_future * 3600 + self.created_at_minutes_future * 60 + self.created_at_seconds_future
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
allow_population_by_field_name = True
|
allow_population_by_field_name = True
|
||||||
class RelayConfig(ClientConfig):
|
class RelayConfig(ClientConfig):
|
||||||
|
|
@ -55,7 +74,7 @@ class NostrRelay(BaseModel):
|
||||||
def info(cls,) -> dict:
|
def info(cls,) -> dict:
|
||||||
return {
|
return {
|
||||||
"contact": "https://t.me/lnbits",
|
"contact": "https://t.me/lnbits",
|
||||||
"supported_nips": [1, 9, 11, 15, 20],
|
"supported_nips": [1, 9, 11, 15, 20, 22],
|
||||||
"software": "LNbits",
|
"software": "LNbits",
|
||||||
"version": "",
|
"version": "",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,108 @@
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
<q-tab-panel name="config">
|
<q-tab-panel name="config">
|
||||||
<div v-if="relay">
|
<div v-if="relay">
|
||||||
|
<div class="row items-center no-wrap q-mb-md">
|
||||||
|
<div class="col-3 q-pr-lg">Created At in Past:</div>
|
||||||
|
<div class="col-2 q-pr-lg">
|
||||||
|
<q-input
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model.trim="relay.config.createdAtDaysPast"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
hint="Days"
|
||||||
|
></q-input>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 q-pr-lg">
|
||||||
|
<q-select
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model="relay.config.createdAtHoursPast"
|
||||||
|
type="number"
|
||||||
|
hint="Hours"
|
||||||
|
:options="hours"
|
||||||
|
></q-select>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 q-pr-lg">
|
||||||
|
<q-select
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model="relay.config.createdAtMinutesPast"
|
||||||
|
type="number"
|
||||||
|
hint="Minutes"
|
||||||
|
:options="range60"
|
||||||
|
></q-select>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 q-pr-lg">
|
||||||
|
<q-select
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model="relay.config.createdAtSecondsPast"
|
||||||
|
type="number"
|
||||||
|
hint="Seconds"
|
||||||
|
:options="range60"
|
||||||
|
></q-select>
|
||||||
|
</div>
|
||||||
|
<div class="col-1 q-pb-md">
|
||||||
|
<q-icon name="info" class="cursor-pointer">
|
||||||
|
<q-tooltip>
|
||||||
|
NIP 22: Lower limit within which a relay will consider an
|
||||||
|
event's created_at to be acceptable.
|
||||||
|
</q-tooltip></q-icon
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row items-center no-wrap q-mb-md">
|
||||||
|
<div class="col-3 q-pr-lg">Created At in Future:</div>
|
||||||
|
<div class="col-2 q-pr-lg">
|
||||||
|
<q-input
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model.trim="relay.config.createdAtDaysFuture"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
hint="Days"
|
||||||
|
></q-input>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 q-pr-lg">
|
||||||
|
<q-select
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model="relay.config.createdAtHoursFuture"
|
||||||
|
type="number"
|
||||||
|
hint="Hours"
|
||||||
|
:options="hours"
|
||||||
|
></q-select>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 q-pr-lg">
|
||||||
|
<q-select
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model="relay.config.createdAtMinutesFuture"
|
||||||
|
type="number"
|
||||||
|
hint="Minutes"
|
||||||
|
:options="range60"
|
||||||
|
></q-select>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 q-pr-lg">
|
||||||
|
<q-select
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model="relay.config.createdAtSecondsFuture"
|
||||||
|
type="number"
|
||||||
|
hint="Seconds"
|
||||||
|
:options="range60"
|
||||||
|
></q-select>
|
||||||
|
</div>
|
||||||
|
<div class="col-1 q-pb-md">
|
||||||
|
<q-icon name="info" class="cursor-pointer">
|
||||||
|
<q-tooltip>
|
||||||
|
NIP 22: Upper limit within which a relay will consider an
|
||||||
|
event's created_at to be acceptable.
|
||||||
|
</q-tooltip></q-icon
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row items-center no-wrap q-mb-md">
|
<div class="row items-center no-wrap q-mb-md">
|
||||||
<div class="col-3 q-pr-lg">Limit per filter:</div>
|
<div class="col-3 q-pr-lg">Limit per filter:</div>
|
||||||
<div class="col-3 q-pr-lg">
|
<div class="col-3 q-pr-lg">
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,23 @@ async function relayDetails(path) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
hours: function () {
|
||||||
|
const y = []
|
||||||
|
for (let i = 0; i <= 24; i++) {
|
||||||
|
y.push(i)
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
},
|
||||||
|
range60: function () {
|
||||||
|
const y = []
|
||||||
|
for (let i = 0; i <= 60; i++) {
|
||||||
|
y.push(i)
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
satBtc(val, showUnit = true) {
|
satBtc(val, showUnit = true) {
|
||||||
return satOrBtc(val, showUnit, this.satsDenominated)
|
return satOrBtc(val, showUnit, this.satsDenominated)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue