Skip to content

Commit

Permalink
Recover from failed splits, mint info screen
Browse files Browse the repository at this point in the history
  • Loading branch information
minibits-cash committed Dec 23, 2023
1 parent 7a74981 commit 7c49e9d
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 7 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "minibits_wallet",
"version": "0.1.5-beta.19",
"version": "0.1.5-beta.20",
"private": true,
"scripts": {
"android:clean": "cd android && ./gradlew clean",
Expand Down
5 changes: 4 additions & 1 deletion src/navigation/TabsNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {
ProfileScreen,
WalletNameScreen,
SettingsScreen,
MintsScreen,
MintsScreen,
MintInfoScreen,
DeveloperScreen,
SecurityScreen,
PrivacyScreen,
Expand Down Expand Up @@ -204,6 +205,7 @@ export type ContactsStackScreenProps<T extends keyof ContactsStackParamList> = S
export type SettingsStackParamList = {
Settings: undefined
Mints: {scannedMintUrl? : string}
MintInfo: {mintUrl : string}
Security: undefined
Privacy: undefined
Update: {
Expand Down Expand Up @@ -238,6 +240,7 @@ const SettingsNavigator = function SettingsNavigator() {
>
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
<SettingsStack.Screen name="Mints" component={MintsScreen} />
<SettingsStack.Screen name="MintInfo" component={MintInfoScreen} />
<SettingsStack.Screen name="Security" component={SecurityScreen} />
<SettingsStack.Screen name="Privacy" component={PrivacyScreen} />
<SettingsStack.Screen name="Update" component={UpdateScreen} />
Expand Down
189 changes: 189 additions & 0 deletions src/screens/MintInfoScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import {observer} from 'mobx-react-lite'
import React, {FC, useEffect, useState} from 'react'
import {Alert, FlatList, TextStyle, View, ViewStyle} from 'react-native'
import {colors, spacing, useThemeColor} from '../theme'
import {SettingsStackScreenProps} from '../navigation'
import {
APP_ENV,
NATIVE_VERSION_ANDROID,
JS_BUNDLE_VERSION,
COMMIT,
MINIBITS_MINT_URL,
MINIBITS_RELAY_URL,
MINIBITS_NIP05_DOMAIN,
MINIBITS_SERVER_API_HOST
} from '@env'
import packageJson from '../../package.json'
import {
Icon,
ListItem,
Screen,
Text,
Card,
Loading,
ErrorModal,
InfoModal,
BottomModal,
Button,
} from '../components'
import {useHeader} from '../utils/useHeader'
import {useStores} from '../models'
import {translate} from '../i18n'
import AppError, { Err } from '../utils/AppError'
import {Database, KeyChain, log, MintClient, NostrClient} from '../services'
import {MMKVStorage} from '../services'
import {maxTransactionsInModel} from '../models/TransactionsStore'
import { LogLevel } from '../services/log/logTypes'
import { GetInfoResponse } from '@cashu/cashu-ts'
import { delay } from '../utils/utils'
import JSONTree from 'react-native-json-tree'
import { getSnapshot } from 'mobx-state-tree'
import { Mint } from '../models/Mint'
import useColorScheme from '../theme/useThemeColor'

// refresh

export const MintInfoScreen: FC<SettingsStackScreenProps<'MintInfo'>> = observer(function MintInfoScreen(_props) {
const {navigation, route} = _props
useHeader({
leftIcon: 'faArrowLeft',
onLeftPress: () => navigation.navigate('Settings'),
})

const {mintsStore} = useStores()

const [isLoading, setIsLoading] = useState(false)
const [mintInfo, setMintInfo] = useState<GetInfoResponse | undefined>()

const [error, setError] = useState<AppError | undefined>()
const [info, setInfo] = useState('')

useEffect(() => {
const getInfo = async () => {
try {
if(!route.params || !route.params.mintUrl) {
throw new AppError(Err.VALIDATION_ERROR, 'Missing mintUrl')
}

log.trace('useEffect', {mintUrl: route.params.mintUrl})

setIsLoading(true)
const info = await MintClient.getMintInfo(route.params.mintUrl)
await delay(1000)
setMintInfo(info)
setIsLoading(false)
} catch (e: any) {
handleError(e)
}
}
getInfo()
}, [])



const handleError = function (e: AppError): void {
setIsLoading(false)
setError(e)
}

const headerBg = useThemeColor('header')
const iconSelectedColor = useThemeColor('button')
const iconColor = useThemeColor('textDim')
const labelColor = useThemeColor('textDim')
const colorScheme = useColorScheme()

return (
<Screen style={$screen} preset="scroll">
<View style={[$headerContainer, {backgroundColor: headerBg}]}>
<Text
preset="heading"
text="Mint info"
style={{color: 'white'}}
/>
</View>
<View style={$contentContainer}>

<>
<Card
ContentComponent={mintInfo ? (
Object.entries(mintInfo).map(([key, value], index) => (
<ListItem
text={key}
RightComponent={<Text text={value.toString().slice(0,20)}/>}
topSeparator={index === 0 ? false : true}
key={key}
/>
))
) : (
isLoading && <Loading style={{backgroundColor: 'transparent'}} statusMessage='Loading public info' />
)}
style={$card}
/>
<Card
style={[$card, {marginTop: spacing.small}]}
ContentComponent={
<>
<Text
style={{color: labelColor, fontSize: 14}}
text="Internal information"
/>
<JSONTree
hideRoot
data={getSnapshot(mintsStore.findByUrl(route.params?.mintUrl) as Mint)}
theme={{
scheme: 'default',
base00: '#eee',
}}
invertTheme={colorScheme === 'light' ? false : true}
/>
</>
}
/>
</>



{error && <ErrorModal error={error} />}
{info && <InfoModal message={info} />}
</View>
</Screen>
)
})

const $screen: ViewStyle = {
flex: 1,
}

const $headerContainer: TextStyle = {
alignItems: 'center',
padding: spacing.medium,
height: spacing.screenHeight * 0.1,
}

const $contentContainer: TextStyle = {
flex: 1,
padding: spacing.extraSmall,
// alignItems: 'center',
}

const $card: ViewStyle = {
marginBottom: 0,
}

const $item: ViewStyle = {
paddingHorizontal: spacing.small,
paddingLeft: 0,
}

const $rightContainer: ViewStyle = {
padding: spacing.extraSmall,
alignSelf: 'center',
marginLeft: spacing.small,
}

const $buttonContainer: ViewStyle = {
flexDirection: 'row',
alignSelf: 'center',
alignItems: 'center',
marginTop: spacing.large,
}
2 changes: 1 addition & 1 deletion src/screens/Mints/MintListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const MintListItem = observer(function(props: {
rightIconColor={props.isBlocked ? iconBlockedColor : iconColor as string}
onPress={props.onMintSelect ? () => props.onMintSelect(props.mint, props.mintBalance) : undefined}
RightComponent={props.mintBalance && <Text text={`${props.mintBalance?.balance}`} style={{alignSelf: 'center', marginRight: spacing.medium}}/>}
style={{paddingHorizontal: spacing.small}}
style={{paddingHorizontal: spacing.tiny}}
containerStyle={{alignSelf: 'stretch'}}
bottomSeparator={props.separator === 'bottom' || props.separator === 'both'}
topSeparator={props.separator === 'top' || props.separator === 'both'}
Expand Down
9 changes: 8 additions & 1 deletion src/screens/MintsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ export const MintsScreen: FC<SettingsStackScreenProps<'Mints'>> = observer(funct
navigation.navigate('WalletNavigator', {screen: 'Scan'})
}


const gotoInfo = function () {
if(!selectedMint) {return}
navigation.navigate('MintInfo', {mintUrl: selectedMint?.mintUrl})
onMintUnselect()
}


const addMint = async function () {
setIsAddMintVisible(false)
Expand Down Expand Up @@ -288,7 +295,7 @@ export const MintsScreen: FC<SettingsStackScreenProps<'Mints'>> = observer(funct
<View style={{}}>
<ListItem
leftIcon="faInfoCircle"
onPress={() => Alert.alert('Not yet implemented')}
onPress={gotoInfo}
tx={'mintsScreen.mintInfo'}
bottomSeparator={true}
style={{paddingHorizontal: spacing.medium}}
Expand Down
13 changes: 10 additions & 3 deletions src/screens/WalletScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,10 @@ export const WalletScreen: FC<WalletScreenProps> = observer(
navigation.navigate('Scan')
}

const gotoMintInfo = function (mintUrl: string) {
navigation.navigate('SettingsNavigator', {screen: 'MintInfo', params: {mintUrl}})
}

const gotoTranHistory = function () {
navigation.navigate('TranHistory')
}
Expand Down Expand Up @@ -468,7 +472,8 @@ export const WalletScreen: FC<WalletScreenProps> = observer(
<View key={mints.hostname} style={{marginHorizontal: spacing.extraSmall, flexGrow: 1}}>
<MintsByHostnameListItem
mintsByHostname={mints}
mintBalances={balances.mintBalances.filter(balance => balance.mint.includes(mints.hostname))}
mintBalances={balances.mintBalances.filter(balance => balance.mint.includes(mints.hostname))}
gotoMintInfo={gotoMintInfo}
/>
{transactionsStore.recentByHostname(mints.hostname).length > 0 && (
<Card
Expand Down Expand Up @@ -635,7 +640,8 @@ const PromoBlock = function (props: {addMint: any}) {

const MintsByHostnameListItem = observer(function (props: {
mintsByHostname: MintsByHostname
mintBalances: MintBalance[]
mintBalances: MintBalance[]
gotoMintInfo: any
}) {
const color = useThemeColor('textDim')
const balanceColor = useThemeColor('amount')
Expand All @@ -647,7 +653,7 @@ const MintsByHostnameListItem = observer(function (props: {
<ListItem
text={props.mintsByHostname.hostname}
textStyle={$cardHeading}
style={{marginHorizontal: spacing.micro}}
style={{marginHorizontal: spacing.micro}}
/>
}
ContentComponent={
Expand All @@ -670,6 +676,7 @@ const MintsByHostnameListItem = observer(function (props: {
}
topSeparator={true}
style={$item}
onPress={() => props.gotoMintInfo(mint.mintUrl)}
/>
))}
</>
Expand Down
1 change: 1 addition & 0 deletions src/screens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export * from './OwnKeysScreen'
// SettingsNavigator
export * from './SettingsScreen'
export * from './MintsScreen'
export * from './MintInfoScreen'
export * from './SecurityScreen'
export * from './PrivacyScreen'
export * from './UpdateScreen'
Expand Down
24 changes: 24 additions & 0 deletions src/services/cashuMintClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,29 @@ const restore = async function (
}
}


const getMintInfo = async function (
mintUrl: string,
) {
try {
const cashuMint = getMint(mintUrl)
const info = await cashuMint.getInfo()
log.trace('[getMintInfo]', {info})
return info
} catch (e: any) {
throw new AppError(
Err.MINT_ERROR,
'The mint could not return mint information.',
{
caller: 'getMintInfo',
mintUrl,
message: e.message
}
)
}
}


export const MintClient = {
getOrCreateMnemonic,
getMnemonic,
Expand All @@ -497,4 +520,5 @@ export const MintClient = {
requestLightningInvoice,
requestProofs,
restore,
getMintInfo,
}

0 comments on commit 7c49e9d

Please sign in to comment.