diff --git a/config/jest.config.ts b/config/jest.config.ts index 3dbf4b5c..319a7ac8 100644 --- a/config/jest.config.ts +++ b/config/jest.config.ts @@ -53,7 +53,7 @@ export default (): JestConfigWithTsJest => ({ // '!**/src/styles/**', '!**/src/consts/**', // '!**/src/components/**', - '!**/src/AppEntry.ts', + '!**/src/App.ts', '!**/src/shim.ts', // '!**/src/storage/store/AsyncStore.ts', '!**/src/storage/store/SecureStore.ts', diff --git a/package-lock.json b/package-lock.json index c4f04d86..720ff227 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@react-navigation/core": "^6.4.10", "@react-navigation/native": "^6.1.9", "@react-navigation/native-stack": "^6.9.17", - "@sentry/react-native": "5.5.0", + "@sentry/react-native": "^5.5.0", "@shopify/flash-list": "1.4.3", "crypto-js": "4.2.0", "expo": "^49.0.18", diff --git a/package.json b/package.json index a7975c62..012a7ed9 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "cpd:tsx": "npx -y jscpd -c config/cpd.config.tsx.json src", "cpd": "npm run cpd:ts && npm run cpd:tsx", "deps:c": "npx -y madge --circular --ts-config tsconfig.json --extensions ts,tsx .", - "eas-build-pre-install": "echo \"require('./src/AppEntry.ts')\" > index.js", + "eas-build-pre-install": "echo \"require('./src/App.ts')\" > index.js", "update-translations": "node utils/update-translations.js", "android": "expo run:android" }, @@ -44,7 +44,7 @@ "@react-navigation/core": "^6.4.10", "@react-navigation/native": "^6.1.9", "@react-navigation/native-stack": "^6.9.17", - "@sentry/react-native": "5.5.0", + "@sentry/react-native": "^5.5.0", "@shopify/flash-list": "1.4.3", "crypto-js": "4.2.0", "expo": "^49.0.18", @@ -84,6 +84,7 @@ "text-encoding-polyfill": "^0.6.7" }, "devDependencies": { + "@babel/core": "^7.23.3", "@babel/plugin-proposal-private-methods": "^7.18.6", "@getify/eslint-plugin-proper-arrows": "^11.0.3", "@testing-library/react-native": "^12.4.0", @@ -118,8 +119,7 @@ "ts-jest-resolver": "^2.0.1", "ts-node": "^10.9.1", "typescript": "^5.2.2", - "websql": "^2.0.3", - "@babel/core": "^7.23.3" + "websql": "^2.0.3" }, "homepage": ".", "contributors": [ @@ -151,10 +151,10 @@ "blind-signatures", "lightning-network" ], - "version": "0.1.0", + "version": "0.1.1", "license": "AGPL-3.0-only", "bugs": { "url": "https://github.com/cashubtc/eNuts/issues" }, - "main": "src/AppEntry.ts" + "main": "src/App.ts" } diff --git a/src/AppEntry.ts b/src/App.ts similarity index 100% rename from src/AppEntry.ts rename to src/App.ts diff --git a/src/components/App.tsx b/src/components/App.tsx index 6a4ffbe7..351867eb 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -140,6 +140,9 @@ function _App() { } const handlePinForeground = async () => { + // check if app has pw + const pw = await secureStore.get(SECURESTORE_KEY) + if (isNull(pw)) { return } // check if app is locked const now = Math.ceil(Date.now() / 1000) const lockData = await store.getObj(STORE_KEYS.lock) diff --git a/src/components/ClipboardModal.tsx b/src/components/ClipboardModal.tsx index 9366997a..f0d6f13e 100644 --- a/src/components/ClipboardModal.tsx +++ b/src/components/ClipboardModal.tsx @@ -1,19 +1,76 @@ +import { getEncodedToken } from '@cashu/cashu-ts' +import { type RootStackParamList } from '@model/nav' +import { type NavigationProp, useNavigation } from '@react-navigation/core' import { useFocusClaimContext } from '@src/context/FocusClaim' +import { usePromptContext } from '@src/context/Prompt' import { useThemeContext } from '@src/context/Theme' import { NS } from '@src/i18n' -import { globals } from '@styles' -import { copyStrToClipboard, formatInt, formatMintUrl, formatSatStr } from '@util' +import { addToHistory } from '@store/latestHistoryEntries' +import { globals, mainColors } from '@styles' +import { copyStrToClipboard, formatInt, formatMintUrl, formatSatStr, isErr } from '@util' +import { claimToken } from '@wallet' +import { getTokenInfo } from '@wallet/proofs' import { useTranslation } from 'react-i18next' import { Text } from 'react-native' import Button, { TxtButton } from './Button' +import useLoading from './hooks/Loading' +import Loading from './Loading' import MyModal from './modal' import Txt from './Txt' +type StackNavigation = NavigationProp + export default function ClipboardModal() { + const nav = useNavigation() const { t } = useTranslation([NS.common]) const { color, highlight } = useThemeContext() - const { tokenInfo, claimOpen, closeModal, handleRedeem } = useFocusClaimContext() + const { tokenInfo, claimOpen, setClaimOpen, setClaimed, closeModal } = useFocusClaimContext() + const { loading, startLoading, stopLoading } = useLoading() + const { openPromptAutoClose } = usePromptContext() + + const handleRedeem = async () => { + startLoading() + if (!tokenInfo) { + setClaimOpen(false) + return stopLoading() + } + const encoded = getEncodedToken(tokenInfo.decoded) + try { + const success = await claimToken(encoded) + if (!success) { + stopLoading() + setClaimOpen(false) + return openPromptAutoClose({ msg: t('invalidOrSpent', { ns: NS.common }) }) + } + } catch (e) { + stopLoading() + setClaimOpen(false) + return openPromptAutoClose({ msg: isErr(e) ? e.message : t('claimTokenErr', { ns: NS.error }) }) + } + const info = getTokenInfo(encoded) + if (!info) { + stopLoading() + setClaimOpen(false) + return openPromptAutoClose({ msg: t('tokenInfoErr', { ns: NS.common }) }) + } + stopLoading() + setClaimOpen(false) + // add as history entry (receive ecash) + await addToHistory({ + amount: info.value, + type: 1, + value: encoded, + mints: info.mints, + }) + nav.navigate('success', { + amount: info?.value, + memo: info?.decoded.memo, + isClaim: true + }) + setClaimed(true) + } + return ( tokenInfo && @@ -31,6 +88,7 @@ export default function ClipboardModal() {