Skip to content

Commit

Permalink
Send large ecash tokens in batches, performance improvements for larg…
Browse files Browse the repository at this point in the history
…e wallets.
  • Loading branch information
minibits-cash committed Oct 16, 2024
1 parent c834342 commit 3affc6e
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 99 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "minibits_wallet",
"version": "0.1.9-beta.23",
"version": "0.1.9-beta.24",
"private": true,
"scripts": {
"android:clean": "cd android && ./gradlew clean",
Expand Down
108 changes: 83 additions & 25 deletions src/screens/DeveloperScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { LogLevel } from '../services/log/logTypes'
import { getSnapshot } from 'mobx-state-tree'
import { delay } from '../utils/delay'
import RNExitApp from 'react-native-exit-app'
import { TransactionStatus } from '../models/Transaction'

// refresh

Expand All @@ -47,7 +48,7 @@ export const DeveloperScreen: FC<SettingsStackScreenProps<'Developer'>> = observ
onLeftPress: () => navigation.goBack(),
})

const {transactionsStore, userSettingsStore} = useStores()
const {transactionsStore, userSettingsStore, proofsStore} = useStores()

const [isLoading, setIsLoading] = useState(false)
const [rnVersion, setRnVersion] = useState<string>('')
Expand Down Expand Up @@ -75,7 +76,7 @@ export const DeveloperScreen: FC<SettingsStackScreenProps<'Developer'>> = observ
init()
}, [])

// Reset of whole model state and reload from DB
// Reset of transaction model state and reload from DB
const syncTransactionsFromDb = async function () {
setIsLoading(true)
try {
Expand Down Expand Up @@ -105,6 +106,48 @@ export const DeveloperScreen: FC<SettingsStackScreenProps<'Developer'>> = observ
}


const deletePending = async function () {
Alert.alert(
translate("common.confirmAlertTitle"),
"This action can not be undone. Use only in development or testing.",
[
{
text: translate('common.cancel'),
style: 'cancel',
onPress: () => { /* Action canceled */ },
},
{
text: translate('common.confirm'),
onPress: async () => {
try {
setIsLoading(true)
const rows = Database.deleteTransactionsByStatus(TransactionStatus.PENDING)

const pending = proofsStore.allPendingProofs
const pendingCount = proofsStore.pendingProofsCount.valueOf()

if(pendingCount > 0) {
proofsStore.removeProofs(pending, true, false) // remove pending proofs and spend the in db
}

if(rows?.length && rows.length > 0) {
await syncTransactionsFromDb()
}

setIsLoading(false)
setInfo(`Removed ${rows?.length || 0} transactions from the database and ${pendingCount} proofs from the wallet state`)

} catch (e: any) {
handleError(e)
}
},
},
],
)

}


const toggleLogLevelSelector = () =>
setIsLogLevelSelectorVisible(previousState => !previousState)

Expand Down Expand Up @@ -180,9 +223,31 @@ export const DeveloperScreen: FC<SettingsStackScreenProps<'Developer'>> = observ
style={{color: headerTitle}}
/>
</View>
<View style={$contentContainer}>
<View style={$contentContainer}>
<Card
style={[$card]}
HeadingComponent={
<ListItem
tx="developerScreen.info"
subText={`Environment: ${APP_ENV}
Native version: ${NATIVE_VERSION_ANDROID}
JS Bundle version: ${JS_BUNDLE_VERSION}
DB version: ${dbVersion}
State size: ${walletStateSize.toLocaleString()} bytes
React Native: ${rnVersion}
Commit: ${COMMIT}
Sentry id: ${userSettingsStore.userSettings.walletId}
`}
leftIcon='faInfoCircle'
leftIconColor={colors.palette.iconGreen300}
leftIconInverse={true}
RightComponent={<View style={$rightContainer} />}
style={$item}
/>
}
/>
<Card
style={$card}
style={[$card, {marginTop: spacing.medium}]}
HeadingComponent={
<>
<ListItem
Expand Down Expand Up @@ -211,30 +276,21 @@ export const DeveloperScreen: FC<SettingsStackScreenProps<'Developer'>> = observ
}
/>
<Card
style={[$card, {marginTop: spacing.medium}]}
label='Danger zone'
labelStyle={{marginTop: spacing.medium}}
style={[$card]}
HeadingComponent={
<>
<ListItem
tx="developerScreen.info"
subText={`Environment: ${APP_ENV}
Native version: ${NATIVE_VERSION_ANDROID}
JS Bundle version: ${JS_BUNDLE_VERSION}
DB version: ${dbVersion}
State size: ${walletStateSize.toLocaleString()} bytes
React Native: ${rnVersion}
Commit: ${COMMIT}
Sentry id: ${userSettingsStore.userSettings.walletId}
`}
leftIcon='faInfoCircle'
leftIconColor={colors.palette.iconGreen300}
leftIconInverse={true}
text="Force delete pending"
subText="Removes ecash from pending state and deletes all pending transactions."
leftIcon='faClock'
leftIconColor={colors.palette.accent400}
leftIconInverse={true}
RightComponent={<View style={$rightContainer} />}
style={$item}
/>
}
/>
<Card
style={[$card, {marginTop: spacing.medium}]}
HeadingComponent={
style={$item}
onPress={deletePending}
/>
<ListItem
tx="developerScreen.reset"
subTx="developerScreen.resetDescription"
Expand All @@ -244,7 +300,9 @@ Sentry id: ${userSettingsStore.userSettings.walletId}
RightComponent={<View style={$rightContainer} />}
style={$item}
onPress={factoryReset}
topSeparator
/>
</>
}
/>
</View>
Expand Down
72 changes: 42 additions & 30 deletions src/screens/ExportBackupScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import { verticalScale } from '@gocodingnow/rn-size-matters'

interface ExportBackupScreenProps extends SettingsStackScreenProps<'ExportBackup'> {}

const OPTIMIZE_FROM_PROOFS_COUNT = 100
const OPTIMIZE_FROM_PROOFS_COUNT = 5

export const ExportBackupScreen: FC<ExportBackupScreenProps> =
function ExportBackup(_props) {
Expand All @@ -65,6 +65,7 @@ export const ExportBackupScreen: FC<ExportBackupScreenProps> =
const [isLoading, setIsLoading] = useState(false)
const [isSendAllSentToQueue, setIsSendAllSentToQueue] = useState<boolean>(false)
const [isReceiveBatchSentToQueue, setIsReceiveBatchSentToQueue] = useState<boolean>(false)
const [totalProofsCount, setTotalProofsCount] = useState<number>(0)
const [totalSentProofsCount, setTotalSentProofsCount] = useState<number>(0)
const [totalReceiveErrorCount, setTotalReceiveErrorCount] = useState<number>(0)
const [totalReceiveCompleteCount, setTotalReceiveCompleteCount] = useState<number>(0)
Expand All @@ -85,12 +86,14 @@ export const ExportBackupScreen: FC<ExportBackupScreenProps> =
await proofsStore.loadProofsFromDatabase()

const orphaned = proofsStore.allProofs.filter(proof => !proof.mintUrl)

if (orphaned.length > 0) {
setOrphanedProofs(orphaned)
setInfo(`Found ${orphaned.length} orphaned proofs not belonging to any active mint. Those won't be included to the backup, but you can copy them separately.`)
}

// log.trace('[loadProofs]', {refreshedProofs: proofsStore.proofs})
setTotalProofsCount(proofsStore.proofsCount)
setIsLoading(false)
} catch (e: any) {
handleError(e)
Expand Down Expand Up @@ -135,7 +138,7 @@ export const ExportBackupScreen: FC<ExportBackupScreenProps> =
}

return () => {
EventEmitter.off('ev_sendTask_result', handleSendAllResult)
EventEmitter.off('ev_sendTask_result', handleSendAllResult)
}
}, [isSendAllSentToQueue])

Expand All @@ -151,14 +154,18 @@ export const ExportBackupScreen: FC<ExportBackupScreenProps> =
if (error) {
setTotalReceiveErrorCount(prev => prev + 1)
} else {
setTotalReceiveCompleteCount(prev => prev + 1)
}
setTotalReceiveCompleteCount(prev => prev + 1)
}
}

if(isReceiveBatchSentToQueue) {
EventEmitter.on('ev_receiveTask_result', handleReceiveTaskResult)
}

return () => {
EventEmitter.off('ev_receiveTask_result', handleReceiveTaskResult)
}

}, [isReceiveBatchSentToQueue])


Expand All @@ -169,12 +176,12 @@ export const ExportBackupScreen: FC<ExportBackupScreenProps> =

setIsLoading(false)

const currentProofsCount = proofsStore.proofsCount
const currentProofsCount = proofsStore.proofsCount

let message = `Original proofs count: ${totalSentProofsCount}, Optimized proofs count: ${currentProofsCount}`

if (totalReceiveErrorCount > 0) {
message += `, errors: ${totalReceiveErrorCount}`
message += `, Errors: ${totalReceiveErrorCount}`
}

setResultModalInfo({
Expand All @@ -185,15 +192,18 @@ export const ExportBackupScreen: FC<ExportBackupScreenProps> =
setIsResultModalVisible(true)
}

if(totalReceiveCompleteCount > 0 || totalReceiveCompleteCount > 0) {
if(totalReceiveCompleteCount > 0 || totalReceiveErrorCount > 0) {
showProofOptimizationResult()
}

}, [totalReceiveErrorCount, totalReceiveCompleteCount])


const toggleResultModal = () =>
setIsResultModalVisible(previousState => !previousState)
const toggleResultModal = () => {
setIsResultModalVisible(previousState => !previousState)
WalletTask.syncPendingStateWithMints()
}



const toggleBackupEcashSwitch = () =>
Expand Down Expand Up @@ -221,7 +231,9 @@ export const ExportBackupScreen: FC<ExportBackupScreenProps> =
{
text: translate('common.confirm'),
onPress: async () => {
// Moves all wallet proofs to pending in transactions split by mints and by units and in offline mode
// Moves all wallet proofs to pending in transactions
// split by mints and by units and in offline mode.
// Supports batching in case proofs count is above limit.
setIsLoading(true)
setIsSendAllSentToQueue(true)
WalletTask.sendAll()
Expand Down Expand Up @@ -578,27 +590,27 @@ export const ExportBackupScreen: FC<ExportBackupScreenProps> =
<Card
ContentComponent={
<>
{proofsStore.proofsCount + proofsStore.pendingProofsCount > 0 && (
{totalProofsCount > 0 && (
<ListItem
text="Ecash proofs"
subText={`Number of proofs: ${proofsStore.proofsCount + proofsStore.pendingProofsCount}`}
RightComponent={
<View style={$rightContainer}>
{proofsStore.proofsCount > OPTIMIZE_FROM_PROOFS_COUNT && (
<Button
preset='secondary'
onPress={optimizeProofAmountsStart}
textStyle={{lineHeight: verticalScale(16), fontSize: verticalScale(14)}}
style={{minHeight: verticalScale(40), paddingVertical: verticalScale(spacing.tiny)}}
text={'Optimize'}
/>
)}
<Switch
onValueChange={toggleBackupEcashSwitch}
value={isEcashInBackup}
text="Ecash proofs"
subText={`Number of proofs: ${proofsStore.proofsCount}`}
RightComponent={
<View style={$rightContainer}>
{proofsStore.proofsCount > OPTIMIZE_FROM_PROOFS_COUNT && (
<Button
preset='secondary'
onPress={optimizeProofAmountsStart}
textStyle={{lineHeight: verticalScale(16), fontSize: verticalScale(14)}}
style={{minHeight: verticalScale(40), paddingVertical: verticalScale(spacing.tiny)}}
text={'Optimize'}
/>
</View>
}
)}
<Switch
onValueChange={toggleBackupEcashSwitch}
value={isEcashInBackup}
/>
</View>
}
/>
)}
{mintsStore.mintCount > 0 && (
Expand All @@ -613,7 +625,7 @@ export const ExportBackupScreen: FC<ExportBackupScreenProps> =
/>
</View>
}
topSeparator={proofsStore.proofsCount + proofsStore.pendingProofsCount > 0 ? true : false}
topSeparator={totalProofsCount > 0 ? true : false}
/>
)}
{contactsStore.count > 0 && (
Expand Down
2 changes: 1 addition & 1 deletion src/services/sqlite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1060,7 +1060,7 @@ const getPendingAmount = function () {
}


const deleteTransactionsByStatus = async function (status: TransactionStatus) {
const deleteTransactionsByStatus = function (status: TransactionStatus) {
try {
const query = `
DELETE FROM transactions
Expand Down
Loading

0 comments on commit 3affc6e

Please sign in to comment.