mirror of
https://github.com/minibits-cash/minibits_wallet.git
synced 2026-10-05 19:28:26 +00:00
312 lines
9.9 KiB
TypeScript
312 lines
9.9 KiB
TypeScript
import {observer} from 'mobx-react-lite'
|
|
import React, {FC, useState, useCallback, useEffect} from 'react'
|
|
import {TextStyle, View, ViewStyle} from 'react-native'
|
|
import {spacing, useThemeColor, colors} from '../theme'
|
|
import {AppStackScreenProps} from '../navigation'
|
|
import {
|
|
Button,
|
|
Icon,
|
|
Card,
|
|
Screen,
|
|
ListItem,
|
|
Text,
|
|
ErrorModal,
|
|
InfoModal,
|
|
} from '../components'
|
|
import {useHeader} from '../utils/useHeader'
|
|
import {log} from '../services/logService'
|
|
import AppError from '../utils/AppError'
|
|
import { useStores } from '../models'
|
|
import { SyncStateTaskResult, WalletTask } from '../services/walletService'
|
|
import EventEmitter from '../utils/eventEmitter'
|
|
import { translate } from '../i18n'
|
|
|
|
/* export enum RecoveryOption {
|
|
SEND_TOKEN = 'SEND_TOKEN',
|
|
PASTE_OR_SCAN_INVOICE = 'PASTE_OR_SCAN_INVOICE',
|
|
SHOW_TOKEN = 'SHOW_TOKEN',
|
|
PAY_PAYMENT_REQUEST = 'PAY_PAYMENT_REQUEST',
|
|
LNURL_PAY = 'LNURL_PAY',
|
|
LNURL_ADDRESS = 'LNURL_ADDRESS',
|
|
DONATION = 'DONATION',
|
|
} */
|
|
|
|
export const RecoveryOptionsScreen: FC<AppStackScreenProps<'RecoveryOptions'>> = observer(
|
|
function RecoveryOptionsScreen({route, navigation}) {
|
|
useHeader({
|
|
leftIcon: 'faArrowLeft',
|
|
onLeftPress: () => navigation.goBack(),
|
|
})
|
|
|
|
const {mintsStore} = useStores()
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
const [error, setError] = useState<AppError | undefined>()
|
|
const [info, setInfo] = useState('')
|
|
const [isSyncStateSentToQueue, setIsSyncStateSentToQueue] = useState<boolean>(false)
|
|
const [totalSpentAmount, setTotalSpentAmount] = useState<number>(0)
|
|
const [syncErrors, setSyncErrors] = useState<AppError[]>([])
|
|
|
|
|
|
useEffect(() => {
|
|
const removeSpentByMintTaskResult = async (result: SyncStateTaskResult) => {
|
|
log.trace('[removeSpentByMintTaskResult] event handler triggered')
|
|
|
|
if (!isSyncStateSentToQueue) { return false }
|
|
|
|
setIsLoading(false)
|
|
|
|
// runs per each mint
|
|
if (result.error && result.error) {
|
|
setSyncErrors(prev => [...prev, result.error!])
|
|
}
|
|
|
|
if (result && result.transactionStateUpdates.length > 0) {
|
|
|
|
log.trace('[removeSpentByMintTaskResult]', {transactionStateUpdates: result.transactionStateUpdates})
|
|
|
|
let totalSpentPerMint = 0
|
|
|
|
for (const update of result.transactionStateUpdates) {
|
|
if(update.spentByMintAmount) {
|
|
totalSpentPerMint += update.spentByMintAmount
|
|
}
|
|
}
|
|
setTotalSpentAmount(prev => prev + totalSpentPerMint)
|
|
}
|
|
|
|
if(totalSpentAmount === 0 && result.transactionStateUpdates.length === 0) {
|
|
setInfo('Spent ecash has not been found in the wallet.')
|
|
}
|
|
}
|
|
|
|
if(isSyncStateSentToQueue) {
|
|
EventEmitter.on('ev__syncStateWithMintTask_result', removeSpentByMintTaskResult)
|
|
}
|
|
|
|
return () => {
|
|
EventEmitter.off('ev__syncStateWithMintTask_result', removeSpentByMintTaskResult)
|
|
}
|
|
}, [isSyncStateSentToQueue])
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
const showSpentEcashResult = () => {
|
|
log.trace('[showSpentEcashResult] got update', {totalSpentAmount})
|
|
|
|
if (totalSpentAmount === 0) { return false }
|
|
|
|
setInfo(`Removed spent ecash with amount ${totalSpentAmount}.`)
|
|
}
|
|
|
|
showSpentEcashResult()
|
|
|
|
}, [totalSpentAmount])
|
|
|
|
|
|
useEffect(() => {
|
|
const showSyncErrors = () => {
|
|
log.trace('[showSyncErrors] got update', {syncErrors})
|
|
|
|
if (syncErrors.length === 0) { return false }
|
|
|
|
setError(syncErrors[syncErrors.length - 1])
|
|
}
|
|
|
|
showSyncErrors()
|
|
|
|
}, [syncErrors])
|
|
|
|
const gotoSeedRecovery = function () {
|
|
navigation.navigate('SeedRecovery')
|
|
}
|
|
|
|
|
|
const gotoImportBackup = function () {
|
|
navigation.navigate('ImportBackup', {isAddressOnlyRecovery: false})
|
|
}
|
|
|
|
|
|
const gotoAddressRecovery = function () {
|
|
navigation.navigate('ImportBackup', {isAddressOnlyRecovery: true})
|
|
}
|
|
|
|
|
|
const checkSpent = async function () {
|
|
setIsLoading(true)
|
|
setIsSyncStateSentToQueue(true)
|
|
WalletTask.syncSpendableStateWithMints()
|
|
}
|
|
|
|
|
|
const increaseCounters = async function () {
|
|
const increaseAmount = 20
|
|
for (const mint of mintsStore.allMints) {
|
|
for(const counter of mint.proofsCounters) {
|
|
counter.increaseProofsCounter(increaseAmount)
|
|
}
|
|
}
|
|
setInfo(translate("recoveryIndexesIncSuccess", { indCount: increaseAmount }))
|
|
}
|
|
|
|
const handleError = function (e: AppError): void {
|
|
log.error(e.name, e.message)
|
|
setError(e)
|
|
}
|
|
|
|
const headerBg = useThemeColor('header')
|
|
const subtitleColor = useThemeColor('textDim')
|
|
|
|
return (
|
|
<Screen preset="scroll" contentContainerStyle={$screen}>
|
|
<View style={[$headerContainer, {backgroundColor: headerBg}]}>
|
|
<Text
|
|
preset="heading"
|
|
tx="recoveryOptions.title"
|
|
style={{color: 'white'}}
|
|
/>
|
|
</View>
|
|
<View style={$contentContainer}>
|
|
{route.params && route.params.fromScreen !== 'Settings' && (
|
|
<Card
|
|
style={$ecashCard}
|
|
ContentComponent={
|
|
<>
|
|
<ListItem
|
|
tx="recoveryOptions.fromBackup"
|
|
subTx="recoveryOptions.fromBackupDescription"
|
|
leftIcon='faDownload'
|
|
leftIconColor={colors.palette.focus300}
|
|
leftIconInverse={true}
|
|
style={$item}
|
|
bottomSeparator={true}
|
|
onPress={gotoImportBackup}
|
|
/>
|
|
<ListItem
|
|
tx="recoveryOptions.fromSeed"
|
|
subTx="recoveryOptions.fromSeedDescription"
|
|
leftIcon='faSeedling'
|
|
leftIconColor={colors.palette.orange400}
|
|
leftIconInverse={true}
|
|
style={$item}
|
|
onPress={gotoSeedRecovery}
|
|
/>
|
|
</>
|
|
}
|
|
/>
|
|
)}
|
|
{route.params && route.params.fromScreen === 'Settings' && (
|
|
<>
|
|
<Card
|
|
style={$card}
|
|
HeadingComponent={
|
|
<ListItem
|
|
tx="walletAddressRecovery"
|
|
subTx="walletAddressRecoveryDesc"
|
|
leftIcon='faCircleUser'
|
|
leftIconColor={colors.palette.iconViolet300}
|
|
leftIconInverse={true}
|
|
style={$item}
|
|
onPress={gotoAddressRecovery}
|
|
/>}
|
|
/>
|
|
<Card
|
|
style={$card}
|
|
HeadingComponent={
|
|
<ListItem
|
|
tx="backupScreen.removeSpentCoins"
|
|
subTx="backupScreen.removeSpentCoinsDescription"
|
|
leftIcon='faRecycle'
|
|
leftIconColor={colors.palette.secondary300}
|
|
leftIconInverse={true}
|
|
RightComponent={
|
|
<View style={$rightContainer}>
|
|
<Button
|
|
onPress={checkSpent}
|
|
text='Remove'
|
|
preset='secondary'
|
|
/>
|
|
</View>
|
|
}
|
|
style={$item}
|
|
/>
|
|
}
|
|
/>
|
|
<Card
|
|
style={$card}
|
|
HeadingComponent={
|
|
<>
|
|
<ListItem
|
|
tx="increaseRecoveryIndexes"
|
|
subTx="increaseRecoveryIndexesDesc"
|
|
leftIcon='faArrowUp'
|
|
leftIconColor={colors.palette.success300}
|
|
leftIconInverse={true}
|
|
RightComponent={
|
|
<View style={$rightContainer}>
|
|
<Button
|
|
onPress={increaseCounters}
|
|
text='Increase'
|
|
preset='secondary'
|
|
/>
|
|
</View>
|
|
}
|
|
style={$item}
|
|
/>
|
|
</>
|
|
}
|
|
/>
|
|
</>
|
|
)}
|
|
</View>
|
|
{error && <ErrorModal error={error} />}
|
|
{info && <InfoModal message={info} />}
|
|
</Screen>
|
|
)
|
|
},
|
|
)
|
|
|
|
const $screen: ViewStyle = {
|
|
// flex: 1,
|
|
}
|
|
|
|
const $headerContainer: TextStyle = {
|
|
alignItems: 'center',
|
|
padding: spacing.medium,
|
|
height: spacing.screenHeight * 0.20,
|
|
}
|
|
|
|
const $contentContainer: TextStyle = {
|
|
// flex: 1,
|
|
marginTop: -spacing.extraLarge * 2,
|
|
padding: spacing.extraSmall,
|
|
// alignItems: 'center',
|
|
}
|
|
|
|
const $ecashCard: ViewStyle = {
|
|
// marginTop: -spacing.extraLarge * 1.5,
|
|
marginBottom: spacing.small,
|
|
// paddingTop: 0,
|
|
}
|
|
|
|
const $card: ViewStyle = {
|
|
marginBottom: spacing.small,
|
|
}
|
|
|
|
const $rightContainer: ViewStyle = {
|
|
// padding: spacing.extraSmall,
|
|
// alignSelf: 'center',
|
|
marginLeft: spacing.tiny,
|
|
marginRight: -10
|
|
}
|
|
|
|
const $lightningCard: ViewStyle = {
|
|
marginVertical: spacing.small,
|
|
// paddingTop: 0,
|
|
}
|
|
|
|
const $item: ViewStyle = {
|
|
paddingHorizontal: spacing.small,
|
|
paddingLeft: 0,
|
|
}
|