Git Nostr signer from currently-logged-in account

This commit is contained in:
Alex Gleason 2024-03-15 15:15:53 -05:00
parent 44411fdf29
commit a83916537a
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
5 changed files with 17 additions and 70 deletions

View file

@ -1,8 +1,5 @@
import { nip19 } from 'nostr-tools';
import { importEntities } from 'soapbox/entity-store/actions';
import { Entities } from 'soapbox/entity-store/entities';
import { signer } from 'soapbox/features/nostr/sign';
import { selectAccount } from 'soapbox/selectors';
import { isLoggedIn } from 'soapbox/utils/auth';
import { getFeatures, parseVersion, PLEROMA } from 'soapbox/utils/features';
@ -132,14 +129,8 @@ const noOp = () => new Promise(f => f(undefined));
const createAccount = (params: Record<string, any>) =>
async (dispatch: AppDispatch, getState: () => RootState) => {
const { instance } = getState();
const { nostrSignup } = getFeatures(instance);
const pubkey = (signer && nostrSignup) ? await signer.getPublicKey() : undefined;
dispatch({ type: ACCOUNT_CREATE_REQUEST, params });
return api(getState, 'app').post('/api/v1/accounts', params, {
headers: pubkey ? { authorization: `Bearer ${nip19.npubEncode(pubkey)}` } : undefined,
}).then(({ data: token }) => {
return api(getState, 'app').post('/api/v1/accounts', params).then(({ data: token }) => {
return dispatch({ type: ACCOUNT_CREATE_SUCCESS, params, token });
}).catch(error => {
dispatch({ type: ACCOUNT_CREATE_FAIL, error, params });

View file

@ -5,6 +5,14 @@ import { type AppDispatch } from 'soapbox/store';
import { verifyCredentials } from './auth';
import { closeModal } from './modals';
/** Log in with a Nostr pubkey. */
function logInNostr(pubkey: string) {
return (dispatch: AppDispatch) => {
const npub = nip19.npubEncode(pubkey);
return dispatch(verifyCredentials(npub));
};
}
/** Log in with a Nostr extension. */
function nostrExtensionLogIn() {
return async (dispatch: AppDispatch) => {
@ -13,10 +21,9 @@ function nostrExtensionLogIn() {
}
const pubkey = await window.nostr.getPublicKey();
const npub = nip19.npubEncode(pubkey);
dispatch(closeModal('NOSTR_SIGNIN'));
return dispatch(verifyCredentials(npub));
return dispatch(logInNostr(pubkey));
};
}

View file

@ -1,7 +1,8 @@
import { NRelay, NRelay1, NostrSigner } from '@soapbox/nspec';
import React, { createContext, useContext, useState, useEffect } from 'react';
import { signer } from 'soapbox/features/nostr/sign';
import { NKeys } from 'soapbox/features/nostr/keys';
import { useOwnAccount } from 'soapbox/hooks';
import { useInstance } from 'soapbox/hooks/useInstance';
interface NostrContextType {
@ -20,8 +21,13 @@ export const NostrProvider: React.FC<NostrProviderProps> = ({ children }) => {
const instance = useInstance();
const [relay, setRelay] = useState<NRelay1>();
const { account } = useOwnAccount();
const url = instance.nostr?.relay;
const pubkey = instance.nostr?.pubkey;
const accountPubkey = account?.nostr.pubkey;
const signer = (accountPubkey ? NKeys.get(accountPubkey) : undefined) ?? window.nostr;
useEffect(() => {
if (url) {

View file

@ -1,44 +0,0 @@
import { hexToBytes } from '@noble/hashes/utils';
import { type NostrSigner, type NostrEvent, NSecSigner } from '@soapbox/nspec';
/** Use key from `localStorage` if available, falling back to NIP-07. */
export class SoapboxSigner implements NostrSigner {
#signer: NostrSigner;
constructor() {
const privateKey = localStorage.getItem('soapbox:nostr:privateKey');
const signer = privateKey ? new NSecSigner(hexToBytes(privateKey)) : window.nostr;
if (!signer) {
throw new Error('No Nostr signer available');
}
this.#signer = signer;
}
async getPublicKey(): Promise<string> {
return this.#signer.getPublicKey();
}
async signEvent(event: Omit<NostrEvent, 'id' | 'pubkey' | 'sig'>): Promise<NostrEvent> {
return this.#signer.signEvent(event);
}
nip04 = {
encrypt: (pubkey: string, plaintext: string): Promise<string> => {
if (!this.#signer.nip04) {
throw new Error('NIP-04 not supported by signer');
}
return this.#signer.nip04.encrypt(pubkey, plaintext);
},
decrypt: (pubkey: string, ciphertext: string): Promise<string> => {
if (!this.#signer.nip04) {
throw new Error('NIP-04 not supported by signer');
}
return this.#signer.nip04.decrypt(pubkey, ciphertext);
},
};
}

View file

@ -1,13 +0,0 @@
import { type NostrSigner } from '@soapbox/nspec';
import { SoapboxSigner } from './SoapboxSigner';
let signer: NostrSigner | undefined;
try {
signer = new SoapboxSigner();
} catch (_) {
// No signer available
}
export { signer };