diff --git a/src/components/hooks/Restore.tsx b/src/components/hooks/Restore.tsx index 953d10b7..eeafdeec 100644 --- a/src/components/hooks/Restore.tsx +++ b/src/components/hooks/Restore.tsx @@ -15,18 +15,19 @@ import { useTranslation } from 'react-i18next' type StackNavigation = NavigationProp -type TRestoreInterval = Promise<{ proofs: Proof[]; newKeys?: MintKeys; lastCount: number } | undefined> +type TRestoreInterval = Promise<{ proofs: Proof[]; newKeys?: MintKeys; start: number; lastCount: number } | undefined> interface IUseRestoreProps { - from?: number - to?: number + from: number + to: number mintUrl: string keysetId: string mnemonic: string comingFromOnboarding?: boolean + shouldOvershoot?: boolean } -export function useRestore({ from, to, mintUrl, keysetId, mnemonic, comingFromOnboarding }: IUseRestoreProps) { +export function useRestore({ from, to, mintUrl, keysetId, mnemonic, comingFromOnboarding, shouldOvershoot }: IUseRestoreProps) { const navigation = useNavigation() const { t } = useTranslation([NS.common]) @@ -34,120 +35,123 @@ export function useRestore({ from, to, mintUrl, keysetId, mnemonic, comingFromOn const [restored, setRestored] = useState({ proofs: [] as Proof[], - start: from ?? 0, - end: to ?? RESTORE_INTERVAL, + start: from, + end: to, overshoot: 0, }) - useEffect(() => { - const restore = async () => { - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const proofs = await restoreWallet(mintUrl, mnemonic) - if (!proofs?.length) { - openPromptAutoClose({ msg: t('noProofsRestored'), success: false }) - setRestored({ - proofs: [] as Proof[], - start: from ?? 0, - end: to ?? RESTORE_INTERVAL, - overshoot: 0, - }) - if (comingFromOnboarding) { - return navigation.navigate('auth', { pinHash: '' }) - } - return navigation.navigate('dashboard') + const resetRestoredState = () => { + setRestored({ + proofs: [] as Proof[], + start: from, + end: to, + overshoot: 0, + }) + } + + const restore = async () => { + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const { proofs, start, end } = await restoreWallet(mintUrl, mnemonic) + if (!proofs?.length) { + openPromptAutoClose({ msg: t('noProofsRestored'), success: false }) + resetRestoredState() + if (comingFromOnboarding) { + return navigation.navigate('auth', { pinHash: '' }) } - const bal = await getMintBalance(mintUrl) - await addToHistory({ - mints: [mintUrl], - amount: bal, - type: 4, - value: '', - }) - setRestored({ - proofs: [] as Proof[], - start: from ?? 0, - end: to ?? RESTORE_INTERVAL, - overshoot: 0, - }) - navigation.navigate('restoreSuccess', { - mint: mintUrl, - keysetID: keysetId, - cycle: { start: restored.start, end: restored.end }, - amount: bal, - comingFromOnboarding, - }) - } catch (e) { - l('[handleRecovery] error: ', e) - setRestored({ - proofs: [] as Proof[], - start: from ?? 0, - end: to ?? RESTORE_INTERVAL, - overshoot: 0, - }) - navigation.navigate('processingError', { - errorMsg: isErr(e) ? e.message : t('restoreErr'), - comingFromOnboarding, - }) + return navigation.navigate('dashboard') } + const bal = await getMintBalance(mintUrl) + await addToHistory({ + mints: [mintUrl], + amount: bal, + type: 4, + value: '', + }) + navigation.navigate('restoreSuccess', { + mnemonic, + mint: mintUrl, + keysetID: keysetId, + cycle: { start, end }, + amount: bal, + comingFromOnboarding, + }) + } catch (e) { + l('[handleRecovery] error: ', e) + resetRestoredState() + navigation.navigate('processingError', { + errorMsg: isErr(e) ? e.message : t('restoreErr'), + comingFromOnboarding, + }) } - const restoreWallet = async (mintUrl: string, mnemonic: string) => { - try { - const { wallet, seed } = await getSeedWalletByMnemonic({ mintUrl, mnemonic }) - const resp = await restoreInterval(wallet, from ?? 0, to ?? RESTORE_INTERVAL) - if (!resp) { - l('[restoreWallet] restore interval did not return a proper object!') - throw new Error('[restoreWallet] restore interval did not return a proper object!') - } - await saveSeed(seed) - // adds counter if not exists - await getCounterByMintUrl(mintUrl) - if (!resp.proofs.length) { - l('[restoreWallet] no proofs found during the restore process!') - return [] - } - const proofsSpent = await wallet.checkProofsSpent(resp.proofs) - const proofs = resp.proofs.filter(p => !proofsSpent.map(x => x.secret).includes(p.secret)) - if (resp.newKeys) { _setKeys(mintUrl, resp.newKeys) } - await addToken({ token: [{ mint: mintUrl, proofs }] }) - await incrementCounterByMintUrl(mintUrl, resp.lastCount + 1) - return proofs - } catch (e) { - l('[restoreWallet] error', { e }) + } + + const restoreWallet = async (mintUrl: string, mnemonic: string) => { + try { + const { wallet, seed } = await getSeedWalletByMnemonic({ mintUrl, mnemonic }) + const resp = await restoreInterval(wallet, from, to) + if (!resp) { + l('[restoreWallet] restore interval did not return a proper object!') + throw new Error('[restoreWallet] restore interval did not return a proper object!') + } + const { proofs, newKeys, start, lastCount } = resp + await saveSeed(seed) + // adds counter if not exists + await getCounterByMintUrl(mintUrl) + if (!proofs.length) { + l('[restoreWallet] no proofs found during the restore process!') + return { proofs: [], start: from, end: to } } + const proofsSpent = await wallet.checkProofsSpent(proofs) + const proofsUnspent = proofs.filter(p => !proofsSpent.map(x => x.secret).includes(p.secret)) + if (newKeys) { _setKeys(mintUrl, newKeys) } + await addToken({ token: [{ mint: mintUrl, proofs: proofsUnspent }] }) + await incrementCounterByMintUrl(mintUrl, lastCount + 1) + return { proofs: proofsUnspent, start, end: lastCount } + } catch (e) { + l('[restoreWallet] error', { e }) + return { proofs: [], start: from, end: to } } - const restoreInterval = async ( - wallet: CashuWallet, - start: number, - end: number, - restoredProofs: Proof[] = [], - overshoot: number = 0 - ): TRestoreInterval => { - try { + } + + const restoreInterval = async ( + wallet: CashuWallet, + start: number, + end: number, + restoredProofs: Proof[] = [], + overshoot: number = 0 + ): TRestoreInterval => { + try { + const { proofs, newKeys } = await wallet.restore(start, end, keysetId) + l('[restoreInterval] restored proofs: ', { from: start, to: end, proofsLength: proofs.length }) + if (proofs.length) { + restoredProofs.push(...proofs) + overshoot = 0 + start += RESTORE_INTERVAL + end += RESTORE_INTERVAL setRestored({ proofs: restoredProofs, start, end, overshoot }) - const { proofs, newKeys } = await wallet.restore(start, end, keysetId) + return restoreInterval(wallet, start, end, restoredProofs, overshoot) + } + if (shouldOvershoot && overshoot < RESTORE_OVERSHOOT) { + l('[restoreInterval] no proofs to restore! overshooting now: ', { proofsLength: proofs.length, overshoot }) + overshoot++ start += RESTORE_INTERVAL end += RESTORE_INTERVAL - if (proofs.length) { - l('[restoreInterval] restored proofs: ', { from, to, proofsLength: proofs.length }) - restoredProofs.push(...proofs) - overshoot = 0 - return restoreInterval(wallet, start, end, restoredProofs, overshoot) - } - if (overshoot < RESTORE_OVERSHOOT) { - l('[restoreInterval] no proofs to restore! overshooting now: ', { from, to, proofsLength: proofs.length, overshoot }) - overshoot++ - return restoreInterval(wallet, start, end, restoredProofs, overshoot) - } - l('[restoreInterval] no proofs to restore! overshooting limit reached: ', { from, to, restoredProofs: restoredProofs.length, overshoot }) - return { proofs: restoredProofs, newKeys, lastCount: end } - } catch (e) { - l('[restoreInterval] error', { e }) + setRestored({ proofs: restoredProofs, start, end, overshoot }) + return restoreInterval(wallet, start, end, restoredProofs, overshoot) } + l('[restoreInterval] no proofs to restore! overshooting limit reached: ', { restoredProofsLength: restoredProofs.length, overshoot }) + return { proofs: restoredProofs, newKeys, start, lastCount: end } + } catch (e) { + l('[restoreInterval] error', { e }) + return { proofs: restoredProofs, newKeys: undefined, start, lastCount: end } } + } + + useEffect(() => { void restore() // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + }, [mintUrl, keysetId, from, to]) - return { ...restored } + return restored } diff --git a/src/model/nav.ts b/src/model/nav.ts index 985d8032..f6870f7f 100644 --- a/src/model/nav.ts +++ b/src/model/nav.ts @@ -178,7 +178,6 @@ export type RootStackParamList = { isZap?: boolean nostr?: INostrSendData isScanned?: boolean - isRestored?: boolean change?: number comingFromOnboarding?: boolean } @@ -236,17 +235,19 @@ export type RootStackParamList = { comingFromOnboarding?: boolean } Recovering: { - from?: number - to?: number + from: number + to: number mintUrl: string keysetId: string mnemonic: string comingFromOnboarding?: boolean + shouldOvershoot?: boolean } 'Restore warning': { comingFromOnboarding?: boolean } restoreSuccess: { + mnemonic: string amount: number mint: string keysetID: string diff --git a/src/screens/Dashboard.tsx b/src/screens/Dashboard.tsx index 0c788342..9983329d 100644 --- a/src/screens/Dashboard.tsx +++ b/src/screens/Dashboard.tsx @@ -307,14 +307,14 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) { txt={t('send', { ns: NS.wallet })} color={hi[highlight]} onPress={() => { - // setModal(prev => ({ ...prev, sendOpts: true })) - navigation.navigate('restoreSuccess', { - mint: 'https://testnut.cashu.space', - keysetID: 'jkasfhgkjg', - cycle: { start: 300, end: 350 }, - amount: 100, - comingFromOnboarding: true, - }) + setModal(prev => ({ ...prev, sendOpts: true })) + // navigation.navigate('restoreSuccess', { + // mint: 'https://testnut.cashu.space', + // keysetID: 'jkasfhgkjg', + // cycle: { start: 300, end: 350 }, + // amount: 100, + // comingFromOnboarding: true, + // }) }} /> : @@ -323,14 +323,14 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) { txt={t('mint')} color={hi[highlight]} onPress={() => { - // navigation.navigate('mints') - navigation.navigate('restoreSuccess', { - mint: 'https://testnut.cashu.space', - keysetID: 'jkasfhgkjg', - cycle: { start: 300, end: 350 }, - amount: 100, - comingFromOnboarding: true, - }) + navigation.navigate('mints') + // navigation.navigate('restoreSuccess', { + // mint: 'https://testnut.cashu.space', + // keysetID: 'jkasfhgkjg', + // cycle: { start: 300, end: 350 }, + // amount: 100, + // comingFromOnboarding: true, + // }) }} /> } diff --git a/src/screens/Payment/Success.tsx b/src/screens/Payment/Success.tsx index 9586788e..0e06c47c 100644 --- a/src/screens/Payment/Success.tsx +++ b/src/screens/Payment/Success.tsx @@ -28,7 +28,7 @@ export default function SuccessPage({ navigation, route }: TSuccessPageProps) { isZap, nostr, isScanned, - isRestored, + comingFromOnboarding } = route.params const { t } = useTranslation([NS.common]) const { color } = useThemeContext() @@ -68,13 +68,10 @@ export default function SuccessPage({ navigation, route }: TSuccessPageProps) { isAutoSwap ? t('autoSwapSuccess') : - isRestored ? - <>{formatSatStr(amount || 0)} {t('restored')}! + !nostr ? + <>{formatSatStr(amount || 0)} {isClaim ? t('claimed') : t('minted')}! : - !nostr ? - <>{formatSatStr(amount || 0)} {isClaim ? t('claimed') : t('minted')}! - : - null + null } {memo && @@ -120,7 +117,7 @@ export default function SuccessPage({ navigation, route }: TSuccessPageProps) {