Switch bip39 generator (#92)
* adding needed polyfills * adding new package * updated key validation * updated suggusted words component * updated breez test function * updated mnemoinc generator to new package * updated mnemoic to seed to new package * updated back btn * added a minute sync count * updated restore page
This commit is contained in:
@@ -6,8 +6,7 @@
|
||||
*/
|
||||
|
||||
import {NavigationContainer} from '@react-navigation/native';
|
||||
import 'text-encoding-polyfill';
|
||||
import 'react-native-gesture-handler';
|
||||
import './pollyfills';
|
||||
import './i18n'; // for translation option
|
||||
import {createNativeStackNavigator} from '@react-navigation/native-stack';
|
||||
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import {TouchableOpacity, View, Text, StyleSheet, Image} from 'react-native';
|
||||
import {SIZES, COLORS, ICONS, FONT, CENTER} from '../../constants';
|
||||
import {TouchableOpacity, StyleSheet, Image} from 'react-native';
|
||||
import {ICONS} from '../../constants';
|
||||
import {useNavigation} from '@react-navigation/native';
|
||||
import {keyboardGoBack} from '../../functions/customNavigation';
|
||||
import ThemeImage from '../../functions/CustomElements/themeImage';
|
||||
|
||||
export default function Back_BTN(props) {
|
||||
export default function Back_BTN() {
|
||||
const navigate = useNavigation();
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={() => props.navigation(props.destination)}
|
||||
onPress={() => keyboardGoBack(navigate)}
|
||||
style={styles.container}>
|
||||
<Image
|
||||
source={ICONS.smallArrowLeft}
|
||||
style={{width: 30, height: 30, marginRight: 4}}
|
||||
resizeMode="contain"
|
||||
<ThemeImage
|
||||
lightModeIcon={ICONS.smallArrowLeft}
|
||||
darkModeIcon={ICONS.smallArrowLeft}
|
||||
lightsOutIcon={ICONS.smallArrowLeft}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
@@ -17,13 +21,6 @@ export default function Back_BTN(props) {
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: 'transparent',
|
||||
marginBottom: 10,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
text: {
|
||||
fontSize: SIZES.large,
|
||||
fontFamily: FONT.Other_Medium,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,15 +2,14 @@ import {useNavigation} from '@react-navigation/native';
|
||||
import {StyleSheet, View} from 'react-native';
|
||||
import Back_BTN from './back_BTN';
|
||||
import CustomButton from '../../functions/CustomElements/button';
|
||||
import {SIZES} from '../../constants';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
|
||||
export default function LoginNavbar({destination}) {
|
||||
export default function LoginNavbar() {
|
||||
const navigate = useNavigation();
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Back_BTN navigation={navigate.navigate} destination={destination} />
|
||||
<Back_BTN />
|
||||
<CustomButton
|
||||
buttonStyles={{
|
||||
width: 'auto',
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import {Wordlists} from '@dreson4/react-native-quick-bip39';
|
||||
import {COLORS, SIZES} from '../../constants';
|
||||
import {StyleSheet, TouchableOpacity, View} from 'react-native';
|
||||
import {ThemeText} from '../../functions/CustomElements';
|
||||
import {wordlist} from '@scure/bip39/wordlists/english';
|
||||
import {useMemo} from 'react';
|
||||
|
||||
export default function SuggestedWordContainer({
|
||||
inputedKey,
|
||||
@@ -10,40 +11,44 @@ export default function SuggestedWordContainer({
|
||||
keyRefs,
|
||||
}) {
|
||||
const searchingWord = inputedKey[`key${selectedKey}`] || '';
|
||||
const suggestedWordElements = Wordlists.en
|
||||
.filter(word => word.toLowerCase().startsWith(searchingWord.toLowerCase()))
|
||||
.map(word => {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={{
|
||||
minHeight: 60,
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
onPress={() => {
|
||||
setInputedKey(prev => ({...prev, [`key${selectedKey}`]: word}));
|
||||
if (selectedKey === 12) {
|
||||
keyRefs.current[12].blur();
|
||||
return;
|
||||
}
|
||||
|
||||
keyRefs.current[selectedKey + 1].focus();
|
||||
}}
|
||||
key={word}>
|
||||
<ThemeText
|
||||
CustomNumberOfLines={1}
|
||||
styles={{
|
||||
textTransform: 'capitalize',
|
||||
fontSize: SIZES.large,
|
||||
color: COLORS.lightModeText,
|
||||
includeFontPadding: false,
|
||||
const suggestedWordElements = useMemo(() => {
|
||||
return wordlist
|
||||
.filter(word =>
|
||||
word.toLowerCase().startsWith(searchingWord.toLowerCase()),
|
||||
)
|
||||
.map(word => {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={{
|
||||
minHeight: 60,
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
content={word}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
});
|
||||
onPress={() => {
|
||||
setInputedKey(prev => ({...prev, [`key${selectedKey}`]: word}));
|
||||
if (selectedKey === 12) {
|
||||
keyRefs.current[12].blur();
|
||||
return;
|
||||
}
|
||||
|
||||
keyRefs.current[selectedKey + 1].focus();
|
||||
}}
|
||||
key={word}>
|
||||
<ThemeText
|
||||
CustomNumberOfLines={1}
|
||||
styles={{
|
||||
textTransform: 'capitalize',
|
||||
fontSize: SIZES.large,
|
||||
color: COLORS.lightModeText,
|
||||
includeFontPadding: false,
|
||||
}}
|
||||
content={word}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
});
|
||||
}, [selectedKey, inputedKey, setInputedKey, keyRefs]);
|
||||
|
||||
return (
|
||||
<View
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {CashuMint, CashuWallet} from '@cashu/cashu-ts';
|
||||
import {mnemonicToSeed} from '@dreson4/react-native-quick-bip39';
|
||||
import {mnemonicToSeed} from '@scure/bip39';
|
||||
import EventEmitter from 'events';
|
||||
import {sumProofsValue} from './proofs';
|
||||
import {getStoredProofs, setMintCounter, storeProofs} from './db';
|
||||
@@ -13,7 +13,7 @@ export const restoreMintProofs = async mintURL => {
|
||||
const mnemonic = await retrieveData('mnemonic');
|
||||
|
||||
try {
|
||||
const seed = mnemonicToSeed(mnemonic);
|
||||
const seed = await mnemonicToSeed(mnemonic);
|
||||
let progress = 0;
|
||||
|
||||
restoreProofsEventListener.emit(
|
||||
|
||||
@@ -6,8 +6,7 @@ import {
|
||||
MintQuoteState,
|
||||
} from '@cashu/cashu-ts';
|
||||
import {retrieveData} from '../secureStore';
|
||||
import {mnemonicToSeed} from '@dreson4/react-native-quick-bip39';
|
||||
import {parseInput} from '@breeztech/react-native-breez-sdk';
|
||||
import {mnemonicToSeed} from '@scure/bip39';
|
||||
import {getLocalStorageItem, setLocalStorageItem} from '../localStorage';
|
||||
|
||||
import {BLITZ_DEFAULT_PAYMENT_DESCRIPTION} from '../../constants';
|
||||
@@ -42,7 +41,7 @@ export const initEcashWallet = async mintURL => {
|
||||
ks => ks.unit === 'sat',
|
||||
);
|
||||
const keys = (await mint.getKeys()).keysets.find(ks => ks.unit === 'sat');
|
||||
const seed = mnemonicToSeed(mnemonic);
|
||||
const seed = await mnemonicToSeed(mnemonic);
|
||||
const wallet = new CashuWallet(mint, {
|
||||
bip39seed: Uint8Array.from(seed),
|
||||
mintInfo: await mint.getInfo(),
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import {mnemonicToSeed} from '@breeztech/react-native-breez-sdk';
|
||||
export default async function isValidMnemonic(mnemonic) {
|
||||
import * as bip39 from '@scure/bip39';
|
||||
import {wordlist} from '@scure/bip39/wordlists/english';
|
||||
|
||||
export default function isValidMnemonic(mnemonic) {
|
||||
const mnemoincToString = mnemonic.join(' ');
|
||||
try {
|
||||
await mnemonicToSeed(mnemoincToString);
|
||||
|
||||
return new Promise(resolve => {
|
||||
resolve(true);
|
||||
});
|
||||
const isValid = bip39.validateMnemonic(mnemoincToString, wordlist);
|
||||
if (!isValid) throw new Error('Not a valid mnemoinc');
|
||||
return true;
|
||||
} catch (err) {
|
||||
// console.log(err);
|
||||
return new Promise(resolve => {
|
||||
resolve(false);
|
||||
});
|
||||
console.log('validate mnemoinc error', err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import {generateMnemonic} from '@dreson4/react-native-quick-bip39';
|
||||
import {storeData} from './secureStore';
|
||||
import {generateMnemonic} from '@scure/bip39';
|
||||
import {wordlist} from '@scure/bip39/wordlists/english';
|
||||
|
||||
export default function createAccountMnemonic() {
|
||||
export default async function createAccountMnemonic() {
|
||||
try {
|
||||
let generatedMnemonic = generateMnemonic();
|
||||
let generatedMnemonic = generateMnemonic(wordlist);
|
||||
const unuiqueKeys = new Set(generatedMnemonic.split(' '));
|
||||
|
||||
if (unuiqueKeys.size != 12) {
|
||||
if (unuiqueKeys.size !== 12) {
|
||||
let runCount = 0;
|
||||
let didFindValidMnemoinc = false;
|
||||
while (runCount < 50 && !didFindValidMnemoinc) {
|
||||
console.log('RUNNING IN WHILE LOOP');
|
||||
console.log(`Running retry for account mnemoinc count: ${runCount}`);
|
||||
runCount += 1;
|
||||
const newTry = generateMnemonic();
|
||||
const newTry = generateMnemonic(wordlist);
|
||||
const uniqueItems = new Set(newTry.split(' '));
|
||||
if (uniqueItems.size != 12) continue;
|
||||
didFindValidMnemoinc = true;
|
||||
@@ -24,7 +25,7 @@ export default function createAccountMnemonic() {
|
||||
.split(' ')
|
||||
.filter(word => word.length > 2)
|
||||
.join(' ');
|
||||
storeData('mnemonic', generatedMnemonic);
|
||||
await storeData('mnemonic', generatedMnemonic);
|
||||
return filtedMnemoinc;
|
||||
} catch (err) {
|
||||
console.log('generate mnemoinc error:', err);
|
||||
|
||||
@@ -5,12 +5,11 @@ import {
|
||||
NodeConfigVariant,
|
||||
connect,
|
||||
defaultConfig,
|
||||
listFiatCurrencies,
|
||||
mnemonicToSeed,
|
||||
nodeInfo,
|
||||
} from '@breeztech/react-native-breez-sdk';
|
||||
import {btoa, atob, toByteArray} from 'react-native-quick-base64';
|
||||
import {generateMnemonic} from '@dreson4/react-native-quick-bip39';
|
||||
import {generateMnemonic} from '@scure/bip39';
|
||||
import {wordlist} from '@scure/bip39/wordlists/english';
|
||||
import {ThemeText} from '../functions/CustomElements';
|
||||
import {startLiquidSession} from '../functions/breezLiquid';
|
||||
|
||||
@@ -46,7 +45,7 @@ async function connectToBreezNode() {
|
||||
try {
|
||||
// Create the default config
|
||||
// const mnemoinc = await retrieveData('mnemonic');
|
||||
const mnemonic = generateMnemonic();
|
||||
const mnemonic = generateMnemonic(wordlist);
|
||||
|
||||
const seed = await mnemonicToSeed(mnemonic);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function DislaimerPage({navigation: {navigate}}) {
|
||||
return (
|
||||
<GlobalThemeView useStandardWidth={true}>
|
||||
<View style={styles.contentContainer}>
|
||||
<LoginNavbar destination={'Home'} />
|
||||
<LoginNavbar />
|
||||
<ThemeText
|
||||
styles={{
|
||||
fontSize: SIZES.xxLarge,
|
||||
|
||||
@@ -2,8 +2,6 @@ import React, {useEffect} from 'react';
|
||||
import {View, StyleSheet} from 'react-native';
|
||||
import {COLORS, SIZES} from '../../constants';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
|
||||
import {useGlobalContextProvider} from '../../../context-store/context';
|
||||
import {GlobalThemeView, ThemeText} from '../../functions/CustomElements';
|
||||
import CustomButton from '../../functions/CustomElements/button';
|
||||
import {createAccountMnemonic} from '../../functions';
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function GenerateKey() {
|
||||
return (
|
||||
<GlobalThemeView useStandardWidth={true}>
|
||||
<View style={styles.contentContainer}>
|
||||
<LoginNavbar destination={'DisclaimerPage'} />
|
||||
<LoginNavbar />
|
||||
<View style={styles.container}>
|
||||
<ThemeText
|
||||
styles={{...styles.header, marginTop: 30, marginBottom: 30}}
|
||||
|
||||
@@ -2,19 +2,20 @@ import {
|
||||
View,
|
||||
TextInput,
|
||||
StyleSheet,
|
||||
KeyboardAvoidingView,
|
||||
TouchableWithoutFeedback,
|
||||
Keyboard,
|
||||
ScrollView,
|
||||
Platform,
|
||||
} from 'react-native';
|
||||
import {Back_BTN} from '../../../components/login';
|
||||
import {retrieveData, storeData} from '../../../functions';
|
||||
import {CENTER, COLORS, FONT, SIZES} from '../../../constants';
|
||||
import {CENTER, COLORS, FONT, ICONS, SIZES} from '../../../constants';
|
||||
import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
|
||||
import isValidMnemonic from '../../../functions/isValidMnemonic';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {GlobalThemeView, ThemeText} from '../../../functions/CustomElements';
|
||||
import {
|
||||
CustomKeyboardAvoidingView,
|
||||
ThemeText,
|
||||
} from '../../../functions/CustomElements';
|
||||
import SuggestedWordContainer from '../../../components/login/suggestedWords';
|
||||
import CustomButton from '../../../functions/CustomElements/button';
|
||||
import FullLoadingScreen from '../../../functions/CustomElements/loadingScreen';
|
||||
@@ -24,14 +25,17 @@ import {WINDOWWIDTH} from '../../../constants/theme';
|
||||
import {useGlobalThemeContext} from '../../../../context-store/theme';
|
||||
import useHandleBackPressNew from '../../../hooks/useHandleBackPressNew';
|
||||
import getClipboardText from '../../../functions/getClipboardText';
|
||||
import {useNavigation} from '@react-navigation/native';
|
||||
|
||||
const NUMARRAY = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
||||
const NUMARRAY = Array.from({length: 12}, (_, i) => i + 1);
|
||||
const INITIAL_KEY_STATE = NUMARRAY.reduce((acc, num) => {
|
||||
acc[`key${num}`] = '';
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
export default function RestoreWallet({
|
||||
navigation: {navigate, reset},
|
||||
route: {params},
|
||||
}) {
|
||||
export default function RestoreWallet({navigation: {reset}, route: {params}}) {
|
||||
useHandleBackPressNew();
|
||||
const navigate = useNavigation();
|
||||
const {t} = useTranslation();
|
||||
const {theme, darkModeType} = useGlobalThemeContext();
|
||||
const insets = useSafeAreaInsets();
|
||||
@@ -42,20 +46,16 @@ export default function RestoreWallet({
|
||||
const [isValidating, setIsValidating] = useState(false);
|
||||
const [currentFocused, setCurrentFocused] = useState(null);
|
||||
const keyRefs = useRef({});
|
||||
const [inputedKey, setInputedKey] = useState({
|
||||
key1: '',
|
||||
key2: '',
|
||||
key3: '',
|
||||
key4: '',
|
||||
key5: '',
|
||||
key6: '',
|
||||
key7: '',
|
||||
key8: '',
|
||||
key9: '',
|
||||
key10: '',
|
||||
key11: '',
|
||||
key12: '',
|
||||
});
|
||||
const [inputedKey, setInputedKey] = useState(INITIAL_KEY_STATE);
|
||||
|
||||
// Helper functions
|
||||
const navigateToError = useCallback(
|
||||
errorMessage => {
|
||||
navigate.navigate('ErrorScreen', {errorMessage});
|
||||
},
|
||||
[navigate],
|
||||
);
|
||||
|
||||
const handleInputElement = useCallback((text, keyNumber) => {
|
||||
setInputedKey(prev => ({...prev, [`key${keyNumber}`]: text}));
|
||||
}, []);
|
||||
@@ -76,46 +76,166 @@ export default function RestoreWallet({
|
||||
[keyRefs],
|
||||
);
|
||||
|
||||
const handleSeedFromClipboard = useCallback(async () => {
|
||||
try {
|
||||
const response = await getClipboardText();
|
||||
if (!response.didWork) throw new Error(response.reason);
|
||||
|
||||
const data = response.data;
|
||||
const splitSeed = data.split(' ');
|
||||
if (!splitSeed.every(word => word.trim().length > 0))
|
||||
throw new Error('Not every word is of valid length');
|
||||
if (splitSeed.length != 12)
|
||||
throw new Error('Unable to find 12 words from copied recovery phrase.');
|
||||
console.log(Object.entries(inputedKey));
|
||||
|
||||
const newKeys = {};
|
||||
NUMARRAY.forEach((num, index) => {
|
||||
newKeys[`key${num}`] = splitSeed[index];
|
||||
});
|
||||
setInputedKey(newKeys);
|
||||
} catch (err) {
|
||||
console.log('Error getting data from clipbarod', err);
|
||||
navigateToError(err.message);
|
||||
}
|
||||
}, [navigateToError]);
|
||||
|
||||
const didEnterCorrectSeed = useCallback(async () => {
|
||||
try {
|
||||
const keys = await retrieveData('mnemonic');
|
||||
const didEnterAllKeys =
|
||||
Object.keys(inputedKey).filter(value => inputedKey[value]).length ===
|
||||
12;
|
||||
|
||||
if (!didEnterAllKeys)
|
||||
throw new Error(t('createAccount.restoreWallet.home.error1'));
|
||||
const enteredMnemonic = Object.values(inputedKey).map(val =>
|
||||
val.trim().toLowerCase(),
|
||||
);
|
||||
const savedMnemonic = keys.split(' ').filter(item => item);
|
||||
|
||||
if (JSON.stringify(savedMnemonic) === JSON.stringify(enteredMnemonic)) {
|
||||
navigate.navigate('PinSetup', {didRestoreWallet: true});
|
||||
} else throw new Error(t('createAccount.restoreWallet.home.error3'));
|
||||
} catch (err) {
|
||||
console.log('did enter correct seed error', err);
|
||||
navigateToError(err.message);
|
||||
}
|
||||
}, [inputedKey, navigateToError]);
|
||||
|
||||
const keyValidation = useCallback(async () => {
|
||||
try {
|
||||
setIsValidating(true);
|
||||
const enteredKeys =
|
||||
Object.keys(inputedKey).filter(value => inputedKey[value]).length ===
|
||||
12;
|
||||
|
||||
if (!enteredKeys)
|
||||
throw new Error(t('createAccount.restoreWallet.home.error1'));
|
||||
|
||||
const mnemonic = Object.values(inputedKey).map(val =>
|
||||
val.trim().toLowerCase(),
|
||||
);
|
||||
|
||||
const hasAccount = isValidMnemonic(mnemonic);
|
||||
const hasPin = await retrieveData('pin');
|
||||
|
||||
if (!hasAccount)
|
||||
throw new Error(t('createAccount.restoreWallet.home.error2'));
|
||||
else {
|
||||
await storeData('mnemonic', mnemonic.join(' '));
|
||||
if (hasPin) {
|
||||
reset({
|
||||
index: 0,
|
||||
routes: [
|
||||
{
|
||||
name: 'ConnectingToNodeLoadingScreen',
|
||||
params: {
|
||||
isInitialLoad: true,
|
||||
didRestoreWallet: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
} else navigate.navigate('PinSetup', {didRestoreWallet: true});
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('key validation error', err);
|
||||
navigateToError(err.message);
|
||||
} finally {
|
||||
setIsValidating(false);
|
||||
}
|
||||
}, [inputedKey, reset, navigate, navigateToError, t]);
|
||||
|
||||
const seedItemBackgroundColor = useMemo(
|
||||
() => (theme ? COLORS.darkModeBackgroundOffset : COLORS.darkModeText),
|
||||
[theme],
|
||||
);
|
||||
|
||||
const inputKeys = useMemo(() => {
|
||||
let keyRows = [];
|
||||
let keyItem = [];
|
||||
NUMARRAY.forEach(item => {
|
||||
keyItem.push(
|
||||
const rows = [];
|
||||
|
||||
// Process input fields in pairs
|
||||
for (let i = 0; i < NUMARRAY.length; i += 2) {
|
||||
const item1 = NUMARRAY[i];
|
||||
const item2 = NUMARRAY[i + 1];
|
||||
|
||||
rows.push(
|
||||
<View
|
||||
key={item}
|
||||
style={{
|
||||
...styles.seedItem,
|
||||
backgroundColor: theme
|
||||
? COLORS.darkModeBackgroundOffset
|
||||
: COLORS.darkModeText,
|
||||
}}>
|
||||
<ThemeText styles={styles.numberText} content={`${item}.`} />
|
||||
<TextInput
|
||||
keyboardAppearance={theme ? 'dark' : 'light'}
|
||||
ref={ref => (keyRefs.current[item] = ref)} // Store ref for each input
|
||||
value={inputedKey[`key${item}`]}
|
||||
onFocus={() => handleFocus(item)} // Track the currently focused input
|
||||
onSubmitEditing={() => handleSubmit(item)} // Move to next input on submit
|
||||
onChangeText={e => handleInputElement(e, item)}
|
||||
blurOnSubmit={false}
|
||||
cursorColor={COLORS.lightModeText}
|
||||
style={styles.textInputStyle}
|
||||
/>
|
||||
key={`row${item1}`}
|
||||
style={[styles.seedRow, {marginBottom: item2 !== 12 ? 10 : 0}]}>
|
||||
{/* First item in row */}
|
||||
<View
|
||||
style={[
|
||||
styles.seedItem,
|
||||
{backgroundColor: seedItemBackgroundColor},
|
||||
]}>
|
||||
<ThemeText styles={styles.numberText} content={`${item1}.`} />
|
||||
<TextInput
|
||||
keyboardAppearance={theme ? 'dark' : 'light'}
|
||||
ref={ref => (keyRefs.current[item1] = ref)}
|
||||
value={inputedKey[`key${item1}`]}
|
||||
onFocus={() => handleFocus(item1)}
|
||||
onSubmitEditing={() => handleSubmit(item1)}
|
||||
onChangeText={e => handleInputElement(e, item1)}
|
||||
blurOnSubmit={false}
|
||||
cursorColor={COLORS.lightModeText}
|
||||
style={styles.textInputStyle}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* Second item in row */}
|
||||
<View
|
||||
style={[
|
||||
styles.seedItem,
|
||||
{backgroundColor: seedItemBackgroundColor},
|
||||
]}>
|
||||
<ThemeText styles={styles.numberText} content={`${item2}.`} />
|
||||
<TextInput
|
||||
keyboardAppearance={theme ? 'dark' : 'light'}
|
||||
ref={ref => (keyRefs.current[item2] = ref)}
|
||||
value={inputedKey[`key${item2}`]}
|
||||
onFocus={() => handleFocus(item2)}
|
||||
onSubmitEditing={() => handleSubmit(item2)}
|
||||
onChangeText={e => handleInputElement(e, item2)}
|
||||
blurOnSubmit={false}
|
||||
cursorColor={COLORS.lightModeText}
|
||||
style={styles.textInputStyle}
|
||||
/>
|
||||
</View>
|
||||
</View>,
|
||||
);
|
||||
if (item % 2 === 0) {
|
||||
keyRows.push(
|
||||
<View
|
||||
key={`row${item - 1}`}
|
||||
style={[styles.seedRow, {marginBottom: item !== 12 ? 10 : 0}]}>
|
||||
{keyItem}
|
||||
</View>,
|
||||
);
|
||||
keyItem = [];
|
||||
}
|
||||
});
|
||||
return keyRows;
|
||||
}, [handleSubmit, theme, inputedKey, keyRefs]);
|
||||
}
|
||||
|
||||
return rows;
|
||||
}, [
|
||||
handleFocus,
|
||||
handleSubmit,
|
||||
handleInputElement,
|
||||
theme,
|
||||
inputedKey,
|
||||
seedItemBackgroundColor,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const keyboardDidHideListener = Keyboard.addListener(
|
||||
@@ -130,206 +250,105 @@ export default function RestoreWallet({
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (isValidating) {
|
||||
return <FullLoadingScreen text={t('constants.validating')} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableWithoutFeedback
|
||||
onPress={() => {
|
||||
console.log('RUNNING');
|
||||
Keyboard.dismiss();
|
||||
}}
|
||||
style={{flex: 1}}>
|
||||
<KeyboardAvoidingView
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : null}
|
||||
style={{flex: 1}}>
|
||||
<GlobalThemeView styles={{paddingBottom: 0}}>
|
||||
{isValidating ? (
|
||||
<FullLoadingScreen text={t('constants.validating')} />
|
||||
) : (
|
||||
<>
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
width: WINDOWWIDTH,
|
||||
...CENTER,
|
||||
}}>
|
||||
<Back_BTN
|
||||
navigation={navigate}
|
||||
destination={params ? params.goBackName : 'Home'}
|
||||
/>
|
||||
<CustomKeyboardAvoidingView
|
||||
touchableWithoutFeedbackFunction={Keyboard.dismiss}
|
||||
useLocalPadding={false}
|
||||
useTouchableWithoutFeedback={true}>
|
||||
<View style={styles.keyContainer}>
|
||||
<View style={styles.navContainer}>
|
||||
<Back_BTN />
|
||||
</View>
|
||||
<ThemeText
|
||||
styles={styles.headerText}
|
||||
content={
|
||||
params
|
||||
? t('createAccount.verifyKeyPage.header')
|
||||
: t('createAccount.restoreWallet.home.header')
|
||||
}
|
||||
/>
|
||||
|
||||
<ThemeText
|
||||
styles={{...styles.headerText}}
|
||||
content={
|
||||
params
|
||||
? t('createAccount.verifyKeyPage.header')
|
||||
: t('createAccount.restoreWallet.home.header')
|
||||
}
|
||||
/>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={styles.contentContainer}
|
||||
contentContainerStyle={{
|
||||
paddingBottom: 10,
|
||||
paddingTop: 20,
|
||||
}}>
|
||||
{inputKeys}
|
||||
</ScrollView>
|
||||
{params && !currentFocused && (
|
||||
<CustomButton
|
||||
buttonStyles={styles.pasteButton}
|
||||
textContent={t('constants.paste')}
|
||||
actionFunction={handleSeedFromClipboard}
|
||||
/>
|
||||
)}
|
||||
{!currentFocused && (
|
||||
<View
|
||||
style={{
|
||||
...styles.mainBTCContainer,
|
||||
paddingBottom: bottomOffset,
|
||||
}}>
|
||||
<CustomButton
|
||||
buttonStyles={{
|
||||
width: 145,
|
||||
marginRight: 10,
|
||||
}}
|
||||
textStyles={{
|
||||
color: COLORS.lightModeText,
|
||||
}}
|
||||
textContent={params ? t('constants.skip') : 'Paste'}
|
||||
actionFunction={() =>
|
||||
params
|
||||
? navigate('PinSetup', {isInitialLoad: true})
|
||||
: handleSeedFromClipboard()
|
||||
}
|
||||
/>
|
||||
<CustomButton
|
||||
buttonStyles={{
|
||||
width: 145,
|
||||
backgroundColor: COLORS.primary,
|
||||
}}
|
||||
textStyles={{
|
||||
color: COLORS.darkModeText,
|
||||
}}
|
||||
textContent={params ? t('constants.verify') : 'Restore'}
|
||||
actionFunction={params ? didEnterCorrectSeed : keyValidation}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={styles.contentContainer}
|
||||
contentContainerStyle={{paddingBottom: 10}}>
|
||||
{inputKeys}
|
||||
</ScrollView>
|
||||
{params && !currentFocused && (
|
||||
<CustomButton
|
||||
buttonStyles={styles.pasteButton}
|
||||
textContent={t('constants.paste')}
|
||||
actionFunction={handleSeedFromClipboard}
|
||||
/>
|
||||
)}
|
||||
{!currentFocused && (
|
||||
<View
|
||||
style={{
|
||||
...styles.mainBTCContainer,
|
||||
paddingBottom: bottomOffset,
|
||||
}}>
|
||||
<CustomButton
|
||||
buttonStyles={{
|
||||
width: 145,
|
||||
marginRight: 10,
|
||||
}}
|
||||
textStyles={{
|
||||
color: COLORS.lightModeText,
|
||||
}}
|
||||
textContent={params ? t('constants.skip') : 'Paste'}
|
||||
actionFunction={() =>
|
||||
params
|
||||
? navigate('PinSetup', {isInitialLoad: true})
|
||||
: handleSeedFromClipboard()
|
||||
}
|
||||
/>
|
||||
<CustomButton
|
||||
buttonStyles={{
|
||||
width: 145,
|
||||
backgroundColor: COLORS.primary,
|
||||
}}
|
||||
textStyles={{
|
||||
color: COLORS.darkModeText,
|
||||
}}
|
||||
textContent={params ? t('constants.verify') : 'Restore'}
|
||||
actionFunction={
|
||||
params ? didEnterCorrectSeed : keyValidation
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{currentFocused && (
|
||||
<SuggestedWordContainer
|
||||
inputedKey={inputedKey}
|
||||
setInputedKey={setInputedKey}
|
||||
selectedKey={currentFocused}
|
||||
keyRefs={keyRefs}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</GlobalThemeView>
|
||||
</KeyboardAvoidingView>
|
||||
</TouchableWithoutFeedback>
|
||||
{currentFocused && (
|
||||
<SuggestedWordContainer
|
||||
inputedKey={inputedKey}
|
||||
setInputedKey={setInputedKey}
|
||||
selectedKey={currentFocused}
|
||||
keyRefs={keyRefs}
|
||||
/>
|
||||
)}
|
||||
</CustomKeyboardAvoidingView>
|
||||
);
|
||||
|
||||
async function handleSeedFromClipboard() {
|
||||
const response = await getClipboardText();
|
||||
if (!response.didWork) {
|
||||
navigate('ErrorScreen', {errorMessage: response.reason});
|
||||
return;
|
||||
}
|
||||
const data = response.data;
|
||||
const splitSeed = data.split(' ');
|
||||
if (!splitSeed.every(word => word.trim().length > 0)) return;
|
||||
if (splitSeed.length != 12) return;
|
||||
console.log(Object.entries(inputedKey));
|
||||
|
||||
const newKeys = Object.entries(inputedKey).reduce((acc, key) => {
|
||||
const index = Object.entries(acc).length;
|
||||
acc[key[0]] = splitSeed[index];
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
setInputedKey(newKeys);
|
||||
}
|
||||
|
||||
async function didEnterCorrectSeed() {
|
||||
const keys = await retrieveData('mnemonic');
|
||||
const didEnterAllKeys =
|
||||
Object.keys(inputedKey).filter(value => inputedKey[value]).length === 12;
|
||||
|
||||
if (!didEnterAllKeys) {
|
||||
navigate('ErrorScreen', {
|
||||
errorMessage: t('createAccount.restoreWallet.home.error1'),
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
const enteredMnemonic = Object.values(inputedKey).map(val =>
|
||||
val.trim().toLowerCase(),
|
||||
);
|
||||
const savedMnemonic = keys.split(' ').filter(item => item);
|
||||
|
||||
if (JSON.stringify(savedMnemonic) === JSON.stringify(enteredMnemonic)) {
|
||||
navigate('PinSetup', {didRestoreWallet: true});
|
||||
} else {
|
||||
navigate('ErrorScreen', {
|
||||
errorMessage: t('createAccount.restoreWallet.home.error3'),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function keyValidation() {
|
||||
setIsValidating(true);
|
||||
const enteredKeys =
|
||||
Object.keys(inputedKey).filter(value => inputedKey[value]).length === 12;
|
||||
|
||||
if (!enteredKeys) {
|
||||
setIsValidating(false);
|
||||
navigate('ErrorScreen', {
|
||||
errorMessage: t('createAccount.restoreWallet.home.error1'),
|
||||
});
|
||||
return;
|
||||
}
|
||||
const mnemonic = Object.values(inputedKey).map(val =>
|
||||
val.trim().toLowerCase(),
|
||||
);
|
||||
|
||||
const hasAccount = await isValidMnemonic(mnemonic);
|
||||
const hasPin = await retrieveData('pin');
|
||||
|
||||
if (!hasAccount) {
|
||||
setIsValidating(false);
|
||||
navigate('ErrorScreen', {
|
||||
errorMessage: t('createAccount.restoreWallet.home.error2'),
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
storeData('mnemonic', mnemonic.join(' '));
|
||||
if (hasPin) {
|
||||
reset({
|
||||
index: 0,
|
||||
routes: [
|
||||
{
|
||||
name: 'ConnectingToNodeLoadingScreen',
|
||||
params: {
|
||||
isInitialLoad: true,
|
||||
didRestoreWallet: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
} else navigate('PinSetup', {didRestoreWallet: true});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
keyContainer: {
|
||||
flex: 1,
|
||||
width: WINDOWWIDTH,
|
||||
...CENTER,
|
||||
},
|
||||
navContainer: {
|
||||
marginRight: 'auto',
|
||||
},
|
||||
headerText: {
|
||||
width: '95%',
|
||||
fontSize: SIZES.xLarge,
|
||||
textAlign: 'center',
|
||||
marginBottom: 30,
|
||||
...CENTER,
|
||||
marginBottom: 10,
|
||||
},
|
||||
contentContainer: {
|
||||
flex: 1,
|
||||
|
||||
@@ -24,6 +24,7 @@ export function LiquidEventProvider({children}) {
|
||||
const [pendingNavigation, setPendingNavigation] = useState(null);
|
||||
const [liquidEvent, setLiquidEvent] = useState(null);
|
||||
const receivedPayments = useRef([]);
|
||||
const syncRunCounter = useRef(0);
|
||||
// Add debug logging
|
||||
useEffect(() => {
|
||||
console.log('liquidEvent changed:', liquidEvent);
|
||||
@@ -163,6 +164,16 @@ export function LiquidEventProvider({children}) {
|
||||
debouncedStartInterval(
|
||||
e.type === SdkEventVariant.PAYMENT_SUCCEEDED ? 1 : 0,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
`Running in sync else statment for liquiid on sync count:${syncRunCounter.current}`,
|
||||
);
|
||||
if (syncRunCounter.current > 6) {
|
||||
console.log('running debounce sync else statment for liquiid');
|
||||
debouncedStartInterval(0);
|
||||
syncRunCounter.current = 0;
|
||||
}
|
||||
syncRunCounter.current = syncRunCounter.current + 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2690,6 +2690,8 @@ PODS:
|
||||
- Yoga
|
||||
- react-native-context-menu-view (1.16.0):
|
||||
- React
|
||||
- react-native-get-random-values (1.11.0):
|
||||
- React-Core
|
||||
- react-native-image-picker (8.0.0):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
@@ -3282,6 +3284,7 @@ DEPENDENCIES:
|
||||
- React-Mapbuffer (from `../node_modules/react-native/ReactCommon`)
|
||||
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
|
||||
- react-native-context-menu-view (from `../node_modules/react-native-context-menu-view`)
|
||||
- react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
|
||||
- react-native-image-picker (from `../node_modules/react-native-image-picker`)
|
||||
- react-native-pager-view (from `../node_modules/react-native-pager-view`)
|
||||
- react-native-quick-base64 (from `../node_modules/react-native-quick-base64`)
|
||||
@@ -3483,6 +3486,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
|
||||
react-native-context-menu-view:
|
||||
:path: "../node_modules/react-native-context-menu-view"
|
||||
react-native-get-random-values:
|
||||
:path: "../node_modules/react-native-get-random-values"
|
||||
react-native-image-picker:
|
||||
:path: "../node_modules/react-native-image-picker"
|
||||
react-native-pager-view:
|
||||
@@ -3668,6 +3673,7 @@ SPEC CHECKSUMS:
|
||||
React-Mapbuffer: 9f1c73f53cb27bba0d913545c0ae14c6f0e6e865
|
||||
React-microtasksnativemodule: e8d0d98c5928b3993bc1f558acde32b70fd94cf4
|
||||
react-native-context-menu-view: 3bb7e1aa97c897e26a027d23895a60066f7e4e17
|
||||
react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba
|
||||
react-native-image-picker: 07dcbae358126947798da44f3ceab1c73f066527
|
||||
react-native-pager-view: b466d0c2a37d506d20a5041b8a5eba79fa175420
|
||||
react-native-quick-base64: d63ae7b77d91c24cb72b46dc66b10c1f3b45ae6e
|
||||
|
||||
+3
-1
@@ -19,7 +19,7 @@
|
||||
"@breeztech/react-native-breez-sdk": "^0.6.6",
|
||||
"@breeztech/react-native-breez-sdk-liquid": "0.7.1",
|
||||
"@cashu/cashu-ts": "^2.4.1",
|
||||
"@dreson4/react-native-quick-bip39": "^0.0.6",
|
||||
"@craftzdog/react-native-buffer": "^6.0.5",
|
||||
"@getalby/sdk": "^3.7.0",
|
||||
"@miblanchard/react-native-slider": "^2.6.0",
|
||||
"@noble/secp256k1": "^2.2.3",
|
||||
@@ -33,6 +33,7 @@
|
||||
"@react-navigation/drawer": "^6.7.2",
|
||||
"@react-navigation/native": "^6.1.18",
|
||||
"@react-navigation/native-stack": "^6.11.0",
|
||||
"@scure/bip39": "^1.5.4",
|
||||
"bip21": "^3.0.0",
|
||||
"bolt11": "^1.4.1",
|
||||
"boltz-swap-web-context": "https://github.com/BlakeKaufman/boltz-swap-web-context.git",
|
||||
@@ -65,6 +66,7 @@
|
||||
"react-native-device-info": "^14.0.1",
|
||||
"react-native-email-link": "^1.16.1",
|
||||
"react-native-gesture-handler": "^2.19.0",
|
||||
"react-native-get-random-values": "^1.11.0",
|
||||
"react-native-image-picker": "^8.0.0",
|
||||
"react-native-pager-view": "^6.4.1",
|
||||
"react-native-qrcode-svg": "^6.3.2",
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// Must be the first import
|
||||
import 'react-native-get-random-values';
|
||||
|
||||
import 'react-native-gesture-handler';
|
||||
|
||||
// Buffer polyfill
|
||||
import {Buffer} from '@craftzdog/react-native-buffer';
|
||||
global.Buffer = Buffer;
|
||||
|
||||
// Text encoder/decoder polyfill (if needed)
|
||||
import 'text-encoding-polyfill';
|
||||
|
||||
// Process polyfill
|
||||
global.process = global.process || {};
|
||||
global.process.env = global.process.env || {};
|
||||
global.process.browser = true;
|
||||
@@ -1821,7 +1821,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@craftzdog/react-native-buffer@npm:^6.0.4, @craftzdog/react-native-buffer@npm:^6.0.5":
|
||||
"@craftzdog/react-native-buffer@npm:^6.0.5":
|
||||
version: 6.0.5
|
||||
resolution: "@craftzdog/react-native-buffer@npm:6.0.5"
|
||||
dependencies:
|
||||
@@ -1831,17 +1831,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@dreson4/react-native-quick-bip39@npm:^0.0.6":
|
||||
version: 0.0.6
|
||||
resolution: "@dreson4/react-native-quick-bip39@npm:0.0.6"
|
||||
dependencies:
|
||||
"@craftzdog/react-native-buffer": ^6.0.5
|
||||
react-native-quick-crypto: ^0.5.0
|
||||
unorm: ^1.6.0
|
||||
checksum: 5cb15b73befbd26f6fb8eefbaea48b58101cfe868e5dfdffe070880db2303d0bfcc0ecfb900abaa174ebd220569f3ba05859bba630f4e3ea9f78126b2bc57369
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@egjs/hammerjs@npm:^2.0.17":
|
||||
version: 2.0.17
|
||||
resolution: "@egjs/hammerjs@npm:2.0.17"
|
||||
@@ -3317,6 +3306,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@noble/hashes@npm:~1.7.1":
|
||||
version: 1.7.1
|
||||
resolution: "@noble/hashes@npm:1.7.1"
|
||||
checksum: 4f1b56428a10323feef17e4f437c9093556cb18db06f94d254043fadb69c3da8475f96eb3f8322d41e8670117d7486475a8875e68265c2839f60fd03edd6a616
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@noble/secp256k1@npm:^1.7.1":
|
||||
version: 1.7.1
|
||||
resolution: "@noble/secp256k1@npm:1.7.1"
|
||||
@@ -4240,6 +4236,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@scure/base@npm:~1.2.4":
|
||||
version: 1.2.4
|
||||
resolution: "@scure/base@npm:1.2.4"
|
||||
checksum: db554eb550a1bd17684af9282e1ad751050a13d4add0e83ad61cc496680d7d1c1c1120ca780e72935a293bb59721c20a006a53a5eec6f6b5bdcd702cf27c8cae
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@scure/bip32@npm:1.3.1":
|
||||
version: 1.3.1
|
||||
resolution: "@scure/bip32@npm:1.3.1"
|
||||
@@ -4282,6 +4285,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@scure/bip39@npm:^1.5.4":
|
||||
version: 1.5.4
|
||||
resolution: "@scure/bip39@npm:1.5.4"
|
||||
dependencies:
|
||||
"@noble/hashes": ~1.7.1
|
||||
"@scure/base": ~1.2.4
|
||||
checksum: 744f302559ad05ee6ea4928572ac8f0b5443e8068fd53234c9c2e158814e910a043c54f0688d05546decadd2ff66e0d0c76355d10e103a28cb8f44efe140857a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@segment/loosely-validate-event@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "@segment/loosely-validate-event@npm:2.0.0"
|
||||
@@ -4482,13 +4495,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:^17.0.31":
|
||||
version: 17.0.45
|
||||
resolution: "@types/node@npm:17.0.45"
|
||||
checksum: aa04366b9103b7d6cfd6b2ef64182e0eaa7d4462c3f817618486ea0422984c51fc69fd0d436eae6c9e696ddfdbec9ccaa27a917f7c2e8c75c5d57827fe3d95e8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:^18.0.0":
|
||||
version: 18.19.50
|
||||
resolution: "@types/node@npm:18.19.50"
|
||||
@@ -4828,7 +4834,7 @@ __metadata:
|
||||
"@breeztech/react-native-breez-sdk": ^0.6.6
|
||||
"@breeztech/react-native-breez-sdk-liquid": 0.7.1
|
||||
"@cashu/cashu-ts": ^2.4.1
|
||||
"@dreson4/react-native-quick-bip39": ^0.0.6
|
||||
"@craftzdog/react-native-buffer": ^6.0.5
|
||||
"@getalby/sdk": ^3.7.0
|
||||
"@miblanchard/react-native-slider": ^2.6.0
|
||||
"@noble/secp256k1": ^2.2.3
|
||||
@@ -4846,6 +4852,7 @@ __metadata:
|
||||
"@react-navigation/drawer": ^6.7.2
|
||||
"@react-navigation/native": ^6.1.18
|
||||
"@react-navigation/native-stack": ^6.11.0
|
||||
"@scure/bip39": ^1.5.4
|
||||
"@types/react": ^18.2.6
|
||||
"@types/react-test-renderer": ^18.0.0
|
||||
babel-jest: ^29.6.3
|
||||
@@ -4887,6 +4894,7 @@ __metadata:
|
||||
react-native-dotenv: ^3.4.11
|
||||
react-native-email-link: ^1.16.1
|
||||
react-native-gesture-handler: ^2.19.0
|
||||
react-native-get-random-values: ^1.11.0
|
||||
react-native-image-picker: ^8.0.0
|
||||
react-native-pager-view: ^6.4.1
|
||||
react-native-qrcode-svg: ^6.3.2
|
||||
@@ -8080,6 +8088,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-base64-decode@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "fast-base64-decode@npm:1.0.0"
|
||||
checksum: 4c59eb1775a7f132333f296c5082476fdcc8f58d023c42ed6d378d2e2da4c328c7a71562f271181a725dd17cdaa8f2805346cc330cdbad3b8e4b9751508bd0a3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3":
|
||||
version: 3.1.3
|
||||
resolution: "fast-deep-equal@npm:3.1.3"
|
||||
@@ -12713,6 +12728,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-native-get-random-values@npm:^1.11.0":
|
||||
version: 1.11.0
|
||||
resolution: "react-native-get-random-values@npm:1.11.0"
|
||||
dependencies:
|
||||
fast-base64-decode: ^1.0.0
|
||||
peerDependencies:
|
||||
react-native: ">=0.56"
|
||||
checksum: 07729f70a007f7a3b8f98ebf687c1298ba288b87dd71d8ba385be6b5a377718b27b97547bbe1db6b225b83ee109dfce0b01721e6ed535d53892f3ac81e6bf975
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-native-image-picker@npm:^8.0.0":
|
||||
version: 8.0.0
|
||||
resolution: "react-native-image-picker@npm:8.0.0"
|
||||
@@ -12748,7 +12774,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-native-quick-base64@npm:^2.0.2, react-native-quick-base64@npm:^2.0.5, react-native-quick-base64@npm:^2.0.8":
|
||||
"react-native-quick-base64@npm:^2.0.5, react-native-quick-base64@npm:^2.0.8":
|
||||
version: 2.1.2
|
||||
resolution: "react-native-quick-base64@npm:2.1.2"
|
||||
dependencies:
|
||||
@@ -12760,24 +12786,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-native-quick-crypto@npm:^0.5.0":
|
||||
version: 0.5.0
|
||||
resolution: "react-native-quick-crypto@npm:0.5.0"
|
||||
dependencies:
|
||||
"@craftzdog/react-native-buffer": ^6.0.4
|
||||
"@types/node": ^17.0.31
|
||||
crypto-browserify: ^3.12.0
|
||||
events: ^3.3.0
|
||||
react-native-quick-base64: ^2.0.2
|
||||
stream-browserify: ^3.0.0
|
||||
string_decoder: ^1.3.0
|
||||
peerDependencies:
|
||||
react: "*"
|
||||
react-native: "*"
|
||||
checksum: b9ddb2f83b0190d2831dd912dd425a5a873a89744fe02248ac7125c5afee1945a67df61c343295ab22267a4ec1f4a8e9d380a7ad5deee415d22d7437d4c554e7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-native-quick-crypto@npm:^0.7.4":
|
||||
version: 0.7.5
|
||||
resolution: "react-native-quick-crypto@npm:0.7.5"
|
||||
@@ -14797,13 +14805,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unorm@npm:^1.6.0":
|
||||
version: 1.6.0
|
||||
resolution: "unorm@npm:1.6.0"
|
||||
checksum: 9a86546256a45f855b6cfe719086785d6aada94f63778cecdecece8d814ac26af76cb6da70130da0a08b8803bbf0986e56c7ec4249038198f3de02607fffd811
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unpipe@npm:~1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "unpipe@npm:1.0.0"
|
||||
|
||||
Reference in New Issue
Block a user