Skip to main content
Glama

convertNip19

Convert NIP-19 entities between formats like npub, nsec, note, hex, nprofile, nevent, and naddr for Nostr network compatibility.

Instructions

Convert any NIP-19 entity (npub, nsec, note, nprofile, nevent, naddr) to another format

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
inputYesThe NIP-19 entity or hex string to convert
targetTypeYesThe target format to convert to
relaysNoOptional relay URLs for complex entities (nprofile, nevent, naddr)
authorNoOptional author pubkey (hex format) for nevent/naddr
kindNoOptional event kind for nevent/naddr
identifierNoRequired identifier for naddr conversion

Implementation Reference

  • Main handler function that processes the tool inputs, constructs conversion options, calls the core convertNip19Entity function, and formats the response.
    export async function convertNip19(
      input: string,
      targetType: 'npub' | 'nsec' | 'note' | 'hex' | 'nprofile' | 'nevent' | 'naddr',
      relays?: string[],
      author?: string,
      kind?: number,
      identifier?: string
    ): Promise<{ success: boolean, message: string, result?: string, originalType?: string, data?: any }> {
      try {
        const options: ConversionInput = {
          input,
          targetType,
          entityData: {
            ...(relays && { relays }),
            ...(author && { author }),
            ...(kind && { kind }),
            ...(identifier && { identifier })
          }
        };
    
        const result = convertNip19Entity(options);
        
        if (!result.success) {
          return {
            success: false,
            message: result.message || 'Conversion failed'
          };
        }
    
        return {
          success: true,
          message: result.message || 'Conversion successful',
          result: result.result,
          originalType: result.originalType,
          data: result.data
        };
      } catch (error) {
        return {
          success: false,
          message: `Error during conversion: ${error instanceof Error ? error.message : 'Unknown error'}`
        };
      }
    }
  • Zod schema defining the input parameters for the convertNip19 tool.
    // Schema for convertNip19 tool
    export const convertNip19ToolConfig = {
      input: z.string().describe("The NIP-19 entity or hex string to convert"),
      targetType: z.enum(['npub', 'nsec', 'note', 'hex', 'nprofile', 'nevent', 'naddr']).describe("The target format to convert to"),
      relays: z.array(z.string()).optional().describe("Optional relay URLs for complex entities (nprofile, nevent, naddr)"),
      author: z.string().optional().describe("Optional author pubkey (hex format) for nevent/naddr"),
      kind: z.number().optional().describe("Optional event kind for nevent/naddr"),
      identifier: z.string().optional().describe("Required identifier for naddr conversion"),
    };
  • index.ts:999-1049 (registration)
    MCP server tool registration for 'convertNip19', including description, schema reference, and wrapper handler that calls the main convertNip19 function and formats MCP response.
    // Register NIP-19 conversion tools
    server.tool(
      "convertNip19",
      "Convert any NIP-19 entity (npub, nsec, note, nprofile, nevent, naddr) to another format",
      convertNip19ToolConfig,
      async ({ input, targetType, relays, author, kind, identifier }) => {
        try {
          const result = await convertNip19(input, targetType, relays, author, kind, identifier);
          
          if (result.success) {
            let response = `Conversion successful!\n\n`;
            response += `Original: ${result.originalType} entity\n`;
            response += `Target: ${targetType}\n`;
            response += `Result: ${result.result}\n`;
            
            if (result.originalType && ['nprofile', 'nevent', 'naddr'].includes(result.originalType)) {
              response += `\nOriginal entity data:\n${formatAnalysisResult(result.originalType, result.data)}`;
            }
            
            return {
              content: [
                {
                  type: "text",
                  text: response,
                },
              ],
            };
          } else {
            return {
              content: [
                {
                  type: "text",
                  text: `Conversion failed: ${result.message}`,
                },
              ],
            };
          }
        } catch (error) {
          console.error("Error in convertNip19 tool:", error);
          
          return {
            content: [
              {
                type: "text",
                text: `Error during conversion: ${error instanceof Error ? error.message : "Unknown error"}`,
              },
            ],
          };
        }
      },
    );
  • Core conversion logic that detects input type, decodes NIP-19 entities or validates hex, applies security filters, and performs the actual format conversion using snstr library functions.
    export function convertNip19Entity(options: ConversionInput): ConversionResult {
      try {
        const { input, targetType, entityData } = options;
        const cleanInput = input.trim();
    
        // First, detect what type of input we have
        let sourceData: any;
        let sourceType: string | undefined;
    
        // Try to decode as NIP-19 entity first
        if (cleanInput.includes('1')) {
          try {
            const decoded = decode(cleanInput as `${string}1${string}`);
            sourceType = decoded.type;
            sourceData = decoded.data;
          } catch (e) {
            // Not a valid NIP-19 entity, might be hex
          }
        }
    
        // If not NIP-19, check if it's hex
        if (!sourceType) {
          if (/^[0-9a-fA-F]{64}$/.test(cleanInput)) {
            sourceType = 'hex';
            sourceData = cleanInput.toLowerCase();
          } else {
            return {
              success: false,
              message: 'Input is not a valid NIP-19 entity or hex string'
            };
          }
        }
    
        // Apply security filtering for complex types
        if (['nprofile', 'nevent', 'naddr'].includes(sourceType)) {
          if (sourceType === 'nprofile') {
            sourceData = filterProfile(sourceData);
          } else if (sourceType === 'nevent') {
            sourceData = filterEvent(sourceData);
          } else if (sourceType === 'naddr') {
            sourceData = filterAddress(sourceData);
          }
        }
    
        // Now convert to target type
        let result: string;
    
        switch (targetType) {
          case 'hex':
            const hexResult = extractHexFromEntity(sourceType, sourceData);
            if (!hexResult) throw new Error('Cannot extract hex from input');
            result = hexResult;
            break;
    
          case 'npub':
            const pubkeyHex = extractHexFromEntity(sourceType, sourceData);
            if (!pubkeyHex) throw new Error('Cannot extract pubkey from input');
            result = encodePublicKey(pubkeyHex);
            break;
    
          case 'nsec':
            if (sourceType !== 'nsec' && sourceType !== 'hex') {
              throw new Error('Can only convert private keys to nsec format');
            }
            const privkeyHex = sourceData;
            result = encodePrivateKey(privkeyHex);
            break;
    
          case 'note':
            if (sourceType === 'nevent') {
              result = encodeNoteId(sourceData.id);
            } else if (sourceType === 'note') {
              result = cleanInput; // Already a note
            } else if (sourceType === 'hex') {
              result = encodeNoteId(sourceData);
            } else {
              throw new Error('Cannot convert this entity type to note format');
            }
            break;
    
          case 'nprofile':
            const profilePubkey = extractHexFromEntity(sourceType, sourceData);
            if (!profilePubkey) throw new Error('Cannot extract pubkey from input');
            
            const profileData = {
              pubkey: profilePubkey,
              relays: entityData?.relays?.filter(url => isValidRelayUrl(url)) || []
            };
            result = encodeProfile(profileData);
            break;
    
          case 'nevent':
            let eventId: string;
            if (sourceType === 'nevent') {
              eventId = sourceData.id;
            } else if (sourceType === 'note') {
              eventId = sourceData;
            } else if (sourceType === 'hex') {
              eventId = sourceData;
            } else {
              throw new Error('Cannot convert this entity type to nevent format');
            }
    
            const eventData = {
              id: eventId,
              relays: entityData?.relays?.filter(url => isValidRelayUrl(url)) || [],
              ...(entityData?.author && { author: entityData.author }),
              ...(entityData?.kind && { kind: entityData.kind })
            };
            result = encodeEvent(eventData);
            break;
    
          case 'naddr':
            if (!entityData?.identifier || !entityData?.kind) {
              throw new Error('naddr conversion requires identifier and kind');
            }
    
            const addrPubkey = extractHexFromEntity(sourceType, sourceData);
            if (!addrPubkey) {
              if (!entityData?.author) {
                throw new Error('naddr conversion requires a pubkey (from input or entityData.author)');
              }
            }
    
            const addressData = {
              identifier: entityData.identifier,
              pubkey: addrPubkey || entityData.author!,
              kind: entityData.kind,
              relays: entityData?.relays?.filter(url => isValidRelayUrl(url)) || []
            };
            result = encodeAddress(addressData);
            break;
    
          default:
            throw new Error(`Unsupported target type: ${targetType}`);
        }
    
        return {
          success: true,
          result,
          originalType: sourceType,
          targetType,
          message: `Successfully converted ${sourceType} to ${targetType}`,
          data: sourceData
        };
    
      } catch (error) {
        return {
          success: false,
          message: `Conversion failed: ${error instanceof Error ? error.message : 'Unknown error'}`
        };
      }
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/AustinKelsay/nostr-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server