sdk: cached zap provider queries.
This commit is contained in:
@@ -40,6 +40,7 @@ type System struct {
|
|||||||
RelaySetsCache cache.Cache32[GenericSets[string, RelayURL]]
|
RelaySetsCache cache.Cache32[GenericSets[string, RelayURL]]
|
||||||
FollowSetsCache cache.Cache32[GenericSets[nostr.PubKey, ProfileRef]]
|
FollowSetsCache cache.Cache32[GenericSets[nostr.PubKey, ProfileRef]]
|
||||||
TopicSetsCache cache.Cache32[GenericSets[string, Topic]]
|
TopicSetsCache cache.Cache32[GenericSets[string, Topic]]
|
||||||
|
ZapProviderCache cache.Cache32[nostr.PubKey]
|
||||||
Hints hints.HintsDB
|
Hints hints.HintsDB
|
||||||
Pool *nostr.Pool
|
Pool *nostr.Pool
|
||||||
RelayListRelays *RelayStream
|
RelayListRelays *RelayStream
|
||||||
@@ -131,6 +132,9 @@ func NewSystem() *System {
|
|||||||
if sys.RelayListCache == nil {
|
if sys.RelayListCache == nil {
|
||||||
sys.RelayListCache = cache_memory.New[GenericList[string, Relay]](8000)
|
sys.RelayListCache = cache_memory.New[GenericList[string, Relay]](8000)
|
||||||
}
|
}
|
||||||
|
if sys.ZapProviderCache == nil {
|
||||||
|
sys.ZapProviderCache = cache_memory.New[nostr.PubKey](8000)
|
||||||
|
}
|
||||||
|
|
||||||
if sys.Store == nil {
|
if sys.Store == nil {
|
||||||
sys.Store = &nullstore.NullStore{}
|
sys.Store = &nullstore.NullStore{}
|
||||||
|
|||||||
49
sdk/zap.go
Normal file
49
sdk/zap.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package sdk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"fiatjaf.com/nostr"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FetchZapProvider fetches the zap provider public key for a given user from their profile metadata.
|
||||||
|
// It uses a cache to avoid repeated fetches. If no zap provider is set in the profile, returns an empty PubKey.
|
||||||
|
func (sys *System) FetchZapProvider(ctx context.Context, pk nostr.PubKey) nostr.PubKey {
|
||||||
|
if v, ok := sys.ZapProviderCache.Get(pk); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
pm := sys.FetchProfileMetadata(ctx, pk)
|
||||||
|
|
||||||
|
if pm.LUD16 != "" {
|
||||||
|
parts := strings.Split(pm.LUD16, "@")
|
||||||
|
if len(parts) == 2 {
|
||||||
|
url := "http://" + parts[1] + "/.well-known/lnurlp/" + parts[0]
|
||||||
|
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||||
|
if err == nil {
|
||||||
|
client := &http.Client{Timeout: 10 * time.Second}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err == nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if body, err := io.ReadAll(resp.Body); err == nil {
|
||||||
|
gj := gjson.ParseBytes(body)
|
||||||
|
if gj.Get("allowsNostr").Type == gjson.True {
|
||||||
|
if pk, err := nostr.PubKeyFromHex(gj.Get("nostrPubkey").Str); err == nil {
|
||||||
|
sys.ZapProviderCache.SetWithTTL(pk, pk, time.Hour*6)
|
||||||
|
return pk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sys.ZapProviderCache.SetWithTTL(pk, nostr.ZeroPK, time.Hour*2)
|
||||||
|
return nostr.ZeroPK
|
||||||
|
}
|
||||||
22
sdk/zap_test.go
Normal file
22
sdk/zap_test.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package sdk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"fiatjaf.com/nostr"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFetchZapProvider(t *testing.T) {
|
||||||
|
sys := NewSystem()
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
pk, err := nostr.PubKeyFromHex("fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
zp := sys.FetchZapProvider(ctx, pk)
|
||||||
|
expected, err := nostr.PubKeyFromHex("f81611363554b64306467234d7396ec88455707633f54738f6c4683535098cd3")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, expected, zp)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user