nostr-crypto-utils 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -50,3 +50,4 @@ export declare function neventEncode(eventId: string, relays?: string[], author?
50
50
  * @returns Decoded data with type and metadata
51
51
  */
52
52
  export declare function decode(str: string): Nip19Data;
53
+ export declare function encodeBytes(prefix: string, data: Uint8Array): string;
@@ -111,8 +111,7 @@ export function decode(str) {
111
111
  }
112
112
  }
113
113
  // Helper functions
114
- function encodeBytes(prefix, hex) {
115
- const data = Buffer.from(hex, 'hex');
114
+ export function encodeBytes(prefix, data) {
116
115
  const words = bech32.toWords(data);
117
116
  return bech32.encode(prefix, words, 1000);
118
117
  }
@@ -38,7 +38,6 @@ export async function verifyDelegation(delegation) {
38
38
  * @returns True if conditions are met
39
39
  */
40
40
  export function checkDelegationConditions(event, conditions) {
41
- const now = Math.floor(Date.now() / 1000);
42
41
  if (conditions.kind !== undefined && event.kind !== conditions.kind) {
43
42
  return false;
44
43
  }
@@ -4,20 +4,21 @@
4
4
  */
5
5
  import pino from 'pino';
6
6
  /**
7
- * Create a logger instance
7
+ * Create a logger instance with consistent configuration
8
+ * @param name - Component or module name for the logger
9
+ * @param _options - Optional additional configuration
10
+ * @returns Configured pino logger instance
8
11
  */
9
12
  export declare function createLogger(name: string, _options?: unknown): pino.Logger;
10
13
  /**
11
- * @description Simple logger utility
12
- */
13
- /**
14
- * Log a message with optional data
14
+ * Simple log function for basic logging needs
15
15
  * @param message - Message to log
16
- * @param data - Optional data to log
16
+ * @param data - Optional data to include
17
17
  */
18
18
  export declare function log(message: string, data?: unknown): void;
19
19
  /**
20
- * Logger instance for the application
20
+ * Default logger instance for the application
21
+ * Includes enhanced error handling and formatting
21
22
  */
22
23
  export declare const logger: pino.Logger;
23
24
  export type { Logger } from 'pino';
@@ -4,7 +4,10 @@
4
4
  */
5
5
  import pino from 'pino';
6
6
  /**
7
- * Create a logger instance
7
+ * Create a logger instance with consistent configuration
8
+ * @param name - Component or module name for the logger
9
+ * @param _options - Optional additional configuration
10
+ * @returns Configured pino logger instance
8
11
  */
9
12
  export function createLogger(name, _options) {
10
13
  return pino({
@@ -13,36 +16,56 @@ export function createLogger(name, _options) {
13
16
  transport: process.env.NODE_ENV === 'development' ? {
14
17
  target: 'pino-pretty',
15
18
  options: {
16
- colorize: true
19
+ colorize: true,
20
+ translateTime: 'HH:MM:ss',
21
+ ignore: 'pid,hostname',
17
22
  }
18
- } : undefined
23
+ } : undefined,
24
+ formatters: {
25
+ level: (label) => {
26
+ return { level: label.toUpperCase() };
27
+ }
28
+ }
19
29
  });
20
30
  }
21
31
  /**
22
- * @description Simple logger utility
23
- */
24
- /**
25
- * Log a message with optional data
32
+ * Simple log function for basic logging needs
26
33
  * @param message - Message to log
27
- * @param data - Optional data to log
34
+ * @param data - Optional data to include
28
35
  */
29
36
  export function log(message, data) {
30
37
  console.log(message, data);
31
38
  }
32
- // Export a default logger instance
33
39
  /**
34
- * Logger instance for the application
40
+ * Default logger instance for the application
41
+ * Includes enhanced error handling and formatting
35
42
  */
36
43
  export const logger = pino({
37
- name: 'default',
38
- level: 'info',
44
+ name: 'nostr-crypto-utils',
45
+ level: process.env.LOG_LEVEL || 'info',
46
+ transport: process.env.NODE_ENV === 'development' ? {
47
+ target: 'pino-pretty',
48
+ options: {
49
+ colorize: true,
50
+ translateTime: 'HH:MM:ss',
51
+ ignore: 'pid,hostname',
52
+ }
53
+ } : undefined,
39
54
  formatters: {
55
+ level: (label) => {
56
+ return { level: label.toUpperCase() };
57
+ },
40
58
  log: (obj) => {
41
59
  // Convert error objects to strings for better logging
42
60
  if (obj && typeof obj === 'object' && 'err' in obj) {
43
61
  const newObj = { ...obj };
44
62
  if (newObj.err instanceof Error) {
45
- newObj.err = newObj.err.message;
63
+ const err = newObj.err;
64
+ newObj.err = {
65
+ message: err.message,
66
+ stack: err.stack,
67
+ name: err.name,
68
+ };
46
69
  }
47
70
  return newObj;
48
71
  }
@@ -21,6 +21,12 @@ export interface ValidationResult {
21
21
  * ```
22
22
  */
23
23
  export declare function validateEvent(event: NostrEvent): ValidationResult;
24
+ /**
25
+ * Gets the hex representation of a public key
26
+ * @param pubkey - Public key in either hex or details format
27
+ * @returns Hex representation of the public key
28
+ */
29
+ export declare function getPublicKeyHex(pubkey: string): string;
24
30
  /**
25
31
  * Validates a signed Nostr event (NIP-01)
26
32
  * @category Validation
@@ -60,8 +60,8 @@ export function validateEvent(event) {
60
60
  * @param pubkey - Public key in either hex or details format
61
61
  * @returns Hex representation of the public key
62
62
  */
63
- function getPublicKeyHex(pubkey) {
64
- return typeof pubkey === 'string' ? pubkey : pubkey.hex;
63
+ export function getPublicKeyHex(pubkey) {
64
+ return pubkey.startsWith('npub1') ? pubkey.slice(5) : pubkey;
65
65
  }
66
66
  /**
67
67
  * Validates a signed Nostr event (NIP-01)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nostr-crypto-utils",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "A comprehensive TypeScript library for Nostr protocol implementation, supporting multiple NIPs with strict validation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,19 +0,0 @@
1
- import type { KeyPair, NostrEvent, SignedNostrEvent, ValidationResult } from './types';
2
- import { NostrEventKind } from './types';
3
- export declare function generatePrivateKey(): Promise<string>;
4
- export declare function generateKeyPair(seed?: string): Promise<KeyPair>;
5
- export declare function getPublicKey(privateKey: string): string;
6
- export declare function getEventHash(event: NostrEvent): Promise<string>;
7
- export declare function serializeEvent(event: NostrEvent): string;
8
- export declare function createEvent(params: {
9
- kind: NostrEventKind;
10
- content: string;
11
- tags?: string[][];
12
- created_at?: number;
13
- pubkey?: string;
14
- }): NostrEvent;
15
- export declare function signEvent(event: NostrEvent, privateKey: string): SignedNostrEvent;
16
- export declare function verifySignature(event: SignedNostrEvent): boolean;
17
- export declare function validateKeyPair(publicKey: string, privateKey: string): ValidationResult;
18
- export declare function encrypt(message: string, recipientPubKey: string, senderPrivKey: string): Promise<string>;
19
- export declare function decrypt(encryptedMessage: string, senderPubKey: string, recipientPrivKey: string): Promise<string>;
package/dist/functions.js DELETED
@@ -1,127 +0,0 @@
1
- import { schnorr } from '@noble/curves/secp256k1';
2
- import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
3
- import { sha256 } from '@noble/hashes/sha256';
4
- import * as secp256k1 from '@noble/secp256k1';
5
- import { generatePrivateKey as generateNostrPrivateKey } from 'nostr-tools';
6
- import { webcrypto } from 'node:crypto';
7
- import pino from 'pino';
8
- const logger = pino({
9
- level: process.env.LOG_LEVEL || 'info',
10
- transport: {
11
- target: 'pino-pretty',
12
- options: {
13
- colorize: true
14
- }
15
- }
16
- });
17
- // Configure crypto for Node.js and test environments
18
- let customCrypto;
19
- if (typeof window !== 'undefined' && window.crypto) {
20
- customCrypto = window.crypto;
21
- }
22
- else {
23
- customCrypto = webcrypto;
24
- }
25
- export async function generatePrivateKey() {
26
- return generateNostrPrivateKey();
27
- }
28
- export async function generateKeyPair(seed) {
29
- const privateKey = await generatePrivateKey();
30
- const publicKey = getPublicKey(privateKey);
31
- return { privateKey, publicKey };
32
- }
33
- export function getPublicKey(privateKey) {
34
- return secp256k1.getPublicKey(privateKey, true);
35
- }
36
- export async function getEventHash(event) {
37
- const serialized = serializeEvent(event);
38
- const hash = await sha256(new TextEncoder().encode(serialized));
39
- return bytesToHex(hash);
40
- }
41
- export function serializeEvent(event) {
42
- return JSON.stringify([
43
- 0,
44
- event.pubkey,
45
- event.created_at,
46
- event.kind,
47
- event.tags,
48
- event.content
49
- ]);
50
- }
51
- export function createEvent(params) {
52
- const { kind, content, tags = [], created_at = Math.floor(Date.now() / 1000), pubkey = '' } = params;
53
- return {
54
- kind,
55
- content,
56
- tags,
57
- created_at,
58
- pubkey,
59
- };
60
- }
61
- export function signEvent(event, privateKey) {
62
- const hash = getEventHash(event);
63
- const sig = secp256k1.sign(hash, privateKey);
64
- return {
65
- ...event,
66
- id: hash,
67
- sig: sig.toCompactHex(),
68
- };
69
- }
70
- export function verifySignature(event) {
71
- try {
72
- const hash = getEventHash(event);
73
- return schnorr.verify(event.sig, hash, event.pubkey);
74
- }
75
- catch (error) {
76
- logger.error('Failed to verify signature:', error);
77
- return false;
78
- }
79
- }
80
- export function validateKeyPair(publicKey, privateKey) {
81
- try {
82
- const derivedPublicKey = getPublicKey(privateKey);
83
- const isValid = derivedPublicKey === publicKey;
84
- return {
85
- isValid,
86
- error: isValid ? undefined : 'Public key does not match private key'
87
- };
88
- }
89
- catch (error) {
90
- return {
91
- isValid: false,
92
- error: error instanceof Error ? error.message : 'Unknown error'
93
- };
94
- }
95
- }
96
- export async function encrypt(message, recipientPubKey, senderPrivKey) {
97
- try {
98
- const sharedSecret = secp256k1.getSharedSecret(senderPrivKey, '02' + recipientPubKey);
99
- const sharedKey = await customCrypto.subtle.importKey('raw', sharedSecret.slice(1), { name: 'AES-CBC', length: 256 }, true, ['encrypt']);
100
- const iv = crypto.getRandomValues(new Uint8Array(16));
101
- const encrypted = await customCrypto.subtle.encrypt({ name: 'AES-CBC', iv }, sharedKey, new TextEncoder().encode(message));
102
- const encryptedArray = new Uint8Array(encrypted);
103
- const combined = new Uint8Array(iv.length + encryptedArray.length);
104
- combined.set(iv);
105
- combined.set(encryptedArray, iv.length);
106
- return bytesToHex(combined);
107
- }
108
- catch (error) {
109
- logger.error('Failed to encrypt:', error);
110
- throw error;
111
- }
112
- }
113
- export async function decrypt(encryptedMessage, senderPubKey, recipientPrivKey) {
114
- try {
115
- const sharedSecret = secp256k1.getSharedSecret(recipientPrivKey, '02' + senderPubKey);
116
- const sharedKey = await customCrypto.subtle.importKey('raw', sharedSecret.slice(1), { name: 'AES-CBC', length: 256 }, true, ['decrypt']);
117
- const encrypted = hexToBytes(encryptedMessage);
118
- const iv = encrypted.slice(0, 16);
119
- const ciphertext = encrypted.slice(16);
120
- const decrypted = await customCrypto.subtle.decrypt({ name: 'AES-CBC', iv }, sharedKey, ciphertext);
121
- return new TextDecoder().decode(decrypted);
122
- }
123
- catch (error) {
124
- logger.error('Failed to decrypt:', error);
125
- throw error;
126
- }
127
- }
package/dist/types.d.ts DELETED
@@ -1,82 +0,0 @@
1
- /**
2
- * @module nostr-crypto-utils/types
3
- * @description Type definitions for the nostr-crypto-utils library
4
- */
5
- export interface KeyPair {
6
- privateKey: string;
7
- publicKey: string;
8
- }
9
- export interface NostrEvent {
10
- kind: NostrEventKind;
11
- content: string;
12
- tags: string[][];
13
- created_at: number;
14
- pubkey: string;
15
- }
16
- export interface SignedNostrEvent extends NostrEvent {
17
- id: string;
18
- sig: string;
19
- }
20
- export interface ValidationResult {
21
- isValid: boolean;
22
- error?: string;
23
- }
24
- export interface EncryptionResult {
25
- ciphertext: string;
26
- iv: string;
27
- }
28
- export interface NostrFilter {
29
- ids?: string[];
30
- authors?: string[];
31
- kinds?: number[];
32
- since?: number;
33
- until?: number;
34
- limit?: number;
35
- search?: string;
36
- [key: string]: any;
37
- }
38
- export interface NostrSubscription {
39
- id: string;
40
- filters: NostrFilter[];
41
- }
42
- export interface NostrMessage {
43
- type: NostrMessageType;
44
- payload: any;
45
- }
46
- export interface NostrResponse {
47
- success: boolean;
48
- message?: string;
49
- data?: any;
50
- }
51
- export interface NostrError {
52
- code: string;
53
- message: string;
54
- details?: any;
55
- }
56
- export declare enum NostrEventKind {
57
- SET_METADATA = 0,
58
- TEXT_NOTE = 1,
59
- RECOMMEND_SERVER = 2,
60
- CONTACT_LIST = 3,
61
- ENCRYPTED_DIRECT_MESSAGE = 4,
62
- DELETE = 5,
63
- REPOST = 6,
64
- REACTION = 7,
65
- CHANNEL_CREATE = 40,
66
- CHANNEL_METADATA = 41,
67
- CHANNEL_MESSAGE = 42,
68
- CHANNEL_HIDE_MESSAGE = 43,
69
- CHANNEL_MUTE_USER = 44,
70
- REPORT = 1984,
71
- ZAP_REQUEST = 9734,
72
- ZAP = 9735
73
- }
74
- export declare enum NostrMessageType {
75
- EVENT = "EVENT",
76
- REQ = "REQ",
77
- CLOSE = "CLOSE",
78
- NOTICE = "NOTICE",
79
- EOSE = "EOSE",
80
- OK = "OK",
81
- AUTH = "AUTH"
82
- }
package/dist/types.js DELETED
@@ -1,33 +0,0 @@
1
- /**
2
- * @module nostr-crypto-utils/types
3
- * @description Type definitions for the nostr-crypto-utils library
4
- */
5
- export var NostrEventKind;
6
- (function (NostrEventKind) {
7
- NostrEventKind[NostrEventKind["SET_METADATA"] = 0] = "SET_METADATA";
8
- NostrEventKind[NostrEventKind["TEXT_NOTE"] = 1] = "TEXT_NOTE";
9
- NostrEventKind[NostrEventKind["RECOMMEND_SERVER"] = 2] = "RECOMMEND_SERVER";
10
- NostrEventKind[NostrEventKind["CONTACT_LIST"] = 3] = "CONTACT_LIST";
11
- NostrEventKind[NostrEventKind["ENCRYPTED_DIRECT_MESSAGE"] = 4] = "ENCRYPTED_DIRECT_MESSAGE";
12
- NostrEventKind[NostrEventKind["DELETE"] = 5] = "DELETE";
13
- NostrEventKind[NostrEventKind["REPOST"] = 6] = "REPOST";
14
- NostrEventKind[NostrEventKind["REACTION"] = 7] = "REACTION";
15
- NostrEventKind[NostrEventKind["CHANNEL_CREATE"] = 40] = "CHANNEL_CREATE";
16
- NostrEventKind[NostrEventKind["CHANNEL_METADATA"] = 41] = "CHANNEL_METADATA";
17
- NostrEventKind[NostrEventKind["CHANNEL_MESSAGE"] = 42] = "CHANNEL_MESSAGE";
18
- NostrEventKind[NostrEventKind["CHANNEL_HIDE_MESSAGE"] = 43] = "CHANNEL_HIDE_MESSAGE";
19
- NostrEventKind[NostrEventKind["CHANNEL_MUTE_USER"] = 44] = "CHANNEL_MUTE_USER";
20
- NostrEventKind[NostrEventKind["REPORT"] = 1984] = "REPORT";
21
- NostrEventKind[NostrEventKind["ZAP_REQUEST"] = 9734] = "ZAP_REQUEST";
22
- NostrEventKind[NostrEventKind["ZAP"] = 9735] = "ZAP";
23
- })(NostrEventKind || (NostrEventKind = {}));
24
- export var NostrMessageType;
25
- (function (NostrMessageType) {
26
- NostrMessageType["EVENT"] = "EVENT";
27
- NostrMessageType["REQ"] = "REQ";
28
- NostrMessageType["CLOSE"] = "CLOSE";
29
- NostrMessageType["NOTICE"] = "NOTICE";
30
- NostrMessageType["EOSE"] = "EOSE";
31
- NostrMessageType["OK"] = "OK";
32
- NostrMessageType["AUTH"] = "AUTH";
33
- })(NostrMessageType || (NostrMessageType = {}));