diff --git a/.changeset/README.md b/.changeset/README.md
deleted file mode 100644
index e5b6d8d6..00000000
--- a/.changeset/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Changesets
-
-Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
-with multi-package repos, or single-package repos to help you version and publish your code. You can
-find the full documentation for it [in our repository](https://github.com/changesets/changesets)
-
-We have a quick list of common questions to get you started engaging with this project in
-[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
diff --git a/.changeset/cold-pianos-tickle.md b/.changeset/cold-pianos-tickle.md
deleted file mode 100644
index e7993579..00000000
--- a/.changeset/cold-pianos-tickle.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@nostr-dev-kit/ndk": minor
----
-
-deprecate user.zap/ndk.zap -- use new NDKZapper instead
diff --git a/.changeset/config.json b/.changeset/config.json
deleted file mode 100644
index 77b04199..00000000
--- a/.changeset/config.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
- "changelog": "@changesets/cli/changelog",
- "commit": false,
- "fixed": [],
- "linked": [],
- "access": "public",
- "baseBranch": "master",
- "updateInternalDependencies": "patch",
- "ignore": []
-}
diff --git a/.changeset/eighty-toes-refuse.md b/.changeset/eighty-toes-refuse.md
deleted file mode 100644
index 21a099c7..00000000
--- a/.changeset/eighty-toes-refuse.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@nostr-dev-kit/ndk": patch
----
-
-move NWC to ndk-wallet
diff --git a/.changeset/fifty-llamas-boil.md b/.changeset/fifty-llamas-boil.md
deleted file mode 100644
index 657b902d..00000000
--- a/.changeset/fifty-llamas-boil.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@nostr-dev-kit/ndk": patch
----
-
-add pubkey hint to e tags
diff --git a/.changeset/flat-garlics-taste.md b/.changeset/flat-garlics-taste.md
deleted file mode 100644
index e59d34d0..00000000
--- a/.changeset/flat-garlics-taste.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@nostr-dev-kit/ndk-mobile": patch
----
-
-add useUserProfile hook
diff --git a/.changeset/fresh-oranges-guess.md b/.changeset/fresh-oranges-guess.md
deleted file mode 100644
index a56d009c..00000000
--- a/.changeset/fresh-oranges-guess.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@nostr-dev-kit/ndk-svelte": minor
----
-
-add support for Svelte 5's runes
diff --git a/.changeset/great-keys-knock.md b/.changeset/great-keys-knock.md
deleted file mode 100644
index 11cf8620..00000000
--- a/.changeset/great-keys-knock.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@nostr-dev-kit/ndk-mobile": patch
----
-
-add LRU cache for profiles
diff --git a/.changeset/khaki-pets-smell.md b/.changeset/khaki-pets-smell.md
deleted file mode 100644
index 4638c43b..00000000
--- a/.changeset/khaki-pets-smell.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@nostr-dev-kit/ndk": patch
----
-
-fix bug where both a and e tags were going in zap requests
diff --git a/.changeset/pretty-berries-talk.md b/.changeset/pretty-berries-talk.md
deleted file mode 100644
index 76efd29c..00000000
--- a/.changeset/pretty-berries-talk.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@nostr-dev-kit/ndk-wallet": patch
----
-
-NWC support
diff --git a/.changeset/purple-fireants-invite.md b/.changeset/purple-fireants-invite.md
deleted file mode 100644
index 5e7433de..00000000
--- a/.changeset/purple-fireants-invite.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@nostr-dev-kit/ndk-mobile": patch
----
-
-add sync profile fetching from cache
diff --git a/.changeset/silly-cows-boil.md b/.changeset/silly-cows-boil.md
deleted file mode 100644
index f809c2d9..00000000
--- a/.changeset/silly-cows-boil.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@nostr-dev-kit/ndk-cache-dexie": patch
----
-
-add support in dexie cache to retrieve profile info synchronously
diff --git a/.changeset/strong-files-fly.md b/.changeset/strong-files-fly.md
deleted file mode 100644
index 2fef01c2..00000000
--- a/.changeset/strong-files-fly.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@nostr-dev-kit/ndk": patch
----
-
-add NIP-22 support
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
deleted file mode 100644
index 0ccefc48..00000000
--- a/.devcontainer/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-# FIXME: Hardcoded node version
-# FIXME: Use prod and dev stages!
-FROM node:20-slim
-
-RUN corepack enable
-
-# FIXME: We need to use a WORKDIR because of
-# https://stackoverflow.com/a/65443098 but
-# the choice of the actual dir is quite arbitrary.
-COPY . /app
-WORKDIR /app
-
-RUN pnpm install
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
deleted file mode 100644
index 709d82c2..00000000
--- a/.devcontainer/devcontainer.json
+++ /dev/null
@@ -1,29 +0,0 @@
-// For format details, see https://aka.ms/devcontainer.json. For config options, see the
-// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node
-{
- "name": "NDK devcontainer",
- "build": {
- // Path is relative to the devcontainer.json file.
- "dockerfile": "Dockerfile",
- "context": "../"
- },
- "customizations": {
- "vscode": {
- "settings": {
- "terminal.integrated.shell.linux": "/bin/bash"
- }
- }
- },
- // Add pnpm bin to path, so we have turbo available
- "postStartCommand": "echo 'export PATH=$(pnpm bin):$PATH' >> ~/.bashrc && . ~/.bashrc"
- // Features to add to the dev container. More info: https://containers.dev/features.
- // "features": {},
- // Use 'forwardPorts' to make a list of ports inside the container available locally.
- // "forwardPorts": [],
- // Use 'postCreateCommand' to run commands after the container is created.
- // "postCreateCommand": "yarn install",
- // Configure tool-specific properties.
- // "customizations": {},
- // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
- // "remoteUser": "root"
-}
diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index e5dc490a..00000000
--- a/.eslintignore
+++ /dev/null
@@ -1,13 +0,0 @@
-.DS_Store
-node_modules
-build
-dist
-package
-.env
-.env.*
-!.env.example
-
-# Ignore files for PNPM, NPM and YARN
-pnpm-lock.yaml
-package-lock.json
-yarn.lock
diff --git a/.eslintrc.js b/.eslintrc.js
deleted file mode 100644
index 8b05a81c..00000000
--- a/.eslintrc.js
+++ /dev/null
@@ -1,3 +0,0 @@
-module.exports = {
- extends: ["@nostr-dev-kit/custom"],
-};
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
deleted file mode 100644
index 605f05db..00000000
--- a/.github/workflows/deploy.yml
+++ /dev/null
@@ -1,66 +0,0 @@
-# Sample workflow for building and deploying a VitePress site to GitHub Pages
-#
-name: Deploy VitePress site to Pages
-
-on:
- # Runs on pushes targeting the `main` branch. Change this to `master` if you're
- # using the `master` branch as the default branch.
- push:
- branches:
- - '*'
-
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
-permissions:
- contents: read
- pages: write
- id-token: write
-
-# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
-# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
-concurrency:
- group: pages
- cancel-in-progress: false
-
-jobs:
- # Build job
- build:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 0 # Not needed if lastUpdated is not enabled
- - name: Setup Node
- uses: actions/setup-node@v4
- with:
- node-version: '20'
- - name: Setup PNPM
- uses: pnpm/action-setup@v4
- - name: Setup Pages
- uses: actions/configure-pages@v4
- - name: Install dependencies
- run: pnpm install # or pnpm install / yarn install / bun install
- - name: Build with VitePress
- run: pnpm docs:build # or pnpm docs:build / yarn docs:build / bun run docs:build
- - name: Build typedoc
- run: cd ndk && pnpm typedoc --out ../docs/.vitepress/dist/api
- - name: Upload artifact
- uses: actions/upload-pages-artifact@v3
- with:
- path: docs/.vitepress/dist
-
- # Deployment job
- deploy:
- environment:
- name: github-pages
- url: ${{ steps.deployment.outputs.page_url }}
- needs: build
- runs-on: ubuntu-latest
- name: Deploy
- steps:
- - name: Deploy to GitHub Pages
- id: deployment
- uses: actions/deploy-pages@v4
diff --git a/.prettierignore b/.prettierignore
deleted file mode 100644
index f757754f..00000000
--- a/.prettierignore
+++ /dev/null
@@ -1,5 +0,0 @@
-dist
-docs
-coverage
-**/.changeset
-**/.svelte-kit
diff --git a/.prettierrc b/.prettierrc
deleted file mode 100644
index 4431ccbf..00000000
--- a/.prettierrc
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "useTabs": false,
- "tabWidth": 4,
- "singleQuote": false,
- "semi": true,
- "trailingComma": "es5",
- "printWidth": 100,
- "overrides": [
- {
- "files": "*.svelte",
- "options": {
- "parser": "svelte"
- }
- }
- ]
-}
diff --git a/BUILD.md b/BUILD.md
deleted file mode 100644
index 741a89e4..00000000
--- a/BUILD.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Build NDK
-
-NDK is structured as a monorepo using `pnpm` as the package manager.
-
-```
-git clone https://github.com/nostr-dev-kit/ndk
-cd ndk
-pnpm install
-pnpm build
-```
-
-If you only care about building ndk core and not the family of packages you can just
-
-```
-git clone https://github.com/nostr-dev-kit/ndk
-cd ndk
-pnpm install
-cd ndk
-pnpm build
-```
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 2a6ea523..00000000
--- a/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2023 Pablo Fernandez
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/REFERENCES.md b/REFERENCES.md
deleted file mode 100644
index 48274ac7..00000000
--- a/REFERENCES.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# Open source Nostr apps using NDK
-
-This is a running list of applications using NDK that are open source. Use these codebases to understand
-how others handle Nostr things using NDK.
-
-If you are the author of an application that uses NDK, send a pull-request to this repo adding your application
-to this list.
-
-- [Highlighter](https://github.com/kind-0/highlighter) - By [@pablof7z](https://njump.me/npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft)
- - Svelte, frontend
-- [nsecBunker](https://github.com/kind-0/nsecbunkerd) - By [@pablof7z](https://njump.me/npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft)
- - Typescript, backend
-- [Highlighter Chrome Extension](https://github.com/pablof7z/highlighter-chrome-extension/) - By [@pablof7z](https://njump.me/npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft)
- - Typescript, Chrome extension
-- [Nostr Data Vending Machine](https://github.com/pablof7z/nostr-data-vending-machine) - By [@pablof7z](https://njump.me/npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft)
- - Typescript, backend
-- [Nostr Chat Widget](https://github.com/pablof7z/nostr-chat-widget) - By [@pablof7z](https://njump.me/npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft)
- - Svelte, Rollup, embeddable widget
-- [Zapstr](https://github.com/zapstr/zapstr) - By [@pablof7z](https://njump.me/npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft)
- - Svelte, Frontend
-- [Ostrich.work](https://github.com/erskingardner/ostrich.work) - By [@jeffg](https://njump.me/npub1zuuajd7u3sx8xu92yav9jwxpr839cs0kc3q6t56vd5u9q033xmhsk6c2uc)
- - Svelte, frontend
-- [Listr.lol](https://github.com/erskingardner/listr) - By [@jeffg](https://njump.me/npub1zuuajd7u3sx8xu92yav9jwxpr839cs0kc3q6t56vd5u9q033xmhsk6c2uc)
- - Svelte, frontend
-- [Lume](https://github.com/luminous-devs/lume) - By [@reya](https://njump.me/npub1zfss807aer0j26mwp2la0ume0jqde3823rmu97ra6sgyyg956e0s6xw445)
- - Tauri, Desktop app
-- [Nostr App Manager](https://github.com/nostrband/nostr-app-manager) - By [@nostrband](https://njump.me/npub1wc4rc9wxl2gfzxl384g0cw3f79nrms0sfdpe02y7aasy7c3we4sqd0qywr)
- - React, Frontend
-- [Stemstr](https://github.com/stemstr/Client) - By [@stemstr](https://njump.me/npub1stemstrls4f5plqeqkeq43gtjhtycuqd9w25v5r5z5ygaq2n2sjsd6mul5)
-- [Audgit.ai](https://github.com/ArcadeLabsInc/audgit.ai) - By [@ArcadeLabsInc](https://njump.me/npub1tlv67m7xvlyplzexuynmfpguvyet0sjffce3y8vu0suuyuwgzauqjk7fdm)
-- [Swarmstr](https://github.com/ptrio42/swarmstr.com) - By [@pitiunited](https://njump.me/npub178umpxtdflcm7a08nexvs4mu384kx0ngg9w8ltm5eut6q7lcp0vq05qrg4)
-- [zapddit](https://github.com/vivganes/zapddit) - By [@vivganes](https://njump.me/npub1ltx67888tz7lqnxlrg06x234vjnq349tcfyp52r0lstclp548mcqnuz40t)
-- [Nuxstr](https://github.com/Sebastix/nuxstr) - By [@Sebastix](https://njump.me/sebastian@sebastix.dev)
- - Nuxt (Vue), frontend
-- [Flockstr](https://github.com/zmeyer44/flockstr) - By [@zach](https://njump.me/npub1zach44xjpc4yyhx6pgse2cj2pf98838kja03dv2e8ly8lfr094vqvm5dy5)
-- [Flare.pub](https://github.com/zmeyer44/flare) - By [@zach](https://njump.me/npub1zach44xjpc4yyhx6pgse2cj2pf98838kja03dv2e8ly8lfr094vqvm5dy5)
-- [Pinstr.app](https://github.com/sepehr-safari/pinstr) - By [@sepehr](https://njump.me/nprofile1qqsru22d9lfnnwck54qr4phrvey50h2q33xc0gqxv5j03ftn4efu4rspr9mhxue69uhhyetvv9ujuumwdae8gtnnda3kjctv9uq3wamnwvaz7tmjwdekccte9ehx7um5wghx6mm99uq36amnwvaz7tmwdaehgu3wd46hg6tw09mkzmrvv46zucm0d5hsv6ffvh)
- - React, Nostr Web Client
-- [Nostr-Hooks](https://github.com/ostyjs/nostr-hooks) - By [@sepehr](https://njump.me/nprofile1qqsru22d9lfnnwck54qr4phrvey50h2q33xc0gqxv5j03ftn4efu4rspr9mhxue69uhhyetvv9ujuumwdae8gtnnda3kjctv9uq3wamnwvaz7tmjwdekccte9ehx7um5wghx6mm99uq36amnwvaz7tmwdaehgu3wd46hg6tw09mkzmrvv46zucm0d5hsv6ffvh)
- - Stateful wrapper library of React hooks around NDK.
-- [magicCity h=n](https://github.com/tezosmiami/hicetnunc) - By [@hicetnunc2000](https://github.com/hicetnunc2000/), [@tezosmiami](https://njump.me/npub190rqwj0nud4uhvmaeg7cgn0gypu0s09j87vqjluhfhju0req2khsskh9w7)
-- [notepress](https://github.com/utxo-one/notepress) - By [@utxo](httsp://njump.me/_@utxo.one)
- - No frameworks! A very simple long-form (NIP-23) reader
-- [Olas 🌊](https://github.com/pablof7z/snapstr) - By [@pablof7z](https://njump.me/f7z.io)
- - React Native, mobile-only app
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
deleted file mode 100644
index 75669e0d..00000000
--- a/docs/.vitepress/config.mts
+++ /dev/null
@@ -1,78 +0,0 @@
-import { defineConfig } from 'vitepress'
-import { withMermaid } from "vitepress-plugin-mermaid";
-
-// https://vitepress.dev/reference/site-config
-export default withMermaid(defineConfig({
- title: "NDK",
- description: "NDK Docs",
- base: "/ndk/",
- ignoreDeadLinks: true,
- themeConfig: {
- // https://vitepress.dev/reference/default-theme-config
- nav: [
- { text: 'Home', link: '/' },
- { text: 'API Reference', link: '/api/', target: '_blank' },
- { text: 'Wiki', link: 'https://wikifreedia.xyz/?c=NDK', target: '_blank' },
- ],
-
- sidebar: [
- {
- text: "Getting Started",
- items: [
- { text: 'Introduction', link: '/getting-started/introduction' },
- { text: 'Usage', link: '/getting-started/usage' },
- { text: 'Signers', link: '/getting-started/signers' },
- ]
- },
- {
- text: 'Tutorial',
- items: [
- { text: 'Local-first', link: '/tutorial/local-first' },
- { text: 'Publishing', link: '/tutorial/publishing' },
- { text: "Subscription Management", link: '/tutorial/subscription-management' },
- { text: "Speed", link: '/tutorial/speed' },
- { text: 'Zaps', link: '/tutorial/zaps' },
- ]
- },
- {
- text: "Cache Adapters",
- items: [
- { text: 'In-memory + dexie', link: '/cache/dexie' },
- { text: 'Local Nostr Relay', link: '/cache/nostr' },
- ]
- },
- {
- text: "Wallet",
- items: [
- { text: 'Introduction', link: '/wallet/index' },
- { text: 'Nutsack (NIP-60)', link: '/wallet/nutsack' },
- { text: 'Nutzaps', link: '/wallet/nutzaps' },
- ]
- },
- {
- text: "Wrappers",
- items: [
- { text: 'NDK Svelte', link: '/wrappers/svelte' },
- ]
- },
- {
- text: "Mobile",
- items: [
- { text: 'Introduction', link: '/mobile/index' },
- { text: 'Session', link: '/mobile/session' },
- { text: 'Wallet', link: '/mobile/wallet' },
- ]
- },
- {
- text: "Internals",
- items: [
- { text: "Subscription Lifecycle", link: '/internals/subscriptions' },
- ]
- }
- ],
-
- socialLinks: [
- { icon: 'github', link: 'https://github.com/nostr-dev-kit/ndk' }
- ]
- }
-}))
\ No newline at end of file
diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts
deleted file mode 100644
index def4cfc8..00000000
--- a/docs/.vitepress/theme/index.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-// https://vitepress.dev/guide/custom-theme
-import { h } from 'vue'
-import type { Theme } from 'vitepress'
-import DefaultTheme from 'vitepress/theme'
-import './style.css'
-
-export default {
- extends: DefaultTheme,
- Layout: () => {
- return h(DefaultTheme.Layout, null, {
- // https://vitepress.dev/guide/extending-default-theme#layout-slots
- })
- },
- enhanceApp({ app, router, siteData }) {
- // ...
- }
-} satisfies Theme
diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css
deleted file mode 100644
index d63aee82..00000000
--- a/docs/.vitepress/theme/style.css
+++ /dev/null
@@ -1,139 +0,0 @@
-/**
- * Customize default theme styling by overriding CSS variables:
- * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css
- */
-
-/**
- * Colors
- *
- * Each colors have exact same color scale system with 3 levels of solid
- * colors with different brightness, and 1 soft color.
- *
- * - `XXX-1`: The most solid color used mainly for colored text. It must
- * satisfy the contrast ratio against when used on top of `XXX-soft`.
- *
- * - `XXX-2`: The color used mainly for hover state of the button.
- *
- * - `XXX-3`: The color for solid background, such as bg color of the button.
- * It must satisfy the contrast ratio with pure white (#ffffff) text on
- * top of it.
- *
- * - `XXX-soft`: The color used for subtle background such as custom container
- * or badges. It must satisfy the contrast ratio when putting `XXX-1` colors
- * on top of it.
- *
- * The soft color must be semi transparent alpha channel. This is crucial
- * because it allows adding multiple "soft" colors on top of each other
- * to create a accent, such as when having inline code block inside
- * custom containers.
- *
- * - `default`: The color used purely for subtle indication without any
- * special meanings attched to it such as bg color for menu hover state.
- *
- * - `brand`: Used for primary brand colors, such as link text, button with
- * brand theme, etc.
- *
- * - `tip`: Used to indicate useful information. The default theme uses the
- * brand color for this by default.
- *
- * - `warning`: Used to indicate warning to the users. Used in custom
- * container, badges, etc.
- *
- * - `danger`: Used to show error, or dangerous message to the users. Used
- * in custom container, badges, etc.
- * -------------------------------------------------------------------------- */
-
- :root {
- --vp-c-default-1: var(--vp-c-gray-1);
- --vp-c-default-2: var(--vp-c-gray-2);
- --vp-c-default-3: var(--vp-c-gray-3);
- --vp-c-default-soft: var(--vp-c-gray-soft);
-
- --vp-c-brand-1: var(--vp-c-indigo-1);
- --vp-c-brand-2: var(--vp-c-indigo-2);
- --vp-c-brand-3: var(--vp-c-indigo-3);
- --vp-c-brand-soft: var(--vp-c-indigo-soft);
-
- --vp-c-tip-1: var(--vp-c-brand-1);
- --vp-c-tip-2: var(--vp-c-brand-2);
- --vp-c-tip-3: var(--vp-c-brand-3);
- --vp-c-tip-soft: var(--vp-c-brand-soft);
-
- --vp-c-warning-1: var(--vp-c-yellow-1);
- --vp-c-warning-2: var(--vp-c-yellow-2);
- --vp-c-warning-3: var(--vp-c-yellow-3);
- --vp-c-warning-soft: var(--vp-c-yellow-soft);
-
- --vp-c-danger-1: var(--vp-c-red-1);
- --vp-c-danger-2: var(--vp-c-red-2);
- --vp-c-danger-3: var(--vp-c-red-3);
- --vp-c-danger-soft: var(--vp-c-red-soft);
-}
-
-/**
- * Component: Button
- * -------------------------------------------------------------------------- */
-
-:root {
- --vp-button-brand-border: transparent;
- --vp-button-brand-text: var(--vp-c-white);
- --vp-button-brand-bg: var(--vp-c-brand-3);
- --vp-button-brand-hover-border: transparent;
- --vp-button-brand-hover-text: var(--vp-c-white);
- --vp-button-brand-hover-bg: var(--vp-c-brand-2);
- --vp-button-brand-active-border: transparent;
- --vp-button-brand-active-text: var(--vp-c-white);
- --vp-button-brand-active-bg: var(--vp-c-brand-1);
-}
-
-/**
- * Component: Home
- * -------------------------------------------------------------------------- */
-
-:root {
- --vp-home-hero-name-color: transparent;
- --vp-home-hero-name-background: -webkit-linear-gradient(
- 120deg,
- #bd34fe 30%,
- #41d1ff
- );
-
- --vp-home-hero-image-background-image: linear-gradient(
- -45deg,
- #bd34fe 50%,
- #47caff 50%
- );
- --vp-home-hero-image-filter: blur(44px);
-}
-
-@media (min-width: 640px) {
- :root {
- --vp-home-hero-image-filter: blur(56px);
- }
-}
-
-@media (min-width: 960px) {
- :root {
- --vp-home-hero-image-filter: blur(68px);
- }
-}
-
-/**
- * Component: Custom Block
- * -------------------------------------------------------------------------- */
-
-:root {
- --vp-custom-block-tip-border: transparent;
- --vp-custom-block-tip-text: var(--vp-c-text-1);
- --vp-custom-block-tip-bg: var(--vp-c-brand-soft);
- --vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
-}
-
-/**
- * Component: Algolia
- * -------------------------------------------------------------------------- */
-
-.DocSearch {
- --docsearch-primary-color: var(--vp-c-brand-1) !important;
-}
-
diff --git a/docs/api-examples.md b/docs/api-examples.md
deleted file mode 100644
index 6bd8bb5c..00000000
--- a/docs/api-examples.md
+++ /dev/null
@@ -1,49 +0,0 @@
----
-outline: deep
----
-
-# Runtime API Examples
-
-This page demonstrates usage of some of the runtime APIs provided by VitePress.
-
-The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files:
-
-```md
-
-
-## Results
-
-### Theme Data
-
{{ theme }}
-
-### Page Data
-{{ page }}
-
-### Page Frontmatter
-{{ frontmatter }}
-```
-
-
-
-## Results
-
-### Theme Data
-{{ theme }}
-
-### Page Data
-{{ page }}
-
-### Page Frontmatter
-{{ frontmatter }}
-
-## More
-
-Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata).
diff --git a/docs/cache/dexie.md b/docs/cache/dexie.md
deleted file mode 100644
index 114b53bd..00000000
--- a/docs/cache/dexie.md
+++ /dev/null
@@ -1,153 +0,0 @@
-# Dexie Cache
-
-Meant to be used client-side within a browser context. This is a cache adapter for [Dexie](https://dexie.org/), a wrapper around IndexedDB.
-
-## Usage
-
-NDK will attempt to use the Dexie adapter to store users, events, and tags. The default behaviour is to always check the cache first and then hit relays, replacing older cached events as needed.
-
-## Support
-
-- [x] Events
-- [x] User profiles
-- [x] Event<>Tag indexes
-- [x] NIP-05 lookups
-- [x] Unpublished events
-
-### Install
-
-```
-pnpm add @nostr-dev-kit/ndk-cache-dexie
-```
-
-### Add as a cache adapter
-
-```ts
-import NDKCacheAdapterDexie from "@nostr-dev-kit/ndk-cache-dexie";
-
-const dexieAdapter = new NDKCacheAdapterDexie({ dbName: 'your-db-name' });
-const ndk = new NDK({cacheAdapter: dexieAdapter, ...other config options});
-```
-
-🚨 Because Dexie only exists client-side, this cache adapter will not work in pure node.js environments. You'll need to make sure that you're using the right cache adapter in the right place (e.g. Redis on the backend, Dexie on the frontend).
-
-## Slowness
-
-Because IndexDB is painfully slow, this adapter will primarly act via an LRU cache that periodically flushes to the database. Individual read/writes don't directly hit the database.
-
-## Options
-
-[**NDK Dexie Cache Adapter**](../README.md) • **Docs**
-
-***
-
-[NDK Dexie Cache Adapter](../globals.md) / NDKCacheAdapterDexieOptions
-
-# Interface: NDKCacheAdapterDexieOptions
-
-## Properties
-
-### dbName?
-
-> `optional` **dbName**: `string`
-
-The name of the database to use
-
-#### Defined in
-
-[ndk-cache-dexie/src/index.ts:34](https://github.com/nostr-dev-kit/ndk/blob/26ea669eeeadbc93b894cac1f29829e9a41694cb/ndk-cache-dexie/src/index.ts#L34)
-
-***
-
-### debug?
-
-> `optional` **debug**: `Debugger`
-
-Debug instance to use for logging
-
-#### Defined in
-
-[ndk-cache-dexie/src/index.ts:39](https://github.com/nostr-dev-kit/ndk/blob/26ea669eeeadbc93b894cac1f29829e9a41694cb/ndk-cache-dexie/src/index.ts#L39)
-
-***
-
-### eventCacheSize?
-
-> `optional` **eventCacheSize**: `number`
-
-#### Defined in
-
-[ndk-cache-dexie/src/index.ts:53](https://github.com/nostr-dev-kit/ndk/blob/26ea669eeeadbc93b894cac1f29829e9a41694cb/ndk-cache-dexie/src/index.ts#L53)
-
-***
-
-### eventTagsCacheSize?
-
-> `optional` **eventTagsCacheSize**: `number`
-
-#### Defined in
-
-[ndk-cache-dexie/src/index.ts:54](https://github.com/nostr-dev-kit/ndk/blob/26ea669eeeadbc93b894cac1f29829e9a41694cb/ndk-cache-dexie/src/index.ts#L54)
-
-***
-
-### expirationTime?
-
-> `optional` **expirationTime**: `number`
-
-The number of seconds to store events in Dexie (IndexedDB) before they expire
-Defaults to 3600 seconds (1 hour)
-
-#### Defined in
-
-[ndk-cache-dexie/src/index.ts:45](https://github.com/nostr-dev-kit/ndk/blob/26ea669eeeadbc93b894cac1f29829e9a41694cb/ndk-cache-dexie/src/index.ts#L45)
-
-***
-
-### indexableKinds?
-
-> `optional` **indexableKinds**: `number`[] \| `"all"` \| `"none"`
-
-The kinds of events that should be indexed
-
-#### Default
-
-```ts
-"all"
-```
-
-#### Defined in
-
-[ndk-cache-dexie/src/index.ts:60](https://github.com/nostr-dev-kit/ndk/blob/26ea669eeeadbc93b894cac1f29829e9a41694cb/ndk-cache-dexie/src/index.ts#L60)
-
-***
-
-### nip05CacheSize?
-
-> `optional` **nip05CacheSize**: `number`
-
-#### Defined in
-
-[ndk-cache-dexie/src/index.ts:52](https://github.com/nostr-dev-kit/ndk/blob/26ea669eeeadbc93b894cac1f29829e9a41694cb/ndk-cache-dexie/src/index.ts#L52)
-
-***
-
-### profileCacheSize?
-
-> `optional` **profileCacheSize**: `number`
-
-Number of profiles to keep in an LRU cache
-
-#### Defined in
-
-[ndk-cache-dexie/src/index.ts:50](https://github.com/nostr-dev-kit/ndk/blob/26ea669eeeadbc93b894cac1f29829e9a41694cb/ndk-cache-dexie/src/index.ts#L50)
-
-***
-
-### zapperCacheSize?
-
-> `optional` **zapperCacheSize**: `number`
-
-#### Defined in
-
-[ndk-cache-dexie/src/index.ts:51](https://github.com/nostr-dev-kit/ndk/blob/26ea669eeeadbc93b894cac1f29829e9a41694cb/ndk-cache-dexie/src/index.ts#L51)
diff --git a/docs/cache/nostr.md b/docs/cache/nostr.md
deleted file mode 100644
index ec166e2a..00000000
--- a/docs/cache/nostr.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# Nostr Cache Adapter
-
-NDK cache adapter using a nostr relay as the database.
-
-This cache adapter is meant to be run against a local relay. This adapter will generate two NDK instances:
-
-`ndk` -- This talks exclusively to the local relay, with outbox model disabled.
-`fallbackNdk` -- This is used to hydrate the cache and uses the outbox model -- each query the cache receives is placed in a queue in the background so that subsequent requests can be served from the cache. All events from other relays
-
-## Usage
-
-### Install
-
-```
-npm add @nostr-dev-kit/ndk-cache-nostr
-
-```
-
-### Add as a cache adapter
-
-```ts
-import NDKCacheAdapterNostr from "@nostr-dev-kit/ndk-cache-nostr";
-
-const cacheAdapter = new NDKCacheAdapterNostr({
- relayUrl: 'ws://localhost:5577',
-});
-const ndk = new NDK({ cacheAdapter });
-```
-
-If running server-side in a NodeJS environment, you should make sure to polyfill `WebSocket`.
-
-# License
-
-MIT
diff --git a/docs/getting-started/introduction.md b/docs/getting-started/introduction.md
deleted file mode 100644
index 50c63b8f..00000000
--- a/docs/getting-started/introduction.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Getting started
-
-## Installation
-
-```sh
-npm add @nostr-dev-kit/ndk
-```
-
-## Debugging
-
-NDK uses the `debug` package to assist in understanding what's happening behind the hood. If you are building a package
-that runs on the server define the `DEBUG` envionment variable like
-
-```sh
-export DEBUG='ndk:*'
-```
-
-or in the browser enable it by writing in the DevTools console
-
-```sh
-localStorage.debug = 'ndk:*'
-```
-
-## Network Debugging
-
-You can construct NDK passing a netDebug callback to receive network traffic events, particularly useful for debugging applications not running in a browser.
-
-```ts
-const netDebug = (msg: string, relay: NDKRelay, direction?: "send" | "recv") = {
- const hostname = new URL(relay.url).hostname;
- netDebug(hostname, msg, direction);
-}
-
-ndk = new NDK({ netDebug });
-```
diff --git a/docs/getting-started/signers.md b/docs/getting-started/signers.md
deleted file mode 100644
index 47346bef..00000000
--- a/docs/getting-started/signers.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Signers
-
-NDK uses signers _optionally_ passed in to sign events. Note that it is possible to use NDK without signing events (e.g. [to get someone's profile](https://github.com/nostr-dev-kit/ndk-cli/blob/master/src/commands/profile.ts)).
-
-Signing adapters can be passed in when NDK is instantiated or later during runtime.
-
-### Using a NIP-07 browser extension (e.g. Alby, nos2x)
-
-Instatiate NDK with a NIP-07 signer
-
-```ts
-// Import the package, NIP-07 signer and NDK event
-import NDK, { NDKEvent, NDKNip07Signer } from "@nostr-dev-kit/ndk";
-
-const nip07signer = new NDKNip07Signer();
-const ndk = new NDK({ signer: nip07signer });
-```
-
-NDK can now ask for permission, via their NIP-07 extension, to...
-
-**Read the user's public key**
-
-```ts
-nip07signer.user().then(async (user) => {
- if (!!user.npub) {
- console.log("Permission granted to read their public key:", user.npub);
- }
-});
-```
-
-**Sign & publish events**
-
-```ts
-const ndkEvent = new NDKEvent(ndk);
-ndkEvent.kind = 1;
-ndkEvent.content = "Hello, world!";
-ndkEvent.publish(); // This will trigger the extension to ask the user to confirm signing.
-```
\ No newline at end of file
diff --git a/docs/getting-started/usage.md b/docs/getting-started/usage.md
deleted file mode 100644
index 068f985c..00000000
--- a/docs/getting-started/usage.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# Usage
-
-## Instantiate an NDK instance
-
-You can pass an object with several options to a newly created instance of NDK.
-
-- `explicitRelayUrls` – an array of relay URLs.
-- `signer` - an instance of a [signer](#signers).
-- `cacheAdapter` - an instance of a [Cache Adapter](#caching)
-- `debug` - Debug instance to use for logging. Defaults to `debug("ndk")`.
-
-```ts
-// Import the package
-import NDK from "@nostr-dev-kit/ndk";
-
-// Create a new NDK instance with explicit relays
-const ndk = new NDK({
- explicitRelayUrls: ["wss://a.relay", "wss://another.relay"],
-});
-```
-
-If the signer implements the `getRelays()` method, NDK will use the relays returned by that method as the explicit relays.
-
-```ts
-// Import the package
-import NDK, { NDKNip07Signer } from "@nostr-dev-kit/ndk";
-
-// Create a new NDK instance with just a signer (provided the signer implements the getRelays() method)
-const nip07signer = new NDKNip07Signer();
-const ndk = new NDK({ signer: nip07signer });
-```
-
-Note: In normal client use, it's best practice to instantiate NDK as a singleton class. [See more below](#architecture-decisions--suggestions).
-
-## Connecting
-
-After you've instatiated NDK, you need to tell it to connect before you'll be able to interact with any relays.
-
-```ts
-// Import the package
-import NDK from "@nostr-dev-kit/ndk";
-
-// Create a new NDK instance with explicit relays
-const ndk = new NDK({
- explicitRelayUrls: ["wss://a.relay", "wss://another.relay"],
-});
-// Now connect to specified relays
-await ndk.connect();
-```
-
-## Architecture decisions & suggestions
-
-- Users of NDK should instantiate a single NDK instance.
-- That instance tracks state with all relays connected, explicit and otherwise.
-- All relays are tracked in a single pool that handles connection errors/reconnection logic.
-- RelaySets are assembled ad-hoc as needed depending on the queries set, although some RelaySets might be long-lasting, like the `explicitRelayUrls` specified by the user.
-- RelaySets are always a subset of the pool of all available relays.
diff --git a/docs/index.md b/docs/index.md
deleted file mode 100644
index 52fac990..00000000
--- a/docs/index.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-# https://vitepress.dev/reference/default-theme-home-page
-layout: home
-
-hero:
- name: "NDK Documentation"
- tagline: "Nostr Development Kit Docs"
- actions:
- - theme: brand
- text: Getting Started
- link: /getting-started/introduction.html
- - theme: secondary
- text: References
- link: https://github.com/nostr-dev-kit/ndk/blob/master/REFERENCES.md
-
----
-
-NDK is a nostr development kit that makes the experience of building Nostr-related applications, whether they are relays, clients, or anything in between, better, more reliable and overall nicer to work with than existing solutions.
\ No newline at end of file
diff --git a/docs/internals/subscriptions.md b/docs/internals/subscriptions.md
deleted file mode 100644
index ab328ce8..00000000
--- a/docs/internals/subscriptions.md
+++ /dev/null
@@ -1,205 +0,0 @@
-# Subscriptions Lifecycle
-When an application creates a subscription a lot of things happen under the hood.
-
-Say we want to see `kind:1` events from pubkeys `123`, `456`, and `678`.
-
-```ts
-const subscription = ndk.subscribe({ kinds: [1], authors: [ "123", "456", "678" ]})
-```
-
-Since the application level didn't explicitly provide a relay-set, which is the most common use case, NDK will calculate a relay set based on the outbox model plus a variety of some other factors.
-
-So the first thing we'll do before talking to relays is, decide to *which* relays we should talk to.
-
-The `calculateRelaySetsFromFilters` function will take care of this and provide us with a map of relay URLs and filters for each relay.
-
-This means that the query, as specified by the client might be broken into distinct queries specialized for the different relays.
-
-For example, if we have 3 relays, and the query is for `kind:1` events from pubkeys `a` and `b`, the `calculateRelaySetsFromFilters` function might return something like this:
-
-```ts
-{
- "wss://relay1": { kinds: [1], authors: [ "a" ] },
- "wss://relay2": { kinds: [1], authors: [ "b" ] },
-}
-```
-
-```mermaid
-flowchart TD
- Client -->|"kinds: [1], authors: [a, b]"| Subscription1
- Subscription1 -->|"kinds: [1], authors: [a]"| wss://relay1
- Subscription1 -->|"kinds: [1], authors: [b]"| wss://relay2
-```
-
-## Subscription bundling
-Once the subscription has been split into the filters each relay should receive, the filters are sent to the individual `NDKRelay`'s `NDKRelaySubscriptionManager` instances.
-
-`NDKRelaySubscriptionManager` is responsible for keeping track of the active and scheduled subscriptions that are pending to be executed within an individual relay.
-
-This is an important aspect to consider:
-
-> `NDKSubscription` have a different lifecycle than `NDKRelaySubscription`. For example, a subscription that is set to close after EOSE might still be active within the `NDKSubscription` lifecycle, but it might have been already been closed within the `NDKRelaySubscription` lifecycle, since NDK attempts to keep the minimum amount of open subscriptions at any given time.
-
-## NDKRelaySubscription
-Most NDK subscriptions (by default) are set to be executed with a grouping delay. Will cover what this looks like in practice later, but for now, let's understand than when the `NDKRelaySubscriptionManager` receives an order, it might not execute it right away.
-
-The different filters that can be grouped together (thus executed as a single `REQ` within a relay) are grouped within the same `NDKRelaySubscription` instance and the execution scheduler is computed respecting what each individual `NDKSubscription` has requested.
-
-(For example, if a subscription with a `groupingDelay` of `at-least` 500 millisecond has been grouped with another subscription with a `groupingDelay` of `at-least` 1000 milliseconds, the `NDKRelaySubscriptionManager` will wait 1000 ms before sending the `REQ` to this particular relay).
-
-### Execution
-Once the filter is executed at the relay level, the `REQ` is submitted into that relay's `NDKRelayConnectivity` instance, which will take care of monitoring for responses for this particular REQ and communicate them back into the `NDKRelaySubscription` instance.
-
-Each `EVENT` that comes back as a response to our `REQ` within this `NDKRelaySubscription` instance is then compared with the filters of each `NDKSubscription` that has been grouped and if it matches, it is sent back to the `NDKSubscription` instance.
-
-
-# Example
-
-If an application requests `kind:1` of pubkeys `123`, `456`, and `789`. It creates an `NDKSubscription`:
-
-```ts
-ndk.subscribe({ kinds: [1], authors: [ "123", "456", "789" ]}, { groupableDelay: 500, groupableDelayType: 'at-least' })
-// results in NDKSubscription1 with filters { kinds: [1], authors: [ "123", "456", "789" ] }
-```
-
-Some other part of the application requests a kind:7 from pubkey `123` at the same time.
-
-```ts
-ndk.subscribe({ kinds: [7], authors: [ "123" ]}, { groupableDelay: 500, groupableDelayType: 'at-most' })
-// results in NDKSubscription2 with filters { kinds: [7], authors: [ "123" ] }
-```
-
-```mermaid
-flowchart TD
- subgraph Subscriptions Lifecycle
- A[Application] -->|"kinds: [1], authors: [123, 456, 678], groupingDelay: at-least 500ms"| B[NDKSubscription1]
-
- A2[Application] -->|"kinds: [7], authors: [123], groupingDelay: at-most 1000ms"| B2[NDKSubscription2]
- end
-```
-
-Both subscriptions have their relayset calculated by NDK and, the resulting filters are sent into the `NDKRelaySubscriptionManager`, which will decide what, and how filters can be grouped.
-
-```mermaid
-flowchart TD
- subgraph Subscriptions Lifecycle
- A[Application] -->|"kinds: [1], authors: [123, 456, 678], groupingDelay: at-least 500ms"| B[NDKSubscription1]
- B --> C{Calculate Relay Sets}
-
- A2[Application] -->|"kinds: [7], authors: [123], groupingDelay: at-most 1000ms"| B2[NDKSubscription2]
- B2 --> C2{Calculate Relay Sets}
- end
-
- subgraph Subscription Bundling
- C -->|"kinds: [1], authors: [123]"| E1[wss://relay1 NDKRelaySubscriptionManager]
- C -->|"kinds: [1], authors: [456]"| E2[wss://relay2 NDKRelaySubscriptionManager]
- C -->|"kinds: [1], authors: [678]"| E3[wss://relay3 NDKRelaySubscriptionManager]
-
- C2 -->|"kinds: [7], authors: [123]"| E1
- end
-```
-
-The `NDKRelaySubscriptionManager` will create `NDKRelaySubscription` instances, or add filters to them if `NDKRelaySubscription` with the same filter fingerprint exists.
-
-```mermaid
-flowchart TD
- subgraph Subscriptions Lifecycle
- A[Application] -->|"kinds: [1], authors: [123, 456, 678], groupingDelay: at-least 500ms"| B[NDKSubscription1]
- B --> C{Calculate Relay Sets}
-
- A2[Application] -->|"kinds: [7], authors: [123], groupingDelay: at-most 1000ms"| B2[NDKSubscription2]
- B2 --> C2{Calculate Relay Sets}
- end
-
- subgraph Subscription Bundling
- C -->|"kinds: [1], authors: [123]"| E1[wss://relay1 NDKRelaySubscriptionManager]
- C -->|"kinds: [1], authors: [456]"| E2[wss://relay2 NDKRelaySubscriptionManager]
- C -->|"kinds: [1], authors: [678]"| E3[wss://relay3 NDKRelaySubscriptionManager]
-
- C2 -->|"kinds: [7], authors: [123]"| E1
-
- E1 -->|"Grouping Delay: at-most 1000ms"| F1[NDKRelaySubscription]
- E2 -->|"Grouping Delay: at-least 500ms"| F2[NDKRelaySubscription]
- E3 -->|"Grouping Delay: at-least 500ms"| F3[NDKRelaySubscription]
- end
-```
-
-Each individual `NDKRelaySubscription` computes the execution schedule of the filters it has received and sends them to the `NDKRelayConnectivity` instance, which in turns sends the `REQ` to the relay.
-
-```mermaid
-flowchart TD
- subgraph Subscriptions Lifecycle
- A[Application] -->|"kinds: [1], authors: [123, 456, 678], groupingDelay: at-least 500ms"| B[NDKSubscription1]
- B --> C{Calculate Relay Sets}
-
- A2[Application] -->|"kinds: [7], authors: [123], groupingDelay: at-most 1000ms"| B2[NDKSubscription2]
- B2 --> C2{Calculate Relay Sets}
- end
-
- subgraph Subscription Bundling
- C -->|"kinds: [1], authors: [123]"| E1[wss://relay1 NDKRelaySubscriptionManager]
- C -->|"kinds: [1], authors: [456]"| E2[wss://relay2 NDKRelaySubscriptionManager]
- C -->|"kinds: [1], authors: [678]"| E3[wss://relay3 NDKRelaySubscriptionManager]
-
- C2 -->|"kinds: [7], authors: [123]"| E1
-
- E1 -->|"Grouping Delay: at-most 1000ms"| F1[NDKRelaySubscription]
- E2 -->|"Grouping Delay: at-least 500ms"| F2[NDKRelaySubscription]
- E3 -->|"Grouping Delay: at-least 500ms"| F3[NDKRelaySubscription]
-
- F1 -->|"REQ: kinds: [1, 7], authors: [123]"| G1[NDKRelayConnectivity]
- F2 -->|"REQ: kinds: [1], authors: [456]"| G2[NDKRelayConnectivity]
- F3 -->|"REQ: kinds: [1], authors: [678]"| G3[NDKRelayConnectivity]
- end
-
- subgraph Execution
- G1 -->|"Send REQ to wss://relay1 after 1000ms"| R1[Relay1]
- G2 -->|"Send REQ to wss://relay2 after 500ms"| R2[Relay2]
- G3 -->|"Send REQ to wss://relay3 after 500ms"| R3[Relay3]
- end
-```
-
-As the events come from the relays, `NDKRelayConnectivity` will send them back to the `NDKRelaySubscription` instance, which will compare the event with the filters of the `NDKSubscription` instances that have been grouped together and send the received event back to the correct `NDKSubscription` instance.
-
-```mermaid
-flowchart TD
- subgraph Subscriptions Lifecycle
- A[Application] -->|"kinds: [1], authors: [123, 456, 678], groupingDelay: at-least 500ms"| B[NDKSubscription1]
- B --> C{Calculate Relay Sets}
-
- A2[Application] -->|"kinds: [7], authors: [123], groupingDelay: at-most 1000ms"| B2[NDKSubscription2]
- B2 --> C2{Calculate Relay Sets}
- end
-
- subgraph Subscription Bundling
- C -->|"kinds: [1], authors: [123]"| E1[wss://relay1 NDKRelaySubscriptionManager]
- C -->|"kinds: [1], authors: [456]"| E2[wss://relay2 NDKRelaySubscriptionManager]
- C -->|"kinds: [1], authors: [678]"| E3[wss://relay3 NDKRelaySubscriptionManager]
-
- C2 -->|"kinds: [7], authors: [123]"| E1
-
- E1 -->|"Grouping Delay: at-most 1000ms"| F1[NDKRelaySubscription]
- E2 -->|"Grouping Delay: at-least 500ms"| F2[NDKRelaySubscription]
- E3 -->|"Grouping Delay: at-least 500ms"| F3[NDKRelaySubscription]
-
- F1 -->|"REQ: kinds: [1, 7], authors: [123]"| G1[NDKRelayConnectivity]
- F2 -->|"REQ: kinds: [1], authors: [456]"| G2[NDKRelayConnectivity]
- F3 -->|"REQ: kinds: [1], authors: [678]"| G3[NDKRelayConnectivity]
- end
-
- subgraph Execution
- G1 -->|"Send REQ to wss://relay1 after 1000ms"| R1[Relay1]
- G2 -->|"Send REQ to wss://relay2 after 500ms"| R2[Relay2]
- G3 -->|"Send REQ to wss://relay3 after 500ms"| R3[Relay3]
-
- R1 -->|"EVENT: kinds: [1]"| H1[NDKRelaySubscription]
- R1 -->|"EVENT: kinds: [7]"| H2[NDKRelaySubscription]
- R2 -->|"EVENT"| H3[NDKRelaySubscription]
- R3 -->|"EVENT"| H4[NDKRelaySubscription]
-
- H1 -->|"Matched Filters: kinds: [1]"| I1[NDKSubscription1]
- H2 -->|"Matched Filters: kinds: [7]"| I2[NDKSubscription2]
- H3 -->|"Matched Filters: kinds: [1]"| I1
- H4 -->|"Matched Filters: kinds: [1]"| I1
- end
-```
\ No newline at end of file
diff --git a/docs/markdown-examples.md b/docs/markdown-examples.md
deleted file mode 100644
index f9258a55..00000000
--- a/docs/markdown-examples.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Markdown Extension Examples
-
-This page demonstrates some of the built-in markdown extensions provided by VitePress.
-
-## Syntax Highlighting
-
-VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting:
-
-**Input**
-
-````md
-```js{4}
-export default {
- data () {
- return {
- msg: 'Highlighted!'
- }
- }
-}
-```
-````
-
-**Output**
-
-```js{4}
-export default {
- data () {
- return {
- msg: 'Highlighted!'
- }
- }
-}
-```
-
-## Custom Containers
-
-**Input**
-
-```md
-::: info
-This is an info box.
-:::
-
-::: tip
-This is a tip.
-:::
-
-::: warning
-This is a warning.
-:::
-
-::: danger
-This is a dangerous warning.
-:::
-
-::: details
-This is a details block.
-:::
-```
-
-**Output**
-
-::: info
-This is an info box.
-:::
-
-::: tip
-This is a tip.
-:::
-
-::: warning
-This is a warning.
-:::
-
-::: danger
-This is a dangerous warning.
-:::
-
-::: details
-This is a details block.
-:::
-
-## More
-
-Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown).
diff --git a/docs/mobile/index.md b/docs/mobile/index.md
deleted file mode 100644
index e78b9544..00000000
--- a/docs/mobile/index.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# NDK Mobile
-
-A React Native/Expo implementation of [NDK (Nostr Development Kit)](https://github.com/nostr-dev-kit/ndk) that provides a complete toolkit for building Nostr applications on mobile platforms.
-
-## Features
-
-- 🔐 Multiple signer implementations (NIP-07, NIP-46, Private Key)
-- 💾 SQLite-based caching for offline support
-- 🔄 Subscription management with automatic reconnection
-- 📱 React Native and Expo compatibility
-- 🪝 React hooks for easy state management
-- 👛 Integrated wallet support
-
-## Installation
-
-```sh
-npm install @nostr-dev-kit/ndk-mobile
-```
-
-## Usage
-
-When using this library don't import `@nostr-dev-kit/ndk` directly, instead import `@nostr-dev-kit/ndk-mobile`. `ndk-mobile` exports the same classes as `ndk`, so you can just swap the import.
-
-Once you have imported the library, you can use the `NDKProvider` to wrap your application. Pass as props all the typical arguments you would pass to an `new NDK()` call.
-
-```tsx
-function App() {
- return {/* your app here */} ;
-}
-```
-
-## useNDK()
-
-`useNDK()` provides access to the `ndk` instance and some other useful information.
-
-```tsx
-function LoginScreen() {
- const { ndk, currentUser, login } = useNDK();
-
- useEffect(() => {
- if (currentUser) alert("you are now logged in as ", +currentUser.pubkey);
- }, [currentUser]);
-
- return login(withPayload("nsec1..."))} title="Login" />;
-}
-```
-
-## Example
-
-There is a barebones repository showing how to use this library:
-[ndk-mobile-sample](https://github.com/pablof7z/ndk-mobile-sample).
-
-For a real application using this look at [Olas](https://github.com/pablof7z/snapstr).
diff --git a/docs/mobile/profile-hook.md b/docs/mobile/profile-hook.md
deleted file mode 100644
index b7f3b0f4..00000000
--- a/docs/mobile/profile-hook.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Using `useUserProfile` in `ndk-mobile`
-
-Efficiently managing user profiles is crucial for mobile applications. The `useUserProfile` hook helps streamline this process by using the SQLite cache adapter, reducing unnecessary re-renderings when the profile can be loaded synchronously.
-
-Here's a simple example of how to use the `useUserProfile` hook in a component:
-
-```tsx
-import React from "react";
-import { useUserProfile } from "ndk-mobile";
-
-function UserProfile({ pubkey }) {
- const { userProfile, loading } = useUserProfile(pubkey);
-
- if (loading) return Loading... ;
-
- return {userProfile.displayName} ;
-}
-
-export default UserProfile;
-```
diff --git a/docs/mobile/session.md b/docs/mobile/session.md
deleted file mode 100644
index 718478f1..00000000
--- a/docs/mobile/session.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# Session Management
-
-`ndk-mobile` provides a way to manage session events that are typically necessary to have available throughout an entire app.
-
-Wrapping your application with `` provides access to the session context.
-
-Say for example you want to allow your user to interface with their bookmarks, you want to have access to their bookmarks anywhere in the app both for reading and writing.
-
-```ts
-
-const kinds = new Map([
- [NDKKind.ImageCurationSet, { wrapper: NDKList }],
-]);
-
-
-
-
-```
-
-Now say you want to allow the user to bookmark something with the click of a button:
-
-```tsx
-const { imageCurationSet } = useNDKSessionEventKind(NDKList, NDKKind.ImageCurationSet, {
- create: true,
-});
-
-const bookmark = async () => {
- await imageCurationSet.addItem(event);
-};
-```
-
-Now, when your app calls the `bookmark` function, it will add the event to the user's image curation set, if none exists it will create one for you.
-
-```
-
-```
diff --git a/docs/mobile/subscriptions.md b/docs/mobile/subscriptions.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/mobile/wallet.md b/docs/mobile/wallet.md
deleted file mode 100644
index 63ec5d1d..00000000
--- a/docs/mobile/wallet.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Wallet
-
-ndk-mobile makes operating with nostr wallets as seamless as possible.
-
-## Initialize
-
-When setting up your NDKSession provider, make sure to activate the wallet prop, to indicate you want to enable this feature.
-
-```ts
-
-```
-
-If your user has implicitly or explicitly enabled a wallet in your app you can also pass the configuration into the provider to immediately make the wallet available throughout your app.
-
-```ts
-const walletConfig = {
- // type of wallet to enable
- type: 'nip-60',
-
- // some wallet Id this user can use
- walletId: 'naddr1qvzqqqy3lupzq8mxja28nlfd6269zzzsm8feqxrl5eapf7g5fretnpucjh0xlannqythwumn8ghj7un9d3shjtnswf5k6ctv9ehx2ap0qqgx5un0weuxsmp5w4ax2e3cwe382kngsvc'
-
-
-```
-
-## Using the wallet
-
-Now from within your app you can easily zap via the `NDKZapper`, check balance, receive payments, and any other interaction you can use `ndk-wallet`.
-
-```ts
-const { activeWallet, balances } = useNDKSession();
-
-async function generateDeposit() {
- const deposit = activeWallet.deposit(10, activeWallet.mints[0], 'sat');
- deposit.on('success', () => console.log('✅ deposit'))
- const bolt11 = await deposit.start();
- console.log('pay this LN invoice', bolt11);
-}
-
-return (
-
- Wallet balances = {JSON.stringify(balances)}
-
-
-
-)
-```
diff --git a/docs/tutorial/auth.md b/docs/tutorial/auth.md
deleted file mode 100644
index 664c6cdd..00000000
--- a/docs/tutorial/auth.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Relay Authentication
-
-NIP-42 defines that relays can request authentication from clients.
-
-NDK makes working with NIP-42 very simple. NDK uses an `NDKAuthPolicy` callback to provide a way to handle authentication requests.
-
-* Relays can have specific `NDKAuthPolicy` functions.
-* NDK can be configured with a default `relayAuthDefaultPolicy` function.
-* NDK provides some generic policies:
- * `NDKAuthPolicies.signIn`: Authenticate to the relay (using the `ndk.signer` signer).
- * `NDKAuthPolicies.disconnect`: Immediately disconnect from the relay if asked to authenticate.
-
-```ts
-import { NDK, NDKRelayAuthPolicies } from "@nostr-dev-kit/ndk";
-
-const ndk = new NDK();
-ndk.addExplicitRelay("wss://relay.f7z.io", NDKRelayAuthPolicies.signIn({ndk}));
-```
-
-Clients should typically allow their users to choose where to authenticate. This can be accomplished by returning the decision the user made from the `NDKAuthPolicy` function.
-
-```ts
-import { NDK, NDKRelayAuthPolicies } from "@nostr-dev-kit/ndk";
-
-const ndk = new NDK();
-ndk.relayAuthDefaultPolicy = (relay: NDKRelay) => {
- return confirm(`Authenticate to ${relay.url}?`);
-};
-```
diff --git a/docs/tutorial/index.md b/docs/tutorial/index.md
deleted file mode 100644
index 5570c7ff..00000000
--- a/docs/tutorial/index.md
+++ /dev/null
@@ -1 +0,0 @@
-# Hello
\ No newline at end of file
diff --git a/docs/tutorial/local-first.md b/docs/tutorial/local-first.md
deleted file mode 100644
index aa9efa93..00000000
--- a/docs/tutorial/local-first.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# Local first
-
-NDK allows for local-first software.
-
-This mode of operation depends on a few key things:
-* A cache adapter must be present
-* Events `event:publish-failed` should be handled by the application
-
-A few considerations:
-* Failed events are automatically retried by NDK
-* Handling of failed events is up to the application; handling here exclusively refers to notifying the user and updating the UI accordingly
-
-## Blocked publishing
-The default behavior when publishing an event will make `event.publish()` block
-until the event has been published or a failure has ocurred.
-```ts
-const event = new NDKEvent(ndk, { kind: 1, content: 'Blocking event' });
-const publishedToRelays = await event.publish();
-console.log(publishedToRelays); // relays where the event has published to
-```
-
-## Optimistic publishing
-If you want to publish an event without waiting for it to be published, you can use the `event.publish()` method.
-```ts
-const event = new NDKEvent(ndk, { kind: 1, content: 'Optimistic event' });
-event.publish();
-```
-
-When using a cache adapter that supports unpublished event tracking (like `NDKCacheAdapterDexie`), the event will be first
-written to the cache and then published to relays. When a minimal amount of relays have successfully received the event, the event will be removed from the cache.
-
-With this technique you can fire and forget event publshing.
-
-## Handling persistent failures
-When an event fails to publish, you can handle the failure by listening to the `event.failed` event.
-
-You should handle this event to notify the user that the event has failed to publish and update the UI accordingly.
-
-```ts
-// application-wide
-function handlePublishingFailures(event: NDKEvent, error: NDKPublishError) {
- console.log(`Event ${event.id} failed to publish`, { publishedToRelays: error.publishedToRelays });
-}
-
-ndk.on("event:publish-failed", handlePublishingFailures);
-const event = new NDKEvent(ndk, { kind: 1, content: 'Failing event' });
-event.publish();
-```
-
-## Querying cached failed events
-Cache adapters with support for failed publish tracking can be queried via the `getUnpublishedEvents` interface.
-
-```ts
-const failedEvents = ndk.cachedAdapter.getUnpublishedEvents()
-
-console.log(failedEvents.length + " events have not published before; trying now");
-failedEvents.forEach((event) => event.publish());
-```
-
-When an event successfully publishes, the event will emit `published`.
-
-## Handling retries
-When booting up your application, NDK will automatically reattempt to publish any events that have failed to publish in the past.
diff --git a/docs/tutorial/publishing.md b/docs/tutorial/publishing.md
deleted file mode 100644
index 4298ebe2..00000000
--- a/docs/tutorial/publishing.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Publishing Events
-
-## Optimistic publish lifecycle
-
-Read more about the [local-first](./local-first.md) mode of operation.
-
-## Publishing Replaceable Events
-
-Some events in Nostr allow for replacement.
-
-Kinds `0`, `3`, range `10000-19999`.
-
-Range `30000-39999` is parameterized replaceable events, which means that multiple events of the same kind under the same pubkey can exist and are differentiated via their `d` tag.
-
-Since replaceable events depend on having a newer `created_at`, NDK provides a convenience method to reset `id`, `sig`, and `created_at` to allow for easy replacement.
-
-```ts
-const existingEvent = await ndk.fetchEvent({ kinds: [0], authors: []}); // fetch the event to replace
-existingEvent.tags.push(
- [ "p", "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" ] // follow a new user
-);
-existingEvent.publish();
-```
-
-Since this is a replaceable event but the id+sig+created_at hasn't been changed, this won't work.
-
-```ts
-existingEvent.id = "";
-existingEvent.sig = "";
-existingEvent.created_at = undefined;
-existingEvent.publish(); // this will work
-```
-
-or what's equivalent:
-
-```ts
-existingEvent.publishReplaceable();
-```
\ No newline at end of file
diff --git a/docs/tutorial/speed.md b/docs/tutorial/speed.md
deleted file mode 100644
index 80cde51b..00000000
--- a/docs/tutorial/speed.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# Built for speed
-
-NDK makes multiple optimizations possible to create a performant client.
-
-## Signature Verifications
-Signature validation is typically the most computationally expensive operation in a nostr client. Thus, NDK attempts to reduce the number of signature verifications that need to be done as much as possible.
-
-### Service Worker signature validation
-In order to create performant clients, it's very useful to offload this computation to a service worker, to avoid blocking the main thread.
-
-```ts
-// Using with vite
-const sigWorker = import.meta.env.DEV ?
- new Worker(new URL('@nostr-dev-kit/ndk/workers/sig-verification?worker', import.meta.url), { type: 'module' }) : new NDKSigVerificationWorker();
-
-const ndk = new NDK();
-ndk.signatureVerificationWorker = worker
-```
-
-Since signature verification will thus be done asynchronously, it's important to listen for invalid signatures and handle them appropriately; you should
-always warn your users when they are receiving invalid signatures from a relay and/or immediately disconnect from an evil relay.
-
-```ts
-ndk.on("event:invalid-sig", (event) => {
- const { relay } = event;
- console.error("Invalid signature coming from relay", relay.url);
-});
-```
-
-### Signature verification sampling
-Another parameter we can tweak is how many signatures we verify. By default, NDK will verify every signature, but you can change this by setting a per-relay verification rate.
-
-```ts
-ndk.initialValidationRatio = 0.5; // Only verify 50% of the signatures for each relay
-ndk.lowestValidationRatio = 0.01; // Never verify less than 1% of the signatures for each relay
-```
-
-NDK will then begin verifying signatures from each relay and, as signatures as verified, it will reduce the verification rate for that relay.
-
-### Custom validation ratio function
-If you need further control on how the verification rate is adjusted, you can provide a validation ratio function. This function will be called periodically and the returning value will be used to adjust the verification rate.
-
-```ts
-ndk.validationRatioFn = (relay: NDKRelay, validatedEvents: number, nonValidatedEvents: number): number => {
- // write your own custom function here
- return validatedEvents / (validatedEvents + nonValidatedEvents);
-}
-```
\ No newline at end of file
diff --git a/docs/tutorial/subscription-management.md b/docs/tutorial/subscription-management.md
deleted file mode 100644
index 4461f666..00000000
--- a/docs/tutorial/subscription-management.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Subscription Management
-
-NDK attempts to intelligently group subscriptions to avoid excessively hitting relays with too many subscriptions when similar requests are going to be created with similar requests.
-
-Take the example of an application rendering a list of events along with the authors' name.
-
-This would typically be accomplished by creating a subscription for the desired events, say, kind:1s with a `#nostr` tag.
-
-```ts
-const sub = ndk.subscribe({ kinds: [ 1 ], "#t": [ "nostr" ] })
-sub.on("event", (event: NDKEvent) => {
- const author = event.author;
- const profile = await author.fetchProfile();
-
- console.log(`${profile.name}: ${event.content}`);
-})
-```
-
-Now, this seemingly simple approach would have created a kind:0 subscription (`fetchProfile()`) for each note.
-
-Not great. Most relays will start to reject subscriptions when you have around 10 or 20 active requests.
-
-In this case, NDK will automatically realize that you are requesting `kind:0` events for a lot of different pubkeys and group them into a single subscription.
-
-Without grouping:
-```ts
-[ "REQ", "", '{ "kinds": [0], pubkeys: [ "pubkey1" ] }'],
-[ "REQ", "", '{ "kinds": [0], pubkeys: [ "pubkey2" ] }'],
-[ "REQ", "", '{ "kinds": [0], pubkeys: [ "pubkey3" ] }'],
-[ "REQ", "", '{ "kinds": [0], pubkeys: [ "pubkey4" ] }'],
-[ "REQ", "", '{ "kinds": [0], pubkeys: [ "pubkey5" ] }'],
-```
-
-With grouping:
-```ts
-[ "REQ", "", '{ "kinds": [0], pubkeys: [ "pubkey1", "pubkey2", "pubkey3", "pubkey4", "pubkey5" ] }'],
-```
-
-Application code doesn't need to concern itself with checking if the event they are receiving is the one they asked for; NDK will only call the event handler with the correct event so that the grouping is transparent to the application.
-
-## Disabling Grouping
-
-Sometimes you have a specific need or are certain that you won't be requesting multiple requests of the same type, so we can safely disable grouping and enjoy a small performance boost (since we don't need to wait for grouping to happen).
-
-```ts
-const sub = ndk.subscribe({ kinds: [ 1 ], "#t": [ "nostr" ] }, { groupable: false })
-```
-
-This will make the REQ for `kind:1` events to hit the relays immediately and skip the `100ms` (default) grouping window.
-
-If you want to change the grouping delay you can do so by setting the `groupingDelay` option
-
-```ts
-const sub = ndk.subscribe({ kinds: [ 1 ], "#t": [ "nostr" ] }, { groupingDelay: 500 })
-```
-
-You can also establish how the delay should be interpreted:
-
-```ts
-const sub = ndk.subscribe({ kinds: [ 1 ], "#t": [ "nostr" ] }, { groupingDelayType: "at-least" })
-// * "at-least" means "wait at least this long before sending the subscription"
-// * "at-most" means "wait at most this long before sending the subscription"
-```
-
-When using `at-least` the subscription timer will be reset every time a new subscription is added to the group.
-
-For example, if you create two subscriptions, one at `t=0` and the other one 50ms later (`t=50ms`), with a `groupableDelay` of `200ms`, `at-least` would send the subscription at `t=250ms` and `at-most` would send it at `t=200ms`.
\ No newline at end of file
diff --git a/docs/tutorial/zaps/index.md b/docs/tutorial/zaps/index.md
deleted file mode 100644
index 1c388ebd..00000000
--- a/docs/tutorial/zaps/index.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Zaps
-
-NDK comes with an interface to make zapping as simple as possible.
-
-```ts
-const user = await ndk.getUserFromNip05("pablo@f7z.io");
-const lnPay = ({ pr: string }) => {
- console.log("please pay to complete the zap", pr);
-};
-const zapper = new NDKZapper(user, 1000, { lnPay });
-zapper.zap();
-```
-
-## NDK-Wallet
-
-Refer to the Wallet section of the tutorial to learn more about zapping. NDK-wallet provides many conveniences to integrate with zaps.
diff --git a/docs/wallet/discover.md b/docs/wallet/discover.md
deleted file mode 100644
index 7a378678..00000000
--- a/docs/wallet/discover.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# Discover wallets
-
-A user might have configured your application to use a specific wallet (e.g. via WebLN), or they could be
-interfacing with your application with a NIP-60 wallet created somewhere else.
-
-Additionally, a user might have NIP-61 nutzaps enabled.
-
-The `NDKWalletService` provides a simple interface to handle these cases:
-* Configure + Discover configured wallets
-* See NIP-61 nutzaps
-
-## Discovering configured wallets
-```typescript
-const walletService = new NDKWalletService(ndk);
-
-walletService.start();
-walletService.on("wallet", (wallet: NDKWallet, isDefault: boolean) => {
- console.log("Found a wallet of type " + wallet.type, isDefault ? "(default)" : "");
-});
-```
-
-`walletService.start()` will do the following:
-* If you have established a client name via `ndk.clientName`, it will look for a NIP-78 configuration
-
-## Configuring a wallet for your application
-```typescript
-ndk.clientName = 'my-application';
-const walletService = new NDKWalletService(ndk);
-const wallet = new NDKWebLNWallet();
-await walletService.setDefaultWallet(wallet);
-```
-
-`walletService.setDefaultWallet(wallet)` will add to your applications's NIP-78, the configuration to be able to use this wallet next time your application starts, next time your application is initialized, `walletService.start()` will emit a `wallet` event for this wallet.
-
-## Seeing NIP-61 nutzaps
-```typescript
-const walletService = new NDKWalletService(ndk);
-walletService.start();
-walletService.on("nutzap", (nutzap: NDKNutzap) => {
- console.log("Received a nutzap from " + nutzap.pubkey + " for " + nutzap.amount + " " + nutzap.unit + " on mint " + nutzap.mint);
- // -> "Received a nutzap from fa98..... for 1 usd on mint https://..."
-});
-```
-
diff --git a/docs/wallet/index.md b/docs/wallet/index.md
deleted file mode 100644
index 421fb57f..00000000
--- a/docs/wallet/index.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Wallet
-
-NDK provides an optional `@nostr-dev-kit/ndk-wallet` package, which provides common interfaces and functionalities to interface with different wallet adapters.
-
-Currently ndk-wallet supports:
-
-- NIP-60 wallets (nutsacks)
-- NIP-47 connectors (NWC)
-- WebLN (when available)
-
-## Connecting NDK with a wallet
-
-As a developer, the first thing you need to do to use a wallet in your app is to choose how you will connect to your wallet by using one of the wallet adapters.
-
-Once you instantiate the desired wallet, you simply pass it to ndk.
-
-```ts
-const wallet = new NDKNWCWallet(ndk);
-await wallet.initWithPairingCode("nostr+walletconnect:....");
-ndk.wallet = wallet;
-```
-
-Now whenever you want to pay something, the wallet will be called. Refer to the Nutsack adapter to see more details of the interface.
diff --git a/docs/wallet/nutsack.md b/docs/wallet/nutsack.md
deleted file mode 100644
index 28760f65..00000000
--- a/docs/wallet/nutsack.md
+++ /dev/null
@@ -1,95 +0,0 @@
-# NIP-60 (Nutack) wallets
-
-NIP-60 provides wallets that are available to any nostr application immediately; the goal of NIP-60 is to provide the same
-seamless experience nostr users expect from their apps with regards to the immediate aailability of their data, to their money.
-
-## Creating a NIP-60 wallet
-
-```ts
-import NDKWallet from "@nostr-dev-kit/ndk-wallet";
-import NDK from "@nostr-dev-kit/ndk";
-
-// instantiate your NDK
-const ndk = new NDK({
- explicitRelayUrls: [ ],
- signer = NDKPrivateKeySigner.generate();
-});
-ndk.connect();
-
-// create a new NIP-60 wallet
-const unit = "sat"; // unit of the wallet
-const mints = [ 'https://testnut.cashu.space' ] // mints the wallet will use
-const relays = [ 'wss://f7z.io', 'ws://localhost:4040' ]; // relays where proofs will be stored
-const wallet = NDKCashuWallet.create(ndk, unit, mints, relays);
-await wallet.publish();
-```
-
-This will publish a wallet `kind:37376` event, which contains the wallet information.
-
-We now have a NIP-60 wallet -- this wallet will be available from any nostr client that supports NIP-60.
-
-## Deposit money
-
-```ts
-const deposit = wallet.deposit(1000, mints[0]);
-const bolt11 = deposit.start(); // get a LN PR
-deposit.on("success", () => console.log("we have money!", wallet.balance()));
-```
-
-## Configure NDK to use a wallet
-
-You can configure NDK to use some wallet, this is equivalent for whatever wallet adapter you choose to use.
-
-```ts
-ndk.wallet = wallet;
-```
-
-## Send a zap
-
-Now that we have a wallet, some funds, and we have ndk prepared to use that wallet, we'll send a zap. NDK provides a convenient `wallet` setter that allows
-
-```ts
-const user = await NDKUser.fronNip05("_@f7z.io");
-const zapper = new NDKZapper(user, 1, "sat", {
- comment: "hello from my wallet!",
-});
-zapper.on("complete", () => console.log("pablo was zapped!"));
-zapper.zap();
-```
-
-## Zapping without a wallet
-
-If you don't connect a wallet to ndk and attempt to zap, you will receive the zapping information(s) so you can give your users the possibility of paying manually.
-
-```ts
-// no wallet
-ndk.wallet = undefined;
-
-// this function will be called when a bolt11 needs to be paid
-const lnPay = async (payment: NDKZapDetails) => {
- console.log("please pay this invoice to complete the zap", payment.pr);
-};
-
-const zapper = new NDKZapper(user, 1, "sat", { comment: "manual zapping", lnPay });
-const paymentInfo = await zapper.zap();
-```
-
-You can also configure this at the application level, for example, to open a modal whenever a payment needs to be done
-
-```ts
-const lnPay = async (payment: NDKZapDetails) => {
- alert("please pay this invoice: " + payment.pr);
-};
-
-ndk.wallet = { lnPay };
-```
-
-## Receiving ecash
-
-To receive ecash just call the `receiveToken` method on the wallet.
-
-```ts
-const tokenEvent = await wallet.receiveToken(token);
-```
-
-This will swap the tokens in the right mint and add them to the wallet. Note that if the mint of this token is not one of the ones in the wallet you will need to move them to the mint you want manually.
diff --git a/docs/wallet/nutzaps.md b/docs/wallet/nutzaps.md
deleted file mode 100644
index d5b92826..00000000
--- a/docs/wallet/nutzaps.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Nutzaps
-
-ndk-wallet provides a simple way to automatically redeem nutzaps. You can run this periodically or you can just start it as part of the boostrap of your application
-
-# Sweeping NIP-61 nutzaps
-
-When a user receives a nutzap, they should sweep the public tokens into their wallet, the `@nostr-dev-kit/ndk-wallet` package takes care of this for you when
-the `NDKWalletService` is running by default.
-
-```ts
-const walletService = new NDKWalletService(ndk);
-walletService.start();
-walletService.on("nutzap", (nutzap: NDKNutzap) => {
- console.log("Received a nutzap", nutzap);
-});
-```
diff --git a/docs/wrappers/svelte.md b/docs/wrappers/svelte.md
deleted file mode 100644
index c3946a43..00000000
--- a/docs/wrappers/svelte.md
+++ /dev/null
@@ -1,107 +0,0 @@
-# NDK Svelte
-
-NDK Svelte is a wrapper around NDK that provides convenient accessors to use NDK in Svelte applications.
-
-## Install
-
-```
-pnpm add @nostr-dev-kit/ndk-svelte --save
-```
-
-## Store subscriptions
-
-NDK-svelte provides Svelte Store subscriptions so your components can have simple reactivity
-when events arrive.
-
-Events in the store will appear in a set ordered by `created_at`.
-
-```typescript
-import NDKSvelte from "@nostr-dev-kit/ndk-svelte";
-
-const ndk = new NDKSvelte({
- explicitRelayUrls: ["wss://relay.f7z.io"],
-});
-```
-
-```typescript
-// in your components
-
-
-
- {$highlights.length} highlights seen
-
-
-
- {$nostrHighlightsAndReposts.length} nostr highlights (including reposts)
-
-```
-
-## Reference Counting with ref/unref
-
-NDK-svelte introduces a reference counting mechanism through the ref and unref methods on the stores. This system is particularly useful for optimizing the lifecycle of subscriptions in components that might be frequently mounted and unmounted.
-
-### Benefits:
-
-- **Optimized Lifecycle**: Instead of starting a new subscription every time a component mounts, and ending it when it unmounts, you can reuse an existing subscription if another component is already using it.
-
-- **Resource Efficiency**: By preventing redundant subscriptions, you save both network bandwidth and processing power.
-
-- **`Synchronization**: Ensures that multiple components referencing the same data are synchronized with a single data source.
-
-### How to use:
-
-Whenever you subscribe to a store in a component, call ref to increment the reference count:
-
-```ts
-// lib/stores/highlightsStore.ts
-const highlightsStore = $ndk.storeSubscribe(..., { autoStart: false } });
-
-// component 1
-
-
-{$highlightsStore.length} highlights seen
-```
-
-You can mount this component as many times as you want, and the subscription will only be started once. When the last component unmounts, the subscription will be terminated.
-
-## Manual access to subscriptions
-You should probably not need this, so if you are peaking into how to try to access directly to the subscriptions, you are probably doing something wrong. But, in the extremely rare case you need to access the subscriptions directly, you can do so by adding a callback with the `onEvent` option.
-
-Note that this is not recommended and the `onEvent` callback will be called immediately, without ordering events by latest version (i.e. on replace events)
-
-```ts
-const highlights = $ndk.storeSubscribe(
- { kinds: [9802 as number] }, // Highlights
- {
- onEvent: (event) => console.log("Event received", event),
- onEose: () => console.log("Subscription EOSE reached")
- }
-);
-```
\ No newline at end of file
diff --git a/ndk-cache-dexie/.gitignore b/ndk-cache-dexie/.gitignore
deleted file mode 100644
index 0fd84284..00000000
--- a/ndk-cache-dexie/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-.DS_Store
-node_modules
-**/*.js
-dist
-docs
diff --git a/ndk-cache-dexie/.prettierignore b/ndk-cache-dexie/.prettierignore
deleted file mode 100644
index 53c37a16..00000000
--- a/ndk-cache-dexie/.prettierignore
+++ /dev/null
@@ -1 +0,0 @@
-dist
\ No newline at end of file
diff --git a/ndk-cache-dexie/CHANGELOG.md b/ndk-cache-dexie/CHANGELOG.md
deleted file mode 100644
index ea37cb50..00000000
--- a/ndk-cache-dexie/CHANGELOG.md
+++ /dev/null
@@ -1,389 +0,0 @@
-# @nostr-dev-kit/ndk-cache-dexie
-
-## 2.5.8
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.7
-
-## 2.5.7
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.6
-
-## 2.5.6
-
-### Patch Changes
-
-- Updated dependencies [5939a3e]
-- Updated dependencies
-- Updated dependencies [f2a0cce]
- - @nostr-dev-kit/ndk@2.10.5
-
-## 2.5.5
-
-### Patch Changes
-
-- Updated dependencies [5bed70c]
-- Updated dependencies [873ad4a]
- - @nostr-dev-kit/ndk@2.10.4
-
-## 2.5.4
-
-### Patch Changes
-
-- Updated dependencies [0fc66c5]
- - @nostr-dev-kit/ndk@2.10.3
-
-## 2.5.3
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.2
-
-## 2.5.2
-
-### Patch Changes
-
-- d6cfa8a: track at which timestamp we cached events
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [722345b]
- - @nostr-dev-kit/ndk@2.10.1
-
-## 2.5.1
-
-### Patch Changes
-
-- apply limit filter
-- abb3cd9: add tests
-- index event kinds and add byKinds filter
-- improve profile fetching from dexie
-- 3029124: add methods to access and manage unpublished events from the cache
-- Updated dependencies [ec83ddc]
-- Updated dependencies [18c55bb]
-- Updated dependencies
-- Updated dependencies [18c55bb]
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies [3029124]
- - @nostr-dev-kit/ndk@2.10.0
-
-## 2.5.0
-
-### Minor Changes
-
-- fix bug where we are indexing really events tags unrestricted
-- control that we don't unnecessarily load more stuff into the LRU beyond it's max size
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.9.1
-
-## 2.4.3
-
-### Patch Changes
-
-- 548f4d8: add optimistic updates
-- Updated dependencies [94018b4]
-- Updated dependencies [548f4d8]
- - @nostr-dev-kit/ndk@2.9.0
-
-## 2.4.2
-
-### Patch Changes
-
-- cache relay reconnection status
-- Updated dependencies [0af033f]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.8.2
-
-## 2.4.1
-
-### Patch Changes
-
-- e40312b: get all profiles that match a filter function from a cahce
-- Updated dependencies [e40312b]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.8.1
-
-## 2.4.0
-
-### Minor Changes
-
-- 949d26a: Add LRU cache for zappers specs
-- ba2a206: improve LRU caches -- refactor to make adding new caches easier
-- bump
-
-### Patch Changes
-
-- a602d0c: performance improvements on cache
-- fcd41ba: fix bug where we are REQing events even if they were cached and the filter has completed
-- Updated dependencies [91d873c]
-- Updated dependencies [6fd9ddc]
-- Updated dependencies [0b8f331]
-- Updated dependencies
-- Updated dependencies [f2898ad]
-- Updated dependencies [9b92cd9]
-- Updated dependencies
-- Updated dependencies [6814f0c]
-- Updated dependencies [89b5b3f]
-- Updated dependencies [9b92cd9]
-- Updated dependencies [27b10cc]
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies [ed7cdc4]
- - @nostr-dev-kit/ndk@2.8.0
-
-## 2.3.1
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.7.1
-
-## 2.3.0
-
-### Minor Changes
-
-- Cache NIP-05 and zap specs
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.7.0
-
-## 2.2.10
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.6.1
-
-## 2.2.9
-
-### Patch Changes
-
-- c2db3c1: delete events from cache
-- Updated dependencies
-- Updated dependencies [c2db3c1]
-- Updated dependencies
-- Updated dependencies [c2db3c1]
-- Updated dependencies [c2db3c1]
- - @nostr-dev-kit/ndk@2.6.0
-
-## 2.2.8
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.5.1
-
-## 2.2.7
-
-### Patch Changes
-
-- Updated dependencies [e08fc74]
- - @nostr-dev-kit/ndk@2.5.0
-
-## 2.2.6
-
-### Patch Changes
-
-- 15bcc10: fix profile LRU Cache
-- Updated dependencies [111c1ea]
-- Updated dependencies [5c0ae51]
-- Updated dependencies [6f5ea49]
-- Updated dependencies [3738d39]
-- Updated dependencies [d22239a]
- - @nostr-dev-kit/ndk@2.4.1
-
-## 2.2.5
-
-### Patch Changes
-
-- Updated dependencies [b9bbf1d]
- - @nostr-dev-kit/ndk@2.4.0
-
-## 2.2.4
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [885b6c2]
-- Updated dependencies [5666d56]
- - @nostr-dev-kit/ndk@2.3.3
-
-## 2.2.3
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [4628481]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.3.2
-
-## 2.2.2
-
-### Patch Changes
-
-- Updated dependencies [ece965f]
- - @nostr-dev-kit/ndk@2.3.1
-
-## 2.2.1
-
-### Patch Changes
-
-- Updated dependencies [54cec78]
-- Updated dependencies [ef61d83]
-- Updated dependencies [98b77dd]
-- Updated dependencies [46b0c77]
-- Updated dependencies [082e243]
- - @nostr-dev-kit/ndk@2.3.0
-
-## 2.1.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.2.0
-
-## 2.0.10
-
-### Patch Changes
-
-- Updated dependencies [180d774]
-- Updated dependencies [7f00c40]
- - @nostr-dev-kit/ndk@2.1.3
-
-## 2.0.9
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.2
-
-## 2.0.8
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.1
-
-## 2.0.7
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.0
-
-## 2.0.6
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.6
-
-## 2.0.5
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [d45d962]
- - @nostr-dev-kit/ndk@2.0.5
-
-## 2.0.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.4
-
-## 2.0.3
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.3
-
-## 2.0.2
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.2
-
-## 1.3.6
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.0
-
-## 1.3.5
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.2
-
-## 1.3.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.1
-
-## 1.3.3
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.0
-
-## 1.3.3
-
-### Patch Changes
-
-- Updated dependencies [b3561af]
- - @nostr-dev-kit/ndk@1.3.2
-
-## 1.3.2
-
-### Patch Changes
-
-- Add kind:0 to LRU cache regardless of how they are fetched
-
-## 1.3.1
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.3.1
-
-## 1.3.0
-
-### Minor Changes
-
-- 3440768: User profile dedicated cache
-
-### Patch Changes
-
-- Updated dependencies [88df10a]
-- Updated dependencies [c225094]
-- Updated dependencies [cf4a648]
-- Updated dependencies [3946078]
-- Updated dependencies [3440768]
- - @nostr-dev-kit/ndk@1.3.0
diff --git a/ndk-cache-dexie/README.md b/ndk-cache-dexie/README.md
deleted file mode 100644
index e79c24a6..00000000
--- a/ndk-cache-dexie/README.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# ndk-cache-dexie
-
-NDK cache adapter for [Dexie](https://dexie.org/). Dexie is a wrapper around IndexedDB, an in-browser database.
-
-## Usage
-
-NDK will attempt to use the Dexie adapter to store users, events, and tags. The default behaviour is to always check the cache first and then hit relays, replacing older cached events as needed.
-
-### Install
-
-```
-pnpm add @nostr-dev-kit/ndk-cache-dexie
-```
-
-### Add as a cache adapter
-
-```ts
-import NDKCacheAdapterDexie from "@nostr-dev-kit/ndk-cache-dexie";
-
-const dexieAdapter = new NDKCacheAdapterDexie({ dbName: 'your-db-name' });
-const ndk = new NDK({cacheAdapter: dexieAdapter, ...other config options});
-```
-
-🚨 Because Dexie only exists client-side, this cache adapter will not work in pure node.js environments. You'll need to make sure that you're using the right cache adapter in the right place (e.g. Redis on the backend, Dexie on the frontend).
-
-# License
-
-MIT
diff --git a/ndk-cache-dexie/jest.config.ts b/ndk-cache-dexie/jest.config.ts
deleted file mode 100644
index 8cac051d..00000000
--- a/ndk-cache-dexie/jest.config.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import type { Config } from "jest";
-
-const config: Config = {
- preset: "ts-jest",
- verbose: true,
- expand: true,
- testEnvironment: "node",
- testTimeout: 10000,
- setupFiles: ["fake-indexeddb/auto"],
- openHandlesTimeout: 4000,
- moduleNameMapper: {
- "^(\\.{1,2}/.*)\\.js$": "$1",
- },
-};
-
-export default config;
diff --git a/ndk-cache-dexie/package.json b/ndk-cache-dexie/package.json
deleted file mode 100644
index 3146bd46..00000000
--- a/ndk-cache-dexie/package.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{
- "name": "@nostr-dev-kit/ndk-cache-dexie",
- "version": "2.5.8",
- "description": "NDK Dexie Cache Adapter",
- "license": "MIT",
- "docs": "typedoc",
- "bugs": {
- "url": "https://github.com/nostr-dev-kit/ndk-cache-dexie/issues"
- },
- "homepage": "https://github.com/nostr-dev-kit/ndk-cache-dexie#readme",
- "main": "./dist/index.js",
- "module": "./dist/index.mjs",
- "exports": {
- "import": {
- "types": "./dist/index.d.mts",
- "default": "./dist/index.mjs"
- },
- "require": {
- "types": "./dist/index.d.ts",
- "default": "./dist/index.js"
- }
- },
- "files": [
- "dist",
- "README.md"
- ],
- "scripts": {
- "dev": "pnpm build --watch",
- "build": "tsup src/index.ts --format cjs,esm --dts",
- "clean": "rm -rf dist",
- "lint": "prettier --check . && eslint .",
- "format": "prettier --write ."
- },
- "keywords": [
- "nostr",
- "dexie",
- "cache"
- ],
- "authors": [
- "pablof7z",
- "erskingardner"
- ],
- "devDependencies": {
- "@nostr-dev-kit/eslint-config-custom": "workspace:*",
- "@nostr-dev-kit/tsconfig": "workspace:*",
- "@types/debug": "^4.1.12",
- "@types/jest": "^29.5.13",
- "@types/node": "^22.6.1",
- "fake-indexeddb": "^6.0.0",
- "jest": "^29.7.0",
- "prettier": "^3.3.3",
- "ts-jest": "^29.2.5",
- "tsup": "^8.3.0",
- "typedoc": "^0.26.7",
- "typedoc-plugin-markdown": "^4.3.0"
- },
- "dependencies": {
- "@nostr-dev-kit/ndk": "workspace:*",
- "debug": "^4.3.7",
- "dexie": "^4.0.8",
- "nostr-tools": "^2.4.0",
- "typescript-lru-cache": "^2.0.0"
- }
-}
diff --git a/ndk-cache-dexie/src/caches/event-tags.ts b/ndk-cache-dexie/src/caches/event-tags.ts
deleted file mode 100644
index 37495f81..00000000
--- a/ndk-cache-dexie/src/caches/event-tags.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import type { Table } from "dexie";
-import type { CacheHandler } from "../lru-cache";
-import type debug from "debug";
-import type { EventTag } from "../db";
-import type { LRUCache } from "typescript-lru-cache";
-
-export type EventTagCacheEntry = string;
-
-export async function eventTagsWarmUp(
- cacheHandler: CacheHandler,
- eventTags: Table
-) {
- const array = await eventTags.limit(cacheHandler.maxSize).toArray();
- for (const event of array) {
- cacheHandler.add(event.tagValue, event.eventId, false);
- }
-}
-
-export const eventTagsDump = (eventTags: Table, debug: debug.IDebugger) => {
- return async (dirtyKeys: Set, cache: LRUCache) => {
- const entries = [];
-
- for (const tagValue of dirtyKeys) {
- const eventIds = cache.get(tagValue);
- if (eventIds) {
- for (const eventId of eventIds) entries.push({ tagValue, eventId });
- }
- }
-
- if (entries.length > 0) {
- debug(`Saving ${entries.length} events cache entries to database`);
- await eventTags.bulkPut(entries);
- }
-
- dirtyKeys.clear();
- };
-};
diff --git a/ndk-cache-dexie/src/caches/events.ts b/ndk-cache-dexie/src/caches/events.ts
deleted file mode 100644
index ebed2635..00000000
--- a/ndk-cache-dexie/src/caches/events.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import type { Table } from "dexie";
-import type { CacheHandler } from "../lru-cache";
-import type debug from "debug";
-import type { Event } from "../db";
-import type { LRUCache } from "typescript-lru-cache";
-
-export type EventCacheEntry = Event;
-
-export async function eventsWarmUp(
- cacheHandler: CacheHandler,
- events: Table
-) {
- const array = await events.limit(cacheHandler.maxSize).toArray();
- for (const event of array) {
- cacheHandler.set(event.id, event, false);
- }
-}
-
-export const eventsDump = (events: Table, debug: debug.IDebugger) => {
- return async (dirtyKeys: Set, cache: LRUCache) => {
- const entries: EventCacheEntry[] = [];
-
- for (const event of dirtyKeys) {
- const entry = cache.get(event);
- if (entry) entries.push(entry);
- }
-
- if (entries.length > 0) {
- debug(`Saving ${entries.length} events cache entries to database`);
- await events.bulkPut(entries);
- }
-
- dirtyKeys.clear();
- };
-};
diff --git a/ndk-cache-dexie/src/caches/nip05.ts b/ndk-cache-dexie/src/caches/nip05.ts
deleted file mode 100644
index 1334fc7b..00000000
--- a/ndk-cache-dexie/src/caches/nip05.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import type { Table } from "dexie";
-import type { CacheHandler } from "../lru-cache";
-import type debug from "debug";
-import type { Nip05 } from "../db";
-import type { LRUCache } from "typescript-lru-cache";
-
-export type Nip05CacheEntry = {
- profile: string | null;
- fetchedAt: number;
-};
-
-export async function nip05WarmUp(
- cacheHandler: CacheHandler,
- nip05s: Table
-) {
- const array = await nip05s.limit(cacheHandler.maxSize).toArray();
- for (const nip05 of array) {
- cacheHandler.set(nip05.nip05, nip05, false);
- }
-}
-
-export const nip05Dump = (nip05s: Table, debug: debug.IDebugger) => {
- return async (dirtyKeys: Set, cache: LRUCache) => {
- const entries = [];
-
- for (const nip05 of dirtyKeys) {
- const entry = cache.get(nip05);
- if (entry) {
- entries.push({
- nip05,
- ...entry,
- });
- }
- }
-
- if (entries.length) {
- debug(`Saving ${entries.length} NIP-05 cache entries to database`);
- await nip05s.bulkPut(entries);
- }
-
- dirtyKeys.clear();
- };
-};
diff --git a/ndk-cache-dexie/src/caches/profiles.ts b/ndk-cache-dexie/src/caches/profiles.ts
deleted file mode 100644
index 96fefcc7..00000000
--- a/ndk-cache-dexie/src/caches/profiles.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import type { Table } from "dexie";
-import type { Profile } from "../db";
-import type { CacheHandler } from "../lru-cache";
-import type { LRUCache } from "typescript-lru-cache";
-export { db } from "../db.js";
-import createDebug from "debug";
-
-const d = createDebug("ndk:dexie-adapter:profiles");
-
-export async function profilesWarmUp(
- cacheHandler: CacheHandler,
- profiles: Table
-): Promise {
- const array = await profiles.limit(cacheHandler.maxSize).toArray();
- for (const user of array) {
- const obj = user;
- cacheHandler.set(user.pubkey, obj, false);
- }
-
- d("Loaded %d profiles from database", cacheHandler.size());
-}
-
-export const profilesDump = (profiles: Table, debug: debug.IDebugger) => {
- return async (dirtyKeys: Set, cache: LRUCache) => {
- const entries = [];
-
- for (const pubkey of dirtyKeys) {
- const entry = cache.get(pubkey);
- if (entry) {
- entries.push(entry);
- }
- }
-
- if (entries.length) {
- debug(`Saving ${entries.length} users to database`);
-
- await profiles.bulkPut(entries);
- }
-
- dirtyKeys.clear();
- };
-};
diff --git a/ndk-cache-dexie/src/caches/relay-info.ts b/ndk-cache-dexie/src/caches/relay-info.ts
deleted file mode 100644
index 13f72d2b..00000000
--- a/ndk-cache-dexie/src/caches/relay-info.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import type { Table } from "dexie";
-import type { CacheHandler } from "../lru-cache";
-import type debug from "debug";
-import type { LRUCache } from "typescript-lru-cache";
-import { RelayStatus } from "../db";
-
-export async function relayInfoWarmUp(
- cacheHandler: CacheHandler,
- relayStatus: Table
-) {
- const array = await relayStatus.limit(cacheHandler.maxSize).toArray();
- for (const entry of array) {
- cacheHandler.set(
- entry.url,
- {
- url: entry.url,
- updatedAt: entry.updatedAt,
- lastConnectedAt: entry.lastConnectedAt,
- dontConnectBefore: entry.dontConnectBefore,
- },
- false
- );
- }
-}
-
-export const relayInfoDump = (relayStatus: Table, debug: debug.IDebugger) => {
- return async (dirtyKeys: Set, cache: LRUCache) => {
- const entries = [];
-
- for (const url of dirtyKeys) {
- const info = cache.get(url);
- if (info) {
- entries.push({
- url,
- updatedAt: info.updatedAt,
- lastConnectedAt: info.lastConnectedAt,
- dontConnectBefore: info.dontConnectBefore,
- });
- }
- }
-
- if (entries.length > 0) {
- debug(`Saving ${entries.length} relay status cache entries to database`);
- await relayStatus.bulkPut(entries);
- }
-
- dirtyKeys.clear();
- };
-};
diff --git a/ndk-cache-dexie/src/caches/unpublished-events.ts b/ndk-cache-dexie/src/caches/unpublished-events.ts
deleted file mode 100644
index 0beaa6ef..00000000
--- a/ndk-cache-dexie/src/caches/unpublished-events.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-import { NDKEvent, NDKEventId, NDKRelay } from "@nostr-dev-kit/ndk";
-import { UnpublishedEvent } from "../db";
-import type debug from "debug";
-import type { Table } from "dexie";
-import { LRUCache } from "typescript-lru-cache";
-import { CacheHandler } from "../lru-cache";
-import NDKCacheAdapterDexie from "..";
-
-/**
- * The threshold
- */
-const WRITE_STATUS_THRESHOLD = 3;
-
-export async function unpublishedEventsWarmUp(
- cacheHandler: CacheHandler,
- unpublishedEvents: Table
-) {
- await unpublishedEvents.each((unpublishedEvent) => {
- cacheHandler.set(unpublishedEvent.event.id!, unpublishedEvent, false);
- });
-}
-
-export function unpublishedEventsDump(
- unpublishedEvents: Table,
- debug: debug.IDebugger
-) {
- return async (dirtyKeys: Set, cache: LRUCache) => {
- const entries: UnpublishedEvent[] = [];
-
- for (const eventId of dirtyKeys) {
- const entry = cache.get(eventId);
- if (entry) {
- entries.push(entry);
- }
- }
-
- if (entries.length > 0) {
- debug(`Saving ${entries.length} unpublished events cache entries to database`);
- await unpublishedEvents.bulkPut(entries);
- }
-
- dirtyKeys.clear();
- };
-}
-
-export async function discardUnpublishedEvent(
- unpublishedEvents: Table,
- eventId: NDKEventId
-): Promise {
- await unpublishedEvents.delete(eventId);
-}
-
-export async function getUnpublishedEvents(
- unpublishedEvents: Table
-): Promise<{ event: NDKEvent; relays: WebSocket["url"][]; lastTryAt?: number }[]> {
- const events: { event: NDKEvent; relays: WebSocket["url"][]; lastTryAt?: number }[] = [];
-
- await unpublishedEvents.each((unpublishedEvent) => {
- events.push({
- event: new NDKEvent(undefined, unpublishedEvent.event),
- relays: Object.keys(unpublishedEvent.relays),
- lastTryAt: unpublishedEvent.lastTryAt,
- });
- });
-
- return events;
-}
-
-export function addUnpublishedEvent(
- this: NDKCacheAdapterDexie,
- event: NDKEvent,
- relays: WebSocket["url"][]
-): void {
- const r: UnpublishedEvent["relays"] = {};
- relays.forEach((url) => (r[url] = false));
- this.unpublishedEvents.set(event.id!, { id: event.id, event: event.rawEvent(), relays: r });
-
- const onPublished = (relay: NDKRelay) => {
- const url = relay.url;
-
- const existingEntry = this.unpublishedEvents.get(event.id);
-
- if (!existingEntry) {
- event.off("publushed", onPublished);
- return;
- }
-
- existingEntry.relays[url] = true;
- this.unpublishedEvents.set(event.id, existingEntry);
-
- let successWrites = Object.values(existingEntry.relays).filter((v) => v).length;
- let unsuccessWrites = Object.values(existingEntry.relays).length - successWrites;
-
- if (successWrites >= WRITE_STATUS_THRESHOLD || unsuccessWrites === 0) {
- // this.debug(`Removing ${event.id} from cache`, { successWrites, unsuccessWrites });
- this.unpublishedEvents.delete(event.id);
- event.off("published", onPublished);
- // } else {
- // this.debug(`Keeping ${event.id} in cache`, { successWrites, unsuccessWrites });
- }
- };
-
- event.on("published", onPublished);
-}
diff --git a/ndk-cache-dexie/src/caches/zapper.ts b/ndk-cache-dexie/src/caches/zapper.ts
deleted file mode 100644
index 679e30a4..00000000
--- a/ndk-cache-dexie/src/caches/zapper.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import type { Table } from "dexie";
-import type { CacheHandler } from "../lru-cache";
-import type debug from "debug";
-import type { Lnurl } from "../db";
-import type { LRUCache } from "typescript-lru-cache";
-
-export type ZapperCacheEntry = {
- document: string | null;
- fetchedAt: number;
-};
-
-export async function zapperWarmUp(
- cacheHandler: CacheHandler,
- lnurls: Table
-) {
- const array = await lnurls.limit(cacheHandler.maxSize).toArray();
- for (const lnurl of array) {
- cacheHandler.set(
- lnurl.pubkey,
- { document: lnurl.document, fetchedAt: lnurl.fetchedAt },
- false
- );
- }
-}
-
-export const zapperDump = (lnurls: Table, debug: debug.IDebugger) => {
- return async (dirtyKeys: Set, cache: LRUCache) => {
- const entries = [];
-
- for (const pubkey of dirtyKeys) {
- const entry = cache.get(pubkey);
- if (entry) {
- entries.push({
- pubkey,
- ...entry,
- });
- }
- }
-
- if (entries.length) {
- debug(`Saving ${entries.length} zapper cache entries to database`);
- await lnurls.bulkPut(entries);
- }
-
- dirtyKeys.clear();
- };
-};
diff --git a/ndk-cache-dexie/src/db.ts b/ndk-cache-dexie/src/db.ts
deleted file mode 100644
index 9267431e..00000000
--- a/ndk-cache-dexie/src/db.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import type { NDKEvent, NDKEventId, NDKUser, NDKUserProfile, NostrEvent } from "@nostr-dev-kit/ndk";
-import Dexie, { type Table } from "dexie";
-
-export interface Profile extends NDKUserProfile {
- pubkey: string;
- cachedAt: number;
-}
-
-export interface Event {
- id: string;
- pubkey: string;
- kind: number;
- createdAt: number;
- relay?: string;
- event: string;
-}
-
-export interface EventTag {
- eventId: string;
- tagValue: string;
-}
-
-export interface Nip05 {
- nip05: string;
- profile: string | null;
- fetchedAt: number;
-}
-
-export interface Lnurl {
- pubkey: string;
- document: string | null;
- fetchedAt: number;
-}
-
-export interface RelayStatus {
- url: string;
- updatedAt: number;
- lastConnectedAt?: number;
- dontConnectBefore?: number;
-}
-
-export interface UnpublishedEvent {
- id: NDKEventId;
- event: NostrEvent;
- relays: Record;
- lastTryAt?: number;
-}
-
-export class Database extends Dexie {
- profiles!: Table;
- events!: Table;
- eventTags!: Table;
- nip05!: Table;
- lnurl!: Table;
- relayStatus!: Table;
- unpublishedEvents!: Table;
-
- constructor(name: string) {
- super(name);
- this.version(15).stores({
- profiles: "&pubkey",
- events: "&id, kind",
- eventTags: "&tagValue",
- nip05: "&nip05",
- lnurl: "&pubkey",
- relayStatus: "&url",
- unpublishedEvents: "&id",
- });
- }
-}
-
-export let db: Database;
-
-/**
- * Create database
- *
- * @param name - Database name
- */
-export function createDatabase(name: string): void {
- db = new Database(name);
-}
diff --git a/ndk-cache-dexie/src/index.test.ts b/ndk-cache-dexie/src/index.test.ts
deleted file mode 100644
index 8ec4b9bf..00000000
--- a/ndk-cache-dexie/src/index.test.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import NDK, { NDKEvent, NDKPrivateKeySigner, NDKSubscription } from "@nostr-dev-kit/ndk";
-import NDKCacheAdapterDexie from "./index.js";
-
-const ndk = new NDK();
-ndk.signer = NDKPrivateKeySigner.generate();
-ndk.cacheAdapter = new NDKCacheAdapterDexie();
-
-describe("foundEvents", () => {
- it("applies limit filter", async () => {
- const startTime = Math.floor(Date.now() / 1000);
- const times = [];
- for (let i = 0; i < 10; i++) {
- const event = new NDKEvent(ndk);
- event.kind = 2;
- event.created_at = startTime - i * 60;
- times.push(event.created_at);
- await event.sign();
- ndk.cacheAdapter!.setEvent(event, []);
- }
-
- const subscription = new NDKSubscription(ndk, [{ kinds: [2], limit: 2 }]);
- const spy = jest.spyOn(subscription, "eventReceived");
- await ndk.cacheAdapter!.query(subscription);
- expect(subscription.eventReceived).toBeCalledTimes(2);
-
- // the time of the events that were received must be the first two in the list
- expect(spy.mock.calls[0][0].created_at).toBe(times[0]);
- expect(spy.mock.calls[1][0].created_at).toBe(times[1]);
- });
-});
-
-describe("foundEvent", () => {
- beforeAll(async () => {
- // save event
- const event = new NDKEvent(ndk);
- event.kind = 1;
- event.tags.push(["a", "123"]);
- await event.sign();
- ndk.cacheAdapter!.setEvent(event, []);
- });
-
- it("correctly avoids reporting events that don't fully match NIP-01 filter", async () => {
- const subscription = new NDKSubscription(ndk, [{ "#a": ["123"], "#t": ["hello"] }]);
- jest.spyOn(subscription, "eventReceived");
- await ndk.cacheAdapter!.query(subscription);
- expect(subscription.eventReceived).toBeCalledTimes(0);
- });
-
- it("correctly reports events that fully match NIP-01 filter", async () => {
- const subscription = new NDKSubscription(ndk, [{ "#a": ["123"] }]);
- jest.spyOn(subscription, "eventReceived");
- await ndk.cacheAdapter!.query(subscription);
- expect(subscription.eventReceived).toBeCalledTimes(1);
- });
-});
-
-describe("by kind filter", () => {
- beforeAll(async () => {
- // save event
- const event = new NDKEvent(ndk);
- event.kind = 10002;
- await event.sign();
- ndk.cacheAdapter!.setEvent(event, []);
- });
-
- it("returns an event when fetching by kind", async () => {
- const subscription = new NDKSubscription(ndk, [{ kinds: [10002] }]);
- jest.spyOn(subscription, "eventReceived");
- await ndk.cacheAdapter!.query(subscription);
- expect(subscription.eventReceived).toBeCalledTimes(1);
- });
-
- it("matches by kind even when there is a since filter", async () => {
- const subscription = new NDKSubscription(ndk, [{ kinds: [10002], since: 1000 }]);
- jest.spyOn(subscription, "eventReceived");
- await ndk.cacheAdapter!.query(subscription);
- expect(subscription.eventReceived).toBeCalledTimes(1);
- });
-});
diff --git a/ndk-cache-dexie/src/index.ts b/ndk-cache-dexie/src/index.ts
deleted file mode 100644
index 8a8c0a7b..00000000
--- a/ndk-cache-dexie/src/index.ts
+++ /dev/null
@@ -1,607 +0,0 @@
-import { NDKEvent, NDKRelay, deserialize, profileFromEvent } from "@nostr-dev-kit/ndk";
-import type {
- Hexpubkey,
- NDKEventId,
- NDKCacheAdapter,
- NDKFilter,
- NDKSubscription,
- NDKUserProfile,
- NDKLnUrlData,
- ProfilePointer,
- NostrEvent,
- NDKCacheRelayInfo,
- NDKTag,
-} from "@nostr-dev-kit/ndk";
-import createDebug from "debug";
-import { matchFilter } from "nostr-tools";
-import { RelayStatus, UnpublishedEvent, Profile, createDatabase, db, type Event } from "./db.js";
-import { CacheHandler } from "./lru-cache.js";
-import { profilesDump, profilesWarmUp } from "./caches/profiles.js";
-import { ZapperCacheEntry, zapperDump, zapperWarmUp } from "./caches/zapper.js";
-import { Nip05CacheEntry, nip05Dump, nip05WarmUp } from "./caches/nip05.js";
-import { EventCacheEntry, eventsDump, eventsWarmUp } from "./caches/events.js";
-import { EventTagCacheEntry, eventTagsDump, eventTagsWarmUp } from "./caches/event-tags.js";
-import { relayInfoDump, relayInfoWarmUp } from "./caches/relay-info.js";
-import {
- addUnpublishedEvent,
- discardUnpublishedEvent,
- getUnpublishedEvents,
- unpublishedEventsDump,
- unpublishedEventsWarmUp,
-} from "./caches/unpublished-events.js";
-
-export { db } from "./db";
-
-const INDEXABLE_TAGS_LIMIT = 10;
-
-export interface NDKCacheAdapterDexieOptions {
- /**
- * The name of the database to use
- */
- dbName?: string;
-
- /**
- * Debug instance to use for logging
- */
- debug?: debug.IDebugger;
-
- /**
- * Number of profiles to keep in an LRU cache
- */
- profileCacheSize?: number;
- zapperCacheSize?: number;
- nip05CacheSize?: number;
- eventCacheSize?: number;
- eventTagsCacheSize?: number;
-}
-
-export default class NDKCacheAdapterDexie implements NDKCacheAdapter {
- public debug: debug.Debugger;
- public locking = false;
- public ready = false;
- public profiles: CacheHandler;
- public zappers: CacheHandler;
- public nip05s: CacheHandler;
- public events: CacheHandler;
- public eventTags: CacheHandler;
- public relayInfo: CacheHandler;
- public unpublishedEvents: CacheHandler;
- private warmedUp: boolean = false;
- private warmUpPromise: Promise;
- public devMode = false;
- public _onReady?: () => void;
-
- constructor(opts: NDKCacheAdapterDexieOptions = {}) {
- createDatabase(opts.dbName || "ndk");
- this.debug = opts.debug || createDebug("ndk:dexie-adapter");
-
- this.profiles = new CacheHandler({
- maxSize: opts.profileCacheSize || 100000,
- dump: profilesDump(db.profiles, this.debug),
- debug: this.debug,
- });
-
- this.zappers = new CacheHandler({
- maxSize: opts.zapperCacheSize || 200,
- dump: zapperDump(db.lnurl, this.debug),
- debug: this.debug,
- });
-
- this.nip05s = new CacheHandler({
- maxSize: opts.nip05CacheSize || 1000,
- dump: nip05Dump(db.nip05, this.debug),
- debug: this.debug,
- });
-
- this.events = new CacheHandler({
- maxSize: opts.eventCacheSize || 50000,
- dump: eventsDump(db.events, this.debug),
- debug: this.debug,
- });
- this.events.addIndex("pubkey");
-
- this.events.addIndex("kind");
-
- this.eventTags = new CacheHandler({
- maxSize: opts.eventTagsCacheSize || 100000,
- dump: eventTagsDump(db.eventTags, this.debug),
- debug: this.debug,
- });
-
- this.relayInfo = new CacheHandler({
- maxSize: 500,
- debug: this.debug,
- dump: relayInfoDump(db.relayStatus, this.debug),
- });
-
- this.unpublishedEvents = new CacheHandler({
- maxSize: 5000,
- debug: this.debug,
- dump: unpublishedEventsDump(db.unpublishedEvents, this.debug),
- });
-
- const profile = (label: string, fn: () => Promise) => {
- const start = Date.now();
- return fn().then(() => {
- const end = Date.now();
- this.debug(label, "took", end - start, "ms");
- });
- };
-
- const startTime = Date.now();
- this.warmUpPromise = Promise.allSettled([
- profile("profilesWarmUp", () => profilesWarmUp(this.profiles, db.profiles)),
- profile("zapperWarmUp", () => zapperWarmUp(this.zappers, db.lnurl)),
- profile("nip05WarmUp", () => nip05WarmUp(this.nip05s, db.nip05)),
- profile("relayInfoWarmUp", () => relayInfoWarmUp(this.relayInfo, db.relayStatus)),
- profile("unpublishedEventsWarmUp", () =>
- unpublishedEventsWarmUp(this.unpublishedEvents, db.unpublishedEvents)
- ),
- profile("eventsWarmUp", () => eventsWarmUp(this.events, db.events)),
- profile("eventTagsWarmUp", () => eventTagsWarmUp(this.eventTags, db.eventTags)),
- ]);
- this.warmUpPromise.then(() => {
- const endTime = Date.now();
- this.warmedUp = true;
- this.ready = true;
- this.locking = true;
- this.debug("Warm up completed, time", endTime - startTime, "ms");
-
- // call the onReady callback if it's set
- if (this._onReady) this._onReady();
- });
- }
-
- public onReady(callback: () => void) {
- this._onReady = callback;
- }
-
- public async query(subscription: NDKSubscription): Promise {
- // ensure we have warmed up before processing the filter
- if (!this.warmedUp) {
- const startTime = Date.now();
- await this.warmUpPromise;
- this.debug("froze query for", Date.now() - startTime, "ms", subscription.filters);
- }
-
- const startTime = Date.now();
- subscription.filters.map((filter) => this.processFilter(filter, subscription));
- const dur = Date.now() - startTime;
- if (dur > 100) this.debug("query took", dur, "ms", subscription.filter);
- }
-
- public async fetchProfile(pubkey: Hexpubkey) {
- if (!this.profiles) return null;
-
- let user = await this.profiles.getWithFallback(pubkey, db.profiles);
-
- return user as NDKUserProfile | null;
- }
-
- public fetchProfileSync(pubkey: Hexpubkey) {
- if (!this.profiles) return null;
-
- let user = this.profiles.get(pubkey);
-
- return user as NDKUserProfile | null;
- }
-
- public async getProfiles(
- fn: (pubkey: Hexpubkey, profile: NDKUserProfile) => boolean
- ): Promise | undefined> {
- if (!this.profiles) return;
- return this.profiles.getAllWithFilter(fn);
- }
-
- public saveProfile(pubkey: Hexpubkey, profile: NDKUserProfile) {
- const existingValue = this.profiles.get(pubkey);
- if (
- existingValue?.created_at &&
- profile.created_at &&
- existingValue.created_at >= profile.created_at
- ) {
- return;
- }
- const cachedAt = Math.floor(Date.now() / 1000);
- this.profiles.set(pubkey, { pubkey, ...profile, cachedAt });
- this.debug("Saved profile for pubkey", pubkey, profile);
- }
-
- public async loadNip05(
- nip05: string,
- maxAgeForMissing: number = 3600
- ): Promise {
- const cache = this.nip05s?.get(nip05);
-
- if (cache) {
- if (cache.profile === null) {
- // If the profile has been marked as missing and is older than the max age for missing, return missing
- if (cache.fetchedAt + maxAgeForMissing * 1000 < Date.now()) return "missing";
-
- // Otherwise, return null
- return null;
- }
-
- try {
- return JSON.parse(cache.profile);
- } catch (e) {
- return "missing";
- }
- }
-
- const nip = await db.nip05.get({ nip05 });
-
- if (!nip) return "missing";
-
- const now = Date.now();
-
- // If the document is older than the max age, return missing
- if (nip.profile === null) {
- // If the document has been marked as missing and is older than the max age for missing, return missing
- if (nip.fetchedAt + maxAgeForMissing * 1000 < now) return "missing";
-
- // Otherwise, return null
- return null;
- }
-
- try {
- return JSON.parse(nip.profile);
- } catch (e) {
- return "missing";
- }
- }
-
- public async saveNip05(nip05: string, profile: ProfilePointer | null): Promise {
- try {
- const document = profile ? JSON.stringify(profile) : null;
-
- this.nip05s.set(nip05, { profile: document, fetchedAt: Date.now() });
- } catch (error) {
- console.error("Failed to save NIP-05 profile for nip05:", nip05, error);
- }
- }
-
- public async loadUsersLNURLDoc?(
- pubkey: Hexpubkey,
- maxAgeInSecs: number = 86400,
- maxAgeForMissing: number = 3600
- ): Promise {
- const cache = this.zappers?.get(pubkey);
- if (cache) {
- if (cache.document === null) {
- // If the document has been marked as missing and is older than the max age for missing, return missing
- if (cache.fetchedAt + maxAgeForMissing * 1000 < Date.now()) return "missing";
-
- // Otherwise, return null
- return null;
- }
-
- try {
- return JSON.parse(cache.document);
- } catch (e) {
- return "missing";
- }
- }
-
- const lnurl = await db.lnurl.get({ pubkey });
-
- if (!lnurl) return "missing";
-
- const now = Date.now();
-
- // If the document is older than the max age, return missing
- if (lnurl.fetchedAt + maxAgeInSecs * 1000 < now) return "missing";
- if (lnurl.document === null) {
- // If the document has been marked as missing and is older than the max age for missing, return missing
- if (lnurl.fetchedAt + maxAgeForMissing * 1000 < now) return "missing";
-
- // Otherwise, return null
- return null;
- }
-
- try {
- return JSON.parse(lnurl.document);
- } catch (e) {
- return "missing";
- }
- }
-
- public async saveUsersLNURLDoc(pubkey: Hexpubkey, doc: NDKLnUrlData | null): Promise {
- try {
- const document = doc ? JSON.stringify(doc) : null;
- this.zappers?.set(pubkey, { document, fetchedAt: Date.now() });
- } catch (error) {
- console.error("Failed to save LNURL document for pubkey:", pubkey, error);
- }
- }
-
- private processFilter(filter: NDKFilter, subscription: NDKSubscription): void {
- const _filter = { ...filter };
- delete _filter.limit;
- const filterKeys = new Set(Object.keys(_filter || {}));
-
- // strip always-allowed filter-keys
- filterKeys.delete("since");
- filterKeys.delete("limit");
- filterKeys.delete("until");
-
- try {
- // start with NIP-33 query
- if (this.byNip33Query(filterKeys, filter, subscription)) return; // exit = true;
-
- // Continue with author
- if (this.byAuthors(filter, subscription)) return; // exit = true;
-
- // Continue with ids
- if (this.byIdsQuery(filter, subscription)) return; // exit = true;
-
- // By tags
- if (this.byTags(filter, subscription)) return; // exit = true;
-
- if (this.byKinds(filterKeys, filter, subscription)) return; // exit = true;
- } catch (error) {
- console.error(error);
- }
- }
-
- public async deleteEventIds(eventIds: NDKEventId[]): Promise {
- eventIds.forEach((id) => this.events.delete(id));
- await db.events.where({ id: eventIds }).delete();
- }
-
- public addUnpublishedEvent = addUnpublishedEvent.bind(this);
- public getUnpublishedEvents = () => getUnpublishedEvents(db.unpublishedEvents);
- public discardUnpublishedEvent = (id: string) =>
- discardUnpublishedEvent(db.unpublishedEvents, id);
-
- public async setEvent(event: NDKEvent, filters: NDKFilter[], relay?: NDKRelay): Promise {
- if (event.kind === 0) {
- if (!this.profiles) return;
-
- try {
- const profile: NDKUserProfile = profileFromEvent(event);
- this.saveProfile(event.pubkey, profile);
- } catch {
- this.debug(`Failed to save profile for pubkey: ${event.pubkey}`);
- }
- }
- let addEvent = true;
-
- if (event.isParamReplaceable()) {
- const existingEvent = this.events.get(event.tagId());
- if (existingEvent && event.created_at && existingEvent.createdAt > event.created_at) {
- addEvent = false;
- }
- }
-
- if (addEvent) {
- this.events.set(event.tagId(), {
- id: event.tagId(),
- pubkey: event.pubkey,
- kind: event.kind!,
- createdAt: event.created_at!,
- relay: relay?.url,
- event: event.serialize(true, true),
- });
-
- // Don't cache contact lists as tags since it's expensive
- // and there is no use case for it
- const indexableTags = getIndexableTags(event);
- for (const tag of indexableTags) {
- this.eventTags.add(tag[0] + tag[1], event.tagId());
- }
- }
- }
-
- public updateRelayStatus(url: string, info: NDKCacheRelayInfo): void {
- const val = { url, updatedAt: Date.now(), ...info };
- this.relayInfo.set(url, val);
- }
-
- public getRelayStatus(url: string): NDKCacheRelayInfo | undefined {
- const a = this.relayInfo.get(url);
- if (a) {
- return {
- lastConnectedAt: a.lastConnectedAt,
- dontConnectBefore: a.dontConnectBefore,
- };
- }
- }
-
- /**
- * Searches by authors
- */
- private byAuthors(filter: NDKFilter, subscription: NDKSubscription): boolean {
- if (!filter.authors) return false;
-
- let total = 0;
-
- for (const pubkey of filter.authors) {
- // const eventsFromDb = await db.events.where({ pubkey }).toArray();
- let events = Array.from(this.events.getFromIndex("pubkey", pubkey));
-
- const prev = events.length;
-
- // reduce by kind if needed
- if (filter.kinds) events = events.filter((e) => filter.kinds!.includes(e.kind!));
-
- foundEvents(subscription, events, filter);
- total += events.length;
- }
-
- return true;
- }
-
- /**
- * Searches by ids
- */
- private byIdsQuery(filter: NDKFilter, subscription: NDKSubscription): boolean {
- if (filter.ids) {
- for (const id of filter.ids) {
- const event = this.events.get(id);
- if (event) foundEvent(subscription, event, event.relay, filter);
- }
-
- return true;
- }
-
- return false;
- }
-
- /**
- * Searches by NIP-33
- */
- private byNip33Query(
- filterKeys: Set,
- filter: NDKFilter,
- subscription: NDKSubscription
- ): boolean {
- const f = ["#d", "authors", "kinds"];
- const hasAllKeys = filterKeys.size === f.length && f.every((k) => filterKeys.has(k));
-
- if (hasAllKeys && filter.kinds && filter.authors) {
- for (const kind of filter.kinds) {
- const replaceableKind = kind >= 30000 && kind < 40000;
-
- if (!replaceableKind) continue;
-
- for (const author of filter.authors) {
- for (const dTag of filter["#d"]!) {
- const replaceableId = `${kind}:${author}:${dTag}`;
- const event = this.events.get(replaceableId);
- if (event) foundEvent(subscription, event, event.relay, filter);
- }
- }
- }
- return true;
- }
- return false;
- }
-
- /**
- * Searches by tags and optionally filters by tags
- */
- private byTags(filter: NDKFilter, subscription: NDKSubscription): boolean {
- const tagFilters = Object.entries(filter)
- .filter(([filter]) => filter.startsWith("#") && filter.length === 2)
- .map(([filter, values]) => [filter[1], values]);
- if (tagFilters.length === 0) return false;
-
- // Go through all the tags (#e, #p, etc)
- for (const [tag, values] of tagFilters) {
- // Go throgh each value in the filter
- for (const value of values as string[]) {
- const tagValue = tag + value;
-
- // Get all events with this tag
- const eventIds = this.eventTags.getSet(tagValue);
- if (!eventIds) continue;
-
- // Go through each event that came back
- eventIds.forEach((id) => {
- const event = this.events.get(id);
- if (!event) return;
-
- if (!filter.kinds || filter.kinds.includes(event.kind!)) {
- foundEvent(subscription, event, event.relay, filter);
- }
- });
- }
- }
-
- return true;
- }
-
- private byKinds(
- filterKeys: Set,
- filter: NDKFilter,
- subscription: NDKSubscription
- ): boolean {
- if (!filter.kinds) return false;
- const f = ["kinds"];
- const hasAllKeys = filterKeys.size === f.length && f.every((k) => filterKeys.has(k));
-
- let events: Event[] = [];
-
- if (!hasAllKeys) return false;
-
- for (const kind of filter.kinds) {
- events = [...events, ...Array.from(this.events.getFromIndex("kind", kind))];
- }
-
- foundEvents(subscription, events, filter);
-
- return true;
- }
-}
-
-export function checkEventMatchesFilter(event: Event, filter: NDKFilter): NDKEvent | undefined {
- let deserializedEvent: NostrEvent;
-
- try {
- deserializedEvent = deserialize(event.event);
-
- // Make sure all passed filters match the event
- if (!matchFilter(filter, deserializedEvent as any)) return;
- } catch (e) {
- console.log("failed to parse event", e);
- return;
- }
-
- const ndkEvent = new NDKEvent(undefined, deserializedEvent);
- const relay = event.relay ? new NDKRelay(event.relay) : undefined;
- ndkEvent.relay = relay;
-
- return ndkEvent;
-}
-
-export function foundEvents(subscription: NDKSubscription, events: Event[], filter?: NDKFilter) {
- // if we have a limit, sort and slice
- if (filter?.limit && events.length > filter.limit) {
- events = events.sort((a, b) => b.createdAt - a.createdAt).slice(0, filter.limit);
- }
-
- for (const event of events) {
- foundEvent(subscription, event, event.relay, filter);
- }
-}
-
-export function foundEvent(
- subscription: NDKSubscription,
- event: Event,
- relayUrl: WebSocket["url"] | undefined,
- filter?: NDKFilter
-) {
- try {
- const deserializedEvent = deserialize(event.event);
-
- if (filter && !matchFilter(filter, deserializedEvent as any)) return;
-
- const ndkEvent = new NDKEvent(undefined, deserializedEvent);
- const relay = relayUrl ? subscription.pool.getRelay(relayUrl, false) : undefined;
- ndkEvent.relay = relay;
- subscription.eventReceived(ndkEvent, relay, true);
- } catch (e) {
- console.error("failed to deserialize event", e);
- }
-}
-
-/**
- * Returns the tags that should be indexed, if an event has
- * more indexable tags than the limit, none will be returned
- */
-function getIndexableTags(event: NDKEvent): NDKTag[] {
- let indexableTags: NDKTag[] = [];
-
- if (event.kind === 3) return [];
-
- for (const tag of event.tags) {
- if (tag[0].length !== 1) continue;
-
- indexableTags.push(tag);
-
- if (indexableTags.length >= INDEXABLE_TAGS_LIMIT) return [];
- }
-
- return indexableTags;
-}
diff --git a/ndk-cache-dexie/src/lru-cache.ts b/ndk-cache-dexie/src/lru-cache.ts
deleted file mode 100644
index 2c099591..00000000
--- a/ndk-cache-dexie/src/lru-cache.ts
+++ /dev/null
@@ -1,164 +0,0 @@
-import { Table } from "dexie";
-import { LRUCache } from "typescript-lru-cache";
-
-export type WarmUpFunction = (
- cacheHandler: CacheHandler,
- debug: debug.IDebugger
-) => Promise;
-
-export interface CacheOptions {
- maxSize: number;
- dump: (dirtyKeys: Set, cache: LRUCache) => Promise;
- debug: debug.IDebugger;
-}
-
-export class CacheHandler {
- private cache?: LRUCache;
- private dirtyKeys: Set = new Set();
- private options: CacheOptions;
- private debug: debug.IDebugger;
- public indexes: Map>>;
- public isSet = false;
- public maxSize = 0;
-
- constructor(options: CacheOptions) {
- this.debug = options.debug;
- this.options = options;
- this.maxSize = options.maxSize;
- if (options.maxSize > 0) {
- this.cache = new LRUCache({ maxSize: options.maxSize });
- setInterval(() => this.dump().catch(console.error), 1000 * 10);
- }
-
- this.indexes = new Map();
- }
-
- public getSet(key: string): Set | null {
- return this.cache?.get(key) as Set | null;
- }
-
- /**
- * Get all entries that match the filter.
- */
- public getAllWithFilter(filter: (key: string, val: T) => boolean): Map {
- const ret = new Map();
- this.cache?.forEach((val, key) => {
- if (filter(key, val)) {
- ret.set(key, val);
- }
- });
- return ret;
- }
-
- public get(key: string): T | null | undefined {
- return this.cache?.get(key);
- }
-
- public async getWithFallback(key: string, table: Table) {
- let entry = this.get(key);
- if (!entry) {
- entry = await table.get(key);
- if (entry) {
- // this.debug(`Cache miss for key ${JSON.stringify(key)}`);
- this.set(key, entry);
- }
- }
- return entry;
- }
-
- public async getManyWithFallback(keys: string[], table: Table) {
- const entries: T[] = [];
- const missingKeys: string[] = [];
- // get all entries from cache without hitting the database
- for (const key of keys) {
- const entry = this.get(key);
- if (entry) entries.push(entry);
- else missingKeys.push(key);
- }
-
- if (entries.length > 0) {
- this.debug(
- `Cache hit for keys ${entries.length} and miss for ${missingKeys.length} keys`
- );
- }
-
- // get missing entries from the database
- if (missingKeys.length > 0) {
- const startTime = Date.now();
- const missingEntries = await table.bulkGet(missingKeys);
- const endTime = Date.now();
- let foundKeys = 0;
-
- for (const entry of missingEntries) {
- if (entry) {
- this.set(entry.id, entry);
- entries.push(entry);
- foundKeys++;
- }
- }
- this.debug(
- `Time spent querying database: ${endTime - startTime}ms for ${
- missingKeys.length
- } keys, which added ${foundKeys} entries to the cache`
- );
- }
-
- return entries;
- }
-
- public add(key: string, value: K, dirty = true) {
- const existing = this.get(key) ?? new Set();
- (existing as Set).add(value);
- this.cache?.set(key, existing as T);
-
- if (dirty) this.dirtyKeys.add(key);
- }
-
- public set(key: string, value: T, dirty = true) {
- this.cache?.set(key, value);
- if (dirty) this.dirtyKeys.add(key);
-
- // update indexes
- for (const [attribute, index] of this.indexes.entries()) {
- const indexKey = (value as any)[attribute] as string;
- if (indexKey) {
- const indexValue = index.get(indexKey) || new Set();
- indexValue.add(key);
- index.set(indexKey, indexValue);
- }
- }
- }
-
- public size(): number {
- return this.cache?.size || 0;
- }
-
- public delete(key: string) {
- this.cache?.delete(key);
- this.dirtyKeys.add(key);
- }
-
- private async dump() {
- if (this.dirtyKeys.size > 0) {
- await this.options.dump(this.dirtyKeys, this.cache!);
- this.dirtyKeys.clear();
- }
- }
-
- public addIndex(attribute: string | number) {
- this.indexes.set(attribute, new LRUCache({ maxSize: this.options.maxSize }));
- }
-
- public getFromIndex(attribute: string, key: string | number) {
- const ret = new Set();
- this.indexes
- .get(attribute)
- ?.get(key)
- ?.forEach((key) => {
- const entry = this.get(key);
- if (entry) ret.add(entry as T);
- });
-
- return ret;
- }
-}
diff --git a/ndk-cache-dexie/tsconfig.json b/ndk-cache-dexie/tsconfig.json
deleted file mode 100644
index fe257ae3..00000000
--- a/ndk-cache-dexie/tsconfig.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "extends": "../packages/tsconfig/ndk-cache-dexie.json",
- "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts"],
- "exclude": ["dist", "build", "node_modules"]
-}
diff --git a/ndk-cache-dexie/typedoc.json b/ndk-cache-dexie/typedoc.json
deleted file mode 100644
index b4f1de3d..00000000
--- a/ndk-cache-dexie/typedoc.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "entryPoints": ["src/index.ts"],
- "out": "docs",
- "name": "NDK Dexie Cache Adapter",
- "theme": "default",
- "plugin": ["typedoc-plugin-markdown"],
- "excludeExternals": true,
- "excludePrivate": true,
- "excludeProtected": true,
- "categorizeByGroup": true,
- "hideParameterTypesInTitle": false,
- "navigation": {
- "includeGroups": true
- },
- "customCss": "../ndk/docs-styles.css"
-}
diff --git a/ndk-cache-nostr/.gitignore b/ndk-cache-nostr/.gitignore
deleted file mode 100644
index c92e9f04..00000000
--- a/ndk-cache-nostr/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-node_modules
-**/*.js
-dist
diff --git a/ndk-cache-nostr/.prettierignore b/ndk-cache-nostr/.prettierignore
deleted file mode 100644
index 1521c8b7..00000000
--- a/ndk-cache-nostr/.prettierignore
+++ /dev/null
@@ -1 +0,0 @@
-dist
diff --git a/ndk-cache-nostr/CHANGELOG.md b/ndk-cache-nostr/CHANGELOG.md
deleted file mode 100644
index c243888e..00000000
--- a/ndk-cache-nostr/CHANGELOG.md
+++ /dev/null
@@ -1,56 +0,0 @@
-# @nostr-dev-kit/ndk-cache-nostr
-
-## 0.1.7
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.7
-
-## 0.1.6
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.6
-
-## 0.1.5
-
-### Patch Changes
-
-- Updated dependencies [5939a3e]
-- Updated dependencies
-- Updated dependencies [f2a0cce]
- - @nostr-dev-kit/ndk@2.10.5
-
-## 0.1.4
-
-### Patch Changes
-
-- Updated dependencies [5bed70c]
-- Updated dependencies [873ad4a]
- - @nostr-dev-kit/ndk@2.10.4
-
-## 0.1.3
-
-### Patch Changes
-
-- Updated dependencies [0fc66c5]
- - @nostr-dev-kit/ndk@2.10.3
-
-## 0.1.2
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.2
-
-## 0.1.1
-
-### Patch Changes
-
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [722345b]
- - @nostr-dev-kit/ndk@2.10.1
diff --git a/ndk-cache-nostr/README.md b/ndk-cache-nostr/README.md
deleted file mode 100644
index 79e4d3fd..00000000
--- a/ndk-cache-nostr/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# ndk-cache-nostr
-
-NDK cache adapter using a nostr relay as the database.
-
-This cache adapter is meant to be run against a local relay. This adapter will generate two NDK instances:
-
-`ndk` -- This talks exclusively to the local relay, with outbox model disabled.
-`fallbackNdk` -- This is used to hydrate the cache and uses the outbox model -- each query the cache receives is placed in a queue in the background so that subsequent requests can be served from the cache. All events from other relays
-
-## Usage
-
-### Install
-
-```
-npm add @nostr-dev-kit/ndk-cache-nostr
-
-```
-
-### Add as a cache adapter
-
-```ts
-import NDKCacheAdapterNostr from "@nostr-dev-kit/ndk-cache-nostr";
-
-const cacheAdapter = new NDKCacheAdapterNostr({
- relayUrl: "ws://localhost:5577",
-});
-const ndk = new NDK({ cacheAdapter });
-```
-
-If running server-side in a NodeJS environment, you should make sure to polyfill `WebSocket`.
-
-# License
-
-MIT
diff --git a/ndk-cache-nostr/jest.config.ts b/ndk-cache-nostr/jest.config.ts
deleted file mode 100644
index 931e01ef..00000000
--- a/ndk-cache-nostr/jest.config.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { Config } from "jest";
-
-const config: Config = {
- preset: "ts-jest",
- testEnvironment: "node",
- moduleNameMapper: {
- "^(\\.{1,2}/.*)\\.js$": "$1",
- },
-};
-
-export default config;
diff --git a/ndk-cache-nostr/package.json b/ndk-cache-nostr/package.json
deleted file mode 100644
index ba8228e8..00000000
--- a/ndk-cache-nostr/package.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- "name": "@nostr-dev-kit/ndk-cache-nostr",
- "version": "0.1.7",
- "description": "NDK cache adapter that uses a local nostr relay.",
- "main": "./dist/index.js",
- "module": "./dist/index.mjs",
- "exports": {
- "import": {
- "types": "./dist/index.d.mts",
- "default": "./dist/index.mjs"
- },
- "require": {
- "types": "./dist/index.d.ts",
- "default": "./dist/index.js"
- }
- },
- "scripts": {
- "dev": "pnpm build --watch",
- "build": "tsup src/index.ts --format cjs,esm --dts",
- "clean": "rm -rf dist",
- "test": "jest",
- "lint": "prettier --check . && eslint .",
- "format": "prettier --write ."
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/nostr-dev-kit/ndk.git"
- },
- "keywords": [
- "nostr",
- "cache"
- ],
- "author": "pablof7z",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/nostr-dev-kit/ndk/issues"
- },
- "homepage": "https://github.com/nostr-dev-kit/ndk",
- "dependencies": {
- "@nostr-dev-kit/ndk": "workspace:*",
- "debug": "^4.3.4",
- "typescript": "^5.4.4",
- "websocket-polyfill": "^0.0.3"
- },
- "devDependencies": {
- "@nostr-dev-kit/eslint-config-custom": "workspace:*",
- "@nostr-dev-kit/tsconfig": "workspace:*",
- "@types/debug": "^4.1.7",
- "@types/jest": "^29.5.5",
- "@types/node": "^18.15.11",
- "jest": "^29.7.0",
- "ts-jest": "^29.1.2",
- "ts-node": "^10.9.2",
- "tsup": "^7.2.0"
- }
-}
diff --git a/ndk-cache-nostr/src/index.ts b/ndk-cache-nostr/src/index.ts
deleted file mode 100644
index 7cf2c464..00000000
--- a/ndk-cache-nostr/src/index.ts
+++ /dev/null
@@ -1,272 +0,0 @@
-import {
- NDKCacheAdapter,
- NDKCacheRelayInfo,
- NDKFilter,
- NDKKind,
- NDKLnUrlData,
- NDKRelaySet,
- NDKUserProfile,
- NostrEvent,
- ProfilePointer,
-} from "@nostr-dev-kit/ndk";
-import NDK, { NDKRelay } from "@nostr-dev-kit/ndk";
-import { NDKEvent, type NDKSubscription } from "@nostr-dev-kit/ndk";
-import createDebugger from "debug";
-import { Queue } from "./queue";
-
-export interface NDKNostrCacheAdapterOptions {
- relayUrl: string;
-}
-
-let d: debug.IDebugger;
-
-export default class NDKNostrCacheAdapter implements NDKCacheAdapter {
- public locking: boolean;
- public ready?: boolean | undefined;
-
- /**
- * The NDK instance used to interact with the local nostr relay.
- */
- private ndk: NDK;
-
- /**
- * The fallback NDK is used to gather events on the background, to hydrate the
- * cache
- */
- private fallbackNdk: NDK;
- private relaySet: NDKRelaySet;
- private relay: NDKRelay;
-
- /**
- * How long it's acceptable to block until queries finish.
- */
- public queryTimeout = 4000;
-
- public backgroundSubscriptionQueue: Queue = new Queue("ndk-nostr-cache-adapter", 5);
-
- private hydratedEvents = 0;
-
- constructor(options: NDKNostrCacheAdapterOptions) {
- this.locking = false;
- this.ready = true;
- d = createDebugger("ndk:nostr-cache-adapter");
-
- this.ndk = new NDK({
- explicitRelayUrls: [options.relayUrl],
- enableOutboxModel: false,
- debug: d.extend("ndk"),
- });
- this.ndk.connect().then(() => this.onConnect());
-
- this.fallbackNdk = new NDK({
- enableOutboxModel: true,
- debug: d.extend("fallback-ndk"),
- });
- this.fallbackNdk.connect().then(() => {
- d(
- "Connected to fallback NDK %o",
- this.fallbackNdk.pool.connectedRelays().map((relay) => relay.url)
- );
- });
-
- this.relaySet = NDKRelaySet.fromRelayUrls([options.relayUrl], this.ndk);
- this.relay = Array.from(this.relaySet.relays)[0];
-
- if (d.enabled) {
- setInterval(() => {
- d("Cache adapter has injested %d events", this.hydratedEvents);
- }, 10000);
- }
- }
-
- private onConnect() {
- d(
- "Connected to %o",
- this.ndk.pool.connectedRelays().map((relay) => relay.url)
- );
- this.locking = true;
- this.ready = true;
- }
-
- /**
- * Processes the query locally.
- * @param subscription
- * @returns The number of events received.
- */
- private async queryLocally(subscription: NDKSubscription): Promise {
- const subId =
- subscription.subId ??
- subscription.filters.map((filter) => Object.keys(filter).join(",")).join("-");
- const _ = d.extend(subId);
-
- return new Promise((resolve, reject) => {
- let eventCount = 0;
-
- _("Querying %o", subscription.filters);
-
- // Generate a subscription
- const sub = this.ndk.subscribe(
- subscription.filters,
- {
- subId: subscription.subId,
- closeOnEose: true,
- },
- this.relaySet,
- false
- );
-
- // Process events
- sub.on("event", (event) => {
- subscription.eventReceived(event, undefined, true);
- eventCount++;
- _("Event received %d", event.kind);
- });
-
- // Finish when we EOSE
- sub.on("eose", () => {
- _("Eose received");
- this.relay.off("notice", onRelayNotice);
- resolve(eventCount);
- });
-
- // Handle relay notices
- const onRelayNotice = (notice: string) => {
- _("Notice received %s", notice);
- reject(notice);
- };
-
- this.relay.once("notice", (notice) => {
- _("Notice received %o", notice);
- });
-
- // Start the subscription
- sub.start();
- });
- }
-
- async query(subscription: NDKSubscription): Promise {
- const subId =
- subscription.subId ??
- subscription.filters.map((filter) => Object.keys(filter).join(",")).join("-");
- let eventCount = 0;
-
- const _ = d.extend(subId);
-
- await Promise.race([this.queryLocally(subscription), timeout(this.queryTimeout)])
- .then((count: unknown) => {
- if (typeof count === "number") {
- eventCount = count;
-
- _("Query finished with %d events", eventCount);
-
- setTimeout(() => this.hydrate(subscription), 2500);
- }
- })
- .catch((err) => {
- _("Error %o", err);
- });
- }
-
- private async hydrate(subscription: NDKSubscription) {
- this.backgroundSubscriptionQueue.add({
- id: subscription.filters.flatMap((filter) => Object.keys(filter).join(",")).join("-"),
- func: async (): Promise => {
- let publishedEvents = 0;
- return new Promise((resolve, reject) => {
- d("Hydrating %o", subscription.filters);
- const sub = this.fallbackNdk.subscribe(
- subscription.filters,
- {
- closeOnEose: true,
- },
- undefined,
- false
- );
- sub.on("event", (event) => {
- this.hydrateLocalRelayWithEvent(event);
- publishedEvents++;
- });
- sub.on("eose", () => {
- d("Hydrated %d events", publishedEvents);
- resolve();
- });
- sub.on("close", () => {
- d("Hydration closed");
- reject();
- });
- sub.start();
- });
- },
- });
- }
-
- private hydrateLocalRelayWithEvent(event: NDKEvent) {
- d(`relay status %s`, this.relay.status);
- event.ndk = this.ndk;
- this.relay
- .publish(event)
- .then(() => {
- this.hydratedEvents++;
- })
- .catch((err) => {
- d("Error hydrating event %o", err);
- });
- }
-
- async setEvent(
- event: NDKEvent,
- filters: NDKFilter[],
- relay?: NDKRelay | undefined
- ): Promise {
- this.hydrateLocalRelayWithEvent(event);
- }
-
- // async deleteEvent?(event: NDKEvent): Promise {
- // d("deleteEvent method not implemented.");
- // }
- // async fetchProfile?(pubkey: string): Promise {
- // d("fetchProfile method not implemented.");
- // }
- // saveProfile?(pubkey: string, profile: NDKUserProfile): void {
- // d("saveProfile method not implemented.");
- // }
- // getProfiles?: ((filter: (pubkey: string, profile: NDKUserProfile) => boolean) => Promise | undefined>) | undefined;
- // async loadNip05?(nip05: string, maxAgeForMissing?: number | undefined): Promise {
- // d("loadNip05 method not implemented.");
- // }
- // saveNip05?(nip05: string, profile: ProfilePointer | null): void {
- // d("saveNip05 method not implemented.");
- // }
- // async loadUsersLNURLDoc?(pubkey: string, maxAgeInSecs?: number | undefined, maxAgeForMissing?: number | undefined): Promise<"missing" | NDKLnUrlData | null> {
- // d("loadUsersLNURLDoc method not implemented.");
- // }
- // saveUsersLNURLDoc?(pubkey: string, doc: NDKLnUrlData | null): void {
- // d("saveUsersLNURLDoc method not implemented.");
- // }
- // updateRelayStatus?(relayUrl: string, info: NDKCacheRelayInfo): void {
- // d("updateRelayStatus method not implemented.");
- // }
- // addUnpublishedEvent?(event: NDKEvent, relayUrls: string[]): void {
- // d("addUnpublishedEvent method not implemented.");
- // }
- // async getUnpublishedEvents?(): Promise<{ event: NDKEvent; relays?: string[] | undefined; lastTryAt?: number | undefined; }[]> {
- // d("getUnpublishedEvents method not implemented.");
- // }
- // discardUnpublishedEvent?(eventId: string): void {
- // d("discardUnpublishedEvent method not implemented.");
- // }
- // onReady?(callback: () => void): void {
- // d("onReady method not implemented.");
- // }
-}
-
-const timeout = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
-
-const profile = async (fn: (...args: any[]) => any) => {
- return async (...args: any[]) => {
- const start = Date.now();
- const result = await fn(...args);
- d("Function took %d ms", Date.now() - start);
- return result;
- };
-};
diff --git a/ndk-cache-nostr/src/queue.ts b/ndk-cache-nostr/src/queue.ts
deleted file mode 100644
index 8d389cdf..00000000
--- a/ndk-cache-nostr/src/queue.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-type QueueItem = {
- /**
- * Deterministic id of the item
- */
- id: string;
-
- /**
- * A function to process the item
- * @returns
- */
- func: () => Promise;
-};
-
-export class Queue {
- private queue: QueueItem[] = [];
- private maxConcurrency: number;
- private processing: Set = new Set();
- private promises: Map> = new Map();
-
- constructor(name: string, maxConcurrency: number) {
- this.maxConcurrency = maxConcurrency;
- }
-
- public add(item: QueueItem): Promise {
- if (this.promises.has(item.id)) {
- return this.promises.get(item.id)!;
- } else {
- }
-
- const promise = new Promise((resolve, reject) => {
- this.queue.push({
- ...item,
- func: () =>
- item.func().then(
- (result) => {
- resolve(result);
- return result; // Return the result to match the expected type.
- },
- (error) => {
- reject(error);
- // It's important to rethrow the error here to not accidentally resolve the promise.
- // However, since TypeScript 4.4, you can set "useUnknownInCatchVariables" to false if this line errors.
- throw error;
- }
- ),
- });
- this.process();
- });
-
- this.promises.set(item.id, promise);
- promise.finally(() => {
- this.promises.delete(item.id);
- this.processing.delete(item.id);
- this.process();
- });
-
- return promise;
- }
-
- private process() {
- if (this.processing.size >= this.maxConcurrency || this.queue.length === 0) {
- return;
- }
-
- const item = this.queue.shift();
- if (!item || this.processing.has(item.id)) {
- return;
- }
-
- this.processing.add(item.id);
- item.func();
- }
-
- public clear() {
- this.queue = [];
- }
-
- public clearProcessing() {
- this.processing.clear();
- }
-
- public clearAll() {
- this.clear();
- this.clearProcessing();
- }
-
- public length() {
- return this.queue.length;
- }
-}
diff --git a/ndk-cache-nostr/tsconfig.json b/ndk-cache-nostr/tsconfig.json
deleted file mode 100644
index ecc6d9be..00000000
--- a/ndk-cache-nostr/tsconfig.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "extends": "@nostr-dev-kit/tsconfig/ndk-cache-redis.json",
- "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts"],
- "exclude": ["dist", "build", "node_modules"]
-}
diff --git a/ndk-cache-redis/.gitignore b/ndk-cache-redis/.gitignore
deleted file mode 100644
index c92e9f04..00000000
--- a/ndk-cache-redis/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-node_modules
-**/*.js
-dist
diff --git a/ndk-cache-redis/.prettierignore b/ndk-cache-redis/.prettierignore
deleted file mode 100644
index 1521c8b7..00000000
--- a/ndk-cache-redis/.prettierignore
+++ /dev/null
@@ -1 +0,0 @@
-dist
diff --git a/ndk-cache-redis/CHANGELOG.md b/ndk-cache-redis/CHANGELOG.md
deleted file mode 100644
index 9aa56fd0..00000000
--- a/ndk-cache-redis/CHANGELOG.md
+++ /dev/null
@@ -1,362 +0,0 @@
-# @nostr-dev-kit/ndk-cache-redis
-
-## 2.1.24
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.7
-
-## 2.1.23
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.6
-
-## 2.1.22
-
-### Patch Changes
-
-- Updated dependencies [5939a3e]
-- Updated dependencies
-- Updated dependencies [f2a0cce]
- - @nostr-dev-kit/ndk@2.10.5
-
-## 2.1.21
-
-### Patch Changes
-
-- Updated dependencies [5bed70c]
-- Updated dependencies [873ad4a]
- - @nostr-dev-kit/ndk@2.10.4
-
-## 2.1.20
-
-### Patch Changes
-
-- Updated dependencies [0fc66c5]
- - @nostr-dev-kit/ndk@2.10.3
-
-## 2.1.19
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.2
-
-## 2.1.18
-
-### Patch Changes
-
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [722345b]
- - @nostr-dev-kit/ndk@2.10.1
-
-## 2.1.17
-
-### Patch Changes
-
-- Updated dependencies [ec83ddc]
-- Updated dependencies [18c55bb]
-- Updated dependencies
-- Updated dependencies [18c55bb]
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies [3029124]
- - @nostr-dev-kit/ndk@2.10.0
-
-## 2.1.16
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.9.1
-
-## 2.1.15
-
-### Patch Changes
-
-- Updated dependencies [94018b4]
-- Updated dependencies [548f4d8]
- - @nostr-dev-kit/ndk@2.9.0
-
-## 2.1.14
-
-### Patch Changes
-
-- Updated dependencies [0af033f]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.8.2
-
-## 2.1.13
-
-### Patch Changes
-
-- Updated dependencies [e40312b]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.8.1
-
-## 2.1.12
-
-### Patch Changes
-
-- Updated dependencies [91d873c]
-- Updated dependencies [6fd9ddc]
-- Updated dependencies [0b8f331]
-- Updated dependencies
-- Updated dependencies [f2898ad]
-- Updated dependencies [9b92cd9]
-- Updated dependencies
-- Updated dependencies [6814f0c]
-- Updated dependencies [89b5b3f]
-- Updated dependencies [9b92cd9]
-- Updated dependencies [27b10cc]
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies [ed7cdc4]
- - @nostr-dev-kit/ndk@2.8.0
-
-## 2.1.11
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.7.1
-
-## 2.1.10
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.7.0
-
-## 2.1.9
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.6.1
-
-## 2.1.8
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [c2db3c1]
-- Updated dependencies
-- Updated dependencies [c2db3c1]
-- Updated dependencies [c2db3c1]
- - @nostr-dev-kit/ndk@2.6.0
-
-## 2.1.7
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.5.1
-
-## 2.1.6
-
-### Patch Changes
-
-- Updated dependencies [e08fc74]
- - @nostr-dev-kit/ndk@2.5.0
-
-## 2.1.5
-
-### Patch Changes
-
-- Updated dependencies [111c1ea]
-- Updated dependencies [5c0ae51]
-- Updated dependencies [6f5ea49]
-- Updated dependencies [3738d39]
-- Updated dependencies [d22239a]
- - @nostr-dev-kit/ndk@2.4.1
-
-## 2.1.4
-
-### Patch Changes
-
-- Updated dependencies [b9bbf1d]
- - @nostr-dev-kit/ndk@2.4.0
-
-## 2.1.3
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [885b6c2]
-- Updated dependencies [5666d56]
- - @nostr-dev-kit/ndk@2.3.3
-
-## 2.1.2
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [4628481]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.3.2
-
-## 2.1.1
-
-### Patch Changes
-
-- Updated dependencies [ece965f]
- - @nostr-dev-kit/ndk@2.3.1
-
-## 2.1.0
-
-### Minor Changes
-
-- 06c83ea: Aggressively cache all filters and their responses so the same filter can hit the cache
-
-### Patch Changes
-
-- Updated dependencies [54cec78]
-- Updated dependencies [ef61d83]
-- Updated dependencies [98b77dd]
-- Updated dependencies [46b0c77]
-- Updated dependencies [082e243]
- - @nostr-dev-kit/ndk@2.3.0
-
-## 2.0.11
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.2.0
-
-## 2.0.10
-
-### Patch Changes
-
-- Updated dependencies [180d774]
-- Updated dependencies [7f00c40]
- - @nostr-dev-kit/ndk@2.1.3
-
-## 2.0.9
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.2
-
-## 2.0.8
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.1
-
-## 2.0.7
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.0
-
-## 2.0.6
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.6
-
-## 2.0.5
-
-### Patch Changes
-
-- Updated dependencies [d45d962]
- - @nostr-dev-kit/ndk@2.0.5
-
-## 2.0.5
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [d45d962]
- - @nostr-dev-kit/ndk@2.0.5
-
-## 2.0.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.4
-
-## 2.0.3
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.3
-
-## 2.0.2
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.2
-
-## 1.8.7
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.0
-
-## 1.8.6
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.2
-
-## 1.8.5
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.1
-
-## 1.8.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.0
-
-## 1.8.3
-
-### Patch Changes
-
-- Updated dependencies [b3561af]
- - @nostr-dev-kit/ndk@1.3.2
-
-## 1.8.2
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.3.1
-
-## 1.8.1
-
-### Patch Changes
-
-- Updated dependencies [88df10a]
-- Updated dependencies [c225094]
-- Updated dependencies [cf4a648]
-- Updated dependencies [3946078]
-- Updated dependencies [3440768]
- - @nostr-dev-kit/ndk@1.3.0
diff --git a/ndk-cache-redis/README.md b/ndk-cache-redis/README.md
deleted file mode 100644
index 42d65328..00000000
--- a/ndk-cache-redis/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# ndk-cache-redis
-
-NDK cache adapter for redis.
-
-This cache is mostly a skeleton; the cache hit logic is very basic and only checks if
-a query is using precisely `kinds` and `authors` filtering.
-
-## Usage
-
-### Install
-
-```
-npm add @nostr-dev-kit/ndk-cache-redis
-```
-
-### Add as a cache adapter
-
-```ts
-import NDKRedisCacheAdapter from "@nostr-dev-kit/ndk-cache-redis";
-
-const cacheAdapter = new NDKRedisCacheAdapter();
-const ndk = new NDK({ cacheAdapter });
-```
-
-# License
-
-MIT
diff --git a/ndk-cache-redis/jest.config.ts b/ndk-cache-redis/jest.config.ts
deleted file mode 100644
index 931e01ef..00000000
--- a/ndk-cache-redis/jest.config.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { Config } from "jest";
-
-const config: Config = {
- preset: "ts-jest",
- testEnvironment: "node",
- moduleNameMapper: {
- "^(\\.{1,2}/.*)\\.js$": "$1",
- },
-};
-
-export default config;
diff --git a/ndk-cache-redis/package.json b/ndk-cache-redis/package.json
deleted file mode 100644
index 60b4c9df..00000000
--- a/ndk-cache-redis/package.json
+++ /dev/null
@@ -1,58 +0,0 @@
-{
- "name": "@nostr-dev-kit/ndk-cache-redis",
- "version": "2.1.24",
- "description": "NDK cache adapter for redis.",
- "main": "./dist/index.js",
- "module": "./dist/index.mjs",
- "exports": {
- "import": {
- "types": "./dist/index.d.mts",
- "default": "./dist/index.mjs"
- },
- "require": {
- "types": "./dist/index.d.ts",
- "default": "./dist/index.js"
- }
- },
- "scripts": {
- "dev": "pnpm build --watch",
- "build": "tsup src/index.ts --format cjs,esm --dts",
- "clean": "rm -rf dist",
- "test": "jest",
- "lint": "prettier --check . && eslint .",
- "format": "prettier --write ."
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/nostr-dev-kit/ndk.git"
- },
- "keywords": [
- "nostr",
- "redis",
- "cache"
- ],
- "author": "pablof7z",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/nostr-dev-kit/ndk/issues"
- },
- "homepage": "https://github.com/nostr-dev-kit/ndk",
- "dependencies": {
- "@nostr-dev-kit/ndk": "workspace:*",
- "debug": "^4.3.4",
- "ioredis": "^5.3.2",
- "nostr-tools": "^2.4.0",
- "typescript": "^5.4.4"
- },
- "devDependencies": {
- "@nostr-dev-kit/eslint-config-custom": "workspace:*",
- "@nostr-dev-kit/tsconfig": "workspace:*",
- "@types/debug": "^4.1.7",
- "@types/jest": "^29.5.5",
- "@types/node": "^18.15.11",
- "jest": "^29.7.0",
- "ts-jest": "^29.1.2",
- "ts-node": "^10.9.2",
- "tsup": "^7.2.0"
- }
-}
diff --git a/ndk-cache-redis/src/index.test.ts b/ndk-cache-redis/src/index.test.ts
deleted file mode 100644
index 88755105..00000000
--- a/ndk-cache-redis/src/index.test.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import NDK, {
- NDKEvent,
- NDKKind,
- NDKPrivateKeySigner,
- NDKSubscription,
- type NostrEvent,
- type NDKUser,
- NDKSubscriptionCacheUsage,
- NDKRelay,
-} from "@nostr-dev-kit/ndk";
-import NDKRedisCacheAdapter from ".";
-import Redis from "ioredis";
-
-const signer = NDKPrivateKeySigner.generate();
-const ndk = new NDK({
- cacheAdapter: new NDKRedisCacheAdapter(),
- signer,
-});
-const redis = new Redis();
-const relay = new NDKRelay("ws://localhost");
-
-let user: NDKUser;
-
-beforeAll(async () => {
- user = await signer.blockUntilReady();
-});
-
-async function storeEvent(sub: NDKSubscription, event?: NDKEvent) {
- event ??= new NDKEvent(ndk, {
- kind: NDKKind.Text,
- content: "hello, world",
- } as NostrEvent);
- await event.sign();
-
- await sub.eventReceived(event, relay);
-
- return event;
-}
-
-describe("setEvent", () => {
- it("stores the event", async () => {
- const sub = new NDKSubscription(
- ndk,
- {
- authors: [user.pubkey],
- kinds: [NDKKind.Text],
- },
- { cacheUsage: NDKSubscriptionCacheUsage.ONLY_CACHE, closeOnEose: true }
- );
- const event = await storeEvent(sub);
-
- await sleep(100); // We don't want the cache to await the event to be stored, but we need to test that it is stored
-
- const result = await redis.get(event.id);
- expect(result).toBeTruthy();
- });
-
- it("finds the event", async () => {
- const sub = new NDKSubscription(
- ndk,
- {
- authors: [user.pubkey],
- kinds: [NDKKind.Text],
- },
- { cacheUsage: NDKSubscriptionCacheUsage.ONLY_CACHE, closeOnEose: true }
- );
- const event = await storeEvent(sub);
-
- // sub should have an event fired to it
- await new Promise((resolve) => {
- sub.on("event", (event) => {
- expect(event.id).toEqual(event.id);
- resolve();
- });
-
- sub.start();
- });
- });
-});
-
-async function sleep(ms: number) {
- return new Promise((resolve) => setTimeout(resolve, ms));
-}
diff --git a/ndk-cache-redis/src/index.ts b/ndk-cache-redis/src/index.ts
deleted file mode 100644
index 6e83073a..00000000
--- a/ndk-cache-redis/src/index.ts
+++ /dev/null
@@ -1,160 +0,0 @@
-import type { NDKCacheAdapter, NDKFilter, NostrEvent, ProfilePointer } from "@nostr-dev-kit/ndk";
-import { NDKRelay } from "@nostr-dev-kit/ndk";
-import { NDKEvent, type NDKSubscription } from "@nostr-dev-kit/ndk";
-import _debug from "debug";
-import Redis from "ioredis";
-import { matchFilter } from "nostr-tools";
-
-type NostrEventWithRelay = NostrEvent & { relay?: string };
-interface RedisAdapterOptions {
- /**
- * Debug instance to use for logging.
- */
- debug?: debug.IDebugger;
-
- /**
- * The number of seconds to store events in redis before they expire.
- */
- expirationTime?: number;
- /**
- * Redis instance connection path
- */
- path?: string;
-}
-
-export default class RedisAdapter implements NDKCacheAdapter {
- public redis;
- public debug;
- private expirationTime;
- readonly locking;
-
- constructor(opts: RedisAdapterOptions = {}) {
- this.redis = opts.path ? new Redis(opts.path) : new Redis();
- this.debug = opts.debug || _debug("ndk:redis-adapter");
- this.redis.on("error", (err) => {
- this.debug("redis error", err);
- });
- this.locking = true;
- this.expirationTime = opts.expirationTime || 3600;
- }
-
- public async query(subscription: NDKSubscription): Promise {
- this.debug("query redis status", this.redis.status);
- if (this.redis.status !== "connect") return;
- await Promise.all(
- subscription.filters.map((filter) => this.processFilter(filter, subscription))
- );
- }
-
- private async processFilter(filter: NDKFilter, subscription: NDKSubscription): Promise {
- const filterString = JSON.stringify(filter);
-
- const eventIds = await this.redis.smembers(filterString);
-
- return new Promise((resolve) => {
- Promise.all(
- eventIds.map(async (eventId) => {
- const event = await this.redis.get(eventId);
- if (!event) return;
-
- const parsedEvent = JSON.parse(event);
- const relayUrl = parsedEvent.relay;
- delete parsedEvent.relay;
- const relay =
- subscription.ndk.pool.getRelay(relayUrl, false) || new NDKRelay(relayUrl);
-
- subscription.eventReceived(
- new NDKEvent(subscription.ndk, parsedEvent),
- relay,
- true
- );
- })
- ).then(() => {
- resolve();
- });
- });
- }
-
- private storeEvent(event: NostrEventWithRelay, relay: NDKRelay) {
- event.relay = relay.url;
- return this.redis.set(event.id!, JSON.stringify(event), "EX", this.expirationTime);
- }
-
- private async storeEventWithFilter(
- event: NostrEvent,
- filter: NDKFilter,
- relay: NDKRelay
- ): Promise {
- const filterString = JSON.stringify(filter);
-
- // very naive quick implementation of storing the filter
- this.redis.sadd(filterString, event.id!);
- this.redis.expire(filterString, this.expirationTime);
-
- // store the event if it doesn't already exist
- const exists = await this.redis.exists(event.id!);
-
- if (!exists) {
- await this.storeEvent(event, relay);
- } else {
- // renew the expiration time
- this.redis.expire(event.id!, this.expirationTime);
- }
- }
-
- public shouldSkipFilter(filter: NDKFilter): boolean {
- const values = Object.values(filter);
-
- // if it has too many things tagged in an array
- if (values.some((v) => Array.isArray(v) && v.length > 10)) {
- this.debug("skipping filter", filter);
- return true;
- }
-
- // if it has too many queries
- if (values && values.length > 3) return true;
-
- // if it uses since or until
- if (filter.since || filter.until) return true;
-
- return false;
- }
-
- public async setEvent(event: NDKEvent, filters: NDKFilter[], relay: NDKRelay): Promise {
- this.debug("setEvent redis status", this.redis.status);
- if (this.redis.status !== "connect") return;
- const rawEvent = event.rawEvent();
-
- if (filters.length === 1) {
- if (this.shouldSkipFilter(filters[0])) return;
-
- await this.storeEventWithFilter(rawEvent, filters[0], relay);
- } else if (filters.length > 1) {
- for (const filter of filters) {
- if (this.shouldSkipFilter(filter)) continue;
-
- if (matchFilter(filter, rawEvent as any)) {
- await this.storeEventWithFilter(rawEvent, filter, relay);
- continue;
- }
- }
- }
- }
-
- public async loadNip05?(nip05: string): Promise {
- this.debug("loadNip05 redis status", this.redis.status);
- if (this.redis.status !== "connect") return null;
- const profile = await this.redis.get(this.nip05Key(nip05));
- return profile ? JSON.parse(profile) : null;
- }
-
- public saveNip05?(nip05: string, profile: ProfilePointer): void {
- this.debug("saveNip05 redis status", this.redis.status);
- if (this.redis.status !== "connect") return;
- this.redis.set(this.nip05Key(nip05), JSON.stringify(profile), "EX", this.expirationTime);
- }
-
- private nip05Key(nip05: string): string {
- return `nip05:${nip05}`;
- }
-}
diff --git a/ndk-cache-redis/tsconfig.json b/ndk-cache-redis/tsconfig.json
deleted file mode 100644
index ecc6d9be..00000000
--- a/ndk-cache-redis/tsconfig.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "extends": "@nostr-dev-kit/tsconfig/ndk-cache-redis.json",
- "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts"],
- "exclude": ["dist", "build", "node_modules"]
-}
diff --git a/ndk-mobile/CHANGELOG.md b/ndk-mobile/CHANGELOG.md
deleted file mode 100644
index cf774503..00000000
--- a/ndk-mobile/CHANGELOG.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# @nostr-dev-kit/ndk-mobile
-
-## 0.2.1
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.7
- - @nostr-dev-kit/ndk-wallet@0.3.15
-
-## 0.2.0
-
-### Minor Changes
-
-- add the very handy useNDKSessionEventKind
-
-## 0.1.5
-
-### Patch Changes
-
-- add default export
diff --git a/ndk-mobile/LICENSE b/ndk-mobile/LICENSE
deleted file mode 100644
index 2a6ea523..00000000
--- a/ndk-mobile/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2023 Pablo Fernandez
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/ndk-mobile/README.md b/ndk-mobile/README.md
deleted file mode 100644
index 71c109e0..00000000
--- a/ndk-mobile/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# NDK Mobile
-
-A React Native/Expo implementation of [NDK (Nostr Development Kit)](https://github.com/nostr-dev-kit/ndk) that provides a complete toolkit for building Nostr applications on mobile platforms.
-
-## Features
-
-- 🔐 Multiple signer implementations (NIP-07, NIP-46, Private Key)
-- 💾 SQLite-based caching for offline support
-- 🔄 Subscription management with automatic reconnection
-- 📱 React Native and Expo compatibility
-- 🪝 React hooks for easy state management
-- 👛 Integrated wallet support
-
-## Installation
-
-npm install @nostr-dev-kit/ndk-mobile
-
-## Usage
-
-When using this library don't import `@nostr-dev-kit/ndk` directly, instead import `@nostr-dev-kit/ndk-mobile`. `ndk-mobile` exports the same classes as `ndk`, so you can just swap the import.
-
-## Example
-
-There is a barebones repository showing how to use this library:
-[ndk-mobile-sample](https://github.com/pablof7z/ndk-mobile-sample).
-
-For a real application using this look at [Olas](https://github.com/pablof7z/snapstr).
-
-## License
-
-This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
-
-## Author
-
-[@pablof7z](https://njump.me/f7z.io)
diff --git a/ndk-mobile/index.ts b/ndk-mobile/index.ts
deleted file mode 100644
index faf045ad..00000000
--- a/ndk-mobile/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import '@bacons/text-decoder/install';
-import 'react-native-get-random-values';
-
-export * from './src/hooks';
-export * from './src/context';
-export * from './src/providers';
-export * from './src/cache-adapter/sqlite';
-export * from './src/components';
-export * from './src/components/relays';
-export * from '@nostr-dev-kit/ndk';
diff --git a/ndk-mobile/package.json b/ndk-mobile/package.json
deleted file mode 100644
index 01c50da3..00000000
--- a/ndk-mobile/package.json
+++ /dev/null
@@ -1,83 +0,0 @@
-{
- "name": "@nostr-dev-kit/ndk-mobile",
- "version": "0.2.1",
- "description": "NDK Mobile",
- "private": false,
- "license": "MIT",
- "peerDependencies": {
- "expo": "*"
- },
- "devDependencies": {
- "react-native-builder-bob": "^0.35.2",
- "typescript": "^5.7.2"
- },
- "keywords": [
- "ndk",
- "nostr",
- "react-native",
- "expo"
- ],
- "dependencies": {
- "@bacons/text-decoder": "^0.0.0",
- "@nostr-dev-kit/ndk": "workspace:*",
- "@nostr-dev-kit/ndk-wallet": "workspace:*",
- "react-native-get-random-values": "~1.11.0",
- "typescript-lru-cache": "^2.0.0",
- "zustand": "^5.0.2"
- },
- "source": "./src/index.ts",
- "module": "./lib/module/index.js",
- "react-native": "lib/module/index.js",
- "exports": {
- ".": {
- "import": {
- "types": "./lib/typescript/module/index.d.ts",
- "default": "./lib/module/index.js"
- }
- },
- "./components": {
- "import": {
- "types": "./lib/typescript/module/components/index.d.ts",
- "default": "./lib/module/components/index.js"
- }
- },
- "./components/relays": {
- "import": {
- "types": "./lib/typescript/module/components/relays/index.d.ts",
- "default": "./lib/module/components/relays/index.js"
- }
- }
- },
- "scripts": {
- "prepare": "cd ../ndk-wallet && pnpm build && cd ../ndk-mobile && bob build"
- },
- "files": [
- "src",
- "lib",
- "!**/__tests__",
- "!**/__fixtures__",
- "!**/__mocks__"
- ],
- "react-native-builder-bob": {
- "source": "src",
- "output": "lib",
- "targets": [
- [
- "module",
- {
- "esm": true
- }
- ],
- [
- "typescript",
- {
- "esm": true
- }
- ]
- ]
- },
- "eslintIgnore": [
- "node_modules/",
- "lib/"
- ]
-}
diff --git a/ndk-mobile/src/cache-adapter/migrations.ts b/ndk-mobile/src/cache-adapter/migrations.ts
deleted file mode 100644
index b52b5280..00000000
--- a/ndk-mobile/src/cache-adapter/migrations.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import * as SQLite from 'expo-sqlite';
-
-export const migrations = [
- {
- version: 0,
- up: async (db: SQLite.SQLiteDatabase) => {
- await db.execAsync(
- `CREATE TABLE IF NOT EXISTS unpublished_events (
- id TEXT PRIMARY KEY,
- event TEXT,
- relays TEXT,
- last_try_at INTEGER
- );`
- );
-
- await db.execAsync(
- `CREATE TABLE IF NOT EXISTS events (
- id TEXT PRIMARY KEY,
- created_at INTEGER,
- pubkey TEXT,
- event TEXT,
- kind INTEGER,
- relay TEXT
- );`
- );
- await db.execAsync(
- `CREATE TABLE IF NOT EXISTS profiles (
- pubkey TEXT PRIMARY KEY,
- profile TEXT,
- catched_at INTEGER
- );`
- );
- await db.execAsync(
- `CREATE TABLE IF NOT EXISTS relay_status (
- url TEXT PRIMARY KEY,
- lastConnectedAt INTEGER,
- dontConnectBefore INTEGER
- );`
- );
- // New table for event tags
- await db.execAsync(
- `CREATE TABLE IF NOT EXISTS event_tags (
- event_id TEXT,
- tag TEXT,
- value TEXT,
- PRIMARY KEY (event_id, tag)
- );`
- );
-
- await db.execAsync(`CREATE INDEX IF NOT EXISTS idx_events_pubkey ON events (pubkey);`);
- await db.execAsync(`CREATE INDEX IF NOT EXISTS idx_events_kind ON events (kind);`);
- await db.execAsync(`CREATE INDEX IF NOT EXISTS idx_events_tags_tag ON event_tags (tag);`);
- },
- },
- {
- version: 1,
- up: async (db: SQLite.SQLiteDatabase) => {
- await db.execAsync(`ALTER TABLE profiles ADD COLUMN created_at INTEGER;`);
- },
- },
-];
\ No newline at end of file
diff --git a/ndk-mobile/src/cache-adapter/sqlite.ts b/ndk-mobile/src/cache-adapter/sqlite.ts
deleted file mode 100644
index cb5363b0..00000000
--- a/ndk-mobile/src/cache-adapter/sqlite.ts
+++ /dev/null
@@ -1,314 +0,0 @@
-import {
- NDKCacheAdapter,
- NDKEvent,
- NDKFilter,
- NDKSubscription,
- NDKUserProfile,
- Hexpubkey,
- NDKCacheEntry,
- NDKRelay,
- deserialize,
- NDKEventId,
- NDKKind,
-} from '@nostr-dev-kit/ndk';
-import { LRUCache } from 'typescript-lru-cache';
-import * as SQLite from 'expo-sqlite';
-import { matchFilter } from 'nostr-tools';
-import { migrations } from './migrations';
-
-type EventRecord = {
- id: string;
- created_at: number;
- pubkey: string;
- event: string;
- kind: number;
- relay: string;
-};
-
-type UnpublishedEventRecord = {
- id: string;
- event: string;
- relays: string; // JSON string of {[url: string]: boolean}
- last_try_at: number;
-};
-
-type PendingCallback = (...arg: any) => any;
-
-export class NDKCacheAdapterSqlite implements NDKCacheAdapter {
- readonly dbName: string;
- private db: SQLite.SQLiteDatabase;
- locking: boolean = false;
- ready: boolean = false;
- private pendingCallbacks: PendingCallback[] = [];
- private profileCache: LRUCache>;
-
- constructor(dbName: string, maxProfiles: number = 200) {
- this.dbName = dbName ?? 'ndk-cache';
- this.profileCache = new LRUCache({ maxSize: maxProfiles });
- this.initialize();
- }
-
- private async initialize() {
- this.db = await SQLite.openDatabaseAsync(this.dbName);
-
- // get current schema version
- let { user_version: schemaVersion } = (await this.db.getFirstSync(`PRAGMA user_version;`)) as { user_version: number };
-
- if (!schemaVersion) {
- schemaVersion = 0;
-
- // set the schema version
- await this.db.execAsync(`PRAGMA user_version = ${schemaVersion};`);
- }
-
- if (!schemaVersion || Number(schemaVersion) < migrations.length) {
- await this.db.withTransactionAsync(async () => {
- for (let i = Number(schemaVersion); i < migrations.length; i++) {
- try {
- await migrations[i].up(this.db);
- } catch (e) {
- console.error('error running migration', e);
- throw e;
- }
- await this.db.execAsync(`PRAGMA user_version = ${i + 1};`);
- }
-
- // set the schema version
- await this.db.execAsync(`PRAGMA user_version = ${migrations.length};`);
- });
- }
-
- this.ready = true;
- this.locking = true;
-
- Promise.all(this.pendingCallbacks.map((f) => f()));
- }
-
- onReady(callback: () => void) {
- if (this.ready) {
- callback();
- } else {
- this.pendingCallbacks.unshift(callback);
- }
- }
-
- async query(subscription: NDKSubscription): Promise {
- // Ensure the adapter is ready
- if (!this.ready) return;
-
- // Process filters from the subscription
- for (const filter of subscription.filters) {
- // Example: Fetch events by pubkey
- if (filter.authors) {
- const events = this.db.getAllSync(
- `SELECT * FROM events WHERE pubkey IN (${filter.authors.map(() => '?').join(',')})`,
- filter.authors
- ) as EventRecord[];
- if (events.length > 0) foundEvents(subscription, events, filter);
- }
-
- // Example: Fetch events by kind
- if (filter.kinds) {
- const events = this.db.getAllSync(
- `SELECT * FROM events WHERE kind IN (${filter.kinds.map(() => '?').join(',')})`,
- filter.kinds
- ) as EventRecord[];
- if (events.length > 0) foundEvents(subscription, events, filter);
- }
- }
- }
-
- async setEvent(event: NDKEvent, filters: NDKFilter[], relay?: NDKRelay): Promise {
- const filterTags: [string, string][] = event.tags.filter((tag) => tag[0].length === 1).map((tag) => [tag[0], tag[1]]);
- await Promise.all([
- this.db.runAsync(`INSERT OR REPLACE INTO events (id, created_at, pubkey, event, kind, relay) VALUES (?, ?, ?, ?, ?, ?);`, [
- event.id,
- event.created_at!,
- event.pubkey,
- event.serialize(true, true),
- event.kind!,
- relay?.url || '',
- ]),
- filterTags.map((tag) =>
- // Use INSERT OR REPLACE to avoid UNIQUE constraint violation
- this.db.runAsync(`INSERT OR REPLACE INTO event_tags (event_id, tag, value) VALUES (?, ?, ?);`, [event.id, tag[0], tag[1]])
- ),
- ]);
-
- // if this event is a delete event, see if the deleted events are in the cache and remove them
- if (event.kind === NDKKind.EventDeletion) {
- this.deleteEventIds(event.tags.filter((tag) => tag[0] === 'e').map((tag) => tag[1]));
- }
- }
-
- async deleteEventIds(eventIds: NDKEventId[]): Promise {
- await this.db.runAsync(`DELETE FROM events WHERE id IN (${eventIds.map(() => '?').join(',')});`, eventIds);
- await this.db.runAsync(`DELETE FROM event_tags WHERE event_id IN (${eventIds.map(() => '?').join(',')});`, eventIds);
- }
-
- fetchProfileSync(pubkey: Hexpubkey): NDKCacheEntry | null {
- if (!this.ready) return null;
-
- const cached = this.profileCache.get(pubkey);
- if (cached) return cached;
-
- const result = this.db.getFirstSync(`SELECT profile, catched_at FROM profiles WHERE pubkey = ?;`, [pubkey]) as {
- profile: string;
- catched_at: number;
- };
-
- if (result) {
- try {
- const profile = JSON.parse(result.profile);
- const entry = { ...profile, fetchedAt: result.catched_at };
- this.profileCache.set(pubkey, entry);
- return entry;
- } catch (e) {
- console.error('failed to parse profile', result.profile);
- }
- }
- }
-
- async fetchProfile(pubkey: Hexpubkey): Promise | null> {
- if (!this.ready) return;
-
- const cached = this.profileCache.get(pubkey);
- if (cached) return cached;
-
- const result = this.db.getFirstSync(`SELECT profile, catched_at FROM profiles WHERE pubkey = ?;`, [pubkey]) as {
- profile: string;
- catched_at: number;
- };
-
- if (result) {
- try {
- const profile = JSON.parse(result.profile);
- const entry = { ...profile, fetchedAt: result.catched_at };
- this.profileCache.set(pubkey, entry);
- return entry;
- } catch (e) {
- console.error('failed to parse profile', result.profile);
- }
- }
- return null;
- }
-
- async saveProfile(pubkey: Hexpubkey, profile: NDKUserProfile): Promise {
- // check if the profile we have is newer based on created_at
- const existingProfile = await this.fetchProfile(pubkey);
- if (existingProfile?.created_at && profile.created_at && existingProfile.created_at >= profile.created_at) return;
-
- const now = Date.now();
- const entry = { ...profile, fetchedAt: now };
- this.profileCache.set(pubkey, entry);
-
- this.db.runAsync(`INSERT OR REPLACE INTO profiles (pubkey, profile, catched_at, created_at) VALUES (?, ?, ?, ?);`, [
- pubkey,
- JSON.stringify(profile),
- now,
- profile.created_at,
- ]);
- }
-
- addUnpublishedEvent(event: NDKEvent, relayUrls: WebSocket['url'][]): void {
- const relayStatus: { [key: string]: boolean } = {};
- relayUrls.forEach(url => relayStatus[url] = false);
-
- try {
- this.db.runSync(`INSERT OR REPLACE INTO unpublished_events (id, event, relays, last_try_at) VALUES (?, ?, ?, ?);`, [
- event.id,
- event.serialize(true, true),
- JSON.stringify(relayStatus),
- Date.now(),
- ]);
-
- const onPublished = (relay: NDKRelay) => {
- const url = relay.url;
- const record = this.db.getFirstSync(
- `SELECT relays FROM unpublished_events WHERE id = ?`,
- [event.id]
- ) as UnpublishedEventRecord | undefined;
-
- if (!record) {
- event.off('published', onPublished);
- return;
- }
-
- const relays = JSON.parse(record.relays);
- relays[url] = true;
-
- const successWrites = Object.values(relays).filter(v => v).length;
- const unsuccessWrites = Object.values(relays).length - successWrites;
-
- if (successWrites >= 3 || unsuccessWrites === 0) {
- this.discardUnpublishedEvent(event.id);
- event.off('published', onPublished);
- } else {
- this.db.runSync(
- `UPDATE unpublished_events SET relays = ? WHERE id = ?`,
- [JSON.stringify(relays), event.id]
- );
- }
- };
-
- event.once('published', onPublished);
- } catch (e) {
- console.error('error adding unpublished event', e);
- }
- }
-
- async getUnpublishedEvents(): Promise<{ event: NDKEvent; relays?: WebSocket['url'][]; lastTryAt?: number }[]> {
- const call = () => this._getUnpublishedEvents();
-
- if (!this.ready) {
- return new Promise((resolve, reject) => {
- this.pendingCallbacks.push(() => call().then(resolve).catch(reject));
- });
- } else {
- return call();
- }
- }
-
- async _getUnpublishedEvents(): Promise<{ event: NDKEvent; relays?: WebSocket['url'][]; lastTryAt?: number }[]> {
- const events = (await this.db.getAllAsync(`SELECT * FROM unpublished_events`)) as UnpublishedEventRecord[];
- return events.map((event) => {
- const deserializedEvent = new NDKEvent(undefined, deserialize(event.event));
- const relays = JSON.parse(event.relays);
- return {
- event: deserializedEvent,
- relays: Object.keys(relays),
- lastTryAt: event.last_try_at,
- };
- });
- }
-
- discardUnpublishedEvent(eventId: NDKEventId): void {
- this.db.runAsync(`DELETE FROM unpublished_events WHERE id = ?;`, [eventId]);
- }
-}
-
-export function foundEvents(subscription: NDKSubscription, events: EventRecord[], filter?: NDKFilter) {
- // if we have a limit, sort and slice
- if (filter?.limit && events.length > filter.limit) {
- events = events.sort((a, b) => b.created_at - a.created_at).slice(0, filter.limit);
- }
-
- for (const event of events) {
- foundEvent(subscription, event, event.relay, filter);
- }
-}
-
-export function foundEvent(subscription: NDKSubscription, event: EventRecord, relayUrl: WebSocket['url'] | undefined, filter?: NDKFilter) {
- try {
- const deserializedEvent = deserialize(event.event);
-
- if (filter && !matchFilter(filter, deserializedEvent as any)) return;
-
- const ndkEvent = new NDKEvent(undefined, deserializedEvent);
- const relay = relayUrl ? subscription.pool.getRelay(relayUrl, false) : undefined;
- ndkEvent.relay = relay;
- subscription.eventReceived(ndkEvent, relay, true);
- } catch (e) {
- console.error('failed to deserialize event', e, event);
- }
-}
diff --git a/ndk-mobile/src/components/index.ts b/ndk-mobile/src/components/index.ts
deleted file mode 100644
index 1e5cf076..00000000
--- a/ndk-mobile/src/components/index.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Relays from "./relays";
-
-const Components = {
- Relays
-};
-
-export { Components };
diff --git a/ndk-mobile/src/components/relays/index.tsx b/ndk-mobile/src/components/relays/index.tsx
deleted file mode 100644
index 67091c10..00000000
--- a/ndk-mobile/src/components/relays/index.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-import ConnectivityIndicator from "./indicator";
-
-export default { ConnectivityIndicator };
diff --git a/ndk-mobile/src/components/relays/indicator.tsx b/ndk-mobile/src/components/relays/indicator.tsx
deleted file mode 100644
index dc04b61e..00000000
--- a/ndk-mobile/src/components/relays/indicator.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import React from "react";
-import { NDKRelay } from "@nostr-dev-kit/ndk";
-
-import { NDKRelayStatus } from "@nostr-dev-kit/ndk";
-import { useState, useEffect } from "react";
-import { View } from "react-native";
-
-const CONNECTIVITY_STATUS_COLORS: Record = {
- [NDKRelayStatus.RECONNECTING]: '#f1c40f',
- [NDKRelayStatus.CONNECTING]: '#f1c40f',
- [NDKRelayStatus.DISCONNECTED]: '#aa4240',
- [NDKRelayStatus.DISCONNECTING]: '#aa4240',
- [NDKRelayStatus.CONNECTED]: '#66cc66',
- [NDKRelayStatus.FLAPPING]: '#2ecc71',
- [NDKRelayStatus.AUTHENTICATING]: '#3498db',
- [NDKRelayStatus.AUTHENTICATED]: '#e74c3c',
- [NDKRelayStatus.AUTH_REQUESTED]: '#e74c3c',
-} as const;
-
-export default function RelayConnectivityIndicator({ relay }: { relay: NDKRelay }) {
- const [ color, setColor ] = useState(CONNECTIVITY_STATUS_COLORS[relay.status]);
-
- useEffect(() => {
- relay.on("connect", () => setColor(CONNECTIVITY_STATUS_COLORS[relay.status]));
- relay.on("disconnect", () => setColor(CONNECTIVITY_STATUS_COLORS[relay.status]));
- relay.on("ready", () => setColor(CONNECTIVITY_STATUS_COLORS[relay.status]));
- relay.on("flapping", () => setColor(CONNECTIVITY_STATUS_COLORS[relay.status]));
- relay.on("notice", () => setColor(CONNECTIVITY_STATUS_COLORS[relay.status]));
- relay.on("auth", () => setColor(CONNECTIVITY_STATUS_COLORS[relay.status]));
- relay.on("authed", () => setColor(CONNECTIVITY_STATUS_COLORS[relay.status]));
- relay.on("auth:failed", () => setColor(CONNECTIVITY_STATUS_COLORS[relay.status]));
- relay.on("delayed-connect", () => setColor(CONNECTIVITY_STATUS_COLORS[relay.status]));
- }, []);
-
- return (
-
- );
-}
diff --git a/ndk-mobile/src/context/index.ts b/ndk-mobile/src/context/index.ts
deleted file mode 100644
index 4a64a434..00000000
--- a/ndk-mobile/src/context/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './ndk';
-export * from './session';
\ No newline at end of file
diff --git a/ndk-mobile/src/context/ndk.ts b/ndk-mobile/src/context/ndk.ts
deleted file mode 100644
index 95cf76bb..00000000
--- a/ndk-mobile/src/context/ndk.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import NDK, { NDKFilter, NDKEvent, NDKUser, NDKNip07Signer, NDKNip46Signer, NDKPrivateKeySigner, NDKSigner } from '@nostr-dev-kit/ndk';
-import { createContext } from 'react';
-import { UnpublishedEventEntry } from '../providers/ndk';
-
-interface NDKContext {
- ndk: NDK | undefined;
-
- login: (promise: Promise) => Promise;
- loginWithPayload: (payload: string, { save }: { save?: boolean }) => Promise;
- logout: () => Promise;
- unpublishedEvents: Map;
-
- currentUser: NDKUser | null;
-
- cacheInitialized: boolean | null;
-}
-
-const NDKContext = createContext({
- ndk: undefined,
- login: () => Promise.resolve(undefined),
- loginWithPayload: () => Promise.resolve(undefined),
- logout: () => Promise.resolve(undefined),
-
- currentUser: null,
- unpublishedEvents: new Map(),
-
- cacheInitialized: null,
-});
-
-export default NDKContext;
diff --git a/ndk-mobile/src/context/session.ts b/ndk-mobile/src/context/session.ts
deleted file mode 100644
index f00b55ca..00000000
--- a/ndk-mobile/src/context/session.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { Hexpubkey, NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
-import { NDKCashuWallet, NDKWallet, NDKWalletBalance } from '@nostr-dev-kit/ndk-wallet';
-import { createContext } from 'react';
-
-interface NDKSessionContext {
- follows?: Array;
- events?: Map>;
- mutePubkey: (pubkey: Hexpubkey) => void;
- muteList: Set;
-
- activeWallet?: NDKWallet;
- setActiveWallet: (wallet: NDKWallet) => void;
-
- balances: NDKWalletBalance[];
-}
-
-const NDKSessionContext = createContext({
- follows: [],
- events: new Map(),
- mutePubkey: () => {},
- muteList: new Set(),
- activeWallet: undefined,
- setActiveWallet: () => {},
- balances: [],
-});
-
-export default NDKSessionContext;
diff --git a/ndk-mobile/src/hooks/index.ts b/ndk-mobile/src/hooks/index.ts
deleted file mode 100644
index 788732fb..00000000
--- a/ndk-mobile/src/hooks/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './subscribe';
-export * from './ndk';
-export * from './session';
-export * from './user-profile';
\ No newline at end of file
diff --git a/ndk-mobile/src/hooks/ndk.ts b/ndk-mobile/src/hooks/ndk.ts
deleted file mode 100644
index 256a8a4d..00000000
--- a/ndk-mobile/src/hooks/ndk.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { useContext } from 'react';
-import NDKContext from '../context/ndk';
-
-const useNDK = (): NDKContext => {
- const context = useContext(NDKContext);
- if (context === undefined) {
- throw new Error('useNDK must be used within an NDKProvider');
- }
- return context;
-};
-
-export { useNDK };
diff --git a/ndk-mobile/src/hooks/session.ts b/ndk-mobile/src/hooks/session.ts
deleted file mode 100644
index 9dc5a1ff..00000000
--- a/ndk-mobile/src/hooks/session.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { useContext } from 'react';
-import NDKSessionContext from '../context/session';
-import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
-import { useNDK } from './ndk';
-import { NDKEventWithFrom } from './subscribe';
-
-const useNDKSession = (): NDKSessionContext => {
- const context = useContext(NDKSessionContext);
- if (context === undefined) {
- throw new Error('useNDK must be used within an NDKProvider');
- }
- return context;
-};
-
-/**
- * This hook allows you to get a specific kind, wrapped in the event class you provide.
- * @param EventClass
- * @param kind
- * @param opts.create - If true, and the event kind is not found, an unpublished event will be provided.
- * @returns
- */
-const useNDKSessionEventKind = (
- EventClass: NDKEventWithFrom,
- kind: NDKKind,
- { create }: { create: boolean } = { create: false }
-): T | undefined => {
- const { ndk } = useNDK();
- const { events } = useNDKSession();
- const kindEvents = events.get(kind) || [];
- const firstEvent = !!kindEvents[0];
-
- if (create && !firstEvent) {
- const event = new EventClass(ndk);
- event.kind = kind;
- events.set(kind, [event]);
- return event;
- }
-
- return firstEvent ? EventClass.from(firstEvent) : undefined;
-};
-
-const useNDKSessionEvents = (
- kinds: NDKKind[],
- eventClass?: NDKEventWithFrom,
-): T[] => {
- const { events } = useNDKSession();
- let allEvents = kinds.flatMap((kind) => events.get(kind) || []);
-
- if (kinds.length > 1) allEvents = allEvents.sort((a, b) => a.created_at - b.created_at);
-
- // remove deleted events if replaceable
- allEvents = allEvents.filter((e) => !e.isReplaceable() || !e.hasTag('deleted'));
-
- return allEvents.map((e) => eventClass ? eventClass.from(e) : e as T);
-};
-
-export { useNDKSession, useNDKSessionEventKind, useNDKSessionEvents };
diff --git a/ndk-mobile/src/hooks/subscribe.ts b/ndk-mobile/src/hooks/subscribe.ts
deleted file mode 100644
index 5dfd2b05..00000000
--- a/ndk-mobile/src/hooks/subscribe.ts
+++ /dev/null
@@ -1,252 +0,0 @@
-import '@bacons/text-decoder/install';
-import { createStore } from 'zustand/vanilla';
-import { NDKEvent, NDKFilter, NDKKind, NDKRelaySet, NDKSubscription, NDKSubscriptionOptions } from '@nostr-dev-kit/ndk';
-import { useCallback, useEffect, useMemo, useRef } from 'react';
-import { useNDK } from './ndk';
-import { useStore } from 'zustand';
-import { useSessionStore } from '../stores/session';
-
-/**
- * Extends NDKEvent with a 'from' method to wrap events with a kind-specific handler
- */
-export type NDKEventWithFrom = T & { from: (event: NDKEvent) => T };
-
-/**
- * Parameters for the useSubscribe hook
- * @interface UseSubscribeParams
- * @property {NDKFilter[] | null} filters - Nostr filters to subscribe to
- * @property {Object} [opts] - Subscription options
- * @property {NDKEventWithFrom} [opts.klass] - Class to convert events to
- * @property {boolean} [opts.includeMuted] - Whether to include muted events
- * @property {boolean} [opts.includeDeleted] - Whether to include deleted events
- * @property {number | false} [opts.bufferMs] - Buffer time in ms, false to disable
- * @property {string[]} [relays] - Optional relay URLs to connect to
- */
-interface UseSubscribeParams {
- filters: NDKFilter[] | null;
- opts?: NDKSubscriptionOptions & {
- klass?: NDKEventWithFrom;
- includeMuted?: boolean;
- includeDeleted?: boolean;
- bufferMs?: number | false;
- };
- relays?: string[];
-}
-
-/**
- * Store interface for managing subscription state
- * @interface SubscribeStore
- * @property {T[]} events - Array of received events
- * @property {Map} eventMap - Map of events by ID
- * @property {boolean} eose - End of stored events flag
- * @property {boolean} isSubscribed - Subscription status
- */
-interface SubscribeStore {
- events: T[];
- eventMap: Map;
- eose: boolean;
- isSubscribed: boolean;
- addEvent: (event: T) => void;
- removeEventId: (id: string) => void;
- setEose: () => void;
- clearEvents: () => void;
- setSubscription: (sub: NDKSubscription | undefined) => void;
- subscriptionRef: NDKSubscription | undefined;
-}
-
-/**
- * Creates a store to manage subscription state with optional event buffering
- * @param bufferMs - Buffer time in milliseconds, false to disable buffering
- */
-const createSubscribeStore = (bufferMs: number | false = 16) =>
- createStore>((set, get) => {
- let buffer: T[] = [];
- let timeout: NodeJS.Timeout | null = null;
-
- // Function to flush the buffered events to the store
- const flushBuffer = () => {
- set((state) => {
- const { eventMap } = state;
- buffer.forEach((event) => {
- const currentEvent = eventMap.get(event.tagId());
- if (currentEvent && currentEvent.created_at! >= event.created_at!) return;
- eventMap.set(event.tagId(), event);
- });
- const events = Array.from(eventMap.values());
- buffer = [];
- return { eventMap, events };
- });
- timeout = null;
- };
-
- return {
- events: [],
- eventMap: new Map(),
- eose: false,
- isSubscribed: false,
- subscriptionRef: undefined,
-
- addEvent: (event) => {
- const { eose } = get();
-
- if (!eose && bufferMs !== false) {
- buffer.push(event);
- if (!timeout) {
- timeout = setTimeout(flushBuffer, bufferMs);
- }
- } else {
- // Direct update logic when buffering is disabled or after EOSE
- set((state) => {
- const { eventMap } = state;
- const currentEvent = eventMap.get(event.tagId());
- if (currentEvent && currentEvent.created_at! >= event.created_at!) return state;
-
- eventMap.set(event.tagId(), event);
- const events = Array.from(eventMap.values());
- return { eventMap, events };
- });
- }
- },
-
- removeEventId: (id) => {
- set((state) => {
- state.eventMap.delete(id);
- const events = Array.from(state.eventMap.values());
- return { eventMap: state.eventMap, events };
- });
- },
-
- setEose: () => {
- if (timeout) {
- clearTimeout(timeout);
- flushBuffer(); // Ensure any remaining buffered events are flushed immediately
- }
- set({ eose: true });
- },
-
- clearEvents: () => set({ eventMap: new Map(), eose: false }),
- setSubscription: (sub) => set({ subscriptionRef: sub, isSubscribed: !!sub }),
- };
- });
-
-/**
- * React hook for subscribing to Nostr events
- * @param params - Subscription parameters
- * @returns {Object} Subscription state
- * @returns {T[]} events - Array of received events
- * @returns {boolean} eose - End of stored events flag
- * @returns {boolean} isSubscribed - Subscription status
- */
-export const useSubscribe = ({ filters, opts = undefined, relays = undefined }: UseSubscribeParams) => {
- const { ndk } = useNDK();
- const muteList = useSessionStore((state) => state.muteList);
- const store = useMemo(() => createSubscribeStore(opts?.bufferMs), [opts?.bufferMs]);
- const storeInstance = useStore(store);
-
- /**
- * Map of eventIds that have been received by this subscription.
- *
- * Key: event identifier (event.dTag or event.id)
- *
- * Value: timestamp of the event, used to choose the
- * most recent event on replaceable events
- */
- const eventIds = useRef>(new Map());
-
- const relaySet = useMemo(() => {
- if (ndk && relays && relays.length > 0) {
- return NDKRelaySet.fromRelayUrls(relays, ndk);
- }
- return undefined;
- }, [ndk, relays]);
-
- const shouldAcceptEvent = (event: NDKEvent) => {
- const id = event.tagId();
- const currentVal = eventIds.current.get(id);
-
- // if it's from a muted pubkey, we don't accept it
- if (opts?.includeMuted !== true && muteList.has(event.pubkey)) {
- console.log('rejecting from muted pubkey', event.pubkey);
- return false;
- }
-
- // We have not seen this ID yet
- if (!currentVal) return true;
-
- // The ID we have seen is older
- if (currentVal < event.created_at!) return true;
-
- return false;
- };
-
- const handleEvent = useCallback(
- (event: NDKEvent) => {
- const id = event.tagId();
-
- if (!shouldAcceptEvent(event)) return;
-
- if (opts?.includeDeleted !== true && event.isParamReplaceable() && event.hasTag('deleted')) {
- // We mark the event but we don't add the actual event, since
- // it has been deleted
- eventIds.current.set(id, event.created_at!);
-
- return;
- }
-
- // If we need to convert the event, we do so
- if (opts?.klass) event = opts.klass.from(event);
-
- event.once("deleted", () => {
- storeInstance.removeEventId(id);
- });
-
- // If conversion failed, we bail
- if (!event) return;
-
- storeInstance.addEvent(event as T);
- eventIds.current.set(id, event.created_at!);
- },
- [opts?.klass]
- );
-
- const handleEose = () => {
- storeInstance.setEose();
- };
-
- const handleClosed = () => {
- storeInstance.setSubscription(undefined);
- };
-
- useEffect(() => {
- if (!filters || filters.length === 0 || !ndk) return;
-
- if (storeInstance.subscriptionRef) {
- storeInstance.subscriptionRef.stop();
- storeInstance.setSubscription(undefined);
- }
-
- const subscription = ndk.subscribe(filters, opts, relaySet, false);
- subscription.on('event', handleEvent);
- subscription.on('eose', handleEose);
- subscription.on('closed', handleClosed);
-
- storeInstance.setSubscription(subscription);
- subscription.start();
-
- return () => {
- if (storeInstance.subscriptionRef) {
- storeInstance.subscriptionRef.stop();
- storeInstance.setSubscription(undefined);
- }
- eventIds.current.clear();
- storeInstance.clearEvents();
- };
- }, [filters, opts, relaySet, ndk]);
-
- return {
- events: storeInstance.events,
- eose: storeInstance.eose,
- isSubscribed: storeInstance.isSubscribed,
- subscription: storeInstance.subscriptionRef,
- };
-};
diff --git a/ndk-mobile/src/hooks/user-profile.ts b/ndk-mobile/src/hooks/user-profile.ts
deleted file mode 100644
index d61ad521..00000000
--- a/ndk-mobile/src/hooks/user-profile.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import { useEffect, useState, useMemo, useCallback, useRef } from 'react'
-import { useNDK } from './ndk'
-
-export function useUserProfile(pubkey: string) {
- const { ndk } = useNDK();
-
- const user = useMemo(() => ndk?.getUser({ pubkey }), [ndk, pubkey]);
-
- const fetchFromCache = useCallback(() => {
- if (!ndk) return null;
-
- const cachedProfile = ndk.cacheAdapter.fetchProfileSync?.(pubkey);
- if (cachedProfile) cachedProfile.pubkey = pubkey;
-
- return cachedProfile;
- }, [ndk, pubkey]);
-
- const [state, setState] = useState(() => {
- if (!ndk || !pubkey) {
- return { userProfile: null, user: null, loading: false, cache: false, pubkey };
- }
-
- const cachedProfile = fetchFromCache();
- return {
- userProfile: cachedProfile,
- user,
- loading: !cachedProfile,
- cache: !!cachedProfile,
- pubkey,
- };
- });
-
- // Use a ref to track the currently active pubkey fetch
- const activePubkeyRef = useRef(pubkey);
-
- useEffect(() => {
- activePubkeyRef.current = pubkey;
-
- if (!ndk || !pubkey) return;
-
- // If the cached profile is already loaded, don't fetch again
- if (state.userProfile && state.userProfile.pubkey === pubkey) return;
-
- const cachedProfile = fetchFromCache();
- if (cachedProfile) {
- setState({
- userProfile: cachedProfile,
- user,
- loading: false,
- cache: true,
- pubkey,
- });
- return; // If we have a cached profile, no need to fetch remotely
- }
-
- setState((prev) => ({ ...prev, loading: true, userProfile: null, cache: false, pubkey }));
-
- const fetchProfile = async () => {
- try {
- const profile = await user?.fetchProfile();
- if (activePubkeyRef.current !== pubkey) {
- return;
- }
- if (profile) profile.pubkey = pubkey;
-
- setState({
- userProfile: profile || null,
- user,
- loading: false,
- cache: false,
- pubkey,
- });
- } catch (error) {
- console.error(`Error fetching user profile for ${pubkey}:`, error);
- if (activePubkeyRef.current === pubkey) {
- setState((prev) => ({ ...prev, loading: false }));
- }
- }
- };
-
- fetchProfile();
- }, [ndk, pubkey, user, fetchFromCache]);
-
- return state;
-}
\ No newline at end of file
diff --git a/ndk-mobile/src/index.ts b/ndk-mobile/src/index.ts
deleted file mode 100644
index 5ac2fc89..00000000
--- a/ndk-mobile/src/index.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import '@bacons/text-decoder/install';
-import 'react-native-get-random-values';
-
-export * from './hooks';
-export * from './context';
-export * from './providers';
-export * from './cache-adapter/sqlite';
-export * from './components';
-
-export * from '@nostr-dev-kit/ndk';
-import NDK from '@nostr-dev-kit/ndk';
-
-export default NDK;
\ No newline at end of file
diff --git a/ndk-mobile/src/providers/index.ts b/ndk-mobile/src/providers/index.ts
deleted file mode 100644
index 4a64a434..00000000
--- a/ndk-mobile/src/providers/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './ndk';
-export * from './session';
\ No newline at end of file
diff --git a/ndk-mobile/src/providers/ndk/index.tsx b/ndk-mobile/src/providers/ndk/index.tsx
deleted file mode 100644
index 811f380a..00000000
--- a/ndk-mobile/src/providers/ndk/index.tsx
+++ /dev/null
@@ -1,118 +0,0 @@
-import React, { PropsWithChildren, useEffect, useRef, useState } from 'react';
-import NDK, { NDKConstructorParams, NDKEvent, NDKSigner, NDKUser } from '@nostr-dev-kit/ndk';
-import 'react-native-get-random-values';
-import '@bacons/text-decoder/install';
-import NDKContext from '../../context/ndk';
-import * as SecureStore from 'expo-secure-store';
-import { withPayload } from './signers';
-
-export interface UnpublishedEventEntry {
- event: NDKEvent;
- relays?: string[];
- lastTryAt?: number;
-}
-
-const NDKProvider = ({
- children,
- connect = true,
- ...opts
-}: PropsWithChildren<
- NDKConstructorParams & {
- connect?: boolean;
- }
->) => {
- const ndk = useRef(new NDK({ ...opts }));
- const [currentUser, setCurrentUser] = useState(null);
- const [unpublishedEvents, setUnpublishedEvents] = useState>(new Map());
- const [cacheInitialized, setCacheInitialized] = useState(opts?.cacheAdapter ? false : null);
-
- if (!ndk.current.cacheAdapter?.ready) {
- ndk.current.cacheAdapter?.onReady(() => {
- setCacheInitialized(true);
- });
- }
-
- useEffect(() => {
- ndk.current.cacheAdapter?.getUnpublishedEvents?.().then((entries) => {
- const e = new Map();
- entries.forEach((entry) => {
- e.set(entry.event.id, entry);
- });
- setUnpublishedEvents(e);
- });
- }, []);
-
- if (connect) {
- ndk.current.connect();
- }
-
- ndk.current.on('event:publish-failed', (event: NDKEvent) => {
- if (unpublishedEvents.has(event.id)) return;
- unpublishedEvents.set(event.id, { event });
- setUnpublishedEvents(unpublishedEvents);
- event.once('published', () => {
- unpublishedEvents.delete(event.id);
- setUnpublishedEvents(unpublishedEvents);
- });
- });
-
- useEffect(() => {
- const storePayload = SecureStore.getItem('key');
-
- if (storePayload) {
- loginWithPayload(storePayload, { save: false });
- }
- }, []);
-
- async function loginWithPayload(payload: string, opts?: { save?: boolean }) {
- const signer = withPayload(ndk.current, payload);
- await login(signer);
- if (!ndk.current.signer) return;
-
- if (opts?.save) {
- SecureStore.setItemAsync('key', payload);
- }
- }
-
- async function login(promise: Promise) {
- promise
- .then((signer) => {
- ndk.current.signer = signer ?? undefined;
-
- if (signer) {
- signer.user().then(setCurrentUser);
- } else {
- setCurrentUser(null);
- }
- })
- .catch((e) => {
- console.log('error in login, removing signer', ndk.current.signer, e);
- ndk.current.signer = undefined;
- });
- }
-
- async function logout() {
- ndk.current.signer = undefined;
-
- setCurrentUser(null);
-
- SecureStore.deleteItemAsync('key');
- }
-
- return (
-
- {children}
-
- );
-};
-
-export { NDKProvider };
diff --git a/ndk-mobile/src/providers/ndk/signers/index.ts b/ndk-mobile/src/providers/ndk/signers/index.ts
deleted file mode 100644
index dd719da0..00000000
--- a/ndk-mobile/src/providers/ndk/signers/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './pk';
-export * from './nip07';
-export * from './nip46';
-export * from './nip55';
diff --git a/ndk-mobile/src/providers/ndk/signers/nip07.ts b/ndk-mobile/src/providers/ndk/signers/nip07.ts
deleted file mode 100644
index 11b58999..00000000
--- a/ndk-mobile/src/providers/ndk/signers/nip07.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { NDKNip07Signer, NDKUser } from '@nostr-dev-kit/ndk';
-
-export async function loginWithNip07() {
- try {
- const signer = new NDKNip07Signer();
- return signer.user().then(async (user: NDKUser) => {
- if (user.npub) {
- return { user: user, npub: user.npub, signer: signer };
- }
- });
- } catch (e) {
- throw e;
- }
-}
diff --git a/ndk-mobile/src/providers/ndk/signers/nip46.ts b/ndk-mobile/src/providers/ndk/signers/nip46.ts
deleted file mode 100644
index 2d0e7a34..00000000
--- a/ndk-mobile/src/providers/ndk/signers/nip46.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import NDK, { NDKPrivateKeySigner, NDKNip46Signer, NDKSigner } from '@nostr-dev-kit/ndk';
-
-export async function withNip46(ndk: NDK, token: string, sk?: string): Promise {
- let localSigner = NDKPrivateKeySigner.generate();
- if (sk) {
- localSigner = new NDKPrivateKeySigner(sk);
- }
-
- const signer = new NDKNip46Signer(ndk, token, localSigner);
-
- return new Promise((resolve, reject) => {
- signer.blockUntilReady().then(() => {
- resolve(signer);
- }).catch(reject);
- });
-}
diff --git a/ndk-mobile/src/providers/ndk/signers/nip55.ts b/ndk-mobile/src/providers/ndk/signers/nip55.ts
deleted file mode 100644
index dfea5bb9..00000000
--- a/ndk-mobile/src/providers/ndk/signers/nip55.ts
+++ /dev/null
@@ -1,324 +0,0 @@
-import debug from "debug";
-
-import {
- type NostrEvent,
- Hexpubkey,
- NDKUser,
- DEFAULT_ENCRYPTION_SCHEME,
- ENCRYPTION_SCHEMES,
- type NDKSigner,
- NDKRelay,
-} from "@nostr-dev-kit/ndk";
-import * as IntentLauncher from "expo-intent-launcher";
-
-type Nip04QueueItem = {
- type: "encrypt" | "decrypt";
- counterpartyHexpubkey: string;
- value: string;
- resolve: (value: string) => void;
- reject: (reason?: Error) => void;
-};
-
-type Nip55RelayMap = {
- [key: string]: {
- read: boolean;
- write: boolean;
- };
-};
-
-/**
- * NDKNip55Signer implements the NDKSigner interface for signing Nostr events
- * with a NIP-55 compatible android mobile client.
- */
-export class NDKNip55Signer implements NDKSigner {
- private _userPromise: Promise | undefined;
- public nip04Queue: Nip04QueueItem[] = [];
- private nip04Processing = false;
- private debug: debug.Debugger;
- private waitTimeout: number;
-
- /**
- * @param waitTimeout - The timeout in milliseconds to wait for the NIP-55 to become available
- */
- public constructor(waitTimeout: number = 1000) {
- this.debug = debug("ndk:nip55");
- this.waitTimeout = waitTimeout;
- }
-
- public async blockUntilReady(): Promise {
- // TODO
- // Set the type to be a Hexpubkey or npub
- let npub = await this.getPublicKey();
-
- // TODO
- // Also add check to to see if an external signer is installed
- if (!npub) {
- // TODO
- // Handle gracefully instead of crashing
- // If unable to obtain pubkey, error out
- throw new Error("Unable to obtain pubkey from external signer");
- }
-
- // TODO
- // Convert npub to hexpubkey if necessary
- // return new NDKUser({ pubkey: pubkey });
- return new NDKUser({ npub: npub });
- }
-
- // TODO
- // Test this method
- /**
- * Getter for the user property.
- * @returns The NDKUser instance.
- */
- public async user(): Promise {
- if (!this._userPromise) {
- this._userPromise = this.blockUntilReady();
- }
-
- return this._userPromise;
- }
-
- // TODO
- // Implement these methods
- /**
- * Signs the given Nostr event.
- * @param event - The Nostr event to be signed.
- * @returns The signature of the signed event.
- * @throws Error if the NIP-07 is not available on the window object.
- */
- public async sign(event: NostrEvent): Promise {
- await this.waitForExtension();
-
- const signedEvent = await window.nostr!.signEvent(event);
- return signedEvent.sig;
- }
-
- // TODO import NDK type, ndk?: NDK
- public async relays(ndk?: any): Promise {
- await this.waitForExtension();
-
- const relays = (await window.nostr!.getRelays?.()) || {};
-
- const activeRelays = [];
- for (const url of Object.keys(relays)) {
- // Currently only respects relays that are both readable and writable.
- if (relays[url].read && relays[url].write) {
- activeRelays.push(url);
- }
- }
- return activeRelays.map((url) => new NDKRelay(url, ndk?.relayAuthDefaultPolicy, ndk));
- }
-
- public async encrypt(
- recipient: NDKUser,
- value: string,
- type: ENCRYPTION_SCHEMES = DEFAULT_ENCRYPTION_SCHEME
- ): Promise {
- if (type === "nip44") {
- return this.nip44Encrypt(recipient, value);
- } else {
- return this.nip04Encrypt(recipient, value);
- }
- }
-
- public async decrypt(
- sender: NDKUser,
- value: string,
- type: ENCRYPTION_SCHEMES = DEFAULT_ENCRYPTION_SCHEME
- ): Promise {
- if (type === "nip44") {
- return this.nip44Decrypt(sender, value);
- } else {
- return this.nip04Decrypt(sender, value);
- }
- }
-
- public async nip44Encrypt(recipient: NDKUser, value: string): Promise {
- await this.waitForExtension();
- return await this.nip44.encrypt(recipient.pubkey, value);
- }
-
- get nip44(): Nip44 {
- if (!window.nostr?.nip44) {
- throw new Error("NIP-44 not supported by your browser extension");
- }
-
- return window.nostr.nip44;
- }
-
- public async nip44Decrypt(sender: NDKUser, value: string): Promise {
- await this.waitForExtension();
- return await this.nip44.decrypt(sender.pubkey, value);
- }
-
- public async nip04Encrypt(recipient: NDKUser, value: string): Promise {
- await this.waitForExtension();
-
- const recipientHexPubKey = recipient.pubkey;
- return this.queueNip04("encrypt", recipientHexPubKey, value);
- }
-
- public async nip04Decrypt(sender: NDKUser, value: string): Promise {
- await this.waitForExtension();
-
- const senderHexPubKey = sender.pubkey;
- return this.queueNip04("decrypt", senderHexPubKey, value);
- }
-
- private async queueNip04(
- type: "encrypt" | "decrypt",
- counterpartyHexpubkey: string,
- value: string
- ): Promise {
- return new Promise((resolve, reject) => {
- this.nip04Queue.push({
- type,
- counterpartyHexpubkey,
- value,
- resolve,
- reject,
- });
-
- if (!this.nip04Processing) {
- this.processNip04Queue();
- }
- });
- }
-
- private async processNip04Queue(item?: Nip04QueueItem, retries = 0): Promise {
- if (!item && this.nip04Queue.length === 0) {
- this.nip04Processing = false;
- return;
- }
-
- this.nip04Processing = true;
- const { type, counterpartyHexpubkey, value, resolve, reject } =
- item || this.nip04Queue.shift()!;
-
- try {
- let result;
-
- if (type === "encrypt") {
- result = await window.nostr!.nip04!.encrypt(counterpartyHexpubkey, value);
- } else {
- result = await window.nostr!.nip04!.decrypt(counterpartyHexpubkey, value);
- }
-
- resolve(result);
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- } catch (error: any) {
- // retry a few times if the call is already executing
- if (error.message && error.message.includes("call already executing")) {
- if (retries < 5) {
- this.debug("Retrying encryption queue item", {
- type,
- counterpartyHexpubkey,
- value,
- retries,
- });
- setTimeout(() => {
- this.processNip04Queue(item, retries + 1);
- }, 50 * retries);
-
- return;
- }
- }
- reject(error);
- }
-
- this.processNip04Queue();
- }
-
- private waitForExtension(): Promise {
- return new Promise((resolve, reject) => {
- if (window.nostr) {
- resolve();
- return;
- }
-
- let timerId: NodeJS.Timeout | number;
-
- // Create an interval to repeatedly check for window.nostr
- const intervalId = setInterval(() => {
- if (window.nostr) {
- clearTimeout(timerId as number);
- clearInterval(intervalId);
- resolve();
- }
- }, 100);
-
- // Set a timer to reject the promise if window.nostr is not available within the timeout
- timerId = setTimeout(() => {
- clearInterval(intervalId);
- reject(new Error("NIP-07 extension not available"));
- }, this.waitTimeout);
- });
- }
-
- // TODO
- // Add timeout like in the waitForExtension
- // Update string type to be hexpubkey
- private async getPublicKey(): Promise {
- try {
- const permissions = [
- { permission: "sign_event", id: 22242 },
- { permission: "nip04_encrypt" },
- { permission: "nip04_decrypt" },
- { permission: "nip44_encrypt" },
- { permission: "nip44_decrypt" },
- { permission: "decrypt_zap_event" },
- ];
-
- const result = await IntentLauncher.startActivityAsync("android.intent.action.VIEW", {
- category: "android.intent.category.BROWSABLE",
- data: "nostrsigner:",
- extra: {
- package: "com.greenart7c3.nostrsigner", // TODO Detect and specify a general app package
- permissions: JSON.stringify(permissions),
- type: "get_public_key",
- },
- });
-
- // TODO
- // Handle Canceled, Error, and maybe FirstUser results from expo-intent-launcher
- // If the result was successful, handle the response
- if (result.resultCode === -1) {
- const resultExtraObj = result.extra;
- console.log("Signer result:", resultExtraObj);
- // TODO
- // Fix this by defining a type
- // @ts-ignore
- return resultExtraObj.result;
- } else {
- // If the result code indicates the user rejected the request
- console.log("Sign request rejected");
- return "";
- }
- } catch (error) {
- // If there is an error launching the intent, handle the failure
- console.error("Error getting the public key:", error);
- return "";
- }
- }
-}
-
-type Nip44 = {
- encrypt: (recipient: Hexpubkey, value: string) => Promise;
- decrypt: (sender: Hexpubkey, value: string) => Promise;
-};
-
-declare global {
- interface Window {
- nostr?: {
- getPublicKey(): Promise;
- signEvent(event: NostrEvent): Promise<{ sig: string }>;
- getRelays?: () => Promise;
- nip04?: {
- encrypt(recipientHexPubKey: string, value: string): Promise;
- decrypt(senderHexPubKey: string, value: string): Promise;
- };
- nip44?: Nip44;
- };
- }
-}
diff --git a/ndk-mobile/src/providers/ndk/signers/pk.ts b/ndk-mobile/src/providers/ndk/signers/pk.ts
deleted file mode 100644
index cab9bfa5..00000000
--- a/ndk-mobile/src/providers/ndk/signers/pk.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import NDK, { NDKNip46Signer, NDKPrivateKeySigner, NDKSigner, NDKUser } from '@nostr-dev-kit/ndk';
-import { withNip46 } from './nip46';
-
-export async function withPrivateKey(key: string): Promise {
- return new NDKPrivateKeySigner(key);
-}
-
-export async function withPayload(ndk: NDK, payload: string): Promise {
- if (payload.startsWith('nsec1')) return withPrivateKey(payload);
-
- return withNip46(ndk, payload);
-}
diff --git a/ndk-mobile/src/providers/session/index.tsx b/ndk-mobile/src/providers/session/index.tsx
deleted file mode 100644
index 3ebec72a..00000000
--- a/ndk-mobile/src/providers/session/index.tsx
+++ /dev/null
@@ -1,273 +0,0 @@
-import React from 'react';
-import NDKSessionContext from '../../context/session';
-import { NDKEventWithFrom } from '../../hooks';
-import { useNDK } from '../../hooks/ndk';
-import NDK, { NDKEvent, NDKEventId, NDKFilter, NDKKind, NDKRelay, NDKSubscription, NDKSubscriptionCacheUsage, NostrEvent } from '@nostr-dev-kit/ndk';
-import { PropsWithChildren, useEffect } from 'react';
-import { useSessionStore } from '../../stores/session';
-import { NDKCashuWallet, NDKNutzapMonitor, NDKNWCWallet, NDKWallet, NDKWalletTypes } from '@nostr-dev-kit/ndk-wallet';
-import { useWalletStore } from '../../stores/wallet';
-
-type SettingsStore = {
- get: (key: string) => Promise;
- set: (key: string, value: string) => Promise;
- delete: (key: string) => Promise;
-}
-
-/**
- * Options for the NDKSessionProvider
- *
- * @param follows - Whether to subscribe to follow events
- * @param muteList - Whether to subscribe to mute list events
- * @param wallet - Whether to subscribe to wallet events
- * @param settingsStore - A store for storing and retrieving configuration values
- * @param kinds - A map of kinds to wrap with a custom wrapper
- */
-interface NDKSessionProviderProps {
- follows?: boolean;
- muteList?: boolean;
- wallet?: boolean
- settingsStore?: SettingsStore;
- kinds?: Map }>;
-}
-
-const NDKSessionProvider = ({ children, ...opts }: PropsWithChildren) => {
- const { ndk, currentUser } = useNDK();
- const { setFollows, setMuteList, addEvent } = useSessionStore();
- const walletStore = useWalletStore();
- let sub: NDKSubscription | undefined;
- let knownEventIds = new Set();
- let followEvent: NDKEvent | undefined;
- const balances = useWalletStore((state) => state.balances);
- const setBalances = useWalletStore((state) => state.setBalances);
- const setNutzapMonitor = useWalletStore((state) => state.setNutzapMonitor);
- const processFollowEvent = (event: NDKEvent, relay: NDKRelay) => {
- if (followEvent && followEvent.created_at! > event.created_at!) return;
-
- const pubkeys = new Set(event.tags.filter((tag) => tag[0] === 'p' && !!tag[1]).map((tag) => tag[1]));
- setFollows(Array.from(pubkeys));
- followEvent = event;
- };
-
- const processMuteListEvent = (event: NDKEvent, relay: NDKRelay) => {
- setMuteList(event);
- };
-
- const processCashuWalletEvent = (event: NDKEvent) => {
- addEvent(NDKKind.CashuWallet, event);
- };
-
- const handleEvent = (event: NDKEvent, relay: NDKRelay) => {
- if (knownEventIds.has(event.id)) return;
- knownEventIds.add(event.id);
- const kind = event.kind!;
-
- switch (kind) {
- case 3:
- return processFollowEvent(event, relay);
- case NDKKind.MuteList:
- return processMuteListEvent(event, relay);
- case NDKKind.CashuWallet:
- return processCashuWalletEvent(event);
- default:
- const entry = opts.kinds!.get(kind);
- if (entry?.wrapper) {
- event = entry.wrapper.from(event);
- }
- addEvent(kind, event);
- }
- };
-
- /**
- * Set the active wallet
- * @param wallet - The wallet to set
- * @param save - Whether to store this setting locally
- */
- const setActiveWallet = (
- wallet: NDKWallet,
- save = true
- ) => {
- ndk.wallet = wallet;
-
- const updateBalance = () => {
- if (!wallet) return;
- console.log('Updating balance from balance_updated event')
- setBalances(wallet.balance());
- }
-
- if (wallet) {
- wallet.on("ready", () => {
- console.log('Updating balance from ready event')
- setBalances(wallet.balance());
- });
-
- wallet.on('balance_updated', () => {
- updateBalance();
- });
-
- if (wallet instanceof NDKCashuWallet) {
- wallet.start({
- cacheUsage: NDKSubscriptionCacheUsage.ONLY_RELAY
- });
- const monitor = new NDKNutzapMonitor(ndk, currentUser);
- monitor.addWallet(wallet);
- monitor.on('seen', (zap) => {
- console.log('zap seen', zap.rawEvent());
- });
- monitor.on('redeem', (zap) => {
- console.log('zap redeemed', zap.rawEvent());
- });
- setNutzapMonitor(monitor);
-
- monitor.start();
- }
- }
-
- walletStore.setActiveWallet(wallet);
- if (wallet) updateBalance();
- else {
- setBalances([]);
- }
-
- if (save && opts.settingsStore) {
- persistWalletConfiguration(wallet, opts.settingsStore);
- }
- }
-
- useEffect(() => {
- if (!ndk || !currentUser) return;
- if (sub) {
- sub.stop();
- }
-
- let filters: NDKFilter[] = [];
-
- filters.push({ kinds: [], authors: [currentUser.pubkey] });
-
- if (opts.follows) filters[0].kinds!.push(3);
- if (opts.muteList) filters[0].kinds!.push(NDKKind.MuteList);
- if (opts.wallet) filters[0].kinds!.push(NDKKind.CashuWallet);
- if (opts.kinds) filters[0].kinds!.push(...opts.kinds.keys());
-
- if (opts.settingsStore && !ndk.wallet) {
- loadWallet(ndk, opts.settingsStore, (wallet) => setActiveWallet(wallet, false));
- }
-
- if (filters[0].kinds!.length > 0) {
- sub = ndk.subscribe(filters, { closeOnEose: false }, undefined, false);
- sub.on('event', handleEvent);
- sub.start();
- }
- }, [ndk, opts.follows, opts.muteList, opts.settingsStore, currentUser]);
-
- return (
- state.follows),
- events: useSessionStore((state) => state.events),
- muteList: useSessionStore((state) => state.muteList),
- mutePubkey: useSessionStore((state) => state.mutePubkey),
- ...walletStore,
- balances,
- setActiveWallet
- }}>
- {children}
-
- );
-};
-
-function walletPayload(wallet: NDKWallet) {
- if (wallet instanceof NDKNWCWallet) {
- return wallet.pairingCode;
- } else if (wallet instanceof NDKCashuWallet) {
- return wallet.event.rawEvent();
- }
-}
-
-/**
- * Persist the wallet configuration
- * @param wallet - The wallet to persist
- * @param settingsStore - The settings store to use
- */
-function persistWalletConfiguration(wallet: NDKWallet, settingsStore: SettingsStore) {
- if (!wallet) {
- settingsStore.delete('wallet');
- return;
- }
-
- const payload = walletPayload(wallet);
- if (!payload) {
- alert('Failed to persist wallet configuration!');
- return;
- }
-
- const type = wallet.type;
- settingsStore.set('wallet', JSON.stringify({ type, payload }));
-}
-
-async function loadWallet(ndk: NDK, settingsStore: SettingsStore, setActiveWallet: (wallet: NDKWallet | null) => void) {
- const walletConfig = await settingsStore.get('wallet');
- if (!walletConfig) return;
-
- const loadNWCWallet = (pairingCode: string) => {
- const wallet = new NDKNWCWallet(ndk);
- wallet.initWithPairingCode(pairingCode).then(() => {
- setActiveWallet(wallet);
- });
- }
-
- const loadNIP60Wallet = async (payload: NostrEvent) => {
- try {
- // Load the cached event
- const event = new NDKEvent(ndk, payload);
- const wallet = await NDKCashuWallet.from(event);
- setActiveWallet(wallet);
-
- const relaySet = wallet.relaySet;
-
- // Load remotely
- const freshEvent = await ndk.fetchEvent(event.encode(), { cacheUsage: NDKSubscriptionCacheUsage.ONLY_RELAY }, relaySet);
- if (!freshEvent) {
- console.log("Refreshing the event came back empty, has the wallet been deleted?")
- setActiveWallet(null);
- return null;
- }
-
- if (freshEvent.hasTag('deleted')) {
- alert('This wallet has been deleted');
- setActiveWallet(null);
- return null;
- } else if (freshEvent.created_at! > event.created_at!) {
- const wallet = await NDKCashuWallet.from(freshEvent);
- alert('This wallet has been updated');
- setActiveWallet(wallet);
-
- // update the cache
- persistWalletConfiguration(wallet, settingsStore);
-
- return wallet;
- }
-
- return wallet;
- } catch (e) {
- console.error('Error activating wallet', e);
- console.log(payload)
- }
- }
-
- try {
- const { type, payload } = JSON.parse(walletConfig);
- if (type === 'nwc') {
- loadNWCWallet(payload);
- } else if (type === 'nip-60') {
- loadNIP60Wallet(payload);
- } else {
- alert('Unknown wallet type: ' + type);
- }
- } catch (e) {
- alert('Failed to load wallet configuration');
- settingsStore.delete('wallet');
- }
-}
-
-export { NDKSessionProvider };
diff --git a/ndk-mobile/src/stores/session.ts b/ndk-mobile/src/stores/session.ts
deleted file mode 100644
index 897d03f3..00000000
--- a/ndk-mobile/src/stores/session.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-import { create } from 'zustand'
-import { NDKEvent, NDKKind, Hexpubkey, NDKList } from '@nostr-dev-kit/ndk'
-
-interface SessionState {
- follows: string[] | undefined
- muteListEvent: NDKEvent | undefined
- muteList: Set
- events: Map
-
- setFollows: (follows: string[]) => void
- setMuteList: (muteList: NDKEvent) => void
- setEvents: (kind: NDKKind, events: NDKEvent[]) => void
- mutePubkey: (pubkey: Hexpubkey) => void
-
- addEvent: (kind: NDKKind, event: NDKEvent) => void
-}
-
-export const useSessionStore = create((set) => ({
- follows: undefined,
-
- muteList: new Set(),
- muteListEvent: undefined,
- mutePubkey: (pubkey: Hexpubkey) => set((state) => {
- state.muteList.add(pubkey);
- console.log('muting user', pubkey);
- if (state.muteListEvent) {
- console.log('publishing mute list event');
- state.muteListEvent.tags.push(['p', pubkey]);
- state.muteListEvent.publishReplaceable();
- } else {
- console.log('no mute list event, creating one');
- }
- return state;
- }),
-
- events: new Map(),
- setFollows: (follows) => set({ follows }),
- setMuteList: (muteList: NDKEvent) => {
- set((state) => {
- console.log('setting mute list', muteList.created_at, state.muteListEvent?.created_at);
- if (state.muteListEvent && state.muteListEvent.created_at >= muteList.created_at) {
- return state
- }
-
- const pubkeys = new Set(muteList.tags.filter((tag) => tag[0] === 'p' && !!tag[1]).map((tag) => tag[1]));
- console.log('have a mute list of ', pubkeys.size, 'users');
- return { muteList: pubkeys, muteListEvent: NDKList.from(muteList) }
- })
- },
- setEvents: (kind, events) => set((state) => {
- const newEvents = new Map(state.events)
- newEvents.set(kind, events)
- return { events: newEvents }
- }),
- addEvent: (kind, event) => set((state) => {
- const newEvents = new Map(state.events)
- let existing = newEvents.get(kind) || []
-
- // safety check for replaceable events
- if (event.isReplaceable()) {
- const existingEvent = existing.find((e) => e.dTag === event.dTag)
- if (existingEvent) {
- if (existingEvent.created_at >= event.created_at) {
- return state
- } else {
- // remove the existing event
- existing = existing.filter((e) => e.id !== existingEvent.id)
- }
- }
- }
-
- newEvents.set(kind, [...existing, event])
- return { events: newEvents }
- })
-}))
diff --git a/ndk-mobile/src/stores/wallet.ts b/ndk-mobile/src/stores/wallet.ts
deleted file mode 100644
index cdc8cdb9..00000000
--- a/ndk-mobile/src/stores/wallet.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { NDKNutzapMonitor, NDKWallet, NDKWalletBalance } from "@nostr-dev-kit/ndk-wallet"
-import { create } from "zustand"
-
-interface WalletState {
- activeWallet: NDKWallet | undefined
- setActiveWallet: (wallet: NDKWallet) => void
-
- balances: NDKWalletBalance[],
- setBalances: (balances: NDKWalletBalance[]) => void
-
- nutzapMonitor: NDKNutzapMonitor | undefined
- setNutzapMonitor: (monitor: NDKNutzapMonitor) => void
-}
-
-export const useWalletStore = create((set) => ({
- activeWallet: undefined,
- setActiveWallet: (wallet: NDKWallet) => set({ activeWallet: wallet }),
-
- balances: [],
- setBalances: (balances) => {
- console.log('Setting balances to:', balances);
- set({ balances });
- },
-
- nutzapMonitor: undefined,
- setNutzapMonitor: (monitor: NDKNutzapMonitor) => set({ nutzapMonitor: monitor }),
-}))
\ No newline at end of file
diff --git a/ndk-mobile/tsconfig.json b/ndk-mobile/tsconfig.json
deleted file mode 100644
index 1e6152b0..00000000
--- a/ndk-mobile/tsconfig.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "compilerOptions": {
- "types": ["node", "react-native"],
- "target": "esnext",
- "skipLibCheck": true,
- "module": "commonjs",
- "strict": false,
- "jsx": "react",
- "declaration": true,
- "esModuleInterop": true
- },
- "include": ["src/**/*.ts", "src/**/*.tsx"],
- "exclude": ["node_modules"],
- "paths": {
- "@/*": ["src/*"]
- }
-}
diff --git a/ndk-svelte-components/.eslintrc.cjs b/ndk-svelte-components/.eslintrc.cjs
deleted file mode 100644
index 64aacdc8..00000000
--- a/ndk-svelte-components/.eslintrc.cjs
+++ /dev/null
@@ -1,32 +0,0 @@
-module.exports = {
- root: true,
- extends: [
- "eslint:recommended",
- "plugin:@typescript-eslint/recommended",
- "plugin:svelte/recommended",
- "prettier",
- "plugin:storybook/recommended",
- ],
- parser: "@typescript-eslint/parser",
- plugins: ["@typescript-eslint"],
- parserOptions: {
- sourceType: "module",
- ecmaVersion: 2020,
- extraFileExtensions: [".svelte"],
- },
- env: {
- browser: true,
- es2017: true,
- node: true,
- },
- overrides: [
- {
- files: ["*.svelte"],
- parser: "svelte-eslint-parser",
- parserOptions: {
- parser: "@typescript-eslint/parser",
- },
- },
- ],
- ignorePatterns: ["dist/", ".storybook/"],
-};
diff --git a/ndk-svelte-components/.gitignore b/ndk-svelte-components/.gitignore
deleted file mode 100644
index 5dbd1b22..00000000
--- a/ndk-svelte-components/.gitignore
+++ /dev/null
@@ -1,14 +0,0 @@
-.DS_Store
-node_modules
-**/build
-**/dist
-**/.svelte-kit
-**/package
-.env
-.env.*
-!.env.example
-vite.config.js.timestamp-*
-vite.config.ts.timestamp-*
-pnpm-lock.yaml
-justfile
-storybook-static
diff --git a/ndk-svelte-components/.npmrc b/ndk-svelte-components/.npmrc
deleted file mode 100644
index 4045e675..00000000
--- a/ndk-svelte-components/.npmrc
+++ /dev/null
@@ -1,5 +0,0 @@
-engine-strict=true
-resolution-mode=highest
-uto-install-peers=true
-legacy-peer-deps=true
-node-linker=hoisted
\ No newline at end of file
diff --git a/ndk-svelte-components/.prettierignore b/ndk-svelte-components/.prettierignore
deleted file mode 100644
index 4af38e24..00000000
--- a/ndk-svelte-components/.prettierignore
+++ /dev/null
@@ -1,3 +0,0 @@
-dist
-.svelte-kit
-.storybook
diff --git a/ndk-svelte-components/.storybook/main.ts b/ndk-svelte-components/.storybook/main.ts
deleted file mode 100644
index 61ac19bc..00000000
--- a/ndk-svelte-components/.storybook/main.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import type { StorybookConfig } from "@storybook/sveltekit";
-import { join, dirname } from "path";
-
-/**
- * This function is used to resolve the absolute path of a package.
- * It is needed in projects that use Yarn PnP or are set up within a monorepo.
- */
-function getAbsolutePath(value: string): any {
- return dirname(require.resolve(join(value, "package.json")));
-}
-const config: StorybookConfig = {
- stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
- addons: [
- getAbsolutePath("@storybook/addon-links"),
- getAbsolutePath("@storybook/addon-essentials"),
- getAbsolutePath("@storybook/addon-interactions"),
- getAbsolutePath("@storybook/addon-mdx-gfm"),
- ],
- framework: {
- name: "@storybook/sveltekit",
- },
- docs: {
- autodocs: "tag",
- },
-};
-export default config;
diff --git a/ndk-svelte-components/.storybook/preview.ts b/ndk-svelte-components/.storybook/preview.ts
deleted file mode 100644
index 999117f3..00000000
--- a/ndk-svelte-components/.storybook/preview.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import type { Preview } from "@storybook/svelte";
-import "../src/styles/global.css";
-
-const preview: Preview = {
- parameters: {
- actions: { argTypesRegex: "^on[A-Z].*" },
- controls: {
- matchers: {
- color: /(background|color)$/i,
- date: /Date$/,
- },
- },
- },
-};
-
-export default preview;
diff --git a/ndk-svelte-components/CHANGELOG.md b/ndk-svelte-components/CHANGELOG.md
deleted file mode 100644
index 3fb07a64..00000000
--- a/ndk-svelte-components/CHANGELOG.md
+++ /dev/null
@@ -1,380 +0,0 @@
-# @nostr-dev-kit/ndk-svelte-components
-
-## 2.3.5
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.7
-
-## 2.3.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.6
-
-## 2.3.3
-
-### Patch Changes
-
-- Updated dependencies [5939a3e]
-- Updated dependencies
-- Updated dependencies [f2a0cce]
- - @nostr-dev-kit/ndk@2.10.5
-
-## 2.3.2
-
-### Patch Changes
-
-- Updated dependencies [5bed70c]
-- Updated dependencies [873ad4a]
- - @nostr-dev-kit/ndk@2.10.4
-
-## 2.3.1
-
-### Patch Changes
-
-- Updated dependencies [0fc66c5]
- - @nostr-dev-kit/ndk@2.10.3
-
-## 2.3.0
-
-### Minor Changes
-
-- Refactor how markdown parsing is done to use a more modular approach with user-supplied svelte component rendering support
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.2
-
-## 2.2.20
-
-### Patch Changes
-
-- 5ac3ce8: use urlFactory to generate URLs on rendering engine
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [722345b]
- - @nostr-dev-kit/ndk@2.10.1
-
-## 2.2.19
-
-### Patch Changes
-
-- Updated dependencies [ec83ddc]
-- Updated dependencies [18c55bb]
-- Updated dependencies
-- Updated dependencies [18c55bb]
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies [3029124]
- - @nostr-dev-kit/ndk@2.10.0
-
-## 2.2.18
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.9.1
-
-## 2.2.17
-
-### Patch Changes
-
-- 548f4d8: add optimistic updates
-- Updated dependencies [94018b4]
-- Updated dependencies [548f4d8]
- - @nostr-dev-kit/ndk@2.9.0
-
-## 2.2.16
-
-### Patch Changes
-
-- Updated dependencies [0af033f]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.8.2
-
-## 2.2.15
-
-### Patch Changes
-
-- Updated dependencies [e40312b]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.8.1
-
-## 2.2.14
-
-### Patch Changes
-
-- truncate npub by default
-- 1e854f7: better event content rendering and mentions
-- Updated dependencies [91d873c]
-- Updated dependencies [6fd9ddc]
-- Updated dependencies [0b8f331]
-- Updated dependencies
-- Updated dependencies [f2898ad]
-- Updated dependencies [9b92cd9]
-- Updated dependencies
-- Updated dependencies [6814f0c]
-- Updated dependencies [89b5b3f]
-- Updated dependencies [9b92cd9]
-- Updated dependencies [27b10cc]
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies [ed7cdc4]
- - @nostr-dev-kit/ndk@2.8.0
-
-## 2.2.13
-
-### Patch Changes
-
-- fix display of markdown
-
-## 2.2.12
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.7.1
-
-## 2.2.11
-
-### Patch Changes
-
-- improve markdown rendering
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.7.0
-
-## 2.2.10
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.6.1
-
-## 2.2.9
-
-### Patch Changes
-
-- c2db3c1: Add Delete to EventCardDropdownMenu
-- Updated dependencies
-- Updated dependencies [c2db3c1]
-- Updated dependencies
-- Updated dependencies [c2db3c1]
-- Updated dependencies [c2db3c1]
- - @nostr-dev-kit/ndk@2.6.0
-
-## 2.2.8
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.5.1
-
-## 2.2.7
-
-### Patch Changes
-
-- Updated dependencies [e08fc74]
- - @nostr-dev-kit/ndk@2.5.0
-
-## 2.2.6
-
-### Patch Changes
-
-- 55011e3: fix rendering issues on RelayList
-- Updated dependencies [111c1ea]
-- Updated dependencies [5c0ae51]
-- Updated dependencies [6f5ea49]
-- Updated dependencies [3738d39]
-- Updated dependencies [d22239a]
- - @nostr-dev-kit/ndk@2.4.1
-
-## 2.2.5
-
-### Patch Changes
-
-- Updated dependencies [b9bbf1d]
- - @nostr-dev-kit/ndk@2.4.0
-
-## 2.2.4
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [885b6c2]
-- Updated dependencies [5666d56]
- - @nostr-dev-kit/ndk@2.3.3
-
-## 2.2.3
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [4628481]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.3.2
-
-## 2.2.2
-
-### Patch Changes
-
-- Updated dependencies [ece965f]
- - @nostr-dev-kit/ndk@2.3.1
-
-## 2.2.1
-
-### Patch Changes
-
-- Updated dependencies [54cec78]
-- Updated dependencies [ef61d83]
-- Updated dependencies [98b77dd]
-- Updated dependencies [46b0c77]
-- Updated dependencies [082e243]
- - @nostr-dev-kit/ndk@2.3.0
-
-## 2.1.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.2.0
-
-## 2.1.1
-
-### Patch Changes
-
-- 3bcbb59: allow Avatar and Name to work without an ndk instance
-- Updated dependencies [180d774]
-- Updated dependencies [7f00c40]
- - @nostr-dev-kit/ndk@2.1.3
-
-## 2.1.0
-
-### Minor Changes
-
-- Improve how multiple media images can be handled
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.2
-
-## 2.0.8
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.1
-
-## 2.0.7
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.0
-
-## 2.0.6
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.6
-
-## 2.0.5
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [d45d962]
- - @nostr-dev-kit/ndk@2.0.5
-
-## 2.0.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.4
-
-## 2.0.3
-
-### Patch Changes
-
-- 375e62f: Display NIP-23 titles
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.3
-
-## 2.0.2
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.2
-
-## 1.4.2
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.0
-
-## 1.4.1
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.2
-
-## 1.4.0
-
-### Minor Changes
-
-- New EventThread component to finally and easily properly display threads and replies.
-
-## 1.3.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.1
-
-## 1.3.3
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.0
-
-## 1.3.2
-
-### Patch Changes
-
-- Updated dependencies [b3561af]
- - @nostr-dev-kit/ndk@1.3.2
-
-## 1.3.1
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.3.1
-
-## 1.2.4
-
-### Patch Changes
-
-- Updated dependencies [88df10a]
-- Updated dependencies [c225094]
-- Updated dependencies [cf4a648]
-- Updated dependencies [3946078]
-- Updated dependencies [3440768]
- - @nostr-dev-kit/ndk@1.3.0
diff --git a/ndk-svelte-components/LICENSE b/ndk-svelte-components/LICENSE
deleted file mode 100644
index 2a6ea523..00000000
--- a/ndk-svelte-components/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2023 Pablo Fernandez
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/ndk-svelte-components/README.md b/ndk-svelte-components/README.md
deleted file mode 100644
index 6ae8fcec..00000000
--- a/ndk-svelte-components/README.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# ndk-svelte-components
-
-Reusable Svelte components.
-
-## Installation
-
-```
-# With npm
-npm add @nostr-dev-kit/ndk-svelte-components
-
-# With pnpm
-pnpm add @nostr-dev-kit/ndk-svelte-components
-
-# With yarn
-yarn install @nostr-dev-kit/ndk-svelte-components
-```
-
-## Storybook
-
-This project uses `pnpm` to manage dependencies.
-
-```
-git clone https://github.com/nostr-dev-kit/ndk-svelte-components
-cd ndk-svelte-components
-pnpm i
-pnpm run storybook
-```
-
-# Components
-
-## Event
-
-### ``
-
-Displays a card with formatted event content.
-
-### ``
-
-Formats the content of an event for an `EventCard`. Currently supports:
-
-- kind 1 events
-- Embedded kind 1 events in other kind 1 events
-
-## User
-
-### ``
-
-Displays a user's avatar
-
-### ``
-
-Displays a user's name
-
-## Relay
-
-### ` `
-
-Displays a list of relays the NDK instance is connected to, along with information about active subscriptions and connectivity stats.
-
-![](images/relay-list.png)
-
-# License
-
-MIT
-
-# Author
-
-- pablof7z ([npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft](https://primal.net/pablof7z))
-- jeffg ([npub1zuuajd7u3sx8xu92yav9jwxpr839cs0kc3q6t56vd5u9q033xmhsk6c2uc](https://primal.net/jeffg))
diff --git a/ndk-svelte-components/images/relay-list.png b/ndk-svelte-components/images/relay-list.png
deleted file mode 100644
index 4151551a..00000000
Binary files a/ndk-svelte-components/images/relay-list.png and /dev/null differ
diff --git a/ndk-svelte-components/package.json b/ndk-svelte-components/package.json
deleted file mode 100644
index 5f1e26f8..00000000
--- a/ndk-svelte-components/package.json
+++ /dev/null
@@ -1,97 +0,0 @@
-{
- "name": "@nostr-dev-kit/ndk-svelte-components",
- "version": "2.3.5",
- "description": "",
- "license": "MIT",
- "type": "module",
- "svelte": "./dist/index.js",
- "types": "./dist/index.d.ts",
- "exports": {
- ".": {
- "types": "./dist/index.d.ts",
- "svelte": "./dist/index.js"
- }
- },
- "files": [
- "dist",
- "!dist/**/*.test.*",
- "!dist/**/*.spec.*"
- ],
- "scripts": {
- "dev": "vite build --watch",
- "build": "vite build && pnpm run package",
- "preview": "vite preview",
- "package": "svelte-kit sync && svelte-package && publint",
- "prepublishOnly": "pnpm run package",
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
- "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
- "lint": "prettier --check . && eslint .",
- "format": "prettier --write .",
- "storybook": "storybook dev -p 6006",
- "build-storybook": "storybook build"
- },
- "devDependencies": {
- "@nostr-dev-kit/eslint-config-custom": "workspace:*",
- "@nostr-dev-kit/ndk-cache-dexie": "workspace:*",
- "@nostr-dev-kit/ndk-svelte": "workspace:*",
- "@nostr-dev-kit/tailwind-config": "workspace:*",
- "@nostr-dev-kit/tsconfig": "workspace:*",
- "@storybook/addon-essentials": "^7.6.20",
- "@storybook/addon-interactions": "^7.6.20",
- "@storybook/addon-links": "^7.6.20",
- "@storybook/addon-mdx-gfm": "^7.6.20",
- "@storybook/blocks": "^7.6.20",
- "@storybook/cli": "^7.6.20",
- "@storybook/manager-api": "^7.6.20",
- "@storybook/svelte": "^7.6.20",
- "@storybook/sveltekit": "^7.6.20",
- "@storybook/testing-library": "^0.2.2",
- "@storybook/theming": "^7.6.20",
- "@sveltejs/adapter-auto": "^2.1.1",
- "@sveltejs/kit": "^2.6.4",
- "@sveltejs/package": "^2.3.5",
- "@types/ramda": "^0.29.12",
- "@types/sanitize-html": "^2.13.0",
- "@typescript-eslint/eslint-plugin": "^6.21.0",
- "@typescript-eslint/parser": "^6.21.0",
- "autoprefixer": "^10.4.20",
- "eslint-plugin-storybook": "0.6.14",
- "mdsvex": "^0.12.3",
- "postcss": "^8.4.47",
- "prettier": "^3.3.3",
- "prettier-plugin-svelte": "^3.2.6",
- "publint": "^0.2.11",
- "react": "^18.3.1",
- "react-dom": "^18.3.1",
- "storybook": "^7.6.20",
- "svelte": "^4.2.19",
- "svelte-check": "^4.0.4",
- "tailwindcss": "^3.4.12",
- "tslib": "^2.7.0",
- "vite": "^5.4.8"
- },
- "dependencies": {
- "@nostr-dev-kit/ndk": "workspace:*",
- "@sveltejs/vite-plugin-svelte": "^3.1.2",
- "classnames": "^2.5.1",
- "lucide-svelte": "^0.451.0",
- "marked": "^14.1.2",
- "marked-footnote": "^1.2.4",
- "marked-gfm-heading-id": "^4.1.0",
- "marked-mangle": "^1.1.9",
- "nostr-tools": "^2.7.2",
- "ramda": "^0.29.1",
- "rehype-autolink-headings": "^7.1.0",
- "rehype-slug": "^6.0.0",
- "sanitize-html": "^2.13.0",
- "svelte-markdown": "^0.4.1",
- "svelte-preprocess": "^5.1.4",
- "svelte-time": "^0.9.0"
- },
- "peerDependencies": {
- "svelte": "^4.2.0"
- },
- "publishConfig": {
- "access": "public"
- }
-}
diff --git a/ndk-svelte-components/postcss.config.cjs b/ndk-svelte-components/postcss.config.cjs
deleted file mode 100644
index 307e497d..00000000
--- a/ndk-svelte-components/postcss.config.cjs
+++ /dev/null
@@ -1,7 +0,0 @@
-module.exports = {
- plugins: {
- "tailwindcss/nesting": {},
- tailwindcss: {},
- autoprefixer: {},
- },
-};
diff --git a/ndk-svelte-components/src/app.html b/ndk-svelte-components/src/app.html
deleted file mode 100644
index b50d0a54..00000000
--- a/ndk-svelte-components/src/app.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
- %sveltekit.head%
-
-
-
-
- %sveltekit.body%
-
-
diff --git a/ndk-svelte-components/src/lib/event/ElementConnector.svelte b/ndk-svelte-components/src/lib/event/ElementConnector.svelte
deleted file mode 100644
index fbf79733..00000000
--- a/ndk-svelte-components/src/lib/event/ElementConnector.svelte
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/ndk-svelte-components/src/lib/event/EventCard.svelte b/ndk-svelte-components/src/lib/event/EventCard.svelte
deleted file mode 100644
index 34cd04fa..00000000
--- a/ndk-svelte-components/src/lib/event/EventCard.svelte
+++ /dev/null
@@ -1,109 +0,0 @@
-
-
-{#await eventPromise then}
-
-
- {#if !$$slots.default}
-
- {:else}
-
- {/if}
-
-{:catch error}
-
-{/await}
-
-
diff --git a/ndk-svelte-components/src/lib/event/EventCardDropdownMenu.svelte b/ndk-svelte-components/src/lib/event/EventCardDropdownMenu.svelte
deleted file mode 100644
index 9b4b773b..00000000
--- a/ndk-svelte-components/src/lib/event/EventCardDropdownMenu.svelte
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
- { open = !open}}>
-
-
-
- {#if open}
-
- {/if}
-
-
-
\ No newline at end of file
diff --git a/ndk-svelte-components/src/lib/event/EventThread.svelte b/ndk-svelte-components/src/lib/event/EventThread.svelte
deleted file mode 100644
index fa9ec263..00000000
--- a/ndk-svelte-components/src/lib/event/EventThread.svelte
+++ /dev/null
@@ -1,217 +0,0 @@
-
-
-
- {#if !skipEvent}
-
- {#each Array.from(threadIds.values()).sort(sortThread) as event (event.id)}
-
- {/each}
-
- {/if}
-
- {#if replyIds.size > 0 || $extraItems}
-
- {#each $extraItems??[] as item (item.props.key)}
-
-
-
- {/each}
-
- {#each Array.from(replyIds.values()).sort(sortReplies) as reply (reply.id)}
- {#if !whitelistPubkeys || !useWhitelist || whitelistPubkeys.has(reply.pubkey)}
-
-
-
- {:else if whitelistPubkeys && useWhitelist && !whitelistPubkeys.has(reply.pubkey)}
-
-
- This reply was hidden
- useWhitelist = false}>Show anyway
-
-
- {/if}
- {/each}
-
- {/if}
-
-
-
\ No newline at end of file
diff --git a/ndk-svelte-components/src/lib/event/content/EventContent.svelte b/ndk-svelte-components/src/lib/event/content/EventContent.svelte
deleted file mode 100644
index e9411834..00000000
--- a/ndk-svelte-components/src/lib/event/content/EventContent.svelte
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-{#if event}
- {#if event.kind === 1}
-
- {:else if event.kind === 40}
-
- {:else if event.kind === 1063}
-
- {:else if event.kind === 1985}
-
- {:else if event.kind === 9802}
-
- {:else if event.kind === 30000}
-
- {:else if event.kind === 30001}
-
- {:else if markdownKinds.includes(event.kind)}
-
- {:else}
-
- {/if}
-{/if}
diff --git a/ndk-svelte-components/src/lib/event/content/Kind1.svelte b/ndk-svelte-components/src/lib/event/content/Kind1.svelte
deleted file mode 100644
index e9a11e78..00000000
--- a/ndk-svelte-components/src/lib/event/content/Kind1.svelte
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
-
- {#each groupedContent as { type, value }, i}
- {#if type === NEWLINE}
-
- {:else if type === TOPIC}
-
- {:else if type === LINK}
-
- {:else if type === LINKCOLLECTION}
- {#if mediaCollectionComponent}
- v.value.url)} />
- {:else}
-
- {#each value as {type: _type, value: _value}, j}
-
- {/each}
-
- {/if}
- {:else if type.match(/^nostr:np(rofile|ub)$/)}
-
- {:else if type.startsWith('nostr:') && showMedia && isStartOrEnd(i) && value.id !== anchorId}
-
- {:else if type.startsWith('nostr:')}
-
- {:else}
- {value}
- {/if}
- {' '}
- {/each}
-
-
-
diff --git a/ndk-svelte-components/src/lib/event/content/Kind1063.svelte b/ndk-svelte-components/src/lib/event/content/Kind1063.svelte
deleted file mode 100644
index 4dfab226..00000000
--- a/ndk-svelte-components/src/lib/event/content/Kind1063.svelte
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
File metadata
-
Description: {event.content}
-
-
MIME type: {mimeType}
-
File size: {size}
-
Dimensions: {dim}
- {#if showMedia && SUPPORTED_IMAGE_TYPES.includes(mimeType)}
-
File preview:
-
-
-
- {/if}
- {#if showMedia && SUPPORTED_VIDEO_TYPES.includes(mimeType)}
-
File preview:
-
- {/if}
-
-
-
diff --git a/ndk-svelte-components/src/lib/event/content/Kind30000.svelte b/ndk-svelte-components/src/lib/event/content/Kind30000.svelte
deleted file mode 100644
index 8b11f1c5..00000000
--- a/ndk-svelte-components/src/lib/event/content/Kind30000.svelte
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-{#each list.items as tag (tag[1])}
-
-{/each}
-
-
\ No newline at end of file
diff --git a/ndk-svelte-components/src/lib/event/content/Kind30001.svelte b/ndk-svelte-components/src/lib/event/content/Kind30001.svelte
deleted file mode 100644
index 997fd0a3..00000000
--- a/ndk-svelte-components/src/lib/event/content/Kind30001.svelte
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-{#each list.items as tag (tag[1])}
-
-
-
-{/each}
-
-
\ No newline at end of file
diff --git a/ndk-svelte-components/src/lib/event/content/Kind30023.svelte b/ndk-svelte-components/src/lib/event/content/Kind30023.svelte
deleted file mode 100644
index 86c33fc5..00000000
--- a/ndk-svelte-components/src/lib/event/content/Kind30023.svelte
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-
-
-
-
-
diff --git a/ndk-svelte-components/src/lib/event/content/Kind9802.svelte b/ndk-svelte-components/src/lib/event/content/Kind9802.svelte
deleted file mode 100644
index ae9960b6..00000000
--- a/ndk-svelte-components/src/lib/event/content/Kind9802.svelte
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
- {@html sanitizeHtml(context || event.content)}
-
-
-
-{#if ref}
-
-
-
-{/if}
diff --git a/ndk-svelte-components/src/lib/event/content/NoteContentLink.svelte b/ndk-svelte-components/src/lib/event/content/NoteContentLink.svelte
deleted file mode 100644
index 1160cc62..00000000
--- a/ndk-svelte-components/src/lib/event/content/NoteContentLink.svelte
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-{#if showMedia && value.isMedia}
- {#if !!isImage(value.url)}
-
- {:else if isVideo(value.url)}
-
-
- {:else if isAudio(value.url)}
-
- {value.url.replace(/https?:\/\/(www\.)?/, "")}
-
- {:else}
-
- {value.url.replace(/https?:\/\/(www\.)?/, "")}
-
- {/if}
-{:else}
-
- {value.url.replace(/https?:\/\/(www\.)?/, "")}
-
-{/if}
diff --git a/ndk-svelte-components/src/lib/event/content/NoteContentNewline.svelte b/ndk-svelte-components/src/lib/event/content/NoteContentNewline.svelte
deleted file mode 100644
index f66bdb11..00000000
--- a/ndk-svelte-components/src/lib/event/content/NoteContentNewline.svelte
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-{#each value as _}
-
-{/each}
diff --git a/ndk-svelte-components/src/lib/event/content/NoteContentPerson.svelte b/ndk-svelte-components/src/lib/event/content/NoteContentPerson.svelte
deleted file mode 100644
index 18f5a24d..00000000
--- a/ndk-svelte-components/src/lib/event/content/NoteContentPerson.svelte
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
- @
-
diff --git a/ndk-svelte-components/src/lib/event/content/NoteContentTopic.svelte b/ndk-svelte-components/src/lib/event/content/NoteContentTopic.svelte
deleted file mode 100644
index 39cfd007..00000000
--- a/ndk-svelte-components/src/lib/event/content/NoteContentTopic.svelte
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-#{value}
diff --git a/ndk-svelte-components/src/lib/event/content/RenderHtml.svelte b/ndk-svelte-components/src/lib/event/content/RenderHtml.svelte
deleted file mode 100644
index dfe53313..00000000
--- a/ndk-svelte-components/src/lib/event/content/RenderHtml.svelte
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
- {@html renderedContent}
-
\ No newline at end of file
diff --git a/ndk-svelte-components/src/lib/event/content/renderer/hashtag.svelte b/ndk-svelte-components/src/lib/event/content/renderer/hashtag.svelte
deleted file mode 100644
index 9bd02eed..00000000
--- a/ndk-svelte-components/src/lib/event/content/renderer/hashtag.svelte
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-{hashtag}
\ No newline at end of file
diff --git a/ndk-svelte-components/src/lib/event/content/renderer/index.ts b/ndk-svelte-components/src/lib/event/content/renderer/index.ts
deleted file mode 100644
index 1c8e4ab5..00000000
--- a/ndk-svelte-components/src/lib/event/content/renderer/index.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import Link from "./link.svelte";
-import Hashtag from "./hashtag.svelte";
-import Mention from "./mention.svelte";
-import NostrEvent from "./nostr-event.svelte";
-import markedFootnote from "marked-footnote";
-
-export default {
- link: Link,
- hashtag: Hashtag,
- mention: Mention,
- nostrEvent: NostrEvent,
-}
diff --git a/ndk-svelte-components/src/lib/event/content/renderer/link.svelte b/ndk-svelte-components/src/lib/event/content/renderer/link.svelte
deleted file mode 100644
index 34efd6f1..00000000
--- a/ndk-svelte-components/src/lib/event/content/renderer/link.svelte
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-{#if showMedia}
- {#if !!isImage(href)}
-
- {:else if isVideo(href)}
-
-
- {:else if isAudio(href)}
-
- {text}
-
- {:else}
-
- {text}
-
- {/if}
-{:else}
-
- {text}
-
-{/if}
diff --git a/ndk-svelte-components/src/lib/event/content/renderer/mention.svelte b/ndk-svelte-components/src/lib/event/content/renderer/mention.svelte
deleted file mode 100644
index 129447f1..00000000
--- a/ndk-svelte-components/src/lib/event/content/renderer/mention.svelte
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/ndk-svelte-components/src/lib/event/content/renderer/nostr-event.svelte b/ndk-svelte-components/src/lib/event/content/renderer/nostr-event.svelte
deleted file mode 100644
index c78237c1..00000000
--- a/ndk-svelte-components/src/lib/event/content/renderer/nostr-event.svelte
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-{#if event}
-
-{/if}
diff --git a/ndk-svelte-components/src/lib/index.ts b/ndk-svelte-components/src/lib/index.ts
deleted file mode 100644
index 0af3c569..00000000
--- a/ndk-svelte-components/src/lib/index.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import EventCard from "./event/EventCard.svelte";
-import EventCardDropdownMenu from "./event/EventCardDropdownMenu.svelte";
-import EventContent from "./event/content/EventContent.svelte";
-import RelayList from "./relay/RelayList.svelte";
-import Avatar from "./user/Avatar.svelte";
-import Name from "./user/Name.svelte";
-import Nip05 from "./user/Nip05.svelte";
-import UserCard from "./user/UserCard.svelte";
-import EventThread from "./event/EventThread.svelte";
-
-export * from "./utils";
-
-export type UrlType = "hashtag" | "mention";
-
-export type UrlFactory = (type: UrlType, value: string) => string;
-
-export {
- // Event
- EventContent,
- EventCard,
- EventCardDropdownMenu,
- EventThread,
-
- // User
- Avatar,
- Name,
- Nip05,
- UserCard,
-
- // Relay
- RelayList,
-};
diff --git a/ndk-svelte-components/src/lib/relay/RelayList.svelte b/ndk-svelte-components/src/lib/relay/RelayList.svelte
deleted file mode 100644
index 5f8ec133..00000000
--- a/ndk-svelte-components/src/lib/relay/RelayList.svelte
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
- {#each relays as relay}
-
- {/each}
-
diff --git a/ndk-svelte-components/src/lib/relay/RelayListItem.svelte b/ndk-svelte-components/src/lib/relay/RelayListItem.svelte
deleted file mode 100644
index deafc8fa..00000000
--- a/ndk-svelte-components/src/lib/relay/RelayListItem.svelte
+++ /dev/null
@@ -1,208 +0,0 @@
-
-
-
- expanded = !expanded}
- >
- {#if relay.status === NDKRelayStatus.CONNECTING || relay.status === NDKRelayStatus.RECONNECTING}
-
- {:else if relay.status === NDKRelayStatus.DISCONNECTED}
-
- {:else if relay.status === NDKRelayStatus.CONNECTED}
-
- {:else if relay.status === NDKRelayStatus.FLAPPING}
-
- {:else if relay.status === NDKRelayStatus.AUTHENTICATING}
-
- {/if}
-
- {#if activeSubCount > 0}
-
- {activeSubCount}
- {activeSubCount === 1 ? 'subscription' : 'subscriptions'}
-
- {/if}
-
-
- {#if relay.connectionStats.attempts > 1 && relay.status !== NDKRelayStatus.CONNECTED}
-
-
- Reconnection attempts: {relay.connectionStats.attempts}
-
-
- {#if nextReconnectIn}
-
- Next reconnect in
- {nextReconnectIn} seconds
-
- {/if}
-
- {/if}
-
- {#if notices.length > 0}
-
- {#each notices as notice, i (i)}
- {notice}
- {/each}
-
- {/if}
-
- {#if expanded}
-
- {/if}
-
-
-
-
diff --git a/ndk-svelte-components/src/lib/relay/RelayName.svelte b/ndk-svelte-components/src/lib/relay/RelayName.svelte
deleted file mode 100644
index 83ca82cc..00000000
--- a/ndk-svelte-components/src/lib/relay/RelayName.svelte
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-{formatRelayName(relay)}
diff --git a/ndk-svelte-components/src/lib/stores/ndk.ts b/ndk-svelte-components/src/lib/stores/ndk.ts
deleted file mode 100644
index b2868fcd..00000000
--- a/ndk-svelte-components/src/lib/stores/ndk.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk";
-import { writable } from "svelte/store";
-
-const _ndk = new NDK({
- explicitRelayUrls: [
- "wss://relay.f7z.io",
- "wss://nos.lol",
- "wss://relay.damus.io",
- "wss://relay.snort.social",
- ],
-});
-
-export default writable(_ndk);
diff --git a/ndk-svelte-components/src/lib/user/Avatar.svelte b/ndk-svelte-components/src/lib/user/Avatar.svelte
deleted file mode 100644
index a4021c7e..00000000
--- a/ndk-svelte-components/src/lib/user/Avatar.svelte
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-{#await fetchProfilePromise}
-
-{:then userProfile}
-
-{:catch error}
-
-{/await}
-
-
diff --git a/ndk-svelte-components/src/lib/user/Name.svelte b/ndk-svelte-components/src/lib/user/Name.svelte
deleted file mode 100644
index 7d8b200f..00000000
--- a/ndk-svelte-components/src/lib/user/Name.svelte
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
- {#if userProfile}
- {chooseNameFromDisplay(userProfile)}
- {:else if user}
- {#await user.fetchProfile({ closeOnEose: true, groupable: true, groupableDelay: 200 })}
- {chooseNameFromDisplay()}
- {:then}
- {chooseNameFromDisplay(user.profile)}
- {:catch error}
-
- {truncatedNpub}
-
- {/await}
- {/if}
-
diff --git a/ndk-svelte-components/src/lib/user/Nip05.svelte b/ndk-svelte-components/src/lib/user/Nip05.svelte
deleted file mode 100644
index e6b74ea3..00000000
--- a/ndk-svelte-components/src/lib/user/Nip05.svelte
+++ /dev/null
@@ -1,99 +0,0 @@
-
-
-
- {#await fetchAndValidate()}
-
-
-
- {:then validationResponse}
-
-
-
- {validationResponse.userProfile?.nip05 ? prettifyNip05(validationResponse.userProfile.nip05, nip05MaxLength) : ""}
-
-
- {:catch}
-
-
- Error loading user profile
-
- {/await}
-
diff --git a/ndk-svelte-components/src/lib/user/Npub.svelte b/ndk-svelte-components/src/lib/user/Npub.svelte
deleted file mode 100644
index 390b465d..00000000
--- a/ndk-svelte-components/src/lib/user/Npub.svelte
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
- {#if user && user.npub}
-
- {npubMaxLength ? truncatedBech32(user.npub, npubMaxLength) : user.npub}
-
-
-
- {#if checkVisible}
-
-
-
- {/if}
-
- {:else}
- Error loading user
- {/if}
-
-
-
diff --git a/ndk-svelte-components/src/lib/user/UserCard.svelte b/ndk-svelte-components/src/lib/user/UserCard.svelte
deleted file mode 100644
index 384303ed..00000000
--- a/ndk-svelte-components/src/lib/user/UserCard.svelte
+++ /dev/null
@@ -1,110 +0,0 @@
-
-
-{#await fetchProfilePromise}
- Loading user...
-{:then userProfile}
-
-
-
-
-
-
-
{userProfile?.bio || userProfile?.about}
-
-
-{:catch}
- Error fetching user
-{/await}
-
-
diff --git a/ndk-svelte-components/src/lib/utils/event/index.ts b/ndk-svelte-components/src/lib/utils/event/index.ts
deleted file mode 100644
index bd2794d3..00000000
--- a/ndk-svelte-components/src/lib/utils/event/index.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * Format bytes as human-readable text.
- *
- * @param bytes Number of bytes.
- * @param si True to use metric (SI) units, aka powers of 1000. False to use
- * binary (IEC), aka powers of 1024.
- * @param dp Number of decimal places to display.
- *
- * @return Formatted string.
- */
-export function humanFileSize(bytes: number, si = false, dp = 1): string {
- const thresh = si ? 1000 : 1024;
-
- if (Math.abs(bytes) < thresh) {
- return bytes + " B";
- }
-
- const units = si
- ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
- : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
- let u = -1;
- const r = 10 ** dp;
-
- do {
- bytes /= thresh;
- ++u;
- } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
-
- return bytes.toFixed(dp) + " " + units[u];
-}
diff --git a/ndk-svelte-components/src/lib/utils/extensions/event.svelte b/ndk-svelte-components/src/lib/utils/extensions/event.svelte
deleted file mode 100644
index c78237c1..00000000
--- a/ndk-svelte-components/src/lib/utils/extensions/event.svelte
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-{#if event}
-
-{/if}
diff --git a/ndk-svelte-components/src/lib/utils/extensions/hashtag.svelte b/ndk-svelte-components/src/lib/utils/extensions/hashtag.svelte
deleted file mode 100644
index 9bd02eed..00000000
--- a/ndk-svelte-components/src/lib/utils/extensions/hashtag.svelte
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-{hashtag}
\ No newline at end of file
diff --git a/ndk-svelte-components/src/lib/utils/extensions/image.svelte b/ndk-svelte-components/src/lib/utils/extensions/image.svelte
deleted file mode 100644
index 17391abd..00000000
--- a/ndk-svelte-components/src/lib/utils/extensions/image.svelte
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-{#if isImage($$props.href)}
-
-{:else}
- {$$props.children??$$props.text}
-{/if}
diff --git a/ndk-svelte-components/src/lib/utils/extensions/mention.svelte b/ndk-svelte-components/src/lib/utils/extensions/mention.svelte
deleted file mode 100644
index 4da65f06..00000000
--- a/ndk-svelte-components/src/lib/utils/extensions/mention.svelte
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/ndk-svelte-components/src/lib/utils/index.ts b/ndk-svelte-components/src/lib/utils/index.ts
deleted file mode 100644
index 38920bc5..00000000
--- a/ndk-svelte-components/src/lib/utils/index.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export * from "./relay";
-export * from "./user";
-
-export function truncatedBech32(bech32: string, length?: number): string {
- return `${bech32.substring(0, length || 9)}...`;
-}
-
-export async function copyToClipboard(textToCopy: string | undefined) {
- try {
- await navigator.clipboard.writeText(textToCopy as string);
- } catch (err) {
- console.error("Failed to copy: ", err);
- }
-}
diff --git a/ndk-svelte-components/src/lib/utils/markdown.ts b/ndk-svelte-components/src/lib/utils/markdown.ts
deleted file mode 100644
index 0b67d787..00000000
--- a/ndk-svelte-components/src/lib/utils/markdown.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-import { marked, type MarkedExtension, type TokenizerAndRendererExtension, type TokensList } from "marked";
-import { gfmHeadingId } from "marked-gfm-heading-id";
-import { mangle } from "marked-mangle";
-import markedFootnote from "marked-footnote";
-
-export const markdownToHtml = (
- content: string,
- extraMarkedExtensions?: MarkedExtension[]
-): TokensList => {
- marked.use(mangle());
- marked.use(gfmHeadingId());
- marked.use(markedFootnote());
-
- extraMarkedExtensions?.forEach((extension) => {
- console.log('adding extension', extension)
- marked.use(extension);
- });
-
- const mentionRegexp = /^(nostr:|@)npub1[a-zA-Z0-9]+/;
- const eventRegexp = /^(nostr:|@)n(event|ote|addr)1[0-9a-zA-Z]+/;
- const hashtagRegexp = /^#\w+/;
-
- marked.use({
- extensions: [{
- name: "mention",
- level: "inline",
- start(src: string) {
- return src.indexOf("nostr:npub1");
- },
- tokenizer(src: string, tokens) {
- const match = mentionRegexp.exec(src);
- if (!match) return;
-
- const token = { type: 'mention', raw: match[0], npub: match[0].replace(/^(nostr:|@)/, '') };
- return token;
-
-
- // if (match.index > 0) {
- // const text = src.slice(0, match.index);
- // tokens.push({ type: 'text', raw: text, text });
- // }
-
- // const npub = match[0].replace(/^(nostr:|@)/, '');
- // tokens.push({ type: 'nostrMention', raw: "nostr:" + npub, npub });
-
- // // if there is more after the mention, add it as text
- // if (match.index + match[0].length < src.length) {
- // const text = src.slice(match.index + match[0].length);
- // tokens.push({ type: 'text', raw: text, text });
- // }
-
- // return { type: 'block', raw: src, text: src, tokens };
- }
- }, {
- name: "nostrEvent",
- level: "inline",
- start(src: string) {
- return src.indexOf("nostr:note") ?? src.indexOf("nostr:nevent") ?? src.indexOf("nostr:naddr");
- },
- tokenizer(src: string, tokens) {
- const match = eventRegexp.exec(src);
- if (!match) return;
-
- const token = { type: 'nostrEvent', raw: match[0], id: match[0].replace(/^(nostr:|@)/, '') };
- return token;
-
- // const match = eventRegexp.exec(src); // Use extracted event regex
- // if (match) {
- // const id = match[0].replace(/^(nostr:|@)/, '');
-
- // // Add prefix as text token
- // const prefix = src.slice(0, match.index);
- // if (prefix) {
- // tokens.push({ type: 'text', raw: prefix, text: prefix });
- // }
-
- // // Add the main event token
- // tokens.push({ type: "nostrEvent", raw: match[0], id });
-
- // // Add suffix as text token if there's more text after the match
- // const suffix = src.slice(match.index + match[0].length);
- // if (suffix) {
- // tokens.push({ type: 'text', raw: suffix, text: suffix });
- // }
-
- // return { type: 'block', raw: src, text: src, tokens };
- // }
- }
- }, {
- name: 'hashtag',
- level: 'inline',
- start(src: string) {
- return src.indexOf('#');
- },
- tokenizer(src: string, tokens) {
- const match = hashtagRegexp.exec(src);
- if (!match) return;
-
- const token = { type: 'hashtag', raw: match[0], hashtag: match[0], tokens };
- // this.lexer.inline(token.text, token.tokens);
-
- return token;
- }
- }]
- });
-
- // marked.Lexer.lex(content)
-
- const tokens = marked.lexer(content);
- return tokens;
-};
diff --git a/ndk-svelte-components/src/lib/utils/notes.ts b/ndk-svelte-components/src/lib/utils/notes.ts
deleted file mode 100644
index e6132251..00000000
--- a/ndk-svelte-components/src/lib/utils/notes.ts
+++ /dev/null
@@ -1,312 +0,0 @@
-import { nip19 } from "nostr-tools";
-import { identity, last } from "ramda";
-
-export const NEWLINE = "newline";
-export const TEXT = "text";
-export const TOPIC = "topic";
-export const LINK = "link";
-export const LINKCOLLECTION = "link[]";
-export const HTML = "html";
-export const INVOICE = "invoice";
-export const NOSTR_NOTE = "nostr:note";
-export const NOSTR_NEVENT = "nostr:nevent";
-export const NOSTR_NPUB = "nostr:npub";
-export const NOSTR_NPROFILE = "nostr:nprofile";
-export const NOSTR_NADDR = "nostr:naddr";
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-const first = (list: any) => (list ? list[0] : undefined);
-
-export const fromNostrURI = (s: string) => s.replace(/^[\w+]+:\/?\/?/, "");
-
-export const urlIsMedia = (url: string) =>
- !url.match(/\.(apk|docx|xlsx|csv|dmg)/) && last(url.split("://"))?.includes("/");
-
-type ContentArgs = {
- content: string;
- tags?: Array<[string, string, string]>;
- html?: boolean;
-};
-
-export type ParsedPart = {
- type: string;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- value: any;
-};
-
-export const isEmbeddableMedia = (url: string) => isImage(url) || isVideo(url) || isAudio(url);
-
-export const isImage = (url: string) => url?.match(/^.*\.(jpg|jpeg|png|webp|gif|avif|svg)/gi);
-export const isVideo = (url: string) => url?.match(/^.*\.(mov|mkv|mp4|avi|m4v|webm)/gi);
-export const isAudio = (url: string) => url?.match(/^.*\.(ogg|mp3|wav)/gi);
-
-/**
- * Groups content parts into link collections when they are consecutive media links
- */
-export function groupContent(parts: ParsedPart[]): ParsedPart[] {
- // if there are multiple consecutive links, group them together, but if
- const result: ParsedPart[] = [];
- let buffer: ParsedPart | undefined;
-
- const popBuffer = () => {
- if (buffer) {
- if (buffer.value.length > 1) {
- result.push(buffer);
- } else {
- // If there is only one link in the buffer, just push the link to the result
- result.push({
- type: LINK,
- value: buffer.value[0].value,
- });
- }
- buffer = undefined;
- }
- };
-
- parts.forEach((part, index) => {
- if (
- part.type === LINK &&
- (isImage(part.value.url) || isVideo(part.value.url) || isAudio(part.value.url))
- ) {
- if (!buffer) {
- buffer = {
- type: LINKCOLLECTION,
- value: [],
- };
- }
-
- buffer.value.push(part);
- } else {
- let nextPartsAreNoops: boolean | undefined = undefined;
-
- for (const nextPart of parts.slice(index + 1)) {
- const isNewline = nextPart.type === NEWLINE;
- const isBlankText = nextPart.type === TEXT && nextPart.value.trim() === "";
- const isLink = nextPart.type === LINK;
-
- // This is a noop, keep checking the next part
- if (isNewline || isBlankText) continue;
-
- nextPartsAreNoops = isLink;
-
- break;
- }
-
- if (nextPartsAreNoops === false) {
- // we found a non-noop part after the current part
- popBuffer();
- result.push(part);
- } else {
- result.push(part);
- }
- }
- });
-
- popBuffer();
-
- return result;
-}
-
-export const parseContent = ({ content, tags = [], html = false }: ContentArgs): ParsedPart[] => {
- const result: ParsedPart[] = [];
- let text = content.trim();
- let buffer = "";
-
- const parseNewline = () => {
- if (html) return;
- const newline = first(text.match(/^\n+/));
-
- if (newline) {
- return [NEWLINE, newline, newline];
- }
- };
-
- const parseMention = () => {
- // Convert legacy mentions to bech32 entities
- const mentionMatch = text.match(/^#\[(\d+)\]/i);
-
- if (mentionMatch) {
- const i = parseInt(mentionMatch[1]);
-
- if (tags[i]) {
- const [tag, value, url] = tags[i];
- const relays = [url].filter(identity);
-
- let type, data, entity;
- try {
- if (tag === "p") {
- type = "nprofile";
- data = { pubkey: value, relays };
- entity = nip19.nprofileEncode(data);
- } else {
- type = "nevent";
- data = { id: value, relays, pubkey: null };
- entity = nip19.neventEncode(data);
- }
- } catch {
- /**/
- }
-
- return [`nostr:${type}`, mentionMatch[0], { ...data, entity }];
- }
- }
- };
-
- const parseTopic = () => {
- const topic = first(text.match(/^#\w+/i));
-
- // Skip numeric topics
- if (topic && !topic.match(/^#\d+$/)) {
- return [TOPIC, topic, topic.slice(1)];
- }
- };
-
- const parseBech32 = () => {
- const bech32 = first(
- text.match(/^(web\+)?(nostr:)?\/?\/?n(event|ote|profile|pub|addr)1[\d\w]+/i)
- );
-
- if (bech32) {
- try {
- const entity = fromNostrURI(bech32);
- const { type, data } = nip19.decode(entity) as { type: string; data: object };
-
- let value = data;
- if (type === "note") {
- value = { id: data };
- } else if (type === "npub") {
- value = { pubkey: data };
- }
-
- return [`nostr:${type}`, bech32, { ...value, entity }];
- } catch (e) {
- console.log(e);
- // pass
- }
- }
- };
-
- const parseInvoice = () => {
- const invoice = first(text.match(/^ln(bc|url)[\d\w]{50,1000}/i));
-
- if (invoice) {
- return [INVOICE, invoice, invoice];
- }
- };
-
- const parseUrl = () => {
- const raw = first(text.match(/^([a-z+:]{2,30}:\/\/)?[^\s]+\.[a-z]{2,6}[^\s]*[^.!?,:\s]/gi));
-
- // Skip url if it's just the end of a filepath
- if (raw) {
- const prev = last(result);
-
- if (prev?.type === "text" && prev.value.endsWith("/")) {
- return;
- }
-
- let url = raw;
-
- // Skip ellipses and very short non-urls
- if (url.match(/\.\./)) {
- return;
- }
-
- if (!url.match("://")) {
- url = "https://" + url;
- }
-
- return [LINK, raw, { url, isMedia: urlIsMedia(url) }];
- }
- };
-
- const parseHtml = (): any[] | undefined => {
- // Only parse out specific html tags
- const raw = first(text.match(/^<(pre|code)>.*?<\/\1>/gis));
-
- if (raw) {
- return [HTML, raw, raw];
- }
- };
-
- while (text) {
- let part: any[] | undefined;
-
- if (html) {
- part = parseBech32() || parseMention() || parseTopic();
- } else {
- part =
- parseHtml() ||
- parseNewline() ||
- parseMention() ||
- parseTopic() ||
- parseBech32() ||
- parseUrl() ||
- parseInvoice();
- }
-
- if (part) {
- if (buffer) {
- result.push({ type: "text", value: buffer });
- buffer = "";
- }
-
- const [type, raw, value] = part;
-
- result.push({ type, value });
- text = text.slice(raw.length);
- } else {
- // Instead of going character by character and re-running all the above regular expressions
- // a million times, try to match the next word and add it to the buffer
- const match = first(text.match(/^[\w\d]+ ?/i)) || text[0];
-
- buffer += match;
- text = text.slice(match.length);
- }
- }
-
- if (buffer) {
- result.push({ type: TEXT, value: buffer });
- }
-
- return result;
-};
-
-export const truncateContent = (content, { showEntire, maxLength, showMedia = false }) => {
- if (showEntire) {
- return content;
- }
-
- let length = 0;
- const result = [];
- const truncateAt = maxLength * 0.6;
-
- content.every((part, i) => {
- const isText =
- [TOPIC, TEXT].includes(part.type) || (part.type === LINK && !part.value.isMedia);
- const isMedia =
- part.type === INVOICE || part.type.startsWith("nostr:") || part.value.isMedia;
-
- if (isText) {
- length += part.value.length;
- }
-
- if (isMedia) {
- length += showMedia ? maxLength / 3 : part.value.length;
- }
-
- result.push(part);
-
- if (length > truncateAt && i < content.length - 1) {
- if (isText || (isMedia && !showMedia)) {
- result.push({ type: TEXT, value: "..." });
- }
-
- return false;
- }
-
- return true;
- });
-
- return result;
-};
diff --git a/ndk-svelte-components/src/lib/utils/relay/index.ts b/ndk-svelte-components/src/lib/utils/relay/index.ts
deleted file mode 100644
index 4a9d7b30..00000000
--- a/ndk-svelte-components/src/lib/utils/relay/index.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import type { NDKRelay } from "@nostr-dev-kit/ndk";
-
-export function formatRelayName(relay: NDKRelay): string {
- let name = relay.url;
-
- // Some well known relays
- switch (relay.url) {
- case "wss://purplepag.es":
- return "Purple Pages";
- case "wss://relay.damus.io":
- return "Damus relay";
- case "wss://relay.snort.social":
- return "Snort relay";
- }
-
- // strip protocol prefix
- name = name.replace(/^(ws|wss):\/\//, "");
-
- return name;
-}
diff --git a/ndk-svelte-components/src/lib/utils/user/index.ts b/ndk-svelte-components/src/lib/utils/user/index.ts
deleted file mode 100644
index fd751888..00000000
--- a/ndk-svelte-components/src/lib/utils/user/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export function prettifyNip05(nip05: string, maxLength?: number | undefined): string {
- const trimmedNip05: string = nip05.startsWith("_@") ? nip05.substring(2) : nip05;
- if (maxLength) {
- return trimmedNip05.slice(0, maxLength);
- } else {
- return trimmedNip05;
- }
-}
diff --git a/ndk-svelte-components/src/routes/+page.svelte b/ndk-svelte-components/src/routes/+page.svelte
deleted file mode 100644
index d7bb508b..00000000
--- a/ndk-svelte-components/src/routes/+page.svelte
+++ /dev/null
@@ -1,6 +0,0 @@
-What are you looking at?
-
-
- If you got here by running npm run dev
you're doing it wrong. You should run
- npm run storybook
instead.
-
diff --git a/ndk-svelte-components/src/stories/Introduction.mdx b/ndk-svelte-components/src/stories/Introduction.mdx
deleted file mode 100644
index 3086bbbe..00000000
--- a/ndk-svelte-components/src/stories/Introduction.mdx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Meta } from "@storybook/blocks";
-
-
-
-# NDK Svelte Component Library
-
-The goal of these components is to make it as easy as possible to develop Nostr apps using NDK and Svelte. Think of the components detailed in this Storybook as unstyled legos that you can use to build your Nostr apps without having to think about fetching data for common patterns.
-
-## Use the components in your app
-
-First, install the library using: `npm install @nostr-dev-kit/ndk-svelte-components`
-
-Then, simply import any of the components that you want to use: `import { Avatar, Name } from '@nostr-dev-kit/ndk-svelte-components'`
-
-### Styling components
-
-You can pass `style` or `class` attributes on any component to pass those through to the outermost `HTMLElement` rendered in a component. This allows you to style directly or to use a framework like [Tailwind](https://tailwindcss.com/).
-
-## Contribute
-
-Any and all contributions are welcome. You can find the code for [this repo on GitHub here](https://github.com/nostr-dev-kit/ndk-svelte-components).
diff --git a/ndk-svelte-components/src/stories/events/EventCard.stories.ts b/ndk-svelte-components/src/stories/events/EventCard.stories.ts
deleted file mode 100644
index 85a32ee0..00000000
--- a/ndk-svelte-components/src/stories/events/EventCard.stories.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import EventCard from "../../lib/event/EventCard.svelte";
-
-/**
- * Renders an event's card
- */
-
-const meta = {
- title: "Event/EventCard",
- component: EventCard,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: null },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- id: {
- control: { type: null },
- type: { name: "other", value: "Event", required: true },
- table: { type: { summary: "string" } },
- description: "The event ID you want to render in hex or bech32 format",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://nos.lol"] });
-await ndk.connect();
-
-const id = "note194n247lecqgcskk5rmmfgrapt4jx7ppq64xec0eca3s4ta3hwkrsex7pxa";
-
-const withEmbeddedNoteId =
- "nevent1qqsrjpqwtmwy2aw0t745d6vdj6k267wjv5xjklek7ucr2pv65p2ydgspz9mhxue69uhkummnw3ezuamfdejj7qmsa3q";
-
-const withImage = "note1np37t0mgh0ucuujf7lm7wawz42d8krcwc95cng9090yglcltpk7sgat8rs";
-
-export const Kind1Event: Story = {
- args: {
- ndk,
- id,
- },
-};
-
-export const Kind1EventWithEmbeddedNote: Story = {
- args: {
- ndk,
- id: withEmbeddedNoteId,
- },
-};
-
-export const Kind1EventWithImage: Story = {
- args: {
- ndk,
- id: withImage,
- },
-};
diff --git a/ndk-svelte-components/src/stories/events/EventCardDropdownMenu.stories.ts b/ndk-svelte-components/src/stories/events/EventCardDropdownMenu.stories.ts
deleted file mode 100644
index 5e3891d6..00000000
--- a/ndk-svelte-components/src/stories/events/EventCardDropdownMenu.stories.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import EventCardDropdownMenu from "../../lib/event/EventCardDropdownMenu.svelte";
-
-/**
- * Renders an event's card
- */
-
-const meta = {
- title: "Event/EventCardDropdownMenu",
- component: EventCardDropdownMenu,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: null },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- event: {
- control: { type: null },
- type: { name: "other", value: "NDKEvent", required: true },
- table: { type: { summary: "NDKEvent" } },
- description: "The event you want to render",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://nos.lol"] });
-await ndk.connect();
-
-const id = "note194n247lecqgcskk5rmmfgrapt4jx7ppq64xec0eca3s4ta3hwkrsex7pxa";
-const event = await ndk.fetchEvent(id);
-event.relay = undefined;
-
-export const Kind1Event: Story = {
- args: {
- ndk,
- event,
- },
-};
diff --git a/ndk-svelte-components/src/stories/events/EventContent.stories.ts b/ndk-svelte-components/src/stories/events/EventContent.stories.ts
deleted file mode 100644
index 2cb34469..00000000
--- a/ndk-svelte-components/src/stories/events/EventContent.stories.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import NDK, { NDKArticle, type NDKEvent } from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import EventContent from "../../lib/event/content/EventContent.svelte";
-
-/**
- * Renders an event's content
- */
-
-const meta: Meta = {
- title: "Event/EventContent",
- component: EventContent,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: null },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- event: {
- control: { type: null },
- type: { name: "other", value: "Event", required: true },
- table: { type: { summary: "NDKEvent" } },
- description: "The event you want to render.",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://relay.nostr.band"] });
-ndk.connect();
-
-let event: NDKEvent;
-let article: NDKEvent;
-
-ndk.fetchEvent("note194n247lecqgcskk5rmmfgrapt4jx7ppq64xec0eca3s4ta3hwkrsex7pxa").then(
- (e) => (event = e!)
-);
-
-article = await ndk.fetchEvent("naddr1qqxnzdejxyurxveexymnxwfeqgsg3nqnfvdxta2w7j9vc80nvegx85l2ghcya2u273jxu4sutt5eq7grqsqqqa286jzgn2")
-// article = await ndk.fetchEvent("naddr1qvzqqqr4gupzqkcpsw4kc03j906dg8rt8thes432z3yy0d6fj4phylz48xs3g437qy88wumn8ghj7mn0wvhxcmmv9uqq6vfhxg6rjd33x5cnvd33xcvvu6c4")
-article.relay = undefined;
-
-export const Kind1Event: Story = {
- args: {
- ndk,
- event,
- },
-};
-
-export const Kind30023Event: Story = {
- args: {
- ndk,
- event: article,
- },
-};
diff --git a/ndk-svelte-components/src/stories/events/EventThread.stories.ts b/ndk-svelte-components/src/stories/events/EventThread.stories.ts
deleted file mode 100644
index 178c0e75..00000000
--- a/ndk-svelte-components/src/stories/events/EventThread.stories.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk-svelte";
-import { NDKEvent } from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-import NDKCacheAdapterDexie from "@nostr-dev-kit/ndk-cache-dexie";
-
-import EventThread from "../../lib/event/EventThread.svelte";
-
-/**
- * Render an event as a thread.
- */
-
-const meta = {
- title: "Event/EventThread",
- component: EventThread,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: null },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- event: {
- control: { type: null },
- type: { name: "other", value: "Event", required: true },
- table: { type: { summary: "NDKEvent" } },
- description: "The root event of the thread.",
- },
- skipEvent: {
- control: { type: "boolean" },
- type: { name: "boolean", required: false },
- table: { type: { summary: "boolean" } },
- description: "Skip rendering the root event; just render the events tagging this event",
- defaultValue: false,
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const cacheAdapter = new NDKCacheAdapterDexie({ dbName: "ndk-svelte-components-storybook" });
-
-const ndk = new NDK({
- explicitRelayUrls: ["wss://nos.lol"],
- enableOutboxModel: true,
- cacheAdapter,
-});
-await ndk.connect();
-
-const event = new NDKEvent(ndk, {
- id: "9dcccd571449f26bd8505eb88fdb9b11dbe123635db918e31304a1b5e462536f",
- pubkey: "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52",
- created_at: 1697028628,
- kind: 1,
- tags: [],
- content: "The new note view in my new upcoming client handles threads quite nicely.",
- sig: "afb176fb960c87ec9456e7275cadf3b444d2de3be447f1e62c5e802715120685ff464070b33dcdb264225c52cf617600280838950585db38203c59ac9bb6737c",
-});
-
-export const Thread: Story = {
- args: {
- ndk,
- event,
- },
-};
diff --git a/ndk-svelte-components/src/stories/events/kinds/1.stories.ts b/ndk-svelte-components/src/stories/events/kinds/1.stories.ts
deleted file mode 100644
index a882acf7..00000000
--- a/ndk-svelte-components/src/stories/events/kinds/1.stories.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import Kind1Component from "../../../lib/event/content/Kind1.svelte";
-
-/**
- * Renders a Kind 1 event content
- */
-
-const meta = {
- title: "Event/Kinds/Kind 1 - Text note",
- component: Kind1Component,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: null },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- event: {
- control: { type: null },
- type: { name: "other", value: "NDKEvent", required: true },
- table: { type: { summary: "NDKEvent" } },
- description: "The event you want to render",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://nos.lol"] });
-await ndk.connect();
-
-const id =
- "nevent1qqstuzqnw6czlugwszyj0z6gvffz8y27tsg4mfmnqnjqlj2vx5kac4cprpmhxue69uhhyetvv9ujumn0wd68yct5dyhxxmmdqgsx8zd7vjg70d5na8ek3m8g3lx3ghc8cp5d9sdm4epy0wd4aape6vsxrtmuk";
-const event = await ndk.fetchEvent(id);
-
-event.relay = undefined;
-event.onRelays = [];
-
-export const Kind1: Story = {
- args: {
- ndk,
- event,
- },
-};
diff --git a/ndk-svelte-components/src/stories/events/kinds/1063.stories.ts b/ndk-svelte-components/src/stories/events/kinds/1063.stories.ts
deleted file mode 100644
index 119d735a..00000000
--- a/ndk-svelte-components/src/stories/events/kinds/1063.stories.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import Kind1063Component from "../../../lib/event/content/Kind1063.svelte";
-
-/**
- * Renders a Kind 1063 metadata event
- */
-
-const meta = {
- title: "Event/Kinds/Kind 1063 - File metadata",
- component: Kind1063Component,
- tags: ["autodocs"],
- argTypes: {
- event: {
- control: { type: null },
- type: { name: "other", value: "NDKEvent", required: true },
- description: "The event you want to render",
- },
- showMedia: {
- control: { type: "boolean" },
- type: { required: false },
- description: "Whether or not to render media inline (images, video, audio)",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://nos.lol"] });
-await ndk.connect();
-
-const id = "nevent1qqs2vrx4ffqyq42yge95v3rfyr5gqr9z3pqpe7j7dymlk4lv3pwse6qfcjqkn";
-const event = await ndk.fetchEvent(id);
-
-event.relay = undefined;
-
-export const Kind1063: Story = {
- args: {
- event,
- },
-};
diff --git a/ndk-svelte-components/src/stories/events/kinds/30023.stories.ts b/ndk-svelte-components/src/stories/events/kinds/30023.stories.ts
deleted file mode 100644
index 6100360f..00000000
--- a/ndk-svelte-components/src/stories/events/kinds/30023.stories.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk";
-import { NDKArticle } from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import Kind30023Component from "../../../lib/event/content/Kind30023.svelte";
-
-/**
- * Renders a Kind 30023 long-form article
- */
-
-const meta = {
- title: "Event/Kinds/Kind 30023 - Long-form articles",
- component: Kind30023Component,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: null },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- article: {
- control: { type: null },
- type: { name: "other", value: "NDKArticle", required: true },
- table: { type: { summary: "NDKArticle" } },
- description: "The article you want to render",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://nos.lol"] });
-await ndk.connect();
-
-const id =
- "naddr1qvzqqqr4gupzq6ksswfdrw4r7mlh49qfu2k9u4zrtpextk955kquvpna3r4rq9vyqyfhwumn8ghj7ur4wfcxcetsv9njuetn9uq32amnwvaz7tmjv4kxz7fwv3sk6atn9e5k7tcpzamhxue69uhhyetvv9ujumn0wd68ytnzv9hxgtcpz3mhxue69uhhyetvv9ukzcnvv5hx7un89uq3zamnwvaz7tmwdaehgu3wwa5kuef0qqv9yetkd9jhw6twvuk4yetkd9jhwuedd3cxjmncvv3euyg7";
-// Tony 'naddr1qqz82unvwvpzql6u9d8y3g8flm9x8frtz0xmsfyf7spq8xxkpgs8p2tge25p346aqvzqqqr4gupdy396';
-// Der Gigi 'naddr1qqxnzd3cxqmrzv3exgmr2wfeqgsxu35yyt0mwjjh8pcz4zprhxegz69t4wr9t74vk6zne58wzh0waycrqsqqqa28pjfdhz';
-const event = await ndk.fetchEvent(id);
-
-event.relay = undefined;
-
-const article = NDKArticle.from(event);
-
-export const Kind30023: Story = {
- args: {
- ndk,
- article,
- },
-};
diff --git a/ndk-svelte-components/src/stories/events/kinds/9802.stories.ts b/ndk-svelte-components/src/stories/events/kinds/9802.stories.ts
deleted file mode 100644
index 00ad8570..00000000
--- a/ndk-svelte-components/src/stories/events/kinds/9802.stories.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import Kind9802Component from "../../../lib/event/content/Kind9802.svelte";
-
-/**
- * Renders a Kind 9802 highlight event
- */
-
-const meta = {
- title: "Event/Kinds/Kind 9802 - Highlights",
- component: Kind9802Component,
- tags: ["autodocs"],
- argTypes: {
- event: {
- control: { type: null },
- type: { name: "other", value: "NDKEvent", required: true },
- description: "The event you want to render",
- },
- showMedia: {
- control: { type: "boolean" },
- type: { required: false },
- description: "Whether or not to render media inline (images, video, audio)",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://nos.lol"] });
-await ndk.connect();
-
-const id =
- "nevent1qqsg643qyh3anmfmuqckt7dm082uk5qtlqpuv6z8c2fa45352sh502qzyphydppzm7m554ecwq4gsgaek2qk32atse2l4t9ks57dpms4mmhfx0qhfet";
-const event = await ndk.fetchEvent(id);
-
-event.relay = undefined;
-
-export const Kind9802: Story = {
- args: {
- ndk,
- event,
- },
-};
diff --git a/ndk-svelte-components/src/stories/events/kinds/lists/30000.stories.ts b/ndk-svelte-components/src/stories/events/kinds/lists/30000.stories.ts
deleted file mode 100644
index 094a9053..00000000
--- a/ndk-svelte-components/src/stories/events/kinds/lists/30000.stories.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import NDK, { NDKList } from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import Kind30000 from "../../../../lib/event/content/Kind30000.svelte";
-
-/**
- * Renders a Kind 30000 (Categorized People) list.
- */
-
-const meta = {
- title: "Event/Kinds/Lists/Kind 30000 - Categorized People",
- component: Kind30000,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: null },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- list: {
- control: { type: null },
- type: { name: "other", value: "NDKList", required: true },
- table: { type: { summary: "NDKList" } },
- description: "The kind 30001 event ID want to render",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://nos.lol"] });
-await ndk.connect();
-
-const id =
- "naddr1qq9yummnw3ezq3r9weesygqh88vn0hyvp3ehp238tpvn3sgeufwyrakygxjaxnrd8pgruvfkaupsgqqqw5cq9prfqc";
-const list = NDKList.from(await ndk.fetchEvent(id));
-
-export const Default: Story = {
- args: {
- ndk,
- list,
- },
-};
diff --git a/ndk-svelte-components/src/stories/events/kinds/lists/30001.stories.ts b/ndk-svelte-components/src/stories/events/kinds/lists/30001.stories.ts
deleted file mode 100644
index 83fcb87a..00000000
--- a/ndk-svelte-components/src/stories/events/kinds/lists/30001.stories.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import NDK, { NDKList } from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import Kind30001 from "../../../../lib/event/content/Kind30001.svelte";
-
-/**
- * Renders a Kind 30001 (Categorized Bookmarks) list.
- */
-
-const meta = {
- title: "Event/Kinds/Lists/Kind 30001 - Categorized Bookmarks",
- component: Kind30001,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: null },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- list: {
- control: { type: null },
- type: { name: "other", value: "NDKList", required: true },
- table: { type: { summary: "NDKList" } },
- description: "The kind 30001 event ID want to render",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://nos.lol"] });
-await ndk.connect();
-
-const id =
- "naddr1qqv5ummnw3fks6tjwssyxatnw3hk6etjypfx2anfv4msygxv35rjalwvvahuhtq57mxksf0dcdtku40t0p4z4967uq62dgpxevpsgqqqw5cswq0n3l";
-const list = NDKList.from(await ndk.fetchEvent(id));
-
-export const Default: Story = {
- args: {
- ndk,
- list,
- },
-};
diff --git a/ndk-svelte-components/src/stories/relay/RelayList.stories.ts b/ndk-svelte-components/src/stories/relay/RelayList.stories.ts
deleted file mode 100644
index 03c5e3a9..00000000
--- a/ndk-svelte-components/src/stories/relay/RelayList.stories.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import RelayList from "../../lib/relay/RelayList.svelte";
-
-const meta = {
- title: "Relay/RelayList",
- component: RelayList,
- tags: ["autodocs"],
- parameters: {
- docs: {
- description: {
- component:
- "Displays a list of relays the NDK instance is connected to, along with information about active subscriptions and connectivity stats.",
- },
- },
- },
-} satisfies Meta;
-
-export default meta;
-
-type Story = StoryObj;
-
-const ndk = new NDK({
- explicitRelayUrls: [
- "wss://relay.f7z.io",
- "wss://nos.lol",
- "wss://relay.damus.io",
- "wss://relay.snort.social",
- "wss://filter.nostr.wine/npub1zuuajd7u3sx8xu92yav9jwxpr839cs0kc3q6t56vd5u9q033xmhsk6c2uc?broadcast=true",
- ],
-});
-ndk.connect();
-const pablo = ndk.getUser({
- npub: "npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft",
-});
-// pablo.fetchProfile()
-
-const sub1 = ndk.subscribe({ limit: 10 }, { closeOnEose: false });
-const sub2 = ndk.subscribe(
- { authors: [pablo.pubkey], kinds: [1] },
- { groupable: true, subId: "pablo-kind-1s" }
-);
-const sub3 = ndk.subscribe(
- { authors: [pablo.pubkey], kinds: [7] },
- { groupable: true, subId: "pablo-kind-7s" }
-);
-
-setTimeout(() => sub1.stop(), 1000);
-setTimeout(() => sub2.stop(), 2000);
-setTimeout(() => sub3.stop(), 5000);
-
-export const Default: Story = {
- args: {
- ndk: ndk,
- },
-};
diff --git a/ndk-svelte-components/src/stories/user/Avatar.stories.ts b/ndk-svelte-components/src/stories/user/Avatar.stories.ts
deleted file mode 100644
index 083dd578..00000000
--- a/ndk-svelte-components/src/stories/user/Avatar.stories.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import Avatar from "../../lib/user/Avatar.svelte";
-
-/**
- * Renders a user's avatar image using the `user.userProfile.image` value from their latest kind `0` event.
- *
- * You can pass `class` or `style` props to the component to style the resulting image.
- */
-
-const meta = {
- title: "User/Avatar",
- component: Avatar,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: null },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- npub: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description:
- "The user's npub. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- pubkey: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description:
- "The user's hex pubkey. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- user: {
- control: { type: null },
- type: { name: "other", value: "NDKUser", required: false },
- table: { type: { summary: "NDKUser" } },
- description:
- "An NDKUser object. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- userProfile: {
- control: { type: null },
- type: { name: "other", value: "NDKUserProfile", required: false },
- table: { type: { summary: "NDKUserProfile" } },
- description:
- "An NDKUserProfile object. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- class: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description: "Any classes you want applied to the ` ` HTML element",
- },
- style: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description: "Any styles you want applied to the ` ` HTML element",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://purplepag.es"] });
-ndk.connect();
-
-export const Default: Story = {
- args: {
- ndk: ndk,
- npub: "npub1zuuajd7u3sx8xu92yav9jwxpr839cs0kc3q6t56vd5u9q033xmhsk6c2uc",
- style: "width: 64px; height: 64px;",
- },
-};
-
-export const Nonexistent: Story = {
- args: {
- ndk: ndk,
- npub: "npub1vqtlp64gdfdqr64xq9g7t8qc9kyyns7nd23nnsf3mv94aqht8ensn29e34",
- style: "width: 64px; height: 64px;",
- },
-};
diff --git a/ndk-svelte-components/src/stories/user/Name.stories.ts b/ndk-svelte-components/src/stories/user/Name.stories.ts
deleted file mode 100644
index b04bdcfe..00000000
--- a/ndk-svelte-components/src/stories/user/Name.stories.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import Name from "../../lib/user/Name.svelte";
-
-/**
- * Renders a user name, falling back depending on what values are available. The order used is:
- * 1. `user.userProfile.displayName`
- * 2. `user.userProfile.name`
- * 3. `user.userProfile.nip05`
- * 4. `npub` optionally truncated with the npubMaxLength param
- *
- * As with all components, you can pass `class` or `style` props to the component.
- * If no `class` or `style` prop is passed, default styles will render the name as normal text.
- */
-
-const meta = {
- title: "User/Name",
- component: Name,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: "object" },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- npub: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description:
- "The user's npub. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- pubkey: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description:
- "The user's hex pubkey. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- user: {
- control: { type: null },
- type: { name: "other", value: "NDKUser", required: false },
- table: { type: { summary: "NDKUser" } },
- description:
- "An NDKUser object. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- userProfile: {
- control: { type: null },
- type: { name: "other", value: "NDKUserProfile", required: false },
- table: { type: { summary: "NDKUserProfile" } },
- description:
- "An NDKUserProfile object. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- npubMaxLength: {
- control: "number",
- type: "number",
- table: { type: { summary: "number" } },
- description: "The max length of the npub",
- },
- class: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description: "Any classes you want applied to the ` ` HTML element",
- },
- style: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description: "Any styles you want applied to the ` ` HTML element",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://purplepag.es"] });
-ndk.connect();
-
-export const Default: Story = {
- args: {
- ndk: ndk,
- npub: "npub1zuuajd7u3sx8xu92yav9jwxpr839cs0kc3q6t56vd5u9q033xmhsk6c2uc",
- },
-};
diff --git a/ndk-svelte-components/src/stories/user/Nip05.stories.ts b/ndk-svelte-components/src/stories/user/Nip05.stories.ts
deleted file mode 100644
index b8955a02..00000000
--- a/ndk-svelte-components/src/stories/user/Nip05.stories.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-import NDK from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-import Nip05 from "../../lib/user/Nip05.svelte";
-
-/**
- * Renders a user's NIP-05 string.
- *
- * If a user's NIP-05 starts with an `_` (underscore), only the domain will be rendered.
- *
- * This component has a named slot called "badge", that you can use to pass in an icon, image or anything else you want.
- *
- * As with all components, you can pass `class` or `style` props to the component.
- * If no `class` or `style` prop is passed, default styles will render the name as normal text.
- */
-
-const meta = {
- title: "User/NIP-05",
- component: Nip05,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: "object" },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- npub: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description:
- "The user's npub. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- pubkey: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description:
- "The user's hex pubkey. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- user: {
- control: { type: null },
- type: { name: "other", value: "NDKUser", required: false },
- table: { type: { summary: "NDKUser" } },
- description:
- "An NDKUser object. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- userProfile: {
- control: { type: null },
- type: { name: "other", value: "NDKUserProfile", required: false },
- table: { type: { summary: "NDKUserProfile" } },
- description:
- "An NDKUserProfile object. Only one of `npub`, `pubkey`, `user`, or `userProfile` is required.",
- },
- nip05MaxLength: {
- control: "number",
- type: "number",
- table: { type: { summary: "number" } },
- description: "The max length of the nip-05",
- },
- class: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description: "Any classes you want applied to the ` ` HTML element",
- },
- style: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description: "Any styles you want applied to the ` ` HTML element",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://purplepag.es"] });
-ndk.connect();
-
-export const Default: Story = {
- args: {
- ndk: ndk,
- npub: "npub1qny3tkh0acurzla8x3zy4nhrjz5zd8l9sy9jys09umwng00manysew95gx",
- },
-};
-
-export const WithUnderscore: Story = {
- args: {
- ndk: ndk,
- npub: "npub1zuuajd7u3sx8xu92yav9jwxpr839cs0kc3q6t56vd5u9q033xmhsk6c2uc",
- },
-};
diff --git a/ndk-svelte-components/src/stories/user/Npub.stories.ts b/ndk-svelte-components/src/stories/user/Npub.stories.ts
deleted file mode 100644
index 0b410cc3..00000000
--- a/ndk-svelte-components/src/stories/user/Npub.stories.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import Npub from "$lib/user/Npub.svelte";
-import NDK from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-/**
- * Renders a user's npub string.
- *
- * Displays a truncated version of a user's npub and an icon that allows user's to copy the npub.
- *
- * As with all components, you can pass `class` or `style` props to the component.
- * If no `class` or `style` prop is passed, default styles will render the name as normal text.
- */
-
-const meta = {
- title: "User/Npub",
- component: Npub,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: "object" },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- npub: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description: "The user's npub. Only one of `npub`, `pubkey`, or `user` is required.",
- },
- pubkey: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description:
- "The user's hex pubkey. Only one of `npub`, `pubkey`, or `user` is required.",
- },
- user: {
- control: { type: null },
- type: { name: "other", value: "NDKUser", required: false },
- table: { type: { summary: "NDKUser" } },
- description: "An NDKUser object. Only one of `npub`, `pubkey`, or `user` is required.",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://purplepag.es"] });
-ndk.connect();
-
-export const Default: Story = {
- args: {
- ndk: ndk,
- npub: "npub1qny3tkh0acurzla8x3zy4nhrjz5zd8l9sy9jys09umwng00manysew95gx",
- },
-};
diff --git a/ndk-svelte-components/src/stories/user/UserCard.stories.ts b/ndk-svelte-components/src/stories/user/UserCard.stories.ts
deleted file mode 100644
index a979ad4a..00000000
--- a/ndk-svelte-components/src/stories/user/UserCard.stories.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-import UserCard from "$lib/user/UserCard.svelte";
-import NDK from "@nostr-dev-kit/ndk";
-import type { Meta, StoryObj } from "@storybook/svelte";
-
-/**
- * Renders a user card with basic metadata info on the user.
- *
- * You can pass `class` or `style` props to the component to style the card itself.
- */
-
-const meta = {
- title: "User/UserCard",
- component: UserCard,
- tags: ["autodocs"],
- argTypes: {
- ndk: {
- control: { type: null },
- type: { name: "other", value: "NDK", required: true },
- table: { type: { summary: "NDK" } },
- description:
- "The NDK instance you want to use. This should be already connected to relays.",
- },
- npub: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description: "The user's npub. Only one of `npub`, `pubkey`, or `user` is required.",
- },
- pubkey: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description:
- "The user's hex pubkey. Only one of `npub`, `pubkey`, or `user` is required.",
- },
- user: {
- control: { type: null },
- type: { name: "other", value: "NDKUser", required: false },
- table: { type: { summary: "NDKUser" } },
- description: "An NDKUser object. Only one of `npub`, `pubkey`, or `user` is required.",
- },
- class: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description: "Any classes you want applied to the ` ` HTML element",
- },
- style: {
- control: "text",
- type: "string",
- table: { type: { summary: "string" } },
- description: "Any styles you want applied to the ` ` HTML element",
- },
- },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
-
-const ndk = new NDK({ explicitRelayUrls: ["wss://purplepag.es"] });
-ndk.connect();
-
-export const Default: Story = {
- args: {
- ndk: ndk,
- npub: "npub1zuuajd7u3sx8xu92yav9jwxpr839cs0kc3q6t56vd5u9q033xmhsk6c2uc",
- },
-};
-
-export const Nonexistent: Story = {
- args: {
- ndk: ndk,
- npub: "npub1vqtlp64gdfdqr64xq9g7t8qc9kyyns7nd23nnsf3mv94aqht8ensn29e34",
- },
-};
diff --git a/ndk-svelte-components/src/styles/global.css b/ndk-svelte-components/src/styles/global.css
deleted file mode 100644
index 524bf4a9..00000000
--- a/ndk-svelte-components/src/styles/global.css
+++ /dev/null
@@ -1,21 +0,0 @@
-:root {
- --color-shadow: rgba(0, 0, 0, 0.2);
- --color-border: #eaeaea;
- --color-bg: white;
-
- --color-primary: #0070f3;
-
- --connector-width: 4px;
- --connector-style: solid;
- --connector-color: var(--color-border);
-}
-
-a {
- color: var(--color-primary);
- text-decoration: none;
-}
-
-.event-card .event-content img {
- /* fit content */
- width: 100%;
-}
diff --git a/ndk-svelte-components/static/favicon.png b/ndk-svelte-components/static/favicon.png
deleted file mode 100644
index 825b9e65..00000000
Binary files a/ndk-svelte-components/static/favicon.png and /dev/null differ
diff --git a/ndk-svelte-components/svelte.config.js b/ndk-svelte-components/svelte.config.js
deleted file mode 100644
index ae0a4ef3..00000000
--- a/ndk-svelte-components/svelte.config.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import preprocess from "svelte-preprocess";
-import adapter from "@sveltejs/adapter-auto";
-
-/** @type {import('@sveltejs/kit').Config} */
-const config = {
- preprocess: preprocess(),
- compilerOptions: {
- customElement: true,
- },
- kit: {
- adapter: adapter(),
- },
-};
-
-export default config;
diff --git a/ndk-svelte-components/tailwind.config.js b/ndk-svelte-components/tailwind.config.js
deleted file mode 100644
index 6c855fcf..00000000
--- a/ndk-svelte-components/tailwind.config.js
+++ /dev/null
@@ -1,4 +0,0 @@
-module.exports = {
- prefix: "ndk-svelte-",
- presets: [require("@nostr-dev-kit/tailwind-config/tailwind.config.js")],
-};
diff --git a/ndk-svelte-components/tsconfig.json b/ndk-svelte-components/tsconfig.json
deleted file mode 100644
index cb286cec..00000000
--- a/ndk-svelte-components/tsconfig.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "extends": "./.svelte-kit/tsconfig.json",
- "compilerOptions": {
- "allowJs": true,
- "checkJs": true,
- "esModuleInterop": true,
- "forceConsistentCasingInFileNames": true,
- "resolveJsonModule": true,
- "skipLibCheck": true,
- "sourceMap": true,
- "strict": true
- }
-}
diff --git a/ndk-svelte-components/vite.config.ts b/ndk-svelte-components/vite.config.ts
deleted file mode 100644
index 4a79a4b1..00000000
--- a/ndk-svelte-components/vite.config.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { sveltekit } from "@sveltejs/kit/vite";
-import { defineConfig } from "vite";
-
-export default defineConfig({
- plugins: [sveltekit()],
-});
diff --git a/ndk-svelte/.gitignore b/ndk-svelte/.gitignore
deleted file mode 100644
index 8d40ce19..00000000
--- a/ndk-svelte/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-**/node_modules
-**/build
-**/dist
-**/lib
-**/.vscode
-justfile
-package-lock.json
-**/*.js
-!jest.config.js
-**/*.d.ts
-**/*.d.ts.map
-*.tgz
-.DS_Store
diff --git a/ndk-svelte/.prettierignore b/ndk-svelte/.prettierignore
deleted file mode 100644
index 53c37a16..00000000
--- a/ndk-svelte/.prettierignore
+++ /dev/null
@@ -1 +0,0 @@
-dist
\ No newline at end of file
diff --git a/ndk-svelte/CHANGELOG.md b/ndk-svelte/CHANGELOG.md
deleted file mode 100644
index 86ce28e9..00000000
--- a/ndk-svelte/CHANGELOG.md
+++ /dev/null
@@ -1,362 +0,0 @@
-# @nostr-dev-kit/ndk-svelte
-
-## 2.3.2
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.7
-
-## 2.3.1
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.6
-
-## 2.3.0
-
-### Minor Changes
-
-- 7bddeff: skip by default, PRE that have been tagged as "deleted"
-
-### Patch Changes
-
-- Updated dependencies [5939a3e]
-- Updated dependencies
-- Updated dependencies [f2a0cce]
- - @nostr-dev-kit/ndk@2.10.5
-
-## 2.2.22
-
-### Patch Changes
-
-- Updated dependencies [5bed70c]
-- Updated dependencies [873ad4a]
- - @nostr-dev-kit/ndk@2.10.4
-
-## 2.2.21
-
-### Patch Changes
-
-- Updated dependencies [0fc66c5]
- - @nostr-dev-kit/ndk@2.10.3
-
-## 2.2.20
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.10.2
-
-## 2.2.19
-
-### Patch Changes
-
-- d6cfa8a: Fix inconsistent store result
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [d6cfa8a]
-- Updated dependencies [722345b]
- - @nostr-dev-kit/ndk@2.10.1
-
-## 2.2.18
-
-### Patch Changes
-
-- e8ad796: expose a way to peak into events as they come
-- Updated dependencies [ec83ddc]
-- Updated dependencies [18c55bb]
-- Updated dependencies
-- Updated dependencies [18c55bb]
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies [3029124]
- - @nostr-dev-kit/ndk@2.10.0
-
-## 2.2.17
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.9.1
-
-## 2.2.16
-
-### Patch Changes
-
-- 548f4d8: add optimistic updates
-- Updated dependencies [94018b4]
-- Updated dependencies [548f4d8]
- - @nostr-dev-kit/ndk@2.9.0
-
-## 2.2.15
-
-### Patch Changes
-
-- Updated dependencies [0af033f]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.8.2
-
-## 2.2.14
-
-### Patch Changes
-
-- Updated dependencies [e40312b]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.8.1
-
-## 2.2.13
-
-### Patch Changes
-
-- fix broken subscription unref
-- Updated dependencies [91d873c]
-- Updated dependencies [6fd9ddc]
-- Updated dependencies [0b8f331]
-- Updated dependencies
-- Updated dependencies [f2898ad]
-- Updated dependencies [9b92cd9]
-- Updated dependencies
-- Updated dependencies [6814f0c]
-- Updated dependencies [89b5b3f]
-- Updated dependencies [9b92cd9]
-- Updated dependencies [27b10cc]
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies [ed7cdc4]
- - @nostr-dev-kit/ndk@2.8.0
-
-## 2.2.12
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.7.1
-
-## 2.2.11
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.7.0
-
-## 2.2.10
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.6.1
-
-## 2.2.9
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [c2db3c1]
-- Updated dependencies
-- Updated dependencies [c2db3c1]
-- Updated dependencies [c2db3c1]
- - @nostr-dev-kit/ndk@2.6.0
-
-## 2.2.8
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.5.1
-
-## 2.2.7
-
-### Patch Changes
-
-- Updated dependencies [e08fc74]
- - @nostr-dev-kit/ndk@2.5.0
-
-## 2.2.6
-
-### Patch Changes
-
-- Updated dependencies [111c1ea]
-- Updated dependencies [5c0ae51]
-- Updated dependencies [6f5ea49]
-- Updated dependencies [3738d39]
-- Updated dependencies [d22239a]
- - @nostr-dev-kit/ndk@2.4.1
-
-## 2.2.5
-
-### Patch Changes
-
-- Updated dependencies [b9bbf1d]
- - @nostr-dev-kit/ndk@2.4.0
-
-## 2.2.4
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [885b6c2]
-- Updated dependencies [5666d56]
- - @nostr-dev-kit/ndk@2.3.3
-
-## 2.2.3
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies [4628481]
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.3.2
-
-## 2.2.2
-
-### Patch Changes
-
-- Updated dependencies [ece965f]
- - @nostr-dev-kit/ndk@2.3.1
-
-## 2.2.1
-
-### Patch Changes
-
-- Updated dependencies [54cec78]
-- Updated dependencies [ef61d83]
-- Updated dependencies [98b77dd]
-- Updated dependencies [46b0c77]
-- Updated dependencies [082e243]
- - @nostr-dev-kit/ndk@2.3.0
-
-## 2.1.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.2.0
-
-## 2.0.10
-
-### Patch Changes
-
-- Updated dependencies [180d774]
-- Updated dependencies [7f00c40]
- - @nostr-dev-kit/ndk@2.1.3
-
-## 2.0.9
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.2
-
-## 2.0.8
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.1
-
-## 2.0.7
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.1.0
-
-## 2.0.6
-
-### Patch Changes
-
-- Updated dependencies
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.6
-
-## 2.0.5
-
-### Patch Changes
-
-- Updated dependencies [d45d962]
- - @nostr-dev-kit/ndk@2.0.5
-
-## 2.0.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.4
-
-## 2.0.3
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.3
-
-## 2.0.2
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.2
-
-## 1.3.6
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@2.0.0
-
-## 1.3.5
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.2
-
-## 1.3.4
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.1
-
-## 1.3.3
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.4.0
-
-## 1.3.2
-
-### Patch Changes
-
-- Updated dependencies [b3561af]
- - @nostr-dev-kit/ndk@1.3.2
-
-## 1.3.1
-
-### Patch Changes
-
-- Updated dependencies
- - @nostr-dev-kit/ndk@1.3.1
-
-## 1.3.0
-
-### Minor Changes
-
-- 38fa741: Fixes issue where NIP-33 events are not properly replaced
-
-### Patch Changes
-
-- Updated dependencies [88df10a]
-- Updated dependencies [c225094]
-- Updated dependencies [cf4a648]
-- Updated dependencies [3946078]
-- Updated dependencies [3440768]
- - @nostr-dev-kit/ndk@1.3.0
diff --git a/ndk-svelte/LICENSE b/ndk-svelte/LICENSE
deleted file mode 100644
index 2a6ea523..00000000
--- a/ndk-svelte/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2023 Pablo Fernandez
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/ndk-svelte/README.md b/ndk-svelte/README.md
deleted file mode 100644
index 5e954ff2..00000000
--- a/ndk-svelte/README.md
+++ /dev/null
@@ -1,102 +0,0 @@
-# ndk-svelte
-
-This package provides convenience functionalities to make usage of NDK with Svelte nicer.
-
-## Install
-
-```
-pnpm add @nostr-dev-kit/ndk-svelte
-```
-
-## Store subscriptions
-
-NDK-svelte provides Svelte Store subscriptions so your components can have simple reactivity
-when events arrive.
-
-Events in the store will appear in a set ordered by `created_at`.
-
-```typescript
-import NDKSvelte from "@nostr-dev-kit/ndk-svelte";
-
-const ndk = new NDKSvelte({
- explicitRelayUrls: ["wss://relay.f7z.io"],
-});
-```
-
-```typescript
-// in your components
-
-
-
- {$highlights.length} highlights seen
-
-
-
- {$nostrHighlightsAndReposts.length} nostr highlights (including reposts)
-
-```
-
-## Reference Counting with ref/unref
-
-NDK-svelte introduces a reference counting mechanism through the ref and unref methods on the stores. This system is particularly useful for optimizing the lifecycle of subscriptions in components that might be frequently mounted and unmounted.
-
-### Benefits:
-
-- **Optimized Lifecycle**: Instead of starting a new subscription every time a component mounts, and ending it when it unmounts, you can reuse an existing subscription if another component is already using it.
-
-- **Resource Efficiency**: By preventing redundant subscriptions, you save both network bandwidth and processing power.
-
-- **Synchronization**: Ensures that multiple components referencing the same data are synchronized with a single data source.
-
-### How to use:
-
-Whenever you subscribe to a store in a component, call ref to increment the reference count:
-
-```typescript
-// lib/stores/highlightsStore.ts
-const highlightsStore = $ndk.storeSubscribe(..., { autoStart: false } });
-
-// component 1
-
-
-{$highlightsStore.length} highlights seen
-```
-
-You can mount this component as many times as you want, and the subscription will only be started once. When the last component unmounts, the subscription will be terminated.
-
-# Notes
-
-If you are interested in NDK and Svelte you might want to checkout the
-[ndk-svelte-components](https://github.com/nostr-dev-kit/ndk-svelte-components) package
-which provides some components to make it easier to build nostr apps with Svelte.
-
-# Authors
-
-- [@pablof7z](https://njump.me/npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft)
diff --git a/ndk-svelte/package.json b/ndk-svelte/package.json
deleted file mode 100644
index f53210e3..00000000
--- a/ndk-svelte/package.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "name": "@nostr-dev-kit/ndk-svelte",
- "version": "2.3.2",
- "description": "This package provides convenience functionalities to make usage of NDK with Svelte nicer.",
- "main": "./dist/index.js",
- "module": "./dist/index.mjs",
- "exports": {
- ".": {
- "import": {
- "types": "./dist/index.d.mts",
- "default": "./dist/index.mjs"
- },
- "require": {
- "types": "./dist/index.d.ts",
- "default": "./dist/index.js"
- }
- },
- "./svelte5": {
- "import": {
- "types": "./dist/index.svelte.d.mts",
- "default": "./dist/index.svelte.js"
- },
- "require": {
- "types": "./dist/index.svelte.d.ts",
- "default": "./dist/index.svelte.js"
- }
- }
- },
- "files": [
- "dist",
- "README.md"
- ],
- "scripts": {
- "build": "tsup src/index.ts src/index.svelte.ts --format cjs,esm --dts",
- "dev": "tsup --watch src src/index.ts --format cjs,esm --dts",
- "lint": "prettier --check . && eslint .",
- "format": "prettier --write .",
- "postbuild": "mv dist/index.svelte.mjs dist/index.svelte.js; mv dist/index.svelte.d.mts dist/index.svelte.d.ts"
- },
- "keywords": [
- "nostr",
- "nostr-dev-kit",
- "ndk",
- "svelte"
- ],
- "author": "pablof7z",
- "license": "MIT",
- "dependencies": {
- "@nostr-dev-kit/ndk": "workspace:*"
- },
- "peerDependencies": {
- "svelte": "*"
- },
- "devDependencies": {
- "@nostr-dev-kit/eslint-config-custom": "workspace:*",
- "@nostr-dev-kit/tsconfig": "workspace:*",
- "svelte": "5.0.0-next.272",
- "tsup": "^7.2.0"
- }
-}
diff --git a/ndk-svelte/src/index.svelte.ts b/ndk-svelte/src/index.svelte.ts
deleted file mode 100644
index 96a45688..00000000
--- a/ndk-svelte/src/index.svelte.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-import NDK, {
- type NDKConstructorParams,
- NDKEvent,
- type NDKFilter,
- type NDKRelay,
- type NDKRelaySet,
- type NDKSubscriptionOptions,
-} from "@nostr-dev-kit/ndk";
-import { onDestroy } from "svelte";
-
-type ClassWithConvertFunction = {
- from: (event: NDKEvent) => T | undefined;
-};
-
-type NDKSubscribeOptions = NDKSubscriptionOptions & {
- autoStart?: boolean;
- repostsFilters?: NDKFilter[];
- unrefUnsubscribeTimeout?: number;
- relaySet?: NDKRelaySet;
- skipDeleted?: boolean;
- onEose?: () => void;
- onEvent?: (event: NDKEvent, relay?: NDKRelay) => void;
-};
-
-type Actions = {
- unsubscribe?: () => void;
-};
-
-class NDKSvelte extends NDK {
- constructor(opts?: NDKConstructorParams) {
- super(opts);
- }
-
- /**
- * Subscribes to NDK events and returns a reactive list of events.
- * Automatically cleans up the subscription when no longer needed.
- */
- public $subscribe = (
- filters: NDKFilter[],
- opts?: NDKSubscribeOptions,
- klass?: ClassWithConvertFunction
- ) => {
- // A reactive list for the events
- const eventList = $state([]);
- const eventMap = new Map(); // Map for deduplication
-
- // Process an incoming event
- const processEvent = (event: NDKEvent) => {
- let e = event;
-
- // Convert the event to a specific class if provided
- if (klass) {
- const convertedEvent = klass.from(event);
- if (!convertedEvent) return;
- e = convertedEvent;
- e.relay = event.relay;
- }
-
- const dedupKey = e.deduplicationKey();
-
- // Avoid duplicate or older events
- if (eventMap.has(dedupKey)) {
- const existingEvent = eventMap.get(dedupKey)!;
- if (existingEvent.created_at! >= e.created_at!) return;
- }
-
- // Check if the event is marked as deleted
- const isDeleted = e.isParamReplaceable() && e.hasTag("deleted");
-
- // Update the event map
- eventMap.set(dedupKey, e as T);
-
- // If the event is deleted and skipDeleted is true (default), remove it from the list
- if (isDeleted && opts?.skipDeleted !== false) {
- const index = eventList.findIndex(event => event.deduplicationKey() === dedupKey);
- if (index !== -1) {
- eventList.splice(index, 1);
- }
- return;
- }
-
- // Update the reactive event list inserting the event in the right position according to the created_at timestamp
- const pos = eventList.findIndex(event => event.created_at! < e.created_at!);
- eventList.splice(pos, 0, e as T);
- };
-
- // Create the subscription
- const subscription = this.subscribe(
- Array.isArray(filters) ? filters : [filters],
- opts,
- opts?.relaySet,
- false
- );
-
- // Handle incoming events
- subscription.on("event", (event, relay) => {
- processEvent(event);
- if (opts?.onEvent) opts.onEvent(event, relay);
- });
-
- // Handle EOSE
- subscription.on("eose", () => {
- if (opts?.onEose) opts.onEose();
- });
-
- subscription.start();
-
- // Cleanup when the component or context is destroyed
- onDestroy(() => {
- subscription.stop();
- });
-
- eventList.unsubscribe = () => subscription.stop();
-
- return eventList;
- }
-}
-
-export default NDKSvelte;
diff --git a/ndk-svelte/src/index.ts b/ndk-svelte/src/index.ts
deleted file mode 100644
index dc26f010..00000000
--- a/ndk-svelte/src/index.ts
+++ /dev/null
@@ -1,359 +0,0 @@
-import NDK, {
- type NDKConstructorParams,
- NDKEvent,
- type NDKFilter,
- NDKKind,
- type NDKRelay,
- type NDKRelaySet,
- NDKRepost,
- type NDKSubscription,
- type NDKSubscriptionOptions,
-} from "@nostr-dev-kit/ndk";
-import { type Unsubscriber, type Writable, writable } from "svelte/store";
-
-/**
- * Type for NDKEvent classes that have a static `from` method like NDKHighlight.
- */
-type ClassWithConvertFunction