Skip to content

Commit

Permalink
remove responsbility of serializing/loading wallet configurations -- …
Browse files Browse the repository at this point in the history
…apps should own that responsibility
  • Loading branch information
pablof7z committed Feb 20, 2025
1 parent ac6cb6e commit b279b5c
Show file tree
Hide file tree
Showing 10 changed files with 27 additions and 72 deletions.
4 changes: 2 additions & 2 deletions docs/mobile/session.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ return (<View>
Now say you want to allow the user to bookmark something with the click of a button:
```tsx
const { imageCurationSet } = useNDKSessionEventKind<NDKList>(NDKList, NDKKind.ImageCurationSet, {
create: true,
const { imageCurationSet } = useNDKSessionEventKind<NDKList>(NDKKind.ImageCurationSet, {
create: NDKList,
});

const bookmark = async () => {
Expand Down
36 changes: 6 additions & 30 deletions ndk-mobile/src/hooks/session.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import NDK, { NDKEvent, NDKKind, NDKUser } from '@nostr-dev-kit/ndk';
import { useState, useEffect } from 'react';
import { useNDK } from './ndk.js';
import { NDKEventWithFrom, NDKEventWithAsyncFrom } from './subscribe.js';
import { NDKEventWithFrom } from './subscribe.js';
import { useNDKSession } from '../stores/session/index.js';

const useNDKSessionInit = () => {
Expand All @@ -24,51 +23,29 @@ const useWOT = () => useNDKSession(s => s.wot);

/**
* This hook allows you to get a specific kind, wrapped in the event class you provide.
* Note that the wrapping must be specified when requesting the event from the NDKSession initializer.
* @param EventClass
* @param kind
* @param opts.create - If true, and the event kind is not found, an unpublished event will be provided.
* @returns
*/
const useNDKSessionEventKind = <T extends NDKEvent>(
EventClass: NDKEventWithFrom<any>,
kind?: NDKKind,
{ create }: { create: boolean } = { create: false }
kind: NDKKind,
{ create }: { create: NDKEventWithFrom<any> | false } = { create: false }
): T | undefined => {
kind ??= EventClass.kind;
const { ndk } = useNDK();
const events = useNDKSession(s => s.events);
const kindEvents = events.get(kind) || [];
const firstEvent = kindEvents[0];

if (create && !firstEvent) {
const event = new EventClass(ndk, { kind });
const event = new create(ndk, { kind });
event.kind = kind;
events.set(kind, [event]);
return event;
}

return firstEvent ? EventClass.from(firstEvent) : undefined;
};

const useNDKSessionEventKindAsync = <T>(
EventClass: NDKEventWithAsyncFrom<any>,
kind?: NDKKind,
{ create }: { create: boolean } = { create: false }
): T | undefined => {
kind ??= EventClass.kind;
const events = useNDKSession(s => s.events);
const kindEvents = events.get(kind) || [];
const firstEvent = kindEvents[0];
const [res, setRes] = useState<T | undefined>(undefined);

useEffect(() => {
if (!firstEvent) return;
EventClass.from(firstEvent).then((event) => {
setRes(event);
});
}, [firstEvent]);

return res;
return firstEvent as T;
};

const useNDKSessionEvents = <T extends NDKEvent>(
Expand All @@ -94,5 +71,4 @@ export {
useNDKSessionEventKind,
useNDKSessionEvents,
useNDKSessionInit,
useNDKSessionEventKindAsync,
};
1 change: 1 addition & 0 deletions ndk-mobile/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './cache-adapter/sqlite.js';
export * from './components/index.js';
export * from './components/relays/index.js';
export * from './signers/index.js';
export * from './stores/session/index.js';
export * from '@nostr-dev-kit/ndk';
export * as DBCache from './db/index.js';
import NDK from '@nostr-dev-kit/ndk';
Expand Down
9 changes: 0 additions & 9 deletions ndk-mobile/src/stores/ndk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,10 @@ export const useNDKStore = create<State & Actions & EventHandler>((set, get) =>
settingsStore.delete('wot.last_updated_at');
settingsStore.delete('wot.length');
settingsStore.delete('ndkMobileSessionLastEose');
settingsStore.delete('wallet');

// nuke the database
if (ndk.cacheAdapter instanceof NDKCacheAdapterSqlite) {
ndk.cacheAdapter.clear();
}
}
}))

function getUserFromSettingsStore(ndk: NDK, settingsStore?: SettingsStore) {
const currentUser = settingsStore?.getSync('currentUser');
if (currentUser) {
return ndk.getUser({pubkey: currentUser});
}
return null;
}
2 changes: 2 additions & 0 deletions ndk-mobile/src/stores/session/actions/addEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export const addEvent = (event: NDKEvent, onAdded, set) => {
const newEvents = new Map(state.events);
let existing = newEvents.get(kind) || [];

console.log('\tadding event', event.kind);

if (event.isParamReplaceable()) {
const existingEvent = existing.find((e) => e.dTag === event.dTag);
if (existingEvent) {
Expand Down
2 changes: 0 additions & 2 deletions ndk-mobile/src/stores/session/actions/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ export const initSession = (
// if we have already eosed, get the pubkeys that are not in the wotEntries and add them to the wotEntries
if (eosed && opts.wot) {
const newEntries = follows.filter((pubkey) => !wotEntries.has(pubkey));
console.log('eosed, adding wot entries', follows.length, newEntries.length);
addWotEntries(ndk, newEntries, settingsStore, set, () => {
on.onWotReady?.();
});
Expand All @@ -97,7 +96,6 @@ export const initSession = (
settingsStore?.set?.('ndkMobileSessionLastEose', Math.floor(Date.now() / 1000).toString())

if (opts.wot) {
console.log('shouldUpdateWot', shouldUpdateWot(ndk, settingsStore));
if (shouldUpdateWot(ndk, settingsStore)) {
addWotEntries(ndk, follows, settingsStore, set, () => {
on.onWotReady?.();
Expand Down
17 changes: 10 additions & 7 deletions ndk-wallet/src/wallets/cashu/wallet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import NDK, { NDKEvent, NDKKind, NDKPrivateKeySigner, NDKRelaySet, NDKUser } fro
import { NDKCashuDeposit } from "../deposit.js";
import createDebug from "debug";
import type { MintUrl } from "../mint/utils.js";
import type { CashuWallet, MintKeys, Proof, SendResponse } from "@cashu/cashu-ts";
import { getDecodedToken } from "@cashu/cashu-ts";
import type { CashuWallet, GetInfoResponse, MintKeys, Proof, SendResponse } from "@cashu/cashu-ts";
import { CashuMint, getDecodedToken } from "@cashu/cashu-ts";
import { consolidateTokens } from "../validate.js";
import { NDKWallet, NDKWalletBalance, NDKWalletEvents, NDKWalletStatus } from "../../index.js";
import { EventEmitter } from "tseep";
Expand All @@ -36,7 +36,6 @@ export type WalletWarning = {
import { PaymentHandler, PaymentWithOptionalZapInfo } from "./payment.js";
import { createInTxEvent, createOutTxEvent } from "./txs.js";
import { WalletState } from "./state/index.js";
import { MintInfo } from "@cashu/cashu-ts/dist/lib/es5/model/MintInfo.js";

/**
* This class tracks state of a NIP-60 wallet
Expand Down Expand Up @@ -79,12 +78,12 @@ export class NDKCashuWallet extends EventEmitter<NDKWalletEvents & {
* Called when the wallet needs to load mint info. Use this
* to load mint info from a database or other source.
*/
public onMintInfoNeeded?: (mint: string) => Promise<MintInfo | undefined>;
public onMintInfoNeeded?: (mint: string) => Promise<GetInfoResponse | undefined>;

/**
* Called when the wallet has loaded mint info.
*/
public onMintInfoLoaded?: (mint: string, info: MintInfo) => void;
public onMintInfoLoaded?: (mint: string, info: GetInfoResponse) => void;

/**
* Called when the wallet needs to load mint keys. Use this
Expand Down Expand Up @@ -412,12 +411,16 @@ export class NDKCashuWallet extends EventEmitter<NDKWalletEvents & {
async cashuWallet(mint: string): Promise<CashuWallet> {
if (this.wallets.has(mint)) return this.wallets.get(mint) as CashuWallet;

const mintInfo = await this.onMintInfoNeeded?.(mint);
let mintInfo = await this.onMintInfoNeeded?.(mint);
const mintKeys = await this.onMintKeysNeeded?.(mint);

if (!mintInfo && this.onMintInfoLoaded) {
mintInfo = await CashuMint.getInfo(mint);
this.onMintInfoLoaded?.(mint, mintInfo);
}

const w = await walletForMint(mint, { mintInfo, mintKeys });

if (w?.mintInfo) this.onMintInfoLoaded?.(mint, w.mintInfo);
if (w?.keys) this.onMintKeysLoaded?.(mint, w.keys);

if (!w) throw new Error("unable to load wallet for mint " + mint);
Expand Down
15 changes: 1 addition & 14 deletions ndk-wallet/src/wallets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,4 @@ export interface NDKWallet
* Serializes the wallet configuration in a way that can be restored later.
*/
toLoadingString?(): string;
}

export async function walletFromLoadingString(ndk: NDK, str: string): Promise<NDKNWCWallet | NDKCashuWallet | undefined> {
const payload = JSON.parse(str);

switch (payload.type) {
case 'nwc':
return new NDKNWCWallet(ndk, { timeout: payload.timeout, pairingCode: payload.pairingCode });
case 'nip60':
const event = await ndk.fetchEvent(payload.bech32);
if (!event) return undefined;
return await NDKCashuWallet.from(event);
}
}
}
7 changes: 0 additions & 7 deletions ndk-wallet/src/wallets/nwc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,6 @@ export class NDKNWCWallet extends EventEmitter<NDKNWCWalletEvents> implements ND
return new NDKPool(relayUrls, [], this.ndk, { name: 'NWC' });
}

toLoadingString(): string {
return JSON.stringify({
type: 'nwc',
pairingCode: this.pairingCode
});
}

async lnPay(payment: LnPaymentInfo): Promise<NDKPaymentConfirmationLN | undefined> {
if (!this.signer) throw new Error("Wallet not initialized");

Expand Down
6 changes: 5 additions & 1 deletion ndk/src/ndk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,11 @@ export class NDK extends EventEmitter<{
const sub = new NDKSubscription(this, filters);
const events = this.cacheAdapter.query(sub);
if (events instanceof Promise) throw new Error("Cache adapter is async");
return events;
return events
.map(e => {
e.ndk = this;
return e;
})
}

/**
Expand Down

0 comments on commit b279b5c

Please sign in to comment.