Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cashu token memo #25

Merged
merged 14 commits into from
Jun 8, 2023
Merged
5 changes: 3 additions & 2 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ export default function App(_initialProps: IInitialProps) {
if (!tokenInfo) { return }
const encoded = getEncodedToken(tokenInfo.decoded)
const success = await claimToken(encoded).catch(l)
stopLoading()
if (!success) {
alert('Token invalid or already claimed')
setClaimOpen(false)
Expand All @@ -151,6 +150,7 @@ export default function App(_initialProps: IInitialProps) {
})
openPrompt(`Successfully claimed ${formatInt(info.value)} Satoshi!`)
setClaimed(true)
stopLoading()
setClaimOpen(false)
}

Expand Down Expand Up @@ -256,11 +256,12 @@ export default function App(_initialProps: IInitialProps) {
Found a cashu token in your clipboard
</Text>
<Text style={globals(color, highlight).modalTxt}>
Memo: {tokenInfo?.decoded.memo}{'\n'}
<Text style={{ fontWeight: '500' }}>
{formatInt(tokenInfo?.value || 0)}
</Text>
{' '}Satoshi from the following mint:{' '}
{tokenInfo?.mints.map(m => m)}
{tokenInfo?.mints.join(', ')}
</Text>
<Button
txt={loading ? 'Claiming...' : 'Claim now!'}
Expand Down
8 changes: 7 additions & 1 deletion src/components/Success.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ interface ISuccessProps {
fee?: number
mints?: string[]
mint?: string
memo?: string
nav?: NativeStackNavigationProp<RootStackParamList, 'success', 'MyStack'>
hash?: string
}

export default function Success({ amount, fee, mints, mint, nav, hash }: ISuccessProps) {
export default function Success({ amount, fee, mints, mint, memo, nav, hash }: ISuccessProps) {
const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList, 'success', 'MyStack'>>()
const [testMintTokenRdy, setTestMintTokenRdy] = useState(false)
// Only for the hard-coded test mint. Otherwise this is done for other mints before landing in this page
Expand Down Expand Up @@ -59,6 +60,11 @@ export default function Success({ amount, fee, mints, mint, nav, hash }: ISucces
<>{formatInt(amount)} Satoshi {mints ? 'claimed' : 'minted'}!</>
}
</Text>
{memo &&
<Text style={styles.mints}>
{memo}
</Text>
}
{mints && mints.map(m => (
<Text style={styles.mints} key={m}>
{formatMintUrl(m)}
Expand Down
35 changes: 35 additions & 0 deletions src/components/Toaster.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { mainColors } from '@src/styles'
import { StyleSheet, Text } from 'react-native'
import Animated, { FadeInUp, FadeOutUp } from 'react-native-reanimated'

export default function Toaster({ success, txt }: { success?: boolean, txt: string }) {
return (
<Animated.View
entering={FadeInUp}
exiting={FadeOutUp}
style={[styles.container, { backgroundColor: success ? mainColors.VALID : '#FF6666' }]}
>
<Text style={styles.txt}>
{txt}
</Text>
</Animated.View>
)
}

const styles = StyleSheet.create({
container: {
width: '90%',
position: 'absolute',
padding: 20,
alignItems: 'center',
top: 50,
left: 20,
right: 20,
borderRadius: 8,
},
txt: {
fontSize: 18,
fontWeight: '500',
color: '#FAFAFA'
},
})
18 changes: 16 additions & 2 deletions src/components/hooks/Prompt.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import { useState } from 'react'

interface IPromptState {
open: boolean
success?: boolean
msg: string
}

export default function usePrompt() {
const [prompt, setPrompt] = useState({ open: false, msg: '' })
const [prompt, setPrompt] = useState<IPromptState>({ open: false, msg: '' })
const openPrompt = (msg: string) => {
setPrompt({ open: true, msg })
}
const closePrompt = () => {
setPrompt({ open: false, msg: '' })
}
const openPromptAutoClose = (success: boolean, msg: string) => {
setPrompt({ success, open: true, msg })
const t = setTimeout(() => {
setPrompt({ open: false, msg: '' })
clearTimeout(t)
}, 2500)
}

return {
prompt,
openPrompt,
closePrompt
closePrompt,
openPromptAutoClose
}

}
6 changes: 3 additions & 3 deletions src/components/pages/Addressbook/Book.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,19 +169,19 @@ export default function AddressBook({ nav, isModal, closeModal, setInput }: IAdd
{openNew.open && !prompt.open &&
<MyModal type='bottom' animation='slide' visible={true}>
<Text style={globals(color).modalHeader}>
{openNew.isOwner ? 'Your LN address' : 'New address'}
{openNew.isOwner ? 'Your LNURL' : 'New contact'}
</Text>
{!openNew.isOwner &&
<TextInput
style={globals(color).input}
style={[globals(color).input, { marginBottom: 20 }]}
placeholder="Name"
placeholderTextColor={color.INPUT_PH}
selectionColor={hi[highlight]}
onChangeText={setNewContactName}
/>
}
<TextInput
style={globals(color).input}
style={[globals(color).input, { marginBottom: 20 }]}
placeholder="zap@me.now"
placeholderTextColor={color.INPUT_PH}
selectionColor={hi[highlight]}
Expand Down
6 changes: 3 additions & 3 deletions src/components/pages/Addressbook/Contact.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ export default function ContactPage({ navigation, route }: IContactPageProps) {
{openEdit && !prompt.open &&
<MyModal type='bottom' animation='slide' visible={true}>
<Text style={globals(color).modalHeader}>
{route.params.contact?.isOwner ? 'Edit' : 'Edit contact'}
Edit contact
</Text>
{!route.params.contact?.isOwner &&
<TextInput
style={globals(color).input}
style={[globals(color).input, { marginBottom: 20 }]}
placeholder="Name"
placeholderTextColor={color.INPUT_PH}
selectionColor={hi[highlight]}
Expand All @@ -120,7 +120,7 @@ export default function ContactPage({ navigation, route }: IContactPageProps) {
/>
}
<TextInput
style={globals(color).input}
style={[globals(color).input, { marginBottom: 20 }]}
placeholder="zap@me.now"
placeholderTextColor={color.INPUT_PH}
selectionColor={hi[highlight]}
Expand Down
23 changes: 10 additions & 13 deletions src/components/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import Button from '@comps/Button'
import useLoading from '@comps/hooks/Loading'
import usePrompt from '@comps/hooks/Prompt'
import useCashuToken from '@comps/hooks/Token'
import Toaster from '@comps/Toaster'
import { addMint, getBalance, getMintsUrls, hasMints } from '@db'
import { l } from '@log'
import MyModal from '@modal'
import OptsModal from '@modal/OptsModal'
import { PromptModal } from '@modal/Prompt'
import TrustMintModal from '@modal/TrustMint'
import { TDashboardPageProps } from '@model/nav'
import BottomNav from '@nav/BottomNav'
Expand All @@ -35,7 +35,7 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
// Total Balance state (all mints)
const [balance, setBalance] = useState(0)
// Prompt modal
const { prompt, openPrompt, closePrompt } = usePrompt()
const { prompt, openPromptAutoClose } = usePrompt()
// Cashu token hook
const {
token,
Expand All @@ -60,7 +60,7 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
// TODO Maybe we should provide the user the possibility to choose mints
// in the trust modal-question once multiple mints per token are available...
if (!tokenInfo) {
openPrompt('Your clipboard contains an invalid cashu token!')
openPromptAutoClose(false, 'Your clipboard contains an invalid cashu token!')
setModal({ ...modal, receiveOpts: false })
stopLoading()
return
Expand All @@ -84,7 +84,7 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
const handleTokenSubmit = async (url: string) => {
const tokenInfo = getTokenInfo(url)
if (!tokenInfo) {
openPrompt('Your clipboard contains an invalid cashu token!')
openPromptAutoClose(false, 'Your clipboard contains an invalid cashu token!')
setModal({ ...modal, receiveOpts: false })
stopLoading()
return
Expand All @@ -110,7 +110,7 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
setToken('')
stopLoading()
if (!success) {
openPrompt('Token invalid or already claimed')
openPromptAutoClose(false, 'Token invalid or already claimed')
return
}
const info = getTokenInfo(encodedToken)
Expand All @@ -127,7 +127,8 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
})
navigation.navigate('success', {
amount: info?.value,
mints: info?.mints
mints: info?.mints,
memo: info?.decoded.memo
})
}

Expand Down Expand Up @@ -217,7 +218,7 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
void (async () => {
const clipboard = await Clipboard.getStringAsync()
if (!isCashuToken(clipboard)) {
openPrompt('Your clipboard contains an invalid cashu token!')
openPromptAutoClose(false, 'Your clipboard contains an invalid cashu token!')
setModal({ ...modal, receiveOpts: false })
return
}
Expand Down Expand Up @@ -250,12 +251,8 @@ export default function Dashboard({ navigation, route }: TDashboardPageProps) {
onPressCancel={() => setModal({ ...modal, sendOpts: false })}
/>
}
{/* Prompt modal */}
<PromptModal
header={prompt.msg}
visible={prompt.open}
close={closePrompt}
/>
{/* Prompt toaster */}
{prompt.open && <Toaster success={prompt.success} txt={prompt.msg} />}
</View>
)
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/pages/History/Entry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default function HistoryEntry({ nav, item }: IHistoryEntryProps) {
</Text>
</View>
<Text style={[globals(color, highlight).txt, styles.amount, { color: item.amount < 0 ? color.ERROR : mainColors.VALID }]}>
{formatInt(item.amount < 0 ? Math.abs(item.amount) : item.amount, 'compact')}
{formatInt(item.amount < 0 ? Math.abs(item.amount) : item.amount, 'compact', 'en')}
<ZapIcon width={15} height={15} color={item.amount < 0 ? color.ERROR : mainColors.VALID} />
</Text>
</TouchableOpacity>
Expand Down
2 changes: 1 addition & 1 deletion src/components/pages/Lightning/mintPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function MintPanel({ nav, mints, selectedMint, lnAmount, setSelec
return nav.route.params?.mint ?
<View style={styles.minBalWrap}>
<Text style={[styles.singleMint, { color: color.TEXT }]}>
{formatMintUrl(nav.route.params.mint.mint_url)}
{nav.route.params.mint.customName || formatMintUrl(nav.route.params.mint.mint_url)}
</Text>
<View style={styles.mintBal}>
<Text style={[
Expand Down
Loading