diff --git a/src/actions/nostr.ts b/src/actions/nostr.ts index b639537a3..b05ccb461 100644 --- a/src/actions/nostr.ts +++ b/src/actions/nostr.ts @@ -2,6 +2,7 @@ import { NostrSigner, NRelay1, NSecSigner } from '@nostrify/nostrify'; import { generateSecretKey } from 'nostr-tools'; import { NBunker } from 'soapbox/features/nostr/NBunker'; +import { keyring } from 'soapbox/features/nostr/keyring'; import { useBunkerStore } from 'soapbox/hooks/nostr/useBunkerStore'; import { type AppDispatch } from 'soapbox/store'; @@ -53,11 +54,13 @@ function logInNostr(signer: NostrSigner, relay: NRelay1) { const accessToken = dispatch(authLoggedIn(token)).access_token as string; const bunkerState = useBunkerStore.getState(); + keyring.add(authorization.seckey); + bunkerState.connect({ pubkey, accessToken, authorizedPubkey, - bunkerSeckey: authorization.seckey, + bunkerPubkey, }); await dispatch(verifyCredentials(accessToken)); diff --git a/src/hooks/nostr/useBunkerStore.ts b/src/hooks/nostr/useBunkerStore.ts index b7a40342c..2608df303 100644 --- a/src/hooks/nostr/useBunkerStore.ts +++ b/src/hooks/nostr/useBunkerStore.ts @@ -1,5 +1,5 @@ +import { NSchema as n } from '@nostrify/nostrify'; import { produce } from 'immer'; -import { nip19 } from 'nostr-tools'; import { z } from 'zod'; import { create } from 'zustand'; // eslint-disable-next-line import/extensions @@ -19,15 +19,15 @@ interface BunkerConnection { accessToken: string; /** Pubkey of the app authorized to sign events with this connection. */ authorizedPubkey: string; - /** Secret key for this connection. NIP-46 responses will be signed by this key. */ - bunkerSeckey: Uint8Array; + /** Pubkey for this connection. Secret key is stored in the keyring. NIP-46 responses will be signed by this key. */ + bunkerPubkey: string; } -const connectionSchema = z.object({ - pubkey: z.string(), +const connectionSchema: z.ZodType = z.object({ + pubkey: n.id(), accessToken: z.string(), - authorizedPubkey: z.string(), - bunkerSeckey: z.custom((value) => value instanceof Uint8Array), + authorizedPubkey: n.id(), + bunkerPubkey: n.id(), }); interface BunkerState { @@ -65,7 +65,7 @@ export const useBunkerStore = create()( getItem(name) { const value = localStorage.getItem(name); - const connections = jsonSchema(nsecReviver) + const connections = jsonSchema() .pipe(filteredArray(connectionSchema)) .catch([]) .parse(value); @@ -73,7 +73,7 @@ export const useBunkerStore = create()( return { state: { connections } }; }, setItem(name, { state }) { - localStorage.setItem(name, JSON.stringify(state.connections, nsecReplacer)); + localStorage.setItem(name, JSON.stringify(state.connections)); }, removeItem(name) { localStorage.removeItem(name); @@ -82,21 +82,3 @@ export const useBunkerStore = create()( }, ), ); - -/** Encode Uint8Arrays into nsec strings. */ -function nsecReplacer(_key: string, value: unknown): unknown { - if (value instanceof Uint8Array) { - return nip19.nsecEncode(value); - } - - return value; -} - -/** Decode nsec strings into Uint8Arrays. */ -function nsecReviver(_key: string, value: unknown): unknown { - if (typeof value === 'string' && value.startsWith('nsec1')) { - return nip19.decode(value as `nsec1${string}`).data; - } - - return value; -} \ No newline at end of file diff --git a/src/hooks/nostr/useSigner.ts b/src/hooks/nostr/useSigner.ts index fdae1c2a7..13eed0f72 100644 --- a/src/hooks/nostr/useSigner.ts +++ b/src/hooks/nostr/useSigner.ts @@ -1,6 +1,4 @@ -import { NSecSigner } from '@nostrify/nostrify'; import { useQuery } from '@tanstack/react-query'; -import { useMemo } from 'react'; import { keyring } from 'soapbox/features/nostr/keyring'; import { useAppSelector } from 'soapbox/hooks'; @@ -16,7 +14,7 @@ export function useSigner() { } }); - const { pubkey, bunkerSeckey, authorizedPubkey } = connection ?? {}; + const { pubkey, bunkerPubkey, authorizedPubkey } = connection ?? {}; const { data: signer, ...rest } = useQuery({ queryKey: ['nostr', 'signer', pubkey ?? ''], @@ -35,15 +33,9 @@ export function useSigner() { enabled: !!pubkey, }); - const bunkerSigner = useMemo(() => { - if (bunkerSeckey) { - return new NSecSigner(bunkerSeckey); - } - }, [bunkerSeckey]); - return { signer: signer ?? undefined, - bunkerSigner, + bunkerSigner: bunkerPubkey ? keyring.get(bunkerPubkey) : undefined, authorizedPubkey, ...rest, };