Skip to content

Commit

Permalink
Implement QR Code Generation and Scanning for Cashu Wallet (#213)
Browse files Browse the repository at this point in the history
* added QRCODE

* removed vision camera lib

* reverted tsconfig

* added expo camera for qrcode scanning

* added qrcode send or recieve functionality

* added qrcode send or recieve functionality

* added qrcode identifiier

* removed unecessary folders

* made modifications

* made modifications

* corrected tsconfig

* made changes
  • Loading branch information
akintewe authored Oct 25, 2024
1 parent c209641 commit b6ec2e3
Show file tree
Hide file tree
Showing 8 changed files with 283 additions and 134 deletions.
8 changes: 4 additions & 4 deletions apps/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"@starknet-react/core": "^2.8.2",
"@starknet-wc/core": "0.0.4",
"@starknet-wc/react": "0.0.4",
"@stripe/stripe-react-native": "0.38.6",
"@tanstack/react-query": "^5.40.0",
"@tanstack/react-query-persist-client": "5.40.0",
"@uniswap/sdk-core": "^5.3.1",
Expand All @@ -72,7 +73,7 @@
"common": "workspace:*",
"crypto-es": "^2.1.0",
"events": "^3.3.0",
"expo": "~51.0.28",
"expo": "~51.0.38",
"expo-application": "^5.9.1",
"expo-auth-session": "^5.5.2",
"expo-av": "~14.0.7",
Expand Down Expand Up @@ -110,7 +111,7 @@
"react-native-pager-view": "6.3.0",
"react-native-passkey": "2.1.1",
"react-native-portalize": "^1.0.7",
"react-native-qrcode-svg": "^6.3.1",
"react-native-qrcode-svg": "^6.3.12",
"react-native-reanimated": "~3.10.1",
"react-native-redash": "^18.1.3",
"react-native-safe-area-context": "4.10.1",
Expand All @@ -126,8 +127,7 @@
"text-encoding": "^0.7.0",
"viem": "2.x",
"wagmi": "^2.12.8",
"zustand": "^4.5.2",
"@stripe/stripe-react-native":"0.38.6"
"zustand": "^4.5.2"
},
"devDependencies": {
"@babel/core": "^7.20.0",
Expand Down
9 changes: 3 additions & 6 deletions apps/mobile/src/modules/Cashu/GenerateInvoiceCashu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {useStyles, useTheme} from '../../hooks';
import {useDialog, useToast} from '../../hooks/modals';
import {SelectedTab} from '../../types/tab';
import {getInvoices, storeInvoices} from '../../utils/storage_cashu';
import GenerateQRCode from './qr/GenerateQRCode';
import stylesheet from './styles';

export const GenerateInvoiceCashu = () => {
Expand Down Expand Up @@ -122,8 +123,6 @@ export const GenerateInvoiceCashu = () => {

const cashuInvoice: ICashuInvoice = {
bolt11: quote?.request?.request,
// quote: quote?.request?.quote,
// state: quote?.request?.state,
date: new Date().getTime(),
amount: Number(invoiceAmount),
mint: mintUrl,
Expand All @@ -133,12 +132,8 @@ export const GenerateInvoiceCashu = () => {

if (invoicesLocal) {
const invoices: ICashuInvoice[] = JSON.parse(invoicesLocal);

console.log('invoices', invoices);
storeInvoices([...invoices, cashuInvoice]);
} else {
console.log('no old invoicesLocal', invoicesLocal);

storeInvoices([cashuInvoice]);
}
} catch (error) {
Expand Down Expand Up @@ -222,6 +217,8 @@ export const GenerateInvoiceCashu = () => {
</TouchableOpacity>
}
/>
{/* Ensure the data prop is correctly passed */}
<GenerateQRCode data={quote?.request} size={200} />
</View>
)}
</View>
Expand Down
72 changes: 14 additions & 58 deletions apps/mobile/src/modules/Cashu/ReceiveEcash.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {useStyles, useTheme} from '../../hooks';
import {useDialog, useToast} from '../../hooks/modals';
import {SelectedTab} from '../../types/tab';
import {getInvoices, storeInvoices} from '../../utils/storage_cashu';
import GenerateQRCode from './qr/GenerateQRCode'; // Import the QR code component
import stylesheet from './styles';
// import QRCode from 'qrcode'; // replace with reactnative qrcode lib

export const ReceiveEcash = () => {
const tabs = ['lightning', 'ecash'];
Expand All @@ -37,7 +37,6 @@ export const ReceiveEcash = () => {
const {isSeedCashuStorage, setIsSeedCashuStorage} = useCashuStore();

const styles = useStyles(stylesheet);
// const [mintUrl, setMintUrl] = useState<string | undefined>("https://mint.minibits.cash/Bitcoin")

const [quote, setQuote] = useState<MintQuoteResponse | undefined>();
const [infoMint, setMintInfo] = useState<GetInfoResponse | undefined>();
Expand Down Expand Up @@ -149,35 +148,10 @@ export const ReceiveEcash = () => {
}
};

// Encode the Cashu token into a string

// Generate the QR Code from the Cashu token string
useEffect(() => {
// QRCode.toDataURL(ecash)
// .then((url: React.SetStateAction<string | undefined>) => {
// setQRCodeUrl(url); // Set the generated QR code URL
// })
// .catch((err: any) => console.error(err));
}, [ecash]);

return (
<SafeAreaView
// style={styles.safeArea}
>
<View
// style={styles.container}
>
<View
// style={styles.container}
>
{/* <View style={styles.content}>
<TextInput
placeholder="Mint URL"
value={mintUrl}
onChangeText={setMintUrl}
style={styles.input}
/>
</View> */}
<SafeAreaView>
<View>
<View>
<View style={styles.tabContainer}>
{tabs.map((tab) => (
<TouchableOpacity
Expand All @@ -193,21 +167,14 @@ export const ReceiveEcash = () => {
{activeTab == 'ecash' && (
<>
<TextInput
// className="bg-accent text-white rounded-lg px-4 py-2 hover:bg-opacity-90 transition-colors duration-150"
// className="bg-black text-white rounded-lg px-4 py-2 hover:bg-opacity-90 transition-colors duration-150"
placeholder="Enter token: cashuXYZ"
// keyboardType=""
value={ecash}
onChangeText={setEcash}
style={styles.input}
></TextInput>
/>

{ecash && (
<View
style={{
marginVertical: 3,
}}
>
<View style={{marginVertical: 3}}>
<Text style={styles.text}>ecash token</Text>

<Input
Expand All @@ -216,23 +183,15 @@ export const ReceiveEcash = () => {
right={
<TouchableOpacity
onPress={() => handleCopy('ecash')}
style={{
marginRight: 10,
}}
style={{marginRight: 10}}
>
<CopyIconStack color={theme.colors.primary} />
</TouchableOpacity>
}
/>

{/* {qrCodeUrl ? (
<Image
href={qrCodeUrl}
style={{ width: 200, height: 200 }}
/>
) : (
<Text>Generating QR Code...</Text>
)} */}
{/* Generate QR code for the eCash token */}
<GenerateQRCode data={ecash} size={200} />
</View>
)}

Expand All @@ -253,11 +212,7 @@ export const ReceiveEcash = () => {
<Button onPress={generateInvoice}>Generate invoice</Button>

{quote?.request && (
<View
style={{
marginVertical: 3,
}}
>
<View style={{marginVertical: 3}}>
<Text style={styles.text}>Invoice address</Text>

<Input
Expand All @@ -266,14 +221,15 @@ export const ReceiveEcash = () => {
right={
<TouchableOpacity
onPress={() => handleCopy('lnbc')}
style={{
marginRight: 10,
}}
style={{marginRight: 10}}
>
<CopyIconStack color={theme.colors.primary} />
</TouchableOpacity>
}
/>

{/* Display the QR code for the invoice */}
<GenerateQRCode data={quote?.request} size={200} />
</View>
)}
</>
Expand Down
16 changes: 15 additions & 1 deletion apps/mobile/src/modules/Cashu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {InvoicesListCashu} from './InvoicesListCashu';
import {MintListCashu} from './MintListCashu';
import {MnemonicCashu} from './MnemonicCashu';
import {NoMintBanner} from './NoMintBanner';
import ScanCashuQRCode from './qr/ScanCode'; // Adjust the import path as needed
import {ReceiveEcash} from './ReceiveEcash';
import {SendEcash} from './SendEcash';
import stylesheet from './styles';
Expand Down Expand Up @@ -109,6 +110,16 @@ export const CashuView = () => {
const [selectedTab, setSelectedTab] = useState<SelectedTab | undefined>(SelectedTab.CASHU_WALLET);
const [showMore, setShowMore] = useState<boolean>(false);

const [isScannerVisible, setIsScannerVisible] = useState(false);

const handleQRCodeClick = () => {
setIsScannerVisible(true);
};

const handleCloseScanner = () => {
setIsScannerVisible(false);
};

const handleTabSelected = (tab: string | SelectedTab, screen?: string) => {
setSelectedTab(tab as any);
if (screen) {
Expand Down Expand Up @@ -199,7 +210,7 @@ export const CashuView = () => {
</View>
<Text style={styles.orText}>or</Text>
<View>
<Button onPress={() => console.log('todo: add scanner')} style={styles.qrButton}>
<Button onPress={handleQRCodeClick} style={styles.qrButton}>
<ScanQrIcon width={60} height={60} color={theme.colors.primary} />
</Button>
</View>
Expand Down Expand Up @@ -297,6 +308,9 @@ export const CashuView = () => {
)}
</ScrollView>
</SafeAreaView>
<Modal visible={isScannerVisible} onRequestClose={handleCloseScanner}>
<ScanCashuQRCode onClose={handleCloseScanner} />
</Modal>
</View>
);
};
Expand Down
25 changes: 25 additions & 0 deletions apps/mobile/src/modules/Cashu/qr/GenerateQRCode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import {StyleSheet, View} from 'react-native';
import QRCode from 'react-native-qrcode-svg';

interface GenerateQRCodeProps {
data: string;
size?: number;
}

const GenerateQRCode: React.FC<GenerateQRCodeProps> = ({data, size = 200}) => {
return (
<View style={styles.container}>
<QRCode value={data} size={size} />
</View>
);
};

const styles = StyleSheet.create({
container: {
alignItems: 'center',
justifyContent: 'center',
},
});

export default GenerateQRCode;
Loading

0 comments on commit b6ec2e3

Please sign in to comment.