import { useCallback, useEffect, useState } from 'react' import { useMe } from './me' import { useShowModal } from './modal' import useVault, { useVaultConfigurator, useVaultMigration } from './use-vault' import { Button, InputGroup } from 'react-bootstrap' import { Form, Input, PasswordInput, SubmitButton } from './form' import bip39Words from '@/lib/bip39-words' import Info from './info' import CancelButton from './cancel-button' import * as yup from 'yup' import { deviceSyncSchema } from '@/lib/validate' import RefreshIcon from '@/svgs/refresh-line.svg' import { useApolloClient } from '@apollo/client' export default function DeviceSync () { const { me } = useMe() const apollo = useApolloClient() const [value, setVaultKey, clearVault, disconnectVault] = useVaultConfigurator() const showModal = useShowModal() const enabled = !!me?.privates?.vaultKeyHash const connected = !!value?.key const migrate = useVaultMigration() const [debugValue, setDebugValue, clearValue] = useVault(me, 'debug') const manage = useCallback(async () => { if (enabled && connected) { showModal((onClose) => (

Device sync is enabled!

Sensitive data (like wallet credentials) is now securely synced between all connected devices.

Disconnect to prevent this device from syncing data or to reset your passphrase.

)) } else { showModal((onClose) => ( )) } }, [migrate, enabled, connected, value]) const reset = useCallback(async () => { const schema = yup.object().shape({ confirm: yup.string() .oneOf(['yes'], 'you must confirm by typing "yes"') .required('required') }) showModal((onClose) => (

Reset device sync

This will delete all encrypted data on the server and disconnect all devices.

You will need to enter a new passphrase on this and all other devices to sync data again.

{ await clearVault() onClose() }} >
continue
)) }, []) const onConnect = useCallback(async (values, formik) => { if (values.passphrase) { try { await setVaultKey(values.passphrase) await migrate() apollo.cache.evict({ fieldName: 'BestWallets' }) apollo.cache.gc() await apollo.refetchQueries({ include: ['BestWallets'] }) } catch (e) { formik?.setErrors({ passphrase: e.message }) throw e } } }, [setVaultKey, migrate]) return ( <>
device sync

Device sync uses end-to-end encryption to securely synchronize your data across devices.

Your sensitive data remains private and inaccessible to our servers while being synced across all your connected devices using only a passphrase.

{enabled && !connected && (

If you have lost your passphrase or wish to erase all encrypted data from the server, you can reset the device sync data and start over.

This action cannot be undone.

)} ) } const generatePassphrase = (n = 12) => { const rand = new Uint32Array(n) window.crypto.getRandomValues(rand) return Array.from(rand).map(i => bip39Words[i % bip39Words.length]).join(' ') } function ConnectForm ({ onClose, onConnect, enabled }) { const [passphrase, setPassphrase] = useState(!enabled ? generatePassphrase : '') useEffect(() => { const scannedPassphrase = window.localStorage.getItem('qr:passphrase') if (scannedPassphrase) { setPassphrase(scannedPassphrase) window.localStorage.removeItem('qr:passphrase') } }) const newPassphrase = useCallback(() => { setPassphrase(() => generatePassphrase(12)) }, []) return (

{!enabled ? 'Enable device sync' : 'Input your passphrase'}

{!enabled ? 'Enable secure sync of sensitive data (like wallet credentials) between your devices. You’ll need to enter this passphrase on each device you want to connect.' : 'Enter the passphrase from device sync to access your encrypted sensitive data (like wallet credentials) on the server.'}

{ try { await onConnect(values, formik) onClose() } catch {} }} > ) } />

{ !enabled ? 'This passphrase is stored only on your device and cannot be shown again.' : 'If you have forgotten your passphrase, you can reset and start over.' }

{enabled ? 'connect' : 'enable'}
) }