### Installing Core Welshman Components (bash) Source: https://github.com/coracle-social/welshman/blob/master/docs/getting-started.md Shows how to install a basic set of core Welshman components, including utilities (`@welshman/util`), networking (`@welshman/net`), and signing (`@welshman/signer`), for developers who prefer to build their application by assembling individual modules. ```bash npm i @welshman/util @welshman/net @welshman/signer ``` -------------------------------- ### Installing the Full Welshman App Framework (bash) Source: https://github.com/coracle-social/welshman/blob/master/docs/getting-started.md Provides the npm command to install the complete `@welshman/app` framework, which is suitable for building a conventional client application using all components of the Welshman library. ```bash npm i @welshman/app ``` -------------------------------- ### Installing Welshman Content Module (bash) Source: https://github.com/coracle-social/welshman/blob/master/docs/getting-started.md Provides the npm command to install only the `@welshman/content` module, which is specifically designed for parsing and rendering content within an application. ```bash npm i @welshman/content ``` -------------------------------- ### Installing Individual Welshman Modules (bash) Source: https://github.com/coracle-social/welshman/blob/master/docs/getting-started.md Provides individual npm installation commands for each core module of the Welshman library, allowing users to install specific components like utilities, relay adapters, networking, signing, feeds, content processing, editor, store, or the full app framework based on their project needs. ```bash # Core nostr utilities (events, filters, tags) npm i @welshman/util # In-memory event store and relay adapter npm i @welshman/relay # Networking and relay management npm i @welshman/net # Event signing and encryption npm i @welshman/signer # Dynamic feed compilation npm i @welshman/feeds # Content parsing and rendering npm i @welshman/content # Rich text editor component npm i @welshman/editor # Svelte stores and state management npm i @welshman/store # Complete application framework npm i @welshman/app ``` -------------------------------- ### Installing Application Dependencies npm Shell Source: https://github.com/coracle-social/welshman/blob/master/README.md This standard command installs all dependencies listed in the application's package.json. Note that running `npm install` after successfully linking Welshman packages will likely break the links, requiring the linking process (specifically the command in the previous snippet) to be repeated. ```Shell npm install ``` -------------------------------- ### Setting up Multi-Target Executor (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/net/targets.md This comprehensive example demonstrates setting up an `Executor` using a `Multi` target that combines a `Local` relay for caching and a `Relays` target for network communication. It shows how to initialize this setup and subscribe to events, handling responses differently based on the source relay. ```typescript import { Executor, Multi, Local, Relays } from '@welshman/net' import {Repository, Relay} from '@welshman/util' // Setup const setupRelayInfrastructure = () => { // Create local repository & relay const repository = new Repository() const localRelay = new Relay(repository) // Get remote connections from pool const remoteConnections = [ pool.get("wss://relay1.example.com"), pool.get("wss://relay2.example.com") ] // Create multi-target executor const executor = new Executor( new Multi([ // Local relay for immediate responses new Local(localRelay), // Remote relays for network queries new Relays(remoteConnections) ]) ) // Subscribe using combined target const sub = executor.subscribe( [{kinds: [1], limit: 10}], { onEvent: (url, event) => { if (url === LOCAL_RELAY_URL) { console.log('Got from cache:', event) } else { console.log('Got from network:', url, event) } } } ) return {executor, sub} } ``` -------------------------------- ### Defining Example Zapper Configurations - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/zaps.md Provides concrete examples of `Zapper` objects manually configured for hypothetical Alby and LNbits providers. These examples illustrate how the `Zapper` interface properties would be populated with specific values, including `lnurl`, `pubkey`, `callback`, `nostrPubkey`, `allowsNostr`, `minSendable`, and `maxSendable` to represent different zapper setups. ```typescript // Example Alby zapper configuration const albyZapper: Zapper = { lnurl: "lnurl1...", pubkey: "alby_user_pubkey", nostrPubkey: "alby_signing_key", allowsNostr: true, minSendable: 1000, // 1 sat minimum maxSendable: 100000000 // 100k sats maximum } // Example LNbits zapper const lnbitsZapper: Zapper = { lnurl: "lnurl1...", callback: "https://lnbits.com/callback", nostrPubkey: "lnbits_signing_key", allowsNostr: true } ``` -------------------------------- ### Installing Package - npm - Bash Source: https://github.com/coracle-social/welshman/blob/master/docs/dvm/index.md This command demonstrates how to install the @welshman/dvm package using the npm package manager. ```bash npm install @welshman/dvm ``` -------------------------------- ### Installing @welshman/content (Bash) Source: https://github.com/coracle-social/welshman/blob/master/docs/content/index.md This snippet provides the standard command-line instruction to install the `@welshman/content` library using the npm package manager. It adds the package as a project dependency and requires npm to be installed. ```Bash npm install @welshman/content ``` -------------------------------- ### Initializing and Starting Basic DVM (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/dvm/handler.md Shows how to initialize and start a basic Data Vending Machine (DVM) instance using the `@welshman/dvm` library. It defines a simple handler for event kind 5001, instantiates the DVM with a private key, relays, the defined handler, expiration time, and mention requirement, and then starts the DVM. ```typescript import { DVM } from '@welshman/dvm' // Create handlers for different event kinds const handlers = { // Handler for kind 5001 "5001": (dvm: DVM) => ({ handleEvent: async function*(event: TrustedEvent) { // Process event and yield responses yield { kind: 6001, content: "Processed result", created_at: now(), tags: [] } } }) } // Initialize DVM const dvm = new DVM({ sk: "your-private-key", relays: ["wss://relay.example.com"], handlers, expireAfter: 3600, // 1 hour requireMention: true }) // Start the DVM await dvm.start() ``` -------------------------------- ### Installing @welshman/lib using npm - Shell Source: https://github.com/coracle-social/welshman/blob/master/docs/lib/index.md This snippet provides the command to install the @welshman/lib utility library using the npm package manager. It fetches the latest version from the npm registry and adds it as a dependency to your project. ```Shell npm install @welshman/lib ``` -------------------------------- ### Complete Example: Processing and Rendering Handlers (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/util/handlers.md Presents a comprehensive example showing how to process a handler event using `readHandlers` and `getHandlerKey` to populate a registry, how to find a handler by kind using `findHandler`, and how to structure data for display using `displayHandler` and other handler properties in `renderHandler`. ```typescript // Process handler information event function processHandlerEvent(event: TrustedEvent) { // Read all handlers from event const handlers = readHandlers(event) // Process each handler handlers.forEach(handler => { // Generate unique key const key = getHandlerKey(handler) // Store handler information handlerRegistry.set(key, { name: handler.name, kind: handler.kind, about: handler.about, image: handler.image, website: handler.website, address: getHandlerAddress(handler.event) }) }) } // Find handler for event kind function findHandler(kind: number): Handler | undefined { return Array.from(handlerRegistry.values()) .find(h => h.kind === kind) } // Display handler information function renderHandler(handler: Handler) { return { title: displayHandler(handler, "Unknown"), description: handler.about, icon: handler.image, website: handler.website || null } } ``` -------------------------------- ### Installing the Package - Bash Source: https://github.com/coracle-social/welshman/blob/master/docs/router/index.md This command demonstrates how to install the `@welshman/router` package using the npm package manager. It fetches the latest version of the package from the npm registry and adds it to the project's dependencies. ```bash npm install @welshman/router ``` -------------------------------- ### Installing Welshman Util Package - Shell Source: https://github.com/coracle-social/welshman/blob/master/docs/util/index.md This command installs the `@welshman/util` package from the npm registry. It is a prerequisite for using the utility functions and types provided by the package in a Node.js or browser environment. ```Shell npm install @welshman/util ``` -------------------------------- ### Installing npm Package (Bash) Source: https://github.com/coracle-social/welshman/blob/master/docs/store/index.md This command installs the @welshman/store package and its dependencies from the npm registry. It is the standard way to add the library to a Node.js project using the npm package manager. Running this command makes the library available for use in your project's code. ```bash npm install @welshman/store ``` -------------------------------- ### Installing Welshman Signer Library using npm in Bash Source: https://github.com/coracle-social/welshman/blob/master/docs/signer/index.md This command installs the `@welshman/signer` package from the npm registry. It's a standard dependency installation step using the Node Package Manager (npm), making the library available for use in a Node.js or web project. This requires Node.js and npm to be installed. ```bash npm install @welshman/signer ``` -------------------------------- ### Implementing Search DVM with Signal Handling (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/dvm/handler.md Presents a detailed example of implementing a DVM specifically for search requests (kind 5001). It defines a `createSearchHandler`, initializes the DVM with environment variables for the key and multiple relays, sets expiration and mention requirements, starts the DVM, and includes signal handling to gracefully stop the DVM on process interruption. ```typescript import { DVM, CreateDVMHandler } from '@welshman/dvm' import { now } from '@welshman/lib' // Create a search handler const createSearchHandler: CreateDVMHandler = (dvm) => ({ handleEvent: async function*(event) { const query = event.content const results = await performSearch(query) yield { kind: 6001, content: JSON.stringify(results), created_at: now(), tags: [ ["search", query], ["results", String(results.length)] ] } } }) // Initialize DVM const searchDVM = new DVM({ sk: process.env.DVM_KEY!, relays: ["wss://relay1.com", "wss://relay2.com"], handlers: { "5001": createSearchHandler }, expireAfter: 24 * 60 * 60, // 24 hours requireMention: true }) // Start DVM await searchDVM.start() // Stop DVM when needed process.on('SIGINT', () => { searchDVM.stop() }) ``` -------------------------------- ### Loading Nostr Profile with @welshman/net (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/net/subscribe.md Provides a real-world example of using the `subscribe` function to fetch a user's profile event (kind 0). It shows how to get optimal relays for a specific pubkey, set up the subscription with filters, and use a Promise to asynchronously wait for the first event before resolving and closing the subscription. ```typescript // Combine local and remote relays const loadProfile = async (pubkey: string) => { // Get optimal relays const relays = ctx.app.router .ForPubkey(pubkey) .getUrls() const sub = subscribe({ filters: [{ kinds: [0], authors: [pubkey], limit: 1 }], relays, // This creates internally: // 1. Connections via Pool // 2. Multi target with Local + Relays // 3. Executor to manage subscription }) return new Promise(resolve => { sub.on('event', (url, event) => { resolve(event) sub.close() }) }) } ``` -------------------------------- ### Installing Welshman App Package (Bash) Source: https://github.com/coracle-social/welshman/blob/master/docs/app/index.md This command uses npm (Node Package Manager) to install the @welshman/app package. This package contains the core framework for building Nostr clients. Node.js and npm are required prerequisites. ```bash npm install @welshman/app ``` -------------------------------- ### Installing @welshman/relay npm package (Bash) Source: https://github.com/coracle-social/welshman/blob/master/docs/relay/index.md Installs the @welshman/relay library using the npm package manager. This command is a required prerequisite for using the library in a project. ```bash npm install @welshman/relay ``` -------------------------------- ### Complete NIP-07 Signing Example - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/signer/nip-07.md This comprehensive example demonstrates a full workflow using the `Nip07Signer`. It includes checking for the provider, creating the signer, fetching the user's public key, signing a simple text note event, and encrypting a message using NIP-44, all mediated by the browser extension. It also includes basic error handling for cases like a missing provider or user rejecting a permission prompt. Required dependencies: `@welshman/signer`, `@welshman/util`. Input: `recipientPubkey` string for encryption. Output: Logs of the public key, signed event object, encrypted message string, or an error message if operations fail. ```typescript import { Nip07Signer, getNip07 } from '@welshman/signer'; import { createEvent, NOTE } from '@welshman/util'; async function example() { // Check for NIP-07 provider if (!getNip07()) { throw new Error('No NIP-07 provider found. Please install a Nostr browser extension.'); } // Create signer const signer = new Nip07Signer(); try { // Get public key (will prompt user) const pubkey = await signer.getPubkey(); console.log('Public key:', pubkey); // Create and sign an event (will prompt user) const event = createEvent(NOTE, { content: "Hello via browser extension!", tags: [["t", "test"]] }); const signedEvent = await signer.sign(event); console.log('Signed event:', signedEvent); // Encrypt a message (will prompt user) const recipientPubkey = "..."; const encrypted = await signer.nip44.encrypt(recipientPubkey, "Secret message"); console.log('Encrypted message:', encrypted); } catch (error) { // Handle user rejection or other errors console.error('Operation failed:', error); } } ``` -------------------------------- ### Installing Welshman Net NPM Package - Bash Source: https://github.com/coracle-social/welshman/blob/master/docs/net/index.md This command provides the standard way to install the @welshman/net library into a project using the npm package manager. It adds the library as a dependency to the project's package.json file. This requires Node.js and npm to be installed. ```bash npm install @welshman/net ``` -------------------------------- ### Installing @welshman/feeds Package Bash Source: https://github.com/coracle-social/welshman/blob/master/docs/feeds/index.md This command installs the @welshman/feeds package from the npm registry. It is a prerequisite for using the library in a JavaScript or TypeScript project. The command uses the npm package manager, which must be installed and configured. ```bash npm install @welshman/feeds ``` -------------------------------- ### Installing Dependency | Nostr Signer | Bash Source: https://github.com/coracle-social/welshman/blob/master/docs/signer/nip-55.md This command installs the necessary Capacitor plugin (`nostr-signer-capacitor-plugin`) which acts as the bridge between the web view/JavaScript code and the native mobile platform to interact with NIP-55 compatible signing applications. ```bash npm install nostr-signer-capacitor-plugin ``` -------------------------------- ### Querying with Multiple Filters Example - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/repository.md Provides an example showcasing how to use the `query` method with multiple filter objects simultaneously. The example demonstrates filtering by `kinds`, `authors`, and `since` timestamp in one filter, and by specific tag values (`#t`) and a `limit` in another, illustrating the repository's flexible query syntax. ```typescript // Query with multiple filters const events = repo.query([ // Recent events from specific authors { kinds: [1], authors: ['pub1', 'pub2'], since: now() - 24 * 60 * 60 }, // Events with specific tags { '#t': ['bitcoin', 'nostr'], limit: 50 } ]) ``` -------------------------------- ### Implementing Basic Sync and Pull Welshman Net Typescript Source: https://github.com/coracle-social/welshman/blob/master/docs/net/sync.md Provides two examples demonstrating the usage of the `sync` and `pull` functions. The `syncProfiles` example shows how to use `sync` to fetch profile (kind 0) events for specific pubkeys, specifying filters, target relays, and existing local events. The `loadFeed` example uses `pull` for an initial feed load (kind 1 events), defining filters, relays, and an `onEvent` callback for processing incoming events. These illustrate how to configure synchronization tasks based on specific event types and relay targets. ```typescript import {sync, pull, getFilterSelections} from '@welshman/net' // Sync user profile data const syncProfiles = async (pubkeys: string[]) => { await sync({ // What to sync filters: [{ kinds: [0], authors: pubkeys }], // Which relays relays: ctx.app.router .ForPubkeys(pubkeys) .getUrls(), // Local events to consider events: repository.query([{ kinds: [0], authors: pubkeys }]) }) } // Initial feed load with negentropy const loadFeed = async () => { await pull({ filters: [{ kinds: [1], limit: 100 }], relays: ctx.app.router .ForUser() .getUrls(), events: [], // No local events yet onEvent: (event) => { // Handle new events } }) } ``` -------------------------------- ### Displaying Nostr Profile Information (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/util/profile.md Provides examples for using the profile display helper functions. It shows how to use `displayProfile` to get a formatted name with a fallback, `displayPubkey` to get a shortened pubkey string from the profile's event, and `profileHasName` to conditionally display a name or fallback value based on profile availability. ```typescript // Display profile name const name = displayProfile(profile, "Anonymous") // Display pubkey const shortPubkey = displayPubkey(profile.event.pubkey) // => "npub1abc...xyz" // Check for name if (profileHasName(profile)) { showName(profile) } else { showPubkey(profile) } ``` -------------------------------- ### Quick Example: Parse, Truncate, Render (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/content/index.md This snippet provides a complete example workflow using `@welshman/content`, demonstrating how to import functions, parse multiline content with tags, optionally truncate the parsed output, and finally render the result as HTML with a custom base URL for entities. ```TypeScript import { parse, renderAsHtml, truncate } from '@welshman/content' // Parse and process content const parsed = parse({ content: ` Hello #nostr! Check out this note: nostr:note1... https://example.com/image.jpg `, tags: [["p", "pubkey123"]] }) // Truncate if needed const truncated = truncate(parsed, { maxLength: 500, mediaLength: 150 }) // Render as HTML const html = renderAsHtml(truncated, { entityBase: "https://your-app.com/" }).toString() ``` -------------------------------- ### Basic Repository Operations Example - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/repository.md Provides a simple example demonstrating core `Repository` usage in TypeScript. It shows how to instantiate a repository, add an event using `publish`, query events with a basic filter using `query`, and check if an event has been deleted using `isDeleted` before processing it. ```typescript // Create repository const repo = new Repository() // Add events repo.publish(event) // Query events const events = repo.query([ { kinds: [1], limit: 100 } ]) // Check event status if (!repo.isDeleted(event)) { processEvent(event) } ``` -------------------------------- ### Example: Creating a Nostr Bookmark List - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/list.md Demonstrates creating a bookmark list (kind 10003) using `makeList`. This example populates the `privateTags` with event IDs ('e' tags), indicating that bookmarks are typically kept private. ```typescript const bookmarks = makeList({ kind: 10003, privateTags: [ ['e', 'id1'], ['e', 'id2'] ] }) ``` -------------------------------- ### Using the Router Singleton - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/router/index.md This snippet demonstrates how to configure and use the global Router singleton provided by the @welshman/router package. It shows configuration using `Router.configure`, accessing the singleton with `Router.get`, and examples of using various relay selection methods like `FromPubkeys`, `PublishEvent`, and chaining options like `allowLocal`, `limit`, and `policy`. ```typescript import {routerContext, addMaximalFallbacks, Router} from '@welshman/router' // Configure the global router instance based on RouterOptions Router.configure({ defaultRelays: ['wss://relay.example.com/'], getPubkeyRelays: (pubkey, mode) => ['wss://myrelay.example.com/'], }) // Get the singleton and use it to select some relays const router = Router.get() // Get a hint based on pubkey router.FromPubkeys(pubkeys).getUrl() // Send an event to the author's outbox and mentions' inboxes router.PublishEvent(event).getUrls() // Try as hard as we can to find a quoted note router .FromPubkeys(event, quotedEventId, hints) .allowLocal(true) .allowOnion(true) .allowInsecure(true) .policy(addMaximalFallbacks) .limit(10) .getUrls() ``` -------------------------------- ### Basic Usage of normalizeUrl in TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/lib/normalize-url.md Shows simple examples of how to call the `normalizeUrl` function. The first example demonstrates prepending the default protocol, and the second shows how to use the `stripHash` option to remove the URL fragment. ```typescript normalizeUrl('example') //=> 'http://example' normalizeUrl('sindresorhus.com/about.html#contact', {stripHash: true}); //=> 'http://sindresorhus.com/about.html' ``` -------------------------------- ### Example: Using Handler Utility Functions (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/util/handlers.md Provides practical examples demonstrating the use of `getHandlerKey` to generate a unique identifier, `displayHandler` to format a handler's name with a fallback, and `getHandlerAddress` to extract the handler's address from an event's tags. ```typescript // Get unique handler identifier const key = getHandlerKey(handler) // => "1:30023:note-viewer" (kind:pubkey:identifier) // Display handler name const name = displayHandler(handler, "Unknown Handler") // => "Note Viewer" or fallback if handler undefined // Get handler address const address = getHandlerAddress(event) // Returns address from tags with 'web' marker or first address ``` -------------------------------- ### Examples of Simple and Complex Feed Definitions Source: https://github.com/coracle-social/welshman/blob/master/docs/feeds/core.md Provides various examples of instantiating feed definitions using the defined types, showcasing simple author and time-filtered feeds, a complex nested feed, and a DVM feed with inline mappings. ```typescript const authorFeed: Feed = [FeedType.Author, "pubkey1", "pubkey2"] ``` ```typescript const recentFeed: Feed = [ FeedType.CreatedAt, { since: Date.now() - 24 * 60 * 60 * 1000, // Last 24 hours relative: ["since"] } ] ``` ```typescript const complexFeed: Feed = [ FeedType.Intersection, [FeedType.Kind, 1], // Text notes [FeedType.WOT, { min: 0.5 }], // Trusted authors [ FeedType.Union, [FeedType.Scope, Scope.Follows], // From follows [FeedType.List, { addresses: ["list_id"] }] // Or from list ] ] ``` ```typescript const dvmFeed: Feed = [ FeedType.DVM, { kind: 5300, mappings: [ ["p", [FeedType.Author]], // Map 'p' tags to authors ["t", [FeedType.Tag, "#t"]] // Map 't' tags to hashtags ] } ] ``` -------------------------------- ### Complete Content Parsing and Processing Example - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/content/parser.md This comprehensive TypeScript example demonstrates the end-to-end workflow of the content parser system. It shows how to parse multi-line content including Nostr entities, code, and multiple images, then process links, optionally truncate the result, and finally iterate through the parsed elements using type guards to handle each type appropriately. ```typescript // Parse content with tags const parsed = parse({ content: ` Hello #nostr! Check out this note: nostr:note1... And this profile: nostr:npub1... Some code: \`console.log(\"hello\")\` https://example.com/image.jpg https://example.com/image2.jpg `, tags: [ ["p", "pubkey123"], ["e", "event456"] ] }) // Process the content const processed = reduceLinks(parsed) // Truncate if needed const final = truncate(processed, { maxLength: 500, mediaLength: 150 }) // Check types and handle accordingly final.forEach(item => { if (isImage(item)) { // Handle image } else if (isProfile(item)) { // Handle profile reference } else if (isCode(item)) { // Handle code block } }) ``` -------------------------------- ### Instantiating Nip46Broker - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/signer/nip-46.md This snippet illustrates the recommended way to obtain a `Nip46Broker` instance using the static `get` factory method. It also mentions direct instantiation, though the factory method is preferred for potential singleton management. ```typescript // Recommended: use the singleton factory const broker = Nip46Broker.get({ relays: string[], clientSecret: string, connectSecret?: string, signerPubkey?: string, algorithm?: "nip04" | "nip44" }) // Direct instantiation (not recommended) new Nip46Broker(params) ``` -------------------------------- ### Initializing Nip55Signer | Nostr Signer | TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/signer/nip-55.md This code demonstrates the basic steps to detect available NIP-55 compatible native signing applications using `getNip55` and then instantiate a `Nip55Signer` using the package name of the first detected app. It's the starting point for integrating native signing capabilities. ```typescript import { Nip55Signer, getNip55 } from '@welshman/signer' // Check for available signing apps const apps = await getNip55() if (apps.length > 0) { const signer = new Nip55Signer(apps[0].packageName) } ``` -------------------------------- ### Using Nip55Signer Example | Nostr Signer | TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/signer/nip-55.md This comprehensive asynchronous function demonstrates the full flow of using the `Nip55Signer`. It includes detecting apps, creating the signer instance, retrieving the user's public key, creating and signing a Nostr event, and performing NIP-44 encryption, all while handling potential errors. ```typescript import { Nip55Signer, getNip55 } from '@welshman/signer' import { createEvent, NOTE } from '@welshman/util' async function example() { try { // Get available signing apps const apps = await getNip55() if (apps.length === 0) { throw new Error('No native signing apps available') } // Create signer with first available app const signer = new Nip55Signer(apps[0].packageName) // Get public key const pubkey = await signer.getPubkey() console.log('Public key:', pubkey) // Sign an event const event = createEvent(NOTE, { content: "Hello from native app!", tags: [["t", "test"]] }) const signedEvent = await signer.sign(event) console.log('Signed event:', signedEvent) // Encrypt a message const encrypted = await signer.nip44.encrypt( recipientPubkey, "Secret message" ) console.log('Encrypted:', encrypted) } catch (error) { console.error('Native signer error:', error) } } ``` -------------------------------- ### Complete Asynchronous DVM Request Example (TypeScript/JS) Source: https://github.com/coracle-social/welshman/blob/master/docs/dvm/request.md This comprehensive example shows how to create a DVM request event, sign it, make the request with progress reporting enabled, and handle both progress updates and the final result within an asynchronous function. It also includes a mechanism to handle request timeouts and close the subscription. Dependencies include event creation/finalization and the DVM module. ```typescript import { makeDvmRequest, DVMEvent } from '@welshman/dvm' import { createEvent, finalizeEvent } from '@welshman/util' async function queryDVM() { // Create the request event const event = createEvent(5001, { content: JSON.stringify({ query: "search terms" }) }) // Sign the event const signedEvent = finalizeEvent(event, privateKey) // Make the request const dvmRequest = makeDvmRequest({ event: signedEvent, relays: ["wss://relay.example.com"], timeout: 30000, reportProgress: true }) // Handle progress updates dvmRequest.emitter.on(DVMEvent.Progress, (url, event) => { console.log('Progress:', event.content) }) // Return a promise that resolves with the result return new Promise((resolve, reject) => { const timeout = setTimeout(() => { dvmRequest.sub.close() reject(new Error('DVM request timeout')) }, 30000) dvmRequest.emitter.on(DVMEvent.Result, (url, event) => { clearTimeout(timeout) resolve(event) }) }) } ``` -------------------------------- ### Detailed NIP-59 Wrapping and Unwrapping Example TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/signer/nip-59.md This detailed example demonstrates the full flow of wrapping and unwrapping within an asynchronous function context. It shows how to instantiate `Nip59` using `Nip01Signer`, create a direct message event, wrap it using `nip59.wrap` (highlighting that the result includes both the original and wrapped versions), and subsequently unwrap a hypothetical received event. Requires `@welshman/signer` and `@welshman/util`. ```typescript import { Nip59, Nip01Signer } from '@welshman/signer' import { createEvent, DIRECT_MESSAGE } from '@welshman/util' async function example() { // Create NIP-59 instance const signer = new Nip01Signer(mySecret) const nip59 = Nip59.fromSigner(signer) // Create and wrap an event const event = createEvent(DIRECT_MESSAGE, { content: "Secret message", tags: [["p", recipientPubkey]] }) const rumor = await nip59.wrap(recipientPubkey, event) // rumor contains: // - The original event (rumor) // - The wrapped version to publish (rumor.wrap) // Later, unwrap a received event const unwrapped = await nip59.unwrap(receivedEvent) } ``` -------------------------------- ### Example: Creating a Private Nostr List - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/list.md Illustrates the process of creating a new private mute list. It demonstrates using `makeList` to initialize the list, `addToListPrivately` to add user public keys, and finally `reconcile` with an encrypt function to prepare the list data for encrypted publishing. ```typescript // Create new mute list const muteList = makeList({ kind: 10000, publicTags: [ ['d', 'mutes'], ['name', 'My Mute List'] ] }) // Add items privately const updated = addToListPrivately( muteList, ['p', 'pubkey1'], ['p', 'pubkey2'] ) // Encrypt and publish const encrypted = await updated.reconcile(encrypt) ``` -------------------------------- ### Example: Creating and Reading NIP-89 Handler Event (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/util/handlers.md Illustrates how to construct a sample event object conforming to the NIP-89 handler information format (kind 31990) and then uses the `readHandlers` function to parse this event into an array of structured `Handler` objects. ```typescript const event = { kind: 31990, // Handler Information kind content: JSON.stringify({ name: "Note Viewer", about: "Displays text notes with formatting", image: "https://example.com/icon.png" }), tags: [ ['k', '1'], // Handles kind 1 (text notes) ['d', 'note-viewer'] ] } const handlers = readHandlers(event) // Returns array of handlers defined in the event ``` -------------------------------- ### Linking Individual Welshman Package npm Shell Source: https://github.com/coracle-social/welshman/blob/master/README.md This command is executed within each specific package directory inside the cloned Welshman repository. It makes the package available for linking globally or within the local npm environment, preparing it to be referenced by a dependent application. ```Shell npm link ``` -------------------------------- ### Example: Creating a Nostr Relay List - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/list.md Shows how to create a relay list (kind 10002) using `makeList`. It includes relay addresses ('r' tags) in the `publicTags`, demonstrating how to specify relay URLs and optionally their usage (like 'write'). ```typescript const relays = makeList({ kind: 10002, publicTags: [[ ['r', 'wss://relay1.com'], ['r', 'wss://relay2.com', 'write'] ]] }) ``` -------------------------------- ### Understanding Internal Nostr Subscription Structure (@welshman/net, TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/net/subscribe.md Shows the underlying components used by the `subscribe` function in `@welshman/net`. It demonstrates how connections are obtained from a `Pool`, grouped into a `Relays` target, and managed by an `Executor`. Includes a manual implementation example mirroring the core steps for educational purposes. ```typescript import {subscribe, Pool, Executor, Relays} from '@welshman/net' // Under the hood, subscribe: // 1. Gets connections from global pool // 2. Creates a target (usually Relays) // 3. Uses Executor to manage subscription // This is roughly equivalent to: const manualSubscribe = (urls: string[]) => { // Get connections from pool const connections = urls.map(url => ctx.net.pool.get(url) ) // Create target const target = new Relays(connections) // Create executor const executor = new Executor(target) // Subscribe via executor return executor.subscribe( [{kinds: [1], limit: 10}], { onEvent: (url, event) => { console.log(`Got event from ${url}`) } } ) } ``` -------------------------------- ### Working with Nostr Event Threads Example (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/util/events.md Demonstrates how to use the thread-related utility functions to analyze event relationships. The example shows retrieving thread ancestors to find root and reply references and checking if one event is a direct child of another. ```typescript // Get thread context const ancestors = getAncestors(event) const rootId = ancestors.roots[0] const replyTo = ancestors.replies[0] // Check threading if (isChildOf(event, parentEvent)) { // Handle reply } ``` -------------------------------- ### Performing Basic Event Loading with FeedController - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/feeds/controller.md This example shows a straightforward usage pattern for the `FeedController`. After creating an instance with the necessary options, the `load` method is called with a limit of 20, initiating the process to fetch up to 20 events from the configured feed. ```typescript const controller = new FeedController(options) ``` ```typescript await controller.load(20) // Load 20 events ``` -------------------------------- ### Example: Collecting All References - Nostr Tags - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/tags.md This example demonstrates combining several tag extraction functions to collect all major reference types (events, profiles, addresses) from an event's tags into a single structured object. It showcases how the individual functions can be used together for comprehensive tag analysis. ```typescript // Collect all references function collectReferences(tags: string[][]) { return { events: getEventTagValues(tags), profiles: getPubkeyTagValues(tags), addresses: getAddressTagValues(tags) } } ``` -------------------------------- ### Using Nip46Broker Connection Methods - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/signer/nip-46.md This section outlines the key methods available on the `Nip46Broker` instance for managing the connection lifecycle, including generating a connection URL, waiting for user approval, getting a reusable bunker URL, and parsing a bunker URL. ```typescript // Generate a nostrconnect:// URL for the remote signer broker.makeNostrconnectUrl(metadata: Record): Promise // Wait for connection approval broker.waitForNostrconnect( url: string, abort?: AbortController ): Promise // Get bunker URL for later reconnection broker.getBunkerUrl(): string // Parse a bunker URL Nip46Broker.parseBunkerUrl(url: string): { signerPubkey: string, connectSecret: string, relays: string[] } ``` -------------------------------- ### Bulk Event Operations Example - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/repository.md Illustrates how to perform bulk operations using the `Repository`. It shows the `load` method being used to add a collection of events efficiently, specifying an optional `chunkSize` for processing, and the `dump` method for retrieving all events currently stored in the repository. ```typescript // Load multiple events repo.load(events, 500) // Process in chunks of 500 // Get all events const allEvents = repo.dump() ``` -------------------------------- ### Creating New Nostr Profile and Event (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/util/profile.md Provides an example demonstrating the usage of `makeProfile` to create a basic `Profile` object with key fields like name, about, picture, and lud16. It then shows how to use `createProfile` to generate a Nostr `EventTemplate` suitable for publishing this new profile. ```typescript // Create basic profile const profile = makeProfile({ name: "Alice", about: "Nostr user", picture: "https://example.com/avatar.jpg", lud16: "alice@getalby.com" }) // Create profile event const event = createProfile(profile) ``` -------------------------------- ### Examples of Tag Feed Mapping Usage Source: https://github.com/coracle-social/welshman/blob/master/docs/feeds/core.md Illustrates how to define and use `TagFeedMapping` arrays to transform event tags into specific feed types within DVM and List feed definitions. ```typescript // Example mappings const mappings: TagFeedMapping[] = [ // Convert 'p' tags into author feeds ["p", [FeedType.Author]], // Convert 't' tags into hashtag filters ["t", [FeedType.Tag, "#t"]], // Convert 'e' tags into event ID feeds ["e", [FeedType.ID]], // Convert 'r' tags into relay feeds ["r", [FeedType.Relay]] ] ``` ```typescript // Using mappings in a DVM feed const dvmFeed: Feed = [ FeedType.DVM, { kind: 5300, mappings: mappings } ] ``` ```typescript // Using mappings in a List feed const listFeed: Feed = [ FeedType.List, { addresses: ["list_id"], mappings: mappings } ] ``` -------------------------------- ### Using LRU Cache Basic Functions - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/lib/lru.md Demonstrates creating a cache instance with a maximum size, adding items using `set`, retrieving items using `get` (which marks them as recently used), checking for existence with `has`, and illustrating eviction when the size limit is reached. ```typescript // Create cache with max size const cache = new LRUCache(3) // Add items cache.set('a', 1) cache.set('b', 2) cache.set('c', 3) // Access items cache.get('a') // => 1 // Check if key exists cache.has('b') // => true // Adding beyond max size evicts least recently used cache.set('d', 4) // Evicts oldest item ``` -------------------------------- ### Example: Working with Nostr List Tags - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/list.md Provides examples of retrieving and filtering tags within a list. It shows using `getListTags` to get all tags and `removeFromListByPredicate` to remove tags that match a specific condition, such as removing all 'p' tags (representing people). ```typescript // Get all list tags const tags = getListTags(list) // Remove by predicate const noMentions = removeFromListByPredicate( list, tag => tag[0] === 'p' ) ``` -------------------------------- ### Compiling a Basic Author Feed (TypeScript) Source: https://github.com/coracle-social/welshman/blob/master/docs/feeds/compiler.md This example shows how to instantiate the `FeedCompiler` and compile a simple feed definition specifying multiple authors. The output demonstrates how this translates into a single `RequestItem` with a filter containing the specified authors, illustrating a basic use case for the compiler. ```typescript const compiler = new FeedCompiler(options) // Simple author feed const feed = [FeedType.Author, "pubkey1", "pubkey2"] const requests = await compiler.compile(feed) // => [{ filters: [{ authors: ["pubkey1", "pubkey2"] }] }] ``` -------------------------------- ### Example: Basic Tag Extraction - Nostr Tags - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/tags.md This example shows how to use the basic tag helper functions to extract different types of tags ('p', 't', 'r', 'e') from an event's tags. It demonstrates getting specific tag types, multiple types, and a single tag value, providing practical use cases for the core functions. ```typescript // Get specific tag types const pubkeys = getPubkeyTagValues(event.tags) const topics = getTopicTagValues(event.tags) const relays = getRelayTagValues(event.tags) // Get multiple tag types const refs = getTags(['p', 'e'], event.tags) // Get single tag const topic = getTagValue('t', event.tags) ``` -------------------------------- ### Creating a New Nostr List - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/list.md Defines and demonstrates the `makeList` function, used to create a new `List` object from base parameters and optional tags. The example shows how to initialize a mute list with a kind of 10000 and populate it with both public and private tags. ```typescript function makeList(list: ListParams & Partial): List // Example const muteList = makeList({ kind: 10000, publicTags: [['d', 'mutes']], privateTags: [['p', 'pubkey1'], ['p', 'pubkey2']] }) ``` -------------------------------- ### Following Best Practices - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/feeds/utils.md Provides examples of recommended practices when working with feed utilities: using factory functions for creation, type guards for safe type checking, transformation functions (like `feedsFromTags`) for dynamic feed generation, and traversal (`walkFeed`) for analysis or processing. ```typescript // Good const feed = makeAuthorFeed("pubkey1") // Avoid const feed = [FeedType.Author, "pubkey1"] ``` ```typescript if (isAuthorFeed(feed)) { const pubkeys = getFeedArgs(feed) // Properly typed } ``` ```typescript // Convert event tags to feeds const feeds = feedsFromTags(event.tags) // Convert filters to feeds const feed = feedFromFilter(filter) ``` ```typescript const kinds = new Set() walkFeed(feed, (node) => { if (isKindFeed(node)) { getFeedArgs(node).forEach(k => kinds.add(k)) } }) ``` -------------------------------- ### Retrieving All Tags from a Nostr List - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/list.md Defines and demonstrates the `getListTags` function, which retrieves all tags (both public and private) from a given `List` or `PublishedList`. The example shows calling the function on a list object to get a combined array of tags. ```typescript function getListTags(list: List | undefined): string[][] // Example const allTags = getListTags(list) // Combines public and private tags ``` -------------------------------- ### Initializing Nip07Signer - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/signer/nip-07.md This snippet shows the basic initialization of the `Nip07Signer` class. Once an instance is created, it is ready to perform signing, encryption, or public key retrieval operations by interacting with the user's NIP-07 browser extension. Operations will typically trigger prompts in the extension requiring user permission. Required dependencies: `@welshman/signer`. Input: None. Output: An instance of `Nip07Signer`. ```typescript import { Nip07Signer } from '@welshman/signer'; // Create a new signer instance const signer = new Nip07Signer(); // The extension will prompt the user for permission // when operations are performed ``` -------------------------------- ### Initializing Storage System with Adapters - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/app/storage.md Initializes the Welshman application's IndexedDB storage system. It requires the database name, version, and a configuration object for storage adapters. This example uses default adapters and adds a custom one, demonstrating the structure required for custom adapters including `keyPath`, `init`, and `sync` methods. ```typescript import {initStorage, defaultStorageAdapters} from '@welshman/app' // Use default storage adapters, which track important metadata events, // relays, handles, zappers, etc. await initStorage("my-db", 1, { ...defaultStorageAdapters, custom: { keyPath: "key", init: async () => console.log(await getAll("custom")), sync: () => { // Set up a listener for changes, using bulkPut to save records. // Return an unsubscribe function for cleanup }, }, }) ``` -------------------------------- ### Signing Nostr Event using Nip01Signer in TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/signer/index.md This snippet demonstrates initializing a NIP-01 signer instance with a generated secret and using it to sign a basic Nostr event. It requires the `@welshman/signer` and `@welshman/util` libraries installed. The `sign` method returns a promise that resolves with the signed event object. ```typescript import { makeEvent } from '@welshman/util' import { ISigner, Nip01Signer, makeSecret } from '@welshman/signer' const signer: ISigner = new Nip01Signer(makeSecret()) signer.sign(makeEvent(1)).then(signedEvent => console.log(signedEvent)) ``` -------------------------------- ### Example: Creating a Nostr Mute List - TypeScript Source: https://github.com/coracle-social/welshman/blob/master/docs/util/list.md Shows a specific use case of `makeList` for creating a mute list (kind 10000). It illustrates setting the 'd' tag to 'mutes' for identification and initializing with an empty private tags array, as mute lists typically keep muted users private. ```typescript const muteList = makeList({ kind: 10000, publicTags: [['d', 'mutes']], privateTags: [] // Keep muted users private }) ```