diff --git a/src/components/App.tsx b/src/components/App.tsx
index b3ca053e..0e732792 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -8,6 +8,7 @@ import { NavigationContainer, NavigationContainerRef } from '@react-navigation/n
import { CustomErrorBoundary } from '@screens/ErrorScreen/ErrorBoundary'
import { ErrorDetails } from '@screens/ErrorScreen/ErrorDetails'
import * as Sentry from '@sentry/react-native'
+import { BalanceProvider } from '@src/context/Balance'
import { FocusClaimProvider } from '@src/context/FocusClaim'
import { HistoryProvider } from '@src/context/History'
import { KeyboardProvider } from '@src/context/Keyboard'
@@ -207,25 +208,27 @@ function _App() {
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Balance.tsx b/src/components/Balance.tsx
index ac162b66..83294e6f 100644
--- a/src/components/Balance.tsx
+++ b/src/components/Balance.tsx
@@ -4,6 +4,7 @@ import { type TTXType, txType } from '@model'
import type { RootStackParamList } from '@model/nav'
import type { NativeStackNavigationProp } from '@react-navigation/native-stack'
import EntryTime from '@screens/History/entryTime'
+import { useBalanceContext } from '@src/context/Balance'
import { useHistoryContext } from '@src/context/History'
import { usePrivacyContext } from '@src/context/Privacy'
import { useThemeContext } from '@src/context/Theme'
@@ -21,15 +22,15 @@ import Logo from './Logo'
import Txt from './Txt'
interface IBalanceProps {
- balance: number
nav?: NativeStackNavigationProp
}
-export default function Balance({ balance, nav }: IBalanceProps) {
+export default function Balance({ nav }: IBalanceProps) {
const { t } = useTranslation([NS.common])
const { pref, color, highlight } = useThemeContext()
const { hidden, handleLogoPress } = usePrivacyContext()
const [formatSats, setFormatSats] = useState(pref?.formatBalance)
+ const { balance } = useBalanceContext()
const { latestHistory } = useHistoryContext()
const toggleBalanceFormat = () => {
diff --git a/src/context/Balance.tsx b/src/context/Balance.tsx
new file mode 100644
index 00000000..488ad44b
--- /dev/null
+++ b/src/context/Balance.tsx
@@ -0,0 +1,45 @@
+/* eslint-disable @typescript-eslint/require-await */
+/* eslint-disable require-await */
+import { getBalance } from '@db'
+import { l } from '@log'
+import { createContext, useContext, useEffect, useState } from 'react'
+
+import { useFocusClaimContext } from './FocusClaim'
+
+// Total Balance state (all mints)
+const useBalance = () => {
+ const [balance, setBalance] = useState(0)
+ const { claimed } = useFocusClaimContext()
+
+ const updateBalance = async () => {
+ const bal = await getBalance()
+ setBalance(bal)
+ }
+
+ useEffect(() => {
+ void updateBalance()
+ }, [])
+
+ useEffect(() => {
+ void updateBalance()
+ }, [claimed])
+
+ return {
+ balance,
+ updateBalance
+ }
+}
+type useBalanceType = ReturnType
+
+const BalanceCtx = createContext({
+ balance: 0,
+ updateBalance: async () => l(''),
+})
+
+export const useBalanceContext = () => useContext(BalanceCtx)
+
+export const BalanceProvider = ({ children }: { children: React.ReactNode }) => (
+
+ {children}
+
+)
\ No newline at end of file
diff --git a/src/context/History.tsx b/src/context/History.tsx
index c00865ce..c6c33c45 100644
--- a/src/context/History.tsx
+++ b/src/context/History.tsx
@@ -12,6 +12,7 @@ import { requestToken } from '@wallet'
import { createContext, useContext, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
+import { useBalanceContext } from './Balance'
import { useFocusClaimContext } from './FocusClaim'
import { usePromptContext } from './Prompt'
@@ -22,6 +23,7 @@ const useHistory = () => {
// State to indicate token claim from clipboard after app comes to the foreground, to re-render total balance
const { claimed } = useFocusClaimContext()
const { openPromptAutoClose } = usePromptContext()
+ const { updateBalance } = useBalanceContext()
const allHisoryEntries = useRef([])
const hasEntries = useMemo(() => Object.keys(history).length > 0, [history])
const lastCalled = useRef(0)
@@ -99,7 +101,6 @@ const useHistory = () => {
if (entry) {
await updateHistoryEntry(entry, { ...entry, isPending: false })
}
- // TODO update balance
await delInvoice(invoice.hash)
} else {
openPromptAutoClose({ msg: t('paymentPending'), success: false })
@@ -109,12 +110,14 @@ const useHistory = () => {
const addHistoryEntry = async (entry: Omit) => {
const resp = await addToHistory(entry)
await setHistoryEntries()
+ await updateBalance()
return resp
}
const updateHistoryEntry = async (oldEntry: IHistoryEntry, newEntry: IHistoryEntry) => {
await updateHistory(oldEntry, newEntry)
await setHistoryEntries()
+ await updateBalance()
}
const deleteHistory = async () => {
diff --git a/src/screens/Dashboard.tsx b/src/screens/Dashboard.tsx
index ecdb4a32..4e4f5ce4 100644
--- a/src/screens/Dashboard.tsx
+++ b/src/screens/Dashboard.tsx
@@ -8,7 +8,7 @@ import OptsModal from '@comps/modal/OptsModal'
import { PromptModal } from '@comps/modal/Prompt'
import Txt from '@comps/Txt'
import { _testmintUrl, env } from '@consts'
-import { addMint, getBalance, getMintsUrls, hasMints } from '@db'
+import { addMint, getMintsUrls, hasMints } from '@db'
import { l } from '@log'
import TrustMintModal from '@modal/TrustMint'
import type { TBeforeRemoveEvent, TDashboardPageProps } from '@model/nav'
@@ -56,8 +56,6 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
trustModal,
setTrustModal
} = useCashuToken()
- // Total Balance state (all mints)
- const [balance, setBalance] = useState(0)
const [hasMint, setHasMint] = useState(false)
// modals
const [modal, setModal] = useState({
@@ -236,7 +234,6 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
}))
clearTimeout(t)
}, 1000)
-
})()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
@@ -244,16 +241,13 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
// check for available mints of the user
useEffect(() => {
void (async () => {
- const [userHasMints, explainerSeen, balance] = await Promise.all([
+ const [userHasMints, explainerSeen] = await Promise.all([
hasMints(),
store.get(STORE_KEYS.explainer),
- getBalance(),
])
setHasMint(userHasMints)
setModal(prev => ({ ...prev, mint: !userHasMints && explainerSeen !== '1' }))
- setBalance(balance)
})()
- // eslint-disable-next-line react-hooks/exhaustive-deps
}, [claimed])
// handle deep links
@@ -274,15 +268,11 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url])
- // get balance after navigating to this page
+ // update states after navigating to this page
useEffect(() => {
const focusHandler = navigation.addListener('focus', async () => {
- const data = await Promise.all([
- getBalance(),
- hasMints()
- ])
- setBalance(data[0])
- setHasMint(data[1])
+ const data = await hasMints()
+ setHasMint(data)
})
return focusHandler
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -298,7 +288,7 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
return (
{/* Balance, Disclaimer & History */}
-
+
{/* Receive/send/mints buttons */}
{/* Send button or add first mint */}
diff --git a/src/screens/Payment/Send/EncodedToken.tsx b/src/screens/Payment/Send/EncodedToken.tsx
index 4cd9e153..983ebe0d 100644
--- a/src/screens/Payment/Send/EncodedToken.tsx
+++ b/src/screens/Payment/Send/EncodedToken.tsx
@@ -7,9 +7,11 @@ import type { TBeforeRemoveEvent, TEncodedTokenPageProps } from '@model/nav'
import TopNav from '@nav/TopNav'
import { preventBack } from '@nav/utils'
import { isIOS } from '@src/consts'
+import { useBalanceContext } from '@src/context/Balance'
+import { useHistoryContext } from '@src/context/History'
import { useThemeContext } from '@src/context/Theme'
import { NS } from '@src/i18n'
-import { historyStore, store } from '@store'
+import { store } from '@store'
import { STORE_KEYS } from '@store/consts'
import { globals, highlight as hi, mainColors } from '@styles'
import { formatInt, formatSatStr, share, vib } from '@util'
@@ -27,6 +29,8 @@ export default function EncodedTokenPage({ navigation, route }: TEncodedTokenPag
const { value, amount } = route.params.entry
const { t } = useTranslation([NS.common])
const { color, highlight } = useThemeContext()
+ const { updateHistoryEntry } = useHistoryContext()
+ const { updateBalance } = useBalanceContext()
const [error, setError] = useState({ msg: '', open: false })
const [spent, setSpent] = useState(false)
const { copied, copy } = useCopy()
@@ -43,8 +47,7 @@ export default function EncodedTokenPage({ navigation, route }: TEncodedTokenPag
setSpent(!isSpendable)
if (!isSpendable) {
clearTokenInterval()
- // update history item
- await historyStore.updateHistoryEntry(route.params.entry, { ...route.params.entry, isSpent: true })
+ await updateHistoryEntry(route.params.entry, { ...route.params.entry, isSpent: true })
}
}
@@ -63,6 +66,7 @@ export default function EncodedTokenPage({ navigation, route }: TEncodedTokenPag
// auto check payment in intervals
useEffect(() => {
+ void updateBalance()
intervalRef.current = setInterval(() => {
void checkPayment()
}, 3000)
diff --git a/src/screens/Payment/Success.tsx b/src/screens/Payment/Success.tsx
index 76b7ff3b..f4acefbf 100644
--- a/src/screens/Payment/Success.tsx
+++ b/src/screens/Payment/Success.tsx
@@ -5,9 +5,9 @@ import { isIOS } from '@consts'
import type { TBeforeRemoveEvent, TSuccessPageProps } from '@model/nav'
import { preventBack } from '@nav/utils'
import ProfilePic from '@screens/Addressbook/ProfilePic'
+import { useBalanceContext } from '@src/context/Balance'
import { useThemeContext } from '@src/context/Theme'
import { NS } from '@src/i18n'
-import { l } from '@src/logger'
import { formatSatStr, isNum, vib } from '@util'
import LottieView from 'lottie-react-native'
import { useEffect } from 'react'
@@ -33,9 +33,14 @@ export default function SuccessPage({ navigation, route }: TSuccessPageProps) {
} = route.params
const { t } = useTranslation([NS.common])
const { color } = useThemeContext()
+ const { updateBalance } = useBalanceContext()
const insets = useSafeAreaInsets()
- useEffect(() => vib(400), [])
+ useEffect(() => {
+ vib(400)
+ void updateBalance()
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [])
// prevent back navigation - https://reactnavigation.org/docs/preventing-going-back/
useEffect(() => {
@@ -44,8 +49,6 @@ export default function SuccessPage({ navigation, route }: TSuccessPageProps) {
return () => navigation.removeListener('beforeRemove', backHandler)
}, [navigation])
- l({ amount, memo, fee, mint, isClaim, isMelt, nostr, isScanned })
-
return (
{nostr && nostr.contact && nostr.contact.picture ?