### Install Nostrify with Bun via jsr Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/start/index.md Installs the Nostrify library using Bun by leveraging the jsr package manager via bunx. Bun is a fast all-in-one JavaScript runtime. ```sh bunx jsr add @nostrify/nostrify ``` -------------------------------- ### Install Nostrify with Deno via jsr Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/start/index.md Adds the Nostrify library as a dependency in a Deno project using the jsr protocol. Deno natively supports fetching packages from jsr. ```sh deno add jsr:@nostrify/nostrify ``` -------------------------------- ### Install Nostrify with npm via jsr Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/start/index.md Installs the Nostrify library using npm by leveraging the jsr package manager via npx. This command fetches the package from the jsr registry. ```sh npx jsr add @nostrify/nostrify ``` -------------------------------- ### Install Nostrify with yarn via jsr Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/start/index.md Installs the Nostrify library using yarn by specifying the dependency via the jsr protocol. This command adds the package to your project's dependencies. ```sh yarn add jsr:@nostrify/nostrify ``` -------------------------------- ### Install Nostrify with pnpm via jsr Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/start/index.md Adds the Nostrify library as a dependency using pnpm by specifying the dependency via the jsr protocol. pnpm efficiently manages dependencies, often using a content-addressable store. ```sh pnpm add jsr:@nostrify/nostrify ``` -------------------------------- ### Install @nostrify/react Package Source: https://github.com/soapbox-pub/nostrify/blob/main/packages/react/README.md Instructions for installing the @nostrify/react package using various package managers. ```sh npx jsr add @nostrify/react ``` ```sh deno add jsr:@nostrify/react ``` ```sh yarn add jsr:@nostrify/react ``` ```sh pnpm add jsr:@nostrify/react ``` ```sh bunx jsr add @nostrify/react ``` -------------------------------- ### Install Deno via Curl (Bash) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/mcp.md Provides the standard command-line instruction to download and install the Deno runtime using curl and a shell script, which is a prerequisite for running the Nostrify MCP server. ```bash curl -fsSL https://deno.land/install.sh | sh ``` -------------------------------- ### Initialize NPostgres with Kysely and Pglite Dialect (Development) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/postgres.md Initializes the `NPostgres` database instance using the `kysely` library with the `PgliteDialect`. This setup is suitable for local development as it uses an embedded Pglite database, avoiding the need for a separate PostgreSQL installation. It connects to a file-based database and runs necessary migrations. ```ts import { PGlite } from '@electric-sql/pglite'; import { NPostgres } from '@nostrify/db'; import { PgliteDialect } from '@soapbox/kysely-pglite'; import { Kysely } from 'kysely'; const kysely = new Kysely({ dialect: new PgliteDialect({ database: new PGlite('file://data/pgdata'), }), }); const db = new NPostgres(kysely); await db.migrate(); ``` -------------------------------- ### Installing Nostrify Package from JSR Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/install.md These commands demonstrate how to add the @nostrify/nostrify package from the jsr registry using various JavaScript package managers and runtimes like npm, Deno, yarn, pnpm, and Bun. Choose the command appropriate for your environment. ```sh npx jsr add @nostrify/nostrify ``` ```sh deno add jsr:@nostrify/nostrify ``` ```sh yarn add jsr:@nostrify/nostrify ``` ```sh pnpm add jsr:@nostrify/nostrify ``` ```sh bunx jsr add @nostrify/nostrify ``` -------------------------------- ### Installing Deno for strfry Policies (Shell) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/strfry.md Provides shell commands to download and install the Deno runtime, which is required to run Nostrify policy scripts with strfry. Requires `unzip` and uses `sudo` for system-wide installation. ```Shell sudo apt install -y unzip curl -fsSL https://deno.land/install.sh | sudo DENO_INSTALL=/usr/local sh ``` -------------------------------- ### Installing @nostrify/welshman Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/integrations/welshman.md Provides commands to install the `@nostrify/welshman` package using various package managers. This package is required to use Nostrify with the Welshman library. ```sh npx jsr add @nostrify/welshman ``` ```sh deno add jsr:@nostrify/welshman ``` ```sh yarn add jsr:@nostrify/welshman ``` ```sh pnpm add jsr:@nostrify/welshman ``` ```sh bunx jsr add @nostrify/welshman ``` -------------------------------- ### Installing Nostrify Database Package Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/sql.md Instructions for installing the @nostrify/db package using various package managers (npm, Deno, yarn, pnpm, Bun) from JSR. This package provides the NDatabase class for SQL database integration. ```npm npx jsr add @nostrify/db ``` ```Deno deno add jsr:@nostrify/db ``` ```yarn yarn add jsr:@nostrify/db ``` ```pnpm pnpm add jsr:@nostrify/db ``` ```Bun bunx jsr add @nostrify/db ``` -------------------------------- ### Install @nostrify/ndk package Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/integrations/ndk.md Commands to add the `@nostrify/ndk` package using various package managers. ```sh npx jsr add @nostrify/ndk ``` ```sh deno add jsr:@nostrify/ndk ``` ```sh yarn add jsr:@nostrify/ndk ``` ```sh pnpm add jsr:@nostrify/ndk ``` ```sh bunx jsr add @nostrify/ndk ``` -------------------------------- ### Example NIP-94 Tags from NostrBuildUploader (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/upload/nostr-build.md This snippet provides an example of the `string[][]` array structure returned by the `uploader.upload()` method, representing NIP-94 tags. It shows common tags like `url`, `m` (MIME type), `x` (SHA-256 hash), `size`, `dim` (dimensions), and `blurhash`. ```TypeScript [ ['url', 'https://image.nostr.build/7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539.png'], ['m', 'image/png'], ['x', '21608eecb7df80ca3838deb428fd6568a0d0d3b1baac56491e2247a1c110649a'], ['ox', '7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539'], ['size', '171'], ['dim', '16x16'], ['blurhash', 'LCB20ssn0+NcbsfjRmaz12WW}osn'], ]; ``` -------------------------------- ### Installing @nostrify/db Package (Shell) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/postgres.md Instructions for adding the @nostrify/db package to a project using various package managers (npm, Deno, yarn, pnpm, Bun) via JSR. ```sh npx jsr add @nostrify/db ``` ```sh deno add jsr:@nostrify/db ``` ```sh yarn add jsr:@nostrify/db ``` ```sh pnpm add jsr:@nostrify/db ``` ```sh bunx jsr add @nostrify/db ``` -------------------------------- ### Running Local Development Server - Shell Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/README.md This command starts the local development server for the Nostrify project using Deno tasks. It is typically used to preview documentation changes or develop locally. ```sh deno task dev ``` -------------------------------- ### Using the NPool Instance (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/relay/outbox.md Provides a basic example of how to use the configured `NPool` instance to make requests and iterate over the received messages. ```ts for await (const msg of pool.req(filters)) { console.log(msg); } ``` -------------------------------- ### Configure NostrLoginProvider TSX Source: https://github.com/soapbox-pub/nostrify/blob/main/packages/react/README.md Example showing how to use the NostrLoginProvider to manage user logins, specifying a storage key. ```tsx import { NostrLoginProvider } from '@nostrify/react/login'; function App() { return ( ); } ``` -------------------------------- ### Using NCustodial Signer Manager (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/README.md Provides an example of using the `NCustodial` class, a signer manager that generates deterministic keys for multiple users from a single shared secret. This is suitable for custodial authentication scenarios, showing how to get signers for specific user identifiers and use their methods. ```TypeScript const SECRET_KEY = Deno.env.get('SECRET_KEY'); // generate with `openssl rand -base64 48` const seed = new TextEncoder().encode(SECRET_KEY); const signers = new NCustodial(seed); const alex = await signers.get('alex'); const fiatjaf = await signers.get('fiatjaf'); alex.getPublicKey(); fiatjaf.signEvent(t); ``` -------------------------------- ### Run Nostrify MCP Server (Bash) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/mcp.md Executes the Nostrify documentation MCP server using the Deno runtime, specifying the server name and the documentation site. This command is used for direct MCP client setup, Goose extension configuration, and local testing. ```bash deno run -A jsr:@soapbox/docs-mcp --name Nostrify --site nostrify.dev ``` -------------------------------- ### Install @nostrify/react package Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/react.md Install the @nostrify/react package using various package managers from JSR. This package provides the necessary components and hooks for React integration. ```sh npx jsr add @nostrify/react ``` ```sh deno add jsr:@nostrify/react ``` ```sh yarn add jsr:@nostrify/react ``` ```sh pnpm add jsr:@nostrify/react ``` ```sh bunx jsr add @nostrify/react ``` -------------------------------- ### Run MCP Inspector (Bash) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/mcp.md Starts the MCP Inspector tool, which is used for debugging and interacting with a locally running MCP server to verify its functionality. ```bash deno task dev ``` -------------------------------- ### Configure NostrContext Provider TSX Source: https://github.com/soapbox-pub/nostrify/blob/main/packages/react/README.md Example demonstrating how to wrap your application with the NostrContext.Provider, providing a Nostr relay instance. ```tsx import { NostrContext } from '@nostrify/react'; import { NRelay1 } from '@nostrify/nostrify'; function App() { return ( ); } ``` -------------------------------- ### Configuring DomainPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the DomainPolicy, showing how to configure a blacklist of NIP-05 domains. Events from authors with these domains will be filtered. ```JavaScript { blacklist: ['replyguy.dev'] } ``` -------------------------------- ### Configuring WhitelistPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the WhitelistPolicy, showing how to provide an array of pubkeys. Only events from these specific pubkeys will be allowed; all others will be rejected. ```JavaScript ['e810...', 'fafa...', '1e89...'] ``` -------------------------------- ### Initializing NSeedSigner with HD Seed (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/README.md Illustrates the initialization of the `NSeedSigner` using an HD seed and an account index. This signer derives keys according to NIP-06, useful for managing multiple accounts or integrating with Bitcoin wallets, and shows calls to get the public key and sign an event. ```TypeScript const signer = new NSeedSigner(seed, 0); signer.getPublicKey(); signer.signEvent(t); ``` -------------------------------- ### Initializing NSecSigner with Secret Key (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/README.md Demonstrates how to initialize the `NSecSigner` class using a secret key. This signer is a direct NIP-07 compatible replacement for `window.nostr` and shows basic usage for getting the public key and signing an event. ```TypeScript const signer = new NSecSigner(secretKey); const pubkey = await signer.getPublicKey(); const event = await signer.signEvent({ kind: 1, content: 'Hello, world!', tags: [], created_at: 0 }); ``` -------------------------------- ### Configuring KeywordPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the KeywordPolicy, showing how to provide an array of strings. Events containing any of these strings in their content will be rejected. ```JavaScript ['moo', 'oink', 'honk'] ``` -------------------------------- ### Configuring AnyPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the AnyPolicy, demonstrating how to provide an array of other policy instances. The AnyPolicy accepts an event if *any* of the listed policies accept it. ```JavaScript [new PowPolicy(), new KeywordPolicy()] ``` -------------------------------- ### Configuring RegexPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the RegexPolicy, showing how to provide a regular expression. Events whose content matches this regex will be rejected. ```JavaScript /(🟠|🔥|😳)ChtaGPT/i ``` -------------------------------- ### Configuring PipePolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the PipePolicy, demonstrating how to provide an array of other policy instances. The PipePolicy composes multiple policies, typically applying them sequentially. ```JavaScript [new PowPolicy(), new KeywordPolicy()] ``` -------------------------------- ### Implementing a Custom NStore Storage in Nostrify (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/index.md This example shows how to create a custom storage solution by implementing the NStore interface. It outlines the required asynchronous methods (event, query, count, remove) that must be defined to handle event storage and retrieval logic. ```typescript import { NostrEvent, NostrFilter, NStore } from '@nostrify/nostrify'; class MyStorage implements NStore { async event(event: NostrEvent): Promise { // Store the event. } async query(filters: NostrFilter[]): Promise { // Query events. } async count(filters: NostrFilter[]): Promise<{ count: number }> { // Count events. } async remove(filters: NostrFilter[]): Promise { // Remove events. } } ``` -------------------------------- ### Configuring PowPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the PowPolicy, showing how to set the required Proof-of-Work difficulty. Events that do not meet this NIP-13 criteria will be rejected. ```JavaScript { difficulty: 20 } ``` -------------------------------- ### Configuring AntiDuplicationPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the AntiDuplicationPolicy, showing how to configure a Deno KV store for storage, set an expiration time for duplicates in milliseconds, and define a minimum content length to consider for duplication checks. ```JavaScript { kv: await Deno.openKv(), expireIn: 60000, minLength: 50 } ``` -------------------------------- ### Configuring HellthreadPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the HellthreadPolicy, showing how to set a limit on the number of participants tagged in a message. Messages exceeding this limit will be rejected. ```JavaScript { limit: 15 } ``` -------------------------------- ### Configuring FiltersPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the FiltersPolicy, showing how to provide an array of Nostr filter objects. Events that do not match these filters will be rejected. ```JavaScript [{ kinds: [0, 1, 3, 5, 6, 7] }] ``` -------------------------------- ### Using NSeedSigner for Nostr Identity Derivation (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/sign/seed.md Demonstrates the basic usage of the NSeedSigner class from the @nostrify/nostrify library. It shows how to import the class, instantiate it with a binary seed and account index 0, and then use the instance to get the public key and sign an event. Requires a Uint8Array seed. ```TypeScript import { NSeedSigner } from '@nostrify/nostrify'; const seed: Uint8Array = /* your seed */; const signer = new NSeedSigner(seed, 0); signer.getPublicKey(); signer.signEvent(t); ``` -------------------------------- ### Connecting NDatabase to Postgres in Deno Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/sql.md Provides a complete example of setting up NDatabase to connect to a Postgres database in a Deno environment. It uses x/postgresjs and kysely-postgres-js to create the Kysely dialect and database connection, reading the connection URL from an environment variable. ```TypeScript import { NDatabase } from '@nostrify/db'; import { PostgresJSDialect } from 'kysely-postgres-js'; import { Kysely } from 'kysely'; import postgres from 'postgres'; const databaseUrl = Deno.env.get('DATABASE_URL'); const kysely = new Kysely({ dialect: new PostgresJSDialect({ postgres: postgres(databaseUrl), }), }); const db = new NDatabase(kysely); await db.migrate(); ``` -------------------------------- ### Configuring OpenAIPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the OpenAIPolicy, showing how to provide an OpenAI API key. Event content is passed to OpenAI for moderation, and flagged events are rejected. ```JavaScript { apiKey: '123...' } ``` -------------------------------- ### Configuring SizePolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the SizePolicy, showing how to set the maximum allowed event size in bytes. Events larger than this limit will be rejected. ```JavaScript { maxBytes: 8192 } ``` -------------------------------- ### Creating a Nested Policy Pipeline with AnyPolicy and PipePolicy (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/pipe.md Illustrates how to create a nested policy structure using AnyPolicy and PipePolicy. This example accepts an event if it meets a proof-of-work requirement OR if it passes a PipePolicy that checks for specific keywords and regex patterns, demonstrating how to combine 'OR' and 'AND' logic. ```ts import { AnyPolicy, PipePolicy } from '@nostrify/policies'; const policy = new AnyPolicy([ new PowPolicy({ difficulty: 5 }), new PipePolicy([ new KeywordPolicy(['https://t.me/']), new RegexPolicy(/(🟠|🔥|😳)ChtaGPT/i), ]), ]); ``` -------------------------------- ### Connecting NDatabase to SQLite in Deno Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/sql.md Provides a complete example of setting up NDatabase to connect to an SQLite database in a Deno environment. It uses @db/sqlite and @soapbox/kysely-deno-sqlite to create the Kysely dialect and database connection. ```TypeScript import { NDatabase } from '@nostrify/db'; import { Database } from '@db/sqlite'; import { DenoSqlite3Dialect } from '@soapbox/kysely-deno-sqlite'; import { Kysely } from 'kysely'; const kysely = new Kysely({ dialect: new DenoSqlite3Dialect({ database: new Database('./nostr.sqlite3'), }), }); const db = new NDatabase(kysely); await db.migrate(); ``` -------------------------------- ### Initializing NPostgres with Kysely (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/postgres.md Demonstrates how to create a new instance of NPostgres by providing a configured Kysely instance and running the necessary database migrations to set up tables. ```ts import { NPostgres } from '@nostrify/db'; import { Kysely } from 'kysely'; const kysely = new Kysely(/* set up your database */); const db = new NPostgres(kysely); await db.migrate(); // create the database tables ``` -------------------------------- ### Querying Events from NDenoKv - TypeScript Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/denokv.md Illustrates querying events from the NDenoKv store using the `query` method. Takes an array of Nostr filter objects and returns matching events. This example filters for kinds 1 or 6 with a limit of 5. ```TypeScript const events = await db.query([{ kinds: [1, 6], limit: 5 }]); ``` -------------------------------- ### Creating and Applying a Policy Pipeline in TypeScript Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md This snippet shows how to import various policy types from `@nostrify/policies` and compose them into a `PipePolicy`. It demonstrates instantiating the pipeline with specific configurations (filters, keywords, regex, bans, hellthread limit, duplication check) and then calling the policy's `call` method with a Nostr event to get the result. ```TypeScript import { AntiDuplicationPolicy, FiltersPolicy, HellthreadPolicy, KeywordPolicy, PipePolicy, PowPolicy, RegexPolicy, PubkeyBanPolicy } from '@nostrify/policies'; const policy = new PipePolicy([ new FiltersPolicy([{ kinds: [0, 1, 3, 5, 7, 1984, 9734, 9735, 10002] }]), new KeywordPolicy(['https://t.me/']), new RegexPolicy(/(🟠|🔥|😳)ChtaGPT/i), new PubkeyBanPolicy(['e810fafa1e89cdf80cced8e013938e87e21b699b24c8570537be92aec4b12c18']), new HellthreadPolicy({ limit: 100 }), new AntiDuplicationPolicy({ kv: await Deno.openKv(), expireIn: 60000, minLength: 50 }) ]); const [_, eventId, ok, reason] = await policy.call(event); ``` -------------------------------- ### Using NCustodial for Deterministic User Signers (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/sign/custodial.md Demonstrates how to initialize the NCustodial class with a seed derived from a shared secret and retrieve deterministic signer instances for specific user IDs. It shows how to access user-specific signers for operations like getting public keys or signing events. ```TypeScript import { NCustodial } from '@nostrify/nostrify'; const SECRET_KEY = Deno.env.get('SECRET_KEY'); // generate with `openssl rand -base64 48` const seed = new TextEncoder().encode(SECRET_KEY); const signers = new NCustodial(seed); const alex = await signers.get('alex'); const fiatjaf = await signers.get('fiatjaf'); alex.getPublicKey(); fiatjaf.signEvent(t); ``` -------------------------------- ### Initializing and Using BlossomUploader in TypeScript Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/upload/blossom.md Demonstrates how to import and instantiate the BlossomUploader, providing the required server URLs and a Nostr signer. It then shows how to call the `upload` method with a file to initiate the upload process and receive the resulting NIP-94 tags. ```TypeScript import { BlossomUploader } from '@nostrify/nostrify/uploaders'; const uploader = new BlossomUploader({ servers: ['https://blossom.primal.net/' /*, https://cdn.satellite.earth */], signer: window.nostr, }); const tags = await uploader.upload(file); ``` -------------------------------- ### Counting Nostr Events (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/postgres.md Provides an example of using the count() method to get the number of events matching specific filters, such as kinds. ```ts const { count } = await db.count([{ kinds: [1, 6] }]); ``` -------------------------------- ### Initializing NDKStore with NDK Source: https://github.com/soapbox-pub/nostrify/blob/main/packages/ndk/README.md This snippet demonstrates how to import the necessary classes, initialize and connect an NDK instance, and then create an NDKStore instance compatible with the NStore interface, using the connected NDK. ```ts import NDK from '@nostr-dev-kit/ndk'; import { NDKStore } from '@nostrify/ndk'; const ndk = new NDK(/* set up NDK */); await ndk.connect(); const relay = new NDKStore(ndk); // `NStore` compatible ``` -------------------------------- ### Example NIP-94 Tags Result from Blossom Upload Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/upload/blossom.md Illustrates the expected format of the result returned by the `uploader.upload(file)` method. The result is a string array of arrays representing NIP-94 tags, including the public URL, SHA-256 hashes, size, and MIME type of the uploaded file. ```TypeScript [ ['url', 'https://blossom.primal.net/7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539.png'], ['x', '7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539'], ['ox', '7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539'], ['size', '172'], ['m', 'image/png'], ]; ``` -------------------------------- ### Creating and Applying Nostrify Policies (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/packages/policies/README.md This snippet demonstrates how to create a policy pipeline using PipePolicy, combining various individual policies like FiltersPolicy, KeywordPolicy, RegexPolicy, PubkeyBanPolicy, HellthreadPolicy, and AntiDuplicationPolicy. It shows how to instantiate these policies with specific configurations and then apply the combined policy to a Nostr event using the 'call' method to get the validation result. ```TypeScript import { AntiDuplicationPolicy, FiltersPolicy, HellthreadPolicy, KeywordPolicy, PipePolicy, PowPolicy, RegexPolicy, } from '@nostrify/policies'; const policy = new PipePolicy([ new FiltersPolicy([{ kinds: [0, 1, 3, 5, 7, 1984, 9734, 9735, 10002] }]), new KeywordPolicy(['https://t.me/']), new RegexPolicy(/(🟠|🔥|😳)ChtaGPT/i), new PubkeyBanPolicy(['e810fafa1e89cdf80cced8e013938e87e21b699b24c8570537be92aec4b12c18']), new HellthreadPolicy({ limit: 100 }), new AntiDuplicationPolicy({ kv: await Deno.openKv(), expireIn: 60000, minLength: 50 }), ]); const [_, eventId, ok, reason] = await policy.call(event); ``` -------------------------------- ### Composing a Complex Policy Pipeline with Nested Policies (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/pipe.md Shows a more complex example of a PipePolicy that includes various top-level policies (PubkeyBanPolicy, HellthreadPolicy, AntiDuplicationPolicy) and incorporates a nested AnyPolicy structure. This demonstrates how to build sophisticated, multi-layered policy rules by combining different policy types and nesting pipelines. ```ts import { AntiDuplicationPolicy, AnyPolicy, HellthreadPolicy, PipePolicy, PubkeyBanPolicy } from '@nostrify/policies'; const policy = new PipePolicy([ new PubkeyBanPolicy(['e810fafa1e89cdf80cced8e013938e87e21b699b24c8570537be92aec4b12c18']), new HellthreadPolicy({ limit: 100 }), new AnyPolicy([ new PowPolicy({ difficulty: 5 }), new PipePolicy([ new KeywordPolicy(['https://t.me/']), new RegexPolicy(/(🟠|🔥|😳)ChtaGPT/i), ]), ]), new AntiDuplicationPolicy({ kv: await Deno.openKv(), expireIn: 60000, minLength: 50 }), ]); ``` -------------------------------- ### Using NSet Basic Operations (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/memory.md Demonstrates the basic methods of the `NSet` class, including adding, deleting, checking existence, clearing, getting size, and iterating over events. `NSet` implements the standard ES6 `Set` interface while adding Nostr-specific behaviors like sorting and handling replaceable/parameterized events. ```TypeScript import { NSet } from '@nostrify/nostrify'; const set = new NSet(); set.add(event); set.delete(event); set.has(event); set.clear(); set.size; for (const event of set) { console.log(event); } ``` -------------------------------- ### Initializing Nostrify Deno KV Store (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/packages/denokv/README.md This snippet demonstrates how to initialize the Nostrify Deno KV store. It requires importing the `NDenoKv` class from the `@nostrify/denokv` package and opening a Deno KV database instance using `Deno.openKv()`. The `NDenoKv` class is then instantiated with the opened KV database. ```TypeScript import { NDenoKv } from '@nostrify/denokv'; const kv = await Deno.openKv(); const db = new NDenoKv(kv); ``` -------------------------------- ### Initializing NPostgres Database with Kysely (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/packages/db/README.md Demonstrates how to initialize the NPostgres database adapter for Nostrify. It requires importing NPostgres and Kysely, setting up a Kysely instance connected to a Postgres database, and then creating an NPostgres instance with the Kysely object. Finally, it shows how to run migrations. ```TypeScript import { NPostgres } from '@nostrify/db'; import { Kysely } from 'kysely'; const kysely = new Kysely(/* set up your database */); const db = new NPostgres(kysely); await db.migrate(); ``` -------------------------------- ### Initialize NDKStore with NDK instance Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/integrations/ndk.md Demonstrates how to create an NDK instance, connect it, and then wrap it with `NDKStore` to use it as a Nostrify relay backend. ```ts import NDK from '@nostr-dev-kit/ndk'; import { NDKStore } from '@nostrify/ndk'; const ndk = new NDK(/* set up NDK */); await ndk.connect(); const relay = new NDKStore(ndk); // Now it works like a Nostrify relay! ``` -------------------------------- ### Initialize NPostgres with Kysely and PostgresJS Dialect (Production) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/postgres.md Initializes the `NPostgres` database instance using the `kysely` library with the `PostgresJSDialect`. This configuration is recommended for production environments. It connects to a PostgreSQL database using the `postgres` library and runs necessary migrations. ```ts import { NPostgres } from '@nostrify/db'; import { PostgresJSDialect } from 'kysely-postgres-js'; import { Kysely } from 'kysely'; import postgres from 'postgres'; const databaseUrl = Deno.env.get('DATABASE_URL'); const kysely = new Kysely({ dialect: new PostgresJSDialect({ postgres: postgres(databaseUrl), }), }); const db = new NPostgres(kysely); await db.migrate(); ``` -------------------------------- ### Creating Executable Policy File (Shell) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/strfry.md Shows how to create an empty file at a specified path (`/opt/policy.ts`) and make it executable using `sudo touch` and `sudo chmod +x`. This file will serve as the entrypoint for the Deno policy script. ```Shell sudo touch /opt/policy.ts sudo chmod +x /opt/policy.ts ``` -------------------------------- ### Initializing NDatabase with Kysely Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/sql.md Demonstrates how to initialize the NDatabase class by creating a Kysely instance connected to a database and passing it to the NDatabase constructor. It also shows calling db.migrate() to create necessary database tables. ```TypeScript import { NDatabase } from '@nostrify/db'; import { Kysely } from 'kysely'; const kysely = new Kysely(/* set up your database */); const db = new NDatabase(kysely); await db.migrate(); // create the database tables ``` -------------------------------- ### Initializing NDenoKv with Deno KV - TypeScript Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/denokv.md Demonstrates how to initialize the NDenoKv store by opening a Deno.Kv instance and passing it to the NDenoKv constructor. Requires the `@nostrify/denokv` package. ```TypeScript import { NDenoKv } from '@nostrify/denokv'; const kv = await Deno.openKv(); const db = new NDenoKv(kv); ``` -------------------------------- ### Configure VSCode MCP Server (JSON) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/mcp.md Defines the configuration for the Nostrify MCP server within a VSCode project's `.vscode/mcp.json` file, allowing GitHub Copilot to access the documentation via a stdio connection. ```json { "servers": { "nostrify": { "type": "stdio", "command": "deno", "args": [ "run", "-A", "jsr:@soapbox/docs-mcp", "--name", "Nostrify", "--site", "nostrify.dev" ] } } } ``` -------------------------------- ### Using the NDatabase Class with Kysely (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/packages/nostrify/README.md Shows how to set up and use the NDatabase class, which provides a SQLite storage adapter for Nostr events using Kysely. It requires creating a Kysely instance with a DenoSqliteDialect, passing it to the NDatabase constructor, migrating the database, and then using it as a regular NStore. ```TypeScript // Create a Kysely instance. const kysely = new Kysely({ dialect: new DenoSqliteDialect({ database: new Sqlite('./db.sqlite3'), }), }); // Pass Kysely into the constructor. const db = new NDatabase(kysely); // Migrate the database before use. await db.migrate(); // Now it's just a regular storage. await db.event(event1); await db.event(event2); const events = await db.query([{ kinds: [1] }]); ``` -------------------------------- ### Configuring PubkeyBanPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the PubkeyBanPolicy, showing how to provide an array of pubkeys. Events from these specific pubkeys will be banned from publishing to the relay. ```JavaScript ['e810...', 'fafa...', '1e89...'] ``` -------------------------------- ### Configuring HashtagPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the HashtagPolicy, showing how to provide an array of banned hashtags. Events containing any of these hashtags in their content will be rejected. ```JavaScript ['nsfw'] ``` -------------------------------- ### Initializing NDatabase with Kysely (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/packages/db/README.md Shows how to initialize the general-purpose NDatabase adapter for Nostrify, compatible with databases like SQLite and MySQL. It involves importing NDatabase and Kysely, configuring a Kysely instance for your specific database, creating an NDatabase instance using the Kysely object, and running migrations. ```TypeScript import { NDatabase } from '@nostrify/db'; import { Kysely } from 'kysely'; const kysely = new Kysely(/* set up your database */); const db = new NDatabase(kysely); await db.migrate(); ``` -------------------------------- ### Instantiating NWelshman Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/integrations/welshman.md Demonstrates how to import the `NWelshman` class from `@nostrify/welshman` and create a new instance. This class acts as a relay pool and requires a configured Welshman `router` object. ```ts import { NWelshman } from '@nostrify/welshman'; const pool = new NWelshman(router); ``` -------------------------------- ### Initializing NPhraseSigner with Mnemonic Phrase (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/README.md Shows how to create an `NPhraseSigner` instance from a BIP-39 mnemonic phrase. It supports optional account numbers and passphrases for derivation, converting the phrase to a seed internally, and demonstrates calling the public key and sign event methods. ```TypeScript const signer = new NPhraseSigner('abandon baby cabbage dad ...', { account: 0, // Optional account number. Default is 0. passphrase: 'very special mother', // Optional passphrase. Default is no passphrase. }); signer.getPublicKey(); signer.signEvent(t); ``` -------------------------------- ### Initializing NPool and Subscribing to Events (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/relay/pool.md This snippet demonstrates how to instantiate the NPool class, providing functions for opening relays (`open`), selecting relays for requests (`reqRelays`), and selecting relays for publishing events (`eventRelays`). It then shows how to use the initialized pool to subscribe to events using `pool.req` and process the incoming messages, specifically handling 'EVENT' and 'EOSE' types. ```TypeScript const pool = new NPool({ open(url) { return new NRelay1(url); }, async reqRelays(filters) { return [/* Return an array of relay URLs. */]; }, async eventRelays(event) { return [/* Return an array of relay URLs. */]; }, }); // Now you can use the pool like a regular relay. for await (const msg of pool.req([{ kinds: [1] }])) { if (msg[0] === 'EVENT') console.log(msg[2]); if (msg[0] === 'EOSE') break; } ``` -------------------------------- ### Instantiating and Using NPool for Multiple Relay Requests (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/README.md Illustrates how to instantiate the `NPool` class to manage connections and requests across multiple Nostr relays. It shows how to configure the pool with functions to open relay instances and determine which relays to use for requests (`reqRelays`) and event publishing (`eventRelays`), and then demonstrates using the `req` method to stream events from the configured pool of relays. ```ts const pool = new NPool({ open: (url) => new NRelay1(url), reqRelays: async (filters) => ['wss://relay1.mostr.pub', 'wss://relay2.mostr.pub'], eventRelays: async (event) => ['wss://relay1.mostr.pub', 'wss://relay2.mostr.pub'] }); // Now you can use the pool like a regular relay. for await (const msg of pool.req([{ kinds: [1] }])) { if (msg[0] === 'EVENT') console.log(msg[2]); if (msg[0] === 'EOSE') break; } ``` -------------------------------- ### Configuring InvertPolicy (JavaScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/index.md Example options for the InvertPolicy, showing how to wrap another policy instance. The InvertPolicy accepts an event if the wrapped policy *rejects* it, and rejects it if the wrapped policy *accepts* it. ```JavaScript new PubkeyBanPolicy([...]) ``` -------------------------------- ### Initializing NConnectSigner with Nostrify (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/sign/connect.md Demonstrates how to initialize the NConnectSigner class from the @nostrify/nostrify library. It requires creating a local signer (e.g., NSecSigner), a relay instance (NRelay1), and the remote user's pubkey to configure the NConnectSigner for remote signing via NIP-46. ```TypeScript import { NConnectSigner, NSecSigner, NRelay1 } from '@nostrify/nostrify'; import { generateSecretKey } from 'nostr-tools'; const local = new NSecSigner(generateSecretKey()); const relay = new NRelay1('wss://example.tld/relay'); const pubkey = /* get the user's pubkey */; const signer = new NConnectSigner({ pubkey, signer: local, relay, }); ``` -------------------------------- ### Using NPool to Connect and Request Events from Multiple Relays (JavaScript/TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/packages/nostrify/README.md Illustrates how to instantiate NPool with functions to determine which relays to use for opening connections, requesting events, and publishing events, and then using the req method similarly to NRelay1. ```TypeScript const pool = new NPool({ open: (url) => new NRelay1(url), reqRelays: async (filters) => ['wss://relay1.mostr.pub', 'wss://relay2.mostr.pub'], eventRelays: async (event) => ['wss://relay1.mostr.pub', 'wss://relay2.mostr.pub'], }); // Now you can use the pool like a regular relay. for await (const msg of pool.req([{ kinds: [1] }])) { if (msg[0] === 'EVENT') console.log(msg[2]); if (msg[0] === 'EOSE') break; } ``` -------------------------------- ### Implementing Event Publishing with NPool (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/relay/outbox.md Demonstrates how to configure the `eventRouter` function in an `NPool` instance to select relays for publishing events. It shows how to query the user's NIP-65 relay list from the outbox and use those relays, falling back to hardcoded ones if the list is empty. ```ts import { NPool, NRelay1 } from '@nostrify/nostrify'; import { outbox } from './outbox.ts'; export const pool = new NPool({ open(url) { return new NRelay1(url); }, // Get the relays to use for making requests. async reqRouter(filters) { /* Same as above. */ }, // Get the relays to use for publishing events. async eventRouter(event) { const relays = new Set(); // Get just the current user's relay list. const [relayList] = await outbox.query([ { kinds: [10002], authors: [event.pubkey], limit: 1 }, ]); // Gather relays from NIP-65 events. for (const [name, value] of relayList?.tags ?? []) { if (name === 'r') { try { const url = new URL(value).toString(); // Normalize the URL. relays.add(url); } catch (_e) { // skip } } } if (relays.size) { return [...relays]; } else { return ['wss://relay1.mostr.pub', 'wss://relay2.mostr.pub']; } }, }); ``` -------------------------------- ### Limiting Event Size with SizePolicy in TypeScript Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/all.md The SizePolicy rejects events that exceed a specified maximum size in bytes. This example demonstrates creating a policy to reject events larger than 8 kilobytes. ```TypeScript import { SizePolicy } from '@nostrify/policies'; // Reject events larger than 8 Kb. const policy = new SizePolicy({ maxBytes: 8 * 1024 }); ``` -------------------------------- ### Banning Pubkeys with PubkeyBanPolicy in TypeScript Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/policy/all.md The PubkeyBanPolicy allows rejecting events originating from a specific list of public keys. This example demonstrates creating a policy that will reject any events sent by the listed pubkeys. ```TypeScript import { PubkeyBanPolicy } from '@nostrify/policies'; // Reject events from these pubkeys. const policy = new PubkeyBanPolicy(['e810...', 'fafa...', '1e89...']); ``` -------------------------------- ### Creating a Welshman Router Instance Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/integrations/welshman.md Provides a template for creating a `Router` object from the `@welshman/util` library. This router is a dependency for `NWelshman` and defines the logic for relay selection and management. ```ts import { RelayMode, Router } from '@welshman/util'; const router = new Router({ getUserPubkey: (): string | null => null, getGroupRelays: (address: string): string[] => [], getCommunityRelays: (address: string): string[] => [], getPubkeyRelays: (pubkey: string, mode?: RelayMode): string[] => [], getStaticRelays: (): string[] => [], getIndexerRelays: (): string[] => [], getSearchRelays: (): string[] => [], getRelayQuality: (url: string): number => 1, getRedundancy: (): number => 2, getLimit: (): number => 10, }); ``` -------------------------------- ### Initializing NSeedSigner with HD Seed in TypeScript Source: https://github.com/soapbox-pub/nostrify/blob/main/packages/nostrify/README.md This snippet shows how to initialize `NSeedSigner` with an HD seed and an optional account index according to NIP-06. It illustrates calling `getPublicKey` and `signEvent` on the created signer instance. ```TypeScript const signer = new NSeedSigner(seed, 0); signer.getPublicKey(); signer.signEvent(t); ``` -------------------------------- ### Using the NDatabase Class with Kysely (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/README.md Illustrates how to use the `NDatabase` class, a SQLite storage adapter for Nostr events built on Kysely. It shows creating a Kysely instance with a Deno SQLite dialect, passing it to the `NDatabase` constructor, migrating the database, and then using it as a standard `NStore` for adding and querying events. ```typescript // Create a Kysely instance. const kysely = new Kysely({ dialect: new DenoSqliteDialect({ database: new Sqlite('./db.sqlite3'), }), }); // Pass Kysely into the constructor. const db = new NDatabase(kysely); // Migrate the database before use. await db.migrate(); // Now it's just a regular storage. await db.event(event1); await db.event(event2); const events = await db.query([{ kinds: [1] }]); ``` -------------------------------- ### Customizing NSet Storage with LRUCache (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/store/memory.md Illustrates how to provide a custom internal storage mechanism for `NSet` by passing a Map-like object to its constructor. This example uses an `LRUCache` instance to limit the number of events stored in the set. ```TypeScript import { LRUCache } from 'lru-cache'; const set = new NSet(new LRUCache({ max: 1000 })); ``` -------------------------------- ### Defining NostrSigner Interface (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/README.md Defines the `NostrSigner` TypeScript interface, mirroring the NIP-07 standard. This interface specifies the methods required for a Nostr signer, including getting the public key, signing events, and optional NIP-04/NIP-44 encryption/decryption methods. ```TypeScript /** NIP-07 Nostr signer. */ interface NostrSigner { /** Returns a public key as hex. */ getPublicKey(): Promise; /** Takes an event template, adds `id`, `pubkey` and `sig` and returns it. */ signEvent(event: Omit): Promise; /** Returns a record of relay URLs to relay policies. */ getRelays?(): Promise>; /** @deprecated NIP-04 crypto methods. Use `nip44` instead. */ nip04?: { /** @deprecated Returns ciphertext and iv as specified in NIP-04. */ encrypt(pubkey: string, plaintext: string): Promise; /** @deprecated Takes ciphertext and iv as specified in NIP-04. */ decrypt(pubkey: string, ciphertext: string): Promise; }; /** NIP-44 crypto methods. */ nip44?: { /** Returns ciphertext as specified in NIP-44. */ encrypt(pubkey: string, plaintext: string): Promise; /** Takes ciphertext as specified in NIP-44. */ decrypt(pubkey: string, ciphertext: string): Promise; }; } ``` -------------------------------- ### Converting Upload Result to imeta Tag (TypeScript) Source: https://github.com/soapbox-pub/nostrify/blob/main/docs/upload/index.md Illustrates how to transform the NIP-94 tags array into an `imeta` tag suitable for use in other Nostr event kinds, such as Kind 1. The example also shows how to embed the file URL within the event's content. ```TypeScript const imeta = await uploader.upload(file); const event = { kind: 1, content: `hello world!\n\n${url}`, tags: [ ['imeta', ...imeta.map((value) => value.join(' '))], ], }; ```