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={
-
-
-
-
- }
style={[$card]}
/>
)}
+
+
+
+
+
+ {/*
-
+ */}
{isLoading && }
{error && }
{info && }
diff --git a/src/screens/NwcScreen.tsx b/src/screens/NwcScreen.tsx
index a4b7c7f6..64215b1b 100644
--- a/src/screens/NwcScreen.tsx
+++ b/src/screens/NwcScreen.tsx
@@ -16,9 +16,9 @@ import { QRCodeBlock } from './Wallet/QRCode'
import { CollapsibleText } from '../components/CollapsibleText'
import { isSameDay } from 'date-fns/isSameDay'
-interface SettingsScreenProps extends SettingsStackScreenProps<'Nwc'> {}
+interface NwcScreenProps extends SettingsStackScreenProps<'Nwc'> {}
-export const NwcScreen: FC = observer(
+export const NwcScreen: FC = observer(
function NwcScreen(_props) {
const {navigation} = _props
diff --git a/src/screens/SecurityScreen.tsx b/src/screens/SecurityScreen.tsx
index 0ac2bf13..8d73e648 100644
--- a/src/screens/SecurityScreen.tsx
+++ b/src/screens/SecurityScreen.tsx
@@ -109,7 +109,7 @@ export const SecurityScreen: FC> = observer
style={$card}
ContentComponent={
<>
- > = observer
}
style={$item}
- />
+ />*/}
{isStorageEncrypted && (
= observer(
} = useStores()
const [isUpdateAvailable, setIsUpdateAvailable] = useState(false)
- const [updateDescription, setUpdateDescription] = useState('')
+ const [updateDescription, setUpdateDescription] = useState('')
+ const [currentTheme, setCurrentTheme] = useState(userSettingsStore.theme)
const [updateSize, setUpdateSize] = useState('')
const [isCurrencyModalVisible, setIsCurrencyModalVisible] = useState(false)
@@ -180,9 +182,9 @@ export const SettingsScreen: FC = observer(
await notifee.openNotificationSettings()
}
- const gotoPreferredUnit = function() {
+ /* const gotoPreferredUnit = function() {
Alert.alert('Preferred unit is set based on your Wallet screen.')
- }
+ } */
const getRateColor = function () {
@@ -221,19 +223,42 @@ export const SettingsScreen: FC = observer(
toggleCurrencyModal()
}
- const onSelectTheme = function(theme: ThemeCode) {
- const currentTheme = userSettingsStore.theme
+ const onSelectTheme = async function(theme: ThemeCode) {
if(currentTheme !== theme) {
+ try {
// state update causes crash because of hooks
Database.updateUserSettings({...userSettingsStore, theme})
+ setCurrentTheme(theme)
+
+ const currentIcon = await getIcon()
+ log.trace('[onSelectTheme]', {currentIcon})
+
+ if(theme === ThemeCode.GOLDEN) {
+ await changeIcon('Golden')
+ const updatedIcon = await getIcon()
+ log.trace('[onSelectTheme]', {updatedIcon})
+ }
+
+ if(currentIcon !== 'Default') {
+ await changeIcon('Default')
+ const updatedIcon = await getIcon()
+ log.trace('[onSelectTheme]', {updatedIcon})
+ }
+
setInfo('Restart the wallet to apply new theme.')
+ } catch (e: any) {
+ log.warn('[onSelectTheme]', e.message)
+ }
}
+
toggleThemeModal()
}
const $itemRight = {color: useThemeColor('textDim')}
const headerBg = useThemeColor('header')
- const headerTitle = useThemeColor('headerTitle')
+ const headerTitle = useThemeColor('headerTitle')
+ const colorScheme = useColorScheme()
+ const defaultThemeColor = colorScheme === 'dark' ? Themes[ThemeCode.DARK]?.color : Themes[ThemeCode.LIGHT]?.color
return (
@@ -279,19 +304,20 @@ export const SettingsScreen: FC = observer(
style={$itemRight}
/>
- }
+ }
+ bottomSeparator={true}
onPress={toggleCurrencyModal}
/>
@@ -462,19 +488,26 @@ export const SettingsScreen: FC = observer(
/>
- {[ThemeCode.DEFAULT, ThemeCode.DARK, ThemeCode.LIGHT, ThemeCode.GOLDEN].map(code =>
+ {[ThemeCode.DEFAULT, ThemeCode.DARK, ThemeCode.LIGHT, ThemeCode.GOLDEN].map(code =>
onSelectTheme(code as ThemeCode)}
+ RightComponent={
+
+ {currentTheme === code && (
+
+ )}
+
+ }
bottomSeparator={true}
- />
+ />
)}
>
}
diff --git a/src/screens/WalletScreen.tsx b/src/screens/WalletScreen.tsx
index 74ae9279..a03381d4 100644
--- a/src/screens/WalletScreen.tsx
+++ b/src/screens/WalletScreen.tsx
@@ -39,7 +39,7 @@ import {useStores} from '../models'
import {WalletStackScreenProps} from '../navigation'
import {Mint, UnitBalance} from '../models/Mint'
import {MintsByUnit} from '../models/MintsStore'
-import {log, MinibitsClient, NostrClient} from '../services'
+import {Database, log, MinibitsClient, NostrClient} from '../services'
import {Env} from '../utils/envtypes'
import {Transaction} from '../models/Transaction'
import {TransactionListItem} from './Transactions/TransactionListItem'
@@ -63,6 +63,8 @@ import { LeftProfileHeader } from './ContactsScreen'
import { maxTransactionsByUnit } from '../models/TransactionsStore'
import { NavigationState, Route, TabBar, TabView } from 'react-native-tab-view'
import { NwcConnection, NwcConnectionModel } from '../models/NwcStore'
+import { getSnapshot } from 'mobx-state-tree'
+import { BackupProof, Proof } from '../models/Proof'
const deploymentKey = APP_ENV === Env.PROD ? CODEPUSH_PRODUCTION_DEPLOYMENT_KEY : CODEPUSH_STAGING_DEPLOYMENT_KEY
@@ -97,7 +99,6 @@ export const WalletScreen: FC = observer(
const [info, setInfo] = useState('')
const [defaultMintUrl, setDefaultMintUrl] = useState(MINIBITS_MINT_URL)
- const [lastClaimCheck, setLastClaimCheck] = useState(getUnixTime(new Date()))
const [error, setError] = useState()
const [isLoading, setIsLoading] = useState(false)
@@ -149,7 +150,8 @@ export const WalletScreen: FC = observer(
// On app start
useEffect(() => {
// get deeplink if any
- const getInitialData = async () => {
+ const getInitialData = async () => {
+ // get deeplink data if any
const url = await Linking.getInitialURL()
if (url) {
@@ -525,6 +527,7 @@ export const WalletScreen: FC = observer(
renderLabel={({ route, focused, color }) => (
)}
@@ -796,7 +799,7 @@ const UnitBalanceBlock = observer(function (props: {
diff --git a/src/screens/index.ts b/src/screens/index.ts
index ac01143c..d247f1eb 100644
--- a/src/screens/index.ts
+++ b/src/screens/index.ts
@@ -33,7 +33,7 @@ export * from './UpdateScreen'
export * from './BackupScreen'
export * from './RemoteBackupScreen'
export * from './RemoteRecoveryScreen'
-export * from './LocalRecoveryScreen'
+export * from './ExportEcashScreen'
export * from './DeveloperScreen'
export * from './RelaysScreen'
export * from './NwcScreen'
diff --git a/src/services/notificationService.ts b/src/services/notificationService.ts
index a4325dc4..5eec010c 100644
--- a/src/services/notificationService.ts
+++ b/src/services/notificationService.ts
@@ -10,6 +10,7 @@ import { NostrClient, NostrEvent, NostrProfile } from './nostrService'
import AppError, { Err } from '../utils/AppError'
import { Platform } from 'react-native'
import { RootStoreModel, rootStoreInstance, setupRootStore } from '../models';
+import { ProofsStoreModel } from '../models/ProofsStore';
export type NotifyReceiveToLnurlData = {
type: 'NotifyReceiveToLnurlData',
@@ -90,11 +91,11 @@ const _receiveToLnurlHandler = async function(remoteData: NotifyReceiveToLnurlDa
const _nwcRequestHandler = async function(remoteData: NotifyNwcRequestData) {
const {requestEvent} = remoteData.data
- const {nwcStore} = rootStoreInstance
+ const {nwcStore, proofsStore} = rootStoreInstance
// If app is killed, state is not loaded
if(nwcStore.all.length === 0) {
- await setupRootStore(rootStoreInstance)
+ await setupRootStore(rootStoreInstance)
}
log.trace('[_nwcRequestHandler]', {connections: nwcStore.all})
diff --git a/src/services/sqlite.ts b/src/services/sqlite.ts
index 5d75fb6a..d91ea6d5 100644
--- a/src/services/sqlite.ts
+++ b/src/services/sqlite.ts
@@ -21,7 +21,7 @@ import { ThemeCode } from '../theme'
let _db: QuickSQLiteConnection
-const _dbVersion = 15 // Update this if db changes require migrations
+const _dbVersion = 16 // Update this if db changes require migrations
const getInstance = function () {
if (!_db) {
@@ -99,6 +99,7 @@ const _createOrUpdateSchema = function (db: QuickSQLiteConnection) {
C TEXT NOT NULL,
unit TEXT,
tId INTEGER,
+ mintUrl TEXT,
isPending BOOLEAN,
isSpent BOOLEAN,
updatedAt TEXT
@@ -294,6 +295,15 @@ const _runMigrations = function (db: QuickSQLiteConnection) {
log.info(`Prepared database migrations from ${currentVersion} -> 15`)
}
+ if (currentVersion < 16) {
+ migrationQueries.push([
+ `ALTER TABLE proofs
+ ADD COLUMN mintUrl`,
+ ])
+
+ log.info(`Prepared database migrations from ${currentVersion} -> 16`)
+ }
+
// Update db version as a part of migration sqls
migrationQueries.push([
`INSERT OR REPLACE INTO dbversion (id, version, createdAt)
@@ -903,7 +913,7 @@ const updateOutputToken = function (id: number, outputToken: string) {
}
}
-
+// proof of payment, e.g. preimage
const updateProof = function (id: number, proof: string) {
try {
const query = `
@@ -1073,8 +1083,8 @@ const addOrUpdateProof = function (
const now = new Date()
const query = `
- INSERT OR REPLACE INTO proofs (id, amount, secret, C, tId, isPending, isSpent, updatedAt)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+ INSERT OR REPLACE INTO proofs (id, amount, secret, C, tId, mintUrl, isPending, isSpent, updatedAt)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
`
const params = [
proof.id,
@@ -1082,6 +1092,7 @@ const addOrUpdateProof = function (
proof.secret,
proof.C,
proof.tId,
+ proof.mintUrl,
isPending,
isSpent,
now.toISOString(),
@@ -1090,7 +1101,7 @@ const addOrUpdateProof = function (
const db = getInstance()
const result = db.execute(query, params)
// DO NOT log proof secrets to Sentry
- log.info('[addOrUpdateProof]', `${isPending ? ' Pending' : ''} proof added or updated in the database backup`,
+ log.info('[addOrUpdateProof]', `${isPending ? ' Pending' : ''} proof added or updated in the database`,
{id: result.insertId, tId: proof.tId, isPending, isSpent},
)
@@ -1118,8 +1129,8 @@ const addOrUpdateProofs = function (
for (const proof of proofs) {
insertQueries.push([
- ` INSERT OR REPLACE INTO proofs (id, amount, secret, C, unit, tId, isPending, isSpent, updatedAt)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
+ ` INSERT OR REPLACE INTO proofs (id, amount, secret, C, unit, tId, mintUrl, isPending, isSpent, updatedAt)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`,
[
proof.id,
@@ -1128,6 +1139,7 @@ const addOrUpdateProofs = function (
proof.C,
proof.unit,
proof.tId,
+ proof.mintUrl,
isPending,
isSpent,
now.toISOString(),
@@ -1145,7 +1157,7 @@ const addOrUpdateProofs = function (
// DO NOT log proof secrets to Sentry
log.info('[addOrUpdateProofs]',
`${rowsAffected}${isPending ? ' pending' : ''
- } proofs were added or updated in the database backup`,
+ } proofs were added or updated in the database`,
{isPending, isSpent}
)
@@ -1159,6 +1171,31 @@ const addOrUpdateProofs = function (
}
}
+// migration
+const updateProofsMintUrl = function (id: string, mintUrl: string) {
+ try {
+ const query = `
+ UPDATE proofs
+ SET mintUrl = ?
+ WHERE id = ?
+ `
+ const params = [mintUrl, id]
+
+ const db = getInstance()
+ db.execute(query, params)
+
+ log.debug('[updateMintUrl]', 'Proof mintUrl updated', {id, mintUrl})
+
+
+ } catch (e: any) {
+ throw new AppError(
+ Err.DATABASE_ERROR,
+ 'Could not update proof mintUrl in database',
+ e.message,
+ )
+ }
+}
+
const removeAllProofs = async function () {
try {
const query = `
@@ -1229,10 +1266,20 @@ const getProofs = async function (
ORDER BY id DESC
`
}
+ if (isUnspent && isPending) {
+ if (isPending) {
+ query = `
+ SELECT *
+ FROM proofs
+ WHERE isSpent = 0
+ ORDER BY id DESC
+ `
+ }
+ }
const db = getInstance()
const {rows} = await db.executeAsync(query)
-
+
return rows?._array as BackupProof[]
} catch (e: any) {
@@ -1315,6 +1362,7 @@ export const Database = {
getPendingAmount,
addOrUpdateProof,
addOrUpdateProofs,
+ updateProofsMintUrl,
removeAllProofs,
getProofById,
getProofs,
diff --git a/src/services/walletService.ts b/src/services/walletService.ts
index e8da74a7..b6822f46 100644
--- a/src/services/walletService.ts
+++ b/src/services/walletService.ts
@@ -14,7 +14,6 @@ import {MintBalance, MintProofsCounter, MintStatus} from '../models/Mint'
import {MeltQuoteResponse, MintQuoteState} from '@cashu/cashu-ts'
import {Mint} from '../models/Mint'
import {pollerExists, stopPolling} from '../utils/poller'
-import EventEmitter from '../utils/eventEmitter'
import { NostrClient, NostrEvent, NostrProfile } from './nostrService'
import { MINIBITS_NIP05_DOMAIN, MINIBITS_SERVER_API_HOST, MINIBIT_SERVER_NOSTR_PUBKEY } from '@env'
import { PaymentRequest, PaymentRequestStatus, PaymentRequestType } from '../models/PaymentRequest'
diff --git a/src/theme/colors.ts b/src/theme/colors.ts
index fba37c33..59613586 100644
--- a/src/theme/colors.ts
+++ b/src/theme/colors.ts
@@ -23,7 +23,7 @@ const palette = {
neutral500: '#978F8A',
neutral600: '#564E4A',
neutral700: '#2e2e2e',
- neutral800: '#232323',
+ neutral800: '#181818',
neutral900: '#050505',
primary100: '#D6E4FF',
diff --git a/yarn.lock b/yarn.lock
index ae7a49ee..fd4bf4da 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3867,6 +3867,15 @@ __metadata:
languageName: node
linkType: hard
+"@synonymdev/react-native-change-icon@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "@synonymdev/react-native-change-icon@npm:5.0.0"
+ peerDependencies:
+ react-native: "*"
+ checksum: 01e049715dc01ffdb081badd1803fbbb3630037be526224ff0ccec8d7aea8495b49bbafc0ace0926c8fbc1ac416ec5976626527b786586334fa3a964805db2c8
+ languageName: node
+ linkType: hard
+
"@tootallnate/quickjs-emscripten@npm:^0.23.0":
version: 0.23.0
resolution: "@tootallnate/quickjs-emscripten@npm:0.23.0"
@@ -9381,6 +9390,7 @@ __metadata:
"@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
"@tsconfig/react-native": ^3.0.0
"@types/lodash.clonedeep": ^4.5.9
"@types/react": ^18.2.6