89 lines
2.9 KiB
TypeScript
89 lines
2.9 KiB
TypeScript
import { useNostr } from '@nostrify/react';
|
|
import { type NLoginType, NUser, useNostrLogin } from '@nostrify/react/login';
|
|
import { NRelay1, NSecSigner } from '@nostrify/nostrify';
|
|
import { nip19 } from 'nostr-tools';
|
|
import { useCallback, useMemo } from 'react';
|
|
|
|
import { useAuthor } from './useAuthor.ts';
|
|
import { NSecSignerBtc, NBrowserSignerBtc, NConnectSignerBtc } from '@/lib/bitcoin-signers';
|
|
import { signerWithNudge } from '@/lib/signerWithNudge';
|
|
|
|
export function useCurrentUser() {
|
|
const { nostr } = useNostr();
|
|
const { logins } = useNostrLogin();
|
|
|
|
const loginToUser = useCallback((login: NLoginType): NUser => {
|
|
let user: NUser;
|
|
let isBunkerConnected: (() => boolean) | undefined;
|
|
|
|
switch (login.type) {
|
|
case 'nsec': {
|
|
const sk = nip19.decode(login.data.nsec) as { type: 'nsec'; data: Uint8Array };
|
|
user = new NUser(login.type, login.pubkey, new NSecSignerBtc(sk.data));
|
|
break;
|
|
}
|
|
case 'bunker': {
|
|
const clientSk = nip19.decode(login.data.clientNsec) as { type: 'nsec'; data: Uint8Array };
|
|
const clientSigner = new NSecSigner(clientSk.data);
|
|
const bunkerRelays = login.data.relays;
|
|
|
|
user = new NUser(
|
|
login.type,
|
|
login.pubkey,
|
|
new NConnectSignerBtc({
|
|
relay: nostr.group(bunkerRelays),
|
|
pubkey: login.data.bunkerPubkey,
|
|
signer: clientSigner,
|
|
timeout: 60_000,
|
|
}),
|
|
);
|
|
|
|
// Called at nudge time to check whether any of the bunker's relay
|
|
// WebSockets are OPEN. Relay instances are shared with the main pool
|
|
// so pool.relays will contain them once they have been opened.
|
|
isBunkerConnected = () => bunkerRelays.some((url) => {
|
|
const relay = nostr.relay(url);
|
|
return relay instanceof NRelay1 && relay.socket.readyState === WebSocket.OPEN;
|
|
});
|
|
break;
|
|
}
|
|
case 'extension':
|
|
user = new NUser(login.type, login.pubkey, new NBrowserSignerBtc());
|
|
break;
|
|
// Other login types can be defined here
|
|
default:
|
|
throw new Error(`Unsupported login type: ${login.type}`);
|
|
}
|
|
return new NUser(user.method, user.pubkey, signerWithNudge(user.signer, isBunkerConnected));
|
|
}, [nostr]);
|
|
|
|
const users = useMemo(() => {
|
|
const users: NUser[] = [];
|
|
|
|
for (const login of logins) {
|
|
try {
|
|
const user = loginToUser(login);
|
|
users.push(user);
|
|
} catch (error) {
|
|
console.warn("Skipped invalid login", login.id, error);
|
|
}
|
|
}
|
|
|
|
return users;
|
|
}, [logins, loginToUser]);
|
|
|
|
const user = users[0] as NUser | undefined;
|
|
|
|
// The current user's kind 0 profile is served from useAuthor, which
|
|
// may resolve instantly if pre-cached by useFeed. Otherwise it fetches
|
|
// from relays in the background.
|
|
const author = useAuthor(user?.pubkey);
|
|
|
|
return {
|
|
user,
|
|
users,
|
|
...author.data,
|
|
isLoading: author.isLoading,
|
|
};
|
|
}
|