diff --git a/index.js b/index.js index a850d03..f60fd57 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ * @format */ +import 'react-native-get-random-values' import {AppRegistry} from 'react-native'; import App from './App'; import {name as appName} from './app.json'; diff --git a/ios/Podfile.lock b/ios/Podfile.lock index d277632..6501d80 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1244,7 +1244,9 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-status-keycard (2.6.0): + - react-native-get-random-values (1.11.0): + - React-Core + - react-native-status-keycard (2.6.1): - Keycard - React - React-nativeconfig (0.75.3) @@ -1509,6 +1511,8 @@ PODS: - React-utils (= 0.75.3) - RNCAsyncStorage (2.0.0): - React-Core + - RNSVG (15.7.1): + - React-Core - RNVectorIcons (10.2.0): - DoubleConversion - glog @@ -1580,6 +1584,7 @@ DEPENDENCIES: - React-logger (from `../node_modules/react-native/ReactCommon/logger`) - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) - React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) + - react-native-get-random-values (from `../node_modules/react-native-get-random-values`) - react-native-status-keycard (from `../node_modules/react-native-status-keycard`) - React-nativeconfig (from `../node_modules/react-native/ReactCommon`) - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) @@ -1608,6 +1613,7 @@ DEPENDENCIES: - ReactCodegen (from `build/generated/ios`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" + - RNSVG (from `../node_modules/react-native-svg`) - RNVectorIcons (from `../node_modules/react-native-vector-icons`) - secp256k1 (from `https://github.com/status-im/secp256k1.swift.git`) - SSZipArchive (= 2.4.3) @@ -1696,6 +1702,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon" React-microtasksnativemodule: :path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" + react-native-get-random-values: + :path: "../node_modules/react-native-get-random-values" react-native-status-keycard: :path: "../node_modules/react-native-status-keycard" React-nativeconfig: @@ -1752,6 +1760,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon" RNCAsyncStorage: :path: "../node_modules/@react-native-async-storage/async-storage" + RNSVG: + :path: "../node_modules/react-native-svg" RNVectorIcons: :path: "../node_modules/react-native-vector-icons" secp256k1: @@ -1810,7 +1820,8 @@ SPEC CHECKSUMS: React-logger: 4072f39df335ca443932e0ccece41fbeb5ca8404 React-Mapbuffer: 714f2fae68edcabfc332b754e9fbaa8cfc68fdd4 React-microtasksnativemodule: 4943ad8f99be8ccf5a63329fa7d269816609df9e - react-native-status-keycard: deb3fa9fdb1438b0ee6111d22ff85e4b5800fcb4 + react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06 + react-native-status-keycard: 9803b8545df3bde6880a2419ffbf3df404b3201f React-nativeconfig: 4a9543185905fe41014c06776bf126083795aed9 React-NativeModulesApple: 0506da59fc40d2e1e6e12a233db5e81c46face27 React-perflogger: 3bbb82f18e9ac29a1a6931568e99d6305ef4403b @@ -1838,6 +1849,7 @@ SPEC CHECKSUMS: ReactCodegen: ff95a93d5ab5d9b2551571886271478eaa168565 ReactCommon: 289214026502e6a93484f4a46bcc0efa4f3f2864 RNCAsyncStorage: d35c79ffba52c1013013e16b1fc295aec2feabb6 + RNSVG: 4590aa95758149fa27c5c83e54a6a466349a1688 RNVectorIcons: 6382277afab3c54658e9d555ee0faa7a37827136 secp256k1: f61d67e6fdcb85fd727acf1bf35ace6036db540c SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d diff --git a/package-lock.json b/package-lock.json index d621f89..c189423 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,13 +10,17 @@ "dependencies": { "@noble/hashes": "^1.5.0", "@react-native-async-storage/async-storage": "^2.0.0", + "@scure/bip39": "^1.4.0", "bech32": "^2.0.0", "react": "18.3.1", "react-native": "0.75.3", + "react-native-get-random-values": "^1.11.0", "react-native-modal": "^13.0.1", "react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.6.1", + "react-native-svg": "^15.7.1", "react-native-vector-icons": "^10.1.0", - "react-native-vision-camera": "^4.5.3" + "react-native-vision-camera": "^4.5.3", + "react-qr-code": "^2.0.15" }, "devDependencies": { "@babel/core": "^7.20.0", @@ -4658,6 +4662,28 @@ } } }, + "node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.4.0.tgz", + "integrity": "sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.5.0", + "@scure/base": "~1.1.8" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -5727,6 +5753,12 @@ "readable-stream": "^3.4.0" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -6423,6 +6455,47 @@ "node": ">= 8" } }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -6666,6 +6739,61 @@ "node": ">=6.0.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -6706,6 +6834,18 @@ "node": ">= 0.8" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -7770,6 +7910,12 @@ "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", "license": "Apache-2.0" }, + "node_modules/fast-base64-decode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz", + "integrity": "sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -11538,6 +11684,12 @@ "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", "license": "Apache-2.0" }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0" + }, "node_modules/memoize-one": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", @@ -12253,6 +12405,18 @@ "node": ">=8" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/nullthrows": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", @@ -12867,6 +13031,12 @@ ], "license": "MIT" }, + "node_modules/qr.js": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", + "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==", + "license": "MIT" + }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -13004,6 +13174,18 @@ "prop-types": "^15.7.2" } }, + "node_modules/react-native-get-random-values": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/react-native-get-random-values/-/react-native-get-random-values-1.11.0.tgz", + "integrity": "sha512-4BTbDbRmS7iPdhYLRcz3PGFIpFJBwNZg9g42iwa2P6FOv9vZj/xJc678RZXnLNZzd0qd7Q3CCF6Yd+CU2eoXKQ==", + "license": "MIT", + "dependencies": { + "fast-base64-decode": "^1.0.0" + }, + "peerDependencies": { + "react-native": ">=0.56" + } + }, "node_modules/react-native-modal": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-13.0.1.tgz", @@ -13023,6 +13205,21 @@ "resolved": "git+ssh://git@github.com/status-im/react-native-status-keycard.git#2f9d46b2c720a8f2d76b510259bf8f538463ffa3", "license": "MPL 2.0" }, + "node_modules/react-native-svg": { + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.7.1.tgz", + "integrity": "sha512-Xc11L4t6/DtmUwrQqHR7S45Qy3cIWpcfGlmEatVeZ9c1N8eAK79heJmGRgCOVrXESrrLEHfP/AYGf0BGyrvV6A==", + "license": "MIT", + "dependencies": { + "css-select": "^5.1.0", + "css-tree": "^1.1.3", + "warn-once": "0.1.1" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-vector-icons": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-10.2.0.tgz", @@ -13275,6 +13472,19 @@ "async-limiter": "~1.0.0" } }, + "node_modules/react-qr-code": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.15.tgz", + "integrity": "sha512-MkZcjEXqVKqXEIMVE0mbcGgDpkfSdd8zhuzXEl9QzYeNcw8Hq2oVIzDLWuZN2PQBwM5PWjc2S31K8Q1UbcFMfw==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1", + "qr.js": "0.0.0" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", @@ -14778,6 +14988,12 @@ "makeerror": "1.0.12" } }, + "node_modules/warn-once": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", + "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==", + "license": "MIT" + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", diff --git a/package.json b/package.json index bd77105..3ea480d 100644 --- a/package.json +++ b/package.json @@ -13,13 +13,17 @@ "dependencies": { "@noble/hashes": "^1.5.0", "@react-native-async-storage/async-storage": "^2.0.0", + "@scure/bip39": "^1.4.0", "bech32": "^2.0.0", "react": "18.3.1", "react-native": "0.75.3", + "react-native-get-random-values": "^1.11.0", "react-native-modal": "^13.0.1", "react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.6.1", + "react-native-svg": "^15.7.1", "react-native-vector-icons": "^10.1.0", - "react-native-vision-camera": "^4.5.3" + "react-native-vision-camera": "^4.5.3", + "react-qr-code": "^2.0.15" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/src/components/steps/MnemonicScreen.tsx b/src/components/steps/MnemonicScreen.tsx index bd3d09b..e947522 100644 --- a/src/components/steps/MnemonicScreen.tsx +++ b/src/components/steps/MnemonicScreen.tsx @@ -1,10 +1,14 @@ import {FC, useState } from "react"; import { StyleSheet, Text, TextInput, View } from "react-native"; +import * as bip39 from '@scure/bip39'; +import { wordlist } from '@scure/bip39/wordlists/english'; import Button from "../Button"; import { MNEMONIC } from "../../MnemonicList"; import Dialpad from "../Dialpad"; enum LoadMnemonicSteps { + Home, + CreateMnemonic, InsertMnemonic, InsertPin } @@ -20,7 +24,7 @@ const MnemonicScreen: FC = props => { const {pinRequired, pinRetryCounter, onPressFunc, onCancelFunc} = props; const [mnemonic, setMnemonic] = useState(''); const [errMessage, setErrMessage] = useState(''); - const [step, setStep] = useState(LoadMnemonicSteps.InsertMnemonic); + const [step, setStep] = useState(LoadMnemonicSteps.Home); const updateMnemonic = (str: string) => { const mn = str.split(' ').filter((el: string) => el != "").map((word: string) => word.trim().toLowerCase()); @@ -36,12 +40,15 @@ const MnemonicScreen: FC = props => { } setErrMessage(""); + submitMnemonic(mn.join(' ')); + } + const submitMnemonic = (mn: string) => { if(pinRequired) { setStep(LoadMnemonicSteps.InsertPin); } else { - onPressFunc(mn.join(' ')); - } + onPressFunc(mn); + } } const submitPin = (p: string) => { @@ -49,8 +56,21 @@ const MnemonicScreen: FC = props => { return true; } + const generateMnemonic = () => { + setMnemonic(bip39.generateMnemonic(wordlist)); + setStep(LoadMnemonicSteps.CreateMnemonic); + } + return ( + { step == LoadMnemonicSteps.Home && + + Load card + + + + + } { step == LoadMnemonicSteps.InsertMnemonic && Load mnemonic @@ -58,12 +78,19 @@ const MnemonicScreen: FC = props => { setMnemonic(val)} value={mnemonic} style={styles.mnemonic} placeholder="Type your passphrase"/> - + {errMessage} } + { step == LoadMnemonicSteps.CreateMnemonic && + + {mnemonic} + + + + } { step == LoadMnemonicSteps.InsertPin && setStep(LoadMnemonicSteps.InsertMnemonic)} onNextFunc={submitPin}>} )};