web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

commit 9be97c83006f2a88302d8b5705c4e6755a215170
parent b9af45317927dddd4b6f8f82d211e55afcb5dbd3
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Fri, 30 Aug 2024 21:19:42 +0000

client: add iclientnostrlib

Diffstat:
Mclient/package.json | 4+++-
Mclient/src/nostr/index.ts | 6++++++
Aclient/src/nostr/lib.ts | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mclient/src/types.ts | 21+++++++++++++++++++--
4 files changed, 144 insertions(+), 3 deletions(-)

diff --git a/client/package.json b/client/package.json @@ -21,6 +21,7 @@ "@capacitor/share": "^6.0.0", "@capacitor/splash-screen": "^6.0.0", "@capacitor/status-bar": "^6.0.0", + "@noble/hashes": "^1.4.0", "@nostr-dev-kit/ndk": "^2.7.1", "@radroots/capacitor-bluetooth-le": "workspace:*", "@radroots/capacitor-date-picker": "workspace:*", @@ -29,7 +30,8 @@ "@radroots/capacitor-sqlite": "workspace:*", "@radroots/capacitor-wifi": "workspace:*", "@radroots/models": "workspace:*", - "@radroots/utils": "workspace:*" + "@radroots/utils": "workspace:*", + "nostr-tools": "^2.7.2" }, "devDependencies": { "typescript": "^5.3.3" diff --git a/client/src/nostr/index.ts b/client/src/nostr/index.ts @@ -1,10 +1,16 @@ import type { IClientNostr } from "../types"; import { ClientNostrEvents } from "./events"; +import { ClientNostrLib } from "./lib"; export class ClientNostr implements IClientNostr { private _ev: ClientNostrEvents = new ClientNostrEvents(); + private _lib: ClientNostrLib = new ClientNostrLib(); public get ev() { return this._ev; } + + public get lib() { + return this._lib; + } } \ No newline at end of file diff --git a/client/src/nostr/lib.ts b/client/src/nostr/lib.ts @@ -0,0 +1,116 @@ +import { bytesToHex, hexToBytes } from '@noble/hashes/utils'; +import { Relay, generateSecretKey, getPublicKey, nip19, } from 'nostr-tools'; +import type { IClientNostrLib, IClientNostrLibRelayConnectResponse } from '../types'; + +export class ClientNostrLib implements IClientNostrLib { + private generate_key_bytes(): Uint8Array { + const secret_key = generateSecretKey(); + return secret_key; + }; + + private get_key_hex(bytes: Uint8Array): string { + const hex = bytesToHex(bytes); + return hex; + }; + + private get_key_bytes(hex: string): Uint8Array { + const bytes = hexToBytes(hex); + return bytes; + }; + + public async relay_connect(url: string): Promise<IClientNostrLibRelayConnectResponse | undefined> { + try { + + if (!url) return undefined; + const conn = await Relay.connect(url); + if (conn && typeof conn.connected === `boolean` && typeof conn.url === `string` && conn.url) return { url: conn.url, connected: conn.connected }; + return undefined; + } catch (e) { + return undefined; + }; + } + + /** + * + * @returns nostr secret key hex + */ + public generate_key(): string { + const bytes = this.generate_key_bytes(); + const hex = this.get_key_hex(bytes); + return hex; + }; + + /** + * + * @returns nostr public key hex + */ + public public_key(secret_key_hex: string | undefined): string { + if (!secret_key_hex) throw new Error('Error: Secret key hex'); + const bytes = this.get_key_bytes(secret_key_hex); + const hex = getPublicKey(bytes) + return hex; + } + + /** + * + * @returns nostr public key npub + */ + public npub(public_key_hex: string | undefined): string { + if (!public_key_hex) throw new Error(`Error: public_key_hex must be defined`); + const npub = nip19.npubEncode(public_key_hex) + return npub; + } + + /** + * + * @returns public key hex from npub + */ + public npub_decode(npub: string): string { + const hex = nip19.decode(npub); + if (hex && hex.type === `npub` && hex.data) return hex.data + return ``; + } + + /** + * + * @returns nostr secret key nsec + */ + public nsec(secret_key_hex: string | undefined): string { + if (!secret_key_hex) return ``; + const bytes = this.get_key_bytes(secret_key_hex); + const nsec = nip19.nsecEncode(bytes); + return nsec; + } + + /** + * + * @returns nostr secret key hex from nsec + */ + public nsec_decode(nsec: string): string | undefined { + if (!nsec) return undefined; + const decode = nip19.decode(nsec); + if (decode && decode.type === `nsec` && decode.data && typeof decode.data === `string`) return decode.data + return undefined; + } + + /** + * + * @returns nostr public key nprofile + */ + public nprofile(public_key_hex: string, relays: string[]): string { + if (!public_key_hex || !relays.length) return ``; + const nprofile = nip19.nprofileEncode({ pubkey: public_key_hex, relays }) + return nprofile; + } + + /** + * + * @returns nostr public key nprofile + */ + public nprofile_decode(nprofile: string): [string, string[]] | undefined { + if (!nprofile) return undefined; + const decode = nip19.decode(nprofile); + if (decode && decode.type === `nprofile` && decode.data && decode.data.pubkey && decode.data.relays) return [decode.data.pubkey, decode.data.relays] + return undefined; + } +}; diff --git a/client/src/types.ts b/client/src/types.ts @@ -27,6 +27,7 @@ export type IClient = { export type IClientNostr = { ev: IClientNostrEvents; + lib: IClientNostrLib }; export type IClientPlatform = `androiď` | `ios` | `web`; @@ -260,4 +261,21 @@ export type IClientSettings = { export type IClientNostrEvents = { first_tag_value(event: NDKEvent, tag_name: string): string; -}; -\ No newline at end of file +}; + +export type IClientNostrLibRelayConnectResponse = { + url: string; + connected: boolean; +}; + +export type IClientNostrLib = { + relay_connect(url: string): Promise<IClientNostrLibRelayConnectResponse | undefined>; + generate_key(): string; + public_key(secret_key_hex: string | undefined): string; + npub(public_key_hex: string | undefined): string; + npub_decode(npub: string): string; + nsec(secret_key_hex: string | undefined): string; + nsec_decode(nsec: string): string | undefined; + nprofile(public_key_hex: string, relays: string[]): string; + nprofile_decode(nprofile: string): [string, string[]] | undefined; +};