diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 1832f71c..e279a284 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -11,47 +11,62 @@ android:supportsRtl="true" android:usesCleartextTraffic="true" > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_golden.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_golden.xml new file mode 100644 index 00000000..cdc53830 --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_golden.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index ab84284b..2670a063 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png index 20af0781..a0054b38 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png index ba312e5c..db233a97 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden.png new file mode 100644 index 00000000..f1e75414 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden_background.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden_background.png new file mode 100644 index 00000000..9aef2e95 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden_background.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden_foreground.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden_foreground.png new file mode 100644 index 00000000..1ef27155 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden_foreground.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden_monochrome.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden_monochrome.png new file mode 100644 index 00000000..1ef27155 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_golden_monochrome.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png index ba312e5c..db233a97 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b523998..00000000 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 00316bc6..fbcedb9d 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png index 10195402..bc6e4815 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png index 739f599f..0a3e2c3a 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden.png new file mode 100644 index 00000000..55dc4abc Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden_background.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden_background.png new file mode 100644 index 00000000..819719d1 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden_background.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden_foreground.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden_foreground.png new file mode 100644 index 00000000..b6893f1a Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden_foreground.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden_monochrome.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden_monochrome.png new file mode 100644 index 00000000..b6893f1a Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_golden_monochrome.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png index 739f599f..0a3e2c3a 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c76..00000000 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index e71698b1..b50d9da7 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png index 40bc2519..4f9401cb 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png index b7a8a206..77943544 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden.png new file mode 100644 index 00000000..7eff91ce Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden_background.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden_background.png new file mode 100644 index 00000000..ba384493 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden_background.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden_foreground.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden_foreground.png new file mode 100644 index 00000000..7b88eab7 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden_monochrome.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden_monochrome.png new file mode 100644 index 00000000..7b88eab7 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_golden_monochrome.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png index b7a8a206..77943544 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609..00000000 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 904957b8..4903e11a 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png index 7ebf7f67..40c33289 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png index 88541732..663780db 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden.png new file mode 100644 index 00000000..26ac0362 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden_background.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden_background.png new file mode 100644 index 00000000..7975e0df Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden_background.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden_foreground.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden_foreground.png new file mode 100644 index 00000000..9cf231a7 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden_monochrome.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden_monochrome.png new file mode 100644 index 00000000..9cf231a7 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_golden_monochrome.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png index 88541732..663780db 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410..00000000 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index e02a361a..25fe8a23 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png index ad4a1293..e98409f3 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png index bf11d7af..d97eaf64 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden.png new file mode 100644 index 00000000..545a517c Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden_background.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden_background.png new file mode 100644 index 00000000..e12771c6 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden_background.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden_foreground.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden_foreground.png new file mode 100644 index 00000000..41715747 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden_monochrome.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden_monochrome.png new file mode 100644 index 00000000..41715747 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_golden_monochrome.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png index bf11d7af..d97eaf64 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c..00000000 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/package.json b/package.json index 6b492af1..424825e4 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@react-navigation/native-stack": "^6.11.0", "@react-navigation/stack": "^6.4.1", "@sentry/react-native": "^5.32.0", + "@synonymdev/react-native-change-icon": "^5.0.0", "date-fns": "^4.0.0", "i18n-js": "^4.4.3", "js-lnurl": "^0.6.0", diff --git a/src/i18n_messages/en.json b/src/i18n_messages/en.json index b4f42512..f9958b7d 100644 --- a/src/i18n_messages/en.json +++ b/src/i18n_messages/en.json @@ -15,8 +15,8 @@ "missingMnemonicOrSeedError": "Missing mnemonic or seed.", "mnemonicDesc": "This 12 word sequence represents your seed and allows you to recover your ecash balance in case of device loss. Keep them in safe place.", "mnemonicTitle": "Your mnemonic phrase", - "recoveryTool": "Local recovery tool", - "recoveryToolDescription": "Show ecash backed up in the local database and attempt to recover unspent ones into the wallet in case the wallet storage gets corrupted or a transaction fails due to an unexpected error.", + "recoveryTool": "Export ecash", + "recoveryToolDescription": "Filter and export all ecash from local database grouped by mint keysets.", "remoteBackupDescription": "Mnemonic phrase encodes your seed and allows you to recover your ecash balance in case of device loss.", "removeSpentCoins": "Remove spent ecash", "removeSpentCoinsDescription": "In case of a SEND or TRANSFER transaction error, spent ecash may remain in your wallet. This blocks further transactions with the mint, making the wallet unusable. This tool removes spent ecash from the wallet.", @@ -231,7 +231,7 @@ "nsecMissingProfileError": "Missing profile to update", "nsecPasteError": "Copy your nsec key first, then paste.", "nsecPrivatePublicKeyMismatchError": "Provided private key does not match your new profile public key.", - "numberOfBackedupProofs": "Number of backed up proofs", + "numberOfBackedupProofs": "Number of stored proofs", "onDeviceInfo": "On-device information", "pasteEcashTokenDesc": "Paste ecash token you want to receive.", "payCommon": { @@ -370,7 +370,7 @@ "recoveryInsertMnemonicDesc": "Paste or rewrite 12 word phrase to recover your ecash balance and wallet address on this device. Separate words by blank spaces.", "recoveryInsertMnemonicDescAddrOnly": "Paste or rewrite 12 word phrase to recover your wallet address on this device. Separate words by blank spaces.", "recoveryInvalidMnemonicError": "Invalid mnemonic phrase. Provide 12 word sequence separated by blank spaces.", - "recoveryTool": "Recovery tool", + "exportEcash": "Export ecash", "relayExists": "Relay already exists", "relays": "Relays", "relayurlPasteError": "Copy your relay URL key before pasting", diff --git a/src/models/ProofsStore.ts b/src/models/ProofsStore.ts index 01326950..716943f3 100644 --- a/src/models/ProofsStore.ts +++ b/src/models/ProofsStore.ts @@ -4,9 +4,10 @@ import { types, isStateTreeNode, detach, + flow, } from 'mobx-state-tree' import {withSetPropAction} from './helpers/withSetPropAction' -import {ProofModel, Proof} from './Proof' +import {ProofModel, Proof, BackupProof} from './Proof' import {log} from '../services/logService' import {getRootStore} from './helpers/getRootStore' import AppError, {Err} from '../utils/AppError' @@ -87,6 +88,43 @@ export const ProofsStoreModel = types }, })) .actions(self => ({ + // Proofs are not more persisted in mmkv storage but loaded from database on afterCreate model + loadProofsFromDatabase: flow(function* laodProofs() { + + const unspentAndPendingProofs = yield Database.getProofs(true, true, false) + + // Group into isUnspent and isPending + const groupedProofs = unspentAndPendingProofs.reduce( + (acc: {isPending: BackupProof[], isUnspent: BackupProof[]}, proof: BackupProof) => { + if (proof.isPending) { + acc.isPending.push(proof); + } else { + acc.isUnspent.push(proof); + } + return acc; + }, + { isUnspent: [], isPending: [] } // Initialize the groups + ) + + const cleanProofs = (proofs: BackupProof[]) => { + return proofs.map(p => { + // Destructure the unwanted properties and collect the rest in `cleaned` + const { isPending, isSpent, updatedAt, ...cleaned } = p + // Return the cleaned object + return cleaned as Proof + }) + } + + self.proofs.replace(cleanProofs(groupedProofs.isUnspent)) + self.pendingProofs.replace(cleanProofs(groupedProofs.isPending)) + }), + })) + .actions(self => ({ + /*afterCreate() { + // not used to be able to load proofs without blocking app start + // Trigger the load proofs action when the store is initialized + self.loadProofsFromDatabase() + },*/ addProofs(newProofs: Proof[], isPending: boolean = false): {addedAmount: number, addedProofs: Proof[]} { try { const proofs = isPending ? self.pendingProofs : self.proofs @@ -405,7 +443,13 @@ export const ProofsStoreModel = types getProofsSubset: (proofs: Proof[], proofsToRemove: Proof[]) => { return proofs.filter(proof => !proofsToRemove.includes(proof)) }, - })) + })).postProcessSnapshot((snapshot) => { // NOT persisted to storage except last pendingByMintSecrets! + return { + proofs: [], + pendingProofs: [], + pendingByMintSecrets: snapshot.pendingByMintSecrets + } + }) export interface Proofs extends Instance {} diff --git a/src/models/RootStore.ts b/src/models/RootStore.ts index e6c2d745..d80f52fa 100644 --- a/src/models/RootStore.ts +++ b/src/models/RootStore.ts @@ -11,7 +11,7 @@ import {WalletStoreModel} from './WalletStore' import {NwcStoreModel} from './NwcStore' import { log } from '../services' -export const rootStoreModelVersion = 26 // Update this if model changes require migrations defined in setupRootStore.ts +export const rootStoreModelVersion = 28 // Update this if model changes require migrations defined in setupRootStore.ts /** * A RootStore model. diff --git a/src/models/UserSettingsStore.ts b/src/models/UserSettingsStore.ts index 5157fb0d..b2a8f37b 100644 --- a/src/models/UserSettingsStore.ts +++ b/src/models/UserSettingsStore.ts @@ -103,7 +103,7 @@ export const UserSettingsStoreModel = types self.isLocalBackupOn = isLocalBackupOn return isLocalBackupOn }, - setIsStorageEncrypted: flow(function* setIsStorageEncryptedvalue( + setIsStorageEncrypted: flow(function* setIsStorageEncryptedvalue( // legacy, tobe removed isEncrypted: boolean, ) { if (isEncrypted) { @@ -115,7 +115,7 @@ export const UserSettingsStoreModel = types self.isStorageEncrypted = isEncrypted return isEncrypted }), - setIsTorDaemonOn: (isTorDaemonOn: boolean) => { + setIsTorDaemonOn: (isTorDaemonOn: boolean) => { // legacy, tobe removed Database.updateUserSettings({...self, isTorDaemonOn}) self.isTorDaemonOn = isTorDaemonOn return isTorDaemonOn diff --git a/src/models/helpers/setupRootStore.ts b/src/models/helpers/setupRootStore.ts index 678ed597..8126bb46 100644 --- a/src/models/helpers/setupRootStore.ts +++ b/src/models/helpers/setupRootStore.ts @@ -54,6 +54,7 @@ export async function setupRootStore(rootStore: RootStore) { Sentry.setUser({ id: userSettings.walletId }) } + // legacy, encryption is sunset, to be replaced by opt-in biometric auth to read the seed if (userSettings.isStorageEncrypted) { try { await MMKVStorage.initEncryption() @@ -77,21 +78,27 @@ export async function setupRootStore(rootStore: RootStore) { } } } - } + } // legacy end // load the last known state from storage + const start = performance.now() restoredState = MMKVStorage.load(ROOT_STORAGE_KEY) || {} - - // dirty mobx fix - restoredState.walletProfileStore.isBatchClaimOn = undefined + const mmkvLoaded = performance.now() + const dataSize = Buffer.byteLength(JSON.stringify(restoredState), 'utf8') - const dataSize = Buffer.byteLength(JSON.stringify(restoredState), 'utf8') + log.trace('[setupRootStore]', `Loading ${dataSize.toLocaleString()} bytes of state from MMKV took ${(mmkvLoaded - start).toLocaleString()} ms.`) - log.trace('[setupRootStore]', `restored state has ${dataSize} bytes.`) - // log.trace(restoredState) - applySnapshot(rootStore, restoredState) + const stateHydrated = performance.now() + log.trace(`[setupRootStore] Hydrating rooStoreModel took ${stateHydrated - mmkvLoaded} ms.`) + + const {proofsStore} = rootStore + await proofsStore.loadProofsFromDatabase() + + const proofsLoaded = performance.now() + log.trace(`[setupRootStore] Loading proofs from DB and hydrating took ${proofsLoaded - stateHydrated} ms.`) + } catch (e: any) { log.error('[setupRootStore]', Err.STORAGE_ERROR, {message: e.message, params: e.params}) } @@ -326,6 +333,30 @@ async function _runMigrations(rootStore: RootStore) { rootStore.setVersion(rootStoreModelVersion) log.info(`Completed rootStore migrations to the version v${rootStoreModelVersion}`) } + + if(currentVersion < 28) { + log.trace(`Starting rootStore migrations from version v${currentVersion} -> v27`) + if(userSettingsStore.isStorageEncrypted) { + await userSettingsStore.setIsStorageEncrypted(false) + } + if(!userSettingsStore.isLocalBackupOn) { + const proofs = proofsStore.allProofs + const pendingProofs = proofsStore.pendingProofs + + Database.addOrUpdateProofs(proofs, false, false) + Database.addOrUpdateProofs(pendingProofs, true, false) + userSettingsStore.setIsLocalBackupOn(true) + } + + for (const mint of mintsStore.allMints) { + for(const keysetId of mint.keysetIds) { + Database.updateProofsMintUrl(keysetId, mint.mintUrl) + } + } + + rootStore.setVersion(rootStoreModelVersion) + log.info(`Completed rootStore migrations to the version v${rootStoreModelVersion}`) + } } catch (e: any) { throw new AppError( Err.STORAGE_ERROR, @@ -334,5 +365,4 @@ async function _runMigrations(rootStore: RootStore) { ) } - } diff --git a/src/navigation/TabsNavigator.tsx b/src/navigation/TabsNavigator.tsx index a6e6c837..22278625 100644 --- a/src/navigation/TabsNavigator.tsx +++ b/src/navigation/TabsNavigator.tsx @@ -29,7 +29,7 @@ import { UpdateScreen, BackupScreen, RemoteBackupScreen, - LocalRecoveryScreen, + ExportEcashScreen, RelaysScreen, TranDetailScreen, TranHistoryScreen, @@ -287,7 +287,7 @@ export type SettingsStackParamList = { } Backup: undefined RemoteBackup: undefined - LocalRecovery: undefined + ExportEcash: undefined Developer: undefined Relays: undefined RemoteRecovery: {isAddressOnlyRecovery: boolean} @@ -320,7 +320,7 @@ const SettingsNavigator = function SettingsNavigator() { - + diff --git a/src/screens/BackupScreen.tsx b/src/screens/BackupScreen.tsx index 58ee8ef2..cdad7667 100644 --- a/src/screens/BackupScreen.tsx +++ b/src/screens/BackupScreen.tsx @@ -20,7 +20,7 @@ import {useStores} from '../models' import AppError from '../utils/AppError' import EventEmitter from '../utils/eventEmitter' import {ResultModalInfo} from './Wallet/ResultModalInfo' -import {Database, log, WalletTask, WalletTaskResult} from '../services' +import {Database, log, SyncStateTaskResult, WalletTask, WalletTaskResult} from '../services' import { translate } from '../i18n' export const BackupScreen: FC> = observer(function BackupScreen(_props) { @@ -41,22 +41,32 @@ export const BackupScreen: FC> = observer(fun const [totalSpentAmount, setTotalSpentAmount] = useState(0) useEffect(() => { - const removeSpentByMintTaskResult = async (result: WalletTaskResult) => { + const removeSpentByMintTaskResult = async (result: SyncStateTaskResult) => { log.trace('removeSpentByMintTaskResult event handler triggered') if (!isSyncStateSentToQueue) { return false } setIsLoading(false) // runs per each mint - if (result && result.spentAmount > 0) { + if (result && result.transactionStateUpdates.length > 0) { + + let totalSpentPerMint = 0 + + for (const update of result.transactionStateUpdates) { + if(update.spentByMintAmount && update.spentByMintAmount > 0) { + totalSpentPerMint += update.spentByMintAmount + } + } + setTotalSpentAmount(prev => prev + result.spentAmount) setTotalSpentCount(prev => prev + result.spentCount) setInfo( - translate("backupScreen.result", { proofCount: totalSpentCount, amount: totalSpentAmount }) + translate("backupScreen.result", { proofCount: totalSpentCount, amount: totalSpentAmount }) ) return } - setInfo(translate("noSpentEcashFound")) + + setInfo(translate("noSpentEcashFound")) } EventEmitter.on('ev__syncStateWithMintTask_result', removeSpentByMintTaskResult) @@ -66,7 +76,7 @@ export const BackupScreen: FC> = observer(fun } }, [isSyncStateSentToQueue]) - const toggleBackupSwitch = () => { + /* const toggleBackupSwitch = () => { try { setIsLoading(true) const result = userSettingsStore.setIsLocalBackupOn(!isLocalBackupOn) @@ -97,13 +107,13 @@ export const BackupScreen: FC> = observer(fun } catch (e: any) { handleError(e) } - } + }*/ const toggleBackupModal = () => setIsBackupModalVisible(previousState => !previousState) - const gotoLocalRecovery = function () { - navigation.navigate('LocalRecovery') + const gotoExportEcash = function () { + navigation.navigate('ExportEcash') } const gotoRemoteBackup = function () { @@ -180,7 +190,7 @@ export const BackupScreen: FC> = observer(fun style={$card} HeadingComponent={ <> - > = observer(fun } style={$item} - /> + />*/} {isLocalBackupOn && ( > = observer(fun leftIconColor={colors.palette.focus300} leftIconInverse={true} style={$item} - onPress={gotoLocalRecovery} - topSeparator={true} + onPress={gotoExportEcash} + // topSeparator={true} /> )} diff --git a/src/screens/LocalRecoveryScreen.tsx b/src/screens/ExportEcashScreen.tsx similarity index 88% rename from src/screens/LocalRecoveryScreen.tsx rename to src/screens/ExportEcashScreen.tsx index 79cf11d8..a2e59a0f 100644 --- a/src/screens/LocalRecoveryScreen.tsx +++ b/src/screens/ExportEcashScreen.tsx @@ -4,10 +4,8 @@ import { TextStyle, ViewStyle, View, - useColorScheme, - Alert, } from 'react-native' -import {useThemeColor, spacing, colors, typography} from '../theme' +import {useThemeColor, spacing, typography} from '../theme' import { Button, Icon, @@ -28,28 +26,24 @@ import {BackupProof} from '../models/Proof' import { useStores } from '../models' import { CashuUtils, ProofV3, TokenV3 } from '../services/cashu/cashuUtils' import Clipboard from '@react-native-clipboard/clipboard' -import { Transaction, TransactionData, TransactionRecord, TransactionStatus, TransactionType } from '../models/Transaction' -import { WalletUtils } from '../services/wallet/utils' -import { MintUnit, MintUnits, getCurrency } from '../services/wallet/currency' +import { MintUnits, getCurrency } from '../services/wallet/currency' import { CurrencyAmount } from './Wallet/CurrencyAmount' import { translate } from '../i18n' -interface LocalRecoveryScreenProps - extends SettingsStackScreenProps<'LocalRecovery'> {} +interface ExportEcashScreenProps extends SettingsStackScreenProps<'ExportEcash'> {} -export const LocalRecoveryScreen: FC = - function LocalRecoveryScreen(_props) { +export const ExportEcashScreen: FC = + function ExportEcash(_props) { const { navigation } = _props - const { mintsStore, proofsStore, transactionsStore } = useStores() + const { mintsStore } = useStores() useHeader({ leftIcon: 'faArrowLeft', onLeftPress: () => navigation.goBack(), }) - const [showUnspentOnly, setShowUnspentOnly] = useState(true) const [showPendingOnly, setShowPendingOnly] = useState(false) const [showSpentOnly, setShowSpentOnly] = useState(false) @@ -72,7 +66,7 @@ export const LocalRecoveryScreen: FC = try { setIsLoading(true) // update empty unit fields to resolve v0.1.7 upgrade issue of backed up proofs not having unit migrated - await Database.updateProofsToDefaultUnit() + // await Database.updateProofsToDefaultUnit() const backupProofs = await Database.getProofs(isUnspent, isPending, isDeleted) setProofs(backupProofs) setIsLoading(false) @@ -188,7 +182,7 @@ export const LocalRecoveryScreen: FC = } - const onRecovery = async function () { + /* const onRecovery = async function () { if (!showUnspentOnly) { setInfo(translate("unspentOnlyRecoverable")) return @@ -337,7 +331,7 @@ export const LocalRecoveryScreen: FC = } catch (e: any) { handleError(e) } - } + } */ const groupProofsByMint = function (proofs: BackupProof[]) { return proofs.reduce((acc: Record, proof) => { @@ -383,7 +377,7 @@ export const LocalRecoveryScreen: FC = const headerBg = useThemeColor('header') const iconColor = useThemeColor('textDim') - const activeIconColor = useThemeColor('button') + const activeIconColor = useThemeColor('tint') const headerTitle = useThemeColor('headerTitle') @@ -392,7 +386,7 @@ export const LocalRecoveryScreen: FC = @@ -474,44 +468,36 @@ export const LocalRecoveryScreen: FC = ))} } - FooterComponent={ - -