diff --git a/.buckconfig b/.buckconfig new file mode 100644 index 0000000000000000000000000000000000000000..934256cb29d4a3616c740861c6af35ff6a165917 --- /dev/null +++ b/.buckconfig @@ -0,0 +1,6 @@ + +[android] + target = Google Inc.:Google APIs:23 + +[maven_repositories] + central = https://repo1.maven.org/maven2 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..7c286132fe9a986352e329ab1a1baa8e3bf4dd8c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +# Windows files +[*.bat] +end_of_line = crlf diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000000000000000000000000000000000000..4e90c8a35b9f382e6cd73f4f297de4c9469d4929 --- /dev/null +++ b/.env.sample @@ -0,0 +1,2 @@ +MEDIATOR_URL=https://gaiax.vereign.com/mediator?c_i=eyJAdHlwZSI6ICJkaWQ6c292OkJ6Q2JzTlloTXJqSGlxWkRUVUFTSGc7c3BlYy9jb25uZWN0aW9ucy8xLjAvaW52aXRhdGlvbiIsICJAaWQiOiAiMWY0ZjVhN2QtOWNmMi00NjZhLWJjNmItNTczOTMwMDVmNDE3IiwgInJlY2lwaWVudEtleXMiOiBbIkRBc2prQTdZeXZCM3hrc1NtYXRMVDVyM2hqUU4zQnN4R1VKWHhiU3l6RWtIIl0sICJzZXJ2aWNlRW5kcG9pbnQiOiAiaHR0cHM6Ly9nYWlheC52ZXJlaWduLmNvbS9tZWRpYXRvciIsICJsYWJlbCI6ICJNZWRpYXRvciJ9 +NOTIFICATION_URL=https://gaiax.vereign.com/ocm/notification diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000000000000000000000000000000000..1db90ae99061e954c190c3fbe087cd5808e84a1b --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,17 @@ +module.exports = { + root: true, + extends: '@react-native-community', + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], + overrides: [ + { + files: ['*.ts', '*.tsx'], + rules: { + '@typescript-eslint/no-shadow': ['off'], + '@typescript-eslint/no-unused-vars': ['warn'], + 'no-shadow': 'off', + 'no-undef': 'off', + }, + }, + ], +}; diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..45a3dcb2a203165a9a5bf50c6858fd813f978313 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Windows files should use crlf line endings +# https://help.github.com/articles/dealing-with-line-endings/ +*.bat text eol=crlf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..564b10bc36423cad01992d53b2e1d853356a761e --- /dev/null +++ b/.gitignore @@ -0,0 +1,83 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +ios/.xcode.env.local + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof +.cxx/ + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# BUCK +buck-out/ +\.buckd/ +*.keystore +!debug.keystore + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +**/fastlane/report.xml +**/fastlane/Preview.html +**/fastlane/screenshots +**/fastlane/test_output + +# Bundle artifact +*.jsbundle + +# Ruby / CocoaPods +/ios/Pods + + +# Enabling this option can dramatically improve ESLint's running time +# by ensuring that only changed files are linted. +# https://eslint.org/docs/user-guide/command-line-interface#caching +.eslintcache + +# Android bundle files (generated when bundling app) +android/app/src/main/assets/index.android.bundle +android/app/src/main/res/drawable-hdpi/ +android/app/src/main/res/drawable-mdpi/ +android/app/src/main/res/drawable-xhdpi/ +android/app/src/main/res/drawable-xxhdpi/ +android/app/src/main/res/drawable-xxxhdpi/ +android/app/src/main/res/raw/ + +# env urls +.env +.env.development +.env.production diff --git a/.gitlab/issue_templates/.gitkeep b/.gitlab/issue_templates/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.gitlab/issue_templates/Default.md b/.gitlab/issue_templates/Default.md new file mode 100644 index 0000000000000000000000000000000000000000..a344a524c5c2f5207f4e74ce9412d615b4f49f67 --- /dev/null +++ b/.gitlab/issue_templates/Default.md @@ -0,0 +1,23 @@ +## Description + +Add small description + +## Libraries + +- libraries used + +## Expected Output + +- Expected Output + +## Dependencies + +- dependencies + +## Blocker + +- blocker + +## Merge Request Url + +- merge request url diff --git a/.gitlab/merge_request_templates/merge_request_template.md b/.gitlab/merge_request_templates/merge_request_template.md new file mode 100644 index 0000000000000000000000000000000000000000..28e626791a8d0f333e3d489d133017c77464deda --- /dev/null +++ b/.gitlab/merge_request_templates/merge_request_template.md @@ -0,0 +1,11 @@ +## Scope + +## Work Done + +## Steps to Test + +## Linting + +- [x] Committed using husky + +## Screenshots diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000000000000000000000000000000000..591e53116f03a38d3d780485ef5f996a223a4a0e --- /dev/null +++ b/.prettierignore @@ -0,0 +1,9 @@ +package-lock.json +app.json +ios/ +android/ +node_modules/ +# Ignore all png files: +*.png +*.snap +*.ttf diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000000000000000000000000000000000000..2fcfd653d1102f745ee8503ac57ce755e1ac415c --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + arrowParens: 'avoid', + bracketSameLine: false, + singleQuote: true, + trailingComma: 'all', + bracketSpacing: true, +}; diff --git a/.watchmanconfig b/.watchmanconfig new file mode 100644 index 0000000000000000000000000000000000000000..9e26dfeeb6e641a33dae4961196235bdb965b21b --- /dev/null +++ b/.watchmanconfig @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/App.tsx b/App.tsx new file mode 100644 index 0000000000000000000000000000000000000000..77461221e35c9d32b24eaafa3a87a533ab83d2df --- /dev/null +++ b/App.tsx @@ -0,0 +1,53 @@ +import React, { useState } from 'react'; +import { NavigationContainer } from '@react-navigation/native'; +import { Agent } from '@aries-framework/core'; +import AntDesignProvider from '@ant-design/react-native/lib/provider'; +import AgentProvider from '@aries-framework/react-hooks'; +import Toast from 'react-native-toast-message'; +import { SafeAreaProvider } from 'react-native-safe-area-context'; +import { Platform } from 'react-native'; +import { ColorPallet, customTheme } from './src/theme/theme'; +import RootStack from './src/navigators/RootStack'; +import { initStoredLanguage } from './src/localization'; +import toastConfig from './src/components/toast/ToastConfig'; + +const navigationTheme = { + dark: false, + colors: { + primary: ColorPallet.brand.primary, + background: ColorPallet.grayscale.white, + card: ColorPallet.brand.primary, + text: ColorPallet.grayscale.white, + border: ColorPallet.grayscale.white, + notification: ColorPallet.grayscale.white, + }, +}; + +const App = () => { + const [agent, setAgent] = useState<Agent | undefined>(undefined); + + initStoredLanguage(); + + const setupAgent = (agent: Agent) => { + setAgent(agent); + }; + + return ( + <SafeAreaProvider> + <AntDesignProvider theme={customTheme}> + {/* @ts-ignore @aries-framework/react-hooks missed children in the props */} + <AgentProvider agent={agent}> + <NavigationContainer theme={navigationTheme}> + <RootStack setAgent={setupAgent} /> + <Toast + topOffset={Platform.OS === 'android' ? 5 : 50} + config={toastConfig} + /> + </NavigationContainer> + </AgentProvider> + </AntDesignProvider> + </SafeAreaProvider> + ); +}; + +export default App; diff --git a/GDPR.md b/GDPR.md new file mode 100644 index 0000000000000000000000000000000000000000..3a81da9568c34b14830e2462e496cce24991a9d7 --- /dev/null +++ b/GDPR.md @@ -0,0 +1,31 @@ +# GDPR Compliance Document + +The objective of this document is to detail, the data being stored and processed by the Personal Credential Manager. + +## What information is stored + +### Source User Information + +The Open Id connect claims that MAY contain all sorts of personal data (like email, name, age and others), are received from any external source. + +### Technical User Information (Public) + +Connection Information - The list of connections with different OCM agents, connection history with respect to the available connections. +Verifiable Credential Specific Information - The various VC's held by the user. +Proof Presentation Specific Information - Information with respect to the proof presentations shared by the user. + +### DID Information + +DID of holder is stored on the PCM agent itself. + +## How is the information stored + +Source User Information and Technical User Information are encrypted using the Private Key of the Individual PCM's SSI Agent and stored internally (on the agent) on SQLite. + +## Who can access the information + +The Source User Information and Technical User Information both are accessible only locally on the PCM device after user authentication. + +## How long will the information stay + +Source User Information and Technical User Information is wiped out by the user. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..fc93f159a66cb1e0c30f1588f5c8896ca028c798 --- /dev/null +++ b/LICENSE @@ -0,0 +1,1279 @@ +GAIA-X "Personal Credential Manager" + +enables a natural person to act as a principal of an organization within the +SSI-based Gaia-X ecosystem in a privacy-preserving, trustful and secure way. +This comprises the following main functionalities: + +* Establishment of trustful connections to other parties +* Reception and management of verifiable credentials from other parties + (e.g.,a principal credential from a Gaia-X articipant) +* Presenting Verifiable Presentations to other parties in a proved manner +* Secure storage and management of respective secrets + +Copyright 2022 Vereign AG + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +This Personal Credential Manager incorporates + +"Ant Design Mobile RN" + +, a configurable Mobile UI specification and React-based implementation, which +is covered by the following copyright and permission notice: + +Copyright (c) 2016-present Alipay.com, https://www.alipay.com/ + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +This Personal Credential Manager also incorporates + +"Aries Framework JavaScript" + +, a framework written in TypeScript for building SSI Agents and DIDComm services that +aims to be compliant and interoperable with the standards defined in the Aries RFCs, +which is covered by the following copyright and permission notice: + +Copyright 2020-present Hyperledger Contributors. +Copyright 2021 Queen’s Printer for Ontario. Mostafa Youssef (https://github.com/MosCD3), +Amit Padmani (https://github.com/nbAmit), Prasad Katkar (https://github.com/NB-PrasadKatkar), +Mike Richardson (https://github.com/NB-MikeRichardson) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +This Personal Credential Manager also incorporates + +"React Native Async Storage" + +, an asynchronous, persistent, key-value storage system for React Native, and + +"React Native Clipboard" + +, a React Native Clipboard API for both iOS and Android, and + +"React Native SegmentedControl library" + +, to render a UISegmentedControl iOS, all of which is covered by the following +copyright and permission notice: + +Copyright (c) 2015-present, Facebook, Inc. + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"React Native CLI" + +, react Native command line tools, which is covered by the following copyright and +permission notice: + +Copyright (c) 2018 react-native-community + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"React Native Slider" + +, react Native component exposing Slider from iOS and SeekBar from +Android, which is covered by the following copyright and permission notice: + +Copyright (c) 2019 react-native-community + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-navigation/bottom-tabs" + +, bottom tab navigator for React Navigation following iOS design guidelines, which is +covered by the following copyright and permission notice: + +Copyright (c) 2021 react-native-community + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-navigation" + +, routing and navigation for React Native apps, which is covered by the +following copyright and permission notice: + +Copyright (c) 2021 react-native-community + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"React Native Testing Library" + +, React Native testing utilities, which is covered by the following copyright and +permission notice: + +Copyright (c) 2018 Callstack and Rally Health + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"axios" + +, promise based HTTP client for the browser and node.js, which is covered by the following +copyright and permission notice: + +Copyright (c) 2014-present Matt Zabriskie & Collaborators + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"fbjs" + +, a collection of utility libraries used by other Facebook JS projects, which is +covered by the following copyright and permission notice: + +Copyright (c) 2013-present, Facebook, Inc. + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"i18next" + +, internationalization framework for browser or any other javascript +environment (eg. Node.js, Deno), which is covered by the following copyright +and permission notice: + +Copyright (c) 2022 i18next + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"React Native Indy SDK" + +, React Native wrapper around Indy SDK Java and Objective-C wrappers, +which contains the following copyright and permission notice: + +Copyright 2019 ABSA Group Limited + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +This Personal Credential Manager also incorporates + +"intl-pluralrules" + +, a spec-compliant implementation & polyfill for Intl.PluralRules, including +the selectRange(start, end) method introduced in Intl.NumberFormat v3, which +contains the following copyright and permission notice: + +Copyright 2015-2018 by Eemeli Aro <eemeli@gmail.com> + +(ISC License) +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +This Personal Credential Manager also incorporates + +"md5" + +, a JavaScript function for hashing messages with MD5, which contains the +following copyright and permission notice: + +Copyright © 2011-2012, Paul Vorbach. +Copyright © 2009, Jeff Mott. + +All rights reserved. + +(BDS-3 Clause License) +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name Crypto-JS nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +This Personal Credential Manager also incorporates + +"query-string" + +, parse and stringify URL query strings, which contains the +following copyright and permission notice: + +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (http://sindresorhus.com) + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react" + +, a JavaScript library for creating user interfaces, which contains the +following copyright and permission notice: + +Copyright (c) Facebook, Inc. and its affiliates. + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-i18next" + +, internationalization for react using the i18next i18n ecosystem, which contains the +following copyright and permission notice: + +Copyright (c) 2022 i18next + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"React Native" + +, brings React's declarative UI framework to iOS and Android, which +contains the following copyright and permission notice: + +Copyright (c) Meta Platforms, Inc. and affiliates. + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-app-intro-slider" + +, app introduction slider/swiper based on FlatList that supports RTL, which +contains the following copyright and permission notice: + +Copyright (c) 2015 Joel Arvidsson + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-argon2" + +, react Native Wrapper around native Argon2 implementations, which contains +the following copyright and permission notice: + +Copyright (c) 2020 Zane J. Chua + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-biometrics" + +, a simple bridge to native iOS and Android keystore management, which +contains the following copyright and permission notice: + +Copyright (c) 2018-present, Self Lender, Inc. + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-camera" + +, a camera component for React Native, which contains the following +copyright and permission notice: + +Copyright (c) 2015 Loch Wansbrough + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"React Native Circular Progress Indicator" + +, a simple and customizable React Native circular progress indicator component, +which contains the following copyright and permission notice: + +Copyright (c) 2021 nithinpp69 + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-config" + +, a module to expose config variables to your javascript code in React Native, +which contains the following copyright and permission notice: + +Copyright (c) 2015 Lugg + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-device-info" + +, device information for React Native, which contains the following copyright +and permission notice: + +Copyright (c) 2015 Rebecca Hughes + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-document-picker" + +, a document Picker for React Native using Document Providers, which contains the following +copyright and permission notice: + +Copyright (c) 2016 Elyx0 + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"React Native Dropdown Picker" + +, a single / multiple, categorizable, customizable, localizable and searchable item picker +(drop-down) component for react native which supports both Android & iOS , which contains +the following copyright and permission notice: + +Copyright (c) Hossein Zare + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-fs" + +, a native filesystem access for react-native, which contains the following +copyright and permission notice: + +Copyright (c) 2015 Johannes Lumpe + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"React Native Gesture Handler" + +, declarative API exposing platform native touch and gesture system to React Native, +which contains the following copyright and permission notice: + +Copyright (c) 2016 Software Mansion <swmansion.com> + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-get-random-values" + +, a small implementation of crypto.getRandomValues for React Native, which contains +the following copyright and permission notice: + +Copyright (c) 2018, 2020 Linus Unnebäck + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-keychain" + +, Keychain Access for React Native, which contains the following copyright +and permission notice: + +Copyright (c) 2015 Joel Arvidsson + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-localize" + +, a toolbox for your React Native app localization, which contains the following +copyright and permission notice: + +Copyright (c) 2017-present, Mathieu Acthernoene + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-paper" + +, material design for React Native, which contains the following copyright +and permission notice: + +Copyright (c) 2017 Callstack + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-reanimated" + +, a more comprehensive, low level abstraction for the Animated library API to be +built on top of and hence allow for much greater flexibility, which contains the +following copyright and permission notice: + +Copyright (c) 2016 Software Mansion <swmansion.com> + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-safe-area-contex" + +, a flexible way to handle safe area, also works on Android and Web, which +contains the following copyright and permission notice: + +Copyright (c) 2019 Th3rd Wave + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-screens" + +, expose native navigation container components to React Native, which contains +the following copyright and permission notice: + +Copyright (c) 2018 Software Mansion <swmansion.com> + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-share" + +, react Native Share, a simple tool for share message and file to other apps, +which contains the following copyright and permission notice: + +Copyright (c) 2015 Esteban Fuentealba 🇨🇱, Mateus Andrade 🇧🇷, Mike Hardy 🇪🇨, João Marins 🇧🇷 + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-splash-screen" + +, a splash screen API for react-native which can programatically hide and show the +splash screen, which contains the following copyright and permission notice: + +Copyright (c) 2016 Jia PengHui + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-svg" + +, provides SVG support to React Native, which contains the following copyright +and permission notice: + +Copyright (c) [2015-2016] [Horcrux] + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-toast-message" + +, animated toast message component for React Native, which contains the following +copyright and permission notice: + +Copyright (c) 2019 Calin Tamas + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-user-inactivity" + +, React Native component that notifies if the user is active or not, which contains +the following copyright and permission notice: + +Copyright (c) 2019 Alberto Schiabel + +(The MIT License) +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + + +This Personal Credential Manager also incorporates + +"react-native-vector-icons" + +, customizable Icons for React Native with support for image source and full styling, +which contains the following copyright and permission notice: + +Copyright (c) 2015 Joel Arvidsson + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +This Personal Credential Manager also incorporates + +"rn-fetch-blob" + +, a project committed to making file access and data transfer easier, efficient for +React Native developers, which contains the following copyright and permission notice: + +Copyright (c) 2017 xeiyan@gmail.com + +(The MIT License) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 62743471cd04db7923ec8a677243f96985307a47..6f2c63fc8ca607e18b8c66cd6ebcbccb516cd9da 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,153 @@ -# Vereign Credential Manager +# PCM App +## Code +This project utilizes [Aries Framework Javascript (AFJ)](https://github.com/hyperledger/aries-framework-javascript) and [indy-sdk-react-native](https://github.com/hyperledger/indy-sdk-react-native). -## Getting started +## Project State -To make it easy for you to get started with GitLab, here's a list of recommended next steps. +### Platform -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! +PCM currently is built on React Native 0.70.6 -## Add your files +As of now PCM targets Android API 30.0.2 -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: +iOS targets iOS 12.4+.PCM can only be run on physical devices as of right now. +## Install + +1. React Native Setup: + - React Native installation instructions are documented [here](https://reactnative.dev/docs/environment-setup). + - (iOS) Install [Cocoa Pods](https://cocoapods.org/) +2. Clone the PCM repo and install its dependencies: + ```sh + git clone https://gitlab.com/gaia-x/data-infrastructure-federation-services/pcm/app.git + yarn install + ``` +3. (iOS) iOS specific install: + - Install iOS Pods: + ```sh + cd ios + pod install + ``` + - In the /ios directory, open the project workspace file in Xcode. + Once the project is open, navigate to the project's Signing & Capabilities tab and apply your personal Apple Developer Account or your organization's team to target PCM + - Adjust the bundle identifier if needed. + +## Configure + +In the root directory add an `.env` file containing: ``` -cd existing_repo -git remote add origin https://code.vereign.com/ssi/vpw/vcm.git -git branch -M main -git push -uf origin main +MEDIATOR_URL=https://gaiax.vereign.com/mediator?c_i=eyJAdHlwZSI6ICJkaWQ6c292OkJ6Q2JzTlloTXJqSGlxWkRUVUFTSGc7c3BlYy9jb25uZWN0aW9ucy8xLjAvaW52aXRhdGlvbiIsICJAaWQiOiAiMWY0ZjVhN2QtOWNmMi00NjZhLWJjNmItNTczOTMwMDVmNDE3IiwgInJlY2lwaWVudEtleXMiOiBbIkRBc2prQTdZeXZCM3hrc1NtYXRMVDVyM2hqUU4zQnN4R1VKWHhiU3l6RWtIIl0sICJzZXJ2aWNlRW5kcG9pbnQiOiAiaHR0cHM6Ly9nYWlheC52ZXJlaWduLmNvbS9tZWRpYXRvciIsICJsYWJlbCI6ICJNZWRpYXRvciJ9 +NOTIFICATION_URL=https://gaiax.vereign.com/ocm/notification ``` -## Integrate with your tools -- [ ] [Set up project integrations](https://code.vereign.com/ssi/vpw/vcm/-/settings/integrations) +## Run + +- Launch the metro bundler: + ```sh + yarn start + ``` +- Open a second terminal and run: + - (Android) + ```sh + yarn android + ``` + - (iOS) + ```sh + yarn ios + ``` + - (iOS) Via Xcode: + Choose your physical iOS device as the destination. Click the "Play" button to Build and Run. + +**NOTE: PCM does not work on iOS simulators** -- use a physical device instead. + +### Advanced Configuration -## Collaborate with your team +#### Mediator -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) +In order to use PCM, you must have a mediator to use with the app. PCM is configured to use 'Implicit' mediation and requires a mediator that supports the [coordinate-mediation protocol](https://github.com/hyperledger/aries-rfcs/tree/main/features/0211-route-coordination). -## Test and Deploy +## Troubleshooting -Use the built-in continuous integration in GitLab. +#### Hot Reloading -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) +Hot reloading may not work correctly with instantiated Agent objects. Reloading (`r`) or reopening the app may work. Any changes made to native modules require you to re-run the compile step. -*** +### Dependency Issues, Native Module Linking Issues, or Usage Issues -# Editing this README +If you end up changing dependencies or structures, you may need to perform the following steps: -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template. +#### Android -## Suggestions for a good README -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. +```sh +rm -rf node_modules +yarn install +``` + +Clean the Android build: + +```sh +cd android +./gradlew clean +cd .. +``` + +Start and clean the Metro cache: -## Name -Choose a self-explaining name for your project. +```sh +yarn start +``` + +In your second terminal, you can now run: + +```sh +yarn android +``` + +## Building local android apk file in debug mode + +Create .env file with environment variables + +Run command in root folder of app project + +```sh +npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res +``` + +Go to path `android` and run the command + +```sh +./gradlew assembleDebug +``` -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. +As a result you will get apk file in `./android/app/build/outputs/apk/[production|development]` -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. +## Useful commends -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. +`./gradlew signingReport` - In order to find out what's wrong with apk signing you can use gradle's signingReport command. -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. +## Latest Android version +<hr/> -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. +[Android PCM](https://vereign0-my.sharepoint.com/:f:/g/personal/kalin_canov_vereign_com/EiwSfVWCOllDiSC57_DE_xABBVKkiJYx_tANEvbJiI9lGQ?e=3VBnIX) -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. +## GDPR +<hr/> -## Contributing -State if you are open to contributions and what your requirements are for accepting them. +[GDPR](GDPR.md) -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. +### Note +`Man in the mid` security concern it will be addressed in Phase II. One of the discussed options is to use [TRAIN API](https://train.trust-scheme.de/info/) -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. +## Dependencies +<hr/> -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. +[Dependencies](package.json) ## License -For open source projects, say how it is licensed. +<hr/> -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. +[Apache 2.0 license](LICENSE) diff --git a/__mocks__/@aries-framework/react-hooks.ts b/__mocks__/@aries-framework/react-hooks.ts new file mode 100644 index 0000000000000000000000000000000000000000..041551c4548332bdf199b7df30fc6f1c72792a7d --- /dev/null +++ b/__mocks__/@aries-framework/react-hooks.ts @@ -0,0 +1,35 @@ +import { CredentialExchangeRecord, ProofRecord } from '@aries-framework/core'; + +const useCredentials = jest.fn().mockReturnValue({ credentials: [] } as any); +const useCredentialByState = jest + .fn() + .mockReturnValue([] as CredentialExchangeRecord[]); +const useProofByState = jest.fn().mockReturnValue([] as ProofRecord[]); +const mockCredentialModule = { + acceptOffer: jest.fn(), + declineOffer: jest.fn(), +}; +const mockProofModule = { + getRequestedCredentialsForProofRequest: jest.fn(), + acceptRequest: jest.fn(), + declineRequest: jest.fn(), +}; +const useAgent = () => ({ + agent: { + credentials: mockCredentialModule, + proofs: mockProofModule, + }, +}); +const useCredentialById = jest.fn(); +const useProofById = jest.fn(); +const useConnectionById = jest.fn(); + +export { + useAgent, + useConnectionById, + useCredentials, + useCredentialById, + useCredentialByState, + useProofById, + useProofByState, +}; diff --git a/__mocks__/@react-native-async-storage/async-storage.ts b/__mocks__/@react-native-async-storage/async-storage.ts new file mode 100644 index 0000000000000000000000000000000000000000..ef43ca918972593fde7ed284f59af8959e7b6732 --- /dev/null +++ b/__mocks__/@react-native-async-storage/async-storage.ts @@ -0,0 +1,3 @@ +import AsyncStorageMock from '@react-native-async-storage/async-storage/jest/async-storage-mock'; + +export default AsyncStorageMock; diff --git a/__mocks__/@react-navigation/core.ts b/__mocks__/@react-navigation/core.ts new file mode 100644 index 0000000000000000000000000000000000000000..183eb04764a464bae0a0bc2f08e91ca292b2deaf --- /dev/null +++ b/__mocks__/@react-navigation/core.ts @@ -0,0 +1,21 @@ +const navigate = jest.fn(); + +const navigation = { + navigate, + setOptions: jest.fn(), + getParent: jest.fn(() => ({ + navigate, + })), + getState: jest.fn(() => ({ + index: jest.fn(), + })), + goBack: jest.fn(), + pop: jest.fn(), + reset: jest.fn(), +}; + +const useNavigation = () => { + return navigation; +}; + +export { useNavigation }; diff --git a/__mocks__/@react-navigation/native.ts b/__mocks__/@react-navigation/native.ts new file mode 100644 index 0000000000000000000000000000000000000000..96ef7e535f067cade3d20ee9a529f23e60cdfe97 --- /dev/null +++ b/__mocks__/@react-navigation/native.ts @@ -0,0 +1,3 @@ +const useFocusEffect = jest.fn(); + +export default { useFocusEffect }; diff --git a/__mocks__/i18next.ts b/__mocks__/i18next.ts new file mode 100644 index 0000000000000000000000000000000000000000..7c437468b811ab066774eedfe40b8e0899020354 --- /dev/null +++ b/__mocks__/i18next.ts @@ -0,0 +1,3 @@ +const i18nextMock = jest.mock('i18next'); + +export default i18nextMock; diff --git a/__mocks__/react-i18next.ts b/__mocks__/react-i18next.ts new file mode 100644 index 0000000000000000000000000000000000000000..5d5027f86554d743a2e4e0714b56d8ace72ac0ba --- /dev/null +++ b/__mocks__/react-i18next.ts @@ -0,0 +1,8 @@ +const mockT = jest.fn((key: string) => key); +const useTranslation = jest.fn().mockReturnValue({ t: mockT }); +const initReactI18next = { + type: '3rdParty', + init: jest.fn(), +}; + +export { useTranslation, initReactI18next }; diff --git a/__mocks__/react-native-argon2.ts b/__mocks__/react-native-argon2.ts new file mode 100644 index 0000000000000000000000000000000000000000..d60a4ed2bf30694c742f10b571d6764273b47f8f --- /dev/null +++ b/__mocks__/react-native-argon2.ts @@ -0,0 +1,3 @@ +const rnArgon2MockedModule = jest.mock('react-native-argon2'); + +module.exports = rnArgon2MockedModule; diff --git a/__mocks__/react-native-camera.ts b/__mocks__/react-native-camera.ts new file mode 100644 index 0000000000000000000000000000000000000000..b9e6b6f43e873825ff7650196b50c48df9eb325c --- /dev/null +++ b/__mocks__/react-native-camera.ts @@ -0,0 +1,21 @@ +import React from 'react'; + +export class RNCamera extends React.Component { + static Constants = { + Aspect: {}, + BarCodeType: {}, + Type: { back: 'back', front: 'front' }, + CaptureMode: {}, + CaptureTarget: {}, + CaptureQuality: {}, + Orientation: {}, + FlashMode: {}, + TorchMode: {}, + }; + + render() { + return null; + } +} + +export default RNCamera; diff --git a/__mocks__/react-native-config.ts b/__mocks__/react-native-config.ts new file mode 100644 index 0000000000000000000000000000000000000000..5787082af9ce5b5ec60202c3c1d331b0380ccb84 --- /dev/null +++ b/__mocks__/react-native-config.ts @@ -0,0 +1,3 @@ +const rnConfigMockedModule = jest.mock('react-native-config'); + +module.exports = rnConfigMockedModule; diff --git a/__mocks__/react-native-dropdown-picker.ts b/__mocks__/react-native-dropdown-picker.ts new file mode 100644 index 0000000000000000000000000000000000000000..f23f12f03bcf2018c292d50b183f929ce5870531 --- /dev/null +++ b/__mocks__/react-native-dropdown-picker.ts @@ -0,0 +1,3 @@ +const rnDropDownMock = jest.mock('react-native-dropdown-picker'); + +module.exports = rnDropDownMock; diff --git a/__mocks__/react-native-keychain.ts b/__mocks__/react-native-keychain.ts new file mode 100644 index 0000000000000000000000000000000000000000..bd930e8d1cdf3a03720641103f0fe4d4f23ddbb8 --- /dev/null +++ b/__mocks__/react-native-keychain.ts @@ -0,0 +1,3 @@ +const rnkeychainMock = jest.mock('react-native-keychain'); + +module.exports = rnkeychainMock; diff --git a/__mocks__/react-native-localize.ts b/__mocks__/react-native-localize.ts new file mode 100644 index 0000000000000000000000000000000000000000..070884373025105b3f816893fe80380ed5698ed0 --- /dev/null +++ b/__mocks__/react-native-localize.ts @@ -0,0 +1,60 @@ +// const rnLocalizeMock = jest.mock('react-native-localize', () => ({ +// getLocales: () => [ +// { +// countryCode: 'GB', +// languageTag: 'en-GB', +// languageCode: 'en', +// isRTL: false, +// }, +// { +// countryCode: 'US', +// languageTag: 'en-US', +// languageCode: 'en', +// isRTL: false, +// }, +// { +// countryCode: 'FR', +// languageTag: 'fr-FR', +// languageCode: 'fr', +// isRTL: false, +// }, +// ], + +// getNumberFormatSettings: () => ({ +// decimalSeparator: '.', +// groupingSeparator: ',', +// }), + +// getCalendar: () => 'gregorian', // or "japanese", "buddhist" +// getCountry: () => 'US', // the country code you want +// getCurrencies: () => ['USD', 'EUR'], // can be empty array +// getTemperatureUnit: () => 'celsius', // or "fahrenheit" +// getTimeZone: () => 'Europe/Paris', // the timezone you want +// uses24HourClock: () => true, +// usesMetricSystem: () => true, + +// addEventListener: jest.fn(), +// removeEventListener: jest.fn(), +// findBestAvailableLanguage: () => ({ +// languageTag: 'en-US', +// isRTL: false, +// }), +// })) + +// export default rnLocalizeMock +// // export const findBestAvailableLanguage = jest.fn(() => ({ +// // languageTag: 'en', +// // isRTL: false, +// // })) +// import RNLocalize from 'react-native-localize/mock' + +// const rnLocalizeMock = jest.mock('react-native-localize', () => RNLocalize) + +// export default rnLocalizeMock + +const findBestAvailableLanguage = () => ({ + languageTag: 'en-US', + isRTL: false, +}); + +export default { findBestAvailableLanguage }; diff --git a/__mocks__/react-native-splash-screen.ts b/__mocks__/react-native-splash-screen.ts new file mode 100644 index 0000000000000000000000000000000000000000..7614277cf9d45f35fb7b243a1e4216a66cbe6094 --- /dev/null +++ b/__mocks__/react-native-splash-screen.ts @@ -0,0 +1,3 @@ +const rnSplashScreenMock = jest.mock('react-native-splash-screen'); + +module.exports = rnSplashScreenMock; diff --git a/__mocks__/react-native-toast-message.ts b/__mocks__/react-native-toast-message.ts new file mode 100644 index 0000000000000000000000000000000000000000..412dbe1b11962295fb80b44a1141d921c82472cf --- /dev/null +++ b/__mocks__/react-native-toast-message.ts @@ -0,0 +1,3 @@ +const rnToastMessageModule = jest.mock('react-native-toast-message'); + +module.exports = rnToastMessageModule; diff --git a/android/app/_BUCK b/android/app/_BUCK new file mode 100644 index 0000000000000000000000000000000000000000..6d47c800cf6cc04579c74eee3004229d9d2be26f --- /dev/null +++ b/android/app/_BUCK @@ -0,0 +1,55 @@ +# To learn about Buck see [Docs](https://buckbuild.com/). +# To run your application with Buck: +# - install Buck +# - `npm start` - to start the packager +# - `cd android` +# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` +# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck +# - `buck install -r android/app` - compile, install and run application +# + +load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") + +lib_deps = [] + +create_aar_targets(glob(["libs/*.aar"])) + +create_jar_targets(glob(["libs/*.jar"])) + +android_library( + name = "all-libs", + exported_deps = lib_deps, +) + +android_library( + name = "app-code", + srcs = glob([ + "src/main/java/**/*.java", + ]), + deps = [ + ":all-libs", + ":build_config", + ":res", + ], +) + +android_build_config( + name = "build_config", + package = "eu.gaiax.difs.pcm", +) + +android_resource( + name = "res", + package = "eu.gaiax.difs.pcm", + res = "src/main/res", +) + +android_binary( + name = "app", + keystore = "//android/keystores:debug", + manifest = "src/main/AndroidManifest.xml", + package_type = "debug", + deps = [ + ":app-code", + ], +) diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..2ccd9f80f8261931b181db6a365aee549c27d9c4 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,327 @@ +apply plugin: "com.android.application" + +import com.android.build.OutputFile +import org.apache.tools.ant.taskdefs.condition.Os + +/** + * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets + * and bundleReleaseJsAndAssets). + * These basically call `react-native bundle` with the correct arguments during the Android build + * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the + * bundle directly from the development server. Below you can see all the possible configurations + * and their defaults. If you decide to add a configuration block, make sure to add it before the + * `apply from: "../../node_modules/react-native/react.gradle"` line. + * + * project.ext.react = [ + * // the name of the generated asset file containing your JS bundle + * bundleAssetName: "index.android.bundle", + * + * // the entry file for bundle generation. If none specified and + * // "index.android.js" exists, it will be used. Otherwise "index.js" is + * // default. Can be overridden with ENTRY_FILE environment variable. + * entryFile: "index.android.js", + * + * // https://reactnative.dev/docs/performance#enable-the-ram-format + * bundleCommand: "ram-bundle", + * + * // whether to bundle JS and assets in debug mode + * bundleInDebug: false, + * + * // whether to bundle JS and assets in release mode + * bundleInRelease: true, + * + * // whether to bundle JS and assets in another build variant (if configured). + * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants + * // The configuration property can be in the following formats + * // 'bundleIn${productFlavor}${buildType}' + * // 'bundleIn${buildType}' + * // bundleInFreeDebug: true, + * // bundleInPaidRelease: true, + * // bundleInBeta: true, + * + * // whether to disable dev mode in custom build variants (by default only disabled in release) + * // for example: to disable dev mode in the staging build type (if configured) + * devDisabledInStaging: true, + * // The configuration property can be in the following formats + * // 'devDisabledIn${productFlavor}${buildType}' + * // 'devDisabledIn${buildType}' + * + * // the root of your project, i.e. where "package.json" lives + * root: "../../", + * + * // where to put the JS bundle asset in debug mode + * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", + * + * // where to put the JS bundle asset in release mode + * jsBundleDirRelease: "$buildDir/intermediates/assets/release", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in debug mode + * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in release mode + * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", + * + * // by default the gradle tasks are skipped if none of the JS files or assets change; this means + * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to + * // date; if you have any other folders that you want to ignore for performance reasons (gradle + * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ + * // for example, you might want to remove it from here. + * inputExcludes: ["android/**", "ios/**"], + * + * // override which node gets called and with what additional arguments + * nodeExecutableAndArgs: ["node"], + * + * // supply additional arguments to the packager + * extraPackagerArgs: [] + * ] + */ + +project.ext.react = [ + enableHermes: true, // clean and rebuild if changing +] + +apply from: "../../node_modules/react-native/react.gradle" + +/** + * Set this to true to create two separate APKs instead of one: + * - An APK that only works on ARM devices + * - An APK that only works on x86 devices + * The advantage is the size of the APK is reduced by about 4MB. + * Upload all the APKs to the Play Store and people will download + * the correct one based on the CPU architecture of their device. + */ +def enableSeparateBuildPerCPUArchitecture = false + +/** + * Run Proguard to shrink the Java bytecode in release builds. + */ +def enableProguardInReleaseBuilds = false + +/** + * The preferred build flavor of JavaScriptCore. + * + * For example, to use the international variant, you can use: + * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'org.webkit:android-jsc:+' + +/** + * Whether to enable the Hermes VM. + * + * This should be set on project.ext.react and that value will be read here. If it is not set + * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode + * and the benefits of using Hermes will therefore be sharply reduced. + */ +def enableHermes = project.ext.react.get("enableHermes", false); + +/** + * Architectures to build native code for. + */ +def reactNativeArchitectures() { + def value = project.getProperties().get("reactNativeArchitectures") + return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] +} + +android { + ndkVersion rootProject.ext.ndkVersion + + compileSdkVersion rootProject.ext.compileSdkVersion + + defaultConfig { + applicationId "eu.gaiax.difs.pcm" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode rootProject.ext.versionCode.toInteger() + versionName rootProject.ext.versionName + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() + + if (isNewArchitectureEnabled()) { + // We configure the CMake build only if you decide to opt-in for the New Architecture. + externalNativeBuild { + cmake { + arguments "-DPROJECT_BUILD_DIR=$buildDir", + "-DREACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid", + "-DREACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build", + "-DNODE_MODULES_DIR=$rootDir/../node_modules", + "-DANDROID_STL=c++_shared" + } + } + if (!enableSeparateBuildPerCPUArchitecture) { + ndk { + abiFilters (*reactNativeArchitectures()) + } + } + } + } + + if (isNewArchitectureEnabled()) { + // We configure the NDK build only if you decide to opt-in for the New Architecture. + externalNativeBuild { + cmake { + path "$projectDir/src/main/jni/CMakeLists.txt" + } + } + def reactAndroidProjectDir = project(':ReactAndroid').projectDir + def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) { + dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck") + from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib") + into("$buildDir/react-ndk/exported") + } + def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) { + dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck") + from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib") + into("$buildDir/react-ndk/exported") + } + afterEvaluate { + // If you wish to add a custom TurboModule or component locally, + // you should uncomment this line. + // preBuild.dependsOn("generateCodegenArtifactsFromSchema") + preDebugBuild.dependsOn(packageReactNdkDebugLibs) + preReleaseBuild.dependsOn(packageReactNdkReleaseLibs) + + // Due to a bug inside AGP, we have to explicitly set a dependency + // between configureCMakeDebug* tasks and the preBuild tasks. + // This can be removed once this is solved: https://issuetracker.google.com/issues/207403732 + configureCMakeRelWithDebInfo.dependsOn(preReleaseBuild) + configureCMakeDebug.dependsOn(preDebugBuild) + reactNativeArchitectures().each { architecture -> + tasks.findByName("configureCMakeDebug[${architecture}]")?.configure { + dependsOn("preDebugBuild") + } + tasks.findByName("configureCMakeRelWithDebInfo[${architecture}]")?.configure { + dependsOn("preReleaseBuild") + } + } + } + } + + splits { + abi { + reset() + enable enableSeparateBuildPerCPUArchitecture + universalApk false // If true, also generate a universal APK + include (*reactNativeArchitectures()) + } + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + release { + if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) { + storeFile file(MYAPP_UPLOAD_STORE_FILE) + storePassword MYAPP_UPLOAD_STORE_PASSWORD + keyAlias MYAPP_UPLOAD_KEY_ALIAS + keyPassword MYAPP_UPLOAD_KEY_PASSWORD + } + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.release + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } + + // applicationVariants are e.g. debug, release + applicationVariants.all { variant -> + variant.outputs.each { output -> + // For each separate APK per architecture, set a unique version code as described here: + // https://developer.android.com/studio/build/configure-apk-splits.html + // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. + def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] + def abi = output.getFilter(OutputFile.ABI) + if (abi != null) { // null for the universal-debug, universal-release variants + output.versionCodeOverride = + defaultConfig.versionCode * 1000 + versionCodes.get(abi) + } + + } + } +} + +dependencies { + implementation fileTree(dir: "libs", include: ["*.jar"]) + + //noinspection GradleDynamicVersion + implementation "com.facebook.react:react-native:+" // From node_modules + + implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" + + implementation 'net.java.dev.jna:jna:5.2.0' + + implementation project(':react-native-config') + + debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { + exclude group:'com.facebook.fbjni' + } + + debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { + exclude group:'com.facebook.flipper' + exclude group:'com.squareup.okhttp3', module:'okhttp' + } + + debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { + exclude group:'com.facebook.flipper' + } + + if (enableHermes) { + //noinspection GradleDynamicVersion + implementation("com.facebook.react:hermes-engine:+") { // From node_modules + exclude group:'com.facebook.fbjni' + } + } else { + implementation jscFlavor + } +} + +if (isNewArchitectureEnabled()) { + // If new architecture is enabled, we let you build RN from source + // Otherwise we fallback to a prebuilt .aar bundled in the NPM package. + // This will be applied to all the imported transtitive dependency. + configurations.all { + resolutionStrategy.dependencySubstitution { + substitute(module("com.facebook.react:react-native")) + .using(project(":ReactAndroid")) + .because("On New Architecture we're building React Native from source") + substitute(module("com.facebook.react:hermes-engine")) + .using(project(":ReactAndroid:hermes-engine")) + .because("On New Architecture we're building Hermes from source") + } + } +} + +// Run this once to be able to run the application with BUCK +// puts all compile dependencies into folder libs for BUCK to use +task copyDownloadableDepsToLibs(type: Copy) { + from configurations.implementation + into 'libs' +} + +apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) + +def isNewArchitectureEnabled() { + // To opt-in for the New Architecture, you can either: + // - Set `newArchEnabled` to true inside the `gradle.properties` file + // - Invoke gradle with `-newArchEnabled=true` + // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true` + return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" +} + +apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" diff --git a/android/app/build_defs.bzl b/android/app/build_defs.bzl new file mode 100644 index 0000000000000000000000000000000000000000..fff270f8d1d48432e85353a715d7ebad229b6d94 --- /dev/null +++ b/android/app/build_defs.bzl @@ -0,0 +1,19 @@ +"""Helper definitions to glob .aar and .jar targets""" + +def create_aar_targets(aarfiles): + for aarfile in aarfiles: + name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] + lib_deps.append(":" + name) + android_prebuilt_aar( + name = name, + aar = aarfile, + ) + +def create_jar_targets(jarfiles): + for jarfile in jarfiles: + name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] + lib_deps.append(":" + name) + prebuilt_jar( + name = name, + binary_jar = jarfile, + ) diff --git a/android/app/debug.keystore b/android/app/debug.keystore new file mode 100644 index 0000000000000000000000000000000000000000..364e105ed39fbfd62001429a68140672b06ec0de Binary files /dev/null and b/android/app/debug.keystore differ diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro new file mode 100644 index 0000000000000000000000000000000000000000..11b025724a3f7a4a3685bbcd27da16440749f5e8 --- /dev/null +++ b/android/app/proguard-rules.pro @@ -0,0 +1,10 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..4b185bc1597eb762051660198c02074bf82ab974 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools"> + + <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> + + <application + android:usesCleartextTraffic="true" + tools:targetApi="28" + tools:ignore="GoogleAppIndexingWarning"> + <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false" /> + </application> +</manifest> diff --git a/android/app/src/debug/java/com/personalcredentialmanager/ReactNativeFlipper.java b/android/app/src/debug/java/com/personalcredentialmanager/ReactNativeFlipper.java new file mode 100644 index 0000000000000000000000000000000000000000..f96d922600e8097098822d03372212d2385516ec --- /dev/null +++ b/android/app/src/debug/java/com/personalcredentialmanager/ReactNativeFlipper.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * <p>This source code is licensed under the MIT license found in the LICENSE file in the root + * directory of this source tree. + */ +package eu.gaiax.difs.pcm; + +import android.content.Context; +import com.facebook.flipper.android.AndroidFlipperClient; +import com.facebook.flipper.android.utils.FlipperUtils; +import com.facebook.flipper.core.FlipperClient; +import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; +import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; +import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; +import com.facebook.flipper.plugins.inspector.DescriptorMapping; +import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; +import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; +import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; +import com.facebook.flipper.plugins.react.ReactFlipperPlugin; +import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; +import com.facebook.react.ReactInstanceEventListener; +import com.facebook.react.ReactInstanceManager; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.modules.network.NetworkingModule; +import okhttp3.OkHttpClient; + +public class ReactNativeFlipper { + public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { + if (FlipperUtils.shouldEnableFlipper(context)) { + final FlipperClient client = AndroidFlipperClient.getInstance(context); + + client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); + client.addPlugin(new ReactFlipperPlugin()); + client.addPlugin(new DatabasesFlipperPlugin(context)); + client.addPlugin(new SharedPreferencesFlipperPlugin(context)); + client.addPlugin(CrashReporterPlugin.getInstance()); + + NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); + NetworkingModule.setCustomClientBuilder( + new NetworkingModule.CustomClientBuilder() { + @Override + public void apply(OkHttpClient.Builder builder) { + builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); + } + }); + client.addPlugin(networkFlipperPlugin); + client.start(); + + // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized + // Hence we run if after all native modules have been initialized + ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); + if (reactContext == null) { + reactInstanceManager.addReactInstanceEventListener( + new ReactInstanceEventListener() { + @Override + public void onReactContextInitialized(ReactContext reactContext) { + reactInstanceManager.removeReactInstanceEventListener(this); + reactContext.runOnNativeModulesQueueThread( + new Runnable() { + @Override + public void run() { + client.addPlugin(new FrescoFlipperPlugin()); + } + }); + } + }); + } else { + client.addPlugin(new FrescoFlipperPlugin()); + } + } + } +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..de3c44cbdb51ddc2cd66f5e066e6d28cbb51e007 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,39 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="eu.gaiax.difs.pcm"> + + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.CAMERA" /> + <uses-permission android:name="android.permission.VIBRATE" /> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> + + <application + android:name=".MainApplication" + android:label="@string/app_name" + android:icon="@mipmap/ic_launcher" + android:roundIcon="@mipmap/ic_launcher_round" + android:allowBackup="false" + android:theme="@style/AppTheme" + android:usesCleartextTraffic="true"> + <activity + android:name=".MainActivity" + android:label="@string/app_name" + android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" + android:launchMode="singleTask" + android:screenOrientation="portrait" + android:windowSoftInputMode="adjustPan" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + <data android:scheme="gxfspcm" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/android/app/src/main/assets/fonts/AntDesign.ttf b/android/app/src/main/assets/fonts/AntDesign.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2abf03542c17e6f7a7806a226c3be732b51c5a40 Binary files /dev/null and b/android/app/src/main/assets/fonts/AntDesign.ttf differ diff --git a/android/app/src/main/assets/fonts/Entypo.ttf b/android/app/src/main/assets/fonts/Entypo.ttf new file mode 100644 index 0000000000000000000000000000000000000000..76d91cb9895982d66c398f9da3daa61470488fb6 Binary files /dev/null and b/android/app/src/main/assets/fonts/Entypo.ttf differ diff --git a/android/app/src/main/assets/fonts/EvilIcons.ttf b/android/app/src/main/assets/fonts/EvilIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6868f7bb64ba71b131690286ddc82aa0f542293e Binary files /dev/null and b/android/app/src/main/assets/fonts/EvilIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/Feather.ttf b/android/app/src/main/assets/fonts/Feather.ttf new file mode 100644 index 0000000000000000000000000000000000000000..49698e74205843ebf63e7af48dda68e5b6fde879 Binary files /dev/null and b/android/app/src/main/assets/fonts/Feather.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome.ttf b/android/app/src/main/assets/fonts/FontAwesome.ttf new file mode 100644 index 0000000000000000000000000000000000000000..35acda2fa1196aad98c2adf4378a7611dd713aa3 Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf new file mode 100644 index 0000000000000000000000000000000000000000..fc567cd2f11d83683d9eb4ca1a5fdc912f7d417c Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d1ac9ba1169e4076832034c5585e1c5bf9d6f83c Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f33e8162997aaa9da582aa81428ee87aa48953a6 Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf differ diff --git a/android/app/src/main/assets/fonts/Fontisto.ttf b/android/app/src/main/assets/fonts/Fontisto.ttf new file mode 100755 index 0000000000000000000000000000000000000000..96e2e81a3d1e00f2638000e2110075d3af23cfbe Binary files /dev/null and b/android/app/src/main/assets/fonts/Fontisto.ttf differ diff --git a/android/app/src/main/assets/fonts/Foundation.ttf b/android/app/src/main/assets/fonts/Foundation.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6cce217ddc2efe3411dc9fa34e294e48e4cdf4f5 Binary files /dev/null and b/android/app/src/main/assets/fonts/Foundation.ttf differ diff --git a/android/app/src/main/assets/fonts/Ionicons.ttf b/android/app/src/main/assets/fonts/Ionicons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..719442d420a9c3d8df77d85b6f6ea1bc55bd39cc Binary files /dev/null and b/android/app/src/main/assets/fonts/Ionicons.ttf differ diff --git a/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf b/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ba873595714be0aed5b3f40c3f409125d58b741e Binary files /dev/null and b/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/MaterialIcons.ttf b/android/app/src/main/assets/fonts/MaterialIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e50801b3b620af91f824c7655df7d064db05b764 Binary files /dev/null and b/android/app/src/main/assets/fonts/MaterialIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/Octicons.ttf b/android/app/src/main/assets/fonts/Octicons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f8daedca4515bb70b84038c6c447022f868f57ab Binary files /dev/null and b/android/app/src/main/assets/fonts/Octicons.ttf differ diff --git a/android/app/src/main/assets/fonts/SimpleLineIcons.ttf b/android/app/src/main/assets/fonts/SimpleLineIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6ecb68683477ecc5aed38ec3fc8910d9bb66276c Binary files /dev/null and b/android/app/src/main/assets/fonts/SimpleLineIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/TitilliumWeb-Light.ttf b/android/app/src/main/assets/fonts/TitilliumWeb-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..fa9393d1cbf42cabd8bcc9d4a94176534ba2b590 Binary files /dev/null and b/android/app/src/main/assets/fonts/TitilliumWeb-Light.ttf differ diff --git a/android/app/src/main/assets/fonts/TitilliumWeb-Regular.ttf b/android/app/src/main/assets/fonts/TitilliumWeb-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e0e2dc888cfeaa9b7ecd53ffa85d911afd6d9542 Binary files /dev/null and b/android/app/src/main/assets/fonts/TitilliumWeb-Regular.ttf differ diff --git a/android/app/src/main/assets/fonts/TitilliumWeb-SemiBold.ttf b/android/app/src/main/assets/fonts/TitilliumWeb-SemiBold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2a1a0bca99246e923732bfc382bdb96e3074216f Binary files /dev/null and b/android/app/src/main/assets/fonts/TitilliumWeb-SemiBold.ttf differ diff --git a/android/app/src/main/assets/fonts/Zocial.ttf b/android/app/src/main/assets/fonts/Zocial.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e2b5fbb02fd0ce400780207ac39d203a319af7bb Binary files /dev/null and b/android/app/src/main/assets/fonts/Zocial.ttf differ diff --git a/android/app/src/main/assets/fonts/antfill.ttf b/android/app/src/main/assets/fonts/antfill.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2553f565c3ed1d20384c66140a88bf1c9daf975c Binary files /dev/null and b/android/app/src/main/assets/fonts/antfill.ttf differ diff --git a/android/app/src/main/assets/fonts/antoutline.ttf b/android/app/src/main/assets/fonts/antoutline.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f96ca4c1c419a0b05a6ddf31e275fe080a62af92 Binary files /dev/null and b/android/app/src/main/assets/fonts/antoutline.ttf differ diff --git a/android/app/src/main/java/eu/gaiax/difs/pcm/MainActivity.java b/android/app/src/main/java/eu/gaiax/difs/pcm/MainActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..eb35fb7c0de8a405f7eceed0426bdb255695714f --- /dev/null +++ b/android/app/src/main/java/eu/gaiax/difs/pcm/MainActivity.java @@ -0,0 +1,62 @@ +package eu.gaiax.difs.pcm; +import android.os.Bundle; +import android.system.Os; +import android.system.ErrnoException; +import com.facebook.react.ReactActivity; +import com.facebook.react.ReactActivityDelegate; +import com.facebook.react.ReactRootView; + +public class MainActivity extends ReactActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(null); + + try { + Os.setenv("EXTERNAL_STORAGE", getExternalFilesDir(null).getAbsolutePath(), true); + System.loadLibrary("indy"); + } catch (ErrnoException e) { + e.printStackTrace(); + } + } + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + @Override + protected String getMainComponentName() { + return "PersonalCredentialManager"; + } + + /** + * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and + * you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer + * (Paper). + */ + @Override + protected ReactActivityDelegate createReactActivityDelegate() { + return new MainActivityDelegate(this, getMainComponentName()); + } + + public static class MainActivityDelegate extends ReactActivityDelegate { + public MainActivityDelegate(ReactActivity activity, String mainComponentName) { + super(activity, mainComponentName); + } + + @Override + protected ReactRootView createRootView() { + ReactRootView reactRootView = new ReactRootView(getContext()); + // If you opted-in for the New Architecture, we enable the Fabric Renderer. + reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED); + return reactRootView; + } + + @Override + protected boolean isConcurrentRootEnabled() { + // If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18). + // More on this on https://reactjs.org/blog/2022/03/29/react-v18.html + return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + } + } +} diff --git a/android/app/src/main/java/eu/gaiax/difs/pcm/MainApplication.java b/android/app/src/main/java/eu/gaiax/difs/pcm/MainApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..a8d267703dbfabd921b8f3c7aa68eb076e65899e --- /dev/null +++ b/android/app/src/main/java/eu/gaiax/difs/pcm/MainApplication.java @@ -0,0 +1,91 @@ +package eu.gaiax.difs.pcm; + +import android.app.Application; +import android.content.Context; +import com.facebook.react.PackageList; +import com.facebook.react.ReactApplication; +import com.facebook.react.ReactInstanceManager; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.config.ReactFeatureFlags; +import com.facebook.soloader.SoLoader; +import eu.gaiax.difs.pcm.newarchitecture.MainApplicationReactNativeHost; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +public class MainApplication extends Application implements ReactApplication { + + private final ReactNativeHost mReactNativeHost = + new ReactNativeHost(this) { + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List<ReactPackage> getPackages() { + @SuppressWarnings("UnnecessaryLocalVariable") + List<ReactPackage> packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + return packages; + } + + @Override + protected String getJSMainModuleName() { + return "index"; + } + }; + + private final ReactNativeHost mNewArchitectureNativeHost = + new MainApplicationReactNativeHost(this); + + @Override + public ReactNativeHost getReactNativeHost() { + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + return mNewArchitectureNativeHost; + } else { + return mReactNativeHost; + } + } + + @Override + public void onCreate() { + super.onCreate(); + // If you opted-in for the New Architecture, we enable the TurboModule system + ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + SoLoader.init(this, /* native exopackage */ false); + initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + } + + /** + * Loads Flipper in React Native templates. Call this in the onCreate method with something like + * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + * + * @param context + * @param reactInstanceManager + */ + private static void initializeFlipper( + Context context, ReactInstanceManager reactInstanceManager) { + if (BuildConfig.DEBUG) { + try { + /* + We use reflection here to pick up the class that initializes Flipper, + since Flipper library is not available in release mode + */ + Class<?> aClass = Class.forName("eu.gaiax.difs.pcm.ReactNativeFlipper"); + aClass + .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) + .invoke(null, context, reactInstanceManager); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } +} diff --git a/android/app/src/main/java/eu/gaiax/difs/pcm/newarchitecture/MainApplicationReactNativeHost.java b/android/app/src/main/java/eu/gaiax/difs/pcm/newarchitecture/MainApplicationReactNativeHost.java new file mode 100644 index 0000000000000000000000000000000000000000..959460f4edb7fbd9965a80e86965f30a598a4c87 --- /dev/null +++ b/android/app/src/main/java/eu/gaiax/difs/pcm/newarchitecture/MainApplicationReactNativeHost.java @@ -0,0 +1,116 @@ +package eu.gaiax.difs.pcm.newarchitecture; + +import android.app.Application; +import androidx.annotation.NonNull; +import com.facebook.react.PackageList; +import com.facebook.react.ReactInstanceManager; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.ReactPackageTurboModuleManagerDelegate; +import com.facebook.react.bridge.JSIModulePackage; +import com.facebook.react.bridge.JSIModuleProvider; +import com.facebook.react.bridge.JSIModuleSpec; +import com.facebook.react.bridge.JSIModuleType; +import com.facebook.react.bridge.JavaScriptContextHolder; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.UIManager; +import com.facebook.react.fabric.ComponentFactory; +import com.facebook.react.fabric.CoreComponentsRegistry; +import com.facebook.react.fabric.FabricJSIModuleProvider; +import com.facebook.react.fabric.ReactNativeConfig; +import com.facebook.react.uimanager.ViewManagerRegistry; +import eu.gaiax.difs.pcm.BuildConfig; +import eu.gaiax.difs.pcm.newarchitecture.components.MainComponentsRegistry; +import eu.gaiax.difs.pcm.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate; +import java.util.ArrayList; +import java.util.List; + +/** + * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both + * TurboModule delegates and the Fabric Renderer. + * + * <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the + * `newArchEnabled` property). Is ignored otherwise. + */ +public class MainApplicationReactNativeHost extends ReactNativeHost { + public MainApplicationReactNativeHost(Application application) { + super(application); + } + + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List<ReactPackage> getPackages() { + List<ReactPackage> packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + // TurboModules must also be loaded here providing a valid TurboReactPackage implementation: + // packages.add(new TurboReactPackage() { ... }); + // If you have custom Fabric Components, their ViewManagers should also be loaded here + // inside a ReactPackage. + return packages; + } + + @Override + protected String getJSMainModuleName() { + return "index"; + } + + @NonNull + @Override + protected ReactPackageTurboModuleManagerDelegate.Builder + getReactPackageTurboModuleManagerDelegateBuilder() { + // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary + // for the new architecture and to use TurboModules correctly. + return new MainApplicationTurboModuleManagerDelegate.Builder(); + } + + @Override + protected JSIModulePackage getJSIModulePackage() { + return new JSIModulePackage() { + @Override + public List<JSIModuleSpec> getJSIModules( + final ReactApplicationContext reactApplicationContext, + final JavaScriptContextHolder jsContext) { + final List<JSIModuleSpec> specs = new ArrayList<>(); + + // Here we provide a new JSIModuleSpec that will be responsible of providing the + // custom Fabric Components. + specs.add( + new JSIModuleSpec() { + @Override + public JSIModuleType getJSIModuleType() { + return JSIModuleType.UIManager; + } + + @Override + public JSIModuleProvider<UIManager> getJSIModuleProvider() { + final ComponentFactory componentFactory = new ComponentFactory(); + CoreComponentsRegistry.register(componentFactory); + + // Here we register a Components Registry. + // The one that is generated with the template contains no components + // and just provides you the one from React Native core. + MainComponentsRegistry.register(componentFactory); + + final ReactInstanceManager reactInstanceManager = getReactInstanceManager(); + + ViewManagerRegistry viewManagerRegistry = + new ViewManagerRegistry( + reactInstanceManager.getOrCreateViewManagers(reactApplicationContext)); + + return new FabricJSIModuleProvider( + reactApplicationContext, + componentFactory, + ReactNativeConfig.DEFAULT_CONFIG, + viewManagerRegistry); + } + }); + return specs; + } + }; + } +} diff --git a/android/app/src/main/java/eu/gaiax/difs/pcm/newarchitecture/components/MainComponentsRegistry.java b/android/app/src/main/java/eu/gaiax/difs/pcm/newarchitecture/components/MainComponentsRegistry.java new file mode 100644 index 0000000000000000000000000000000000000000..ed375a8acd1b2b85a332f4e304cbd6416c6f43fc --- /dev/null +++ b/android/app/src/main/java/eu/gaiax/difs/pcm/newarchitecture/components/MainComponentsRegistry.java @@ -0,0 +1,36 @@ +package eu.gaiax.difs.pcm.newarchitecture.components; + +import com.facebook.jni.HybridData; +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.fabric.ComponentFactory; +import com.facebook.soloader.SoLoader; + +/** + * Class responsible to load the custom Fabric Components. This class has native methods and needs a + * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ + * folder for you). + * + * <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the + * `newArchEnabled` property). Is ignored otherwise. + */ +@DoNotStrip +public class MainComponentsRegistry { + static { + SoLoader.loadLibrary("fabricjni"); + } + + @DoNotStrip private final HybridData mHybridData; + + @DoNotStrip + private native HybridData initHybrid(ComponentFactory componentFactory); + + @DoNotStrip + private MainComponentsRegistry(ComponentFactory componentFactory) { + mHybridData = initHybrid(componentFactory); + } + + @DoNotStrip + public static MainComponentsRegistry register(ComponentFactory componentFactory) { + return new MainComponentsRegistry(componentFactory); + } +} diff --git a/android/app/src/main/java/eu/gaiax/difs/pcm/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java b/android/app/src/main/java/eu/gaiax/difs/pcm/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java new file mode 100644 index 0000000000000000000000000000000000000000..720a8e383a18d620d6f1e96dc3c4bb4a88ec88bd --- /dev/null +++ b/android/app/src/main/java/eu/gaiax/difs/pcm/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java @@ -0,0 +1,48 @@ +package eu.gaiax.difs.pcm.newarchitecture.modules; + +import com.facebook.jni.HybridData; +import com.facebook.react.ReactPackage; +import com.facebook.react.ReactPackageTurboModuleManagerDelegate; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.soloader.SoLoader; +import java.util.List; + +/** + * Class responsible to load the TurboModules. This class has native methods and needs a + * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ + * folder for you). + * + * <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the + * `newArchEnabled` property). Is ignored otherwise. + */ +public class MainApplicationTurboModuleManagerDelegate + extends ReactPackageTurboModuleManagerDelegate { + + private static volatile boolean sIsSoLibraryLoaded; + + protected MainApplicationTurboModuleManagerDelegate( + ReactApplicationContext reactApplicationContext, List<ReactPackage> packages) { + super(reactApplicationContext, packages); + } + + protected native HybridData initHybrid(); + + native boolean canCreateTurboModule(String moduleName); + + public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder { + protected MainApplicationTurboModuleManagerDelegate build( + ReactApplicationContext context, List<ReactPackage> packages) { + return new MainApplicationTurboModuleManagerDelegate(context, packages); + } + } + + @Override + protected synchronized void maybeLoadOtherSoLibraries() { + if (!sIsSoLibraryLoaded) { + // If you change the name of your application .so file in the Android.mk file, + // make sure you update the name here as well. + SoLoader.loadLibrary("eu.gaiax.difs.pcm_appmodules"); + sIsSoLibraryLoaded = true; + } + } +} diff --git a/android/app/src/main/jni/CMakeLists.txt b/android/app/src/main/jni/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..49e836702f22b9905488eaf5f8cb52699228595c --- /dev/null +++ b/android/app/src/main/jni/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.13) + +# Define the library name here. +project(eu.gaiax.difs.pcm_appmodules) + +# This file includes all the necessary to let you build your application with the New Architecture. +include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake) diff --git a/android/app/src/main/jni/MainApplicationModuleProvider.cpp b/android/app/src/main/jni/MainApplicationModuleProvider.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26162dd872338a5f64ad34d87bdfd7e71a5d5eed --- /dev/null +++ b/android/app/src/main/jni/MainApplicationModuleProvider.cpp @@ -0,0 +1,32 @@ +#include "MainApplicationModuleProvider.h" + +#include <rncli.h> +#include <rncore.h> + +namespace facebook { +namespace react { + +std::shared_ptr<TurboModule> MainApplicationModuleProvider( + const std::string &moduleName, + const JavaTurboModule::InitParams ¶ms) { + // Here you can provide your own module provider for TurboModules coming from + // either your application or from external libraries. The approach to follow + // is similar to the following (for a library called `samplelibrary`: + // + // auto module = samplelibrary_ModuleProvider(moduleName, params); + // if (module != nullptr) { + // return module; + // } + // return rncore_ModuleProvider(moduleName, params); + + // Module providers autolinked by RN CLI + auto rncli_module = rncli_ModuleProvider(moduleName, params); + if (rncli_module != nullptr) { + return rncli_module; + } + + return rncore_ModuleProvider(moduleName, params); +} + +} // namespace react +} // namespace facebook diff --git a/android/app/src/main/jni/MainApplicationModuleProvider.h b/android/app/src/main/jni/MainApplicationModuleProvider.h new file mode 100644 index 0000000000000000000000000000000000000000..b38ccf53fd49bfbfe14f423c78c2356ecddf8145 --- /dev/null +++ b/android/app/src/main/jni/MainApplicationModuleProvider.h @@ -0,0 +1,16 @@ +#pragma once + +#include <memory> +#include <string> + +#include <ReactCommon/JavaTurboModule.h> + +namespace facebook { +namespace react { + +std::shared_ptr<TurboModule> MainApplicationModuleProvider( + const std::string &moduleName, + const JavaTurboModule::InitParams ¶ms); + +} // namespace react +} // namespace facebook diff --git a/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp b/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5fd688c509d1775f3a0d4142c237494a0960f2d8 --- /dev/null +++ b/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp @@ -0,0 +1,45 @@ +#include "MainApplicationTurboModuleManagerDelegate.h" +#include "MainApplicationModuleProvider.h" + +namespace facebook { +namespace react { + +jni::local_ref<MainApplicationTurboModuleManagerDelegate::jhybriddata> +MainApplicationTurboModuleManagerDelegate::initHybrid( + jni::alias_ref<jhybridobject>) { + return makeCxxInstance(); +} + +void MainApplicationTurboModuleManagerDelegate::registerNatives() { + registerHybrid({ + makeNativeMethod( + "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid), + makeNativeMethod( + "canCreateTurboModule", + MainApplicationTurboModuleManagerDelegate::canCreateTurboModule), + }); +} + +std::shared_ptr<TurboModule> +MainApplicationTurboModuleManagerDelegate::getTurboModule( + const std::string &name, + const std::shared_ptr<CallInvoker> &jsInvoker) { + // Not implemented yet: provide pure-C++ NativeModules here. + return nullptr; +} + +std::shared_ptr<TurboModule> +MainApplicationTurboModuleManagerDelegate::getTurboModule( + const std::string &name, + const JavaTurboModule::InitParams ¶ms) { + return MainApplicationModuleProvider(name, params); +} + +bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule( + const std::string &name) { + return getTurboModule(name, nullptr) != nullptr || + getTurboModule(name, {.moduleName = name}) != nullptr; +} + +} // namespace react +} // namespace facebook diff --git a/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h b/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h new file mode 100644 index 0000000000000000000000000000000000000000..8a1afeed4d1a6ffbd940987eb3f0976430654d38 --- /dev/null +++ b/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h @@ -0,0 +1,38 @@ +#include <memory> +#include <string> + +#include <ReactCommon/TurboModuleManagerDelegate.h> +#include <fbjni/fbjni.h> + +namespace facebook { +namespace react { + +class MainApplicationTurboModuleManagerDelegate + : public jni::HybridClass< + MainApplicationTurboModuleManagerDelegate, + TurboModuleManagerDelegate> { + public: + // Adapt it to the package you used for your Java class. + static constexpr auto kJavaDescriptor = + "Leu/gaiax/difs/pcm/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;"; + + static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject>); + + static void registerNatives(); + + std::shared_ptr<TurboModule> getTurboModule( + const std::string &name, + const std::shared_ptr<CallInvoker> &jsInvoker) override; + std::shared_ptr<TurboModule> getTurboModule( + const std::string &name, + const JavaTurboModule::InitParams ¶ms) override; + + /** + * Test-only method. Allows user to verify whether a TurboModule can be + * created by instances of this class. + */ + bool canCreateTurboModule(const std::string &name); +}; + +} // namespace react +} // namespace facebook diff --git a/android/app/src/main/jni/MainComponentsRegistry.cpp b/android/app/src/main/jni/MainComponentsRegistry.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54f598a486ade2637323369975872064245704fc --- /dev/null +++ b/android/app/src/main/jni/MainComponentsRegistry.cpp @@ -0,0 +1,65 @@ +#include "MainComponentsRegistry.h" + +#include <CoreComponentsRegistry.h> +#include <fbjni/fbjni.h> +#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h> +#include <react/renderer/components/rncore/ComponentDescriptors.h> +#include <rncli.h> + +namespace facebook { +namespace react { + +MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {} + +std::shared_ptr<ComponentDescriptorProviderRegistry const> +MainComponentsRegistry::sharedProviderRegistry() { + auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry(); + + // Autolinked providers registered by RN CLI + rncli_registerProviders(providerRegistry); + + // Custom Fabric Components go here. You can register custom + // components coming from your App or from 3rd party libraries here. + // + // providerRegistry->add(concreteComponentDescriptorProvider< + // AocViewerComponentDescriptor>()); + return providerRegistry; +} + +jni::local_ref<MainComponentsRegistry::jhybriddata> +MainComponentsRegistry::initHybrid( + jni::alias_ref<jclass>, + ComponentFactory *delegate) { + auto instance = makeCxxInstance(delegate); + + auto buildRegistryFunction = + [](EventDispatcher::Weak const &eventDispatcher, + ContextContainer::Shared const &contextContainer) + -> ComponentDescriptorRegistry::Shared { + auto registry = MainComponentsRegistry::sharedProviderRegistry() + ->createComponentDescriptorRegistry( + {eventDispatcher, contextContainer}); + + auto mutableRegistry = + std::const_pointer_cast<ComponentDescriptorRegistry>(registry); + + mutableRegistry->setFallbackComponentDescriptor( + std::make_shared<UnimplementedNativeViewComponentDescriptor>( + ComponentDescriptorParameters{ + eventDispatcher, contextContainer, nullptr})); + + return registry; + }; + + delegate->buildRegistryFunction = buildRegistryFunction; + return instance; +} + +void MainComponentsRegistry::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid), + }); +} + +} // namespace react +} // namespace facebook diff --git a/android/app/src/main/jni/MainComponentsRegistry.h b/android/app/src/main/jni/MainComponentsRegistry.h new file mode 100644 index 0000000000000000000000000000000000000000..28c461f57614fba109788a110298b3994fbf402a --- /dev/null +++ b/android/app/src/main/jni/MainComponentsRegistry.h @@ -0,0 +1,32 @@ +#pragma once + +#include <ComponentFactory.h> +#include <fbjni/fbjni.h> +#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h> +#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h> + +namespace facebook { +namespace react { + +class MainComponentsRegistry + : public facebook::jni::HybridClass<MainComponentsRegistry> { + public: + // Adapt it to the package you used for your Java class. + constexpr static auto kJavaDescriptor = + "Leu/gaiax/difs/pcm/newarchitecture/components/MainComponentsRegistry;"; + + static void registerNatives(); + + MainComponentsRegistry(ComponentFactory *delegate); + + private: + static std::shared_ptr<ComponentDescriptorProviderRegistry const> + sharedProviderRegistry(); + + static jni::local_ref<jhybriddata> initHybrid( + jni::alias_ref<jclass>, + ComponentFactory *delegate); +}; + +} // namespace react +} // namespace facebook diff --git a/android/app/src/main/jni/OnLoad.cpp b/android/app/src/main/jni/OnLoad.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c569b6e865dab50c7ee59cc2ac0ebe898c802c55 --- /dev/null +++ b/android/app/src/main/jni/OnLoad.cpp @@ -0,0 +1,11 @@ +#include <fbjni/fbjni.h> +#include "MainApplicationTurboModuleManagerDelegate.h" +#include "MainComponentsRegistry.h" + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { + return facebook::jni::initialize(vm, [] { + facebook::react::MainApplicationTurboModuleManagerDelegate:: + registerNatives(); + facebook::react::MainComponentsRegistry::registerNatives(); + }); +} diff --git a/android/app/src/main/jniLibs/arm64-v8a/libindy.so b/android/app/src/main/jniLibs/arm64-v8a/libindy.so new file mode 100755 index 0000000000000000000000000000000000000000..aa860e1e52a7da5fc2fca7e067748a9b2961e642 Binary files /dev/null and b/android/app/src/main/jniLibs/arm64-v8a/libindy.so differ diff --git a/android/app/src/main/jniLibs/arm64-v8a/libjnidispatch.so b/android/app/src/main/jniLibs/arm64-v8a/libjnidispatch.so new file mode 100644 index 0000000000000000000000000000000000000000..61553b215288a844ef4ebb18d74d97eec20b32d6 Binary files /dev/null and b/android/app/src/main/jniLibs/arm64-v8a/libjnidispatch.so differ diff --git a/android/app/src/main/jniLibs/armeabi-v7a/libindy.so b/android/app/src/main/jniLibs/armeabi-v7a/libindy.so new file mode 100755 index 0000000000000000000000000000000000000000..a03b93164c92a4546e9235256c9822a714f90175 Binary files /dev/null and b/android/app/src/main/jniLibs/armeabi-v7a/libindy.so differ diff --git a/android/app/src/main/jniLibs/armeabi-v7a/libjnidispatch.so b/android/app/src/main/jniLibs/armeabi-v7a/libjnidispatch.so new file mode 100644 index 0000000000000000000000000000000000000000..06834819147f9bcdb9c67188592c0795e9e3a124 Binary files /dev/null and b/android/app/src/main/jniLibs/armeabi-v7a/libjnidispatch.so differ diff --git a/android/app/src/main/jniLibs/x86/libindy.so b/android/app/src/main/jniLibs/x86/libindy.so new file mode 100755 index 0000000000000000000000000000000000000000..91a2804fb55d6ae7a4fca51109ec90eca544c789 Binary files /dev/null and b/android/app/src/main/jniLibs/x86/libindy.so differ diff --git a/android/app/src/main/jniLibs/x86/libjnidispatch.so b/android/app/src/main/jniLibs/x86/libjnidispatch.so new file mode 100644 index 0000000000000000000000000000000000000000..8587fdfcd679f0c4443978d90722b514bc5b1781 Binary files /dev/null and b/android/app/src/main/jniLibs/x86/libjnidispatch.so differ diff --git a/android/app/src/main/jniLibs/x86_64/libindy.so b/android/app/src/main/jniLibs/x86_64/libindy.so new file mode 100755 index 0000000000000000000000000000000000000000..1cc0634f8ebf98345d8543b72a31d58f58652305 Binary files /dev/null and b/android/app/src/main/jniLibs/x86_64/libindy.so differ diff --git a/android/app/src/main/jniLibs/x86_64/libjnidispatch.so b/android/app/src/main/jniLibs/x86_64/libjnidispatch.so new file mode 100644 index 0000000000000000000000000000000000000000..e3475dce90a3c300c6fc67c390fc0718576ae78f Binary files /dev/null and b/android/app/src/main/jniLibs/x86_64/libjnidispatch.so differ diff --git a/android/app/src/main/res/layout/launch_screen.xml b/android/app/src/main/res/layout/launch_screen.xml new file mode 100644 index 0000000000000000000000000000000000000000..876940694869e7073edc94cba54c180c4cd32f51 --- /dev/null +++ b/android/app/src/main/res/layout/launch_screen.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <ImageView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:scaleType="fitXY" + android:src="@mipmap/gaiax" /> + +</LinearLayout> \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/gaiax.png b/android/app/src/main/res/mipmap-hdpi/gaiax.png new file mode 100644 index 0000000000000000000000000000000000000000..9d4122e8d2f731fce22d7dcc651ec5cc3ce3c6af Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/gaiax.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..92563b40342ac1d2d933ae58d2049d8cbd52af9f Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..2bd6fa7aee86ddc8628c83cd71bff56f46871e2f Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..2bd6fa7aee86ddc8628c83cd71bff56f46871e2f Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-ldpi/gaiax.png b/android/app/src/main/res/mipmap-ldpi/gaiax.png new file mode 100644 index 0000000000000000000000000000000000000000..9d4122e8d2f731fce22d7dcc651ec5cc3ce3c6af Binary files /dev/null and b/android/app/src/main/res/mipmap-ldpi/gaiax.png differ diff --git a/android/app/src/main/res/mipmap-ldpi/ic_launcher.png b/android/app/src/main/res/mipmap-ldpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..92563b40342ac1d2d933ae58d2049d8cbd52af9f Binary files /dev/null and b/android/app/src/main/res/mipmap-ldpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-ldpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-ldpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..2bd6fa7aee86ddc8628c83cd71bff56f46871e2f Binary files /dev/null and b/android/app/src/main/res/mipmap-ldpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-ldpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-ldpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..2bd6fa7aee86ddc8628c83cd71bff56f46871e2f Binary files /dev/null and b/android/app/src/main/res/mipmap-ldpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/gaiax.png b/android/app/src/main/res/mipmap-mdpi/gaiax.png new file mode 100644 index 0000000000000000000000000000000000000000..9d4122e8d2f731fce22d7dcc651ec5cc3ce3c6af Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/gaiax.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..59c92fdd1588a40cf997669359be8138817e794f Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..1a76fb4255568852c961a3101615fbb37f3f8225 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..1a76fb4255568852c961a3101615fbb37f3f8225 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/gaiax.png b/android/app/src/main/res/mipmap-xhdpi/gaiax.png new file mode 100644 index 0000000000000000000000000000000000000000..9d4122e8d2f731fce22d7dcc651ec5cc3ce3c6af Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/gaiax.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..18e1accd2b7ad11960e337335185ec0d142f4691 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..84c5bbd61db6665ef22c78b94077e080b606eede Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..84c5bbd61db6665ef22c78b94077e080b606eede Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/gaiax.png b/android/app/src/main/res/mipmap-xxhdpi/gaiax.png new file mode 100644 index 0000000000000000000000000000000000000000..9d4122e8d2f731fce22d7dcc651ec5cc3ce3c6af Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/gaiax.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7772ea1836b39b60e9597abd283cbe4ff27cb597 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..b18b8d491c071540d4149f2ba922ca6c63d4f6e2 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..b18b8d491c071540d4149f2ba922ca6c63d4f6e2 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/gaiax.png b/android/app/src/main/res/mipmap-xxxhdpi/gaiax.png new file mode 100644 index 0000000000000000000000000000000000000000..9d4122e8d2f731fce22d7dcc651ec5cc3ce3c6af Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/gaiax.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..f45772dab9deb6c1b2b30c4ad9c814cfd61a2457 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..79eadd287182b72aaafdb61d42bc121bb949f8e2 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..79eadd287182b72aaafdb61d42bc121bb949f8e2 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..f5668e997b0339ca12eb94b58752b2d431038be5 --- /dev/null +++ b/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ +<resources> + <string name="app_name">PCM</string> +</resources> diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000000000000000000000000000000000000..24bc061368750ca8dedb8779fc7eceb59c2025e5 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ +<resources> + + <!-- Base application theme. --> + <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar"> + <!-- Customize your theme here. --> + </style> + +</resources> diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..af9807ff99b8a9a9f5bd53308d6ce07465b8ba4f --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,58 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext { + versionCode = 2 + versionName = "0.0.1" + buildToolsVersion = "31.0.0" + minSdkVersion = 26 + compileSdkVersion = 31 + targetSdkVersion = 31 + VisionCameraCodeScanner_targetSdkVersion = 31 + VisionCameraCodeScanner_compileSdkVersion = 31 + + if (System.properties['os.arch'] == "aarch64") { + // For M1 Users we need to use the NDK 24 which added support for aarch64 + ndkVersion = "24.0.8215888" + } else { + // Otherwise we default to the side-by-side NDK version from AGP. + ndkVersion = "21.4.7075529" + } + } + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle:7.2.1") + classpath("com.facebook.react:react-native-gradle-plugin") + classpath("de.undercouch:gradle-download-task:5.0.1") + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url("$rootDir/../node_modules/react-native/android") + } + maven { + // Android JSC is installed from npm + url("$rootDir/../node_modules/jsc-android/dist") + } + maven { + url 'https://repo.sovrin.org/repository/maven-public' + } + mavenCentral { + // We don't want to fetch react-native from Maven Central as there are + // older versions over there. + content { + excludeGroup "com.facebook.react" + } + } + google() + maven { url 'https://www.jitpack.io' } + } +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000000000000000000000000000000000000..6194c5e3a89aea94a0368b7d1bf0dbfe6aa6dcfe --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,45 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + +# Version of flipper SDK to use with React Native +FLIPPER_VERSION=0.125.0 + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew <task> -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=false + +MYAPP_UPLOAD_STORE_FILE=my-upload-key.keystore +MYAPP_UPLOAD_KEY_ALIAS=my-key-alias +MYAPP_UPLOAD_STORE_PASSWORD=123456 +MYAPP_UPLOAD_KEY_PASSWORD=123456 diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..41d9927a4d4fb3f96a785543079b8df6723c946b Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..8fad3f5a98bf4a104de5df8345c1f59f984cba8a --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 0000000000000000000000000000000000000000..1b6c787337ffb79f0e3cf8b1e9f00f680a959de1 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 0000000000000000000000000000000000000000..107acd32c4e687021ef32db511e8a206129b88ec --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000000000000000000000000000000000000..1260ed48bb34511ebee7c631f9784b9bce5b78f4 --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,21 @@ +rootProject.name = 'PersonalCredentialManager' +apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) + +include ':reactnativeaesgcmcrypto' +project(':reactnativeaesgcmcrypto').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-aes-gcm-crypto/android') + +include ':react-native-rsa-native' +project(':react-native-rsa-native').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-rsa-native/android') + +include ':app' +includeBuild('../node_modules/react-native-gradle-plugin') + +if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") { + include(":ReactAndroid") + project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid') + include(":ReactAndroid:hermes-engine") + project(":ReactAndroid:hermes-engine").projectDir = file('../node_modules/react-native/ReactAndroid/hermes-engine') +} + +include ':react-native-config' +project(':react-native-config').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-config/android') diff --git a/app.json b/app.json new file mode 100644 index 0000000000000000000000000000000000000000..2e5122c984b9146efad89422ebea5a96c2715a27 --- /dev/null +++ b/app.json @@ -0,0 +1,4 @@ +{ + "name": "PersonalCredentialManager", + "displayName": "PCM" +} diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000000000000000000000000000000000000..e421fed01269110f7121fcb313533bc89267229b --- /dev/null +++ b/babel.config.js @@ -0,0 +1,12 @@ +module.exports = { + presets: ['module:metro-react-native-babel-preset'], + plugins: [ + ['import', { libraryName: '@ant-design/react-native' }], + [ + 'react-native-reanimated/plugin', + { + globals: ['__scanCodes'], + }, + ], + ], +}; diff --git a/configs/ledgers/indy/bcovrin-test/genesis-file.ts b/configs/ledgers/indy/bcovrin-test/genesis-file.ts new file mode 100644 index 0000000000000000000000000000000000000000..7c301db44b053d72786a106d9c300550200dccb5 --- /dev/null +++ b/configs/ledgers/indy/bcovrin-test/genesis-file.ts @@ -0,0 +1,4 @@ +export default `{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node1","blskey":"4N8aUNHSgjQVgkpm8nhNEfDf6txHznoYREg9kirmJrkivgL4oSEimFF6nsQ6M41QvhM2Z33nves5vfSn9n1UwNFJBYtWVnHYMATn76vLuL3zU88KyeAYcHfsih3He6UHcXDxcaecHVz6jhCYz1P2UZn2bDVruL5wXpehgBfBaLKm3Ba","blskey_pop":"RahHYiCvoNCtPTrVtP7nMC5eTYrsUA8WjXbdhNc8debh1agE9bGiJxWBXYNFbnJXoXhWFMvyqhqhRoq737YQemH5ik9oL7R4NTTCz2LEZhkgLJzB3QRQqJyBNyv7acbdHrAT8nQ9UkLbaVL9NBpnWXBTw4LEMePaSHEw66RzPNdAX1","client_ip":"138.197.138.255","client_port":9702,"node_ip":"138.197.138.255","node_port":9701,"services":["VALIDATOR"]},"dest":"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv"},"metadata":{"from":"Th7MpTaRZVRYnPiabds81Y"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node2","blskey":"37rAPpXVoxzKhz7d9gkUe52XuXryuLXoM6P6LbWDB7LSbG62Lsb33sfG7zqS8TK1MXwuCHj1FKNzVpsnafmqLG1vXN88rt38mNFs9TENzm4QHdBzsvCuoBnPH7rpYYDo9DZNJePaDvRvqJKByCabubJz3XXKbEeshzpz4Ma5QYpJqjk","blskey_pop":"Qr658mWZ2YC8JXGXwMDQTzuZCWF7NK9EwxphGmcBvCh6ybUuLxbG65nsX4JvD4SPNtkJ2w9ug1yLTj6fgmuDg41TgECXjLCij3RMsV8CwewBVgVN67wsA45DFWvqvLtu4rjNnE9JbdFTc1Z4WCPA3Xan44K1HoHAq9EVeaRYs8zoF5","client_ip":"138.197.138.255","client_port":9704,"node_ip":"138.197.138.255","node_port":9703,"services":["VALIDATOR"]},"dest":"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb"},"metadata":{"from":"EbP4aYNeTHL6q385GuVpRV"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node3","blskey":"3WFpdbg7C5cnLYZwFZevJqhubkFALBfCBBok15GdrKMUhUjGsk3jV6QKj6MZgEubF7oqCafxNdkm7eswgA4sdKTRc82tLGzZBd6vNqU8dupzup6uYUf32KTHTPQbuUM8Yk4QFXjEf2Usu2TJcNkdgpyeUSX42u5LqdDDpNSWUK5deC5","blskey_pop":"QwDeb2CkNSx6r8QC8vGQK3GRv7Yndn84TGNijX8YXHPiagXajyfTjoR87rXUu4G4QLk2cF8NNyqWiYMus1623dELWwx57rLCFqGh7N4ZRbGDRP4fnVcaKg1BcUxQ866Ven4gw8y4N56S5HzxXNBZtLYmhGHvDtk6PFkFwCvxYrNYjh","client_ip":"138.197.138.255","client_port":9706,"node_ip":"138.197.138.255","node_port":9705,"services":["VALIDATOR"]},"dest":"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya"},"metadata":{"from":"4cU41vWW82ArfxJxHkzXPG"},"type":"0"},"txnMetadata":{"seqNo":3,"txnId":"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node4","blskey":"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw","blskey_pop":"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP","client_ip":"138.197.138.255","client_port":9708,"node_ip":"138.197.138.255","node_port":9707,"services":["VALIDATOR"]},"dest":"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA"},"metadata":{"from":"TWwCRQRZ2ZHMJFn9TzLp7W"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008"},"ver":"1"}`; diff --git a/configs/ledgers/indy/bcovrin-test/pool-config.ts b/configs/ledgers/indy/bcovrin-test/pool-config.ts new file mode 100644 index 0000000000000000000000000000000000000000..cf7d2ace8c299d815a581b7c6f396fb32d8207ea --- /dev/null +++ b/configs/ledgers/indy/bcovrin-test/pool-config.ts @@ -0,0 +1,11 @@ +import { IndyPoolConfig } from '@aries-framework/core/build/modules/ledger/IndyPool'; + +import genesisFile from './genesis-file'; + +const config: IndyPoolConfig = { + id: 'BCovrinTest', + genesisTransactions: genesisFile, + isProduction: false, +}; + +export default config; diff --git a/configs/ledgers/indy/green-light-bcovrin/genesis-file.ts b/configs/ledgers/indy/green-light-bcovrin/genesis-file.ts new file mode 100644 index 0000000000000000000000000000000000000000..df9a0ccb79f3f81a28da70268417c82a22a1a367 --- /dev/null +++ b/configs/ledgers/indy/green-light-bcovrin/genesis-file.ts @@ -0,0 +1,4 @@ +export default `{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node1","blskey":"4N8aUNHSgjQVgkpm8nhNEfDf6txHznoYREg9kirmJrkivgL4oSEimFF6nsQ6M41QvhM2Z33nves5vfSn9n1UwNFJBYtWVnHYMATn76vLuL3zU88KyeAYcHfsih3He6UHcXDxcaecHVz6jhCYz1P2UZn2bDVruL5wXpehgBfBaLKm3Ba","blskey_pop":"RahHYiCvoNCtPTrVtP7nMC5eTYrsUA8WjXbdhNc8debh1agE9bGiJxWBXYNFbnJXoXhWFMvyqhqhRoq737YQemH5ik9oL7R4NTTCz2LEZhkgLJzB3QRQqJyBNyv7acbdHrAT8nQ9UkLbaVL9NBpnWXBTw4LEMePaSHEw66RzPNdAX1","client_ip":"138.197.161.221","client_port":9702,"node_ip":"138.197.161.221","node_port":9701,"services":["VALIDATOR"]},"dest":"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv"},"metadata":{"from":"Th7MpTaRZVRYnPiabds81Y"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node2","blskey":"37rAPpXVoxzKhz7d9gkUe52XuXryuLXoM6P6LbWDB7LSbG62Lsb33sfG7zqS8TK1MXwuCHj1FKNzVpsnafmqLG1vXN88rt38mNFs9TENzm4QHdBzsvCuoBnPH7rpYYDo9DZNJePaDvRvqJKByCabubJz3XXKbEeshzpz4Ma5QYpJqjk","blskey_pop":"Qr658mWZ2YC8JXGXwMDQTzuZCWF7NK9EwxphGmcBvCh6ybUuLxbG65nsX4JvD4SPNtkJ2w9ug1yLTj6fgmuDg41TgECXjLCij3RMsV8CwewBVgVN67wsA45DFWvqvLtu4rjNnE9JbdFTc1Z4WCPA3Xan44K1HoHAq9EVeaRYs8zoF5","client_ip":"138.197.161.221","client_port":9704,"node_ip":"138.197.161.221","node_port":9703,"services":["VALIDATOR"]},"dest":"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb"},"metadata":{"from":"EbP4aYNeTHL6q385GuVpRV"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node3","blskey":"3WFpdbg7C5cnLYZwFZevJqhubkFALBfCBBok15GdrKMUhUjGsk3jV6QKj6MZgEubF7oqCafxNdkm7eswgA4sdKTRc82tLGzZBd6vNqU8dupzup6uYUf32KTHTPQbuUM8Yk4QFXjEf2Usu2TJcNkdgpyeUSX42u5LqdDDpNSWUK5deC5","blskey_pop":"QwDeb2CkNSx6r8QC8vGQK3GRv7Yndn84TGNijX8YXHPiagXajyfTjoR87rXUu4G4QLk2cF8NNyqWiYMus1623dELWwx57rLCFqGh7N4ZRbGDRP4fnVcaKg1BcUxQ866Ven4gw8y4N56S5HzxXNBZtLYmhGHvDtk6PFkFwCvxYrNYjh","client_ip":"138.197.161.221","client_port":9706,"node_ip":"138.197.161.221","node_port":9705,"services":["VALIDATOR"]},"dest":"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya"},"metadata":{"from":"4cU41vWW82ArfxJxHkzXPG"},"type":"0"},"txnMetadata":{"seqNo":3,"txnId":"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node4","blskey":"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw","blskey_pop":"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP","client_ip":"138.197.161.221","client_port":9708,"node_ip":"138.197.161.221","node_port":9707,"services":["VALIDATOR"]},"dest":"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA"},"metadata":{"from":"TWwCRQRZ2ZHMJFn9TzLp7W"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008"},"ver":"1"}`; diff --git a/configs/ledgers/indy/green-light-bcovrin/pool-config.ts b/configs/ledgers/indy/green-light-bcovrin/pool-config.ts new file mode 100644 index 0000000000000000000000000000000000000000..8a0f09d49582e65db985acd72a079ed850092dbc --- /dev/null +++ b/configs/ledgers/indy/green-light-bcovrin/pool-config.ts @@ -0,0 +1,11 @@ +import { IndyPoolConfig } from '@aries-framework/core/build/modules/ledger/IndyPool'; + +import genesisFile from './genesis-file'; + +const config: IndyPoolConfig = { + id: 'GreenLightBcovrin', + genesisTransactions: genesisFile, + isProduction: false, +}; + +export default config; diff --git a/configs/ledgers/indy/idunion-bosch/genesis-file.ts b/configs/ledgers/indy/idunion-bosch/genesis-file.ts new file mode 100644 index 0000000000000000000000000000000000000000..ab4cf6511b7a68f1f2286eec472c20f68f348d1a --- /dev/null +++ b/configs/ledgers/indy/idunion-bosch/genesis-file.ts @@ -0,0 +1,4 @@ +export default `{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node1","blskey":"4N8aUNHSgjQVgkpm8nhNEfDf6txHznoYREg9kirmJrkivgL4oSEimFF6nsQ6M41QvhM2Z33nves5vfSn9n1UwNFJBYtWVnHYMATn76vLuL3zU88KyeAYcHfsih3He6UHcXDxcaecHVz6jhCYz1P2UZn2bDVruL5wXpehgBfBaLKm3Ba","blskey_pop":"RahHYiCvoNCtPTrVtP7nMC5eTYrsUA8WjXbdhNc8debh1agE9bGiJxWBXYNFbnJXoXhWFMvyqhqhRoq737YQemH5ik9oL7R4NTTCz2LEZhkgLJzB3QRQqJyBNyv7acbdHrAT8nQ9UkLbaVL9NBpnWXBTw4LEMePaSHEw66RzPNdAX1","client_ip":"40.89.175.63","client_port":9702,"node_ip":"40.89.175.63","node_port":9701,"services":["VALIDATOR"]},"dest":"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv"},"metadata":{"from":"Th7MpTaRZVRYnPiabds81Y"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node2","blskey":"37rAPpXVoxzKhz7d9gkUe52XuXryuLXoM6P6LbWDB7LSbG62Lsb33sfG7zqS8TK1MXwuCHj1FKNzVpsnafmqLG1vXN88rt38mNFs9TENzm4QHdBzsvCuoBnPH7rpYYDo9DZNJePaDvRvqJKByCabubJz3XXKbEeshzpz4Ma5QYpJqjk","blskey_pop":"Qr658mWZ2YC8JXGXwMDQTzuZCWF7NK9EwxphGmcBvCh6ybUuLxbG65nsX4JvD4SPNtkJ2w9ug1yLTj6fgmuDg41TgECXjLCij3RMsV8CwewBVgVN67wsA45DFWvqvLtu4rjNnE9JbdFTc1Z4WCPA3Xan44K1HoHAq9EVeaRYs8zoF5","client_ip":"40.89.175.63","client_port":9704,"node_ip":"40.89.175.63","node_port":9703,"services":["VALIDATOR"]},"dest":"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb"},"metadata":{"from":"EbP4aYNeTHL6q385GuVpRV"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node3","blskey":"3WFpdbg7C5cnLYZwFZevJqhubkFALBfCBBok15GdrKMUhUjGsk3jV6QKj6MZgEubF7oqCafxNdkm7eswgA4sdKTRc82tLGzZBd6vNqU8dupzup6uYUf32KTHTPQbuUM8Yk4QFXjEf2Usu2TJcNkdgpyeUSX42u5LqdDDpNSWUK5deC5","blskey_pop":"QwDeb2CkNSx6r8QC8vGQK3GRv7Yndn84TGNijX8YXHPiagXajyfTjoR87rXUu4G4QLk2cF8NNyqWiYMus1623dELWwx57rLCFqGh7N4ZRbGDRP4fnVcaKg1BcUxQ866Ven4gw8y4N56S5HzxXNBZtLYmhGHvDtk6PFkFwCvxYrNYjh","client_ip":"40.89.175.63","client_port":9706,"node_ip":"40.89.175.63","node_port":9705,"services":["VALIDATOR"]},"dest":"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya"},"metadata":{"from":"4cU41vWW82ArfxJxHkzXPG"},"type":"0"},"txnMetadata":{"seqNo":3,"txnId":"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node4","blskey":"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw","blskey_pop":"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP","client_ip":"40.89.175.63","client_port":9708,"node_ip":"40.89.175.63","node_port":9707,"services":["VALIDATOR"]},"dest":"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA"},"metadata":{"from":"TWwCRQRZ2ZHMJFn9TzLp7W"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008"},"ver":"1"}`; diff --git a/configs/ledgers/indy/idunion-bosch/pool-config.ts b/configs/ledgers/indy/idunion-bosch/pool-config.ts new file mode 100644 index 0000000000000000000000000000000000000000..cd1f1b728ea1bc04ac7c3d2c5e35a80704900fe4 --- /dev/null +++ b/configs/ledgers/indy/idunion-bosch/pool-config.ts @@ -0,0 +1,11 @@ +import { IndyPoolConfig } from '@aries-framework/core/build/modules/ledger/IndyPool'; + +import genesisFile from './genesis-file'; + +const config: IndyPoolConfig = { + id: 'IDunionBosch', + genesisTransactions: genesisFile, + isProduction: false, +}; + +export default config; diff --git a/configs/ledgers/indy/idunion-test/genesis-file.ts b/configs/ledgers/indy/idunion-test/genesis-file.ts new file mode 100644 index 0000000000000000000000000000000000000000..a0b5241c76dd047e2bec44de9bb5d59e978875b3 --- /dev/null +++ b/configs/ledgers/indy/idunion-test/genesis-file.ts @@ -0,0 +1,9 @@ +export default `{"reqSignature":{},"txn":{"data":{"data":{"alias":"MainIncubator","blskey":"14MPfxHnRvCL5dnbpD3SjxekAGnKyjkmifDFLnMJAvHcvEAarDLWX6KawhubPujSmmUMqRmQfPQzBambrdUqBGgHDryDS6Aj8BioWRwZkyTcH1zzkVQ7vZjE5S6ri5epkiS1VkVX42Z22z4cohdHVuKTgeQB5mjAwi55xNeRxpxhrNb","blskey_pop":"QoqRe3vMPr5Bt1qHDstYewWkxb5VEdugnvumLCWpkZAeUpdqjjaSTSKKJtT7U7aCe8CmShGSdCZFWs9hcpmMSGfMnmon7R99UTJj4jEr48smyxo1UpBcgooznc8N8USkZ8hSec3bRbN9y6NppuaFzfgt1WmJ3cdFi9L1Wbj1fNs5CK","client_ip":"35.207.81.15","client_port":"9702","node_ip":"35.207.81.15","node_port":"9701","services":["VALIDATOR"]},"dest":"EQ2oCtWpMdUCzKgQ2hvbyQ2i6VyJuQF9LcpHRfiah6rW"},"metadata":{"from":"2MZYuPv2Km7Q1eD4GCsSb6"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"0a35c047f19448f12a0c2961d8e3085140b8149d87291acbdaf56ed956900d48"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"tubzecm","blskey":"3Zpdx6LMWPdybnQKPq62S3TaWUhwypr7RV2BBFkeFigjKuue7KJ7rh5w1gZY9qgugww9vZnpURLSjBuTonJpfyfN5nn2ofwFQQa3viiT77hhFf6kQqoMH53f66ZfBNWU2LzphQikXsma9zjZWALMtMsNWx7ftNZ8yzMrZpf1X6VqYX5","blskey_pop":"RbPQSMsV8iuxNXVFNEUPvb6k1wQe1rxaXroMMkpHTstiiJfCApER38jW79Ew1yrnt5ndz7wJeDRU7CkLNzJ6pEZaRYjLzhZL2shRgyaGqnMqkxvD1ewxNMSz7cSgBSChwUgLBxsms5iDyshwAM5dx8B1GayMyATcFxAdgCRiDv3EHm","client_ip":"141.23.35.186","client_port":"9702","node_ip":"141.23.35.186","node_port":"9701","services":["VALIDATOR"]},"dest":"Ddqm5GATTcEb5hrgMBbVL8w6R6mtTHjUpdpyCeWg3pVS"},"metadata":{"from":"JhyMn8Nn3xy2zsXjPaPu3B"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"e2f9efff1bfef015098ae299a665154fa39a898a5071d0af03c7f2311fe8577f"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Bosch","blskey":"WNBd2CBPJMSaBan72XhY1v5XSkExX7GRCqxM7WNSfveoDcHSLXbQ59K1mWAcgoJZd89NaYa5pLb7N3AcLxSNUj8HJXwjd8jMECvX9iiGESVn2ssb8VFX2TDE2RBVC4nU5jDexzpwqnhJk27ev64J8H21SpbBecbHvP49ZQpRVaq6WL","blskey_pop":"QkmprUBuiKmoUGkFLGVbozGfiFRcNnjfyL8Zg4VfjPpUT7i8YPoPExbDhFxUKofgavJ1ZEsG8VZECpNDC75anfTfivsuMBr5w4a31ZKuqwCscAXzmeTPrkTPo7QLXuYc1SQMTjrm8YEkBYzHuXktJzkJXvLERnoAdLWqPqMyYWUzGo","client_ip":"20.52.38.11","client_port":"9702","node_ip":"20.52.38.11","node_port":"9701","services":["VALIDATOR"]},"dest":"9oB1GdDzFyn4p1Pb6BotYuSXozdwDWXW5s2jRjg86KpZ"},"metadata":{"from":"K3Bf63TUe3nTj1SKuQVZ2e"},"type":"0"},"txnMetadata":{"seqNo":3,"txnId":"865ce0cf621e0d5f9c2dccb9e5079733a83d80ea2e814d32c3300bc2c2755b7b"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Bundesdruckerei","blskey":"ypA6Fzaqx3WgyeBWjahz94ZYMXdyRuC9v4NruuNVehxt3VgyRPnBeiRxNcXuN9x7PgD4Y585EkAZMSEUrpego9H75hiNppqFTBppPh8cMisKKxW2qZmePnwM8AR2MkWfsytP64AcZFxhXQw1Sx9SeDZwEZAhzNFg2CGY1Ywf1VyCkB","blskey_pop":"RBGcyWimwwZhTtJrW8f3br5osAFkSbpEsEyR3UtX3Lq82kFCA2yEn1H2HHYapmQ5KQ42ZAE2srfjYa5ihZGgs96oxAHpKdkPWX4rXcnxyFcbPihDCmqY9YvnR6DrzfLMc9ew5ac6xeQfiefiEZGMENFsehLPtiQyohSzZBFEqB8Tdy","client_ip":"193.28.64.163","client_port":"9702","node_ip":"193.28.64.163","node_port":"9701","services":["VALIDATOR"]},"dest":"8CMjmTUmAULZ25XUmLx3Gd2HX8bKf5uwPvF6oxcv3qfz"},"metadata":{"from":"BdrsFY8EFRNDwQpdKb6f5k"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"8406be5a8bde1145f642a9955a80475c7256a9957b3a984c74ca6a8484f9c0f7"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"esatus_AG","blskey":"2L1Egvidsqj44HosrLCUXDgCLC9g9SwU6XD3wY6XiudgWajEM6zpxVzvyagB4SY8ZgWinAnBRjQv2zdsUHrfdFCfEm6csB9sgG2HryqcLgLUtskSrctSEd7AgYTAE3mcYdZmGAACTQgkskkcNkmFh61Rh9uADyP6xoDoT7PXPgmW5Wx","blskey_pop":"RGtbexx5BMxZhr7hnEaPqPGvEQANjZozqdZk5fDJBXRLcnQwnii4YYefpvSCpBLnsy6iTBQTFQpUfs2gvwM92Cyi1J2SivPJF1hKr7FmiZbWuoR7dRpdJGFYw7avU12T6yYFjiwLieJ5LsHVyosHVLj1XDrrHKBBsEUFRHJCp8GBhZ","client_ip":"194.110.133.202","client_port":"9702","node_ip":"194.110.133.202","node_port":"9701","services":["VALIDATOR"]},"dest":"BQ1YEL8oXssKxaF4ZVwZCCk3px4BxDjVim3pFG8Y5Gk6"},"metadata":{"from":"PbvRAYyQfi1GS8ioCNZXTp"},"type":"0"},"txnMetadata":{"seqNo":5,"txnId":"b26a8b1ec76a165330faf13f0b9565f8167211c37d83845226b7986dd0f624e3"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"Commerzbank","blskey":"4Y5aB7ywZaw2Vqg63Mb2XiaQbaxCwUS1zSkczTzTS6dg8FCzqJdmvkU9PucY4A144VjoubvQLS6Cxvt9ZRcWr1NTdUX6f3LYqCyp1W5vFWn2s8pLSirimxGcZuhNp8XYRJGYsMjH781cgoriEB1R6GBxP6u7PamA7zybYqdng5GKcr7","blskey_pop":"RVYvd1Pf6wGyEXTsGQpHtV3M3vzCvXernbdLxa6ngBrkShDhR1TbbzrHsNsbkoZeimdtcJ2quNqux57k3RbyuggB86kCjH7asmkKp7w8Pa4Pzrzy3hyvTQ8qwNiZZmNb3CEXNWFctkXBeLeB6ip5z3TWoYDx7LWBC3b5KLtjbhgN6K","client_ip":"20.52.50.218","client_port":"9702","node_ip":"20.52.50.218","node_port":"9701","services":["VALIDATOR"]},"dest":"5coVfaQRWkjapQTxvJutUciSHLRwzk8yuR2CngufN78T"},"metadata":{"from":"9UMDJTxi6RHtGmYdUJr6iR"},"type":"0"},"txnMetadata":{"seqNo":6,"txnId":"f630e5a6719c639039ad66be6e3ed30b54ace3bb2ef5eaa84e7f3d5ee2b5e2a9"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"DeutscheBahn","blskey":"4nJSdxfx7MPdBH1ioFy4dk9hDgRV1D21JTKbWCkWAtvqwnMNfLgg8qrXhuNf5Ux8owBjMZPPQMiYsgwd7UbBTKmi8P4Hef6udXDq7p2EYGcM512JRRi8Z6igeijcRinnzLTM3Bso7xjJngaohMTZ2yNdRmB5WuyJKbZfr5qRbzEReMd","blskey_pop":"RZTAfkfry51g41qCVbYkKbsE9Nw16hx9k6Dnnun4vJbFLbtnyvuRfWHUVrjvfdbq48MRRRyY3miVGgxdugKMCSA9LxzmXJSCJG2Hxck2xsiFKUzznsqF6DWtGfo639WNz4Qk5xCvbDxhmmRYmZ3mJhUg8X3MEoCkQCsqAEi2oAQg9D","client_ip":"81.200.193.232","client_port":"9702","node_ip":"81.200.193.232","node_port":"9701","services":["VALIDATOR"]},"dest":"Ahb65rjbm94hNxM8jynTbWBMZyNmuuvtvsCAyntKSd3k"},"metadata":{"from":"JoCzEPXHeef6zYoXGx87aZ"},"type":"0"},"txnMetadata":{"seqNo":7,"txnId":"58b0a0cb860a20b41082d4d1b2419867156ca7aea3a0bdf2bdb318a270a6a367"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"siemens","blskey":"2DpsFyaZFWpHChf9pbHiNtZx9ze7RfzRhdnaAp3ZHZmLrZivyyMcnM7xhyKoc9LkZCAd1kuQHtfYNtAW4yY4DsoDQnXzKmWkLbRRwA8aNjxFK1uGP8npAXpVNTnWieNuQpj9EgQSDU5WJYR3SDgrV7sx51vwsa6ggkhAJNENyMRqZHY","blskey_pop":"RCx6QwyeaLpAHaD3AGgGZSNqyxQLsaAa9H2kKoQAMpQXkh9XZfsZtGbZTvPK2ZTXHMVvUyfCmWvaM8YxuJGRZ7QQTFAg9ECaqLPKexrp3P4huHMMs7nzj992ECVnuu66Dppbn6AEEF46NQXcXEDsEquHEHhuzD1JV9oAvcqaPGu2Hm","client_ip":"3.120.0.165","client_port":"9702","node_ip":"3.120.0.165","node_port":"9701","services":["VALIDATOR"]},"dest":"9XrquGpmLMXq5v5UuVLmPdZ5nPVDbdtMLSEWzE9Phm8H"},"metadata":{"from":"GewebF4Nq1LLRw5gwX1Dwv"},"type":"0"},"txnMetadata":{"seqNo":8,"txnId":"30e363d3e8c59f2c1319f8d73d48e3ad26db5e087951a4d7ab809c6f5401aea8"},"ver":"1"} +{"reqSignature":{},"txn":{"data":{"data":{"alias":"T-Labs","blskey":"qLCWHTGoARJxSM8yCj3zDnx4gUDaTwMoX2v9enhYTg1FRLN2Wcu9Dg91hrHKcrp1RiJMphAvRYbpXZLYN7AGiu3vCfiTfSuwM9qEWmhRe23KF67kQyRDNDVa8PZjPL7xhtsQRkJ5Gox3H6TmC8H2JFYBZ5JwcbieGfZMzMF5eDku1c","blskey_pop":"RPrk8q1pZAQhzEM8KhPTp9BKixe2PrJFJFhEV6M3uq8qDrUvpbZEWJUvm9iPnfh5cXrXTojNFo472XrVtbcxtnRwxz9Xrm2dfbARu5Gjxd5s9TGn145iKuzEEFrVt2usyf18E8XudD4ZwPovVVQgp9seKStnfYPKVTYTp726Ps5fQs","client_ip":"185.27.183.119","client_port":"9702","node_ip":"185.27.183.119","node_port":"9701","services":["VALIDATOR"]},"dest":"9k4Sjfxg2XqP2GcVAPHFuVJeY2bLbSUCPcVty6FRLzbY"},"metadata":{"from":"Ta94MpvKrQwTtiNMegQMvs"},"type":"0"},"txnMetadata":{"seqNo":9,"txnId":"1626d887a6323309883ab5fb8381f6176ab5e4ff4502389bb2978daee076cc39"},"ver":"1"}`; diff --git a/configs/ledgers/indy/idunion-test/pool-config.ts b/configs/ledgers/indy/idunion-test/pool-config.ts new file mode 100644 index 0000000000000000000000000000000000000000..7dcaf9f0cf204d2981f8b647cdadc71f6b3e8540 --- /dev/null +++ b/configs/ledgers/indy/idunion-test/pool-config.ts @@ -0,0 +1,11 @@ +import { IndyPoolConfig } from '@aries-framework/core/build/modules/ledger/IndyPool'; + +import genesisFile from './genesis-file'; + +const config: IndyPoolConfig = { + id: 'IDunionTest', + genesisTransactions: genesisFile, + isProduction: false, +}; + +export default config; diff --git a/configs/ledgers/indy/index.ts b/configs/ledgers/indy/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..6e41a949db5fc0e5a8e2867ce8ab8d70dba46fc2 --- /dev/null +++ b/configs/ledgers/indy/index.ts @@ -0,0 +1,6 @@ +import BCovrinTest from './bcovrin-test/pool-config'; +import IDunionTest from './idunion-test/pool-config'; +import IDunionBosch from './idunion-bosch/pool-config'; +import GreenLightBcovrin from './green-light-bcovrin/pool-config'; + +export default [BCovrinTest, IDunionBosch, IDunionTest, GreenLightBcovrin]; diff --git a/docs/GAIA-X-Overview-blockDiagram.png b/docs/GAIA-X-Overview-blockDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..2d16bb7022b7d67b0aac91af1e414ebc33943623 Binary files /dev/null and b/docs/GAIA-X-Overview-blockDiagram.png differ diff --git a/docs/GAIA-X-PCM-BlockDiagram.png b/docs/GAIA-X-PCM-BlockDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..c99e0c65d2b41b9292e4b2c38a44fae76e2e458e Binary files /dev/null and b/docs/GAIA-X-PCM-BlockDiagram.png differ diff --git a/docs/GAIA-X-PCM.Registration.png b/docs/GAIA-X-PCM.Registration.png new file mode 100644 index 0000000000000000000000000000000000000000..763a81b47ab9d36b06fbb6dadbdb07ab5f87367e Binary files /dev/null and b/docs/GAIA-X-PCM.Registration.png differ diff --git a/docs/PCMUserManual.pdf b/docs/PCMUserManual.pdf new file mode 100644 index 0000000000000000000000000000000000000000..581a7d09232de9df4bc2d75800b53ec09bc77b1d Binary files /dev/null and b/docs/PCMUserManual.pdf differ diff --git a/index.js b/index.js new file mode 100644 index 0000000000000000000000000000000000000000..1164afb708614a05b931aa8f9ed8ea2474585abd --- /dev/null +++ b/index.js @@ -0,0 +1,7 @@ +import { AppRegistry } from 'react-native'; +import App from './App'; +import { name as appName } from './app.json'; +import 'intl-pluralrules'; +import 'react-native-reanimated'; + +AppRegistry.registerComponent(appName, () => App); diff --git a/ios/.xcode.env b/ios/.xcode.env new file mode 100644 index 0000000000000000000000000000000000000000..3d5782c71568d32eec2fe71b034efcde053305f9 --- /dev/null +++ b/ios/.xcode.env @@ -0,0 +1,11 @@ +# This `.xcode.env` file is versioned and is used to source the environment +# used when running script phases inside Xcode. +# To customize your local environment, you can create an `.xcode.env.local` +# file that is not versioned. + +# NODE_BINARY variable contains the PATH to the node executable. +# +# Customize the NODE_BINARY variable here. +# For example, to use nvm with brew, add the following line +# . "$(brew --prefix nvm)/nvm.sh" --no-use +export NODE_BINARY=$(command -v node) diff --git a/ios/PersonalCredentialManager.xcodeproj/project.pbxproj b/ios/PersonalCredentialManager.xcodeproj/project.pbxproj new file mode 100644 index 0000000000000000000000000000000000000000..a9096e88540850cd823b7dcd41f4772ca3b1e969 --- /dev/null +++ b/ios/PersonalCredentialManager.xcodeproj/project.pbxproj @@ -0,0 +1,789 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 00E356F31AD99517003FC87E /* PersonalCredentialManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* PersonalCredentialManagerTests.m */; }; + 0C80B921A6F3F58F76C31292 /* libPods-PersonalCredentialManager.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-PersonalCredentialManager.a */; }; + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 45C868E35EB249A298F128C4 /* TitilliumWeb-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34AF55BBFD0A4B44AB7DBE8B /* TitilliumWeb-Regular.ttf */; }; + 7699B88040F8A987B510C191 /* libPods-PersonalCredentialManager-PersonalCredentialManagerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-PersonalCredentialManager-PersonalCredentialManagerTests.a */; }; + 7BA9C4503A9B4E6D8132A42C /* antoutline.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1035D30535C64F25B3B6EF5A /* antoutline.ttf */; }; + 7D1BB02F91E54B0297C6C67D /* TitilliumWeb-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EF7CF2CD60574ADD8E0AFAD9 /* TitilliumWeb-SemiBold.ttf */; }; + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; + B89EBF06EC1149C6A7A0B91E /* antfill.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E329655F7F8247C4AA1220C1 /* antfill.ttf */; }; + BD211E3DFD554642A53882D4 /* TitilliumWeb-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = CDFADC7BA94A49E8BD7C41B7 /* TitilliumWeb-Light.ttf */; }; + FE5B187A27BB9E9700E39BA4 /* Indy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FE5B187927BB9E9700E39BA4 /* Indy.framework */; platformFilter = ios; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 13B07F861A680F5B00A75B9A; + remoteInfo = PersonalCredentialManager; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 00E356EE1AD99517003FC87E /* PersonalCredentialManagerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PersonalCredentialManagerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + 00E356F21AD99517003FC87E /* PersonalCredentialManagerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PersonalCredentialManagerTests.m; sourceTree = "<group>"; }; + 03B2BF05DABF47D5860D21AA /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = "<group>"; }; + 1035D30535C64F25B3B6EF5A /* antoutline.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = antoutline.ttf; path = "../node_modules/@ant-design/icons-react-native/fonts/antoutline.ttf"; sourceTree = "<group>"; }; + 13B07F961A680F5B00A75B9A /* PersonalCredentialManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PersonalCredentialManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = PersonalCredentialManager/AppDelegate.h; sourceTree = "<group>"; }; + 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = PersonalCredentialManager/AppDelegate.mm; sourceTree = "<group>"; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = PersonalCredentialManager/Images.xcassets; sourceTree = "<group>"; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = PersonalCredentialManager/Info.plist; sourceTree = "<group>"; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = PersonalCredentialManager/main.m; sourceTree = "<group>"; }; + 186C1DA476994FEBB2A0FB48 /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = "<group>"; }; + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-PersonalCredentialManager-PersonalCredentialManagerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PersonalCredentialManager-PersonalCredentialManagerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1C10BC92F9394E6486AF27F0 /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialCommunityIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"; sourceTree = "<group>"; }; + 22925182963E43AABAFC6DE1 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Ionicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = "<group>"; }; + 34AF55BBFD0A4B44AB7DBE8B /* TitilliumWeb-Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "TitilliumWeb-Regular.ttf"; path = "../src/assets/fonts/TitilliumWeb-Regular.ttf"; sourceTree = "<group>"; }; + 3B4392A12AC88292D35C810B /* Pods-PersonalCredentialManager.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PersonalCredentialManager.debug.xcconfig"; path = "Target Support Files/Pods-PersonalCredentialManager/Pods-PersonalCredentialManager.debug.xcconfig"; sourceTree = "<group>"; }; + 3CF1B5970F764466AA5B532C /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = "<group>"; }; + 42E4200B2E44481BAB5535A4 /* Foundation.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Foundation.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Foundation.ttf"; sourceTree = "<group>"; }; + 56C06A0D868D49B28D5EE2DB /* MaterialIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf"; sourceTree = "<group>"; }; + 5709B34CF0A7D63546082F79 /* Pods-PersonalCredentialManager.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PersonalCredentialManager.release.xcconfig"; path = "Target Support Files/Pods-PersonalCredentialManager/Pods-PersonalCredentialManager.release.xcconfig"; sourceTree = "<group>"; }; + 5B7EB9410499542E8C5724F5 /* Pods-PersonalCredentialManager-PersonalCredentialManagerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PersonalCredentialManager-PersonalCredentialManagerTests.debug.xcconfig"; path = "Target Support Files/Pods-PersonalCredentialManager-PersonalCredentialManagerTests/Pods-PersonalCredentialManager-PersonalCredentialManagerTests.debug.xcconfig"; sourceTree = "<group>"; }; + 5DCACB8F33CDC322A6C60F78 /* libPods-PersonalCredentialManager.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PersonalCredentialManager.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = PersonalCredentialManager/LaunchScreen.storyboard; sourceTree = "<group>"; }; + 89C6BE57DB24E9ADA2F236DE /* Pods-PersonalCredentialManager-PersonalCredentialManagerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PersonalCredentialManager-PersonalCredentialManagerTests.release.xcconfig"; path = "Target Support Files/Pods-PersonalCredentialManager-PersonalCredentialManagerTests/Pods-PersonalCredentialManager-PersonalCredentialManagerTests.release.xcconfig"; sourceTree = "<group>"; }; + A20DE76CC5794D40B00346D9 /* FontAwesome5_Brands.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Brands.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf"; sourceTree = "<group>"; }; + A78E245B6B044A8193B781D6 /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = "<group>"; }; + B472E6D57FD947A8A95A3D9A /* AntDesign.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = AntDesign.ttf; path = "../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf"; sourceTree = "<group>"; }; + B490EA60295A4303AC328F11 /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = "<group>"; }; + B511E1FF35794D8384EEB91B /* FontAwesome5_Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Regular.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf"; sourceTree = "<group>"; }; + BA90FEF376154B83B2B914CF /* FontAwesome.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf"; sourceTree = "<group>"; }; + C1ED828338A44A30836FBA4C /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = "<group>"; }; + CDFADC7BA94A49E8BD7C41B7 /* TitilliumWeb-Light.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "TitilliumWeb-Light.ttf"; path = "../src/assets/fonts/TitilliumWeb-Light.ttf"; sourceTree = "<group>"; }; + D3FD2AA880404D3FBE7B5654 /* Fontisto.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Fontisto.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf"; sourceTree = "<group>"; }; + E329655F7F8247C4AA1220C1 /* antfill.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = antfill.ttf; path = "../node_modules/@ant-design/icons-react-native/fonts/antfill.ttf"; sourceTree = "<group>"; }; + ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; + EDCB2B460766460B81E66726 /* FontAwesome5_Solid.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Solid.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf"; sourceTree = "<group>"; }; + EF7CF2CD60574ADD8E0AFAD9 /* TitilliumWeb-SemiBold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "TitilliumWeb-SemiBold.ttf"; path = "../src/assets/fonts/TitilliumWeb-SemiBold.ttf"; sourceTree = "<group>"; }; + FE5B187927BB9E9700E39BA4 /* Indy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Indy.framework; path = Pods/Frameworks/Indy.framework; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 00E356EB1AD99517003FC87E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7699B88040F8A987B510C191 /* libPods-PersonalCredentialManager-PersonalCredentialManagerTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FE5B187A27BB9E9700E39BA4 /* Indy.framework in Frameworks */, + 0C80B921A6F3F58F76C31292 /* libPods-PersonalCredentialManager.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00E356EF1AD99517003FC87E /* PersonalCredentialManagerTests */ = { + isa = PBXGroup; + children = ( + 00E356F21AD99517003FC87E /* PersonalCredentialManagerTests.m */, + 00E356F01AD99517003FC87E /* Supporting Files */, + ); + path = PersonalCredentialManagerTests; + sourceTree = "<group>"; + }; + 00E356F01AD99517003FC87E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 00E356F11AD99517003FC87E /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = "<group>"; + }; + 13B07FAE1A68108700A75B9A /* PersonalCredentialManager */ = { + isa = PBXGroup; + children = ( + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.mm */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, + 13B07FB71A68108700A75B9A /* main.m */, + ); + name = PersonalCredentialManager; + sourceTree = "<group>"; + }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + FE5B187927BB9E9700E39BA4 /* Indy.framework */, + ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + 5DCACB8F33CDC322A6C60F78 /* libPods-PersonalCredentialManager.a */, + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-PersonalCredentialManager-PersonalCredentialManagerTests.a */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + 50EEF0ED1A1541FF830C1A70 /* Resources */ = { + isa = PBXGroup; + children = ( + B472E6D57FD947A8A95A3D9A /* AntDesign.ttf */, + 03B2BF05DABF47D5860D21AA /* Entypo.ttf */, + A78E245B6B044A8193B781D6 /* EvilIcons.ttf */, + C1ED828338A44A30836FBA4C /* Feather.ttf */, + BA90FEF376154B83B2B914CF /* FontAwesome.ttf */, + A20DE76CC5794D40B00346D9 /* FontAwesome5_Brands.ttf */, + B511E1FF35794D8384EEB91B /* FontAwesome5_Regular.ttf */, + EDCB2B460766460B81E66726 /* FontAwesome5_Solid.ttf */, + D3FD2AA880404D3FBE7B5654 /* Fontisto.ttf */, + 42E4200B2E44481BAB5535A4 /* Foundation.ttf */, + 22925182963E43AABAFC6DE1 /* Ionicons.ttf */, + 1C10BC92F9394E6486AF27F0 /* MaterialCommunityIcons.ttf */, + 56C06A0D868D49B28D5EE2DB /* MaterialIcons.ttf */, + 186C1DA476994FEBB2A0FB48 /* Octicons.ttf */, + B490EA60295A4303AC328F11 /* SimpleLineIcons.ttf */, + 3CF1B5970F764466AA5B532C /* Zocial.ttf */, + E329655F7F8247C4AA1220C1 /* antfill.ttf */, + 1035D30535C64F25B3B6EF5A /* antoutline.ttf */, + CDFADC7BA94A49E8BD7C41B7 /* TitilliumWeb-Light.ttf */, + 34AF55BBFD0A4B44AB7DBE8B /* TitilliumWeb-Regular.ttf */, + EF7CF2CD60574ADD8E0AFAD9 /* TitilliumWeb-SemiBold.ttf */, + ); + name = Resources; + sourceTree = "<group>"; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + ); + name = Libraries; + sourceTree = "<group>"; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* PersonalCredentialManager */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 00E356EF1AD99517003FC87E /* PersonalCredentialManagerTests */, + 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, + BBD78D7AC51CEA395F1C20DB /* Pods */, + 50EEF0ED1A1541FF830C1A70 /* Resources */, + ); + indentWidth = 2; + sourceTree = "<group>"; + tabWidth = 2; + usesTabs = 0; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* PersonalCredentialManager.app */, + 00E356EE1AD99517003FC87E /* PersonalCredentialManagerTests.xctest */, + ); + name = Products; + sourceTree = "<group>"; + }; + BBD78D7AC51CEA395F1C20DB /* Pods */ = { + isa = PBXGroup; + children = ( + 3B4392A12AC88292D35C810B /* Pods-PersonalCredentialManager.debug.xcconfig */, + 5709B34CF0A7D63546082F79 /* Pods-PersonalCredentialManager.release.xcconfig */, + 5B7EB9410499542E8C5724F5 /* Pods-PersonalCredentialManager-PersonalCredentialManagerTests.debug.xcconfig */, + 89C6BE57DB24E9ADA2F236DE /* Pods-PersonalCredentialManager-PersonalCredentialManagerTests.release.xcconfig */, + ); + path = Pods; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 00E356ED1AD99517003FC87E /* PersonalCredentialManagerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "PersonalCredentialManagerTests" */; + buildPhases = ( + A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */, + 00E356EA1AD99517003FC87E /* Sources */, + 00E356EB1AD99517003FC87E /* Frameworks */, + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */, + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 00E356F51AD99517003FC87E /* PBXTargetDependency */, + ); + name = PersonalCredentialManagerTests; + productName = PersonalCredentialManagerTests; + productReference = 00E356EE1AD99517003FC87E /* PersonalCredentialManagerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 13B07F861A680F5B00A75B9A /* PersonalCredentialManager */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "PersonalCredentialManager" */; + buildPhases = ( + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, + FD10A7F022414F080027D42C /* Start Packager */, + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PersonalCredentialManager; + productName = PersonalCredentialManager; + productReference = 13B07F961A680F5B00A75B9A /* PersonalCredentialManager.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1210; + TargetAttributes = { + 00E356ED1AD99517003FC87E = { + CreatedOnToolsVersion = 6.2; + TestTargetID = 13B07F861A680F5B00A75B9A; + }; + 13B07F861A680F5B00A75B9A = { + LastSwiftMigration = 1120; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "PersonalCredentialManager" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* PersonalCredentialManager */, + 00E356ED1AD99517003FC87E /* PersonalCredentialManagerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + B89EBF06EC1149C6A7A0B91E /* antfill.ttf in Resources */, + 7BA9C4503A9B4E6D8132A42C /* antoutline.ttf in Resources */, + BD211E3DFD554642A53882D4 /* TitilliumWeb-Light.ttf in Resources */, + 45C868E35EB249A298F128C4 /* TitilliumWeb-Regular.ttf in Resources */, + 7D1BB02F91E54B0297C6C67D /* TitilliumWeb-SemiBold.ttf in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/.xcode.env", + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; + }; + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager/Pods-PersonalCredentialManager-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager/Pods-PersonalCredentialManager-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager/Pods-PersonalCredentialManager-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-PersonalCredentialManager-PersonalCredentialManagerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-PersonalCredentialManager-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager-PersonalCredentialManagerTests/Pods-PersonalCredentialManager-PersonalCredentialManagerTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager-PersonalCredentialManagerTests/Pods-PersonalCredentialManager-PersonalCredentialManagerTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager-PersonalCredentialManagerTests/Pods-PersonalCredentialManager-PersonalCredentialManagerTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager/Pods-PersonalCredentialManager-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager/Pods-PersonalCredentialManager-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager/Pods-PersonalCredentialManager-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager-PersonalCredentialManagerTests/Pods-PersonalCredentialManager-PersonalCredentialManagerTests-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager-PersonalCredentialManagerTests/Pods-PersonalCredentialManager-PersonalCredentialManagerTests-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PersonalCredentialManager-PersonalCredentialManagerTests/Pods-PersonalCredentialManager-PersonalCredentialManagerTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + FD10A7F022414F080027D42C /* Start Packager */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Start Packager"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 00E356EA1AD99517003FC87E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 00E356F31AD99517003FC87E /* PersonalCredentialManagerTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, + 13B07FC11A68108700A75B9A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 13B07F861A680F5B00A75B9A /* PersonalCredentialManager */; + targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 00E356F61AD99517003FC87E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-PersonalCredentialManager-PersonalCredentialManagerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = PersonalCredentialManagerTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = eu.gaiax.difs.pcm; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PersonalCredentialManager.app/PersonalCredentialManager"; + }; + name = Debug; + }; + 00E356F71AD99517003FC87E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-PersonalCredentialManager-PersonalCredentialManagerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = PersonalCredentialManagerTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = eu.gaiax.difs.pcm; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PersonalCredentialManager.app/PersonalCredentialManager"; + }; + name = Release; + }; + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-PersonalCredentialManager.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 20; + DEVELOPMENT_TEAM = P2KF5SHM9P; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Pods/Frameworks", + ); + INFOPLIST_FILE = PersonalCredentialManager/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 0.0.1; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = eu.gaiax.pcm; + PRODUCT_NAME = PersonalCredentialManager; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-PersonalCredentialManager.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 20; + DEVELOPMENT_TEAM = P2KF5SHM9P; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Pods/Frameworks", + ); + INFOPLIST_FILE = PersonalCredentialManager/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 0.0.1; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = eu.gaiax.pcm; + PRODUCT_NAME = PersonalCredentialManager; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "PersonalCredentialManagerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 00E356F61AD99517003FC87E /* Debug */, + 00E356F71AD99517003FC87E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "PersonalCredentialManager" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "PersonalCredentialManager" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/ios/PersonalCredentialManager.xcodeproj/xcshareddata/xcschemes/PersonalCredentialManager.xcscheme b/ios/PersonalCredentialManager.xcodeproj/xcshareddata/xcschemes/PersonalCredentialManager.xcscheme new file mode 100644 index 0000000000000000000000000000000000000000..f28059725313ed741272b37b968c27b16444d8da --- /dev/null +++ b/ios/PersonalCredentialManager.xcodeproj/xcshareddata/xcschemes/PersonalCredentialManager.xcscheme @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "1210" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + <BuildActionEntries> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "13B07F861A680F5B00A75B9A" + BuildableName = "PersonalCredentialManager.app" + BlueprintName = "PersonalCredentialManager" + ReferencedContainer = "container:PersonalCredentialManager.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + </BuildActionEntries> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES"> + <Testables> + <TestableReference + skipped = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "00E356ED1AD99517003FC87E" + BuildableName = "PersonalCredentialManagerTests.xctest" + BlueprintName = "PersonalCredentialManagerTests" + ReferencedContainer = "container:PersonalCredentialManager.xcodeproj"> + </BuildableReference> + </TestableReference> + </Testables> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "13B07F861A680F5B00A75B9A" + BuildableName = "PersonalCredentialManager.app" + BlueprintName = "PersonalCredentialManager" + ReferencedContainer = "container:PersonalCredentialManager.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + </LaunchAction> + <ProfileAction + buildConfiguration = "Release" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "13B07F861A680F5B00A75B9A" + BuildableName = "PersonalCredentialManager.app" + BlueprintName = "PersonalCredentialManager" + ReferencedContainer = "container:PersonalCredentialManager.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/ios/PersonalCredentialManager.xcworkspace/contents.xcworkspacedata b/ios/PersonalCredentialManager.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000000000000000000000000000000000..c2bcab7816737afb87bcb02d306f60e8c6cbb68d --- /dev/null +++ b/ios/PersonalCredentialManager.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "group:PersonalCredentialManager.xcodeproj"> + </FileRef> + <FileRef + location = "group:Pods/Pods.xcodeproj"> + </FileRef> +</Workspace> diff --git a/ios/PersonalCredentialManager.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/PersonalCredentialManager.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000000000000000000000000000000000..18d981003d68d0546c4804ac2ff47dd97c6e7921 --- /dev/null +++ b/ios/PersonalCredentialManager.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> diff --git a/ios/PersonalCredentialManager/AppDelegate.h b/ios/PersonalCredentialManager/AppDelegate.h new file mode 100644 index 0000000000000000000000000000000000000000..ef1de86a2a80acb9c8c18d0879a7f70d9a191f0f --- /dev/null +++ b/ios/PersonalCredentialManager/AppDelegate.h @@ -0,0 +1,8 @@ +#import <React/RCTBridgeDelegate.h> +#import <UIKit/UIKit.h> + +@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate> + +@property (nonatomic, strong) UIWindow *window; + +@end diff --git a/ios/PersonalCredentialManager/AppDelegate.mm b/ios/PersonalCredentialManager/AppDelegate.mm new file mode 100644 index 0000000000000000000000000000000000000000..61c98aa099cd906d9b147505f18422ea7df0e279 --- /dev/null +++ b/ios/PersonalCredentialManager/AppDelegate.mm @@ -0,0 +1,142 @@ +#import "AppDelegate.h" + +#import <React/RCTBridge.h> +#import <React/RCTBundleURLProvider.h> +#import <React/RCTRootView.h> + +#import <React/RCTAppSetupUtils.h> +#import <React/RCTLinkingManager.h> + +#if RCT_NEW_ARCH_ENABLED +#import <React/CoreModulesPlugins.h> +#import <React/RCTCxxBridgeDelegate.h> +#import <React/RCTFabricSurfaceHostingProxyRootView.h> +#import <React/RCTSurfacePresenter.h> +#import <React/RCTSurfacePresenterBridgeAdapter.h> +#import <ReactCommon/RCTTurboModuleManager.h> + +#import <react/config/ReactNativeConfig.h> + +static NSString *const kRNConcurrentRoot = @"concurrentRoot"; + +@interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate> { + RCTTurboModuleManager *_turboModuleManager; + RCTSurfacePresenterBridgeAdapter *_bridgeAdapter; + std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig; + facebook::react::ContextContainer::Shared _contextContainer; +} +@end +#endif + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + RCTAppSetupPrepareApp(application); + + RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; + +#if RCT_NEW_ARCH_ENABLED + _contextContainer = std::make_shared<facebook::react::ContextContainer const>(); + _reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>(); + _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); + _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer]; + bridge.surfacePresenter = _bridgeAdapter.surfacePresenter; +#endif + + NSDictionary *initProps = [self prepareInitialProps]; + UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"PersonalCredentialManager", initProps); + + if (@available(iOS 13.0, *)) { + rootView.backgroundColor = [UIColor systemBackgroundColor]; + } else { + rootView.backgroundColor = [UIColor whiteColor]; + } + + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + UIViewController *rootViewController = [UIViewController new]; + rootViewController.view = rootView; + self.window.rootViewController = rootViewController; + [self.window makeKeyAndVisible]; + return YES; +} + +/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off. +/// +/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html +/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture). +/// @return: `true` if the `concurrentRoot` feture is enabled. Otherwise, it returns `false`. +- (BOOL)concurrentRootEnabled +{ + // Switch this bool to turn on and off the concurrent root + return true; +} + +- (NSDictionary *)prepareInitialProps +{ + NSMutableDictionary *initProps = [NSMutableDictionary new]; + +#ifdef RCT_NEW_ARCH_ENABLED + initProps[kRNConcurrentRoot] = @([self concurrentRootEnabled]); +#endif + + return initProps; +} + +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge +{ +#if DEBUG + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; +#else + return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; +#endif +} + +#if RCT_NEW_ARCH_ENABLED + +#pragma mark - RCTCxxBridgeDelegate + +- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge +{ + _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge + delegate:self + jsInvoker:bridge.jsCallInvoker]; + return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager); +} + +#pragma mark RCTTurboModuleManagerDelegate + +- (Class)getModuleClassFromName:(const char *)name +{ + return RCTCoreModulesClassProvider(name); +} + +- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name + jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker +{ + return nullptr; +} + +- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name + initParams: + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return nullptr; +} + +- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass +{ + return RCTAppSetupDefaultModuleFromClass(moduleClass); +} + +#endif + +// Add this inside `@implementation AppDelegate` above `@end`: +- (BOOL)application:(UIApplication *)application + openURL:(NSURL *)url + options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options +{ + return [RCTLinkingManager application:application openURL:url options:options]; +} + +@end diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Contents.json b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..e83c3bf5794980102056647dfc71d8d5c07f23ab --- /dev/null +++ b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,128 @@ +{ + "images":[ + { + "idiom":"iphone", + "size":"20x20", + "scale":"2x", + "filename":"Icon-App-20x20@2x.png" + }, + { + "idiom":"iphone", + "size":"20x20", + "scale":"3x", + "filename":"Icon-App-20x20@3x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"1x", + "filename":"Icon-App-29x29@1x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"2x", + "filename":"Icon-App-29x29@2x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"3x", + "filename":"Icon-App-29x29@3x.png" + }, + { + "idiom":"iphone", + "size":"40x40", + "scale":"2x", + "filename":"Icon-App-40x40@2x.png" + }, + { + "idiom":"iphone", + "size":"40x40", + "scale":"3x", + "filename":"Icon-App-40x40@3x.png" + }, + { + "idiom":"iphone", + "size":"60x60", + "scale":"2x", + "filename":"Icon-App-60x60@2x.png" + }, + { + "idiom":"iphone", + "size":"60x60", + "scale":"3x", + "filename":"Icon-App-60x60@3x.png" + }, + { + "idiom":"iphone", + "size":"76x76", + "scale":"2x", + "filename":"Icon-App-76x76@2x.png" + }, + { + "idiom":"ipad", + "size":"20x20", + "scale":"1x", + "filename":"Icon-App-20x20@1x.png" + }, + { + "idiom":"ipad", + "size":"20x20", + "scale":"2x", + "filename":"Icon-App-20x20@2x.png" + }, + { + "idiom":"ipad", + "size":"29x29", + "scale":"1x", + "filename":"Icon-App-29x29@1x.png" + }, + { + "idiom":"ipad", + "size":"29x29", + "scale":"2x", + "filename":"Icon-App-29x29@2x.png" + }, + { + "idiom":"ipad", + "size":"40x40", + "scale":"1x", + "filename":"Icon-App-40x40@1x.png" + }, + { + "idiom":"ipad", + "size":"40x40", + "scale":"2x", + "filename":"Icon-App-40x40@2x.png" + }, + { + "idiom":"ipad", + "size":"76x76", + "scale":"1x", + "filename":"Icon-App-76x76@1x.png" + }, + { + "idiom":"ipad", + "size":"76x76", + "scale":"2x", + "filename":"Icon-App-76x76@2x.png" + }, + { + "idiom":"ipad", + "size":"83.5x83.5", + "scale":"2x", + "filename":"Icon-App-83.5x83.5@2x.png" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "scale" : "1x", + "filename" : "ItunesArtwork@2x.png" + } + ], + "info":{ + "version":1, + "author":"easyappicon" + } +} diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..a9d5712ba5e6a4d014930dcebda4febba36def3d Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ed7a85ee3738988e35845c9727af324a11c2871d Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..3f21b032a9e78ff6e8e98e2ac21b3643b7fff6f8 Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..f42f818735820e52f35bdbe854991512dd4f5eb6 Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9d3cb0a333240ba91c304be12412a3dbdee4e7b1 Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe0736f024e9d505ae0f993d5eb98a68a3bc2e99 Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..ed7a85ee3738988e35845c9727af324a11c2871d Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ee741ed60fcd9c2cee5082d7804301571a9b77ae Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..95e9b89209e51f5b8efd74d18efca93ec9b63831 Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..95e9b89209e51f5b8efd74d18efca93ec9b63831 Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a946b7e91d3dc61f258943c6208e00a168a21b33 Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..07cac0ab2b18c04e545afe1c85ae12fcb1555333 Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..278430dd8ae49ac0c524c303a54a7ca09b295315 Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ce592749aeed7b4abfd1ccb51508ee116259cd2a Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..143527c5a1b15fa6a7badf702aff38828b8e93e3 Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/Contents.json b/ios/PersonalCredentialManager/Images.xcassets/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..2d92bd53fdb2223e4d23bf1fb6c134fe72931116 --- /dev/null +++ b/ios/PersonalCredentialManager/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/Contents.json b/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..216a1d522e3c0defe20b182877b2475fa12031a5 --- /dev/null +++ b/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "splash@1X.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "splash@2X.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "splash@3X.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/splash@1X.png b/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/splash@1X.png new file mode 100644 index 0000000000000000000000000000000000000000..9d4122e8d2f731fce22d7dcc651ec5cc3ce3c6af Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/splash@1X.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/splash@2X.png b/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/splash@2X.png new file mode 100644 index 0000000000000000000000000000000000000000..9d4122e8d2f731fce22d7dcc651ec5cc3ce3c6af Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/splash@2X.png differ diff --git a/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/splash@3X.png b/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/splash@3X.png new file mode 100644 index 0000000000000000000000000000000000000000..9d4122e8d2f731fce22d7dcc651ec5cc3ce3c6af Binary files /dev/null and b/ios/PersonalCredentialManager/Images.xcassets/Launch Screen Icon.imageset/splash@3X.png differ diff --git a/ios/PersonalCredentialManager/Info.plist b/ios/PersonalCredentialManager/Info.plist new file mode 100644 index 0000000000000000000000000000000000000000..0fddbb9a2d53616bfcb28b50bfb073b6046ce92d --- /dev/null +++ b/ios/PersonalCredentialManager/Info.plist @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleDisplayName</key> + <string>PersonalCredentialManager</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>$(MARKETING_VERSION)</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleURLTypes</key> + <array> + <dict> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>CFBundleURLName</key> + <string>gxfspcm</string> + <key>CFBundleURLSchemes</key> + <array> + <string>gxfspcm</string> + </array> + </dict> + </array> + <key>CFBundleVersion</key> + <string>$(CURRENT_PROJECT_VERSION)</string> + <key>ITSAppUsesNonExemptEncryption</key> + <false/> + <key>LSApplicationCategoryType</key> + <string></string> + <key>LSRequiresIPhoneOS</key> + <true/> + <key>LSSupportsOpeningDocumentsInPlace</key> + <true/> + <key>NSAppTransportSecurity</key> + <dict> + <key>NSExceptionDomains</key> + <dict> + <key>localhost</key> + <dict> + <key>NSExceptionAllowsInsecureHTTPLoads</key> + <true/> + </dict> + </dict> + </dict> + <key>NSCameraUsageDescription</key> + <string>$(PRODUCT_NAME) requires access to camera to scan the qrcodes.</string> + <key>NSDocumentsFolderUsageDescription</key> + <string>$(PRODUCT_NAME) requires access to the Document folder to store the backup files</string> + <key>NSFaceIDUsageDescription</key> + <string>$(PRODUCT_NAME) requires access of face id or touch id for app authentication.</string> + <key>NSLocationWhenInUseUsageDescription</key> + <string></string> + <key>NSPhotoLibraryUsageDescription</key> + <string>$(PRODUCT_NAME) requires access to the library to upload your wallet while importing.</string> + <key>UIAppFonts</key> + <array> + <string>AntDesign.ttf</string> + <string>Entypo.ttf</string> + <string>EvilIcons.ttf</string> + <string>Feather.ttf</string> + <string>FontAwesome.ttf</string> + <string>FontAwesome5_Brands.ttf</string> + <string>FontAwesome5_Regular.ttf</string> + <string>FontAwesome5_Solid.ttf</string> + <string>Fontisto.ttf</string> + <string>Foundation.ttf</string> + <string>Ionicons.ttf</string> + <string>MaterialCommunityIcons.ttf</string> + <string>MaterialIcons.ttf</string> + <string>Octicons.ttf</string> + <string>SimpleLineIcons.ttf</string> + <string>Zocial.ttf</string> + <string>antfill.ttf</string> + <string>antoutline.ttf</string> + <string>TitilliumWeb-Light.ttf</string> + <string>TitilliumWeb-Regular.ttf</string> + <string>TitilliumWeb-SemiBold.ttf</string> + </array> + <key>UIApplicationSceneManifest</key> + <dict> + <key>UIApplicationSupportsMultipleScenes</key> + <false/> + </dict> + <key>UIFileSharingEnabled</key> + <true/> + <key>UILaunchStoryboardName</key> + <string>LaunchScreen</string> + <key>UIRequiredDeviceCapabilities</key> + <array> + <string>armv7</string> + </array> + <key>UIRequiresFullScreen</key> + <true/> + <key>UISupportedInterfaceOrientations</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> + <key>UIViewControllerBasedStatusBarAppearance</key> + <false/> +</dict> +</plist> diff --git a/ios/PersonalCredentialManager/LaunchScreen.storyboard b/ios/PersonalCredentialManager/LaunchScreen.storyboard new file mode 100644 index 0000000000000000000000000000000000000000..e1edaa88316d32a993e7c12229070601336b0a7e --- /dev/null +++ b/ios/PersonalCredentialManager/LaunchScreen.storyboard @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Dtp-p8-LvN"> + <device id="retina6_1" orientation="portrait" appearance="light"/> + <dependencies> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/> + <capability name="Safe area layout guides" minToolsVersion="9.0"/> + <capability name="System colors in document resources" minToolsVersion="11.0"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> + </dependencies> + <scenes> + <!--View Controller--> + <scene sceneID="Fnd-62-7zz"> + <objects> + <viewController id="Dtp-p8-LvN" sceneMemberID="viewController"> + <view key="view" contentMode="scaleAspectFit" id="Zpf-HN-ZpS"> + <rect key="frame" x="0.0" y="0.0" width="414" height="896"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <subviews> + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Launch Screen Icon" highlightedImage="Launch Screen Icon" translatesAutoresizingMaskIntoConstraints="NO" id="kqf-jw-L6Y"> + <rect key="frame" x="0.0" y="0.0" width="414" height="896"/> + </imageView> + </subviews> + <viewLayoutGuide key="safeArea" id="bT9-wi-ewf"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <constraints> + <constraint firstItem="bT9-wi-ewf" firstAttribute="trailing" secondItem="kqf-jw-L6Y" secondAttribute="trailing" id="Xfy-gy-31o"/> + <constraint firstItem="kqf-jw-L6Y" firstAttribute="top" secondItem="Zpf-HN-ZpS" secondAttribute="topMargin" constant="-44" id="oC8-CN-1L5"/> + <constraint firstItem="kqf-jw-L6Y" firstAttribute="centerY" secondItem="Zpf-HN-ZpS" secondAttribute="centerY" id="oRc-j0-0xP"/> + <constraint firstItem="kqf-jw-L6Y" firstAttribute="leading" secondItem="Zpf-HN-ZpS" secondAttribute="leading" id="pz5-jo-Uwc"/> + </constraints> + </view> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="Lvb-Jr-bCV" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="0.0" y="0.0"/> + </scene> + </scenes> + <resources> + <image name="Launch Screen Icon" width="180" height="320"/> + <systemColor name="systemBackgroundColor"> + <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + </systemColor> + </resources> +</document> diff --git a/ios/PersonalCredentialManager/main.m b/ios/PersonalCredentialManager/main.m new file mode 100644 index 0000000000000000000000000000000000000000..d645c7246c42e45510cfcdcd7a7ff584a700d4c1 --- /dev/null +++ b/ios/PersonalCredentialManager/main.m @@ -0,0 +1,10 @@ +#import <UIKit/UIKit.h> + +#import "AppDelegate.h" + +int main(int argc, char *argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/ios/PersonalCredentialManagerTests/Info.plist b/ios/PersonalCredentialManagerTests/Info.plist new file mode 100644 index 0000000000000000000000000000000000000000..ba72822e8728ef2951005e49b6c27a2f1da6572d --- /dev/null +++ b/ios/PersonalCredentialManagerTests/Info.plist @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> +</dict> +</plist> diff --git a/ios/PersonalCredentialManagerTests/PersonalCredentialManagerTests.m b/ios/PersonalCredentialManagerTests/PersonalCredentialManagerTests.m new file mode 100644 index 0000000000000000000000000000000000000000..c1b68efa2e51c7a6b668930243f505c13efd5a26 --- /dev/null +++ b/ios/PersonalCredentialManagerTests/PersonalCredentialManagerTests.m @@ -0,0 +1,66 @@ +#import <UIKit/UIKit.h> +#import <XCTest/XCTest.h> + +#import <React/RCTLog.h> +#import <React/RCTRootView.h> + +#define TIMEOUT_SECONDS 600 +#define TEXT_TO_LOOK_FOR @"Welcome to React" + +@interface PersonalCredentialManagerTests : XCTestCase + +@end + +@implementation PersonalCredentialManagerTests + +- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test +{ + if (test(view)) { + return YES; + } + for (UIView *subview in [view subviews]) { + if ([self findSubviewInView:subview matching:test]) { + return YES; + } + } + return NO; +} + +- (void)testRendersWelcomeScreen +{ + UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; + BOOL foundElement = NO; + + __block NSString *redboxError = nil; +#ifdef DEBUG + RCTSetLogFunction( + ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { + if (level >= RCTLogLevelError) { + redboxError = message; + } + }); +#endif + + while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + + foundElement = [self findSubviewInView:vc.view + matching:^BOOL(UIView *view) { + if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { + return YES; + } + return NO; + }]; + } + +#ifdef DEBUG + RCTSetLogFunction(RCTDefaultLogFunction); +#endif + + XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); + XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); +} + +@end diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000000000000000000000000000000000000..5aaf021a27b5e787a595af74da8d9a378c030326 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,44 @@ +# source 'https://github.com/hyperledger/indy-sdk-react-native' +require_relative '../node_modules/react-native/scripts/react_native_pods' +require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' + +platform :ios, '12.4' +install! 'cocoapods', :deterministic_uuids => false + +target 'PersonalCredentialManager' do + config = use_native_modules! + + # Flags change depending on the env values. + flags = get_default_flags() + + use_react_native!( + :path => config[:reactNativePath], + # Hermes is now enabled by default. Disable by setting this flag to false. + # Upcoming versions of React Native may rely on get_default_flags(), but + # we make it explicit here to aid in the React Native upgrade process. + :hermes_enabled => true, + :fabric_enabled => flags[:fabric_enabled], + # Enables Flipper. + # + # Note that if you have use_frameworks! enabled, Flipper will not work and + # you should disable the next line. +# :flipper_configuration => FlipperConfiguration.enabled, + # An absolute path to your application root. + :app_path => "#{Pod::Config.instance.installation_root}/.." + ) + + target 'PersonalCredentialManagerTests' do + inherit! :complete + # Pods for testing + end + + post_install do |installer| + react_native_post_install( + installer, + # Set `mac_catalyst_enabled` to `true` in order to apply patches + # necessary for Mac Catalyst builds + :mac_catalyst_enabled => false + ) + __apply_Xcode_12_5_M1_post_install_workaround(installer) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000000000000000000000000000000000000..e9bd0ac1aacb09a1811937ae7dda3623323aa594 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,728 @@ +PODS: + - boost (1.76.0) + - CatCrypto (0.3.2) + - DoubleConversion (1.1.6) + - FBLazyVector (0.70.6) + - FBReactNativeSpec (0.70.6): + - RCT-Folly (= 2021.07.22.00) + - RCTRequired (= 0.70.6) + - RCTTypeSafety (= 0.70.6) + - React-Core (= 0.70.6) + - React-jsi (= 0.70.6) + - ReactCommon/turbomodule/core (= 0.70.6) + - fmt (6.2.1) + - glog (0.3.5) + - GoogleDataTransport (9.2.0): + - GoogleUtilities/Environment (~> 7.7) + - nanopb (< 2.30910.0, >= 2.30908.0) + - PromisesObjC (< 3.0, >= 1.2) + - GoogleMLKit/BarcodeScanning (3.2.0): + - GoogleMLKit/MLKitCore + - MLKitBarcodeScanning (~> 2.2.0) + - GoogleMLKit/MLKitCore (3.2.0): + - MLKitCommon (~> 8.0.0) + - GoogleToolboxForMac/DebugUtils (2.3.2): + - GoogleToolboxForMac/Defines (= 2.3.2) + - GoogleToolboxForMac/Defines (2.3.2) + - GoogleToolboxForMac/Logger (2.3.2): + - GoogleToolboxForMac/Defines (= 2.3.2) + - "GoogleToolboxForMac/NSData+zlib (2.3.2)": + - GoogleToolboxForMac/Defines (= 2.3.2) + - "GoogleToolboxForMac/NSDictionary+URLArguments (2.3.2)": + - GoogleToolboxForMac/DebugUtils (= 2.3.2) + - GoogleToolboxForMac/Defines (= 2.3.2) + - "GoogleToolboxForMac/NSString+URLArguments (= 2.3.2)" + - "GoogleToolboxForMac/NSString+URLArguments (2.3.2)" + - GoogleUtilities/Environment (7.10.0): + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.10.0): + - GoogleUtilities/Environment + - GoogleUtilities/UserDefaults (7.10.0): + - GoogleUtilities/Logger + - GoogleUtilitiesComponents (1.1.0): + - GoogleUtilities/Logger + - GTMSessionFetcher/Core (1.7.2) + - hermes-engine (0.70.6) + - Indy (1.16.0) + - indy-sdk-react-native (0.3.0): + - Indy + - React + - libevent (2.1.12) + - MLImage (1.0.0-beta3) + - MLKitBarcodeScanning (2.2.0): + - MLKitCommon (~> 8.0) + - MLKitVision (~> 4.2) + - MLKitCommon (8.0.0): + - GoogleDataTransport (~> 9.0) + - GoogleToolboxForMac/Logger (~> 2.1) + - "GoogleToolboxForMac/NSData+zlib (~> 2.1)" + - "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)" + - GoogleUtilities/UserDefaults (~> 7.0) + - GoogleUtilitiesComponents (~> 1.0) + - GTMSessionFetcher/Core (~> 1.1) + - Protobuf (~> 3.12) + - MLKitVision (4.2.0): + - GoogleToolboxForMac/Logger (~> 2.1) + - "GoogleToolboxForMac/NSData+zlib (~> 2.1)" + - GTMSessionFetcher/Core (~> 1.1) + - MLImage (= 1.0.0-beta3) + - MLKitCommon (~> 8.0) + - Protobuf (~> 3.12) + - nanopb (2.30909.0): + - nanopb/decode (= 2.30909.0) + - nanopb/encode (= 2.30909.0) + - nanopb/decode (2.30909.0) + - nanopb/encode (2.30909.0) + - PromisesObjC (2.1.1) + - Protobuf (3.21.10) + - RCT-Folly (2021.07.22.00): + - boost + - DoubleConversion + - fmt (~> 6.2.1) + - glog + - RCT-Folly/Default (= 2021.07.22.00) + - RCT-Folly/Default (2021.07.22.00): + - boost + - DoubleConversion + - fmt (~> 6.2.1) + - glog + - RCT-Folly/Futures (2021.07.22.00): + - boost + - DoubleConversion + - fmt (~> 6.2.1) + - glog + - libevent + - RCTRequired (0.70.6) + - RCTTypeSafety (0.70.6): + - FBLazyVector (= 0.70.6) + - RCTRequired (= 0.70.6) + - React-Core (= 0.70.6) + - React (0.70.6): + - React-Core (= 0.70.6) + - React-Core/DevSupport (= 0.70.6) + - React-Core/RCTWebSocket (= 0.70.6) + - React-RCTActionSheet (= 0.70.6) + - React-RCTAnimation (= 0.70.6) + - React-RCTBlob (= 0.70.6) + - React-RCTImage (= 0.70.6) + - React-RCTLinking (= 0.70.6) + - React-RCTNetwork (= 0.70.6) + - React-RCTSettings (= 0.70.6) + - React-RCTText (= 0.70.6) + - React-RCTVibration (= 0.70.6) + - React-bridging (0.70.6): + - RCT-Folly (= 2021.07.22.00) + - React-jsi (= 0.70.6) + - React-callinvoker (0.70.6) + - React-Codegen (0.70.6): + - FBReactNativeSpec (= 0.70.6) + - RCT-Folly (= 2021.07.22.00) + - RCTRequired (= 0.70.6) + - RCTTypeSafety (= 0.70.6) + - React-Core (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - ReactCommon/turbomodule/core (= 0.70.6) + - React-Core (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default (= 0.70.6) + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/CoreModulesHeaders (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/Default (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/DevSupport (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default (= 0.70.6) + - React-Core/RCTWebSocket (= 0.70.6) + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-jsinspector (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/RCTActionSheetHeaders (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/RCTAnimationHeaders (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/RCTBlobHeaders (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/RCTImageHeaders (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/RCTLinkingHeaders (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/RCTNetworkHeaders (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/RCTSettingsHeaders (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/RCTTextHeaders (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/RCTVibrationHeaders (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-Core/RCTWebSocket (0.70.6): + - glog + - RCT-Folly (= 2021.07.22.00) + - React-Core/Default (= 0.70.6) + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-perflogger (= 0.70.6) + - Yoga + - React-CoreModules (0.70.6): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.70.6) + - React-Codegen (= 0.70.6) + - React-Core/CoreModulesHeaders (= 0.70.6) + - React-jsi (= 0.70.6) + - React-RCTImage (= 0.70.6) + - ReactCommon/turbomodule/core (= 0.70.6) + - React-cxxreact (0.70.6): + - boost (= 1.76.0) + - DoubleConversion + - glog + - RCT-Folly (= 2021.07.22.00) + - React-callinvoker (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsinspector (= 0.70.6) + - React-logger (= 0.70.6) + - React-perflogger (= 0.70.6) + - React-runtimeexecutor (= 0.70.6) + - React-hermes (0.70.6): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2021.07.22.00) + - RCT-Folly/Futures (= 2021.07.22.00) + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-jsiexecutor (= 0.70.6) + - React-jsinspector (= 0.70.6) + - React-perflogger (= 0.70.6) + - React-jsi (0.70.6): + - boost (= 1.76.0) + - DoubleConversion + - glog + - RCT-Folly (= 2021.07.22.00) + - React-jsi/Default (= 0.70.6) + - React-jsi/Default (0.70.6): + - boost (= 1.76.0) + - DoubleConversion + - glog + - RCT-Folly (= 2021.07.22.00) + - React-jsiexecutor (0.70.6): + - DoubleConversion + - glog + - RCT-Folly (= 2021.07.22.00) + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-perflogger (= 0.70.6) + - React-jsinspector (0.70.6) + - React-logger (0.70.6): + - glog + - react-native-biometrics (3.0.1): + - React-Core + - react-native-config (1.4.11): + - react-native-config/App (= 1.4.11) + - react-native-config/App (1.4.11): + - React-Core + - react-native-document-picker (8.1.3): + - React-Core + - react-native-get-random-values (1.8.0): + - React-Core + - react-native-safe-area-context (4.4.1): + - RCT-Folly + - RCTRequired + - RCTTypeSafety + - React-Core + - ReactCommon/turbomodule/core + - react-native-splash-screen (3.3.0): + - React-Core + - React-perflogger (0.70.6) + - React-RCTActionSheet (0.70.6): + - React-Core/RCTActionSheetHeaders (= 0.70.6) + - React-RCTAnimation (0.70.6): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.70.6) + - React-Codegen (= 0.70.6) + - React-Core/RCTAnimationHeaders (= 0.70.6) + - React-jsi (= 0.70.6) + - ReactCommon/turbomodule/core (= 0.70.6) + - React-RCTBlob (0.70.6): + - RCT-Folly (= 2021.07.22.00) + - React-Codegen (= 0.70.6) + - React-Core/RCTBlobHeaders (= 0.70.6) + - React-Core/RCTWebSocket (= 0.70.6) + - React-jsi (= 0.70.6) + - React-RCTNetwork (= 0.70.6) + - ReactCommon/turbomodule/core (= 0.70.6) + - React-RCTImage (0.70.6): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.70.6) + - React-Codegen (= 0.70.6) + - React-Core/RCTImageHeaders (= 0.70.6) + - React-jsi (= 0.70.6) + - React-RCTNetwork (= 0.70.6) + - ReactCommon/turbomodule/core (= 0.70.6) + - React-RCTLinking (0.70.6): + - React-Codegen (= 0.70.6) + - React-Core/RCTLinkingHeaders (= 0.70.6) + - React-jsi (= 0.70.6) + - ReactCommon/turbomodule/core (= 0.70.6) + - React-RCTNetwork (0.70.6): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.70.6) + - React-Codegen (= 0.70.6) + - React-Core/RCTNetworkHeaders (= 0.70.6) + - React-jsi (= 0.70.6) + - ReactCommon/turbomodule/core (= 0.70.6) + - React-RCTSettings (0.70.6): + - RCT-Folly (= 2021.07.22.00) + - RCTTypeSafety (= 0.70.6) + - React-Codegen (= 0.70.6) + - React-Core/RCTSettingsHeaders (= 0.70.6) + - React-jsi (= 0.70.6) + - ReactCommon/turbomodule/core (= 0.70.6) + - React-RCTText (0.70.6): + - React-Core/RCTTextHeaders (= 0.70.6) + - React-RCTVibration (0.70.6): + - RCT-Folly (= 2021.07.22.00) + - React-Codegen (= 0.70.6) + - React-Core/RCTVibrationHeaders (= 0.70.6) + - React-jsi (= 0.70.6) + - ReactCommon/turbomodule/core (= 0.70.6) + - React-runtimeexecutor (0.70.6): + - React-jsi (= 0.70.6) + - ReactCommon/turbomodule/core (0.70.6): + - DoubleConversion + - glog + - RCT-Folly (= 2021.07.22.00) + - React-bridging (= 0.70.6) + - React-callinvoker (= 0.70.6) + - React-Core (= 0.70.6) + - React-cxxreact (= 0.70.6) + - React-jsi (= 0.70.6) + - React-logger (= 0.70.6) + - React-perflogger (= 0.70.6) + - rn-fetch-blob (0.12.0): + - React-Core + - RNArgon2 (2.0.1): + - CatCrypto + - React-Core + - RNCAsyncStorage (1.17.11): + - React-Core + - RNCClipboard (1.11.1): + - React-Core + - RNDeviceInfo (10.3.0): + - React-Core + - RNFS (2.20.0): + - React-Core + - RNGestureHandler (2.8.0): + - React-Core + - RNKeychain (8.1.1): + - React-Core + - RNLocalize (2.2.4): + - React-Core + - RNReanimated (2.13.0): + - DoubleConversion + - FBLazyVector + - FBReactNativeSpec + - glog + - RCT-Folly + - RCTRequired + - RCTTypeSafety + - React-callinvoker + - React-Core + - React-Core/DevSupport + - React-Core/RCTWebSocket + - React-CoreModules + - React-cxxreact + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-RCTActionSheet + - React-RCTAnimation + - React-RCTBlob + - React-RCTImage + - React-RCTLinking + - React-RCTNetwork + - React-RCTSettings + - React-RCTText + - ReactCommon/turbomodule/core + - Yoga + - RNScreens (3.18.2): + - React-Core + - React-RCTImage + - RNShare (8.0.1): + - React-Core + - RNSVG (13.6.0): + - React-Core + - RNVectorIcons (9.2.0): + - React-Core + - vision-camera-code-scanner (0.2.0): + - GoogleMLKit/BarcodeScanning + - React-Core + - VisionCamera (2.15.2): + - React + - React-callinvoker + - React-Core + - Yoga (1.14.0) + +DEPENDENCIES: + - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) + - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) + - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) + - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) + - hermes-engine (from `../node_modules/react-native/sdks/hermes/hermes-engine.podspec`) + - indy-sdk-react-native (from `../node_modules/indy-sdk-react-native`) + - libevent (~> 2.1.12) + - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) + - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) + - React (from `../node_modules/react-native/`) + - React-bridging (from `../node_modules/react-native/ReactCommon`) + - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) + - React-Codegen (from `build/generated/ios`) + - React-Core (from `../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `../node_modules/react-native/`) + - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) + - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) + - React-hermes (from `../node_modules/react-native/ReactCommon/hermes`) + - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) + - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) + - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) + - React-logger (from `../node_modules/react-native/ReactCommon/logger`) + - react-native-biometrics (from `../node_modules/react-native-biometrics`) + - react-native-config (from `../node_modules/react-native-config`) + - react-native-document-picker (from `../node_modules/react-native-document-picker`) + - react-native-get-random-values (from `../node_modules/react-native-get-random-values`) + - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) + - react-native-splash-screen (from `../node_modules/react-native-splash-screen`) + - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) + - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) + - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) + - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) + - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) + - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) + - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) + - React-RCTText (from `../node_modules/react-native/Libraries/Text`) + - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) + - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) + - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - rn-fetch-blob (from `../node_modules/rn-fetch-blob`) + - RNArgon2 (from `../node_modules/react-native-argon2`) + - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" + - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)" + - RNDeviceInfo (from `../node_modules/react-native-device-info`) + - RNFS (from `../node_modules/react-native-fs`) + - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) + - RNKeychain (from `../node_modules/react-native-keychain`) + - RNLocalize (from `../node_modules/react-native-localize`) + - RNReanimated (from `../node_modules/react-native-reanimated`) + - RNScreens (from `../node_modules/react-native-screens`) + - RNShare (from `../node_modules/react-native-share`) + - RNSVG (from `../node_modules/react-native-svg`) + - RNVectorIcons (from `../node_modules/react-native-vector-icons`) + - vision-camera-code-scanner (from `../node_modules/vision-camera-code-scanner`) + - VisionCamera (from `../node_modules/react-native-vision-camera`) + - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) + +SPEC REPOS: + https://github.com/hyperledger/indy-sdk-react-native: + - Indy + trunk: + - CatCrypto + - fmt + - GoogleDataTransport + - GoogleMLKit + - GoogleToolboxForMac + - GoogleUtilities + - GoogleUtilitiesComponents + - GTMSessionFetcher + - libevent + - MLImage + - MLKitBarcodeScanning + - MLKitCommon + - MLKitVision + - nanopb + - PromisesObjC + - Protobuf + +EXTERNAL SOURCES: + boost: + :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" + DoubleConversion: + :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + FBLazyVector: + :path: "../node_modules/react-native/Libraries/FBLazyVector" + FBReactNativeSpec: + :path: "../node_modules/react-native/React/FBReactNativeSpec" + glog: + :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" + hermes-engine: + :podspec: "../node_modules/react-native/sdks/hermes/hermes-engine.podspec" + indy-sdk-react-native: + :path: "../node_modules/indy-sdk-react-native" + RCT-Folly: + :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + RCTRequired: + :path: "../node_modules/react-native/Libraries/RCTRequired" + RCTTypeSafety: + :path: "../node_modules/react-native/Libraries/TypeSafety" + React: + :path: "../node_modules/react-native/" + React-bridging: + :path: "../node_modules/react-native/ReactCommon" + React-callinvoker: + :path: "../node_modules/react-native/ReactCommon/callinvoker" + React-Codegen: + :path: build/generated/ios + React-Core: + :path: "../node_modules/react-native/" + React-CoreModules: + :path: "../node_modules/react-native/React/CoreModules" + React-cxxreact: + :path: "../node_modules/react-native/ReactCommon/cxxreact" + React-hermes: + :path: "../node_modules/react-native/ReactCommon/hermes" + React-jsi: + :path: "../node_modules/react-native/ReactCommon/jsi" + React-jsiexecutor: + :path: "../node_modules/react-native/ReactCommon/jsiexecutor" + React-jsinspector: + :path: "../node_modules/react-native/ReactCommon/jsinspector" + React-logger: + :path: "../node_modules/react-native/ReactCommon/logger" + react-native-biometrics: + :path: "../node_modules/react-native-biometrics" + react-native-config: + :path: "../node_modules/react-native-config" + react-native-document-picker: + :path: "../node_modules/react-native-document-picker" + react-native-get-random-values: + :path: "../node_modules/react-native-get-random-values" + react-native-safe-area-context: + :path: "../node_modules/react-native-safe-area-context" + react-native-splash-screen: + :path: "../node_modules/react-native-splash-screen" + React-perflogger: + :path: "../node_modules/react-native/ReactCommon/reactperflogger" + React-RCTActionSheet: + :path: "../node_modules/react-native/Libraries/ActionSheetIOS" + React-RCTAnimation: + :path: "../node_modules/react-native/Libraries/NativeAnimation" + React-RCTBlob: + :path: "../node_modules/react-native/Libraries/Blob" + React-RCTImage: + :path: "../node_modules/react-native/Libraries/Image" + React-RCTLinking: + :path: "../node_modules/react-native/Libraries/LinkingIOS" + React-RCTNetwork: + :path: "../node_modules/react-native/Libraries/Network" + React-RCTSettings: + :path: "../node_modules/react-native/Libraries/Settings" + React-RCTText: + :path: "../node_modules/react-native/Libraries/Text" + React-RCTVibration: + :path: "../node_modules/react-native/Libraries/Vibration" + React-runtimeexecutor: + :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" + ReactCommon: + :path: "../node_modules/react-native/ReactCommon" + rn-fetch-blob: + :path: "../node_modules/rn-fetch-blob" + RNArgon2: + :path: "../node_modules/react-native-argon2" + RNCAsyncStorage: + :path: "../node_modules/@react-native-async-storage/async-storage" + RNCClipboard: + :path: "../node_modules/@react-native-clipboard/clipboard" + RNDeviceInfo: + :path: "../node_modules/react-native-device-info" + RNFS: + :path: "../node_modules/react-native-fs" + RNGestureHandler: + :path: "../node_modules/react-native-gesture-handler" + RNKeychain: + :path: "../node_modules/react-native-keychain" + RNLocalize: + :path: "../node_modules/react-native-localize" + RNReanimated: + :path: "../node_modules/react-native-reanimated" + RNScreens: + :path: "../node_modules/react-native-screens" + RNShare: + :path: "../node_modules/react-native-share" + RNSVG: + :path: "../node_modules/react-native-svg" + RNVectorIcons: + :path: "../node_modules/react-native-vector-icons" + vision-camera-code-scanner: + :path: "../node_modules/vision-camera-code-scanner" + VisionCamera: + :path: "../node_modules/react-native-vision-camera" + Yoga: + :path: "../node_modules/react-native/ReactCommon/yoga" + +SPEC CHECKSUMS: + boost: a7c83b31436843459a1961bfd74b96033dc77234 + CatCrypto: a477899b6be4954e75be4897e732da098cc0a5a8 + DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 + FBLazyVector: 48289402952f4f7a4e235de70a9a590aa0b79ef4 + FBReactNativeSpec: dd1186fd05255e3457baa2f4ca65e94c2cd1e3ac + fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 + glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b + GoogleDataTransport: 1c8145da7117bd68bbbed00cf304edb6a24de00f + GoogleMLKit: 0017a6a8372e1a182139b9def4d89be5d87ca5a7 + GoogleToolboxForMac: 8bef7c7c5cf7291c687cf5354f39f9db6399ad34 + GoogleUtilities: bad72cb363809015b1f7f19beb1f1cd23c589f95 + GoogleUtilitiesComponents: 679b2c881db3b615a2777504623df6122dd20afe + GTMSessionFetcher: 5595ec75acf5be50814f81e9189490412bad82ba + hermes-engine: 2af7b7a59128f250adfd86f15aa1d5a2ecd39995 + Indy: d9976ce47c0308bd1fea6f90e3ad3db59a3b49b9 + indy-sdk-react-native: e1b23dea59196985f503488d0fe8d331e0206552 + libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 + MLImage: 489dfec109f21da8621b28d476401aaf7a0d4ff4 + MLKitBarcodeScanning: d92fe1911001ec36870162c5a0eb206f612b7169 + MLKitCommon: f6da6c5659618c070b50a80db01248ebe2964175 + MLKitVision: 96c96571190b7f63eddf4a12068ce8a8689e0d2c + nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 + PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb + Protobuf: ced4c17d029d7566cbfc51cfb44193e4aaafae27 + RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda + RCTRequired: e1866f61af7049eb3d8e08e8b133abd38bc1ca7a + RCTTypeSafety: 27c2ac1b00609a432ced1ae701247593f07f901e + React: bb3e06418d2cc48a84f9666a576c7b38e89cd7db + React-bridging: 572502ec59c9de30309afdc4932e278214288913 + React-callinvoker: 6b708b79c69f3359d42f1abb4663f620dbd4dadf + React-Codegen: 74e1cd7cee692a8b983c18df3274b5e749de07c8 + React-Core: b587d0a624f9611b0e032505f3d6f25e8daa2bee + React-CoreModules: c6ff48b985e7aa622e82ca51c2c353c7803eb04e + React-cxxreact: ade3d9e63c599afdead3c35f8a8bd12b3da6730b + React-hermes: ed09ae33512bbb8d31b2411778f3af1a2eb681a1 + React-jsi: 5a3952e0c6d57460ad9ee2c905025b4c28f71087 + React-jsiexecutor: b4a65947391c658450151275aa406f2b8263178f + React-jsinspector: 60769e5a0a6d4b32294a2456077f59d0266f9a8b + React-logger: 1623c216abaa88974afce404dc8f479406bbc3a0 + react-native-biometrics: 352e5a794bfffc46a0c86725ea7dc62deb085bdc + react-native-config: bcafda5b4c51491ee1b0e1d0c4e3905bc7b56c1b + react-native-document-picker: 958e2bc82e128be69055be261aeac8d872c8d34c + react-native-get-random-values: a6ea6a8a65dc93e96e24a11105b1a9c8cfe1d72a + react-native-safe-area-context: 99b24a0c5acd0d5dcac2b1a7f18c49ea317be99a + react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457 + React-perflogger: 8c79399b0500a30ee8152d0f9f11beae7fc36595 + React-RCTActionSheet: 7316773acabb374642b926c19aef1c115df5c466 + React-RCTAnimation: 5341e288375451297057391227f691d9b2326c3d + React-RCTBlob: b0615fc2daf2b5684ade8fadcab659f16f6f0efa + React-RCTImage: 6487b9600f268ecedcaa86114d97954d31ad4750 + React-RCTLinking: c8018ae9ebfefcec3839d690d4725f8d15e4e4b3 + React-RCTNetwork: 8aa63578741e0fe1205c28d7d4b40dbfdabce8a8 + React-RCTSettings: d00c15ad369cd62242a4dfcc6f277912b4a84ed3 + React-RCTText: f532e5ca52681ecaecea452b3ad7a5b630f50d75 + React-RCTVibration: c75ceef7aa60a33b2d5731ebe5800ddde40cefc4 + React-runtimeexecutor: 15437b576139df27635400de0599d9844f1ab817 + ReactCommon: 349be31adeecffc7986a0de875d7fb0dcf4e251c + rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba + RNArgon2: 1481820722fd4af1575c09f7fc9ad67c00ee8a42 + RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60 + RNCClipboard: 2834e1c4af68697089cdd455ee4a4cdd198fa7dd + RNDeviceInfo: 4701f0bf2a06b34654745053db0ce4cb0c53ada7 + RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 + RNGestureHandler: 62232ba8f562f7dea5ba1b3383494eb5bf97a4d3 + RNKeychain: ff836453cba46938e0e9e4c22e43d43fa2c90333 + RNLocalize: 0df7970cfc60389f00eb62fd7c097dc75af3fb4f + RNReanimated: ce445c233a6ff5600223484a88ad5704945d972a + RNScreens: 34cc502acf1b916c582c60003dc3089fa01dc66d + RNShare: d93e00e906e6174657f6370b480437e4702bc86e + RNSVG: 3a79c0c4992213e4f06c08e62730c5e7b9e4dc17 + RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8 + vision-camera-code-scanner: dda884a7f3ec8243a2a6d6489b91860648371bca + VisionCamera: 4cfd685b1e671fea4aa0400905ab397f0e972210 + Yoga: 99caf8d5ab45e9d637ee6e0174ec16fbbb01bcfc + +PODFILE CHECKSUM: 7aadfec5fb591cddde206a872846b514dbbf98d8 + +COCOAPODS: 1.11.3 diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000000000000000000000000000000000000..97a3feb5c30132017f2a39b1b53cbdbf9cf1a392 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,7 @@ +module.exports = { + preset: 'react-native', + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + transformIgnorePatterns: [ + 'node_modules/(?!(@react-native|react-native|react-native-vector-icons|react-native-argon2|react-native-toast-message||react-native-camera|react-native-dropdown-picker)/)', + ], +}; diff --git a/metro.config.js b/metro.config.js new file mode 100644 index 0000000000000000000000000000000000000000..2d17624e1ae331bf0ad5fd5a6bd7a142893d42c1 --- /dev/null +++ b/metro.config.js @@ -0,0 +1,29 @@ +/** + * Metro configuration for React Native + * https://github.com/facebook/react-native + * + * @format + */ + +const { getDefaultConfig } = require('metro-config'); + +module.exports = (async () => { + const { + resolver: { sourceExts, assetExts }, + } = await getDefaultConfig(); + return { + transformer: { + babelTransformerPath: require.resolve('react-native-svg-transformer'), + getTransformOptions: async () => ({ + transform: { + experimentalImportSupport: false, + inlineRequires: true, + }, + }), + }, + resolver: { + assetExts: assetExts.filter(ext => ext !== 'svg'), + sourceExts: [...sourceExts, 'svg', 'cjs'], + }, + }; +})(); diff --git a/package.json b/package.json new file mode 100644 index 0000000000000000000000000000000000000000..f9c3898abc59defaaceadecad5a823168dd8b3db --- /dev/null +++ b/package.json @@ -0,0 +1,103 @@ +{ + "name": "personalcredentialmanager", + "version": "0.0.1", + "private": true, + "scripts": { + "android": "react-native run-android", + "ios": "react-native run-ios", + "start": "react-native start", + "test": "jest", + "lint": "eslint . --ext .js,.jsx,.ts,.tsx --fix" + }, + "dependencies": { + "@ant-design/react-native": "^5.0.2", + "@aries-framework/core": "^0.2.5", + "@aries-framework/react-hooks": "^0.2.0", + "@aries-framework/react-native": "^0.2.5", + "@react-native-async-storage/async-storage": "^1.17.11", + "@react-native-clipboard/clipboard": "^1.11.1", + "@react-navigation/bottom-tabs": "^6.4.3", + "@react-navigation/native": "^6.0.16", + "@react-navigation/stack": "^6.3.7", + "@testing-library/react-native": "^11.5.0", + "@vereign/light-utils": "git+ssh://git@code.vereign.com:seal/building-blocks/signing-verification-utilities.git#feature-seal-reading-injecting", + "babel-plugin-import": "^1.13.5", + "buffer": "^6.0.3", + "date-fns": "^2.29.1", + "fflate": "^0.7.3", + "i18next": "^22.4.6", + "indy-sdk-react-native": "^0.3.0", + "intl-pluralrules": "^1.3.1", + "js-sha256": "^0.9.0", + "md5": "^2.3.0", + "query-string": "^7.1.1", + "react": "18.1.0", + "react-i18next": "^12.1.1", + "react-native": "0.70.6", + "react-native-aes-gcm-crypto": "^0.2.2", + "react-native-app-intro-slider": "^4.0.4", + "react-native-argon2": "^2.0.1", + "react-native-biometrics": "^3.0.1", + "react-native-circular-progress-indicator": "^4.4.0", + "react-native-config": "^1.4.11", + "react-native-device-info": "^10.3.0", + "react-native-document-picker": "^8.1.3", + "react-native-dropdown-picker": "^5.4.3", + "react-native-fs": "^2.20.0", + "react-native-gesture-handler": "^2.8.0", + "react-native-get-random-values": "^1.8.0", + "react-native-keychain": "^8.1.1", + "react-native-localize": "^2.2.4", + "react-native-reanimated": "^2.13.0", + "react-native-render-html": "^6.3.4", + "react-native-rsa-native": "^2.0.5", + "react-native-safe-area-context": "^4.4.1", + "react-native-screens": "^3.18.2", + "react-native-share": "^8.0.0", + "react-native-splash-screen": "^3.3.0", + "react-native-svg": "^13.6.0", + "react-native-toast-message": "^2.1.5", + "react-native-user-inactivity": "^1.2.0", + "react-native-uuid": "^2.0.1", + "react-native-vector-icons": "^9.2.0", + "react-native-vision-camera": "^2.15.2", + "react-native-webview": "^11.23.0", + "rn-fetch-blob": "^0.12.0", + "url-parse": "^1.5.10", + "vision-camera-code-scanner": "^0.2.0" + }, + "devDependencies": { + "@babel/core": "^7.12.9", + "@babel/runtime": "^7.12.5", + "@react-native-community/eslint-config": "^2.0.0", + "@tsconfig/react-native": "^2.0.2", + "@types/jest": "^26.0.23", + "@types/md5": "^2.3.2", + "@types/react": "^18.0.21", + "@types/react-native": "^0.70.6", + "@types/react-native-vector-icons": "^6.4.12", + "@types/react-test-renderer": "^18.0.0", + "@typescript-eslint/eslint-plugin": "^5.37.0", + "@typescript-eslint/parser": "^5.37.0", + "@vereign/lib-mime": "^1.1.9", + "@vereign/lib-png": "^1.0.3", + "babel-jest": "^26.6.3", + "eslint": "^7.32.0", + "jest": "^26.6.3", + "metro-react-native-babel-preset": "0.72.3", + "react-native-svg-transformer": "^1.0.0", + "react-test-renderer": "18.1.0", + "typescript": "^4.8.3" + }, + "jest": { + "preset": "react-native", + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "jsx", + "json", + "node" + ] + } +} diff --git a/react-native.config.js b/react-native.config.js new file mode 100644 index 0000000000000000000000000000000000000000..d4866098609d73371fe035c8ec9666aafa1dc7cf --- /dev/null +++ b/react-native.config.js @@ -0,0 +1,7 @@ +module.exports = { + project: { + ios: {}, + android: {}, + }, + assets: ['./src/assets/fonts'], +}; diff --git a/src/assets/biometric.png b/src/assets/biometric.png new file mode 100644 index 0000000000000000000000000000000000000000..fa27c21a3b12c4f722b5a8f237026976d7e11c0c Binary files /dev/null and b/src/assets/biometric.png differ diff --git a/src/assets/connections-icon.png b/src/assets/connections-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e22294c09cf610f0a00505b78cf17cdd5d94e562 Binary files /dev/null and b/src/assets/connections-icon.png differ diff --git a/src/assets/credentials-icon.png b/src/assets/credentials-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0e4e7179f65b707c40f1d3356bebb24877272005 Binary files /dev/null and b/src/assets/credentials-icon.png differ diff --git a/src/assets/credentials.png b/src/assets/credentials.png new file mode 100644 index 0000000000000000000000000000000000000000..21cf98e6c79620d9a79063353d8cc7e0c6815961 Binary files /dev/null and b/src/assets/credentials.png differ diff --git a/src/assets/fonts/TitilliumWeb-Light.ttf b/src/assets/fonts/TitilliumWeb-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..fa9393d1cbf42cabd8bcc9d4a94176534ba2b590 Binary files /dev/null and b/src/assets/fonts/TitilliumWeb-Light.ttf differ diff --git a/src/assets/fonts/TitilliumWeb-Regular.ttf b/src/assets/fonts/TitilliumWeb-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e0e2dc888cfeaa9b7ecd53ffa85d911afd6d9542 Binary files /dev/null and b/src/assets/fonts/TitilliumWeb-Regular.ttf differ diff --git a/src/assets/fonts/TitilliumWeb-SemiBold.ttf b/src/assets/fonts/TitilliumWeb-SemiBold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2a1a0bca99246e923732bfc382bdb96e3074216f Binary files /dev/null and b/src/assets/fonts/TitilliumWeb-SemiBold.ttf differ diff --git a/src/assets/home-icon.png b/src/assets/home-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3d8c12e926705ece63d94d19a1a25a53d1828d23 Binary files /dev/null and b/src/assets/home-icon.png differ diff --git a/src/assets/img/connection-pending.svg b/src/assets/img/connection-pending.svg new file mode 100644 index 0000000000000000000000000000000000000000..152bf581918136ab486133f2e48ebbdc4ca1d188 --- /dev/null +++ b/src/assets/img/connection-pending.svg @@ -0,0 +1,71 @@ +<svg id="Group_2230" data-name="Group 2230" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="250" height="250" viewBox="0 0 250 250"> + <defs> + <clipPath id="clip-path"> + <rect id="Rectangle_1594" data-name="Rectangle 1594" width="250" height="250" fill="none"/> + </clipPath> + <clipPath id="clip-path-2"> + <path id="Path_528" data-name="Path 528" d="M21.272,71.4l-.118.323a4.39,4.39,0,0,0,8.246,3l.129-.313.148-.363-8.243-3.04-.162.4" transform="translate(-20.944 -71.005)" fill="none"/> + </clipPath> + <clipPath id="clip-path-3"> + <path id="Path_529" data-name="Path 529" d="M120.1,16.171A105.345,105.345,0,0,0,21.69,84.208L21.205,85.4c1.377.5,2.064.751,2.064.751.688.25,1.376.5,2.065.752s1.376.5,2.065.751l2.064.752q.446-1.088.447-1.088A96.552,96.552,0,0,1,120.1,24.958h.025a96.3,96.3,0,0,1,96.4,95.262c.009.393.02.786.03,1.177h8.787q-.015-.64-.033-1.282A105.17,105.17,0,0,0,120.126,16.171Z" transform="translate(-21.205 -16.171)" fill="none"/> + </clipPath> + <clipPath id="clip-path-4"> + <path id="Path_530" data-name="Path 530" d="M176.822,99.694l.01.393.006.215a4.392,4.392,0,0,0,8.782-.009c0-.069,0-.138,0-.206l-.011-.428Z" transform="translate(-176.822 -99.659)" fill="none"/> + </clipPath> + <clipPath id="clip-path-5"> + <path id="Path_531" data-name="Path 531" d="M171.908,127.843l-.127.3-.005.011c-.043.1-.085.2-.129.3l-.025.059,8.188,3.186.168-.4c.039-.1.079-.2.12-.309a4.391,4.391,0,0,0-8.191-3.148" transform="translate(-171.622 -125.187)" fill="none"/> + </clipPath> + <clipPath id="clip-path-6"> + <path id="Path_532" data-name="Path 532" d="M22.76,100H16.17c.01.428.02.855.031,1.283A105.172,105.172,0,0,0,121.384,205.228h.028a105.344,105.344,0,0,0,97.743-66.316s.168-.393.5-1.182l-2.05-.786c-.684-.265-1.367-.526-2.05-.788s-1.368-.525-2.051-.788l-2.051-.787q-.465,1.081-.464,1.081a96.56,96.56,0,0,1-89.581,60.781h-.025a96.3,96.3,0,0,1-96.4-95.262c-.009-.393-.02-.787-.03-1.179Z" transform="translate(-16.17 -100)" fill="none"/> + </clipPath> + <clipPath id="clip-path-7"> + <path id="Path_533" data-name="Path 533" d="M20.453,96.416a4.394,4.394,0,0,0-4.283,4.289v.21c0,.143.008.285.01.427l8.787-.035-.01-.392-.006-.215a4.392,4.392,0,0,0-4.388-4.285h-.109" transform="translate(-16.17 -96.415)" fill="none"/> + </clipPath> + <image id="image" width="10.042" height="7.532" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAGCAYAAAD+Bd/7AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAYSURBVBhXY/z//z8DPsAEpXGCgVfAwAAATzwDCfhL/VYAAAAASUVORK5CYII="/> + </defs> + <g id="Group_2229" data-name="Group 2229" clip-path="url(#clip-path)"> + <g id="Group_2216" data-name="Group 2216" transform="translate(26.29 89.129)"> + <g id="Group_2215" data-name="Group 2215" clip-path="url(#clip-path-2)"> + <use id="Rectangle_1587" data-name="Rectangle 1587" transform="translate(-1.184 -0.006)" xlink:href="#image"/> + </g> + </g> + <g id="Group_2218" data-name="Group 2218" transform="translate(26.618 20.299)"> + <g id="Group_2217" data-name="Group 2217" clip-path="url(#clip-path-3)"> + <image id="Rectangle_1588" data-name="Rectangle 1588" width="204.606" height="105.441" transform="translate(-0.257 -0.215)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKMAAABUCAYAAADu+4chAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAhpSURBVHhe7Z07iCRVFIZ3Znd9oCIiIq6BkaGZ2WbCbqCggSaKGogPREQEA1EUX6uIb1BUFFEQRQwMFATXTDAwMzIyMXAFWUTE967r/9+6f+3ft6tf01U11d3ngzPn3FPVTXfdb29VV8+wW6dOndoTnObk0QOXI21ZbCMIs49ZE461zYNs7z3049e5DmawsTJCusuQXKiyVkg+9TUu9y8f1xSN+0DYL5E3no2REfJdisTJJxLKxVKUwvi+PvZ91PcxaXquprruQczPkTeStZQR4l2cS04wKQUqx94rJfF9y21EvXKb94hvb9p3b9mDmJ8ibwxrJSMkvCiXPqmEk9+UfR/KQEpR/DE+1uO8r8d4lP2m/djzvmqiHuX8JHXWlJWXEQJemEtNGqknMI2qySXe9yASoJYiH5smSbYIMmGvfCzxMTNh7f1yH9XE91HU+0DMj5DXipWVERJekEtNXjlxCuI1J7POeP++r6IUwcepLmQs9/GY9lw+HjtN55j6/JDyQ+S1YKVkhIDn51KTQcpa2YNs20pHyn3K8Mkfq+eUsdxGfD/WClJuU+1jZVKPIeX7qbPCrISMkPC8XGpifDKUyz7fW9P2mbHv8LHvkZcGr/sgkp63lMmjaVUs9+OYQSY+F6R8D3klGbSMmMxzc8kDrTyzzu9JvakB8X5A3hXw/g4h6bVIyEkSes+3NfYg5TvIK8VgZcREnZNLHuAyK0jKeRX0ntecIEL5juV6UOD9Xo3kcpW1j307Ue29tB+kfLsaDp/ByYhJORspHcjUqPCx6jQuVkEysh3y/cy8SuAYXIfk76OUrek2FFFf4/oxkPLN1Bkwg5ERE3AWkh/EiTmvgoTZg3D1O57rtQDH5gYkF8+vMYn3iLbpMST1IOXr1XB4DELGLCLRgSM6oKK8FiQjNST8JddrC47VjUguJsNXRAX3IY09SPlqrgfDrsqIA3tmLnmgHI3TQbTXONJnQMBfU2fDwLG7Gak+DgiK5gKWwhLv8XvwV9gcCrsm44kvLjkj36rTgVImda8Qse5Dwt9yvdFAyluR/LTNkHSk7KmfxhDy5Wq4+/QuIyTcj6QDwrvHKaWB5eJ1sZ+2QcLfmYPTQMjbcqnjVK6KLmd5bckV8oVquLv0KmMWUaQDcvqLjGqM1+MHqs6Q8I80CiYCKW9HKldAZu+V2+sxpHwudXaJ3mQsRBTpgFBIk5CoThki/plGwVxAyruQkmAIXxV93LgNQj5bDfunFxkh4r5c6o2LelwImTIk/CuNgh0BKe9GknBjp+eqTFk1+1whn6mG/dK5jCYi0cEYAzLytaTtkPDv1AxaAVLeiyQpXUQfp2OfM1fII9WwPzqTERL6va+SiT2I+E8aBa0CIe9D4jFuWiGZ1ZOoeyHkE7nuhU5kNBGF3qgz0oOE/+Yy6AgIeT/SrBWSjNSQ8vFcd0rrMkJEvdmSib0QsV8g5QNIPPZ+9vJ58zptg5CPVsPukP2tkEUkNLzJ8rJ3KkTsH4j1fC6JpBPuBGVNYwj8JHOXtCajiTgJiVgLCRFP5DLoGQjp9xR1Hak5ZO2Spm0Q8ulq2A2tnKbnEJHozfGrvJBwIECwh5EkYimhep4p8oPMbTOPRFOBiP7ip5GsDxGHBcQ6gngqDyeJ6Mw73wuztIwZijZziYWIJ3MZDAwIqds4dIKh60XKx6hP5VhNO/nacCkZF1gVKeJ/uQwGCoR8LJeaV2V5orwFIV/MdWvsWMYJImqFHFklQ8TVAUKWt3C0OtYiIlINIV9ibosdyRgr4noDIR9BknSevU73KCFka7+gu7CMFJG/1DAHvIcYIq4oEPKhXBJNuEQU6ToSQrbyJwwLy0h0O2ialBBx5geaYNhASN7CkSMu4qR6KRaWkZJJNErZJGSIuFZwgiUcczo9Z2oRsTou/VeHC8soJBz+9dRyBusH5pffY5f4bR+Sagj5RjXcGa39ogReSHquEHM9yR9UfJUkWsxGxhD4zjRaED3Z0sQKud5gfvn7kGSSiEvTye8zBusLVsjXkCatjnUNefUXi3PT2soYbAaQ7J5cklJK1klKSPsum4sQMgY7Qaugsr63JnJqYbfiNB3sCKx8byFJSFJKmPpYSW9JozlY2N4gIJDsjlySJhFZL+RXyBgsg0vH4Fg9wnuPH+R6JiFjsGOKT8ySUNePujHufzc/lZAxWBZK1/SNTJ2xOn6cRjMIGYOlsA8ovhIyM8rT9lRCxqANyhXRJUw9rI4z/6u5kDFYGqyON+VSEhKJqFB/InGfMWiNfG0o+ZxaUIh7ba7HKB8UBMvgImqV1LVkCgj7GXIjIWPQGlj1rs8lJawFtJCgjXCHIGiTUkQXkOOJ9x3jmjFonXwq9hVQYpLUxyp6OI0M7RAEbaLVkasgg9eNRP1G70LGoHWw6l2TS8onASmkTtEhY9ArcovZw1fKEfSAIGgbrYQMesZxvVLiuvIr5BFCxqArtBL6qZohORkjjDWCoA1w3XhVLksBFWOnajaDoCt0qnYBtVLyFtA3zCJkDLpEfpWnaoYkrRkZBEGb4FR9EEkSUj4iGRU1I4Mg6AA6plXQT9lptcSp+lvkRMgYdI3EI8y8bmRIytrBkDHoFJyqr1SJ8FM1a62UiZAx6AN6pnABU8ap+rt6EAQd4xJ6kFpONYKgM3CqviKXxGVk6DoyZAx6g67tR/iNb4akDBmD3nDxGP4BJnmYfgRBD7h4Z9g4rhmD3pF4LqVH9SMIeqCUz4OCpiII+qBpRfQPNPHXgUE/nDx64CekJB1oXARDxqA3IOTxXDbSaGgQdISfosvYxx9B0BdjAlpsh4xBn7h8SUCPkDHokxH5yuCPIOiLMQE9+CMI+mJMQA/+CIK+kHikyHu2/wdYD/E7W8lFCgAAAABJRU5ErkJggg=="/> + </g> + </g> + <g id="Group_2220" data-name="Group 2220" transform="translate(221.956 125.097)"> + <g id="Group_2219" data-name="Group 2219" clip-path="url(#clip-path-4)"> + <image id="Rectangle_1589" data-name="Rectangle 1589" width="10.042" height="6.276" transform="translate(-1.032 -0.827)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAkSURBVBhXY/yzS/IfAwT8B2JGdJoJygFhGBuFBhF4AaUKGBgAg00F4iY3qXwAAAAASUVORK5CYII="/> + </g> + </g> + <g id="Group_2222" data-name="Group 2222" transform="translate(215.429 157.141)"> + <g id="Group_2221" data-name="Group 2221" clip-path="url(#clip-path-5)"> + <use id="Rectangle_1590" data-name="Rectangle 1590" transform="translate(-0.781 -0.235)" xlink:href="#image"/> + </g> + </g> + <g id="Group_2224" data-name="Group 2224" transform="translate(20.297 125.525)"> + <g id="Group_2223" data-name="Group 2223" clip-path="url(#clip-path-6)"> + <image id="Rectangle_1591" data-name="Rectangle 1591" width="204.606" height="105.441" transform="translate(-0.213)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKMAAABUCAYAAADu+4chAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAhpSURBVHhe7Z1LiBxVFIYzefhGEAmYgBt3Lt3pyoXEbEQEQQRBUEEUX/hCJaIiKoiCii5EEEVRBEFBBCFxJ7hy59qNi1FERMS3Scb/v3P/yuk7t2b6UdVd3fN/cDzn3qoeaqq+nFvVzvSsnTx+6NSeM+xFnNwsN9l3ZP1ALo3pFcp3OsSIiMbMk1LGWhgzFyyjGQxtMnK5VhgzF6KMUcAopjFzgTLWBIxhzFzwPaMZDDUZ43J98tSJwz8iG9M7e/cdWT+ITAn55jdjowhKaUzvsDMSSqiuGLukwpjekYwUrhRRS7VlNHMhyhgFjGKyNqZ3ShmjgHFsTO9IxrIT8h6SmcGHGGN6J3ZGPUnrYYb1fwgKaUzvSEaKp64YO2Ti1InD3+bSmN4o7xlJzCNSGtMnScZ9R9YvT6OtIsYwplfUGQk7oJbpuFyn+0gs1d8gG9MbUcZGvJxVS0ov16ZXGhmxVF+RS4kXuyODchrTG7EzEglIJCG7Y+qQWKq/QjamF0oZo4BaqkkU1JheGJERS/WVSBRQUpbLtZdq0xtlZyQSj0GY41L9JSeN6ZqajLETarkmmmMY0zlbZMRSfTUSBUydEBGXanVIYzqn1hlJ7IIKScjamM5pk7HshPGhhj848TmzMV3SJiPlk4CEcpZiGtMpVRlx33gUSZ2QP9NIAYnm+FT9aZoxpiPaOiNRF+Q+jYQ5JKcxnbGdjBIvvtVDCbVMszt+jGxMJ7TKiKX6eqQoIDulpCTaZkwnbNcZKeQNuZSAhLWWcD5Zf8hszKxsK2NG3VChbqgxhfyA2ZhZ2FFGdMcbc6nlupGwko2ZmnE6I4kSKrRUM7M7vsdszLSMJSO64025VAeMS7WE5FO3MVMzbmcksRPGzihB2R3fzqUxEzO2jOiOtyDFzsg6xoiYxkzKJJ2RULgonTLnEuiOb+XSmIlY29hoPBoLyPYuUilhHLPeQCe9O80YMyaTdkZSEzHePyobMxETy4iOdzuShJN8/DqqE+igb+TSmLGYpjNSyDuQ2A0ZJHbGRkoI+RqzMeMwlYwZvVZCUkKi7pjGEPKVNDJmB6aWEd3xTqQoHuuyO6YMIV9GNivGyeOH1nLZCbN0RgrJJ2aJR1SrWzZAyJdyaVYAidilkDPJSCDkPbmMUpJ4H6lsVoBSwK6EnFnGTK07klhzuX4h12ZJaROP87NK2YmM6I73I1G8uDyXUiYg5PO5NEsGZNvRF1zfqYXsqjNSyAdzSSElInOsU8YBP4tslohxRCST/h+9SGcyEgj5UC4lH4kiNkDIZ3JpBs64IpL91/4wtY2dykgg5CNIUcSYNZ8yhHw6jcxgqYjIZbi6FM8iIulcRgIhH0PigVE6LdsMzum+Mh04hHwyjczggIj7clljpoeVGr3ImFEXFPpXwxxrCnkM8USaMYNgBxFF0yVn7Ypk4h8hmwQIxidndUSimiFZtS29L4mu+uLm0CwCSLgfqZSiHI8AEcvGMxV9dkYu18eQJF6Ur6ybt4QgMO85zQLIIpLyvrB1Se5KRNKrjARCPpXLKCEp/7U1Ywj5cC7NnICIB3LZRilopyKSXpfpCASjlGVHJKzbxly2X+Wk6Y8gIs97jXJ+o2sRydxkFJCST88jT9Q5J/lyEI5TQMjX04zpFEh4Vi5LCbYdQ8TmtqpLel+mSyDWc7mUeIwooiRknYDA9+bSdAREPHttrfVWsKTZsS8Rydw7o4BgjyNJPsI6dkwdmORMgkLmNzlppgMSnoMUL7rqOEdGxpCw9w9pWJiMBEI+isQD0EGoIzJUkzhOASn9K7ETAAnPRYrnU9TmIrw/nMunhSxURgIh+VYOD2I7+WJNmjlI6U+x2AGIeB5SPHcxk7aaHZEfoz0XFi6jgJT8qR8ejA6IsjFIlJFRjnkv+g6zOQMkPD+XzXmq5D353hEqNFOpmKeIZDAyEgj5AJJEI8xbxAM1OfnU/T7yrgcSXpBLnS+dJ5FqScj/MMsFSPhvKubMoGQkEPI+JB4UoxQzzmmeDz0ap4CUu/LDSyHhhbmM50M040JCoprnbiEiksHJSCAkf6+G0hGdRMZ2c1HSVOPEfoS80kDAi5Di+SDVegcJ/8n1whikjAJS3oXUnEwQhYtzmifMGiufwsn+BHllgIQXI/F7U5C2cRRR20iqcW7+TqMFM2gZBaTk72hHEYly+d6kxnH/2lL+GfJSAQEPIsXvg8Rczm+0dMM0xjn4i3koLIWMAlLyY1WakwmicKxJnFOUMo68DhflC+RBAgEvQYrHziBtY0IJ4/xIxvf7Z64HxVLJKCDlbUg16TRHRoQrcjnfyIoLtbA/7g7xLkWKx6fgMnsa12pkrshlFyz34/f2x+ZwmCyljAJS3oqkk84oBSRblmhETcpyTvMx84J+jdwJkO8yJH5tslOOx8UgqS7uB7WNNK/Fcf+e68Gy1DIKSKmPeI4Xg5lzcV4R53SPqfm4jTVRHefK/Zpt+ZyOs3+5PeZyu8YpwjJMNE9Gakj4W64Hz0rIKCDlzUi6GIrywsdtCnXPcnvbmNS+LnOUMe7TbM+5NrddloAMUtbKFPDXzeFysVIyCkjJPxXCb6y2RDOaC4yI+3C+VhON42vjfsxpW4uMqkk5TzRuInS/2j5kpIaEv+R6KVlJGSMQk3//UBetuXAICVHmGOWcxiRui1+jtkzHXEZ6Teh6bUG2zEHAn5lXgZWXsQRyXocULyhlqIkS55IwINbl9mZbKWN4wIivqY0ZpJwbCQj4E/LKsetkjEDMo0hbLjYiSlITpoxyH1Kb11iZxO3VgHzryCvPrpYxAjGvyWUpjIJjohMWt5f7ktp8Oa4G5PseeddhGScAwl6FFMWpySa0TXNb9oV03yGbxJ49/wP1Lt714Yy15AAAAABJRU5ErkJggg=="/> + </g> + </g> + <g id="Group_2226" data-name="Group 2226" transform="translate(20.297 121.025)"> + <g id="Group_2225" data-name="Group 2225" clip-path="url(#clip-path-7)"> + <image id="Rectangle_1592" data-name="Rectangle 1592" width="10.042" height="6.276" transform="translate(-0.213 -0.521)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAhSURBVBhXY/yzS/I/Ax7ABKVxAuooALnhHxKG8YE0w38AQ0sKzHTI7lUAAAAASUVORK5CYII="/> + </g> + </g> + <g id="Group_2228" data-name="Group 2228"> + <g id="Group_2227" data-name="Group 2227" clip-path="url(#clip-path)"> + <path id="Path_534" data-name="Path 534" d="M34.775,102.553A12.553,12.553,0,1,1,22.223,90a12.552,12.552,0,0,1,12.553,12.553" transform="translate(2.468 22.973)" fill="#fcba19"/> + <path id="Path_535" data-name="Path 535" d="M195.435,102.553A12.553,12.553,0,1,1,182.883,90a12.552,12.552,0,0,1,12.553,12.553" transform="translate(43.477 22.973)" fill="#fcba19"/> + <path id="Path_536" data-name="Path 536" d="M133.773,117.962v3.206a14.207,14.207,0,0,0,14.193,14.206h25.243v14.836a8.691,8.691,0,0,1-8.694,8.693H55.468a8.691,8.691,0,0,1-8.694-8.693V66.761a8.692,8.692,0,0,0,8.694,8.694H164.515a8.7,8.7,0,0,1,8.694,8.694v19.62H147.966a14.2,14.2,0,0,0-14.193,14.193" transform="translate(11.939 17.041)" fill="#8099b3"/> + <path id="Path_537" data-name="Path 537" d="M133.773,117.962v3.206a14.207,14.207,0,0,0,14.193,14.206h25.243v14.836a8.691,8.691,0,0,1-8.694,8.693H55.468a8.691,8.691,0,0,1-8.694-8.693V66.761a8.692,8.692,0,0,0,8.694,8.694H164.515a8.7,8.7,0,0,1,8.694,8.694v19.62H147.966A14.2,14.2,0,0,0,133.773,117.962Z" transform="translate(11.939 17.041)" fill="none" stroke="#036" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_538" data-name="Path 538" d="M147.128,68.529v8.694H55.468a8.694,8.694,0,0,1,0-17.388h82.966a8.7,8.7,0,0,1,8.694,8.694" transform="translate(11.939 15.273)" fill="#335c85"/> + <path id="Path_539" data-name="Path 539" d="M147.128,68.529v8.694H55.468a8.694,8.694,0,0,1,0-17.388h82.966A8.7,8.7,0,0,1,147.128,68.529Z" transform="translate(11.939 15.273)" fill="none" stroke="#036" stroke-linecap="round" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_540" data-name="Path 540" d="M162.707,96.242v31.606H130.275a14.207,14.207,0,0,1-14.193-14.206v-3.207a14.2,14.2,0,0,1,14.193-14.193Z" transform="translate(29.63 24.566)" fill="#8099b3"/> + <path id="Path_541" data-name="Path 541" d="M162.707,96.242v31.606H130.275a14.207,14.207,0,0,1-14.193-14.206v-3.207a14.2,14.2,0,0,1,14.193-14.193Z" transform="translate(29.63 24.566)" fill="none" stroke="#036" stroke-linejoin="round" stroke-width="4"/> + <circle id="Ellipse_65" data-name="Ellipse 65" cx="5.096" cy="5.096" r="5.096" transform="translate(155.316 141.038) rotate(-82.982)" fill="none" stroke="#036" stroke-miterlimit="10" stroke-width="4"/> + </g> + </g> + </g> +</svg> diff --git a/src/assets/img/credential-declined.svg b/src/assets/img/credential-declined.svg new file mode 100644 index 0000000000000000000000000000000000000000..2c395af8c87391ef8cd44330b0bac35e457f8b2d --- /dev/null +++ b/src/assets/img/credential-declined.svg @@ -0,0 +1,16 @@ +<svg id="Group_2284" data-name="Group 2284" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="250" height="250" viewBox="0 0 250 250"> + <defs> + <clipPath id="clip-path"> + <rect id="Rectangle_1624" data-name="Rectangle 1624" width="250" height="250" fill="none"/> + </clipPath> + </defs> + <g id="Group_2283" data-name="Group 2283" clip-path="url(#clip-path)"> + <path id="Path_584" data-name="Path 584" d="M189.942,147.681H16.307A14.307,14.307,0,0,1,2,133.375V26.474A14.308,14.308,0,0,1,16.308,12.166H189.942A14.307,14.307,0,0,1,204.25,26.474v106.9a14.307,14.307,0,0,1-14.307,14.306" transform="translate(21.875 21.742)" fill="#f9f1c6"/> + <path id="Rectangle_1622" data-name="Rectangle 1622" d="M13.865,0h174.52A13.865,13.865,0,0,1,202.25,13.865V121.65a13.866,13.866,0,0,1-13.866,13.866H13.865A13.865,13.865,0,0,1,0,121.652V13.865A13.865,13.865,0,0,1,13.865,0Z" transform="translate(23.875 33.908)" fill="none" stroke="#fcba19" stroke-linejoin="round" stroke-width="4"/> + <line id="Line_73" data-name="Line 73" x2="97.331" transform="translate(47.639 113.491)" fill="none" stroke="#fcba19" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <rect id="Rectangle_1623" data-name="Rectangle 1623" width="202.25" height="22.261" transform="translate(23.875 69.315)" fill="#fcba19"/> + <path id="Path_585" data-name="Path 585" d="M101.193,108.832a38.6,38.6,0,1,0,38.6,38.6,38.6,38.6,0,0,0-38.6-38.6" transform="translate(23.807 24.824)" fill="#f2dede"/> + <path id="Path_586" data-name="Path 586" d="M101.193,108.832a38.6,38.6,0,1,0,38.6,38.6A38.6,38.6,0,0,0,101.193,108.832Z" transform="translate(23.807 24.824)" fill="none" stroke="#a12622" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_587" data-name="Path 587" d="M111.137,162.805l-10.483-10.483L90.471,162.5a4.133,4.133,0,0,1-5.845-5.845l10.183-10.183L84.928,136.6a4.133,4.133,0,0,1,5.845-5.845l9.881,9.881,10.183-10.183a4.133,4.133,0,0,1,5.845,5.845L106.5,146.478l10.483,10.483a4.133,4.133,0,1,1-5.845,5.845" transform="translate(24.471 25.475)" fill="#a12622"/> + </g> +</svg> diff --git a/src/assets/img/credential-pending.svg b/src/assets/img/credential-pending.svg new file mode 100644 index 0000000000000000000000000000000000000000..4979d01740cbacddd2410965344865d782c26259 --- /dev/null +++ b/src/assets/img/credential-pending.svg @@ -0,0 +1,69 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="250" height="250" viewBox="0 0 250 250"> + <defs> + <clipPath id="clip-path"> + <rect id="Rectangle_1583" data-name="Rectangle 1583" width="250" height="250" fill="none"/> + </clipPath> + <clipPath id="clip-path-3"> + <rect id="Rectangle_1578" data-name="Rectangle 1578" width="5" height="32.021" fill="none"/> + </clipPath> + <clipPath id="clip-path-4"> + <rect id="Rectangle_1579" data-name="Rectangle 1579" width="5" height="27.66" fill="none"/> + </clipPath> + <clipPath id="clip-path-5"> + <rect id="Rectangle_1580" data-name="Rectangle 1580" width="5" height="17.766" fill="none"/> + </clipPath> + <clipPath id="clip-path-6"> + <rect id="Rectangle_1581" data-name="Rectangle 1581" width="5" height="12.235" fill="none"/> + </clipPath> + </defs> + <g id="Group_2212" data-name="Group 2212" transform="translate(-0.5 -0.5)"> + <g id="Group_2211" data-name="Group 2211" transform="translate(0.5 0.5)" clip-path="url(#clip-path)"> + <g id="Group_2210" data-name="Group 2210"> + <g id="Group_2209" data-name="Group 2209" clip-path="url(#clip-path)"> + <path id="Path_511" data-name="Path 511" d="M134.007,172.22v3.25a14.4,14.4,0,0,0,14.387,14.4h25.588v15.038a8.81,8.81,0,0,1-8.812,8.812H54.632a8.81,8.81,0,0,1-8.812-8.812V120.32a8.81,8.81,0,0,0,8.813,8.813H165.169a8.818,8.818,0,0,1,8.813,8.813v19.887H148.394a14.39,14.39,0,0,0-14.387,14.387" transform="translate(10.987 29.612)" fill="#8099b3"/> + <path id="Path_512" data-name="Path 512" d="M134.007,172.22v3.25a14.4,14.4,0,0,0,14.387,14.4h25.588v15.038a8.81,8.81,0,0,1-8.812,8.812H54.632a8.81,8.81,0,0,1-8.812-8.812V120.32a8.81,8.81,0,0,0,8.813,8.813H165.169a8.818,8.818,0,0,1,8.813,8.813v19.887H148.394A14.39,14.39,0,0,0,134.007,172.22Z" transform="translate(10.987 29.612)" fill="none" stroke="#036" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_513" data-name="Path 513" d="M147.544,122.082V130.9H54.63a8.813,8.813,0,0,1,0-17.625h84.1a8.819,8.819,0,0,1,8.814,8.812" transform="translate(10.987 27.849)" fill="#335c85"/> + <path id="Path_514" data-name="Path 514" d="M147.544,122.082V130.9H54.63a8.813,8.813,0,0,1,0-17.625h84.1A8.819,8.819,0,0,1,147.544,122.082Z" transform="translate(10.987 27.849)" fill="none" stroke="#036" stroke-linecap="round" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_515" data-name="Path 515" d="M163.63,150.33v32.038H130.756a14.4,14.4,0,0,1-14.388-14.4v-3.25a14.39,14.39,0,0,1,14.388-14.387Z" transform="translate(28.624 37.114)" fill="#8099b3"/> + <path id="Path_516" data-name="Path 516" d="M163.63,150.33v32.038H130.756a14.4,14.4,0,0,1-14.388-14.4v-3.25a14.39,14.39,0,0,1,14.388-14.387Z" transform="translate(28.624 37.114)" fill="none" stroke="#036" stroke-linejoin="round" stroke-width="4"/> + <circle id="Ellipse_62" data-name="Ellipse 62" cx="5.166" cy="5.166" r="5.166" transform="translate(155.32 198.288)" fill="none" stroke="#036" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_517" data-name="Path 517" d="M154.272,112.732H61.5a7.643,7.643,0,0,1-7.644-7.644V47.971A7.644,7.644,0,0,1,61.5,40.327h92.771a7.644,7.644,0,0,1,7.644,7.645v57.116a7.644,7.644,0,0,1-7.644,7.644" transform="translate(12.996 9.614)" fill="#f9f1c6"/> + <rect id="Rectangle_1576" data-name="Rectangle 1576" width="108.059" height="72.405" rx="6.115" transform="translate(66.854 49.94)" fill="none" stroke="#fcba19" stroke-linejoin="round" stroke-width="4"/> + <line id="Line_57" data-name="Line 57" x2="52.002" transform="translate(79.55 92.461)" fill="none" stroke="#fcba19" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <rect id="Rectangle_1577" data-name="Rectangle 1577" width="108.06" height="11.894" transform="translate(66.853 68.858)" fill="#fcba19"/> + <line id="Line_58" data-name="Line 58" y1="27.021" transform="translate(90.245 13.441)" fill="none" stroke="#036" stroke-linecap="round" stroke-miterlimit="10" stroke-width="4"/> + <g id="Group_2199" data-name="Group 2199" transform="translate(149.022 10.942)" opacity="0.5"> + <g id="Group_2198" data-name="Group 2198"> + <g id="Group_2197" data-name="Group 2197" clip-path="url(#clip-path-3)"> + <line id="Line_59" data-name="Line 59" y1="27.021" transform="translate(2.499 2.5)" fill="none" stroke="#036" stroke-linecap="round" stroke-miterlimit="10" stroke-width="4"/> + </g> + </g> + </g> + <line id="Line_60" data-name="Line 60" y1="6.382" transform="translate(136.388 34.08)" fill="none" stroke="#036" stroke-linecap="round" stroke-miterlimit="10" stroke-width="4"/> + <line id="Line_61" data-name="Line 61" y1="19.361" transform="translate(136.388 6.208)" fill="none" stroke="#036" stroke-linecap="round" stroke-miterlimit="10" stroke-width="4"/> + <g id="Group_2202" data-name="Group 2202" transform="translate(117.051 15.303)" opacity="0.75"> + <g id="Group_2201" data-name="Group 2201"> + <g id="Group_2200" data-name="Group 2200" clip-path="url(#clip-path-4)"> + <line id="Line_62" data-name="Line 62" y1="22.66" transform="translate(2.5 2.5)" fill="none" stroke="#036" stroke-linecap="round" stroke-miterlimit="10" stroke-width="4"/> + </g> + </g> + </g> + <g id="Group_2205" data-name="Group 2205" transform="translate(100.191 25.197)" opacity="0.5"> + <g id="Group_2204" data-name="Group 2204"> + <g id="Group_2203" data-name="Group 2203" clip-path="url(#clip-path-5)"> + <line id="Line_63" data-name="Line 63" y1="12.766" transform="translate(2.5 2.5)" fill="none" stroke="#036" stroke-linecap="round" stroke-miterlimit="10" stroke-width="4"/> + </g> + </g> + </g> + <g id="Group_2208" data-name="Group 2208" transform="translate(100.191 3.707)" opacity="0.5"> + <g id="Group_2207" data-name="Group 2207"> + <g id="Group_2206" data-name="Group 2206" clip-path="url(#clip-path-6)"> + <line id="Line_64" data-name="Line 64" y1="7.234" transform="translate(2.5 2.501)" fill="none" stroke="#036" stroke-linecap="round" stroke-miterlimit="10" stroke-width="4"/> + </g> + </g> + </g> + </g> + </g> + </g> + </g> +</svg> diff --git a/src/assets/img/credential-success.svg b/src/assets/img/credential-success.svg new file mode 100644 index 0000000000000000000000000000000000000000..7e518f17ed1fad7d808323e6186973f5cc988483 --- /dev/null +++ b/src/assets/img/credential-success.svg @@ -0,0 +1,23 @@ +<svg id="Group_2214" data-name="Group 2214" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="250" height="250" viewBox="0 0 250 250"> + <defs> + <clipPath id="clip-path"> + <rect id="Rectangle_1586" data-name="Rectangle 1586" width="250" height="250" fill="none"/> + </clipPath> + </defs> + <g id="Group_2213" data-name="Group 2213" clip-path="url(#clip-path)"> + <path id="Path_518" data-name="Path 518" d="M147.544,122.082V130.9H54.63a8.813,8.813,0,0,1,0-17.625h84.1a8.819,8.819,0,0,1,8.814,8.813" transform="translate(11.455 28.317)" fill="#335c85"/> + <path id="Path_519" data-name="Path 519" d="M147.544,122.082V130.9H54.63a8.813,8.813,0,0,1,0-17.625h84.1A8.819,8.819,0,0,1,147.544,122.082Z" transform="translate(11.455 28.317)" fill="none" stroke="#036" stroke-linecap="round" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_520" data-name="Path 520" d="M154.272,160.469H61.5a7.643,7.643,0,0,1-7.644-7.644V95.708A7.644,7.644,0,0,1,61.5,88.064h92.771a7.644,7.644,0,0,1,7.644,7.645v57.116a7.644,7.644,0,0,1-7.644,7.644" transform="translate(13.464 22.016)" fill="#f9f1c6"/> + <rect id="Rectangle_1584" data-name="Rectangle 1584" width="108.059" height="72.405" rx="6.115" transform="translate(67.322 110.079)" fill="none" stroke="#fcba19" stroke-linejoin="round" stroke-width="4"/> + <line id="Line_65" data-name="Line 65" x2="52.002" transform="translate(80.018 152.6)" fill="none" stroke="#fcba19" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <rect id="Rectangle_1585" data-name="Rectangle 1585" width="108.06" height="11.894" transform="translate(67.321 128.997)" fill="#fcba19"/> + <path id="Path_521" data-name="Path 521" d="M134.007,172.22v3.25a14.4,14.4,0,0,0,14.388,14.4h25.587v15.037a8.81,8.81,0,0,1-8.812,8.812H54.632a8.81,8.81,0,0,1-8.812-8.812V120.32a8.81,8.81,0,0,0,8.813,8.813H165.169a8.818,8.818,0,0,1,8.813,8.812v19.888H148.394a14.39,14.39,0,0,0-14.388,14.387" transform="translate(11.455 30.08)" fill="#8099b3"/> + <path id="Path_522" data-name="Path 522" d="M134.007,172.22v3.25a14.4,14.4,0,0,0,14.388,14.4h25.587v15.037a8.81,8.81,0,0,1-8.812,8.812H54.632a8.81,8.81,0,0,1-8.812-8.812V120.32a8.81,8.81,0,0,0,8.813,8.813H165.169a8.818,8.818,0,0,1,8.813,8.812v19.888H148.394A14.39,14.39,0,0,0,134.007,172.22Z" transform="translate(11.455 30.08)" fill="none" stroke="#036" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_523" data-name="Path 523" d="M163.63,150.33v32.038H130.756a14.4,14.4,0,0,1-14.388-14.4v-3.25a14.39,14.39,0,0,1,14.388-14.387Z" transform="translate(29.092 37.583)" fill="#8099b3"/> + <path id="Path_524" data-name="Path 524" d="M163.63,150.33v32.038H130.756a14.4,14.4,0,0,1-14.388-14.4v-3.25a14.39,14.39,0,0,1,14.388-14.387Z" transform="translate(29.092 37.583)" fill="none" stroke="#036" stroke-linejoin="round" stroke-width="4"/> + <circle id="Ellipse_63" data-name="Ellipse 63" cx="5.166" cy="5.166" r="5.166" transform="translate(155.788 198.756)" fill="none" stroke="#036" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_525" data-name="Path 525" d="M123.628,60.639a19.69,19.69,0,1,1-19.69-19.69,19.69,19.69,0,0,1,19.69,19.69" transform="translate(21.062 10.237)" fill="#dff0d8"/> + <circle id="Ellipse_64" data-name="Ellipse 64" cx="19.69" cy="19.69" r="19.69" transform="translate(105.31 51.187)" fill="none" stroke="#2d4821" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_527" data-name="Path 527" d="M92.811,59.264l7.079,7.079L112.464,51.49" transform="translate(23.203 12.873)" fill="none" stroke="#2d4821" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + </g> +</svg> diff --git a/src/assets/img/proof-declined.svg b/src/assets/img/proof-declined.svg new file mode 100644 index 0000000000000000000000000000000000000000..b8df4cccdec22cdcc9295bb3fad18c9eedb1db5f --- /dev/null +++ b/src/assets/img/proof-declined.svg @@ -0,0 +1,20 @@ +<svg id="Group_2359" data-name="Group 2359" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="250" height="250" viewBox="0 0 250 250"> + <defs> + <clipPath id="clip-path"> + <rect id="Rectangle_1644" data-name="Rectangle 1644" width="250" height="250" fill="none"/> + </clipPath> + </defs> + <path id="Path_631" data-name="Path 631" d="M88.616,84.015l11.522-11.522,11.575,11.576" transform="translate(25.046 19.237)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <line id="Line_97" data-name="Line 97" y2="41" transform="translate(125 93.5)" fill="none" stroke="#036" stroke-linejoin="round" stroke-width="4" stroke-dasharray="8 4"/> + <g id="Group_2358" data-name="Group 2358"> + <g id="Group_2357" data-name="Group 2357" clip-path="url(#clip-path)"> + <path id="Path_632" data-name="Path 632" d="M107.8,2.594a38.989,38.989,0,1,0,38.989,38.99A38.99,38.99,0,0,0,107.8,2.594" transform="translate(17.202 0.649)" fill="#f2dede"/> + <circle id="Ellipse_67" data-name="Ellipse 67" cx="38.989" cy="38.989" r="38.989" transform="translate(86.011 3.243)" fill="none" stroke="#a12622" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_633" data-name="Path 633" d="M113.95,53.639,103.361,43.05,93.075,53.335a4.175,4.175,0,0,1-5.9-5.9L97.458,37.145l-9.983-9.981a4.175,4.175,0,0,1,5.9-5.9l9.982,9.981,10.285-10.285a4.175,4.175,0,0,1,5.9,5.9L109.265,37.145l10.589,10.59a4.175,4.175,0,0,1-5.9,5.9" transform="translate(21.487 4.934)" fill="#a12622"/> + <path id="Path_634" data-name="Path 634" d="M188.528,220.033H44.924A11.832,11.832,0,0,1,33.092,208.2V119.788a11.832,11.832,0,0,1,11.833-11.832h143.6a11.832,11.832,0,0,1,11.833,11.832V208.2a11.832,11.832,0,0,1-11.833,11.833" transform="translate(8.273 26.989)" fill="#f9f1c6"/> + <rect id="Rectangle_1642" data-name="Rectangle 1642" width="167.269" height="112.077" rx="9.466" transform="translate(41.366 134.945)" fill="none" stroke="#fcba19" stroke-linejoin="round" stroke-width="4"/> + <line id="Line_98" data-name="Line 98" x2="80.496" transform="translate(61.019 200.763)" fill="none" stroke="#fcba19" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <rect id="Rectangle_1643" data-name="Rectangle 1643" width="167.27" height="18.411" transform="translate(41.365 164.228)" fill="#fcba19"/> + </g> + </g> +</svg> diff --git a/src/assets/img/proof-pending.svg b/src/assets/img/proof-pending.svg new file mode 100644 index 0000000000000000000000000000000000000000..d1ad68a4e048f6f831340f76b53c98752f340cde --- /dev/null +++ b/src/assets/img/proof-pending.svg @@ -0,0 +1,27 @@ +<svg id="Group_2444" data-name="Group 2444" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="250" height="250" viewBox="0 0 250 250"> + <defs> + <clipPath id="clip-path"> + <rect id="Rectangle_1660" data-name="Rectangle 1660" width="250" height="250" fill="none"/> + </clipPath> + </defs> + <g id="Group_2443" data-name="Group 2443" clip-path="url(#clip-path)"> + <path id="Path_640" data-name="Path 640" d="M147.493,92.682v65.5a39.263,39.263,0,1,1-78.526,0V111.907a3.557,3.557,0,0,1,3.552-3.553h1.605A10.552,10.552,0,0,1,84.669,118.91V76.854a7.857,7.857,0,0,1,15.714,0V69.029a7.852,7.852,0,0,1,15.7,0v7.825a7.851,7.851,0,0,1,15.7,0V92.682a7.852,7.852,0,1,1,15.7,0" transform="translate(17.242 15.293)" fill="#8099b3"/> + <path id="Path_641" data-name="Path 641" d="M128.648,162.507H81.531v38.976s5.4,7.89,23.559,7.89,23.559-7.89,23.559-7.89Z" transform="translate(20.383 40.627)" fill="#8099b3"/> + <path id="Path_642" data-name="Path 642" d="M81.531,117.345V75.281a7.853,7.853,0,0,1,15.706,0" transform="translate(20.383 16.857)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_643" data-name="Path 643" d="M119.225,87.945a7.853,7.853,0,0,1,15.705,0v46.714" transform="translate(29.806 20.023)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_644" data-name="Path 644" d="M106.66,75.281a7.853,7.853,0,0,1,15.706,0v51.308" transform="translate(26.665 16.857)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_645" data-name="Path 645" d="M94.1,123.56V69.025a7.853,7.853,0,1,1,15.706,0V123.56" transform="translate(23.524 15.293)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_646" data-name="Path 646" d="M68.966,117.3v26.849a39.264,39.264,0,0,0,78.529,0V117.3" transform="translate(17.242 29.325)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <line id="Line_115" data-name="Line 115" y2="35.632" transform="translate(149.031 205.649)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <line id="Line_116" data-name="Line 116" y1="35.632" transform="translate(101.914 205.649)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_647" data-name="Path 647" d="M171.96,139.66H58.916a9.314,9.314,0,0,1-9.315-9.315v-69.6a9.315,9.315,0,0,1,9.315-9.315H171.96a9.315,9.315,0,0,1,9.315,9.315v69.6a9.315,9.315,0,0,1-9.315,9.315" transform="translate(12.4 12.858)" fill="#f9f1c6"/> + <rect id="Rectangle_1658" data-name="Rectangle 1658" width="131.674" height="88.227" rx="7.452" transform="translate(62.001 64.291)" fill="none" stroke="#fcba19" stroke-linejoin="round" stroke-width="4"/> + <line id="Line_117" data-name="Line 117" x2="63.366" transform="translate(77.472 116.103)" fill="none" stroke="#fcba19" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <rect id="Rectangle_1659" data-name="Rectangle 1659" width="131.674" height="14.493" transform="translate(62.001 87.343)" fill="#fcba19"/> + <path id="Path_648" data-name="Path 648" d="M108.231,154.94a23.559,23.559,0,0,0-23.559-23.559V109.466A10.551,10.551,0,0,0,74.121,98.915h-1.6a3.554,3.554,0,0,0-3.554,3.554v40.459" transform="translate(17.242 24.729)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_649" data-name="Path 649" d="M108.231,154.94a23.559,23.559,0,0,0-23.559-23.559V109.466A10.551,10.551,0,0,0,74.121,98.915h-1.6a3.554,3.554,0,0,0-3.554,3.554v40.459" transform="translate(17.242 24.729)" fill="#8099b3"/> + <path id="Path_650" data-name="Path 650" d="M108.231,154.94a23.559,23.559,0,0,0-23.559-23.559V109.466A10.551,10.551,0,0,0,74.121,98.915h-1.6a3.554,3.554,0,0,0-3.554,3.554v40.459" transform="translate(17.242 24.729)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_655" data-name="Path 655" d="M133.563,89.116a6.112,6.112,0,0,0-6.1,6.105v3.868h3.18V95.117a2.894,2.894,0,1,1,5.789,0v3.971h3.243V95.221a6.112,6.112,0,0,0-6.106-6.105" transform="translate(31.865 22.279)" fill="#036"/> + <path id="Path_656" data-name="Path 656" d="M144.828,96.594H124.471a1.481,1.481,0,0,0-1.481,1.481v14.4a1.481,1.481,0,0,0,1.481,1.481h20.356a1.48,1.48,0,0,0,1.481-1.481v-14.4a1.48,1.48,0,0,0-1.481-1.481m-9.055,9.891v2.647a.45.45,0,0,1-.45.45h-1.345a.451.451,0,0,1-.451-.45v-2.647a2.874,2.874,0,1,1,2.246,0" transform="translate(30.747 24.149)" fill="#036"/> + </g> +</svg> diff --git a/src/assets/img/proof-success.svg b/src/assets/img/proof-success.svg new file mode 100644 index 0000000000000000000000000000000000000000..72c51345edf3f41b0e33b4a414e2aa3a1782ed6a --- /dev/null +++ b/src/assets/img/proof-success.svg @@ -0,0 +1,31 @@ +<svg id="Group_2444" data-name="Group 2444" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="250" height="250" viewBox="0 0 250 250"> + <defs> + <clipPath id="clip-path"> + <rect id="Rectangle_1660" data-name="Rectangle 1660" width="250" height="250" fill="none"/> + </clipPath> + </defs> + <g id="Group_2443" data-name="Group 2443" clip-path="url(#clip-path)"> + <path id="Path_640" data-name="Path 640" d="M147.493,92.682v65.5a39.263,39.263,0,1,1-78.526,0V111.907a3.557,3.557,0,0,1,3.552-3.553h1.605A10.552,10.552,0,0,1,84.669,118.91V76.854a7.857,7.857,0,0,1,15.714,0V69.029a7.852,7.852,0,0,1,15.7,0v7.825a7.851,7.851,0,0,1,15.7,0V92.682a7.852,7.852,0,1,1,15.7,0" transform="translate(17.242 15.293)" fill="#8099b3"/> + <path id="Path_641" data-name="Path 641" d="M128.648,162.507H81.531v38.976s5.4,7.89,23.559,7.89,23.559-7.89,23.559-7.89Z" transform="translate(20.383 40.627)" fill="#8099b3"/> + <path id="Path_642" data-name="Path 642" d="M81.531,117.345V75.281a7.853,7.853,0,0,1,15.706,0" transform="translate(20.383 16.857)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_643" data-name="Path 643" d="M119.225,87.945a7.853,7.853,0,0,1,15.705,0v46.714" transform="translate(29.806 20.023)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_644" data-name="Path 644" d="M106.66,75.281a7.853,7.853,0,0,1,15.706,0v51.308" transform="translate(26.665 16.857)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_645" data-name="Path 645" d="M94.1,123.56V69.025a7.853,7.853,0,1,1,15.706,0V123.56" transform="translate(23.524 15.293)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_646" data-name="Path 646" d="M68.966,117.3v26.849a39.264,39.264,0,0,0,78.529,0V117.3" transform="translate(17.242 29.325)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <line id="Line_115" data-name="Line 115" y2="35.632" transform="translate(149.031 205.649)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <line id="Line_116" data-name="Line 116" y1="35.632" transform="translate(101.914 205.649)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_647" data-name="Path 647" d="M171.96,139.66H58.916a9.314,9.314,0,0,1-9.315-9.315v-69.6a9.315,9.315,0,0,1,9.315-9.315H171.96a9.315,9.315,0,0,1,9.315,9.315v69.6a9.315,9.315,0,0,1-9.315,9.315" transform="translate(12.4 12.858)" fill="#f9f1c6"/> + <rect id="Rectangle_1658" data-name="Rectangle 1658" width="131.674" height="88.227" rx="7.452" transform="translate(62.001 64.291)" fill="none" stroke="#fcba19" stroke-linejoin="round" stroke-width="4"/> + <line id="Line_117" data-name="Line 117" x2="63.366" transform="translate(77.472 116.103)" fill="none" stroke="#fcba19" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <rect id="Rectangle_1659" data-name="Rectangle 1659" width="131.674" height="14.493" transform="translate(62.001 87.343)" fill="#fcba19"/> + <path id="Path_648" data-name="Path 648" d="M108.231,154.94a23.559,23.559,0,0,0-23.559-23.559V109.466A10.551,10.551,0,0,0,74.121,98.915h-1.6a3.554,3.554,0,0,0-3.554,3.554v40.459" transform="translate(17.242 24.729)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_649" data-name="Path 649" d="M108.231,154.94a23.559,23.559,0,0,0-23.559-23.559V109.466A10.551,10.551,0,0,0,74.121,98.915h-1.6a3.554,3.554,0,0,0-3.554,3.554v40.459" transform="translate(17.242 24.729)" fill="#8099b3"/> + <path id="Path_650" data-name="Path 650" d="M108.231,154.94a23.559,23.559,0,0,0-23.559-23.559V109.466A10.551,10.551,0,0,0,74.121,98.915h-1.6a3.554,3.554,0,0,0-3.554,3.554v40.459" transform="translate(17.242 24.729)" fill="none" stroke="#036" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_651" data-name="Path 651" d="M125.9,21.8a19.689,19.689,0,1,1-19.69-19.69A19.69,19.69,0,0,1,125.9,21.8" transform="translate(21.63 0.527)" fill="#dff0d8"/> + <path id="Path_652" data-name="Path 652" d="M125.9,21.8a19.689,19.689,0,1,1-19.69-19.69A19.69,19.69,0,0,1,125.9,21.8Z" transform="translate(21.63 0.527)" fill="none" stroke="#2d4821" stroke-miterlimit="10" stroke-width="4"/> + <path id="Path_653" data-name="Path 653" d="M95.081,20.422,102.16,27.5l12.574-14.853" transform="translate(23.77 3.162)" fill="#dff0d8"/> + <path id="Path_654" data-name="Path 654" d="M95.081,20.422,102.16,27.5l12.574-14.853" transform="translate(23.77 3.162)" fill="none" stroke="#2d4821" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <path id="Path_655" data-name="Path 655" d="M133.563,89.116a6.112,6.112,0,0,0-6.1,6.105v3.868h3.18V95.117a2.894,2.894,0,1,1,5.789,0v3.971h3.243V95.221a6.112,6.112,0,0,0-6.106-6.105" transform="translate(31.865 22.279)" fill="#036"/> + <path id="Path_656" data-name="Path 656" d="M144.828,96.594H124.471a1.481,1.481,0,0,0-1.481,1.481v14.4a1.481,1.481,0,0,0,1.481,1.481h20.356a1.48,1.48,0,0,0,1.481-1.481v-14.4a1.48,1.48,0,0,0-1.481-1.481m-9.055,9.891v2.647a.45.45,0,0,1-.45.45h-1.345a.451.451,0,0,1-.451-.45v-2.647a2.874,2.874,0,1,1,2.246,0" transform="translate(30.747 24.149)" fill="#036"/> + </g> +</svg> diff --git a/src/assets/import.png b/src/assets/import.png new file mode 100644 index 0000000000000000000000000000000000000000..677d406c3f54467e266e1c5895f9a1b8c6139b33 Binary files /dev/null and b/src/assets/import.png differ diff --git a/src/assets/index.ts b/src/assets/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..be374937c949b545bb778e38f6ffd60f0df5ce9b --- /dev/null +++ b/src/assets/index.ts @@ -0,0 +1,21 @@ +const Images = { + infoIcon: require('./info-icon.png'), + termsIcon: require('./terms-icon.png'), + termsAcceptedIcon: require('./terms-accepted.png'), + homeIcon: require('./home-icon.png'), + connectionsIcon: require('./connections-icon.png'), + credentialsIcon: require('./credentials-icon.png'), + scanIcon: require('./scan-icon.png'), + settingsIcon: require('./settings-icon.png'), + loaderIcon: require('./loader.png'), + pinIcon: require('./pin.png'), + biometricIcon: require('./biometric.png'), + importIcon: require('./import.png'), + initializeIcon: require('./initialize.png'), + walletInitializedIcon: require('./walletinitialized.png'), + secureImage: require('./secure-image.png'), + scanToConnectImage: require('./scan-to-connect.png'), + credentialListImage: require('./credentials.png'), +}; + +export default Images; diff --git a/src/assets/info-icon.png b/src/assets/info-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e0eb24c4ce24cb781d0b041c005c3a97ccff6ba7 Binary files /dev/null and b/src/assets/info-icon.png differ diff --git a/src/assets/initialize.png b/src/assets/initialize.png new file mode 100644 index 0000000000000000000000000000000000000000..54d61154fcb2c22f57604cdfd17ff5cb19e94bf4 Binary files /dev/null and b/src/assets/initialize.png differ diff --git a/src/assets/loader.png b/src/assets/loader.png new file mode 100644 index 0000000000000000000000000000000000000000..4be5b5229b6879350d8cee9bb95f5504890f7a88 Binary files /dev/null and b/src/assets/loader.png differ diff --git a/src/assets/pin.png b/src/assets/pin.png new file mode 100644 index 0000000000000000000000000000000000000000..311a8a9096c22f3d0bf041c7b3ffcc0f0547cb15 Binary files /dev/null and b/src/assets/pin.png differ diff --git a/src/assets/scan-icon.png b/src/assets/scan-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..64f3546757156f2694e92486efc8ce80cbe28865 Binary files /dev/null and b/src/assets/scan-icon.png differ diff --git a/src/assets/scan-to-connect.png b/src/assets/scan-to-connect.png new file mode 100644 index 0000000000000000000000000000000000000000..abe7f8c9d816314a8e75d79fef9670ecbbd7f8eb Binary files /dev/null and b/src/assets/scan-to-connect.png differ diff --git a/src/assets/secure-image.png b/src/assets/secure-image.png new file mode 100644 index 0000000000000000000000000000000000000000..472235c111ddf1cb8e01f16b0b1ebb64bfb3f056 Binary files /dev/null and b/src/assets/secure-image.png differ diff --git a/src/assets/settings-icon.png b/src/assets/settings-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f048158ac787f786e1eb35b7e959531e797da018 Binary files /dev/null and b/src/assets/settings-icon.png differ diff --git a/src/assets/terms-accepted.png b/src/assets/terms-accepted.png new file mode 100644 index 0000000000000000000000000000000000000000..c959b97a9ad09a0d30afd58983f9b86161395808 Binary files /dev/null and b/src/assets/terms-accepted.png differ diff --git a/src/assets/terms-icon.png b/src/assets/terms-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a9aceaa6ae60158fc8ee238f3a5864e726f68912 Binary files /dev/null and b/src/assets/terms-icon.png differ diff --git a/src/assets/walletinitialized.png b/src/assets/walletinitialized.png new file mode 100644 index 0000000000000000000000000000000000000000..9da7952377b3fd6775af6e76c36343259f0e8524 Binary files /dev/null and b/src/assets/walletinitialized.png differ diff --git a/src/components/accordion/Accordion.tsx b/src/components/accordion/Accordion.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c2be25ca59842386b2d341da60b0aeb74810d7e4 --- /dev/null +++ b/src/components/accordion/Accordion.tsx @@ -0,0 +1,160 @@ +import React, { useState, ReactNode } from 'react'; +import { + View, + Text, + LayoutAnimation, + StyleSheet, + UIManager, + Platform, + TouchableOpacity, +} from 'react-native'; +import Icon from 'react-native-vector-icons/Ionicons'; +import { ColorPallet, TextTheme } from '../../theme/theme'; + +if (Platform.OS === 'android') { + if (UIManager.setLayoutAnimationEnabledExperimental) { + UIManager.setLayoutAnimationEnabledExperimental(true); + } +} + +interface AccordionProps { + title: string; + innerAccordion: boolean; + date?: Date; + status?: string; + children?: ReactNode; +} + +const Accordion: React.FC<AccordionProps> = ({ + title, + children, + innerAccordion, + date = new Date(), + status = '', +}) => { + const [isOpen, setIsOpen] = useState(false); + + const toggleOpen = () => { + setIsOpen(value => !value); + LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); + }; + + const getFormattedDate = (date: Date) => { + return [date.getDate(), date.getMonth() + 1, date.getFullYear()] + .map(n => (n < 10 ? `0${n}` : `${n}`)) + .join('-'); + }; + + return ( + <> + <TouchableOpacity + onPress={toggleOpen} + style={styles.heading} + activeOpacity={0.6} + > + {!innerAccordion ? ( + <> + <Text style={styles.sectionTitle}>{title}</Text> + <Icon + name={isOpen ? 'chevron-up-outline' : 'chevron-down-outline'} + size={18} + color="black" + /> + </> + ) : ( + <> + <View style={styles.innerAccordionView}> + <View> + <Text style={styles.sectionTitle}>{title}</Text> + <Text style={styles.sectionSubTitle}>{status}</Text> + </View> + </View> + <View style={styles.sectionDateTime}> + <View> + <Text style={styles.sectionTitle}> + {getFormattedDate(date)} + </Text> + <Text style={styles.sectionSubTitle}> + {date.toLocaleTimeString()} + </Text> + </View> + <Icon + name={isOpen ? 'chevron-up-outline' : 'chevron-down-outline'} + size={18} + color="black" + style={styles.icon} + /> + </View> + </> + )} + </TouchableOpacity> + <View style={[styles.list, !isOpen && styles.hidden]}>{children}</View> + </> + ); +}; + +export default Accordion; + +const styles = StyleSheet.create({ + card: { + backgroundColor: ColorPallet.baseColors.white, + borderRadius: 15, + elevation: 10, + padding: 10, + }, + cardIos: { + backgroundColor: ColorPallet.baseColors.white, + shadowColor: ColorPallet.baseColors.white, + shadowOffset: { + width: 0, + height: 6, + }, + shadowOpacity: 0.39, + shadowRadius: 8.3, + borderRadius: 15, + padding: 10, + }, + text: { + fontSize: 18, + marginBottom: 20, + }, + innerAccordionView: { + flexDirection: 'row', + }, + icon: { + alignSelf: 'center', + marginLeft: 10, + }, + circle: { + backgroundColor: ColorPallet.brand.primary, + height: 40, + width: 40, + borderRadius: 20, + marginRight: 10, + }, + heading: { + alignItems: 'center', + flexDirection: 'row', + justifyContent: 'space-between', + paddingVertical: 10, + }, + hidden: { + height: 0, + }, + list: { + overflow: 'hidden', + }, + sectionDateTime: { + flexDirection: 'row', + justifyContent: 'flex-end', + }, + sectionTitle: { + ...TextTheme.normal, + fontWeight: 'bold', + color: ColorPallet.brand.primary, + }, + sectionSubTitle: { + ...TextTheme.caption, + color: ColorPallet.baseColors.black, + }, +}); diff --git a/src/components/button/Button.tsx b/src/components/button/Button.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5d0dea746de7c58eae7bb043164a3260535da477 --- /dev/null +++ b/src/components/button/Button.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { ViewStyle } from 'react-native'; + +import AntButton from '@ant-design/react-native/lib/button'; + +export enum ButtonType { + Primary = 'primary', + Warning = 'warning', + Ghost = 'ghost', +} + +interface ButtonProps { + title: string; + buttonType: ButtonType; + onPress?: () => void; + disabled?: boolean; + buttonStyle?: ViewStyle; +} + +const Button: React.FC<ButtonProps> = ({ + title, + buttonType = ButtonType.Primary, + buttonStyle, + onPress, + disabled = false, +}) => { + return ( + <AntButton + testID="button" + accessibilityLabel={title} + type={buttonType} + style={buttonStyle} + disabled={disabled} + onPress={onPress} + > + {title} + </AntButton> + ); +}; + +export default Button; diff --git a/src/components/button/__tests__/Button.test.tsx b/src/components/button/__tests__/Button.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..fe8478f4abe49104feb412e4eebf488b38547c74 --- /dev/null +++ b/src/components/button/__tests__/Button.test.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { render } from '@testing-library/react-native'; +import Button, { ButtonType } from '../Button'; + +describe('Button Component', () => { + it('should render primary button correctly', () => { + const { getByLabelText } = render( + <Button title="PrimaryButton" buttonType={ButtonType.Primary} />, + ); + expect(getByLabelText('PrimaryButton')).toBeTruthy(); + }); + + it('should render warning button correctly', () => { + const { getByLabelText } = render( + <Button title="WarningButton" buttonType={ButtonType.Warning} />, + ); + expect(getByLabelText('WarningButton')).toBeTruthy(); + }); + + it('should render ghost button correctly', () => { + const { getByLabelText } = render( + <Button title="GhostButton" buttonType={ButtonType.Ghost} />, + ); + expect(getByLabelText('GhostButton')).toBeTruthy(); + }); +}); diff --git a/src/components/cards/InfoCard.tsx b/src/components/cards/InfoCard.tsx new file mode 100644 index 0000000000000000000000000000000000000000..fd24cbbc7cb3b3834d1e624119ed2e5713e3e69e --- /dev/null +++ b/src/components/cards/InfoCard.tsx @@ -0,0 +1,82 @@ +import React from 'react'; +import { Image, StyleSheet, Text, View } from 'react-native'; + +import { ColorPallet, TextTheme } from '../../theme/theme'; +import Images from '../../assets'; + +export interface TextBoxProps { + children: string | React.ReactNode; + showTopIcon?: boolean; + showBottomIcon?: boolean; + errorMsg?: string; + mnemonicText?: boolean; +} + +const InfoCard: React.FC<TextBoxProps> = ({ + children, + showTopIcon = false, + showBottomIcon = false, + errorMsg, + mnemonicText = false, +}) => { + return ( + <View style={styles.container}> + {showTopIcon && ( + <View> + <Image + source={Images.infoIcon} + style={{ width: iconSize, height: iconSize }} + /> + </View> + )} + {errorMsg ? ( + <View style={styles.bottomIconContainer}> + <Text style={styles.headerText}>{errorMsg}</Text> + </View> + ) : ( + <Text + style={mnemonicText ? styles.mnemonicText : styles.headerText} + testID="InfoCard" + accessibilityLabel="InfoCard" + > + {children} + </Text> + )} + {showBottomIcon && ( + <View style={styles.bottomIconContainer}> + <Image source={Images.termsIcon} style={styles.bottomIcon} /> + </View> + )} + </View> + ); +}; + +export default InfoCard; + +const iconSize = 20; + +const styles = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.veryLightGrey, + borderRadius: 20, + padding: 20, + }, + headerText: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + marginTop: 10, + }, + mnemonicText: { + ...TextTheme.caption, + fontWeight: 'bold', + color: ColorPallet.baseColors.black, + marginTop: 10, + }, + bottomIconContainer: { + alignSelf: 'flex-start', + }, + bottomIcon: { + width: 60, + height: 60, + }, +}); diff --git a/src/components/cards/__tests__/InfoCard.test.tsx b/src/components/cards/__tests__/InfoCard.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..55d1b96383911662e193e8bb617ca16f2c9046d0 --- /dev/null +++ b/src/components/cards/__tests__/InfoCard.test.tsx @@ -0,0 +1,12 @@ +import { render } from '@testing-library/react-native'; +import React from 'react'; +import InfoCard from '../InfoCard'; + +describe('InfoCard', () => { + it('should render correctly', () => { + const { getByText } = render(<InfoCard showBottomIcon>Testing</InfoCard>); + + const infoCard = getByText('Testing'); + expect(infoCard).toBeTruthy(); + }); +}); diff --git a/src/components/checkbox/CheckBoxRow.tsx b/src/components/checkbox/CheckBoxRow.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6946f276ff2437da2959eda402a9f7eb3e1c2d14 --- /dev/null +++ b/src/components/checkbox/CheckBoxRow.tsx @@ -0,0 +1,66 @@ +import React from 'react'; +import { View, StyleSheet, TouchableOpacity, Text, Image } from 'react-native'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import Images from '../../assets'; + +import { ColorPallet, TextTheme } from '../../theme/theme'; + +interface Props { + title: string; + accessibilityLabel?: string; + checked: boolean; + onPress: () => void; +} + +const CheckBoxRow: React.FC<Props> = ({ + title, + accessibilityLabel, + checked, + onPress, +}) => { + const accessible = !!(accessibilityLabel && accessibilityLabel !== ''); + + return ( + <View style={styles.container} testID="checkBoxRowView"> + <TouchableOpacity + style={styles.container} + testID="checkBoxRow" + accessible={accessible} + accessibilityLabel={accessibilityLabel} + onPress={onPress} + > + {checked ? ( + <Image source={Images.termsAcceptedIcon} style={styles.bottomIcon} /> + ) : ( + <Icon + name="check-box-outline-blank" + size={36} + color={ColorPallet.brand.secondary} + /> + )} + <Text style={styles.text}>{title}</Text> + </TouchableOpacity> + </View> + ); +}; + +export default CheckBoxRow; + +const styles = StyleSheet.create({ + container: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + margin: 10, + }, + text: { + flexShrink: 1, + ...TextTheme.normal, + marginLeft: 10, + color: ColorPallet.baseColors.black, + }, + bottomIcon: { + width: 60, + height: 60, + }, +}); diff --git a/src/components/checkbox/__tests__/CheckBoxRow.test.tsx b/src/components/checkbox/__tests__/CheckBoxRow.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..46e741df5ba435dff9fd3515640cc4b2899a3268 --- /dev/null +++ b/src/components/checkbox/__tests__/CheckBoxRow.test.tsx @@ -0,0 +1,22 @@ +import { fireEvent, render } from '@testing-library/react-native'; +import React from 'react'; +import CheckBoxRow from '../CheckBoxRow'; + +describe('CheckBoxRow', () => { + it('should render correctly and respond when clicked on check box', () => { + const onPressMock = jest.fn(); + const { getByTestId } = render( + <CheckBoxRow + title="CheckBoxRow" + accessibilityLabel="CheckBoxRow" + checked={false} + onPress={onPressMock} + />, + ); + + const checkbox = getByTestId('checkBoxRow'); + fireEvent(checkbox, 'onPress'); + fireEvent.press(checkbox); + expect(onPressMock).toHaveBeenCalled(); + }); +}); diff --git a/src/components/iconButton/IconButton.tsx b/src/components/iconButton/IconButton.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0f0895f134b8d04bc8432fa3bfd846c0707b07e4 --- /dev/null +++ b/src/components/iconButton/IconButton.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import { StyleSheet, TouchableOpacity, View } from 'react-native'; +import Icon from 'react-native-vector-icons/AntDesign'; +import { ColorPallet } from '../../theme/theme'; + +interface IconButtonProps { + isRight?: boolean; + isDisabled?: boolean; + onPress: () => void; +} + +const IconButton: React.FC<IconButtonProps> = ({ + isRight = false, + isDisabled = false, + onPress, +}) => { + return ( + <TouchableOpacity + testID="IconButton" + onPress={isDisabled ? undefined : onPress} + style={isDisabled ? styles.disabledIconContainer : styles.iconContainer} + > + {isRight ? ( + <View> + <Icon + name="arrowright" + size={iconSize} + color={ColorPallet.baseColors.white} + /> + </View> + ) : ( + <View> + <Icon + name="arrowleft" + size={iconSize} + color={ColorPallet.baseColors.white} + /> + </View> + )} + </TouchableOpacity> + ); +}; + +export default IconButton; + +const iconSize = 30; + +const styles = StyleSheet.create({ + iconContainer: { + width: 60, + height: 60, + borderRadius: 60 / 2, + backgroundColor: ColorPallet.brand.secondary, + alignItems: 'center', + justifyContent: 'center', + }, + disabledIconContainer: { + width: 60, + height: 60, + borderRadius: 60 / 2, + backgroundColor: ColorPallet.grayscale.lightGrey, + alignItems: 'center', + justifyContent: 'center', + }, +}); diff --git a/src/components/iconButton/__tests__/IconButton.test.tsx b/src/components/iconButton/__tests__/IconButton.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..bed7bd46d2ed8f3dcda8c10b60fcd5e952ba9982 --- /dev/null +++ b/src/components/iconButton/__tests__/IconButton.test.tsx @@ -0,0 +1,15 @@ +import { fireEvent, render } from '@testing-library/react-native'; +import React from 'react'; +import IconButton from '../IconButton'; + +describe('IconButton', () => { + it('should render correctly and respond when pressed', () => { + const onPressMock = jest.fn(); + const { getByTestId } = render(<IconButton onPress={onPressMock} />); + + const iconButton = getByTestId('IconButton'); + fireEvent(iconButton, 'onPress'); + fireEvent.press(iconButton); + expect(onPressMock).toHaveBeenCalled(); + }); +}); diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..1c359234bbf2ee4acd730a2aa993e5e231f5cb5f --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,33 @@ +import HighlightTextBox from './text/HighlightTextBox'; +import Label from './text/Label'; +import Text from './text/Text'; +import Title from './text/Title'; +import TextInput from './inputs/TextInput'; +import ContactListItem from './listItems/ContactListItem'; +import SealListItem from './listItems/SealListItem'; +import NotificationListItem from './listItems/NotificationListItem'; +import SettingListItem from './listItems/SettingListItem'; +import Loader from './loader/Loader'; +import SafeAreaScrollView from './views/SafeAreaScrollView'; +import SingleSelectBlock from './inputs/SingleSelectBlock'; +import IconButton from './iconButton/IconButton'; +import ScreenNavigatorButtons from './screenNavigatorButtons/ScreenNavigatorButtons'; +import InfoCard from './cards/InfoCard'; + +export { + HighlightTextBox, + Label, + Text, + Title, + TextInput, + ContactListItem, + SealListItem, + NotificationListItem, + Loader, + SettingListItem, + SafeAreaScrollView, + SingleSelectBlock, + IconButton, + ScreenNavigatorButtons, + InfoCard, +}; diff --git a/src/components/inputs/QRScanner.tsx b/src/components/inputs/QRScanner.tsx new file mode 100644 index 0000000000000000000000000000000000000000..98cb5d0d7553764ad54c5e79701036e60366040e --- /dev/null +++ b/src/components/inputs/QRScanner.tsx @@ -0,0 +1,298 @@ +import React, { useState, ReactNode, useEffect } from 'react'; +import { useNavigation } from '@react-navigation/core'; +import { useTranslation } from 'react-i18next'; +import { + useWindowDimensions, + Vibration, + View, + StyleSheet, + Text, + Platform, + TextInput, + KeyboardAvoidingView, + TouchableOpacity, + Dimensions, + Pressable, + Keyboard, +} from 'react-native'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import { Camera, useCameraDevices } from 'react-native-vision-camera'; +import { useScanBarcodes, BarcodeFormat } from 'vision-camera-code-scanner'; +import AntDesign from 'react-native-vector-icons/AntDesign'; +import QRScannerClose from '../misc/QRScannerClose'; +import QRScannerTorch from '../misc/QRScannerTorch'; +import QrCodeScanError from '../../types/error'; +import { ColorPallet } from '../../theme/theme'; +import useKeyboard from '../../utils/keyboard'; + +interface Props { + handleCodeScan: (data: string) => Promise<void>; + textInputSubmit?: () => void; + error?: QrCodeScanError | null; + enableCameraOnError?: boolean; + url?: string; + onChangeText: (text: string) => void; +} + +const CameraViewContainer: React.FC<{ + portrait: boolean; + children?: ReactNode; +}> = ({ portrait, children }) => { + return ( + <View + style={{ + ...styles.cameraViewContainer, + flexDirection: portrait ? 'column' : 'row', + }} + > + {children} + </View> + ); +}; + +const QRScanner: React.FC<Props> = ({ + handleCodeScan, + error, + enableCameraOnError, + url, + onChangeText, + textInputSubmit, +}) => { + const navigation = useNavigation(); + const [cameraActive, setCameraActive] = useState(true); + const [torchActive, setTorchActive] = useState(false); + const [invalidQrCodes] = useState(() => new Set<string>()); + + const { keyboardHeight, isKeyBoardOpen } = useKeyboard(); + + const { width, height } = useWindowDimensions(); + const portraitMode = height > width; + const { t } = useTranslation(); + + const [hasPermission, setHasPermission] = React.useState(false); + const devices = useCameraDevices(); + const device = devices.back; + + const [frameProcessor, barcodes] = useScanBarcodes([BarcodeFormat.QR_CODE], { + checkInverted: true, + }); + + React.useEffect(() => { + (async () => { + const status = await Camera.requestCameraPermission(); + setHasPermission(status === 'authorized'); + })(); + }, []); + + useEffect(() => { + if (barcodes.length === 0 || !barcodes[0].rawValue) { + return; + } + + const data = barcodes[0].rawValue; + + if (invalidQrCodes.has(data)) { + return; + } + if (error?.data === data) { + invalidQrCodes.add(error.data); + if (enableCameraOnError) { + setCameraActive(true); + } + } + if (cameraActive) { + Vibration.vibrate(); + handleCodeScan(data); + setCameraActive(false); + } + }, [ + invalidQrCodes, + barcodes, + enableCameraOnError, + cameraActive, + error, + handleCodeScan, + ]); + + if (!hasPermission || device == null) { + return null; + } + + return ( + <Pressable + onPress={() => Keyboard.dismiss()} + style={styles.container} + testID="QRScannerTest" + > + <Camera + style={styles.container} + device={device} + isActive={true} + frameProcessor={frameProcessor} + frameProcessorFps={5} + torch={torchActive ? 'on' : 'off'} + audio={false} + // TODO + // androidCameraPermissionOptions={{ + // title: t<string>('QRScanner.PermissionToUseCamera'), + // message: t<string>('QRScanner.PermissionMessage'), + // buttonPositive: t<string>('Global.Okay'), + // buttonNegative: t<string>('Global.Cancel'), + // }} + /> + <CameraViewContainer portrait={portraitMode}> + <View style={styles.actionsView}> + <QRScannerTorch + active={torchActive} + onPress={() => setTorchActive(!torchActive)} + /> + <QRScannerClose onPress={() => navigation.goBack()} /> + </View> + <View style={styles.scanTextView}> + <Text style={styles.scanText}> + {t<string>('QRScanner.ScanMessage')} + </Text> + <Text style={styles.scanText}> + {t<string>('QRScanner.VerifyMessage')} + </Text> + </View> + {error && ( + <View style={styles.errorContainer}> + <Icon style={styles.icon} name="cancel" size={30} /> + <Text>{error.message}</Text> + </View> + )} + <View style={styles.viewFinderContainer}> + <View style={styles.viewFinder} /> + </View> + </CameraViewContainer> + <View + style={[ + styles.bottomView, + { + marginTop: + Platform.OS === 'ios' && isKeyBoardOpen + ? -keyboardHeight - 80 + : -80, + }, + ]} + > + <KeyboardAvoidingView + behavior="padding" + keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 20} + enabled={Platform.OS === 'ios'} + style={styles.rowTextInputView} + > + <TextInput + style={styles.textInputStyle} + placeholder="url" + value={url} + onChangeText={onChangeText} + placeholderTextColor={ColorPallet.baseColors.black} + /> + <TouchableOpacity + onPress={textInputSubmit} + style={styles.submitIconStyle} + > + <AntDesign + name="right" + color={ColorPallet.baseColors.black} + size={Platform.OS === 'ios' ? height / 30 : height / 28} + /> + </TouchableOpacity> + </KeyboardAvoidingView> + </View> + </Pressable> + ); +}; + +export default QRScanner; + +const { width, height } = Dimensions.get('window'); + +const styles = StyleSheet.create({ + container: { + width: '100%', + height: '100%', + // backgroundColor: ColorPallet.baseColors.black, + justifyContent: 'center', + alignItems: 'center', + }, + cameraViewContainer: { + position: 'absolute', + alignItems: 'center', + left: 0, + top: 0, + width: '100%', + height: '100%', + }, + viewFinder: { + width: 250, + height: 250, + borderRadius: 24, + borderWidth: 2, + borderColor: ColorPallet.baseColors.white, + backgroundColor: ColorPallet.baseColors.transparent, + }, + viewFinderContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + errorContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + icon: { + color: ColorPallet.baseColors.white, + padding: 4, + }, + submitIconStyle: { + alignSelf: 'center', + }, + bottomView: { + flex: 1, + marginTop: -80, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + backgroundColor: ColorPallet.baseColors.white, + width: '100%', + }, + textInputStyle: { + width: width - 100, + paddingTop: 5, + color: ColorPallet.baseColors.black, + alignItems: 'center', + fontSize: Platform.OS === 'ios' ? height / 50 : height / 45, + justifyContent: 'center', + height: Platform.OS === 'ios' ? height / 19 : height / 18, + borderBottomWidth: 1, + borderBottomColor: 'black', + alignSelf: 'center', + marginVertical: 20, + }, + rowTextInputView: { + flexDirection: 'row', + justifyContent: 'space-evenly', + }, + actionsView: { + flexDirection: 'row', + justifyContent: 'space-between', + padding: 20, + width: '100%', + position: 'absolute', + top: 10, + }, + scanTextView: { + flexDirection: 'column', + padding: 20, + width: '100%', + position: 'absolute', + alignItems: 'center', + top: 78, + }, + scanText: { + fontSize: Platform.OS === 'ios' ? height / 40 : height / 35, + textAlign: 'center', + }, +}); diff --git a/src/components/inputs/SearchBar.tsx b/src/components/inputs/SearchBar.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a9e8188a3efe10b7fe8238c8ff8b8a1da11e3aaa --- /dev/null +++ b/src/components/inputs/SearchBar.tsx @@ -0,0 +1,98 @@ +import Icon from 'react-native-vector-icons/MaterialIcons'; +import React from 'react'; +import { StyleSheet, View, Keyboard, Button, TextInput } from 'react-native'; +import { ColorPallet } from '../../theme/theme'; + +interface Props { + clicked: boolean; + searchPhrase: string; + setSearchPhrase: (text: string) => void; + setClicked: (value: boolean) => void; +} + +const SearchBar: React.FC<Props> = ({ + clicked, + searchPhrase, + setSearchPhrase, + setClicked, +}) => { + return ( + <View style={styles.container}> + <View style={clicked ? styles.searchBarClicked : styles.searchBar}> + {/* search Icon */} + <Icon + name="search" + color={ColorPallet.grayscale.darkGrey} + size={20} + style={styles.searchIcon} + /> + {/* Input field */} + <TextInput + style={styles.input} + returnKeyType="done" + placeholder="Search" + value={searchPhrase} + onChangeText={setSearchPhrase} + onFocus={() => { + setClicked(true); + }} + /> + </View> + {/* cancel button, depending on whether the search bar is clicked or not */} + {clicked && ( + <View style={styles.buttonStyle}> + <Button + title="Cancel" + color={ColorPallet.brand.secondary} + onPress={() => { + Keyboard.dismiss(); + setClicked(false); + setSearchPhrase(''); + }} + /> + </View> + )} + </View> + ); +}; + +export default SearchBar; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + width: '95%', + }, + searchBar: { + marginLeft: 15, + marginRight: 15, + height: 50, + flexDirection: 'row', + width: '95%', + backgroundColor: ColorPallet.grayscale.veryLightGrey, + borderRadius: 10, + }, + searchBarClicked: { + marginLeft: 15, + marginRight: 10, + height: 50, + flexDirection: 'row', + width: '70%', + backgroundColor: ColorPallet.grayscale.veryLightGrey, + borderRadius: 10, + }, + searchIcon: { + paddingLeft: 0.5, + paddingTop: 0.5, + marginTop: 15, + marginLeft: 10, + }, + input: { + fontSize: 18, + alignSelf: 'center', + width: '90%', + }, + buttonStyle: { + alignSelf: 'center', + }, +}); diff --git a/src/components/inputs/SingleSelectBlock.tsx b/src/components/inputs/SingleSelectBlock.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d39a7c779f520ea86d7cf576bf793ad4b2d50e9a --- /dev/null +++ b/src/components/inputs/SingleSelectBlock.tsx @@ -0,0 +1,69 @@ +import React, { useState } from 'react'; +import { StyleSheet, TouchableOpacity, View } from 'react-native'; +import Icon from 'react-native-vector-icons/MaterialIcons'; + +import { + borderRadius, + ColorPallet, + SingleSelectBlockTheme, +} from '../../theme/theme'; +import Text from '../text/Text'; + +export interface BlockSelection { + value: string; + id: string; +} + +interface Props { + selection: BlockSelection[]; + onSelect: (selected: BlockSelection) => void; + initialSelect?: BlockSelection; +} + +const SingleSelectBlock: React.FC<Props> = ({ + selection, + onSelect, + initialSelect, +}) => { + const [selected, setSelected] = useState(initialSelect ?? selection[0]); + + const handleSelect = (selected: BlockSelection) => { + setSelected(selected); + onSelect(selected); + }; + + return ( + <View style={styles.container} testID="SingleSelectBlock"> + {selection.map(item => ( + <TouchableOpacity + key={item.id} + style={styles.row} + onPress={() => handleSelect(item)} + > + <Text>{item.value}</Text> + {item.id === selected.id ? ( + <Icon name="check" size={25} color={ColorPallet.brand.primary} /> + ) : null} + </TouchableOpacity> + ))} + </View> + ); +}; + +export default SingleSelectBlock; + +const styles = StyleSheet.create({ + container: { + width: '100%', + padding: 20, + }, + row: { + borderRadius: borderRadius * 2, + backgroundColor: SingleSelectBlockTheme.background, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + padding: 12, + marginBottom: 8, + }, +}); diff --git a/src/components/inputs/TextInput.tsx b/src/components/inputs/TextInput.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5abc9141899d743b5fbdc3b72eb7abef98b474c8 --- /dev/null +++ b/src/components/inputs/TextInput.tsx @@ -0,0 +1,71 @@ +import React, { useState, useRef, useEffect } from 'react'; +import { + View, + Text, + StyleSheet, + TextInput as RNTextInput, + TextInputProps, +} from 'react-native'; + +import { ColorPallet, TextTheme, borderRadius } from '../../theme/theme'; + +interface Props extends TextInputProps { + label: string; +} + +const TextInput: React.FC<Props> = ({ label, ...textInputProps }) => { + const [focused, setFocused] = useState(false); + const ref = useRef<RNTextInput>(null); + + useEffect(() => { + if (focused) { + setTimeout(() => { + if (ref.current) { + ref.current.focus(); + } + }, 40); + } + }, [focused]); + + const focusInput = () => setFocused(true); + + return ( + <View style={styles.container}> + <Text testID="label" style={styles.label}> + {label} + </Text> + <RNTextInput + ref={ref} + style={[ + styles.textInput, + focused && { borderColor: ColorPallet.brand.primary }, + ]} + selectionColor={ColorPallet.brand.primary} + onFocus={focusInput} + onBlur={focusInput} + {...textInputProps} + /> + </View> + ); +}; + +export default TextInput; + +const styles = StyleSheet.create({ + container: { + marginVertical: 10, + }, + label: { + ...TextTheme.label, + marginBottom: 3, + }, + textInput: { + padding: 10, + borderRadius, + fontSize: 16, + backgroundColor: ColorPallet.grayscale.white, + color: ColorPallet.brand.primary, + borderWidth: 2, + borderColor: ColorPallet.brand.primary, + }, +}); diff --git a/src/components/inputs/__tests__/QRScanner.test.tsx b/src/components/inputs/__tests__/QRScanner.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9f605c103a87329cd14be4afaf93a7e8523fca85 --- /dev/null +++ b/src/components/inputs/__tests__/QRScanner.test.tsx @@ -0,0 +1,14 @@ +import { render } from '@testing-library/react-native'; +import React from 'react'; +import QRScanner from '../QRScanner'; + +describe('QRScanner', () => { + it('should render correctly and change data after scanning the QRCode', () => { + const onEventMock = jest.fn(); + const { getByTestId } = render( + <QRScanner handleCodeScan={onEventMock} onChangeText={() => {}} />, + ); + + expect(getByTestId('QRScannerTest')).toBeTruthy(); + }); +}); diff --git a/src/components/inputs/__tests__/SearchBar.test.tsx b/src/components/inputs/__tests__/SearchBar.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..53c6a3a7bb2cdcd496a58a77c6d6103c55a7ffde --- /dev/null +++ b/src/components/inputs/__tests__/SearchBar.test.tsx @@ -0,0 +1,23 @@ +import { fireEvent, render } from '@testing-library/react-native'; +import React from 'react'; +import SearchBar from '../SearchBar'; + +describe('SearchBar', () => { + it('should render correctly and change searchPhrase when searched with textInput', () => { + const onPressMock = jest.fn(); + + const onEventMock = jest.fn(); + const { getByPlaceholderText } = render( + <SearchBar + clicked={false} + searchPhrase="" + setSearchPhrase={onEventMock} + setClicked={onPressMock} + />, + ); + + const searchBar = getByPlaceholderText('Search'); + fireEvent(searchBar, 'onChangeText', 'searchText'); + expect(onEventMock).toHaveBeenCalledWith('searchText'); + }); +}); diff --git a/src/components/inputs/__tests__/SingleSelectBlock.test.tsx b/src/components/inputs/__tests__/SingleSelectBlock.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e3e8b7d70b99b5040f10638af5baee7c5a591af3 --- /dev/null +++ b/src/components/inputs/__tests__/SingleSelectBlock.test.tsx @@ -0,0 +1,23 @@ +import { fireEvent, render } from '@testing-library/react-native'; +import React from 'react'; +import SingleSelectBlock from '../SingleSelectBlock'; + +describe('SingleSelectBlock', () => { + it('should render correctly and get selected value from array', () => { + const mockData = [ + { id: '1', value: 'value1' }, + { id: '2', value: 'value2' }, + { id: '3', value: 'value3' }, + ]; + + const onPressMock = jest.fn(); + + const { getByText } = render( + <SingleSelectBlock selection={mockData} onSelect={onPressMock} />, + ); + + const singleSelectBlockValue = getByText('value3'); + fireEvent.press(singleSelectBlockValue); + expect(onPressMock).toHaveBeenCalledWith(mockData[2]); + }); +}); diff --git a/src/components/inputs/__tests__/TextInput.test.tsx b/src/components/inputs/__tests__/TextInput.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..314a3e88ad9a6274adcbb981a15b681ad00d963e --- /dev/null +++ b/src/components/inputs/__tests__/TextInput.test.tsx @@ -0,0 +1,22 @@ +import { fireEvent, render } from '@testing-library/react-native'; +import React from 'react'; +import TextInput from '../TextInput'; + +describe('TextInput', () => { + it('should render correctly and change textInput values after input is added', () => { + const onEventMock = jest.fn(); + const { getByPlaceholderText, getByTestId } = render( + <TextInput + label="textInput" + placeholder="placeholder" + onChangeText={onEventMock} + />, + ); + + const text = getByTestId('label'); + expect(text.children[0]).toBe('textInput'); + const textInput = getByPlaceholderText('placeholder'); + fireEvent(textInput, 'onChangeText', 'text'); + expect(onEventMock).toHaveBeenCalledWith('text'); + }); +}); diff --git a/src/components/listItems/ContactListItem.tsx b/src/components/listItems/ContactListItem.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a51f19b4d5c38a20e7303d3dc7fd5db533435524 --- /dev/null +++ b/src/components/listItems/ContactListItem.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import type { ConnectionRecord } from '@aries-framework/core'; +import { Pressable, StyleSheet } from 'react-native'; +import { StackNavigationProp } from '@react-navigation/stack'; +import { useNavigation } from '@react-navigation/core'; +import { borderRadius, ContactTheme } from '../../theme/theme'; +import { dateFormatOptions } from '../../constants'; +import Text from '../text/Text'; +import Title from '../text/Title'; +import { ContactStackParams, Screens } from '../../types/navigators'; + +interface Props { + contact: ConnectionRecord; +} + +const ContactListItem: React.FC<Props> = ({ contact }) => { + const navigation = useNavigation<StackNavigationProp<ContactStackParams>>(); + return ( + <Pressable + testID="contact-list-item" + onPress={() => + navigation.navigate(Screens.ContactDetails, { + connectionId: contact.id, + }) + } + key={contact.id} + style={styles.container} + > + <Title>{contact?.alias || contact?.theirLabel}</Title> + <Text>DID : {contact.did}</Text> + <Text>State : {contact.state}</Text> + <Text style={styles.date}> + {contact.createdAt.toLocaleDateString('en-CA', dateFormatOptions)} + </Text> + </Pressable> + ); +}; + +export default ContactListItem; + +const styles = StyleSheet.create({ + container: { + marginTop: 15, + marginHorizontal: 15, + padding: 10, + borderRadius, + backgroundColor: ContactTheme.background, + }, + date: { + textAlign: 'right', + }, +}); diff --git a/src/components/listItems/CredentialListItem.tsx b/src/components/listItems/CredentialListItem.tsx new file mode 100644 index 0000000000000000000000000000000000000000..8ed492f1316774c5e0e6db59b480a6315ddc92d8 --- /dev/null +++ b/src/components/listItems/CredentialListItem.tsx @@ -0,0 +1,33 @@ +import { CredentialExchangeRecord } from '@aries-framework/core'; +import { useNavigation } from '@react-navigation/core'; +import { StackNavigationProp } from '@react-navigation/stack'; +import React from 'react'; +import { Pressable } from 'react-native'; +import CredentialCard from '../misc/CredentialCard'; +import { CredentialStackParams, Screens } from '../../types/navigators'; + +interface CredentialListItemProps { + credential: CredentialExchangeRecord; +} + +const CredentialListItem: React.FC<CredentialListItemProps> = ({ + credential, +}) => { + const navigation = + useNavigation<StackNavigationProp<CredentialStackParams>>(); + + return ( + <Pressable + testID="credential-list-item" + onPress={() => + navigation.navigate(Screens.CredentialDetails, { + credentialId: credential.id, + }) + } + > + <CredentialCard credential={credential} /> + </Pressable> + ); +}; + +export default CredentialListItem; diff --git a/src/components/listItems/DropDown.tsx b/src/components/listItems/DropDown.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4ca23b38f9a706fd02aa5a05ec4f7b10835ae995 --- /dev/null +++ b/src/components/listItems/DropDown.tsx @@ -0,0 +1,68 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import DropDownPicker, { + ItemType, + ValueType, +} from 'react-native-dropdown-picker'; +import Icon from 'react-native-vector-icons/AntDesign'; +import { StyleSheet } from 'react-native'; +import { TextTheme } from '../../theme/theme'; + +interface Item { + value: string; + label: string; +} + +interface Props { + items: Item[]; + onSelectItem: (item: ItemType<ValueType>) => void; +} + +const DropDown = ({ items, onSelectItem }: Props) => { + const [open, setOpen] = useState(false); + const [value, setValue] = useState<ValueType | null>(null); + + const updateValue = useCallback(() => { + setValue(items[0].value); + }, [items]); + + useEffect(() => { + updateValue(); + }, [updateValue]); + + return ( + <DropDownPicker + testID="dropdown" + zIndex={10} + multiple={false} + setOpen={setOpen} + setValue={setValue} + open={open} + listMode="SCROLLVIEW" + value={value} + style={styles.dropdown} + dropDownContainerStyle={styles.dropdownContainer} + textStyle={styles.text} + ArrowDownIconComponent={() => ( + <Icon name="caretdown" size={10} color="#000FFF" /> + )} + ArrowUpIconComponent={() => ( + <Icon name="caretup" size={10} color="#00DDDD" /> + )} + items={items} + onSelectItem={onSelectItem} + /> + ); +}; + +export default DropDown; + +const styles = StyleSheet.create({ + dropdown: { + borderRadius: 0, + }, + dropdownContainer: { borderRadius: 0 }, + text: { + ...TextTheme.normal, + fontSize: 14, + }, +}); diff --git a/src/components/listItems/NotificationListItem.tsx b/src/components/listItems/NotificationListItem.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2ec2af1d3ffb36db031a2a79dc6f0fc75961c488 --- /dev/null +++ b/src/components/listItems/NotificationListItem.tsx @@ -0,0 +1,132 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { CredentialExchangeRecord, ProofRecord } from '@aries-framework/core'; +import { useNavigation } from '@react-navigation/core'; +import { StackNavigationProp } from '@react-navigation/stack'; +import { useTranslation } from 'react-i18next'; +import { StyleSheet, View, Text, Image } from 'react-native'; +import { useAgent, useConnectionById } from '@aries-framework/react-hooks'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import Button, { ButtonType } from '../button/Button'; +import { HomeStackParams, Screens } from '../../types/navigators'; +import { parseCredDef } from '../../utils/helpers'; +import Images from '../../assets'; + +const iconSize = 30; + +export enum NotificationType { + CredentialOffer = 'Offer', + ProofRequest = 'Proof', +} + +interface NotificationListItemProps { + notificationType: NotificationType; + notification: CredentialExchangeRecord | ProofRecord; +} + +const NotificationListItem: React.FC<NotificationListItemProps> = ({ + notificationType, + notification, +}) => { + const navigation = useNavigation<StackNavigationProp<HomeStackParams>>(); + const { t } = useTranslation(); + const [title, setTitle] = useState(''); + const [body, setBody] = useState(''); + const { agent } = useAgent(); + const connection = useConnectionById(notification?.connectionId || ''); + + const getNotificationData = useCallback(async () => { + if (notificationType === NotificationType.CredentialOffer) { + setTitle(t<string>('CredentialOffer.CredentialOffer')); + const credentialRecord = await agent?.credentials.getFormatData( + notification.id, + ); + const credentialDefinitionId = credentialRecord?.offer?.indy?.cred_def_id; + + const { credName } = parseCredDef(credentialDefinitionId); + setBody(credName); + } else { + setTitle(t<string>('ProofRequest.ProofRequest')); + setBody(connection?.theirLabel ?? 'Connectionless proof request'); + } + }, [ + agent?.credentials, + connection?.theirLabel, + notification.id, + notificationType, + t, + ]); + + useEffect(() => { + getNotificationData(); + }, [getNotificationData]); + + const navigateToNotification = () => { + if (notificationType === NotificationType.CredentialOffer) { + navigation.navigate(Screens.CredentialOffer, { + credentialId: notification.id, + }); + } else { + navigation.navigate(Screens.ProofRequest, { proofId: notification.id }); + } + }; + + return ( + <View testID="notification-list-item" style={styles.container}> + <View style={styles.headerContainer}> + <View style={styles.icon}> + <Image + source={Images.infoIcon} + style={{ width: iconSize, height: iconSize }} + /> + </View> + <Text style={styles.headerText}>{title}</Text> + </View> + <View style={styles.bodyContainer}> + <Text style={styles.bodyText}>{body}</Text> + <Button + buttonType={ButtonType.Primary} + title={t<string>('Global.View')} + onPress={navigateToNotification} + /> + </View> + </View> + ); +}; + +export default NotificationListItem; + +const styles = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.veryLightGrey, + borderRadius: 5, + padding: 10, + }, + headerContainer: { + flexDirection: 'row', + paddingHorizontal: 5, + paddingTop: 5, + }, + bodyContainer: { + flexGrow: 1, + flexDirection: 'column', + marginLeft: 10 + iconSize, + paddingHorizontal: 5, + paddingBottom: 5, + }, + headerText: { + ...TextTheme.normal, + flexShrink: 1, + fontWeight: 'bold', + alignSelf: 'center', + }, + bodyText: { + ...TextTheme.normal, + flexShrink: 1, + marginVertical: 15, + paddingBottom: 10, + }, + icon: { + marginRight: 10, + alignSelf: 'center', + }, +}); diff --git a/src/components/listItems/SealListItem.tsx b/src/components/listItems/SealListItem.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f23ee035b85aec233d25680f003bd661f16ceee1 --- /dev/null +++ b/src/components/listItems/SealListItem.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { Pressable, StyleSheet } from 'react-native'; +import { StackNavigationProp } from '@react-navigation/stack'; +import { useNavigation } from '@react-navigation/core'; +import { borderRadius, ContactTheme } from '../../theme/theme'; +import { dateFormatOptions } from '../../constants'; +import Text from '../text/Text'; +import Title from '../text/Title'; +import { + ContactStackParams, + ScanStackParams, + Screens, +} from '../../types/navigators'; + +interface Props { + date: Date; + url: string; + subject: string | undefined; +} + +const styles = StyleSheet.create({ + container: { + marginTop: 15, + marginHorizontal: 15, + padding: 10, + borderRadius, + backgroundColor: ContactTheme.background, + }, + date: { + textAlign: 'right', + }, + url: { + color: 'gray', + }, +}); + +const SealListItem: React.FC<Props> = ({ date, url, subject }) => { + const navigation = useNavigation<StackNavigationProp<ScanStackParams>>(); + return ( + <Pressable + onPress={() => navigation.navigate(Screens.SealInformation, { url })} + key={date.getTime()} + style={styles.container} + > + <Title> + {date.toLocaleDateString('en-CA', { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + })} + </Title> + {subject && <Text>Subject : {subject}</Text>} + <Text style={styles.url}>Url : {url}</Text> + </Pressable> + ); +}; + +export default SealListItem; diff --git a/src/components/listItems/SettingListItem.tsx b/src/components/listItems/SettingListItem.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a807e01e549946e564f5c2d38dd1720503b9b1da --- /dev/null +++ b/src/components/listItems/SettingListItem.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { StyleSheet, TouchableOpacity } from 'react-native'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import { borderRadius, ColorPallet, TextTheme } from '../../theme/theme'; +import Text from '../text/Text'; + +interface Props { + title: string; + onPress: () => void; +} + +const SettingListItem: React.FC<Props> = ({ title, onPress }) => { + return ( + <TouchableOpacity + testID="setting-list-item" + style={styles.container} + onPress={onPress} + > + <Text style={styles.bodyText}>{title}</Text> + <Icon name="chevron-right" size={25} color={ColorPallet.brand.primary} /> + </TouchableOpacity> + ); +}; + +export default SettingListItem; + +const styles = StyleSheet.create({ + container: { + borderRadius: borderRadius * 2, + backgroundColor: ColorPallet.baseColors.lightBlue, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + padding: 12, + marginBottom: 10, + }, + bodyText: { + ...TextTheme.normal, + flexShrink: 1, + }, +}); diff --git a/src/components/listItems/__tests__/ContactListItem.test.tsx b/src/components/listItems/__tests__/ContactListItem.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4ea806ceeccf8e2c87166a3d1d0ae1cf7e11d9f7 --- /dev/null +++ b/src/components/listItems/__tests__/ContactListItem.test.tsx @@ -0,0 +1,36 @@ +import { DidExchangeState } from '@aries-framework/core'; +import { useNavigation } from '@react-navigation/core'; +import { fireEvent, render } from '@testing-library/react-native'; +import React from 'react'; +import ContactListItem from '../ContactListItem'; + +import { getMockConnection } from '../../../utils/testhelpers'; + +const connectionRecord = getMockConnection({ + id: 'testConnectionId', + theirLabel: 'private beta', + did: 'SL2dA5wcdY8NEhkKwYeVNb', + state: DidExchangeState.Completed, + createdAt: new Date('2022-04-29T06:36:48.244Z'), +}); + +describe('ContactListItem', () => { + it('should render connection details correctly when connection record is passed as prop', () => { + const navigation = useNavigation(); + const { getByTestId, getByText } = render( + <ContactListItem contact={connectionRecord} />, + ); + const label = getByText('private beta'); + const didText = getByText('DID : SL2dA5wcdY8NEhkKwYeVNb'); + const stateText = getByText('State : completed'); + expect(label.props.children).toBe(connectionRecord?.theirLabel); + expect(didText.props.children[1]).toBe(connectionRecord?.did); + expect(stateText.props.children[1]).toBe(connectionRecord.state); + + const contactListItem = getByTestId('contact-list-item'); + fireEvent.press(contactListItem); + expect(navigation.navigate).toHaveBeenCalledWith('ConnectionDetails', { + connectionId: 'testConnectionId', + }); + }); +}); diff --git a/src/components/listItems/__tests__/CredentialListItem.test.tsx b/src/components/listItems/__tests__/CredentialListItem.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..14cb34df27b633b4368fa2e4628a7e5cf6ef78a4 --- /dev/null +++ b/src/components/listItems/__tests__/CredentialListItem.test.tsx @@ -0,0 +1,37 @@ +import { + V1CredentialPreview, + CredentialExchangeRecord, + CredentialState, +} from '@aries-framework/core'; +import { useNavigation } from '@react-navigation/core'; +import { fireEvent, render } from '@testing-library/react-native'; +import React from 'react'; +import CredentialListItem from '../CredentialListItem'; + +const credentialRecord = new CredentialExchangeRecord({ + connectionId: '34da4abe-7578-464f-909c-ee19a3bdf7ac', + threadId: 'threadId', + state: CredentialState.Done, + credentialId: '30ba35ab-7823-4123-8bdf-7a112a366d3b', + credentialAttributes: [ + new V1CredentialPreview({ + name: 'age', + value: '25', + }), + ], +}); + +describe('CredentialListItem', () => { + it('should render credential details correctly when credential record is passed as prop', () => { + const navigation = useNavigation(); + const { getByTestId } = render( + <CredentialListItem credential={credentialRecord} />, + ); + + const credentialListItem = getByTestId('credential-list-item'); + fireEvent.press(credentialListItem); + expect(navigation.navigate).toHaveBeenCalledWith('Credential Details', { + credentialId: credentialRecord.id, + }); + }); +}); diff --git a/src/components/listItems/__tests__/DropDown.test.tsx b/src/components/listItems/__tests__/DropDown.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..013fcde08c3c2bbd7a854dcfa5bad3245a1abed9 --- /dev/null +++ b/src/components/listItems/__tests__/DropDown.test.tsx @@ -0,0 +1,24 @@ +import { fireEvent, render } from '@testing-library/react-native'; +import React from 'react'; +import DropDown from '../DropDown'; + +jest.mock('react-native-dropdown-picker', () => 'DropDown'); + +describe('DropDown', () => { + it('should render DropDown correctly and respond on press', () => { + const items = [ + { value: '1', label: 'item 1', testID: 'item1' }, + { value: '2', label: 'item 2', testID: 'item2' }, + { value: '3', label: 'item 3', testID: 'item3' }, + ]; + + const onSelectItemMock = jest.fn(); + + const { getByTestId } = render( + <DropDown items={items} onSelectItem={onSelectItemMock} />, + ); + const dropDown = getByTestId('dropdown'); + fireEvent(dropDown, 'onSelectItem'); + expect(onSelectItemMock).toHaveBeenCalled(); + }); +}); diff --git a/src/components/listItems/__tests__/NotificationListItem.test.tsx b/src/components/listItems/__tests__/NotificationListItem.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6af451d2ce2f80e94bc7286ed6da8a155a536f53 --- /dev/null +++ b/src/components/listItems/__tests__/NotificationListItem.test.tsx @@ -0,0 +1,91 @@ +import { + CredentialExchangeRecord, + CredentialState, + INDY_PROOF_REQUEST_ATTACHMENT_ID, + ProofRecord, + ProofState, + RequestPresentationMessage, + CredentialPreviewAttribute, +} from '@aries-framework/core'; +import { + Attachment, + AttachmentData, +} from '@aries-framework/core/build/decorators/attachment/Attachment'; +import { useNavigation } from '@react-navigation/core'; +import { fireEvent, render } from '@testing-library/react-native'; +import React from 'react'; +import NotificationListItem, { + NotificationType, +} from '../NotificationListItem'; + +const credentialRecord = new CredentialExchangeRecord({ + connectionId: '34da4abe-7578-464f-909c-ee19a3bdf7ac', + threadId: 'threadId', + state: CredentialState.OfferReceived, + credentialAttributes: [ + new CredentialPreviewAttribute({ + name: 'age', + value: '25', + }), + ], + protocolVersion: 'v1', +}); + +const requestAttachment = new Attachment({ + id: INDY_PROOF_REQUEST_ATTACHMENT_ID, + mimeType: 'application/json', + data: new AttachmentData({ + base64: + 'eyJuYW1lIjogIlByb29mIHJlcXVlc3QiLCAibm9uX3Jldm9rZWQiOiB7ImZyb20iOiAxNjQwOTk1MTk5LCAidG8iOiAxNjQwOTk1MTk5fSwgIm5vbmNlIjogIjEiLCAicmVxdWVzdGVkX2F0dHJpYnV0ZXMiOiB7ImFkZGl0aW9uYWxQcm9wMSI6IHsibmFtZSI6ICJmYXZvdXJpdGVEcmluayIsICJub25fcmV2b2tlZCI6IHsiZnJvbSI6IDE2NDA5OTUxOTksICJ0byI6IDE2NDA5OTUxOTl9LCAicmVzdHJpY3Rpb25zIjogW3siY3JlZF9kZWZfaWQiOiAiV2dXeHF6dHJOb29HOTJSWHZ4U1RXdjozOkNMOjIwOnRhZyJ9XX19LCAicmVxdWVzdGVkX3ByZWRpY2F0ZXMiOiB7fSwgInZlcnNpb24iOiAiMS4wIn0=', + }), +}); + +const requestMessage = new RequestPresentationMessage({ + comment: 'some comment', + requestPresentationAttachments: [requestAttachment], +}); + +const proofRecord = new ProofRecord({ + requestMessage, + id: 'ID', + state: ProofState.RequestReceived, + threadId: 'fd9c5ddb-ec11-4acd-bc32-540736249746', + connectionId: 'b1e2f039-aa39-40be-8643-6ce2797b5190', +}); + +describe('NotificationListItem', () => { + const navigation = useNavigation(); + it('should render notification correctly when credential record is passed as prop', () => { + const { getByText } = render( + <NotificationListItem + notification={credentialRecord} + notificationType={NotificationType.CredentialOffer} + />, + ); + const title = getByText('CredentialOffer.CredentialOffer'); + expect(title.props.children).toBe('CredentialOffer.CredentialOffer'); + + const button = getByText('Global.View'); + fireEvent.press(button); + expect(navigation.navigate).toHaveBeenCalledWith('CredentialOffer', { + credentialId: credentialRecord.id, + }); + }); + + it('should render notification correctly when proof record is passed as prop', () => { + const { getByText } = render( + <NotificationListItem + notification={proofRecord} + notificationType={NotificationType.ProofRequest} + />, + ); + const title = getByText('ProofRequest.ProofRequest'); + expect(title.props.children).toBe('ProofRequest.ProofRequest'); + + const button = getByText('Global.View'); + fireEvent.press(button); + expect(navigation.navigate).toHaveBeenCalledWith('ProofRequest', { + proofId: proofRecord.id, + }); + }); +}); diff --git a/src/components/listItems/__tests__/SettingListItem.test.tsx b/src/components/listItems/__tests__/SettingListItem.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f1f7f6626cb40dd73695a7c6b27517fb0e09cd23 --- /dev/null +++ b/src/components/listItems/__tests__/SettingListItem.test.tsx @@ -0,0 +1,16 @@ +import { fireEvent, render } from '@testing-library/react-native'; +import React from 'react'; +import SettingListItem from '../SettingListItem'; + +describe('SettingListItem', () => { + it('should render settings item correctly and respond on press', () => { + const onPressMock = jest.fn(); + const { getByTestId } = render( + <SettingListItem title="Language" onPress={onPressMock} />, + ); + + const contactListItem = getByTestId('setting-list-item'); + fireEvent.press(contactListItem); + expect(onPressMock).toHaveBeenCalled(); + }); +}); diff --git a/src/components/loader/Loader.tsx b/src/components/loader/Loader.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ac034d71b4da48125661a3b0f61d160074e71207 --- /dev/null +++ b/src/components/loader/Loader.tsx @@ -0,0 +1,66 @@ +import React, { useEffect, useMemo } from 'react'; +import { Animated, Easing, Modal, StyleSheet } from 'react-native'; +import Images from '../../assets'; +import { ColorPallet } from '../../theme/theme'; + +type Props = { + loading: boolean; +}; + +const Loader: React.FC<Props> = ({ loading }) => { + const spinValue = useMemo(() => new Animated.Value(0), []); + + useEffect(() => { + Animated.loop( + Animated.timing(spinValue, { + toValue: 1, + duration: 1000, + easing: Easing.linear, + useNativeDriver: true, + }), + ).start(); + }, [spinValue]); + + const spin = spinValue.interpolate({ + inputRange: [0, 1], + outputRange: ['0deg', '360deg'], + }); + return ( + <Modal + visible={loading} + transparent + style={styles.container} + testID="loader" + > + <Animated.View style={styles.activityIndicatorWrapper}> + <Animated.Image + style={{ + flex: 1, + alignSelf: 'center', + height: 70, + width: 70, + transform: [{ rotate: spin }], + }} + resizeMode="contain" + source={Images.loaderIcon} + /> + </Animated.View> + </Modal> + ); +}; + +export default Loader; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + activityIndicatorWrapper: { + backgroundColor: `${ColorPallet.baseColors.black}20`, + flex: 1, + alignItems: 'center', + justifyContent: 'space-around', + }, +}); diff --git a/src/components/loader/__tests__/Loader.test.tsx b/src/components/loader/__tests__/Loader.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9cf8c24245b9e9861253c0d4af10d565f7acdecb --- /dev/null +++ b/src/components/loader/__tests__/Loader.test.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { render } from '@testing-library/react-native'; +import Loader from '../Loader'; + +describe('Loader Component', () => { + jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper'); + it('should render loader start correctly', () => { + const { getByTestId } = render(<Loader loading />); + const loader = getByTestId('loader'); + expect(loader.props.visible).toBe(true); + }); + it('should render loader close correctly', () => { + const { getByTestId } = render(<Loader loading={false} />); + const loader = getByTestId('loader'); + expect(loader.props.visible).toBe(false); + }); +}); diff --git a/src/components/misc/AvatarView.tsx b/src/components/misc/AvatarView.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0a74f9595edbe65d74119bfb4ede203c0b4ce3c0 --- /dev/null +++ b/src/components/misc/AvatarView.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { StyleSheet, View } from 'react-native'; +import { Title } from '..'; +import { TextTheme } from '../../theme/theme'; +import { hashToRGBA, hashCode } from '../../utils/helpers'; + +interface AvatarViewProps { + name: string; +} + +const AvatarView: React.FC<AvatarViewProps> = ({ name }) => { + return ( + <View style={[styles.avatar, { borderColor: hashToRGBA(hashCode(name)) }]}> + <Title style={{ ...TextTheme.headingTwo, fontWeight: 'normal' }}> + {name.charAt(0)} + </Title> + </View> + ); +}; + +export default AvatarView; + +const styles = StyleSheet.create({ + avatar: { + width: TextTheme.headingTwo.fontSize * 2, + height: TextTheme.headingTwo.fontSize * 2, + margin: 12, + borderWidth: 3, + justifyContent: 'center', + alignItems: 'center', + borderRadius: TextTheme.headingTwo.fontSize, + borderColor: TextTheme.headingTwo.color, + }, +}); diff --git a/src/components/misc/CredentialCard.tsx b/src/components/misc/CredentialCard.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d4d310897c776592ac7e807bc9e62b66cc37b27b --- /dev/null +++ b/src/components/misc/CredentialCard.tsx @@ -0,0 +1,57 @@ +import { CredentialExchangeRecord } from '@aries-framework/core'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { StyleSheet, Text, View, ViewStyle } from 'react-native'; +import { Title } from '..'; + +import { dateFormatOptions } from '../../constants'; +import { ContactTheme, TextTheme } from '../../theme/theme'; +import { parsedSchema } from '../../utils/helpers'; +import AvatarView from './AvatarView'; + +interface CredentialCardProps { + credential: CredentialExchangeRecord; + style?: ViewStyle; +} + +const CredentialCard: React.FC<CredentialCardProps> = ({ + credential, + style = {}, +}) => { + const { t } = useTranslation(); + + return ( + <View style={[styles.container, style]}> + <View style={styles.row}> + <AvatarView name={parsedSchema(credential).name} /> + <View style={styles.details}> + <Title>{parsedSchema(credential).name}</Title> + <Text style={{ ...TextTheme.caption }}> + {t<string>('CredentialDetails.Issued')}:{' '} + {credential.createdAt.toLocaleDateString( + 'en-CA', + dateFormatOptions, + )} + </Text> + </View> + </View> + </View> + ); +}; + +export default CredentialCard; + +const styles = StyleSheet.create({ + container: { + minHeight: 125, + backgroundColor: ContactTheme.background, + justifyContent: 'center', + borderRadius: 15, + padding: 10, + }, + row: { + flexDirection: 'row', + alignItems: 'center', + }, + details: { flexShrink: 1 }, +}); diff --git a/src/components/misc/QRScannerClose.tsx b/src/components/misc/QRScannerClose.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ab4bd9e348dcc193b626016b0a27edfe87a9e545 --- /dev/null +++ b/src/components/misc/QRScannerClose.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { StyleSheet, TouchableOpacity, View } from 'react-native'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import { ColorPallet } from '../../theme/theme'; + +interface Props { + onPress?: () => void; +} + +const CloseButton: React.FC<Props> = ({ onPress }) => { + return ( + <View style={styles.container}> + <TouchableOpacity + testID="closeButton" + style={styles.button} + onPress={onPress} + > + <Icon name="close" size={24} color={ColorPallet.baseColors.white} /> + </TouchableOpacity> + </View> + ); +}; + +const QRScannerClose: React.FC<Props> = ({ onPress }) => { + return <CloseButton onPress={onPress} />; +}; + +export default QRScannerClose; + +const styles = StyleSheet.create({ + container: { + alignSelf: 'center', + }, + button: { + padding: 0, + }, +}); diff --git a/src/components/misc/QRScannerTorch.tsx b/src/components/misc/QRScannerTorch.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2f819246354503f672513d96f6c571ea1fd5ccac --- /dev/null +++ b/src/components/misc/QRScannerTorch.tsx @@ -0,0 +1,64 @@ +import React, { ReactNode } from 'react'; +import { TouchableOpacity, StyleSheet } from 'react-native'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import { ColorPallet } from '../../theme/theme'; + +type Props = { + active: boolean; + onPress: () => void; + children?: ReactNode; +}; + +const TorchButton: React.FC<Props> = ({ active, onPress, children }) => { + return ( + <TouchableOpacity + onPress={onPress} + style={[ + styles.container, + { backgroundColor: active ? ColorPallet.baseColors.white : undefined }, + ]} + > + {children} + </TouchableOpacity> + ); +}; + +const TorchIcon: React.FC<{ active: boolean }> = ({ active }) => { + return ( + <Icon + name={active ? 'flash-on' : 'flash-off'} + color={ + active ? ColorPallet.baseColors.black : ColorPallet.baseColors.white + } + size={24} + style={styles.icon} + /> + ); +}; + +const QRScannerTorch: React.FC<Props> = ({ active, onPress }) => { + return ( + <TorchButton active={active} onPress={onPress}> + <TorchIcon active={active} /> + </TorchButton> + ); +}; + +export default QRScannerTorch; + +const styles = StyleSheet.create({ + container: { + width: 48, + height: 48, + justifyContent: 'center', + alignItems: 'center', + alignSelf: 'flex-start', + borderWidth: 1, + borderColor: ColorPallet.baseColors.white, + borderRadius: 24, + }, + icon: { + marginLeft: 2, + marginTop: 2, + }, +}); diff --git a/src/components/misc/__tests__/AvatarView.test.tsx b/src/components/misc/__tests__/AvatarView.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f2122c6ac6e66fe6c227f62764d9b474043933fa --- /dev/null +++ b/src/components/misc/__tests__/AvatarView.test.tsx @@ -0,0 +1,18 @@ +import { render } from '@testing-library/react-native'; +import React from 'react'; +import AvatarView from '../AvatarView'; + +describe('AvatarView', () => { + it('should render avatarText with first character of the title', () => { + const { getByText } = render(<AvatarView name="avatar" />); + + const avatarText = getByText('a'); + expect(avatarText.props.children).toBe('a'); + }); + it('should render avatarText with first character of the title with single character', () => { + const { getByText } = render(<AvatarView name="K" />); + + const avatarText = getByText('K'); + expect(avatarText.props.children).toBe('K'); + }); +}); diff --git a/src/components/misc/__tests__/CredentialCard.test.tsx b/src/components/misc/__tests__/CredentialCard.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..47816c6dc5f306c0074dde97a62c7ae4f4c0fa3b --- /dev/null +++ b/src/components/misc/__tests__/CredentialCard.test.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { + CredentialMetadataKeys, + V1CredentialPreview, + CredentialExchangeRecord, + CredentialState, +} from '@aries-framework/core'; +import { Alert } from 'react-native'; +import { render } from '@testing-library/react-native'; +import CredentialCard from '../CredentialCard'; +import { parsedSchema } from '../../../utils/helpers'; + +const credentialRecord = new CredentialExchangeRecord({ + connectionId: '28790bfe-1345-4c64-b21a-7d98982b3894', + threadId: 'threadId', + state: CredentialState.Done, + credentialAttributes: [ + new V1CredentialPreview({ + name: 'age', + value: '25', + }), + ], +}); +credentialRecord.metadata.set(CredentialMetadataKeys.IndyCredential, { + credentialDefinitionId: 'Th7MpTaRZVRYnPiabds81Y:3:CL:17:TA', + schemaId: 'TL1EaPFCZ8Si5aUrqScBDt:2:testschema:1.0', +}); + +describe('CredentialCard', () => { + jest.mock('react-native', () => { + const RN = jest.requireActual('react-native'); + + return Object.setPrototypeOf( + { + Alert: { + ...RN.Alert, + alert: jest.fn(), + }, + }, + RN, + ); + }); + + it('testing', () => { + // Alert.alert = jest.genMockFunction(); + Alert.alert = jest.fn(); + const { getByText } = render( + <CredentialCard credential={credentialRecord} />, + ); + const name = getByText(parsedSchema(credentialRecord).name); + + expect(name.props.children).toBe(parsedSchema(credentialRecord).name); + }); +}); diff --git a/src/components/misc/__tests__/QRScannerClose.test.tsx b/src/components/misc/__tests__/QRScannerClose.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..51c3bc2e913973365a3c9488707a6eee155b560e --- /dev/null +++ b/src/components/misc/__tests__/QRScannerClose.test.tsx @@ -0,0 +1,14 @@ +import { fireEvent, render } from '@testing-library/react-native'; +import React from 'react'; +import QRScannerClose from '../QRScannerClose'; + +describe('QRScannerClose', () => { + it('should render QRScannerClose and respond onPress', () => { + const onPressMock = jest.fn(); + const { getByTestId } = render(<QRScannerClose onPress={onPressMock} />); + + const qrClose = getByTestId('closeButton'); + fireEvent.press(qrClose); + expect(onPressMock).toHaveBeenCalled(); + }); +}); diff --git a/src/components/modals/FlowDetailModal.tsx b/src/components/modals/FlowDetailModal.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b6aedaf35a255e20aa6d5fb35f8e2e58b86e95dd --- /dev/null +++ b/src/components/modals/FlowDetailModal.tsx @@ -0,0 +1,121 @@ +import React, { useEffect, useState, ReactNode } from 'react'; +import { useNavigation } from '@react-navigation/core'; +import { StackNavigationProp } from '@react-navigation/stack'; +import { useTranslation } from 'react-i18next'; +import { Modal, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; +import Icon from 'react-native-vector-icons/MaterialIcons'; + +import Button, { ButtonType } from '../button/Button'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { HomeStackParams, Screens } from '../../types/navigators'; + +interface NotificationModalProps { + title: string; + doneTitle?: string; + onDone?: () => void; + onHome?: () => void; + visible?: boolean; + doneHidden?: boolean; + homeHidden?: boolean; + children?: ReactNode; +} + +const NotificationModal: React.FC<NotificationModalProps> = ({ + title, + doneTitle, + onDone, + onHome, + visible, + doneHidden = false, + homeHidden = false, + children, +}) => { + const { t } = useTranslation(); + const navigation = useNavigation<StackNavigationProp<HomeStackParams>>(); + const [modalVisible, setModalVisible] = useState<boolean>(true); + + useEffect(() => { + if (visible !== undefined) { + setModalVisible(visible); + } + }, [visible]); + + const close = () => { + setModalVisible(false); + }; + + const closeHome = () => { + close(); + navigation.navigate(Screens.Home); + }; + + return ( + <Modal testID="notificationModal" visible={modalVisible} transparent> + <View style={styles.container}> + {homeHidden ? null : ( + <View style={styles.iconContainer}> + <TouchableOpacity + style={styles.iconButton} + onPress={onHome || closeHome} + testID="closeModal" + > + <Icon + name="home" + size={24} + color={ColorPallet.notification.infoText} + /> + </TouchableOpacity> + </View> + )} + <View style={styles.childContainer}> + <Text + style={[ + TextTheme.headingThree, + { fontWeight: 'normal', textAlign: 'center' }, + ]} + > + {title} + </Text> + {children} + </View> + {doneHidden ? null : ( + <View style={styles.buttonContainer}> + <Button + buttonType={ButtonType.Primary} + title={doneTitle || t<string>('Global.Done')} + onPress={onDone || close} + /> + </View> + )} + </View> + </Modal> + ); +}; + +export default NotificationModal; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: ColorPallet.grayscale.white, + }, + childContainer: { + flexGrow: 1, + justifyContent: 'center', + alignItems: 'center', + padding: 25, + }, + buttonContainer: { + marginBottom: 35, + marginHorizontal: 20, + }, + iconContainer: { + width: '100%', + flexDirection: 'row', + justifyContent: 'flex-end', + }, + iconButton: { + padding: 20, + paddingVertical: 28, + }, +}); diff --git a/src/components/modals/__tests__/FlowDetailModal.test.tsx b/src/components/modals/__tests__/FlowDetailModal.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d7018c6c502f9b8732dab161a339eb4d3561d3c0 --- /dev/null +++ b/src/components/modals/__tests__/FlowDetailModal.test.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import { useNavigation } from '@react-navigation/core'; +import FlowDetailModal from '../FlowDetailModal'; + +describe('Modal Component', () => { + const navigation = useNavigation(); + it('should render notification modal start correctly', () => { + const { getByTestId } = render( + <FlowDetailModal visible title="Modal Open" />, + ); + const notificationModal = getByTestId('notificationModal'); + const closeModal = getByTestId('closeModal'); + expect(notificationModal.props.visible).toBe(true); + fireEvent.press(closeModal); + expect(navigation.navigate).toHaveBeenCalledWith('Home'); + }); + it('should render notification modal close correctly', () => { + const { getByTestId } = render( + <FlowDetailModal visible={false} title="Modal Close" />, + ); + const notificationModal = getByTestId('notificationModal'); + expect(notificationModal.props.visible).toBe(false); + }); +}); diff --git a/src/components/record/Record.tsx b/src/components/record/Record.tsx new file mode 100644 index 0000000000000000000000000000000000000000..78ad4788de48d1358336a8bdb6301b4d21365003 --- /dev/null +++ b/src/components/record/Record.tsx @@ -0,0 +1,91 @@ +import { CredentialPreviewAttributeOptions } from '@aries-framework/core'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { + FlatList, + StyleSheet, + Text, + TouchableOpacity, + View, +} from 'react-native'; +import { TextTheme, ColorPallet } from '../../theme/theme'; + +import RecordAttribute from './RecordAttribute'; +import RecordFooter from './RecordFooter'; +import RecordHeader from './RecordHeader'; + +interface RecordProps { + header: () => React.ReactElement | null; + footer: () => React.ReactElement | null; + attributes?: CredentialPreviewAttributeOptions[]; + hideAttributeValues?: boolean; + attribute?: ( + attribute: CredentialPreviewAttributeOptions, + ) => React.ReactElement | null; +} + +const Record: React.FC<RecordProps> = ({ + header, + footer, + attributes = [], + hideAttributeValues = false, + attribute = null, +}) => { + const { t } = useTranslation(); + + return ( + <FlatList + testID="flat-list" + ListHeaderComponent={ + <RecordHeader> + {header()} + {hideAttributeValues ? ( + <View style={styles.linkContainer}> + <TouchableOpacity + testID="HideAll" + style={styles.link} + activeOpacity={1} + accessible + accessibilityLabel={t<string>('Record.HideAll')} + > + <Text + style={[TextTheme.normal, { color: ColorPallet.brand.link }]} + > + {t<string>('Record.HideAll')} + </Text> + </TouchableOpacity> + </View> + ) : null} + </RecordHeader> + } + ListFooterComponent={<RecordFooter>{footer()}</RecordFooter>} + data={attributes} + keyExtractor={({ name }) => name} + renderItem={({ item: attr, index }) => + attribute ? ( + attribute(attr) + ) : ( + <RecordAttribute key={index.toString()} attribute={attr} /> + ) + } + /> + ); +}; + +export default Record; + +const styles = StyleSheet.create({ + linkContainer: { + flexDirection: 'row', + justifyContent: 'flex-end', + paddingHorizontal: 25, + paddingVertical: 16, + background: ColorPallet.grayscale.white, + }, + link: { + minHeight: TextTheme.normal.fontSize, + paddingVertical: 2, + color: ColorPallet.brand.link, + background: ColorPallet.grayscale.white, + }, +}); diff --git a/src/components/record/RecordAttribute.tsx b/src/components/record/RecordAttribute.tsx new file mode 100644 index 0000000000000000000000000000000000000000..502cd0fe17c190b707e85669af694502831b6cfe --- /dev/null +++ b/src/components/record/RecordAttribute.tsx @@ -0,0 +1,82 @@ +import { CredentialPreviewAttributeOptions } from '@aries-framework/core'; +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; +import { ColorPallet, TextTheme } from '../../theme/theme'; + +interface RecordAttributeProps { + attribute: CredentialPreviewAttributeOptions; + attributeLabel?: ( + attribute: CredentialPreviewAttributeOptions, + ) => React.ReactElement | null; + attributeValue?: ( + attribute: CredentialPreviewAttributeOptions, + ) => React.ReactElement | null; +} + +const RecordAttribute: React.FC<RecordAttributeProps> = ({ + attribute, + attributeLabel = null, + attributeValue = null, +}) => { + const startCase = (str: string) => + str + .split(' ') + .map(w => w[0].toUpperCase() + w.substring(1).toLowerCase()) + .join(' '); + + return ( + <View style={styles.container}> + {attributeLabel ? ( + attributeLabel(attribute) + ) : ( + <Text style={TextTheme.label} testID="AttributeName"> + {startCase(attribute.name)} + </Text> + )} + <View style={styles.valueContainer}> + {attributeValue ? ( + attributeValue(attribute) + ) : ( + <View style={styles.valueText}> + <Text style={styles.text} testID="AttributeValue"> + {attribute.value} + </Text> + </View> + )} + </View> + <View style={styles.border} /> + </View> + ); +}; + +export default RecordAttribute; + +const styles = StyleSheet.create({ + container: { + paddingHorizontal: 25, + paddingTop: 16, + backgroundColor: ColorPallet.grayscale.white, + }, + border: { + borderBottomColor: ColorPallet.brand.primaryBackground, + borderBottomWidth: 2, + paddingTop: 12, + }, + link: { + minHeight: TextTheme.normal.fontSize, + paddingVertical: 2, + color: ColorPallet.brand.link, + }, + text: { + ...TextTheme.normal, + }, + valueContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + paddingTop: 10, + }, + valueText: { + minHeight: TextTheme.normal.fontSize, + paddingVertical: 4, + }, +}); diff --git a/src/components/record/RecordFooter.tsx b/src/components/record/RecordFooter.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5aaaedc3e1a6dcd3e76f8c7a519cf91fd3530992 --- /dev/null +++ b/src/components/record/RecordFooter.tsx @@ -0,0 +1,22 @@ +import React, { ReactNode } from 'react'; +import { StyleSheet, View } from 'react-native'; +import { ColorPallet } from '../../theme/theme'; + +const RecordFooter: React.FC<{ children?: ReactNode }> = ({ children }) => { + return ( + <View style={styles.container} testID="recordFooter"> + {children} + </View> + ); +}; + +export default RecordFooter; + +const styles = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + height: '100%', + paddingHorizontal: 25, + paddingVertical: 16, + }, +}); diff --git a/src/components/record/RecordHeader.tsx b/src/components/record/RecordHeader.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f5216e285cbc6d5c3a35c772b3bca6190a29bd10 --- /dev/null +++ b/src/components/record/RecordHeader.tsx @@ -0,0 +1,19 @@ +import React, { ReactNode } from 'react'; +import { StyleSheet, View } from 'react-native'; +import { ColorPallet } from '../../theme/theme'; + +const RecordHeader: React.FC<{ children?: ReactNode }> = ({ children }) => { + return ( + <View style={styles.container} testID="recordHeader"> + {children} + </View> + ); +}; + +export default RecordHeader; + +const styles = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + }, +}); diff --git a/src/components/record/__tests__/Record.test.tsx b/src/components/record/__tests__/Record.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5eb57208243a070d25297ffbe350a16ac0b6ea27 --- /dev/null +++ b/src/components/record/__tests__/Record.test.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import RecordAttribute from '../RecordAttribute'; +import RecordFooter from '../RecordFooter'; +import RecordHeader from '../RecordHeader'; + +describe('Record Component', () => { + it('should render record attribute correctly', () => { + const attribute = [{ name: 'JoieDon', value: 'JoieDon-Value' }]; + + const { getByTestId } = render( + <RecordAttribute attribute={attribute[0]} />, + ); + const AttributeName = getByTestId('AttributeName'); + fireEvent.press(AttributeName); + const AttributeValue = getByTestId('AttributeValue'); + fireEvent.press(AttributeValue); + }); + it('should render record footer correctly', () => { + const { getByTestId } = render(<RecordFooter />); + const recordFooter = getByTestId('recordFooter'); + fireEvent.press(recordFooter); + }); + it('should render record header correctly', () => { + const { getByTestId } = render(<RecordHeader />); + const recordHeader = getByTestId('recordHeader'); + fireEvent.press(recordHeader); + }); +}); diff --git a/src/components/screenNavigatorButtons/ScreenNavigatorButtons.tsx b/src/components/screenNavigatorButtons/ScreenNavigatorButtons.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1ee0ca0bc3a3199b6120062efc5a1fa3f85b10fc --- /dev/null +++ b/src/components/screenNavigatorButtons/ScreenNavigatorButtons.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { StyleSheet, View } from 'react-native'; +import IconButton from '../iconButton/IconButton'; + +interface IconButtonProps { + isLeftDisabled?: boolean; + isRightDisabled?: boolean; + onLeftPress: () => void; + onRightPress: () => void; +} + +const ScreenNavigatorButtons: React.FC<IconButtonProps> = ({ + isLeftDisabled = false, + isRightDisabled = false, + onLeftPress, + onRightPress, +}) => { + return ( + <View style={styles.container} testID="ScreenNavigatorButtons"> + <IconButton isDisabled={isLeftDisabled} onPress={onLeftPress} /> + <IconButton isRight isDisabled={isRightDisabled} onPress={onRightPress} /> + </View> + ); +}; + +export default ScreenNavigatorButtons; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + justifyContent: 'space-between', + }, +}); diff --git a/src/components/screenNavigatorButtons/__tests__/ScreenNavigatorButtons.test.tsx b/src/components/screenNavigatorButtons/__tests__/ScreenNavigatorButtons.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0ed575d5fc9606f1ddf7dc68c9bf444a6cae74a7 --- /dev/null +++ b/src/components/screenNavigatorButtons/__tests__/ScreenNavigatorButtons.test.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import { ReactTestInstance } from 'react-test-renderer'; +import ScreenNavigatorButtons from '../ScreenNavigatorButtons'; + +describe('ScreenNavigatorButtons Component', () => { + it('should render ScreenNavigatorButtons correctly and respond on press', () => { + const onLeftPressMock = jest.fn(); + const onRightPressMock = jest.fn(); + + const { getByTestId } = render( + <ScreenNavigatorButtons + onLeftPress={onLeftPressMock} + onRightPress={onRightPressMock} + />, + ); + const screenNavigatorButtons = getByTestId('ScreenNavigatorButtons'); + fireEvent( + screenNavigatorButtons.children[0] as ReactTestInstance, + 'onPress', + ); + fireEvent.press(screenNavigatorButtons); + expect(onLeftPressMock).toHaveBeenCalled(); + + fireEvent( + screenNavigatorButtons.children[1] as ReactTestInstance, + 'onPress', + ); + fireEvent.press(screenNavigatorButtons); + expect(onRightPressMock).toHaveBeenCalled(); + }); +}); diff --git a/src/components/text/HighlightTextBox.tsx b/src/components/text/HighlightTextBox.tsx new file mode 100644 index 0000000000000000000000000000000000000000..8404a36d7c5cfaaedcae933d236836307f67d20b --- /dev/null +++ b/src/components/text/HighlightTextBox.tsx @@ -0,0 +1,48 @@ +import React, { ReactNode } from 'react'; +import { StyleSheet, Text, View } from 'react-native'; +import { ColorPallet, TextTheme } from '../../theme/theme'; + +export interface TextBoxProps { + children?: ReactNode; +} + +const HighlightTextBox: React.FC<TextBoxProps> = ({ children }) => { + return ( + <View style={[style.container]}> + <View style={[style.accentBox]} /> + <Text + style={[ + style.headerText, + { paddingTop: offset, paddingBottom: offset }, + ]} + testID="HighlightTextBox" + accessibilityLabel="HighlightTextBox" + > + {children} + </Text> + </View> + ); +}; + +export default HighlightTextBox; + +const offset = 10; + +const style = StyleSheet.create({ + icon: { + marginRight: offset, + }, + container: { + flexDirection: 'row', + backgroundColor: ColorPallet.grayscale.white, + }, + accentBox: { + marginRight: offset, + backgroundColor: ColorPallet.baseColors.yellow, + width: 8, + }, + headerText: { + ...TextTheme.normal, + flexShrink: 1, + }, +}); diff --git a/src/components/text/InfoTextBox.tsx b/src/components/text/InfoTextBox.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4993b4f237e5b6981ee835021abba3b28b20db13 --- /dev/null +++ b/src/components/text/InfoTextBox.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { Image, StyleSheet, Text, View } from 'react-native'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import Images from '../../assets'; + +export interface TextBoxProps { + children?: React.ReactNode; + showIcon?: boolean; +} + +const InfoTextBox: React.FC<TextBoxProps> = ({ + children, + showIcon = false, +}) => { + return ( + <View style={styles.container}> + {showIcon && ( + <View style={styles.icon}> + <Image source={Images.infoIcon} style={styles.infoIcon} /> + </View> + )} + <Text + style={styles.headerText} + testID="InfoTextBox" + accessibilityLabel="InfoTextBox" + > + {children} + </Text> + </View> + ); +}; + +export default InfoTextBox; + +const iconSize = 30; +const offset = 10; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + backgroundColor: ColorPallet.grayscale.veryLightGrey, + borderRadius: 5, + padding: 10, + }, + headerText: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + flexShrink: 1, + alignSelf: 'center', + }, + icon: { + marginRight: offset, + alignSelf: 'center', + }, + infoIcon: { + width: iconSize, + height: iconSize, + }, +}); diff --git a/src/components/text/Label.tsx b/src/components/text/Label.tsx new file mode 100644 index 0000000000000000000000000000000000000000..70a9064c98e5a31b9b4319282670421ea64a6306 --- /dev/null +++ b/src/components/text/Label.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; + +import Text from './Text'; + +type Props = { + title: string; + subtitle?: string; + label?: string; +}; + +const Label: React.FC<Props> = ({ title, subtitle = '', label = '' }) => { + return ( + <View style={styles.container}> + <View style={styles.titleContainer}> + <Text style={styles.title}>{title}:</Text> + <Text style={styles.subtitle}>{subtitle}</Text> + </View> + <Text style={styles.label}>{label}</Text> + </View> + ); +}; + +export default Label; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + width: '90%', + marginTop: 10, + }, + titleContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + title: { + fontWeight: 'bold', + fontSize: 16, + marginRight: 7, + }, + subtitle: {}, + label: { + marginLeft: 10, + fontSize: 10, + fontStyle: 'italic', + }, +}); diff --git a/src/components/text/Text.tsx b/src/components/text/Text.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b598040a9a44251b46f4fd680a9049971e3150e5 --- /dev/null +++ b/src/components/text/Text.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { Text as T, StyleSheet, TextStyle, StyleProp } from 'react-native'; +import { ColorPallet } from '../../theme/theme'; + +type Props = { + children: React.ReactNode; + style?: StyleProp<TextStyle>; +}; + +const Text: React.FC<Props> = ({ children, style }) => { + return ( + <T style={[styles.text, style]} testID="Text" accessibilityLabel="Text"> + {children} + </T> + ); +}; + +export default Text; + +const styles = StyleSheet.create({ + text: { + color: ColorPallet.brand.primary, + }, +}); diff --git a/src/components/text/Title.tsx b/src/components/text/Title.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e2a2964b856c7e0bb7fb508f03bc35271978fda6 --- /dev/null +++ b/src/components/text/Title.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { Text, StyleSheet, TextStyle } from 'react-native'; +import { ColorPallet } from '../../theme/theme'; + +interface Props { + children?: React.ReactNode; + style?: TextStyle; +} + +const Title: React.FC<Props> = ({ children, style }) => { + return ( + <Text + style={[styles.title, style]} + testID="Title" + accessibilityLabel="Title" + > + {children} + </Text> + ); +}; + +export default Title; + +const styles = StyleSheet.create({ + title: { + fontWeight: 'bold', + fontSize: 20, + color: ColorPallet.brand.primary, + }, +}); diff --git a/src/components/text/__tests__/Text.test.tsx b/src/components/text/__tests__/Text.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..7f88784918f3d494b20bb4b28b972442fb2d3b29 --- /dev/null +++ b/src/components/text/__tests__/Text.test.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { render } from '@testing-library/react-native'; +import HighlightTextBox from '../HighlightTextBox'; +import InfoTextBox from '../InfoTextBox'; +import Text from '../Text'; +import Title from '../Title'; + +describe('Text Component', () => { + it('should render highlight text correctly', () => { + const { getByLabelText } = render( + <HighlightTextBox>HighlightTextBox</HighlightTextBox>, + ); + expect(getByLabelText('HighlightTextBox')).toBeTruthy(); + }); + + it('should render info text correctly', () => { + const { getByLabelText } = render(<InfoTextBox>InfoTextBox</InfoTextBox>); + expect(getByLabelText('InfoTextBox')).toBeTruthy(); + }); + + it('should render text correctly', () => { + const { getByLabelText } = render(<Text>Text</Text>); + expect(getByLabelText('Text')).toBeTruthy(); + }); + + it('should render title correctly', () => { + const { getByLabelText } = render(<Title>Title</Title>); + expect(getByLabelText('Title')).toBeTruthy(); + }); +}); diff --git a/src/components/toast/BaseToast.tsx b/src/components/toast/BaseToast.tsx new file mode 100644 index 0000000000000000000000000000000000000000..fa4eb5a9f313126e2102309d4c2e54a753b8ec4b --- /dev/null +++ b/src/components/toast/BaseToast.tsx @@ -0,0 +1,129 @@ +import React from 'react'; +import { View, Text, useWindowDimensions, StyleSheet } from 'react-native'; +import Icon from 'react-native-vector-icons/MaterialIcons'; + +import { + TextTheme, + borderRadius, + borderWidth, + ColorPallet, +} from '../../theme/theme'; + +interface BaseToastProps { + title: string; + body: string; + toastType: string; +} + +export enum ToastType { + Success = 'success', + Info = 'info', + Warn = 'warn', + Error = 'error', +} + +const BaseToast: React.FC<BaseToastProps> = ({ title, body, toastType }) => { + const { width } = useWindowDimensions(); + const iconSize = 24; + let iconName = ''; + let backgroundColor = ''; + let borderColor = ''; + let iconColor = ''; + let textColor = ''; + + switch (toastType) { + case ToastType.Success: + iconName = 'check-circle'; + backgroundColor = ColorPallet.notification.success; + borderColor = ColorPallet.notification.successBorder; + iconColor = ColorPallet.notification.successIcon; + textColor = ColorPallet.notification.successText; + break; + + case ToastType.Info: + iconName = 'info'; + backgroundColor = ColorPallet.notification.info; + borderColor = ColorPallet.notification.infoBorder; + iconColor = ColorPallet.notification.infoIcon; + textColor = ColorPallet.notification.infoText; + break; + + case ToastType.Warn: + iconName = 'report-problem'; + backgroundColor = ColorPallet.notification.warn; + borderColor = ColorPallet.notification.warnBorder; + iconColor = ColorPallet.notification.warnIcon; + textColor = ColorPallet.notification.warnText; + break; + + case ToastType.Error: + iconName = 'error'; + backgroundColor = ColorPallet.notification.error; + borderColor = ColorPallet.notification.errorBorder; + iconColor = ColorPallet.notification.errorIcon; + textColor = ColorPallet.notification.errorText; + break; + + default: + throw new Error('ToastType was not set correctly.'); + } + + return ( + <View + style={[ + styles.container, + { backgroundColor, borderColor, width: width - width * 0.1 }, + ]} + > + <Icon + style={styles.icon} + name={iconName} + color={iconColor} + size={iconSize} + /> + <View style={[styles.textContainer]}> + <Text + style={[TextTheme.normal, styles.title, { color: textColor }]} + testID="toastTitle" + accessibilityLabel={title} + > + {title} + </Text> + <Text + style={[TextTheme.label, styles.body, { color: textColor }]} + testID="toastBpdy" + accessibilityLabel={body} + > + {body} + </Text> + </View> + </View> + ); +}; + +export default BaseToast; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'flex-start', + flexDirection: 'row', + borderWidth, + borderRadius, + }, + textContainer: { + flexShrink: 1, + marginVertical: 10, + marginRight: 10, + }, + icon: { + marginTop: 15, + marginHorizontal: 15, + }, + title: { + fontWeight: 'bold', + }, + body: { + marginTop: 10, + }, +}); diff --git a/src/components/toast/ToastConfig.tsx b/src/components/toast/ToastConfig.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ffb93c444141f8d2fa2ccbb0d5ccf9da6fd11557 --- /dev/null +++ b/src/components/toast/ToastConfig.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { ToastShowParams } from 'react-native-toast-message'; + +import BaseToast, { ToastType } from './BaseToast'; + +const toastConfig = { + success: (props: ToastShowParams) => ( + <BaseToast + title={props.text1!} + body={props.text2!} + toastType={ToastType.Success} + /> + ), + warn: (props: ToastShowParams) => ( + <BaseToast + title={props.text1!} + body={props.text2!} + toastType={ToastType.Warn} + /> + ), + error: (props: ToastShowParams) => ( + <BaseToast + title={props.text1!} + body={props.text2!} + toastType={ToastType.Error} + /> + ), + info: (props: ToastShowParams) => ( + <BaseToast + title={props.text1!} + body={props.text2!} + toastType={ToastType.Info} + /> + ), +}; + +export default toastConfig; diff --git a/src/components/toast/__tests__/Toast.test.tsx b/src/components/toast/__tests__/Toast.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..8795c458e60523fe5d3d2acf07f9375e1082020e --- /dev/null +++ b/src/components/toast/__tests__/Toast.test.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { render } from '@testing-library/react-native'; +import BaseToast, { ToastType } from '../BaseToast'; + +describe('Toast Component', () => { + it('should render success toast correctly', () => { + const { getByLabelText } = render( + <BaseToast + title="SuccessToastTitle" + toastType={ToastType.Success} + body="Success Toast Message" + />, + ); + expect(getByLabelText('SuccessToastTitle')).toBeTruthy(); + }); + + it('should render info toast correctly', () => { + const { getByLabelText } = render( + <BaseToast + title="InfoToastTitle" + toastType={ToastType.Info} + body="Info Toast Message" + />, + ); + expect(getByLabelText('InfoToastTitle')).toBeTruthy(); + }); + + it('should render warn toast correctly', () => { + const { getByLabelText } = render( + <BaseToast + title="WarnToastTitle" + toastType={ToastType.Warn} + body="Warn Toast Message" + />, + ); + expect(getByLabelText('WarnToastTitle')).toBeTruthy(); + }); + + it('should render error toast correctly', () => { + const { getByLabelText } = render( + <BaseToast + title="ErrorToastTitle" + toastType={ToastType.Error} + body="Error Toast Message" + />, + ); + expect(getByLabelText('ErrorToastTitle')).toBeTruthy(); + }); +}); diff --git a/src/components/views/ProofRequestAttribute.tsx b/src/components/views/ProofRequestAttribute.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4402c6257c2c495aa0c994318157403248a0e2bf --- /dev/null +++ b/src/components/views/ProofRequestAttribute.tsx @@ -0,0 +1,74 @@ +import React from 'react'; +import { StyleSheet, View } from 'react-native'; +import DropDown from '../listItems/DropDown'; +import Text from '../text/Text'; +import { TextTheme } from '../../theme/theme'; +import { CredentialDisplay } from '../../types/record'; + +interface Props { + proofRequest: CredentialDisplay[]; + onSelectItem: (item: any, key: string) => void; +} + +const ProofRequestAttribute: React.FC<Props> = ({ + proofRequest, + onSelectItem, +}: Props) => { + return ( + <View testID="proofRequestAttribute"> + {proofRequest?.map((item: any) => ( + <View key={item.names[0]} style={styles.attributeView}> + {item.names?.map((name: string, index: number) => ( + <View key={name} style={styles.credentialView}> + <Text style={[TextTheme.normal, styles.nameText]}>{name} : </Text> + <Text style={[TextTheme.normal, styles.valueText]}> + {item.values[index]} + </Text> + </View> + ))} + {item.credentials.length <= 1 ? ( + <Text style={styles.credentialName}> + {item.credentials[0].label} + </Text> + ) : ( + <View style={styles.dropdownContainer}> + <DropDown + items={item.credentials} + onSelectItem={value => onSelectItem(value, item.key)} + /> + </View> + )} + </View> + ))} + </View> + ); +}; + +export default ProofRequestAttribute; + +const styles = StyleSheet.create({ + attributeView: { + borderBottomWidth: 1, + paddingVertical: 12, + alignItems: 'center', + }, + credentialView: { + flexDirection: 'row', + width: '100%', + }, + valueText: { + flex: 1, + textAlign: 'right', + }, + nameText: { + flex: 1, + textAlign: 'left', + }, + credentialName: { + ...TextTheme.label, + width: '100%', + textAlign: 'left', + marginTop: 8, + }, + dropdownContainer: { marginTop: 8 }, +}); diff --git a/src/components/views/SafeAreaScrollView.tsx b/src/components/views/SafeAreaScrollView.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ca033f6fbdd2c983bffc8df7c87d27ce9ca857da --- /dev/null +++ b/src/components/views/SafeAreaScrollView.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { ScrollView, StyleSheet } from 'react-native'; +import { ColorPallet } from '../../theme/theme'; + +interface Props { + children: React.ReactNode; +} + +const SafeAreaScrollView: React.FC<Props> = ({ children }) => { + return ( + <ScrollView contentContainerStyle={styles.scrollView} testID="safeareaview"> + {children} + </ScrollView> + ); +}; + +export default SafeAreaScrollView; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: ColorPallet.grayscale.white, + }, + scrollView: { + alignItems: 'center', + }, +}); diff --git a/src/components/views/__tests__/ProofRequestAttribute.test.tsx b/src/components/views/__tests__/ProofRequestAttribute.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4c4e51607d682b22226caf345049512a86bd2c6d --- /dev/null +++ b/src/components/views/__tests__/ProofRequestAttribute.test.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import SafeAreaScrollView from '../SafeAreaScrollView'; +import ProofRequestAttribute from '../ProofRequestAttribute'; + +describe('ProofRequestAttribute Component', () => { + it('should render proof request attribute correctly', () => { + const proofRequest = [ + { + key: 'JoieDon', + credentials: [ + { + isSelected: true, + label: 'name', + value: 'JoieDon', + }, + ], + names: ['JoieDon', 'JoieDon1'], + values: ['JoieDon', 'JoieDon1'], + }, + { + key: 'kevin', + credentials: [ + { + isSelected: true, + label: 'name', + value: 'kevin', + }, + ], + names: ['kevin', 'kevin1'], + values: ['kevinvalues', 'kevin1'], + }, + ]; + const onSelectItemMock = jest.fn(); + const { getByTestId } = render( + <ProofRequestAttribute + proofRequest={proofRequest} + onSelectItem={onSelectItemMock} + />, + ); + const proofRequestAttribute = getByTestId('proofRequestAttribute'); + fireEvent.press(proofRequestAttribute); + }); + it('should render safeareaview correctly', () => { + const { getByTestId } = render( + <SafeAreaScrollView>safeareaview</SafeAreaScrollView>, + ); + const safeareaview = getByTestId('safeareaview'); + fireEvent.press(safeareaview); + }); +}); diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..fa332302e0ab07e3335c8677ad9e1647a3d592f7 --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,28 @@ +export const defaultLanguage = 'en'; + +export const testIdPrefix = 'com.pcm:id/'; + +export const salt = + '1234567891011121314151617181920212223242526272829303132333435363'; + +export enum LocalStorageKeys { + Language = 'language', + OnboardingCompleteStage = 'onboardingCompleteStage', +} + +export enum KeychainStorageKeys { + GUID = 'email', + Passphrase = 'passphrase', + Passcode = 'passcode', + ScannedQrCodes = 'scannedQrCodes', +} + +export const dateFormatOptions: { + year: 'numeric'; + month: 'short'; + day: 'numeric'; +} = { + year: 'numeric', + month: 'short', + day: 'numeric', +}; diff --git a/src/hooks/notifications.ts b/src/hooks/notifications.ts new file mode 100644 index 0000000000000000000000000000000000000000..c373d3b1648a3b036aefca3fa17adea84aeee378 --- /dev/null +++ b/src/hooks/notifications.ts @@ -0,0 +1,65 @@ +import { + CredentialExchangeRecord, + CredentialState, + ProofRecord, + ProofState, +} from '@aries-framework/core'; +import { + useAgent, + useCredentialByState, + useProofByState, +} from '@aries-framework/react-hooks'; +import { useCallback, useEffect, useState } from 'react'; + +interface Notifications { + total: number; + notifications: Array<CredentialExchangeRecord | ProofRecord>; +} + +const useNotifications = (): Notifications => { + const { agent } = useAgent(); + const offers = useCredentialByState(CredentialState.OfferReceived); + const proofs = useProofByState(ProofState.RequestReceived); + const [notificationsList, setNotificationsList] = useState< + Array<CredentialExchangeRecord | ProofRecord> + >([]); + + const deleteUnwantedRecords = useCallback(async () => { + // Declining the credential if connection is deleted + for await (const offer of offers) { + if (!offer?.connectionId) { + await agent?.credentials.declineOffer(offer.id); + } + } + + // Declining the proof if connection is deleted and message doesn't have ~service decorator + for await (const proof of proofs) { + if (!proof?.connectionId && !proof.requestMessage?.service) { + await agent?.proofs.declineRequest(proof.id); + } + } + }, [agent?.credentials, agent?.proofs, offers, proofs]); + + useEffect(() => { + deleteUnwantedRecords(); + }, [deleteUnwantedRecords]); + + const notifications = [...offers, ...proofs].sort( + (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(), + ); + + useEffect(() => { + const interval = setInterval(() => { + setNotificationsList(notifications); + }, 500); + + return () => clearInterval(interval); + }, [notifications]); + + return { + total: notificationsList.length, + notifications: notificationsList ?? [], + }; +}; + +export default useNotifications; diff --git a/src/hooks/useSealQrCodes.ts b/src/hooks/useSealQrCodes.ts new file mode 100644 index 0000000000000000000000000000000000000000..cdc86bf2786be48b660f964b522d65640c4bf8f6 --- /dev/null +++ b/src/hooks/useSealQrCodes.ts @@ -0,0 +1,100 @@ +import { useEffect, useState } from 'react'; +import { Alert } from 'react-native'; +import { KeychainStorageKeys } from '../constants'; +import { getValueFromKeychain } from '../screens/PinEnter/PinEnter.utils'; +import { setValueKeychain } from '../utils/keychain'; + +export interface SealQrCodeRecord { + subject: undefined | string; + date: number; + url: string; +} + +interface Notifications { + sealedQrCodes: SealQrCodeRecord[]; + addSealedQrCode: (url: string) => void; + updateSealedQrCodeSubject: (url: string, subject: string) => void; +} + +const useSealQrCodes = (): Notifications => { + const [sealedQrCodes, setSealedQrCodes] = useState<SealQrCodeRecord[]>([]); + const readFromLocalStorage = async (): Promise<SealQrCodeRecord[]> => { + const lsValue = await getValueFromKeychain( + KeychainStorageKeys.ScannedQrCodes, + ); + if (!lsValue) { + return []; + } + let data: SealQrCodeRecord[]; + try { + data = JSON.parse(lsValue.password); + } catch (e) { + return []; + } + + if (Array.isArray(data)) { + return data; + } + return []; + }; + useEffect(() => { + (async () => { + const urls = await readFromLocalStorage(); + setSealedQrCodes(urls); + })(); + }, []); + + const addSealedQrCode = async (url: string) => { + const urls = []; + let subject; + sealedQrCodes.forEach(p => { + if (p.url !== url) { + urls.push(p); + } else { + subject = p.subject; + } + }); + const newUrls = [ + ...urls, + { + subject, + date: new Date().getTime(), + url, + }, + ]; + try { + await setValueKeychain('Sealed qr codes', JSON.stringify(newUrls), { + service: KeychainStorageKeys.ScannedQrCodes, + }); + setSealedQrCodes(newUrls); + } catch (e) { + console.error(e); + Alert.alert(e); + } + }; + + const updateSealedQrCodeSubject = async (url: string, subject: string) => { + const obj = sealedQrCodes.find(p => p.url === url); + if (!obj) { + return; + } + obj.subject = subject; + try { + await setValueKeychain('Sealed qr codes', JSON.stringify(sealedQrCodes), { + service: KeychainStorageKeys.ScannedQrCodes, + }); + setSealedQrCodes(sealedQrCodes); + } catch (e) { + console.error(e); + Alert.alert(e); + } + }; + + return { + sealedQrCodes, + addSealedQrCode, + updateSealedQrCodeSubject, + }; +}; + +export default useSealQrCodes; diff --git a/src/localization/de/index.ts b/src/localization/de/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..8caabf575059eaa956b697d661e5fac84b820183 --- /dev/null +++ b/src/localization/de/index.ts @@ -0,0 +1,240 @@ +// prettier-ignore +const translation = { + 'Global': { + 'EnterPin': 'Pin eingeben', + 'EnterNewPin': 'Neue PIN eingeben', + '6DigitPin': '6-stellige Pin', + 'Submit': 'Senden', + 'NoneYet!': 'Noch keine!', + 'Cancel': 'Abbrechen', + 'Confirm': 'Bestätigen Sie', + 'Accept': 'Akzeptieren', + 'Reject': 'Ablehnen', + 'Share': 'Teilen', + 'Decline': 'Ablehnen', + 'Back': 'Zurück', + 'Next': 'Weiter', + 'Continue': 'Weiter', + 'Info': 'Informationen', + 'Failure': 'Scheitern', + 'Success': 'Erfolg', + 'SomethingWentWrong': 'Etwas ging schief', + 'Done': 'Erledigt', + 'Skip': 'Überspringen', + 'Previous': 'Vorher', + 'View': 'Ansicht', + 'Home': 'Startseite', + 'ErrorCode': 'Fehlercode', + 'Okay': 'Okay', + 'Verify': 'Verifizieren', + 'ChangePin': 'PIN ändern', + 'OldPin': 'Alte PIN eingeben', + 'Copy': 'Kopieren', + 'from': 'von', + 'ThisDecisionCannotBeChanged.': 'Diese Entscheidung kann nicht geändert werden.', + 'ZeroRecords': 'Keine Aufzeichnungen verfügbar', + 'ImportWallet': 'Brieftasche importieren', + 'WalletInitialized':'Ihre Brieftasche wurde erfolgreich initialisiert', + 'UserInactivity': 'Abmelden aufgrund von Inaktivität', + }, + 'Language': { + 'English': 'Englisch', + 'French': 'Französisch', + 'German': 'Deutsch', + }, + 'Terms': { + 'AcceptTerms': 'Bitte lesen und akzeptieren Sie die nachstehenden Bedingungen, bevor Sie diese Anwendung verwenden.', + 'TermsAndConditions': 'Diese Bedingungen legen die Rechte und Pflichten aller Nutzer in Bezug auf die Nutzung des Dienstes fest. Ihr Zugang zu und Ihre Nutzung des Dienstes setzt voraus, dass Sie diese Bedingungen akzeptieren und einhalten. Diese Allgemeinen Geschäftsbedingungen gelten für alle Besucher, Benutzer und andere, die auf den Dienst zugreifen oder ihn nutzen.', + 'Attestation': 'Ich habe die AGB gelesen, verstanden und akzeptiere sie.', + }, + 'Registration':{ + 'RegisterAgain': 'Bitte registrieren Sie sich erneut', + 'MnemonicMsg': 'Dieser Satz ist die einzige Möglichkeit, Brieftaschen zu exportieren und zu importieren und an einem sicheren und geheimen Ort aufzubewahren.Die Phrase kann später unter der Registerkarte Einstellungen gefunden werden', + 'Passphrase': 'Passphrase', + 'Mnemonic': 'Mnemonik', + 'SecondCounter': 'Zweite links', + 'WalletInitialized':'Wallet erfolgreich initialisiert.', + }, + 'PinCreate': { + 'UserAuthenticationPin': 'Benutzerauthentifizierungs-PIN', + 'PinMustBe6DigitsInLength': 'Die PIN muss 6 Ziffern lang sein', + 'ReEnterPinMustBe6DigitsInLength': 'Unzureichende PIN-Länge', + 'PinsEnteredDoNotMatch': 'Die eingegebenen Pins stimmen nicht überein', + 'PinsSuccess': 'Pin erfolgreich erstellt', + 'PinChange': 'PIN-Änderung erfolgreich', + 'NewPinMatchwithOld': 'Der neue Pin ist derselbe wie der alte Pin', + '6DigitPin': '6-stellige PIN', + 'ReenterPin': 'PIN erneut eingeben', + 'ReenterNewPin': 'Geben Sie die neue PIN erneut ein', + 'Create': 'Schaffen', + 'ValidOldPin': 'Bitte geben Sie eine gültige alte PIN ein', + 'WalletCreated': 'Die Brieftasche wurde erfolgreich erstellt', + 'OR': 'ODER', + 'PinInfo': 'Dieser Pin wird für die Anmeldung verwendet', + }, + 'Biometric': { + 'Biometric': 'Biometrisch', + 'BiometricConfirm': 'Confirm fingerprint', + 'BiometricSuccess': 'Fingerabdruck erfolgreich konfiguriert', + 'BiometricFailed': 'Biometrie fehlgeschlagen', + 'BiometricCancel': 'Der Benutzer hat die biometrische Eingabeaufforderung abgebrochen', + 'BiometricNotSupport': 'Biometrische Daten werden nicht unterstützt', + 'RegisterPinandBiometric': 'Registrieren Sie PIN und Biometrie', + 'BiometricInfo': 'Registrieren Sie die biometrische Verwendung für die Anmeldung', + }, + 'Initialization':{ + 'CompleteInitialization':'Schließen Sie die Initialisierung ab', + 'InitializationInfo':"Initialiser le nouveau portefeuille ou importer l'ancien portefeuille", + }, + 'Mnemonic':{ + 'MnemonicTitle':'Unten ist die Mnemonik für zukünftige Referenzen', + }, + 'Home': { + 'Welcome': 'Herzlich willkommen', + 'Notifications': 'Benachrichtigungen', + 'NoNewUpdates': 'Es gibt keine neue Benachrichtigung.', + 'NoCredentials': 'Es gibt keine Zugangsdaten in der Wallet.', + 'SeeAll': 'Alle anzeigen', + 'YouHave': 'Sie haben', + 'Credential': 'Zugangsdaten', + 'Credentials': 'Zugangsdaten', + 'InYourWallet': 'in Ihrem Wallet', + }, + 'PinEnter': { + 'IncorrectPin': 'Falsche PIN', + }, + 'Settings': { + 'ChangePin': 'Pin ändern', + 'Version': 'Version', + 'AppPreferences': 'App-Einstellungen', + 'AboutApp': 'Über App', + 'Language': 'Sprache', + 'Logout': 'Ausloggen', + 'LogoutMsg': 'Bitte bestätigen Sie die Abmeldung', + 'MnemonicMsg': 'Mnemonik darf nicht leer sein', + 'EnterMnemonic': 'Geben Sie Mnemonik ein', + 'ValidMnemonic': 'Gültige Mnemonik', + 'InvalidMnemonic': 'Ungültige Mnemonik', + 'Yes': 'Jawohl', + 'No': 'Nein', + 'ExportWallet': 'Brieftasche exportieren', + 'ViewMnemonic': 'Mnemonik ansehen', + }, + 'ExportWallet':{ + 'WalletExportedPath': 'Wallet in den Pfad exportiert :', + }, + 'ImportWallet':{ + 'SelectWalletFile': 'Wählen Sie Wallet-Datei aus', + 'EmptyMnemonic': 'Mnemoniken dürfen nicht leer sein', + 'InvalidMnemonic': 'Ungültige Mnemonik ', + 'WalletRestoreFailed':'Wallet-Wiederherstellung fehlgeschlagen', + 'ImportError': 'Entweder Ihre E-Mail oder Mnemonik ist falsch, bitte überprüfen Sie es sorgfältig', + }, + 'ConnectionInvitation':{ + 'VerifyMessage': 'Überprüfen Sie die Verbindungsdetails sorgfältig', + 'ConsentMessage': 'Neue Verbindungsanforderung', + }, + 'ContactDetails': { + 'Created': 'Erstellt', + 'ConnectionState': 'Verbindungs status', + 'AContact': 'Ein Kontakt', + 'DeleteConnection': 'Verbindung löschen', + 'DeleteConnectionAlert': 'Möchten Sie diese Verbindung wirklich löschen?', + 'DeleteConnectionSuccess': 'Verbindung erfolgreich gelöscht', + 'DeleteConnectionFailed': 'Fehler beim Löschen der Verbindung', + 'ConnectionCannotDelete': 'Mediator-Verbindung kann nicht gelöscht werden', + }, + 'Credentials': { + 'CredentialsNotFound': 'Anmeldedaten nicht gefunden', + }, + 'CredentialDetails': { + 'Id': 'Ausweis:', + 'CreatedAt': 'Hergestellt in:', + 'Version': 'Ausführung', + 'Issued': 'Problematisch', + 'PrivacyPolicy': 'Datenschutz-Bestimmungen', + 'TermsAndConditions': 'Geschäftsbedingungen', + 'RemoveFromWallet': 'Aus der Brieftasche entfernen', + }, + 'CredentialOffer': { + 'ThisIsTakingLongerThanExpected': 'Dies dauert länger als erwartet. Schauen Sie später noch einmal vorbei, um einen neuen Berechtigungsnachweis zu erhalten.', + 'RejectThisCredential?': 'Diese Anmeldeinformationen ablehnen?', + 'AcceptingCredential': 'Akzeptieren von Anmeldeinformationen', + 'SuccessfullyAcceptedCredential': 'Anmeldeinformationen erfolgreich akzeptiert', + 'RejectingCredential':'Ausweis ablehnen', + 'SuccessfullyRejectedCredential':'Die Anmeldeinformationen wurden erfolgreich abgelehnt', + 'CredentialNotFound': 'Anmeldedaten nicht gefunden', + 'CredentialAccepted': 'Anmeldeinformationen akzeptiert', + 'CredentialRejected': 'Anmeldeinformationen abgelehnt', + 'CredentialAddedToYourWallet': 'Der Brieftasche hinzugefügte Anmeldeinformationen', + 'CredentialDeclined': 'Anmeldedaten abgelehnt', + 'CredentialOnTheWay': 'Der Ausweis ist unterwegs', + 'CredentialOffer': 'Neue Anmeldeinformationen', + 'IsOfferingYouACredential': 'is offering a credential', + }, + 'TabStack': { + 'Home': 'Zuhause', + 'Connections': 'Verbindung', + 'Scan': 'Scan', + 'Credentials': 'Referenzen', + 'Settings': 'Einstellungen', + }, + 'ProofRequest': { + 'Title': '<b>{{connection}}</b> demande une vérification à partir de votre portefeuille. \n\nSie bitten darum, zu teilen :', + 'OfferDelay': 'Angebotsverzögerung', + 'RejectThisProof?': 'Diesen Nachweis ablehnen?', + 'AcceptingProof': 'Nachweis wird akzeptiert', + 'SuccessfullyAcceptedProof': 'Nachweis erfolgreich akzeptiert', + 'ProofNotFound': 'Nachweis nicht gefunden', + 'RejectingProof': 'Nachweis wird abgelehnt', + 'ProofAccepted': 'Nachweis akzeptiert', + 'ProofRejected': 'Nachweis abgelehnt', + 'RequestedCredentialsCouldNotBeFound': 'Angeforderte Anmeldeinformationen konnten nicht gefunden werden', + 'ProofRequest': 'Neuer Nachweis angefordert', + 'NotAvailableInYourWallet': 'Diesen Nachweis ablehnen?0', + 'IsRequestng': 'Diesen Nachweis ablehnen?1', + 'IsRequestingSomethingYouDontHaveAvailable': 'fordert etwas an, das nicht in der Brieftasche verfügbar ist?2', + 'IsRequestingYouToShare': 'bittet um Freigabe?3', + 'WhichYouCanProvideFrom': 'die bereitgestellt werden können?4', + 'Details': 'Diesen Nachweis ablehnen?5', + 'SendingTheInformationSecurely': 'Diesen Nachweis ablehnen?6', + 'InformationSentSuccessfully': 'Diesen Nachweis ablehnen?7', + 'ProofRequestDeclined': 'Diesen Nachweis ablehnen?8', + 'ProofUpdateErrorTitle': 'Abgerufene Anmeldeinformationen können nicht aktualisiert werden', + 'ProofUpdateErrorMessage': 'Beim Aktualisieren der abgerufenen Anmeldeinformationen ist ein Problem aufgetreten', + 'ProofAcceptErrorTitle': 'Nachweisanforderung kann nicht angenommen werden', + 'ProofAcceptErrorMessage': 'Beim Akzeptieren der Nachweisanforderung ist ein Problem aufgetreten', + 'ProofRejectErrorTitle': 'Die Nachweisanforderung kann nicht abgelehnt werden', + 'ProofRejectErrorMessage': 'Beim Ablehnen der Nachweisanforderung ist ein Problem aufgetreten', + 'MissingInformation': { + 'Title': 'Die Anfrage kann nicht abgeschlossen werden', + 'AlertMissingInformation': { + 'Title': 'Der Brieftasche fehlen Informationen', + }, + }, + 'ProofRequestParamsError':'ProofRequest-Routenkinderwagen wurden nicht richtig eingestellt', + 'FetchProofError':'Nachweis von AFJ konnte nicht abgerufen werden', + }, + 'Toasts':{ + 'Success': 'Erfolg', + 'Error': 'Fehler', + 'Info': 'Die Info', + 'Warning': 'Warnung', + }, + 'Record': { + 'Hide': 'Ausblenden', + 'Show': 'Zeigen', + 'HideAll': 'Versteck alles', + 'Hidden': 'Versteckt', + }, + 'QRScanner':{ + 'PermissionToUseCamera':'Erlaubnis zur Verwendung der Kamera', + 'PermissionMessage':'Wir benötigen Ihre Erlaubnis, Ihre Kamera zu verwenden', + 'ScanMessage': 'Zum Verbinden scannen', + 'VerifyMessage':'Scannen Sie nur vertrauenswürdige Quellen und überprüfen Sie die Verbindungsdetails sorgfältig', + 'NotAValidURL':'URL non valide', + 'NotBlankURL': 'Bitte URL eingeben', + 'InvalidQrCode':'QrCode invalide', + }, +}; +export default translation; diff --git a/src/localization/en/index.ts b/src/localization/en/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..0798ad04e359d51dc53c99e6ef119b981aa06157 --- /dev/null +++ b/src/localization/en/index.ts @@ -0,0 +1,240 @@ +// prettier-ignore +const translation = { + 'Global': { + 'EnterPin': 'Enter PIN', + 'EnterNewPin': 'Enter New PIN', + '6DigitPin': '6 Digit PIN', + 'Submit': 'Submit', + 'NoneYet!': 'None yet!', + 'Cancel': 'Cancel', + 'Confirm': 'Confirm', + 'Accept': 'Accept', + 'Reject': 'Reject', + 'Share': 'Share', + 'Decline': 'Decline', + 'Back': 'Back', + 'Next': 'Next', + 'Continue': 'Continue', + 'Info': 'Information', + 'Failure': 'Failure', + 'Success': 'Success', + 'SomethingWentWrong': 'Something went wrong', + 'Done': 'Done', + 'Skip': 'Skip', + 'Previous': 'Prev', + 'View': 'View', + 'Home': 'Home', + 'ErrorCode': 'Error Code', + 'Okay': 'Okay', + 'Verify': 'Verify', + 'ChangePin': 'Change Pin', + 'OldPin': 'Enter Old Pin', + 'Copy': 'Copy', + 'from': 'from', + 'ThisDecisionCannotBeChanged.': 'This decision cannot be changed.', + 'ZeroRecords': 'No records available', + 'ImportWallet': 'Import Wallet', + 'UserInactivity': 'Logging out due to inactivity', + }, + 'Language': { + 'English': 'English', + 'French': 'French', + 'German': 'German', + }, + 'Registration':{ + 'RegisterAgain': 'Please register again', + 'MnemonicMsg': 'This phrase is the only way to export and import wallet, save it somewhere safe and secret. The phrase can be later found under the settings tab.', + 'Passphrase': 'Passphrase', + 'Mnemonic': 'Mnemonic', + 'SecondCounter': 'Seconds Left', + 'WalletInitialized':'Wallet initialized successfully.', + }, + 'Terms': { + 'AcceptTerms': 'Please read and agree to the terms and conditions below before using this application.', + 'TermsAndConditions': 'These Terms and Conditions set out the rights and obligations of all users regarding the use of the Service. Your access to and use of the Service is conditioned on Your acceptance of and compliance with these Terms and Conditions. These Terms and Conditions apply to all visitors, users and others who access or use the Service.', + 'Attestation': 'I, have read, understand and accept the terms and conditions.', + }, + 'PinCreate': { + 'UserAuthenticationPin': 'User authentication pin', + 'PinMustBe6DigitsInLength': 'PIN must be 6 digits in length', + 'ReEnterPinMustBe6DigitsInLength': 'Insufficient PIN length', + 'PinsEnteredDoNotMatch': 'Pin entered does not match', + 'PinsSuccess': 'PIN created successfully', + 'PinChange': 'PIN changed successfully', + 'NewPinMatchwithOld': 'New Pin is same as the Old Pin', + '6DigitPin': '6 Digit PIN', + 'ReenterPin': 'Re-Enter PIN', + 'ReenterNewPin': 'Re-Enter the New PIN', + 'Create': 'Create', + 'ValidOldPin': 'Please enter valid Old PIN', + 'WalletCreated': 'The wallet is created successfully.', + 'OR': 'OR', + 'PinInfo': 'This pin is used for login', + }, + 'Biometric': { + 'Biometric': 'Biometric', + 'BiometricConfirm': 'Confirm fingerprint', + 'BiometricSuccess': 'Fingerprint configured successfully', + 'BiometricFailed': 'Biometrics failed', + 'BiometricCancel': 'User cancelled the biometric prompt', + 'BiometricNotSupport': 'Biometrics not supported', + 'RegisterPinandBiometric': 'Register PIN and Biometric', + 'BiometricInfo': 'Register Biometric use for login', + }, + 'Initialization':{ + 'CompleteInitialization':'Complete the initialization', + 'InitializationInfo':'Initialize new wallet or import old wallet', + }, + 'Mnemonic':{ + 'MnemonicTitle':'Below is the mnemonic for future references', + }, + 'Home': { + 'Welcome': 'Welcome', + 'Notifications': 'Notifications', + 'NoNewUpdates': 'There is no new notification.', + 'NoCredentials': 'There are no credentials in the wallet.', + 'SeeAll': 'See all', + 'YouHave': 'You have', + 'Credential': 'credential', + 'Credentials': 'credentials', + 'InYourWallet': 'in your wallet', + 'CredentialCountUndefinedError':'Credential count cannot be undefined', + }, + 'PinEnter': { + 'IncorrectPin': 'Incorrect PIN', + }, + 'Settings': { + 'ChangePin': 'Change Pin', + 'Version': 'Version', + 'AppPreferences': 'App Preferences', + 'AboutApp': 'About App', + 'Language': 'Language', + 'Logout': 'Logout', + 'LogoutMsg': 'Please confirm to logout', + 'EnterMnemonic': 'Enter Mnemonic', + 'ValidMnemonic': 'Valid Mnemonic', + 'InvalidMnemonic': 'Invalid Mnemonic', + 'MnemonicMsg': 'Mnemonic can not be blank', + 'Yes': 'Yes', + 'No': 'No', + 'ExportWallet': 'Export Wallet', + 'ViewMnemonic': 'View Mnemonic', + }, + 'ExportWallet':{ + 'WalletExportedPath': 'Wallet Exported to the path:', + }, + 'ImportWallet':{ + 'SelectWalletFile': 'Select Wallet File', + 'EmptyMnemonic': 'Mnemonics cannot be empty', + 'InvalidMnemonic': 'Invalid Mnemonics ', + 'WalletRestoreFailed':'Wallet restore failed', + 'ImportError': 'Your mnemonic is incorrect please check it carefully', + }, + 'ConnectionInvitation':{ + 'VerifyMessage': 'Verify connection details carefully', + 'ConsentMessage': 'New Connection Request', + }, + 'ContactDetails': { + 'Created': 'Created', + 'ConnectionState': 'Connection State', + 'AContact': 'A contact', + 'DeleteConnection': 'Delete Connection', + 'DeleteConnectionAlert': 'Are you sure you want to delete this connection?', + 'DeleteConnectionSuccess': 'Connection deleted successfully', + 'DeleteConnectionFailed': 'Failed to delete connection', + 'ConnectionCannotDelete': 'Mediator connection cannot be deleted', + }, + 'Credentials': { + 'CredentialsNotFound': 'Credentials not found', + }, + 'CredentialDetails': { + 'Id': 'Id:', + 'CreatedAt': 'Created At:', + 'Version': 'Version', + 'Issued': 'Issued', + 'PrivacyPolicy': 'Privacy policy', + 'TermsAndConditions': 'Terms and conditions', + 'RemoveFromWallet': 'Remove from wallet', + }, + 'CredentialOffer': { + 'ThisIsTakingLongerThanExpected': 'This is taking longer than expected. Check back later for a new credential.', + 'RejectThisCredential?': 'Reject this Credential?', + 'AcceptingCredential': 'Accepting Credential', + 'SuccessfullyAcceptedCredential': 'Successfully accepted the Credential', + 'RejectingCredential':'Rejecting Credential', + 'SuccessfullyRejectedCredential':'Successfully rejected the Credential', + 'CredentialNotFound': 'Credential not found', + 'CredentialAccepted': 'Credential Accepted', + 'CredentialRejected': 'Credential Rejected', + 'CredentialAddedToYourWallet': 'Credential added to the wallet', + 'CredentialDeclined': 'Credential declined', + 'CredentialOnTheWay': 'The credential is on the way', + 'CredentialOffer': 'New Credential Offer', + 'IsOfferingYouACredential': 'is offering a credential', + }, + 'TabStack': { + 'Home': 'Home', + 'Connections': 'Connection', + 'Scan': 'Scan', + 'Credentials': 'Credential', + 'Settings': 'Settings', + }, + 'Toasts':{ + 'Success': 'Success', + 'Error': 'Error', + 'Info': 'Info', + 'Warning': 'Warning', + }, + 'ProofRequest': { + 'Title': '<b>{{connection}}</b> is requesting a verification from the Wallet. \n\nThey are asking to share:', + 'OfferDelay': 'Offer delay', + 'RejectThisProof?': 'Reject this Proof?', + 'AcceptingProof': 'Accepting Proof', + 'SuccessfullyAcceptedProof': 'Successfully Accepted Proof', + 'ProofNotFound': 'Proof not Found', + 'RejectingProof': 'Rejecting Proof', + 'ProofAccepted': 'Proof Accepted', + 'ProofRejected': 'Proof Rejected', + 'RequestedCredentialsCouldNotBeFound': 'Requested credentials could not be found', + 'ProofRequest': 'New Proof Request', + 'NotAvailableInYourWallet': 'Not available in the wallet', + 'IsRequestng': 'is requesting', + 'IsRequestingSomethingYouDontHaveAvailable': 'is requesting something not available in wallet', + 'IsRequestingYouToShare': 'is requesting to share', + 'WhichYouCanProvideFrom': 'which can be provided from', + 'Details': 'Details', + 'SendingTheInformationSecurely': 'Sending the information securely', + 'InformationSentSuccessfully': 'Information sent successfully', + 'ProofRequestDeclined': 'Proof request declined', + 'ProofUpdateErrorTitle': 'Unable to update retrieved credentials', + 'ProofUpdateErrorMessage': 'There was a problem while updating retrieved credentials', + 'ProofAcceptErrorTitle': 'Unable to accept proof request', + 'ProofAcceptErrorMessage': 'There was a problem while accepting the proof request', + 'ProofRejectErrorTitle': 'Unable to reject the proof request', + 'ProofRejectErrorMessage': 'There was a problem while rejecting the proof request', + 'MissingInformation': { + 'Title': 'The request cannot be completed', + 'AlertMissingInformation': { + 'Title': 'The wallet is missing information', + }, + }, + 'ProofRequestParamsError':'ProofRequest route prams were not set properly', + 'FetchProofError':'Unable to fetch proof from AFJ', + }, + 'Record': { + 'Hide': 'Hide', + 'Show': 'Show', + 'HideAll': 'Hide all', + 'Hidden': 'Hidden', + }, + 'QRScanner':{ + 'PermissionToUseCamera':'Permission To Use Camera', + 'PermissionMessage':'We need your permission to use your camera', + 'ScanMessage': 'Scan to connect', + 'VerifyMessage':'Only scan trustworthy sources and verify connection details carefully', + 'NotAValidURL':'URL non valid', + 'NotBlankURL': 'Please enter URL', + 'InvalidQrCode':'Invalid QrCode', + }, +}; +export default translation; diff --git a/src/localization/fr/index.ts b/src/localization/fr/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..13350a9f88d037c7d2ecf6f205701c1f4ab221c5 --- /dev/null +++ b/src/localization/fr/index.ts @@ -0,0 +1,239 @@ +// prettier-ignore +const translation = { + 'Global': { + 'EnterPin': 'Entrer le code PIN', + 'EnterNewPin': 'Entrez le nouveau NIP', + '6DigitPin': 'Pin à 6 chiffres', + 'Submit': 'Soumettre', + 'NoneYet!': 'Pas encore !', + 'Cancel': 'Annuler', + 'Confirm': 'Confirmer', + 'Accept': 'Accepter', + 'Reject': 'Rejeter', + 'Share': 'Partager', + 'Decline': 'Refuser', + 'Back': 'Retour', + 'Next': 'Suivant', + 'Continue': 'Continuer', + 'Info': 'Information', + 'Failure': 'Échec', + 'Success': 'Succès', + 'SomethingWentWrong': "Quelque chose s'est mal passé", + 'Done': 'Terminé', + 'Skip': 'Ignorer', + 'Previous': 'Précédente', + 'View': 'Voir', + 'Home': 'Accueil', + 'ErrorCode': "Code d'erreur", + 'Okay': 'Okay', + 'Verify': 'Vérifier', + 'ChangePin': 'Changer dépingle', + 'OldPin': 'Saisir lancien code PIN', + 'Copy': 'Copie', + 'from': 'à partir de', + 'ThisDecisionCannotBeChanged.': 'Cette décision ne peut être modifiée.', + 'ZeroRecords': 'Aucun enregistrement disponible', + 'ImportWallet': 'Importer un portefeuille', + 'WalletInitialized':'Portefeuille initialisé avec succès.', + 'UserInactivity': "Déconnexion en raison de l'inactivité", + }, + 'Language': { + 'English': 'Anglais', + 'French': 'Français', + 'German': 'Allemand', + }, + 'Registration':{ + 'RegisterAgain': 'Veuillez vous inscrire à nouveau', + 'MnemonicMsg': "Cette phrase est le seul moyen d'exporter et d'importer un portefeuille, enregistrez-le dans un endroit sûr et secret. La phrase peut être trouvée plus tard sous l'onglet Paramètres", + 'Passphrase': 'Mot de passe', + 'Mnemonic': 'Mnémonique', + 'SecondCounter': 'Deuxième à gauche', + 'WalletInitialized':'Portefeuille initialisé avec succès.', + }, + 'Terms': { + 'AcceptTerms': "Veuillez lire et accepter les termes et conditions ci-dessous avant d'utiliser cette application.", + 'TermsAndConditions': "Les présentes conditions générales définissent les droits et obligations de tous les utilisateurs concernant l'utilisation du service. Votre accès au service et son utilisation sont conditionnés par votre acceptation et votre respect des présentes conditions générales. Ces conditions générales s'appliquent à tous les visiteurs, utilisateurs et autres personnes qui accèdent ou utilisent le service.", + 'Attestation': "J'ai lu, compris et accepté les termes et conditions.", + }, + 'PinCreate': { + 'UserAuthenticationPin': "NIP d'authentification de l'utilisateur", + 'PinMustBe6DigitsInLength': 'La broche doit comporter 6 chiffres', + 'ReEnterPinMustBe6DigitsInLength': 'Longueur du code PIN insuffisante', + 'PinsEnteredDoNotMatch': 'Le code PIN saisi ne correspond pas', + 'PinsSuccess': 'Épingle créée avec succès', + 'PinChange': 'Changement de code PIN réussi', + 'NewPinMatchwithOld': "La nouvelle broche est identique à l'ancienne broche", + '6DigitPin': 'Broche à 6 chiffres', + 'ReenterPin': 'Entrez à nouveau le nouveau code PIN', + 'Create': 'Créer', + 'ValidOldPin': 'Veuillez saisir un ancien code PIN valide', + 'WalletCreated': 'Le portefeuille est créé avec succès', + 'OR': 'OU', + 'PinInfo': 'Cette broche est utilisée pour la connexion', + }, + 'Biometric': { + 'Biometric': 'Biométrique', + 'BiometricConfirm': "Confirmer l'empreinte digitale", + 'BiometricSuccess': 'Empreinte digitale configurée avec succès', + 'BiometricFailed': 'Échec de la biométrie', + 'BiometricCancel': "L'utilisateur a annulé l'invite biométrique", + 'BiometricNotSupport': 'Biométrie non prise en charge', + 'RegisterPinandBiometric': 'Enregistrer le code PIN et la biométrie', + 'BiometricInfo': "S'inscrire Utilisation biométrique pour la connexion", + }, + 'Initialization':{ + 'CompleteInitialization':"Terminer l'initialisation", + 'InitializationInfo':"Initialiser le nouveau portefeuille ou importer l'ancien portefeuille", + }, + 'Mnemonic':{ + 'MnemonicTitle':'Ci-dessous le mnémonique pour les futures références', + }, + 'Home': { + 'Welcome': 'Bienvenue', + 'Notifications': 'Notifications', + 'NoNewUpdates': "Il n'y a pas de nouvelle notification.", + 'NoCredentials': "Il n'y a pas d'informations d'identification dans le portefeuille.", + 'SeeAll': 'Voir tous', + 'YouHave': 'Vous avez', + 'Credential': "informations d'identification", + 'Credentials': "informations d'identification", + 'InYourWallet': 'dans votre portefeuille', + }, + 'PinEnter': { + 'IncorrectPin': 'Broche incorrecte', + }, + 'Settings': { + 'ChangePin': 'Changer la broche', + 'Version': 'Version', + 'AppPreferences': "Préférences de l'application", + 'AboutApp': "À propos de l'application", + 'Language': 'Langue', + 'Logout': 'Se déconnecter', + 'LogoutMsg': 'Veuillez confirmer pour vous déconnecter', + 'MnemonicMsg': 'Le mnémonique ne peut pas être vide', + 'EnterMnemonic': 'Entrez le mnémonique', + 'ValidMnemonic': 'Mnémonique valide', + 'InvalidMnemonic': 'Mnémonique invalide', + 'Yes': 'Oui', + 'No': 'Non', + 'ExportWallet': "Portefeuille d'exportation", + 'ViewMnemonic': 'Voir Mnémonique', + }, + 'ExportWallet':{ + 'WalletExportedPath': 'Portefeuille exporté vers le chemin :', + }, + 'ImportWallet':{ + 'SelectWalletFile': 'Sélectionnez le fichier de portefeuille', + 'EmptyMnemonic': 'Les mnémoniques ne peuvent pas être vides', + 'InvalidMnemonic': 'Mnémoniques invalides ', + 'WalletRestoreFailed':'Échec de la restauration du portefeuille', + 'ImportError': 'Votre e-mail ou mnémonique est incorrect, veuillez le vérifier attentivement', + }, + 'ConnectionInvitation': { + 'VerifyMessage': 'Vérifiez soigneusement les détails de connexion', + 'ConsentMessage': 'Nouvelle demande de connexion', + }, + 'ContactDetails': { + 'Created': 'Créé', + 'ConnectionState': 'État de la connexion', + 'AContact': 'Un contact', + 'DeleteConnection': 'Supprimer la connexion', + 'DeleteConnectionAlert': 'Êtes-vous sûr de vouloir supprimer cette connexion ?', + 'DeleteConnectionSuccess': 'La connexion a été supprimée avec succès', + 'DeleteConnectionFailed': 'Échec de la suppression de la connexion', + 'ConnectionCannotDelete': 'La connexion du médiateur ne peut pas être supprimée', + }, + 'Credentials': { + 'CredentialsNotFound': 'Identifiants introuvables', + }, + 'CredentialDetails': { + 'Id': 'Identifiant:', + 'CreatedAt': 'Créé à:', + 'Version': 'Version', + 'Issued': 'Publié', + 'PrivacyPolicy': 'Politique de confidentialité', + 'TermsAndConditions': 'Termes et conditions', + 'RemoveFromWallet': 'Retirer du portefeuille', + }, + 'CredentialOffer': { + 'ThisIsTakingLongerThanExpected': 'Cela prend plus de temps que prévu. Revenez plus tard pour un nouvel identifiant.', + 'RejectThisCredential?': 'Refuser cet identifiant ?', + 'AcceptingCredential': "Acceptation des informations d'identification", + 'SuccessfullyAcceptedCredential': 'Accepté avec succès le Credential', + 'RejectingCredential':"Rejeter les informations d'identification", + 'SuccessfullyRejectedCredential':"L'identifiant a été rejeté avec succès", + 'CredentialNotFound': 'Identifiant introuvable', + 'CredentialAccepted': 'Titre accepté', + 'CredentialRejected': 'Identifiant refusé', + 'CredentialAddedToYourWallet': 'Identifiant ajouté au portefeuille', + 'CredentialDeclined': 'Identifiant refusé', + 'CredentialOnTheWay': 'Votre accréditation est en route', + 'CredentialOffer': "Nouvelle offre d'accréditation", + 'IsOfferingYouACredential': 'offre un diplôme', + }, + 'TabStack': { + 'Home': 'Maison', + 'Connections': 'Connexion', + 'Scan': 'Analyse', + 'Credentials': 'Identifiants', + 'Settings': 'Réglages', + }, + 'Toasts':{ + 'Success': 'Succès', + 'Error': 'Erreur', + 'Info': 'Info', + 'Warning': 'Avertissement', + }, + 'ProofRequest': { + 'Title': '<b>{{connection}}</b> demande une vérification au Wallet. \n\nIls demandent à partager:', + 'OfferDelay': "Retard de l'offre", + 'RejectThisProof?': 'Rejeter cette preuve ?', + 'AcceptingProof': 'Acceptation de la preuve', + 'SuccessfullyAcceptedProof': 'Preuve acceptée avec succès', + 'ProofNotFound': 'Preuve introuvable', + 'RejectingProof': 'Rejet de la preuve', + 'ProofAccepted': 'Preuve acceptée', + 'ProofRejected': 'Preuve rejetée', + 'RequestedCredentialsCouldNotBeFound': "Les informations d'identification demandées sont introuvables", + 'ProofRequest': 'Nouvelle demande de preuve', + 'NotAvailableInYourWallet': 'Non disponible dans le portefeuille?0', + 'IsRequestng': 'Rejeter cette preuve ?1', + 'IsRequestingSomethingYouDontHaveAvailable': "Demande quelque chose qui n'est pas disponible dans le portefeuille?2", + 'IsRequestingYouToShare': 'Rejeter cette preuve ?3', + 'WhichYouCanProvideFrom': 'Qui peut être fourni par ?4', + 'Details': 'Rejeter cette preuve ?5', + 'SendingTheInformationSecurely': 'Rejeter cette preuve ?6', + 'InformationSentSuccessfully': 'Rejeter cette preuve ?7', + 'ProofRequestDeclined': 'Rejeter cette preuve ?8', + 'ProofUpdateErrorTitle': 'Impossible de mettre à jour les identifiants récupérés', + 'ProofUpdateErrorMessage': "Un problème est survenu lors de la mise à jour des informations d'identification récupérées", + 'ProofAcceptErrorTitle': "Impossible d'accepter la demande de justificatif", + 'ProofAcceptErrorMessage': "Un problème est survenu lors de l'acceptation de la demande de preuve", + 'ProofRejectErrorTitle': 'Impossible de rejeter la demande de justificatif', + 'ProofRejectErrorMessage': 'Un problème est survenu lors du rejet de la demande de preuve ', + 'MissingInformation': { + 'Title': 'La demande ne peut pas être complétée', + 'AlertMissingInformation': { + 'Title': "Le portefeuille manque d'informations", + }, + }, + 'ProofRequestParamsError':"Les poussettes d'itinéraire ProofRequest n'ont pas été correctement définies", + 'FetchProofError':"Impossible de récupérer la preuve auprès de l'AFJ", + }, + 'Record': { + 'Hide': 'Cacher', + 'Show': 'Montrer', + 'HideAll': 'Cacher tout', + 'Hidden': 'Caché', + }, + 'QRScanner':{ + 'PermissionToUseCamera':"Autorisation d'utiliser l'appareil photo", + 'PermissionMessage':'Nous avons besoin de votre autorisation pour utiliser votre appareil photo', + 'ScanMessage': 'Scannez pour vous connecter', + 'VerifyMessage':"N'analysez que des sources fiables et vérifiez soigneusement les détails de connexion", + 'NotAValidURL':'URL non valide', + 'NotBlankURL': 'Veuillez entrer lURL', + 'InvalidQrCode':'QrCode invalide', + }, +}; +export default translation; diff --git a/src/localization/index.ts b/src/localization/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..5258e729ed4df5775f8532da1a50c604f8ce12d7 --- /dev/null +++ b/src/localization/index.ts @@ -0,0 +1,64 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import { findBestAvailableLanguage } from 'react-native-localize'; +import { defaultLanguage, LocalStorageKeys } from '../constants'; +import en from './en'; +import fr from './fr'; +import de from './de'; + +export type Translation = typeof en; + +const resources = { + en: { + translation: en, + }, + fr: { + translation: fr, + }, + de: { + translation: de, + }, +}; + +export enum Locales { + en = 'en', + fr = 'fr', + de = 'de', +} + +const currentLanguage = i18n.language; + +// Store language into the AsyncStorage +const storeLanguage = async (language: string) => { + await AsyncStorage.setItem(LocalStorageKeys.Language, language); +}; + +// Fetch user preference language from the AsyncStorage and set if require +const initStoredLanguage = async () => { + const langId = await AsyncStorage.getItem(LocalStorageKeys.Language); + if (langId !== null) { + if (langId !== currentLanguage) { + await i18n.changeLanguage(langId); + } + } +}; + +const availableLanguages = Object.keys(resources); +const bestLanguageMatch = findBestAvailableLanguage(availableLanguages); +let translationToUse = defaultLanguage; + +if ( + bestLanguageMatch && + availableLanguages.includes(bestLanguageMatch.languageTag) +) { + translationToUse = bestLanguageMatch.languageTag; +} +i18n.use(initReactI18next).init({ + debug: true, + lng: translationToUse, + fallbackLng: defaultLanguage, + resources, +}); + +export { i18n, initStoredLanguage, storeLanguage, currentLanguage }; diff --git a/src/navigators/AuthenticateStack.tsx b/src/navigators/AuthenticateStack.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a3511867fba43f4d107bfd3febc55e08f45de238 --- /dev/null +++ b/src/navigators/AuthenticateStack.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { createStackNavigator } from '@react-navigation/stack'; +import { AuthenticateStackParams, Screens } from '../types/navigators'; +import PinEnter from '../screens/PinEnter'; + +import defaultStackOptions from './defaultStackOptions'; + +interface AuthenticateStackProps { + setAuthenticated: React.Dispatch<React.SetStateAction<boolean>>; +} + +const Stack = createStackNavigator<AuthenticateStackParams>(); + +const AuthenticateStack: React.FC<AuthenticateStackProps> = ({ + setAuthenticated, +}) => { + return ( + <Stack.Navigator + screenOptions={{ + ...defaultStackOptions, + presentation: 'transparentModal', + headerShown: false, + }} + > + <Stack.Screen + name={Screens.EnterPin} + component={PinEnter} + initialParams={{ setAuthenticated }} + /> + </Stack.Navigator> + ); +}; + +export default AuthenticateStack; diff --git a/src/navigators/ContactStack.tsx b/src/navigators/ContactStack.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c5ce0729e673ea9e36ff4ffd60239822c3292fa1 --- /dev/null +++ b/src/navigators/ContactStack.tsx @@ -0,0 +1,32 @@ +import { createStackNavigator } from '@react-navigation/stack'; +import React from 'react'; + +import ListContacts from '../screens/ListContacts'; +import { ContactStackParams, Screens } from '../types/navigators'; +import ContactDetails from '../screens/ContactDetails'; + +import defaultStackOptions from './defaultStackOptions'; +import { ColorPallet } from '../theme/theme'; + +const Stack = createStackNavigator<ContactStackParams>(); + +const ContactStack: React.FC = () => { + return ( + <Stack.Navigator screenOptions={{ ...defaultStackOptions }}> + <Stack.Screen + name={Screens.ListContacts} + component={ListContacts} + options={() => ({ + title: 'Connections', + headerTintColor: ColorPallet.baseColors.white, + headerShown: true, + headerLeft: () => false, + rightLeft: () => false, + })} + /> + <Stack.Screen name={Screens.ContactDetails} component={ContactDetails} /> + </Stack.Navigator> + ); +}; + +export default ContactStack; diff --git a/src/navigators/CredentialStack.tsx b/src/navigators/CredentialStack.tsx new file mode 100644 index 0000000000000000000000000000000000000000..30c04a5f77efd000b4bbebe44c5f3b03cc4d26eb --- /dev/null +++ b/src/navigators/CredentialStack.tsx @@ -0,0 +1,23 @@ +import { createStackNavigator } from '@react-navigation/stack'; +import React from 'react'; +import CredentialDetails from '../screens/CredentialDetails'; +import ListCredentials from '../screens/ListCredentials'; +import { CredentialStackParams, Screens } from '../types/navigators'; + +import defaultStackOptions from './defaultStackOptions'; + +const Stack = createStackNavigator<CredentialStackParams>(); + +const CredentialStack: React.FC = () => { + return ( + <Stack.Navigator screenOptions={{ ...defaultStackOptions }}> + <Stack.Screen name={Screens.Credentials} component={ListCredentials} /> + <Stack.Screen + name={Screens.CredentialDetails} + component={CredentialDetails} + /> + </Stack.Navigator> + ); +}; + +export default CredentialStack; diff --git a/src/navigators/HomeStack.tsx b/src/navigators/HomeStack.tsx new file mode 100644 index 0000000000000000000000000000000000000000..82e79aa9cc6df31274b35960ec78dd87adfb2fb0 --- /dev/null +++ b/src/navigators/HomeStack.tsx @@ -0,0 +1,33 @@ +import { createStackNavigator } from '@react-navigation/stack'; +import React from 'react'; +import Home from '../screens/Home'; +import { HomeStackParams, Screens } from '../types/navigators'; +import ListNotifications from '../screens/ListNotifications'; +import CredentialOffer from '../screens/CredentialOffer'; +import defaultStackOptions from './defaultStackOptions'; +import ProofRequest from '../screens/ProofRequest'; + +const Stack = createStackNavigator<HomeStackParams>(); + +const HomeStack: React.FC = () => { + return ( + <Stack.Navigator + screenOptions={{ + ...defaultStackOptions, + }} + > + <Stack.Screen name={Screens.Home} component={Home} /> + <Stack.Screen + name={Screens.Notifications} + component={ListNotifications} + /> + <Stack.Screen + name={Screens.CredentialOffer} + component={CredentialOffer} + /> + <Stack.Screen name={Screens.ProofRequest} component={ProofRequest} /> + </Stack.Navigator> + ); +}; + +export default HomeStack; diff --git a/src/navigators/MainStack.tsx b/src/navigators/MainStack.tsx new file mode 100644 index 0000000000000000000000000000000000000000..85e5efd3825a31f9721980d642d3e10ca50d7d28 --- /dev/null +++ b/src/navigators/MainStack.tsx @@ -0,0 +1,46 @@ +import { createStackNavigator } from '@react-navigation/stack'; +import React from 'react'; +import ConnectionInvitation from '../screens/ConnectionInvitation'; +import SealInformation from '../screens/SealInformation'; +import ScannedSealQrCodes from '../screens/ScannedSealQrCodes'; +import Home from '../screens/Home'; +import ListContacts from '../screens/ListContacts'; +import { MainStackParams, Screens, Stacks } from '../types/navigators'; +import ScanStack from './ScanStack'; +import defaultStackOptions from './defaultStackOptions'; +import TabStack from './TabStack'; + +const Stack = createStackNavigator<MainStackParams>(); + +const MainStack: React.FC = () => { + return ( + <Stack.Navigator + screenOptions={{ ...defaultStackOptions, headerShown: false }} + > + <Stack.Screen name={Stacks.TabStack} component={TabStack} /> + <Stack.Screen name={Screens.Home} component={Home} /> + <Stack.Screen name={Screens.Scan} options={{ presentation: 'modal' }}> + {() => <ScanStack />} + </Stack.Screen> + <Stack.Screen + name={Screens.ListContacts} + component={ListContacts} + options={{ headerShown: true }} + /> + <Stack.Screen + name={Screens.ConnectionInvitation} + component={ConnectionInvitation} + /> + <Stack.Screen + name={Screens.SealInformation} + component={SealInformation} + /> + <Stack.Screen + name={Screens.ScannedSealQrCodes} + component={ScannedSealQrCodes} + /> + </Stack.Navigator> + ); +}; + +export default MainStack; diff --git a/src/navigators/OnboardingStack.tsx b/src/navigators/OnboardingStack.tsx new file mode 100644 index 0000000000000000000000000000000000000000..247e871043042b66ae9e04cb5c4b2db1917598a0 --- /dev/null +++ b/src/navigators/OnboardingStack.tsx @@ -0,0 +1,163 @@ +import { createStackNavigator } from '@react-navigation/stack'; +import React from 'react'; +import { Agent } from '@aries-framework/core'; +import PinCreate from '../screens/PinCreate'; +import Biometric from '../screens/Biometric'; +import PinEnter from '../screens/PinEnter'; +import Splash from '../screens/Splash'; +import Terms from '../screens/Terms'; +import Onboarding from '../screens/Onboarding'; +import { ColorPallet } from '../theme/theme'; + +import { OnboardingStackParams, Screens } from '../types/navigators'; + +import defaultStackOptions from './defaultStackOptions'; +import ImportWallet from '../screens/ImportWallet'; +import CreateWallet from '../screens/CreateWallet/CreateWallet'; +import Initialization from '../screens/Initialization'; +import WalletInitialized from '../screens/WalletInitialized'; +import SetupDelay from '../screens/SetupDelay'; + +const Stack = createStackNavigator<OnboardingStackParams>(); + +type OnboardingStackProps = { + setAuthenticated: React.Dispatch<React.SetStateAction<boolean>>; + initAgent: (guid: string, walletPin: string, seed: string) => void; + setAgent: (agent: Agent) => void; + setActive: React.Dispatch<React.SetStateAction<boolean>>; +}; + +const OnboardingStack: React.FC<OnboardingStackProps> = ({ + setAuthenticated, + initAgent, + setAgent, + setActive, +}) => { + return ( + <Stack.Navigator + initialRouteName={Screens.Splash} + screenOptions={{ + ...defaultStackOptions, + headerShown: false, + }} + > + <Stack.Screen name={Screens.Splash} component={Splash} /> + <Stack.Screen + name={Screens.Onboarding} + options={() => ({ + title: 'App Introduction', + headerTintColor: ColorPallet.baseColors.white, + headerShown: true, + headerLeft: () => false, + rightLeft: () => false, + })} + component={Onboarding} + /> + <Stack.Screen + name={Screens.Terms} + options={() => ({ + title: 'Terms & Conditions', + headerTintColor: ColorPallet.baseColors.white, + headerShown: true, + headerLeft: () => false, + rightLeft: () => false, + })} + component={Terms} + /> + <Stack.Screen + name={Screens.CreatePin} + component={PinCreate} + initialParams={{ initAgent, setAuthenticated }} + options={() => ({ + title: 'PIN Setup', + headerTintColor: ColorPallet.baseColors.white, + headerShown: true, + headerLeft: () => false, + rightLeft: () => false, + })} + /> + <Stack.Screen + name={Screens.Biometric} + component={Biometric} + initialParams={{ initAgent, setAuthenticated }} + options={() => ({ + title: 'Biometric', + headerTintColor: ColorPallet.baseColors.white, + headerShown: true, + headerLeft: () => false, + rightLeft: () => false, + })} + /> + <Stack.Screen + name={Screens.Initialization} + component={Initialization} + options={() => ({ + title: 'Intialize wallet', + headerTintColor: ColorPallet.baseColors.white, + headerShown: true, + headerLeft: () => false, + rightLeft: () => false, + })} + /> + <Stack.Screen + name={Screens.CreateWallet} + component={CreateWallet} + initialParams={{ initAgent }} + options={() => ({ + title: 'Intialize wallet', + headerTintColor: ColorPallet.baseColors.white, + headerShown: true, + headerLeft: () => false, + rightLeft: () => false, + })} + /> + <Stack.Screen + name={Screens.WalletInitialized} + component={WalletInitialized} + initialParams={{ setAuthenticated }} + options={() => ({ + title: 'Registration ', + headerTintColor: ColorPallet.baseColors.white, + headerShown: true, + headerLeft: () => false, + rightLeft: () => false, + })} + /> + <Stack.Screen + name={Screens.ImportWallet} + component={ImportWallet} + initialParams={{ setAuthenticated, setAgent, setActive }} + options={() => ({ + title: 'Import Wallet', + headerTintColor: ColorPallet.baseColors.white, + headerShown: true, + })} + /> + <Stack.Screen + name={Screens.EnterPin} + component={PinEnter} + initialParams={{ initAgent, setAuthenticated }} + options={() => ({ + title: 'Login', + headerTintColor: ColorPallet.baseColors.white, + headerShown: true, + headerLeft: () => false, + rightLeft: () => false, + })} + /> + <Stack.Screen + name={Screens.SetupDelay} + component={SetupDelay} + options={() => ({ + title: 'Initializing Wallet', + headerTintColor: ColorPallet.baseColors.white, + headerShown: true, + headerLeft: () => false, + rightLeft: () => false, + })} + /> + </Stack.Navigator> + ); +}; + +export default OnboardingStack; diff --git a/src/navigators/RootStack.tsx b/src/navigators/RootStack.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b18f7c9bd179009ab6f3882d3d1b478eee95b552 --- /dev/null +++ b/src/navigators/RootStack.tsx @@ -0,0 +1,144 @@ +import React, { useState, useMemo, useEffect, useCallback } from 'react'; +import { + Agent, + AutoAcceptCredential, + ConsoleLogger, + HttpOutboundTransport, + LogLevel, + MediatorPickupStrategy, + WsOutboundTransport, + AutoAcceptProof, +} from '@aries-framework/core'; +import { Linking } from 'react-native'; +import Config from 'react-native-config'; +import uuid from 'react-native-uuid'; +import { agentDependencies } from '@aries-framework/react-native'; +import UserInactivity from 'react-native-user-inactivity'; +import Toast from 'react-native-toast-message'; +import { useTranslation } from 'react-i18next'; +import { useAgent } from '@aries-framework/react-hooks'; +import indyLedgers from '../../configs/ledgers/indy'; +import MainStack from './MainStack'; +import OnboardingStack from './OnboardingStack'; +import { MainStackContext } from '../utils/helpers'; +import { ToastType } from '../components/toast/BaseToast'; +import { getValueFromKeychain, saveValueInKeychain } from "../utils/generic"; +import { KeychainStorageKeys } from "../constants"; + +interface Props { + setAgent: (agent: Agent) => void; +} + +const RootStack: React.FC<Props> = ({ setAgent }) => { + const { t } = useTranslation(); + const [uuidInitialized, setUuidInitialized] = useState(false); + const [authenticated, setAuthenticated] = useState(false); + const [deepLinkUrl, setDeepLinkUrl] = useState<string | null>(); + const [active, setActive] = useState(true); + const { agent } = useAgent(); + + useEffect(() => { + (async () => { + const guid = await getValueFromKeychain(KeychainStorageKeys.GUID) + if (!guid) { + const guid = uuid.v4() as string; + + await saveValueInKeychain( + KeychainStorageKeys.GUID, + guid, + 'GUID', + ); + } + setUuidInitialized(true); + })(); + }, []) + const initAgent = async (guid: string, walletPin: string, seed: string) => { + const newAgent = new Agent( + { + label: guid, // added guid as label + mediatorConnectionsInvite: Config.MEDIATOR_URL, + mediatorPickupStrategy: MediatorPickupStrategy.Implicit, + walletConfig: { id: guid, key: walletPin }, + autoAcceptConnections: true, + publicDidSeed: seed, + autoAcceptCredentials: AutoAcceptCredential.ContentApproved, + autoAcceptProofs: AutoAcceptProof.ContentApproved, + logger: new ConsoleLogger(LogLevel.trace), + autoUpdateStorageOnStartup: true, + connectToIndyLedgersOnStartup: true, + indyLedgers, + }, + agentDependencies, + ); + + const wsTransport = new WsOutboundTransport(); + const httpTransport = new HttpOutboundTransport(); + + newAgent.registerOutboundTransport(wsTransport); + newAgent.registerOutboundTransport(httpTransport); + + await newAgent.initialize(); + setAgent(newAgent); + setActive(true); + }; + + const shutDownAgent = useCallback(async () => { + if (!active) { + setAuthenticated(false); + await agent?.shutdown(); + Toast.show({ + type: ToastType.Info, + text1: t<string>('Toasts.Info'), + text2: t<string>('Global.UserInactivity'), + }); + } + }, [active, agent, t]); + + useEffect(() => { + shutDownAgent(); + }, [shutDownAgent]); + + useEffect(() => { + (async () => { + const handleDeepLinking = async (url: string) => { + setDeepLinkUrl(url); + }; + + Linking.addEventListener('url', ({ url }) => handleDeepLinking(url)); + const initialUrl = await Linking.getInitialURL(); + if (initialUrl) { + handleDeepLinking(initialUrl); + } + })(); + }, []); + + const mainStackProviderValue = useMemo( + () => ({ + setAuthenticated, + deepLinkUrl, + resetDeepLinkUrl: () => setDeepLinkUrl(null), + }), + [setAuthenticated, deepLinkUrl, setDeepLinkUrl], + ); + + return authenticated && uuidInitialized ? ( + <UserInactivity + isActive={active} + timeForInactivity={300000} + onAction={isActive => setActive(isActive)} + > + <MainStackContext.Provider value={mainStackProviderValue}> + <MainStack /> + </MainStackContext.Provider> + </UserInactivity> + ) : ( + <OnboardingStack + initAgent={initAgent} + setAuthenticated={setAuthenticated} + setAgent={setAgent} + setActive={setActive} + /> + ); +}; + +export default RootStack; diff --git a/src/navigators/ScanStack.tsx b/src/navigators/ScanStack.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b78c478d640e3b7407424ea756ebfc92a21e0b8c --- /dev/null +++ b/src/navigators/ScanStack.tsx @@ -0,0 +1,23 @@ +import { createStackNavigator } from '@react-navigation/stack'; +import React from 'react'; +import Scan from '../screens/Scan'; +import { ScanStackParams, Screens } from '../types/navigators'; + +import defaultStackOptions from './defaultStackOptions'; + +const Stack = createStackNavigator<ScanStackParams>(); + +const ScanStack: React.FC = () => { + return ( + <Stack.Navigator + screenOptions={{ + ...defaultStackOptions, + headerShown: false, + }} + > + <Stack.Screen name={Screens.Scan} component={Scan} /> + </Stack.Navigator> + ); +}; + +export default ScanStack; diff --git a/src/navigators/SettingStack.tsx b/src/navigators/SettingStack.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6e4d8fcceb7adbb9b2875c3c640fc244a2ab014c --- /dev/null +++ b/src/navigators/SettingStack.tsx @@ -0,0 +1,48 @@ +import { createStackNavigator } from '@react-navigation/stack'; +import React from 'react'; +import ChangePin from '../screens/ChangePin'; +import Settings from '../screens/Settings'; +import ExportWallet from '../screens/ExportWallet'; +import { Screens, SettingStackParams } from '../types/navigators'; + +import defaultStackOptions from './defaultStackOptions'; +import Language from '../screens/Language'; +import { MainStackContext } from '../utils/helpers'; +import ViewMnemonic from '../screens/ViewMnemonic'; + +const Stack = createStackNavigator<SettingStackParams>(); + +interface SettingStackProp {} + +const SettingStack: React.FC<SettingStackProp> = () => { + const { setAuthenticated } = React.useContext(MainStackContext); + return ( + <Stack.Navigator screenOptions={{ ...defaultStackOptions }}> + <Stack.Screen name={Screens.Settings}> + {props => <Settings {...props} setAuthenticated={setAuthenticated} />} + </Stack.Screen> + <Stack.Screen name={Screens.Language} component={Language} /> + <Stack.Screen + name={Screens.ExportWallet} + component={ExportWallet} + options={() => ({ + title: 'Export Wallet', + })} + /> + <Stack.Screen + name={Screens.ViewMnemonic} + component={ViewMnemonic} + options={() => ({ + title: 'View Mnemonic', + })} + /> + <Stack.Screen + name={Screens.ChangePin} + component={ChangePin} + options={{ headerShown: true }} + /> + </Stack.Navigator> + ); +}; + +export default SettingStack; diff --git a/src/navigators/TabStack.tsx b/src/navigators/TabStack.tsx new file mode 100644 index 0000000000000000000000000000000000000000..cb9df88aa9a3111ee24467bb470ccb4a7c942b37 --- /dev/null +++ b/src/navigators/TabStack.tsx @@ -0,0 +1,247 @@ +import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; +import React, { useEffect } from 'react'; +import { useNavigation } from '@react-navigation/core'; +import { useTranslation } from 'react-i18next'; +import { StyleSheet, Text, View, Image, ImageProps } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; +import { Buffer } from 'buffer'; +import { useAgent } from '@aries-framework/react-hooks'; +import useNotifications from '../hooks/notifications'; +import { ColorPallet, TextTheme } from '../theme/theme'; +import { Screens, TabStackParams, TabStacks } from '../types/navigators'; +import SettingStack from './SettingStack'; +import ContactStack from './ContactStack'; +import CredentialStack from './CredentialStack'; +import HomeStack from './HomeStack'; +import Images from '../assets'; +import { MainStackContext } from '../utils/helpers'; + +const MainTabNavigator = createBottomTabNavigator<TabStackParams>(); + +type TabBarIconProps = { + focused: boolean; + imageName: ImageProps['source']; +}; + +type TabBarLabelProps = { + label: string; +}; + +const TabBarIcon = ({ imageName, focused }: TabBarIconProps) => { + return ( + <View + style={[ + styles.tabView, + focused + ? { + borderWidth: 2, + borderColor: ColorPallet.grayscale.white, + } + : {}, + ]} + > + <Image + source={imageName} + style={!focused ? styles.tabBarIcon : styles.tabBarIcon} + resizeMode="contain" + /> + </View> + ); +}; + +const TabBarLabel = ({ label }: TabBarLabelProps) => { + return ( + <Text + style={{ + ...TextTheme.label, + fontWeight: 'normal', + paddingBottom: 5, + color: ColorPallet.grayscale.white, + }} + numberOfLines={1} + > + {label} + </Text> + ); +}; + +const ScannerIcon = () => { + return ( + <View style={styles.scannerIconWrapper}> + <Image + source={Images.scanIcon} + style={styles.scanIcon} + resizeMode="contain" + /> + </View> + ); +}; + +const TabStack: React.FC = () => { + const navigation = useNavigation(); + const { total } = useNotifications(); + const { t } = useTranslation(); + const { agent } = useAgent(); + + const { deepLinkUrl, resetDeepLinkUrl } = React.useContext(MainStackContext); + useEffect(() => { + if (!deepLinkUrl) { + return; + } + (async () => { + resetDeepLinkUrl(); + + let message; + const [, urlData] = deepLinkUrl.includes('?c_i') + ? deepLinkUrl.split('?c_i=') + : deepLinkUrl.split('?d_m='); + message = JSON.parse(Buffer.from(urlData.trim(), 'base64').toString()); + + if (message['~service']) { + await agent?.receiveMessage(message); + navigation.navigate(TabStacks.HomeStack); + } else { + navigation.navigate(Screens.ConnectionInvitation, { url: deepLinkUrl }); + } + })(); + }, [deepLinkUrl, resetDeepLinkUrl, navigation, agent]); + + return ( + <SafeAreaView + style={{ flex: 1, backgroundColor: ColorPallet.brand.primary }} + > + <MainTabNavigator.Navigator + screenOptions={{ + tabBarStyle: styles.tabBarStyle, + tabBarActiveTintColor: ColorPallet.baseColors.white, + tabBarInactiveTintColor: ColorPallet.brand.primary, + header: () => null, + tabBarHideOnKeyboard: true, + unmountOnBlur: true, + tabBarShowLabel: true, + tabBarLabelPosition: 'below-icon', + }} + > + <MainTabNavigator.Screen + name={TabStacks.HomeStack} + component={HomeStack} + options={{ + tabBarIcon: ({ focused }) => ( + <TabBarIcon focused={focused} imageName={Images.homeIcon} /> + ), + tabBarLabel: () => ( + <TabBarLabel label={t<string>('TabStack.Home')} /> + ), + tabBarBadge: total > 0 ? total : undefined, + tabBarBadgeStyle: { + backgroundColor: ColorPallet.semantic.error, + }, + tabBarIconStyle: { + backgroundColor: ColorPallet.baseColors.white, + }, + unmountOnBlur: true, + }} + /> + <MainTabNavigator.Screen + name={TabStacks.ConnectionStack} + component={ContactStack} + options={{ + headerTitle: 'Connection', + tabBarIcon: ({ focused }) => ( + <TabBarIcon + focused={focused} + imageName={Images.connectionsIcon} + /> + ), + tabBarLabel: () => ( + <TabBarLabel label={t<string>('TabStack.Connections')} /> + ), + unmountOnBlur: true, + }} + /> + <MainTabNavigator.Screen + name={TabStacks.ScanStack} + options={{ + tabBarIcon: () => <ScannerIcon />, + tabBarLabel: () => ( + <TabBarLabel label={t<string>('TabStack.Scan')} /> + ), + tabBarAccessibilityLabel: t<string>('TabStack.Scan'), + }} + listeners={({ navigation }) => ({ + tabPress: e => { + e.preventDefault(); + navigation.navigate(Screens.Scan); + }, + })} + > + {/* Just a placeholder, the the tab will navigate to a different stack */} + {() => <View />} + </MainTabNavigator.Screen> + <MainTabNavigator.Screen + name={TabStacks.CredentialStack} + component={CredentialStack} + options={{ + tabBarIcon: ({ focused }) => ( + <TabBarIcon + focused={focused} + imageName={Images.credentialsIcon} + /> + ), + tabBarLabel: () => ( + <TabBarLabel label={t<string>('TabStack.Credentials')} /> + ), + unmountOnBlur: true, + }} + /> + <MainTabNavigator.Screen + name={TabStacks.SettingsStack} + component={SettingStack} + options={{ + tabBarIcon: ({ focused }) => ( + <TabBarIcon focused={focused} imageName={Images.settingsIcon} /> + ), + tabBarLabel: () => ( + <TabBarLabel label={t<string>('TabStack.Settings')} /> + ), + unmountOnBlur: true, + }} + /> + </MainTabNavigator.Navigator> + </SafeAreaView> + ); +}; + +export default TabStack; + +const styles = StyleSheet.create({ + tabView: { + height: 45, + width: 45, + alignItems: 'center', + justifyContent: 'center', + }, + tabBarStyle: { + height: 80, + backgroundColor: ColorPallet.brand.primary, + borderTopWidth: 0, + paddingBottom: 0, + }, + scannerIconWrapper: { + height: 60, + width: 60, + backgroundColor: ColorPallet.baseColors.white, + top: -10, + borderRadius: 10, + justifyContent: 'center', + alignItems: 'center', + }, + tabBarIcon: { + height: 40, + width: 40, + }, + scanIcon: { + height: 40, + width: 40, + }, +}); diff --git a/src/navigators/defaultStackOptions.ts b/src/navigators/defaultStackOptions.ts new file mode 100644 index 0000000000000000000000000000000000000000..8fb43e3080fe2ba2cf1ff06d0a14e4436d578815 --- /dev/null +++ b/src/navigators/defaultStackOptions.ts @@ -0,0 +1,16 @@ +import { StackNavigationOptions } from '@react-navigation/stack'; +import { ColorPallet } from '../theme/theme'; + +const defaultStackOptions: StackNavigationOptions = { + headerStyle: { + backgroundColor: ColorPallet.brand.primary, + elevation: 0, + shadowOpacity: 0, + borderBottomWidth: 0, + }, + headerTintColor: ColorPallet.grayscale.white, + headerBackTitleVisible: false, + headerTitleAlign: 'center', +}; + +export default defaultStackOptions; diff --git a/src/screens/Biometric/Biometric.tsx b/src/screens/Biometric/Biometric.tsx new file mode 100644 index 0000000000000000000000000000000000000000..8c2301e0930ca04f4184a6212ea57fe0aca6bcec --- /dev/null +++ b/src/screens/Biometric/Biometric.tsx @@ -0,0 +1,80 @@ +import React, { useState } from 'react'; +import { StyleSheet, View, Image } from 'react-native'; +import { useTranslation } from 'react-i18next'; +import { StackScreenProps } from '@react-navigation/stack'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { InfoCard, ScreenNavigatorButtons } from '../../components'; +import { OnboardingStackParams, Screens } from '../../types/navigators'; +import { + checkIfSensorAvailable, + createBiometricKeys, + showBiometricPrompt, +} from './Biometric.utils'; +import Images from '../../assets'; + +type BiometricProps = StackScreenProps< + OnboardingStackParams, + Screens.Biometric +>; + +const Biometric: React.FC<BiometricProps> = ({ navigation }) => { + const [error, setError] = useState<string | undefined>(''); + const { t } = useTranslation(); + + const biometricEnable = async () => { + const { available } = await checkIfSensorAvailable(); + if (available) { + const { success, error } = await showBiometricPrompt(); + if (success) { + await createBiometricKeys(); + setError(t<string>('Biometric.BiometricSuccess')); + navigation.navigate(Screens.Initialization); + } else { + setError(error); + } + } else { + setError(t<string>('Biometric.BiometricNotSupport')); + } + }; + + const onBack = async () => { + navigation.navigate(Screens.CreatePin); + }; + + return ( + <View style={[style.container]}> + <Image source={Images.biometricIcon} style={style.biometricIconImg} /> + <InfoCard showBottomIcon={false} showTopIcon errorMsg={error}> + {t<string>('Biometric.BiometricInfo')} + </InfoCard> + <ScreenNavigatorButtons + onLeftPress={onBack} + onRightPress={biometricEnable} + /> + </View> + ); +}; + +export default Biometric; + +const style = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + flex: 1, + justifyContent: 'space-between', + }, + btnContainer: { + marginTop: 20, + }, + label: { + ...TextTheme.label, + fontWeight: 'bold', + textAlign: 'center', + }, + biometricIconImg: { + height: 150, + width: '40%', + alignSelf: 'center', + }, +}); diff --git a/src/screens/Biometric/Biometric.utils.test.ts b/src/screens/Biometric/Biometric.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..9dbb0457da9b644d71c5cd42528b3be13349ef98 --- /dev/null +++ b/src/screens/Biometric/Biometric.utils.test.ts @@ -0,0 +1,13 @@ +import * as Utils from './Biometric.utils'; + +describe('PinCreate.utils', () => { + describe('storeOnboardingCompleteStage', () => { + it('should store a value for onboarding complete stage', async () => { + jest.spyOn(Utils, 'storeOnboardingCompleteStage'); + + await Utils.storeOnboardingCompleteStage(); + + expect(Utils.storeOnboardingCompleteStage).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/Biometric/Biometric.utils.ts b/src/screens/Biometric/Biometric.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..521cde96a0b6f45b335e7cb0c1442b9e00a8ddb6 --- /dev/null +++ b/src/screens/Biometric/Biometric.utils.ts @@ -0,0 +1,27 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import ReactNativeBiometrics from 'react-native-biometrics'; +import i18next from 'i18next'; +import { LocalStorageKeys } from '../../constants'; + +const rnBiometrics = new ReactNativeBiometrics(); + +export const storeOnboardingCompleteStage = async () => { + await AsyncStorage.setItem(LocalStorageKeys.OnboardingCompleteStage, 'true'); +}; + +export const checkIfSensorAvailable = async () => { + const result = await rnBiometrics.isSensorAvailable(); + return result; +}; + +export const showBiometricPrompt = async () => { + const result = await rnBiometrics.simplePrompt({ + promptMessage: i18next.t<string>('Biometric.BiometricConfirm'), + }); + return result; +}; + +export const createBiometricKeys = async () => { + const result = await rnBiometrics.createKeys(); + return result; +}; diff --git a/src/screens/Biometric/index.ts b/src/screens/Biometric/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..16371488908134ab450c19bff08c885b2233b5e9 --- /dev/null +++ b/src/screens/Biometric/index.ts @@ -0,0 +1,3 @@ +import Biometric from './Biometric'; + +export default Biometric; diff --git a/src/screens/ChangePin/ChangePin.tsx b/src/screens/ChangePin/ChangePin.tsx new file mode 100644 index 0000000000000000000000000000000000000000..16884eff993bdc1021daeb14ef0aa02d1590d2ea --- /dev/null +++ b/src/screens/ChangePin/ChangePin.tsx @@ -0,0 +1,158 @@ +import React, { useState } from 'react'; +import { Alert, Keyboard, StyleSheet, View } from 'react-native'; +import { useTranslation } from 'react-i18next'; +import { StackScreenProps } from '@react-navigation/stack'; +import { useAgent } from '@aries-framework/react-hooks'; +import { UserCredentials } from 'react-native-keychain'; +import { ColorPallet } from '../../theme/theme'; +import { TextInput, Loader } from '../../components'; +import Button, { ButtonType } from '../../components/button/Button'; +import { Screens, SettingStackParams } from '../../types/navigators'; +import { warningToast, successToast } from '../../utils/toast'; +import { KeychainStorageKeys } from '../../constants'; +import { getValueFromKeychain, saveValueInKeychain } from '../../utils/generic'; + +type ChangePinProps = StackScreenProps<SettingStackParams, Screens.ChangePin>; + +const ChangePin: React.FC<ChangePinProps> = () => { + const [loading, setLoading] = useState(false); + const [pin, setPin] = useState(''); + const [pinTwo, setPinTwo] = useState(''); + const [pinThree, setPinThree] = useState(''); + const { t } = useTranslation(); + const { agent } = useAgent(); + + const passcodeCreate = async (passcode: string) => { + try { + setLoading(true); + const [guid, oldPasscode] = await Promise.all([ + new Promise(resolve => { + resolve(getValueFromKeychain(KeychainStorageKeys.GUID)); + }), + new Promise(resolve => { + resolve(getValueFromKeychain(KeychainStorageKeys.Passcode)); + }), + new Promise(resolve => { + resolve( + saveValueInKeychain( + KeychainStorageKeys.Passcode, + passcode, + 'passcode', + ), + ); + }), + ]); + setLoading(true); + await agent?.shutdown(); + await agent?.wallet.rotateKey({ + id: (guid as UserCredentials).password, + key: (oldPasscode as UserCredentials).password, + rekey: passcode, + }); + await agent?.initialize(); + await saveValueInKeychain( + KeychainStorageKeys.Passcode, + passcode, + 'passcode', + ); + setLoading(false); + successToast(t<string>('PinCreate.PinChange')); + } catch (e: any) { + Alert.alert(e); + setLoading(false); + } + }; + + const confirmEntry = async ( + oldPin: string, + newPin: string, + reEnterNewPin: string, + ) => { + const passcode = (await getValueFromKeychain( + KeychainStorageKeys.Passcode, + )) as UserCredentials; + + if (oldPin.length < 6 || newPin.length < 6) { + warningToast(t<string>('PinCreate.PinMustBe6DigitsInLength')); + } else if (newPin !== reEnterNewPin) { + warningToast(t<string>('PinCreate.PinsEnteredDoNotMatch')); + } else if (passcode.password !== oldPin) { + warningToast(t<string>('PinCreate.ValidOldPin')); + } else if (newPin === oldPin) { + warningToast(t<string>('PinCreate.NewPinMatchwithOld')); + } else { + passcodeCreate(newPin); + } + }; + + return ( + <View style={style.container}> + <Loader loading={loading} /> + + <TextInput + label={t<string>('Global.OldPin')} + placeholder={t<string>('Global.6DigitPin')} + placeholderTextColor={ColorPallet.baseColors.lightGrey} + accessible + accessibilityLabel={t<string>('Global.OldPin')} + maxLength={6} + autoFocus + secureTextEntry + keyboardType="number-pad" + value={pin} + onChangeText={setPin} + returnKeyType="done" + /> + <TextInput + label={t<string>('Global.EnterNewPin')} + accessible + accessibilityLabel={t<string>('Global.EnterNewPin')} + placeholder={t<string>('Global.6DigitPin')} + placeholderTextColor={ColorPallet.baseColors.lightGrey} + maxLength={6} + secureTextEntry + keyboardType="number-pad" + returnKeyType="done" + value={pinTwo} + onChangeText={(text: string) => { + setPinTwo(text); + }} + /> + <TextInput + label={t<string>('PinCreate.ReenterNewPin')} + accessible + accessibilityLabel={t<string>('PinCreate.ReenterNewPin')} + placeholder={t<string>('Global.6DigitPin')} + placeholderTextColor={ColorPallet.baseColors.lightGrey} + maxLength={6} + secureTextEntry + keyboardType="number-pad" + returnKeyType="done" + value={pinThree} + onChangeText={(text: string) => { + setPinThree(text); + if (text.length === 6) { + Keyboard.dismiss(); + } + }} + /> + <Button + title="Change PIN" + buttonType={ButtonType.Primary} + onPress={() => { + Keyboard.dismiss(); + confirmEntry(pin, pinTwo, pinThree); + }} + /> + </View> + ); +}; + +export default ChangePin; + +const style = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + }, +}); diff --git a/src/screens/ChangePin/index.ts b/src/screens/ChangePin/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..82eec7e1e878137a8329aaeef0b25861ebe1258c --- /dev/null +++ b/src/screens/ChangePin/index.ts @@ -0,0 +1,3 @@ +import ChangePin from './ChangePin'; + +export default ChangePin; diff --git a/src/screens/ConnectionInvitation/ConnectionInvitation.tsx b/src/screens/ConnectionInvitation/ConnectionInvitation.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1588d479dae545579c4aa1150a19bca5e10c08d1 --- /dev/null +++ b/src/screens/ConnectionInvitation/ConnectionInvitation.tsx @@ -0,0 +1,90 @@ +import { t } from 'i18next'; +import { View, StyleSheet, Text } from 'react-native'; +import React, { useState } from 'react'; +import { useAgent } from '@aries-framework/react-hooks'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { TabStacks } from '../../types/navigators'; +import { Loader } from '../../components'; +import Button, { ButtonType } from '../../components/button/Button'; +import ConnectionPending from '../../assets/img/connection-pending.svg'; +import { getInvitationFromUrl } from './ConnectionInvitation.utils'; + +interface ConnectionProps { + navigation: any; + route: any; +} + +const ConnectionInvitation: React.FC<ConnectionProps> = ({ + navigation, + route, +}) => { + const { agent } = useAgent(); + const [loading, setLoading] = useState(false); + + const handleAcceptPress = async (): Promise<void> => { + const { url } = route.params; + setLoading(true); + const connectionRecord = await getInvitationFromUrl(agent, url); + if (!connectionRecord?.id) { + throw new Error(t<string>('Scan.ConnectionNotFound')); + } + setLoading(false); + navigation.navigate(TabStacks.ConnectionStack); + }; + + const handleDeclinePress = () => { + navigation.navigate(TabStacks.HomeStack); + }; + + return ( + <View style={[styles.container]}> + <Loader loading={loading} /> + <Text style={[styles.bodyText, { fontWeight: 'bold' }]}> + {t<string>('ConnectionInvitation.ConsentMessage')} + </Text> + <View style={styles.spacer} /> + <Text style={[styles.bodyText, { fontWeight: 'bold' }]}> + {t<string>('ConnectionInvitation.VerifyMessage')} + </Text> + <ConnectionPending style={{ marginVertical: 20, alignSelf: 'center' }} /> + <View style={styles.spacer} /> + <View style={styles.topSpacer}> + <Button + title={t<string>('Global.Accept')} + onPress={handleAcceptPress} + buttonType={ButtonType.Primary} + /> + </View> + <View style={styles.topSpacer}> + <Button + title={t<string>('Global.Decline')} + buttonType={ButtonType.Ghost} + onPress={handleDeclinePress} + /> + </View> + </View> + ); +}; + +export default ConnectionInvitation; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + justifyContent: 'center', + }, + bodyText: { + ...TextTheme.normal, + flexShrink: 1, + alignSelf: 'center', + }, + spacer: { + height: 40, + width: 50, + }, + topSpacer: { + paddingTop: 10, + }, +}); diff --git a/src/screens/ConnectionInvitation/ConnectionInvitation.utils.test.ts b/src/screens/ConnectionInvitation/ConnectionInvitation.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b8a6e98f45c5a7243b6aec052aaa9bb202e4b159 --- /dev/null +++ b/src/screens/ConnectionInvitation/ConnectionInvitation.utils.test.ts @@ -0,0 +1,24 @@ +import * as Utils from './ConnectionInvitation.utils'; + +describe('ConnectionInvitation.utils', () => { + describe('getInvitationFromUrl', () => { + it('we have to get invitation url', async () => { + const getInvitationUrl = { + data: { + uri: 'uri', + autoAcceptConnection: true, + }, + }; + + // Mocked getInvitationFromUrl + jest + .spyOn(Utils, 'getInvitationFromUrl') + .mockResolvedValueOnce(getInvitationUrl); + + const response = await Utils.getInvitationFromUrl('email', 'otpId'); + + expect(Utils.getInvitationFromUrl).toHaveBeenCalledWith('email', 'otpId'); + expect(response).toStrictEqual(getInvitationUrl); + }); + }); +}); diff --git a/src/screens/ConnectionInvitation/ConnectionInvitation.utils.ts b/src/screens/ConnectionInvitation/ConnectionInvitation.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..8023a59602fb4966fdcd792ed0399609bd786cd9 --- /dev/null +++ b/src/screens/ConnectionInvitation/ConnectionInvitation.utils.ts @@ -0,0 +1,12 @@ +import { Agent, ConnectionRecord } from '@aries-framework/core'; + +export const getInvitationFromUrl = async ( + agent: Agent, + url: string, +): Promise<ConnectionRecord> => { + const { connectionRecord } = await agent.oob.receiveInvitationFromUrl(url, { + autoAcceptInvitation: true, + }); + return connectionRecord as ConnectionRecord; +}; +export default getInvitationFromUrl; diff --git a/src/screens/ConnectionInvitation/index.ts b/src/screens/ConnectionInvitation/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..ecc9ee97a29bc0133ba3e8c800e33ef865d14646 --- /dev/null +++ b/src/screens/ConnectionInvitation/index.ts @@ -0,0 +1,3 @@ +import ConnectionInvitation from './ConnectionInvitation'; + +export default ConnectionInvitation; diff --git a/src/screens/ContactDetails/ContactDetails.tsx b/src/screens/ContactDetails/ContactDetails.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a25dbf0e7e6418eb3b3fe2f5fd28050d6d360632 --- /dev/null +++ b/src/screens/ContactDetails/ContactDetails.tsx @@ -0,0 +1,221 @@ +import { + useAgent, + useConnectionById, + useCredentialByState, + useProofByState, +} from '@aries-framework/react-hooks'; +import { StackScreenProps } from '@react-navigation/stack'; +import React, { useCallback, useEffect, useState } from 'react'; + +import { + TouchableOpacity, + StyleSheet, + Text, + Alert, + View, + FlatList, +} from 'react-native'; +import { useTranslation } from 'react-i18next'; +import { Agent, CredentialState, ProofState } from '@aries-framework/core'; +import { Label } from '../../components'; +import { ContactStackParams, Screens } from '../../types/navigators'; +import { dateFormatOptions } from '../../constants'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { errorToast, successToast } from '../../utils/toast'; +import Accordion from '../../components/accordion/Accordion'; +import { RecordHistory } from '../../types/record'; + +type ContactDetailsProps = StackScreenProps< + ContactStackParams, + Screens.ContactDetails +>; + +const ContactDetails: React.FC<ContactDetailsProps> = ({ + navigation, + route, +}) => { + const { t } = useTranslation(); + const { agent: agentUndefined } = useAgent(); + const agent = agentUndefined as Agent; + const connection = useConnectionById(route?.params?.connectionId); + const credentialOffers = useCredentialByState(CredentialState.OfferReceived); + const proofs = useProofByState(ProofState.RequestReceived); + const [history, setHistory] = useState<RecordHistory[]>([]); + useEffect(() => { + navigation.setOptions({ + title: connection?.alias ?? connection?.theirLabel, + }); + }, [connection, navigation]); + + const getConnectionHistory = useCallback(async () => { + // Get credential records for a specific connection + const credentialData = await agent.genericRecords.findAllByQuery({ + connectionId: connection?.id, + type: 'credential', + }); + + // Get proof records for a specific connection + const proofData = await agent.genericRecords.findAllByQuery({ + connectionId: connection?.id, + type: 'proof', + }); + + // Set empty array if no data is returned + const credentialRecords = + credentialData.length > 0 ? credentialData[0].content.records : []; + + // Set empty array if no data is returned + const proofRecords = + proofData.length > 0 ? proofData[0].content.records : []; + + // Combine credential and proof records into one array and filter with connection label + const history = [...credentialRecords, ...proofRecords].filter( + record => record.connectionLabel === connection?.theirLabel, + ); + + // Sort history by timestamp + const sortedHistory = history.sort( + (x, y) => + new Date(y.timestamp).valueOf() - new Date(x.timestamp).valueOf(), + ); + if (sortedHistory) { + setHistory(sortedHistory); + } + }, [agent.genericRecords, connection]); + + useEffect(() => { + getConnectionHistory(); + }, [getConnectionHistory]); + + const showDeleteConnectionAlert = () => { + Alert.alert( + t<string>('ContactDetails.DeleteConnection'), + t<string>('ContactDetails.DeleteConnectionAlert'), + [ + { + text: t<string>('Global.Cancel'), + style: 'cancel', + }, + { text: t<string>('Global.Okay'), onPress: deleteConnection }, + ], + ); + }; + + const deleteConnection = async () => { + try { + if (connection) { + // Delete the connection by id + for await (const offer of credentialOffers) { + if (offer?.connectionId === connection?.id) { + await agent.credentials.declineOffer(offer.id); + } + } + + for await (const proof of proofs) { + if (proof?.connectionId === connection?.id) { + await agent.proofs.declineRequest(proof.id); + } + } + + await agent.connections.deleteById(connection?.id); + successToast(t<string>('ContactDetails.DeleteConnectionSuccess')); + navigation.navigate(Screens.ListContacts); + } + } catch (error) { + errorToast(t<string>('ContactDetails.DeleteConnectionFailed')); + } + }; + + return ( + <View style={styles.container}> + <Label title="Name" subtitle={connection?.theirLabel} /> + <Label title="Id" subtitle={connection?.id} /> + <Label title="Did" subtitle={connection?.did} /> + <Label + title="Created" + subtitle={connection?.createdAt.toLocaleDateString( + 'en-CA', + dateFormatOptions, + )} + /> + <Label title="Connection State" subtitle={connection?.state} /> + {!connection?.theirLabel?.toUpperCase().includes('MEDIATOR') && ( + <TouchableOpacity + testID="delete-contact" + onPress={showDeleteConnectionAlert} + > + <Text + style={[ + styles.footerText, + styles.link, + { color: ColorPallet.semantic.error }, + ]} + > + {t<string>('ContactDetails.DeleteConnection')} + </Text> + </TouchableOpacity> + )} + + <FlatList + data={history} + contentContainerStyle={styles.cardContainer} + renderItem={({ item }) => ( + <View key={item.timestamp.toString()}> + <Accordion + title={item.connectionLabel} + date={new Date(item.timestamp)} + status={item.status} + innerAccordion + key={item.timestamp.toString()} + > + {Object.entries(item.attributes).map(([key, value]) => { + return ( + <View style={styles.attributeContainer}> + <Text style={styles.attribute}>{key}</Text> + <Text style={styles.attribute}>{value.toString()}</Text> + </View> + ); + })} + </Accordion> + <View style={styles.divider} /> + </View> + )} + keyExtractor={item => item.timestamp.toString()} + /> + </View> + ); +}; + +export default ContactDetails; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + }, + footerText: { + ...TextTheme.normal, + padding: 10, + }, + link: { + ...TextTheme.normal, + color: ColorPallet.brand.link, + }, + cardContainer: { + padding: 10, + paddingBottom: 35, + }, + divider: { + borderBottomColor: ColorPallet.baseColors.lightGrey, + borderBottomWidth: 1, + width: '100%', + }, + attribute: { + width: '50%', + color: ColorPallet.baseColors.black, + }, + attributeContainer: { + flexDirection: 'row', + marginVertical: 5, + }, +}); diff --git a/src/screens/ContactDetails/__tests__/ContactDetails.test.tsx b/src/screens/ContactDetails/__tests__/ContactDetails.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d73532398a11e698352de61c5e06a060707ab1f2 --- /dev/null +++ b/src/screens/ContactDetails/__tests__/ContactDetails.test.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { useNavigation } from '@react-navigation/core'; +import { fireEvent, render } from '@testing-library/react-native'; +import { DidExchangeState } from '@aries-framework/core'; +import { Alert } from 'react-native'; +import { Screens } from '../../../types/navigators'; +import ContactDetails from '../ContactDetails'; +import { useConnectionById } from '../../../../__mocks__/@aries-framework/react-hooks'; +import { getMockConnection } from '../../../utils/testhelpers'; + +describe('ContactDetails', () => { + jest.mock('react-native', () => { + const RN = jest.requireActual('react-native'); + + return Object.setPrototypeOf( + { + Alert: { + ...RN.Alert, + alert: jest.fn(), + }, + }, + RN, + ); + }); + + it('testing', () => { + useConnectionById.mockImplementation(() => + getMockConnection({ + id: 'tesid', + theirLabel: 'test-label', + did: 'SL2dA5wcdY8NEhkKwYeVNb', + state: DidExchangeState.Completed, + createdAt: new Date('2022-04-29T06:36:48.244Z'), + }), + ); + // Alert.alert = jest.genMockFunction(); + Alert.alert = jest.fn(); + const { getByText, getByTestId } = render( + <ContactDetails + route={{ + params: { connectionId: 'connectionRecord.id ' }, + key: '', + name: Screens.ContactDetails, + }} + navigation={useNavigation()} + />, + ); + const name = getByText('test-label'); + const didText = getByText('SL2dA5wcdY8NEhkKwYeVNb'); + const stateText = getByText('completed'); + + expect(name.props.children).toBe('test-label'); + expect(didText.props.children).toBe('SL2dA5wcdY8NEhkKwYeVNb'); + expect(stateText.props.children).toBe('completed'); + + const contactListItem = getByTestId('delete-contact'); + fireEvent.press(contactListItem); + expect(Alert.alert.mock.calls.length).toBe(1); + }); +}); diff --git a/src/screens/ContactDetails/index.ts b/src/screens/ContactDetails/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..631abf6017ec7b527ac9a3efb2a9f46e2ab30f43 --- /dev/null +++ b/src/screens/ContactDetails/index.ts @@ -0,0 +1,3 @@ +import ContactDetails from './ContactDetails'; + +export default ContactDetails; diff --git a/src/screens/CreateWallet/CreateWallet.tsx b/src/screens/CreateWallet/CreateWallet.tsx new file mode 100644 index 0000000000000000000000000000000000000000..62ef7e47ae930df3e1b95b6f43a04ed17cbb01c1 --- /dev/null +++ b/src/screens/CreateWallet/CreateWallet.tsx @@ -0,0 +1,128 @@ +import { StackScreenProps } from '@react-navigation/stack'; +import React, { useCallback, useEffect, useState } from 'react'; +import Clipboard from '@react-native-clipboard/clipboard'; +import { View, StyleSheet, Text } from 'react-native'; +import { useTranslation } from 'react-i18next'; +import { UserCredentials } from 'react-native-keychain'; +import { OnboardingStackParams, Screens } from '../../types/navigators'; +import { + createMD5HashFromString, + storeOnboardingCompleteStage, +} from './CreateWallet.utils'; +import { saveValueInKeychain } from '../../utils/generic'; +import { getMnemonicArrayFromWords } from '../../utils/generic'; +import { KeychainStorageKeys } from '../../constants'; +import Button, { ButtonType } from '../../components/button/Button'; +import { InfoCard, Loader, ScreenNavigatorButtons } from '../../components'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { getValueKeychain } from '../../utils/keychain'; +import { errorToast, successToast } from '../../utils/toast'; + +type CreateWalletProps = StackScreenProps< + OnboardingStackParams, + Screens.CreateWallet +>; + +const CreateWallet: React.FC<CreateWalletProps> = ({ navigation, route }) => { + const [mnemonicText, setMnemonicText] = useState(''); + const { initAgent } = route.params; + const [loading, setLoading] = useState(false); + + const { t } = useTranslation(); + const createMnemonic = useCallback(async () => { + const mnemonicWordsList = getMnemonicArrayFromWords(8); + const mnemonic = mnemonicWordsList.join(' '); + setMnemonicText(mnemonic); + await saveValueInKeychain( + KeychainStorageKeys.Passphrase, + mnemonic, + t<string>('Registration.MnemonicMsg'), + ); + }, [t]); + + useEffect(() => { + createMnemonic(); + }, [createMnemonic]); + + const copyMnemonic = async () => { + Clipboard.setString(mnemonicText); + }; + const onBack = async () => { + navigation.navigate(Screens.Terms); + }; + + const startAgent = async (guid: string, pin: string) => { + try { + const rawValue = mnemonicText.replace(/ /g, ''); + const seedHash = createMD5HashFromString(rawValue); + + await initAgent(guid, pin, seedHash); + await storeOnboardingCompleteStage(); + successToast(t<string>('PinCreate.WalletCreated')); + + navigation.navigate(Screens.SetupDelay); + } catch (error: any) { + setLoading(false); + errorToast(error.message); + } + }; + + const createWallet = async () => { + setLoading(true); + const guid = (await getValueKeychain({ + service: KeychainStorageKeys.GUID, + })) as UserCredentials; + const pinCode = (await getValueKeychain({ + service: KeychainStorageKeys.Passcode, + })) as UserCredentials; + await startAgent(guid.password, pinCode.password); + setLoading(false); + }; + + return ( + <View style={style.container}> + <Loader loading={loading} /> + <Text style={style.label}>{t<string>('Mnemonic.MnemonicTitle')}</Text> + <View style={style.container}> + <InfoCard showBottomIcon={false} showTopIcon mnemonicText> + <Text style={style.headerText}>{`${mnemonicText}\n`}</Text> + {t<string>('Registration.MnemonicMsg')} + </InfoCard> + <Button + buttonStyle={style.btnContainer} + title={t<string>('Global.Copy')} + buttonType={ButtonType.Primary} + onPress={copyMnemonic} + /> + </View> + <ScreenNavigatorButtons + onLeftPress={onBack} + onRightPress={createWallet} + /> + </View> + ); +}; + +export default CreateWallet; + +const style = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + flex: 1, + margin: 20, + }, + label: { + ...TextTheme.normal, + fontWeight: 'bold', + textAlign: 'center', + }, + headerText: { + ...TextTheme.normal, + color: ColorPallet.notification.infoText, + flexShrink: 1, + }, + btnContainer: { + marginTop: 20, + alignSelf: 'center', + }, +}); diff --git a/src/screens/CreateWallet/CreateWallet.utils.test.ts b/src/screens/CreateWallet/CreateWallet.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d323959e2d56239dc76ef3d28d95ad566e07cbb4 --- /dev/null +++ b/src/screens/CreateWallet/CreateWallet.utils.test.ts @@ -0,0 +1,45 @@ +import * as Utils from './CreateWallet.utils'; +import { getMnemonicArrayFromWords } from '../../utils/generic'; + +describe('CreateWallet.utils', () => { + describe('storeOnboardingCompleteStage', () => { + it('should store a value for onboarding complete stage', async () => { + jest.spyOn(Utils, 'storeOnboardingCompleteStage'); + + await Utils.storeOnboardingCompleteStage(); + + expect(Utils.storeOnboardingCompleteStage).toHaveBeenCalled(); + }); + }); + + describe('getMnemonicFromWords', () => { + it.each([ + [0, 0], + [5, 5], + [3, 3], + [8, 8], + ])( + 'should return string values from list of words with provided length of Words', + (initialValues, finalLength) => { + const result = getMnemonicArrayFromWords(initialValues); + expect(result.length).toEqual(finalLength); + }, + ); + }); + + describe('createMD5HashFromString', () => { + it.each([ + ['kevin@gmail.com1234566', '31a8cc6fdfd91bd25e777cd928cca890'], + [ + 'kevin.durant@gmail.comThisisateststring', + '01b8b1108447e196002c12f27c2388b6', + ], + ])( + 'should return a hash value for the given string', + (initialValue, expectedValue) => { + const result = Utils.createMD5HashFromString(initialValue); + expect(result).toEqual(expectedValue); + }, + ); + }); +}); diff --git a/src/screens/CreateWallet/CreateWallet.utils.ts b/src/screens/CreateWallet/CreateWallet.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..011865cf124827fbfdbb6f1865dbaa10db32990a --- /dev/null +++ b/src/screens/CreateWallet/CreateWallet.utils.ts @@ -0,0 +1,14 @@ +import { Alert } from 'react-native'; +import md5 from 'md5'; +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { setValueKeychain } from '../../utils/keychain'; +import wordsList from '../../utils/wordsList'; +import { LocalStorageKeys } from '../../constants'; + +export const createMD5HashFromString = (value: string) => { + const hash = String(md5(value)); + return hash; +}; +export const storeOnboardingCompleteStage = async () => { + await AsyncStorage.setItem(LocalStorageKeys.OnboardingCompleteStage, 'true'); +}; diff --git a/src/screens/CreateWallet/index.ts b/src/screens/CreateWallet/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..6b18e86004508ad0d414969b81ab3e1fbd4f71c9 --- /dev/null +++ b/src/screens/CreateWallet/index.ts @@ -0,0 +1,3 @@ +import CreateWallet from './CreateWallet'; + +export default CreateWallet; diff --git a/src/screens/CredentialDetails/CredentialDetails.tsx b/src/screens/CredentialDetails/CredentialDetails.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e7fe03e1ed8d5334d44dd488fa2f9b5eb5d1c519 --- /dev/null +++ b/src/screens/CredentialDetails/CredentialDetails.tsx @@ -0,0 +1,213 @@ +import type { StackScreenProps } from '@react-navigation/stack'; + +import { useAgent, useCredentialById } from '@aries-framework/react-hooks'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { View, Text, StyleSheet, Platform, ScrollView } from 'react-native'; +import CredentialCard from '../../components/misc/CredentialCard'; +import { CredentialStackParams, Screens } from '../../types/navigators'; +import { warningToast, errorToast } from '../../utils/toast'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import Accordion from '../../components/accordion/Accordion'; +import { credentialDefinition } from '../../utils/helpers'; +import { RecordHistory } from '../../types/record'; + +type CredentialDetailsProps = StackScreenProps< + CredentialStackParams, + Screens.CredentialDetails +>; + +const CredentialDetails: React.FC<CredentialDetailsProps> = ({ + navigation, + route, +}) => { + const { t } = useTranslation(); + const { credentialId } = route.params; + const credential = useCredentialById(credentialId); + const { agent } = useAgent(); + const [history, setHistory] = useState<RecordHistory[]>([]); + + const getCredentialHistory = useCallback(async () => { + try { + const data = await agent?.genericRecords.findAllByQuery({ + credentialRecordId: credential?.credentials[0].credentialRecordId, + }); + + const history: any[] = []; + + // Add all credential records to the history + data?.forEach(record => history.push(...record.content.records)); + + // Filter out the credential records which have property credentialLabel + const filteredHistory = history.filter(record => record?.credentialLabel); + + // Sort history by timestamp + const sortedHistory = filteredHistory.sort( + (x, y) => + new Date(y.timestamp).valueOf() - new Date(x.timestamp).valueOf(), + ); + + setHistory(sortedHistory); + } catch (error) { + errorToast(t<string>('credential.get.error')); + } + }, [agent, credential, t]); + + useEffect(() => { + getCredentialHistory(); + }, [getCredentialHistory]); + + if (!route.params.credentialId) { + warningToast(t<string>('CredentialOffer.CredentialNotFound')); + navigation.goBack(); + return null; + } + if (!credential) { + errorToast(t<string>('CredentialOffer.CredentialNotFound')); + navigation.goBack(); + return null; + } + + return ( + <ScrollView contentContainerStyle={styles.scrollView}> + <CredentialCard + credential={credential} + style={styles.credentialCardView} + /> + <View style={Platform.OS === 'android' ? styles.card : styles.cardIos}> + <Accordion title="Info" innerAccordion={false}> + <View> + <View style={styles.innerContainer}> + <Text style={styles.attribute}>Credential </Text> + <Text style={styles.attribute}> + {credentialDefinition(credential)?.split(':')[4]} + </Text> + </View> + <View style={styles.divider} /> + {credential?.credentialAttributes?.map(item => { + return ( + <View style={styles.innerContainer}> + <Text style={styles.attribute}>{item.name}</Text> + <Text style={styles.attribute}>{item.value}</Text> + </View> + ); + })} + </View> + </Accordion> + </View> + <View style={Platform.OS === 'android' ? styles.card : styles.cardIos}> + <Accordion title="Activities" innerAccordion={false}> + {history.map((item, index) => { + return ( + <View> + <Accordion + title={item.connectionLabel} + date={new Date(item.timestamp)} + status={item.status} + innerAccordion + > + {Object.entries(item.attributes).map(([key, value]) => { + return ( + <View style={styles.innerContainer}> + <Text style={styles.attribute}>{key}</Text> + <Text style={styles.attribute}>{value.toString()}</Text> + </View> + ); + })} + </Accordion> + {history.length - 1 !== index && ( + <View style={styles.divider} /> + )} + </View> + ); + })} + </Accordion> + </View> + </ScrollView> + ); +}; + +export default CredentialDetails; + +const styles = StyleSheet.create({ + card: { + backgroundColor: ColorPallet.baseColors.white, + borderRadius: 10, + elevation: 3, + padding: 10, + marginVertical: 10, + width: '90%', + alignSelf: 'center', + }, + cardIos: { + backgroundColor: ColorPallet.baseColors.white, + shadowColor: ColorPallet.baseColors.black, + shadowOffset: { + width: 0, + height: 1, + }, + shadowOpacity: 0.22, + shadowRadius: 2.22, + borderRadius: 10, + padding: 10, + marginVertical: 10, + width: '90%', + alignSelf: 'center', + }, + text: { + fontSize: 18, + marginBottom: 20, + }, + safeArea: { + flex: 1, + }, + heading: { + alignItems: 'center', + flexDirection: 'row', + justifyContent: 'space-between', + paddingVertical: 10, + }, + hidden: { + height: 0, + }, + list: { + overflow: 'hidden', + }, + sectionTitle: { + ...TextTheme.normal, + fontWeight: 'bold', + color: ColorPallet.baseColors.black, + marginLeft: '5%', + }, + sectionSubTitle: { + ...TextTheme.caption, + color: ColorPallet.baseColors.black, + marginLeft: '5%', + }, + sectionDescription: { + ...TextTheme.caption, + color: ColorPallet.baseColors.black, + height: 30, + marginLeft: '5%', + }, + divider: { + borderBottomColor: ColorPallet.baseColors.lightGrey, + borderBottomWidth: 1, + width: '100%', + }, + credentialCardView: { + marginHorizontal: 15, + marginTop: 16, + }, + innerContainer: { + flexDirection: 'row', + marginVertical: 5, + }, + attribute: { + width: '50%', + color: ColorPallet.baseColors.black, + }, + scrollView: { + paddingBottom: 30, + }, +}); diff --git a/src/screens/CredentialDetails/__tests__/CredentialDetails.test.tsx b/src/screens/CredentialDetails/__tests__/CredentialDetails.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5c2587f99a60f81a4c57e15479edabc07355bb62 --- /dev/null +++ b/src/screens/CredentialDetails/__tests__/CredentialDetails.test.tsx @@ -0,0 +1,69 @@ +import React from 'react'; +import { + CredentialMetadataKeys, + CredentialExchangeRecord, + CredentialState, + CredentialPreviewAttribute, +} from '@aries-framework/core'; +import { useNavigation } from '@react-navigation/core'; +import { create } from 'react-test-renderer'; +import CredentialDetails from '../CredentialDetails'; +import { Screens } from '../../../types/navigators'; + +const credentialRecord = new CredentialExchangeRecord({ + connectionId: '28790bfe-1345-4c64-b21a-7d98982b3894', + threadId: 'threadId', + state: CredentialState.Done, + credentialAttributes: [ + new CredentialPreviewAttribute({ + name: 'age', + value: '25', + }), + ], + protocolVersion: 'v1', +}); + +credentialRecord.metadata.set(CredentialMetadataKeys.IndyCredential, { + credentialDefinitionId: 'Th7MpTaRZVRYnPiabds81Y:3:CL:17:TA', + schemaId: 'TL1EaPFCZ8Si5aUrqScBDt:2:testschema:1.0', +}); + +jest.mock('i18next', () => ({ + use: jest.fn(() => ({})), + init: jest.fn(() => ({})), + t: k => k, +})); + +jest.mock('react-native-toast-message', () => ({ + show: jest.fn(), + hide: jest.fn(), +})); +describe('CredentialDetails', () => { + jest.mock('react-native', () => { + const RN = jest.requireActual('react-native'); + + return Object.setPrototypeOf( + { + Alert: { + ...RN.Alert, + alert: jest.fn(), + }, + }, + RN, + ); + }); + it('credential details render correctly', () => { + const tree = create( + <CredentialDetails + route={{ + params: { credentialId: credentialRecord.id }, + key: '', + name: Screens.CredentialDetails, + }} + navigation={useNavigation()} + />, + ); + + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/screens/CredentialDetails/__tests__/__snapshots__/CredentialDetails.test.tsx.snap b/src/screens/CredentialDetails/__tests__/__snapshots__/CredentialDetails.test.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..38730dfaf78033e2f964ff3ec5c434390f5263f9 --- /dev/null +++ b/src/screens/CredentialDetails/__tests__/__snapshots__/CredentialDetails.test.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CredentialDetails credential details render correctly 1`] = `null`; diff --git a/src/screens/CredentialDetails/index.ts b/src/screens/CredentialDetails/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..fd47f3e717f9606722702de9bdf4e8bba422ff3f --- /dev/null +++ b/src/screens/CredentialDetails/index.ts @@ -0,0 +1,3 @@ +import CredentialDetails from './CredentialDetails'; + +export default CredentialDetails; diff --git a/src/screens/CredentialOffer/CredentialOffer.tsx b/src/screens/CredentialOffer/CredentialOffer.tsx new file mode 100644 index 0000000000000000000000000000000000000000..629b08ddac3e57cc798e49fc3f18cca6d9df67dd --- /dev/null +++ b/src/screens/CredentialOffer/CredentialOffer.tsx @@ -0,0 +1,268 @@ +import { StackScreenProps } from '@react-navigation/stack'; +import { + AriesFrameworkError, + CredentialState, + GetFormatDataReturn, + IndyCredentialFormat, +} from '@aries-framework/core'; +import { StyleSheet, Alert, View, Text } from 'react-native'; +import { + useAgent, + useConnectionById, + useCredentialById, +} from '@aries-framework/react-hooks'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import Toast from 'react-native-toast-message'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { HomeStackParams, Screens, TabStacks } from '../../types/navigators'; +import Title from '../../components/text/Title'; +import FlowDetailModal from '../../components/modals/FlowDetailModal'; +import Record from '../../components/record/Record'; +import CredentialCard from '../../components/misc/CredentialCard'; +import CredentialDeclined from '../../assets/img/credential-declined.svg'; +import CredentialPending from '../../assets/img/credential-pending.svg'; +import CredentialSuccess from '../../assets/img/credential-success.svg'; +import Button, { ButtonType } from '../../components/button/Button'; +import { credentialDefinition } from '../../utils/helpers'; +import { ToastType } from '../../components/toast/BaseToast'; + +type CredentialOfferProps = StackScreenProps< + HomeStackParams, + Screens.CredentialOffer +>; + +const CredentialOffer: React.FC<CredentialOfferProps> = ({ + navigation, + route, +}) => { + const { t } = useTranslation(); + if (!route?.params) { + throw new Error(t<string>('CredentialOffer.CredentialOfferParamsError')); + } + const { credentialId } = route.params; + const { agent } = useAgent(); + const [buttonsVisible, setButtonsVisible] = useState(true); + const [pendingModalVisible, setPendingModalVisible] = useState(false); + const [successModalVisible, setSuccessModalVisible] = useState(false); + const [declinedModalVisible, setDeclinedModalVisible] = useState(false); + const [credentialRecord, setCredentialRecord] = useState< + GetFormatDataReturn<[IndyCredentialFormat]> + >({}); + + const credential = useCredentialById(credentialId); + + const connection = useConnectionById(credential?.connectionId); + if (!agent) { + throw new Error(t<string>('CredentialOffer.FetchAFJError')); + } + + if (!credential) { + throw new Error(t<string>('CredentialOffer.CredentialFetchError')); + } + + const getCredentialData = useCallback(async () => { + if (credential) { + const credentialRecord = await agent.credentials.getFormatData( + credential.id, + ); + setCredentialRecord(credentialRecord); + } + }, [agent.credentials, credential]); + + useEffect(() => { + getCredentialData(); + }, [getCredentialData]); + + useEffect(() => { + if (credential.state === CredentialState.Declined) { + setDeclinedModalVisible(true); + } + }, [credential]); + + const saveCredentialInGenericRecords = useCallback(async () => { + if (credential.state === CredentialState.Done) { + const tags = { + connectionId: connection?.id, + credentialRecordId: credential.credentials[0].credentialRecordId, + type: 'credential', + }; + const attributes = {}; + credential?.credentialAttributes?.forEach(attribute => { + attributes[attribute.name] = attribute.value; + }); + const record = { + status: 'issued', + timestamp: new Date().getTime(), + connectionLabel: connection?.theirLabel ?? 'Connection less credential', + credentialLabel: credentialDefinition(credential)?.split(':')[4], + attributes, + }; + const content = { records: [record] }; + await agent.genericRecords.save({ content, tags }); + } + }, [ + agent.genericRecords, + connection?.id, + connection?.theirLabel, + credential, + ]); + + useEffect(() => { + if ( + credential.state === CredentialState.CredentialReceived || + credential.state === CredentialState.Done + ) { + if (pendingModalVisible) { + setPendingModalVisible(false); + } + setSuccessModalVisible(true); + } + if (credential.state === CredentialState.Done) { + saveCredentialInGenericRecords(); + } + }, [credential.state, pendingModalVisible, saveCredentialInGenericRecords]); + + const handleAcceptPress = async () => { + try { + setButtonsVisible(false); + setPendingModalVisible(true); + await agent.credentials.acceptOffer({ + credentialRecordId: credential.id, + }); + } catch (error: unknown) { + const credentialError = error as AriesFrameworkError; + setButtonsVisible(true); + setPendingModalVisible(false); + Toast.show({ + type: ToastType.Error, + text1: credentialError.name, + text2: credentialError.message, + }); + } + }; + + const handleDeclinePress = async () => { + Alert.alert( + t<string>('CredentialOffer.RejectThisCredential?'), + t<string>('Global.ThisDecisionCannotBeChanged.'), + [ + { text: t<string>('Global.Cancel'), style: 'cancel' }, + { + text: t<string>('Global.Confirm'), + style: 'destructive', + onPress: async () => { + try { + setButtonsVisible(false); + await agent.credentials.declineOffer(credential.id); + } catch (e: unknown) { + Toast.show({ + type: ToastType.Error, + text1: t<string>('CredentialOffer.RejectOfferTitle'), + text2: t<string>('CredentialOffer.RejectOfferMessage'), + }); + } + }, + }, + ], + ); + }; + + return ( + <> + <Record + header={() => ( + <> + <View style={styles.headerTextContainer}> + <Text style={styles.headerText}> + <Title> + {connection?.theirLabel || + t<string>('ContactDetails.AContact')} + </Title>{' '} + {t<string>('CredentialOffer.IsOfferingYouACredential')} + </Text> + </View> + <CredentialCard + credential={credential} + style={{ marginHorizontal: 15, marginBottom: 16 }} + /> + </> + )} + footer={() => ( + <View style={{ marginBottom: 30 }}> + <View style={styles.footerButton}> + <Button + title={t<string>('Global.Accept')} + onPress={handleAcceptPress} + disabled={!buttonsVisible} + buttonType={ButtonType.Primary} + /> + </View> + <View style={styles.footerButton}> + <Button + title={t<string>('Global.Decline')} + onPress={handleDeclinePress} + disabled={!buttonsVisible} + buttonType={ButtonType.Ghost} + /> + </View> + </View> + )} + attributes={credentialRecord?.offerAttributes} + /> + <FlowDetailModal + title={t<string>('CredentialOffer.CredentialOnTheWay')} + doneTitle={t<string>('Global.Cancel')} + visible={pendingModalVisible} + onDone={() => { + setPendingModalVisible(false); + }} + > + <CredentialPending style={{ marginVertical: 20 }} /> + </FlowDetailModal> + <FlowDetailModal + title={t<string>('CredentialOffer.CredentialAddedToYourWallet')} + visible={successModalVisible} + onDone={() => { + setSuccessModalVisible(false); + navigation.pop(); + navigation.getParent()?.navigate(TabStacks.CredentialStack, { + screen: Screens.Credentials, + }); + }} + > + <CredentialSuccess style={{ marginVertical: 20 }} /> + </FlowDetailModal> + <FlowDetailModal + title={t<string>('CredentialOffer.CredentialDeclined')} + visible={declinedModalVisible} + onDone={() => { + setDeclinedModalVisible(false); + navigation.pop(); + navigation.navigate(Screens.Home); + }} + > + <CredentialDeclined style={{ marginVertical: 20 }} /> + </FlowDetailModal> + </> + ); +}; + +export default CredentialOffer; + +const styles = StyleSheet.create({ + headerTextContainer: { + paddingHorizontal: 25, + paddingVertical: 16, + backgroundColor: ColorPallet.grayscale.white, + }, + headerText: { + backgroundColor: ColorPallet.grayscale.white, + ...TextTheme.normal, + flexShrink: 1, + }, + footerButton: { + paddingTop: 10, + backgroundColor: ColorPallet.grayscale.white, + }, +}); diff --git a/src/screens/CredentialOffer/CredentialOffer.utils.test.tsx b/src/screens/CredentialOffer/CredentialOffer.utils.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..7adcd8ec5372df3da872370e08c82a5884a6916a --- /dev/null +++ b/src/screens/CredentialOffer/CredentialOffer.utils.test.tsx @@ -0,0 +1,15 @@ +import * as Utils from './CredentialOffer.utils'; + +describe('CredentialOffer', () => { + describe('CredentialOffer.utils', () => { + describe('acceptcredential', () => { + it('should we get retrieved credential for proof', () => { + jest.spyOn(Utils, 'acceptCredential'); + + Utils.acceptCredential('credential'); + + expect(Utils.acceptCredential).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/src/screens/CredentialOffer/CredentialOffer.utils.ts b/src/screens/CredentialOffer/CredentialOffer.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..2bc184b1163191e4a06418cd36e41adfb29d1313 --- /dev/null +++ b/src/screens/CredentialOffer/CredentialOffer.utils.ts @@ -0,0 +1,13 @@ +import { Agent, CredentialExchangeRecord } from '@aries-framework/core'; + +export const acceptCredential = async ( + agent: Agent, + credential: CredentialExchangeRecord, +) => { + const credentialRecord = await agent.credentials.acceptOffer({ + credentialRecordId: credential.id, + }); + return credentialRecord; +}; + +export default { acceptCredential }; diff --git a/src/screens/CredentialOffer/index.ts b/src/screens/CredentialOffer/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..c3f9d3fd054d9454ff412d0c287283d0208c249e --- /dev/null +++ b/src/screens/CredentialOffer/index.ts @@ -0,0 +1,3 @@ +import CredentialOffer from './CredentialOffer'; + +export default CredentialOffer; diff --git a/src/screens/ExportWallet/ExportWallet.ios.tsx b/src/screens/ExportWallet/ExportWallet.ios.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5927b70528cc00f00b630196a26ab8f406e4e9ba --- /dev/null +++ b/src/screens/ExportWallet/ExportWallet.ios.tsx @@ -0,0 +1,167 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { StyleSheet, View } from 'react-native'; +import Toast from 'react-native-toast-message'; +import { WalletExportImportConfig } from '@aries-framework/core/build/types'; +import { useAgent } from '@aries-framework/react-hooks'; +import argon2 from 'react-native-argon2'; +import { useNavigation } from '@react-navigation/core'; +import { UserCredentials } from 'react-native-keychain'; +import RNFetchBlob from 'rn-fetch-blob'; +import Share from 'react-native-share'; +import { Loader, TextInput } from '../../components'; +import { ToastType } from '../../components/toast/BaseToast'; +import { KeychainStorageKeys, salt } from '../../constants'; + +import Button, { ButtonType } from '../../components/button/Button'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { getValueKeychain } from '../../utils/keychain'; +import { authenticateUser } from './ExportWallet.utils'; + +const ExportWallet = () => { + const { t } = useTranslation(); + const [loading, setLoading] = useState(false); + const [mnemonic, setMnemonic] = useState(''); + const { agent } = useAgent(); + const nav = useNavigation(); + + const exportWallet = async () => { + try { + setLoading(true); + + const { fs } = RNFetchBlob; + + const documentDirectory = fs.dirs.DocumentDir; + + const zipDirectory = `${documentDirectory}/PCM_Backup`; + + const destFileExists = await fs.exists(zipDirectory); + if (destFileExists) { + await fs.unlink(zipDirectory); + } + + const date = new Date(); + const dformat = `${date.getHours()}-${date.getMinutes()}-${date.getSeconds()}`; + const WALLET_FILE_NAME = `PCM_Wallet_${dformat}`; + + await fs + .mkdir(zipDirectory) + .then(() => console.log('generated')) + .catch(err => console.log('not generated', err)); + const encryptedFileName = `${WALLET_FILE_NAME}.wallet`; + const encryptedFileLocation = `${zipDirectory}/${encryptedFileName}`; + + const passphraseEntry = (await getValueKeychain({ + service: KeychainStorageKeys.Passphrase, + })) as UserCredentials; + + const result = await argon2(passphraseEntry.password, salt, { + iterations: 5, + memory: 16 * 1024, + parallelism: 2, + hashLength: 20, + mode: 'argon2i', + }); + + const { encodedHash } = result; + + const exportConfig: WalletExportImportConfig = { + key: encodedHash, + path: encryptedFileLocation, + }; + + await agent?.wallet.export(exportConfig); + + const { success, message } = await Share.open({ + title: 'Share file', + failOnCancel: false, + saveToFiles: true, + url: encryptedFileLocation, + }); + + if (success) { + Toast.show({ + type: ToastType.Success, + text1: t<string>('ExportWallet.WalletExportedPath'), + text2: message, + }); + } + setLoading(false); + nav.goBack(); + } catch (err) { + setLoading(false); + console.log(err); + } + }; + + const compareMnemonic = async () => { + const passphraseEntry = (await getValueKeychain({ + service: KeychainStorageKeys.Passphrase, + })) as UserCredentials; + + if (mnemonic !== '') { + const params = [mnemonic, passphraseEntry.password]; + const result = authenticateUser(params); + if (result) { + Toast.show({ + type: ToastType.Success, + text1: t<string>('Toasts.Success'), + text2: t<string>('Settings.ValidMnemonic'), + }); + await exportWallet(); + } else { + Toast.show({ + type: ToastType.Error, + text1: t<string>('Toasts.Error'), + text2: t<string>('Settings.InvalidMnemonic'), + }); + } + } else { + Toast.show({ + type: ToastType.Warn, + text1: t<string>('Toasts.Warning'), + text2: t<string>('Settings.MnemonicMsg'), + }); + } + }; + + return ( + <View style={style.container}> + <Loader loading={loading} /> + <TextInput + label={t<string>('Settings.EnterMnemonic')} + placeholder={t<string>('Settings.EnterMnemonic')} + placeholderTextColor={ColorPallet.brand.primary} + accessible + accessibilityLabel={t<string>('Settings.EnterMnemonic')} + autoFocus + value={mnemonic} + onChangeText={setMnemonic} + autoCapitalize="none" + returnKeyType="done" + /> + <Button + title={t<string>('Settings.ExportWallet')} + buttonType={ButtonType.Primary} + onPress={compareMnemonic} + /> + </View> + ); +}; + +export default ExportWallet; + +const style = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + }, + bodyText: { + ...TextTheme.normal, + flexShrink: 1, + }, + verticalSpacer: { + marginVertical: 20, + textAlign: 'center', + }, +}); diff --git a/src/screens/ExportWallet/ExportWallet.tsx b/src/screens/ExportWallet/ExportWallet.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2c4d02def7d8fe4ece18dffff44ea1d8ed235ec8 --- /dev/null +++ b/src/screens/ExportWallet/ExportWallet.tsx @@ -0,0 +1,197 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { + StyleSheet, + PermissionsAndroid, + Platform, + View, + Keyboard, +} from 'react-native'; +import Toast from 'react-native-toast-message'; +import RNFS from 'react-native-fs'; +import { WalletExportImportConfig } from '@aries-framework/core/build/types'; +import { useAgent } from '@aries-framework/react-hooks'; +import argon2 from 'react-native-argon2'; +import { UserCredentials } from 'react-native-keychain'; +import { useNavigation } from '@react-navigation/core'; +import { Loader, TextInput } from '../../components'; +import { ToastType } from '../../components/toast/BaseToast'; +import { KeychainStorageKeys, salt } from '../../constants'; +import Button, { ButtonType } from '../../components/button/Button'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { getValueKeychain } from '../../utils/keychain'; +import { authenticateUser } from './ExportWallet.utils'; + +const ExportWallet = () => { + const { t } = useTranslation(); + const [loading, setLoading] = useState(false); + const [mnemonic, setMnemonic] = useState(''); + const { agent } = useAgent(); + const nav = useNavigation(); + + const askPermission = async () => { + if (Platform.OS === 'android') { + try { + const granted = await PermissionsAndroid.request( + PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, + { + title: 'Permission', + message: 'PCM needs to write to storage ', + buttonPositive: '', + }, + ); + + if (granted === PermissionsAndroid.RESULTS.GRANTED) { + exportWallet(); + } + } catch (error) { + console.log(error); + } + } else { + exportWallet(); + } + }; + + const exportWallet = async () => { + try { + const granted = await PermissionsAndroid.request( + PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, + { + title: 'Permission', + message: 'PCM needs to write to storage ', + buttonPositive: '', + }, + ); + + if (granted === PermissionsAndroid.RESULTS.GRANTED) { + Keyboard.dismiss(); + setLoading(true); + const documentDirectory = RNFS.DownloadDirectoryPath; + + const zipDirectory = `${documentDirectory}/PCM_Backup`; + + const destFileExists = await RNFS.exists(zipDirectory); + if (destFileExists) { + await RNFS.unlink(zipDirectory); + } + + const date = new Date(); + const dformat = `${date.getHours()}-${date.getMinutes()}-${date.getSeconds()}`; + const WALLET_FILE_NAME = `PCM_Wallet_${dformat}`; + + await RNFS.mkdir(zipDirectory) + .then(() => console.log('generated')) + .catch(err => console.log('not generated', err)); + const encryptedFileName = `${WALLET_FILE_NAME}.wallet`; + const encryptedFileLocation = `${zipDirectory}/${encryptedFileName}`; + + const passphraseEntry = (await getValueKeychain({ + service: KeychainStorageKeys.Passphrase, + })) as UserCredentials; + + const result = await argon2(passphraseEntry.password, salt, { + iterations: 5, + memory: 16 * 1024, + parallelism: 2, + hashLength: 20, + mode: 'argon2i', + }); + + const { encodedHash } = result; + + const exportConfig: WalletExportImportConfig = { + key: encodedHash, + path: encryptedFileLocation, + }; + await agent?.wallet.export(exportConfig); + Toast.show({ + type: ToastType.Success, + text1: t<string>('ExportWallet.WalletExportedPath'), + text2: t<string>(zipDirectory), + }); + setLoading(false); + nav.goBack(); + } else { + setLoading(false); + console.log( + 'Permission Denied!', + 'You need to give permission to see contacts', + ); + } + } catch (err) { + setLoading(false); + console.log(err); + } + }; + + const compareMnemonic = async () => { + const passphraseEntry = (await getValueKeychain({ + service: KeychainStorageKeys.Passphrase, + })) as UserCredentials; + + if (mnemonic !== '') { + const params = [mnemonic, passphraseEntry.password]; + const result = authenticateUser(params); + if (result) { + Toast.show({ + type: ToastType.Success, + text1: t<string>('Toasts.Success'), + text2: t<string>('Settings.ValidMnemonic'), + }); + askPermission(); + } else { + Toast.show({ + type: ToastType.Error, + text1: t<string>('Toasts.Error'), + text2: t<string>('Settings.InvalidMnemonic'), + }); + } + } else { + Toast.show({ + type: ToastType.Warn, + text1: t<string>('Toasts.Warning'), + text2: t<string>('Settings.MnemonicMsg'), + }); + } + }; + + return ( + <View style={style.container}> + <Loader loading={loading} /> + <TextInput + label={t<string>('Settings.EnterMnemonic')} + placeholder={t<string>('Settings.EnterMnemonic')} + placeholderTextColor={ColorPallet.brand.primary} + accessible + accessibilityLabel={t<string>('Settings.EnterMnemonic')} + autoFocus + value={mnemonic} + onChangeText={setMnemonic} + autoCapitalize="none" + returnKeyType="done" + /> + <Button + title={t<string>('Settings.ExportWallet')} + buttonType={ButtonType.Primary} + onPress={compareMnemonic} + /> + </View> + ); +}; + +export default ExportWallet; + +const style = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + }, + bodyText: { + ...TextTheme.normal, + flexShrink: 1, + }, + verticalSpacer: { + marginVertical: 20, + textAlign: 'center', + }, +}); diff --git a/src/screens/ExportWallet/ExportWallet.utils.test.ts b/src/screens/ExportWallet/ExportWallet.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..f651c05b57c3243cb1d8df2e081394483dafc625 --- /dev/null +++ b/src/screens/ExportWallet/ExportWallet.utils.test.ts @@ -0,0 +1,27 @@ +import * as Utils from './ExportWallet.utils'; + +jest.mock('react-native-argon2', () => 'ExportWallet.utils'); + +describe('ExportWallet.utils', () => { + describe('authenticateuser', () => { + it.each([ + { + args: [ + 'mocker calzone unfounded registry vacant lushly ooze catcher', + 'mocker calzone unfounded registry vacant lushly ooze catcher', + ], + expected: true, + }, + { + args: [ + 'mocker calzone unfounded registry vacant lushly ooze catcher', + 'mocker calzone unfounded registry vacant lushly ', + ], + expected: false, + }, + ])('should return a true if the mnemonic matches', initialValue => { + const result = Utils.authenticateUser(initialValue.args); + expect(result).toEqual(initialValue.expected); + }); + }); +}); diff --git a/src/screens/ExportWallet/ExportWallet.utils.ts b/src/screens/ExportWallet/ExportWallet.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..d47852ad3446717bfbb77b1c4ea6845a4e7818b9 --- /dev/null +++ b/src/screens/ExportWallet/ExportWallet.utils.ts @@ -0,0 +1,11 @@ +export const authenticateUser = args => { + const res = args.reduce((prev, curr) => { + if (prev.trim() === curr.trim()) { + return true; + } + return false; + }); + return res; +}; + +export default authenticateUser; diff --git a/src/screens/ExportWallet/index.ts b/src/screens/ExportWallet/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..d9b874e0cef0591807d7f74ebc4c975c993f73df --- /dev/null +++ b/src/screens/ExportWallet/index.ts @@ -0,0 +1,3 @@ +import ExportWallet from './ExportWallet'; + +export default ExportWallet; diff --git a/src/screens/Home/Home.tsx b/src/screens/Home/Home.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0acbfbc2c95b78a8481561a9532ecc01949c4cf8 --- /dev/null +++ b/src/screens/Home/Home.tsx @@ -0,0 +1,186 @@ +import React from 'react'; +import { + Dimensions, + FlatList, + StyleSheet, + Text, + TouchableOpacity, + View, +} from 'react-native'; +import { useTranslation } from 'react-i18next'; +import { StackScreenProps } from '@react-navigation/stack'; +import { CredentialState } from '@aries-framework/core'; +import { useCredentialByState } from '@aries-framework/react-hooks'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import useNotifications from '../../hooks/notifications'; +import { HomeStackParams, Screens } from '../../types/navigators'; +import InfoTextBox from '../../components/text/InfoTextBox'; +import { NotificationListItem } from '../../components'; +import { NotificationType } from '../../components/listItems/NotificationListItem'; + +const { width } = Dimensions.get('window'); + +type HomeProps = StackScreenProps<HomeStackParams, Screens.Home>; + +const Home: React.FC<HomeProps> = ({ navigation }) => { + const { t } = useTranslation(); + const { notifications } = useNotifications(); + const credentials = [ + ...useCredentialByState(CredentialState.CredentialReceived), + ...useCredentialByState(CredentialState.Done), + ]; + const emptyListComponent = () => ( + <View style={{ marginHorizontal: offset, width: width - 2 * offset }}> + <InfoTextBox showIcon> + <Text style={TextTheme.normal}>{t<string>('Home.NoNewUpdates')}</Text> + </InfoTextBox> + </View> + ); + + const displayMessage = (credentialCount: number) => { + if (typeof credentialCount === 'undefined') { + throw new Error(t<string>('Home.CredentialCountUndefinedError')); + } + + let credentialMsg; + + if (credentialCount === 1) { + credentialMsg = ( + <Text> + {t<string>('Home.YouHave')}{' '} + <Text style={{ fontWeight: 'bold' }}>{credentialCount}</Text>{' '} + {t<string>('Home.Credential')} {t<string>('Home.InYourWallet')} + </Text> + ); + } else if (credentialCount > 1) { + credentialMsg = ( + <Text> + {t<string>('Home.YouHave')}{' '} + <Text style={{ fontWeight: 'bold' }}>{credentialCount}</Text>{' '} + {t<string>('Home.Credentials')} {t<string>('Home.InYourWallet')} + </Text> + ); + } else { + credentialMsg = t<string>('Home.NoCredentials'); + } + + return ( + <View style={[styles.messageContainer]}> + {credentialCount === 0 ? ( + <Text + style={[ + TextTheme.headingTwo, + { marginTop: offset, marginBottom: 35 }, + ]} + > + {t<string>('Home.Welcome')} + </Text> + ) : null} + <Text + style={[TextTheme.normal, { marginTop: offset, textAlign: 'center' }]} + > + {credentialMsg} + </Text> + </View> + ); + }; + + return ( + <View> + <View style={styles.rowContainer}> + <Text style={[TextTheme.headingFour, styles.header]}> + {t<string>('Home.Notifications')} + {notifications.length ? ` (${notifications.length})` : ''} + </Text> + {notifications?.length > 1 ? ( + <TouchableOpacity + style={styles.linkContainer} + activeOpacity={1} + onPress={() => navigation.navigate(Screens.Notifications)} + > + <Text style={styles.link}>{t<string>('Home.SeeAll')}</Text> + </TouchableOpacity> + ) : null} + </View> + <FlatList + horizontal + showsHorizontalScrollIndicator={false} + scrollEnabled={notifications.length > 0} + snapToOffsets={[ + 0, + ...Array(notifications.length) + .fill(0) + .map( + (n: number, i: number) => + i * (width - 2 * (offset - offsetPadding)), + ) + .slice(1), + ]} + decelerationRate="fast" + ListEmptyComponent={emptyListComponent()} + data={notifications} + keyExtractor={item => item.id} + renderItem={({ item, index }) => ( + <View + style={{ + width: width - 3.5 * offset, + marginLeft: !index ? offset : offsetPadding, + marginRight: + index === notifications.length - 1 ? offset : offsetPadding, + }} + > + {item.type === 'CredentialRecord' ? ( + <NotificationListItem + key={item.id} + notificationType={NotificationType.CredentialOffer} + notification={item} + /> + ) : ( + <NotificationListItem + key={item.id} + notificationType={NotificationType.ProofRequest} + notification={item} + /> + )} + </View> + )} + /> + <View style={styles.container}>{displayMessage(credentials.length)}</View> + </View> + ); +}; + +export default Home; + +const offset = 25; +const offsetPadding = 5; + +const styles = StyleSheet.create({ + container: { + paddingHorizontal: offset, + }, + rowContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: offset, + }, + messageContainer: { + alignItems: 'center', + justifyContent: 'center', + marginTop: 35, + marginHorizontal: 60, + }, + header: { + marginTop: offset, + marginBottom: 20, + }, + linkContainer: { + minHeight: TextTheme.normal.fontSize, + marginTop: 10, + }, + link: { + ...TextTheme.normal, + color: ColorPallet.brand.link, + }, +}); diff --git a/src/screens/Home/__tests__/Home.test.tsx b/src/screens/Home/__tests__/Home.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f459832645dfc2bb1bb571fb2a1c4b8e50e449a3 --- /dev/null +++ b/src/screens/Home/__tests__/Home.test.tsx @@ -0,0 +1,44 @@ +import { useNavigation } from '@react-navigation/core'; +import { render, waitFor } from '@testing-library/react-native'; +import React from 'react'; +import { FlatList } from 'react-native'; +import { create } from 'react-test-renderer'; +import { NotificationListItem } from '../../../components'; +import Home from '../Home'; + +describe('displays a home screen', () => { + jest.useFakeTimers(); + it('renders correctly', () => { + const tree = create(<Home navigation={useNavigation()} />).toJSON(); + + expect(tree).toMatchSnapshot(); + }); + + /** + * Scenario: Home Screen without any pending notification + * Given wallet has successfully loaded + * When the holder selects the "Home" button in the main navigation bar + * Then the Home Screen is displayed + */ + it('defaults to no notifications', async () => { + const { findByText } = render(<Home navigation={useNavigation()} />); + const notificationLabel = await findByText('Home.NoNewUpdates'); + + expect(notificationLabel).toBeTruthy(); + }); +}); + +describe('with a notifications module, when there are no notifications', () => { + jest.useFakeTimers(); + it('notifications are empty', async () => { + const tree = create(<Home navigation={useNavigation()} />); + const { root } = tree; + const flatListInstance = root.findByType(FlatList); + + await waitFor(() => + expect(flatListInstance.findAllByType(NotificationListItem)).toHaveLength( + 0, + ), + ); + }); +}); diff --git a/src/screens/Home/__tests__/__snapshots__/Home.test.tsx.snap b/src/screens/Home/__tests__/__snapshots__/Home.test.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..4fe73ae2c539579645bfc2bf2ea2acb99f525ac2 --- /dev/null +++ b/src/screens/Home/__tests__/__snapshots__/Home.test.tsx.snap @@ -0,0 +1,220 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`displays a home screen renders correctly 1`] = ` +<View> + <View + style={ + Object { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "space-between", + "paddingHorizontal": 25, + } + } + > + <Text + style={ + Array [ + Object { + "color": "#000000", + "fontFamily": "TitilliumWeb-SemiBold", + "fontSize": 21, + "fontWeight": "bold", + }, + Object { + "marginBottom": 20, + "marginTop": 25, + }, + ] + } + > + Home.Notifications + + </Text> + </View> + <RCTScrollView + ListEmptyComponent={ + <View + style={ + Object { + "marginHorizontal": 25, + "width": 700, + } + } + > + <InfoTextBox + showIcon={true} + > + <Text + style={ + Object { + "color": "#000000", + "fontFamily": "TitilliumWeb-Regular", + "fontSize": 17, + "fontWeight": "normal", + } + } + > + Home.NoNewUpdates + </Text> + </InfoTextBox> + </View> + } + data={Array []} + decelerationRate="fast" + getItem={[Function]} + getItemCount={[Function]} + horizontal={true} + keyExtractor={[Function]} + onContentSizeChange={[Function]} + onLayout={[Function]} + onMomentumScrollBegin={[Function]} + onMomentumScrollEnd={[Function]} + onScroll={[Function]} + onScrollBeginDrag={[Function]} + onScrollEndDrag={[Function]} + removeClippedSubviews={false} + renderItem={[Function]} + scrollEnabled={false} + scrollEventThrottle={50} + showsHorizontalScrollIndicator={false} + snapToOffsets={ + Array [ + 0, + ] + } + stickyHeaderIndices={Array []} + viewabilityConfigCallbackPairs={Array []} + > + <View> + <View + onLayout={[Function]} + style={ + Object { + "marginHorizontal": 25, + "width": 700, + } + } + > + <View + style={ + Object { + "backgroundColor": "#F2F2F2", + "borderRadius": 5, + "flexDirection": "row", + "padding": 10, + } + } + > + <View + style={ + Object { + "alignSelf": "center", + "marginRight": 10, + } + } + > + <Image + source={ + Object { + "testUri": "../../../src/assets/info-icon.png", + } + } + style={ + Object { + "height": 30, + "width": 30, + } + } + /> + </View> + <Text + accessibilityLabel="InfoTextBox" + style={ + Object { + "alignSelf": "center", + "color": "#000000", + "flexShrink": 1, + "fontFamily": "TitilliumWeb-Regular", + "fontSize": 17, + "fontWeight": "normal", + } + } + testID="InfoTextBox" + > + <Text + style={ + Object { + "color": "#000000", + "fontFamily": "TitilliumWeb-Regular", + "fontSize": 17, + "fontWeight": "normal", + } + } + > + Home.NoNewUpdates + </Text> + </Text> + </View> + </View> + </View> + </RCTScrollView> + <View + style={ + Object { + "paddingHorizontal": 25, + } + } + > + <View + style={ + Array [ + Object { + "alignItems": "center", + "justifyContent": "center", + "marginHorizontal": 60, + "marginTop": 35, + }, + ] + } + > + <Text + style={ + Array [ + Object { + "color": "#000000", + "fontFamily": "TitilliumWeb-SemiBold", + "fontSize": 32, + "fontWeight": "bold", + }, + Object { + "marginBottom": 35, + "marginTop": 25, + }, + ] + } + > + Home.Welcome + </Text> + <Text + style={ + Array [ + Object { + "color": "#000000", + "fontFamily": "TitilliumWeb-Regular", + "fontSize": 17, + "fontWeight": "normal", + }, + Object { + "marginTop": 25, + "textAlign": "center", + }, + ] + } + > + Home.NoCredentials + </Text> + </View> + </View> +</View> +`; diff --git a/src/screens/Home/index.ts b/src/screens/Home/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..fbe3fed6bf5f1d95f9d628cd99aa7137f2dfbfb3 --- /dev/null +++ b/src/screens/Home/index.ts @@ -0,0 +1,3 @@ +import Home from './Home'; + +export default Home; diff --git a/src/screens/ImportWallet/ImportWallet.ios.tsx b/src/screens/ImportWallet/ImportWallet.ios.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e8cb747861f6795fba1f2d5eb8b5e25a1053125f --- /dev/null +++ b/src/screens/ImportWallet/ImportWallet.ios.tsx @@ -0,0 +1,234 @@ +import React, { useState } from 'react'; +import { View, StyleSheet, Keyboard } from 'react-native'; +import DocumentPicker from 'react-native-document-picker'; +import Toast from 'react-native-toast-message'; +// @ts-ignore +import argon2 from 'react-native-argon2'; +import { + WalletExportImportConfig, + WalletConfig, +} from '@aries-framework/core/build/types'; +import { agentDependencies } from '@aries-framework/react-native'; +import Config from 'react-native-config'; +import { + Agent, + AutoAcceptCredential, + AutoAcceptProof, + ConsoleLogger, + HttpOutboundTransport, + LogLevel, + MediatorPickupStrategy, + WsOutboundTransport, +} from '@aries-framework/core'; +import { StackScreenProps } from '@react-navigation/stack'; +import AsyncStorage from '@react-native-async-storage/async-storage'; +import RNFS from 'react-native-fs'; +import { useTranslation } from 'react-i18next'; +import { UserCredentials } from 'react-native-keychain'; +import Button, { ButtonType } from '../../components/button/Button'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { TextInput, Loader, Text } from '../../components'; +import { getValueKeychain } from '../../utils/keychain'; +import { ToastType } from '../../components/toast/BaseToast'; +import { KeychainStorageKeys, LocalStorageKeys, salt } from '../../constants'; +import indyLedgers from '../../../configs/ledgers/indy'; +import { OnboardingStackParams, Screens } from '../../types/navigators'; +import { createMD5HashFromString } from './ImportWallet.utils'; +import { saveValueInKeychain } from '../../utils/generic'; + +type ImportWalletProps = StackScreenProps< + OnboardingStackParams, + Screens.ImportWallet +>; + +const ImportWallet: React.FC<ImportWalletProps> = ({ route }) => { + const { t } = useTranslation(); + const { setAgent, setAuthenticated, setActive } = route.params; + const [mnemonic, setMnemonic] = useState(''); + const [walletBackupFilePath, setWalletBackupFilePath] = useState(''); + const [loading, setLoading] = useState(false); + + const storeOnboardingCompleteStage = async () => { + await AsyncStorage.setItem( + LocalStorageKeys.OnboardingCompleteStage, + 'true', + ); + }; + + const pickBackupFile = async () => { + try { + const res = await DocumentPicker.pickSingle({ + type: [DocumentPicker.types.allFiles], + copyTo: 'documentDirectory', + }); + + RNFS.stat(res.uri) + .then(stats => { + // https://github.com/react-native-image-picker/react-native-image-picker/issues/107#issuecomment-443420588 + setWalletBackupFilePath(stats.path.replace('file://', '')); + }) + .catch(err => { + Toast.show({ + type: ToastType.Error, + text1: t<string>('Toasts.Warning'), + text2: t<string>(err), + }); + }); + } catch (err: any) { + if (DocumentPicker.isCancel(err)) { + Toast.show({ + type: ToastType.Error, + text1: t<string>('Toasts.Warning'), + text2: t<string>(err), + }); + // User cancelled the picker, exit any dialogs or menus and move on + } else { + Toast.show({ + type: ToastType.Error, + text1: t<string>('Toasts.Warning'), + text2: t<string>(err), + }); + } + } + }; + + const importWallet = async () => { + if (mnemonic.length === 0) { + Toast.show({ + type: ToastType.Warn, + text1: t<string>('Toasts.Warning'), + text2: t<string>('ImportWallet.EmptyMnemonic'), + }); + } else { + setLoading(true); + const guidEntry = (await getValueKeychain({ + service: KeychainStorageKeys.GUID, + })) as UserCredentials; + const keychainEntry = (await getValueKeychain({ + service: KeychainStorageKeys.Passcode, + })) as UserCredentials; + + const result = await argon2(mnemonic, salt, { + iterations: 5, + memory: 16 * 1024, + parallelism: 2, + hashLength: 20, + mode: 'argon2i', + }); + + const { encodedHash } = result; + + const importConfig: WalletExportImportConfig = { + key: encodedHash, + path: walletBackupFilePath, + }; + + const walletConfig: WalletConfig = { + id: guidEntry.password, + key: keychainEntry.password, + }; + + const rawValue = guidEntry.password + mnemonic.replace(/ /g, ''); + const seedHash = createMD5HashFromString(rawValue); + + const newAgent = new Agent( + { + label: guidEntry.password, // added guid as label + mediatorConnectionsInvite: Config.MEDIATOR_URL, + walletConfig, + mediatorPickupStrategy: MediatorPickupStrategy.Implicit, + autoAcceptConnections: true, + autoAcceptCredentials: AutoAcceptCredential.ContentApproved, + autoAcceptProofs: AutoAcceptProof.ContentApproved, + logger: new ConsoleLogger(LogLevel.trace), + publicDidSeed: seedHash, + autoUpdateStorageOnStartup: true, + indyLedgers, + }, + agentDependencies, + ); + + const wsTransport = new WsOutboundTransport(); + const httpTransport = new HttpOutboundTransport(); + + newAgent.registerOutboundTransport(wsTransport); + newAgent.registerOutboundTransport(httpTransport); + + try { + await newAgent?.wallet.import(walletConfig, importConfig); + await newAgent.wallet.initialize(walletConfig); + await newAgent.initialize(); + await storeOnboardingCompleteStage(); + setAgent(newAgent); + await saveValueInKeychain( + KeychainStorageKeys.Passphrase, + mnemonic, + t<string>('Registration.MnemonicMsg'), + ); + setAuthenticated(true); + setActive(true); + setLoading(false); + } catch (e) { + setLoading(false); + Toast.show({ + type: ToastType.Error, + text1: t<string>('Toasts.Warning'), + text2: t<string>('ImportWallet.ImportError'), + }); + } + } + }; + + return ( + <View style={styles.container}> + <Loader loading={loading} /> + <View style={styles.btnContainer}> + <Button + title={t<string>('ImportWallet.SelectWalletFile')} + buttonType={ButtonType.Primary} + onPress={() => { + Keyboard.dismiss(); + pickBackupFile(); + }} + /> + </View> + <Text style={styles.label}>{walletBackupFilePath}</Text> + <TextInput + label={t<string>('Settings.EnterMnemonic')} + placeholder={t<string>('Settings.EnterMnemonic')} + placeholderTextColor={ColorPallet.brand.primary} + accessible + accessibilityLabel={t<string>('Settings.EnterMnemonic')} + autoFocus + value={mnemonic} + onChangeText={setMnemonic} + autoCapitalize="none" + returnKeyType="done" + /> + <View style={styles.btnContainer}> + <Button + title={t<string>('Global.ImportWallet')} + buttonType={ButtonType.Primary} + disabled={walletBackupFilePath.length === 0 && mnemonic.length === 0} + onPress={importWallet} + /> + </View> + </View> + ); +}; + +export default ImportWallet; + +const styles = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + }, + label: { + ...TextTheme.normal, + fontWeight: 'bold', + }, + btnContainer: { + marginTop: 20, + }, +}); diff --git a/src/screens/ImportWallet/ImportWallet.tsx b/src/screens/ImportWallet/ImportWallet.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0a0c71a8020f37eff6d4b4d7ae73bc55005b0a34 --- /dev/null +++ b/src/screens/ImportWallet/ImportWallet.tsx @@ -0,0 +1,274 @@ +import { t } from 'i18next'; +import React, { useState, useEffect } from 'react'; +import { + View, + StyleSheet, + Keyboard, + PermissionsAndroid, + BackHandler, +} from 'react-native'; +import RNFetchBlob from 'rn-fetch-blob'; +import DocumentPicker from 'react-native-document-picker'; +import Toast from 'react-native-toast-message'; +import argon2 from 'react-native-argon2'; +import { + WalletExportImportConfig, + WalletConfig, +} from '@aries-framework/core/build/types'; +import { UserCredentials } from 'react-native-keychain'; +import { agentDependencies } from '@aries-framework/react-native'; +import Config from 'react-native-config'; +import { + Agent, + AutoAcceptCredential, + AutoAcceptProof, + ConsoleLogger, + HttpOutboundTransport, + LogLevel, + MediatorPickupStrategy, + WsOutboundTransport, +} from '@aries-framework/core'; +import { StackScreenProps } from '@react-navigation/stack'; +import AsyncStorage from '@react-native-async-storage/async-storage'; +import Button, { ButtonType } from '../../components/button/Button'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { TextInput, Loader, Text } from '../../components'; +import { getValueKeychain } from '../../utils/keychain'; +import { ToastType } from '../../components/toast/BaseToast'; +import { KeychainStorageKeys, LocalStorageKeys, salt } from '../../constants'; +import indyLedgers from '../../../configs/ledgers/indy'; +import { OnboardingStackParams, Screens } from '../../types/navigators'; +import { createMD5HashFromString } from './ImportWallet.utils'; +import { saveValueInKeychain } from '../../utils/generic'; + +type ImportWalletProps = StackScreenProps< + OnboardingStackParams, + Screens.ImportWallet +>; + +const ImportWallet: React.FC<ImportWalletProps> = ({ navigation, route }) => { + const { setAgent, setAuthenticated, setActive } = route.params; + const [mnemonic, setMnemonic] = useState(''); + const [walletBackupFilePath, setwalletBackupFIlePath] = useState(''); + const [loading, setLoading] = useState(false); + + const storeOnboardingCompleteStage = async () => { + await AsyncStorage.setItem( + LocalStorageKeys.OnboardingCompleteStage, + 'true', + ); + }; + + useEffect(() => { + const handleBackButtonClick = () => { + navigation.goBack(); + return true; + }; + BackHandler.addEventListener('hardwareBackPress', handleBackButtonClick); + return () => { + BackHandler.removeEventListener( + 'hardwareBackPress', + handleBackButtonClick, + ); + }; + }, [navigation]); + + const askPermission = async () => { + PermissionsAndroid.requestMultiple([ + PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE, + PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, + ]) + .then(result => { + if ( + result['android.permission.READ_EXTERNAL_STORAGE'] && + result['android.permission.WRITE_EXTERNAL_STORAGE'] === 'granted' + ) { + pickBackupFile(); + } + }) + .catch(error => { + Toast.show({ + type: ToastType.Error, + text1: t<string>('Toasts.Warning'), + text2: t<string>(error), + }); + }); + }; + + const pickBackupFile = async () => { + try { + const res = await DocumentPicker.pickSingle({ + type: [DocumentPicker.types.allFiles], + copyTo: 'documentDirectory', + }); + // const exportedFileContent = await RNFS.readFile(res.uri, 'base64') + RNFetchBlob.fs + .stat(res.fileCopyUri) + .then(stats => { + setwalletBackupFIlePath(stats.path); + // output: /storage/emulated/0/WhatsApp/Media/WhatsApp Images/IMG-20200831-WA0019.jpg + }) + .catch((err: any) => { + Toast.show({ + type: ToastType.Error, + text1: t<string>('Toasts.Warning'), + text2: t<string>(err), + }); + }); + } catch (err: any) { + if (DocumentPicker.isCancel(err)) { + Toast.show({ + type: ToastType.Error, + text1: t<string>('Toasts.Warning'), + text2: t<string>(err), + }); + // User cancelled the picker, exit any dialogs or menus and move on + } else { + Toast.show({ + type: ToastType.Error, + text1: t<string>('Toasts.Warning'), + text2: t<string>(err), + }); + } + } + }; + const importWallet = async () => { + if (mnemonic.length === 0) { + Toast.show({ + type: ToastType.Warn, + text1: t<string>('Toasts.Warning'), + text2: t<string>('ImportWallet.EmptyMnemonic'), + }); + } else { + setLoading(true); + const guidEntry = (await getValueKeychain({ + service: KeychainStorageKeys.GUID, + })) as UserCredentials; + const keychainEntry = (await getValueKeychain({ + service: KeychainStorageKeys.Passcode, + })) as UserCredentials; + + const result = await argon2(mnemonic, salt, { + iterations: 5, + memory: 16 * 1024, + parallelism: 2, + hashLength: 20, + mode: 'argon2i', + }); + + const { encodedHash } = result; + + const importConfig: WalletExportImportConfig = { + key: encodedHash, + path: walletBackupFilePath, + }; + + const walletConfig: WalletConfig = { + id: guidEntry.password, + key: keychainEntry.password, + }; + + const rawValue = guidEntry.password + mnemonic.replace(/ /g, ''); + const seedHash = createMD5HashFromString(rawValue); + + const newAgent = new Agent( + { + label: guidEntry.password, // added guid as label + mediatorConnectionsInvite: Config.MEDIATOR_URL, + walletConfig, + mediatorPickupStrategy: MediatorPickupStrategy.Implicit, + autoAcceptConnections: true, + autoAcceptCredentials: AutoAcceptCredential.ContentApproved, + autoAcceptProofs: AutoAcceptProof.ContentApproved, + logger: new ConsoleLogger(LogLevel.trace), + publicDidSeed: seedHash, + autoUpdateStorageOnStartup: true, + indyLedgers, + }, + agentDependencies, + ); + + const wsTransport = new WsOutboundTransport(); + const httpTransport = new HttpOutboundTransport(); + + newAgent.registerOutboundTransport(wsTransport); + newAgent.registerOutboundTransport(httpTransport); + + try { + await newAgent.wallet.import(walletConfig, importConfig); + await newAgent.wallet.initialize(walletConfig); + await newAgent.initialize(); + await storeOnboardingCompleteStage(); + setAgent(newAgent); + await saveValueInKeychain( + KeychainStorageKeys.Passphrase, + mnemonic, + t<string>('Registration.MnemonicMsg'), + ); + setAuthenticated(true); + setActive(true); + setLoading(false); + } catch (e) { + setLoading(false); + Toast.show({ + type: ToastType.Error, + text1: t<string>('Toasts.Warning'), + text2: t<string>('ImportWallet.ImportError'), + }); + } + } + }; + + return ( + <View style={styles.container}> + <Loader loading={loading} /> + <View style={styles.btnContainer}> + <Button + title={t<string>('ImportWallet.SelectWalletFile')} + buttonType={ButtonType.Primary} + onPress={() => { + Keyboard.dismiss(); + askPermission(); + }} + /> + </View> + <Text style={styles.label}>{walletBackupFilePath}</Text> + <TextInput + label={t<string>('Settings.EnterMnemonic')} + placeholder={t<string>('Settings.EnterMnemonic')} + placeholderTextColor={ColorPallet.brand.primary} + accessible + accessibilityLabel={t<string>('Settings.EnterMnemonic')} + autoFocus + value={mnemonic} + onChangeText={setMnemonic} + autoCapitalize="none" + returnKeyType="done" + /> + <View style={styles.btnContainer}> + <Button + title={t<string>('Global.ImportWallet')} + buttonType={ButtonType.Primary} + disabled={walletBackupFilePath.length === 0 && mnemonic.length === 0} + onPress={importWallet} + /> + </View> + </View> + ); +}; + +export default ImportWallet; + +const styles = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + }, + label: { + ...TextTheme.normal, + fontWeight: 'bold', + }, + btnContainer: { + marginTop: 20, + }, +}); diff --git a/src/screens/ImportWallet/ImportWallet.utils.test.ts b/src/screens/ImportWallet/ImportWallet.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..49f08d3e9df43fb4a713cbac366854058950e1d2 --- /dev/null +++ b/src/screens/ImportWallet/ImportWallet.utils.test.ts @@ -0,0 +1,29 @@ +import * as Utils from './ImportWallet.utils'; + +describe('ImportWallet.utils', () => { + describe('storeOnboardingCompleteStage', () => { + it('should store a value for onboarding complete stage', async () => { + jest.spyOn(Utils, 'storeOnboardingCompleteStage'); + + await Utils.storeOnboardingCompleteStage(); + + expect(Utils.storeOnboardingCompleteStage).toHaveBeenCalled(); + }); + }); + + describe('createMD5HashFromString', () => { + it.each([ + ['kevin@gmail.com1234566', '31a8cc6fdfd91bd25e777cd928cca890'], + [ + 'kevin.durant@gmail.comThisisateststring', + '01b8b1108447e196002c12f27c2388b6', + ], + ])( + 'should return a hash value for the given string', + (initialValue, expectedValue) => { + const result = Utils.createMD5HashFromString(initialValue); + expect(result).toEqual(expectedValue); + }, + ); + }); +}); diff --git a/src/screens/ImportWallet/ImportWallet.utils.ts b/src/screens/ImportWallet/ImportWallet.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..0d4d8f0c343f6ff60d08fe03bc54726089bd49be --- /dev/null +++ b/src/screens/ImportWallet/ImportWallet.utils.ts @@ -0,0 +1,12 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import md5 from 'md5'; +import { LocalStorageKeys } from '../../constants'; + +export const storeOnboardingCompleteStage = async () => { + await AsyncStorage.setItem(LocalStorageKeys.OnboardingCompleteStage, 'true'); +}; + +export const createMD5HashFromString = (value: string) => { + const hash = String(md5(value)); + return hash; +}; diff --git a/src/screens/ImportWallet/index.ts b/src/screens/ImportWallet/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..b93942eae669a0f78d58de933c90df450a83076b --- /dev/null +++ b/src/screens/ImportWallet/index.ts @@ -0,0 +1,3 @@ +import ImportWallet from './ImportWallet'; + +export default ImportWallet; diff --git a/src/screens/Initialization/Initialization.tsx b/src/screens/Initialization/Initialization.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2b08ea6a25cad06b5493bb60457fd31d246a9e5e --- /dev/null +++ b/src/screens/Initialization/Initialization.tsx @@ -0,0 +1,115 @@ +import { StackScreenProps } from '@react-navigation/stack'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { Image, Text, View, StyleSheet } from 'react-native'; +import Images from '../../assets'; +import { IconButton, InfoCard } from '../../components'; +import Button, { ButtonType } from '../../components/button/Button'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { OnboardingStackParams, Screens } from '../../types/navigators'; + +type InitializationProps = StackScreenProps< + OnboardingStackParams, + Screens.Initialization +>; + +const Initialization: React.FC<InitializationProps> = ({ navigation }) => { + const { t } = useTranslation(); + const onSubmit = async () => { + navigation.navigate(Screens.CreateWallet); + }; + + const onImportWallet = () => { + navigation.navigate(Screens.ImportWallet); + }; + + const onBack = () => { + navigation.goBack(); + }; + return ( + <View style={[style.container]} testID="Initialization-id"> + <View style={[style.textContainer]}> + <Text style={TextTheme.normal}> + {t<string>('Initialization.CompleteInitialization')} + </Text> + </View> + <View style={[style.flexColumnContainer]}> + <View style={[style.flexRowContainer]}> + <View style={[style.imgContainer]}> + <Image source={Images.importIcon} style={style.pinImg} /> + </View> + <View style={[style.btnContainer]}> + <Button + title="Import Wallet" + buttonType={ButtonType.Primary} + onPress={onImportWallet} + /> + </View> + </View> + <View style={[style.flexRowContainer]}> + <View style={[style.imgContainer]}> + <Image source={Images.initializeIcon} style={style.pinImg} /> + </View> + <View style={[style.btnContainer]}> + <Button + title="Initialization" + buttonType={ButtonType.Primary} + onPress={onSubmit} + /> + </View> + </View> + </View> + <View style={style.info}> + <InfoCard showBottomIcon={false} showTopIcon> + {t<string>('Initialization.InitializationInfo')} + </InfoCard> + </View> + <IconButton isRight={false} isDisabled={false} onPress={onBack} /> + </View> + ); +}; + +export default Initialization; + +const style = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + justifyContent: 'space-between', + flex: 1, + }, + btnContainer: { + flex: 0.8, + }, + info: { + marginTop: 20, + }, + label: { + ...TextTheme.label, + fontWeight: 'bold', + textAlign: 'center', + }, + pinImg: { + height: 40, + width: 50, + padding: 5, + marginRight: 10, + alignSelf: 'flex-end', + }, + textContainer: { + flex: 0.1, + alignItems: 'center', + }, + flexColumnContainer: { + flexDirection: 'column', + flex: 0.5, + }, + flexRowContainer: { + flex: 1, + flexDirection: 'row', + margin: 20, + }, + imgContainer: { + flex: 0.2, + }, +}); diff --git a/src/screens/Initialization/__tests__/initialization.test.tsx b/src/screens/Initialization/__tests__/initialization.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..3efc940208109297357020b74f9c6e213caba036 --- /dev/null +++ b/src/screens/Initialization/__tests__/initialization.test.tsx @@ -0,0 +1,11 @@ +import { render } from '@testing-library/react-native'; +import React from 'react'; +import Initialization from '../initialization'; + +describe('Initialization', () => { + it('should render correctly and respond when pressed', () => { + const { getByTestId } = render( + <Initialization navigation={undefined} route={undefined} />, + ); + }); +}); diff --git a/src/screens/Initialization/index.ts b/src/screens/Initialization/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..23d908fc450b6c75d6e78f49ce2de9ac396d338e --- /dev/null +++ b/src/screens/Initialization/index.ts @@ -0,0 +1,3 @@ +import Initialization from './Initialization'; + +export default Initialization; diff --git a/src/screens/Language/Language.tsx b/src/screens/Language/Language.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c58c3358f4cc7b54d2cb5b3f30cd07aab2ac20d1 --- /dev/null +++ b/src/screens/Language/Language.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { SafeAreaScrollView, SingleSelectBlock } from '../../components'; +import { BlockSelection } from '../../components/inputs/SingleSelectBlock'; + +import { Locales, storeLanguage } from '../../localization'; + +const Language = () => { + const { t, i18n } = useTranslation(); + + // List of available languages into the localization directory + const languages = [ + { id: Locales.en, value: t<string>('Language.English') }, + { id: Locales.fr, value: t<string>('Language.French') }, + { id: Locales.de, value: t<string>('Language.German') }, + ]; + + /** + * Find current set language + */ + const storedLanguage = languages.find(l => l.id === i18n.language); + + /** + * Once user select the particular language from the list, + * store user preference into the AsyncStorage + * + * @param {BlockSelection} language + */ + const handleLanguageChange = async (language: BlockSelection) => { + i18n.changeLanguage(language.id as Locales); + await storeLanguage(language.id); + }; + + return ( + <SafeAreaScrollView> + <SingleSelectBlock + initialSelect={storedLanguage} + selection={languages} + onSelect={handleLanguageChange} + /> + </SafeAreaScrollView> + ); +}; + +export default Language; diff --git a/src/screens/Language/__tests__/Language.test.tsx b/src/screens/Language/__tests__/Language.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..777351ede42f888dbbb2127bf76d7f3e7b5a8539 --- /dev/null +++ b/src/screens/Language/__tests__/Language.test.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { create } from 'react-test-renderer'; +import Language from '../Language'; + +jest.mock('react-native-localize', () => ({ + findBestAvailableLanguage: () => ({ + languageTag: 'en-US', + isRTL: false, + }), +})); + +jest.mock('i18next', () => ({ + use: () => { + return { + init: jest.fn(), + }; + }, + init: jest.fn(), + t: k => k, + language: 'en', +})); + +jest.mock('react-i18next', () => ({ + // this mock makes sure any components using the translate hook can use it without a warning being shown + useTranslation: () => { + return { + t: str => str, + i18n: { + language: 'en', + changeLanguage: () => new Promise(jest.fn()), + }, + }; + }, +})); + +describe('Language', () => { + it('should render correctly', () => { + const tree = create(<Language />); + + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/screens/Language/__tests__/__snapshots__/Language.test.tsx.snap b/src/screens/Language/__tests__/__snapshots__/Language.test.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..d22e4860f622319a2395ef118f6d6d268984a6cc --- /dev/null +++ b/src/screens/Language/__tests__/__snapshots__/Language.test.tsx.snap @@ -0,0 +1,166 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Language should render correctly 1`] = ` +<RCTScrollView + contentContainerStyle={ + Object { + "alignItems": "center", + } + } + testID="safeareaview" +> + <View> + <View + style={ + Object { + "padding": 20, + "width": "100%", + } + } + testID="SingleSelectBlock" + > + <View + accessible={true} + collapsable={false} + focusable={true} + nativeID="animatedComponent" + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "alignItems": "center", + "backgroundColor": "#CCE8F4", + "borderRadius": 8, + "flexDirection": "row", + "justifyContent": "space-between", + "marginBottom": 8, + "opacity": 1, + "padding": 12, + } + } + > + <Text + accessibilityLabel="Text" + style={ + Array [ + Object { + "color": "#000094", + }, + undefined, + ] + } + testID="Text" + > + Language.English + </Text> + <Text + allowFontScaling={false} + selectable={false} + style={ + Array [ + Object { + "color": "#000094", + "fontSize": 25, + }, + undefined, + Object { + "fontFamily": "Material Icons", + "fontStyle": "normal", + "fontWeight": "normal", + }, + Object {}, + ] + } + > + + </Text> + </View> + <View + accessible={true} + collapsable={false} + focusable={true} + nativeID="animatedComponent" + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "alignItems": "center", + "backgroundColor": "#CCE8F4", + "borderRadius": 8, + "flexDirection": "row", + "justifyContent": "space-between", + "marginBottom": 8, + "opacity": 1, + "padding": 12, + } + } + > + <Text + accessibilityLabel="Text" + style={ + Array [ + Object { + "color": "#000094", + }, + undefined, + ] + } + testID="Text" + > + Language.French + </Text> + </View> + <View + accessible={true} + collapsable={false} + focusable={true} + nativeID="animatedComponent" + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "alignItems": "center", + "backgroundColor": "#CCE8F4", + "borderRadius": 8, + "flexDirection": "row", + "justifyContent": "space-between", + "marginBottom": 8, + "opacity": 1, + "padding": 12, + } + } + > + <Text + accessibilityLabel="Text" + style={ + Array [ + Object { + "color": "#000094", + }, + undefined, + ] + } + testID="Text" + > + Language.German + </Text> + </View> + </View> + </View> +</RCTScrollView> +`; diff --git a/src/screens/Language/index.ts b/src/screens/Language/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..e6e1d4e09f1dc942d6960fc80f9f63cb957ce2bf --- /dev/null +++ b/src/screens/Language/index.ts @@ -0,0 +1,3 @@ +import Language from './Language'; + +export default Language; diff --git a/src/screens/ListContacts/ListContacts.tsx b/src/screens/ListContacts/ListContacts.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0db1bf1b50cf85b8554d5c02ffb61aad741ed022 --- /dev/null +++ b/src/screens/ListContacts/ListContacts.tsx @@ -0,0 +1,75 @@ +import { ConnectionRecord } from '@aries-framework/core'; +import { useAgent, useConnections } from '@aries-framework/react-hooks'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { FlatList, StyleSheet, View } from 'react-native'; +import { useIsFocused } from '@react-navigation/core'; +import SearchBar from '../../components/inputs/SearchBar'; +import { ContactListItem, Text } from '../../components'; +import { ColorPallet } from '../../theme/theme'; +import { searchConnectionList } from './ListContacts.utils'; + +const ListContacts: React.FC = () => { + const { connections } = useConnections(); + const { agent } = useAgent(); + const { t } = useTranslation(); + const [searchText, setSearchText] = useState(''); + const [connectionList, setConnectionList] = useState<ConnectionRecord[]>([]); + + const isFocused = useIsFocused(); + + const [clicked, setClicked] = useState(false); + + const fetchConnectionRecords = useCallback(async () => { + const records = await agent?.connections.getAll(); + if (records) { + setConnectionList(records); + } + }, [agent?.connections]); + + useEffect(() => { + if (isFocused) { + fetchConnectionRecords(); + } + }, [fetchConnectionRecords, isFocused, connections]); + + const search = (text: string) => { + const filteredData = searchConnectionList(connections, text); + setConnectionList(filteredData); + setSearchText(text); + }; + + return ( + <View style={styles.container}> + <SearchBar + searchPhrase={searchText} + setSearchPhrase={setSearchText => search(setSearchText)} + clicked={clicked} + setClicked={setClicked} + /> + <FlatList + data={connectionList} + renderItem={({ item }) => ( + <ContactListItem key={item.id} contact={item} /> + )} + keyExtractor={(item: ConnectionRecord) => item.id} + style={{ backgroundColor: ColorPallet.grayscale.white }} + contentContainerStyle={{ paddingBottom: 65 }} + ListEmptyComponent={ + <Text style={{ textAlign: 'center', margin: 100 }}> + {t<string>('Global.ZeroRecords')} + </Text> + } + /> + </View> + ); +}; + +export default ListContacts; + +const styles = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + }, +}); diff --git a/src/screens/ListContacts/ListContacts.utils.ts b/src/screens/ListContacts/ListContacts.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..1382b687839e38b38fbfead092457d0f575f187e --- /dev/null +++ b/src/screens/ListContacts/ListContacts.utils.ts @@ -0,0 +1,19 @@ +import { ConnectionRecord } from '@aries-framework/core'; + +export const searchConnectionList = ( + connectionsList: ConnectionRecord[], + searchText: string, +) => { + const filteredData = connectionsList.filter(item => { + if (!item.theirLabel) { + return false; + } + + const label = item.theirLabel.toUpperCase(); + const text = searchText.toUpperCase(); + return label.includes(text); + }); + return filteredData; +}; + +export default searchConnectionList; diff --git a/src/screens/ListContacts/__tests__/ListContacts.constants.ts b/src/screens/ListContacts/__tests__/ListContacts.constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..6b6c0c5811c1ce488ffc2b93dc983e67f74b06cc --- /dev/null +++ b/src/screens/ListContacts/__tests__/ListContacts.constants.ts @@ -0,0 +1,366 @@ +import { ConnectionRecord } from '@aries-framework/core'; + +const MOCK_CONNECTION_LIST: ConnectionRecord[] = [ + { + _tags: { + did: 'SL2dA5wcdY8NEhkKwYeVNb', + verkey: 'EofsWGeCGAdb3k5gepePiHvPXJkm59dQUwogP3FHHTZp', + state: 'complete', + role: 'invitee', + theirDid: 'XBudZhfzGFFfcEuGyREGQy', + invitationKey: '6PtQuy9St6hD2zJWnfxnN6aBnK3vfY7WU7WhhoZGAaz5', + mediatorId: '68bbc5d0-7b1b-4b35-9c40-fd72ccd67f8e', + theirKey: 'HTJdr7YPxKBb4AiapjwLG5asepcVyPJZPdcmixGqP8V3', + threadId: '03d19628-e119-4763-9f38-0790545922c9', + }, + metadata: {}, + id: '34da4abe-7578-464f-909c-ee19a3bdf7ac', + createdAt: '2022-04-29T06:36:48.244Z', + did: 'SL2dA5wcdY8NEhkKwYeVNb', + didDoc: { + '@context': 'https://w3id.org/did/v1', + publicKey: [ + { + id: 'SL2dA5wcdY8NEhkKwYeVNb#1', + controller: 'SL2dA5wcdY8NEhkKwYeVNb', + type: 'Ed25519VerificationKey2018', + publicKeyBase58: 'EofsWGeCGAdb3k5gepePiHvPXJkm59dQUwogP3FHHTZp', + }, + ], + service: [ + { + id: 'SL2dA5wcdY8NEhkKwYeVNb#IndyAgentService', + serviceEndpoint: 'http://mediator3.test.indiciotech.io:3000', + type: 'IndyAgent', + priority: 0, + recipientKeys: ['EofsWGeCGAdb3k5gepePiHvPXJkm59dQUwogP3FHHTZp'], + routingKeys: ['DGYY31KpABLT4ydNHw11rRneEL8a41X4s6xqre2cAEbn'], + }, + ], + authentication: [ + { + publicKey: 'SL2dA5wcdY8NEhkKwYeVNb#1', + type: 'Ed25519SignatureAuthentication2018', + }, + ], + id: 'SL2dA5wcdY8NEhkKwYeVNb', + }, + verkey: 'EofsWGeCGAdb3k5gepePiHvPXJkm59dQUwogP3FHHTZp', + theirLabel: 'ABC', + state: 'complete', + role: 'invitee', + invitation: { + '@type': 'https://didcomm.org/connections/1.0/invitation', + '@id': '031d7c03-51d2-488f-b53f-659bccbf03b3', + label: 'private beta', + recipientKeys: ['6PtQuy9St6hD2zJWnfxnN6aBnK3vfY7WU7WhhoZGAaz5'], + imageUrl: '', + serviceEndpoint: 'https://ws.app', + }, + imageUrl: '', + multiUseInvitation: false, + mediatorId: '68bbc5d0-7b1b-4b35-9c40-fd72ccd67f8e', + theirDid: 'XBudZhfzGFFfcEuGyREGQy', + theirDidDoc: { + '@context': 'https://w3id.org/did/v1', + publicKey: [ + { + id: 'did:sov:XBudZhfzGFFfcEuGyREGQy#1', + controller: 'did:sov:XBudZhfzGFFfcEuGyREGQy', + type: 'Ed25519VerificationKey2018', + publicKeyBase58: 'HTJdr7YPxKBb4AiapjwLG5asepcVyPJZPdcmixGqP8V3', + }, + ], + service: [ + { + id: 'did:sov:XBudZhfzGFFfcEuGyREGQy;indy', + serviceEndpoint: 'https://ws.app', + type: 'IndyAgent', + priority: 0, + recipientKeys: ['HTJdr7YPxKBb4AiapjwLG5asepcVyPJZPdcmixGqP8V3'], + }, + ], + authentication: [ + { + publicKey: 'did:sov:XBudZhfzGFFfcEuGyREGQy#1', + type: 'Ed25519SignatureAuthentication2018', + }, + ], + id: 'did:sov:XBudZhfzGFFfcEuGyREGQy', + }, + threadId: '03d19628-e119-4763-9f38-0790545922c9', + }, + { + _tags: { + verkey: 'aKrpYPFyqwmovwZahfJtT8K2Ai1Zz7ywH24uJjDNjys', + role: 'invitee', + did: '249Jvb1uAvZr7rm2tfe3qm', + invitationKey: 'E9VXJcZshiXqqLEwzGtmPJBRpm29xvbLaZnZKSSFNvA6', + state: 'complete', + threadId: '31ec4cde-832a-4d10-a581-b668c8f34ab0', + theirDid: 'JgPvbKPJKxaGPEJYHGKaYo', + theirKey: 'AdsmNZ1puUPmBoXSJD9vvpvF2UxTYpYT2vrkdViYuAFa', + }, + metadata: {}, + id: '3f2ccf46-c39c-4afb-a65a-d39879d8324b', + createdAt: '2022-04-29T06:35:20.846Z', + did: '249Jvb1uAvZr7rm2tfe3qm', + didDoc: { + '@context': 'https://w3id.org/did/v1', + publicKey: [ + { + id: '249Jvb1uAvZr7rm2tfe3qm#1', + controller: '249Jvb1uAvZr7rm2tfe3qm', + type: 'Ed25519VerificationKey2018', + publicKeyBase58: 'aKrpYPFyqwmovwZahfJtT8K2Ai1Zz7ywH24uJjDNjys', + }, + ], + service: [ + { + id: '249Jvb1uAvZr7rm2tfe3qm#IndyAgentService', + serviceEndpoint: 'didcomm:transport/queue', + type: 'IndyAgent', + priority: 0, + recipientKeys: ['aKrpYPFyqwmovwZahfJtT8K2Ai1Zz7ywH24uJjDNjys'], + routingKeys: [], + }, + ], + authentication: [ + { + publicKey: '249Jvb1uAvZr7rm2tfe3qm#1', + type: 'Ed25519SignatureAuthentication2018', + }, + ], + id: '249Jvb1uAvZr7rm2tfe3qm', + }, + verkey: 'aKrpYPFyqwmovwZahfJtT8K2Ai1Zz7ywH24uJjDNjys', + theirLabel: 'connection 2', + state: 'complete', + role: 'invitee', + invitation: { + '@type': 'https://didcomm.org/connections/1.0/invitation', + '@id': 'b19a36f7-f8bf-4286-88f9-838e22d24f41', + recipientKeys: ['E9VXJcZshiXqqLEwzGtmPJBRpm29xvbLaZnZKSSFNvA6'], + serviceEndpoint: 'http://mediator3.test.indiciotech.io:3000', + label: 'Indicio Public Mediator', + }, + multiUseInvitation: false, + theirDid: 'JgPvbKPJKxaGPEJYHGKaYo', + theirDidDoc: { + '@context': 'https://w3id.org/did/v1', + publicKey: [ + { + id: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo#1', + controller: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo', + type: 'Ed25519VerificationKey2018', + publicKeyBase58: 'AdsmNZ1puUPmBoXSJD9vvpvF2UxTYpYT2vrkdViYuAFa', + }, + ], + service: [ + { + id: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo;indy', + serviceEndpoint: 'http://mediator3.test.indiciotech.io:3000', + type: 'IndyAgent', + priority: 0, + recipientKeys: ['AdsmNZ1puUPmBoXSJD9vvpvF2UxTYpYT2vrkdViYuAFa'], + }, + { + id: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo;indy1', + serviceEndpoint: 'ws://mediator3.test.indiciotech.io:3000', + type: 'IndyAgent', + priority: 0, + recipientKeys: ['AdsmNZ1puUPmBoXSJD9vvpvF2UxTYpYT2vrkdViYuAFa'], + }, + ], + authentication: [ + { + publicKey: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo#1', + type: 'Ed25519SignatureAuthentication2018', + }, + ], + id: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo', + }, + threadId: '31ec4cde-832a-4d10-a581-b668c8f34ab0', + }, + { + _tags: { + role: 'invitee', + theirDid: '3T3jC2s4BrG64BevAhjxCE', + invitationKey: 'EaTyGxH6wEjcSmFMRNQqQaXGLMRvSav81RJpxKW92mNc', + theirKey: '2LRPR6LjqRTzh1DCX6Qd4HbSi5KTLKwuYk8wmh3jdRJF', + did: 'V6P8ZGxxwnMcyvDK7SJNzu', + verkey: 'GK4xs2HUkDvDdqKL8BdLHr2N97HFiS7xs5aw3jfetWQV', + state: 'complete', + threadId: '1c607534-88f8-4002-a52f-b0d2ddcdb8c9', + mediatorId: '68bbc5d0-7b1b-4b35-9c40-fd72ccd67f8e', + }, + metadata: {}, + id: '23d13911-4ee4-4e76-8533-afb1443e425d', + createdAt: '2022-04-29T06:37:49.618Z', + did: 'V6P8ZGxxwnMcyvDK7SJNzu', + didDoc: { + '@context': 'https://w3id.org/did/v1', + publicKey: [ + { + id: 'V6P8ZGxxwnMcyvDK7SJNzu#1', + controller: 'V6P8ZGxxwnMcyvDK7SJNzu', + type: 'Ed25519VerificationKey2018', + publicKeyBase58: 'GK4xs2HUkDvDdqKL8BdLHr2N97HFiS7xs5aw3jfetWQV', + }, + ], + service: [ + { + id: 'V6P8ZGxxwnMcyvDK7SJNzu#IndyAgentService', + serviceEndpoint: 'http://mediator3.test.indiciotech.io:3000', + type: 'IndyAgent', + priority: 0, + recipientKeys: ['GK4xs2HUkDvDdqKL8BdLHr2N97HFiS7xs5aw3jfetWQV'], + routingKeys: ['DGYY31KpABLT4ydNHw11rRneEL8a41X4s6xqre2cAEbn'], + }, + ], + authentication: [ + { + publicKey: 'V6P8ZGxxwnMcyvDK7SJNzu#1', + type: 'Ed25519SignatureAuthentication2018', + }, + ], + id: 'V6P8ZGxxwnMcyvDK7SJNzu', + }, + verkey: 'GK4xs2HUkDvDdqKL8BdLHr2N97HFiS7xs5aw3jfetWQV', + theirLabel: 'connection 3', + state: 'complete', + role: 'invitee', + invitation: { + '@type': 'https://didcomm.org/connections/1.0/invitation', + '@id': '2b83c729-3a67-44fb-a443-a65ba7a6e80e', + label: 'CANdy-Dev BPA', + recipientKeys: ['EaTyGxH6wEjcSmFMRNQqQaXGLMRvSav81RJpxKW92mNc'], + serviceEndpoint: 'http://11.111.111.11:8030', + }, + multiUseInvitation: false, + mediatorId: '68bbc5d0-7b1b-4b35-9c40-fd72ccd67f8e', + theirDid: '3T3jC2s4BrG64BevAhjxCE', + theirDidDoc: { + '@context': 'https://w3id.org/did/v1', + publicKey: [ + { + id: 'did:sov:3T3jC2s4BrG64BevAhjxCE#1', + controller: 'did:sov:3T3jC2s4BrG64BevAhjxCE', + type: 'Ed25519VerificationKey2018', + publicKeyBase58: '2LRPR6LjqRTzh1DCX6Qd4HbSi5KTLKwuYk8wmh3jdRJF', + }, + ], + service: [ + { + id: 'did:sov:3T3jC2s4BrG64BevAhjxCE;indy', + serviceEndpoint: 'http://11.11.111.11:8030', + type: 'IndyAgent', + priority: 0, + recipientKeys: ['2LRPR6LjqRTzh1DCX6Qd4HbSi5KTLKwuYk8wmh3jdRJF'], + }, + ], + authentication: [ + { + publicKey: 'did:sov:3T3jC2s4BrG64BevAhjxCE#1', + type: 'Ed25519SignatureAuthentication2018', + }, + ], + id: 'did:sov:3T3jC2s4BrG64BevAhjxCE', + }, + threadId: '1c607534-88f8-4002-a52f-b0d2ddcdb8c9', + }, + { + _tags: { + verkey: 'aKrpYPFyqwmovwZahfJtT8K2Ai1Zz7ywH24uJjDNjys', + role: 'invitee', + did: '249Jvb1uAvZr7rm2tfe3qm', + invitationKey: 'E9VXJcZshiXqqLEwzGtmPJBRpm29xvbLaZnZKSSFNvA6', + state: 'complete', + threadId: '31ec4cde-832a-4d10-a581-b668c8f34ab0', + theirDid: 'JgPvbKPJKxaGPEJYHGKaYo', + theirKey: 'AdsmNZ1puUPmBoXSJD9vvpvF2UxTYpYT2vrkdViYuAFa', + }, + metadata: {}, + id: '3f2ccf46-c39c-4afb-a65a-d39879d8324b', + createdAt: '2022-04-29T06:35:20.846Z', + did: '249Jvb1uAvZr7rm2tfe3qm', + didDoc: { + '@context': 'https://w3id.org/did/v1', + publicKey: [ + { + id: '249Jvb1uAvZr7rm2tfe3qm#1', + controller: '249Jvb1uAvZr7rm2tfe3qm', + type: 'Ed25519VerificationKey2018', + publicKeyBase58: 'aKrpYPFyqwmovwZahfJtT8K2Ai1Zz7ywH24uJjDNjys', + }, + ], + service: [ + { + id: '249Jvb1uAvZr7rm2tfe3qm#IndyAgentService', + serviceEndpoint: 'didcomm:transport/queue', + type: 'IndyAgent', + priority: 0, + recipientKeys: ['aKrpYPFyqwmovwZahfJtT8K2Ai1Zz7ywH24uJjDNjys'], + routingKeys: [], + }, + ], + authentication: [ + { + publicKey: '249Jvb1uAvZr7rm2tfe3qm#1', + type: 'Ed25519SignatureAuthentication2018', + }, + ], + id: '249Jvb1uAvZr7rm2tfe3qm', + }, + verkey: 'aKrpYPFyqwmovwZahfJtT8K2Ai1Zz7ywH24uJjDNjys', + theirLabel: 'Mediator', + state: 'complete', + role: 'invitee', + invitation: { + '@type': 'https://didcomm.org/connections/1.0/invitation', + '@id': 'b19a36f7-f8bf-4286-88f9-838e22d24f41', + recipientKeys: ['E9VXJcZshiXqqLEwzGtmPJBRpm29xvbLaZnZKSSFNvA6'], + serviceEndpoint: 'http://mediator3.test.indiciotech.io:3000', + label: 'Mediator', + }, + multiUseInvitation: false, + theirDid: 'JgPvbKPJKxaGPEJYHGKaYo', + theirDidDoc: { + '@context': 'https://w3id.org/did/v1', + publicKey: [ + { + id: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo#1', + controller: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo', + type: 'Ed25519VerificationKey2018', + publicKeyBase58: 'AdsmNZ1puUPmBoXSJD9vvpvF2UxTYpYT2vrkdViYuAFa', + }, + ], + service: [ + { + id: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo;indy', + serviceEndpoint: 'http://mediator3.test.indiciotech.io:3000', + type: 'IndyAgent', + priority: 0, + recipientKeys: ['AdsmNZ1puUPmBoXSJD9vvpvF2UxTYpYT2vrkdViYuAFa'], + }, + { + id: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo;indy1', + serviceEndpoint: 'ws://mediator3.test.indiciotech.io:3000', + type: 'IndyAgent', + priority: 0, + recipientKeys: ['AdsmNZ1puUPmBoXSJD9vvpvF2UxTYpYT2vrkdViYuAFa'], + }, + ], + authentication: [ + { + publicKey: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo#1', + type: 'Ed25519SignatureAuthentication2018', + }, + ], + id: 'did:sov:JgPvbKPJKxaGPEJYHGKaYo', + }, + threadId: '31ec4cde-832a-4d10-a581-b668c8f34ab0', + }, +]; + +export default MOCK_CONNECTION_LIST; diff --git a/src/screens/ListContacts/__tests__/ListContacts.utils.test.ts b/src/screens/ListContacts/__tests__/ListContacts.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..ebe9d2b90416ad6c4946ad4635145f6e758f8db1 --- /dev/null +++ b/src/screens/ListContacts/__tests__/ListContacts.utils.test.ts @@ -0,0 +1,17 @@ +import MOCK_CONNECTION_LIST from './ListContacts.constants'; +import * as Utils from '../ListContacts.utils'; + +describe('ListContacts.utils', () => { + describe('searchConnectionList', () => { + it.each([ + [MOCK_CONNECTION_LIST, 'abc', [MOCK_CONNECTION_LIST[0]]], + [MOCK_CONNECTION_LIST, 'Mediator', [MOCK_CONNECTION_LIST[3]]], + ])( + 'should return a filtered list of connections', + (connections, searchText, expected) => { + const result = Utils.searchConnectionList(connections, searchText); + expect(result).toEqual(expected); + }, + ); + }); +}); diff --git a/src/screens/ListContacts/index.ts b/src/screens/ListContacts/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..9d66617eca80fc8d41f8488d03164bae2fc2a3c1 --- /dev/null +++ b/src/screens/ListContacts/index.ts @@ -0,0 +1,3 @@ +import ListContacts from './ListContacts'; + +export default ListContacts; diff --git a/src/screens/ListCredentials/ListCredentials.constants.ts b/src/screens/ListCredentials/ListCredentials.constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..6d6d937035d273c7e076b0de42e717a81b7b1144 --- /dev/null +++ b/src/screens/ListCredentials/ListCredentials.constants.ts @@ -0,0 +1,127 @@ +import { CredentialExchangeRecord } from '@aries-framework/core'; + +const MOCK_CREDENTIALS_LIST: CredentialExchangeRecord[] = [ + { + _tags: { + connectionId: '07089a4a-7aba-497b-b8bc-c2e1a0934865', + state: 'request-sent', + threadId: '1b93fd9b-147b-47af-97b0-dd94bb5ed70e', + }, + connectionId: '07089a4a-7aba-497b-b8bc-c2e1a0934865', + createdAt: '2022-05-05T10:36:52.936Z', + credentialAttributes: [[Object], [Object], [Object]], + credentialId: '7661764c-df37-4f9b-84f1-357d3c84d11b', + credentialMessage: { + '@id': '058c7dfe-93d2-4291-9787-212b3786cf63', + '@type': 'https://didcomm.org/issue-credential/1.0/issue-credential', + 'credentials~attach': [Array], + '~attach': undefined, + '~l10n': undefined, + '~please_ack': [Object], + '~service': undefined, + '~thread': [Object], + '~timing': undefined, + '~transport': undefined, + }, + id: 'c388b53c-4b04-4e54-ac40-f52e9834a8f7', + metadata: { + '_internal/indyCredential': [ + { + credentialDefinitionId: 'LC5aqqDP6sB7Nyn3GHn4eC:3:CL:258409:UDDI', + schemaId: 'LC5aqqDP6sB7Nyn3GHn4eC:2:identity:1.2', + }, + ], + '_internal/indyRequest': [Object], + }, + offerMessage: { + '@id': '1b93fd9b-147b-47af-97b0-dd94bb5ed70e', + '@type': 'https://didcomm.org/issue-credential/1.0/offer-credential', + comment: 'Created', + credential_preview: [Object], + 'offers~attach': [Array], + '~attach': undefined, + '~l10n': undefined, + '~please_ack': undefined, + '~service': undefined, + '~thread': undefined, + '~timing': undefined, + '~transport': undefined, + }, + requestMessage: { + '@id': '0123042f-d046-408c-8477-a3fdb25ddc58', + '@type': 'https://didcomm.org/issue-credential/1.0/request-credential', + 'requests~attach': [Array], + '~attach': undefined, + '~l10n': undefined, + '~please_ack': undefined, + '~service': undefined, + '~thread': [Object], + '~timing': undefined, + '~transport': undefined, + }, + state: 'done', + threadId: '1b93fd9b-147b-47af-97b0-dd94bb5ed70e', + }, + { + _tags: { + connectionId: '07089a4a-7aba-497b-b8bc-c2e1a0934865', + state: 'request-sent', + threadId: '1b93fd9b-147b-47af-97b0-dd94bb5ed70e', + }, + connectionId: '07089a4a-7aba-497b-b8bc-c2e1a0934865', + createdAt: '2022-05-05T10:36:52.936Z', + credentialAttributes: [[Object], [Object], [Object]], + credentialId: '7661764c-df37-4f9b-84f1-357d3c84d11b', + credentialMessage: { + '@id': '058c7dfe-93d2-4291-9787-212b3786cf63', + '@type': 'https://didcomm.org/issue-credential/1.0/issue-credential', + 'credentials~attach': [Array], + '~attach': undefined, + '~l10n': undefined, + '~please_ack': [Object], + '~service': undefined, + '~thread': [Object], + '~timing': undefined, + '~transport': undefined, + }, + id: 'c388b53c-4b04-4e54-ac40-f52e9834a8f7', + metadata: { + '_internal/indyCredential': [ + { + credentialDefinitionId: 'LC5aqqDP6sB7Nyn3GHn4eC:3:CL:258409:UDDI', + schemaId: 'LC5aqqDP6sB7Nyn3GHn4eC:2:identity:1.2', + }, + ], + '_internal/indyRequest': [Object], + }, + offerMessage: { + '@id': '1b93fd9b-147b-47af-97b0-dd94bb5ed70e', + '@type': 'https://didcomm.org/issue-credential/1.0/offer-credential', + comment: 'Created', + credential_preview: [Object], + 'offers~attach': [Array], + '~attach': undefined, + '~l10n': undefined, + '~please_ack': undefined, + '~service': undefined, + '~thread': undefined, + '~timing': undefined, + '~transport': undefined, + }, + requestMessage: { + '@id': '0123042f-d046-408c-8477-a3fdb25ddc58', + '@type': 'https://didcomm.org/issue-credential/1.0/request-credential', + 'requests~attach': [Array], + '~attach': undefined, + '~l10n': undefined, + '~please_ack': undefined, + '~service': undefined, + '~thread': [Object], + '~timing': undefined, + '~transport': undefined, + }, + state: 'done', + threadId: '1b93fd9b-147b-47af-97b0-dd94bb5ed70e', + }, +]; +export default MOCK_CREDENTIALS_LIST; diff --git a/src/screens/ListCredentials/ListCredentials.tsx b/src/screens/ListCredentials/ListCredentials.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4b4296a1278706174d4c7edfc52c43d38aec789d --- /dev/null +++ b/src/screens/ListCredentials/ListCredentials.tsx @@ -0,0 +1,94 @@ +import { + CredentialState, + CredentialExchangeRecord, +} from '@aries-framework/core'; +import { useCredentialByState } from '@aries-framework/react-hooks'; +import React, { useEffect, useState, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import { FlatList, View, StyleSheet } from 'react-native'; +import { Text } from '../../components'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import CredentialListItem from '../../components/listItems/CredentialListItem'; +import SearchBar from '../../components/inputs/SearchBar'; +import { parsedSchema } from '../../utils/helpers'; + +const ListCredentials: React.FC = () => { + const credentials = useCredentialByState(CredentialState.Done); + + const { t } = useTranslation(); + const [searchPhrase, setSearchPhrase] = useState(''); + const [clicked, setClicked] = useState(false); + const [filteredData, setFilteredData] = useState(credentials); + + const refreshFilteredData = useCallback(() => { + setFilteredData(filteredData); + }, [filteredData]); + // Should not ever set state during rendering, so do this in useEffect instead. + useEffect(() => { + if (filteredData.length < credentials.length) { + refreshFilteredData(); + } + }, [filteredData, credentials.length, refreshFilteredData]); + + const search = (text: string) => { + const filteredData = credentials.filter(item => { + const orgLabel = parsedSchema(item).name.toUpperCase(); + const textData = text.toUpperCase(); + return orgLabel.indexOf(textData) > -1; + }); + + setFilteredData(filteredData); + setSearchPhrase(text); + }; + + const emptyListComponent = () => ( + <Text style={{ textAlign: 'center', marginTop: 100 }}> + {t<string>('Global.ZeroRecords')} + </Text> + ); + + return ( + <View style={styles.container}> + <SearchBar + searchPhrase={searchPhrase} + setSearchPhrase={setSearchPhrase => search(setSearchPhrase)} + clicked={clicked} + setClicked={setClicked} + /> + <FlatList + style={{ backgroundColor: ColorPallet.grayscale.white }} + data={filteredData} + keyExtractor={(item: CredentialExchangeRecord) => item?.id} + ListEmptyComponent={emptyListComponent} + renderItem={({ item, index }) => ( + <View + style={{ + marginHorizontal: 15, + marginTop: 15, + marginBottom: index === filteredData.length - 1 ? 45 : 0, + }} + key={index.toString()} + > + <CredentialListItem key={index.toString()} credential={item} /> + </View> + )} + /> + </View> + ); +}; + +export default ListCredentials; + +const styles = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + }, + bodyText: { + ...TextTheme.normal, + flexShrink: 1, + }, + spacer: { + height: 40, + }, +}); diff --git a/src/screens/ListCredentials/ListCredentials.utils.test.ts b/src/screens/ListCredentials/ListCredentials.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..27f663cee6597f10d213988edb601d7fb7dfb603 --- /dev/null +++ b/src/screens/ListCredentials/ListCredentials.utils.test.ts @@ -0,0 +1,54 @@ +import { + CredentialMetadataKeys, + CredentialExchangeRecord, + CredentialState, + CredentialPreviewAttribute, +} from '@aries-framework/core'; +import searchCredentialsList from './ListCredentials.utils'; + +const credentialRecord = new CredentialExchangeRecord({ + connectionId: '28790bfe-1345-4c64-b21a-7d98982b3894', + threadId: 'threadId', + state: CredentialState.Done, + credentialAttributes: [ + new CredentialPreviewAttribute({ + name: 'age', + value: '25', + }), + ], + protocolVersion: 'v1', +}); +credentialRecord.metadata.set(CredentialMetadataKeys.IndyCredential, { + credentialDefinitionId: 'Th7MpTaRZVRYnPiabds81Y:3:CL:17:TA', + schemaId: 'TL1EaPFCZ8Si5aUrqScBDt:2:testschema:1.0', +}); +const credentialRecord1 = new CredentialExchangeRecord({ + connectionId: '28790bfe-1345-4c64-b21a-7d98982b3894', + threadId: 'threadId', + state: CredentialState.Done, + credentialAttributes: [ + new CredentialPreviewAttribute({ + name: 'age', + value: '25', + }), + ], + protocolVersion: 'v1', +}); +credentialRecord1.metadata.set(CredentialMetadataKeys.IndyCredential, { + credentialDefinitionId: 'Th7MpTaRZVRYnPiabds81Y:3:CL:17:TAG', + schemaId: 'TL1EaPFCZ8Si5aUrqScBDt:2:Identity:1.0', +}); + +describe('ListCredentials.utils', () => { + describe('searchCredentialsList', () => { + it.each([ + [[credentialRecord, credentialRecord1], 'identity', [credentialRecord1]], + ])( + 'should return a filtered list of connections', + (credential, searchText, expected) => { + const result = searchCredentialsList(credential, searchText); + expect(result).toEqual(expected); + }, + ); + }); +}); diff --git a/src/screens/ListCredentials/ListCredentials.utils.ts b/src/screens/ListCredentials/ListCredentials.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..937743cfe8eb1b87f571b68674918b9cc2357774 --- /dev/null +++ b/src/screens/ListCredentials/ListCredentials.utils.ts @@ -0,0 +1,16 @@ +import { CredentialExchangeRecord } from '@aries-framework/core'; +import { parsedSchema } from '../../utils/helpers'; + +const searchCredentialsList = ( + credentialsList: CredentialExchangeRecord[], + searchText: string, +) => { + const filteredData = credentialsList.filter(item => { + const orgLabel = parsedSchema(item).name.toUpperCase(); + const textData = searchText.toUpperCase(); + return orgLabel.indexOf(textData) > -1; + }); + return filteredData; +}; + +export default searchCredentialsList; diff --git a/src/screens/ListCredentials/index.ts b/src/screens/ListCredentials/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..51e1acca96647ad54128916f787839ffa5a97f8f --- /dev/null +++ b/src/screens/ListCredentials/index.ts @@ -0,0 +1,3 @@ +import ListCredentials from './ListCredentials'; + +export default ListCredentials; diff --git a/src/screens/ListNotifications.tsx b/src/screens/ListNotifications.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a39ba6d4b50ed9647cdd6a3b8f2aa52d67580cca --- /dev/null +++ b/src/screens/ListNotifications.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { FlatList, View } from 'react-native'; +import useNotifications from '../hooks/notifications'; +import { NotificationListItem } from '../components'; +import { NotificationType } from '../components/listItems/NotificationListItem'; + +const ListNotifications: React.FC = () => { + const { notifications } = useNotifications(); + + return ( + <FlatList + data={notifications} + renderItem={({ item, index }) => ( + <View + style={{ + marginHorizontal: 15, + marginTop: 15, + marginBottom: index === notifications.length - 1 ? 45 : 0, + }} + > + {item.type === 'CredentialRecord' ? ( + <NotificationListItem + notificationType={NotificationType.CredentialOffer} + notification={item} + /> + ) : ( + <NotificationListItem + notificationType={NotificationType.ProofRequest} + notification={item} + /> + )} + </View> + )} + /> + ); +}; + +export default ListNotifications; diff --git a/src/screens/Onboarding/Onboarding.tsx b/src/screens/Onboarding/Onboarding.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e35a7bec447117292a5b7eb898300279045b8d1a --- /dev/null +++ b/src/screens/Onboarding/Onboarding.tsx @@ -0,0 +1,176 @@ +import { useFocusEffect, useNavigation } from '@react-navigation/native'; +import React, { ReactNode, useCallback } from 'react'; +import { + StyleSheet, + View, + Image, + Text, + BackHandler, + ImageSourcePropType, +} from 'react-native'; +import AppIntroSlider from 'react-native-app-intro-slider'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import { useTranslation } from 'react-i18next'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { storeAppIntroCompleteStage } from './Onboarding.utils'; +import { Screens } from '../../types/navigators'; +import Images from '../../assets'; + +interface ISlide { + key: number; + title: string; + text: string; + image: ImageSourcePropType; +} + +const slides: ISlide[] = [ + { + key: 1, + title: 'Credentials List', + text: 'Get the list of issued credentials', + image: Images.credentialListImage, + }, + { + key: 2, + title: 'Scan to connect', + text: 'Scan QR to connect to organizations', + image: Images.scanToConnectImage, + }, + { + key: 3, + title: 'Secure Storage', + text: 'Store your credentials securely in wallet', + image: Images.secureImage, + }, +]; + +const Onboarding: React.FC = () => { + const navigation = useNavigation(); + const { t } = useTranslation(); + + const renderItem = ({ item }: { item: ISlide }) => { + return ( + <View style={styles.container}> + <Text style={styles.title}>{item.title}</Text> + <Image source={item.image} style={styles.image} /> + <Text style={styles.text}>{item.text}</Text> + </View> + ); + }; + + const keyExtractor = (item: ISlide) => item.title; + + const renderNextButton = () => { + return ( + <View style={styles.buttonCircle}> + <Icon name="east" color={ColorPallet.grayscale.white} size={28} /> + </View> + ); + }; + const renderDoneButton = () => { + return ( + <View style={styles.buttonCircle}> + <Icon + name="check" + color={ColorPallet.grayscale.white} + size={28} + onPress={onDone} + /> + </View> + ); + }; + const renderSkipButton = () => { + return ( + <View> + <Text style={styles.textButton} onPress={onDone}> + {t<string>('Global.Skip')} + </Text> + </View> + ); + }; + const renderPrevButton = () => { + return ( + <View style={styles.buttonCircle}> + <Icon name="west" color={ColorPallet.grayscale.white} size={28} /> + </View> + ); + }; + const onDone = async () => { + // User finished the introduction. Show real app through + // navigation or simply by controlling state + await storeAppIntroCompleteStage(); + navigation.navigate(Screens.Terms); + }; + + useFocusEffect( + useCallback(() => { + const onBackPress = () => { + BackHandler.exitApp(); + return true; + }; + + BackHandler.addEventListener('hardwareBackPress', onBackPress); + + return () => + BackHandler.removeEventListener('hardwareBackPress', onBackPress); + }, []), + ); + + return ( + <View style={{ flex: 1 }}> + <AppIntroSlider + activeDotStyle={{ backgroundColor: ColorPallet.grayscale.darkGrey }} + keyExtractor={keyExtractor} + renderDoneButton={renderDoneButton} + renderNextButton={renderNextButton} + renderSkipButton={renderSkipButton} + renderPrevButton={renderPrevButton} + showPrevButton + showSkipButton + renderItem={renderItem} + data={slides} + /> + </View> + ); +}; + +export default Onboarding; + +const styles = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 10, + flex: 0.75, + alignItems: 'center', + justifyContent: 'center', + }, + image: { + flex: 0.65, + width: 300, + height: 70, + resizeMode: 'contain', + }, + text: { + ...TextTheme.normal, + flexShrink: 1, + textAlign: 'center', + }, + title: { + ...TextTheme.normal, + flexShrink: 1, + textAlign: 'center', + }, + buttonCircle: { + width: 44, + height: 44, + backgroundColor: ColorPallet.brand.primary, + borderRadius: 22, + justifyContent: 'center', + alignItems: 'center', + }, + textButton: { + marginTop: 12, + marginLeft: 5, + ...TextTheme.normal, + }, +}); diff --git a/src/screens/Onboarding/Onboarding.utils.test.ts b/src/screens/Onboarding/Onboarding.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d7c62581e2c8b8c4d1924ef538047acce18a7ad2 --- /dev/null +++ b/src/screens/Onboarding/Onboarding.utils.test.ts @@ -0,0 +1,14 @@ +import * as Utils from './Onboarding.utils'; + +describe('Onboarding.utils', () => { + describe('storeAppIntroCompleteStage', () => { + it('should store a value for the app intro stage', async () => { + // Mocked function to storeAppIntroCompleteStage + jest.spyOn(Utils, 'storeAppIntroCompleteStage'); + + await Utils.storeAppIntroCompleteStage(); + + expect(Utils.storeAppIntroCompleteStage).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/Onboarding/Onboarding.utils.ts b/src/screens/Onboarding/Onboarding.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..89f6da8521b26db033ae423abdee7142dafa5e96 --- /dev/null +++ b/src/screens/Onboarding/Onboarding.utils.ts @@ -0,0 +1,11 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { LocalStorageKeys } from '../../constants'; + +export const storeAppIntroCompleteStage = async () => { + await AsyncStorage.setItem( + LocalStorageKeys.OnboardingCompleteStage, + 'appIntroComplete', + ); +}; + +export default storeAppIntroCompleteStage; diff --git a/src/screens/Onboarding/index.ts b/src/screens/Onboarding/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..470d84e47b2623f4bb7fbe6c86155fd150bbf8c4 --- /dev/null +++ b/src/screens/Onboarding/index.ts @@ -0,0 +1,3 @@ +import Onboarding from './Onboarding'; + +export default Onboarding; diff --git a/src/screens/PinCreate/PinCreate.tsx b/src/screens/PinCreate/PinCreate.tsx new file mode 100644 index 0000000000000000000000000000000000000000..633e2d4a6abe223fc0a2f8b05149e5e19b040cc1 --- /dev/null +++ b/src/screens/PinCreate/PinCreate.tsx @@ -0,0 +1,210 @@ +import React, { useState, useEffect, useCallback } from 'react'; +import { + Keyboard, + StyleSheet, + View, + Image, + BackHandler, + Alert, +} from 'react-native'; +import { useTranslation } from 'react-i18next'; +import { StackScreenProps } from '@react-navigation/stack'; +import { useAgent } from '@aries-framework/react-hooks'; +import { UserCredentials } from 'react-native-keychain'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { + Loader, + TextInput, + InfoCard, + ScreenNavigatorButtons, +} from '../../components'; +import { KeychainStorageKeys } from '../../constants'; +import { OnboardingStackParams, Screens } from '../../types/navigators'; +import { + checkIfSensorAvailable, + createMD5HashFromString, +} from './PinCreate.utils'; +import { getValueFromKeychain, saveValueInKeychain } from '../../utils/generic'; +import Images from '../../assets'; + +type PinCreateProps = StackScreenProps< + OnboardingStackParams, + Screens.CreatePin +>; + +const PinCreate: React.FC<PinCreateProps> = ({ navigation, route }) => { + const { initAgent } = route.params; + const [pin, setPin] = useState(''); + const [pinTwo, setPinTwo] = useState(''); + const [biometricSensorAvailable, setBiometricSensorAvailable] = + useState(false); + const [loading, setLoading] = useState(false); + const { t } = useTranslation(); + const { agent } = useAgent(); + const [error, setError] = useState(''); + + const checkBiometricIfPresent = useCallback(async () => { + const { available } = await checkIfSensorAvailable(); + if (available) { + setBiometricSensorAvailable(true); + } + }, []); + + useEffect(() => { + checkBiometricIfPresent(); + }, [checkBiometricIfPresent]); + + const passcodeCreate = async (passcode: string) => { + try { + await saveValueInKeychain( + KeychainStorageKeys.Passcode, + passcode, + t<string>('PinCreate.UserAuthenticationPin'), + ); + + if (biometricSensorAvailable) { + navigation.navigate(Screens.Biometric); + } else { + navigation.navigate(Screens.Initialization); + } + + setError(t<string>('PinCreate.PinsSuccess')); + } catch (e: any) { + setError(e); + } + }; + const backAction = useCallback(() => { + Alert.alert('Already authenticated!', 'Are you sure you want to go back?', [ + { + text: 'Cancel', + onPress: () => null, + style: 'cancel', + }, + { + text: 'YES', + onPress: () => + navigation.navigate(Screens.Terms), + }, + ]); + return true; + }, [navigation]); + + useEffect(() => { + const backHandler = BackHandler.addEventListener( + 'hardwareBackPress', + backAction, + ); + + return () => backHandler.remove(); + }, [backAction]); + + const confirmEntry = async (pin: string, reEnterPin: string) => { + if (pin.length < 6) { + setError(t<string>('PinCreate.PinMustBe6DigitsInLength')); + } else if (reEnterPin.length < 6) { + setError(t<string>('PinCreate.ReEnterPinMustBe6DigitsInLength')); + } else if (pin !== reEnterPin) { + setError(t<string>('PinCreate.PinsEnteredDoNotMatch')); + } else { + await passcodeCreate(pin); + } + }; + + const onBack = () => { + backAction(); + }; + + return ( + <View style={[style.container]}> + <Loader loading={loading} /> + <View style={{ flex: 0.5 }}> + <View style={style.innerContainer}> + <View style={{ width: '70%' }}> + <TextInput + label={t<string>('Global.EnterPin')} + placeholder={t<string>('Global.6DigitPin')} + placeholderTextColor={ColorPallet.baseColors.lightGrey} + accessible + accessibilityLabel={t<string>('Global.EnterPin')} + maxLength={6} + autoFocus + secureTextEntry + keyboardType="number-pad" + value={pin} + onChangeText={setPin} + returnKeyType="done" + /> + <TextInput + label={t<string>('PinCreate.ReenterPin')} + accessible + accessibilityLabel={t<string>('PinCreate.ReenterPin')} + placeholder={t<string>('Global.6DigitPin')} + placeholderTextColor={ColorPallet.baseColors.lightGrey} + maxLength={6} + secureTextEntry + keyboardType="number-pad" + returnKeyType="done" + value={pinTwo} + onChangeText={(text: string) => { + setPinTwo(text); + if (text.length === 6) { + Keyboard.dismiss(); + } + }} + editable={pin.length === 6 && true} + /> + </View> + <View style={style.pinImgView}> + <Image source={Images.pinIcon} style={style.pinImg} /> + </View> + </View> + </View> + <View style={style.bottomContainer}> + <InfoCard showBottomIcon={false} showTopIcon errorMsg={error}> + {t<string>('PinCreate.PinInfo')} + </InfoCard> + <ScreenNavigatorButtons + onLeftPress={onBack} + onRightPress={() => confirmEntry(pin, pinTwo)} + /> + </View> + </View> + ); +}; + +export default PinCreate; + +const style = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + flex: 1, + justifyContent: 'space-between', + }, + btnContainer: { + marginTop: 20, + }, + label: { + ...TextTheme.label, + fontWeight: 'bold', + textAlign: 'center', + }, + pinImg: { + height: 95, + width: 70, + marginTop: 20, + alignSelf: 'flex-end', + }, + pinImgView: { + justifyContent: 'center', + flex: 1, + alignItems: 'center', + }, + innerContainer: { + flexDirection: 'row', + }, + bottomContainer: { + flex: 0.5, + justifyContent: 'space-between', + }, +}); diff --git a/src/screens/PinCreate/PinCreate.utils.test.ts b/src/screens/PinCreate/PinCreate.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..3d3b05bb1bf61150dfb30fb8ed5624c5059de4e6 --- /dev/null +++ b/src/screens/PinCreate/PinCreate.utils.test.ts @@ -0,0 +1,13 @@ +import * as Utils from './PinCreate.utils'; + +describe('PinCreate.utils', () => { + describe('storeOnboardingCompleteStage', () => { + it('should store a value for onboarding complete stage', async () => { + jest.spyOn(Utils, 'storeOnboardingCompleteStage'); + + await Utils.storeOnboardingCompleteStage(); + + expect(Utils.storeOnboardingCompleteStage).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/PinCreate/PinCreate.utils.ts b/src/screens/PinCreate/PinCreate.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..01c5bc92fec7437387dca886980559064c929a50 --- /dev/null +++ b/src/screens/PinCreate/PinCreate.utils.ts @@ -0,0 +1,35 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { Alert } from 'react-native'; +import ReactNativeBiometrics from 'react-native-biometrics'; +import md5 from 'md5'; +import i18next from 'i18next'; +import { LocalStorageKeys } from '../../constants'; +import { getValueKeychain, setValueKeychain } from '../../utils/keychain'; + +const rnBiometrics = new ReactNativeBiometrics(); + +export const storeOnboardingCompleteStage = async () => { + await AsyncStorage.setItem(LocalStorageKeys.OnboardingCompleteStage, 'true'); +}; + +export const checkIfSensorAvailable = async () => { + const result = await rnBiometrics.isSensorAvailable(); + return result; +}; + +export const showBiometricPrompt = async () => { + const result = await rnBiometrics.simplePrompt({ + promptMessage: i18next.t<string>('Biometric.BiometricConfirm'), + }); + return result; +}; + +export const createBiometricKeys = async () => { + const result = await rnBiometrics.createKeys(); + return result; +}; + +export const createMD5HashFromString = (value: string) => { + const hash = String(md5(value)); + return hash; +}; diff --git a/src/screens/PinCreate/index.ts b/src/screens/PinCreate/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..3c554df1a68ba838c0dd6876ea7cb37190dc1961 --- /dev/null +++ b/src/screens/PinCreate/index.ts @@ -0,0 +1,3 @@ +import PinCreate from './PinCreate'; + +export default PinCreate; diff --git a/src/screens/PinEnter/PinEnter.tsx b/src/screens/PinEnter/PinEnter.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f830ca9937879a76b49c66d177f454399cd22731 --- /dev/null +++ b/src/screens/PinEnter/PinEnter.tsx @@ -0,0 +1,158 @@ +import React, { useState, useEffect, useCallback } from 'react'; +import { + Alert, + BackHandler, + Keyboard, + StyleSheet, + Text, + View, +} from 'react-native'; +import { useTranslation } from 'react-i18next'; +import { StackScreenProps } from '@react-navigation/stack'; +import { useFocusEffect } from '@react-navigation/native'; +import { UserCredentials } from 'react-native-keychain'; +import { TextInput, Loader } from '../../components'; +import Button, { ButtonType } from '../../components/button/Button'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { OnboardingStackParams, Screens } from '../../types/navigators'; +import { KeychainStorageKeys } from '../../constants'; +import { + checkIfSensorAvailable, + removeOnboardingCompleteStage, + createMD5HashFromString, + showBiometricPrompt, +} from './PinEnter.utils'; +import { getValueFromKeychain } from '../../utils/generic'; +import { warningToast, errorToast, successToast } from '../../utils/toast'; + +type PinEnterProps = StackScreenProps<OnboardingStackParams, Screens.EnterPin>; + +const PinEnter: React.FC<PinEnterProps> = ({ navigation, route }) => { + const { initAgent, setAuthenticated } = route.params; + const [pin, setPin] = useState(''); + const [loginAttemtsFailed, setLoginAttemtsFailed] = useState(0); + const [loading, setLoading] = useState(false); + const { t } = useTranslation(); + + useFocusEffect( + useCallback(() => { + const onBackPress = () => { + BackHandler.exitApp(); + return true; + }; + + BackHandler.addEventListener('hardwareBackPress', onBackPress); + + return () => + BackHandler.removeEventListener('hardwareBackPress', onBackPress); + }, []), + ); + + const startAgent = useCallback(async () => { + const [guid, passphrase, passcode] = (await Promise.all([ + new Promise(resolve => { + resolve(getValueFromKeychain(KeychainStorageKeys.GUID)); + }), + new Promise(resolve => { + resolve(getValueFromKeychain(KeychainStorageKeys.Passphrase)); + }), + new Promise(resolve => { + resolve(getValueFromKeychain(KeychainStorageKeys.Passcode)); + }), + ])) as UserCredentials[]; + if (guid && passphrase) { + const rawValue = passphrase.password.replace(/ /g, ''); + const seedHash = createMD5HashFromString(rawValue); + await initAgent(guid.password, passcode.password, seedHash); + } + }, [initAgent]); + + const checkBiometricIfPresent = useCallback(async () => { + const { available } = await checkIfSensorAvailable(); + if (available) { + const { success, error } = await showBiometricPrompt(); + if (success) { + setLoading(true); + await startAgent(); + setLoading(false); + setAuthenticated(true); + } else if (error) { + warningToast(error); + } else { + warningToast(t<string>('Biometric.BiometricCancle')); + } + } + }, [setAuthenticated, startAgent, t]); + + useEffect(() => { + checkBiometricIfPresent(); + }, [checkBiometricIfPresent]); + + const checkPin = async (pin: string) => { + const [passcode] = (await Promise.all([ + new Promise(resolve => { + resolve(getValueFromKeychain(KeychainStorageKeys.Passcode)); + }), + ])) as UserCredentials[]; + if (pin === passcode.password) { + setLoading(true); + await startAgent(); + setAuthenticated(true); + setLoading(false); + } else { + warningToast(t<string>('PinEnter.IncorrectPin')); + setLoginAttemtsFailed(loginAttemtsFailed + 1); + if (loginAttemtsFailed === 5) { + Alert.alert(t<string>('Registration.RegisterAgain')); + navigation.navigate(Screens.EnterPin); + await removeOnboardingCompleteStage(); + } + } + }; + + return ( + <View style={[style.container]}> + <Loader loading={loading} /> + <TextInput + label={t<string>('Global.EnterPin')} + accessible + accessibilityLabel={t<string>('Global.EnterPin')} + placeholder={t<string>('Global.6DigitPin')} + placeholderTextColor={ColorPallet.baseColors.lightGrey} + maxLength={6} + keyboardType="numeric" + secureTextEntry + value={pin} + returnKeyType="done" + onChangeText={(pin: string) => { + setPin(pin.replace(/[^0-9]/g, '')); + if (pin.length === 6) { + Keyboard.dismiss(); + } + }} + /> + <Button + title={t<string>('Global.Submit')} + buttonType={ButtonType.Primary} + onPress={() => checkPin(pin)} + /> + </View> + ); +}; + +export default PinEnter; + +const style = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + }, + bodyText: { + ...TextTheme.normal, + flexShrink: 1, + }, + verticalSpacer: { + marginVertical: 20, + textAlign: 'center', + }, +}); diff --git a/src/screens/PinEnter/PinEnter.utils.test.ts b/src/screens/PinEnter/PinEnter.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..6bba43366fd27ad9038d609dedec2709539d4acd --- /dev/null +++ b/src/screens/PinEnter/PinEnter.utils.test.ts @@ -0,0 +1,29 @@ +import * as Utils from './PinEnter.utils'; + +describe('PinCreate.utils', () => { + describe('removeOnboardingCompleteStage', () => { + it('should remove a value for onboarding complete stage', async () => { + jest.spyOn(Utils, 'removeOnboardingCompleteStage'); + + await Utils.removeOnboardingCompleteStage(); + + expect(Utils.removeOnboardingCompleteStage).toHaveBeenCalled(); + }); + }); + + describe('createMD5HashFromString', () => { + it.each([ + ['kevin@gmail.com1234566', '31a8cc6fdfd91bd25e777cd928cca890'], + [ + 'kevin.durant@gmail.comThisisateststring', + '01b8b1108447e196002c12f27c2388b6', + ], + ])( + 'should return a hash value for the given string', + (initialValue, expectedValue) => { + const result = Utils.createMD5HashFromString(initialValue); + expect(result).toEqual(expectedValue); + }, + ); + }); +}); diff --git a/src/screens/PinEnter/PinEnter.utils.ts b/src/screens/PinEnter/PinEnter.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..c48ea3e87f6633fa3b8d382232e80fa8d05bc3d9 --- /dev/null +++ b/src/screens/PinEnter/PinEnter.utils.ts @@ -0,0 +1,28 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import ReactNativeBiometrics from 'react-native-biometrics'; +import md5 from 'md5'; +import i18next from 'i18next'; +import { LocalStorageKeys } from '../../constants'; + +const rnBiometrics = new ReactNativeBiometrics(); + +export const checkIfSensorAvailable = async () => { + const result = await rnBiometrics.isSensorAvailable(); + return result; +}; + +export const showBiometricPrompt = async () => { + const result = await rnBiometrics.simplePrompt({ + promptMessage: i18next.t<string>('Biometric.BiometricConfirm'), + }); + return result; +}; + +export const createMD5HashFromString = (value: string) => { + const hash = String(md5(value)); + return hash; +}; + +export const removeOnboardingCompleteStage = async () => { + await AsyncStorage.removeItem(LocalStorageKeys.OnboardingCompleteStage); +}; diff --git a/src/screens/PinEnter/index.ts b/src/screens/PinEnter/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..a34ed975ac16a33cb08eff71ee1fc593f0e9b27b --- /dev/null +++ b/src/screens/PinEnter/index.ts @@ -0,0 +1,3 @@ +import PinEnter from './PinEnter'; + +export default PinEnter; diff --git a/src/screens/ProofRequest/ProofRequest.tsx b/src/screens/ProofRequest/ProofRequest.tsx new file mode 100644 index 0000000000000000000000000000000000000000..12fb5ab299545dbddb9644105dd9b501c48500dc --- /dev/null +++ b/src/screens/ProofRequest/ProofRequest.tsx @@ -0,0 +1,644 @@ +import type { StackScreenProps } from '@react-navigation/stack'; +import { + ProofRecord, + ProofState, + RequestedAttribute, + RetrievedCredentials, +} from '@aries-framework/core'; +import { + useAgent, + useProofById, + useConnectionById, +} from '@aries-framework/react-hooks'; +import React, { useState, useEffect } from 'react'; +import { Trans, useTranslation } from 'react-i18next'; +import { Alert, View, StyleSheet, Text, ScrollView } from 'react-native'; +import { Buffer } from 'buffer'; +import { ItemType } from 'react-native-dropdown-picker'; +import { uuid } from '@aries-framework/core/build/utils/uuid'; +import ProofDeclined from '../../assets/img/proof-declined.svg'; +import ProofPending from '../../assets/img/proof-pending.svg'; +import ProofSuccess from '../../assets/img/proof-success.svg'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { HomeStackParams, Screens, Stacks } from '../../types/navigators'; +import { CredentialDisplay, CredentialList } from '../../types/record'; +import { getCredDefName, getSchemaNameFromSchemaId } from '../../utils/helpers'; +import ProofRequestAttribute from '../../components/views/ProofRequestAttribute'; +import Button, { ButtonType } from '../../components/button/Button'; +import FlowDetailModal from '../../components/modals/FlowDetailModal'; +import InfoTextBox from '../../components/text/InfoTextBox'; +import { errorToast } from '../../utils/toast'; +import { getRetrievedCredential } from './ProofRequest.utils'; + +type ProofRequestProps = StackScreenProps< + HomeStackParams, + Screens.ProofRequest +>; + +const ProofRequest: React.FC<ProofRequestProps> = ({ navigation, route }) => { + const { t } = useTranslation(); + if (!route?.params) { + throw new Error(t<string>('ProofRequest.ProofRequestParamsError')); + } + + const { proofId } = route.params; + const { agent } = useAgent(); + const [buttonsVisible, setButtonsVisible] = useState(true); + const [pendingModalVisible, setPendingModalVisible] = useState(false); + const [successModalVisible, setSuccessModalVisible] = useState(false); + const [declinedModalVisible, setDeclinedModalVisible] = useState(false); + + const [attributeCredentials] = useState<[string, RequestedAttribute[]][]>([]); + + const [retrievedCredentials, setRetrievedCredentials] = + useState<RetrievedCredentials>(); + const [isShowError, setIsShowError] = useState(false); + const [missingAttributes, setMissingAttributes] = useState<string[]>([]); + const [credentialsDisplay, setCredentialsDisplay] = useState< + CredentialDisplay[] + >([]); + const proof = useProofById(proofId); + const connection = useConnectionById( + proof?.connectionId ? proof.connectionId : '', + ); + + const transformProofObject = async (creds: RetrievedCredentials) => { + const base64Data = + proof?.requestMessage?.requestPresentationAttachments[0].data.base64; + const proofRequest = JSON.parse( + Buffer.from(base64Data!, 'base64').toString(), + ); + const requestedAttributesKeys = Object.keys( + proofRequest.requested_attributes, + ); + const requestedPredicatesKeys = Object.keys( + proofRequest.requested_predicates, + ); + const displayObject: CredentialDisplay[] = []; + + requestedAttributesKeys.forEach(key => { + const names = proofRequest.requested_attributes[key].name + ? [proofRequest.requested_attributes[key].name] + : proofRequest.requested_attributes[key].names; + + if (creds.requestedAttributes[key].length > 0) { + const credentialList: CredentialList[] = []; + creds.requestedAttributes[key].forEach((cred, index) => { + const credentialDefinitionId = getCredDefName( + JSON.parse(JSON.stringify(cred.credentialInfo)).cred_def_id, + ); + credentialList.push({ + isSelected: index === 0, + label: credentialDefinitionId, + value: JSON.parse(JSON.stringify(cred.credentialInfo)).referent, + }); + }); + const showNames: string[] = []; + const showValues: string[] = []; + names.forEach((name: string) => { + showNames.push(name); + showValues.push( + JSON.parse( + JSON.stringify(creds.requestedAttributes[key][0].credentialInfo), + ).attrs[name], + ); + }); + const object = { + key, + names: showNames, + values: showValues, + credentials: credentialList, + }; + displayObject.push(object); + } else { + // TODO: handle not matching with proof request + proofRequest.requested_attributes[key].restrictions.forEach( + restriction => { + if ( + Object.prototype.hasOwnProperty.call(restriction, 'schema_name') + ) { + names.forEach((name: string) => { + setMissingAttributes(prevState => [ + ...prevState, + `${name} ${t<string>('Global.from')} ${ + restriction.schema_name + }`, + ]); + }); + } else if ( + Object.prototype.hasOwnProperty.call(restriction, 'schema_id') + ) { + const schemaName = getSchemaNameFromSchemaId( + restriction.schema_id, + ); + names.forEach((name: string) => { + setMissingAttributes(prevState => [ + ...prevState, + `${name} ${t<string>('Global.from')} ${schemaName}`, + ]); + }); + } else { + names.forEach((name: string) => { + setMissingAttributes(prevState => [...prevState, name]); + }); + } + }, + ); + setIsShowError(true); + } + }); + + requestedPredicatesKeys.forEach(key => { + const names = proofRequest.requested_predicates[key].name + ? [proofRequest.requested_predicates[key].name] + : proofRequest.requested_predicates[key].names; + + if (creds.requestedPredicates[key].length > 0) { + const credentialList: CredentialList[] = []; + + creds.requestedPredicates[key].forEach((cred, index) => { + const credentialDefinitionId = getCredDefName( + JSON.parse(JSON.stringify(cred.credentialInfo)).cred_def_id, + ); + credentialList.push({ + isSelected: index === 0, + label: credentialDefinitionId, + value: JSON.parse(JSON.stringify(cred.credentialInfo)).referent, + }); + }); + + const showNames: string[] = []; + const showValues: string[] = []; + + names.forEach((name: string) => { + showNames.push( + `${`${name} ${proofRequest.requested_predicates[key].p_type}`} ${ + proofRequest.requested_predicates[key].p_value + }`, + ); + showValues.push( + JSON.parse( + JSON.stringify(creds.requestedPredicates[key][0].credentialInfo), + ).attrs[name], + ); + }); + + const object = { + key, + names: showNames, + values: showValues, + credentials: credentialList, + }; + displayObject.push(object); + } else { + proofRequest.requested_predicates[key].restrictions.forEach( + restriction => { + if ( + Object.prototype.hasOwnProperty.call(restriction, 'schema_name') + ) { + names.forEach((name: string) => { + setMissingAttributes(prevState => [ + ...prevState, + `${`${name + proofRequest.requested_predicates[key].p_type} ${ + proofRequest.requested_predicates[key].p_value + }`} ${t<string>('Global.from')} ${restriction.schema_name}`, + ]); + }); + } else if ( + Object.prototype.hasOwnProperty.call(restriction, 'schema_id') + ) { + const schemaName = getSchemaNameFromSchemaId( + restriction.schema_id, + ); + names.forEach((name: string) => { + setMissingAttributes(prevState => [ + ...prevState, + `${`${name + proofRequest.requested_predicates[key].p_type} ${ + proofRequest.requested_predicates[key].p_value + }`} ${t<string>('Global.from')} ${schemaName}`, + ]); + }); + } else { + names.forEach((name: string) => { + setMissingAttributes(prevState => [ + ...prevState, + `${name + proofRequest.requested_predicates[key].p_type} ${ + proofRequest.requested_predicates[key].p_value + }`, + ]); + }); + } + }, + ); + setIsShowError(true); + } + }); + setCredentialsDisplay(displayObject); + }; + + if (!agent) { + throw new Error(t<string>('CredentialOffer.FetchAFJError')); + } + + if (!proof) { + throw new Error(t<string>('ProofRequest.FetchProofError')); + } + + useEffect(() => { + const updateRetrievedCredentials = async (proof: ProofRecord) => { + const creds = await getRetrievedCredential(agent, proof); + if (!creds) { + throw new Error( + t<string>('ProofRequest.RequestedCredentialsCouldNotBeFound'), + ); + } + transformProofObject(creds); + setRetrievedCredentials(creds); + }; + + updateRetrievedCredentials(proof).catch(() => { + errorToast( + t<string>('ProofRequest.ProofUpdateErrorTitle'), + t<string>('ProofRequest.ProofUpdateErrorMessage'), + ); + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [agent.proofs, proof, t]); + + useEffect(() => { + if (proof.state === ProofState.Done) { + if (pendingModalVisible) { + setPendingModalVisible(false); + } + setSuccessModalVisible(true); + } + }, [pendingModalVisible, proof]); + + useEffect(() => { + if (proof.state === ProofState.Declined) { + setDeclinedModalVisible(true); + } + }, [proof]); + + const anyUnavailable = ( + attributes: [string, RequestedAttribute[]][] = [], + ): boolean => attributes.some(([, values]) => !values?.length); + + const anyRevoked = ( + attributes: [string, RequestedAttribute[]][] = [], + ): boolean => + attributes.some(([, values]) => values?.every(value => value.revoked)); + + const handleAcceptPress = async () => { + try { + setButtonsVisible(false); + setPendingModalVisible(true); + const updateRetrievedCredentials: RetrievedCredentials = { + requestedAttributes: {}, + requestedPredicates: {}, + }; + + credentialsDisplay?.map(async (credential: CredentialDisplay) => { + const isSelectedCredentialId = credential.credentials.find( + credential => credential.isSelected, + )?.value; + if ( + Object.prototype.hasOwnProperty.call( + retrievedCredentials?.requestedAttributes, + credential.key, + ) + ) { + const selectedCredential = retrievedCredentials?.requestedAttributes[ + credential.key + ].filter(item => item.credentialId === isSelectedCredentialId); + const object = { + [credential.key]: selectedCredential, + }; + Object.assign(updateRetrievedCredentials.requestedAttributes, object); + } + + if ( + Object.prototype.hasOwnProperty.call( + retrievedCredentials?.requestedPredicates, + credential.key, + ) + ) { + const selectedCredential = retrievedCredentials?.requestedPredicates[ + credential.key + ].filter(item => item.credentialId === isSelectedCredentialId); + const object = { + [credential.key]: selectedCredential, + }; + Object.assign(updateRetrievedCredentials.requestedPredicates, object); + } + }); + const automaticRequestedCreds = + retrievedCredentials && + agent.proofs.autoSelectCredentialsForProofRequest( + updateRetrievedCredentials, + ); + if (!automaticRequestedCreds) { + throw new Error( + t<string>('ProofRequest.RequestedCredentialsCouldNotBeFound'), + ); + } + await agent.proofs.acceptRequest(proof.id, automaticRequestedCreds); + + for await (const iterator of credentialsDisplay) { + const cred = iterator.credentials.find(item => item.isSelected); + const attributes = {}; + iterator.names.forEach((name, index) => { + attributes[name] = iterator.values[index]; + }); + const record = { + status: 'presented', + timestamp: new Date().getTime(), + connectionLabel: connection?.theirLabel ?? 'Connection less proof', + attributes, + }; + + // Get old record if exists + const oldRecords = await agent.genericRecords.findAllByQuery({ + credentialRecordId: cred.value, + }); + + // If old record exists, update it + oldRecords[0].content = { + records: [...oldRecords[0].content.records, record], + }; + + // Update record + await agent.genericRecords.update(oldRecords[0]); + } + + for await (const iterator of credentialsDisplay) { + const cred = iterator.credentials.find(item => item.isSelected); + const tags = { + connectionId: connection?.id ?? uuid(), + credentialRecordId: cred?.value, + type: 'proof', + }; + const attributes = {}; + iterator.names.forEach((name, index) => { + attributes[name] = iterator.values[index]; + }); + + // Create record object for proof + const record = { + status: 'presented', + timestamp: new Date().getTime(), + connectionLabel: connection?.theirLabel ?? 'Connection less proof', + credentialLabel: cred?.label, + attributes, + }; + + // Get old record if exists + const oldRecords = await agent.genericRecords.findAllByQuery({ + credentialRecordId: cred?.value, + type: 'proof', + }); + + // Create record if not exists + if (oldRecords.length > 0) { + oldRecords[0].content = { + records: [...oldRecords[0].content.records, record], + }; + await agent.genericRecords.update(oldRecords[0]); + } else { + await agent.genericRecords.save({ + tags, + content: { records: [record] }, + }); + } + } + + setPendingModalVisible(false); + setSuccessModalVisible(true); + } catch (e: unknown) { + setButtonsVisible(true); + setPendingModalVisible(false); + errorToast( + t<string>('ProofRequest.ProofAcceptErrorTitle'), + t<string>('ProofRequest.ProofAcceptErrorMessage'), + ); + } + }; + + const handleDeclinePress = async () => { + Alert.alert( + t<string>('ProofRequest.RejectThisProof?'), + t<string>('Global.ThisDecisionCannotBeChanged.'), + [ + { text: t<string>('Global.Cancel'), style: 'cancel' }, + { + text: t<string>('Global.Confirm'), + style: 'destructive', + onPress: async () => { + try { + setButtonsVisible(false); + await agent.proofs.declineRequest(proof.id); + } catch (e: unknown) { + errorToast( + t<string>('ProofRequest.ProofRejectErrorTitle'), + t<string>('ProofRequest.ProofRejectErrorMessage'), + ); + } + }, + }, + ], + ); + }; + + const onCredentialSelect = async (credentialId: string, key: string) => { + const updatedCredentialsDisplay = [...credentialsDisplay]; + const credential = updatedCredentialsDisplay.filter( + (object: { key: string }) => object.key === key, + )[0]; + if (retrievedCredentials?.requestedAttributes?.[key]) { + const keyObject = retrievedCredentials?.requestedAttributes?.[key].filter( + object => object.credentialId === credentialId, + )[0]; + const showValues: string[] = []; + credential?.names.forEach((name: string) => { + showValues.push( + JSON.parse(JSON.stringify(keyObject.credentialInfo)).attrs[name], + ); + }); + credential.credentials.forEach((item: any) => { + const element = item; + if (item.value === credentialId) { + element.isSelected = true; + } else { + element.isSelected = false; + } + }); + credential.values = showValues; + } + const index = updatedCredentialsDisplay.findIndex( + (item: string) => item === key, + ); + updatedCredentialsDisplay[index] = credential; + setCredentialsDisplay(updatedCredentialsDisplay); + }; + + return ( + <View style={styles.container}> + <ScrollView> + {isShowError ? ( + <> + <Text style={styles.missingInformationTitle}> + {t<string>('ProofRequest.MissingInformation.Title')} + </Text> + <InfoTextBox> + {t<string>( + 'ProofRequest.MissingInformation.AlertMissingInformation.Title', + )} + </InfoTextBox> + <View> + {missingAttributes.map(item => ( + <Text key={item} style={TextTheme.normal}> + {item} + </Text> + ))} + </View> + </> + ) : null} + + {!isShowError && ( + <> + <Text + style={TextTheme.normal} + accessibilityLabel={t<string>('ProofRequest.Title', { + connection: connection?.theirLabel ?? 'Verifier', + })} + > + <Trans + i18nKey="ProofRequest.Title" + values={{ + connection: connection?.theirLabel ?? 'Verifier', + }} + components={{ + b: <Text style={{ fontWeight: 'bold' }} />, + }} + t={t} + /> + </Text> + + <View style={{ zIndex: 1 }}> + <ProofRequestAttribute + proofRequest={credentialsDisplay} + onSelectItem={(item: ItemType, key) => + onCredentialSelect(item.value, key) + } + /> + </View> + </> + )} + + <View style={{ marginBottom: 30 }}> + {!( + anyUnavailable(attributeCredentials) || + anyRevoked(attributeCredentials) + ) && !isShowError ? ( + <View style={styles.footerButton}> + <Button + title={t<string>('Global.Share')} + buttonType={ButtonType.Primary} + onPress={handleAcceptPress} + disabled={!buttonsVisible} + /> + </View> + ) : null} + <View style={styles.footerButton}> + <Button + title={t<string>('Global.Decline')} + buttonType={ + anyUnavailable(attributeCredentials) || + anyRevoked(attributeCredentials) + ? ButtonType.Primary + : ButtonType.Ghost + } + onPress={handleDeclinePress} + disabled={!buttonsVisible} + /> + </View> + </View> + {pendingModalVisible && ( + <FlowDetailModal + title={t<string>('ProofRequest.SendingTheInformationSecurely')} + visible={pendingModalVisible} + doneHidden + > + <ProofPending style={{ marginVertical: 20 }} /> + </FlowDetailModal> + )} + + {successModalVisible && ( + <FlowDetailModal + title={t<string>('ProofRequest.InformationSentSuccessfully')} + visible={successModalVisible} + onDone={() => { + setSuccessModalVisible(false); + navigation.pop(); + navigation + .getParent() + ?.navigate(Stacks.TabStack, { screen: Screens.Home }); + }} + > + <ProofSuccess style={{ marginVertical: 20 }} /> + </FlowDetailModal> + )} + {declinedModalVisible && ( + <FlowDetailModal + title={t<string>('ProofRequest.ProofRejected')} + visible={declinedModalVisible} + onDone={() => { + setDeclinedModalVisible(false); + navigation.pop(); + navigation + .getParent() + ?.navigate(Stacks.TabStack, { screen: Screens.Home }); + }} + > + <ProofDeclined style={{ marginVertical: 20 }} /> + </FlowDetailModal> + )} + </ScrollView> + </View> + ); +}; + +export default ProofRequest; + +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: 20, + }, + headerTextContainer: { + paddingHorizontal: 25, + paddingVertical: 16, + }, + headerText: { + ...TextTheme.normal, + flexShrink: 1, + }, + footerButton: { + paddingTop: 10, + }, + link: { + ...TextTheme.normal, + minHeight: TextTheme.normal.fontSize, + color: ColorPallet.brand.link, + paddingVertical: 2, + }, + valueContainer: { + minHeight: TextTheme.normal.fontSize, + paddingVertical: 4, + }, + missingInformationTitle: { + ...TextTheme.headingFour, + color: ColorPallet.notification.errorText, + marginVertical: 10, + }, +}); diff --git a/src/screens/ProofRequest/ProofRequest.utils.test.ts b/src/screens/ProofRequest/ProofRequest.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5689883d315984d99c8f446f8abb1497a3f46df8 --- /dev/null +++ b/src/screens/ProofRequest/ProofRequest.utils.test.ts @@ -0,0 +1,13 @@ +import * as Utils from './ProofRequest.utils'; + +describe('ProofRequest.utils', () => { + describe('getRetrievedCredential', () => { + it('should we get retrieved credential for proof', () => { + jest.spyOn(Utils, 'getRetrievedCredential'); + + Utils.getRetrievedCredential('credential'); + + expect(Utils.getRetrievedCredential).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/ProofRequest/ProofRequest.utils.ts b/src/screens/ProofRequest/ProofRequest.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..e44f48e54281e8577d6511ae956c437a51743b86 --- /dev/null +++ b/src/screens/ProofRequest/ProofRequest.utils.ts @@ -0,0 +1,12 @@ +import { Agent, ProofRecord } from '@aries-framework/core'; + +export const getRetrievedCredential = async ( + agent: Agent, + proof: ProofRecord, +) => { + const retrievedCredentials = + await agent.proofs.getRequestedCredentialsForProofRequest(proof.id); + return retrievedCredentials; +}; + +export default { getRetrievedCredential }; diff --git a/src/screens/ProofRequest/index.ts b/src/screens/ProofRequest/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..9fa7559a6bcca0290dc802c347986caa9debb3da --- /dev/null +++ b/src/screens/ProofRequest/index.ts @@ -0,0 +1,3 @@ +import ProofRequest from './ProofRequest'; + +export default ProofRequest; diff --git a/src/screens/Scan/Scan.tsx b/src/screens/Scan/Scan.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9feabdfa3730947a1970345be018411302924355 --- /dev/null +++ b/src/screens/Scan/Scan.tsx @@ -0,0 +1,143 @@ +import { StackNavigationProp } from '@react-navigation/stack'; +import React, { useState } from 'react'; +import { useAgent } from '@aries-framework/react-hooks'; +import { parseUrl } from 'query-string'; +import { Agent } from '@aries-framework/core'; +import { StyleSheet, View } from 'react-native'; +import { useIsFocused } from '@react-navigation/core'; +import { Buffer } from 'buffer'; +import { useTranslation } from 'react-i18next'; +import QRScanner from '../../components/inputs/QRScanner'; +import { ScanStackParams, Screens, TabStacks } from '../../types/navigators'; +import QrCodeScanError from '../../types/error'; +import { ColorPallet } from '../../theme/theme'; +import { warningToast, errorToast } from '../../utils/toast'; +import useSealQrCodes from '../../hooks/useSealQrCodes'; + +interface ScanProps { + navigation: StackNavigationProp<ScanStackParams, Screens.Scan>; +} + +const Scan: React.FC<ScanProps> = ({ navigation }) => { + const { addSealedQrCode } = useSealQrCodes(); + const { t } = useTranslation(); + const { agent } = useAgent(); + const isFocused = useIsFocused(); + + const [qrCodeScanError, setQrCodeScanError] = + useState<QrCodeScanError | null>(null); + const [urlInput, setUrl] = useState(''); + + const isSealUrl = (url: string): boolean => { + return ( + url.indexOf('app.vereign.com') >= 0 || + url.indexOf('vrgnservices.com') >= 0 + ); + }; + + const isRedirection = (url: string): boolean => { + const queryParams = parseUrl(url).query; + return !(queryParams.c_i || queryParams.d_m); + }; + + const handleSealRedirection = async (url: string) => { + navigation.navigate(Screens.SealInformation, { url }); + }; + + const handleRedirection = async ( + url: string, + ): Promise<{ url?: string; message?: object }> => { + try { + const res = await fetch(url, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + }); + if (res.url) { + const [url] = res.url.split('%'); + return { url }; + } else { + const message = await res.json(); + return { message }; + } + } catch (error) { + errorToast(error); + throw error; + } + }; + + const processUrl = async (url: string) => { + setQrCodeScanError(null); + + if (url === '') { + // TODO No translation + return warningToast(t<string>('QRScanner.NotBlankURL')); + } + + try { + let receivedMessage; + if (isSealUrl(url)) { + await addSealedQrCode(url); + await handleSealRedirection(url); + } else if (isRedirection(url)) { + const { url: redirectedUrl, message } = await handleRedirection(url); + url = redirectedUrl || url; + receivedMessage = message; + } + + if (!(url.includes('?c_i') || url.includes('?d_m') || receivedMessage)) { + throw new Error('QRScanner.NotAValidURL'); + } + + let message; + if (receivedMessage) { + message = receivedMessage; + } else { + const [, value] = url.includes('?c_i') + ? url.split('?c_i=') + : url.split('?d_m='); + const ampIndex = value.indexOf('&'); + const urlData = value.substring( + 0, + ampIndex >= 0 ? ampIndex : undefined, + ); + message = JSON.parse(Buffer.from(urlData.trim(), 'base64').toString()); + } + + if (message['~service']) { + await agent?.receiveMessage(message); + navigation.navigate(TabStacks.HomeStack); + } else { + navigation.navigate(Screens.ConnectionInvitation, { url }); + } + } catch (e: unknown) { + console.error(e); + const error = new QrCodeScanError('QRScanner.InvalidQrCode', url); + setQrCodeScanError(error); + } + }; + + return ( + <View style={[styles.container]}> + {isFocused && ( + <QRScanner + handleCodeScan={url => processUrl(url)} + error={qrCodeScanError} + enableCameraOnError + onChangeText={setUrl} + textInputSubmit={() => processUrl(urlInput)} + /> + )} + </View> + ); +}; + +export default Scan; + +const styles = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + }, +}); diff --git a/src/screens/Scan/Scan.utils.test.ts b/src/screens/Scan/Scan.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..7b538a7470139bad1136dfa0dc19773b9555fe33 --- /dev/null +++ b/src/screens/Scan/Scan.utils.test.ts @@ -0,0 +1,14 @@ +import * as Utils from './Scan.utils'; + +describe('Scan.utils', () => { + test('should return receive message from agent response', () => { + const testData = { current_user: 'Rahul Raj', name: 'Lafarge' }; + + const response = { json: jest.fn().mockResolvedValueOnce(testData) }; + global.fetch = jest.fn().mockResolvedValueOnce(response); + + return Utils.receiveMessageAgent().then(data => { + expect(data).toEqual(testData); + }); + }); +}); diff --git a/src/screens/Scan/Scan.utils.ts b/src/screens/Scan/Scan.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..058a9fc725aaa46de045be854af9af339f7bedf4 --- /dev/null +++ b/src/screens/Scan/Scan.utils.ts @@ -0,0 +1,12 @@ +export async function receiveMessageAgent(url: string) { + return fetch(url, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + }).then(response => { + return response.json(); + }); +} +export default { receiveMessageAgent }; diff --git a/src/screens/Scan/index.ts b/src/screens/Scan/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..96938d0a87fbaea6313ccb8775005a979d5ed487 --- /dev/null +++ b/src/screens/Scan/index.ts @@ -0,0 +1,3 @@ +import Scan from './Scan'; + +export default Scan; diff --git a/src/screens/ScannedSealQrCodes/ScannedSealQrCodes.tsx b/src/screens/ScannedSealQrCodes/ScannedSealQrCodes.tsx new file mode 100644 index 0000000000000000000000000000000000000000..47d53ad04252d05896675115f842dcc351f94e8a --- /dev/null +++ b/src/screens/ScannedSealQrCodes/ScannedSealQrCodes.tsx @@ -0,0 +1,69 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { FlatList, StyleSheet, View } from 'react-native'; +import { SealListItem, Text, SafeAreaScrollView } from '../../components'; +import { ColorPallet } from '../../theme/theme'; +import useSealQrCodes, { SealQrCodeRecord } from '../../hooks/useSealQrCodes'; +import Button, { ButtonType } from '../../components/button/Button'; +import { TabStacks } from '../../types/navigators'; + +const styles = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + }, + topSpacer: { + paddingTop: 10, + paddingBottom: 20, + }, +}); + +interface ScannedSealQrCodesProps { + navigation: any; + route: any; +} + +const ScannedSealQrCodes: React.FC<ScannedSealQrCodesProps> = ({ + navigation, + route, +}) => { + const { t } = useTranslation(); + const { sealedQrCodes } = useSealQrCodes(); + + const handleReturnBack = () => { + navigation.navigate(TabStacks.HomeStack); + }; + const triple = [...sealedQrCodes, ...sealedQrCodes, ...sealedQrCodes]; + return ( + <SafeAreaScrollView style={styles.container}> + <FlatList + data={triple} + renderItem={({ item }) => ( + <SealListItem + key={item.date} + date={new Date(item.date)} + url={item.url} + subject={item.subject} + /> + )} + keyExtractor={(item: SealQrCodeRecord) => item.date.toString()} + style={{ backgroundColor: ColorPallet.grayscale.white }} + contentContainerStyle={{ paddingBottom: 65 }} + ListEmptyComponent={ + <Text style={{ textAlign: 'center', margin: 100 }}> + {t('Global.ZeroRecords')} + </Text> + } + /> + <View style={styles.topSpacer}> + <Button + title="Return back" + onPress={handleReturnBack} + buttonType={ButtonType.Primary} + /> + </View> + </SafeAreaScrollView> + ); +}; + +export default ScannedSealQrCodes; diff --git a/src/screens/ScannedSealQrCodes/index.ts b/src/screens/ScannedSealQrCodes/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..83347b87bbd04a35368d4d234c74a4291b05a6f9 --- /dev/null +++ b/src/screens/ScannedSealQrCodes/index.ts @@ -0,0 +1,3 @@ +import ScannedSealQrCodes from './ScannedSealQrCodes'; + +export default ScannedSealQrCodes; diff --git a/src/screens/SealInformation/SealInformation.tsx b/src/screens/SealInformation/SealInformation.tsx new file mode 100644 index 0000000000000000000000000000000000000000..470374ed3ce3df6026a6152588b91932f9934562 --- /dev/null +++ b/src/screens/SealInformation/SealInformation.tsx @@ -0,0 +1,71 @@ +import { View, StyleSheet } from 'react-native'; +import React from 'react'; +import { + borderRadius, + ColorPallet, + ContactTheme, + TextTheme, +} from '../../theme/theme'; +import { TabStacks } from '../../types/navigators'; +import Button, { ButtonType } from '../../components/button/Button'; +import SealModule from '../../seal-module/components/App'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + }, + webView: { + position: 'absolute', + width: 0, + height: 0, + }, + bodyText: { + ...TextTheme.normal, + flexShrink: 1, + }, + block: { + marginTop: 15, + marginHorizontal: 15, + padding: 10, + borderRadius, + backgroundColor: ContactTheme.background, + }, + spacer: { + height: 40, + width: 50, + }, + topSpacer: { + paddingTop: 10, + }, +}); +interface SealInformationPropsProps { + navigation: any; + route: any; +} + +const SealInformation: React.FC<SealInformationPropsProps> = ({ + navigation, + route, +}) => { + const { url } = route.params; + + const handleReturnBack = () => { + navigation.navigate(TabStacks.HomeStack); + }; + + return ( + <View style={[styles.container]}> + <SealModule url={url} /> + <View style={styles.topSpacer}> + <Button + title="Return back" + onPress={handleReturnBack} + buttonType={ButtonType.Primary} + /> + </View> + </View> + ); +}; +export default SealInformation; diff --git a/src/screens/SealInformation/index.ts b/src/screens/SealInformation/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..74af03a3357cb48baa928f0fee2d2e58a644117f --- /dev/null +++ b/src/screens/SealInformation/index.ts @@ -0,0 +1,3 @@ +import SealInformation from './SealInformation'; + +export default SealInformation; diff --git a/src/screens/Settings.tsx b/src/screens/Settings.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5aa1772fef9bd11da4d6532819ecf5a7dd70fac6 --- /dev/null +++ b/src/screens/Settings.tsx @@ -0,0 +1,94 @@ +import React from 'react'; +import { StackScreenProps } from '@react-navigation/stack'; +import { useTranslation } from 'react-i18next'; +import { StyleSheet, View, Alert } from 'react-native'; +import { getVersion, getBuildNumber } from 'react-native-device-info'; +import { borderRadius, ColorPallet, TextTheme } from '../theme/theme'; +import { Screens, SettingStackParams } from '../types/navigators'; +import { SettingListItem, Text } from '../components'; + +type SettingsProps = { + navigation: StackScreenProps<SettingStackParams, Screens.Settings>; + setAuthenticated: React.Dispatch<React.SetStateAction<boolean>>; +}; + +const Settings: React.FC<SettingsProps> = ({ + navigation, + setAuthenticated, +}) => { + const { t } = useTranslation(); + const logoff = () => + Alert.alert(t<string>('Settings.Logout'), t<string>('Settings.LogoutMsg'), [ + { + text: t<string>('Settings.Yes'), + onPress: () => setAuthenticated(false), + }, + { text: t<string>('Settings.No') }, + ]); + return ( + <View style={styles.container}> + <Text style={styles.groupHeader}> + {t<string>('Settings.AppPreferences')} + </Text> + <SettingListItem + title={t<string>('Settings.ChangePin')} + onPress={() => navigation.navigate(Screens.ChangePin)} + /> + <SettingListItem + title={t<string>('Settings.Language')} + onPress={() => navigation.navigate(Screens.Language)} + /> + <SettingListItem + title={t<string>('Settings.ViewMnemonic')} + onPress={() => navigation.navigate(Screens.ViewMnemonic)} + /> + <SettingListItem + title={t<string>('Settings.ExportWallet')} + onPress={() => navigation.navigate(Screens.ExportWallet)} + /> + <SettingListItem + title="Scanned SEAL QR codes" + onPress={() => navigation.navigate(Screens.ScannedSealQrCodes)} + /> + <SettingListItem title={t<string>('Settings.Logout')} onPress={logoff} /> + <Text style={styles.groupHeader}>{t<string>('Settings.AboutApp')}</Text> + <View style={styles.rowGroup}> + <View style={styles.row}> + <Text style={styles.bodyText}>{t<string>('Settings.Version')}</Text> + <Text + style={styles.bodyText} + >{`${getVersion()}.${getBuildNumber()}`}</Text> + </View> + </View> + </View> + ); +}; + +export default Settings; + +const styles = StyleSheet.create({ + container: { + width: '100%', + padding: 20, + }, + groupHeader: { + ...TextTheme.normal, + marginBottom: 8, + }, + bodyText: { + ...TextTheme.normal, + flexShrink: 1, + color: ColorPallet.baseColors.black, + }, + rowGroup: { + borderRadius: borderRadius * 2, + backgroundColor: ColorPallet.baseColors.lightBlue, + marginBottom: 10, + }, + row: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + padding: 12, + }, +}); diff --git a/src/screens/SetupDelay/SetupDelay.tsx b/src/screens/SetupDelay/SetupDelay.tsx new file mode 100644 index 0000000000000000000000000000000000000000..3c2a9c4632d1d1bfe9e67920f8567d013db1e2e6 --- /dev/null +++ b/src/screens/SetupDelay/SetupDelay.tsx @@ -0,0 +1,75 @@ +import { StackScreenProps } from '@react-navigation/stack'; +import React, { useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Alert, BackHandler, StyleSheet, View } from 'react-native'; +import CircularProgress from 'react-native-circular-progress-indicator'; +import { ColorPallet } from '../../theme/theme'; + +import { OnboardingStackParams, Screens } from '../../types/navigators'; + +type SetupDelayProps = StackScreenProps< + OnboardingStackParams, + Screens.SetupDelay +>; + +const SetupDelay: React.FC<SetupDelayProps> = ({ navigation }) => { + const { t } = useTranslation(); + + const backAction = () => { + // TODO move to translations + Alert.alert('PCM', 'Are you sure you want to exit?', [ + { + text: 'NO', + onPress: () => null, + style: 'cancel', + }, + { text: 'YES', onPress: () => BackHandler.exitApp() }, + ]); + return true; + }; + + useEffect(() => { + BackHandler.addEventListener('hardwareBackPress', backAction); + return () => { + BackHandler.removeEventListener('hardwareBackPress', backAction); + }; + }, []); + + return ( + <View style={styles.container}> + <CircularProgress + value={0} + radius={120} + maxValue={40} + initialValue={40} + title={t<string>('Registration.SecondCounter')} + progressValueFontSize={40} + titleFontSize={16} + progressValueColor={ColorPallet.brand.primary} + activeStrokeColor={ColorPallet.brand.primary} + activeStrokeWidth={15} + inActiveStrokeColor={ColorPallet.grayscale.lightGrey} + inActiveStrokeWidth={17} + duration={40000} + onAnimationComplete={() => + navigation.navigate(Screens.WalletInitialized) + } + /> + </View> + ); +}; + +export default SetupDelay; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + progressText: { + fontSize: 30, + color: 'black', + textAlign: 'center', + }, +}); diff --git a/src/screens/SetupDelay/index.ts b/src/screens/SetupDelay/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..3397877013e45a7b09f3aa22f9981250e88ff730 --- /dev/null +++ b/src/screens/SetupDelay/index.ts @@ -0,0 +1,3 @@ +import SetupDelay from './SetupDelay'; + +export default SetupDelay; diff --git a/src/screens/Splash/Splash.tsx b/src/screens/Splash/Splash.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c981a8e25b1611cebe6f2ed0822ff58732f05cd5 --- /dev/null +++ b/src/screens/Splash/Splash.tsx @@ -0,0 +1,48 @@ +import React, { useEffect } from 'react'; +import { StyleSheet, View } from 'react-native'; +import { StackScreenProps } from '@react-navigation/stack'; +import { Screens, OnboardingStackParams } from '../../types/navigators'; +import { ColorPallet } from '../../theme/theme'; +import { + hideNativeSplashScreen, + getOnboardingCompleteStage, +} from './Splash.utils'; + +type SplashProps = StackScreenProps<OnboardingStackParams, Screens.Splash>; + +const Splash: React.FC<SplashProps> = ({ navigation }) => { + const checkStack = async () => { + const onboardingCompleteStage = await getOnboardingCompleteStage(); + hideNativeSplashScreen(); + switch (onboardingCompleteStage) { + case 'true': + navigation.navigate(Screens.EnterPin); + break; + case 'appIntroComplete': + navigation.navigate(Screens.Terms); + break; + case 'termsComplete': + navigation.navigate(Screens.CreatePin); + break; + default: + navigation.navigate(Screens.Onboarding); + } + }; + + useEffect(() => { + checkStack(); + }); + + return <View style={styles.container} />; +}; + +export default Splash; + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: ColorPallet.grayscale.white, + }, +}); diff --git a/src/screens/Splash/Splash.utils.test.ts b/src/screens/Splash/Splash.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..7ffed62a5a77e823bacf68f36ce928d87ebf23ae --- /dev/null +++ b/src/screens/Splash/Splash.utils.test.ts @@ -0,0 +1,14 @@ +import * as Utils from './Splash.utils'; + +describe('Splash.utils', () => { + describe('getOnboardingCompleteStage', () => { + it('get value is saved in the storage', async () => { + // Mocked function to getOnboardingCompleteStage + jest.spyOn(Utils, 'getOnboardingCompleteStage'); + + await Utils.getOnboardingCompleteStage(); + + expect(Utils.getOnboardingCompleteStage).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/Splash/Splash.utils.ts b/src/screens/Splash/Splash.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..92d8fd33740b76a329d47e28835e93b17579e831 --- /dev/null +++ b/src/screens/Splash/Splash.utils.ts @@ -0,0 +1,14 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import SplashScreen from 'react-native-splash-screen'; +import { LocalStorageKeys } from '../../constants'; + +export const getOnboardingCompleteStage = async () => { + const onboardingCompleteStage = await AsyncStorage.getItem( + LocalStorageKeys.OnboardingCompleteStage, + ); + return onboardingCompleteStage; +}; + +export const hideNativeSplashScreen = () => { + SplashScreen.hide(); +}; diff --git a/src/screens/Splash/index.ts b/src/screens/Splash/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..edd8e85d404e52000b6a90efea70bfe99c421f73 --- /dev/null +++ b/src/screens/Splash/index.ts @@ -0,0 +1,3 @@ +import Splash from './Splash'; + +export default Splash; diff --git a/src/screens/Terms/Terms.tsx b/src/screens/Terms/Terms.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1fd9c30e4a757f90ccf3e025620e4aee8b7ee93a --- /dev/null +++ b/src/screens/Terms/Terms.tsx @@ -0,0 +1,107 @@ +import React, { useCallback, useState } from 'react'; +import { BackHandler, StyleSheet, View, ScrollView } from 'react-native'; +import { useFocusEffect, useNavigation } from '@react-navigation/core'; +import { useTranslation } from 'react-i18next'; +import CheckBoxRow from '../../components/checkbox/CheckBoxRow'; +import InfoTextBox from '../../components/text/InfoTextBox'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { Screens } from '../../types/navigators'; +import { + storeTermsCompleteStage, + restoreAppIntroCompleteStage, +} from './Terms.utils'; +import { InfoCard, ScreenNavigatorButtons } from '../../components'; + +const Terms: React.FC = () => { + const [checked, setChecked] = useState(false); + const nav = useNavigation(); + let backCount = 0; + + const { t } = useTranslation(); + + const onSubmitPressed = async () => { + await storeTermsCompleteStage(); + nav.navigate(Screens.CreatePin); + }; + + const onBack = async () => { + await restoreAppIntroCompleteStage(); + nav.navigate(Screens.Onboarding); + }; + useFocusEffect( + useCallback(() => { + const onBackPress = async () => { + // eslint-disable-next-line no-plusplus + backCount++; + if (backCount === 1) { + await restoreAppIntroCompleteStage(); + nav.navigate(Screens.Onboarding); + } else { + BackHandler.exitApp(); + } + + return true; + }; + + BackHandler.addEventListener('hardwareBackPress', onBackPress); + + return () => + BackHandler.removeEventListener('hardwareBackPress', onBackPress); + }, [backCount, nav]), + ); + return ( + <View style={styles.container}> + <ScrollView> + <InfoTextBox showIcon>{t<string>('Terms.AcceptTerms')}</InfoTextBox> + <View style={styles.verticalSpacer}> + <InfoCard showBottomIcon> + {t<string>('Terms.TermsAndConditions')} + </InfoCard> + </View> + </ScrollView> + <View style={styles.bottom}> + <CheckBoxRow + title={t<string>('Terms.Attestation')} + accessibilityLabel="I Agree" + checked={checked} + onPress={() => setChecked(!checked)} + /> + <ScreenNavigatorButtons + onLeftPress={onBack} + onRightPress={onSubmitPressed} + isRightDisabled={!checked} + /> + </View> + </View> + ); +}; + +export default Terms; + +const styles = StyleSheet.create({ + scrollView: { + height: 200, + }, + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + flex: 1, + }, + bodyText: { + ...TextTheme.normal, + flexShrink: 1, + }, + verticalSpacer: { + marginVertical: 20, + height: 420, + }, + topSpacer: { + paddingTop: 10, + }, + bottom: { + position: 'absolute', + bottom: 0, + backgroundColor: 'white', + width: '100%', + }, +}); diff --git a/src/screens/Terms/Terms.utils.test.ts b/src/screens/Terms/Terms.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..611f9a5a7bf13f2d9c39c0f742d97b6aef43d99a --- /dev/null +++ b/src/screens/Terms/Terms.utils.test.ts @@ -0,0 +1,14 @@ +import * as Utils from './Terms.utils'; + +describe('Terms.utils', () => { + describe('storeTermsCompleteStage', () => { + it('should store a value for the app terms stage', async () => { + // Mocked function to storeTermsCompleteStage + jest.spyOn(Utils, 'storeTermsCompleteStage'); + + await Utils.storeTermsCompleteStage(); + + expect(Utils.storeTermsCompleteStage).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/screens/Terms/Terms.utils.ts b/src/screens/Terms/Terms.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..8863f27696f00aea29bfce7741a89929225c4e56 --- /dev/null +++ b/src/screens/Terms/Terms.utils.ts @@ -0,0 +1,13 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { LocalStorageKeys } from '../../constants'; + +export const storeTermsCompleteStage = async () => { + await AsyncStorage.setItem( + LocalStorageKeys.OnboardingCompleteStage, + 'termsComplete', + ); +}; + +export const restoreAppIntroCompleteStage = async () => { + await AsyncStorage.removeItem(LocalStorageKeys.OnboardingCompleteStage); +}; diff --git a/src/screens/Terms/index.ts b/src/screens/Terms/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..01e7b9c4aa090e4081c4b3fe88ecc5c3e36c0ae0 --- /dev/null +++ b/src/screens/Terms/index.ts @@ -0,0 +1,3 @@ +import Terms from './Terms'; + +export default Terms; diff --git a/src/screens/ViewMnemonic/ViewMnemonic.tsx b/src/screens/ViewMnemonic/ViewMnemonic.tsx new file mode 100644 index 0000000000000000000000000000000000000000..39d7ca22c52f92aab3124fcd081c3e386098f8a7 --- /dev/null +++ b/src/screens/ViewMnemonic/ViewMnemonic.tsx @@ -0,0 +1,159 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Keyboard, StyleSheet, Text, View } from 'react-native'; +import Clipboard from '@react-native-clipboard/clipboard'; +import { UserCredentials } from 'react-native-keychain'; +import { TextInput } from '../../components'; +import Button, { ButtonType } from '../../components/button/Button'; +import { KeychainStorageKeys } from '../../constants'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import { getValueKeychain } from '../../utils/keychain'; +import { + authenticateUser, + checkIfSensorAvailable, + showBiometricPrompt, +} from './ViewMnemonic.utils'; +import { warningToast } from '../../utils/toast'; + +const ViewMnemonic: React.FC = () => { + const [pin, setPin] = useState(''); + const [showMnemonicView, setMnemonicView] = useState(false); + const [mnemonicText, setMnemonic] = useState(''); + const { t } = useTranslation(); + + const checkBiometricIfPresent = useCallback(async () => { + const { available } = await checkIfSensorAvailable(); + if (available) { + const { success, error } = await showBiometricPrompt(); + if (success) { + showMnemonic(); + } else if (error) { + warningToast(error); + } else { + warningToast(t<string>('Biometric.BiometricCancel')); + } + } + }, [t]); + + useEffect(() => { + checkBiometricIfPresent(); + }, [checkBiometricIfPresent]); + + const checkPin = async (pin: string) => { + const passcode = (await getValueKeychain({ + service: 'passcode', + })) as UserCredentials; + + const params = [pin, passcode.password]; + const result = authenticateUser(params); + if (result) { + showMnemonic(); + } else { + warningToast(t<string>('PinEnter.IncorrectPin')); + } + }; + + const showMnemonic = async () => { + const passphraseEntry = (await getValueKeychain({ + service: KeychainStorageKeys.Passphrase, + })) as UserCredentials; + + setMnemonic(passphraseEntry.password); + setMnemonicView(true); + }; + + const copyMnemonic = async () => { + Clipboard.setString(mnemonicText); + }; + + return ( + <View style={[style.container]}> + {!showMnemonicView && ( + <> + <TextInput + label={t<string>('Global.EnterPin')} + accessible + accessibilityLabel={t<string>('Global.EnterPin')} + placeholder={t<string>('Global.6DigitPin')} + placeholderTextColor={ColorPallet.baseColors.lightGrey} + maxLength={6} + keyboardType="numeric" + secureTextEntry + value={pin} + returnKeyType="done" + onChangeText={(pin: string) => { + setPin(pin.replace(/[^0-9]/g, '')); + if (pin.length === 6) { + Keyboard.dismiss(); + } + }} + /> + <Button + title={t<string>('Global.Submit')} + buttonType={ButtonType.Primary} + onPress={() => { + Keyboard.dismiss(); + checkPin(pin); + }} + /> + </> + )} + {showMnemonicView && ( + <> + <Text style={style.label}>Mnemonic</Text> + <View style={style.boxContainer}> + <Text style={style.headerText}>{mnemonicText}</Text> + <Text style={style.bodyText}> + {t<string>('Registration.MnemonicMsg')} + </Text> + <Button + title={t<string>('Global.Copy')} + buttonType={ButtonType.Primary} + onPress={copyMnemonic} + /> + </View> + </> + )} + </View> + ); +}; + +export default ViewMnemonic; + +const style = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + margin: 20, + }, + bodyText: { + ...TextTheme.normal, + flexShrink: 1, + }, + verticalSpacer: { + marginVertical: 20, + textAlign: 'center', + }, + subContainer: { + backgroundColor: ColorPallet.grayscale.white, + flex: 1, + margin: 20, + }, + boxContainer: { + backgroundColor: ColorPallet.notification.info, + borderRadius: 5, + borderWidth: 1, + borderColor: ColorPallet.notification.infoBorder, + padding: 10, + marginTop: 10, + marginBottom: 20, + }, + label: { + ...TextTheme.normal, + fontWeight: 'bold', + }, + headerText: { + ...TextTheme.normal, + color: ColorPallet.notification.infoText, + flexShrink: 1, + }, +}); diff --git a/src/screens/ViewMnemonic/ViewMnemonic.utils.test.ts b/src/screens/ViewMnemonic/ViewMnemonic.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..af13adb8b1a3513cda46c469852911afd3d56aee --- /dev/null +++ b/src/screens/ViewMnemonic/ViewMnemonic.utils.test.ts @@ -0,0 +1,13 @@ +import * as Utils from './ViewMnemonic.utils'; + +describe('ViewMnemonic.utils', () => { + describe('authenticateuser', () => { + it.each([ + { args: [123456, 123456], expected: true }, + { args: [111111, 111222], expected: false }, + ])('should return a true if the pin matches', initialValue => { + const result = Utils.authenticateUser(initialValue.args); + expect(result).toEqual(initialValue.expected); + }); + }); +}); diff --git a/src/screens/ViewMnemonic/ViewMnemonic.utils.ts b/src/screens/ViewMnemonic/ViewMnemonic.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..1f8f589ba02324e9ece700932f2bbf0f36478c04 --- /dev/null +++ b/src/screens/ViewMnemonic/ViewMnemonic.utils.ts @@ -0,0 +1,26 @@ +import i18next from 'i18next'; +import ReactNativeBiometrics from 'react-native-biometrics'; + +const rnBiometrics = new ReactNativeBiometrics(); + +export const checkIfSensorAvailable = async () => { + const result = await rnBiometrics.isSensorAvailable(); + return result; +}; + +export const showBiometricPrompt = async () => { + const result = await rnBiometrics.simplePrompt({ + promptMessage: i18next.t<string>('Biometric.BiometricConfirm'), + }); + return result; +}; + +export const authenticateUser = args => { + const res = args.reduce((prev, curr) => { + if (prev === curr) { + return true; + } + return false; + }); + return res; +}; diff --git a/src/screens/ViewMnemonic/index.ts b/src/screens/ViewMnemonic/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..ffb4e3db22191170f03a007fd5b7389f5cead7db --- /dev/null +++ b/src/screens/ViewMnemonic/index.ts @@ -0,0 +1,3 @@ +import ViewMnemonic from './ViewMnemonic'; + +export default ViewMnemonic; diff --git a/src/screens/WalletInitialized/WalletInitialized.tsx b/src/screens/WalletInitialized/WalletInitialized.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b7d9ba832f129927dd053cd3748d2660c86af17f --- /dev/null +++ b/src/screens/WalletInitialized/WalletInitialized.tsx @@ -0,0 +1,65 @@ +import { StackScreenProps } from '@react-navigation/stack'; +import React from 'react'; +import { View, Image, StyleSheet, Text } from 'react-native'; +import { useTranslation } from 'react-i18next'; +import { OnboardingStackParams, Screens } from '../../types/navigators'; +import { IconButton } from '../../components'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import Images from '../../assets'; + +type WalletInitializedProps = StackScreenProps< + OnboardingStackParams, + Screens.WalletInitialized +>; + +const WalletInitialized: React.FC<WalletInitializedProps> = ({ route }) => { + const { setAuthenticated } = route.params; + const { t } = useTranslation(); + + const onBack = async () => { + setAuthenticated(true); + }; + + return ( + <View style={[style.container]}> + <View style={[style.subcontainer]}> + <Text style={TextTheme.normal}> + {t<string>('Registration.WalletInitialized')} + </Text> + <Image + source={Images.walletInitializedIcon} + style={style.biometricIconImg} + resizeMode="contain" + /> + </View> + <View style={[style.btnContainer]}> + <IconButton isRight onPress={onBack} /> + </View> + </View> + ); +}; + +export default WalletInitialized; + +const style = StyleSheet.create({ + container: { + backgroundColor: ColorPallet.grayscale.white, + flex: 1, + marginTop: 20, + }, + biometricIconImg: { + height: 200, + width: '70%', + alignSelf: 'center', + margin: 20, + }, + subcontainer: { + alignItems: 'center', + flex: 1, + justifyContent: 'center', + }, + btnContainer: { + alignItems: 'flex-end', + margin: 20, + }, +}); diff --git a/src/screens/WalletInitialized/__tests__/WalletInitialized.test.tsx b/src/screens/WalletInitialized/__tests__/WalletInitialized.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ce40f1ffc4a2f0b29501b7e6bd4c23604dca1150 --- /dev/null +++ b/src/screens/WalletInitialized/__tests__/WalletInitialized.test.tsx @@ -0,0 +1,18 @@ +import { useNavigation } from '@react-navigation/core'; +import React from 'react'; +import { create } from 'react-test-renderer'; +import WalletInitialized from '../WalletInitialized'; + +describe('Wallet Initialization', () => { + it('should render correctly', () => { + const setAuthenticatedMock = jest.fn(); + const tree = create( + <WalletInitialized + navigation={useNavigation()} + route={{ params: { setAuthenticated: setAuthenticatedMock } }} + />, + ); + + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/screens/WalletInitialized/__tests__/__snapshots__/WalletInitialized.test.tsx.snap b/src/screens/WalletInitialized/__tests__/__snapshots__/WalletInitialized.test.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..ae9e39515092314a6da6c08abcbdbd1056678a8c --- /dev/null +++ b/src/screens/WalletInitialized/__tests__/__snapshots__/WalletInitialized.test.tsx.snap @@ -0,0 +1,116 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Wallet Initialization should render correctly 1`] = ` +<View + style={ + Array [ + Object { + "backgroundColor": "#FFFFFF", + "flex": 1, + "marginTop": 20, + }, + ] + } +> + <View + style={ + Array [ + Object { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + }, + ] + } + > + <Text + style={ + Object { + "color": "#000000", + "fontFamily": "TitilliumWeb-Regular", + "fontSize": 17, + "fontWeight": "normal", + } + } + > + Registration.WalletInitialized + </Text> + <Image + resizeMode="contain" + source={ + Object { + "testUri": "../../../src/assets/walletinitialized.png", + } + } + style={ + Object { + "alignSelf": "center", + "height": 200, + "margin": 20, + "width": "70%", + } + } + /> + </View> + <View + style={ + Array [ + Object { + "alignItems": "flex-end", + "margin": 20, + }, + ] + } + > + <View + accessible={true} + collapsable={false} + focusable={true} + nativeID="animatedComponent" + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + Object { + "alignItems": "center", + "backgroundColor": "#465AFF", + "borderRadius": 30, + "height": 60, + "justifyContent": "center", + "opacity": 1, + "width": 60, + } + } + testID="IconButton" + > + <View> + <Text + allowFontScaling={false} + selectable={false} + style={ + Array [ + Object { + "color": "#FFFFFF", + "fontSize": 30, + }, + undefined, + Object { + "fontFamily": "anticon", + "fontStyle": "normal", + "fontWeight": "normal", + }, + Object {}, + ] + } + > + + </Text> + </View> + </View> + </View> +</View> +`; diff --git a/src/screens/WalletInitialized/index.tsx b/src/screens/WalletInitialized/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0ccb5bbf9a1c4102e681365c3a8b7e5be2507401 --- /dev/null +++ b/src/screens/WalletInitialized/index.tsx @@ -0,0 +1,3 @@ +import WalletInitialized from './WalletInitialized'; + +export default WalletInitialized; diff --git a/src/seal-module/assets/images/appsource.svg b/src/seal-module/assets/images/appsource.svg new file mode 100644 index 0000000000000000000000000000000000000000..e718e404c409c15a9739aa56ed6733fa86893577 --- /dev/null +++ b/src/seal-module/assets/images/appsource.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 107.96 107.96"><rect width="107.96" height="107.96" style="fill:#f1f1f1"/><rect x="4.56" y="4.56" width="47.14" height="47.14" style="fill:#e64a25"/><rect x="56.26" y="4.56" width="47.14" height="47.14" style="fill:#76b223"/><rect x="4.56" y="56.26" width="47.14" height="47.14" style="fill:#2d97d6"/><rect x="56.26" y="56.26" width="47.14" height="47.14" style="fill:#fab014"/></svg> \ No newline at end of file diff --git a/src/seal-module/assets/images/bg-check.svg b/src/seal-module/assets/images/bg-check.svg new file mode 100644 index 0000000000000000000000000000000000000000..14189aa86f46b804cf2ba8e6ad0d1424232f37b3 --- /dev/null +++ b/src/seal-module/assets/images/bg-check.svg @@ -0,0 +1,21 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 550.29 476.57"> + <polygon points="165.09 190.63 110.06 285.94 220.12 285.94 165.09 190.63" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="165.09 381.25 220.12 285.94 110.06 285.94 165.09 381.25" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="220.12 285.94 165.09 381.25 275.15 381.25 220.12 285.94" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="220.12 476.57 275.15 381.25 165.09 381.25 220.12 476.57" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="275.15 381.25 220.12 476.57 330.18 476.57 275.15 381.25" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="330.18 285.94 275.15 381.25 385.2 381.25 330.18 285.94" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="330.18 476.57 385.2 381.25 275.15 381.25 330.18 476.57" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="385.2 190.63 330.18 285.94 440.24 285.94 385.2 190.63" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="385.2 381.25 440.24 285.94 330.18 285.94 385.2 381.25" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="440.24 95.31 385.2 190.63 495.26 190.63 440.24 95.31" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="440.24 285.94 495.26 190.63 385.2 190.63 440.24 285.94" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="495.26 190.63 550.29 95.31 440.24 95.31 495.26 190.63" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="275.15 190.63 330.18 95.31 220.12 95.31 275.15 190.63" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="110.06 95.31 55.03 190.63 165.09 190.63 110.06 95.31" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="110.06 285.94 165.09 190.63 55.03 190.63 110.06 285.94" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="275.15 0 220.12 95.31 330.18 95.31 275.15 0" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="495.26 0 440.24 95.31 550.29 95.31 495.26 0" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="55.03 0 0 95.31 110.06 95.31 55.03 0" style="fill:#ffffff; stroke:#f0f0f0"/> + <polygon points="55.03 190.63 110.06 95.31 0 95.31 55.03 190.63" style="fill:#ffffff; stroke:#f0f0f0"/> +</svg> \ No newline at end of file diff --git a/src/seal-module/assets/images/chain-links.png b/src/seal-module/assets/images/chain-links.png new file mode 100644 index 0000000000000000000000000000000000000000..d02c068f5b3858a29e0dec9c665759b6357d53e1 Binary files /dev/null and b/src/seal-module/assets/images/chain-links.png differ diff --git a/src/seal-module/assets/images/chain-links.svg b/src/seal-module/assets/images/chain-links.svg new file mode 100644 index 0000000000000000000000000000000000000000..c33978875700b2e363f8d898159ef208a619bf5f --- /dev/null +++ b/src/seal-module/assets/images/chain-links.svg @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 31.891 31.891" style="enable-background:new 0 0 31.891 31.891;" xml:space="preserve"> +<g fill="white"> + <path d="M30.543,5.74l-4.078-4.035c-1.805-1.777-4.736-1.789-6.545-0.02l-4.525,4.414c-1.812,1.768-1.82,4.648-0.02,6.424 + l2.586-2.484c-0.262-0.791,0.061-1.697,0.701-2.324l2.879-2.807c0.912-0.885,2.375-0.881,3.275,0.01l2.449,2.42 + c0.9,0.891,0.896,2.326-0.01,3.213l-2.879,2.809c-0.609,0.594-1.609,0.92-2.385,0.711l-2.533,2.486 + c1.803,1.781,4.732,1.789,6.545,0.02l4.52-4.41C32.34,10.396,32.346,7.519,30.543,5.74z"/> + <path d="M13.975,21.894c0.215,0.773-0.129,1.773-0.752,2.381l-2.689,2.627c-0.922,0.9-2.414,0.895-3.332-0.012l-2.498-2.461 + c-0.916-0.906-0.91-2.379,0.012-3.275l2.691-2.627c0.656-0.637,1.598-0.961,2.42-0.689l2.594-2.57 + c-1.836-1.811-4.824-1.82-6.668-0.02l-4.363,4.26c-1.846,1.803-1.855,4.734-0.02,6.549l4.154,4.107 + c1.834,1.809,4.82,1.818,6.668,0.018l4.363-4.26c1.844-1.805,1.852-4.734,0.02-6.547L13.975,21.894z"/> + <path d="M11.139,20.722c0.611,0.617,1.611,0.623,2.234,0.008l7.455-7.416c0.621-0.617,0.625-1.615,0.008-2.234 + c-0.613-0.615-1.611-0.619-2.23-0.006l-7.457,7.414C10.529,19.103,10.525,20.101,11.139,20.722z"/> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> + <g> + </g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +<g> +</g> +</svg> diff --git a/src/seal-module/assets/images/check-logo.png b/src/seal-module/assets/images/check-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..74119f1378d834ebf1d5f0b77d20c27caf2c4de8 Binary files /dev/null and b/src/seal-module/assets/images/check-logo.png differ diff --git a/src/seal-module/assets/images/check-logo.svg b/src/seal-module/assets/images/check-logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..9f2c07ddbb90bccd317faaca5c3cf21f37640541 --- /dev/null +++ b/src/seal-module/assets/images/check-logo.svg @@ -0,0 +1,7 @@ +<svg id="Group_9453" data-name="Group 9453" xmlns="http://www.w3.org/2000/svg" width="58.298" height="51.303" viewBox="0 0 58.298 51.303"> + <path id="Path_3116" data-name="Path 3116" d="M200.319,125.789v15.382h.885l17.559,31.71h7.409l16.884-31.71h.851V125.789Z" transform="translate(-192.946 -125.789)" fill="#fff"/> + <g id="Group_9390" data-name="Group 9390" transform="translate(0 0)"> + <path id="Path_3117" data-name="Path 3117" d="M203.556,143.02H213.3l4.872,8.616,4.872-8.616,4.872-8.616,4.872-8.616H203.556l4.872,8.616Z" transform="translate(-189.023 -125.789)" fill="#00b3ca"/> + <path id="Path_3118" data-name="Path 3118" d="M250.464,125.789h-9.716l4.858,8.55-4.858,8.55-4.858,8.55-4.858,8.55-4.858,8.551-4.858-8.551-4.858-8.55-4.858-8.55-4.858-8.55,4.858-8.55h-9.716l-4.858,8.55,4.858,8.55,4.858,8.55,4.858,8.55,4.858,8.551,4.858,8.55h9.716l4.858-8.55,4.858-8.551,4.858-8.55,4.858-8.55,4.858-8.55Z" transform="translate(-197.024 -125.789)" fill="#00b3ca"/> + </g> +</svg> diff --git a/src/seal-module/assets/images/check.png b/src/seal-module/assets/images/check.png new file mode 100644 index 0000000000000000000000000000000000000000..648ecbe231976935410accc1ee9f4d667caf1e6b Binary files /dev/null and b/src/seal-module/assets/images/check.png differ diff --git a/src/seal-module/assets/images/check.svg b/src/seal-module/assets/images/check.svg new file mode 100644 index 0000000000000000000000000000000000000000..e4235d506615b0503d90c45dbb8f17204d9e04d4 --- /dev/null +++ b/src/seal-module/assets/images/check.svg @@ -0,0 +1,6 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="27" height="27" viewBox="0 0 27 27"> + <g id="Group_10159" data-name="Group 10159" transform="translate(-402 -291)"> + <circle id="Ellipse_1" data-name="Ellipse 1" cx="13.5" cy="13.5" r="13.5" transform="translate(402 291)" fill="#fff"/> + <path id="Path_3131" data-name="Path 3131" d="M5.434-.269a.8.8,0,0,0,1.131,0l9.2-9.2a.8.8,0,0,0,0-1.131l-1.131-1.131a.8.8,0,0,0-1.131,0L6-4.228l-3.5-3.5a.8.8,0,0,0-1.131,0L.234-6.6a.8.8,0,0,0,0,1.131Z" transform="translate(407.5 311)" fill="#00b3ca"/> + </g> +</svg> diff --git a/src/seal-module/assets/images/chrome-store.svg b/src/seal-module/assets/images/chrome-store.svg new file mode 100644 index 0000000000000000000000000000000000000000..3ca71375a035bc24b573f7f5b70207628c98c12b --- /dev/null +++ b/src/seal-module/assets/images/chrome-store.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 121.39 107.08"><path d="M45.58,125.94a9.5,9.5,0,0,0,9.5,9.5h102.4a9.5,9.5,0,0,0,9.5-9.5v-44H45.58Z" transform="translate(-45.58 -28.36)" style="fill:#edecec"/><rect width="121.39" height="53.54" style="fill:#e2e2e2"/><rect x="41.58" y="11.77" width="38.24" height="12.06" rx="6.03" style="fill:#fff"/><path d="M76.41,81.9h59.73a53.46,53.46,0,0,0-59.73,0Z" transform="translate(-45.58 -28.36)" style="fill:#ce4438"/><path d="M52.82,126.25a53.77,53.77,0,0,0,.77,9,7.49,7.49,0,0,0,1.5.16h29.5L62,96.32A53.18,53.18,0,0,0,52.82,126.25Z" transform="translate(-45.58 -28.36)" style="fill:#139754"/><path d="M106.28,102.7h48a53.63,53.63,0,0,0-18.14-20.8H76.41A53.87,53.87,0,0,0,62,96.32l22.59,39.12a23.56,23.56,0,0,1,21.69-32.74Z" transform="translate(-45.58 -28.36)" style="fill:#d94539"/><path d="M154.28,102.7h-48A23.56,23.56,0,0,1,128,135.44h29.51a7.47,7.47,0,0,0,1.49-.16,53.76,53.76,0,0,0,.78-9A53.17,53.17,0,0,0,154.28,102.7Z" transform="translate(-45.58 -28.36)" style="fill:#fec73e"/><path d="M106.28,107.35a18.89,18.89,0,0,0-16.51,28.09h33a18.89,18.89,0,0,0-16.51-28.09Z" transform="translate(-45.58 -28.36)" style="fill:#4b74b8"/></svg> \ No newline at end of file diff --git a/src/seal-module/assets/images/copy.png b/src/seal-module/assets/images/copy.png new file mode 100644 index 0000000000000000000000000000000000000000..e9cca832f4e62446bd78118609b4a49161be392b Binary files /dev/null and b/src/seal-module/assets/images/copy.png differ diff --git a/src/seal-module/assets/images/copy.svg b/src/seal-module/assets/images/copy.svg new file mode 100644 index 0000000000000000000000000000000000000000..119024dc073738cac72440a8351d4af1275ad9e9 --- /dev/null +++ b/src/seal-module/assets/images/copy.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 115.77 122.88" style="enable-background:new 0 0 115.77 122.88" xml:space="preserve"><style type="text/css">.st0{fill-rule:evenodd;clip-rule:evenodd;}</style><g><path fill="#3C3C3C" class="st0" d="M89.62,13.96v7.73h12.19h0.01v0.02c3.85,0.01,7.34,1.57,9.86,4.1c2.5,2.51,4.06,5.98,4.07,9.82h0.02v0.02 v73.27v0.01h-0.02c-0.01,3.84-1.57,7.33-4.1,9.86c-2.51,2.5-5.98,4.06-9.82,4.07v0.02h-0.02h-61.7H40.1v-0.02 c-3.84-0.01-7.34-1.57-9.86-4.1c-2.5-2.51-4.06-5.98-4.07-9.82h-0.02v-0.02V92.51H13.96h-0.01v-0.02c-3.84-0.01-7.34-1.57-9.86-4.1 c-2.5-2.51-4.06-5.98-4.07-9.82H0v-0.02V13.96v-0.01h0.02c0.01-3.85,1.58-7.34,4.1-9.86c2.51-2.5,5.98-4.06,9.82-4.07V0h0.02h61.7 h0.01v0.02c3.85,0.01,7.34,1.57,9.86,4.1c2.5,2.51,4.06,5.98,4.07,9.82h0.02V13.96L89.62,13.96z M79.04,21.69v-7.73v-0.02h0.02 c0-0.91-0.39-1.75-1.01-2.37c-0.61-0.61-1.46-1-2.37-1v0.02h-0.01h-61.7h-0.02v-0.02c-0.91,0-1.75,0.39-2.37,1.01 c-0.61,0.61-1,1.46-1,2.37h0.02v0.01v64.59v0.02h-0.02c0,0.91,0.39,1.75,1.01,2.37c0.61,0.61,1.46,1,2.37,1v-0.02h0.01h12.19V35.65 v-0.01h0.02c0.01-3.85,1.58-7.34,4.1-9.86c2.51-2.5,5.98-4.06,9.82-4.07v-0.02h0.02H79.04L79.04,21.69z M105.18,108.92V35.65v-0.02 h0.02c0-0.91-0.39-1.75-1.01-2.37c-0.61-0.61-1.46-1-2.37-1v0.02h-0.01h-61.7h-0.02v-0.02c-0.91,0-1.75,0.39-2.37,1.01 c-0.61,0.61-1,1.46-1,2.37h0.02v0.01v73.27v0.02h-0.02c0,0.91,0.39,1.75,1.01,2.37c0.61,0.61,1.46,1,2.37,1v-0.02h0.01h61.7h0.02 v0.02c0.91,0,1.75-0.39,2.37-1.01c0.61-0.61,1-1.46,1-2.37h-0.02V108.92L105.18,108.92z"/></g></svg> diff --git a/src/seal-module/assets/images/documents.png b/src/seal-module/assets/images/documents.png new file mode 100644 index 0000000000000000000000000000000000000000..519ab4e68ef3f05f88765c5e00c76e0a1f725b2d Binary files /dev/null and b/src/seal-module/assets/images/documents.png differ diff --git a/src/seal-module/assets/images/documents.svg b/src/seal-module/assets/images/documents.svg new file mode 100644 index 0000000000000000000000000000000000000000..cb933855fa016d78b00f28e1715e5b0f9c1ffab5 --- /dev/null +++ b/src/seal-module/assets/images/documents.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="16.957" height="20" viewBox="0 0 16.957 20"><defs><style>.a{fill:#fff;}</style></defs><path class="a" d="M-2161.217,26a2.609,2.609,0,0,1-2.609-2.609v-.039A2.609,2.609,0,0,1-2166,20.783V10.837a.873.873,0,0,1,.248-.608l3.883-3.968a.87.87,0,0,1,.625-.26h6.983a2.61,2.61,0,0,1,2.57,2.174h.04a2.608,2.608,0,0,1,2.608,2.609V23.391A2.608,2.608,0,0,1-2151.652,26Zm-3.044-5.217a.869.869,0,0,0,.869.869h9.131a.87.87,0,0,0,.615-.255.87.87,0,0,0,.255-.615V8.609a.87.87,0,0,0-.255-.615.87.87,0,0,0-.615-.255h-6.087V10.13a1.737,1.737,0,0,1-.51,1.229,1.737,1.737,0,0,1-1.229.509h-2.174Zm2.365-1.157a.625.625,0,0,1-.626-.625v-.625a.625.625,0,0,1,.626-.626h6.25a.625.625,0,0,1,.625.626V19a.625.625,0,0,1-.625.625Zm0-3.75a.625.625,0,0,1-.626-.625v-.625A.625.625,0,0,1-2161.9,14h6.25a.624.624,0,0,1,.625.625v.625a.625.625,0,0,1-.625.625Z" transform="translate(2166 -6)"/></svg> \ No newline at end of file diff --git a/src/seal-module/assets/images/download.png b/src/seal-module/assets/images/download.png new file mode 100644 index 0000000000000000000000000000000000000000..c596cbd83615bb70a8a3058dc684ac6958bfd5ae Binary files /dev/null and b/src/seal-module/assets/images/download.png differ diff --git a/src/seal-module/assets/images/exclamation.png b/src/seal-module/assets/images/exclamation.png new file mode 100644 index 0000000000000000000000000000000000000000..7a9bf2646f42f1def216c6ad81d085e0b02064f1 Binary files /dev/null and b/src/seal-module/assets/images/exclamation.png differ diff --git a/src/seal-module/assets/images/exclamation.svg b/src/seal-module/assets/images/exclamation.svg new file mode 100644 index 0000000000000000000000000000000000000000..1d54b66cab85c2a4db98e60377e7a3bb809c4699 --- /dev/null +++ b/src/seal-module/assets/images/exclamation.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="55" height="173" viewBox="0 0 55 173"> + <circle id="Ellipse_1" data-name="Ellipse 1" cx="27.5" cy="27.5" r="27.5" transform="translate(0 118)" fill="#fff"/> + <path id="Path_1" data-name="Path 1" d="M6,0H39a7,7,0,0,1,7,7l-4.078,94a7,7,0,0,1-7,7H10.405a7,7,0,0,1-7-7L-1,7A7,7,0,0,1,6,0Z" transform="translate(5)" fill="#fff"/> +</svg> diff --git a/src/seal-module/assets/images/exclamationCircle.png b/src/seal-module/assets/images/exclamationCircle.png new file mode 100644 index 0000000000000000000000000000000000000000..c667cc3f6b2a3ad011c60f4f68f3f00cc049ff43 Binary files /dev/null and b/src/seal-module/assets/images/exclamationCircle.png differ diff --git a/src/seal-module/assets/images/exclamationCircle.svg b/src/seal-module/assets/images/exclamationCircle.svg new file mode 100644 index 0000000000000000000000000000000000000000..1f990e70261a4a2684a7b1ef1cbfc4a6deb87ba0 --- /dev/null +++ b/src/seal-module/assets/images/exclamationCircle.svg @@ -0,0 +1,6 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="27" height="27" viewBox="0 0 27 27"> + <g id="Group_10160" data-name="Group 10160" transform="translate(-402 -291)"> + <circle id="Ellipse_1" data-name="Ellipse 1" cx="13.5" cy="13.5" r="13.5" transform="translate(402 291)" fill="#fff"/> + <path id="Path_3133" data-name="Path 3133" d="M5.5-.5A2.5,2.5,0,0,0,3-3,2.5,2.5,0,0,0,.5-.5,2.5,2.5,0,0,0,3,2,2.5,2.5,0,0,0,5.5-.5ZM.789-13.212l.425,8.5A.75.75,0,0,0,1.963-4H4.037a.75.75,0,0,0,.749-.713l.425-8.5A.75.75,0,0,0,4.462-14H1.538A.75.75,0,0,0,.789-13.212Z" transform="translate(412.5 311)" fill="#00b3ca"/> + </g> +</svg> diff --git a/src/seal-module/assets/images/hash.png b/src/seal-module/assets/images/hash.png new file mode 100644 index 0000000000000000000000000000000000000000..792a3fa9f56420d3c7230925ee50396d5b0faa97 Binary files /dev/null and b/src/seal-module/assets/images/hash.png differ diff --git a/src/seal-module/assets/images/hourglass-step.png b/src/seal-module/assets/images/hourglass-step.png new file mode 100644 index 0000000000000000000000000000000000000000..f1ad0685e27a7cb8e1acc9da8b7610dbdaad31ff Binary files /dev/null and b/src/seal-module/assets/images/hourglass-step.png differ diff --git a/src/seal-module/assets/images/hourglass-step.svg b/src/seal-module/assets/images/hourglass-step.svg new file mode 100644 index 0000000000000000000000000000000000000000..f8d98de030120156d7af2ad6d40d5780f4b2d41c --- /dev/null +++ b/src/seal-module/assets/images/hourglass-step.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 38.71 51.66"><rect y="47.4" width="38.71" height="4.27" rx="0.89" style="fill:#fff"/><path d="M185,149.87c-9.73,0-17.63,11.09-17.83,24.86h35.66C202.59,161,194.68,149.87,185,149.87Zm0,6.48a11.77,11.77,0,0,1,11.39,9.59H173.57A11.76,11.76,0,0,1,185,156.35Z" transform="translate(-165.6 -127.33)" style="fill:#fff"/><rect width="38.71" height="4.27" rx="0.89" style="fill:#fff"/><path d="M167.18,131.6c.37,13.76,8.19,24.75,17.78,24.75s17.4-11,17.78-24.75Zm28.22,8.55H174.52a1.71,1.71,0,0,1-1.69-1.49l-.74-6h25.74l-.75,6A1.7,1.7,0,0,1,195.4,140.15Z" transform="translate(-165.6 -127.33)" style="fill:#fff"/></svg> \ No newline at end of file diff --git a/src/seal-module/assets/images/hourglass.png b/src/seal-module/assets/images/hourglass.png new file mode 100644 index 0000000000000000000000000000000000000000..a6bf71bc3af596005ee0a5a3ec769c070aab4f7f Binary files /dev/null and b/src/seal-module/assets/images/hourglass.png differ diff --git a/src/seal-module/assets/images/hourglass.svg b/src/seal-module/assets/images/hourglass.svg new file mode 100644 index 0000000000000000000000000000000000000000..29d78edc4c7b4e9f21d2f76bea21ac6711cf57d5 --- /dev/null +++ b/src/seal-module/assets/images/hourglass.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="34.5" height="46" viewBox="0 0 34.5 46"> + <path id="Path_3134" data-name="Path 3134" d="M33.062-37.375h.359A1.078,1.078,0,0,0,34.5-38.453v-.719a1.078,1.078,0,0,0-1.078-1.078H1.078A1.078,1.078,0,0,0,0-39.172v.719a1.078,1.078,0,0,0,1.078,1.078h.359c0,8.25,3.963,17.4,11.648,20.125C5.376-14.515,1.437-5.348,1.437,2.875H1.078A1.078,1.078,0,0,0,0,3.953v.719A1.078,1.078,0,0,0,1.078,5.75H33.422A1.078,1.078,0,0,0,34.5,4.672V3.953a1.078,1.078,0,0,0-1.078-1.078h-.359c0-8.25-3.963-17.4-11.648-20.125C29.124-19.985,33.062-29.152,33.062-37.375Zm-28.75,0H30.187c0,9.924-5.792,17.969-12.937,17.969S4.312-27.451,4.312-37.375ZM30.187,2.875H4.312c0-9.924,5.792-17.969,12.937-17.969S30.187-7.049,30.187,2.875Zm-5.96-29.926a1.077,1.077,0,0,0-.882-1.7H11.154a1.077,1.077,0,0,0-.882,1.7c.194.271.395.53.609.785a1.086,1.086,0,0,0,.831.391H22.788a1.086,1.086,0,0,0,.831-.391C23.833-26.52,24.033-26.78,24.227-27.051ZM8.839-2.875a1.08,1.08,0,0,0-1.042.8q-.1.379-.185.757A1.08,1.08,0,0,0,8.663,0H25.837a1.08,1.08,0,0,0,1.052-1.318c-.056-.253-.119-.509-.185-.757a1.08,1.08,0,0,0-1.042-.8Z" transform="translate(0 40.25)" fill="#00b3ca"/> +</svg> diff --git a/src/seal-module/assets/images/inbox.png b/src/seal-module/assets/images/inbox.png new file mode 100644 index 0000000000000000000000000000000000000000..56440e3b436c1b24c1f3ea208344fca63f1d1139 Binary files /dev/null and b/src/seal-module/assets/images/inbox.png differ diff --git a/src/seal-module/assets/images/inbox.svg b/src/seal-module/assets/images/inbox.svg new file mode 100644 index 0000000000000000000000000000000000000000..b2a098f82ca33e9635f059541ae52802a2b2b963 --- /dev/null +++ b/src/seal-module/assets/images/inbox.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><defs><style>.a{fill:#3C3C3C;}</style></defs><path class="a" d="M6.875-26.563h6.25a.625.625,0,0,0,.625-.625v-.625a.625.625,0,0,0-.625-.625H6.875a.625.625,0,0,0-.625.625v.625A.625.625,0,0,0,6.875-26.563ZM6.25-23.438a.625.625,0,0,0,.625.625h6.25a.625.625,0,0,0,.625-.625v-.625a.625.625,0,0,0-.625-.625H6.875a.625.625,0,0,0-.625.625ZM10-18.706A3.121,3.121,0,0,1,8.17-19.3L0-25.2v8.326A1.875,1.875,0,0,0,1.875-15h16.25A1.875,1.875,0,0,0,20-16.875V-25.2l-8.17,5.9A3.124,3.124,0,0,1,10-18.706Zm9.282-9.929c-.346-.271-.673-.526-1.157-.891V-31.25a1.875,1.875,0,0,0-1.875-1.875H13.221l-.353-.256C12.211-33.861,10.906-35.014,10-35c-.906-.014-2.211,1.139-2.868,1.619l-.353.256H3.75A1.875,1.875,0,0,0,1.875-31.25v1.724c-.483.364-.811.62-1.157.891A1.869,1.869,0,0,0,0-27.159v.416l3.75,2.709V-31.25h12.5v7.216L20-26.743v-.416A1.875,1.875,0,0,0,19.282-28.635Z" transform="translate(0 35)"/></svg> \ No newline at end of file diff --git a/src/seal-module/assets/images/index.ts b/src/seal-module/assets/images/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..e890b1e81c6e17005bf05a69e007aeb3381fe5fa --- /dev/null +++ b/src/seal-module/assets/images/index.ts @@ -0,0 +1,23 @@ +/* eslint-disable global-require */ +const Images = { + chainLinksImage: require('./chain-links.png'), + checkImage: require('./check.png'), + checkLogoImage: require('./check-logo.png'), + copyImage: require('./copy.png'), + documentsImage: require('./documents.png'), + downloadImage: require('./download.png'), + exclamationImage: require('./exclamation.png'), + exclamationCircleImage: require('./exclamationCircle.png'), + hashImage: require('./hash.png'), + hourglassImage: require('./hourglass.png'), + hourglassStepImage: require('./hourglass-step.png'), + inboxImage: require('./inbox.png'), + messagesImage: require('./messages.png'), + questionImage: require('./question.png'), + spinnerBlackImage: require('./spinner-black.png'), + spinnerWhiteImage: require('./spinner-white.png'), + timesImage: require('./times.png'), + vereignLogoImage: require('./vereign-logo.png'), +}; + +export default Images; diff --git a/src/seal-module/assets/images/messages.png b/src/seal-module/assets/images/messages.png new file mode 100644 index 0000000000000000000000000000000000000000..dc5a9c8aeb9c14de75f2cbf43d4ed708eb9530dc Binary files /dev/null and b/src/seal-module/assets/images/messages.png differ diff --git a/src/seal-module/assets/images/messages.svg b/src/seal-module/assets/images/messages.svg new file mode 100644 index 0000000000000000000000000000000000000000..292e61bd11c18e47b20b2effcbc9ffef1fc70b01 --- /dev/null +++ b/src/seal-module/assets/images/messages.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23.49 22.03"><path d="M7.23,7.32c0-3.8,3.56-6.74,8-6.74s8,3.08,8,6.88a6.46,6.46,0,0,1-1.9,4.16.62.62,0,0,0-.16.68c.13.28.13.28.66.67s.67.59.62.88-1.07.43-1.76.3a4.34,4.34,0,0,1-1.27-.38,4,4,0,0,0-2.56-.21" transform="translate(-0.14 -0.08)" style="fill:#fff;stroke:#272123;stroke-miterlimit:10"/><path d="M16.82,14.4c0,4-3.63,7.21-8.09,7.21a6.55,6.55,0,0,1-2.36-.45,3.75,3.75,0,0,0-.89-.28,5.8,5.8,0,0,0-1.22,0c-.28,0-.45,0-1.35.07s-1.22-.12-1.43-.38a1.15,1.15,0,0,1-.13-1.23,3,3,0,0,0,.44-.87.9.9,0,0,0-.14-.54,6.62,6.62,0,0,1-1-3.5c0-4,3.62-7.2,8.09-7.2,4.14,0,7.57,2.77,8,6.36l0,.64A1.34,1.34,0,0,1,16.82,14.4Z" transform="translate(-0.14 -0.08)" style="fill:#fff;stroke:#272123;stroke-miterlimit:10"/><path d="M6.25,13.49a.91.91,0,1,0,.91.91A.91.91,0,0,0,6.25,13.49Z" transform="translate(-0.14 -0.08)" style="fill:#231e20"/><path d="M8.91,13.49a.91.91,0,1,0,.91.91A.91.91,0,0,0,8.91,13.49Z" transform="translate(-0.14 -0.08)" style="fill:#231e20"/><path d="M11.63,13.49a.91.91,0,1,0,.91.91A.9.9,0,0,0,11.63,13.49Z" transform="translate(-0.14 -0.08)" style="fill:#231e20"/></svg> \ No newline at end of file diff --git a/src/seal-module/assets/images/question.png b/src/seal-module/assets/images/question.png new file mode 100644 index 0000000000000000000000000000000000000000..d7d0895e70bfb264e6bc752a3d9a8160d8a4b6df Binary files /dev/null and b/src/seal-module/assets/images/question.png differ diff --git a/src/seal-module/assets/images/question.svg b/src/seal-module/assets/images/question.svg new file mode 100644 index 0000000000000000000000000000000000000000..ba0116a6f9998128c81f3db7397f0cac1dd7890b --- /dev/null +++ b/src/seal-module/assets/images/question.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32.02 32.01"><path d="M30.74,9.77a16,16,0,1,0-8.51,21A16,16,0,0,0,30.74,9.77ZM15.64,24a2.1,2.1,0,1,1,2.1-2.1A2.1,2.1,0,0,1,15.64,24Zm1.83-6v.17a.72.72,0,0,1-.72.72H14.58a.72.72,0,0,1-.72-.72v-.29c0-1.86,1.4-2.59,2.47-3.2.91-.51,1.47-.85,1.47-1.53,0-.9-1.15-1.49-2.07-1.49a2.92,2.92,0,0,0-2.48,1.48.72.72,0,0,1-1,.13l-1.3-1a.73.73,0,0,1-.15-1A5.82,5.82,0,0,1,16,8.6c2.55,0,5.27,2,5.27,4.61C21.23,16.69,17.47,16.74,17.47,18Z" transform="translate(0.01 0.01)" style="fill:#fff"/></svg> \ No newline at end of file diff --git a/src/seal-module/assets/images/spinner-black.png b/src/seal-module/assets/images/spinner-black.png new file mode 100644 index 0000000000000000000000000000000000000000..1611fc2860de6adea356beda9e7a81a3b5be16c1 Binary files /dev/null and b/src/seal-module/assets/images/spinner-black.png differ diff --git a/src/seal-module/assets/images/spinner-black.svg b/src/seal-module/assets/images/spinner-black.svg new file mode 100644 index 0000000000000000000000000000000000000000..b201bb76c4333ced58df88c75b79a2eaefdc60ed --- /dev/null +++ b/src/seal-module/assets/images/spinner-black.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="34.233" height="34.232" viewBox="0 0 34.233 34.232" fill="#272123"> + <g id="Component_89_1" data-name="Component 89 – 1" transform="matrix(0.999, -0.035, 0.035, 0.999, 0, 1.155)"> + <path id="Subtraction_6" data-name="Subtraction 6" d="M-2271-189a15.894,15.894,0,0,1-11.313-4.686A15.9,15.9,0,0,1-2287-205a15.9,15.9,0,0,1,4.686-11.314A15.894,15.894,0,0,1-2271-221v4a12.014,12.014,0,0,0-12,12,12.014,12.014,0,0,0,12,12,12.014,12.014,0,0,0,12-12h4a15.892,15.892,0,0,1-4.687,11.314A15.9,15.9,0,0,1-2271-189Z" transform="matrix(0.999, -0.035, 0.035, 0.999, 2292.32, 141.667)"/> + </g> +</svg> diff --git a/src/seal-module/assets/images/spinner-white.png b/src/seal-module/assets/images/spinner-white.png new file mode 100644 index 0000000000000000000000000000000000000000..3e3b146c395e6b9b0b5205adf2b2599e1ae7e36b Binary files /dev/null and b/src/seal-module/assets/images/spinner-white.png differ diff --git a/src/seal-module/assets/images/spinner-white.svg b/src/seal-module/assets/images/spinner-white.svg new file mode 100644 index 0000000000000000000000000000000000000000..097d5a2976fc09bbc6cc53c1c9932c079d9096b7 --- /dev/null +++ b/src/seal-module/assets/images/spinner-white.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="34.233" height="34.232" viewBox="0 0 34.233 34.232" fill="#ffffff"> + <g id="Component_89_1" data-name="Component 89 – 1" transform="matrix(0.999, -0.035, 0.035, 0.999, 0, 1.155)"> + <path id="Subtraction_6" data-name="Subtraction 6" d="M-2271-189a15.894,15.894,0,0,1-11.313-4.686A15.9,15.9,0,0,1-2287-205a15.9,15.9,0,0,1,4.686-11.314A15.894,15.894,0,0,1-2271-221v4a12.014,12.014,0,0,0-12,12,12.014,12.014,0,0,0,12,12,12.014,12.014,0,0,0,12-12h4a15.892,15.892,0,0,1-4.687,11.314A15.9,15.9,0,0,1-2271-189Z" transform="matrix(0.999, -0.035, 0.035, 0.999, 2292.32, 141.667)"/> + </g> +</svg> diff --git a/src/seal-module/assets/images/times.png b/src/seal-module/assets/images/times.png new file mode 100644 index 0000000000000000000000000000000000000000..06a6d3ab77682ce082379bee38b910287c84713e Binary files /dev/null and b/src/seal-module/assets/images/times.png differ diff --git a/src/seal-module/assets/images/times.svg b/src/seal-module/assets/images/times.svg new file mode 100644 index 0000000000000000000000000000000000000000..84a6a44cf16f861b8b29152e0f94ea547eb03dca --- /dev/null +++ b/src/seal-module/assets/images/times.svg @@ -0,0 +1 @@ +<?xml version="1.0" ?><svg baseProfile="tiny" height="24px" id="Layer_1" version="1.2" viewBox="0 0 24 24" width="24px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path fill="#ffffff" d="M17.414,6.586c-0.78-0.781-2.048-0.781-2.828,0L12,9.172L9.414,6.586c-0.78-0.781-2.048-0.781-2.828,0 c-0.781,0.781-0.781,2.047,0,2.828L9.171,12l-2.585,2.586c-0.781,0.781-0.781,2.047,0,2.828C6.976,17.805,7.488,18,8,18 s1.024-0.195,1.414-0.586L12,14.828l2.586,2.586C14.976,17.805,15.488,18,16,18s1.024-0.195,1.414-0.586 c0.781-0.781,0.781-2.047,0-2.828L14.829,12l2.585-2.586C18.195,8.633,18.195,7.367,17.414,6.586z"/></svg> \ No newline at end of file diff --git a/src/seal-module/assets/images/vereign-logo.png b/src/seal-module/assets/images/vereign-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2706487b712626e82ea7f26ab10b8668276ffb9e Binary files /dev/null and b/src/seal-module/assets/images/vereign-logo.png differ diff --git a/src/seal-module/assets/images/vereign-logo.svg b/src/seal-module/assets/images/vereign-logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..f14a0452a659b69379c7a159c3f93f4794e7125d --- /dev/null +++ b/src/seal-module/assets/images/vereign-logo.svg @@ -0,0 +1,11 @@ +<svg id="Vereign_Logo" data-name="Vereign Logo" xmlns="http://www.w3.org/2000/svg" width="86.78" height="27.461" viewBox="0 0 86.78 27.461"> + <path id="Path_1" data-name="Path 1" d="M74.99,46.2a2.442,2.442,0,0,1,2.442-2.379A2.37,2.37,0,0,1,79.854,46.2Zm2.379-5.479c-4.1,0-6.669,2.761-6.669,7.094s2.549,6.945,6.817,6.966c3.5,0,5.968-1.784,6.393-4.545H79.96A2.349,2.349,0,0,1,77.581,51.7a2.559,2.559,0,0,1-2.655-2.718v-.3h9.048V47.454c0-4.1-2.57-6.754-6.605-6.754" transform="translate(-55.685 -32.056)" fill="#d7112b"/> + <path id="Path_2" data-name="Path 2" d="M143.033,44.115h-.085V41.588H138.7v13.4h4.375V47.938a2.588,2.588,0,0,1,2.825-2.91,3.908,3.908,0,0,1,1.38.255V41.566a3.164,3.164,0,0,0-1.1-.17c-1.572,0-2.655.913-3.143,2.74" transform="translate(-109.243 -32.604)" fill="#d7112b"/> + <path id="Path_3" data-name="Path 3" d="M183.89,46.2a2.442,2.442,0,0,1,2.442-2.379,2.37,2.37,0,0,1,2.421,2.379Zm2.379-5.479c-4.1,0-6.669,2.761-6.669,7.094s2.549,6.945,6.817,6.966c3.5,0,5.968-1.784,6.393-4.545h-3.95a2.331,2.331,0,0,1-2.379,1.465,2.559,2.559,0,0,1-2.655-2.718v-.3h9.048V47.454c0-4.1-2.57-6.754-6.605-6.754" transform="translate(-141.456 -32.056)" fill="#d7112b"/> + <rect id="Rectangle_3" data-name="Rectangle 3" width="4.354" height="13.401" transform="translate(52.628 8.984)" fill="#d7112b"/> + <path id="Path_4" data-name="Path 4" d="M249.65,11.9a2.136,2.136,0,1,0,2.23,2.124,2.129,2.129,0,0,0-2.23-2.124" transform="translate(-194.855 -9.373)" fill="#d7112b"/> + <path id="Path_5" data-name="Path 5" d="M281.066,51.658c-1.572,0-2.506-1.211-2.506-3.377s.956-3.483,2.506-3.483,2.527,1.338,2.527,3.483-.956,3.377-2.527,3.377m2.549-7.688h-.085a4.177,4.177,0,0,0-4.035-2.57c-3.356,0-5.395,2.57-5.395,6.86s2.124,6.626,5.331,6.626a4.172,4.172,0,0,0,4.078-2.379h.085v2.464c0,1.338-.871,2.23-2.549,2.23a2.252,2.252,0,0,1-2.357-1.317H274.44c.255,2.442,2.676,4.163,6.478,4.184,4.163,0,7.009-2,7.009-5.182v-13.3h-4.311Z" transform="translate(-215.886 -32.607)" fill="#d7112b"/> + <path id="Path_6" data-name="Path 6" d="M355.274,41.1a4.107,4.107,0,0,0-4.141,2.782h-.085V41.355H346.8v13.4h4.375V47.2a2.267,2.267,0,0,1,2.251-2.527c1.38,0,2.145.913,2.145,2.442v7.667h4.354v-8.6c0-3.186-1.657-5.055-4.651-5.055" transform="translate(-273.146 -32.371)" fill="#d7112b"/> + <path id="Path_7" data-name="Path 7" d="M16.332,0,8.219,13.762,5.586,8.9,0,8.814,7.9,22.7,18.817,4.375Z" fill="#d7112b"/> + <rect id="Rectangle_4" data-name="Rectangle 4" width="86.78" height="27.436" fill="none"/> +</svg> diff --git a/src/seal-module/components/App.tsx b/src/seal-module/components/App.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b9ef83d3f7358ac523cb233b9af7601d6e5a1368 --- /dev/null +++ b/src/seal-module/components/App.tsx @@ -0,0 +1,41 @@ +import React, { useEffect, useState } from 'react'; +import { ScrollView, StyleSheet, Text } from 'react-native'; +import '../services/injectCryptoServiceMobile'; +import { ColorPallet, TextTheme } from '../../theme/theme'; +import VerificationPageContainer from './VerificationPage'; +import config from '../config'; + +// import './App.scss'; +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: ColorPallet.grayscale.white, + }, + text: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + }, +}); + +interface Props { + url: string; +} + +const App: React.FC<Props> = ({ url }) => { + const [initialized, setInitialized] = useState(false); + useEffect(() => { + setInitialized(false); + (async () => { + await config.load(url); + setInitialized(true); + })(); + }, [url]); + return ( + <ScrollView style={styles.container}> + {initialized && <VerificationPageContainer url={url} />} + {!initialized && <Text style={styles.text}>Initializing</Text>} + </ScrollView> + ); +}; + +export default App; diff --git a/src/seal-module/components/Card/Card.scss b/src/seal-module/components/Card/Card.scss new file mode 100644 index 0000000000000000000000000000000000000000..76805aa8ebc5a61100a44a122599a6c490729a2d --- /dev/null +++ b/src/seal-module/components/Card/Card.scss @@ -0,0 +1,38 @@ +@import "../../styles/vars"; +@import "../../styles/colors"; +@import "../../styles/mixins"; + + +.card { + display: flex; + padding: 30px; + border-radius: 25px; + flex-direction: column; + box-shadow: $shadow; + + &--transparent { + color: $raisin-black; + background-color: rgba($white, 0); + } + + &--white { + color: $raisin-black; + background-color: $white; + } + &--turquoise-surf { + color: $white; + background-color: $turquoise-surf; + } + &--palatinate-purple { + color: $white; + background-color: $palatinate-purple; + } + &--black-live { + color: $white; + background-color: $black-live; + } + + @include respond-to(mobiles) { + padding: 20px; + } +} \ No newline at end of file diff --git a/src/seal-module/components/Card/index.tsx b/src/seal-module/components/Card/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..300186fdb0c1135e50e1a6568fc5f491cd3d139e --- /dev/null +++ b/src/seal-module/components/Card/index.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import { StyleSheet, View } from 'react-native'; +import { ColorPallet } from '../../../theme/theme'; + +const styles = StyleSheet.create({ + card: { + display: 'flex', + padding: '15px', + borderRadius: 20, + flexDirection: 'column', + }, + // cartTransparent: { + // color: $raisin-black, + // backgroundColor: ColorPallet. + // }, + // cartWhite: { + // color: $raisin-black, + // backgroundColor: $white + // }, + // cartTurquoiseSurf: { + // color: $white, + // backgroundColor: $turquoise-surf + // }, + // cartPalatinatePurple: { + // color: $white, + // backgroundColor: $palatinate-purple + // }, + // cartBlackLive: { + // color: $white, + // backgroundColor: $black-live + // }, +}); + +export type ColorsType = + | 'transparent' + | 'white' + | 'turquoiseSurf' + | 'palatinatePurple' + | 'blackLive'; + +export interface Props { + children?: any; + className?: string; + color: ColorsType; +} + +const COLORS = { + transparent: 'card--transparent', + white: 'card--white', + turquoiseSurf: 'card--turquoise-surf', + palatinatePurple: 'card--palatinate-purple', + blackLive: 'card--black-live', +}; + +const Card = ({ children, className, color }: Props) => { + const colorClass = COLORS[color]; + return ( + <View + style={styles.card} + // className={classnames('card', colorClass, className)} + > + {children} + </View> + ); +}; + +export default Card; diff --git a/src/seal-module/components/CardWithIcon/CardWithIcon.scss b/src/seal-module/components/CardWithIcon/CardWithIcon.scss new file mode 100644 index 0000000000000000000000000000000000000000..6e0a6c49592f62408403bf0a9a701cb9ce057dd1 --- /dev/null +++ b/src/seal-module/components/CardWithIcon/CardWithIcon.scss @@ -0,0 +1,35 @@ +@import "../../styles/colors"; +@import "../../styles/mixins"; + +.cardWithIcon { + position: relative; + margin-top: 50px; + padding-top: 60px !important; + padding-bottom: 60px !important; +} + +.cardWithIcon__circle { + display: flex; + position: absolute; + border-radius: 50%; + width: 100px; + height: 100px; + align-items: center; + justify-content: center; + top: -50px; + left: calc(50% - 50px); + box-shadow: 0px 3px 20px #00000029; + + &--white { + background-color: $white; + } + &--mauvelous { + background-color: $mauvelous; + } + &--red { + background-color: $vereign-red; + } + &--pastel-green { + background-color: $pastel-green; + } +} diff --git a/src/seal-module/components/CardWithIcon/CardWithIcon.tsx b/src/seal-module/components/CardWithIcon/CardWithIcon.tsx new file mode 100644 index 0000000000000000000000000000000000000000..28ef7a79b2dccd3bd55c5ff4203d708b4e81c936 --- /dev/null +++ b/src/seal-module/components/CardWithIcon/CardWithIcon.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import classnames from 'classnames'; + +import './CardWithIcon.scss'; +import Card, { Props as CardProps } from '../Card'; + +export type IconBgType = 'white' | 'red' | 'pastelGreen' | 'mauvelous'; + +export interface Props extends CardProps { + icon: any; + iconBg: IconBgType; +} + +const ICON_BG_COLORS = { + red: 'cardWithIcon__circle--red', + white: 'cardWithIcon__circle--white', + mauvelous: 'cardWithIcon__circle--mauvelous', + pastelGreen: 'cardWithIcon__circle--pastel-green', +}; + +const CardWithIcon = ({ + children, + icon, + iconBg, + className, + ...props +}: Props) => { + const circleClass = ICON_BG_COLORS[iconBg]; + return ( + <Card className={classnames('cardWithIcon', className)} {...props}> + <span className={classnames('cardWithIcon__circle', circleClass)}> + {icon} + </span> + {children} + </Card> + ); +}; + +export default CardWithIcon; diff --git a/src/seal-module/components/CardWithIcon/index.ts b/src/seal-module/components/CardWithIcon/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..9bf126bd01acc1087dd862ff3c8e8a729447b17c --- /dev/null +++ b/src/seal-module/components/CardWithIcon/index.ts @@ -0,0 +1,3 @@ +import CardWithIcon from './CardWithIcon'; + +export default CardWithIcon; diff --git a/src/seal-module/components/DetailsCard/DetailsCard.scss b/src/seal-module/components/DetailsCard/DetailsCard.scss new file mode 100644 index 0000000000000000000000000000000000000000..c03fc43471a92f7aefe4f3d35f0172eae5a5572a --- /dev/null +++ b/src/seal-module/components/DetailsCard/DetailsCard.scss @@ -0,0 +1,33 @@ +@import "../../styles/mixins"; +@import "../../styles/colors"; + +.details-card { + min-width: 580px; + + @include respond-to(mobiles) { + width: 100%; + min-width: 100%; + } +} + +.details-card__circle { + display: flex; + border-radius: 50%; + width: 44px; + height: 44px; + align-items: center; + justify-content: center; + margin-left: calc(50% - 22px); + margin-bottom: 16px; + + &--white { + background-color: $white; + } + &--black { + background-color: $raisin-black; + } +} + +.details-card__icon { + +} diff --git a/src/seal-module/components/DetailsCard/DetailsCard.tsx b/src/seal-module/components/DetailsCard/DetailsCard.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6e899a9ea77f4918f495591ff8641e2ff500ff54 --- /dev/null +++ b/src/seal-module/components/DetailsCard/DetailsCard.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import classnames from 'classnames'; + +import './DetailsCard.scss'; +import Icon from '../Icon'; +import Card, { ColorsType } from '../Card'; + +export type IconBgType = 'white' | 'black'; + +interface Props { + className?: string; + iconClassName?: string; + children: JSX.Element | JSX.Element[]; + color: ColorsType; + iconSrc?: any; + iconBgColor?: IconBgType; +} + +const ICON_BG_COLORS = { + white: 'details-card__circle--white', + black: 'details-card__circle--black', +}; + +const DetailsCard = ({ + iconSrc, + iconBgColor = 'white', + children, + className, + iconClassName, + color, +}: Props) => { + const circleClass = ICON_BG_COLORS[iconBgColor]; + return ( + <Card className={classnames('details-card', className)} color={color}> + {iconSrc && ( + <span + className={classnames( + 'details-card__circle', + circleClass, + iconClassName, + )} + > + <Icon width={20} height={20} src={iconSrc} /> + </span> + )} + {children} + </Card> + ); +}; + +export default DetailsCard; diff --git a/src/seal-module/components/DetailsCard/index.tsx b/src/seal-module/components/DetailsCard/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..8dde588abcb60db8f70f4dd6f5e7985cbcbcbc9b --- /dev/null +++ b/src/seal-module/components/DetailsCard/index.tsx @@ -0,0 +1,3 @@ +import DetailsCard from './DetailsCard'; + +export default DetailsCard; diff --git a/src/seal-module/components/Page/Page.scss b/src/seal-module/components/Page/Page.scss new file mode 100644 index 0000000000000000000000000000000000000000..85535bc0022ed46617174615976dce00b0bf0c9c --- /dev/null +++ b/src/seal-module/components/Page/Page.scss @@ -0,0 +1,15 @@ +@import "../../styles/colors"; +@import "../../styles/vars"; +@import "../../styles/mixins"; + +.page { + min-height: calc(100% - #{$header-height}); + display: flex; + flex-direction: column; + align-items: center; + flex: 1; + + @include respond-to(mobiles) { + min-height: calc(100% - #{$header-height-mobile}); + } +} diff --git a/src/seal-module/components/Page/Page.tsx b/src/seal-module/components/Page/Page.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e611b0cb3402d2cd75accf551fa43b798ec40f99 --- /dev/null +++ b/src/seal-module/components/Page/Page.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import classnames from 'classnames'; + +import './Page.scss'; + +interface Props { + children: any; + className?: string; +} + +const Page = ({ children, className }: Props) => { + return <main className={classnames('page', className)}>{children}</main>; +}; + +export default Page; diff --git a/src/seal-module/components/Page/index.ts b/src/seal-module/components/Page/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..12c3418bbc8ab05ef6e17bbe5994a615313fee3a --- /dev/null +++ b/src/seal-module/components/Page/index.ts @@ -0,0 +1,3 @@ +import Page from './Page'; + +export default Page; diff --git a/src/seal-module/components/Spinner/index.tsx b/src/seal-module/components/Spinner/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..bc4d124f1d27cff190de8ec4ffe3bdfe30df5234 --- /dev/null +++ b/src/seal-module/components/Spinner/index.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Image } from 'react-native'; +import Images from '../../assets/images'; + +type ColorsType = 'white' | 'black'; + +interface Props { + width?: number; + height?: number; + color?: ColorsType; +} + +const Spinner = ({ width, height, color = 'black' }: Props) => { + return ( + <Image + style={{ + width: width || 25, + height: height || 25, + }} + source={ + color === 'black' ? Images.spinnerBlackImage : Images.spinnerWhiteImage + } + /> + ); +}; + +export default Spinner; diff --git a/src/seal-module/components/VerificationPage/Details/BlockchainInfo/index.tsx b/src/seal-module/components/VerificationPage/Details/BlockchainInfo/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c0c7ea3124efe79bd810b40fac7a7e1211ab7dee --- /dev/null +++ b/src/seal-module/components/VerificationPage/Details/BlockchainInfo/index.tsx @@ -0,0 +1,117 @@ +import React from 'react'; +import { formatDistance } from 'date-fns'; + +// import './BlockchainInfo.scss'; + +import { VerificationData, StatusData } from '@vereign/light-utils/dist/types'; + +import { StyleSheet, Text, View } from 'react-native'; + +import { ColorPallet, TextTheme } from '../../../../../theme/theme'; + +const styles = StyleSheet.create({ + boxContainer: { + backgroundColor: ColorPallet.notification.info, + borderRadius: 5, + borderWidth: 1, + borderColor: ColorPallet.notification.infoBorder, + padding: 10, + marginTop: 10, + marginBottom: 20, + }, + text: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + }, + textBold: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + fontWeight: 'bold', + }, + h3: { + ...TextTheme.headingThree, + color: ColorPallet.baseColors.black, + }, + rowTextInputView: { + marginBottom: 10, + flexDirection: 'column', + }, +}); + +interface Props { + statusData?: StatusData; + verificationDetails?: VerificationData; + statusId?: string; +} + +const THRESHOLD_CONFIRMATIONS = 2; + +const BlockchainInfo = ({ + statusData, + verificationDetails, + statusId, +}: Props) => { + const confirmationsAmount = + verificationDetails?.blockData?.confirmationsAmount || -1; + + return ( + <View style={styles.boxContainer}> + <Text style={styles.h3}>Blockchain entry for this record</Text> + <View style={styles.rowTextInputView}> + <Text style={styles.textBold}>Block confirmations</Text> + <Text style={styles.text}> + {confirmationsAmount >= 0 ? confirmationsAmount : 'Unknown'} + </Text> + </View> + + <View style={styles.rowTextInputView}> + <Text style={styles.textBold}>Block age</Text> + <Text style={styles.text}> + {verificationDetails?.blockData?.timestamp + ? formatDistance( + verificationDetails.blockData.timestamp, + new Date(), + ) + : 'Unknown'} + </Text> + </View> + + <View style={styles.rowTextInputView}> + <Text style={styles.textBold}>Anchoring block</Text> + <Text style={styles.text}> + {verificationDetails?.blockData?.blockHeight + ? verificationDetails?.blockData?.blockHeight + : 'Unknown'} + </Text> + </View> + + <View style={styles.rowTextInputView}> + <Text style={styles.textBold}>Blockchain record</Text> + <Text style={styles.text}> + {statusData?.transactionHash + ? statusData?.transactionHash + : 'Unknown'} + </Text> + </View> + + <View style={styles.rowTextInputView}> + <Text style={styles.textBold}>Status in Block</Text> + <Text style={styles.text}> + {typeof verificationDetails?.batchVerificationDetails + ?.statusPosition === 'number' && + typeof verificationDetails?.batchVerificationDetails?.batchSize === + 'number' + ? `Status #${verificationDetails?.batchVerificationDetails.statusPosition} of ${verificationDetails?.batchVerificationDetails.batchSize}` + : 'Unknown'} + </Text> + </View> + + <View style={styles.rowTextInputView}> + <Text style={styles.textBold}>Seal Id</Text> + <Text style={styles.text}>{statusId || 'Unknown'}</Text> + </View> + </View> + ); +}; + +export default BlockchainInfo; diff --git a/src/seal-module/components/VerificationPage/Details/IPFSInfo/index.tsx b/src/seal-module/components/VerificationPage/Details/IPFSInfo/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..df3396fdf842b909db33fe6d5307fc2d01c43dba --- /dev/null +++ b/src/seal-module/components/VerificationPage/Details/IPFSInfo/index.tsx @@ -0,0 +1,117 @@ +import React from 'react'; +import { MessageData } from '@vereign/light-utils/dist/types'; +import { StyleSheet, Text, View } from 'react-native'; +import { truncateString } from '../../../../utils/stringUtils'; +import { ColorPallet, TextTheme } from '../../../../../theme/theme'; + +const styles = StyleSheet.create({ + boxContainer: { + backgroundColor: ColorPallet.notification.info, + borderRadius: 5, + borderWidth: 1, + borderColor: ColorPallet.notification.infoBorder, + padding: 10, + marginTop: 10, + marginBottom: 20, + }, + text: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + }, + textBold: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + fontWeight: 'bold', + }, + h3: { + ...TextTheme.headingThree, + color: ColorPallet.baseColors.black, + }, + rowTextInputView: { + marginBottom: 10, + flexDirection: 'column', + }, +}); + +interface Props { + qrCodeData?: MessageData; +} + +interface CIDData { + htmlCID: string | undefined; + plainTextCID: string | undefined; + attachmentsCIDs: string[] | undefined; + attachmentsNames: string[] | undefined; +} + +const IPFSInfo = ({ qrCodeData }: Props) => { + const [cidData, setcidData] = React.useState<CIDData>(); + + React.useEffect(() => { + let attachmentsCidArray: string[] | undefined = []; + attachmentsCidArray = qrCodeData?.ipfs?.attachments.map(a => { + return a.cid; + }); + + let attachmentsNameArray: string[] | undefined = []; + attachmentsNameArray = qrCodeData?.attachments.map(a => { + return a.name; + }); + + setcidData({ + htmlCID: qrCodeData?.ipfs?.html.cid, + plainTextCID: qrCodeData?.ipfs?.plaintText.cid, + attachmentsCIDs: attachmentsCidArray, + attachmentsNames: attachmentsNameArray, + }); + }, [qrCodeData]); + + function listAttachmentCIDs( + cidArr: string[] | undefined, + nameArr: string[] | undefined, + ) { + if ( + !cidArr || + (cidArr && cidArr.length < 1) || + !nameArr || + (nameArr && nameArr.length < 1) + ) { + return null; + } + + const elementArray = []; + + for (let i = 0; i < cidArr?.length; i += 1) { + elementArray.push( + <View style={styles.rowTextInputView}> + <Text style={styles.textBold}> + Attachment: '{truncateString(nameArr[i], 24) || 'N/A'}' + </Text> + <Text style={styles.text}>{cidArr[i] || 'Unknown'}</Text> + </View>, + ); + } + + return elementArray; + } + + return ( + <View style={styles.boxContainer}> + <Text style={styles.h3}>IPFS CIDs for this record</Text> + + <View style={styles.rowTextInputView}> + <Text style={styles.textBold}>HTML</Text> + <Text style={styles.text}>{cidData?.htmlCID || 'N/A'}</Text> + </View> + + <View style={styles.rowTextInputView}> + <Text style={styles.textBold}>Plain Text</Text> + <Text style={styles.text}>{cidData?.plainTextCID || 'N/A'}</Text> + </View> + + {listAttachmentCIDs(cidData?.attachmentsCIDs, cidData?.attachmentsNames)} + </View> + ); +}; + +export default IPFSInfo; diff --git a/src/seal-module/components/VerificationPage/Details/VerificationStepCard/index.tsx b/src/seal-module/components/VerificationPage/Details/VerificationStepCard/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6ed5516a65e81577b2c7936a846fee3dfe838be5 --- /dev/null +++ b/src/seal-module/components/VerificationPage/Details/VerificationStepCard/index.tsx @@ -0,0 +1,118 @@ +import React, { useEffect, useState } from 'react'; +import { Image, StyleSheet, View, Text } from 'react-native'; +import Spinner from '../../../Spinner'; +import Images from '../../../../assets/images'; + +import { + STATE_ERROR, + STATE_PENDING, + STATE_STATUS_DATA_PENDING, + STATE_TAIL_PENDING, + STATE_UNVERIFIED, +} from '../../../../hooks/useVerificationFlow'; +import { ColorPallet, TextTheme } from '../../../../../theme/theme'; + +interface Props { + title: string; + value?: any; + targetState: number; + verificationState: number; +} + +const styles = StyleSheet.create({ + boxContainer: { + backgroundColor: ColorPallet.notification.info, + borderRadius: 5, + borderWidth: 1, + borderColor: ColorPallet.notification.infoBorder, + padding: 10, + marginTop: 10, + marginBottom: 20, + flexDirection: 'row', + }, + text: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + }, + h3: { + ...TextTheme.headingThree, + color: ColorPallet.baseColors.black, + }, + labels: { + marginLeft: 6, + }, +}); + +const STATUS_ERROR = 'STATUS_ERROR'; +const STATUS_NOT_VERIFIED = 'STATUS_NOT_VERIFIED'; +const STATUS_PENDING = 'STATUS_PENDING'; +const STATUS_LOADING = 'STATUS_LOADING'; +const STATUS_COMPLETED = 'STATUS_COMPLETED'; + +const VerificationStepCard = ({ + title, + value, + targetState, + verificationState, +}: Props) => { + const [status, setStatus] = useState<string>(STATUS_LOADING); + + useEffect(() => { + if (verificationState === STATE_ERROR) { + setStatus(STATUS_ERROR); + } else if (verificationState === STATE_UNVERIFIED) { + setStatus(STATUS_NOT_VERIFIED); + } else if ( + verificationState === STATE_STATUS_DATA_PENDING || + verificationState === STATE_TAIL_PENDING || + verificationState === STATE_PENDING + ) { + setStatus(STATUS_PENDING); + } else if (targetState < verificationState) { + setStatus(STATUS_COMPLETED); + } + }, [targetState, verificationState, status]); + + const icon = (() => { + switch (status) { + case STATUS_LOADING: + return <Spinner color="white" width={24} height={24} />; + case STATUS_COMPLETED: + return ( + <Image source={Images.checkImage} style={{ width: 24, height: 24 }} /> + ); + case STATUS_PENDING: + return ( + <Image + source={Images.hourglassImage} + style={{ width: 24, height: 24 }} + /> + ); + case STATUS_NOT_VERIFIED: + return ( + <Image + source={Images.questionImage} + style={{ width: 24, height: 24 }} + /> + ); + default: + return ( + <Image + source={Images.exclamationImage} + style={{ width: 24, height: 24 }} + /> + ); + } + })(); + return ( + <View style={styles.boxContainer}> + {icon} + <View style={styles.labels}> + <Text style={styles.h3}>{title}</Text> + <Text style={styles.text}>{value}</Text> + </View> + </View> + ); +}; + +export default VerificationStepCard; diff --git a/src/seal-module/components/VerificationPage/Details/index.tsx b/src/seal-module/components/VerificationPage/Details/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5b52e335c93311b79f8140f5dc974083b51a8530 --- /dev/null +++ b/src/seal-module/components/VerificationPage/Details/index.tsx @@ -0,0 +1,194 @@ +import React from 'react'; +import { format } from 'date-fns'; + +import { + MessageData, + StatusData, + VerificationData, +} from '@vereign/light-utils'; +import { StyleSheet, Text, View } from 'react-native'; +import { + STATE_ERROR, + STATE_LOADING_STATUS_DATA, + STATE_PENDING, + STATE_STATUS_DATA_PENDING, + STATE_TAIL_PENDING, + STATE_UNVERIFIED, + STATE_VERIFYING_ATTACHMENTS, + STATE_VERIFYING_RECEIVERS, + STATE_VERIFYING_SENDER, +} from '../../../hooks/useVerificationFlow'; + +import VerificationStepCard from './VerificationStepCard'; + +import BlockchainInfo from './BlockchainInfo'; +import IPFSInfo from './IPFSInfo'; +import { ColorPallet, TextTheme } from '../../../../theme/theme'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + boxContainer: { + backgroundColor: ColorPallet.notification.info, + borderRadius: 5, + borderWidth: 1, + borderColor: ColorPallet.notification.infoBorder, + padding: 10, + marginTop: 10, + marginBottom: 20, + }, + text: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + }, + h3: { + ...TextTheme.headingThree, + color: ColorPallet.baseColors.black, + }, + h4: { + ...TextTheme.headingFour, + color: ColorPallet.baseColors.black, + }, + column: {}, +}); + +interface Props { + verificationState: number; + error?: Error; + className?: string; + sealTime?: number; + sentTime?: number; + senderStatusData?: StatusData; + senderVerificationDetails?: VerificationData; + qrCodeData?: MessageData; + numReceiversVerified: number; + sealId?: string; +} + +const Details = ({ + verificationState, + error, + className, + sealTime, + sentTime, + senderStatusData, + senderVerificationDetails, + numReceiversVerified, + qrCodeData, + sealId, +}: Props) => { + const getVerificationStatusText = () => { + switch (verificationState) { + case STATE_LOADING_STATUS_DATA: + return 'Loading statuses data'; + case STATE_VERIFYING_SENDER: + return "Verifying sender's status"; + case STATE_VERIFYING_RECEIVERS: + return 'Verifying statuses of receivers'; + case STATE_VERIFYING_ATTACHMENTS: + return 'Verifying attachments'; + case STATE_STATUS_DATA_PENDING: + return 'Pending for anchoring in blockchain. Please try again later.'; + case STATE_TAIL_PENDING: + return 'Seal tail is pending to be uploaded. Please try again later.'; + case STATE_ERROR: + return 'Something went wrong. Please try again later.'; + case STATE_UNVERIFIED: + return error?.message; + default: + return 'Chain of verification confirmed'; + } + }; + + const getRecipientsAmount = (messageData?: MessageData): number => { + let amount = 0; + + if (messageData?.recipients) { + Object.values(messageData?.recipients).forEach(recipientsList => { + if (Array.isArray(recipientsList)) { + amount += recipientsList.length; + } + }); + } + + return amount; + }; + const recipientsAmount = getRecipientsAmount(qrCodeData); + + return ( + <View> + <Text style={styles.h3}>Status: {getVerificationStatusText()}</Text> + + <View style={styles.boxContainer}> + <VerificationStepCard + title="Sent" + value={sentTime ? format(sentTime, 'dd/MM/yy\xa0HH:mm:ss') : ''} + targetState={STATE_LOADING_STATUS_DATA} + verificationState={verificationState} + /> + <VerificationStepCard + title="Sealed" + value={sealTime ? format(sealTime, 'dd/MM/yy\xa0HH:mm:ss') : ''} + targetState={STATE_VERIFYING_SENDER} + verificationState={verificationState} + /> + <VerificationStepCard + title="Confirmations" + value={ + verificationState > STATE_VERIFYING_RECEIVERS && + recipientsAmount !== 0 && + `Received and verified by\xa0${numReceiversVerified}/${recipientsAmount} recipients` + } + targetState={STATE_VERIFYING_RECEIVERS} + verificationState={ + verificationState > STATE_VERIFYING_RECEIVERS && + numReceiversVerified === 0 && + recipientsAmount !== 0 + ? STATE_PENDING + : verificationState + } + /> + <VerificationStepCard + title="Attachments" + value={(() => { + if ( + verificationState === STATE_UNVERIFIED || + verificationState === STATE_ERROR + ) { + return 'Unverified'; + } + + if (qrCodeData && verificationState > STATE_VERIFYING_ATTACHMENTS) { + if (numReceiversVerified > 0) { + return qrCodeData?.attachments?.length + ? 'Verified' + : 'No attachments'; + } + return 'Pending verification'; + } + return ''; + })()} + targetState={STATE_VERIFYING_ATTACHMENTS} + verificationState={ + verificationState > STATE_VERIFYING_ATTACHMENTS && + numReceiversVerified === 0 && + recipientsAmount !== 0 + ? STATE_PENDING + : verificationState + } + /> + </View> + + <BlockchainInfo + verificationDetails={senderVerificationDetails} + statusData={senderStatusData} + statusId={sealId} + /> + + <IPFSInfo qrCodeData={qrCodeData} /> + </View> + ); +}; + +export default Details; diff --git a/src/seal-module/components/VerificationPage/EmailVerification/AttachmentsCard/index.tsx b/src/seal-module/components/VerificationPage/EmailVerification/AttachmentsCard/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a30679dbc6f804c8c76eb73662cef3389ee13f01 --- /dev/null +++ b/src/seal-module/components/VerificationPage/EmailVerification/AttachmentsCard/index.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import { MessageData } from '@vereign/light-utils/dist/types'; +import { StyleSheet, Text, View } from 'react-native'; +import useIpfsAttachments from '../../../../hooks/useIpfsAttachments'; +import { ColorPallet, TextTheme } from '../../../../../theme/theme'; +import Spinner from '../../../Spinner'; + +const styles = StyleSheet.create({ + boxContainer: { + backgroundColor: ColorPallet.notification.info, + borderRadius: 5, + borderWidth: 1, + borderColor: ColorPallet.notification.infoBorder, + padding: 10, + marginTop: 10, + marginBottom: 20, + }, + text: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + }, + attachment: { + flex: 1, + flexDirection: 'row', + alignItems: 'flex-start', + margin: 10, + }, + h3: { + ...TextTheme.headingThree, + color: ColorPallet.baseColors.black, + }, +}); + +interface Props { + qrCodeData?: MessageData; +} + +const AttachmentsCard = ({ qrCodeData }: Props) => { + const attachments = qrCodeData?.attachments; + const ipfs = qrCodeData?.ipfs; + + const { loadingHashes, downloadAttachment } = useIpfsAttachments(ipfs); + + let body = null; + if (attachments?.length) { + body = attachments.map((attachment, i) => ( + // eslint-disable-next-line react/no-array-index-key + <View key={i} style={styles.attachment}> + <View> + {loadingHashes[attachment.hash] && ( + <Spinner color="white" width={24} height={24} /> + )} + </View> + <Text + style={styles.text} + onPress={() => downloadAttachment(attachment.hash, attachment.name)} + > + {attachment?.name} + </Text> + </View> + )); + } + return ( + <View style={styles.boxContainer}> + <Text style={styles.h3}>Attachments</Text> + {attachments?.length ? ( + body + ) : ( + <Text style={styles.text}>No attachments</Text> + )} + </View> + ); +}; + +export default AttachmentsCard; diff --git a/src/seal-module/components/VerificationPage/EmailVerification/IPFSCard/IPFSCard.scss b/src/seal-module/components/VerificationPage/EmailVerification/IPFSCard/IPFSCard.scss new file mode 100644 index 0000000000000000000000000000000000000000..57af07d49cdb509af6e198c4b61b328edb94aade --- /dev/null +++ b/src/seal-module/components/VerificationPage/EmailVerification/IPFSCard/IPFSCard.scss @@ -0,0 +1,60 @@ +@import "../../../../styles/colors"; +@import "../../../../styles/utils"; +@import "../../../../styles/mixins"; + + +.ipfs-card { + margin-bottom: 20px; + + & * { + min-width: auto !important; + max-width: 100% !important; + word-break: break-word; + } +} + +.ipfs-card__section-main { + display: flex; + flex-direction: column; + align-items: center; +} + +.ipfs-card__header { + font-size: 24px; + line-height: 28px; + margin-bottom: 24px; + font-family: "Helvetica Neue Bold", Arial, sans-serif; +} + +.ipfs-card__content { + max-height: 500px; + overflow: hidden; + position: relative; +} + +.ipfs-card__content--full { + max-height: none; + overflow-x: scroll; + overflow-y: hidden; +} + +.ipfs-card__blackout { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 230px; + background: linear-gradient(180deg, #FFFFFF00 0%, #FFFFFFD5 60%, #FFFFFF 100%); +} + +.ipfs-card__plainText { + word-break: break-word; +} + +.ipfs-card__expand { + color: $palatinate-purple; + padding: 16px 11px; + font-family: "Helvetica Neue Bold", Arial, sans-serif; + border-bottom: 2px solid $palatinate-purple; + cursor: pointer; +} \ No newline at end of file diff --git a/src/seal-module/components/VerificationPage/EmailVerification/IPFSCard/index.tsx b/src/seal-module/components/VerificationPage/EmailVerification/IPFSCard/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b8a2af557e0c0b55a5f45f390b599d982f6396e6 --- /dev/null +++ b/src/seal-module/components/VerificationPage/EmailVerification/IPFSCard/index.tsx @@ -0,0 +1,53 @@ +import React from 'react'; +import { MessageData } from '@vereign/light-utils/dist/types'; +import { StyleSheet, Text, View, useWindowDimensions } from 'react-native'; +import RenderHtml from 'react-native-render-html'; +import useIpfs from '../../../../hooks/useIpfs'; +import { ColorPallet, TextTheme } from '../../../../../theme/theme'; + +const styles = StyleSheet.create({ + boxContainer: { + backgroundColor: ColorPallet.notification.info, + borderRadius: 5, + borderWidth: 1, + borderColor: ColorPallet.notification.infoBorder, + padding: 10, + marginTop: 10, + marginBottom: 20, + }, + text: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + }, + h3: { + ...TextTheme.headingThree, + color: ColorPallet.baseColors.black, + }, +}); + +interface Props { + qrCodeData?: MessageData; +} + +const IPFSCard = ({ qrCodeData }: Props) => { + const ipfs = qrCodeData?.ipfs; + const { width } = useWindowDimensions(); + const { html, plainText } = useIpfs(ipfs); + + if (!ipfs) { + return null; + } + + const source = { + html, + }; + + return ( + <View style={styles.boxContainer}> + <Text style={styles.h3}>Email Content</Text> + <RenderHtml contentWidth={width - 30} source={source} /> + </View> + ); +}; + +export default IPFSCard; diff --git a/src/seal-module/components/VerificationPage/EmailVerification/MessageDetailsCard/index.tsx b/src/seal-module/components/VerificationPage/EmailVerification/MessageDetailsCard/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..879c9dcafba6681863d07d5c6b3866ca663d6b04 --- /dev/null +++ b/src/seal-module/components/VerificationPage/EmailVerification/MessageDetailsCard/index.tsx @@ -0,0 +1,129 @@ +import React, { useMemo } from 'react'; +import { format } from 'date-fns'; +import { MessageData, Participant } from '@vereign/light-utils/dist/types'; +import { StyleSheet, Text, View } from 'react-native'; +import { STATE_LOADING_STATUS_DATA } from '../../../../hooks/useVerificationFlow'; +import { ColorPallet, TextTheme } from '../../../../../theme/theme'; + +const styles = StyleSheet.create({ + boxContainer: { + backgroundColor: ColorPallet.notification.info, + borderRadius: 5, + borderWidth: 1, + borderColor: ColorPallet.notification.infoBorder, + padding: 10, + marginTop: 10, + marginBottom: 20, + }, + text: { + ...TextTheme.normal, + color: ColorPallet.baseColors.black, + }, + h3: { + ...TextTheme.headingThree, + color: ColorPallet.baseColors.black, + }, + h4: { + ...TextTheme.headingFour, + color: ColorPallet.baseColors.black, + }, + column: {}, +}); + +interface Props { + verificationState: number; + qrCodeData?: MessageData; +} + +const MessageDetailsCard = ({ verificationState, qrCodeData }: Props) => { + const loading = verificationState === STATE_LOADING_STATUS_DATA; + + const renderSentDate = (sentDate?: string) => { + if (sentDate) { + return ( + <Text style={styles.h4}> + {format(new Date(sentDate), 'dd/MM/yy\xa0HH:mm:ss')} + </Text> + ); + } + return null; + }; + + const renderSubject = (subject?: string) => { + if (loading) { + return null; + } + return ( + <Text style={styles.h3}>{subject === '' ? 'No subject' : subject}</Text> + ); + }; + + const renderSender = (sender?: Participant) => { + if (loading || !sender) { + return null; + } + + const senderEmail = sender.email && ( + <Text style={styles.text}>{sender.email}</Text> + ); + + return <View style={styles.column}>{senderEmail}</View>; + }; + + const renderRecipients = (recipients?: Array<Participant>) => { + if (loading || !Array.isArray(recipients)) { + return null; + } + + return recipients.map(recipient => ( + <Text style={styles.text} key={recipient.email}> + {recipient.email && `${recipient.email}`} + </Text> + )); + }; + + const recipients = useMemo(() => { + let result: Participant[] = []; + if (qrCodeData?.recipients?.to) { + result = [...qrCodeData.recipients.to]; + } + + if (qrCodeData?.recipients?.cc) { + result = [...result, ...qrCodeData.recipients.cc]; + } + + return result; + }, [qrCodeData]); + + if (loading) { + return ( + <View style={styles.boxContainer}> + <Text style={styles.text}>Loading</Text> + </View> + ); + } + + return ( + <View style={styles.boxContainer}> + {!qrCodeData && <Text style={styles.text}>No data</Text>} + {qrCodeData && ( + <View style={styles.column}> + {renderSentDate(qrCodeData?.date)} + {renderSubject(qrCodeData?.subject)} + </View> + )} + <View style={styles.column}> + <Text style={styles.h3}>Sender</Text> + <View style={styles.column}>{renderSender(qrCodeData?.sender)}</View> + </View> + <View style={styles.column}> + <Text style={styles.h3}> + {recipients.length ? 'Recipients' : 'No Recipients'} + </Text> + <View style={styles.column}>{renderRecipients(recipients)}</View> + </View> + </View> + ); +}; + +export default MessageDetailsCard; diff --git a/src/seal-module/components/VerificationPage/EmailVerification/ProgressCard/index.tsx b/src/seal-module/components/VerificationPage/EmailVerification/ProgressCard/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f0483361adcfd10c53a15e3e77e999a8a79afb81 --- /dev/null +++ b/src/seal-module/components/VerificationPage/EmailVerification/ProgressCard/index.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { format } from 'date-fns'; + +import { StyleSheet, View, Text } from 'react-native'; +import { + STATE_ERROR, + STATE_STATUS_DATA_PENDING, + STATE_TAIL_PENDING, + STATE_UNVERIFIED, +} from '../../../../hooks/useVerificationFlow'; +import { ColorsType } from '../../../Card'; +import { TextTheme } from '../../../../../theme/theme'; + +const styles = StyleSheet.create({ + progressCard: { + width: '100%', + marginBottom: 20, + }, + label: { + ...TextTheme.normal, + textAlign: 'center', + }, +}); + +interface Props { + verificationState: number; + sealTime: number; +} + +const DATE_FORMAT_MOBILE = 'dd/MM/yy HH:mm:ss'; + +const ProgressCard = ({ verificationState, sealTime }: Props) => { + let cardColor: ColorsType = 'white'; + const cardLabel = (() => { + switch (true) { + case verificationState === STATE_ERROR: + return 'Error'; + case verificationState === STATE_UNVERIFIED: + return 'Unverified'; + case verificationState === STATE_STATUS_DATA_PENDING || + verificationState === STATE_TAIL_PENDING: + return 'Pending'; + case !!sealTime: + cardColor = 'turquoiseSurf'; + return `Sealed on ${format(sealTime, DATE_FORMAT_MOBILE)}`; + default: + return 'Working'; + } + })(); + + return ( + <View style={styles.progressCard}> + <Text style={styles.label}>{cardLabel}</Text> + </View> + ); +}; + +export default ProgressCard; diff --git a/src/seal-module/components/VerificationPage/EmailVerification/index.tsx b/src/seal-module/components/VerificationPage/EmailVerification/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5d5ef133cc4ecac18fcdb691d57f03a760dcc28c --- /dev/null +++ b/src/seal-module/components/VerificationPage/EmailVerification/index.tsx @@ -0,0 +1,50 @@ +import React from 'react'; + +// import './EmailVerification.scss'; +import { MessageData } from '@vereign/light-utils'; +import { StyleSheet, Text, View } from 'react-native'; +import ProgressCard from './ProgressCard'; +import MessageDetailsCard from './MessageDetailsCard'; +import IPFSCard from './IPFSCard'; +import AttachmentsCard from './AttachmentsCard'; +// import { STATE_VERIFICATION_COMPLETED } from '../../../hooks/useVerificationFlow'; +// import VerifiedCard from './VerifiedCard'; +// import StoresCard from './StoresCard'; +import { ColorPallet, TextTheme } from '../../../../theme/theme'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}); + +interface Props { + verificationState: number; + sealTime: number; + qrCodeData?: MessageData; + numReceiversVerified: number; +} + +const EmailVerification = ({ + verificationState, + sealTime, + qrCodeData, + numReceiversVerified, +}: Props) => { + return ( + <View style={styles.container}> + <ProgressCard verificationState={verificationState} sealTime={sealTime} /> + <MessageDetailsCard + qrCodeData={qrCodeData} + verificationState={verificationState} + /> + <IPFSCard qrCodeData={qrCodeData} /> + <AttachmentsCard qrCodeData={qrCodeData} /> + {/* {verificationState === STATE_VERIFICATION_COMPLETED && */} + {/* numReceiversVerified > 0 && <VerifiedCard />} */} + {/* <StoresCard /> */} + </View> + ); +}; + +export default EmailVerification; diff --git a/src/seal-module/components/VerificationPage/VerificaionPage.scss b/src/seal-module/components/VerificationPage/VerificaionPage.scss new file mode 100644 index 0000000000000000000000000000000000000000..b2d9484d2fd06e68b2c74a5baeaa6e4bd060437d --- /dev/null +++ b/src/seal-module/components/VerificationPage/VerificaionPage.scss @@ -0,0 +1,125 @@ +@import "../../styles/colors"; +@import "../../styles/vars"; +@import "../../styles/utils"; +@import "../../styles/mixins"; + +.verification-page__tabs { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +.verification-page__tabs-tabbar { + background: $white; + height: 50px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: $shadow-down; + + @include respond-to(mobiles) { + grid-template-columns: auto auto; + } +} + +.verification-page__tab-content { + display: flex; + flex-direction: column; + align-items: center; + max-width: 100%; + + @include respond-to(mobiles) { + padding: 5% 5% 0 5%; + } +} +.verification-page__tab-content__verification { + @extend .verification-page__tab-content; + padding: 48px 48px 0 48px; +} +.verification-page__tab-content__details { + @extend .verification-page__tab-content; + padding: 30px 48px 25px 48px; +} + +.verification-page__section-info { + margin-top: 30px; + position: relative; + display: flex; + justify-content: center; + animation: summary-animation 0.3s ease; + + @include respond-to(mobiles) { + animation: summary-animation--mobile 0.3s ease; + flex-direction: column; + margin: 0; + width: 100%; + } +} + +@keyframes summary-animation { + 0% { + margin-top: 150px; + opacity: 0; + } + 100% { + margin-top: 30px; + opacity: 1; + } +} + +@keyframes summary-animation--mobile { + 0% { + margin-top: 150px; + opacity: 0; + } + 100% { + margin-top: 0; + opacity: 1; + } +} + +@keyframes steps-animation { + 0% { + margin-top: 150px; + opacity: 0; + } + 100% { + margin-top: 0; + opacity: 1; + } +} + +@keyframes steps-animation--mobile { + 0% { + margin-top: 150px; + opacity: 0; + } + 100% { + margin-top: 0; + opacity: 1; + } +} + + + +.verification-outcome-details { + margin-top: 22px; + margin-bottom: 22px; + height: 41px; +} + +.verification-page__section-verification-details { + margin-top: 30px; + margin-bottom: 30px; + + @include respond-to(mobiles) { + margin-top: 20px; + margin-bottom: 20px; + width: 100%; + } +} + +.attachments-details-section { + margin-top: 30px; +} diff --git a/src/seal-module/components/VerificationPage/VerificationPage.tsx b/src/seal-module/components/VerificationPage/VerificationPage.tsx new file mode 100644 index 0000000000000000000000000000000000000000..10f008479ab5037a5ea5fe0ede648d283ac2a994 --- /dev/null +++ b/src/seal-module/components/VerificationPage/VerificationPage.tsx @@ -0,0 +1,70 @@ +import React from 'react'; + +import { StyleSheet, View } from 'react-native'; + +import { + MessageData, + SenderStatusObject, + StatusData, + VerificationData, +} from '@vereign/light-utils/dist/types'; +import EmailVerification from './EmailVerification'; +import Details from './Details'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}); + +interface Props { + senderVerificationDetails?: VerificationData; + senderStatusData?: StatusData; + receiversVerificationDetails?: { [key: string]: VerificationData }; + verificationState: number; + qrCodeData?: MessageData; + error?: Error; + sealId?: string; +} + +const VerificationPage = ({ + senderStatusData, + senderVerificationDetails, + receiversVerificationDetails, + qrCodeData, + verificationState, + error, + sealId, +}: Props) => { + const sentTime = (senderStatusData?.status as SenderStatusObject) + ?.signatureTime; + const sealTime = senderVerificationDetails?.txData?.time || 0; + + const numReceiversVerified = receiversVerificationDetails + ? Object.keys(receiversVerificationDetails).length + : 0; + + return ( + <View style={styles.container}> + <EmailVerification + verificationState={verificationState} + sealTime={sealTime} + qrCodeData={qrCodeData} + numReceiversVerified={numReceiversVerified} + /> + <Details + verificationState={verificationState} + error={error} + sealId={sealId} + sealTime={sealTime} + sentTime={sentTime} + qrCodeData={qrCodeData} + senderStatusData={senderStatusData} + senderVerificationDetails={senderVerificationDetails} + numReceiversVerified={numReceiversVerified} + /> + </View> + ); +}; + +export default VerificationPage; diff --git a/src/seal-module/components/VerificationPage/VerificationPageContainer.tsx b/src/seal-module/components/VerificationPage/VerificationPageContainer.tsx new file mode 100644 index 0000000000000000000000000000000000000000..bff47f6c7c3359cd00194e2d725db58db2f1b9f1 --- /dev/null +++ b/src/seal-module/components/VerificationPage/VerificationPageContainer.tsx @@ -0,0 +1,200 @@ +import React, { useEffect, useState } from 'react'; +import { SenderStatusObject } from '@vereign/light-utils/dist/types'; +import VerificationError from '@vereign/light-utils/dist/services/VerificationService/VerificationError'; +import VerificationPage from './VerificationPage'; +import useVerificationFlow, { + STATE_ERROR, + STATE_LOADING_STATUS_DATA, + STATE_STATUS_DATA_PENDING, + STATE_TAIL_PENDING, + STATE_UNVERIFIED, + STATE_VERIFICATION_COMPLETED, + STATE_VERIFYING_ATTACHMENTS, + STATE_VERIFYING_RECEIVERS, + STATE_VERIFYING_SENDER, +} from '../../hooks/useVerificationFlow'; +import useQrCodeData, { + TAIL_PENDING_ERROR_MESSAGE, +} from '../../hooks/useQrCodeData'; +import useStatuses from '../../hooks/useStatuses'; +import useSealQrCodes from '../../../hooks/useSealQrCodes'; + +interface Props { + url: string; +} + +const VerificationPageContainer: React.FC<Props> = ({ url }) => { + const { updateSealedQrCodeSubject } = useSealQrCodes(); + const [error, setError] = useState<Error>(); + const [verificationState, setVerificationState] = useState<number>( + STATE_LOADING_STATUS_DATA, + ); + const { + qrCodeData, + sealId, + sealHash, + error: qrCodeDataError, + } = useQrCodeData(url); + useEffect(() => { + if (qrCodeData?.subject) { + updateSealedQrCodeSubject(url, qrCodeData.subject); + } + }, [url, updateSealedQrCodeSubject, qrCodeData, qrCodeData?.subject]); + + const { + statusesData, + senderStatusData, + receiversStatusesData, + error: readingStatusesError, + } = useStatuses(sealId, qrCodeData?.senderPublicKeyUuid, sealHash); + + const { + senderVerificationDetails, + receiversVerificationDetails, + error: verificationFlowError, + } = useVerificationFlow(senderStatusData, receiversStatusesData); + + useEffect( + () => readingStatusesError && setError(readingStatusesError), + [readingStatusesError], + ); + + useEffect(() => { + if (qrCodeDataError) { + if (qrCodeDataError.message === TAIL_PENDING_ERROR_MESSAGE) { + setVerificationState(STATE_TAIL_PENDING); + } else { + setError(qrCodeDataError); + } + } + }, [qrCodeDataError]); + + useEffect( + () => verificationFlowError && setError(verificationFlowError), + [verificationFlowError], + ); + + useEffect(() => { + if (error) { + if (error instanceof VerificationError) { + setVerificationState(STATE_UNVERIFIED); + } else { + setVerificationState(STATE_ERROR); + } + } + }, [error]); + + /** + * In case status data is still pending sealing into blockchain + */ + useEffect(() => { + if (statusesData && !statusesData.length) { + setVerificationState(STATE_STATUS_DATA_PENDING); + } + }, [statusesData]); + + useEffect(() => { + if (senderStatusData && !senderStatusData.transactionHash) { + setVerificationState(STATE_STATUS_DATA_PENDING); + } + }, [senderStatusData]); + + /** + * Email sent. Verify sender seal + */ + useEffect(() => { + if ( + senderStatusData && + senderStatusData.transactionHash && + verificationState === STATE_LOADING_STATUS_DATA + ) { + setVerificationState(STATE_VERIFYING_SENDER); + } + }, [senderStatusData, verificationState]); + + /** + * Sender seal verified. Verify recipients. + */ + useEffect(() => { + if ( + senderVerificationDetails && + !senderVerificationDetails.verificationError && + verificationState === STATE_VERIFYING_SENDER + ) { + setVerificationState(STATE_VERIFYING_RECEIVERS); + } + }, [senderVerificationDetails, verificationState]); + + /** + * Recipients verified. Start verifying attachments. + */ + useEffect(() => { + const verificationDetails = + receiversVerificationDetails && + Object.values(receiversVerificationDetails); + + if ( + verificationState === STATE_VERIFYING_RECEIVERS && + receiversStatusesData && + verificationDetails && + verificationDetails.length === receiversStatusesData.length && + verificationDetails.every(({ verificationError }) => !verificationError) + ) { + setVerificationState(STATE_VERIFYING_ATTACHMENTS); + } + }, [receiversStatusesData, receiversVerificationDetails, verificationState]); + + /** + * Check out attachments hashes integrity and complete verification in case all good. + */ + useEffect(() => { + if ( + qrCodeData && + senderStatusData && + verificationState === STATE_VERIFYING_ATTACHMENTS + ) { + if (!qrCodeData?.attachments) { + setVerificationState(STATE_VERIFICATION_COMPLETED); + return; + } + + const signaturesInStatusData: { [key: string]: number } = {}; + let attachmentsVerified = true; + + const { attachmentsSignatures } = + senderStatusData.status as SenderStatusObject; + + if (attachmentsSignatures) { + Object.values(attachmentsSignatures).forEach(({ list }) => { + list.forEach(attachmentSignature => { + signaturesInStatusData[attachmentSignature.value] = 1; + }); + }); + + attachmentsVerified = qrCodeData.attachments.every(attachment => { + return attachment.signature in signaturesInStatusData; + }); + } + + if (attachmentsVerified) { + setVerificationState(STATE_VERIFICATION_COMPLETED); + } else { + setError(new VerificationError('Error verifying attachments')); + } + } + }, [qrCodeData, senderStatusData, verificationState]); + + return ( + <VerificationPage + senderVerificationDetails={senderVerificationDetails} + senderStatusData={senderStatusData} + receiversVerificationDetails={receiversVerificationDetails} + qrCodeData={qrCodeData} + verificationState={verificationState} + error={error} + sealId={sealId} + /> + ); +}; + +export default VerificationPageContainer; diff --git a/src/seal-module/components/VerificationPage/index.ts b/src/seal-module/components/VerificationPage/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..67781b229d41063892ee26ea94e55f8db0020628 --- /dev/null +++ b/src/seal-module/components/VerificationPage/index.ts @@ -0,0 +1,3 @@ +import VerificationPageContainer from './VerificationPageContainer'; + +export default VerificationPageContainer; diff --git a/src/seal-module/config.ts b/src/seal-module/config.ts new file mode 100644 index 0000000000000000000000000000000000000000..87174df9a4bb4a92382965faa7c63e76f5cac041 --- /dev/null +++ b/src/seal-module/config.ts @@ -0,0 +1,86 @@ +import axios from 'axios'; +import URL from 'url-parse'; + +export interface IJsonConfig { + APP_SOURCE_ADDON_URL: string; + CHROME_STORE_EXTENSION_URL: string; + SEAL_BASE_URL: string; + QRCODE_HSM_API_URL: string; + BLOCKCHAIN_CACHE_SERVICE_URL: string; + CDN: { + BASE_URL: string; + STATUSES_BUCKET: string; + KEYS_BUCKET: string; + TAILS_BUCKET: string; + }; + AETERNITY: { + NODES_URLS: string[]; + COMPILERS_URLS: string[]; + CONTRACT_BYTECODE: string; + TX_EXPLORER_TEMPLATE: string; + BLOCK_EXPLORER_TEMPLATE: string; + }; + PRIVACY_POLICY_URL: string; + IPFS_API_URL: string; +} + +const JSON_PATH = '/config.json'; + +const removeBackSlashesFromUrls = (config: any) => { + Object.keys(config).forEach(configEntryKey => { + const entry = config[configEntryKey]; + if (entry && typeof entry === 'object') { + removeBackSlashesFromUrls(entry); + } else if ( + typeof entry === 'string' && + entry.startsWith('http') && + entry.endsWith('/') + ) { + // eslint-disable-next-line no-param-reassign + config[configEntryKey] = entry.slice(0, entry.length - 1); + } + }); +}; + +class Config implements IJsonConfig { + public APP_SOURCE_ADDON_URL = ''; + + public CHROME_STORE_EXTENSION_URL = ''; + + public SEAL_BASE_URL = ''; + + public QRCODE_HSM_API_URL = ''; + + public BLOCKCHAIN_CACHE_SERVICE_URL = ''; + + public CDN = { + BASE_URL: '', + STATUSES_BUCKET: '', + KEYS_BUCKET: '', + TAILS_BUCKET: '', + }; + + public AETERNITY = { + NODES_URLS: [], + COMPILERS_URLS: [], + CONTRACT_BYTECODE: '', + TX_EXPLORER_TEMPLATE: '', + BLOCK_EXPLORER_TEMPLATE: '', + }; + + public PRIVACY_POLICY_URL = ''; + + public IPFS_API_URL = ''; + + public async load(sealUrl: string) { + const url = new URL(sealUrl); + const configUrl = `${url.origin}${JSON_PATH}`; + const response = await axios(configUrl); + + const data = response.data as IJsonConfig; + removeBackSlashesFromUrls(data); + Object.assign(this, data); + } +} + +export default new Config(); diff --git a/src/seal-module/hooks/useIpfs.ts b/src/seal-module/hooks/useIpfs.ts new file mode 100644 index 0000000000000000000000000000000000000000..7f5ca9aeeada8ac9604a16886276a545875b50da --- /dev/null +++ b/src/seal-module/hooks/useIpfs.ts @@ -0,0 +1,71 @@ +import { useState, useEffect } from 'react'; +import { arrayBufferToBase64 } from '@vereign/light-utils/dist/utils/common'; +import { IpfsAttachmentData, IpfsData } from '@vereign/light-utils/dist/types'; +import { Buffer } from 'buffer'; +import { getDecodedContent } from '../services/IPFS'; + +const CID_REGEX = /["']cid:([\d\w-]+)["']/g; + +export default (ipfs?: IpfsData) => { + const [html, setHtml] = useState<string>(''); + const [plainText, setPlainText] = useState<string>(''); + + useEffect(() => { + if (!ipfs) { + return; + } + const readIPFSPayload = async () => { + const htmlBytes = await getDecodedContent( + ipfs.html.cid, + ipfs.html.key, + ipfs.html.head, + ipfs.version, + ); + const plainBytes = await getDecodedContent( + ipfs.plaintText.cid, + ipfs.plaintText.key, + ipfs.plaintText.head, + ipfs.version, + ); + + let html = Buffer.from(htmlBytes).toString('utf8'); + const plainText = Buffer.from(plainBytes).toString('utf8'); + + let match; + const attachmentInfos: { [key: string]: IpfsAttachmentData } = {}; + // eslint-disable-next-line no-cond-assign + while ((match = CID_REGEX.exec(html)) !== null) { + const cid = match[1]; + const attachmentInfo = ipfs.attachments.find(p => p.cid === cid); + if (attachmentInfo) { + attachmentInfos[cid] = attachmentInfo; + } + } + + const attachmentList = Object.values(attachmentInfos); + const cidContents = await Promise.all( + attachmentList.map(p => + getDecodedContent(p.cid, p.key, p.head, ipfs.version), + ), + ); + + attachmentList.forEach((p, i) => { + const attachmentSrc = `data:${ + p.contentType + };base64,${arrayBufferToBase64(cidContents[i])}`; + const id = `cid:${p.cid}`; + html = html.split(id).join(attachmentSrc); + }); + + setHtml(html); + setPlainText(plainText); + }; + + readIPFSPayload(); + }, [ipfs]); + + return { + html, + plainText, + }; +}; diff --git a/src/seal-module/hooks/useIpfsAttachments.ts b/src/seal-module/hooks/useIpfsAttachments.ts new file mode 100644 index 0000000000000000000000000000000000000000..884696ee50b84837e4784815017243edf7b3e17b --- /dev/null +++ b/src/seal-module/hooks/useIpfsAttachments.ts @@ -0,0 +1,40 @@ +import { useState, useCallback } from 'react'; +import { IpfsData } from '@vereign/light-utils'; +import * as ipfsBE from '../services/IPFS'; + +interface LoadingHashed { + [key: string]: boolean; +} +export default (ipfs?: IpfsData) => { + const [loadingHashes, setLoadingHashes] = useState<LoadingHashed>({}); + + const downloadAttachment = useCallback( + async (contentHash: string, fileName: string) => { + if (!ipfs) { + return; + } + + if (loadingHashes[contentHash]) { + return; + } + + setLoadingHashes({ + ...loadingHashes, + [contentHash]: true, + }); + try { + await ipfsBE.downloadAttachment(ipfs, contentHash, fileName); + } catch (e) { + console.error(e); + } + + delete loadingHashes[contentHash]; + setLoadingHashes({ ...loadingHashes }); + }, + [ipfs, loadingHashes], + ); + return { + loadingHashes, + downloadAttachment, + }; +}; diff --git a/src/seal-module/hooks/useQrCodeData.ts b/src/seal-module/hooks/useQrCodeData.ts new file mode 100644 index 0000000000000000000000000000000000000000..b3572819f25844942b8cb5fc82079d82e1919d9d --- /dev/null +++ b/src/seal-module/hooks/useQrCodeData.ts @@ -0,0 +1,122 @@ +import { useEffect, useState } from 'react'; +import CloudflareService from '@vereign/light-utils/dist/services/CloudflareService'; +import { MessageData } from '@vereign/light-utils/dist/types'; +import CryptoService from '@vereign/light-utils/dist/services/CryptoService'; +import QrCodeDataService from '@vereign/light-utils/dist/services/QrCodeDataService'; +import VerificationError from '@vereign/light-utils/dist/services/VerificationService/VerificationError'; +import CommonUtils from '@vereign/light-utils/dist/utils/common'; +import { unlockAESKey } from '../services/API'; +import { getSealHead, getSealId } from '../utils/seal'; +import config from '../config'; + +interface BackblazeDataPartRaw { + // eslint-disable-next-line camelcase + key_signature: string; + // eslint-disable-next-line camelcase + qr_code_data: string; + // eslint-disable-next-line camelcase + session_key: string; +} + +export const TAIL_PENDING_ERROR_MESSAGE = 'Tail pending to be uploaded'; + +export default (sealUrl: string) => { + const [qrCodeData, setQrCodeData] = useState<MessageData>(); + const [sealId, setSealId] = useState<string>(); + const [sealHash, setSealHash] = useState<ArrayBuffer>(); + const [error, setError] = useState<Error>(); + + /** + * Reads QR payload + */ + useEffect(() => { + const readQRCodePayload = async () => { + const sealId = await getSealId(sealUrl); + const sealHead = await getSealHead(sealUrl); + + if (!sealHead) { + setError( + new VerificationError('Cannot obtain head part of the seal from URL'), + ); + return; + } + + const cdnService = new CloudflareService( + config.CDN.BASE_URL, + config.CDN.STATUSES_BUCKET, + ); + + let qrCodeDataPart; + try { + qrCodeDataPart = QrCodeDataService.decodeKeyDataPair(sealHead); + } catch (e) { + setError(e); + return; + } + let backblazeDataPart; + try { + ({ data: backblazeDataPart } = + await cdnService.fetchFile<BackblazeDataPartRaw>( + `qrcode-${sealId}`, + config.CDN.TAILS_BUCKET, + )); + } catch (e) { + setError(new Error(TAIL_PENDING_ERROR_MESSAGE)); + return; + } + + try { + const assembledData = QrCodeDataService.assembleQrCodeData( + CommonUtils.base64ToArrayBuffer(qrCodeDataPart.data), + CommonUtils.base64ToArrayBuffer(backblazeDataPart.qr_code_data), + ); + + const sealHash = await CryptoService.SHA256(assembledData); + setSealHash(sealHash); + + const { key: aesEncryptedSessionKey, data: storageIv } = + QrCodeDataService.decodeKeyDataPair(backblazeDataPart.session_key); + + const rsaEncryptedSessionKey = await CryptoService.decryptAESGCM( + CommonUtils.base64ToArrayBuffer(aesEncryptedSessionKey), + CommonUtils.base64ToArrayBuffer(qrCodeDataPart.key), + CommonUtils.base64ToArrayBuffer(storageIv), + ); + + const encodedSessionKey = await unlockAESKey( + backblazeDataPart.key_signature, + rsaEncryptedSessionKey, + ); + + const decodedSessionKey = + QrCodeDataService.decodeKeyDataPair(encodedSessionKey); + + const decryptedEmailData = await CryptoService.decryptAESGCM( + assembledData, + CommonUtils.base64ToArrayBuffer(decodedSessionKey.key), + CommonUtils.base64ToArrayBuffer(decodedSessionKey.data), + ); + + const decompressedEmailData = + CommonUtils.decompressData(decryptedEmailData); + const decodedEmailData = QrCodeDataService.decodeEmailData( + decompressedEmailData, + ); + + setQrCodeData(decodedEmailData); + setSealId(sealId); + } catch (e) { + setError(e); + } + }; + + readQRCodePayload(); + }, [sealUrl]); + + return { + qrCodeData, + sealId, + error, + sealHash, + }; +}; diff --git a/src/seal-module/hooks/useStatuses.ts b/src/seal-module/hooks/useStatuses.ts new file mode 100644 index 0000000000000000000000000000000000000000..577602c55c3cd7067036d85b52d6d85b3802eb9b --- /dev/null +++ b/src/seal-module/hooks/useStatuses.ts @@ -0,0 +1,138 @@ +import { useEffect, useMemo, useRef, useState } from 'react'; +import CloudflareService from '@vereign/light-utils/dist/services/CloudflareService'; +import StatusesService from '@vereign/light-utils/dist/services/StatusesService'; +import CryptoService from '@vereign/light-utils/dist/services/CryptoService'; +import { + SenderStatusObject, + StatusData, +} from '@vereign/light-utils/dist/types'; +import VerificationError from '@vereign/light-utils/dist/services/VerificationService/VerificationError'; +import CommonUtils from '@vereign/light-utils/dist/utils/common'; +import { Buffer } from 'buffer'; + +import config from '../config'; + +const { SENDER_CLASS_NAME } = StatusesService; + +export default ( + statusId?: string, + senderPublicKeyUuid?: string, + sealHash?: ArrayBuffer, +) => { + const [statusesData, setStatusesData] = useState<Array<StatusData>>(); + const [senderStatusData, setSenderStatusData] = useState<StatusData>(); + const [error, setError] = useState<Error>(); + const cdnService = useRef( + new CloudflareService(config.CDN.BASE_URL, config.CDN.STATUSES_BUCKET), + ); + + useEffect(() => { + if (statusId) { + cdnService.current + .readStatuses(statusId) + .then(setStatusesData) + .catch(setError); + } + }, [statusId]); + + /** + * Find sender statuses + */ + useEffect(() => { + const findSenderStatus = async ( + statusesData: Array<StatusData>, + sealHash: ArrayBuffer, + ) => { + const matchedStatusesData: Array<StatusData> = []; + + const { + data: { key: publicKey }, + } = await cdnService.current.fetchFile<{ key: string }>( + `pubkey-${senderPublicKeyUuid}`, + config.CDN.KEYS_BUCKET, + ); + + const publicKeyPEM = Buffer.from( + CommonUtils.base64ToArrayBuffer(publicKey), + ).toString('utf8'); + + // eslint-disable-next-line no-restricted-syntax + for (const statusData of statusesData) { + if (statusData.statusClassName === SENDER_CLASS_NAME) { + const matchedStatusObject = statusData.status as SenderStatusObject; + + // eslint-disable-next-line no-await-in-loop + const signatureTimeVerified = await CryptoService.verifyRSASignature( + publicKeyPEM, + Buffer.from( + matchedStatusObject.signatureTime.toString(16), + 'utf-8', + ), + CommonUtils.base64ToArrayBuffer( + matchedStatusObject.signatureTimeSignature, + ), + ); + + if (!signatureTimeVerified) { + setError( + new VerificationError( + 'Could not verify sender status signature time', + ), + ); + return; + } + + // eslint-disable-next-line no-await-in-loop + const sealHashVerified = await CryptoService.verifyRSASignature( + publicKeyPEM, + sealHash, + CommonUtils.base64ToArrayBuffer( + matchedStatusObject.sealSignature as string, + ), + ); + + if (!sealHashVerified) { + setError(new VerificationError('Could not verify seal integrity')); + return; + } + + matchedStatusesData.push(statusData); + } + } + + if (matchedStatusesData.length === 0) { + setError(new VerificationError('Sender not found')); + } else if (matchedStatusesData.length > 1) { + setError( + new VerificationError( + 'More than one sender status present for provided status id', + ), + ); + } else if (matchedStatusesData.length === 1) { + setSenderStatusData(matchedStatusesData[0]); + } + }; + + if (statusesData && statusesData.length && sealHash) { + findSenderStatus(statusesData, sealHash).catch(setError); + } + }, [statusesData, senderPublicKeyUuid, sealHash]); + + const receiversStatusesData = useMemo(() => { + return ( + statusesData && + senderStatusData && + statusesData.filter( + statusData => + statusData !== senderStatusData && statusData.transactionHash, + ) + ); + }, [statusesData, senderStatusData]); + + return { + senderStatusData, + receiversStatusesData, + statusesData, + error, + }; +}; diff --git a/src/seal-module/hooks/useVerificationFlow.ts b/src/seal-module/hooks/useVerificationFlow.ts new file mode 100644 index 0000000000000000000000000000000000000000..b011133b79fbeb7fa4d26cbde02d5a1359c2ef0b --- /dev/null +++ b/src/seal-module/hooks/useVerificationFlow.ts @@ -0,0 +1,121 @@ +import { useEffect, useState, useRef } from 'react'; + +import VerificationService from '@vereign/light-utils/dist/services/VerificationService'; +import { VerificationData, StatusData } from '@vereign/light-utils/dist/types'; +import VerificationError from '@vereign/light-utils/dist/services/VerificationService/VerificationError'; + +import config from '../config'; + +export const STATE_LOADING_STATUS_DATA = 0; +export const STATE_VERIFYING_SENDER = 1; +export const STATE_VERIFYING_RECEIVERS = 2; +export const STATE_VERIFYING_ATTACHMENTS = 3; +export const STATE_VERIFICATION_COMPLETED = 4; +export const STATE_ERROR = 5; +export const STATE_UNVERIFIED = 6; +export const STATE_STATUS_DATA_PENDING = 7; +export const STATE_TAIL_PENDING = 8; +export const STATE_PENDING = 9; + +export const UNVERIFIED_STATES = new Set([ + STATE_ERROR, + STATE_UNVERIFIED, + STATE_STATUS_DATA_PENDING, + STATE_TAIL_PENDING, + STATE_PENDING, +]); + +export default ( + senderStatusData?: StatusData, + receiversStatusesData?: Array<StatusData>, +) => { + const [senderVerificationDetails, setSenderVerificationDetails] = + useState<VerificationData>(); + const [receiversVerificationDetails, setReceiversVerificationDetails] = + useState<{ + [key: string]: VerificationData; + }>(); + const [error, setError] = useState<Error>(); + + const verificationService = useRef( + new VerificationService( + config.CDN.BASE_URL, + config.CDN.STATUSES_BUCKET, + config.AETERNITY.NODES_URLS, + config.AETERNITY.COMPILERS_URLS, + config.AETERNITY.CONTRACT_BYTECODE, + ), + ); + + /** + * Process sender verification + */ + useEffect(() => { + if (senderStatusData && senderStatusData.transactionHash) { + verificationService.current + .verifyStatusData(senderStatusData) + .then(verificationResult => { + setSenderVerificationDetails(verificationResult); + if (verificationResult.verificationError) { + setError( + new VerificationError( + `Sender verification problem. ${verificationResult.verificationError}`, + ), + ); + } + }) + .catch(setError); + } + }, [senderStatusData]); + + /** + * Process receivers verification + */ + useEffect(() => { + if ( + senderVerificationDetails && + !senderVerificationDetails?.verificationError && + receiversStatusesData + ) { + Promise.all( + receiversStatusesData + .filter(statusData => !!statusData.transactionHash) + .map(statusData => + verificationService.current.verifyStatusData(statusData), + ), + ) + .then(verificationResults => { + const details = verificationResults.reduce( + (acc: { [key: string]: VerificationData }, result) => + result.statusData + ? Object.assign(acc, { + [result.statusData?.transactionHash]: result, + }) + : acc, + {}, + ); + + setReceiversVerificationDetails(details); + + const failed = verificationResults.find( + result => !!result.verificationError, + ); + + if (failed?.verificationError) { + setError( + new VerificationError( + `Receivers verification problem. ${failed.verificationError}`, + ), + ); + } + }) + .catch(setError); + } + }, [senderVerificationDetails, receiversStatusesData]); + + return { + senderVerificationDetails, + receiversVerificationDetails, + error, + }; +}; diff --git a/src/seal-module/services/API.ts b/src/seal-module/services/API.ts new file mode 100644 index 0000000000000000000000000000000000000000..fee2e477b060f882c09d3f89c858aa87456a5a5e --- /dev/null +++ b/src/seal-module/services/API.ts @@ -0,0 +1,25 @@ +import axios from 'axios'; +import config from '../config'; + +export const unlockAESKey = async ( + keySignature: string, + encryptedKey: string, +): Promise<string> => { + const response = await axios({ + url: `${config.QRCODE_HSM_API_URL}/hsm/decrypt`, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: { + key_signature: keySignature, + encrypted_key: encryptedKey, + }, + }); + + return (response.data as any).key; +}; + +export default { + unlockAESKey, +}; diff --git a/src/seal-module/services/IPFS.ts b/src/seal-module/services/IPFS.ts new file mode 100644 index 0000000000000000000000000000000000000000..412b099fce83511e5dd1535791334e5ebe43058d --- /dev/null +++ b/src/seal-module/services/IPFS.ts @@ -0,0 +1,54 @@ +import { IpfsData, IpfsDataVersion } from '@vereign/light-utils/dist/types'; +import IPFSService from '@vereign/light-utils/dist/services/IPFSService'; +import { arrayBufferToBase64 } from '@vereign/light-utils/dist/utils/common'; +import RNFetchBlob from 'rn-fetch-blob'; +import { successToast } from '../../utils/toast'; +import config from '../config'; + +export const getDecodedContent = async ( + cid: string, + decryptionKey: string, + head: string, + ipfsVersion: IpfsDataVersion, +): Promise<ArrayBuffer> => { + const ipfsService = new IPFSService(config.IPFS_API_URL); + const ipfsContent = await ipfsService.getDecodedContent( + { + cid, + key: decryptionKey, + head, + }, + ipfsVersion, + ); + return ipfsContent; +}; + +export const downloadAttachment = async ( + ipfs: IpfsData, + contentHash: string, + fileName: string, +) => { + const attachmentData = ipfs.attachments.find( + a => a.contentHash === contentHash, + ); + if (!attachmentData) { + return; + } + + const file = await getDecodedContent( + attachmentData.cid, + attachmentData.key, + attachmentData.head, + ipfs.version, + ); + + const { fs } = RNFetchBlob; + + const downloadDirectory = fs.dirs.DownloadDir; + + // write bytes to file + const fileLocation = `${downloadDirectory}/${fileName}`; + const base64FileData = arrayBufferToBase64(file); + await fs.writeFile(fileLocation, base64FileData, 'base64'); + successToast(`File saved to ${fileLocation}`); +}; diff --git a/src/seal-module/services/injectCryptoServiceMobile.ts b/src/seal-module/services/injectCryptoServiceMobile.ts new file mode 100644 index 0000000000000000000000000000000000000000..78629e2ae11e66438de4dac8e12531cd300f1f25 --- /dev/null +++ b/src/seal-module/services/injectCryptoServiceMobile.ts @@ -0,0 +1,164 @@ +import { + AESGCMOutput, + ICryptoService, + RSAKeys, +} from '@vereign/light-utils/dist/services/CryptoService/ICryptoService'; +import CryptoService from '@vereign/light-utils/dist/services/CryptoService'; +import AesGcmCrypto from 'react-native-aes-gcm-crypto'; +import { sha256 } from 'js-sha256'; +import { RSA } from 'react-native-rsa-native'; +import { Buffer } from 'buffer'; + +const getBytes = ( + value: string | ArrayBuffer, + encoding: BufferEncoding, +): Buffer => { + let bytes; + if (typeof value === 'string') { + const valueString = value as string; + bytes = Buffer.from(valueString, encoding); + } else { + bytes = Buffer.from(value); + } + return bytes; +}; + +class CryptoServiceMobile implements ICryptoService { + public async encryptAESGCM(data: string): Promise<AESGCMOutput>; + public async encryptAESGCM(data: ArrayBuffer): Promise<AESGCMOutput>; + + // eslint-disable-next-line class-methods-use-this + public async encryptAESGCM( + data: string | ArrayBuffer, + ): Promise<AESGCMOutput> { + throw new Error('Will not be implemented'); + } + + public async decryptAESGCM( + data: ArrayBuffer, + key: ArrayBuffer, + iv: ArrayBuffer, + ): Promise<string>; + + public async decryptAESGCM( + data: ArrayBuffer, + key: ArrayBuffer, + iv: ArrayBuffer, + returnBuffer: true, + ): Promise<ArrayBuffer>; + + // eslint-disable-next-line class-methods-use-this + public async decryptAESGCM( + data: ArrayBuffer, + key: ArrayBuffer, + iv: ArrayBuffer, + returnBuffer?: boolean, + ): Promise<string | ArrayBuffer> { + const authTag = data.slice(data.byteLength - 16, data.byteLength); + const encrypted = data.slice(0, data.byteLength - 16); + + const decryptedData = await AesGcmCrypto.decrypt( + Buffer.from(encrypted).toString('base64'), + Buffer.from(key).toString('base64'), + Buffer.from(iv).toString('hex'), + Buffer.from(authTag).toString('hex'), + true, + ); + const result = Buffer.from(decryptedData, 'base64'); + + if (returnBuffer) { + return result; + } + + return result.toString('utf-8'); + } + + // eslint-disable-next-line class-methods-use-this + public async verifyRSASignature( + publicKeyPEM: string, + data: ArrayBuffer, + signature: ArrayBuffer, + ): Promise<boolean> { + const result = await RSA.verify64WithAlgorithm( + Buffer.from(signature).toString('base64'), + Buffer.from(data).toString('base64'), + publicKeyPEM, + 'SHA256withRSA', + ); + + return result; + } + + // eslint-disable-next-line class-methods-use-this + public async generateRSAKeys(): Promise<RSAKeys> { + throw new Error('Will not be implemented'); + } + + // eslint-disable-next-line class-methods-use-this + public async encryptRSA( + publicKeyPEM: string, + data: ArrayBuffer, + ): Promise<ArrayBuffer> { + throw new Error('Will not be implemented'); + } + + // eslint-disable-next-line class-methods-use-this + public async decryptRSA( + privateKeyPEM: string, + data: ArrayBuffer, + ): Promise<ArrayBuffer> { + throw new Error('Will not be implemented'); + } + + // eslint-disable-next-line class-methods-use-this + public async signRSA( + privateKeyPEM: string, + data: ArrayBuffer, + ): Promise<ArrayBuffer> { + throw new Error('Will not be implemented'); + } + + // eslint-disable-next-line class-methods-use-this + public async SHA1( + value: string | ArrayBuffer, + encoding = 'utf8', + ): Promise<ArrayBuffer> { + throw new Error('Will not be implemented'); + } + + // eslint-disable-next-line class-methods-use-this + public async SHA256( + value: string | ArrayBuffer, + encoding = 'utf8', + ): Promise<ArrayBuffer> { + const bytes = getBytes(value, encoding); + const hex = sha256(bytes); + return Buffer.from(hex, 'hex'); + } + + // eslint-disable-next-line class-methods-use-this + public async SHA384( + value: string | ArrayBuffer, + encoding = 'utf8', + ): Promise<ArrayBuffer> { + throw new Error('Will not be implemented'); + } + + // eslint-disable-next-line class-methods-use-this + public async SHA512( + value: string | ArrayBuffer, + encoding = 'utf8', + ): Promise<ArrayBuffer> { + throw new Error('Will not be implemented'); + } + + // eslint-disable-next-line class-methods-use-this + public async MD5( + value: string | ArrayBuffer, + encoding = 'utf8', + ): Promise<ArrayBuffer> { + throw new Error('Will not be implemented'); + } +} + +CryptoService.injectCustomImplementation(new CryptoServiceMobile()); diff --git a/src/seal-module/styles/_base.scss b/src/seal-module/styles/_base.scss new file mode 100644 index 0000000000000000000000000000000000000000..cc6758a2e26ec7e9206e3bb64bc0cd77ddad5c2e --- /dev/null +++ b/src/seal-module/styles/_base.scss @@ -0,0 +1,62 @@ +html { + box-sizing: border-box; + height: 100%; + font-size: 14px; + overflow-x: hidden; + margin-right: calc(-1 * (100vw - 100%)); +} + +* { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +body { + color: white; + background-color: #f3f3f3; + height: 100%; +} + +#root { + height: 100%; +} + +body, +div, +p, +h1, +h2, +h3 { + margin: 0; +} + + +*, +*::before, +*::after { + box-sizing: inherit; +} + +input, +textarea, +select, +button { + font-size: inherit; +} + +button, +input { + outline: none; +} + +p { + margin: 0; + padding: 0; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + + + diff --git a/src/seal-module/styles/_colors.scss b/src/seal-module/styles/_colors.scss new file mode 100644 index 0000000000000000000000000000000000000000..aff5c68768796888b0f137b21657457e6e4ce990 --- /dev/null +++ b/src/seal-module/styles/_colors.scss @@ -0,0 +1,31 @@ +@import "~@vereign/react-ui/dist/styles/colors"; + +$mine-shaft: #333333; +$mine-shaft-2: #3b3b3b; +$mine-shaft-3: #313131; +$mine-shaft-4: #2b2b2b; +$emperor: #505050; +$silver-chalice: #B1B1B1; +$silver-chalice-2: #A5A5A5; +$vereign-red: #d51d32; +$dove-gray: #707070; +$gray: #868686; +$gray-2: #898989; +$silver: #B9B9B9; +$silver-2: #C7C7C7; +$alto: #E0E0E0; +$alto-2: #DBDBDB; +$pale-pink: #EB9BA5; +$science-blue: #0877D7; +$cinnabar: #EA4335; +$gallery: #EAEAEA; +$orange: #ff9933; + +$alabaster: #f6efe8; +$turquoise-surf: #00B3CA; +$palatinate-purple: #611f69; +$maximum-purple: #993399; +$black-live: #3C3C3C; +$raisin-black: #272123; +$mauvelous: #EB9CA5; +$pastel-green: #71E07D; \ No newline at end of file diff --git a/src/seal-module/styles/_fonts.scss b/src/seal-module/styles/_fonts.scss new file mode 100644 index 0000000000000000000000000000000000000000..abbc1d2a96df96c0efca4d7826c9b3224c56197a --- /dev/null +++ b/src/seal-module/styles/_fonts.scss @@ -0,0 +1,15 @@ +@font-face { + font-family: "Helvetica Neue Bold"; + src: url("../assets/fonts/HelveticaNeue-Bold.otf") format("opentype"); +} + +@font-face { + font-family: "Helvetica Neue"; + src: url("../assets/fonts/HelveticaNeue.otf") format("opentype"); +} + +@font-face { + font-family: "Helvetica Neue Medium"; + src: url("../assets/fonts/HelveticaNeue-Medium.otf") format("opentype"); +} + diff --git a/src/seal-module/styles/_mixins.scss b/src/seal-module/styles/_mixins.scss new file mode 100644 index 0000000000000000000000000000000000000000..b63bfa7754e92b42bbd54cd387da068ddc979d9c --- /dev/null +++ b/src/seal-module/styles/_mixins.scss @@ -0,0 +1,31 @@ +$break-small: 414px; +$break-wide: 1024px; +$break-large: 1920px; + +@mixin respond-to($media) { + @if $media == handhelds { + @media only screen and (max-width: $break-small) { + @content; + } + } @else if $media == mobiles { + @media only screen and (max-width: $break-wide - 1) { + @content; + } + } @else if $media == medium-screens { + @media only screen and (min-width: $break-small + 1) and (max-width: $break-wide - 1) { + @content; + } + } @else if $media == wide-and-above { + @media only screen and (min-width: $break-wide) { + @content; + } + } @else if $media == wide-screens { + @media only screen and (min-width: $break-wide) and (max-width: $break-large) { + @content; + } + } @else if $media == large-screens { + @media only screen and (min-width: $break-large + 1) { + @content; + } + } +} diff --git a/src/seal-module/styles/_overrides.scss b/src/seal-module/styles/_overrides.scss new file mode 100644 index 0000000000000000000000000000000000000000..ee70cc2cb52ef8bd4d771a73f220197497a1bfc7 --- /dev/null +++ b/src/seal-module/styles/_overrides.scss @@ -0,0 +1,34 @@ +@import "colors"; +@import "mixins"; + +.vrg-tooltip-content { + background-color: #2b2b2b !important; +} + +.vrg-tooltip-arrow { + border-top-color: #2b2b2b !important; +} + +.vrg-tab-pane { + height: 100%; + display: flex; + align-items: center; + justify-content: center; + white-space: nowrap; + font-size: 15px; + line-height: 24px; + font-family: "Helvetica Neue Bold", Arial, sans-serif; + cursor: pointer; + color: $raisin-black; + flex-grow: 1; + max-width: 316px; + min-width: 0; + letter-spacing: 0; + opacity: .6; + + &--active { + opacity: 1; + color: $turquoise-surf; + border-bottom: 2px solid $turquoise-surf; + } +} diff --git a/src/seal-module/styles/_typography.scss b/src/seal-module/styles/_typography.scss new file mode 100644 index 0000000000000000000000000000000000000000..3ee5529a488adb1ca3219985d05f7a2e968f10ee --- /dev/null +++ b/src/seal-module/styles/_typography.scss @@ -0,0 +1 @@ +@import "~@vereign/react-ui/dist/styles/typography"; \ No newline at end of file diff --git a/src/seal-module/styles/_utils.scss b/src/seal-module/styles/_utils.scss new file mode 100644 index 0000000000000000000000000000000000000000..c02e5e312841a378126d1cb21de63edd92152017 --- /dev/null +++ b/src/seal-module/styles/_utils.scss @@ -0,0 +1,5 @@ +@mixin text-overflow { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} diff --git a/src/seal-module/styles/_vars.scss b/src/seal-module/styles/_vars.scss new file mode 100644 index 0000000000000000000000000000000000000000..398d0d7c84a4f893dc317d51023cb6a50f656456 --- /dev/null +++ b/src/seal-module/styles/_vars.scss @@ -0,0 +1,8 @@ +$header-height: 120px; +$header-height-mobile: 100px; +$footer-height: 100px; + + +$shadow: 0 0 15px -10px rgba(black, 0.5); +$shadow-up: 0px -10px 15px -10px rgba(black, 0.2); +$shadow-down: 0px 10px 15px -10px rgba(black, 0.2); \ No newline at end of file diff --git a/src/seal-module/styles/main.scss b/src/seal-module/styles/main.scss new file mode 100644 index 0000000000000000000000000000000000000000..a72da2ab95ab8f9b76f3ed5f9048ae45303cb4e8 --- /dev/null +++ b/src/seal-module/styles/main.scss @@ -0,0 +1,3 @@ +@import "base"; +@import "fonts"; +@import "overrides"; diff --git a/src/seal-module/types.ts b/src/seal-module/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..bd551101b3f831321245999d34d73096cd4250e3 --- /dev/null +++ b/src/seal-module/types.ts @@ -0,0 +1,12 @@ +export interface QrCodeDataPart { + encryptedKey: string; + encryptedData: { + nonce: string; + data: string; + }; +} + +export interface BackblazeDataPart { + keySignature: string; + data: string; +} diff --git a/src/seal-module/utils/seal.ts b/src/seal-module/utils/seal.ts new file mode 100644 index 0000000000000000000000000000000000000000..d2210f1a9cc263321a12c3e9498ddde895c22790 --- /dev/null +++ b/src/seal-module/utils/seal.ts @@ -0,0 +1,17 @@ +import CryptoService from '@vereign/light-utils/dist/services/CryptoService'; +import URL from 'url-parse'; +import { Buffer } from 'buffer'; + +export const decodeBase64URL = (input: string): string => { + return input.replace(/_/g, '/').replace(/-/g, '+'); +}; + +export const getSealHead = (sealUrl: string): string => { + const url = new URL(sealUrl); + return decodeBase64URL(url.hash.replace('#', '')); +}; + +export const getSealId = async (sealUrl: string): Promise<string> => { + const sealHash = await CryptoService.SHA256(sealUrl); + return Buffer.from(sealHash).toString('hex'); +}; diff --git a/src/seal-module/utils/stringUtils.ts b/src/seal-module/utils/stringUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..29a0bbd553d794f59c8bf0e73d3879de4d1d513a --- /dev/null +++ b/src/seal-module/utils/stringUtils.ts @@ -0,0 +1,60 @@ +export const formatBytesSize = (bytes: number): string => { + if (Number.isNaN(bytes) || bytes <= 0 || bytes === Infinity) { + return '0'; + } + + const degrees = ['b', 'kb', 'mb', 'gb']; + let degree = 0; + + let value = bytes; + // eslint-disable-next-line no-constant-condition + while (true) { + if (Math.round(value / 1024) === 0) { + return `${Math.round(value * 100) / 100}${degrees[degree]}`; + } + + value /= 1024; + degree += 1; + } +}; + +export function base64ToHex(str: string) { + const raw = atob(str); + let result = ''; + for (let i = 0; i < raw.length; i += 1) { + const hex = raw.charCodeAt(i).toString(16); + result += hex.length === 2 ? hex : `0${hex}`; + } + return result.toLowerCase(); +} + +export const copyToClipboard = (str: string) => { + const el = document.createElement('textarea'); // Create a <textarea> element + el.value = str; // Set its value to the string that you want copied + el.setAttribute('readonly', ''); // Make it readonly to be tamper-proof + el.style.position = 'absolute'; + el.style.left = '-9999px'; // Move outside the screen to make it invisible + document.body.appendChild(el); // Append the <textarea> element to the HTML document + + const selection = document.getSelection(); + const selected = + selection && selection.rangeCount > 0 // Check if there is any content selected previously + ? selection.getRangeAt(0) // Store selection if found + : false; // Mark as false to know no selection existed before + el.select(); // Select the <textarea> content + document.execCommand('copy'); // Copy - only works as a result of a user action (e.g. click events) + document.body.removeChild(el); // Remove the <textarea> element + if (selection && selected) { + // If a selection existed before copying + selection.removeAllRanges(); // Unselect everything on the HTML document + selection.addRange(selected); // Restore the original selection + } +}; + +export const truncateString = (str: string, length: number): string => { + if (str.length > length) { + return `${str.substring(0, length)}...`; + } + + return str; +}; diff --git a/src/theme/theme.ts b/src/theme/theme.ts new file mode 100644 index 0000000000000000000000000000000000000000..348e463291738d34d6b6b08f0f131203d8e42c17 --- /dev/null +++ b/src/theme/theme.ts @@ -0,0 +1,281 @@ +import { Theme } from '@ant-design/react-native/lib/style'; + +type BaseColor = Record<string, string>; + +interface FontAttributes { + fontSize: number; + fontWeight: + | 'normal' + | 'bold' + | '100' + | '200' + | '300' + | '400' + | '500' + | '600' + | '700' + | '800' + | '900'; + color: string; +} + +interface BrandColors { + primary: string; + secondary: string; + highlight: string; + primaryBackground: string; + secondaryBackground: string; + link: string; +} + +interface SemanticColors { + error: string; + success: string; + focus: string; +} + +interface NotificationColors { + success: string; + successBorder: string; + successIcon: string; + successText: string; + info: string; + infoBorder: string; + infoIcon: string; + infoText: string; + warn: string; + warnBorder: string; + warnIcon: string; + warnText: string; + error: string; + errorBorder: string; + errorIcon: string; + errorText: string; +} + +interface GrayscaleColors { + black: string; + darkGrey: string; + mediumGrey: string; + lightGrey: string; + veryLightGrey: string; + white: string; +} + +interface BaseScaleColors { + black: string; + darkGreen: string; + lightBlue: string; + darkGreenLightTransparent: string; + darkGreenHeavyTransparent: string; + darkGrey: string; + green: string; + lightGrey: string; + red: string; + transparent: string; + yellow: string; + white: string; +} + +interface ColorPallet { + brand: BrandColors; + semantic: SemanticColors; + notification: NotificationColors; + grayscale: GrayscaleColors; + baseColors: BaseScaleColors; +} + +export const borderRadius = 4; +export const heavyOpacity = 0.7; +export const lightOpacity = 0.35; +export const zeroOpacity = 0.0; +export const borderWidth = 2; + +const BrandColors: BrandColors = { + primary: '#000094', + secondary: '#465AFF', + highlight: '#FCBA19', + primaryBackground: '#000000', + secondaryBackground: '#313132', + link: '#D8292F', +}; + +const SemanticColors: SemanticColors = { + error: '#D8292F', + success: '#2E8540', + focus: '#3399ff', +}; + +const NotificationColors: NotificationColors = { + success: '#D2EBCA', + successBorder: '#60775A', + successIcon: '#60775A', + successText: '#60775A', + info: '#CCE8F4', + infoBorder: '#4F7C9E', + infoIcon: '#4F7C9E', + infoText: '#4F7C9E', + warn: '#F7F3D7', + warnBorder: '#AE8E56', + warnIcon: '#AE8E56', + warnText: '#AE8E56', + error: '#ECC8C4', + errorBorder: '#B25B59', + errorIcon: '#B25B59', + errorText: '#B25B59', +}; + +const GrayscaleColors: GrayscaleColors = { + black: '#000000', + darkGrey: '#313132', + mediumGrey: '#606060', + lightGrey: '#d3d3d3', + veryLightGrey: '#F2F2F2', + white: '#FFFFFF', +}; + +const BaseScaleColors: BaseScaleColors = { + black: '#000000', + darkGreen: '#35823F', + lightBlue: '#CCE8F4', + darkGreenLightTransparent: `rgba(53, 130, 63, ${heavyOpacity})`, + darkGreenHeavyTransparent: `rgba(53, 130, 63, ${lightOpacity})`, + darkGrey: '#1C1C1E', + green: '#2D6E35', + lightGrey: '#D3D3D3', + red: '#DE3333', + transparent: `rgba(0, 0, 0, ${zeroOpacity})`, + yellow: '#FCBA19', + white: '#FFFFFF', +}; + +export const ColorPallet: ColorPallet = { + brand: BrandColors, + semantic: SemanticColors, + notification: NotificationColors, + grayscale: GrayscaleColors, + baseColors: BaseScaleColors, +}; + +export const StatusColors: BaseColor = { + error: ColorPallet.baseColors.red, + info: ColorPallet.baseColors.black, + success: ColorPallet.baseColors.green, + warning: ColorPallet.baseColors.black, +}; + +interface FontAttributes { + fontSize: number; + fontWeight: + | 'normal' + | 'bold' + | '100' + | '200' + | '300' + | '400' + | '500' + | '600' + | '700' + | '800' + | '900'; + color: string; + fontFamily: string; +} + +interface TextTheme { + headingOne: FontAttributes; + headingTwo: FontAttributes; + headingThree: FontAttributes; + headingFour: FontAttributes; + normal: FontAttributes; + label: FontAttributes; + caption: FontAttributes; +} + +interface TextBoxTheme { + background: string; + border: string; + text: string; +} + +export const TextBoxTheme: TextBoxTheme = { + background: ColorPallet.baseColors.darkGreenLightTransparent, + border: ColorPallet.baseColors.green, + text: ColorPallet.brand.primary, +}; + +export const TextTheme: TextTheme = { + headingOne: { + fontSize: 38, + fontWeight: 'bold', + color: ColorPallet.brand.primary, + fontFamily: 'TitilliumWeb-SemiBold', + }, + headingTwo: { + fontSize: 32, + fontWeight: 'bold', + fontFamily: 'TitilliumWeb-SemiBold', + color: ColorPallet.baseColors.black, + }, + headingThree: { + fontSize: 26, + fontWeight: 'bold', + color: ColorPallet.brand.primary, + fontFamily: 'TitilliumWeb-SemiBold', + }, + headingFour: { + fontSize: 21, + fontWeight: 'bold', + fontFamily: 'TitilliumWeb-SemiBold', + color: ColorPallet.baseColors.black, + }, + normal: { + fontSize: 17, + fontWeight: 'normal', + fontFamily: 'TitilliumWeb-Regular', + color: ColorPallet.baseColors.black, + }, + label: { + fontSize: 14, + fontWeight: 'bold', + color: ColorPallet.brand.primary, + fontFamily: 'TitilliumWeb-SemiBold', + }, + caption: { + fontSize: 14, + fontWeight: 'normal', + color: ColorPallet.brand.primary, + fontFamily: 'TitilliumWeb-Regular', + }, +}; + +export const customTheme: Partial<Theme> = { + brand_primary: BrandColors.primary, + brand_primary_tap: BrandColors.primary, + + // button + primary_button_fill: BrandColors.primary, + primary_button_fill_tap: BrandColors.primary, + + ghost_button_color: BrandColors.primary, + ghost_button_fill_tap: BrandColors.primary, + + // input_font_size + border_color_base: BaseScaleColors.black, +}; + +interface ContactTheme { + background: string; +} + +interface SingleSelectBlockTheme { + background: string; +} + +export const ContactTheme: ContactTheme = { + background: GrayscaleColors.veryLightGrey, +}; + +export const SingleSelectBlockTheme: SingleSelectBlockTheme = { + background: BaseScaleColors.lightBlue, +}; diff --git a/src/types/error.ts b/src/types/error.ts new file mode 100644 index 0000000000000000000000000000000000000000..f14337a9eb4a4fa6aa3cb1db016a7c84783e8b8a --- /dev/null +++ b/src/types/error.ts @@ -0,0 +1,10 @@ +class QrCodeScanError extends Error { + public data?: string; + + public constructor(message?: string, data?: string) { + super(message); + this.data = data; + } +} + +export default QrCodeScanError; diff --git a/src/types/global.d.ts b/src/types/global.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..abfbee478761ff3ac1ac69e861555265a80e2687 --- /dev/null +++ b/src/types/global.d.ts @@ -0,0 +1,6 @@ +declare module '*.svg' { + import { SvgProps } from 'react-native-svg'; + + const content: React.FC<SvgProps>; + export default content; +} diff --git a/src/types/navigators.ts b/src/types/navigators.ts new file mode 100644 index 0000000000000000000000000000000000000000..3d43c11e80df5f5369f72983fe2d45c5fb41d854 --- /dev/null +++ b/src/types/navigators.ts @@ -0,0 +1,145 @@ +import { Agent } from '@aries-framework/core'; +import { NavigatorScreenParams } from '@react-navigation/core'; + +export enum Screens { + Onboarding = 'Onboarding', + Terms = 'Terms', + CreatePin = 'CreatePin', + Splash = 'Splash', + EnterPin = 'EnterPin', + Initialization = 'Initialization', + Home = 'Home', + Connect = 'Connect', + Consent = 'Consent', + ListContacts = 'ListContacts', + Scan = 'Scan', + ChangePin = 'ChangePin', + Credentials = 'Credentials', + CredentialDetails = 'Credential Details', + Settings = 'Settings', + Notifications = 'Notifications', + CredentialOffer = 'CredentialOffer', + ProofRequest = 'ProofRequest', + Language = 'Language', + ConnectionInvitation = 'ConnectionInvitation', + ProofRequestAttributeDetails = 'ProofRequestAttributeDetails', + ExportWallet = 'ExportWallet', + ImportWallet = 'ImportWallet', + ContactDetails = 'ConnectionDetails', + ViewMnemonic = 'ViewMnemonic', + CreateWallet = 'CreateWallet', + Biometric = 'Biometric', + WalletInitialized = 'WalletInitialized', + SetupDelay = 'SetupDelay', + SealInformation = 'SealInformation', + ScannedSealQrCodes = 'ScannedSealQrCodes', +} + +export type OnboardingStackParams = { + [Screens.Splash]: undefined; + [Screens.Onboarding]: undefined; + [Screens.Terms]: undefined; + [Screens.Initialization]: undefined; + [Screens.CreatePin]: { + initAgent: (guid: string, walletPin: string, seed: string) => void; + setAuthenticated?: React.Dispatch<React.SetStateAction<boolean>>; + }; + [Screens.Biometric]: { + initAgent?: (guid: string, walletPin: string, seed: string) => void; + setAuthenticated?: React.Dispatch<React.SetStateAction<boolean>>; + }; + [Screens.ImportWallet]: { + setAuthenticated: React.Dispatch<React.SetStateAction<boolean>>; + setAgent: (agent: Agent) => void; + setActive: React.Dispatch<React.SetStateAction<boolean>>; + }; + [Screens.EnterPin]: { + initAgent: (guid: string, walletPin: string, seed: string) => void; + setAuthenticated: React.Dispatch<React.SetStateAction<boolean>>; + }; + [Screens.CreateWallet]: { + initAgent: (guid: string, walletPin: string, seed: string) => void; + }; + [Screens.WalletInitialized]: { + setAuthenticated: React.Dispatch<React.SetStateAction<boolean>>; + }; + [Screens.SetupDelay]: undefined; +}; + +export type MainStackParams = { + [Stacks.TabStack]: undefined; + [Screens.Home]: undefined; + [Screens.Scan]: undefined; + [Screens.ListContacts]: undefined; + [Screens.ConnectionInvitation]: undefined; + [Screens.SealInformation]: undefined; + [Screens.ScannedSealQrCodes]: undefined; +}; + +export type AuthenticateStackParams = { + [Screens.EnterPin]: { + initAgent: (guid: string, walletPin: string, seed: string) => void; + setAuthenticated: React.Dispatch<React.SetStateAction<boolean>>; + }; +}; + +export type ContactStackParams = { + [Screens.ListContacts]: undefined; + [Screens.ContactDetails]: { connectionId: string }; +}; + +export type CredentialStackParams = { + [Screens.Credentials]: undefined; + [Screens.CredentialDetails]: { credentialId: string }; +}; + +export type HomeStackParams = { + [Screens.Home]: undefined; + [Screens.Notifications]: undefined; + [Screens.CredentialOffer]: { credentialId: string }; + [Screens.ProofRequest]: { proofId: string }; + [Screens.ProofRequestAttributeDetails]: { + proofId: string; + attributeName: string; + }; +}; + +export type ScanStackParams = { + [Screens.Scan]: undefined; + [Screens.ConnectionInvitation]: undefined; + [Screens.ListContacts]: undefined; +}; + +export type SettingStackParams = { + [Screens.Settings]: undefined; + [Screens.Language]: undefined; + [Screens.ChangePin]: undefined; + [Screens.ExportWallet]: undefined; + [Screens.ViewMnemonic]: undefined; +}; + +export enum TabStacks { + HomeStack = 'Tab Home Stack', + ConnectionStack = 'Tab Connection Stack', + ScanStack = 'Tab Scan Stack', + CredentialStack = 'Tab Credential Stack', + SettingsStack = 'Tab Settings Stack', +} + +export type TabStackParams = { + [TabStacks.HomeStack]: NavigatorScreenParams<HomeStackParams>; + [TabStacks.ConnectionStack]: NavigatorScreenParams<ContactStackParams>; + [TabStacks.ScanStack]: NavigatorScreenParams<ScanStackParams>; + [TabStacks.CredentialStack]: NavigatorScreenParams<CredentialStackParams>; + [TabStacks.SettingsStack]: NavigatorScreenParams<SettingStackParams>; +}; + +export enum Stacks { + TabStack = 'Tab Stack', + HomeStack = 'Home Stack', + ConnectStack = 'Connect Stack', + CredentialStack = 'Credentials Stack', + ScanStack = 'Scan Stack', + SettingStack = 'Settings Stack', + ConnectionStack = 'Connection Stack', +} diff --git a/src/types/pcm_error.ts b/src/types/pcm_error.ts new file mode 100644 index 0000000000000000000000000000000000000000..3ad0c6fa1109b760d31f15d464de5430953fae9b --- /dev/null +++ b/src/types/pcm_error.ts @@ -0,0 +1,16 @@ +class PCMError extends Error { + public title: string; + + public code: number; + + public constructor(title: string, message: string, code: number) { + super(message); + this.title = title; + this.code = code; + + // Set the prototype explicitly. + Object.setPrototypeOf(this, PCMError.prototype); + } +} + +export default PCMError; diff --git a/src/types/record.ts b/src/types/record.ts new file mode 100644 index 0000000000000000000000000000000000000000..488a582a577a38d7501278aa3c66910fedee9930 --- /dev/null +++ b/src/types/record.ts @@ -0,0 +1,27 @@ +import { RequestedAttribute } from '@aries-framework/core'; + +export interface Attribute { + name: string; + value: RequestedAttribute; + values?: RequestedAttribute[]; +} + +export interface RecordHistory { + timestamp: string; + connectionLabel: string; + status: string; + attributes: Record<string, string>; +} + +export interface CredentialDisplay { + key: string; + names: string[]; + values: string[]; + credentials: CredentialList[]; +} + +export interface CredentialList { + isSelected: boolean; + label: string; + value: string; +} diff --git a/src/types/states.ts b/src/types/states.ts new file mode 100644 index 0000000000000000000000000000000000000000..ddc8a954577d2dfd1b4af3026db9aec02eb7e2ef --- /dev/null +++ b/src/types/states.ts @@ -0,0 +1,22 @@ +import PCMError from './pcm_error'; + +export interface Onboarding { + DidCompleteTutorial: boolean; + DidAgreeToTerms: boolean; + DidCreatePIN: boolean; +} + +export interface Notifications { + ConnectionPending: boolean; +} + +export interface State { + onboarding: Onboarding; + notifications: Notifications; + error: PCMError | null; +} + +export interface WalletExportImportConfig { + key: string; + path: string; +} diff --git a/src/utils/generic.ts b/src/utils/generic.ts new file mode 100644 index 0000000000000000000000000000000000000000..3b7a8bed846094ecf65d9a3b5c9b3ae41e257a46 --- /dev/null +++ b/src/utils/generic.ts @@ -0,0 +1,39 @@ +import wordsList from './wordsList'; +import { getValueKeychain, setValueKeychain } from './keychain'; +import { Alert } from 'react-native'; + +export const getMnemonicArrayFromWords = (lengthOfWords: number): string[] => { + const wordsArray = []; + for (let index = 1; index <= lengthOfWords; index += 1) { + let diceNumber = ''; + for (let mnemonicWord = 0; mnemonicWord < 5; mnemonicWord += 1) { + const num = Math.floor(Math.random() * 6) + 1; + diceNumber += num; + } + const element = wordsList[diceNumber]; + wordsArray.push(element); + } + + return wordsArray; +}; + +export const getValueFromKeychain = async (key: string) => { + const data = await getValueKeychain({ + service: key, + }); + return data; +}; + +export const saveValueInKeychain = async ( + service: string, + value: string, + description: string, +) => { + try { + await setValueKeychain(description, value, { + service, + }); + } catch (e: any) { + Alert.alert(e); + } +}; diff --git a/src/utils/generic.utils.test.ts b/src/utils/generic.utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..dd7607dd4e9996bb34c289e8933960abbeda5901 --- /dev/null +++ b/src/utils/generic.utils.test.ts @@ -0,0 +1,22 @@ +import * as Utils from './generic'; + +describe('ChangePin.utils', () => { + describe('saveValueInKeychain', () => { + it('should check value is saved in the keychain', async () => { + // Mocked function to saveValueInKeychain + jest.spyOn(Utils, 'saveValueInKeychain'); + + await Utils.saveValueInKeychain( + 'guid', + 'kevin@gmail.com', + 'guid description', + ); + + expect(Utils.saveValueInKeychain).toHaveBeenCalledWith( + 'guid', + 'kevin@gmail.com', + 'guid description', + ); + }); + }); +}); diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts new file mode 100644 index 0000000000000000000000000000000000000000..88b3c6b2c371368744f1abadb3073df42a63e7f9 --- /dev/null +++ b/src/utils/helpers.ts @@ -0,0 +1,127 @@ +/* eslint-disable react-hooks/rules-of-hooks */ +/* eslint-disable no-bitwise */ +import React from 'react'; +import { + CredentialMetadataKeys, + CredentialExchangeRecord, +} from '@aries-framework/core'; +import { + useConnectionById, + useCredentialById, +} from '@aries-framework/react-hooks'; + +export const connectionRecordFromId = (connectionId: string) => { + const connection = useConnectionById(connectionId); + return connection; +}; + +export function parseSchema(schemaId?: string): { + name: string; + version: string; +} { + let name = 'Credential'; + let version = ''; + if (schemaId) { + const schemaIdRegex = /(.*?):([0-9]):([a-zA-Z .\-_0-9]+):([a-z0-9._-]+)$/; + const schemaIdParts = schemaId.match(schemaIdRegex); + if (schemaIdParts?.length === 5) { + name = `${schemaIdParts?.[3].replace(/_|-/g, ' ')}` + .split(' ') + .map( + schemaIdPart => + schemaIdPart.charAt(0).toUpperCase() + schemaIdPart.substring(1), + ) + .join(' '); + version = schemaIdParts?.[4]; + } + } + return { name, version }; +} + +export function parseCredDef(credentialDefinitionId?: string): { + credName: string; +} { + let credName = ''; + if (credentialDefinitionId) { + const credDefIdRegex = + /^([a-zA-Z0-9]{21,22}):3:CL:(([1-9][0-9]*)|([a-zA-Z0-9]{21,22}:2:.+:[0-9.]+)):(.+)?$/; + const credDefParts = credentialDefinitionId.match(credDefIdRegex); + + if (credDefParts?.length === 6) { + credName = `${credDefParts?.[5].replace(/_|-/g, ' ')}` + .split(' ') + .map( + credDefIdPart => + credDefIdPart.charAt(0).toUpperCase() + credDefIdPart.substring(1), + ) + .join(' '); + } + } + return { credName }; +} + +export function credentialSchema( + credential: CredentialExchangeRecord, +): string | undefined { + return credential.metadata.get(CredentialMetadataKeys.IndyCredential) + ?.schemaId; +} + +export function credentialDefinition( + credential: CredentialExchangeRecord, +): string | undefined { + return credential.metadata.get(CredentialMetadataKeys.IndyCredential) + ?.credentialDefinitionId; +} + +export function parsedSchema(credential: CredentialExchangeRecord): { + name: string; + version: string; +} { + return parseSchema(credentialSchema(credential)); +} + +export function parsedCredentialDefinition( + credential: CredentialExchangeRecord, +): { + credName: string; +} { + return parseCredDef(credentialDefinition(credential)); +} + +export function hashCode(s: string): number { + return s + .split('') + .reduce((hash, char) => char.charCodeAt(0) + ((hash << 5) - hash), 0); +} + +export function hashToRGBA(i: number) { + const colour = (i & 0x00ffffff).toString(16).toUpperCase(); + return `#${'00000'.substring(0, 6 - colour.length)}${colour}`; +} + +export const credentialRecordFromId = (credentialId: string) => { + const credential = useCredentialById(credentialId); + return credential; +}; + +interface MainStackContextValue { + setAuthenticated: React.Dispatch<React.SetStateAction<boolean>>; + deepLinkUrl: string | undefined | null; + resetDeepLinkUrl: () => void; +} +export const MainStackContext = React.createContext<MainStackContextValue>({ + setAuthenticated: () => {}, + deepLinkUrl: null, + resetDeepLinkUrl: () => {}, +}); + +export const getCredDefName = (credentialDefinitionId: string) => { + const data = credentialDefinitionId.split(':'); + return data[data.length - 1]; +}; + +export const getSchemaNameFromSchemaId = (schemaId: string) => { + const data = schemaId.split(':'); + return data[data.length - 1]; +}; diff --git a/src/utils/keyboard.ts b/src/utils/keyboard.ts new file mode 100644 index 0000000000000000000000000000000000000000..395184272f8210a27a398b058a6933664b0f7535 --- /dev/null +++ b/src/utils/keyboard.ts @@ -0,0 +1,36 @@ +import { useState, useEffect } from 'react'; +import { KeyboardEvent, Keyboard } from 'react-native'; + +const useKeyboard = () => { + const [keyboardHeight, setKeyboardHeight] = useState(0); + const [isKeyBoardOpen, setIsKeyBoardOpen] = useState(false); + + const onKeyboardDidShow = (e: KeyboardEvent) => { + setIsKeyBoardOpen(true); + setKeyboardHeight(e.endCoordinates.height); + }; + + const onKeyboardDidHide = () => { + setIsKeyBoardOpen(false); + setKeyboardHeight(0); + }; + + useEffect(() => { + const showSubscription = Keyboard.addListener( + 'keyboardDidShow', + onKeyboardDidShow, + ); + const hideSubscription = Keyboard.addListener( + 'keyboardDidHide', + onKeyboardDidHide, + ); + return () => { + showSubscription.remove(); + hideSubscription.remove(); + }; + }, []); + + return { keyboardHeight, isKeyBoardOpen }; +}; + +export default useKeyboard; diff --git a/src/utils/keychain.ts b/src/utils/keychain.ts new file mode 100644 index 0000000000000000000000000000000000000000..c75016e673b021a18aa9cf38e1c7b1a9c09a5840 --- /dev/null +++ b/src/utils/keychain.ts @@ -0,0 +1,16 @@ +import Keychain from 'react-native-keychain'; + +const setValueKeychain = async ( + username: string, + password: string, + service: any, +) => { + await Keychain.setGenericPassword(username, password, service); +}; + +const getValueKeychain = async (service: any) => { + const credentials = await Keychain.getGenericPassword(service); + return credentials; +}; + +export { setValueKeychain, getValueKeychain }; diff --git a/src/utils/testhelpers.ts b/src/utils/testhelpers.ts new file mode 100644 index 0000000000000000000000000000000000000000..3d29676cdb6d7271f9208721f40206d9f5ede200 --- /dev/null +++ b/src/utils/testhelpers.ts @@ -0,0 +1,30 @@ +import { + ConnectionRecordProps, + ConnectionRecord, + DidExchangeState, + DidExchangeRole, +} from '@aries-framework/core'; + +export function getMockConnection({ + state = DidExchangeState.InvitationReceived, + role = DidExchangeRole.Requester, + id = 'test', + did = 'test-did', + threadId = 'threadId', + tags = {}, + theirLabel, + theirDid = 'their-did', +}: Partial<ConnectionRecordProps> = {}) { + return new ConnectionRecord({ + did, + threadId, + theirDid, + id, + role, + state, + tags, + theirLabel, + }); +} + +export default getMockConnection; diff --git a/src/utils/testtable.ts b/src/utils/testtable.ts new file mode 100644 index 0000000000000000000000000000000000000000..e7f5d22cfeb904989c52ebcc301bad6ac230e241 --- /dev/null +++ b/src/utils/testtable.ts @@ -0,0 +1,7 @@ +import { testIdPrefix } from '../constants'; + +const testIdWithKey = (key: string): string => { + return `${testIdPrefix}${key}`; +}; + +export default testIdWithKey; diff --git a/src/utils/toast.ts b/src/utils/toast.ts new file mode 100644 index 0000000000000000000000000000000000000000..beb198955e1809fa7ddc49e4388cde23d9ec4234 --- /dev/null +++ b/src/utils/toast.ts @@ -0,0 +1,32 @@ +import Toast from 'react-native-toast-message'; +import i18next from 'i18next'; +import { ToastType } from '../components/toast/BaseToast'; + +export const successToast = (message: string, title?: string) => { + Toast.show({ + type: ToastType.Success, + text1: title ?? i18next.t<string>('Toasts.Success'), + text2: message, + }); +}; +export const warningToast = (message: string, title?: string) => { + Toast.show({ + type: ToastType.Warn, + text1: title ?? i18next.t<string>('Toasts.Warning'), + text2: message, + }); +}; +export const infoToast = (message: string, title?: string) => { + Toast.show({ + type: ToastType.Info, + text1: title ?? i18next.t<string>('Toasts.Info'), + text2: message, + }); +}; +export const errorToast = (message: string, title?: string) => { + Toast.show({ + type: ToastType.Error, + text1: title ?? i18next.t<string>('Toasts.Error'), + text2: message, + }); +}; diff --git a/src/utils/wordsList.ts b/src/utils/wordsList.ts new file mode 100644 index 0000000000000000000000000000000000000000..5791fec4e75a3bdc40468347f8759ad406e36739 --- /dev/null +++ b/src/utils/wordsList.ts @@ -0,0 +1,7782 @@ +const wordsList: { + [key: string]: string; +} = { + 11111: 'abacus', + 11112: 'abdomen', + 11113: 'abdominal', + 11114: 'abide', + 11115: 'abiding', + 11116: 'ability', + 11121: 'ablaze', + 11122: 'able', + 11123: 'abnormal', + 11124: 'abrasion', + 11125: 'abrasive', + 11126: 'abreast', + 11131: 'abridge', + 11132: 'abroad', + 11133: 'abruptly', + 11134: 'absence', + 11135: 'absentee', + 11136: 'absently', + 11141: 'absinthe', + 11142: 'absolute', + 11143: 'absolve', + 11144: 'abstain', + 11145: 'abstract', + 11146: 'absurd', + 11151: 'accent', + 11152: 'acclaim', + 11153: 'acclimate', + 11154: 'accompany', + 11155: 'account', + 11156: 'accuracy', + 11161: 'accurate', + 11162: 'accustom', + 11163: 'acetone', + 11164: 'achiness', + 11165: 'aching', + 11166: 'acid', + 11211: 'acorn', + 11212: 'acquaint', + 11213: 'acquire', + 11214: 'acre', + 11215: 'acrobat', + 11216: 'acronym', + 11221: 'acting', + 11222: 'action', + 11223: 'activate', + 11224: 'activator', + 11225: 'active', + 11226: 'activism', + 11231: 'activist', + 11232: 'activity', + 11233: 'actress', + 11234: 'acts', + 11235: 'acutely', + 11236: 'acuteness', + 11241: 'aeration', + 11242: 'aerobics', + 11243: 'aerosol', + 11244: 'aerospace', + 11245: 'afar', + 11246: 'affair', + 11251: 'affected', + 11252: 'affecting', + 11253: 'affection', + 11254: 'affidavit', + 11255: 'affiliate', + 11256: 'affirm', + 11261: 'affix', + 11262: 'afflicted', + 11263: 'affluent', + 11264: 'afford', + 11265: 'affront', + 11266: 'aflame', + 11311: 'afloat', + 11312: 'aflutter', + 11313: 'afoot', + 11314: 'afraid', + 11315: 'afterglow', + 11316: 'afterlife', + 11321: 'aftermath', + 11322: 'aftermost', + 11323: 'afternoon', + 11324: 'aged', + 11325: 'ageless', + 11326: 'agency', + 11331: 'agenda', + 11332: 'agent', + 11333: 'aggregate', + 11334: 'aghast', + 11335: 'agile', + 11336: 'agility', + 11341: 'aging', + 11342: 'agnostic', + 11343: 'agonize', + 11344: 'agonizing', + 11345: 'agony', + 11346: 'agreeable', + 11351: 'agreeably', + 11352: 'agreed', + 11353: 'agreeing', + 11354: 'agreement', + 11355: 'aground', + 11356: 'ahead', + 11361: 'ahoy', + 11362: 'aide', + 11363: 'aids', + 11364: 'aim', + 11365: 'ajar', + 11366: 'alabaster', + 11411: 'alarm', + 11412: 'albatross', + 11413: 'album', + 11414: 'alfalfa', + 11415: 'algebra', + 11416: 'algorithm', + 11421: 'alias', + 11422: 'alibi', + 11423: 'alienable', + 11424: 'alienate', + 11425: 'aliens', + 11426: 'alike', + 11431: 'alive', + 11432: 'alkaline', + 11433: 'alkalize', + 11434: 'almanac', + 11435: 'almighty', + 11436: 'almost', + 11441: 'aloe', + 11442: 'aloft', + 11443: 'aloha', + 11444: 'alone', + 11445: 'alongside', + 11446: 'aloof', + 11451: 'alphabet', + 11452: 'alright', + 11453: 'although', + 11454: 'altitude', + 11455: 'alto', + 11456: 'aluminum', + 11461: 'alumni', + 11462: 'always', + 11463: 'amaretto', + 11464: 'amaze', + 11465: 'amazingly', + 11466: 'amber', + 11511: 'ambiance', + 11512: 'ambiguity', + 11513: 'ambiguous', + 11514: 'ambition', + 11515: 'ambitious', + 11516: 'ambulance', + 11521: 'ambush', + 11522: 'amendable', + 11523: 'amendment', + 11524: 'amends', + 11525: 'amenity', + 11526: 'amiable', + 11531: 'amicably', + 11532: 'amid', + 11533: 'amigo', + 11534: 'amino', + 11535: 'amiss', + 11536: 'ammonia', + 11541: 'ammonium', + 11542: 'amnesty', + 11543: 'amniotic', + 11544: 'among', + 11545: 'amount', + 11546: 'amperage', + 11551: 'ample', + 11552: 'amplifier', + 11553: 'amplify', + 11554: 'amply', + 11555: 'amuck', + 11556: 'amulet', + 11561: 'amusable', + 11562: 'amused', + 11563: 'amusement', + 11564: 'amuser', + 11565: 'amusing', + 11566: 'anaconda', + 11611: 'anaerobic', + 11612: 'anagram', + 11613: 'anatomist', + 11614: 'anatomy', + 11615: 'anchor', + 11616: 'anchovy', + 11621: 'ancient', + 11622: 'android', + 11623: 'anemia', + 11624: 'anemic', + 11625: 'aneurism', + 11626: 'anew', + 11631: 'angelfish', + 11632: 'angelic', + 11633: 'anger', + 11634: 'angled', + 11635: 'angler', + 11636: 'angles', + 11641: 'angling', + 11642: 'angrily', + 11643: 'angriness', + 11644: 'anguished', + 11645: 'angular', + 11646: 'animal', + 11651: 'animate', + 11652: 'animating', + 11653: 'animation', + 11654: 'animator', + 11655: 'anime', + 11656: 'animosity', + 11661: 'ankle', + 11662: 'annex', + 11663: 'annotate', + 11664: 'announcer', + 11665: 'annoying', + 11666: 'annually', + 12111: 'annuity', + 12112: 'anointer', + 12113: 'another', + 12114: 'answering', + 12115: 'antacid', + 12116: 'antarctic', + 12121: 'anteater', + 12122: 'antelope', + 12123: 'antennae', + 12124: 'anthem', + 12125: 'anthill', + 12126: 'anthology', + 12131: 'antibody', + 12132: 'antics', + 12133: 'antidote', + 12134: 'antihero', + 12135: 'antiquely', + 12136: 'antiques', + 12141: 'antiquity', + 12142: 'antirust', + 12143: 'antitoxic', + 12144: 'antitrust', + 12145: 'antiviral', + 12146: 'antivirus', + 12151: 'antler', + 12152: 'antonym', + 12153: 'antsy', + 12154: 'anvil', + 12155: 'anybody', + 12156: 'anyhow', + 12161: 'anymore', + 12162: 'anyone', + 12163: 'anyplace', + 12164: 'anything', + 12165: 'anytime', + 12166: 'anyway', + 12211: 'anywhere', + 12212: 'aorta', + 12213: 'apache', + 12214: 'apostle', + 12215: 'appealing', + 12216: 'appear', + 12221: 'appease', + 12222: 'appeasing', + 12223: 'appendage', + 12224: 'appendix', + 12225: 'appetite', + 12226: 'appetizer', + 12231: 'applaud', + 12232: 'applause', + 12233: 'apple', + 12234: 'appliance', + 12235: 'applicant', + 12236: 'applied', + 12241: 'apply', + 12242: 'appointee', + 12243: 'appraisal', + 12244: 'appraiser', + 12245: 'apprehend', + 12246: 'approach', + 12251: 'approval', + 12252: 'approve', + 12253: 'apricot', + 12254: 'april', + 12255: 'apron', + 12256: 'aptitude', + 12261: 'aptly', + 12262: 'aqua', + 12263: 'aqueduct', + 12264: 'arbitrary', + 12265: 'arbitrate', + 12266: 'ardently', + 12311: 'area', + 12312: 'arena', + 12313: 'arguable', + 12314: 'arguably', + 12315: 'argue', + 12316: 'arise', + 12321: 'armadillo', + 12322: 'armband', + 12323: 'armchair', + 12324: 'armed', + 12325: 'armful', + 12326: 'armhole', + 12331: 'arming', + 12332: 'armless', + 12333: 'armoire', + 12334: 'armored', + 12335: 'armory', + 12336: 'armrest', + 12341: 'army', + 12342: 'aroma', + 12343: 'arose', + 12344: 'around', + 12345: 'arousal', + 12346: 'arrange', + 12351: 'array', + 12352: 'arrest', + 12353: 'arrival', + 12354: 'arrive', + 12355: 'arrogance', + 12356: 'arrogant', + 12361: 'arson', + 12362: 'art', + 12363: 'ascend', + 12364: 'ascension', + 12365: 'ascent', + 12366: 'ascertain', + 12411: 'ashamed', + 12412: 'ashen', + 12413: 'ashes', + 12414: 'ashy', + 12415: 'aside', + 12416: 'askew', + 12421: 'asleep', + 12422: 'asparagus', + 12423: 'aspect', + 12424: 'aspirate', + 12425: 'aspire', + 12426: 'aspirin', + 12431: 'astonish', + 12432: 'astound', + 12433: 'astride', + 12434: 'astrology', + 12435: 'astronaut', + 12436: 'astronomy', + 12441: 'astute', + 12442: 'atlantic', + 12443: 'atlas', + 12444: 'atom', + 12445: 'atonable', + 12446: 'atop', + 12451: 'atrium', + 12452: 'atrocious', + 12453: 'atrophy', + 12454: 'attach', + 12455: 'attain', + 12456: 'attempt', + 12461: 'attendant', + 12462: 'attendee', + 12463: 'attention', + 12464: 'attentive', + 12465: 'attest', + 12466: 'attic', + 12511: 'attire', + 12512: 'attitude', + 12513: 'attractor', + 12514: 'attribute', + 12515: 'atypical', + 12516: 'auction', + 12521: 'audacious', + 12522: 'audacity', + 12523: 'audible', + 12524: 'audibly', + 12525: 'audience', + 12526: 'audio', + 12531: 'audition', + 12532: 'augmented', + 12533: 'august', + 12534: 'authentic', + 12535: 'author', + 12536: 'autism', + 12541: 'autistic', + 12542: 'autograph', + 12543: 'automaker', + 12544: 'automated', + 12545: 'automatic', + 12546: 'autopilot', + 12551: 'available', + 12552: 'avalanche', + 12553: 'avatar', + 12554: 'avenge', + 12555: 'avenging', + 12556: 'avenue', + 12561: 'average', + 12562: 'aversion', + 12563: 'avert', + 12564: 'aviation', + 12565: 'aviator', + 12566: 'avid', + 12611: 'avoid', + 12612: 'await', + 12613: 'awaken', + 12614: 'award', + 12615: 'aware', + 12616: 'awhile', + 12621: 'awkward', + 12622: 'awning', + 12623: 'awoke', + 12624: 'awry', + 12625: 'axis', + 12626: 'babble', + 12631: 'babbling', + 12632: 'babied', + 12633: 'baboon', + 12634: 'backache', + 12635: 'backboard', + 12636: 'backboned', + 12641: 'backdrop', + 12642: 'backed', + 12643: 'backer', + 12644: 'backfield', + 12645: 'backfire', + 12646: 'backhand', + 12651: 'backing', + 12652: 'backlands', + 12653: 'backlash', + 12654: 'backless', + 12655: 'backlight', + 12656: 'backlit', + 12661: 'backlog', + 12662: 'backpack', + 12663: 'backpedal', + 12664: 'backrest', + 12665: 'backroom', + 12666: 'backshift', + 13111: 'backside', + 13112: 'backslid', + 13113: 'backspace', + 13114: 'backspin', + 13115: 'backstab', + 13116: 'backstage', + 13121: 'backtalk', + 13122: 'backtrack', + 13123: 'backup', + 13124: 'backward', + 13125: 'backwash', + 13126: 'backwater', + 13131: 'backyard', + 13132: 'bacon', + 13133: 'bacteria', + 13134: 'bacterium', + 13135: 'badass', + 13136: 'badge', + 13141: 'badland', + 13142: 'badly', + 13143: 'badness', + 13144: 'baffle', + 13145: 'baffling', + 13146: 'bagel', + 13151: 'bagful', + 13152: 'baggage', + 13153: 'bagged', + 13154: 'baggie', + 13155: 'bagginess', + 13156: 'bagging', + 13161: 'baggy', + 13162: 'bagpipe', + 13163: 'baguette', + 13164: 'baked', + 13165: 'bakery', + 13166: 'bakeshop', + 13211: 'baking', + 13212: 'balance', + 13213: 'balancing', + 13214: 'balcony', + 13215: 'balmy', + 13216: 'balsamic', + 13221: 'bamboo', + 13222: 'banana', + 13223: 'banish', + 13224: 'banister', + 13225: 'banjo', + 13226: 'bankable', + 13231: 'bankbook', + 13232: 'banked', + 13233: 'banker', + 13234: 'banking', + 13235: 'banknote', + 13236: 'bankroll', + 13241: 'banner', + 13242: 'bannister', + 13243: 'banshee', + 13244: 'banter', + 13245: 'barbecue', + 13246: 'barbed', + 13251: 'barbell', + 13252: 'barber', + 13253: 'barcode', + 13254: 'barge', + 13255: 'bargraph', + 13256: 'barista', + 13261: 'baritone', + 13262: 'barley', + 13263: 'barmaid', + 13264: 'barman', + 13265: 'barn', + 13266: 'barometer', + 13311: 'barrack', + 13312: 'barracuda', + 13313: 'barrel', + 13314: 'barrette', + 13315: 'barricade', + 13316: 'barrier', + 13321: 'barstool', + 13322: 'bartender', + 13323: 'barterer', + 13324: 'bash', + 13325: 'basically', + 13326: 'basics', + 13331: 'basil', + 13332: 'basin', + 13333: 'basis', + 13334: 'basket', + 13335: 'batboy', + 13336: 'batch', + 13341: 'bath', + 13342: 'baton', + 13343: 'bats', + 13344: 'battalion', + 13345: 'battered', + 13346: 'battering', + 13351: 'battery', + 13352: 'batting', + 13353: 'battle', + 13354: 'bauble', + 13355: 'bazooka', + 13356: 'blabber', + 13361: 'bladder', + 13362: 'blade', + 13363: 'blah', + 13364: 'blame', + 13365: 'blaming', + 13366: 'blanching', + 13411: 'blandness', + 13412: 'blank', + 13413: 'blaspheme', + 13414: 'blasphemy', + 13415: 'blast', + 13416: 'blatancy', + 13421: 'blatantly', + 13422: 'blazer', + 13423: 'blazing', + 13424: 'bleach', + 13425: 'bleak', + 13426: 'bleep', + 13431: 'blemish', + 13432: 'blend', + 13433: 'bless', + 13434: 'blighted', + 13435: 'blimp', + 13436: 'bling', + 13441: 'blinked', + 13442: 'blinker', + 13443: 'blinking', + 13444: 'blinks', + 13445: 'blip', + 13446: 'blissful', + 13451: 'blitz', + 13452: 'blizzard', + 13453: 'bloated', + 13454: 'bloating', + 13455: 'blob', + 13456: 'blog', + 13461: 'bloomers', + 13462: 'blooming', + 13463: 'blooper', + 13464: 'blot', + 13465: 'blouse', + 13466: 'blubber', + 13511: 'bluff', + 13512: 'bluish', + 13513: 'blunderer', + 13514: 'blunt', + 13515: 'blurb', + 13516: 'blurred', + 13521: 'blurry', + 13522: 'blurt', + 13523: 'blush', + 13524: 'blustery', + 13525: 'boaster', + 13526: 'boastful', + 13531: 'boasting', + 13532: 'boat', + 13533: 'bobbed', + 13534: 'bobbing', + 13535: 'bobble', + 13536: 'bobcat', + 13541: 'bobsled', + 13542: 'bobtail', + 13543: 'bodacious', + 13544: 'body', + 13545: 'bogged', + 13546: 'boggle', + 13551: 'bogus', + 13552: 'boil', + 13553: 'bok', + 13554: 'bolster', + 13555: 'bolt', + 13556: 'bonanza', + 13561: 'bonded', + 13562: 'bonding', + 13563: 'bondless', + 13564: 'boned', + 13565: 'bonehead', + 13566: 'boneless', + 13611: 'bonelike', + 13612: 'boney', + 13613: 'bonfire', + 13614: 'bonnet', + 13615: 'bonsai', + 13616: 'bonus', + 13621: 'bony', + 13622: 'boogeyman', + 13623: 'boogieman', + 13624: 'book', + 13625: 'boondocks', + 13626: 'booted', + 13631: 'booth', + 13632: 'bootie', + 13633: 'booting', + 13634: 'bootlace', + 13635: 'bootleg', + 13636: 'boots', + 13641: 'boozy', + 13642: 'borax', + 13643: 'boring', + 13644: 'borough', + 13645: 'borrower', + 13646: 'borrowing', + 13651: 'boss', + 13652: 'botanical', + 13653: 'botanist', + 13654: 'botany', + 13655: 'botch', + 13656: 'both', + 13661: 'bottle', + 13662: 'bottling', + 13663: 'bottom', + 13664: 'bounce', + 13665: 'bouncing', + 13666: 'bouncy', + 14111: 'bounding', + 14112: 'boundless', + 14113: 'bountiful', + 14114: 'bovine', + 14115: 'boxcar', + 14116: 'boxer', + 14121: 'boxing', + 14122: 'boxlike', + 14123: 'boxy', + 14124: 'breach', + 14125: 'breath', + 14126: 'breeches', + 14131: 'breeching', + 14132: 'breeder', + 14133: 'breeding', + 14134: 'breeze', + 14135: 'breezy', + 14136: 'brethren', + 14141: 'brewery', + 14142: 'brewing', + 14143: 'briar', + 14144: 'bribe', + 14145: 'brick', + 14146: 'bride', + 14151: 'bridged', + 14152: 'brigade', + 14153: 'bright', + 14154: 'brilliant', + 14155: 'brim', + 14156: 'bring', + 14161: 'brink', + 14162: 'brisket', + 14163: 'briskly', + 14164: 'briskness', + 14165: 'bristle', + 14166: 'brittle', + 14211: 'broadband', + 14212: 'broadcast', + 14213: 'broaden', + 14214: 'broadly', + 14215: 'broadness', + 14216: 'broadside', + 14221: 'broadways', + 14222: 'broiler', + 14223: 'broiling', + 14224: 'broken', + 14225: 'broker', + 14226: 'bronchial', + 14231: 'bronco', + 14232: 'bronze', + 14233: 'bronzing', + 14234: 'brook', + 14235: 'broom', + 14236: 'brought', + 14241: 'browbeat', + 14242: 'brownnose', + 14243: 'browse', + 14244: 'browsing', + 14245: 'bruising', + 14246: 'brunch', + 14251: 'brunette', + 14252: 'brunt', + 14253: 'brush', + 14254: 'brussels', + 14255: 'brute', + 14256: 'brutishly', + 14261: 'bubble', + 14262: 'bubbling', + 14263: 'bubbly', + 14264: 'buccaneer', + 14265: 'bucked', + 14266: 'bucket', + 14311: 'buckle', + 14312: 'buckshot', + 14313: 'buckskin', + 14314: 'bucktooth', + 14315: 'buckwheat', + 14316: 'buddhism', + 14321: 'buddhist', + 14322: 'budding', + 14323: 'buddy', + 14324: 'budget', + 14325: 'buffalo', + 14326: 'buffed', + 14331: 'buffer', + 14332: 'buffing', + 14333: 'buffoon', + 14334: 'buggy', + 14335: 'bulb', + 14336: 'bulge', + 14341: 'bulginess', + 14342: 'bulgur', + 14343: 'bulk', + 14344: 'bulldog', + 14345: 'bulldozer', + 14346: 'bullfight', + 14351: 'bullfrog', + 14352: 'bullhorn', + 14353: 'bullion', + 14354: 'bullish', + 14355: 'bullpen', + 14356: 'bullring', + 14361: 'bullseye', + 14362: 'bullwhip', + 14363: 'bully', + 14364: 'bunch', + 14365: 'bundle', + 14366: 'bungee', + 14411: 'bunion', + 14412: 'bunkbed', + 14413: 'bunkhouse', + 14414: 'bunkmate', + 14415: 'bunny', + 14416: 'bunt', + 14421: 'busboy', + 14422: 'bush', + 14423: 'busily', + 14424: 'busload', + 14425: 'bust', + 14426: 'busybody', + 14431: 'buzz', + 14432: 'cabana', + 14433: 'cabbage', + 14434: 'cabbie', + 14435: 'cabdriver', + 14436: 'cable', + 14441: 'caboose', + 14442: 'cache', + 14443: 'cackle', + 14444: 'cacti', + 14445: 'cactus', + 14446: 'caddie', + 14451: 'caddy', + 14452: 'cadet', + 14453: 'cadillac', + 14454: 'cadmium', + 14455: 'cage', + 14456: 'cahoots', + 14461: 'cake', + 14462: 'calamari', + 14463: 'calamity', + 14464: 'calcium', + 14465: 'calculate', + 14466: 'calculus', + 14511: 'caliber', + 14512: 'calibrate', + 14513: 'calm', + 14514: 'caloric', + 14515: 'calorie', + 14516: 'calzone', + 14521: 'camcorder', + 14522: 'cameo', + 14523: 'camera', + 14524: 'camisole', + 14525: 'camper', + 14526: 'campfire', + 14531: 'camping', + 14532: 'campsite', + 14533: 'campus', + 14534: 'canal', + 14535: 'canary', + 14536: 'cancel', + 14541: 'candied', + 14542: 'candle', + 14543: 'candy', + 14544: 'cane', + 14545: 'canine', + 14546: 'canister', + 14551: 'cannabis', + 14552: 'canned', + 14553: 'canning', + 14554: 'cannon', + 14555: 'cannot', + 14556: 'canola', + 14561: 'canon', + 14562: 'canopener', + 14563: 'canopy', + 14564: 'canteen', + 14565: 'canyon', + 14566: 'capable', + 14611: 'capably', + 14612: 'capacity', + 14613: 'cape', + 14614: 'capillary', + 14615: 'capital', + 14616: 'capitol', + 14621: 'capped', + 14622: 'capricorn', + 14623: 'capsize', + 14624: 'capsule', + 14625: 'caption', + 14626: 'captivate', + 14631: 'captive', + 14632: 'captivity', + 14633: 'capture', + 14634: 'caramel', + 14635: 'carat', + 14636: 'caravan', + 14641: 'carbon', + 14642: 'cardboard', + 14643: 'carded', + 14644: 'cardiac', + 14645: 'cardigan', + 14646: 'cardinal', + 14651: 'cardstock', + 14652: 'carefully', + 14653: 'caregiver', + 14654: 'careless', + 14655: 'caress', + 14656: 'caretaker', + 14661: 'cargo', + 14662: 'caring', + 14663: 'carless', + 14664: 'carload', + 14665: 'carmaker', + 14666: 'carnage', + 15111: 'carnation', + 15112: 'carnival', + 15113: 'carnivore', + 15114: 'carol', + 15115: 'carpenter', + 15116: 'carpentry', + 15121: 'carpool', + 15122: 'carport', + 15123: 'carried', + 15124: 'carrot', + 15125: 'carrousel', + 15126: 'carry', + 15131: 'cartel', + 15132: 'cartload', + 15133: 'carton', + 15134: 'cartoon', + 15135: 'cartridge', + 15136: 'cartwheel', + 15141: 'carve', + 15142: 'carving', + 15143: 'carwash', + 15144: 'cascade', + 15145: 'case', + 15146: 'cash', + 15151: 'casing', + 15152: 'casino', + 15153: 'casket', + 15154: 'cassette', + 15155: 'casually', + 15156: 'casualty', + 15161: 'catacomb', + 15162: 'catalog', + 15163: 'catalyst', + 15164: 'catalyze', + 15165: 'catapult', + 15166: 'cataract', + 15211: 'catatonic', + 15212: 'catcall', + 15213: 'catchable', + 15214: 'catcher', + 15215: 'catching', + 15216: 'catchy', + 15221: 'caterer', + 15222: 'catering', + 15223: 'catfight', + 15224: 'catfish', + 15225: 'cathedral', + 15226: 'cathouse', + 15231: 'catlike', + 15232: 'catnap', + 15233: 'catnip', + 15234: 'catsup', + 15235: 'cattail', + 15236: 'cattishly', + 15241: 'cattle', + 15242: 'catty', + 15243: 'catwalk', + 15244: 'caucasian', + 15245: 'caucus', + 15246: 'causal', + 15251: 'causation', + 15252: 'cause', + 15253: 'causing', + 15254: 'cauterize', + 15255: 'caution', + 15256: 'cautious', + 15261: 'cavalier', + 15262: 'cavalry', + 15263: 'caviar', + 15264: 'cavity', + 15265: 'cedar', + 15266: 'celery', + 15311: 'celestial', + 15312: 'celibacy', + 15313: 'celibate', + 15314: 'celtic', + 15315: 'cement', + 15316: 'census', + 15321: 'ceramics', + 15322: 'ceremony', + 15323: 'certainly', + 15324: 'certainty', + 15325: 'certified', + 15326: 'certify', + 15331: 'cesarean', + 15332: 'cesspool', + 15333: 'chafe', + 15334: 'chaffing', + 15335: 'chain', + 15336: 'chair', + 15341: 'chalice', + 15342: 'challenge', + 15343: 'chamber', + 15344: 'chamomile', + 15345: 'champion', + 15346: 'chance', + 15351: 'change', + 15352: 'channel', + 15353: 'chant', + 15354: 'chaos', + 15355: 'chaperone', + 15356: 'chaplain', + 15361: 'chapped', + 15362: 'chaps', + 15363: 'chapter', + 15364: 'character', + 15365: 'charbroil', + 15366: 'charcoal', + 15411: 'charger', + 15412: 'charging', + 15413: 'chariot', + 15414: 'charity', + 15415: 'charm', + 15416: 'charred', + 15421: 'charter', + 15422: 'charting', + 15423: 'chase', + 15424: 'chasing', + 15425: 'chaste', + 15426: 'chastise', + 15431: 'chastity', + 15432: 'chatroom', + 15433: 'chatter', + 15434: 'chatting', + 15435: 'chatty', + 15436: 'cheating', + 15441: 'cheddar', + 15442: 'cheek', + 15443: 'cheer', + 15444: 'cheese', + 15445: 'cheesy', + 15446: 'chef', + 15451: 'chemicals', + 15452: 'chemist', + 15453: 'chemo', + 15454: 'cherisher', + 15455: 'cherub', + 15456: 'chess', + 15461: 'chest', + 15462: 'chevron', + 15463: 'chevy', + 15464: 'chewable', + 15465: 'chewer', + 15466: 'chewing', + 15511: 'chewy', + 15512: 'chief', + 15513: 'chihuahua', + 15514: 'childcare', + 15515: 'childhood', + 15516: 'childish', + 15521: 'childless', + 15522: 'childlike', + 15523: 'chili', + 15524: 'chill', + 15525: 'chimp', + 15526: 'chip', + 15531: 'chirping', + 15532: 'chirpy', + 15533: 'chitchat', + 15534: 'chivalry', + 15535: 'chive', + 15536: 'chloride', + 15541: 'chlorine', + 15542: 'choice', + 15543: 'chokehold', + 15544: 'choking', + 15545: 'chomp', + 15546: 'chooser', + 15551: 'choosing', + 15552: 'choosy', + 15553: 'chop', + 15554: 'chosen', + 15555: 'chowder', + 15556: 'chowtime', + 15561: 'chrome', + 15562: 'chubby', + 15563: 'chuck', + 15564: 'chug', + 15565: 'chummy', + 15566: 'chump', + 15611: 'chunk', + 15612: 'churn', + 15613: 'chute', + 15614: 'cider', + 15615: 'cilantro', + 15616: 'cinch', + 15621: 'cinema', + 15622: 'cinnamon', + 15623: 'circle', + 15624: 'circling', + 15625: 'circular', + 15626: 'circulate', + 15631: 'circus', + 15632: 'citable', + 15633: 'citadel', + 15634: 'citation', + 15635: 'citizen', + 15636: 'citric', + 15641: 'citrus', + 15642: 'city', + 15643: 'civic', + 15644: 'civil', + 15645: 'clad', + 15646: 'claim', + 15651: 'clambake', + 15652: 'clammy', + 15653: 'clamor', + 15654: 'clamp', + 15655: 'clamshell', + 15656: 'clang', + 15661: 'clanking', + 15662: 'clapped', + 15663: 'clapper', + 15664: 'clapping', + 15665: 'clarify', + 15666: 'clarinet', + 16111: 'clarity', + 16112: 'clash', + 16113: 'clasp', + 16114: 'class', + 16115: 'clatter', + 16116: 'clause', + 16121: 'clavicle', + 16122: 'claw', + 16123: 'clay', + 16124: 'clean', + 16125: 'clear', + 16126: 'cleat', + 16131: 'cleaver', + 16132: 'cleft', + 16133: 'clench', + 16134: 'clergyman', + 16135: 'clerical', + 16136: 'clerk', + 16141: 'clever', + 16142: 'clicker', + 16143: 'client', + 16144: 'climate', + 16145: 'climatic', + 16146: 'cling', + 16151: 'clinic', + 16152: 'clinking', + 16153: 'clip', + 16154: 'clique', + 16155: 'cloak', + 16156: 'clobber', + 16161: 'clock', + 16162: 'clone', + 16163: 'cloning', + 16164: 'closable', + 16165: 'closure', + 16166: 'clothes', + 16211: 'clothing', + 16212: 'cloud', + 16213: 'clover', + 16214: 'clubbed', + 16215: 'clubbing', + 16216: 'clubhouse', + 16221: 'clump', + 16222: 'clumsily', + 16223: 'clumsy', + 16224: 'clunky', + 16225: 'clustered', + 16226: 'clutch', + 16231: 'clutter', + 16232: 'coach', + 16233: 'coagulant', + 16234: 'coastal', + 16235: 'coaster', + 16236: 'coasting', + 16241: 'coastland', + 16242: 'coastline', + 16243: 'coat', + 16244: 'coauthor', + 16245: 'cobalt', + 16246: 'cobbler', + 16251: 'cobweb', + 16252: 'cocoa', + 16253: 'coconut', + 16254: 'cod', + 16255: 'coeditor', + 16256: 'coerce', + 16261: 'coexist', + 16262: 'coffee', + 16263: 'cofounder', + 16264: 'cognition', + 16265: 'cognitive', + 16266: 'cogwheel', + 16311: 'coherence', + 16312: 'coherent', + 16313: 'cohesive', + 16314: 'coil', + 16315: 'coke', + 16316: 'cola', + 16321: 'cold', + 16322: 'coleslaw', + 16323: 'coliseum', + 16324: 'collage', + 16325: 'collapse', + 16326: 'collar', + 16331: 'collected', + 16332: 'collector', + 16333: 'collide', + 16334: 'collie', + 16335: 'collision', + 16336: 'colonial', + 16341: 'colonist', + 16342: 'colonize', + 16343: 'colony', + 16344: 'colossal', + 16345: 'colt', + 16346: 'coma', + 16351: 'come', + 16352: 'comfort', + 16353: 'comfy', + 16354: 'comic', + 16355: 'coming', + 16356: 'comma', + 16361: 'commence', + 16362: 'commend', + 16363: 'comment', + 16364: 'commerce', + 16365: 'commode', + 16366: 'commodity', + 16411: 'commodore', + 16412: 'common', + 16413: 'commotion', + 16414: 'commute', + 16415: 'commuting', + 16416: 'compacted', + 16421: 'compacter', + 16422: 'compactly', + 16423: 'compactor', + 16424: 'companion', + 16425: 'company', + 16426: 'compare', + 16431: 'compel', + 16432: 'compile', + 16433: 'comply', + 16434: 'component', + 16435: 'composed', + 16436: 'composer', + 16441: 'composite', + 16442: 'compost', + 16443: 'composure', + 16444: 'compound', + 16445: 'compress', + 16446: 'comprised', + 16451: 'computer', + 16452: 'computing', + 16453: 'comrade', + 16454: 'concave', + 16455: 'conceal', + 16456: 'conceded', + 16461: 'concept', + 16462: 'concerned', + 16463: 'concert', + 16464: 'conch', + 16465: 'concierge', + 16466: 'concise', + 16511: 'conclude', + 16512: 'concrete', + 16513: 'concur', + 16514: 'condense', + 16515: 'condiment', + 16516: 'condition', + 16521: 'condone', + 16522: 'conducive', + 16523: 'conductor', + 16524: 'conduit', + 16525: 'cone', + 16526: 'confess', + 16531: 'confetti', + 16532: 'confidant', + 16533: 'confident', + 16534: 'confider', + 16535: 'confiding', + 16536: 'configure', + 16541: 'confined', + 16542: 'confining', + 16543: 'confirm', + 16544: 'conflict', + 16545: 'conform', + 16546: 'confound', + 16551: 'confront', + 16552: 'confused', + 16553: 'confusing', + 16554: 'confusion', + 16555: 'congenial', + 16556: 'congested', + 16561: 'congrats', + 16562: 'congress', + 16563: 'conical', + 16564: 'conjoined', + 16565: 'conjure', + 16566: 'conjuror', + 16611: 'connected', + 16612: 'connector', + 16613: 'consensus', + 16614: 'consent', + 16615: 'console', + 16616: 'consoling', + 16621: 'consonant', + 16622: 'constable', + 16623: 'constant', + 16624: 'constrain', + 16625: 'constrict', + 16626: 'construct', + 16631: 'consult', + 16632: 'consumer', + 16633: 'consuming', + 16634: 'contact', + 16635: 'container', + 16636: 'contempt', + 16641: 'contend', + 16642: 'contented', + 16643: 'contently', + 16644: 'contents', + 16645: 'contest', + 16646: 'context', + 16651: 'contort', + 16652: 'contour', + 16653: 'contrite', + 16654: 'control', + 16655: 'contusion', + 16656: 'convene', + 16661: 'convent', + 16662: 'copartner', + 16663: 'cope', + 16664: 'copied', + 16665: 'copier', + 16666: 'copilot', + 21111: 'coping', + 21112: 'copious', + 21113: 'copper', + 21114: 'copy', + 21115: 'coral', + 21116: 'cork', + 21121: 'cornball', + 21122: 'cornbread', + 21123: 'corncob', + 21124: 'cornea', + 21125: 'corned', + 21126: 'corner', + 21131: 'cornfield', + 21132: 'cornflake', + 21133: 'cornhusk', + 21134: 'cornmeal', + 21135: 'cornstalk', + 21136: 'corny', + 21141: 'coronary', + 21142: 'coroner', + 21143: 'corporal', + 21144: 'corporate', + 21145: 'corral', + 21146: 'correct', + 21151: 'corridor', + 21152: 'corrode', + 21153: 'corroding', + 21154: 'corrosive', + 21155: 'corsage', + 21156: 'corset', + 21161: 'cortex', + 21162: 'cosigner', + 21163: 'cosmetics', + 21164: 'cosmic', + 21165: 'cosmos', + 21166: 'cosponsor', + 21211: 'cost', + 21212: 'cottage', + 21213: 'cotton', + 21214: 'couch', + 21215: 'cough', + 21216: 'could', + 21221: 'countable', + 21222: 'countdown', + 21223: 'counting', + 21224: 'countless', + 21225: 'country', + 21226: 'county', + 21231: 'courier', + 21232: 'covenant', + 21233: 'cover', + 21234: 'coveted', + 21235: 'coveting', + 21236: 'coyness', + 21241: 'cozily', + 21242: 'coziness', + 21243: 'cozy', + 21244: 'crabbing', + 21245: 'crabgrass', + 21246: 'crablike', + 21251: 'crabmeat', + 21252: 'cradle', + 21253: 'cradling', + 21254: 'crafter', + 21255: 'craftily', + 21256: 'craftsman', + 21261: 'craftwork', + 21262: 'crafty', + 21263: 'cramp', + 21264: 'cranberry', + 21265: 'crane', + 21266: 'cranial', + 21311: 'cranium', + 21312: 'crank', + 21313: 'crate', + 21314: 'crave', + 21315: 'craving', + 21316: 'crawfish', + 21321: 'crawlers', + 21322: 'crawling', + 21323: 'crayfish', + 21324: 'crayon', + 21325: 'crazed', + 21326: 'crazily', + 21331: 'craziness', + 21332: 'crazy', + 21333: 'creamed', + 21334: 'creamer', + 21335: 'creamlike', + 21336: 'crease', + 21341: 'creasing', + 21342: 'creatable', + 21343: 'create', + 21344: 'creation', + 21345: 'creative', + 21346: 'creature', + 21351: 'credible', + 21352: 'credibly', + 21353: 'credit', + 21354: 'creed', + 21355: 'creme', + 21356: 'creole', + 21361: 'crepe', + 21362: 'crept', + 21363: 'crescent', + 21364: 'crested', + 21365: 'cresting', + 21366: 'crestless', + 21411: 'crevice', + 21412: 'crewless', + 21413: 'crewman', + 21414: 'crewmate', + 21415: 'crib', + 21416: 'cricket', + 21421: 'cried', + 21422: 'crier', + 21423: 'crimp', + 21424: 'crimson', + 21425: 'cringe', + 21426: 'cringing', + 21431: 'crinkle', + 21432: 'crinkly', + 21433: 'crisped', + 21434: 'crisping', + 21435: 'crisply', + 21436: 'crispness', + 21441: 'crispy', + 21442: 'criteria', + 21443: 'critter', + 21444: 'croak', + 21445: 'crock', + 21446: 'crook', + 21451: 'croon', + 21452: 'crop', + 21453: 'cross', + 21454: 'crouch', + 21455: 'crouton', + 21456: 'crowbar', + 21461: 'crowd', + 21462: 'crown', + 21463: 'crucial', + 21464: 'crudely', + 21465: 'crudeness', + 21466: 'cruelly', + 21511: 'cruelness', + 21512: 'cruelty', + 21513: 'crumb', + 21514: 'crummiest', + 21515: 'crummy', + 21516: 'crumpet', + 21521: 'crumpled', + 21522: 'cruncher', + 21523: 'crunching', + 21524: 'crunchy', + 21525: 'crusader', + 21526: 'crushable', + 21531: 'crushed', + 21532: 'crusher', + 21533: 'crushing', + 21534: 'crust', + 21535: 'crux', + 21536: 'crying', + 21541: 'cryptic', + 21542: 'crystal', + 21543: 'cubbyhole', + 21544: 'cube', + 21545: 'cubical', + 21546: 'cubicle', + 21551: 'cucumber', + 21552: 'cuddle', + 21553: 'cuddly', + 21554: 'cufflink', + 21555: 'culinary', + 21556: 'culminate', + 21561: 'culpable', + 21562: 'culprit', + 21563: 'cultivate', + 21564: 'cultural', + 21565: 'culture', + 21566: 'cupbearer', + 21611: 'cupcake', + 21612: 'cupid', + 21613: 'cupped', + 21614: 'cupping', + 21615: 'curable', + 21616: 'curator', + 21621: 'curdle', + 21622: 'cure', + 21623: 'curfew', + 21624: 'curing', + 21625: 'curled', + 21626: 'curler', + 21631: 'curliness', + 21632: 'curling', + 21633: 'curly', + 21634: 'curry', + 21635: 'curse', + 21636: 'cursive', + 21641: 'cursor', + 21642: 'curtain', + 21643: 'curtly', + 21644: 'curtsy', + 21645: 'curvature', + 21646: 'curve', + 21651: 'curvy', + 21652: 'cushy', + 21653: 'cusp', + 21654: 'cussed', + 21655: 'custard', + 21656: 'custodian', + 21661: 'custody', + 21662: 'customary', + 21663: 'customer', + 21664: 'customize', + 21665: 'customs', + 21666: 'cut', + 22111: 'cycle', + 22112: 'cyclic', + 22113: 'cycling', + 22114: 'cyclist', + 22115: 'cylinder', + 22116: 'cymbal', + 22121: 'cytoplasm', + 22122: 'cytoplast', + 22123: 'dab', + 22124: 'dad', + 22125: 'daffodil', + 22126: 'dagger', + 22131: 'daily', + 22132: 'daintily', + 22133: 'dainty', + 22134: 'dairy', + 22135: 'daisy', + 22136: 'dallying', + 22141: 'dance', + 22142: 'dancing', + 22143: 'dandelion', + 22144: 'dander', + 22145: 'dandruff', + 22146: 'dandy', + 22151: 'danger', + 22152: 'dangle', + 22153: 'dangling', + 22154: 'daredevil', + 22155: 'dares', + 22156: 'daringly', + 22161: 'darkened', + 22162: 'darkening', + 22163: 'darkish', + 22164: 'darkness', + 22165: 'darkroom', + 22166: 'darling', + 22211: 'darn', + 22212: 'dart', + 22213: 'darwinism', + 22214: 'dash', + 22215: 'dastardly', + 22216: 'data', + 22221: 'datebook', + 22222: 'dating', + 22223: 'daughter', + 22224: 'daunting', + 22225: 'dawdler', + 22226: 'dawn', + 22231: 'daybed', + 22232: 'daybreak', + 22233: 'daycare', + 22234: 'daydream', + 22235: 'daylight', + 22236: 'daylong', + 22241: 'dayroom', + 22242: 'daytime', + 22243: 'dazzler', + 22244: 'dazzling', + 22245: 'deacon', + 22246: 'deafening', + 22251: 'deafness', + 22252: 'dealer', + 22253: 'dealing', + 22254: 'dealmaker', + 22255: 'dealt', + 22256: 'dean', + 22261: 'debatable', + 22262: 'debate', + 22263: 'debating', + 22264: 'debit', + 22265: 'debrief', + 22266: 'debtless', + 22311: 'debtor', + 22312: 'debug', + 22313: 'debunk', + 22314: 'decade', + 22315: 'decaf', + 22316: 'decal', + 22321: 'decathlon', + 22322: 'decay', + 22323: 'deceased', + 22324: 'deceit', + 22325: 'deceiver', + 22326: 'deceiving', + 22331: 'december', + 22332: 'decency', + 22333: 'decent', + 22334: 'deception', + 22335: 'deceptive', + 22336: 'decibel', + 22341: 'decidable', + 22342: 'decimal', + 22343: 'decimeter', + 22344: 'decipher', + 22345: 'deck', + 22346: 'declared', + 22351: 'decline', + 22352: 'decode', + 22353: 'decompose', + 22354: 'decorated', + 22355: 'decorator', + 22356: 'decoy', + 22361: 'decrease', + 22362: 'decree', + 22363: 'dedicate', + 22364: 'dedicator', + 22365: 'deduce', + 22366: 'deduct', + 22411: 'deed', + 22412: 'deem', + 22413: 'deepen', + 22414: 'deeply', + 22415: 'deepness', + 22416: 'deface', + 22421: 'defacing', + 22422: 'defame', + 22423: 'default', + 22424: 'defeat', + 22425: 'defection', + 22426: 'defective', + 22431: 'defendant', + 22432: 'defender', + 22433: 'defense', + 22434: 'defensive', + 22435: 'deferral', + 22436: 'deferred', + 22441: 'defiance', + 22442: 'defiant', + 22443: 'defile', + 22444: 'defiling', + 22445: 'define', + 22446: 'definite', + 22451: 'deflate', + 22452: 'deflation', + 22453: 'deflator', + 22454: 'deflected', + 22455: 'deflector', + 22456: 'defog', + 22461: 'deforest', + 22462: 'defraud', + 22463: 'defrost', + 22464: 'deftly', + 22465: 'defuse', + 22466: 'defy', + 22511: 'degraded', + 22512: 'degrading', + 22513: 'degrease', + 22514: 'degree', + 22515: 'dehydrate', + 22516: 'deity', + 22521: 'dejected', + 22522: 'delay', + 22523: 'delegate', + 22524: 'delegator', + 22525: 'delete', + 22526: 'deletion', + 22531: 'delicacy', + 22532: 'delicate', + 22533: 'delicious', + 22534: 'delighted', + 22535: 'delirious', + 22536: 'delirium', + 22541: 'deliverer', + 22542: 'delivery', + 22543: 'delouse', + 22544: 'delta', + 22545: 'deluge', + 22546: 'delusion', + 22551: 'deluxe', + 22552: 'demanding', + 22553: 'demeaning', + 22554: 'demeanor', + 22555: 'demise', + 22556: 'democracy', + 22561: 'democrat', + 22562: 'demote', + 22563: 'demotion', + 22564: 'demystify', + 22565: 'denatured', + 22566: 'deniable', + 22611: 'denial', + 22612: 'denim', + 22613: 'denote', + 22614: 'dense', + 22615: 'density', + 22616: 'dental', + 22621: 'dentist', + 22622: 'denture', + 22623: 'deny', + 22624: 'deodorant', + 22625: 'deodorize', + 22626: 'departed', + 22631: 'departure', + 22632: 'depict', + 22633: 'deplete', + 22634: 'depletion', + 22635: 'deplored', + 22636: 'deploy', + 22641: 'deport', + 22642: 'depose', + 22643: 'depraved', + 22644: 'depravity', + 22645: 'deprecate', + 22646: 'depress', + 22651: 'deprive', + 22652: 'depth', + 22653: 'deputize', + 22654: 'deputy', + 22655: 'derail', + 22656: 'deranged', + 22661: 'derby', + 22662: 'derived', + 22663: 'desecrate', + 22664: 'deserve', + 22665: 'deserving', + 22666: 'designate', + 23111: 'designed', + 23112: 'designer', + 23113: 'designing', + 23114: 'deskbound', + 23115: 'desktop', + 23116: 'deskwork', + 23121: 'desolate', + 23122: 'despair', + 23123: 'despise', + 23124: 'despite', + 23125: 'destiny', + 23126: 'destitute', + 23131: 'destruct', + 23132: 'detached', + 23133: 'detail', + 23134: 'detection', + 23135: 'detective', + 23136: 'detector', + 23141: 'detention', + 23142: 'detergent', + 23143: 'detest', + 23144: 'detonate', + 23145: 'detonator', + 23146: 'detoxify', + 23151: 'detract', + 23152: 'deuce', + 23153: 'devalue', + 23154: 'deviancy', + 23155: 'deviant', + 23156: 'deviate', + 23161: 'deviation', + 23162: 'deviator', + 23163: 'device', + 23164: 'devious', + 23165: 'devotedly', + 23166: 'devotee', + 23211: 'devotion', + 23212: 'devourer', + 23213: 'devouring', + 23214: 'devoutly', + 23215: 'dexterity', + 23216: 'dexterous', + 23221: 'diabetes', + 23222: 'diabetic', + 23223: 'diabolic', + 23224: 'diagnoses', + 23225: 'diagnosis', + 23226: 'diagram', + 23231: 'dial', + 23232: 'diameter', + 23233: 'diaper', + 23234: 'diaphragm', + 23235: 'diary', + 23236: 'dice', + 23241: 'dicing', + 23242: 'dictate', + 23243: 'dictation', + 23244: 'dictator', + 23245: 'difficult', + 23246: 'diffused', + 23251: 'diffuser', + 23252: 'diffusion', + 23253: 'diffusive', + 23254: 'dig', + 23255: 'dilation', + 23256: 'diligence', + 23261: 'diligent', + 23262: 'dill', + 23263: 'dilute', + 23264: 'dime', + 23265: 'diminish', + 23266: 'dimly', + 23311: 'dimmed', + 23312: 'dimmer', + 23313: 'dimness', + 23314: 'dimple', + 23315: 'diner', + 23316: 'dingbat', + 23321: 'dinghy', + 23322: 'dinginess', + 23323: 'dingo', + 23324: 'dingy', + 23325: 'dining', + 23326: 'dinner', + 23331: 'diocese', + 23332: 'dioxide', + 23333: 'diploma', + 23334: 'dipped', + 23335: 'dipper', + 23336: 'dipping', + 23341: 'directed', + 23342: 'direction', + 23343: 'directive', + 23344: 'directly', + 23345: 'directory', + 23346: 'direness', + 23351: 'dirtiness', + 23352: 'disabled', + 23353: 'disagree', + 23354: 'disallow', + 23355: 'disarm', + 23356: 'disarray', + 23361: 'disaster', + 23362: 'disband', + 23363: 'disbelief', + 23364: 'disburse', + 23365: 'discard', + 23366: 'discern', + 23411: 'discharge', + 23412: 'disclose', + 23413: 'discolor', + 23414: 'discount', + 23415: 'discourse', + 23416: 'discover', + 23421: 'discuss', + 23422: 'disdain', + 23423: 'disengage', + 23424: 'disfigure', + 23425: 'disgrace', + 23426: 'dish', + 23431: 'disinfect', + 23432: 'disjoin', + 23433: 'disk', + 23434: 'dislike', + 23435: 'disliking', + 23436: 'dislocate', + 23441: 'dislodge', + 23442: 'disloyal', + 23443: 'dismantle', + 23444: 'dismay', + 23445: 'dismiss', + 23446: 'dismount', + 23451: 'disobey', + 23452: 'disorder', + 23453: 'disown', + 23454: 'disparate', + 23455: 'disparity', + 23456: 'dispatch', + 23461: 'dispense', + 23462: 'dispersal', + 23463: 'dispersed', + 23464: 'disperser', + 23465: 'displace', + 23466: 'display', + 23511: 'displease', + 23512: 'disposal', + 23513: 'dispose', + 23514: 'disprove', + 23515: 'dispute', + 23516: 'disregard', + 23521: 'disrupt', + 23522: 'dissuade', + 23523: 'distance', + 23524: 'distant', + 23525: 'distaste', + 23526: 'distill', + 23531: 'distinct', + 23532: 'distort', + 23533: 'distract', + 23534: 'distress', + 23535: 'district', + 23536: 'distrust', + 23541: 'ditch', + 23542: 'ditto', + 23543: 'ditzy', + 23544: 'dividable', + 23545: 'divided', + 23546: 'dividend', + 23551: 'dividers', + 23552: 'dividing', + 23553: 'divinely', + 23554: 'diving', + 23555: 'divinity', + 23556: 'divisible', + 23561: 'divisibly', + 23562: 'division', + 23563: 'divisive', + 23564: 'divorcee', + 23565: 'dizziness', + 23566: 'dizzy', + 23611: 'doable', + 23612: 'docile', + 23613: 'dock', + 23614: 'doctrine', + 23615: 'document', + 23616: 'dodge', + 23621: 'dodgy', + 23622: 'doily', + 23623: 'doing', + 23624: 'dole', + 23625: 'dollar', + 23626: 'dollhouse', + 23631: 'dollop', + 23632: 'dolly', + 23633: 'dolphin', + 23634: 'domain', + 23635: 'domelike', + 23636: 'domestic', + 23641: 'dominion', + 23642: 'dominoes', + 23643: 'donated', + 23644: 'donation', + 23645: 'donator', + 23646: 'donor', + 23651: 'donut', + 23652: 'doodle', + 23653: 'doorbell', + 23654: 'doorframe', + 23655: 'doorknob', + 23656: 'doorman', + 23661: 'doormat', + 23662: 'doornail', + 23663: 'doorpost', + 23664: 'doorstep', + 23665: 'doorstop', + 23666: 'doorway', + 24111: 'doozy', + 24112: 'dork', + 24113: 'dormitory', + 24114: 'dorsal', + 24115: 'dosage', + 24116: 'dose', + 24121: 'dotted', + 24122: 'doubling', + 24123: 'douche', + 24124: 'dove', + 24125: 'down', + 24126: 'dowry', + 24131: 'doze', + 24132: 'drab', + 24133: 'dragging', + 24134: 'dragonfly', + 24135: 'dragonish', + 24136: 'dragster', + 24141: 'drainable', + 24142: 'drainage', + 24143: 'drained', + 24144: 'drainer', + 24145: 'drainpipe', + 24146: 'dramatic', + 24151: 'dramatize', + 24152: 'drank', + 24153: 'drapery', + 24154: 'drastic', + 24155: 'draw', + 24156: 'dreaded', + 24161: 'dreadful', + 24162: 'dreadlock', + 24163: 'dreamboat', + 24164: 'dreamily', + 24165: 'dreamland', + 24166: 'dreamless', + 24211: 'dreamlike', + 24212: 'dreamt', + 24213: 'dreamy', + 24214: 'drearily', + 24215: 'dreary', + 24216: 'drench', + 24221: 'dress', + 24222: 'drew', + 24223: 'dribble', + 24224: 'dried', + 24225: 'drier', + 24226: 'drift', + 24231: 'driller', + 24232: 'drilling', + 24233: 'drinkable', + 24234: 'drinking', + 24235: 'dripping', + 24236: 'drippy', + 24241: 'drivable', + 24242: 'driven', + 24243: 'driver', + 24244: 'driveway', + 24245: 'driving', + 24246: 'drizzle', + 24251: 'drizzly', + 24252: 'drone', + 24253: 'drool', + 24254: 'droop', + 24255: 'drop-down', + 24256: 'dropbox', + 24261: 'dropkick', + 24262: 'droplet', + 24263: 'dropout', + 24264: 'dropper', + 24265: 'drove', + 24266: 'drown', + 24311: 'drowsily', + 24312: 'drudge', + 24313: 'drum', + 24314: 'dry', + 24315: 'dubbed', + 24316: 'dubiously', + 24321: 'duchess', + 24322: 'duckbill', + 24323: 'ducking', + 24324: 'duckling', + 24325: 'ducktail', + 24326: 'ducky', + 24331: 'duct', + 24332: 'dude', + 24333: 'duffel', + 24334: 'dugout', + 24335: 'duh', + 24336: 'duke', + 24341: 'duller', + 24342: 'dullness', + 24343: 'duly', + 24344: 'dumping', + 24345: 'dumpling', + 24346: 'dumpster', + 24351: 'duo', + 24352: 'dupe', + 24353: 'duplex', + 24354: 'duplicate', + 24355: 'duplicity', + 24356: 'durable', + 24361: 'durably', + 24362: 'duration', + 24363: 'duress', + 24364: 'during', + 24365: 'dusk', + 24366: 'dust', + 24411: 'dutiful', + 24412: 'duty', + 24413: 'duvet', + 24414: 'dwarf', + 24415: 'dweeb', + 24416: 'dwelled', + 24421: 'dweller', + 24422: 'dwelling', + 24423: 'dwindle', + 24424: 'dwindling', + 24425: 'dynamic', + 24426: 'dynamite', + 24431: 'dynasty', + 24432: 'dyslexia', + 24433: 'dyslexic', + 24434: 'each', + 24435: 'eagle', + 24436: 'earache', + 24441: 'eardrum', + 24442: 'earflap', + 24443: 'earful', + 24444: 'earlobe', + 24445: 'early', + 24446: 'earmark', + 24451: 'earmuff', + 24452: 'earphone', + 24453: 'earpiece', + 24454: 'earplugs', + 24455: 'earring', + 24456: 'earshot', + 24461: 'earthen', + 24462: 'earthlike', + 24463: 'earthling', + 24464: 'earthly', + 24465: 'earthworm', + 24466: 'earthy', + 24511: 'earwig', + 24512: 'easeful', + 24513: 'easel', + 24514: 'easiest', + 24515: 'easily', + 24516: 'easiness', + 24521: 'easing', + 24522: 'eastbound', + 24523: 'eastcoast', + 24524: 'easter', + 24525: 'eastward', + 24526: 'eatable', + 24531: 'eaten', + 24532: 'eatery', + 24533: 'eating', + 24534: 'eats', + 24535: 'ebay', + 24536: 'ebony', + 24541: 'ebook', + 24542: 'ecard', + 24543: 'eccentric', + 24544: 'echo', + 24545: 'eclair', + 24546: 'eclipse', + 24551: 'ecologist', + 24552: 'ecology', + 24553: 'economic', + 24554: 'economist', + 24555: 'economy', + 24556: 'ecosphere', + 24561: 'ecosystem', + 24562: 'edge', + 24563: 'edginess', + 24564: 'edging', + 24565: 'edgy', + 24566: 'edition', + 24611: 'editor', + 24612: 'educated', + 24613: 'education', + 24614: 'educator', + 24615: 'eel', + 24616: 'effective', + 24621: 'effects', + 24622: 'efficient', + 24623: 'effort', + 24624: 'eggbeater', + 24625: 'egging', + 24626: 'eggnog', + 24631: 'eggplant', + 24632: 'eggshell', + 24633: 'egomaniac', + 24634: 'egotism', + 24635: 'egotistic', + 24636: 'either', + 24641: 'eject', + 24642: 'elaborate', + 24643: 'elastic', + 24644: 'elated', + 24645: 'elbow', + 24646: 'eldercare', + 24651: 'elderly', + 24652: 'eldest', + 24653: 'electable', + 24654: 'election', + 24655: 'elective', + 24656: 'elephant', + 24661: 'elevate', + 24662: 'elevating', + 24663: 'elevation', + 24664: 'elevator', + 24665: 'eleven', + 24666: 'elf', + 25111: 'eligible', + 25112: 'eligibly', + 25113: 'eliminate', + 25114: 'elite', + 25115: 'elitism', + 25116: 'elixir', + 25121: 'elk', + 25122: 'ellipse', + 25123: 'elliptic', + 25124: 'elm', + 25125: 'elongated', + 25126: 'elope', + 25131: 'eloquence', + 25132: 'eloquent', + 25133: 'elsewhere', + 25134: 'elude', + 25135: 'elusive', + 25136: 'elves', + 25141: 'email', + 25142: 'embargo', + 25143: 'embark', + 25144: 'embassy', + 25145: 'embattled', + 25146: 'embellish', + 25151: 'ember', + 25152: 'embezzle', + 25153: 'emblaze', + 25154: 'emblem', + 25155: 'embody', + 25156: 'embolism', + 25161: 'emboss', + 25162: 'embroider', + 25163: 'emcee', + 25164: 'emerald', + 25165: 'emergency', + 25166: 'emission', + 25211: 'emit', + 25212: 'emote', + 25213: 'emoticon', + 25214: 'emotion', + 25215: 'empathic', + 25216: 'empathy', + 25221: 'emperor', + 25222: 'emphases', + 25223: 'emphasis', + 25224: 'emphasize', + 25225: 'emphatic', + 25226: 'empirical', + 25231: 'employed', + 25232: 'employee', + 25233: 'employer', + 25234: 'emporium', + 25235: 'empower', + 25236: 'emptier', + 25241: 'emptiness', + 25242: 'empty', + 25243: 'emu', + 25244: 'enable', + 25245: 'enactment', + 25246: 'enamel', + 25251: 'enchanted', + 25252: 'enchilada', + 25253: 'encircle', + 25254: 'enclose', + 25255: 'enclosure', + 25256: 'encode', + 25261: 'encore', + 25262: 'encounter', + 25263: 'encourage', + 25264: 'encroach', + 25265: 'encrust', + 25266: 'encrypt', + 25311: 'endanger', + 25312: 'endeared', + 25313: 'endearing', + 25314: 'ended', + 25315: 'ending', + 25316: 'endless', + 25321: 'endnote', + 25322: 'endocrine', + 25323: 'endorphin', + 25324: 'endorse', + 25325: 'endowment', + 25326: 'endpoint', + 25331: 'endurable', + 25332: 'endurance', + 25333: 'enduring', + 25334: 'energetic', + 25335: 'energize', + 25336: 'energy', + 25341: 'enforced', + 25342: 'enforcer', + 25343: 'engaged', + 25344: 'engaging', + 25345: 'engine', + 25346: 'engorge', + 25351: 'engraved', + 25352: 'engraver', + 25353: 'engraving', + 25354: 'engross', + 25355: 'engulf', + 25356: 'enhance', + 25361: 'enigmatic', + 25362: 'enjoyable', + 25363: 'enjoyably', + 25364: 'enjoyer', + 25365: 'enjoying', + 25366: 'enjoyment', + 25411: 'enlarged', + 25412: 'enlarging', + 25413: 'enlighten', + 25414: 'enlisted', + 25415: 'enquirer', + 25416: 'enrage', + 25421: 'enrich', + 25422: 'enroll', + 25423: 'enslave', + 25424: 'ensnare', + 25425: 'ensure', + 25426: 'entail', + 25431: 'entangled', + 25432: 'entering', + 25433: 'entertain', + 25434: 'enticing', + 25435: 'entire', + 25436: 'entitle', + 25441: 'entity', + 25442: 'entomb', + 25443: 'entourage', + 25444: 'entrap', + 25445: 'entree', + 25446: 'entrench', + 25451: 'entrust', + 25452: 'entryway', + 25453: 'entwine', + 25454: 'enunciate', + 25455: 'envelope', + 25456: 'enviable', + 25461: 'enviably', + 25462: 'envious', + 25463: 'envision', + 25464: 'envoy', + 25465: 'envy', + 25466: 'enzyme', + 25511: 'epic', + 25512: 'epidemic', + 25513: 'epidermal', + 25514: 'epidermis', + 25515: 'epidural', + 25516: 'epilepsy', + 25521: 'epileptic', + 25522: 'epilogue', + 25523: 'epiphany', + 25524: 'episode', + 25525: 'equal', + 25526: 'equate', + 25531: 'equation', + 25532: 'equator', + 25533: 'equinox', + 25534: 'equipment', + 25535: 'equity', + 25536: 'equivocal', + 25541: 'eradicate', + 25542: 'erasable', + 25543: 'erased', + 25544: 'eraser', + 25545: 'erasure', + 25546: 'ergonomic', + 25551: 'errand', + 25552: 'errant', + 25553: 'erratic', + 25554: 'error', + 25555: 'erupt', + 25556: 'escalate', + 25561: 'escalator', + 25562: 'escapable', + 25563: 'escapade', + 25564: 'escapist', + 25565: 'escargot', + 25566: 'eskimo', + 25611: 'esophagus', + 25612: 'espionage', + 25613: 'espresso', + 25614: 'esquire', + 25615: 'essay', + 25616: 'essence', + 25621: 'essential', + 25622: 'establish', + 25623: 'estate', + 25624: 'esteemed', + 25625: 'estimate', + 25626: 'estimator', + 25631: 'estranged', + 25632: 'estrogen', + 25633: 'etching', + 25634: 'eternal', + 25635: 'eternity', + 25636: 'ethanol', + 25641: 'ether', + 25642: 'ethically', + 25643: 'ethics', + 25644: 'euphemism', + 25645: 'evacuate', + 25646: 'evacuee', + 25651: 'evade', + 25652: 'evaluate', + 25653: 'evaluator', + 25654: 'evaporate', + 25655: 'evasion', + 25656: 'evasive', + 25661: 'even', + 25662: 'everglade', + 25663: 'evergreen', + 25664: 'everybody', + 25665: 'everyday', + 25666: 'everyone', + 26111: 'evict', + 26112: 'evidence', + 26113: 'evident', + 26114: 'evil', + 26115: 'evoke', + 26116: 'evolution', + 26121: 'evolve', + 26122: 'exact', + 26123: 'exalted', + 26124: 'example', + 26125: 'excavate', + 26126: 'excavator', + 26131: 'exceeding', + 26132: 'exception', + 26133: 'excess', + 26134: 'exchange', + 26135: 'excitable', + 26136: 'exciting', + 26141: 'exclaim', + 26142: 'exclude', + 26143: 'excluding', + 26144: 'exclusion', + 26145: 'exclusive', + 26146: 'excretion', + 26151: 'excretory', + 26152: 'excursion', + 26153: 'excusable', + 26154: 'excusably', + 26155: 'excuse', + 26156: 'exemplary', + 26161: 'exemplify', + 26162: 'exemption', + 26163: 'exerciser', + 26164: 'exert', + 26165: 'exes', + 26166: 'exfoliate', + 26211: 'exhale', + 26212: 'exhaust', + 26213: 'exhume', + 26214: 'exile', + 26215: 'existing', + 26216: 'exit', + 26221: 'exodus', + 26222: 'exonerate', + 26223: 'exorcism', + 26224: 'exorcist', + 26225: 'expand', + 26226: 'expanse', + 26231: 'expansion', + 26232: 'expansive', + 26233: 'expectant', + 26234: 'expedited', + 26235: 'expediter', + 26236: 'expel', + 26241: 'expend', + 26242: 'expenses', + 26243: 'expensive', + 26244: 'expert', + 26245: 'expire', + 26246: 'expiring', + 26251: 'explain', + 26252: 'expletive', + 26253: 'explicit', + 26254: 'explode', + 26255: 'exploit', + 26256: 'explore', + 26261: 'exploring', + 26262: 'exponent', + 26263: 'exporter', + 26264: 'exposable', + 26265: 'expose', + 26266: 'exposure', + 26311: 'express', + 26312: 'expulsion', + 26313: 'exquisite', + 26314: 'extended', + 26315: 'extending', + 26316: 'extent', + 26321: 'extenuate', + 26322: 'exterior', + 26323: 'external', + 26324: 'extinct', + 26325: 'extortion', + 26326: 'extradite', + 26331: 'extras', + 26332: 'extrovert', + 26333: 'extrude', + 26334: 'extruding', + 26335: 'exuberant', + 26336: 'fable', + 26341: 'fabric', + 26342: 'fabulous', + 26343: 'facebook', + 26344: 'facecloth', + 26345: 'facedown', + 26346: 'faceless', + 26351: 'facelift', + 26352: 'faceplate', + 26353: 'faceted', + 26354: 'facial', + 26355: 'facility', + 26356: 'facing', + 26361: 'facsimile', + 26362: 'faction', + 26363: 'factoid', + 26364: 'factor', + 26365: 'factsheet', + 26366: 'factual', + 26411: 'faculty', + 26412: 'fade', + 26413: 'fading', + 26414: 'failing', + 26415: 'falcon', + 26416: 'fall', + 26421: 'false', + 26422: 'falsify', + 26423: 'fame', + 26424: 'familiar', + 26425: 'family', + 26426: 'famine', + 26431: 'famished', + 26432: 'fanatic', + 26433: 'fancied', + 26434: 'fanciness', + 26435: 'fancy', + 26436: 'fanfare', + 26441: 'fang', + 26442: 'fanning', + 26443: 'fantasize', + 26444: 'fantastic', + 26445: 'fantasy', + 26446: 'fascism', + 26451: 'fastball', + 26452: 'faster', + 26453: 'fasting', + 26454: 'fastness', + 26455: 'faucet', + 26456: 'favorable', + 26461: 'favorably', + 26462: 'favored', + 26463: 'favoring', + 26464: 'favorite', + 26465: 'fax', + 26466: 'feast', + 26511: 'federal', + 26512: 'fedora', + 26513: 'feeble', + 26514: 'feed', + 26515: 'feel', + 26516: 'feisty', + 26521: 'feline', + 26522: 'felt-tip', + 26523: 'feminine', + 26524: 'feminism', + 26525: 'feminist', + 26526: 'feminize', + 26531: 'femur', + 26532: 'fence', + 26533: 'fencing', + 26534: 'fender', + 26535: 'ferment', + 26536: 'fernlike', + 26541: 'ferocious', + 26542: 'ferocity', + 26543: 'ferret', + 26544: 'ferris', + 26545: 'ferry', + 26546: 'fervor', + 26551: 'fester', + 26552: 'festival', + 26553: 'festive', + 26554: 'festivity', + 26555: 'fetal', + 26556: 'fetch', + 26561: 'fever', + 26562: 'fiber', + 26563: 'fiction', + 26564: 'fiddle', + 26565: 'fiddling', + 26566: 'fidelity', + 26611: 'fidgeting', + 26612: 'fidgety', + 26613: 'fifteen', + 26614: 'fifth', + 26615: 'fiftieth', + 26616: 'fifty', + 26621: 'figment', + 26622: 'figure', + 26623: 'figurine', + 26624: 'filing', + 26625: 'filled', + 26626: 'filler', + 26631: 'filling', + 26632: 'film', + 26633: 'filter', + 26634: 'filth', + 26635: 'filtrate', + 26636: 'finale', + 26641: 'finalist', + 26642: 'finalize', + 26643: 'finally', + 26644: 'finance', + 26645: 'financial', + 26646: 'finch', + 26651: 'fineness', + 26652: 'finer', + 26653: 'finicky', + 26654: 'finished', + 26655: 'finisher', + 26656: 'finishing', + 26661: 'finite', + 26662: 'finless', + 26663: 'finlike', + 26664: 'fiscally', + 26665: 'fit', + 26666: 'five', + 31111: 'flaccid', + 31112: 'flagman', + 31113: 'flagpole', + 31114: 'flagship', + 31115: 'flagstick', + 31116: 'flagstone', + 31121: 'flail', + 31122: 'flakily', + 31123: 'flaky', + 31124: 'flame', + 31125: 'flammable', + 31126: 'flanked', + 31131: 'flanking', + 31132: 'flannels', + 31133: 'flap', + 31134: 'flaring', + 31135: 'flashback', + 31136: 'flashbulb', + 31141: 'flashcard', + 31142: 'flashily', + 31143: 'flashing', + 31144: 'flashy', + 31145: 'flask', + 31146: 'flatbed', + 31151: 'flatfoot', + 31152: 'flatly', + 31153: 'flatness', + 31154: 'flatten', + 31155: 'flattered', + 31156: 'flatterer', + 31161: 'flattery', + 31162: 'flattop', + 31163: 'flatware', + 31164: 'flatworm', + 31165: 'flavored', + 31166: 'flavorful', + 31211: 'flavoring', + 31212: 'flaxseed', + 31213: 'fled', + 31214: 'fleshed', + 31215: 'fleshy', + 31216: 'flick', + 31221: 'flier', + 31222: 'flight', + 31223: 'flinch', + 31224: 'fling', + 31225: 'flint', + 31226: 'flip', + 31231: 'flirt', + 31232: 'float', + 31233: 'flock', + 31234: 'flogging', + 31235: 'flop', + 31236: 'floral', + 31241: 'florist', + 31242: 'floss', + 31243: 'flounder', + 31244: 'flyable', + 31245: 'flyaway', + 31246: 'flyer', + 31251: 'flying', + 31252: 'flyover', + 31253: 'flypaper', + 31254: 'foam', + 31255: 'foe', + 31256: 'fog', + 31261: 'foil', + 31262: 'folic', + 31263: 'folk', + 31264: 'follicle', + 31265: 'follow', + 31266: 'fondling', + 31311: 'fondly', + 31312: 'fondness', + 31313: 'fondue', + 31314: 'font', + 31315: 'food', + 31316: 'fool', + 31321: 'footage', + 31322: 'football', + 31323: 'footbath', + 31324: 'footboard', + 31325: 'footer', + 31326: 'footgear', + 31331: 'foothill', + 31332: 'foothold', + 31333: 'footing', + 31334: 'footless', + 31335: 'footman', + 31336: 'footnote', + 31341: 'footpad', + 31342: 'footpath', + 31343: 'footprint', + 31344: 'footrest', + 31345: 'footsie', + 31346: 'footsore', + 31351: 'footwear', + 31352: 'footwork', + 31353: 'fossil', + 31354: 'foster', + 31355: 'founder', + 31356: 'founding', + 31361: 'fountain', + 31362: 'fox', + 31363: 'foyer', + 31364: 'fraction', + 31365: 'fracture', + 31366: 'fragile', + 31411: 'fragility', + 31412: 'fragment', + 31413: 'fragrance', + 31414: 'fragrant', + 31415: 'frail', + 31416: 'frame', + 31421: 'framing', + 31422: 'frantic', + 31423: 'fraternal', + 31424: 'frayed', + 31425: 'fraying', + 31426: 'frays', + 31431: 'freckled', + 31432: 'freckles', + 31433: 'freebase', + 31434: 'freebee', + 31435: 'freebie', + 31436: 'freedom', + 31441: 'freefall', + 31442: 'freehand', + 31443: 'freeing', + 31444: 'freeload', + 31445: 'freely', + 31446: 'freemason', + 31451: 'freeness', + 31452: 'freestyle', + 31453: 'freeware', + 31454: 'freeway', + 31455: 'freewill', + 31456: 'freezable', + 31461: 'freezing', + 31462: 'freight', + 31463: 'french', + 31464: 'frenzied', + 31465: 'frenzy', + 31466: 'frequency', + 31511: 'frequent', + 31512: 'fresh', + 31513: 'fretful', + 31514: 'fretted', + 31515: 'friction', + 31516: 'friday', + 31521: 'fridge', + 31522: 'fried', + 31523: 'friend', + 31524: 'frighten', + 31525: 'frightful', + 31526: 'frigidity', + 31531: 'frigidly', + 31532: 'frill', + 31533: 'fringe', + 31534: 'frisbee', + 31535: 'frisk', + 31536: 'fritter', + 31541: 'frivolous', + 31542: 'frolic', + 31543: 'from', + 31544: 'front', + 31545: 'frostbite', + 31546: 'frosted', + 31551: 'frostily', + 31552: 'frosting', + 31553: 'frostlike', + 31554: 'frosty', + 31555: 'froth', + 31556: 'frown', + 31561: 'frozen', + 31562: 'fructose', + 31563: 'frugality', + 31564: 'frugally', + 31565: 'fruit', + 31566: 'frustrate', + 31611: 'frying', + 31612: 'gab', + 31613: 'gaffe', + 31614: 'gag', + 31615: 'gainfully', + 31616: 'gaining', + 31621: 'gains', + 31622: 'gala', + 31623: 'gallantly', + 31624: 'galleria', + 31625: 'gallery', + 31626: 'galley', + 31631: 'gallon', + 31632: 'gallows', + 31633: 'gallstone', + 31634: 'galore', + 31635: 'galvanize', + 31636: 'gambling', + 31641: 'game', + 31642: 'gaming', + 31643: 'gamma', + 31644: 'gander', + 31645: 'gangly', + 31646: 'gangrene', + 31651: 'gangway', + 31652: 'gap', + 31653: 'garage', + 31654: 'garbage', + 31655: 'garden', + 31656: 'gargle', + 31661: 'garland', + 31662: 'garlic', + 31663: 'garment', + 31664: 'garnet', + 31665: 'garnish', + 31666: 'garter', + 32111: 'gas', + 32112: 'gatherer', + 32113: 'gathering', + 32114: 'gating', + 32115: 'gauging', + 32116: 'gauntlet', + 32121: 'gauze', + 32122: 'gave', + 32123: 'gawk', + 32124: 'gazing', + 32125: 'gear', + 32126: 'gecko', + 32131: 'geek', + 32132: 'geiger', + 32133: 'gem', + 32134: 'gender', + 32135: 'generic', + 32136: 'generous', + 32141: 'genetics', + 32142: 'genre', + 32143: 'gentile', + 32144: 'gentleman', + 32145: 'gently', + 32146: 'gents', + 32151: 'geography', + 32152: 'geologic', + 32153: 'geologist', + 32154: 'geology', + 32155: 'geometric', + 32156: 'geometry', + 32161: 'geranium', + 32162: 'gerbil', + 32163: 'geriatric', + 32164: 'germicide', + 32165: 'germinate', + 32166: 'germless', + 32211: 'germproof', + 32212: 'gestate', + 32213: 'gestation', + 32214: 'gesture', + 32215: 'getaway', + 32216: 'getting', + 32221: 'getup', + 32222: 'giant', + 32223: 'gibberish', + 32224: 'giblet', + 32225: 'giddily', + 32226: 'giddiness', + 32231: 'giddy', + 32232: 'gift', + 32233: 'gigabyte', + 32234: 'gigahertz', + 32235: 'gigantic', + 32236: 'giggle', + 32241: 'giggling', + 32242: 'giggly', + 32243: 'gigolo', + 32244: 'gilled', + 32245: 'gills', + 32246: 'gimmick', + 32251: 'girdle', + 32252: 'giveaway', + 32253: 'given', + 32254: 'giver', + 32255: 'giving', + 32256: 'gizmo', + 32261: 'gizzard', + 32262: 'glacial', + 32263: 'glacier', + 32264: 'glade', + 32265: 'gladiator', + 32266: 'gladly', + 32311: 'glamorous', + 32312: 'glamour', + 32313: 'glance', + 32314: 'glancing', + 32315: 'glandular', + 32316: 'glare', + 32321: 'glaring', + 32322: 'glass', + 32323: 'glaucoma', + 32324: 'glazing', + 32325: 'gleaming', + 32326: 'gleeful', + 32331: 'glider', + 32332: 'gliding', + 32333: 'glimmer', + 32334: 'glimpse', + 32335: 'glisten', + 32336: 'glitch', + 32341: 'glitter', + 32342: 'glitzy', + 32343: 'gloater', + 32344: 'gloating', + 32345: 'gloomily', + 32346: 'gloomy', + 32351: 'glorified', + 32352: 'glorifier', + 32353: 'glorify', + 32354: 'glorious', + 32355: 'glory', + 32356: 'gloss', + 32361: 'glove', + 32362: 'glowing', + 32363: 'glowworm', + 32364: 'glucose', + 32365: 'glue', + 32366: 'gluten', + 32411: 'glutinous', + 32412: 'glutton', + 32413: 'gnarly', + 32414: 'gnat', + 32415: 'goal', + 32416: 'goatskin', + 32421: 'goes', + 32422: 'goggles', + 32423: 'going', + 32424: 'goldfish', + 32425: 'goldmine', + 32426: 'goldsmith', + 32431: 'golf', + 32432: 'goliath', + 32433: 'gonad', + 32434: 'gondola', + 32435: 'gone', + 32436: 'gong', + 32441: 'good', + 32442: 'gooey', + 32443: 'goofball', + 32444: 'goofiness', + 32445: 'goofy', + 32446: 'google', + 32451: 'goon', + 32452: 'gopher', + 32453: 'gore', + 32454: 'gorged', + 32455: 'gorgeous', + 32456: 'gory', + 32461: 'gosling', + 32462: 'gossip', + 32463: 'gothic', + 32464: 'gotten', + 32465: 'gout', + 32466: 'gown', + 32511: 'grab', + 32512: 'graceful', + 32513: 'graceless', + 32514: 'gracious', + 32515: 'gradation', + 32516: 'graded', + 32521: 'grader', + 32522: 'gradient', + 32523: 'grading', + 32524: 'gradually', + 32525: 'graduate', + 32526: 'graffiti', + 32531: 'grafted', + 32532: 'grafting', + 32533: 'grain', + 32534: 'granddad', + 32535: 'grandkid', + 32536: 'grandly', + 32541: 'grandma', + 32542: 'grandpa', + 32543: 'grandson', + 32544: 'granite', + 32545: 'granny', + 32546: 'granola', + 32551: 'grant', + 32552: 'granular', + 32553: 'grape', + 32554: 'graph', + 32555: 'grapple', + 32556: 'grappling', + 32561: 'grasp', + 32562: 'grass', + 32563: 'gratified', + 32564: 'gratify', + 32565: 'grating', + 32566: 'gratitude', + 32611: 'gratuity', + 32612: 'gravel', + 32613: 'graveness', + 32614: 'graves', + 32615: 'graveyard', + 32616: 'gravitate', + 32621: 'gravity', + 32622: 'gravy', + 32623: 'gray', + 32624: 'grazing', + 32625: 'greasily', + 32626: 'greedily', + 32631: 'greedless', + 32632: 'greedy', + 32633: 'green', + 32634: 'greeter', + 32635: 'greeting', + 32636: 'grew', + 32641: 'greyhound', + 32642: 'grid', + 32643: 'grief', + 32644: 'grievance', + 32645: 'grieving', + 32646: 'grievous', + 32651: 'grill', + 32652: 'grimace', + 32653: 'grimacing', + 32654: 'grime', + 32655: 'griminess', + 32656: 'grimy', + 32661: 'grinch', + 32662: 'grinning', + 32663: 'grip', + 32664: 'gristle', + 32665: 'grit', + 32666: 'groggily', + 33111: 'groggy', + 33112: 'groin', + 33113: 'groom', + 33114: 'groove', + 33115: 'grooving', + 33116: 'groovy', + 33121: 'grope', + 33122: 'ground', + 33123: 'grouped', + 33124: 'grout', + 33125: 'grove', + 33126: 'grower', + 33131: 'growing', + 33132: 'growl', + 33133: 'grub', + 33134: 'grudge', + 33135: 'grudging', + 33136: 'grueling', + 33141: 'gruffly', + 33142: 'grumble', + 33143: 'grumbling', + 33144: 'grumbly', + 33145: 'grumpily', + 33146: 'grunge', + 33151: 'grunt', + 33152: 'guacamole', + 33153: 'guidable', + 33154: 'guidance', + 33155: 'guide', + 33156: 'guiding', + 33161: 'guileless', + 33162: 'guise', + 33163: 'gulf', + 33164: 'gullible', + 33165: 'gully', + 33166: 'gulp', + 33211: 'gumball', + 33212: 'gumdrop', + 33213: 'gumminess', + 33214: 'gumming', + 33215: 'gummy', + 33216: 'gurgle', + 33221: 'gurgling', + 33222: 'guru', + 33223: 'gush', + 33224: 'gusto', + 33225: 'gusty', + 33226: 'gutless', + 33231: 'guts', + 33232: 'gutter', + 33233: 'guy', + 33234: 'guzzler', + 33235: 'gyration', + 33236: 'habitable', + 33241: 'habitant', + 33242: 'habitat', + 33243: 'habitual', + 33244: 'hacked', + 33245: 'hacker', + 33246: 'hacking', + 33251: 'hacksaw', + 33252: 'had', + 33253: 'haggler', + 33254: 'haiku', + 33255: 'half', + 33256: 'halogen', + 33261: 'halt', + 33262: 'halved', + 33263: 'halves', + 33264: 'hamburger', + 33265: 'hamlet', + 33266: 'hammock', + 33311: 'hamper', + 33312: 'hamster', + 33313: 'hamstring', + 33314: 'handbag', + 33315: 'handball', + 33316: 'handbook', + 33321: 'handbrake', + 33322: 'handcart', + 33323: 'handclap', + 33324: 'handclasp', + 33325: 'handcraft', + 33326: 'handcuff', + 33331: 'handed', + 33332: 'handful', + 33333: 'handgrip', + 33334: 'handgun', + 33335: 'handheld', + 33336: 'handiness', + 33341: 'handiwork', + 33342: 'handlebar', + 33343: 'handled', + 33344: 'handler', + 33345: 'handling', + 33346: 'handmade', + 33351: 'handoff', + 33352: 'handpick', + 33353: 'handprint', + 33354: 'handrail', + 33355: 'handsaw', + 33356: 'handset', + 33361: 'handsfree', + 33362: 'handshake', + 33363: 'handstand', + 33364: 'handwash', + 33365: 'handwork', + 33366: 'handwoven', + 33411: 'handwrite', + 33412: 'handyman', + 33413: 'hangnail', + 33414: 'hangout', + 33415: 'hangover', + 33416: 'hangup', + 33421: 'hankering', + 33422: 'hankie', + 33423: 'hanky', + 33424: 'haphazard', + 33425: 'happening', + 33426: 'happier', + 33431: 'happiest', + 33432: 'happily', + 33433: 'happiness', + 33434: 'happy', + 33435: 'harbor', + 33436: 'hardcopy', + 33441: 'hardcore', + 33442: 'hardcover', + 33443: 'harddisk', + 33444: 'hardened', + 33445: 'hardener', + 33446: 'hardening', + 33451: 'hardhat', + 33452: 'hardhead', + 33453: 'hardiness', + 33454: 'hardly', + 33455: 'hardness', + 33456: 'hardship', + 33461: 'hardware', + 33462: 'hardwired', + 33463: 'hardwood', + 33464: 'hardy', + 33465: 'harmful', + 33466: 'harmless', + 33511: 'harmonica', + 33512: 'harmonics', + 33513: 'harmonize', + 33514: 'harmony', + 33515: 'harness', + 33516: 'harpist', + 33521: 'harsh', + 33522: 'harvest', + 33523: 'hash', + 33524: 'hassle', + 33525: 'haste', + 33526: 'hastily', + 33531: 'hastiness', + 33532: 'hasty', + 33533: 'hatbox', + 33534: 'hatchback', + 33535: 'hatchery', + 33536: 'hatchet', + 33541: 'hatching', + 33542: 'hatchling', + 33543: 'hate', + 33544: 'hatless', + 33545: 'hatred', + 33546: 'haunt', + 33551: 'haven', + 33552: 'hazard', + 33553: 'hazelnut', + 33554: 'hazily', + 33555: 'haziness', + 33556: 'hazing', + 33561: 'hazy', + 33562: 'headache', + 33563: 'headband', + 33564: 'headboard', + 33565: 'headcount', + 33566: 'headdress', + 33611: 'headed', + 33612: 'header', + 33613: 'headfirst', + 33614: 'headgear', + 33615: 'heading', + 33616: 'headlamp', + 33621: 'headless', + 33622: 'headlock', + 33623: 'headphone', + 33624: 'headpiece', + 33625: 'headrest', + 33626: 'headroom', + 33631: 'headscarf', + 33632: 'headset', + 33633: 'headsman', + 33634: 'headstand', + 33635: 'headstone', + 33636: 'headway', + 33641: 'headwear', + 33642: 'heap', + 33643: 'heat', + 33644: 'heave', + 33645: 'heavily', + 33646: 'heaviness', + 33651: 'heaving', + 33652: 'hedge', + 33653: 'hedging', + 33654: 'heftiness', + 33655: 'hefty', + 33656: 'helium', + 33661: 'helmet', + 33662: 'helper', + 33663: 'helpful', + 33664: 'helping', + 33665: 'helpless', + 33666: 'helpline', + 34111: 'hemlock', + 34112: 'hemstitch', + 34113: 'hence', + 34114: 'henchman', + 34115: 'henna', + 34116: 'herald', + 34121: 'herbal', + 34122: 'herbicide', + 34123: 'herbs', + 34124: 'heritage', + 34125: 'hermit', + 34126: 'heroics', + 34131: 'heroism', + 34132: 'herring', + 34133: 'herself', + 34134: 'hertz', + 34135: 'hesitancy', + 34136: 'hesitant', + 34141: 'hesitate', + 34142: 'hexagon', + 34143: 'hexagram', + 34144: 'hubcap', + 34145: 'huddle', + 34146: 'huddling', + 34151: 'huff', + 34152: 'hug', + 34153: 'hula', + 34154: 'hulk', + 34155: 'hull', + 34156: 'human', + 34161: 'humble', + 34162: 'humbling', + 34163: 'humbly', + 34164: 'humid', + 34165: 'humiliate', + 34166: 'humility', + 34211: 'humming', + 34212: 'hummus', + 34213: 'humongous', + 34214: 'humorist', + 34215: 'humorless', + 34216: 'humorous', + 34221: 'humpback', + 34222: 'humped', + 34223: 'humvee', + 34224: 'hunchback', + 34225: 'hundredth', + 34226: 'hunger', + 34231: 'hungrily', + 34232: 'hungry', + 34233: 'hunk', + 34234: 'hunter', + 34235: 'hunting', + 34236: 'huntress', + 34241: 'huntsman', + 34242: 'hurdle', + 34243: 'hurled', + 34244: 'hurler', + 34245: 'hurling', + 34246: 'hurray', + 34251: 'hurricane', + 34252: 'hurried', + 34253: 'hurry', + 34254: 'hurt', + 34255: 'husband', + 34256: 'hush', + 34261: 'husked', + 34262: 'huskiness', + 34263: 'hut', + 34264: 'hybrid', + 34265: 'hydrant', + 34266: 'hydrated', + 34311: 'hydration', + 34312: 'hydrogen', + 34313: 'hydroxide', + 34314: 'hyperlink', + 34315: 'hypertext', + 34316: 'hyphen', + 34321: 'hypnoses', + 34322: 'hypnosis', + 34323: 'hypnotic', + 34324: 'hypnotism', + 34325: 'hypnotist', + 34326: 'hypnotize', + 34331: 'hypocrisy', + 34332: 'hypocrite', + 34333: 'ibuprofen', + 34334: 'ice', + 34335: 'iciness', + 34336: 'icing', + 34341: 'icky', + 34342: 'icon', + 34343: 'icy', + 34344: 'idealism', + 34345: 'idealist', + 34346: 'idealize', + 34351: 'ideally', + 34352: 'idealness', + 34353: 'identical', + 34354: 'identify', + 34355: 'identity', + 34356: 'ideology', + 34361: 'idiocy', + 34362: 'idiom', + 34363: 'idly', + 34364: 'igloo', + 34365: 'ignition', + 34366: 'ignore', + 34411: 'iguana', + 34412: 'illicitly', + 34413: 'illusion', + 34414: 'illusive', + 34415: 'image', + 34416: 'imaginary', + 34421: 'imagines', + 34422: 'imaging', + 34423: 'imbecile', + 34424: 'imitate', + 34425: 'imitation', + 34426: 'immature', + 34431: 'immerse', + 34432: 'immersion', + 34433: 'imminent', + 34434: 'immobile', + 34435: 'immodest', + 34436: 'immorally', + 34441: 'immortal', + 34442: 'immovable', + 34443: 'immovably', + 34444: 'immunity', + 34445: 'immunize', + 34446: 'impaired', + 34451: 'impale', + 34452: 'impart', + 34453: 'impatient', + 34454: 'impeach', + 34455: 'impeding', + 34456: 'impending', + 34461: 'imperfect', + 34462: 'imperial', + 34463: 'impish', + 34464: 'implant', + 34465: 'implement', + 34466: 'implicate', + 34511: 'implicit', + 34512: 'implode', + 34513: 'implosion', + 34514: 'implosive', + 34515: 'imply', + 34516: 'impolite', + 34521: 'important', + 34522: 'importer', + 34523: 'impose', + 34524: 'imposing', + 34525: 'impotence', + 34526: 'impotency', + 34531: 'impotent', + 34532: 'impound', + 34533: 'imprecise', + 34534: 'imprint', + 34535: 'imprison', + 34536: 'impromptu', + 34541: 'improper', + 34542: 'improve', + 34543: 'improving', + 34544: 'improvise', + 34545: 'imprudent', + 34546: 'impulse', + 34551: 'impulsive', + 34552: 'impure', + 34553: 'impurity', + 34554: 'iodine', + 34555: 'iodize', + 34556: 'ion', + 34561: 'ipad', + 34562: 'iphone', + 34563: 'ipod', + 34564: 'irate', + 34565: 'irk', + 34566: 'iron', + 34611: 'irregular', + 34612: 'irrigate', + 34613: 'irritable', + 34614: 'irritably', + 34615: 'irritant', + 34616: 'irritate', + 34621: 'islamic', + 34622: 'islamist', + 34623: 'isolated', + 34624: 'isolating', + 34625: 'isolation', + 34626: 'isotope', + 34631: 'issue', + 34632: 'issuing', + 34633: 'italicize', + 34634: 'italics', + 34635: 'item', + 34636: 'itinerary', + 34641: 'itunes', + 34642: 'ivory', + 34643: 'ivy', + 34644: 'jab', + 34645: 'jackal', + 34646: 'jacket', + 34651: 'jackknife', + 34652: 'jackpot', + 34653: 'jailbird', + 34654: 'jailbreak', + 34655: 'jailer', + 34656: 'jailhouse', + 34661: 'jalapeno', + 34662: 'jam', + 34663: 'janitor', + 34664: 'january', + 34665: 'jargon', + 34666: 'jarring', + 35111: 'jasmine', + 35112: 'jaundice', + 35113: 'jaunt', + 35114: 'java', + 35115: 'jawed', + 35116: 'jawless', + 35121: 'jawline', + 35122: 'jaws', + 35123: 'jaybird', + 35124: 'jaywalker', + 35125: 'jazz', + 35126: 'jeep', + 35131: 'jeeringly', + 35132: 'jellied', + 35133: 'jelly', + 35134: 'jersey', + 35135: 'jester', + 35136: 'jet', + 35141: 'jiffy', + 35142: 'jigsaw', + 35143: 'jimmy', + 35144: 'jingle', + 35145: 'jingling', + 35146: 'jinx', + 35151: 'jitters', + 35152: 'jittery', + 35153: 'job', + 35154: 'jockey', + 35155: 'jockstrap', + 35156: 'jogger', + 35161: 'jogging', + 35162: 'john', + 35163: 'joining', + 35164: 'jokester', + 35165: 'jokingly', + 35166: 'jolliness', + 35211: 'jolly', + 35212: 'jolt', + 35213: 'jot', + 35214: 'jovial', + 35215: 'joyfully', + 35216: 'joylessly', + 35221: 'joyous', + 35222: 'joyride', + 35223: 'joystick', + 35224: 'jubilance', + 35225: 'jubilant', + 35226: 'judge', + 35231: 'judgingly', + 35232: 'judicial', + 35233: 'judiciary', + 35234: 'judo', + 35235: 'juggle', + 35236: 'juggling', + 35241: 'jugular', + 35242: 'juice', + 35243: 'juiciness', + 35244: 'juicy', + 35245: 'jujitsu', + 35246: 'jukebox', + 35251: 'july', + 35252: 'jumble', + 35253: 'jumbo', + 35254: 'jump', + 35255: 'junction', + 35256: 'juncture', + 35261: 'june', + 35262: 'junior', + 35263: 'juniper', + 35264: 'junkie', + 35265: 'junkman', + 35266: 'junkyard', + 35311: 'jurist', + 35312: 'juror', + 35313: 'jury', + 35314: 'justice', + 35315: 'justifier', + 35316: 'justify', + 35321: 'justly', + 35322: 'justness', + 35323: 'juvenile', + 35324: 'kabob', + 35325: 'kangaroo', + 35326: 'karaoke', + 35331: 'karate', + 35332: 'karma', + 35333: 'kebab', + 35334: 'keenly', + 35335: 'keenness', + 35336: 'keep', + 35341: 'keg', + 35342: 'kelp', + 35343: 'kennel', + 35344: 'kept', + 35345: 'kerchief', + 35346: 'kerosene', + 35351: 'kettle', + 35352: 'kick', + 35353: 'kiln', + 35354: 'kilobyte', + 35355: 'kilogram', + 35356: 'kilometer', + 35361: 'kilowatt', + 35362: 'kilt', + 35363: 'kimono', + 35364: 'kindle', + 35365: 'kindling', + 35366: 'kindly', + 35411: 'kindness', + 35412: 'kindred', + 35413: 'kinetic', + 35414: 'kinfolk', + 35415: 'king', + 35416: 'kinship', + 35421: 'kinsman', + 35422: 'kinswoman', + 35423: 'kissable', + 35424: 'kisser', + 35425: 'kissing', + 35426: 'kitchen', + 35431: 'kite', + 35432: 'kitten', + 35433: 'kitty', + 35434: 'kiwi', + 35435: 'kleenex', + 35436: 'knapsack', + 35441: 'knee', + 35442: 'knelt', + 35443: 'knickers', + 35444: 'knoll', + 35445: 'koala', + 35446: 'kooky', + 35451: 'kosher', + 35452: 'krypton', + 35453: 'kudos', + 35454: 'kung', + 35455: 'labored', + 35456: 'laborer', + 35461: 'laboring', + 35462: 'laborious', + 35463: 'labrador', + 35464: 'ladder', + 35465: 'ladies', + 35466: 'ladle', + 35511: 'ladybug', + 35512: 'ladylike', + 35513: 'lagged', + 35514: 'lagging', + 35515: 'lagoon', + 35516: 'lair', + 35521: 'lake', + 35522: 'lance', + 35523: 'landed', + 35524: 'landfall', + 35525: 'landfill', + 35526: 'landing', + 35531: 'landlady', + 35532: 'landless', + 35533: 'landline', + 35534: 'landlord', + 35535: 'landmark', + 35536: 'landmass', + 35541: 'landmine', + 35542: 'landowner', + 35543: 'landscape', + 35544: 'landside', + 35545: 'landslide', + 35546: 'language', + 35551: 'lankiness', + 35552: 'lanky', + 35553: 'lantern', + 35554: 'lapdog', + 35555: 'lapel', + 35556: 'lapped', + 35561: 'lapping', + 35562: 'laptop', + 35563: 'lard', + 35564: 'large', + 35565: 'lark', + 35566: 'lash', + 35611: 'lasso', + 35612: 'last', + 35613: 'latch', + 35614: 'late', + 35615: 'lather', + 35616: 'latitude', + 35621: 'latrine', + 35622: 'latter', + 35623: 'latticed', + 35624: 'launch', + 35625: 'launder', + 35626: 'laundry', + 35631: 'laurel', + 35632: 'lavender', + 35633: 'lavish', + 35634: 'laxative', + 35635: 'lazily', + 35636: 'laziness', + 35641: 'lazy', + 35642: 'lecturer', + 35643: 'left', + 35644: 'legacy', + 35645: 'legal', + 35646: 'legend', + 35651: 'legged', + 35652: 'leggings', + 35653: 'legible', + 35654: 'legibly', + 35655: 'legislate', + 35656: 'lego', + 35661: 'legroom', + 35662: 'legume', + 35663: 'legwarmer', + 35664: 'legwork', + 35665: 'lemon', + 35666: 'lend', + 36111: 'length', + 36112: 'lens', + 36113: 'lent', + 36114: 'leotard', + 36115: 'lesser', + 36116: 'letdown', + 36121: 'lethargic', + 36122: 'lethargy', + 36123: 'letter', + 36124: 'lettuce', + 36125: 'level', + 36126: 'leverage', + 36131: 'levers', + 36132: 'levitate', + 36133: 'levitator', + 36134: 'liability', + 36135: 'liable', + 36136: 'liberty', + 36141: 'librarian', + 36142: 'library', + 36143: 'licking', + 36144: 'licorice', + 36145: 'lid', + 36146: 'life', + 36151: 'lifter', + 36152: 'lifting', + 36153: 'liftoff', + 36154: 'ligament', + 36155: 'likely', + 36156: 'likeness', + 36161: 'likewise', + 36162: 'liking', + 36163: 'lilac', + 36164: 'lilly', + 36165: 'lily', + 36166: 'limb', + 36211: 'limeade', + 36212: 'limelight', + 36213: 'limes', + 36214: 'limit', + 36215: 'limping', + 36216: 'limpness', + 36221: 'line', + 36222: 'lingo', + 36223: 'linguini', + 36224: 'linguist', + 36225: 'lining', + 36226: 'linked', + 36231: 'linoleum', + 36232: 'linseed', + 36233: 'lint', + 36234: 'lion', + 36235: 'lip', + 36236: 'liquefy', + 36241: 'liqueur', + 36242: 'liquid', + 36243: 'lisp', + 36244: 'list', + 36245: 'litigate', + 36246: 'litigator', + 36251: 'litmus', + 36252: 'litter', + 36253: 'little', + 36254: 'livable', + 36255: 'lived', + 36256: 'lively', + 36261: 'liver', + 36262: 'livestock', + 36263: 'lividly', + 36264: 'living', + 36265: 'lizard', + 36266: 'lubricant', + 36311: 'lubricate', + 36312: 'lucid', + 36313: 'luckily', + 36314: 'luckiness', + 36315: 'luckless', + 36316: 'lucrative', + 36321: 'ludicrous', + 36322: 'lugged', + 36323: 'lukewarm', + 36324: 'lullaby', + 36325: 'lumber', + 36326: 'luminance', + 36331: 'luminous', + 36332: 'lumpiness', + 36333: 'lumping', + 36334: 'lumpish', + 36335: 'lunacy', + 36336: 'lunar', + 36341: 'lunchbox', + 36342: 'luncheon', + 36343: 'lunchroom', + 36344: 'lunchtime', + 36345: 'lung', + 36346: 'lurch', + 36351: 'lure', + 36352: 'luridness', + 36353: 'lurk', + 36354: 'lushly', + 36355: 'lushness', + 36356: 'luster', + 36361: 'lustfully', + 36362: 'lustily', + 36363: 'lustiness', + 36364: 'lustrous', + 36365: 'lusty', + 36366: 'luxurious', + 36411: 'luxury', + 36412: 'lying', + 36413: 'lyrically', + 36414: 'lyricism', + 36415: 'lyricist', + 36416: 'lyrics', + 36421: 'macarena', + 36422: 'macaroni', + 36423: 'macaw', + 36424: 'mace', + 36425: 'machine', + 36426: 'machinist', + 36431: 'magazine', + 36432: 'magenta', + 36433: 'maggot', + 36434: 'magical', + 36435: 'magician', + 36436: 'magma', + 36441: 'magnesium', + 36442: 'magnetic', + 36443: 'magnetism', + 36444: 'magnetize', + 36445: 'magnifier', + 36446: 'magnify', + 36451: 'magnitude', + 36452: 'magnolia', + 36453: 'mahogany', + 36454: 'maimed', + 36455: 'majestic', + 36456: 'majesty', + 36461: 'majorette', + 36462: 'majority', + 36463: 'makeover', + 36464: 'maker', + 36465: 'makeshift', + 36466: 'making', + 36511: 'malformed', + 36512: 'malt', + 36513: 'mama', + 36514: 'mammal', + 36515: 'mammary', + 36516: 'mammogram', + 36521: 'manager', + 36522: 'managing', + 36523: 'manatee', + 36524: 'mandarin', + 36525: 'mandate', + 36526: 'mandatory', + 36531: 'mandolin', + 36532: 'manger', + 36533: 'mangle', + 36534: 'mango', + 36535: 'mangy', + 36536: 'manhandle', + 36541: 'manhole', + 36542: 'manhood', + 36543: 'manhunt', + 36544: 'manicotti', + 36545: 'manicure', + 36546: 'manifesto', + 36551: 'manila', + 36552: 'mankind', + 36553: 'manlike', + 36554: 'manliness', + 36555: 'manly', + 36556: 'manmade', + 36561: 'manned', + 36562: 'mannish', + 36563: 'manor', + 36564: 'manpower', + 36565: 'mantis', + 36566: 'mantra', + 36611: 'manual', + 36612: 'many', + 36613: 'map', + 36614: 'marathon', + 36615: 'marauding', + 36616: 'marbled', + 36621: 'marbles', + 36622: 'marbling', + 36623: 'march', + 36624: 'mardi', + 36625: 'margarine', + 36626: 'margarita', + 36631: 'margin', + 36632: 'marigold', + 36633: 'marina', + 36634: 'marine', + 36635: 'marital', + 36636: 'maritime', + 36641: 'marlin', + 36642: 'marmalade', + 36643: 'maroon', + 36644: 'married', + 36645: 'marrow', + 36646: 'marry', + 36651: 'marshland', + 36652: 'marshy', + 36653: 'marsupial', + 36654: 'marvelous', + 36655: 'marxism', + 36656: 'mascot', + 36661: 'masculine', + 36662: 'mashed', + 36663: 'mashing', + 36664: 'massager', + 36665: 'masses', + 36666: 'massive', + 41111: 'mastiff', + 41112: 'matador', + 41113: 'matchbook', + 41114: 'matchbox', + 41115: 'matcher', + 41116: 'matching', + 41121: 'matchless', + 41122: 'material', + 41123: 'maternal', + 41124: 'maternity', + 41125: 'math', + 41126: 'mating', + 41131: 'matriarch', + 41132: 'matrimony', + 41133: 'matrix', + 41134: 'matron', + 41135: 'matted', + 41136: 'matter', + 41141: 'maturely', + 41142: 'maturing', + 41143: 'maturity', + 41144: 'mauve', + 41145: 'maverick', + 41146: 'maximize', + 41151: 'maximum', + 41152: 'maybe', + 41153: 'mayday', + 41154: 'mayflower', + 41155: 'moaner', + 41156: 'moaning', + 41161: 'mobile', + 41162: 'mobility', + 41163: 'mobilize', + 41164: 'mobster', + 41165: 'mocha', + 41166: 'mocker', + 41211: 'mockup', + 41212: 'modified', + 41213: 'modify', + 41214: 'modular', + 41215: 'modulator', + 41216: 'module', + 41221: 'moisten', + 41222: 'moistness', + 41223: 'moisture', + 41224: 'molar', + 41225: 'molasses', + 41226: 'mold', + 41231: 'molecular', + 41232: 'molecule', + 41233: 'molehill', + 41234: 'mollusk', + 41235: 'mom', + 41236: 'monastery', + 41241: 'monday', + 41242: 'monetary', + 41243: 'monetize', + 41244: 'moneybags', + 41245: 'moneyless', + 41246: 'moneywise', + 41251: 'mongoose', + 41252: 'mongrel', + 41253: 'monitor', + 41254: 'monkhood', + 41255: 'monogamy', + 41256: 'monogram', + 41261: 'monologue', + 41262: 'monopoly', + 41263: 'monorail', + 41264: 'monotone', + 41265: 'monotype', + 41266: 'monoxide', + 41311: 'monsieur', + 41312: 'monsoon', + 41313: 'monstrous', + 41314: 'monthly', + 41315: 'monument', + 41316: 'moocher', + 41321: 'moodiness', + 41322: 'moody', + 41323: 'mooing', + 41324: 'moonbeam', + 41325: 'mooned', + 41326: 'moonlight', + 41331: 'moonlike', + 41332: 'moonlit', + 41333: 'moonrise', + 41334: 'moonscape', + 41335: 'moonshine', + 41336: 'moonstone', + 41341: 'moonwalk', + 41342: 'mop', + 41343: 'morale', + 41344: 'morality', + 41345: 'morally', + 41346: 'morbidity', + 41351: 'morbidly', + 41352: 'morphine', + 41353: 'morphing', + 41354: 'morse', + 41355: 'mortality', + 41356: 'mortally', + 41361: 'mortician', + 41362: 'mortified', + 41363: 'mortify', + 41364: 'mortuary', + 41365: 'mosaic', + 41366: 'mossy', + 41411: 'most', + 41412: 'mothball', + 41413: 'mothproof', + 41414: 'motion', + 41415: 'motivate', + 41416: 'motivator', + 41421: 'motive', + 41422: 'motocross', + 41423: 'motor', + 41424: 'motto', + 41425: 'mountable', + 41426: 'mountain', + 41431: 'mounted', + 41432: 'mounting', + 41433: 'mourner', + 41434: 'mournful', + 41435: 'mouse', + 41436: 'mousiness', + 41441: 'moustache', + 41442: 'mousy', + 41443: 'mouth', + 41444: 'movable', + 41445: 'move', + 41446: 'movie', + 41451: 'moving', + 41452: 'mower', + 41453: 'mowing', + 41454: 'much', + 41455: 'muck', + 41456: 'mud', + 41461: 'mug', + 41462: 'mulberry', + 41463: 'mulch', + 41464: 'mule', + 41465: 'mulled', + 41466: 'mullets', + 41511: 'multiple', + 41512: 'multiply', + 41513: 'multitask', + 41514: 'multitude', + 41515: 'mumble', + 41516: 'mumbling', + 41521: 'mumbo', + 41522: 'mummified', + 41523: 'mummify', + 41524: 'mummy', + 41525: 'mumps', + 41526: 'munchkin', + 41531: 'mundane', + 41532: 'municipal', + 41533: 'muppet', + 41534: 'mural', + 41535: 'murkiness', + 41536: 'murky', + 41541: 'murmuring', + 41542: 'muscular', + 41543: 'museum', + 41544: 'mushily', + 41545: 'mushiness', + 41546: 'mushroom', + 41551: 'mushy', + 41552: 'music', + 41553: 'musket', + 41554: 'muskiness', + 41555: 'musky', + 41556: 'mustang', + 41561: 'mustard', + 41562: 'muster', + 41563: 'mustiness', + 41564: 'musty', + 41565: 'mutable', + 41566: 'mutate', + 41611: 'mutation', + 41612: 'mute', + 41613: 'mutilated', + 41614: 'mutilator', + 41615: 'mutiny', + 41616: 'mutt', + 41621: 'mutual', + 41622: 'muzzle', + 41623: 'myself', + 41624: 'myspace', + 41625: 'mystified', + 41626: 'mystify', + 41631: 'myth', + 41632: 'nacho', + 41633: 'nag', + 41634: 'nail', + 41635: 'name', + 41636: 'naming', + 41641: 'nanny', + 41642: 'nanometer', + 41643: 'nape', + 41644: 'napkin', + 41645: 'napped', + 41646: 'napping', + 41651: 'nappy', + 41652: 'narrow', + 41653: 'nastily', + 41654: 'nastiness', + 41655: 'national', + 41656: 'native', + 41661: 'nativity', + 41662: 'natural', + 41663: 'nature', + 41664: 'naturist', + 41665: 'nautical', + 41666: 'navigate', + 42111: 'navigator', + 42112: 'navy', + 42113: 'nearby', + 42114: 'nearest', + 42115: 'nearly', + 42116: 'nearness', + 42121: 'neatly', + 42122: 'neatness', + 42123: 'nebula', + 42124: 'nebulizer', + 42125: 'nectar', + 42126: 'negate', + 42131: 'negation', + 42132: 'negative', + 42133: 'neglector', + 42134: 'negligee', + 42135: 'negligent', + 42136: 'negotiate', + 42141: 'nemeses', + 42142: 'nemesis', + 42143: 'neon', + 42144: 'nephew', + 42145: 'nerd', + 42146: 'nervous', + 42151: 'nervy', + 42152: 'nest', + 42153: 'net', + 42154: 'neurology', + 42155: 'neuron', + 42156: 'neurosis', + 42161: 'neurotic', + 42162: 'neuter', + 42163: 'neutron', + 42164: 'never', + 42165: 'next', + 42166: 'nibble', + 42211: 'nickname', + 42212: 'nicotine', + 42213: 'niece', + 42214: 'nifty', + 42215: 'nimble', + 42216: 'nimbly', + 42221: 'nineteen', + 42222: 'ninetieth', + 42223: 'ninja', + 42224: 'nintendo', + 42225: 'ninth', + 42226: 'nuclear', + 42231: 'nuclei', + 42232: 'nucleus', + 42233: 'nugget', + 42234: 'nullify', + 42235: 'number', + 42236: 'numbing', + 42241: 'numbly', + 42242: 'numbness', + 42243: 'numeral', + 42244: 'numerate', + 42245: 'numerator', + 42246: 'numeric', + 42251: 'numerous', + 42252: 'nuptials', + 42253: 'nursery', + 42254: 'nursing', + 42255: 'nurture', + 42256: 'nutcase', + 42261: 'nutlike', + 42262: 'nutmeg', + 42263: 'nutrient', + 42264: 'nutshell', + 42265: 'nuttiness', + 42266: 'nutty', + 42311: 'nuzzle', + 42312: 'nylon', + 42313: 'oaf', + 42314: 'oak', + 42315: 'oasis', + 42316: 'oat', + 42321: 'obedience', + 42322: 'obedient', + 42323: 'obituary', + 42324: 'object', + 42325: 'obligate', + 42326: 'obliged', + 42331: 'oblivion', + 42332: 'oblivious', + 42333: 'oblong', + 42334: 'obnoxious', + 42335: 'oboe', + 42336: 'obscure', + 42341: 'obscurity', + 42342: 'observant', + 42343: 'observer', + 42344: 'observing', + 42345: 'obsessed', + 42346: 'obsession', + 42351: 'obsessive', + 42352: 'obsolete', + 42353: 'obstacle', + 42354: 'obstinate', + 42355: 'obstruct', + 42356: 'obtain', + 42361: 'obtrusive', + 42362: 'obtuse', + 42363: 'obvious', + 42364: 'occultist', + 42365: 'occupancy', + 42366: 'occupant', + 42411: 'occupier', + 42412: 'occupy', + 42413: 'ocean', + 42414: 'ocelot', + 42415: 'octagon', + 42416: 'octane', + 42421: 'october', + 42422: 'octopus', + 42423: 'ogle', + 42424: 'oil', + 42425: 'oink', + 42426: 'ointment', + 42431: 'okay', + 42432: 'old', + 42433: 'olive', + 42434: 'olympics', + 42435: 'omega', + 42436: 'omen', + 42441: 'ominous', + 42442: 'omission', + 42443: 'omit', + 42444: 'omnivore', + 42445: 'onboard', + 42446: 'oncoming', + 42451: 'ongoing', + 42452: 'onion', + 42453: 'online', + 42454: 'onlooker', + 42455: 'only', + 42456: 'onscreen', + 42461: 'onset', + 42462: 'onshore', + 42463: 'onslaught', + 42464: 'onstage', + 42465: 'onto', + 42466: 'onward', + 42511: 'onyx', + 42512: 'oops', + 42513: 'ooze', + 42514: 'oozy', + 42515: 'opacity', + 42516: 'opal', + 42521: 'open', + 42522: 'operable', + 42523: 'operate', + 42524: 'operating', + 42525: 'operation', + 42526: 'operative', + 42531: 'operator', + 42532: 'opium', + 42533: 'opossum', + 42534: 'opponent', + 42535: 'oppose', + 42536: 'opposing', + 42541: 'opposite', + 42542: 'oppressed', + 42543: 'oppressor', + 42544: 'opt', + 42545: 'opulently', + 42546: 'osmosis', + 42551: 'other', + 42552: 'otter', + 42553: 'ouch', + 42554: 'ought', + 42555: 'ounce', + 42556: 'outage', + 42561: 'outback', + 42562: 'outbid', + 42563: 'outboard', + 42564: 'outbound', + 42565: 'outbreak', + 42566: 'outburst', + 42611: 'outcast', + 42612: 'outclass', + 42613: 'outcome', + 42614: 'outdated', + 42615: 'outdoors', + 42616: 'outer', + 42621: 'outfield', + 42622: 'outfit', + 42623: 'outflank', + 42624: 'outgoing', + 42625: 'outgrow', + 42626: 'outhouse', + 42631: 'outing', + 42632: 'outlast', + 42633: 'outlet', + 42634: 'outline', + 42635: 'outlook', + 42636: 'outlying', + 42641: 'outmatch', + 42642: 'outmost', + 42643: 'outnumber', + 42644: 'outplayed', + 42645: 'outpost', + 42646: 'outpour', + 42651: 'output', + 42652: 'outrage', + 42653: 'outrank', + 42654: 'outreach', + 42655: 'outright', + 42656: 'outscore', + 42661: 'outsell', + 42662: 'outshine', + 42663: 'outshoot', + 42664: 'outsider', + 42665: 'outskirts', + 42666: 'outsmart', + 43111: 'outsource', + 43112: 'outspoken', + 43113: 'outtakes', + 43114: 'outthink', + 43115: 'outward', + 43116: 'outweigh', + 43121: 'outwit', + 43122: 'oval', + 43123: 'ovary', + 43124: 'oven', + 43125: 'overact', + 43126: 'overall', + 43131: 'overarch', + 43132: 'overbid', + 43133: 'overbill', + 43134: 'overbite', + 43135: 'overblown', + 43136: 'overboard', + 43141: 'overbook', + 43142: 'overbuilt', + 43143: 'overcast', + 43144: 'overcoat', + 43145: 'overcome', + 43146: 'overcook', + 43151: 'overcrowd', + 43152: 'overdraft', + 43153: 'overdrawn', + 43154: 'overdress', + 43155: 'overdrive', + 43156: 'overdue', + 43161: 'overeager', + 43162: 'overeater', + 43163: 'overexert', + 43164: 'overfed', + 43165: 'overfeed', + 43166: 'overfill', + 43211: 'overflow', + 43212: 'overfull', + 43213: 'overgrown', + 43214: 'overhand', + 43215: 'overhang', + 43216: 'overhaul', + 43221: 'overhead', + 43222: 'overhear', + 43223: 'overheat', + 43224: 'overhung', + 43225: 'overjoyed', + 43226: 'overkill', + 43231: 'overlabor', + 43232: 'overlaid', + 43233: 'overlap', + 43234: 'overlay', + 43235: 'overload', + 43236: 'overlook', + 43241: 'overlord', + 43242: 'overlying', + 43243: 'overnight', + 43244: 'overpass', + 43245: 'overpay', + 43246: 'overplant', + 43251: 'overplay', + 43252: 'overpower', + 43253: 'overprice', + 43254: 'overrate', + 43255: 'overreach', + 43256: 'overreact', + 43261: 'override', + 43262: 'overripe', + 43263: 'overrule', + 43264: 'overrun', + 43265: 'overshoot', + 43266: 'overshot', + 43311: 'oversight', + 43312: 'oversized', + 43313: 'oversleep', + 43314: 'oversold', + 43315: 'overspend', + 43316: 'overstate', + 43321: 'overstay', + 43322: 'overstep', + 43323: 'overstock', + 43324: 'overstuff', + 43325: 'oversweet', + 43326: 'overtake', + 43331: 'overthrow', + 43332: 'overtime', + 43333: 'overtly', + 43334: 'overtone', + 43335: 'overture', + 43336: 'overturn', + 43341: 'overuse', + 43342: 'overvalue', + 43343: 'overview', + 43344: 'overwrite', + 43345: 'owl', + 43346: 'oxford', + 43351: 'oxidant', + 43352: 'oxidation', + 43353: 'oxidize', + 43354: 'oxidizing', + 43355: 'oxygen', + 43356: 'oxymoron', + 43361: 'oyster', + 43362: 'ozone', + 43363: 'paced', + 43364: 'pacemaker', + 43365: 'pacific', + 43366: 'pacifier', + 43411: 'pacifism', + 43412: 'pacifist', + 43413: 'pacify', + 43414: 'padded', + 43415: 'padding', + 43416: 'paddle', + 43421: 'paddling', + 43422: 'padlock', + 43423: 'pagan', + 43424: 'pager', + 43425: 'paging', + 43426: 'pajamas', + 43431: 'palace', + 43432: 'palatable', + 43433: 'palm', + 43434: 'palpable', + 43435: 'palpitate', + 43436: 'paltry', + 43441: 'pampered', + 43442: 'pamperer', + 43443: 'pampers', + 43444: 'pamphlet', + 43445: 'panama', + 43446: 'pancake', + 43451: 'pancreas', + 43452: 'panda', + 43453: 'pandemic', + 43454: 'pang', + 43455: 'panhandle', + 43456: 'panic', + 43461: 'panning', + 43462: 'panorama', + 43463: 'panoramic', + 43464: 'panther', + 43465: 'pantomime', + 43466: 'pantry', + 43511: 'pants', + 43512: 'pantyhose', + 43513: 'paparazzi', + 43514: 'papaya', + 43515: 'paper', + 43516: 'paprika', + 43521: 'papyrus', + 43522: 'parabola', + 43523: 'parachute', + 43524: 'parade', + 43525: 'paradox', + 43526: 'paragraph', + 43531: 'parakeet', + 43532: 'paralegal', + 43533: 'paralyses', + 43534: 'paralysis', + 43535: 'paralyze', + 43536: 'paramedic', + 43541: 'parameter', + 43542: 'paramount', + 43543: 'parasail', + 43544: 'parasite', + 43545: 'parasitic', + 43546: 'parcel', + 43551: 'parched', + 43552: 'parchment', + 43553: 'pardon', + 43554: 'parish', + 43555: 'parka', + 43556: 'parking', + 43561: 'parkway', + 43562: 'parlor', + 43563: 'parmesan', + 43564: 'parole', + 43565: 'parrot', + 43566: 'parsley', + 43611: 'parsnip', + 43612: 'partake', + 43613: 'parted', + 43614: 'parting', + 43615: 'partition', + 43616: 'partly', + 43621: 'partner', + 43622: 'partridge', + 43623: 'party', + 43624: 'passable', + 43625: 'passably', + 43626: 'passage', + 43631: 'passcode', + 43632: 'passenger', + 43633: 'passerby', + 43634: 'passing', + 43635: 'passion', + 43636: 'passive', + 43641: 'passivism', + 43642: 'passover', + 43643: 'passport', + 43644: 'password', + 43645: 'pasta', + 43646: 'pasted', + 43651: 'pastel', + 43652: 'pastime', + 43653: 'pastor', + 43654: 'pastrami', + 43655: 'pasture', + 43656: 'pasty', + 43661: 'patchwork', + 43662: 'patchy', + 43663: 'paternal', + 43664: 'paternity', + 43665: 'path', + 43666: 'patience', + 44111: 'patient', + 44112: 'patio', + 44113: 'patriarch', + 44114: 'patriot', + 44115: 'patrol', + 44116: 'patronage', + 44121: 'patronize', + 44122: 'pauper', + 44123: 'pavement', + 44124: 'paver', + 44125: 'pavestone', + 44126: 'pavilion', + 44131: 'paving', + 44132: 'pawing', + 44133: 'payable', + 44134: 'payback', + 44135: 'paycheck', + 44136: 'payday', + 44141: 'payee', + 44142: 'payer', + 44143: 'paying', + 44144: 'payment', + 44145: 'payphone', + 44146: 'payroll', + 44151: 'pebble', + 44152: 'pebbly', + 44153: 'pecan', + 44154: 'pectin', + 44155: 'peculiar', + 44156: 'peddling', + 44161: 'pediatric', + 44162: 'pedicure', + 44163: 'pedigree', + 44164: 'pedometer', + 44165: 'pegboard', + 44166: 'pelican', + 44211: 'pellet', + 44212: 'pelt', + 44213: 'pelvis', + 44214: 'penalize', + 44215: 'penalty', + 44216: 'pencil', + 44221: 'pendant', + 44222: 'pending', + 44223: 'penholder', + 44224: 'penknife', + 44225: 'pennant', + 44226: 'penniless', + 44231: 'penny', + 44232: 'penpal', + 44233: 'pension', + 44234: 'pentagon', + 44235: 'pentagram', + 44236: 'pep', + 44241: 'perceive', + 44242: 'percent', + 44243: 'perch', + 44244: 'percolate', + 44245: 'perennial', + 44246: 'perfected', + 44251: 'perfectly', + 44252: 'perfume', + 44253: 'periscope', + 44254: 'perish', + 44255: 'perjurer', + 44256: 'perjury', + 44261: 'perkiness', + 44262: 'perky', + 44263: 'perm', + 44264: 'peroxide', + 44265: 'perpetual', + 44266: 'perplexed', + 44311: 'persecute', + 44312: 'persevere', + 44313: 'persuaded', + 44314: 'persuader', + 44315: 'pesky', + 44316: 'peso', + 44321: 'pessimism', + 44322: 'pessimist', + 44323: 'pester', + 44324: 'pesticide', + 44325: 'petal', + 44326: 'petite', + 44331: 'petition', + 44332: 'petri', + 44333: 'petroleum', + 44334: 'petted', + 44335: 'petticoat', + 44336: 'pettiness', + 44341: 'petty', + 44342: 'petunia', + 44343: 'phantom', + 44344: 'phobia', + 44345: 'phoenix', + 44346: 'phonebook', + 44351: 'phoney', + 44352: 'phonics', + 44353: 'phoniness', + 44354: 'phony', + 44355: 'phosphate', + 44356: 'photo', + 44361: 'phrase', + 44362: 'phrasing', + 44363: 'placard', + 44364: 'placate', + 44365: 'placidly', + 44366: 'plank', + 44411: 'planner', + 44412: 'plant', + 44413: 'plasma', + 44414: 'plaster', + 44415: 'plastic', + 44416: 'plated', + 44421: 'platform', + 44422: 'plating', + 44423: 'platinum', + 44424: 'platonic', + 44425: 'platter', + 44426: 'platypus', + 44431: 'plausible', + 44432: 'plausibly', + 44433: 'playable', + 44434: 'playback', + 44435: 'player', + 44436: 'playful', + 44441: 'playgroup', + 44442: 'playhouse', + 44443: 'playing', + 44444: 'playlist', + 44445: 'playmaker', + 44446: 'playmate', + 44451: 'playoff', + 44452: 'playpen', + 44453: 'playroom', + 44454: 'playset', + 44455: 'plaything', + 44456: 'playtime', + 44461: 'plaza', + 44462: 'pleading', + 44463: 'pleat', + 44464: 'pledge', + 44465: 'plentiful', + 44466: 'plenty', + 44511: 'plethora', + 44512: 'plexiglas', + 44513: 'pliable', + 44514: 'plod', + 44515: 'plop', + 44516: 'plot', + 44521: 'plow', + 44522: 'ploy', + 44523: 'pluck', + 44524: 'plug', + 44525: 'plunder', + 44526: 'plunging', + 44531: 'plural', + 44532: 'plus', + 44533: 'plutonium', + 44534: 'plywood', + 44535: 'poach', + 44536: 'pod', + 44541: 'poem', + 44542: 'poet', + 44543: 'pogo', + 44544: 'pointed', + 44545: 'pointer', + 44546: 'pointing', + 44551: 'pointless', + 44552: 'pointy', + 44553: 'poise', + 44554: 'poison', + 44555: 'poker', + 44556: 'poking', + 44561: 'polar', + 44562: 'police', + 44563: 'policy', + 44564: 'polio', + 44565: 'polish', + 44566: 'politely', + 44611: 'polka', + 44612: 'polo', + 44613: 'polyester', + 44614: 'polygon', + 44615: 'polygraph', + 44616: 'polymer', + 44621: 'poncho', + 44622: 'pond', + 44623: 'pony', + 44624: 'popcorn', + 44625: 'pope', + 44626: 'poplar', + 44631: 'popper', + 44632: 'poppy', + 44633: 'popsicle', + 44634: 'populace', + 44635: 'popular', + 44636: 'populate', + 44641: 'porcupine', + 44642: 'pork', + 44643: 'porous', + 44644: 'porridge', + 44645: 'portable', + 44646: 'portal', + 44651: 'portfolio', + 44652: 'porthole', + 44653: 'portion', + 44654: 'portly', + 44655: 'portside', + 44656: 'poser', + 44661: 'posh', + 44662: 'posing', + 44663: 'possible', + 44664: 'possibly', + 44665: 'possum', + 44666: 'postage', + 45111: 'postal', + 45112: 'postbox', + 45113: 'postcard', + 45114: 'posted', + 45115: 'poster', + 45116: 'posting', + 45121: 'postnasal', + 45122: 'posture', + 45123: 'postwar', + 45124: 'pouch', + 45125: 'pounce', + 45126: 'pouncing', + 45131: 'pound', + 45132: 'pouring', + 45133: 'pout', + 45134: 'powdered', + 45135: 'powdering', + 45136: 'powdery', + 45141: 'power', + 45142: 'powwow', + 45143: 'pox', + 45144: 'praising', + 45145: 'prance', + 45146: 'prancing', + 45151: 'pranker', + 45152: 'prankish', + 45153: 'prankster', + 45154: 'prayer', + 45155: 'praying', + 45156: 'preacher', + 45161: 'preaching', + 45162: 'preachy', + 45163: 'preamble', + 45164: 'precinct', + 45165: 'precise', + 45166: 'precision', + 45211: 'precook', + 45212: 'precut', + 45213: 'predator', + 45214: 'predefine', + 45215: 'predict', + 45216: 'preface', + 45221: 'prefix', + 45222: 'preflight', + 45223: 'preformed', + 45224: 'pregame', + 45225: 'pregnancy', + 45226: 'pregnant', + 45231: 'preheated', + 45232: 'prelaunch', + 45233: 'prelaw', + 45234: 'prelude', + 45235: 'premiere', + 45236: 'premises', + 45241: 'premium', + 45242: 'prenatal', + 45243: 'preoccupy', + 45244: 'preorder', + 45245: 'prepaid', + 45246: 'prepay', + 45251: 'preplan', + 45252: 'preppy', + 45253: 'preschool', + 45254: 'prescribe', + 45255: 'preseason', + 45256: 'preset', + 45261: 'preshow', + 45262: 'president', + 45263: 'presoak', + 45264: 'press', + 45265: 'presume', + 45266: 'presuming', + 45311: 'preteen', + 45312: 'pretended', + 45313: 'pretender', + 45314: 'pretense', + 45315: 'pretext', + 45316: 'pretty', + 45321: 'pretzel', + 45322: 'prevail', + 45323: 'prevalent', + 45324: 'prevent', + 45325: 'preview', + 45326: 'previous', + 45331: 'prewar', + 45332: 'prewashed', + 45333: 'prideful', + 45334: 'pried', + 45335: 'primal', + 45336: 'primarily', + 45341: 'primary', + 45342: 'primate', + 45343: 'primer', + 45344: 'primp', + 45345: 'princess', + 45346: 'print', + 45351: 'prior', + 45352: 'prism', + 45353: 'prison', + 45354: 'prissy', + 45355: 'pristine', + 45356: 'privacy', + 45361: 'private', + 45362: 'privatize', + 45363: 'prize', + 45364: 'proactive', + 45365: 'probable', + 45366: 'probably', + 45411: 'probation', + 45412: 'probe', + 45413: 'probing', + 45414: 'probiotic', + 45415: 'problem', + 45416: 'procedure', + 45421: 'process', + 45422: 'proclaim', + 45423: 'procreate', + 45424: 'procurer', + 45425: 'prodigal', + 45426: 'prodigy', + 45431: 'produce', + 45432: 'product', + 45433: 'profane', + 45434: 'profanity', + 45435: 'professed', + 45436: 'professor', + 45441: 'profile', + 45442: 'profound', + 45443: 'profusely', + 45444: 'progeny', + 45445: 'prognosis', + 45446: 'program', + 45451: 'progress', + 45452: 'projector', + 45453: 'prologue', + 45454: 'prolonged', + 45455: 'promenade', + 45456: 'prominent', + 45461: 'promoter', + 45462: 'promotion', + 45463: 'prompter', + 45464: 'promptly', + 45465: 'prone', + 45466: 'prong', + 45511: 'pronounce', + 45512: 'pronto', + 45513: 'proofing', + 45514: 'proofread', + 45515: 'proofs', + 45516: 'propeller', + 45521: 'properly', + 45522: 'property', + 45523: 'proponent', + 45524: 'proposal', + 45525: 'propose', + 45526: 'props', + 45531: 'prorate', + 45532: 'protector', + 45533: 'protegee', + 45534: 'proton', + 45535: 'prototype', + 45536: 'protozoan', + 45541: 'protract', + 45542: 'protrude', + 45543: 'proud', + 45544: 'provable', + 45545: 'proved', + 45546: 'proven', + 45551: 'provided', + 45552: 'provider', + 45553: 'providing', + 45554: 'province', + 45555: 'proving', + 45556: 'provoke', + 45561: 'provoking', + 45562: 'provolone', + 45563: 'prowess', + 45564: 'prowler', + 45565: 'prowling', + 45566: 'proximity', + 45611: 'proxy', + 45612: 'prozac', + 45613: 'prude', + 45614: 'prudishly', + 45615: 'prune', + 45616: 'pruning', + 45621: 'pry', + 45622: 'psychic', + 45623: 'public', + 45624: 'publisher', + 45625: 'pucker', + 45626: 'pueblo', + 45631: 'pug', + 45632: 'pull', + 45633: 'pulmonary', + 45634: 'pulp', + 45635: 'pulsate', + 45636: 'pulse', + 45641: 'pulverize', + 45642: 'puma', + 45643: 'pumice', + 45644: 'pummel', + 45645: 'punch', + 45646: 'punctual', + 45651: 'punctuate', + 45652: 'punctured', + 45653: 'pungent', + 45654: 'punisher', + 45655: 'punk', + 45656: 'pupil', + 45661: 'puppet', + 45662: 'puppy', + 45663: 'purchase', + 45664: 'pureblood', + 45665: 'purebred', + 45666: 'purely', + 46111: 'pureness', + 46112: 'purgatory', + 46113: 'purge', + 46114: 'purging', + 46115: 'purifier', + 46116: 'purify', + 46121: 'purist', + 46122: 'puritan', + 46123: 'purity', + 46124: 'purple', + 46125: 'purplish', + 46126: 'purposely', + 46131: 'purr', + 46132: 'purse', + 46133: 'pursuable', + 46134: 'pursuant', + 46135: 'pursuit', + 46136: 'purveyor', + 46141: 'pushcart', + 46142: 'pushchair', + 46143: 'pusher', + 46144: 'pushiness', + 46145: 'pushing', + 46146: 'pushover', + 46151: 'pushpin', + 46152: 'pushup', + 46153: 'pushy', + 46154: 'putdown', + 46155: 'putt', + 46156: 'puzzle', + 46161: 'puzzling', + 46162: 'pyramid', + 46163: 'pyromania', + 46164: 'python', + 46165: 'quack', + 46166: 'quadrant', + 46211: 'quail', + 46212: 'quaintly', + 46213: 'quake', + 46214: 'quaking', + 46215: 'qualified', + 46216: 'qualifier', + 46221: 'qualify', + 46222: 'quality', + 46223: 'qualm', + 46224: 'quantum', + 46225: 'quarrel', + 46226: 'quarry', + 46231: 'quartered', + 46232: 'quarterly', + 46233: 'quarters', + 46234: 'quartet', + 46235: 'quench', + 46236: 'query', + 46241: 'quicken', + 46242: 'quickly', + 46243: 'quickness', + 46244: 'quicksand', + 46245: 'quickstep', + 46246: 'quiet', + 46251: 'quill', + 46252: 'quilt', + 46253: 'quintet', + 46254: 'quintuple', + 46255: 'quirk', + 46256: 'quit', + 46261: 'quiver', + 46262: 'quizzical', + 46263: 'quotable', + 46264: 'quotation', + 46265: 'quote', + 46266: 'rabid', + 46311: 'race', + 46312: 'racing', + 46313: 'racism', + 46314: 'rack', + 46315: 'racoon', + 46316: 'radar', + 46321: 'radial', + 46322: 'radiance', + 46323: 'radiantly', + 46324: 'radiated', + 46325: 'radiation', + 46326: 'radiator', + 46331: 'radio', + 46332: 'radish', + 46333: 'raffle', + 46334: 'raft', + 46335: 'rage', + 46336: 'ragged', + 46341: 'raging', + 46342: 'ragweed', + 46343: 'raider', + 46344: 'railcar', + 46345: 'railing', + 46346: 'railroad', + 46351: 'railway', + 46352: 'raisin', + 46353: 'rake', + 46354: 'raking', + 46355: 'rally', + 46356: 'ramble', + 46361: 'rambling', + 46362: 'ramp', + 46363: 'ramrod', + 46364: 'ranch', + 46365: 'rancidity', + 46366: 'random', + 46411: 'ranged', + 46412: 'ranger', + 46413: 'ranging', + 46414: 'ranked', + 46415: 'ranking', + 46416: 'ransack', + 46421: 'ranting', + 46422: 'rants', + 46423: 'rare', + 46424: 'rarity', + 46425: 'rascal', + 46426: 'rash', + 46431: 'rasping', + 46432: 'ravage', + 46433: 'raven', + 46434: 'ravine', + 46435: 'raving', + 46436: 'ravioli', + 46441: 'ravishing', + 46442: 'reabsorb', + 46443: 'reach', + 46444: 'reacquire', + 46445: 'reaction', + 46446: 'reactive', + 46451: 'reactor', + 46452: 'reaffirm', + 46453: 'ream', + 46454: 'reanalyze', + 46455: 'reappear', + 46456: 'reapply', + 46461: 'reappoint', + 46462: 'reapprove', + 46463: 'rearrange', + 46464: 'rearview', + 46465: 'reason', + 46466: 'reassign', + 46511: 'reassure', + 46512: 'reattach', + 46513: 'reawake', + 46514: 'rebalance', + 46515: 'rebate', + 46516: 'rebel', + 46521: 'rebirth', + 46522: 'reboot', + 46523: 'reborn', + 46524: 'rebound', + 46525: 'rebuff', + 46526: 'rebuild', + 46531: 'rebuilt', + 46532: 'reburial', + 46533: 'rebuttal', + 46534: 'recall', + 46535: 'recant', + 46536: 'recapture', + 46541: 'recast', + 46542: 'recede', + 46543: 'recent', + 46544: 'recess', + 46545: 'recharger', + 46546: 'recipient', + 46551: 'recital', + 46552: 'recite', + 46553: 'reckless', + 46554: 'reclaim', + 46555: 'recliner', + 46556: 'reclining', + 46561: 'recluse', + 46562: 'reclusive', + 46563: 'recognize', + 46564: 'recoil', + 46565: 'recollect', + 46566: 'recolor', + 46611: 'reconcile', + 46612: 'reconfirm', + 46613: 'reconvene', + 46614: 'recopy', + 46615: 'record', + 46616: 'recount', + 46621: 'recoup', + 46622: 'recovery', + 46623: 'recreate', + 46624: 'rectal', + 46625: 'rectangle', + 46626: 'rectified', + 46631: 'rectify', + 46632: 'recycled', + 46633: 'recycler', + 46634: 'recycling', + 46635: 'reemerge', + 46636: 'reenact', + 46641: 'reenter', + 46642: 'reentry', + 46643: 'reexamine', + 46644: 'referable', + 46645: 'referee', + 46646: 'reference', + 46651: 'refill', + 46652: 'refinance', + 46653: 'refined', + 46654: 'refinery', + 46655: 'refining', + 46656: 'refinish', + 46661: 'reflected', + 46662: 'reflector', + 46663: 'reflex', + 46664: 'reflux', + 46665: 'refocus', + 46666: 'refold', + 51111: 'reforest', + 51112: 'reformat', + 51113: 'reformed', + 51114: 'reformer', + 51115: 'reformist', + 51116: 'refract', + 51121: 'refrain', + 51122: 'refreeze', + 51123: 'refresh', + 51124: 'refried', + 51125: 'refueling', + 51126: 'refund', + 51131: 'refurbish', + 51132: 'refurnish', + 51133: 'refusal', + 51134: 'refuse', + 51135: 'refusing', + 51136: 'refutable', + 51141: 'refute', + 51142: 'regain', + 51143: 'regalia', + 51144: 'regally', + 51145: 'reggae', + 51146: 'regime', + 51151: 'region', + 51152: 'register', + 51153: 'registrar', + 51154: 'registry', + 51155: 'regress', + 51156: 'regretful', + 51161: 'regroup', + 51162: 'regular', + 51163: 'regulate', + 51164: 'regulator', + 51165: 'rehab', + 51166: 'reheat', + 51211: 'rehire', + 51212: 'rehydrate', + 51213: 'reimburse', + 51214: 'reissue', + 51215: 'reiterate', + 51216: 'rejoice', + 51221: 'rejoicing', + 51222: 'rejoin', + 51223: 'rekindle', + 51224: 'relapse', + 51225: 'relapsing', + 51226: 'relatable', + 51231: 'related', + 51232: 'relation', + 51233: 'relative', + 51234: 'relax', + 51235: 'relay', + 51236: 'relearn', + 51241: 'release', + 51242: 'relenting', + 51243: 'reliable', + 51244: 'reliably', + 51245: 'reliance', + 51246: 'reliant', + 51251: 'relic', + 51252: 'relieve', + 51253: 'relieving', + 51254: 'relight', + 51255: 'relish', + 51256: 'relive', + 51261: 'reload', + 51262: 'relocate', + 51263: 'relock', + 51264: 'reluctant', + 51265: 'rely', + 51266: 'remake', + 51311: 'remark', + 51312: 'remarry', + 51313: 'rematch', + 51314: 'remedial', + 51315: 'remedy', + 51316: 'remember', + 51321: 'reminder', + 51322: 'remindful', + 51323: 'remission', + 51324: 'remix', + 51325: 'remnant', + 51326: 'remodeler', + 51331: 'remold', + 51332: 'remorse', + 51333: 'remote', + 51334: 'removable', + 51335: 'removal', + 51336: 'removed', + 51341: 'remover', + 51342: 'removing', + 51343: 'rename', + 51344: 'renderer', + 51345: 'rendering', + 51346: 'rendition', + 51351: 'renegade', + 51352: 'renewable', + 51353: 'renewably', + 51354: 'renewal', + 51355: 'renewed', + 51356: 'renounce', + 51361: 'renovate', + 51362: 'renovator', + 51363: 'rentable', + 51364: 'rental', + 51365: 'rented', + 51366: 'renter', + 51411: 'reoccupy', + 51412: 'reoccur', + 51413: 'reopen', + 51414: 'reorder', + 51415: 'repackage', + 51416: 'repacking', + 51421: 'repaint', + 51422: 'repair', + 51423: 'repave', + 51424: 'repaying', + 51425: 'repayment', + 51426: 'repeal', + 51431: 'repeated', + 51432: 'repeater', + 51433: 'repent', + 51434: 'rephrase', + 51435: 'replace', + 51436: 'replay', + 51441: 'replica', + 51442: 'reply', + 51443: 'reporter', + 51444: 'repose', + 51445: 'repossess', + 51446: 'repost', + 51451: 'repressed', + 51452: 'reprimand', + 51453: 'reprint', + 51454: 'reprise', + 51455: 'reproach', + 51456: 'reprocess', + 51461: 'reproduce', + 51462: 'reprogram', + 51463: 'reps', + 51464: 'reptile', + 51465: 'reptilian', + 51466: 'repugnant', + 51511: 'repulsion', + 51512: 'repulsive', + 51513: 'repurpose', + 51514: 'reputable', + 51515: 'reputably', + 51516: 'request', + 51521: 'require', + 51522: 'requisite', + 51523: 'reroute', + 51524: 'rerun', + 51525: 'resale', + 51526: 'resample', + 51531: 'rescuer', + 51532: 'reseal', + 51533: 'research', + 51534: 'reselect', + 51535: 'reseller', + 51536: 'resemble', + 51541: 'resend', + 51542: 'resent', + 51543: 'reset', + 51544: 'reshape', + 51545: 'reshoot', + 51546: 'reshuffle', + 51551: 'residence', + 51552: 'residency', + 51553: 'resident', + 51554: 'residual', + 51555: 'residue', + 51556: 'resigned', + 51561: 'resilient', + 51562: 'resistant', + 51563: 'resisting', + 51564: 'resize', + 51565: 'resolute', + 51566: 'resolved', + 51611: 'resonant', + 51612: 'resonate', + 51613: 'resort', + 51614: 'resource', + 51615: 'respect', + 51616: 'resubmit', + 51621: 'result', + 51622: 'resume', + 51623: 'resupply', + 51624: 'resurface', + 51625: 'resurrect', + 51626: 'retail', + 51631: 'retainer', + 51632: 'retaining', + 51633: 'retake', + 51634: 'retaliate', + 51635: 'retention', + 51636: 'rethink', + 51641: 'retinal', + 51642: 'retired', + 51643: 'retiree', + 51644: 'retiring', + 51645: 'retold', + 51646: 'retool', + 51651: 'retorted', + 51652: 'retouch', + 51653: 'retrace', + 51654: 'retract', + 51655: 'retrain', + 51656: 'retread', + 51661: 'retreat', + 51662: 'retrial', + 51663: 'retrieval', + 51664: 'retriever', + 51665: 'retry', + 51666: 'return', + 52111: 'retying', + 52112: 'retype', + 52113: 'reunion', + 52114: 'reunite', + 52115: 'reusable', + 52116: 'reuse', + 52121: 'reveal', + 52122: 'reveler', + 52123: 'revenge', + 52124: 'revenue', + 52125: 'reverb', + 52126: 'revered', + 52131: 'reverence', + 52132: 'reverend', + 52133: 'reversal', + 52134: 'reverse', + 52135: 'reversing', + 52136: 'reversion', + 52141: 'revert', + 52142: 'revisable', + 52143: 'revise', + 52144: 'revision', + 52145: 'revisit', + 52146: 'revivable', + 52151: 'revival', + 52152: 'reviver', + 52153: 'reviving', + 52154: 'revocable', + 52155: 'revoke', + 52156: 'revolt', + 52161: 'revolver', + 52162: 'revolving', + 52163: 'reward', + 52164: 'rewash', + 52165: 'rewind', + 52166: 'rewire', + 52211: 'reword', + 52212: 'rework', + 52213: 'rewrap', + 52214: 'rewrite', + 52215: 'rhyme', + 52216: 'ribbon', + 52221: 'ribcage', + 52222: 'rice', + 52223: 'riches', + 52224: 'richly', + 52225: 'richness', + 52226: 'rickety', + 52231: 'ricotta', + 52232: 'riddance', + 52233: 'ridden', + 52234: 'ride', + 52235: 'riding', + 52236: 'rifling', + 52241: 'rift', + 52242: 'rigging', + 52243: 'rigid', + 52244: 'rigor', + 52245: 'rimless', + 52246: 'rimmed', + 52251: 'rind', + 52252: 'rink', + 52253: 'rinse', + 52254: 'rinsing', + 52255: 'riot', + 52256: 'ripcord', + 52261: 'ripeness', + 52262: 'ripening', + 52263: 'ripping', + 52264: 'ripple', + 52265: 'rippling', + 52266: 'riptide', + 52311: 'rise', + 52312: 'rising', + 52313: 'risk', + 52314: 'risotto', + 52315: 'ritalin', + 52316: 'ritzy', + 52321: 'rival', + 52322: 'riverbank', + 52323: 'riverbed', + 52324: 'riverboat', + 52325: 'riverside', + 52326: 'riveter', + 52331: 'riveting', + 52332: 'roamer', + 52333: 'roaming', + 52334: 'roast', + 52335: 'robbing', + 52336: 'robe', + 52341: 'robin', + 52342: 'robotics', + 52343: 'robust', + 52344: 'rockband', + 52345: 'rocker', + 52346: 'rocket', + 52351: 'rockfish', + 52352: 'rockiness', + 52353: 'rocking', + 52354: 'rocklike', + 52355: 'rockslide', + 52356: 'rockstar', + 52361: 'rocky', + 52362: 'rogue', + 52363: 'roman', + 52364: 'romp', + 52365: 'rope', + 52366: 'roping', + 52411: 'roster', + 52412: 'rosy', + 52413: 'rotten', + 52414: 'rotting', + 52415: 'rotunda', + 52416: 'roulette', + 52421: 'rounding', + 52422: 'roundish', + 52423: 'roundness', + 52424: 'roundup', + 52425: 'roundworm', + 52426: 'routine', + 52431: 'routing', + 52432: 'rover', + 52433: 'roving', + 52434: 'royal', + 52435: 'rubbed', + 52436: 'rubber', + 52441: 'rubbing', + 52442: 'rubble', + 52443: 'rubdown', + 52444: 'ruby', + 52445: 'ruckus', + 52446: 'rudder', + 52451: 'rug', + 52452: 'ruined', + 52453: 'rule', + 52454: 'rumble', + 52455: 'rumbling', + 52456: 'rummage', + 52461: 'rumor', + 52462: 'runaround', + 52463: 'rundown', + 52464: 'runner', + 52465: 'running', + 52466: 'runny', + 52511: 'runt', + 52512: 'runway', + 52513: 'rupture', + 52514: 'rural', + 52515: 'ruse', + 52516: 'rush', + 52521: 'rust', + 52522: 'rut', + 52523: 'sabbath', + 52524: 'sabotage', + 52525: 'sacrament', + 52526: 'sacred', + 52531: 'sacrifice', + 52532: 'sadden', + 52533: 'saddlebag', + 52534: 'saddled', + 52535: 'saddling', + 52536: 'sadly', + 52541: 'sadness', + 52542: 'safari', + 52543: 'safeguard', + 52544: 'safehouse', + 52545: 'safely', + 52546: 'safeness', + 52551: 'saffron', + 52552: 'saga', + 52553: 'sage', + 52554: 'sagging', + 52555: 'saggy', + 52556: 'said', + 52561: 'saint', + 52562: 'sake', + 52563: 'salad', + 52564: 'salami', + 52565: 'salaried', + 52566: 'salary', + 52611: 'saline', + 52612: 'salon', + 52613: 'saloon', + 52614: 'salsa', + 52615: 'salt', + 52616: 'salutary', + 52621: 'salute', + 52622: 'salvage', + 52623: 'salvaging', + 52624: 'salvation', + 52625: 'same', + 52626: 'sample', + 52631: 'sampling', + 52632: 'sanction', + 52633: 'sanctity', + 52634: 'sanctuary', + 52635: 'sandal', + 52636: 'sandbag', + 52641: 'sandbank', + 52642: 'sandbar', + 52643: 'sandblast', + 52644: 'sandbox', + 52645: 'sanded', + 52646: 'sandfish', + 52651: 'sanding', + 52652: 'sandlot', + 52653: 'sandpaper', + 52654: 'sandpit', + 52655: 'sandstone', + 52656: 'sandstorm', + 52661: 'sandworm', + 52662: 'sandy', + 52663: 'sanitary', + 52664: 'sanitizer', + 52665: 'sank', + 52666: 'santa', + 53111: 'sapling', + 53112: 'sappiness', + 53113: 'sappy', + 53114: 'sarcasm', + 53115: 'sarcastic', + 53116: 'sardine', + 53121: 'sash', + 53122: 'sasquatch', + 53123: 'sassy', + 53124: 'satchel', + 53125: 'satiable', + 53126: 'satin', + 53131: 'satirical', + 53132: 'satisfied', + 53133: 'satisfy', + 53134: 'saturate', + 53135: 'saturday', + 53136: 'sauciness', + 53141: 'saucy', + 53142: 'sauna', + 53143: 'savage', + 53144: 'savanna', + 53145: 'saved', + 53146: 'savings', + 53151: 'savior', + 53152: 'savor', + 53153: 'saxophone', + 53154: 'say', + 53155: 'scabbed', + 53156: 'scabby', + 53161: 'scalded', + 53162: 'scalding', + 53163: 'scale', + 53164: 'scaling', + 53165: 'scallion', + 53166: 'scallop', + 53211: 'scalping', + 53212: 'scam', + 53213: 'scandal', + 53214: 'scanner', + 53215: 'scanning', + 53216: 'scant', + 53221: 'scapegoat', + 53222: 'scarce', + 53223: 'scarcity', + 53224: 'scarecrow', + 53225: 'scared', + 53226: 'scarf', + 53231: 'scarily', + 53232: 'scariness', + 53233: 'scarring', + 53234: 'scary', + 53235: 'scavenger', + 53236: 'scenic', + 53241: 'schedule', + 53242: 'schematic', + 53243: 'scheme', + 53244: 'scheming', + 53245: 'schilling', + 53246: 'schnapps', + 53251: 'scholar', + 53252: 'science', + 53253: 'scientist', + 53254: 'scion', + 53255: 'scoff', + 53256: 'scolding', + 53261: 'scone', + 53262: 'scoop', + 53263: 'scooter', + 53264: 'scope', + 53265: 'scorch', + 53266: 'scorebook', + 53311: 'scorecard', + 53312: 'scored', + 53313: 'scoreless', + 53314: 'scorer', + 53315: 'scoring', + 53316: 'scorn', + 53321: 'scorpion', + 53322: 'scotch', + 53323: 'scoundrel', + 53324: 'scoured', + 53325: 'scouring', + 53326: 'scouting', + 53331: 'scouts', + 53332: 'scowling', + 53333: 'scrabble', + 53334: 'scraggly', + 53335: 'scrambled', + 53336: 'scrambler', + 53341: 'scrap', + 53342: 'scratch', + 53343: 'scrawny', + 53344: 'screen', + 53345: 'scribble', + 53346: 'scribe', + 53351: 'scribing', + 53352: 'scrimmage', + 53353: 'script', + 53354: 'scroll', + 53355: 'scrooge', + 53356: 'scrounger', + 53361: 'scrubbed', + 53362: 'scrubber', + 53363: 'scruffy', + 53364: 'scrunch', + 53365: 'scrutiny', + 53366: 'scuba', + 53411: 'scuff', + 53412: 'sculptor', + 53413: 'sculpture', + 53414: 'scurvy', + 53415: 'scuttle', + 53416: 'secluded', + 53421: 'secluding', + 53422: 'seclusion', + 53423: 'second', + 53424: 'secrecy', + 53425: 'secret', + 53426: 'sectional', + 53431: 'sector', + 53432: 'secular', + 53433: 'securely', + 53434: 'security', + 53435: 'sedan', + 53436: 'sedate', + 53441: 'sedation', + 53442: 'sedative', + 53443: 'sediment', + 53444: 'seduce', + 53445: 'seducing', + 53446: 'segment', + 53451: 'seismic', + 53452: 'seizing', + 53453: 'seldom', + 53454: 'selected', + 53455: 'selection', + 53456: 'selective', + 53461: 'selector', + 53462: 'self', + 53463: 'seltzer', + 53464: 'semantic', + 53465: 'semester', + 53466: 'semicolon', + 53511: 'semifinal', + 53512: 'seminar', + 53513: 'semisoft', + 53514: 'semisweet', + 53515: 'senate', + 53516: 'senator', + 53521: 'send', + 53522: 'senior', + 53523: 'senorita', + 53524: 'sensation', + 53525: 'sensitive', + 53526: 'sensitize', + 53531: 'sensually', + 53532: 'sensuous', + 53533: 'sepia', + 53534: 'september', + 53535: 'septic', + 53536: 'septum', + 53541: 'sequel', + 53542: 'sequence', + 53543: 'sequester', + 53544: 'series', + 53545: 'sermon', + 53546: 'serotonin', + 53551: 'serpent', + 53552: 'serrated', + 53553: 'serve', + 53554: 'service', + 53555: 'serving', + 53556: 'sesame', + 53561: 'sessions', + 53562: 'setback', + 53563: 'setting', + 53564: 'settle', + 53565: 'settling', + 53566: 'setup', + 53611: 'sevenfold', + 53612: 'seventeen', + 53613: 'seventh', + 53614: 'seventy', + 53615: 'severity', + 53616: 'shabby', + 53621: 'shack', + 53622: 'shaded', + 53623: 'shadily', + 53624: 'shadiness', + 53625: 'shading', + 53626: 'shadow', + 53631: 'shady', + 53632: 'shaft', + 53633: 'shakable', + 53634: 'shakily', + 53635: 'shakiness', + 53636: 'shaking', + 53641: 'shaky', + 53642: 'shale', + 53643: 'shallot', + 53644: 'shallow', + 53645: 'shame', + 53646: 'shampoo', + 53651: 'shamrock', + 53652: 'shank', + 53653: 'shanty', + 53654: 'shape', + 53655: 'shaping', + 53656: 'share', + 53661: 'sharpener', + 53662: 'sharper', + 53663: 'sharpie', + 53664: 'sharply', + 53665: 'sharpness', + 53666: 'shawl', + 54111: 'sheath', + 54112: 'shed', + 54113: 'sheep', + 54114: 'sheet', + 54115: 'shelf', + 54116: 'shell', + 54121: 'shelter', + 54122: 'shelve', + 54123: 'shelving', + 54124: 'sherry', + 54125: 'shield', + 54126: 'shifter', + 54131: 'shifting', + 54132: 'shiftless', + 54133: 'shifty', + 54134: 'shimmer', + 54135: 'shimmy', + 54136: 'shindig', + 54141: 'shine', + 54142: 'shingle', + 54143: 'shininess', + 54144: 'shining', + 54145: 'shiny', + 54146: 'ship', + 54151: 'shirt', + 54152: 'shivering', + 54153: 'shock', + 54154: 'shone', + 54155: 'shoplift', + 54156: 'shopper', + 54161: 'shopping', + 54162: 'shoptalk', + 54163: 'shore', + 54164: 'shortage', + 54165: 'shortcake', + 54166: 'shortcut', + 54211: 'shorten', + 54212: 'shorter', + 54213: 'shorthand', + 54214: 'shortlist', + 54215: 'shortly', + 54216: 'shortness', + 54221: 'shorts', + 54222: 'shortwave', + 54223: 'shorty', + 54224: 'shout', + 54225: 'shove', + 54226: 'showbiz', + 54231: 'showcase', + 54232: 'showdown', + 54233: 'shower', + 54234: 'showgirl', + 54235: 'showing', + 54236: 'showman', + 54241: 'shown', + 54242: 'showoff', + 54243: 'showpiece', + 54244: 'showplace', + 54245: 'showroom', + 54246: 'showy', + 54251: 'shrank', + 54252: 'shrapnel', + 54253: 'shredder', + 54254: 'shredding', + 54255: 'shrewdly', + 54256: 'shriek', + 54261: 'shrill', + 54262: 'shrimp', + 54263: 'shrine', + 54264: 'shrink', + 54265: 'shrivel', + 54266: 'shrouded', + 54311: 'shrubbery', + 54312: 'shrubs', + 54313: 'shrug', + 54314: 'shrunk', + 54315: 'shucking', + 54316: 'shudder', + 54321: 'shuffle', + 54322: 'shuffling', + 54323: 'shun', + 54324: 'shush', + 54325: 'shut', + 54326: 'shy', + 54331: 'siamese', + 54332: 'siberian', + 54333: 'sibling', + 54334: 'siding', + 54335: 'sierra', + 54336: 'siesta', + 54341: 'sift', + 54342: 'sighing', + 54343: 'silenced', + 54344: 'silencer', + 54345: 'silent', + 54346: 'silica', + 54351: 'silicon', + 54352: 'silk', + 54353: 'silliness', + 54354: 'silly', + 54355: 'silo', + 54356: 'silt', + 54361: 'silver', + 54362: 'similarly', + 54363: 'simile', + 54364: 'simmering', + 54365: 'simple', + 54366: 'simplify', + 54411: 'simply', + 54412: 'sincere', + 54413: 'sincerity', + 54414: 'singer', + 54415: 'singing', + 54416: 'single', + 54421: 'singular', + 54422: 'sinister', + 54423: 'sinless', + 54424: 'sinner', + 54425: 'sinuous', + 54426: 'sip', + 54431: 'siren', + 54432: 'sister', + 54433: 'sitcom', + 54434: 'sitter', + 54435: 'sitting', + 54436: 'situated', + 54441: 'situation', + 54442: 'sixfold', + 54443: 'sixteen', + 54444: 'sixth', + 54445: 'sixties', + 54446: 'sixtieth', + 54451: 'sixtyfold', + 54452: 'sizable', + 54453: 'sizably', + 54454: 'size', + 54455: 'sizing', + 54456: 'sizzle', + 54461: 'sizzling', + 54462: 'skater', + 54463: 'skating', + 54464: 'skedaddle', + 54465: 'skeletal', + 54466: 'skeleton', + 54511: 'skeptic', + 54512: 'sketch', + 54513: 'skewed', + 54514: 'skewer', + 54515: 'skid', + 54516: 'skied', + 54521: 'skier', + 54522: 'skies', + 54523: 'skiing', + 54524: 'skilled', + 54525: 'skillet', + 54526: 'skillful', + 54531: 'skimmed', + 54532: 'skimmer', + 54533: 'skimming', + 54534: 'skimpily', + 54535: 'skincare', + 54536: 'skinhead', + 54541: 'skinless', + 54542: 'skinning', + 54543: 'skinny', + 54544: 'skintight', + 54545: 'skipper', + 54546: 'skipping', + 54551: 'skirmish', + 54552: 'skirt', + 54553: 'skittle', + 54554: 'skydiver', + 54555: 'skylight', + 54556: 'skyline', + 54561: 'skype', + 54562: 'skyrocket', + 54563: 'skyward', + 54564: 'slab', + 54565: 'slacked', + 54566: 'slacker', + 54611: 'slacking', + 54612: 'slackness', + 54613: 'slacks', + 54614: 'slain', + 54615: 'slam', + 54616: 'slander', + 54621: 'slang', + 54622: 'slapping', + 54623: 'slapstick', + 54624: 'slashed', + 54625: 'slashing', + 54626: 'slate', + 54631: 'slather', + 54632: 'slaw', + 54633: 'sled', + 54634: 'sleek', + 54635: 'sleep', + 54636: 'sleet', + 54641: 'sleeve', + 54642: 'slept', + 54643: 'sliceable', + 54644: 'sliced', + 54645: 'slicer', + 54646: 'slicing', + 54651: 'slick', + 54652: 'slider', + 54653: 'slideshow', + 54654: 'sliding', + 54655: 'slighted', + 54656: 'slighting', + 54661: 'slightly', + 54662: 'slimness', + 54663: 'slimy', + 54664: 'slinging', + 54665: 'slingshot', + 54666: 'slinky', + 55111: 'slip', + 55112: 'slit', + 55113: 'sliver', + 55114: 'slobbery', + 55115: 'slogan', + 55116: 'sloped', + 55121: 'sloping', + 55122: 'sloppily', + 55123: 'sloppy', + 55124: 'slot', + 55125: 'slouching', + 55126: 'slouchy', + 55131: 'sludge', + 55132: 'slug', + 55133: 'slum', + 55134: 'slurp', + 55135: 'slush', + 55136: 'sly', + 55141: 'small', + 55142: 'smartly', + 55143: 'smartness', + 55144: 'smasher', + 55145: 'smashing', + 55146: 'smashup', + 55151: 'smell', + 55152: 'smelting', + 55153: 'smile', + 55154: 'smilingly', + 55155: 'smirk', + 55156: 'smite', + 55161: 'smith', + 55162: 'smitten', + 55163: 'smock', + 55164: 'smog', + 55165: 'smoked', + 55166: 'smokeless', + 55211: 'smokiness', + 55212: 'smoking', + 55213: 'smoky', + 55214: 'smolder', + 55215: 'smooth', + 55216: 'smother', + 55221: 'smudge', + 55222: 'smudgy', + 55223: 'smuggler', + 55224: 'smuggling', + 55225: 'smugly', + 55226: 'smugness', + 55231: 'snack', + 55232: 'snagged', + 55233: 'snaking', + 55234: 'snap', + 55235: 'snare', + 55236: 'snarl', + 55241: 'snazzy', + 55242: 'sneak', + 55243: 'sneer', + 55244: 'sneeze', + 55245: 'sneezing', + 55246: 'snide', + 55251: 'sniff', + 55252: 'snippet', + 55253: 'snipping', + 55254: 'snitch', + 55255: 'snooper', + 55256: 'snooze', + 55261: 'snore', + 55262: 'snoring', + 55263: 'snorkel', + 55264: 'snort', + 55265: 'snout', + 55266: 'snowbird', + 55311: 'snowboard', + 55312: 'snowbound', + 55313: 'snowcap', + 55314: 'snowdrift', + 55315: 'snowdrop', + 55316: 'snowfall', + 55321: 'snowfield', + 55322: 'snowflake', + 55323: 'snowiness', + 55324: 'snowless', + 55325: 'snowman', + 55326: 'snowplow', + 55331: 'snowshoe', + 55332: 'snowstorm', + 55333: 'snowsuit', + 55334: 'snowy', + 55335: 'snub', + 55336: 'snuff', + 55341: 'snuggle', + 55342: 'snugly', + 55343: 'snugness', + 55344: 'speak', + 55345: 'spearfish', + 55346: 'spearhead', + 55351: 'spearman', + 55352: 'spearmint', + 55353: 'species', + 55354: 'specimen', + 55355: 'specked', + 55356: 'speckled', + 55361: 'specks', + 55362: 'spectacle', + 55363: 'spectator', + 55364: 'spectrum', + 55365: 'speculate', + 55366: 'speech', + 55411: 'speed', + 55412: 'spellbind', + 55413: 'speller', + 55414: 'spelling', + 55415: 'spendable', + 55416: 'spender', + 55421: 'spending', + 55422: 'spent', + 55423: 'spew', + 55424: 'sphere', + 55425: 'spherical', + 55426: 'sphinx', + 55431: 'spider', + 55432: 'spied', + 55433: 'spiffy', + 55434: 'spill', + 55435: 'spilt', + 55436: 'spinach', + 55441: 'spinal', + 55442: 'spindle', + 55443: 'spinner', + 55444: 'spinning', + 55445: 'spinout', + 55446: 'spinster', + 55451: 'spiny', + 55452: 'spiral', + 55453: 'spirited', + 55454: 'spiritism', + 55455: 'spirits', + 55456: 'spiritual', + 55461: 'splashed', + 55462: 'splashing', + 55463: 'splashy', + 55464: 'splatter', + 55465: 'spleen', + 55466: 'splendid', + 55511: 'splendor', + 55512: 'splice', + 55513: 'splicing', + 55514: 'splinter', + 55515: 'splotchy', + 55516: 'splurge', + 55521: 'spoilage', + 55522: 'spoiled', + 55523: 'spoiler', + 55524: 'spoiling', + 55525: 'spoils', + 55526: 'spoken', + 55531: 'spokesman', + 55532: 'sponge', + 55533: 'spongy', + 55534: 'sponsor', + 55535: 'spoof', + 55536: 'spookily', + 55541: 'spooky', + 55542: 'spool', + 55543: 'spoon', + 55544: 'spore', + 55545: 'sporting', + 55546: 'sports', + 55551: 'sporty', + 55552: 'spotless', + 55553: 'spotlight', + 55554: 'spotted', + 55555: 'spotter', + 55556: 'spotting', + 55561: 'spotty', + 55562: 'spousal', + 55563: 'spouse', + 55564: 'spout', + 55565: 'sprain', + 55566: 'sprang', + 55611: 'sprawl', + 55612: 'spray', + 55613: 'spree', + 55614: 'sprig', + 55615: 'spring', + 55616: 'sprinkled', + 55621: 'sprinkler', + 55622: 'sprint', + 55623: 'sprite', + 55624: 'sprout', + 55625: 'spruce', + 55626: 'sprung', + 55631: 'spry', + 55632: 'spud', + 55633: 'spur', + 55634: 'sputter', + 55635: 'spyglass', + 55636: 'squabble', + 55641: 'squad', + 55642: 'squall', + 55643: 'squander', + 55644: 'squash', + 55645: 'squatted', + 55646: 'squatter', + 55651: 'squatting', + 55652: 'squeak', + 55653: 'squealer', + 55654: 'squealing', + 55655: 'squeamish', + 55656: 'squeegee', + 55661: 'squeeze', + 55662: 'squeezing', + 55663: 'squid', + 55664: 'squiggle', + 55665: 'squiggly', + 55666: 'squint', + 56111: 'squire', + 56112: 'squirt', + 56113: 'squishier', + 56114: 'squishy', + 56115: 'stability', + 56116: 'stabilize', + 56121: 'stable', + 56122: 'stack', + 56123: 'stadium', + 56124: 'staff', + 56125: 'stage', + 56126: 'staging', + 56131: 'stagnant', + 56132: 'stagnate', + 56133: 'stainable', + 56134: 'stained', + 56135: 'staining', + 56136: 'stainless', + 56141: 'stalemate', + 56142: 'staleness', + 56143: 'stalling', + 56144: 'stallion', + 56145: 'stamina', + 56146: 'stammer', + 56151: 'stamp', + 56152: 'stand', + 56153: 'stank', + 56154: 'staple', + 56155: 'stapling', + 56156: 'starboard', + 56161: 'starch', + 56162: 'stardom', + 56163: 'stardust', + 56164: 'starfish', + 56165: 'stargazer', + 56166: 'staring', + 56211: 'stark', + 56212: 'starless', + 56213: 'starlet', + 56214: 'starlight', + 56215: 'starlit', + 56216: 'starring', + 56221: 'starry', + 56222: 'starship', + 56223: 'starter', + 56224: 'starting', + 56225: 'startle', + 56226: 'startling', + 56231: 'startup', + 56232: 'starved', + 56233: 'starving', + 56234: 'stash', + 56235: 'state', + 56236: 'static', + 56241: 'statistic', + 56242: 'statue', + 56243: 'stature', + 56244: 'status', + 56245: 'statute', + 56246: 'statutory', + 56251: 'staunch', + 56252: 'stays', + 56253: 'steadfast', + 56254: 'steadier', + 56255: 'steadily', + 56256: 'steadying', + 56261: 'steam', + 56262: 'steed', + 56263: 'steep', + 56264: 'steerable', + 56265: 'steering', + 56266: 'steersman', + 56311: 'stegosaur', + 56312: 'stellar', + 56313: 'stem', + 56314: 'stench', + 56315: 'stencil', + 56316: 'step', + 56321: 'stereo', + 56322: 'sterile', + 56323: 'sterility', + 56324: 'sterilize', + 56325: 'sterling', + 56326: 'sternness', + 56331: 'sternum', + 56332: 'stew', + 56333: 'stick', + 56334: 'stiffen', + 56335: 'stiffly', + 56336: 'stiffness', + 56341: 'stifle', + 56342: 'stifling', + 56343: 'stillness', + 56344: 'stilt', + 56345: 'stimulant', + 56346: 'stimulate', + 56351: 'stimuli', + 56352: 'stimulus', + 56353: 'stinger', + 56354: 'stingily', + 56355: 'stinging', + 56356: 'stingray', + 56361: 'stingy', + 56362: 'stinking', + 56363: 'stinky', + 56364: 'stipend', + 56365: 'stipulate', + 56366: 'stir', + 56411: 'stitch', + 56412: 'stock', + 56413: 'stoic', + 56414: 'stoke', + 56415: 'stole', + 56416: 'stomp', + 56421: 'stonewall', + 56422: 'stoneware', + 56423: 'stonework', + 56424: 'stoning', + 56425: 'stony', + 56426: 'stood', + 56431: 'stooge', + 56432: 'stool', + 56433: 'stoop', + 56434: 'stoplight', + 56435: 'stoppable', + 56436: 'stoppage', + 56441: 'stopped', + 56442: 'stopper', + 56443: 'stopping', + 56444: 'stopwatch', + 56445: 'storable', + 56446: 'storage', + 56451: 'storeroom', + 56452: 'storewide', + 56453: 'storm', + 56454: 'stout', + 56455: 'stove', + 56456: 'stowaway', + 56461: 'stowing', + 56462: 'straddle', + 56463: 'straggler', + 56464: 'strained', + 56465: 'strainer', + 56466: 'straining', + 56511: 'strangely', + 56512: 'stranger', + 56513: 'strangle', + 56514: 'strategic', + 56515: 'strategy', + 56516: 'stratus', + 56521: 'straw', + 56522: 'stray', + 56523: 'streak', + 56524: 'stream', + 56525: 'street', + 56526: 'strength', + 56531: 'strenuous', + 56532: 'strep', + 56533: 'stress', + 56534: 'stretch', + 56535: 'strewn', + 56536: 'stricken', + 56541: 'strict', + 56542: 'stride', + 56543: 'strife', + 56544: 'strike', + 56545: 'striking', + 56546: 'strive', + 56551: 'striving', + 56552: 'strobe', + 56553: 'strode', + 56554: 'stroller', + 56555: 'strongbox', + 56556: 'strongly', + 56561: 'strongman', + 56562: 'struck', + 56563: 'structure', + 56564: 'strudel', + 56565: 'struggle', + 56566: 'strum', + 56611: 'strung', + 56612: 'strut', + 56613: 'stubbed', + 56614: 'stubble', + 56615: 'stubbly', + 56616: 'stubborn', + 56621: 'stucco', + 56622: 'stuck', + 56623: 'student', + 56624: 'studied', + 56625: 'studio', + 56626: 'study', + 56631: 'stuffed', + 56632: 'stuffing', + 56633: 'stuffy', + 56634: 'stumble', + 56635: 'stumbling', + 56636: 'stump', + 56641: 'stung', + 56642: 'stunned', + 56643: 'stunner', + 56644: 'stunning', + 56645: 'stunt', + 56646: 'stupor', + 56651: 'sturdily', + 56652: 'sturdy', + 56653: 'styling', + 56654: 'stylishly', + 56655: 'stylist', + 56656: 'stylized', + 56661: 'stylus', + 56662: 'suave', + 56663: 'subarctic', + 56664: 'subatomic', + 56665: 'subdivide', + 56666: 'subdued', + 61111: 'subduing', + 61112: 'subfloor', + 61113: 'subgroup', + 61114: 'subheader', + 61115: 'subject', + 61116: 'sublease', + 61121: 'sublet', + 61122: 'sublevel', + 61123: 'sublime', + 61124: 'submarine', + 61125: 'submerge', + 61126: 'submersed', + 61131: 'submitter', + 61132: 'subpanel', + 61133: 'subpar', + 61134: 'subplot', + 61135: 'subprime', + 61136: 'subscribe', + 61141: 'subscript', + 61142: 'subsector', + 61143: 'subside', + 61144: 'subsiding', + 61145: 'subsidize', + 61146: 'subsidy', + 61151: 'subsoil', + 61152: 'subsonic', + 61153: 'substance', + 61154: 'subsystem', + 61155: 'subtext', + 61156: 'subtitle', + 61161: 'subtly', + 61162: 'subtotal', + 61163: 'subtract', + 61164: 'subtype', + 61165: 'suburb', + 61166: 'subway', + 61211: 'subwoofer', + 61212: 'subzero', + 61213: 'succulent', + 61214: 'such', + 61215: 'suction', + 61216: 'sudden', + 61221: 'sudoku', + 61222: 'suds', + 61223: 'sufferer', + 61224: 'suffering', + 61225: 'suffice', + 61226: 'suffix', + 61231: 'suffocate', + 61232: 'suffrage', + 61233: 'sugar', + 61234: 'suggest', + 61235: 'suing', + 61236: 'suitable', + 61241: 'suitably', + 61242: 'suitcase', + 61243: 'suitor', + 61244: 'sulfate', + 61245: 'sulfide', + 61246: 'sulfite', + 61251: 'sulfur', + 61252: 'sulk', + 61253: 'sullen', + 61254: 'sulphate', + 61255: 'sulphuric', + 61256: 'sultry', + 61261: 'superbowl', + 61262: 'superglue', + 61263: 'superhero', + 61264: 'superior', + 61265: 'superjet', + 61266: 'superman', + 61311: 'supermom', + 61312: 'supernova', + 61313: 'supervise', + 61314: 'supper', + 61315: 'supplier', + 61316: 'supply', + 61321: 'support', + 61322: 'supremacy', + 61323: 'supreme', + 61324: 'surcharge', + 61325: 'surely', + 61326: 'sureness', + 61331: 'surface', + 61332: 'surfacing', + 61333: 'surfboard', + 61334: 'surfer', + 61335: 'surgery', + 61336: 'surgical', + 61341: 'surging', + 61342: 'surname', + 61343: 'surpass', + 61344: 'surplus', + 61345: 'surprise', + 61346: 'surreal', + 61351: 'surrender', + 61352: 'surrogate', + 61353: 'surround', + 61354: 'survey', + 61355: 'survival', + 61356: 'survive', + 61361: 'surviving', + 61362: 'survivor', + 61363: 'sushi', + 61364: 'suspect', + 61365: 'suspend', + 61366: 'suspense', + 61411: 'sustained', + 61412: 'sustainer', + 61413: 'swab', + 61414: 'swaddling', + 61415: 'swagger', + 61416: 'swampland', + 61421: 'swan', + 61422: 'swapping', + 61423: 'swarm', + 61424: 'sway', + 61425: 'swear', + 61426: 'sweat', + 61431: 'sweep', + 61432: 'swell', + 61433: 'swept', + 61434: 'swerve', + 61435: 'swifter', + 61436: 'swiftly', + 61441: 'swiftness', + 61442: 'swimmable', + 61443: 'swimmer', + 61444: 'swimming', + 61445: 'swimsuit', + 61446: 'swimwear', + 61451: 'swinger', + 61452: 'swinging', + 61453: 'swipe', + 61454: 'swirl', + 61455: 'switch', + 61456: 'swivel', + 61461: 'swizzle', + 61462: 'swooned', + 61463: 'swoop', + 61464: 'swoosh', + 61465: 'swore', + 61466: 'sworn', + 61511: 'swung', + 61512: 'sycamore', + 61513: 'sympathy', + 61514: 'symphonic', + 61515: 'symphony', + 61516: 'symptom', + 61521: 'synapse', + 61522: 'syndrome', + 61523: 'synergy', + 61524: 'synopses', + 61525: 'synopsis', + 61526: 'synthesis', + 61531: 'synthetic', + 61532: 'syrup', + 61533: 'system', + 61534: 't-shirt', + 61535: 'tabasco', + 61536: 'tabby', + 61541: 'tableful', + 61542: 'tables', + 61543: 'tablet', + 61544: 'tableware', + 61545: 'tabloid', + 61546: 'tackiness', + 61551: 'tacking', + 61552: 'tackle', + 61553: 'tackling', + 61554: 'tacky', + 61555: 'taco', + 61556: 'tactful', + 61561: 'tactical', + 61562: 'tactics', + 61563: 'tactile', + 61564: 'tactless', + 61565: 'tadpole', + 61566: 'taekwondo', + 61611: 'tag', + 61612: 'tainted', + 61613: 'take', + 61614: 'taking', + 61615: 'talcum', + 61616: 'talisman', + 61621: 'tall', + 61622: 'talon', + 61623: 'tamale', + 61624: 'tameness', + 61625: 'tamer', + 61626: 'tamper', + 61631: 'tank', + 61632: 'tanned', + 61633: 'tannery', + 61634: 'tanning', + 61635: 'tantrum', + 61636: 'tapeless', + 61641: 'tapered', + 61642: 'tapering', + 61643: 'tapestry', + 61644: 'tapioca', + 61645: 'tapping', + 61646: 'taps', + 61651: 'tarantula', + 61652: 'target', + 61653: 'tarmac', + 61654: 'tarnish', + 61655: 'tarot', + 61656: 'tartar', + 61661: 'tartly', + 61662: 'tartness', + 61663: 'task', + 61664: 'tassel', + 61665: 'taste', + 61666: 'tastiness', + 62111: 'tasting', + 62112: 'tasty', + 62113: 'tattered', + 62114: 'tattle', + 62115: 'tattling', + 62116: 'tattoo', + 62121: 'taunt', + 62122: 'tavern', + 62123: 'thank', + 62124: 'that', + 62125: 'thaw', + 62126: 'theater', + 62131: 'theatrics', + 62132: 'thee', + 62133: 'theft', + 62134: 'theme', + 62135: 'theology', + 62136: 'theorize', + 62141: 'thermal', + 62142: 'thermos', + 62143: 'thesaurus', + 62144: 'these', + 62145: 'thesis', + 62146: 'thespian', + 62151: 'thicken', + 62152: 'thicket', + 62153: 'thickness', + 62154: 'thieving', + 62155: 'thievish', + 62156: 'thigh', + 62161: 'thimble', + 62162: 'thing', + 62163: 'think', + 62164: 'thinly', + 62165: 'thinner', + 62166: 'thinness', + 62211: 'thinning', + 62212: 'thirstily', + 62213: 'thirsting', + 62214: 'thirsty', + 62215: 'thirteen', + 62216: 'thirty', + 62221: 'thong', + 62222: 'thorn', + 62223: 'those', + 62224: 'thousand', + 62225: 'thrash', + 62226: 'thread', + 62231: 'threaten', + 62232: 'threefold', + 62233: 'thrift', + 62234: 'thrill', + 62235: 'thrive', + 62236: 'thriving', + 62241: 'throat', + 62242: 'throbbing', + 62243: 'throng', + 62244: 'throttle', + 62245: 'throwaway', + 62246: 'throwback', + 62251: 'thrower', + 62252: 'throwing', + 62253: 'thud', + 62254: 'thumb', + 62255: 'thumping', + 62256: 'thursday', + 62261: 'thus', + 62262: 'thwarting', + 62263: 'thyself', + 62264: 'tiara', + 62265: 'tibia', + 62266: 'tidal', + 62311: 'tidbit', + 62312: 'tidiness', + 62313: 'tidings', + 62314: 'tidy', + 62315: 'tiger', + 62316: 'tighten', + 62321: 'tightly', + 62322: 'tightness', + 62323: 'tightrope', + 62324: 'tightwad', + 62325: 'tigress', + 62326: 'tile', + 62331: 'tiling', + 62332: 'till', + 62333: 'tilt', + 62334: 'timid', + 62335: 'timing', + 62336: 'timothy', + 62341: 'tinderbox', + 62342: 'tinfoil', + 62343: 'tingle', + 62344: 'tingling', + 62345: 'tingly', + 62346: 'tinker', + 62351: 'tinkling', + 62352: 'tinsel', + 62353: 'tinsmith', + 62354: 'tint', + 62355: 'tinwork', + 62356: 'tiny', + 62361: 'tipoff', + 62362: 'tipped', + 62363: 'tipper', + 62364: 'tipping', + 62365: 'tiptoeing', + 62366: 'tiptop', + 62411: 'tiring', + 62412: 'tissue', + 62413: 'trace', + 62414: 'tracing', + 62415: 'track', + 62416: 'traction', + 62421: 'tractor', + 62422: 'trade', + 62423: 'trading', + 62424: 'tradition', + 62425: 'traffic', + 62426: 'tragedy', + 62431: 'trailing', + 62432: 'trailside', + 62433: 'train', + 62434: 'traitor', + 62435: 'trance', + 62436: 'tranquil', + 62441: 'transfer', + 62442: 'transform', + 62443: 'translate', + 62444: 'transpire', + 62445: 'transport', + 62446: 'transpose', + 62451: 'trapdoor', + 62452: 'trapeze', + 62453: 'trapezoid', + 62454: 'trapped', + 62455: 'trapper', + 62456: 'trapping', + 62461: 'traps', + 62462: 'trash', + 62463: 'travel', + 62464: 'traverse', + 62465: 'travesty', + 62466: 'tray', + 62511: 'treachery', + 62512: 'treading', + 62513: 'treadmill', + 62514: 'treason', + 62515: 'treat', + 62516: 'treble', + 62521: 'tree', + 62522: 'trekker', + 62523: 'tremble', + 62524: 'trembling', + 62525: 'tremor', + 62526: 'trench', + 62531: 'trend', + 62532: 'trespass', + 62533: 'triage', + 62534: 'trial', + 62535: 'triangle', + 62536: 'tribesman', + 62541: 'tribunal', + 62542: 'tribune', + 62543: 'tributary', + 62544: 'tribute', + 62545: 'triceps', + 62546: 'trickery', + 62551: 'trickily', + 62552: 'tricking', + 62553: 'trickle', + 62554: 'trickster', + 62555: 'tricky', + 62556: 'tricolor', + 62561: 'tricycle', + 62562: 'trident', + 62563: 'tried', + 62564: 'trifle', + 62565: 'trifocals', + 62566: 'trillion', + 62611: 'trilogy', + 62612: 'trimester', + 62613: 'trimmer', + 62614: 'trimming', + 62615: 'trimness', + 62616: 'trinity', + 62621: 'trio', + 62622: 'tripod', + 62623: 'tripping', + 62624: 'triumph', + 62625: 'trivial', + 62626: 'trodden', + 62631: 'trolling', + 62632: 'trombone', + 62633: 'trophy', + 62634: 'tropical', + 62635: 'tropics', + 62636: 'trouble', + 62641: 'troubling', + 62642: 'trough', + 62643: 'trousers', + 62644: 'trout', + 62645: 'trowel', + 62646: 'truce', + 62651: 'truck', + 62652: 'truffle', + 62653: 'trump', + 62654: 'trunks', + 62655: 'trustable', + 62656: 'trustee', + 62661: 'trustful', + 62662: 'trusting', + 62663: 'trustless', + 62664: 'truth', + 62665: 'try', + 62666: 'tubby', + 63111: 'tubeless', + 63112: 'tubular', + 63113: 'tucking', + 63114: 'tuesday', + 63115: 'tug', + 63116: 'tuition', + 63121: 'tulip', + 63122: 'tumble', + 63123: 'tumbling', + 63124: 'tummy', + 63125: 'turban', + 63126: 'turbine', + 63131: 'turbofan', + 63132: 'turbojet', + 63133: 'turbulent', + 63134: 'turf', + 63135: 'turkey', + 63136: 'turmoil', + 63141: 'turret', + 63142: 'turtle', + 63143: 'tusk', + 63144: 'tutor', + 63145: 'tutu', + 63146: 'tux', + 63151: 'tweak', + 63152: 'tweed', + 63153: 'tweet', + 63154: 'tweezers', + 63155: 'twelve', + 63156: 'twentieth', + 63161: 'twenty', + 63162: 'twerp', + 63163: 'twice', + 63164: 'twiddle', + 63165: 'twiddling', + 63166: 'twig', + 63211: 'twilight', + 63212: 'twine', + 63213: 'twins', + 63214: 'twirl', + 63215: 'twistable', + 63216: 'twisted', + 63221: 'twister', + 63222: 'twisting', + 63223: 'twisty', + 63224: 'twitch', + 63225: 'twitter', + 63226: 'tycoon', + 63231: 'tying', + 63232: 'tyke', + 63233: 'udder', + 63234: 'ultimate', + 63235: 'ultimatum', + 63236: 'ultra', + 63241: 'umbilical', + 63242: 'umbrella', + 63243: 'umpire', + 63244: 'unabashed', + 63245: 'unable', + 63246: 'unadorned', + 63251: 'unadvised', + 63252: 'unafraid', + 63253: 'unaired', + 63254: 'unaligned', + 63255: 'unaltered', + 63256: 'unarmored', + 63261: 'unashamed', + 63262: 'unaudited', + 63263: 'unawake', + 63264: 'unaware', + 63265: 'unbaked', + 63266: 'unbalance', + 63311: 'unbeaten', + 63312: 'unbend', + 63313: 'unbent', + 63314: 'unbiased', + 63315: 'unbitten', + 63316: 'unblended', + 63321: 'unblessed', + 63322: 'unblock', + 63323: 'unbolted', + 63324: 'unbounded', + 63325: 'unboxed', + 63326: 'unbraided', + 63331: 'unbridle', + 63332: 'unbroken', + 63333: 'unbuckled', + 63334: 'unbundle', + 63335: 'unburned', + 63336: 'unbutton', + 63341: 'uncanny', + 63342: 'uncapped', + 63343: 'uncaring', + 63344: 'uncertain', + 63345: 'unchain', + 63346: 'unchanged', + 63351: 'uncharted', + 63352: 'uncheck', + 63353: 'uncivil', + 63354: 'unclad', + 63355: 'unclaimed', + 63356: 'unclamped', + 63361: 'unclasp', + 63362: 'uncle', + 63363: 'unclip', + 63364: 'uncloak', + 63365: 'unclog', + 63366: 'unclothed', + 63411: 'uncoated', + 63412: 'uncoiled', + 63413: 'uncolored', + 63414: 'uncombed', + 63415: 'uncommon', + 63416: 'uncooked', + 63421: 'uncork', + 63422: 'uncorrupt', + 63423: 'uncounted', + 63424: 'uncouple', + 63425: 'uncouth', + 63426: 'uncover', + 63431: 'uncross', + 63432: 'uncrown', + 63433: 'uncrushed', + 63434: 'uncured', + 63435: 'uncurious', + 63436: 'uncurled', + 63441: 'uncut', + 63442: 'undamaged', + 63443: 'undated', + 63444: 'undaunted', + 63445: 'undead', + 63446: 'undecided', + 63451: 'undefined', + 63452: 'underage', + 63453: 'underarm', + 63454: 'undercoat', + 63455: 'undercook', + 63456: 'undercut', + 63461: 'underdog', + 63462: 'underdone', + 63463: 'underfed', + 63464: 'underfeed', + 63465: 'underfoot', + 63466: 'undergo', + 63511: 'undergrad', + 63512: 'underhand', + 63513: 'underline', + 63514: 'underling', + 63515: 'undermine', + 63516: 'undermost', + 63521: 'underpaid', + 63522: 'underpass', + 63523: 'underpay', + 63524: 'underrate', + 63525: 'undertake', + 63526: 'undertone', + 63531: 'undertook', + 63532: 'undertow', + 63533: 'underuse', + 63534: 'underwear', + 63535: 'underwent', + 63536: 'underwire', + 63541: 'undesired', + 63542: 'undiluted', + 63543: 'undivided', + 63544: 'undocked', + 63545: 'undoing', + 63546: 'undone', + 63551: 'undrafted', + 63552: 'undress', + 63553: 'undrilled', + 63554: 'undusted', + 63555: 'undying', + 63556: 'unearned', + 63561: 'unearth', + 63562: 'unease', + 63563: 'uneasily', + 63564: 'uneasy', + 63565: 'uneatable', + 63566: 'uneaten', + 63611: 'unedited', + 63612: 'unelected', + 63613: 'unending', + 63614: 'unengaged', + 63615: 'unenvied', + 63616: 'unequal', + 63621: 'unethical', + 63622: 'uneven', + 63623: 'unexpired', + 63624: 'unexposed', + 63625: 'unfailing', + 63626: 'unfair', + 63631: 'unfasten', + 63632: 'unfazed', + 63633: 'unfeeling', + 63634: 'unfiled', + 63635: 'unfilled', + 63636: 'unfitted', + 63641: 'unfitting', + 63642: 'unfixable', + 63643: 'unfixed', + 63644: 'unflawed', + 63645: 'unfocused', + 63646: 'unfold', + 63651: 'unfounded', + 63652: 'unframed', + 63653: 'unfreeze', + 63654: 'unfrosted', + 63655: 'unfrozen', + 63656: 'unfunded', + 63661: 'unglazed', + 63662: 'ungloved', + 63663: 'unglue', + 63664: 'ungodly', + 63665: 'ungraded', + 63666: 'ungreased', + 64111: 'unguarded', + 64112: 'unguided', + 64113: 'unhappily', + 64114: 'unhappy', + 64115: 'unharmed', + 64116: 'unhealthy', + 64121: 'unheard', + 64122: 'unhearing', + 64123: 'unheated', + 64124: 'unhelpful', + 64125: 'unhidden', + 64126: 'unhinge', + 64131: 'unhitched', + 64132: 'unholy', + 64133: 'unhook', + 64134: 'unicorn', + 64135: 'unicycle', + 64136: 'unified', + 64141: 'unifier', + 64142: 'uniformed', + 64143: 'uniformly', + 64144: 'unify', + 64145: 'unimpeded', + 64146: 'uninjured', + 64151: 'uninstall', + 64152: 'uninsured', + 64153: 'uninvited', + 64154: 'union', + 64155: 'uniquely', + 64156: 'unisexual', + 64161: 'unison', + 64162: 'unissued', + 64163: 'unit', + 64164: 'universal', + 64165: 'universe', + 64166: 'unjustly', + 64211: 'unkempt', + 64212: 'unkind', + 64213: 'unknotted', + 64214: 'unknowing', + 64215: 'unknown', + 64216: 'unlaced', + 64221: 'unlatch', + 64222: 'unlawful', + 64223: 'unleaded', + 64224: 'unlearned', + 64225: 'unleash', + 64226: 'unless', + 64231: 'unleveled', + 64232: 'unlighted', + 64233: 'unlikable', + 64234: 'unlimited', + 64235: 'unlined', + 64236: 'unlinked', + 64241: 'unlisted', + 64242: 'unlit', + 64243: 'unlivable', + 64244: 'unloaded', + 64245: 'unloader', + 64246: 'unlocked', + 64251: 'unlocking', + 64252: 'unlovable', + 64253: 'unloved', + 64254: 'unlovely', + 64255: 'unloving', + 64256: 'unluckily', + 64261: 'unlucky', + 64262: 'unmade', + 64263: 'unmanaged', + 64264: 'unmanned', + 64265: 'unmapped', + 64266: 'unmarked', + 64311: 'unmasked', + 64312: 'unmasking', + 64313: 'unmatched', + 64314: 'unmindful', + 64315: 'unmixable', + 64316: 'unmixed', + 64321: 'unmolded', + 64322: 'unmoral', + 64323: 'unmovable', + 64324: 'unmoved', + 64325: 'unmoving', + 64326: 'unnamable', + 64331: 'unnamed', + 64332: 'unnatural', + 64333: 'unneeded', + 64334: 'unnerve', + 64335: 'unnerving', + 64336: 'unnoticed', + 64341: 'unopened', + 64342: 'unopposed', + 64343: 'unpack', + 64344: 'unpadded', + 64345: 'unpaid', + 64346: 'unpainted', + 64351: 'unpaired', + 64352: 'unpaved', + 64353: 'unpeeled', + 64354: 'unpicked', + 64355: 'unpiloted', + 64356: 'unpinned', + 64361: 'unplanned', + 64362: 'unplanted', + 64363: 'unpleased', + 64364: 'unpledged', + 64365: 'unplowed', + 64366: 'unplug', + 64411: 'unpopular', + 64412: 'unproven', + 64413: 'unquote', + 64414: 'unranked', + 64415: 'unrated', + 64416: 'unraveled', + 64421: 'unreached', + 64422: 'unread', + 64423: 'unreal', + 64424: 'unreeling', + 64425: 'unrefined', + 64426: 'unrelated', + 64431: 'unrented', + 64432: 'unrest', + 64433: 'unretired', + 64434: 'unrevised', + 64435: 'unrigged', + 64436: 'unripe', + 64441: 'unrivaled', + 64442: 'unroasted', + 64443: 'unrobed', + 64444: 'unroll', + 64445: 'unruffled', + 64446: 'unruly', + 64451: 'unrushed', + 64452: 'unsaddle', + 64453: 'unsafe', + 64454: 'unsaid', + 64455: 'unsalted', + 64456: 'unsaved', + 64461: 'unsavory', + 64462: 'unscathed', + 64463: 'unscented', + 64464: 'unscrew', + 64465: 'unsealed', + 64466: 'unseated', + 64511: 'unsecured', + 64512: 'unseeing', + 64513: 'unseemly', + 64514: 'unseen', + 64515: 'unselect', + 64516: 'unselfish', + 64521: 'unsent', + 64522: 'unsettled', + 64523: 'unshackle', + 64524: 'unshaken', + 64525: 'unshaved', + 64526: 'unshaven', + 64531: 'unsheathe', + 64532: 'unshipped', + 64533: 'unsightly', + 64534: 'unsigned', + 64535: 'unskilled', + 64536: 'unsliced', + 64541: 'unsmooth', + 64542: 'unsnap', + 64543: 'unsocial', + 64544: 'unsoiled', + 64545: 'unsold', + 64546: 'unsolved', + 64551: 'unsorted', + 64552: 'unspoiled', + 64553: 'unspoken', + 64554: 'unstable', + 64555: 'unstaffed', + 64556: 'unstamped', + 64561: 'unsteady', + 64562: 'unsterile', + 64563: 'unstirred', + 64564: 'unstitch', + 64565: 'unstopped', + 64566: 'unstuck', + 64611: 'unstuffed', + 64612: 'unstylish', + 64613: 'unsubtle', + 64614: 'unsubtly', + 64615: 'unsuited', + 64616: 'unsure', + 64621: 'unsworn', + 64622: 'untagged', + 64623: 'untainted', + 64624: 'untaken', + 64625: 'untamed', + 64626: 'untangled', + 64631: 'untapped', + 64632: 'untaxed', + 64633: 'unthawed', + 64634: 'unthread', + 64635: 'untidy', + 64636: 'untie', + 64641: 'until', + 64642: 'untimed', + 64643: 'untimely', + 64644: 'untitled', + 64645: 'untoasted', + 64646: 'untold', + 64651: 'untouched', + 64652: 'untracked', + 64653: 'untrained', + 64654: 'untreated', + 64655: 'untried', + 64656: 'untrimmed', + 64661: 'untrue', + 64662: 'untruth', + 64663: 'unturned', + 64664: 'untwist', + 64665: 'untying', + 64666: 'unusable', + 65111: 'unused', + 65112: 'unusual', + 65113: 'unvalued', + 65114: 'unvaried', + 65115: 'unvarying', + 65116: 'unveiled', + 65121: 'unveiling', + 65122: 'unvented', + 65123: 'unviable', + 65124: 'unvisited', + 65125: 'unvocal', + 65126: 'unwanted', + 65131: 'unwarlike', + 65132: 'unwary', + 65133: 'unwashed', + 65134: 'unwatched', + 65135: 'unweave', + 65136: 'unwed', + 65141: 'unwelcome', + 65142: 'unwell', + 65143: 'unwieldy', + 65144: 'unwilling', + 65145: 'unwind', + 65146: 'unwired', + 65151: 'unwitting', + 65152: 'unwomanly', + 65153: 'unworldly', + 65154: 'unworn', + 65155: 'unworried', + 65156: 'unworthy', + 65161: 'unwound', + 65162: 'unwoven', + 65163: 'unwrapped', + 65164: 'unwritten', + 65165: 'unzip', + 65166: 'upbeat', + 65211: 'upchuck', + 65212: 'upcoming', + 65213: 'upcountry', + 65214: 'update', + 65215: 'upfront', + 65216: 'upgrade', + 65221: 'upheaval', + 65222: 'upheld', + 65223: 'uphill', + 65224: 'uphold', + 65225: 'uplifted', + 65226: 'uplifting', + 65231: 'upload', + 65232: 'upon', + 65233: 'upper', + 65234: 'upright', + 65235: 'uprising', + 65236: 'upriver', + 65241: 'uproar', + 65242: 'uproot', + 65243: 'upscale', + 65244: 'upside', + 65245: 'upstage', + 65246: 'upstairs', + 65251: 'upstart', + 65252: 'upstate', + 65253: 'upstream', + 65254: 'upstroke', + 65255: 'upswing', + 65256: 'uptake', + 65261: 'uptight', + 65262: 'uptown', + 65263: 'upturned', + 65264: 'upward', + 65265: 'upwind', + 65266: 'uranium', + 65311: 'urban', + 65312: 'urchin', + 65313: 'urethane', + 65314: 'urgency', + 65315: 'urgent', + 65316: 'urging', + 65321: 'urologist', + 65322: 'urology', + 65323: 'usable', + 65324: 'usage', + 65325: 'useable', + 65326: 'used', + 65331: 'uselessly', + 65332: 'user', + 65333: 'usher', + 65334: 'usual', + 65335: 'utensil', + 65336: 'utility', + 65341: 'utilize', + 65342: 'utmost', + 65343: 'utopia', + 65344: 'utter', + 65345: 'vacancy', + 65346: 'vacant', + 65351: 'vacate', + 65352: 'vacation', + 65353: 'vagabond', + 65354: 'vagrancy', + 65355: 'vagrantly', + 65356: 'vaguely', + 65361: 'vagueness', + 65362: 'valiant', + 65363: 'valid', + 65364: 'valium', + 65365: 'valley', + 65366: 'valuables', + 65411: 'value', + 65412: 'vanilla', + 65413: 'vanish', + 65414: 'vanity', + 65415: 'vanquish', + 65416: 'vantage', + 65421: 'vaporizer', + 65422: 'variable', + 65423: 'variably', + 65424: 'varied', + 65425: 'variety', + 65426: 'various', + 65431: 'varmint', + 65432: 'varnish', + 65433: 'varsity', + 65434: 'varying', + 65435: 'vascular', + 65436: 'vaseline', + 65441: 'vastly', + 65442: 'vastness', + 65443: 'veal', + 65444: 'vegan', + 65445: 'veggie', + 65446: 'vehicular', + 65451: 'velcro', + 65452: 'velocity', + 65453: 'velvet', + 65454: 'vendetta', + 65455: 'vending', + 65456: 'vendor', + 65461: 'veneering', + 65462: 'vengeful', + 65463: 'venomous', + 65464: 'ventricle', + 65465: 'venture', + 65466: 'venue', + 65511: 'venus', + 65512: 'verbalize', + 65513: 'verbally', + 65514: 'verbose', + 65515: 'verdict', + 65516: 'verify', + 65521: 'verse', + 65522: 'version', + 65523: 'versus', + 65524: 'vertebrae', + 65525: 'vertical', + 65526: 'vertigo', + 65531: 'very', + 65532: 'vessel', + 65533: 'vest', + 65534: 'veteran', + 65535: 'veto', + 65536: 'vexingly', + 65541: 'viability', + 65542: 'viable', + 65543: 'vibes', + 65544: 'vice', + 65545: 'vicinity', + 65546: 'victory', + 65551: 'video', + 65552: 'viewable', + 65553: 'viewer', + 65554: 'viewing', + 65555: 'viewless', + 65556: 'viewpoint', + 65561: 'vigorous', + 65562: 'village', + 65563: 'villain', + 65564: 'vindicate', + 65565: 'vineyard', + 65566: 'vintage', + 65611: 'violate', + 65612: 'violation', + 65613: 'violator', + 65614: 'violet', + 65615: 'violin', + 65616: 'viper', + 65621: 'viral', + 65622: 'virtual', + 65623: 'virtuous', + 65624: 'virus', + 65625: 'visa', + 65626: 'viscosity', + 65631: 'viscous', + 65632: 'viselike', + 65633: 'visible', + 65634: 'visibly', + 65635: 'vision', + 65636: 'visiting', + 65641: 'visitor', + 65642: 'visor', + 65643: 'vista', + 65644: 'vitality', + 65645: 'vitalize', + 65646: 'vitally', + 65651: 'vitamins', + 65652: 'vivacious', + 65653: 'vividly', + 65654: 'vividness', + 65655: 'vixen', + 65656: 'vocalist', + 65661: 'vocalize', + 65662: 'vocally', + 65663: 'vocation', + 65664: 'voice', + 65665: 'voicing', + 65666: 'void', + 66111: 'volatile', + 66112: 'volley', + 66113: 'voltage', + 66114: 'volumes', + 66115: 'voter', + 66116: 'voting', + 66121: 'voucher', + 66122: 'vowed', + 66123: 'vowel', + 66124: 'voyage', + 66125: 'wackiness', + 66126: 'wad', + 66131: 'wafer', + 66132: 'waffle', + 66133: 'waged', + 66134: 'wager', + 66135: 'wages', + 66136: 'waggle', + 66141: 'wagon', + 66142: 'wake', + 66143: 'waking', + 66144: 'walk', + 66145: 'walmart', + 66146: 'walnut', + 66151: 'walrus', + 66152: 'waltz', + 66153: 'wand', + 66154: 'wannabe', + 66155: 'wanted', + 66156: 'wanting', + 66161: 'wasabi', + 66162: 'washable', + 66163: 'washbasin', + 66164: 'washboard', + 66165: 'washbowl', + 66166: 'washcloth', + 66211: 'washday', + 66212: 'washed', + 66213: 'washer', + 66214: 'washhouse', + 66215: 'washing', + 66216: 'washout', + 66221: 'washroom', + 66222: 'washstand', + 66223: 'washtub', + 66224: 'wasp', + 66225: 'wasting', + 66226: 'watch', + 66231: 'water', + 66232: 'waviness', + 66233: 'waving', + 66234: 'wavy', + 66235: 'whacking', + 66236: 'whacky', + 66241: 'wham', + 66242: 'wharf', + 66243: 'wheat', + 66244: 'whenever', + 66245: 'whiff', + 66246: 'whimsical', + 66251: 'whinny', + 66252: 'whiny', + 66253: 'whisking', + 66254: 'whoever', + 66255: 'whole', + 66256: 'whomever', + 66261: 'whoopee', + 66262: 'whooping', + 66263: 'whoops', + 66264: 'why', + 66265: 'wick', + 66266: 'widely', + 66311: 'widen', + 66312: 'widget', + 66313: 'widow', + 66314: 'width', + 66315: 'wieldable', + 66316: 'wielder', + 66321: 'wife', + 66322: 'wifi', + 66323: 'wikipedia', + 66324: 'wildcard', + 66325: 'wildcat', + 66326: 'wilder', + 66331: 'wildfire', + 66332: 'wildfowl', + 66333: 'wildland', + 66334: 'wildlife', + 66335: 'wildly', + 66336: 'wildness', + 66341: 'willed', + 66342: 'willfully', + 66343: 'willing', + 66344: 'willow', + 66345: 'willpower', + 66346: 'wilt', + 66351: 'wimp', + 66352: 'wince', + 66353: 'wincing', + 66354: 'wind', + 66355: 'wing', + 66356: 'winking', + 66361: 'winner', + 66362: 'winnings', + 66363: 'winter', + 66364: 'wipe', + 66365: 'wired', + 66366: 'wireless', + 66411: 'wiring', + 66412: 'wiry', + 66413: 'wisdom', + 66414: 'wise', + 66415: 'wish', + 66416: 'wisplike', + 66421: 'wispy', + 66422: 'wistful', + 66423: 'wizard', + 66424: 'wobble', + 66425: 'wobbling', + 66426: 'wobbly', + 66431: 'wok', + 66432: 'wolf', + 66433: 'wolverine', + 66434: 'womanhood', + 66435: 'womankind', + 66436: 'womanless', + 66441: 'womanlike', + 66442: 'womanly', + 66443: 'womb', + 66444: 'woof', + 66445: 'wooing', + 66446: 'wool', + 66451: 'woozy', + 66452: 'word', + 66453: 'work', + 66454: 'worried', + 66455: 'worrier', + 66456: 'worrisome', + 66461: 'worry', + 66462: 'worsening', + 66463: 'worshiper', + 66464: 'worst', + 66465: 'wound', + 66466: 'woven', + 66511: 'wow', + 66512: 'wrangle', + 66513: 'wrath', + 66514: 'wreath', + 66515: 'wreckage', + 66516: 'wrecker', + 66521: 'wrecking', + 66522: 'wrench', + 66523: 'wriggle', + 66524: 'wriggly', + 66525: 'wrinkle', + 66526: 'wrinkly', + 66531: 'wrist', + 66532: 'writing', + 66533: 'written', + 66534: 'wrongdoer', + 66535: 'wronged', + 66536: 'wrongful', + 66541: 'wrongly', + 66542: 'wrongness', + 66543: 'wrought', + 66544: 'xbox', + 66545: 'xerox', + 66546: 'yahoo', + 66551: 'yam', + 66552: 'yanking', + 66553: 'yapping', + 66554: 'yard', + 66555: 'yarn', + 66556: 'yeah', + 66561: 'yearbook', + 66562: 'yearling', + 66563: 'yearly', + 66564: 'yearning', + 66565: 'yeast', + 66566: 'yelling', + 66611: 'yelp', + 66612: 'yen', + 66613: 'yesterday', + 66614: 'yiddish', + 66615: 'yield', + 66616: 'yin', + 66621: 'yippee', + 66622: 'yo-yo', + 66623: 'yodel', + 66624: 'yoga', + 66625: 'yogurt', + 66626: 'yonder', + 66631: 'yoyo', + 66632: 'yummy', + 66633: 'zap', + 66634: 'zealous', + 66635: 'zebra', + 66636: 'zen', + 66641: 'zeppelin', + 66642: 'zero', + 66643: 'zestfully', + 66644: 'zesty', + 66645: 'zigzagged', + 66646: 'zipfile', + 66651: 'zipping', + 66652: 'zippy', + 66653: 'zips', + 66654: 'zit', + 66655: 'zodiac', + 66656: 'zombie', + 66661: 'zone', + 66662: 'zoning', + 66663: 'zookeeper', + 66664: 'zoologist', + 66665: 'zoology', + 66666: 'zoom', +}; + +export default wordsList; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..0cc9cdd69a15c9639b66f9b08d4a107b34e7c799 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +// prettier-ignore +{ + "extends": "@tsconfig/react-native/tsconfig.json", /* Recommended React Native TSConfig base */ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Completeness */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000000000000000000000000000000000000..59f0c64535d7c5fb6174ea263ef7df6c7634b25f --- /dev/null +++ b/yarn.lock @@ -0,0 +1,9041 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@ant-design/icons-react-native@^2.3.1": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@ant-design/icons-react-native/-/icons-react-native-2.3.2.tgz#86e412d1ce8d629534a5d9f45cd3d8f7ca6dae56" + integrity sha512-ULCN3+elfAsvu71Xa5KODi97Y3P2aUkJm4s8mJaPoRjiU+BR+Y6ejv3vbc40yV62EOdlAOMKhvKbFlsXMjZ2ow== + +"@ant-design/react-native@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@ant-design/react-native/-/react-native-5.0.2.tgz#7d18079347263508251dabc44204ebc44c8c3bd4" + integrity sha512-TkELOuj8owLzUCsQVOy53hPJrpOdK/FRloN7fdrrQELqUoFXX0RP2QjZSpWDTOuIGNwZO22gPnGIKYYfwA7SuA== + dependencies: + "@ant-design/icons-react-native" "^2.3.1" + "@bang88/react-native-ultimate-listview" "^4.1.0" + "@types/shallowequal" "^1.1.1" + array-tree-filter "~2.1.0" + babel-runtime "^6.x" + classnames "^2.2.1" + normalize-css-color "^1.0.2" + rc-util "^4.21.1" + react-native-codegen "^0.0.7" + react-native-collapsible "^1.6.0" + react-native-modal-popover "^2.0.1" + shallowequal "^1.1.0" + utility-types "^3.10.0" + +"@aries-framework/core@0.2.5", "@aries-framework/core@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@aries-framework/core/-/core-0.2.5.tgz#085b69519c275e742418545a96534f12283de4de" + integrity sha512-UQ5DFSpLrm2TlkFVl8Bufy55RoY+AeP1rOo8Yu7UfU6sjX2qhbqztdVAMocUnwgQny7e7o9p27bL9RItcgAwGA== + dependencies: + "@multiformats/base-x" "^4.0.1" + "@stablelib/ed25519" "^1.0.2" + "@stablelib/sha256" "^1.0.1" + "@types/indy-sdk" "^1.16.19" + "@types/node-fetch" "^2.5.10" + "@types/ws" "^7.4.6" + abort-controller "^3.0.0" + bn.js "^5.2.0" + borc "^3.0.0" + buffer "^6.0.3" + class-transformer "0.5.1" + class-validator "0.13.1" + did-resolver "^3.1.3" + lru_map "^0.4.1" + luxon "^1.27.0" + make-error "^1.3.6" + object-inspect "^1.10.3" + query-string "^7.0.1" + reflect-metadata "^0.1.13" + rxjs "^7.2.0" + tsyringe "^4.5.0" + uuid "^8.3.2" + varint "^6.0.0" + web-did-resolver "^2.0.8" + +"@aries-framework/react-hooks@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@aries-framework/react-hooks/-/react-hooks-0.2.0.tgz#371dfcbad523527fa88a439331a1f71019cb5767" + integrity sha512-husiwP3hlBCpuaQ6z87r4mRPbC1owGUn/VxmlHUk+iLKkXr6t5Djx1/dwl/OrPp5MBPPU2iGfy8GiT3vGBCUEA== + +"@aries-framework/react-native@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@aries-framework/react-native/-/react-native-0.2.5.tgz#0a3bd6a107e87f3fa18003b2f2e453ad252453b2" + integrity sha512-h97vQmYg2/U6/MKK8Xtg/nXFDXtGPNla08tSc8tJoOuKY+xu4Wp2Hw2frZYsDFMXVKXmQHeJe7BertYW7b2qGA== + dependencies: + "@aries-framework/core" "0.2.5" + "@azure/core-asynciterator-polyfill" "^1.0.0" + events "^3.3.0" + +"@azure/core-asynciterator-polyfill@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz#0dd3849fb8d97f062a39db0e5cadc9ffaf861fec" + integrity sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw== + +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.5.tgz#86f172690b093373a933223b4745deeb6049e733" + integrity sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g== + +"@babel/core@^7.1.0", "@babel/core@^7.1.6", "@babel/core@^7.12.3", "@babel/core@^7.12.9", "@babel/core@^7.13.16", "@babel/core@^7.14.0", "@babel/core@^7.19.6", "@babel/core@^7.7.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.5.tgz#45e2114dc6cd4ab167f81daf7820e8fa1250d113" + integrity sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-module-transforms" "^7.20.2" + "@babel/helpers" "^7.20.5" + "@babel/parser" "^7.20.5" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.1" + semver "^6.3.0" + +"@babel/generator@^7.14.0", "@babel/generator@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.5.tgz#cb25abee3178adf58d6814b68517c62bdbfdda95" + integrity sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA== + dependencies: + "@babel/types" "^7.20.5" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" + integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.18.6" + "@babel/types" "^7.18.9" + +"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" + integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== + dependencies: + "@babel/compat-data" "^7.20.0" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.21.3" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.2": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.5.tgz#327154eedfb12e977baa4ecc72e5806720a85a06" + integrity sha512-3RCdA/EmEaikrhayahwToF0fpweU/8o2p8vhc1c/1kftHOdTKuC65kik/TLc+qfbS8JKw4qqJbne4ovICDhmww== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.19.1" + "@babel/helper-split-export-declaration" "^7.18.6" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz#5ea79b59962a09ec2acf20a963a01ab4d076ccca" + integrity sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + regexpu-core "^5.2.1" + +"@babel/helper-define-polyfill-provider@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" + integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== + dependencies: + "@babel/helper-compilation-targets" "^7.17.7" + "@babel/helper-plugin-utils" "^7.16.7" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== + +"@babel/helper-explode-assignable-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" + integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-member-expression-to-functions@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" + integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== + dependencies: + "@babel/types" "^7.18.9" + +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" + integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.2" + +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== + +"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" + integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-wrap-function" "^7.18.9" + "@babel/types" "^7.18.9" + +"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" + integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/traverse" "^7.19.1" + "@babel/types" "^7.19.0" + +"@babel/helper-simple-access@^7.19.4", "@babel/helper-simple-access@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" + integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== + dependencies: + "@babel/types" "^7.20.2" + +"@babel/helper-skip-transparent-expression-wrappers@^7.18.9": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" + integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== + dependencies: + "@babel/types" "^7.20.0" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== + +"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helper-wrap-function@^7.18.9": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz#75e2d84d499a0ab3b31c33bcfe59d6b8a45f62e3" + integrity sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q== + dependencies: + "@babel/helper-function-name" "^7.19.0" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" + +"@babel/helpers@^7.20.5": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.6.tgz#e64778046b70e04779dfbdf924e7ebb45992c763" + integrity sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.13.16", "@babel/parser@^7.14.0", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.20.5", "@babel/parser@^7.7.0": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.5.tgz#7f3c7335fe417665d929f34ae5dceae4c04015e8" + integrity sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA== + +"@babel/plugin-proposal-async-generator-functions@^7.0.0": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.1.tgz#352f02baa5d69f4e7529bdac39aaa02d41146af9" + integrity sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-remap-async-to-generator" "^7.18.9" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.13.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-export-default-from@^7.0.0": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.18.10.tgz#091f4794dbce4027c03cf4ebc64d3fb96b75c206" + integrity sha512-5H2N3R2aQFxkV4PIBUR/i7PUSwgTZjouJKzI8eKswfIjT0PhvzkPn0t0wIS5zn6maQuvtT0t1oHtMUz61LOuow== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/plugin-syntax-export-default-from" "^7.18.6" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.1.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" + integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-object-rest-spread@^7.0.0": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.2.tgz#a556f59d555f06961df1e572bb5eca864c84022d" + integrity sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ== + dependencies: + "@babel/compat-data" "^7.20.1" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.20.1" + +"@babel/plugin-proposal-optional-catch-binding@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" + integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.0.0", "@babel/plugin-proposal-optional-chaining@^7.1.0", "@babel/plugin-proposal-optional-chaining@^7.13.12": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" + integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.0.0", "@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-dynamic-import@^7.0.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-default-from@^7.0.0", "@babel/plugin-syntax-export-default-from@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.18.6.tgz#8df076711a4818c4ce4f23e61d622b0ba2ff84bc" + integrity sha512-Kr//z3ujSVNx6E9z9ih5xXXMqK07VVTuqPmqGe6Mss/zW5XPeLZeSDZoP9ab/hT4wPKqAgjl2PnhPrcpk8Seew== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.18.6", "@babel/plugin-syntax-flow@^7.2.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.18.6.tgz#774d825256f2379d06139be0c723c4dd444f3ca1" + integrity sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" + integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.0.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.0.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + +"@babel/plugin-transform-arrow-functions@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" + integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-async-to-generator@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" + integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== + dependencies: + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" + +"@babel/plugin-transform-block-scoped-functions@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" + integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-block-scoping@^7.0.0": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.5.tgz#401215f9dc13dc5262940e2e527c9536b3d7f237" + integrity sha512-WvpEIW9Cbj9ApF3yJCjIEEf1EiNJLtXagOrL5LNWEZOo3jv8pmPoYTSNJQvqej8OavVlgOoOPw6/htGZro6IkA== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-classes@^7.0.0": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.2.tgz#c0033cf1916ccf78202d04be4281d161f6709bb2" + integrity sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-replace-supers" "^7.19.1" + "@babel/helper-split-export-declaration" "^7.18.6" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.0.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" + integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-destructuring@^7.0.0": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.2.tgz#c23741cfa44ddd35f5e53896e88c75331b8b2792" + integrity sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-exponentiation-operator@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" + integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-flow-strip-types@^7.0.0", "@babel/plugin-transform-flow-strip-types@^7.18.6": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.19.0.tgz#e9e8606633287488216028719638cbbb2f2dde8f" + integrity sha512-sgeMlNaQVbCSpgLSKP4ZZKfsJVnFnNQlUSk6gPYzR/q7tzCgQF2t8RBKAP6cKJeZdveei7Q7Jm527xepI8lNLg== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-flow" "^7.18.6" + +"@babel/plugin-transform-for-of@^7.0.0": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" + integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-function-name@^7.0.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" + integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== + dependencies: + "@babel/helper-compilation-targets" "^7.18.9" + "@babel/helper-function-name" "^7.18.9" + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-literals@^7.0.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" + integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-member-expression-literals@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" + integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.1.0", "@babel/plugin-transform-modules-commonjs@^7.13.8": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.19.6.tgz#25b32feef24df8038fc1ec56038917eacb0b730c" + integrity sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ== + dependencies: + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-simple-access" "^7.19.4" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.0.0": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz#626298dd62ea51d452c3be58b285d23195ba69a8" + integrity sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.20.5" + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-object-assign@^7.16.7": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.18.6.tgz#7830b4b6f83e1374a5afb9f6111bcfaea872cdd2" + integrity sha512-mQisZ3JfqWh2gVXvfqYCAAyRs6+7oev+myBsTwW5RnPhYXOTuCEw2oe3YgxlXMViXUS53lG8koulI7mJ+8JE+A== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-object-super@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" + integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.1": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.5.tgz#f8f9186c681d10c3de7620c916156d893c8a019e" + integrity sha512-h7plkOmcndIUWXZFLgpbrh2+fXAi47zcUX7IrOQuZdLD0I0KvjJ6cvo3BEcAOsDOcZhVKGJqv07mkSqK0y2isQ== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-property-literals@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" + integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-display-name@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" + integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-jsx-self@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.18.6.tgz#3849401bab7ae8ffa1e3e5687c94a753fc75bda7" + integrity sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-jsx-source@^7.0.0": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.19.6.tgz#88578ae8331e5887e8ce28e4c9dc83fb29da0b86" + integrity sha512-RpAi004QyMNisst/pvSanoRdJ4q+jMCWyk9zdw/CyLB9j8RXEahodR6l2GyttDRyEVWZtbN+TpLiHJ3t34LbsQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + +"@babel/plugin-transform-react-jsx@^7.0.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9" + integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-jsx" "^7.18.6" + "@babel/types" "^7.19.0" + +"@babel/plugin-transform-runtime@^7.0.0": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.6.tgz#9d2a9dbf4e12644d6f46e5e75bfbf02b5d6e9194" + integrity sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw== + dependencies: + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.19.0" + babel-plugin-polyfill-corejs2 "^0.3.3" + babel-plugin-polyfill-corejs3 "^0.6.0" + babel-plugin-polyfill-regenerator "^0.4.1" + semver "^6.3.0" + +"@babel/plugin-transform-shorthand-properties@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" + integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-spread@^7.0.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" + integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + +"@babel/plugin-transform-sticky-regex@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" + integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-template-literals@^7.0.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" + integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-typescript@^7.18.6", "@babel/plugin-transform-typescript@^7.5.0": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.2.tgz#91515527b376fc122ba83b13d70b01af8fe98f3f" + integrity sha512-jvS+ngBfrnTUBfOQq8NfGnSbF9BrqlR6hjJ2yVxMkmO5nL/cdifNbI30EfjRlN4g5wYWNnMPyj5Sa6R1pbLeag== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.20.2" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-typescript" "^7.20.0" + +"@babel/plugin-transform-unicode-regex@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" + integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/preset-flow@^7.0.0", "@babel/preset-flow@^7.13.13": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.18.6.tgz#83f7602ba566e72a9918beefafef8ef16d2810cb" + integrity sha512-E7BDhL64W6OUqpuyHnSroLnqyRTcG6ZdOBl1OKI/QK/HJfplqK/S3sq1Cckx7oTodJ5yOXyfw7rEADJ6UjoQDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-flow-strip-types" "^7.18.6" + +"@babel/preset-typescript@^7.1.0", "@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.16.7": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" + integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-typescript" "^7.18.6" + +"@babel/register@^7.0.0", "@babel/register@^7.13.16": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.18.9.tgz#1888b24bc28d5cc41c412feb015e9ff6b96e439c" + integrity sha512-ZlbnXDcNYHMR25ITwwNKT88JiaukkdVj/nG7r3wnuXkOTHc60Uy05PwMCPre0hSkY68E6zK3xz+vUJSP2jWmcw== + dependencies: + clone-deep "^4.0.1" + find-cache-dir "^2.0.0" + make-dir "^2.1.0" + pirates "^4.0.5" + source-map-support "^0.5.16" + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.5", "@babel/runtime@^7.20.6": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3" + integrity sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA== + dependencies: + regenerator-runtime "^0.13.11" + +"@babel/template@^7.0.0", "@babel/template@^7.18.10", "@babel/template@^7.3.3": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.10" + "@babel/types" "^7.18.10" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.14.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1", "@babel/traverse@^7.20.5", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.4": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.5.tgz#78eb244bea8270fdda1ef9af22a5d5e5b7e57133" + integrity sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.5" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.20.5" + "@babel/types" "^7.20.5" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.7.0": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.5.tgz#e206ae370b5393d94dfd1d04cd687cace53efa84" + integrity sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + +"@bang88/react-native-ultimate-listview@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@bang88/react-native-ultimate-listview/-/react-native-ultimate-listview-4.1.0.tgz#efff14ce5a09e8c52116580cdfa17f253faffde2" + integrity sha512-om2CsUXyr5kPvW1qBL+zGWOLwE7jq+wYCY47eBIRs7GmLqnnhbG2LlTHhnid8NI4q2/DQsEVfu8oWk15Atb7BA== + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@cnakazawa/watch@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" + integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ== + dependencies: + exec-sh "^0.3.2" + minimist "^1.2.0" + +"@egjs/hammerjs@^2.0.17": + version "2.0.17" + resolved "https://registry.yarnpkg.com/@egjs/hammerjs/-/hammerjs-2.0.17.tgz#5dc02af75a6a06e4c2db0202cae38c9263895124" + integrity sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A== + dependencies: + "@types/hammerjs" "^2.0.36" + +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@hapi/hoek@^9.0.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" + integrity sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g== + dependencies: + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^26.6.2" + jest-util "^26.6.2" + slash "^3.0.0" + +"@jest/core@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.6.3.tgz#7639fcb3833d748a4656ada54bde193051e45fad" + integrity sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw== + dependencies: + "@jest/console" "^26.6.2" + "@jest/reporters" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-changed-files "^26.6.2" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-resolve-dependencies "^26.6.3" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + jest-watcher "^26.6.2" + micromatch "^4.0.2" + p-each-series "^2.1.0" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/create-cache-key-function@^27.0.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-27.5.1.tgz#7448fae15602ea95c828f5eceed35c202a820b31" + integrity sha512-dmH1yW+makpTSURTy8VzdUwFnfQh1G8R+DxO2Ho2FFmBbKFEVm+3jWdvFhE2VqB/LATCTokkP0dotjyQyw5/AQ== + dependencies: + "@jest/types" "^27.5.1" + +"@jest/environment@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" + integrity sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA== + dependencies: + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + +"@jest/fake-timers@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.6.2.tgz#459c329bcf70cee4af4d7e3f3e67848123535aad" + integrity sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA== + dependencies: + "@jest/types" "^26.6.2" + "@sinonjs/fake-timers" "^6.0.1" + "@types/node" "*" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" + jest-util "^26.6.2" + +"@jest/globals@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.6.2.tgz#5b613b78a1aa2655ae908eba638cc96a20df720a" + integrity sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/types" "^26.6.2" + expect "^26.6.2" + +"@jest/reporters@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.6.2.tgz#1f518b99637a5f18307bd3ecf9275f6882a667f6" + integrity sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.4" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^4.0.3" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + jest-haste-map "^26.6.2" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^7.0.0" + optionalDependencies: + node-notifier "^8.0.0" + +"@jest/schemas@^29.0.0": + version "29.0.0" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" + integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA== + dependencies: + "@sinclair/typebox" "^0.24.1" + +"@jest/source-map@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" + integrity sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.4" + source-map "^0.6.0" + +"@jest/test-result@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" + integrity sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ== + dependencies: + "@jest/console" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz#98e8a45100863886d074205e8ffdc5a7eb582b17" + integrity sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw== + dependencies: + "@jest/test-result" "^26.6.2" + graceful-fs "^4.2.4" + jest-haste-map "^26.6.2" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" + +"@jest/transform@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" + integrity sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^26.6.2" + babel-plugin-istanbul "^6.0.0" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^26.6.2" + jest-regex-util "^26.0.0" + jest-util "^26.6.2" + micromatch "^4.0.2" + pirates "^4.0.1" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + +"@jest/types@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" + integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@jsamr/counter-style@^2.0.1": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@jsamr/counter-style/-/counter-style-2.0.2.tgz#6f08cfa98e1f0416dc1d7f2d8ac38a8cdb004c5d" + integrity sha512-2mXudGVtSzVxWEA7B9jZLKjoXUeUFYDDtFrQoC0IFX9/Dszz4t1vZOmafi3JSw/FxD+udMQ+4TAFR8Qs0J3URQ== + +"@jsamr/react-native-li@^2.3.0": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@jsamr/react-native-li/-/react-native-li-2.3.1.tgz#12a5b5f6e3971cec77b96bee58104eed0ae9314a" + integrity sha512-Qbo4NEj48SQ4k8FZJHFE2fgZDKTWaUGmVxcIQh3msg5JezLdTMMHuRRDYctfdHI6L0FZGObmEv3haWbIvmol8w== + +"@mapbox/node-pre-gyp@^1.0.0": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c" + integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA== + dependencies: + detect-libc "^2.0.0" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.7" + nopt "^5.0.0" + npmlog "^5.0.1" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.11" + +"@multiformats/base-x@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" + integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw== + +"@native-html/css-processor@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@native-html/css-processor/-/css-processor-1.11.0.tgz#27d02e5123b0849f4986d44060ba3f235a15f552" + integrity sha512-NnhBEbJX5M2gBGltPKOetiLlKhNf3OHdRafc8//e2ZQxXN8JaSW/Hy8cm94pnIckQxwaMKxrtaNT3x4ZcffoNQ== + dependencies: + css-to-react-native "^3.0.0" + csstype "^3.0.8" + +"@native-html/transient-render-engine@11.2.3": + version "11.2.3" + resolved "https://registry.yarnpkg.com/@native-html/transient-render-engine/-/transient-render-engine-11.2.3.tgz#e4de0e7c8c023224a2dc27f3bd2b30d3984d94a4" + integrity sha512-zXwgA3gPUEmFs3I3syfnvDvS6WiUHXEE6jY09OBzK+trq7wkweOSFWIoyXiGkbXrozGYG0KY90YgPyr8Tg8Uyg== + dependencies: + "@native-html/css-processor" "1.11.0" + "@types/ramda" "^0.27.44" + csstype "^3.0.9" + domelementtype "^2.2.0" + domhandler "^4.2.2" + domutils "^2.8.0" + htmlparser2 "^7.1.2" + ramda "^0.27.2" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + +"@react-native-async-storage/async-storage@^1.17.11": + version "1.17.11" + resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.17.11.tgz#7ec329c1b9f610e344602e806b04d7c928a2341d" + integrity sha512-bzs45n5HNcDq6mxXnSsOHysZWn1SbbebNxldBXCQs8dSvF8Aor9KCdpm+TpnnGweK3R6diqsT8lFhX77VX0NFw== + dependencies: + merge-options "^3.0.4" + +"@react-native-clipboard/clipboard@^1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@react-native-clipboard/clipboard/-/clipboard-1.11.1.tgz#d3a9e685ce2383b1e92b89a334896c5575cc103d" + integrity sha512-nvSIIHzybVWqYxcJE5hpT17ekxAAg383Ggzw5WrYHtkKX61N1AwaKSNmXs5xHV7pmKSOe/yWjtSwxIzfW51I5Q== + +"@react-native-community/cli-clean@^9.2.1": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-9.2.1.tgz#198c5dd39c432efb5374582073065ff75d67d018" + integrity sha512-dyNWFrqRe31UEvNO+OFWmQ4hmqA07bR9Ief/6NnGwx67IO9q83D5PEAf/o96ML6jhSbDwCmpPKhPwwBbsyM3mQ== + dependencies: + "@react-native-community/cli-tools" "^9.2.1" + chalk "^4.1.2" + execa "^1.0.0" + prompts "^2.4.0" + +"@react-native-community/cli-config@^9.2.1": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-9.2.1.tgz#54eb026d53621ccf3a9df8b189ac24f6e56b8750" + integrity sha512-gHJlBBXUgDN9vrr3aWkRqnYrPXZLztBDQoY97Mm5Yo6MidsEpYo2JIP6FH4N/N2p1TdjxJL4EFtdd/mBpiR2MQ== + dependencies: + "@react-native-community/cli-tools" "^9.2.1" + cosmiconfig "^5.1.0" + deepmerge "^3.2.0" + glob "^7.1.3" + joi "^17.2.1" + +"@react-native-community/cli-debugger-ui@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-9.0.0.tgz#ea5c5dad6008bccd840d858e160d42bb2ced8793" + integrity sha512-7hH05ZwU9Tp0yS6xJW0bqcZPVt0YCK7gwj7gnRu1jDNN2kughf6Lg0Ys29rAvtZ7VO1PK5c1O+zs7yFnylQDUA== + dependencies: + serve-static "^1.13.1" + +"@react-native-community/cli-doctor@^9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-9.3.0.tgz#8817a3fd564453467def5b5bc8aecdc4205eff50" + integrity sha512-/fiuG2eDGC2/OrXMOWI5ifq4X1gdYTQhvW2m0TT5Lk1LuFiZsbTCp1lR+XILKekuTvmYNjEGdVpeDpdIWlXdEA== + dependencies: + "@react-native-community/cli-config" "^9.2.1" + "@react-native-community/cli-platform-ios" "^9.3.0" + "@react-native-community/cli-tools" "^9.2.1" + chalk "^4.1.2" + command-exists "^1.2.8" + envinfo "^7.7.2" + execa "^1.0.0" + hermes-profile-transformer "^0.0.6" + ip "^1.1.5" + node-stream-zip "^1.9.1" + ora "^5.4.1" + prompts "^2.4.0" + semver "^6.3.0" + strip-ansi "^5.2.0" + sudo-prompt "^9.0.0" + wcwidth "^1.0.1" + +"@react-native-community/cli-hermes@^9.3.1": + version "9.3.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-9.3.1.tgz#569d27c1effd684ba451ad4614e29a99228cec49" + integrity sha512-Mq4PK8m5YqIdaVq5IdRfp4qK09aVO+aiCtd6vjzjNUgk1+1X5cgUqV6L65h4N+TFJYJHcp2AnB+ik1FAYXvYPQ== + dependencies: + "@react-native-community/cli-platform-android" "^9.3.1" + "@react-native-community/cli-tools" "^9.2.1" + chalk "^4.1.2" + hermes-profile-transformer "^0.0.6" + ip "^1.1.5" + +"@react-native-community/cli-platform-android@9.3.1", "@react-native-community/cli-platform-android@^9.3.1": + version "9.3.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-9.3.1.tgz#378cd72249653cc74672094400657139f21bafb8" + integrity sha512-m0bQ6Twewl7OEZoVf79I2GZmsDqh+Gh0bxfxWgwxobsKDxLx8/RNItAo1lVtTCgzuCR75cX4EEO8idIF9jYhew== + dependencies: + "@react-native-community/cli-tools" "^9.2.1" + chalk "^4.1.2" + execa "^1.0.0" + fs-extra "^8.1.0" + glob "^7.1.3" + logkitty "^0.7.1" + slash "^3.0.0" + +"@react-native-community/cli-platform-ios@9.3.0", "@react-native-community/cli-platform-ios@^9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-9.3.0.tgz#45abde2a395fddd7cf71e8b746c1dc1ee2260f9a" + integrity sha512-nihTX53BhF2Q8p4B67oG3RGe1XwggoGBrMb6vXdcu2aN0WeXJOXdBLgR900DAA1O8g7oy1Sudu6we+JsVTKnjw== + dependencies: + "@react-native-community/cli-tools" "^9.2.1" + chalk "^4.1.2" + execa "^1.0.0" + glob "^7.1.3" + ora "^5.4.1" + +"@react-native-community/cli-plugin-metro@^9.2.1": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-9.2.1.tgz#0ec207e78338e0cc0a3cbe1b43059c24afc66158" + integrity sha512-byBGBH6jDfUvcHGFA45W/sDwMlliv7flJ8Ns9foCh3VsIeYYPoDjjK7SawE9cPqRdMAD4SY7EVwqJnOtRbwLiQ== + dependencies: + "@react-native-community/cli-server-api" "^9.2.1" + "@react-native-community/cli-tools" "^9.2.1" + chalk "^4.1.2" + metro "0.72.3" + metro-config "0.72.3" + metro-core "0.72.3" + metro-react-native-babel-transformer "0.72.3" + metro-resolver "0.72.3" + metro-runtime "0.72.3" + readline "^1.3.0" + +"@react-native-community/cli-server-api@^9.2.1": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-9.2.1.tgz#41ac5916b21d324bccef447f75600c03b2f54fbe" + integrity sha512-EI+9MUxEbWBQhWw2PkhejXfkcRqPl+58+whlXJvKHiiUd7oVbewFs0uLW0yZffUutt4FGx6Uh88JWEgwOzAdkw== + dependencies: + "@react-native-community/cli-debugger-ui" "^9.0.0" + "@react-native-community/cli-tools" "^9.2.1" + compression "^1.7.1" + connect "^3.6.5" + errorhandler "^1.5.0" + nocache "^3.0.1" + pretty-format "^26.6.2" + serve-static "^1.13.1" + ws "^7.5.1" + +"@react-native-community/cli-tools@^9.2.1": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-9.2.1.tgz#c332324b1ea99f9efdc3643649bce968aa98191c" + integrity sha512-bHmL/wrKmBphz25eMtoJQgwwmeCylbPxqFJnFSbkqJPXQz3ManQ6q/gVVMqFyz7D3v+riaus/VXz3sEDa97uiQ== + dependencies: + appdirsjs "^1.2.4" + chalk "^4.1.2" + find-up "^5.0.0" + mime "^2.4.1" + node-fetch "^2.6.0" + open "^6.2.0" + ora "^5.4.1" + semver "^6.3.0" + shell-quote "^1.7.3" + +"@react-native-community/cli-types@^9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-9.1.0.tgz#dcd6a0022f62790fe1f67417f4690db938746aab" + integrity sha512-KDybF9XHvafLEILsbiKwz5Iobd+gxRaPyn4zSaAerBxedug4er5VUWa8Szy+2GeYKZzMh/gsb1o9lCToUwdT/g== + dependencies: + joi "^17.2.1" + +"@react-native-community/cli@9.3.2": + version "9.3.2" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-9.3.2.tgz#81761880af00c1894d85380d8c9a358659865204" + integrity sha512-IAW4X0vmX/xozNpp/JVZaX7MrC85KV0OP2DF4o7lNGOfpUhzJAEWqTfkxFYS+VsRjZHDve4wSTiGIuXwE7FG1w== + dependencies: + "@react-native-community/cli-clean" "^9.2.1" + "@react-native-community/cli-config" "^9.2.1" + "@react-native-community/cli-debugger-ui" "^9.0.0" + "@react-native-community/cli-doctor" "^9.3.0" + "@react-native-community/cli-hermes" "^9.3.1" + "@react-native-community/cli-plugin-metro" "^9.2.1" + "@react-native-community/cli-server-api" "^9.2.1" + "@react-native-community/cli-tools" "^9.2.1" + "@react-native-community/cli-types" "^9.1.0" + chalk "^4.1.2" + commander "^9.4.0" + execa "^1.0.0" + find-up "^4.1.0" + fs-extra "^8.1.0" + graceful-fs "^4.1.3" + prompts "^2.4.0" + semver "^6.3.0" + +"@react-native-community/eslint-config@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@react-native-community/eslint-config/-/eslint-config-2.0.0.tgz#35dcc529a274803fc4e0a6b3d6c274551fb91774" + integrity sha512-vHaMMfvMp9BWCQQ0lNIXibOJTcXIbYUQ8dSUsMOsrXgVkeVQJj88OwrKS00rQyqwMaC4/a6HuDiFzYUkGKOpVg== + dependencies: + "@react-native-community/eslint-plugin" "^1.1.0" + "@typescript-eslint/eslint-plugin" "^3.1.0" + "@typescript-eslint/parser" "^3.1.0" + babel-eslint "^10.1.0" + eslint-config-prettier "^6.10.1" + eslint-plugin-eslint-comments "^3.1.2" + eslint-plugin-flowtype "2.50.3" + eslint-plugin-jest "22.4.1" + eslint-plugin-prettier "3.1.2" + eslint-plugin-react "^7.20.0" + eslint-plugin-react-hooks "^4.0.4" + eslint-plugin-react-native "^3.8.1" + prettier "^2.0.2" + +"@react-native-community/eslint-plugin@^1.1.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@react-native-community/eslint-plugin/-/eslint-plugin-1.3.0.tgz#9e558170c106bbafaa1ef502bd8e6d4651012bf9" + integrity sha512-+zDZ20NUnSWghj7Ku5aFphMzuM9JulqCW+aPXT6IfIXFbb8tzYTTOSeRFOtuekJ99ibW2fUCSsjuKNlwDIbHFg== + +"@react-native/assets@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@react-native/assets/-/assets-1.0.0.tgz#c6f9bf63d274bafc8e970628de24986b30a55c8e" + integrity sha512-KrwSpS1tKI70wuKl68DwJZYEvXktDHdZMG0k2AXD/rJVSlB23/X2CB2cutVR0HwNMJIal9HOUOBB2rVfa6UGtQ== + +"@react-native/normalize-color@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@react-native/normalize-color/-/normalize-color-2.0.0.tgz#da955909432474a9a0fe1cbffc66576a0447f567" + integrity sha512-Wip/xsc5lw8vsBlmY2MO/gFLp3MvuZ2baBZjDeTjjndMgM0h5sxz7AZR62RDPGgstp8Np7JzjvVqVT7tpFZqsw== + +"@react-native/polyfills@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@react-native/polyfills/-/polyfills-2.0.0.tgz#4c40b74655c83982c8cf47530ee7dc13d957b6aa" + integrity sha512-K0aGNn1TjalKj+65D7ycc1//H9roAQ51GJVk5ZJQFb2teECGmzd86bYDC0aYdbRf7gtovescq4Zt6FR0tgXiHQ== + +"@react-navigation/bottom-tabs@^6.4.3": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.1.tgz#ef146502674e68736cbb47500ba1e3e481456869" + integrity sha512-XhY3rdfI/lxiG/TfdxvYYKSJR6N6K42VEBBQX8yvGBq+7aeCKaX5D7MF6yiI6ViVZ8uPhGyh/MJM3srUW+Yj7w== + dependencies: + "@react-navigation/elements" "^1.3.11" + color "^4.2.3" + warn-once "^0.1.0" + +"@react-navigation/core@^6.4.5": + version "6.4.5" + resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.5.tgz#8254b25c476857d53a649af8e3fded0cbe6e1ded" + integrity sha512-wcde35HeOM5r2P25EwLQZyJ1yhXDGKuWpnKfsSI1xrgYIvWdYi3j/yGnwgNGDelCmtUt1Fyk2pmOv8sEku9KkA== + dependencies: + "@react-navigation/routers" "^6.1.6" + escape-string-regexp "^4.0.0" + nanoid "^3.1.23" + query-string "^7.1.3" + react-is "^16.13.0" + use-latest-callback "^0.1.5" + +"@react-navigation/elements@^1.3.11": + version "1.3.11" + resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.11.tgz#135c2cb3ae4a31bc835bb731110fd1ef9c38e237" + integrity sha512-o4J0g4ofJbbn68e4TpuGkuZLtq5mLll7Ndz9C4O4RvD2chchLuGQ5TycIPTKP428cz8JzuTCFqUe/ZhOPSsudw== + +"@react-navigation/native@^6.0.16": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.1.tgz#79d91db04fbad277f355a10405516df4f67cd308" + integrity sha512-iIozx9c66EjSFyzKrZPixnk6vBuivYXp0jmbKCJXNIa7MY+8OLx9CXj/+1py/l/OGlXDhI6jiUWWetOfOtMaBQ== + dependencies: + "@react-navigation/core" "^6.4.5" + escape-string-regexp "^4.0.0" + fast-deep-equal "^3.1.3" + nanoid "^3.1.23" + +"@react-navigation/routers@^6.1.6": + version "6.1.6" + resolved "https://registry.yarnpkg.com/@react-navigation/routers/-/routers-6.1.6.tgz#f57f2a73855d329255aa225fdad75ae8e7700c6d" + integrity sha512-Z5DeCW3pUvMafbU9Cjy1qJYC2Bvl8iy3+PfsB0DsAwQ6zZ3WAXW5FTMX4Gb9H+Jg6qHWGbMFFwlYpS3UJ3tlVQ== + dependencies: + nanoid "^3.1.23" + +"@react-navigation/stack@^6.3.7": + version "6.3.9" + resolved "https://registry.yarnpkg.com/@react-navigation/stack/-/stack-6.3.9.tgz#e4e2b6aa25973b3bc59200b7e3bf980e93cb5b4f" + integrity sha512-mTT0ZM/Zvp46s8UnphAspg2MR5Ds0mqZa/bEjzFgaYo+cLfjIXttUZYgsMG2fhvoTHpU7QFcZ/0kVhi4jVlzKQ== + dependencies: + "@react-navigation/elements" "^1.3.11" + color "^4.2.3" + warn-once "^0.1.0" + +"@sideway/address@^4.1.3": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" + integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" + integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + +"@sinclair/typebox@^0.24.1": + version "0.24.51" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" + integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== + +"@sinonjs/commons@^1.7.0": + version "1.8.6" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" + integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" + integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@sovpro/delimited-stream@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@sovpro/delimited-stream/-/delimited-stream-1.1.0.tgz#4334bba7ee241036e580fdd99c019377630d26b4" + integrity sha512-kQpk267uxB19X3X2T1mvNMjyvIEonpNSHrMlK5ZaBU6aZxw7wPbpgKJOjHN3+/GPVpXgAV9soVT2oyHpLkLtyw== + +"@stablelib/binary@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/binary/-/binary-1.0.1.tgz#c5900b94368baf00f811da5bdb1610963dfddf7f" + integrity sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q== + dependencies: + "@stablelib/int" "^1.0.1" + +"@stablelib/ed25519@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@stablelib/ed25519/-/ed25519-1.0.3.tgz#f8fdeb6f77114897c887bb6a3138d659d3f35996" + integrity sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg== + dependencies: + "@stablelib/random" "^1.0.2" + "@stablelib/sha512" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/hash@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/hash/-/hash-1.0.1.tgz#3c944403ff2239fad8ebb9015e33e98444058bc5" + integrity sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg== + +"@stablelib/int@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/int/-/int-1.0.1.tgz#75928cc25d59d73d75ae361f02128588c15fd008" + integrity sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w== + +"@stablelib/random@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@stablelib/random/-/random-1.0.2.tgz#2dece393636489bf7e19c51229dd7900eddf742c" + integrity sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/sha256@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/sha256/-/sha256-1.0.1.tgz#77b6675b67f9b0ea081d2e31bda4866297a3ae4f" + integrity sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/sha512@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/sha512/-/sha512-1.0.1.tgz#6da700c901c2c0ceacbd3ae122a38ac57c72145f" + integrity sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw== + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/wipe@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36" + integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg== + +"@svgr/babel-plugin-add-jsx-attribute@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz#74a5d648bd0347bda99d82409d87b8ca80b9a1ba" + integrity sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ== + +"@svgr/babel-plugin-remove-jsx-attribute@*": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.5.0.tgz#652bfd4ed0a0699843585cda96faeb09d6e1306e" + integrity sha512-8zYdkym7qNyfXpWvu4yq46k41pyNM9SOstoWhKlm+IfdCE1DdnRKeMUPsWIEO/DEkaWxJ8T9esNdG3QwQ93jBA== + +"@svgr/babel-plugin-remove-jsx-empty-expression@*": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.5.0.tgz#4b78994ab7d39032c729903fc2dd5c0fa4565cb8" + integrity sha512-NFdxMq3xA42Kb1UbzCVxplUc0iqSyM9X8kopImvFnB+uSDdzIHOdbs1op8ofAvVRtbg4oZiyRl3fTYeKcOe9Iw== + +"@svgr/babel-plugin-replace-jsx-attribute-value@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz#fb9d22ea26d2bc5e0a44b763d4c46d5d3f596c60" + integrity sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg== + +"@svgr/babel-plugin-svg-dynamic-title@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz#01b2024a2b53ffaa5efceaa0bf3e1d5a4c520ce4" + integrity sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw== + +"@svgr/babel-plugin-svg-em-dimensions@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz#dd3fa9f5b24eb4f93bcf121c3d40ff5facecb217" + integrity sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA== + +"@svgr/babel-plugin-transform-react-native-svg@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz#1d8e945a03df65b601551097d8f5e34351d3d305" + integrity sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg== + +"@svgr/babel-plugin-transform-svg-component@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz#48620b9e590e25ff95a80f811544218d27f8a250" + integrity sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ== + +"@svgr/babel-preset@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.5.1.tgz#b90de7979c8843c5c580c7e2ec71f024b49eb828" + integrity sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw== + dependencies: + "@svgr/babel-plugin-add-jsx-attribute" "^6.5.1" + "@svgr/babel-plugin-remove-jsx-attribute" "*" + "@svgr/babel-plugin-remove-jsx-empty-expression" "*" + "@svgr/babel-plugin-replace-jsx-attribute-value" "^6.5.1" + "@svgr/babel-plugin-svg-dynamic-title" "^6.5.1" + "@svgr/babel-plugin-svg-em-dimensions" "^6.5.1" + "@svgr/babel-plugin-transform-react-native-svg" "^6.5.1" + "@svgr/babel-plugin-transform-svg-component" "^6.5.1" + +"@svgr/core@^6.1.2": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.5.1.tgz#d3e8aa9dbe3fbd747f9ee4282c1c77a27410488a" + integrity sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw== + dependencies: + "@babel/core" "^7.19.6" + "@svgr/babel-preset" "^6.5.1" + "@svgr/plugin-jsx" "^6.5.1" + camelcase "^6.2.0" + cosmiconfig "^7.0.1" + +"@svgr/hast-util-to-babel-ast@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz#81800bd09b5bcdb968bf6ee7c863d2288fdb80d2" + integrity sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw== + dependencies: + "@babel/types" "^7.20.0" + entities "^4.4.0" + +"@svgr/plugin-jsx@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz#0e30d1878e771ca753c94e69581c7971542a7072" + integrity sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw== + dependencies: + "@babel/core" "^7.19.6" + "@svgr/babel-preset" "^6.5.1" + "@svgr/hast-util-to-babel-ast" "^6.5.1" + svg-parser "^2.0.4" + +"@svgr/plugin-svgo@^6.1.2": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz#0f91910e988fc0b842f88e0960c2862e022abe84" + integrity sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ== + dependencies: + cosmiconfig "^7.0.1" + deepmerge "^4.2.2" + svgo "^2.8.0" + +"@testing-library/react-native@^11.5.0": + version "11.5.0" + resolved "https://registry.yarnpkg.com/@testing-library/react-native/-/react-native-11.5.0.tgz#b043c5db7b15eca42a65e95d3f3ae196fab9493b" + integrity sha512-seV+qebsbX4E5CWk/wizU1+2wVLsPyqEzG7sTgrhJ81cgAawg7ay06fIZR9IS75pDeWn2KZVd4mGk1pjJ3i3Zw== + dependencies: + pretty-format "^29.0.0" + +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + +"@trysound/sax@0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" + integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== + +"@tsconfig/react-native@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/react-native/-/react-native-2.0.3.tgz#79ad8efc6d3729152da6cb23725b6c364a7349b2" + integrity sha512-jE58snEKBd9DXfyR4+ssZmYJ/W2mOSnNrvljR0aLyQJL9JKX6vlWELHkRjb3HBbcM9Uy0hZGijXbqEAjOERW2A== + +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": + version "7.1.20" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.20.tgz#e168cdd612c92a2d335029ed62ac94c95b362359" + integrity sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": + version "7.18.3" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.3.tgz#dfc508a85781e5698d5b33443416b6268c4b3e8d" + integrity sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w== + dependencies: + "@babel/types" "^7.3.0" + +"@types/eslint-visitor-keys@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" + integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== + +"@types/graceful-fs@^4.1.2": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + dependencies: + "@types/node" "*" + +"@types/hammerjs@^2.0.36": + version "2.0.41" + resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.41.tgz#f6ecf57d1b12d2befcce00e928a6a097c22980aa" + integrity sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA== + +"@types/indy-sdk@^1.16.19": + version "1.16.21" + resolved "https://registry.yarnpkg.com/@types/indy-sdk/-/indy-sdk-1.16.21.tgz#bb6178e2a515115b1bf225fb78506a3017d08aa8" + integrity sha512-SIu1iOa77lkxkGlW09OinFwebe7U5oDYwI70NnPoe9nbDr63i0FozITWEyIdC1BloKvZRXne6nM4i9zy6E3n6g== + dependencies: + buffer "^6.0.0" + +"@types/invariant@^2.2.35": + version "2.2.35" + resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.35.tgz#cd3ebf581a6557452735688d8daba6cf0bd5a3be" + integrity sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg== + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^26.0.23": + version "26.0.24" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a" + integrity sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w== + dependencies: + jest-diff "^26.0.0" + pretty-format "^26.0.0" + +"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/long@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" + integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + +"@types/md5@^2.3.2": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@types/md5/-/md5-2.3.2.tgz#529bb3f8a7e9e9f621094eb76a443f585d882528" + integrity sha512-v+JFDu96+UYJ3/UWzB0mEglIS//MZXgRaJ4ubUPwOM0gvLc/kcQ3TWNYwENEK7/EcXGQVrW8h/XqednSjBd/Og== + +"@types/node-fetch@^2.5.10": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" + integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "18.11.14" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.14.tgz#a8571b25f3a31e9ded14e3ab9488509adef831d8" + integrity sha512-0KXV57tENYmmJMl+FekeW9V3O/rlcqGQQJ/hNh9r8pKIj304pskWuEd8fCyNT86g/TpO0gcOTiLzsHLEURFMIQ== + +"@types/node@>=13.7.0": + version "18.11.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" + integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== + +"@types/normalize-package-data@^2.4.0": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" + integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + +"@types/prettier@^2.0.0": + version "2.7.1" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" + integrity sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow== + +"@types/prop-types@*": + version "15.7.5" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" + integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + +"@types/ramda@^0.27.40", "@types/ramda@^0.27.44": + version "0.27.66" + resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.27.66.tgz#f1a23d13b0087d806a62e3ff941e5e59b3318999" + integrity sha512-i2YW+E2U6NfMt3dp0RxNcejox+bxJUNDjB7BpYuRuoHIzv5juPHkJkNgcUOu+YSQEmaWu8cnAo/8r63C0NnuVA== + dependencies: + ts-toolbelt "^6.15.1" + +"@types/react-native-vector-icons@^6.4.12": + version "6.4.12" + resolved "https://registry.yarnpkg.com/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.12.tgz#4b9c63bf85eb42fca7c5b0a55ec317900e4fb427" + integrity sha512-gSXtv3NMOsRwSXJ/gvGebm7CNjHbkeFKCse9h/Pvi+x2yjCLOkJR1FBfec06DhaFJpsK7Y8WRQpwOS0eLqx5Rg== + dependencies: + "@types/react" "*" + "@types/react-native" "*" + +"@types/react-native@*", "@types/react-native@^0.70.6": + version "0.70.8" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.70.8.tgz#3302a0f7eddcd3350448ca17a9e415d02b1efde6" + integrity sha512-jvs5QMOrlyi0ScfT5Brha2roDoOWtbIOadNkp0jsueVen5+pH4SQAYtzL6xu0+dIcx3J/5LtZ/JYby2C1/zUug== + dependencies: + "@types/react" "*" + +"@types/react-test-renderer@^18.0.0": + version "18.0.0" + resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-18.0.0.tgz#7b7f69ca98821ea5501b21ba24ea7b6139da2243" + integrity sha512-C7/5FBJ3g3sqUahguGi03O79b8afNeSD6T8/GU50oQrJCU0bVCCGQHaGKUbg2Ce8VQEEqTw8/HiS6lXHHdgkdQ== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^18.0.21": + version "18.0.26" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.26.tgz#8ad59fc01fef8eaf5c74f4ea392621749f0b7917" + integrity sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + +"@types/semver@^7.3.12": + version "7.3.13" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" + integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== + +"@types/shallowequal@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/shallowequal/-/shallowequal-1.1.1.tgz#aad262bb3f2b1257d94c71d545268d592575c9b1" + integrity sha512-Lhni3aX80zbpdxRuWhnuYPm8j8UQaa571lHP/xI4W+7BAFhSIhRReXnqjEgT/XzPoXZTJkCqstFMJ8CZTK6IlQ== + +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/urijs@^1.19.15": + version "1.19.19" + resolved "https://registry.yarnpkg.com/@types/urijs/-/urijs-1.19.19.tgz#2789369799907fc11e2bc6e3a00f6478c2281b95" + integrity sha512-FDJNkyhmKLw7uEvTxx5tSXfPeQpO0iy73Ry+PmYZJvQy0QIWX8a7kJ4kLWRf+EbTPJEPDSgPXHaM7pzr5lmvCg== + +"@types/validator@^13.1.3": + version "13.7.10" + resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.10.tgz#f9763dc0933f8324920afa9c0790308eedf55ca7" + integrity sha512-t1yxFAR2n0+VO6hd/FJ9F2uezAZVWHLmpmlJzm1eX03+H7+HsuTAp7L8QJs+2pQCfWkP1+EXsGK9Z9v7o/qPVQ== + +"@types/ws@^7.4.6": + version "7.4.7" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" + integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== + dependencies: + "@types/node" "*" + +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^15.0.0": + version "15.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== + dependencies: + "@types/yargs-parser" "*" + +"@types/yargs@^16.0.0": + version "16.0.4" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" + integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@^3.1.0": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz#7e061338a1383f59edc204c605899f93dc2e2c8f" + integrity sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ== + dependencies: + "@typescript-eslint/experimental-utils" "3.10.1" + debug "^4.1.1" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/eslint-plugin@^5.37.0": + version "5.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.46.1.tgz#098abb4c9354e19f460d57ab18bff1f676a6cff0" + integrity sha512-YpzNv3aayRBwjs4J3oz65eVLXc9xx0PDbIRisHj+dYhvBn02MjYOD96P8YGiWEIFBrojaUjxvkaUpakD82phsA== + dependencies: + "@typescript-eslint/scope-manager" "5.46.1" + "@typescript-eslint/type-utils" "5.46.1" + "@typescript-eslint/utils" "5.46.1" + debug "^4.3.4" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + regexpp "^3.2.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/experimental-utils@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" + integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/parser@^3.1.0": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" + integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "3.10.1" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" + eslint-visitor-keys "^1.1.0" + +"@typescript-eslint/parser@^5.37.0": + version "5.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.46.1.tgz#1fc8e7102c1141eb64276c3b89d70da8c0ba5699" + integrity sha512-RelQ5cGypPh4ySAtfIMBzBGyrNerQcmfA1oJvPj5f+H4jI59rl9xxpn4bonC0tQvUKOEN7eGBFWxFLK3Xepneg== + dependencies: + "@typescript-eslint/scope-manager" "5.46.1" + "@typescript-eslint/types" "5.46.1" + "@typescript-eslint/typescript-estree" "5.46.1" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.46.1": + version "5.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.46.1.tgz#70af8425c79bbc1178b5a63fb51102ddf48e104a" + integrity sha512-iOChVivo4jpwUdrJZyXSMrEIM/PvsbbDOX1y3UCKjSgWn+W89skxWaYXACQfxmIGhPVpRWK/VWPYc+bad6smIA== + dependencies: + "@typescript-eslint/types" "5.46.1" + "@typescript-eslint/visitor-keys" "5.46.1" + +"@typescript-eslint/type-utils@5.46.1": + version "5.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.46.1.tgz#195033e4b30b51b870dfcf2828e88d57b04a11cc" + integrity sha512-V/zMyfI+jDmL1ADxfDxjZ0EMbtiVqj8LUGPAGyBkXXStWmCUErMpW873zEHsyguWCuq2iN4BrlWUkmuVj84yng== + dependencies: + "@typescript-eslint/typescript-estree" "5.46.1" + "@typescript-eslint/utils" "5.46.1" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" + integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== + +"@typescript-eslint/types@5.46.1": + version "5.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.46.1.tgz#4e9db2107b9a88441c4d5ecacde3bb7a5ebbd47e" + integrity sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w== + +"@typescript-eslint/typescript-estree@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" + integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== + dependencies: + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/visitor-keys" "3.10.1" + debug "^4.1.1" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/typescript-estree@5.46.1": + version "5.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.46.1.tgz#5358088f98a8f9939355e0996f9c8f41c25eced2" + integrity sha512-j9W4t67QiNp90kh5Nbr1w92wzt+toiIsaVPnEblB2Ih2U9fqBTyqV9T3pYWZBRt6QoMh/zVWP59EpuCjc4VRBg== + dependencies: + "@typescript-eslint/types" "5.46.1" + "@typescript-eslint/visitor-keys" "5.46.1" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.46.1": + version "5.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.46.1.tgz#7da3c934d9fd0eb4002a6bb3429f33298b469b4a" + integrity sha512-RBdBAGv3oEpFojaCYT4Ghn4775pdjvwfDOfQ2P6qzNVgQOVrnSPe5/Pb88kv7xzYQjoio0eKHKB9GJ16ieSxvA== + dependencies: + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.46.1" + "@typescript-eslint/types" "5.46.1" + "@typescript-eslint/typescript-estree" "5.46.1" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" + integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== + dependencies: + eslint-visitor-keys "^1.1.0" + +"@typescript-eslint/visitor-keys@5.46.1": + version "5.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.46.1.tgz#126cc6fe3c0f83608b2b125c5d9daced61394242" + integrity sha512-jczZ9noovXwy59KjRTk1OftT78pwygdcmCuBf8yMoWt/8O8l+6x2LSEze0E4TeepXK4MezW3zGSyoDRZK7Y9cg== + dependencies: + "@typescript-eslint/types" "5.46.1" + eslint-visitor-keys "^3.3.0" + +"@vereign/lib-mime@^1.1.9": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@vereign/lib-mime/-/lib-mime-1.1.9.tgz#3a3e723bb4aed746a0a79d760808d457ff94c176" + integrity sha512-KpiEbx0N+2S3J6X7K5Xaoq/c9/N05lKsrC0jum4ZI2kmYWBiy+NM9RO3cl1UoElsi2uehaI91+WFeAyxNZ5//w== + +"@vereign/lib-png@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@vereign/lib-png/-/lib-png-1.0.3.tgz#a4d40f68e7f45f81c6bd6b539e81224025c8e68f" + integrity sha512-xY/N/zUHeKYYoq3Z0k5AsaNYYUNG8Ntng4m7Gu7jhcICRr5eRBES9GF1Vg9reR0rRs4SG74bq4D9LJb3W5C4OQ== + +"@vereign/light-utils@git+ssh://git@code.vereign.com:seal/building-blocks/signing-verification-utilities.git#feature-seal-reading-injecting": + version "2.0.8" + resolved "git+ssh://git@code.vereign.com:seal/building-blocks/signing-verification-utilities.git#df3d22547b9abe78c8d9c2adf057052f83d27639" + dependencies: + axios "^0.20.0" + buffer "^6.0.3" + canvas "^2.8.0" + easyqrcodejs "^4.3.1" + easyqrcodejs-nodejs "^4.4.2" + eventemitter2 "^6.4.3" + fflate "^0.7.3" + google-protobuf "^3.13.0" + js-md5 "^0.7.3" + penpal "^5.3.0" + protobufjs "^6.10.1" + url-parse "^1.4.7" + +abab@^2.0.3, abab@^2.0.5, abab@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abs-svg-path@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/abs-svg-path/-/abs-svg-path-0.1.1.tgz#df601c8e8d2ba10d4a76d625e236a9a39c2723bf" + integrity sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA== + +absolute-path@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/absolute-path/-/absolute-path-0.0.0.tgz#a78762fbdadfb5297be99b15d35a785b2f095bf7" + integrity sha512-HQiug4c+/s3WOvEnDRxXVmNtSG5s2gJM9r19BTcqjp7BWcE48PB+Y2G6jE65kqI0LpsQeMZygt/b60Gi4KxGyA== + +accepts@^1.3.7, accepts@~1.3.5, accepts@~1.3.7: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + +acorn-jsx@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn@^7.1.1, acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.2.4, acorn@^8.5.0: + version "8.8.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" + integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== + +add-dom-event-listener@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz#6a92db3a0dd0abc254e095c0f1dc14acbbaae310" + integrity sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw== + dependencies: + object-assign "4.x" + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.11.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.2.tgz#aecb20b50607acf2569b6382167b65a96008bb78" + integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +anser@^1.4.9: + version "1.4.10" + resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.10.tgz#befa3eddf282684bd03b63dcda3927aef8c2e35b" + integrity sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww== + +ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-fragments@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ansi-fragments/-/ansi-fragments-0.2.1.tgz#24409c56c4cc37817c3d7caa99d8969e2de5a05e" + integrity sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w== + dependencies: + colorette "^1.0.7" + slice-ansi "^2.0.0" + strip-ansi "^5.0.0" + +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + +ansi-regex@^5.0.0, ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@^3.0.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +appdirsjs@^1.2.4: + version "1.2.7" + resolved "https://registry.yarnpkg.com/appdirsjs/-/appdirsjs-1.2.7.tgz#50b4b7948a26ba6090d4aede2ae2dc2b051be3b3" + integrity sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw== + +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== + +array-includes@^3.1.5, array-includes@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" + integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" + is-string "^1.0.7" + +array-tree-filter@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-tree-filter/-/array-tree-filter-2.1.0.tgz#873ac00fec83749f255ac8dd083814b4f6329190" + integrity sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== + +array.prototype.flatmap@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" + integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + +array.prototype.tosorted@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz#ccf44738aa2b5ac56578ffda97c03fd3e23dd532" + integrity sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.1.3" + +asap@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + +ast-types@0.14.2: + version "0.14.2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd" + integrity sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA== + dependencies: + tslib "^2.0.1" + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@^3.2.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +axios@^0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd" + integrity sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA== + dependencies: + follow-redirects "^1.10.0" + +babel-core@^7.0.0-bridge.0: + version "7.0.0-bridge.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" + integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== + +babel-eslint@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + +babel-jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" + integrity sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA== + dependencies: + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/babel__core" "^7.1.7" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^26.6.2" + chalk "^4.0.0" + graceful-fs "^4.2.4" + slash "^3.0.0" + +babel-plugin-import@^1.13.5: + version "1.13.5" + resolved "https://registry.yarnpkg.com/babel-plugin-import/-/babel-plugin-import-1.13.5.tgz#42eed1c5afd9a35ee1b1f8fe922b07c44077d753" + integrity sha512-IkqnoV+ov1hdJVofly9pXRJmeDm9EtROfrc5i6eII0Hix2xMs5FEm8FG3ExMvazbnZBbgHIt6qdO8And6lCloQ== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + +babel-plugin-istanbul@^6.0.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz#8185bd030348d254c6d7dd974355e6a28b21e62d" + integrity sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-polyfill-corejs2@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" + integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== + dependencies: + "@babel/compat-data" "^7.17.7" + "@babel/helper-define-polyfill-provider" "^0.3.3" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" + integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.3" + core-js-compat "^3.25.1" + +babel-plugin-polyfill-regenerator@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" + integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.3" + +babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: + version "7.0.0-beta.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" + integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-fbjs@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz#38a14e5a7a3b285a3f3a86552d650dca5cf6111c" + integrity sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow== + dependencies: + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-class-properties" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoped-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-member-expression-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-property-literals" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" + +babel-preset-jest@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz#747872b1171df032252426586881d62d31798fee" + integrity sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ== + dependencies: + babel-plugin-jest-hoist "^26.6.2" + babel-preset-current-node-syntax "^1.0.0" + +babel-runtime@^6.x: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-64@0.1.0, base-64@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" + integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA== + +base64-js@^1.1.2, base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bignumber.js@^9.0.0: + version "9.1.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" + integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== + +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +bn.js@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +borc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/borc/-/borc-3.0.0.tgz#49ada1be84de86f57bb1bb89789f34c186dfa4fe" + integrity sha512-ec4JmVC46kE0+layfnwM3l15O70MlFiEbmQHY/vpqIKiUtPVntv4BY4NVnz3N4vb21edV3mY97XVckFvYHWF9g== + dependencies: + bignumber.js "^9.0.0" + buffer "^6.0.3" + commander "^2.15.0" + ieee754 "^1.1.13" + iso-url "^1.1.5" + json-text-sequence "~0.3.0" + readable-stream "^3.6.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + +browserslist@^4.21.3, browserslist@^4.21.4: + version "4.21.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== + dependencies: + caniuse-lite "^1.0.30001400" + electron-to-chromium "^1.4.251" + node-releases "^2.0.6" + update-browserslist-db "^1.0.9" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +buffer@^6.0.0, buffer@^6.0.2, buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.0.0, camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +camelize@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" + integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== + +caniuse-lite@^1.0.30001400: + version "1.0.30001439" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz#ab7371faeb4adff4b74dad1718a6fd122e45d9cb" + integrity sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A== + +canvas@^2.8.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.11.0.tgz#7f0c3e9ae94cf469269b5d3a7963a7f3a9936434" + integrity sha512-bdTjFexjKJEwtIo0oRx8eD4G2yWoUOXP9lj279jmQ2zMnTQhT8C3512OKz3s+ZOaQlLbE7TuVvRDYDB3Llyy5g== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.0" + nan "^2.17.0" + simple-get "^3.0.3" + +capture-exit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== + dependencies: + rsvp "^4.8.4" + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +character-entities-html4@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.4.tgz#0e64b0a3753ddbf1fdc044c5fd01d0199a02e125" + integrity sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g== + +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +charenc@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-info@^3.2.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.0.tgz#6d01b3696c59915b6ce057e4aa4adfc2fa25f5ef" + integrity sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog== + +cjs-module-lexer@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz#4186fcca0eae175970aee870b9fe2d6cf8d5655f" + integrity sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw== + +class-transformer@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/class-transformer/-/class-transformer-0.5.1.tgz#24147d5dffd2a6cea930a3250a677addf96ab336" + integrity sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +class-validator@0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.13.1.tgz#381b2001ee6b9e05afd133671fbdf760da7dec67" + integrity sha512-zWIeYFhUitvAHBwNhDdCRK09hWx+P0HUwFE8US8/CxFpMVzkUK8RJl7yOIE+BVu2lxyPNgeOaFv78tLE47jBIg== + dependencies: + "@types/validator" "^13.1.3" + libphonenumber-js "^1.9.7" + validator "^13.5.2" + +classnames@^2.2.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" + integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a" + integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw== + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@^1.0.0, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +color@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" + integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== + dependencies: + color-convert "^2.0.1" + color-string "^1.9.0" + +colorette@^1.0.7: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" + integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== + +colors@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@^2.15.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +commander@^9.4.0: + version "9.4.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" + integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== + +commander@~2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.1: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +connect@^3.6.5: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== + +core-js-compat@^3.25.1: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.26.1.tgz#0e710b09ebf689d719545ac36e49041850f943df" + integrity sha512-622/KzTudvXCDLRw70iHW4KKs1aGpcRcowGWyYJr2DEBfRrd6hNJybxSWJFuZYD4ma86xhrwDDHxmDaIq4EA8A== + dependencies: + browserslist "^4.21.4" + +core-js@^2.4.0: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +cosmiconfig@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + +cross-fetch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + +cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.0, cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypt@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== + +css-color-keywords@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" + integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg== + +css-select@^4.1.3: + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== + dependencies: + boolbase "^1.0.0" + css-what "^6.0.1" + domhandler "^4.3.1" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + +css-to-react-native@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.1.0.tgz#e783474149997608986afcff614405714a8fe1ac" + integrity sha512-AryfkFA29b4I3vG7N4kxFboq15DxwSXzhXM37XNEjwJMgjYIc8BcqfiprpAqX0zadI5PMByEIwAMzXxk5Vcc4g== + dependencies: + camelize "^1.0.0" + css-color-keywords "^1.0.0" + postcss-value-parser "^4.0.2" + +css-tree@^1.1.2, css-tree@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + +css-what@^6.0.1, css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +csso@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" + integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== + dependencies: + css-tree "^1.1.2" + +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" + integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + +csstype@^3.0.2, csstype@^3.0.8, csstype@^3.0.9: + version "3.1.1" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" + integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + +data-urls@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" + integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== + dependencies: + abab "^2.0.6" + whatwg-mimetype "^3.0.0" + whatwg-url "^11.0.0" + +date-fns@^2.29.1: + version "2.29.3" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" + integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== + +dayjs@^1.8.15: + version "1.11.7" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2" + integrity sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ== + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decimal.js@^10.2.1, decimal.js@^10.3.1: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + +decode-uri-component@^0.2.0, decode-uri-component@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + +deep-is@^0.1.3, deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.3.0.tgz#d3c47fd6f3a93d517b14426b0628a17b0125f5f7" + integrity sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA== + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + +define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +denodeify@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" + integrity sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-libc@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" + integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +did-resolver@^3.1.3: + version "3.2.2" + resolved "https://registry.yarnpkg.com/did-resolver/-/did-resolver-3.2.2.tgz#6f4e252a810f785d1b28a10265fad6dffee25158" + integrity sha512-Eeo2F524VM5N3W4GwglZrnul2y6TLTwMQP3In62JdG34NZoqihYyOZLk+5wUW8sSgvIYIcJM8Dlt3xsdKZZ3tg== + +did-resolver@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/did-resolver/-/did-resolver-4.0.1.tgz#11bb3f19ed1c8f53f4af4702912fa9f7852fc305" + integrity sha512-eHs2VLKhcANmh08S87PKvOauIAmSOd7nb7AlhNxcvOyDAIGQY1UfbiqI1VOW5IDKvOO6aEWY+5edOt1qrCp1Eg== + +diff-sequences@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-serializer@^1.0.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + +domexception@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673" + integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw== + dependencies: + webidl-conversions "^7.0.0" + +domhandler@^4.2.0, domhandler@^4.2.2, domhandler@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== + dependencies: + domelementtype "^2.2.0" + +domhandler@^5.0.1, domhandler@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + +domutils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + +domutils@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c" + integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.1" + +easyqrcodejs-nodejs@^4.4.2: + version "4.4.5" + resolved "https://registry.yarnpkg.com/easyqrcodejs-nodejs/-/easyqrcodejs-nodejs-4.4.5.tgz#ffd97d1554e0cf899c83faa11e655bad7e0bd47d" + integrity sha512-ILgs2PLs3xJ5QFtbwfmz8QHiLxD1NSSr3tWkQOybocip5gkaaDjsTJD/ex8mxePnTJ6br7ynHGcrJ4/xLC79MQ== + dependencies: + canvas "^2.8.0" + jsdom "^19.0.0" + svgo "^2.8.0" + +easyqrcodejs@^4.3.1: + version "4.4.13" + resolved "https://registry.yarnpkg.com/easyqrcodejs/-/easyqrcodejs-4.4.13.tgz#466c5e807751ae41d5f65cab08e4359f27c28b8e" + integrity sha512-NulfMl+bhx/gAjZcBjgNd99jqPE5wEho1Z3nZwnKNISu0STnVq0xFQ28SVhcnOwt+47BJ80dULVNzpGIwYi66A== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.251: + version "1.4.284" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" + integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== + +emittery@^0.7.1: + version "0.7.2" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.2.tgz#25595908e13af0f5674ab419396e2fb394cdfa82" + integrity sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +entities@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" + integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== + +entities@^4.2.0, entities@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" + integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== + +envinfo@^7.7.2: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser@^2.0.6: + version "2.1.4" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" + integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== + dependencies: + stackframe "^1.3.4" + +errorhandler@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.5.1.tgz#b9ba5d17cf90744cd1e851357a6e75bf806a9a91" + integrity sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A== + dependencies: + accepts "~1.3.7" + escape-html "~1.0.3" + +es-abstract@^1.19.0, es-abstract@^1.20.4: + version "1.20.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.5.tgz#e6dc99177be37cacda5988e692c3fa8b218e95d2" + integrity sha512-7h8MM2EQhsCA7pU/Nv78qOXFpD8Rhqd12gYiSJVkrH9+e8VuA8JlPJK/hQjjlLv6pJvx/z1iRFKzYb0XT/RuAQ== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.3" + get-symbol-description "^1.0.0" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-weakref "^1.0.2" + object-inspect "^1.12.2" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + unbox-primitive "^1.0.2" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@2.0.0, escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-config-prettier@^6.10.1: + version "6.15.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" + integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== + dependencies: + get-stdin "^6.0.0" + +eslint-plugin-eslint-comments@^3.1.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz#9e1cd7b4413526abb313933071d7aba05ca12ffa" + integrity sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ== + dependencies: + escape-string-regexp "^1.0.5" + ignore "^5.0.5" + +eslint-plugin-flowtype@2.50.3: + version "2.50.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.50.3.tgz#61379d6dce1d010370acd6681740fd913d68175f" + integrity sha512-X+AoKVOr7Re0ko/yEXyM5SSZ0tazc6ffdIOocp2fFUlWoDt7DV0Bz99mngOkAFLOAWjqRA5jPwqUCbrx13XoxQ== + dependencies: + lodash "^4.17.10" + +eslint-plugin-jest@22.4.1: + version "22.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.4.1.tgz#a5fd6f7a2a41388d16f527073b778013c5189a9c" + integrity sha512-gcLfn6P2PrFAVx3AobaOzlIEevpAEf9chTpFZz7bYfc7pz8XRv7vuKTIE4hxPKZSha6XWKKplDQ0x9Pq8xX2mg== + +eslint-plugin-prettier@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" + integrity sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-react-hooks@^4.0.4: + version "4.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" + integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== + +eslint-plugin-react-native-globals@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz#ee1348bc2ceb912303ce6bdbd22e2f045ea86ea2" + integrity sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g== + +eslint-plugin-react-native@^3.8.1: + version "3.11.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-native/-/eslint-plugin-react-native-3.11.0.tgz#c73b0886abb397867e5e6689d3a6a418682e6bac" + integrity sha512-7F3OTwrtQPfPFd+VygqKA2VZ0f2fz0M4gJmry/TRE18JBb94/OtMxwbL7Oqwu7FGyrdeIOWnXQbBAveMcSTZIA== + dependencies: + "@babel/traverse" "^7.7.4" + eslint-plugin-react-native-globals "^0.1.1" + +eslint-plugin-react@^7.20.0: + version "7.31.11" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.11.tgz#011521d2b16dcf95795df688a4770b4eaab364c8" + integrity sha512-TTvq5JsT5v56wPa9OYHzsrOlHzKZKjV+aLgS+55NJP/cuzdiQPC7PfYoUjMoxlffKtvijpk7vA/jmuqRb9nohw== + dependencies: + array-includes "^3.1.6" + array.prototype.flatmap "^1.3.1" + array.prototype.tosorted "^1.1.1" + doctrine "^2.1.0" + estraverse "^5.3.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.6" + object.fromentries "^2.0.6" + object.hasown "^1.1.2" + object.values "^1.1.6" + prop-types "^15.8.1" + resolve "^2.0.0-next.3" + semver "^6.3.0" + string.prototype.matchall "^4.0.8" + +eslint-scope@^5.0.0, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + +eslint@^7.32.0: + version "7.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== + dependencies: + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + escape-string-regexp "^4.0.0" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.1.2" + globals "^13.6.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.9" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + +esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +event-target-shim@^5.0.0, event-target-shim@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter2@^6.4.3: + version "6.4.9" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.9.tgz#41f2750781b4230ed58827bc119d293471ecb125" + integrity sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg== + +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +exec-sh@^0.3.2: + version "0.3.6" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" + integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w== + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expect@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" + integrity sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA== + dependencies: + "@jest/types" "^26.6.2" + ansi-styles "^4.0.0" + jest-get-type "^26.3.0" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-regex-util "^26.0.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +fast-base64-decode@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz#b434a0dd7d92b12b43f26819300d2dafb83ee418" + integrity sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.14.0.tgz#107f69d7295b11e0fccc264e1fc6389f623731ce" + integrity sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fflate@^0.7.3: + version "0.7.4" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.7.4.tgz#61587e5d958fdabb5a9368a302c25363f4f69f50" + integrity sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw== + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +filter-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" + integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-cache-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + +flow-parser@0.*: + version "0.195.2" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.195.2.tgz#4891428828c9ab0c1cdb12c9a8bafa72ce4f216d" + integrity sha512-zPXwya4KhbT1xuRN/oqJ5BITjJl9OGCDmaG7qhABgewb4/2wmy4SV0ULRaGoZB5BWt4kWzLG4qve/1mRbpfSOA== + +flow-parser@^0.121.0: + version "0.121.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.121.0.tgz#9f9898eaec91a9f7c323e9e992d81ab5c58e618f" + integrity sha512-1gIBiWJNR0tKUNv8gZuk7l9rVX06OuLzY9AoGio7y/JT4V1IZErEMEq2TJS+PFcw/y0RshZ1J/27VfK1UQzYVg== + +follow-redirects@^1.10.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-extra@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" + integrity sha512-VerQV6vEKuhDWD2HGOybV6v5I73syoc/cXAbKlgTC7M/oFVEtklWlp9QH2Ijw3IaWDOQcMkldSPa7zXy79Z/UQ== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.1.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a" + integrity sha512-f8c0rE8JiCxpa52kWPAOa3ZaYEnzofDzCQLCn3Vdk0Z5OVLq3BsRFJI4S4ykpeVW6QMGBUkMeUpoEgWnMTnw5Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.6.0, globals@^13.9.0: + version "13.19.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.19.0.tgz#7a42de8e6ad4f7242fbcca27ea5b23aca367b5c8" + integrity sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +google-protobuf@^3.13.0: + version "3.21.2" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.2.tgz#4580a2bea8bbb291ee579d1fefb14d6fa3070ea4" + integrity sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA== + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +growly@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" + integrity sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw== + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hermes-estree@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.8.0.tgz#530be27243ca49f008381c1f3e8b18fb26bf9ec0" + integrity sha512-W6JDAOLZ5pMPMjEiQGLCXSSV7pIBEgRR5zGkxgmzGSXHOxqV5dC/M1Zevqpbm9TZDE5tu358qZf8Vkzmsc+u7Q== + +hermes-parser@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.8.0.tgz#116dceaba32e45b16d6aefb5c4c830eaeba2d257" + integrity sha512-yZKalg1fTYG5eOiToLUaw69rQfZq/fi+/NtEXRU7N87K/XobNRhRWorh80oSge2lWUiZfTgUvRJH+XgZWrhoqA== + dependencies: + hermes-estree "0.8.0" + +hermes-profile-transformer@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz#bd0f5ecceda80dd0ddaae443469ab26fb38fc27b" + integrity sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ== + dependencies: + source-map "^0.7.3" + +hoist-non-react-statics@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + +html-encoding-sniffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" + integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== + dependencies: + whatwg-encoding "^2.0.0" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +html-parse-stringify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" + integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg== + dependencies: + void-elements "3.1.0" + +htmlparser2@^7.1.2: + version "7.2.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-7.2.0.tgz#8817cdea38bbc324392a90b1990908e81a65f5a5" + integrity sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.2" + domutils "^2.8.0" + entities "^3.0.1" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + +i18next@^22.4.6: + version "22.4.6" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-22.4.6.tgz#876352c3ba81bdfedc38eeda124e2bbd05f46988" + integrity sha512-9Tm1ezxWyzV+306CIDMBbYBitC1jedQyYuuLtIv7oxjp2ohh8eyxP9xytIf+2bbQfhH784IQKPSYp+Zq9+YSbw== + dependencies: + "@babel/runtime" "^7.20.6" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ieee754@^1.1.13, ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.0.5, ignore@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.1.tgz#c2b1f76cb999ede1502f3a226a9310fdfe88d46c" + integrity sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA== + +image-size@^0.6.0: + version "0.6.3" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.3.tgz#e7e5c65bb534bd7cdcedd6cb5166272a85f75fb2" + integrity sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA== + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indy-sdk-react-native@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/indy-sdk-react-native/-/indy-sdk-react-native-0.3.0.tgz#37b20476bf1207d3dea7b66dba65bf44ed0c903a" + integrity sha512-3qaB4R7QDNQRI9ijpSvMaow/HlZYMB2LdJlRtbhefmrjQYwpz9oSqB595NPKajBIoIxzgDaUdBkK7kmwMY90Xg== + dependencies: + buffer "^6.0.2" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +intl-pluralrules@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/intl-pluralrules/-/intl-pluralrules-1.3.1.tgz#304ec4038a597894f6616633cbf5e66fb3dbee04" + integrity sha512-sNYPls1Q4fyN0EGLFVJ7TIuaMWln01LupLozfIBt69rHK0DHehghMSz6ejfnSklgRddnyQSEaQPIU6d9TCKH3w== + +invariant@2.2.4, invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +ip@^1.1.5: + version "1.1.8" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48" + integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@^1.1.5, is-buffer@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +iso-url@^1.1.5: + version "1.2.1" + resolved "https://registry.yarnpkg.com/iso-url/-/iso-url-1.2.1.tgz#db96a49d8d9a64a1c889fc07cc525d093afb1811" + integrity sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng== + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" + integrity sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ== + dependencies: + "@jest/types" "^26.6.2" + execa "^4.0.0" + throat "^5.0.0" + +jest-cli@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.6.3.tgz#43117cfef24bc4cd691a174a8796a532e135e92a" + integrity sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg== + dependencies: + "@jest/core" "^26.6.3" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + import-local "^3.0.2" + is-ci "^2.0.0" + jest-config "^26.6.3" + jest-util "^26.6.2" + jest-validate "^26.6.2" + prompts "^2.0.1" + yargs "^15.4.1" + +jest-config@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.6.3.tgz#64f41444eef9eb03dc51d5c53b75c8c71f645349" + integrity sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg== + dependencies: + "@babel/core" "^7.1.0" + "@jest/test-sequencer" "^26.6.3" + "@jest/types" "^26.6.2" + babel-jest "^26.6.3" + chalk "^4.0.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.4" + jest-environment-jsdom "^26.6.2" + jest-environment-node "^26.6.2" + jest-get-type "^26.3.0" + jest-jasmine2 "^26.6.3" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + micromatch "^4.0.2" + pretty-format "^26.6.2" + +jest-diff@^26.0.0, jest-diff@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-docblock@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" + integrity sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w== + dependencies: + detect-newline "^3.0.0" + +jest-each@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.6.2.tgz#02526438a77a67401c8a6382dfe5999952c167cb" + integrity sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A== + dependencies: + "@jest/types" "^26.6.2" + chalk "^4.0.0" + jest-get-type "^26.3.0" + jest-util "^26.6.2" + pretty-format "^26.6.2" + +jest-environment-jsdom@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz#78d09fe9cf019a357009b9b7e1f101d23bd1da3e" + integrity sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + jest-util "^26.6.2" + jsdom "^16.4.0" + +jest-environment-node@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.6.2.tgz#824e4c7fb4944646356f11ac75b229b0035f2b0c" + integrity sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + jest-util "^26.6.2" + +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== + +jest-haste-map@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" + integrity sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w== + dependencies: + "@jest/types" "^26.6.2" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-regex-util "^26.0.0" + jest-serializer "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" + micromatch "^4.0.2" + sane "^4.0.3" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.1.2" + +jest-jasmine2@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz#adc3cf915deacb5212c93b9f3547cd12958f2edd" + integrity sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg== + dependencies: + "@babel/traverse" "^7.1.0" + "@jest/environment" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + expect "^26.6.2" + is-generator-fn "^2.0.0" + jest-each "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + pretty-format "^26.6.2" + throat "^5.0.0" + +jest-leak-detector@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz#7717cf118b92238f2eba65054c8a0c9c653a91af" + integrity sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg== + dependencies: + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-matcher-utils@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" + integrity sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw== + dependencies: + chalk "^4.0.0" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-message-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" + integrity sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA== + dependencies: + "@babel/code-frame" "^7.0.0" + "@jest/types" "^26.6.2" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.2" + pretty-format "^26.6.2" + slash "^3.0.0" + stack-utils "^2.0.2" + +jest-mock@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.6.2.tgz#d6cb712b041ed47fe0d9b6fc3474bc6543feb302" + integrity sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew== + dependencies: + "@jest/types" "^26.6.2" + "@types/node" "*" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" + integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== + +jest-regex-util@^27.0.6: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" + integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== + +jest-resolve-dependencies@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz#6680859ee5d22ee5dcd961fe4871f59f4c784fb6" + integrity sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg== + dependencies: + "@jest/types" "^26.6.2" + jest-regex-util "^26.0.0" + jest-snapshot "^26.6.2" + +jest-resolve@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.6.2.tgz#a3ab1517217f469b504f1b56603c5bb541fbb507" + integrity sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ== + dependencies: + "@jest/types" "^26.6.2" + chalk "^4.0.0" + graceful-fs "^4.2.4" + jest-pnp-resolver "^1.2.2" + jest-util "^26.6.2" + read-pkg-up "^7.0.1" + resolve "^1.18.1" + slash "^3.0.0" + +jest-runner@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.6.3.tgz#2d1fed3d46e10f233fd1dbd3bfaa3fe8924be159" + integrity sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ== + dependencies: + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.7.1" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-config "^26.6.3" + jest-docblock "^26.0.0" + jest-haste-map "^26.6.2" + jest-leak-detector "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" + jest-runtime "^26.6.3" + jest-util "^26.6.2" + jest-worker "^26.6.2" + source-map-support "^0.5.6" + throat "^5.0.0" + +jest-runtime@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.6.3.tgz#4f64efbcfac398331b74b4b3c82d27d401b8fa2b" + integrity sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw== + dependencies: + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/globals" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + cjs-module-lexer "^0.6.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.4" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + slash "^3.0.0" + strip-bom "^4.0.0" + yargs "^15.4.1" + +jest-serializer@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" + integrity sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.4" + +jest-serializer@^27.0.6: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" + integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.9" + +jest-snapshot@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.6.2.tgz#f3b0af1acb223316850bd14e1beea9837fb39c84" + integrity sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og== + dependencies: + "@babel/types" "^7.0.0" + "@jest/types" "^26.6.2" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.0.0" + chalk "^4.0.0" + expect "^26.6.2" + graceful-fs "^4.2.4" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + jest-haste-map "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" + natural-compare "^1.4.0" + pretty-format "^26.6.2" + semver "^7.3.2" + +jest-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" + integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q== + dependencies: + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + graceful-fs "^4.2.4" + is-ci "^2.0.0" + micromatch "^4.0.2" + +jest-util@^27.2.0: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" + integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^26.5.2, jest-validate@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.6.2.tgz#23d380971587150467342911c3d7b4ac57ab20ec" + integrity sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ== + dependencies: + "@jest/types" "^26.6.2" + camelcase "^6.0.0" + chalk "^4.0.0" + jest-get-type "^26.3.0" + leven "^3.1.0" + pretty-format "^26.6.2" + +jest-watcher@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.6.2.tgz#a5b683b8f9d68dbcb1d7dae32172d2cca0592975" + integrity sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ== + dependencies: + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^26.6.2" + string-length "^4.0.1" + +jest-worker@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest-worker@^27.2.0: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef" + integrity sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q== + dependencies: + "@jest/core" "^26.6.3" + import-local "^3.0.2" + jest-cli "^26.6.3" + +joi@^17.2.1: + version "17.7.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.7.0.tgz#591a33b1fe1aca2bc27f290bcad9b9c1c570a6b3" + integrity sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.3" + "@sideway/formula" "^3.0.0" + "@sideway/pinpoint" "^2.0.0" + +js-md5@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/js-md5/-/js-md5-0.7.3.tgz#b4f2fbb0b327455f598d6727e38ec272cd09c3f2" + integrity sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ== + +js-sha256@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" + integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsc-android@^250230.2.1: + version "250230.2.1" + resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250230.2.1.tgz#3790313a970586a03ab0ad47defbc84df54f1b83" + integrity sha512-KmxeBlRjwoqCnBBKGsihFtvsBHyUFlBxJPK4FzeYcIuBfdjv6jFys44JITAgSTbQD+vIdwMEfyZklsuQX0yI1Q== + +jscodeshift@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.11.0.tgz#4f95039408f3f06b0e39bb4d53bc3139f5330e2f" + integrity sha512-SdRK2C7jjs4k/kT2mwtO07KJN9RnjxtKn03d9JVj6c3j9WwaLcFYsICYDnLAzY0hp+wG2nxl+Cm2jWLiNVYb8g== + dependencies: + "@babel/core" "^7.1.6" + "@babel/parser" "^7.1.6" + "@babel/plugin-proposal-class-properties" "^7.1.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.1.0" + "@babel/plugin-proposal-optional-chaining" "^7.1.0" + "@babel/plugin-transform-modules-commonjs" "^7.1.0" + "@babel/preset-flow" "^7.0.0" + "@babel/preset-typescript" "^7.1.0" + "@babel/register" "^7.0.0" + babel-core "^7.0.0-bridge.0" + colors "^1.1.2" + flow-parser "0.*" + graceful-fs "^4.2.4" + micromatch "^3.1.10" + neo-async "^2.5.0" + node-dir "^0.1.17" + recast "^0.20.3" + temp "^0.8.1" + write-file-atomic "^2.3.0" + +jscodeshift@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.13.1.tgz#69bfe51e54c831296380585c6d9e733512aecdef" + integrity sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ== + dependencies: + "@babel/core" "^7.13.16" + "@babel/parser" "^7.13.16" + "@babel/plugin-proposal-class-properties" "^7.13.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.8" + "@babel/plugin-proposal-optional-chaining" "^7.13.12" + "@babel/plugin-transform-modules-commonjs" "^7.13.8" + "@babel/preset-flow" "^7.13.13" + "@babel/preset-typescript" "^7.13.0" + "@babel/register" "^7.13.16" + babel-core "^7.0.0-bridge.0" + chalk "^4.1.2" + flow-parser "0.*" + graceful-fs "^4.2.4" + micromatch "^3.1.10" + neo-async "^2.5.0" + node-dir "^0.1.17" + recast "^0.20.4" + temp "^0.8.4" + write-file-atomic "^2.3.0" + +jsdom@^16.4.0: + version "16.7.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" + integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== + dependencies: + abab "^2.0.5" + acorn "^8.2.4" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.3.0" + data-urls "^2.0.0" + decimal.js "^10.2.1" + domexception "^2.0.1" + escodegen "^2.0.0" + form-data "^3.0.0" + html-encoding-sniffer "^2.0.1" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.0" + parse5 "6.0.1" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.5.0" + ws "^7.4.6" + xml-name-validator "^3.0.0" + +jsdom@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-19.0.0.tgz#93e67c149fe26816d38a849ea30ac93677e16b6a" + integrity sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A== + dependencies: + abab "^2.0.5" + acorn "^8.5.0" + acorn-globals "^6.0.0" + cssom "^0.5.0" + cssstyle "^2.3.0" + data-urls "^3.0.1" + decimal.js "^10.3.1" + domexception "^4.0.0" + escodegen "^2.0.0" + form-data "^4.0.0" + html-encoding-sniffer "^3.0.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.0" + parse5 "6.0.1" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^3.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^2.0.0" + whatwg-mimetype "^3.0.0" + whatwg-url "^10.0.0" + ws "^8.2.3" + xml-name-validator "^4.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json-text-sequence@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.3.0.tgz#6603e0ee45da41f949669fd18744b97fb209e6ce" + integrity sha512-7khKIYPKwXQem4lWXfpIN/FEnhztCeRPSxH4qm3fVlqulwujrRDD54xAwDDn/qVKpFtV550+QAkcWJcufzqQuA== + dependencies: + "@sovpro/delimited-stream" "^1.1.0" + +json5@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +"jsx-ast-utils@^2.4.1 || ^3.0.0": + version "3.3.3" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea" + integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw== + dependencies: + array-includes "^3.1.5" + object.assign "^4.1.3" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== + optionalDependencies: + graceful-fs "^4.1.9" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +libphonenumber-js@^1.9.7: + version "1.10.15" + resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.15.tgz#cad454adb5bf271bc820bbf7dd66776afcda7be6" + integrity sha512-sLeVLmWX17VCKKulc+aDIRHS95TxoTsKMRJi5s5gJdwlqNzMWcBCtSHHruVyXjqfi67daXM2SnLf2juSrdx5Sg== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@^4.17.10, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.7.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +logkitty@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/logkitty/-/logkitty-0.7.1.tgz#8e8d62f4085a826e8d38987722570234e33c6aa7" + integrity sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ== + dependencies: + ansi-fragments "^0.2.1" + dayjs "^1.8.15" + yargs "^15.1.0" + +long@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lru_map@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.4.1.tgz#f7b4046283c79fb7370c36f8fca6aee4324b0a98" + integrity sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg== + +luxon@^1.27.0: + version "1.28.0" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf" + integrity sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ== + +make-dir@^2.0.0, make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^3.0.0, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-error@^1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== + dependencies: + object-visit "^1.0.0" + +md5@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" + integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== + dependencies: + charenc "0.0.2" + crypt "0.0.2" + is-buffer "~1.1.6" + +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + +memoize-one@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== + dependencies: + is-plain-obj "^2.1.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +metro-babel-transformer@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.72.3.tgz#2c60493a4eb7a8d20cc059f05e0e505dc1684d01" + integrity sha512-PTOR2zww0vJbWeeM3qN90WKENxCLzv9xrwWaNtwVlhcV8/diNdNe82sE1xIxLFI6OQuAVwNMv1Y7VsO2I7Ejrw== + dependencies: + "@babel/core" "^7.14.0" + hermes-parser "0.8.0" + metro-source-map "0.72.3" + nullthrows "^1.1.1" + +metro-cache-key@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.72.3.tgz#dcc3055b6cb7e35b84b4fe736a148affb4ecc718" + integrity sha512-kQzmF5s3qMlzqkQcDwDxrOaVxJ2Bh6WRXWdzPnnhsq9LcD3B3cYqQbRBS+3tSuXmathb4gsOdhWslOuIsYS8Rg== + +metro-cache@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.72.3.tgz#fd079f90b12a81dd5f1567c607c13b14ae282690" + integrity sha512-++eyZzwkXvijWRV3CkDbueaXXGlVzH9GA52QWqTgAOgSHYp5jWaDwLQ8qpsMkQzpwSyIF4LLK9aI3eA7Xa132A== + dependencies: + metro-core "0.72.3" + rimraf "^2.5.4" + +metro-config@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.72.3.tgz#c2f1a89537c79cec516b1229aa0550dfa769e2ee" + integrity sha512-VEsAIVDkrIhgCByq8HKTWMBjJG6RlYwWSu1Gnv3PpHa0IyTjKJtB7wC02rbTjSaemcr82scldf2R+h6ygMEvsw== + dependencies: + cosmiconfig "^5.0.5" + jest-validate "^26.5.2" + metro "0.72.3" + metro-cache "0.72.3" + metro-core "0.72.3" + metro-runtime "0.72.3" + +metro-core@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.72.3.tgz#e3a276d54ecc8fe667127347a1bfd3f8c0009ccb" + integrity sha512-KuYWBMmLB4+LxSMcZ1dmWabVExNCjZe3KysgoECAIV+wyIc2r4xANq15GhS94xYvX1+RqZrxU1pa0jQ5OK+/6A== + dependencies: + lodash.throttle "^4.1.1" + metro-resolver "0.72.3" + +metro-file-map@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.72.3.tgz#94f6d4969480aa7f47cfe2c5f365ad4e85051f12" + integrity sha512-LhuRnuZ2i2uxkpFsz1XCDIQSixxBkBG7oICAFyLyEMDGbcfeY6/NexphfLdJLTghkaoJR5ARFMiIxUg9fIY/pA== + dependencies: + abort-controller "^3.0.0" + anymatch "^3.0.3" + debug "^2.2.0" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + invariant "^2.2.4" + jest-regex-util "^27.0.6" + jest-serializer "^27.0.6" + jest-util "^27.2.0" + jest-worker "^27.2.0" + micromatch "^4.0.4" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.1.2" + +metro-hermes-compiler@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-hermes-compiler/-/metro-hermes-compiler-0.72.3.tgz#e9ab4d25419eedcc72c73842c8da681a4a7e691e" + integrity sha512-QWDQASMiXNW3j8uIQbzIzCdGYv5PpAX/ZiF4/lTWqKRWuhlkP4auhVY4eqdAKj5syPx45ggpjkVE0p8hAPDZYg== + +metro-inspector-proxy@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.72.3.tgz#8d7ff4240fc414af5b72d86dac2485647fc3cf09" + integrity sha512-UPFkaq2k93RaOi+eqqt7UUmqy2ywCkuxJLasQ55+xavTUS+TQSyeTnTczaYn+YKw+izLTLllGcvqnQcZiWYhGw== + dependencies: + connect "^3.6.5" + debug "^2.2.0" + ws "^7.5.1" + yargs "^15.3.1" + +metro-minify-uglify@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.72.3.tgz#a9d4cd27933b29cfe95d8406b40d185567a93d39" + integrity sha512-dPXqtMI8TQcj0g7ZrdhC8X3mx3m3rtjtMuHKGIiEXH9CMBvrET8IwrgujQw2rkPcXiSiX8vFDbGMIlfxefDsKA== + dependencies: + uglify-es "^3.1.9" + +metro-react-native-babel-preset@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.72.3.tgz#e549199fa310fef34364fdf19bd210afd0c89432" + integrity sha512-uJx9y/1NIqoYTp6ZW1osJ7U5ZrXGAJbOQ/Qzl05BdGYvN1S7Qmbzid6xOirgK0EIT0pJKEEh1s8qbassYZe4cw== + dependencies: + "@babel/core" "^7.14.0" + "@babel/plugin-proposal-async-generator-functions" "^7.0.0" + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-export-default-from" "^7.0.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" + "@babel/plugin-proposal-optional-chaining" "^7.0.0" + "@babel/plugin-syntax-dynamic-import" "^7.0.0" + "@babel/plugin-syntax-export-default-from" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.2.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-syntax-optional-chaining" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-async-to-generator" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-exponentiation-operator" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-react-jsx-self" "^7.0.0" + "@babel/plugin-transform-react-jsx-source" "^7.0.0" + "@babel/plugin-transform-runtime" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-sticky-regex" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.5.0" + "@babel/plugin-transform-unicode-regex" "^7.0.0" + "@babel/template" "^7.0.0" + react-refresh "^0.4.0" + +metro-react-native-babel-transformer@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.72.3.tgz#f8eda8c07c0082cbdbef47a3293edc41587c6b5a" + integrity sha512-Ogst/M6ujYrl/+9mpEWqE3zF7l2mTuftDTy3L8wZYwX1pWUQWQpfU1aJBeWiLxt1XlIq+uriRjKzKoRoIK57EA== + dependencies: + "@babel/core" "^7.14.0" + babel-preset-fbjs "^3.4.0" + hermes-parser "0.8.0" + metro-babel-transformer "0.72.3" + metro-react-native-babel-preset "0.72.3" + metro-source-map "0.72.3" + nullthrows "^1.1.1" + +metro-resolver@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.72.3.tgz#c64ce160454ac850a15431509f54a587cb006540" + integrity sha512-wu9zSMGdxpKmfECE7FtCdpfC+vrWGTdVr57lDA0piKhZV6VN6acZIvqQ1yZKtS2WfKsngncv5VbB8Y5eHRQP3w== + dependencies: + absolute-path "^0.0.0" + +metro-runtime@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.72.3.tgz#1485ed7b5f06d09ebb40c83efcf8accc8d30b8b9" + integrity sha512-3MhvDKfxMg2u7dmTdpFOfdR71NgNNo4tzAyJumDVQKwnHYHN44f2QFZQqpPBEmqhWlojNeOxsqFsjYgeyMx6VA== + dependencies: + "@babel/runtime" "^7.0.0" + react-refresh "^0.4.0" + +metro-source-map@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.72.3.tgz#5efcf354413804a62ff97864e797f60ef3cc689e" + integrity sha512-eNtpjbjxSheXu/jYCIDrbNEKzMGOvYW6/ePYpRM7gDdEagUOqKOCsi3St8NJIQJzZCsxD2JZ2pYOiomUSkT1yQ== + dependencies: + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.0.0" + invariant "^2.2.4" + metro-symbolicate "0.72.3" + nullthrows "^1.1.1" + ob1 "0.72.3" + source-map "^0.5.6" + vlq "^1.0.0" + +metro-symbolicate@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.72.3.tgz#093d4f8c7957bcad9ca2ab2047caa90b1ee1b0c1" + integrity sha512-eXG0NX2PJzJ/jTG4q5yyYeN2dr1cUqUaY7worBB0SP5bRWRc3besfb+rXwfh49wTFiL5qR0oOawkU4ZiD4eHXw== + dependencies: + invariant "^2.2.4" + metro-source-map "0.72.3" + nullthrows "^1.1.1" + source-map "^0.5.6" + through2 "^2.0.1" + vlq "^1.0.0" + +metro-transform-plugins@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.72.3.tgz#b00e5a9f24bff7434ea7a8e9108eebc8386b9ee4" + integrity sha512-D+TcUvCKZbRua1+qujE0wV1onZvslW6cVTs7dLCyC2pv20lNHjFr1GtW01jN2fyKR2PcRyMjDCppFd9VwDKnSg== + dependencies: + "@babel/core" "^7.14.0" + "@babel/generator" "^7.14.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.14.0" + nullthrows "^1.1.1" + +metro-transform-worker@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.72.3.tgz#bdc6cc708ea114bc085e11d675b8ff626d7e6db7" + integrity sha512-WsuWj9H7i6cHuJuy+BgbWht9DK5FOgJxHLGAyULD5FJdTG9rSMFaHDO5WfC0OwQU5h4w6cPT40iDuEGksM7+YQ== + dependencies: + "@babel/core" "^7.14.0" + "@babel/generator" "^7.14.0" + "@babel/parser" "^7.14.0" + "@babel/types" "^7.0.0" + babel-preset-fbjs "^3.4.0" + metro "0.72.3" + metro-babel-transformer "0.72.3" + metro-cache "0.72.3" + metro-cache-key "0.72.3" + metro-hermes-compiler "0.72.3" + metro-source-map "0.72.3" + metro-transform-plugins "0.72.3" + nullthrows "^1.1.1" + +metro@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.72.3.tgz#eb587037d62f48a0c33c8d88f26666b4083bb61e" + integrity sha512-Hb3xTvPqex8kJ1hutQNZhQadUKUwmns/Du9GikmWKBFrkiG3k3xstGAyO5t5rN9JSUEzQT6y9SWzSSOGogUKIg== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/core" "^7.14.0" + "@babel/generator" "^7.14.0" + "@babel/parser" "^7.14.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.0.0" + absolute-path "^0.0.0" + accepts "^1.3.7" + async "^3.2.2" + chalk "^4.0.0" + ci-info "^2.0.0" + connect "^3.6.5" + debug "^2.2.0" + denodeify "^1.2.1" + error-stack-parser "^2.0.6" + fs-extra "^1.0.0" + graceful-fs "^4.2.4" + hermes-parser "0.8.0" + image-size "^0.6.0" + invariant "^2.2.4" + jest-worker "^27.2.0" + lodash.throttle "^4.1.1" + metro-babel-transformer "0.72.3" + metro-cache "0.72.3" + metro-cache-key "0.72.3" + metro-config "0.72.3" + metro-core "0.72.3" + metro-file-map "0.72.3" + metro-hermes-compiler "0.72.3" + metro-inspector-proxy "0.72.3" + metro-minify-uglify "0.72.3" + metro-react-native-babel-preset "0.72.3" + metro-resolver "0.72.3" + metro-runtime "0.72.3" + metro-source-map "0.72.3" + metro-symbolicate "0.72.3" + metro-transform-plugins "0.72.3" + metro-transform-worker "0.72.3" + mime-types "^2.1.27" + node-fetch "^2.2.0" + nullthrows "^1.1.1" + rimraf "^2.5.4" + serialize-error "^2.1.0" + source-map "^0.5.6" + strip-ansi "^6.0.0" + temp "0.8.3" + throat "^5.0.0" + ws "^7.5.1" + yargs "^15.3.1" + +micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mime@^2.4.1: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + +minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.0.0.tgz#7cebb0f9fa7d56f0c5b17853cbe28838a8dbbd3b" + integrity sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw== + dependencies: + yallist "^4.0.0" + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nan@^2.17.0: + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== + +nanoid@^3.1.23: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.5.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +nocache@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/nocache/-/nocache-3.0.4.tgz#5b37a56ec6e09fc7d401dceaed2eab40c8bfdf79" + integrity sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw== + +node-dir@^0.1.17: + version "0.1.17" + resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" + integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg== + dependencies: + minimatch "^3.0.2" + +node-fetch@2.6.7, node-fetch@^2.2.0, node-fetch@^2.6.0: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.7: + version "2.6.8" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.8.tgz#a68d30b162bc1d8fd71a367e81b997e1f4d4937e" + integrity sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg== + dependencies: + whatwg-url "^5.0.0" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-notifier@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.2.tgz#f3167a38ef0d2c8a866a83e318c1ba0efeb702c5" + integrity sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg== + dependencies: + growly "^1.3.0" + is-wsl "^2.2.0" + semver "^7.3.2" + shellwords "^0.1.1" + uuid "^8.3.0" + which "^2.0.2" + +node-releases@^2.0.6: + version "2.0.7" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.7.tgz#593edbc7c22860ee4d32d3933cfebdfab0c0e0e5" + integrity sha512-EJ3rzxL9pTWPjk5arA0s0dgXpnyiAbJDE6wHT62g7VsgrgQgmmZ+Ru++M1BFofncWja+Pnn3rEr3fieRySAdKQ== + +node-stream-zip@^1.9.1: + version "1.15.0" + resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.15.0.tgz#158adb88ed8004c6c49a396b50a6a5de3bca33ea" + integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== + +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + +normalize-css-color@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/normalize-css-color/-/normalize-css-color-1.0.2.tgz#02991e97cccec6623fe573afbbf0de6a1f3e9f8d" + integrity sha512-jPJ/V7Cp1UytdidsPqviKEElFQJs22hUUgK5BOPHTwOonNCk7/2qOxhhqzEajmFrWJowADFfOFh1V+aWkRfy+w== + +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-svg-path@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz#0e614eca23c39f0cffe821d6be6cd17e569a766c" + integrity sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg== + dependencies: + svg-arc-to-cubic-bezier "^3.0.0" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== + dependencies: + path-key "^2.0.0" + +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + +nwsapi@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0" + integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw== + +ob1@0.72.3: + version "0.72.3" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.72.3.tgz#fc1efcfe156f12ed23615f2465a796faad8b91e4" + integrity sha512-OnVto25Sj7Ghp0vVm2THsngdze3tVq0LOg9LUHsAVXMecpqOP0Y8zaATW8M9gEgs2lNEAcCqV0P/hlmOPhVRvg== + +object-assign@4.x, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.10.3, object-inspect@^1.12.2, object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.3, object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.entries@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23" + integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +object.fromentries@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73" + integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +object.hasown@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92" + integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw== + dependencies: + define-properties "^1.1.4" + es-abstract "^1.20.4" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== + dependencies: + isobject "^3.0.1" + +object.values@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +open@^6.2.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" + integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== + dependencies: + is-wsl "^1.1.0" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-each-series@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" + integrity sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA== + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse-svg-path@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/parse-svg-path/-/parse-svg-path-0.1.2.tgz#7a7ec0d1eb06fa5325c7d3e009b859a09b5d49eb" + integrity sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ== + +parse5@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== + +path-dirname@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +penpal@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/penpal/-/penpal-5.3.0.tgz#1a6afc56d6f257189e3d99650f58651a913db3ce" + integrity sha512-ezGckenx66j3RShl4nZiswjgDxyoDaJJ9tLBp46UvVxlA9MlIPF6hWfuppw1AzaDKgUULU1i44QFOuI4SXY/mg== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pirates@^4.0.1, pirates@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== + +postcss-value-parser@^4.0.2: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^2.0.2: + version "2.8.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" + integrity sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg== + +pretty-format@^26.0.0, pretty-format@^26.5.2, pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + +pretty-format@^29.0.0: + version "29.3.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.3.1.tgz#1841cac822b02b4da8971dacb03e8a871b4722da" + integrity sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg== + dependencies: + "@jest/schemas" "^29.0.0" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" + integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== + dependencies: + asap "~2.0.6" + +prompts@^2.0.1, prompts@^2.4.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.7.2, prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +protobufjs@^6.10.1: + version "6.11.3" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74" + integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.1" + "@types/node" ">=13.7.0" + long "^4.0.0" + +psl@^1.1.33: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +query-string@^7.0.1, query-string@^7.1.1, query-string@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" + integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg== + dependencies: + decode-uri-component "^0.2.2" + filter-obj "^1.1.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +ramda@^0.27.2: + version "0.27.2" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.2.tgz#84463226f7f36dc33592f6f4ed6374c48306c3f1" + integrity sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA== + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +rc-util@^4.21.1: + version "4.21.1" + resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-4.21.1.tgz#88602d0c3185020aa1053d9a1e70eac161becb05" + integrity sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg== + dependencies: + add-dom-event-listener "^1.1.0" + prop-types "^15.5.10" + react-is "^16.12.0" + react-lifecycles-compat "^3.0.4" + shallowequal "^1.1.0" + +react-devtools-core@4.24.0: + version "4.24.0" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.24.0.tgz#7daa196bdc64f3626b3f54f2ff2b96f7c4fdf017" + integrity sha512-Rw7FzYOOzcfyUPaAm9P3g0tFdGqGq2LLiAI+wjYcp6CsF3DeeMrRS3HZAho4s273C29G/DJhx0e8BpRE/QZNGg== + dependencies: + shell-quote "^1.6.1" + ws "^7" + +react-freeze@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/react-freeze/-/react-freeze-1.0.3.tgz#5e3ca90e682fed1d73a7cb50c2c7402b3e85618d" + integrity sha512-ZnXwLQnGzrDpHBHiC56TXFXvmolPeMjTn1UOm610M4EXGzbEDR7oOIyS2ZiItgbs6eZc4oU/a0hpk8PrcKvv5g== + +react-i18next@^12.1.1: + version "12.1.1" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-12.1.1.tgz#2626cdbfe6bcb76ef833861c0184a5c4e5e3c089" + integrity sha512-mFdieOI0LDy84q3JuZU6Aou1DoWW2fhapcTGeBS8+vWSJuViuoCLQAMYSb0QoHhXS8B0WKUOPpx4cffAP7r/aA== + dependencies: + "@babel/runtime" "^7.14.5" + html-parse-stringify "^3.0.1" + +react-is@^16.12.0, react-is@^16.13.0, react-is@^16.13.1, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.1.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-lifecycles-compat@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== + +react-native-aes-gcm-crypto@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/react-native-aes-gcm-crypto/-/react-native-aes-gcm-crypto-0.2.2.tgz#e2c355e94a88ef52179dc22ae81988637b9ba7f1" + integrity sha512-vUwkh2zBiIQMRY191IfZhDmhHVT+nV4sxet/A0V8J35lVShCA4kuFzBL+QVB06RM2EF8oZSnNMt/uvFkKAx6QQ== + +react-native-app-intro-slider@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/react-native-app-intro-slider/-/react-native-app-intro-slider-4.0.4.tgz#fa5cda7057db62c448ac975ffd2ba0cff94cc8d8" + integrity sha512-Zkjaol6X3BbZkHUpVDj2LjdidpS6rCgKi0fx80xgGKa0pHxBRd4swWTv2bHnnvu5k1/HXwYk0mY2TbK+2jHl5w== + +react-native-argon2@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/react-native-argon2/-/react-native-argon2-2.0.1.tgz#eaa6fb77c76b8c85ad83dfa4507f83ba37285e4b" + integrity sha512-/iOi0S+VVgS1gQGtQgL4ZxUVS4gz6Lav3bgIbtNmr9KbOunnBYzP6/yBe/XxkbpXvasHDwdQnuppOH/nuOBn7w== + +react-native-biometrics@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/react-native-biometrics/-/react-native-biometrics-3.0.1.tgz#23c5a0bdbae1fcb1e08b22936223fe0fc4af846e" + integrity sha512-Ru80gXRa9KG04sl5AB9HyjLjVbduhqZVjA+AiOSGqr+fNqCDmCu9y5WEksnjbnniNLmq1yGcw+qcLXmR1ddLDQ== + +react-native-circular-progress-indicator@^4.4.0: + version "4.4.2" + resolved "https://registry.yarnpkg.com/react-native-circular-progress-indicator/-/react-native-circular-progress-indicator-4.4.2.tgz#5475d045950e6fcc622e54fb63863b274790fb8e" + integrity sha512-BlgshzIIIk0TP/CZY+5oyRsHl2Sb2l6cK5tzfmrVETfn6pN8dhOKrV0i3Z6i0SM8wRgncdUUSRBpCPAexh7JoQ== + dependencies: + react-native-redash "*" + +react-native-codegen@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.0.7.tgz#86651c5c5fec67a8077ef7f4e36f7ed459043e14" + integrity sha512-dwNgR8zJ3ALr480QnAmpTiqvFo+rDtq6V5oCggKhYFlRjzOmVSFn3YD41u8ltvKS5G2nQ8gCs2vReFFnRGLYng== + dependencies: + flow-parser "^0.121.0" + jscodeshift "^0.11.0" + nullthrows "^1.1.1" + +react-native-codegen@^0.70.6: + version "0.70.6" + resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.70.6.tgz#2ce17d1faad02ad4562345f8ee7cbe6397eda5cb" + integrity sha512-kdwIhH2hi+cFnG5Nb8Ji2JwmcCxnaOOo9440ov7XDzSvGfmUStnCzl+MCW8jLjqHcE4icT7N9y+xx4f50vfBTw== + dependencies: + "@babel/parser" "^7.14.0" + flow-parser "^0.121.0" + jscodeshift "^0.13.1" + nullthrows "^1.1.1" + +react-native-collapsible@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/react-native-collapsible/-/react-native-collapsible-1.6.0.tgz#ca261ffff16914f872059bb0972e3a78c4b37f9c" + integrity sha512-beZjdgbT9Y/Pg591Xy5XkKG20HffJiVad4n9bfcUF/f783A+tvOVXnqvbS58Lkaym93mi4jcDPMuW9Vc1t6rqg== + +react-native-config@^1.4.11: + version "1.4.11" + resolved "https://registry.yarnpkg.com/react-native-config/-/react-native-config-1.4.11.tgz#f9ea08a8dffbe3fd4f2187d80d2594756526dee8" + integrity sha512-PdBFnfR3pljUNrJu4B2wiJ9TbAiz1J1WcG5KP8AFBqZi8ve5MV/CTCDnANaGrqhOxkBDJV73D/SrMENHe7TKBg== + +react-native-device-info@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-10.3.0.tgz#6bab64d84d3415dd00cc446c73ec5e2e61fddbe7" + integrity sha512-/ziZN1sA1REbJTv5mQZ4tXggcTvSbct+u5kCaze8BmN//lbxcTvWsU6NQd4IihLt89VkbX+14IGc9sVApSxd/w== + +react-native-document-picker@^8.1.3: + version "8.1.3" + resolved "https://registry.yarnpkg.com/react-native-document-picker/-/react-native-document-picker-8.1.3.tgz#200b47c182d2d654747b5e41b5843fd378ac9d2e" + integrity sha512-lC+SZnzqIEE30x2CSHeZT+f7FzhQOTJprCNMRPpFVl4mLV9dDCJ/wZAmMByJFT79oQMPrzjlhhJlmjm+sVRUWQ== + dependencies: + invariant "^2.2.4" + +react-native-dropdown-picker@^5.4.3: + version "5.4.3" + resolved "https://registry.yarnpkg.com/react-native-dropdown-picker/-/react-native-dropdown-picker-5.4.3.tgz#adc16cfa52e8f3481220b377dd780040c3debf96" + integrity sha512-cwZzFcpyx/Stw3lZH2bvXxcsgwkR8c3rRZtOnlvyuN5pAplzA/9AiAxYlnJuspP9VvyU1XMePKOpgcHce6iyhA== + +react-native-fs@^2.20.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/react-native-fs/-/react-native-fs-2.20.0.tgz#05a9362b473bfc0910772c0acbb73a78dbc810f6" + integrity sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ== + dependencies: + base-64 "^0.1.0" + utf8 "^3.0.0" + +react-native-gesture-handler@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-2.8.0.tgz#ef9857871c10663c95a51546225b6e00cd4740cf" + integrity sha512-poOSfz/w0IyD6Qwq7aaIRRfEaVTl1ecQFoyiIbpOpfNTjm2B1niY2FLrdVQIOtIOe+K9nH55Qal04nr4jGkHdQ== + dependencies: + "@egjs/hammerjs" "^2.0.17" + hoist-non-react-statics "^3.3.0" + invariant "^2.2.4" + lodash "^4.17.21" + prop-types "^15.7.2" + +react-native-get-random-values@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/react-native-get-random-values/-/react-native-get-random-values-1.8.0.tgz#1cb4bd4bd3966a356e59697b8f372999fe97cb16" + integrity sha512-H/zghhun0T+UIJLmig3+ZuBCvF66rdbiWUfRSNS6kv5oDSpa1ZiVyvRWtuPesQpT8dXj+Bv7WJRQOUP+5TB1sA== + dependencies: + fast-base64-decode "^1.0.0" + +react-native-gradle-plugin@^0.70.3: + version "0.70.3" + resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.70.3.tgz#cbcf0619cbfbddaa9128701aa2d7b4145f9c4fc8" + integrity sha512-oOanj84fJEXUg9FoEAQomA8ISG+DVIrTZ3qF7m69VQUJyOGYyDZmPqKcjvRku4KXlEH6hWO9i4ACLzNBh8gC0A== + +react-native-keychain@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/react-native-keychain/-/react-native-keychain-8.1.1.tgz#3bb5e37946b964a7bcf7df2fe470dd244e01a340" + integrity sha512-8fxgeHKwGcL657eAYpdBTkDIxNhbIHI+kyyO0Yac2dgVAN184JoIwQcW2z6snahwDaCObQOu0biLFHnsH+4KSg== + +react-native-localize@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/react-native-localize/-/react-native-localize-2.2.4.tgz#3bc46ade48499ab9df61bf17a9b66633a5ba9bb9" + integrity sha512-gVmbyAEQQnBQ8vKlAQchFfIISeId3qT6Lc7LHmKF39nsYWX9KN4PHuG6Hk+7gduMI6IHKeZGKcLsOdh6wvN6cg== + +react-native-modal-popover@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/react-native-modal-popover/-/react-native-modal-popover-2.1.0.tgz#45a2060012796f29184e6c41b787f14336d3b435" + integrity sha512-t7KMk1q5Hi3jkk3/0fpa3mA7E3TJLL/Uz48Fa07AlocjMbG3okim9fNPLf5dJGw4JlcYWxLMYeswEcTjKr0M1g== + dependencies: + lodash "^4.17.21" + prop-types "^15.7.2" + +react-native-reanimated@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.13.0.tgz#d64c1386626822d4dc22094b4efe028ff2c49cc9" + integrity sha512-yUHyYVIegWWIza4+nVyS3CSmI/Mc8kLFVHw2c6gnSHaYhYA4LeEjH/jBkoMzHk9Xd0Ra3cwtjYKAMG8OTp6JVg== + dependencies: + "@babel/plugin-transform-object-assign" "^7.16.7" + "@babel/preset-typescript" "^7.16.7" + "@types/invariant" "^2.2.35" + invariant "^2.2.4" + lodash.isequal "^4.5.0" + setimmediate "^1.0.5" + string-hash-64 "^1.0.3" + +react-native-redash@*: + version "18.1.0" + resolved "https://registry.yarnpkg.com/react-native-redash/-/react-native-redash-18.1.0.tgz#ebebace19d0d2ed877cb6836b8c824b49354eb93" + integrity sha512-bdCFl/ZB7Rf2raIlU6SLV+Dc/rL6UXsQNjEVwTGBukHMeSKp1zs4zVtWaGimbN8P22N4qYvb9Jmw/K94ZWYG0Q== + dependencies: + abs-svg-path "^0.1.1" + normalize-svg-path "^1.0.1" + parse-svg-path "^0.1.2" + +react-native-render-html@^6.3.4: + version "6.3.4" + resolved "https://registry.yarnpkg.com/react-native-render-html/-/react-native-render-html-6.3.4.tgz#01684897bed2de84829e540a1dbb3a7bdf9d0e57" + integrity sha512-H2jSMzZjidE+Wo3qCWPUMU1nm98Vs2SGCvQCz/i6xf0P3Y9uVtG/b0sDbG/cYFir2mSYBYCIlS1Dv0WC1LjYig== + dependencies: + "@jsamr/counter-style" "^2.0.1" + "@jsamr/react-native-li" "^2.3.0" + "@native-html/transient-render-engine" "11.2.3" + "@types/ramda" "^0.27.40" + "@types/urijs" "^1.19.15" + prop-types "^15.5.7" + ramda "^0.27.2" + stringify-entities "^3.1.0" + urijs "^1.19.6" + +react-native-rsa-native@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/react-native-rsa-native/-/react-native-rsa-native-2.0.5.tgz#7db4aef49405bb5b5bcaea12b9dfd1b251c690ab" + integrity sha512-gwwvFSwGW5WKrpDyBQ/eTf1UrVABeAvMcT4YWemzPSUo6aHZs1kbBm2rXmwN5okhUzJsry5zjjz/qdx5GXRugQ== + +react-native-safe-area-context@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.4.1.tgz#239c60b8a9a80eac70a38a822b04c0f1d15ffc01" + integrity sha512-N9XTjiuD73ZpVlejHrUWIFZc+6Z14co1K/p1IFMkImU7+avD69F3y+lhkqA2hN/+vljdZrBSiOwXPkuo43nFQA== + +react-native-screens@^3.18.2: + version "3.18.2" + resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.18.2.tgz#d7ab2d145258d3db9fa630fa5379dc4474117866" + integrity sha512-ANUEuvMUlsYJ1QKukEhzhfrvOUO9BVH9Nzg+6eWxpn3cfD/O83yPBOF8Mx6x5H/2+sMy+VS5x/chWOOo/U7QJw== + dependencies: + react-freeze "^1.0.0" + warn-once "^0.1.0" + +react-native-share@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/react-native-share/-/react-native-share-8.0.1.tgz#797fe5648d6b2b0e00ab77d27f914ea9af6d67a0" + integrity sha512-3WfdW76L21heGq00NjtcBIM9XnaAi+P0FdLjIvEI0X+oNvYtReSOorzbYnvY3HGFbdmn6Kt1dJehGQVep25HNg== + +react-native-splash-screen@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.3.0.tgz#3af71ed17afe50fee69590a45aec399d071ead02" + integrity sha512-rGjt6HkoSXxMqH4SQUJ1gnPQlPJV8+J47+4yhgTIan4bVvAwJhEeJH7wWt9hXSdH4+VfwTS0GTaflj1Tw83IhA== + +react-native-svg-transformer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/react-native-svg-transformer/-/react-native-svg-transformer-1.0.0.tgz#7a707e5e95d20321b5f3dcfd0c3c8762ebd0221b" + integrity sha512-ALHU5VvLLyKM/BvyEG7VYJmqglvaXtU7mGRCxrEwwpJO/GBf1ZMUzc4AeJAjSodj7yYtlDYRxNSt9ySWpaa6JQ== + dependencies: + "@svgr/core" "^6.1.2" + "@svgr/plugin-svgo" "^6.1.2" + path-dirname "^1.0.2" + +react-native-svg@^13.6.0: + version "13.6.0" + resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-13.6.0.tgz#46e95a44aabbd778db7c46d8a1047da376b28058" + integrity sha512-1wjHCMJ8siyZbDZ0MX5wM+Jr7YOkb6GADn4/Z+/u1UwJX8WfjarypxDF3UO1ugMHa+7qor39oY+URMcrgPpiww== + dependencies: + css-select "^5.1.0" + css-tree "^1.1.3" + +react-native-toast-message@^2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/react-native-toast-message/-/react-native-toast-message-2.1.5.tgz#550acb9c6c0f1ee49c6b57b65a56d34e297eb723" + integrity sha512-mk3rELtBEhrhWBCN6CTaw0gypgL9ZNauX3xx1LUs4uee9vc0pVsghrKxO57vroUCcNL2hDeZSLJWdQNMCkGeaQ== + +react-native-user-inactivity@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/react-native-user-inactivity/-/react-native-user-inactivity-1.2.0.tgz#b0123951b89db9939eec07cffab724f7e76edcc6" + integrity sha512-VR+zv+cKBOSbJyHLJxvDUVluQ4OD/uW9FomAJVWrXCnSO4tYQieaAR3/5oNIfr6JXAJ/ChdJ/eyc06vHEBvlsA== + dependencies: + usetimeout-react-hook "^0.1.2" + +react-native-uuid@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/react-native-uuid/-/react-native-uuid-2.0.1.tgz#ed4e2dfb1683eddb66967eb5dca140dfe1abddb9" + integrity sha512-cptnoIbL53GTCrWlb/+jrDC6tvb7ypIyzbXNJcpR3Vab0mkeaaVd5qnB3f0whXYzS+SMoSQLcUUB0gEWqkPC0g== + +react-native-vector-icons@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-9.2.0.tgz#3c0c82e95defd274d56363cbe8fead8d53167ebd" + integrity sha512-wKYLaFuQST/chH3AJRjmOLoLy3JEs1JR6zMNgTaemFpNoXs0ztRnTxcxFD9xhX7cJe1/zoN5BpQYe7kL0m5yyA== + dependencies: + prop-types "^15.7.2" + yargs "^16.1.1" + +react-native-vision-camera@^2.15.2: + version "2.15.2" + resolved "https://registry.yarnpkg.com/react-native-vision-camera/-/react-native-vision-camera-2.15.2.tgz#96a17c8b4e557df317734897853a861e0cfbc3ed" + integrity sha512-pkVj0r2nbZaj3+bB9CGPNistCUyoCgS2SmawzugrZs5oMlFWlgZYuJj+6s3Q98xTGgV/8/ST0njohB6soDi0VA== + +react-native-webview@^11.23.0: + version "11.26.0" + resolved "https://registry.yarnpkg.com/react-native-webview/-/react-native-webview-11.26.0.tgz#e524992876fe4a79e69905f0fab8949b470e9f16" + integrity sha512-4T4CKRm8xlaQDz9h/bCMPGAvtkesrhkRWqCX9FDJEzBToaVUIsV0ZOqtC4w/JSnCtFKKYiaC1ReJtCGv+4mFeQ== + dependencies: + escape-string-regexp "2.0.0" + invariant "2.2.4" + +react-native@0.70.6: + version "0.70.6" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.70.6.tgz#d692f8b51baffc28e1a8bc5190cdb779de937aa8" + integrity sha512-xtQdImPHnwgraEx3HIZFOF+D1hJ9bC5mfpIdUGoMHRws6OmvHAjmFpO6qfdnaQ29vwbmZRq7yf14sbury74R/w== + dependencies: + "@jest/create-cache-key-function" "^27.0.1" + "@react-native-community/cli" "9.3.2" + "@react-native-community/cli-platform-android" "9.3.1" + "@react-native-community/cli-platform-ios" "9.3.0" + "@react-native/assets" "1.0.0" + "@react-native/normalize-color" "2.0.0" + "@react-native/polyfills" "2.0.0" + abort-controller "^3.0.0" + anser "^1.4.9" + base64-js "^1.1.2" + event-target-shim "^5.0.1" + invariant "^2.2.4" + jsc-android "^250230.2.1" + memoize-one "^5.0.0" + metro-react-native-babel-transformer "0.72.3" + metro-runtime "0.72.3" + metro-source-map "0.72.3" + mkdirp "^0.5.1" + nullthrows "^1.1.1" + pretty-format "^26.5.2" + promise "^8.3.0" + react-devtools-core "4.24.0" + react-native-codegen "^0.70.6" + react-native-gradle-plugin "^0.70.3" + react-refresh "^0.4.0" + react-shallow-renderer "^16.15.0" + regenerator-runtime "^0.13.2" + scheduler "^0.22.0" + stacktrace-parser "^0.1.3" + use-sync-external-store "^1.0.0" + whatwg-fetch "^3.0.0" + ws "^6.1.4" + +react-refresh@^0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.3.tgz#966f1750c191672e76e16c2efa569150cc73ab53" + integrity sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA== + +react-shallow-renderer@^16.15.0: + version "16.15.0" + resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457" + integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA== + dependencies: + object-assign "^4.1.1" + react-is "^16.12.0 || ^17.0.0 || ^18.0.0" + +react-test-renderer@18.1.0: + version "18.1.0" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-18.1.0.tgz#35b75754834cf9ab517b6813db94aee0a6b545c3" + integrity sha512-OfuueprJFW7h69GN+kr4Ywin7stcuqaYAt1g7airM5cUgP0BoF5G5CXsPGmXeDeEkncb2fqYNECO4y18sSqphg== + dependencies: + react-is "^18.1.0" + react-shallow-renderer "^16.15.0" + scheduler "^0.22.0" + +react@18.1.0: + version "18.1.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890" + integrity sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ== + dependencies: + loose-envify "^1.1.0" + +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readline@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" + integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg== + +recast@^0.20.3, recast@^0.20.4: + version "0.20.5" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.20.5.tgz#8e2c6c96827a1b339c634dd232957d230553ceae" + integrity sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ== + dependencies: + ast-types "0.14.2" + esprima "~4.0.0" + source-map "~0.6.1" + tslib "^2.0.1" + +reflect-metadata@^0.1.13: + version "0.1.13" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" + integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== + +regenerate-unicode-properties@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" + integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.2: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + +regexpp@^3.0.0, regexpp@^3.1.0, regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +regexpu-core@^5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc" + integrity sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsgen "^0.7.1" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regjsgen@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" + integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== + +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== + dependencies: + jsesc "~0.5.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== + +resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.18.1: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^2.0.0-next.3: + version "2.0.0-next.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" + integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^2.5.4: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rimraf@~2.2.6: + version "2.2.8" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" + integrity sha512-R5KMKHnPAQaZMqLOsyuyUmcIjSeDm+73eoqQpaXA7AZ22BL+6C+1mcUscgOsNd8WVlJuvlgAPsegcx7pjlV0Dg== + +rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +rn-fetch-blob@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/rn-fetch-blob/-/rn-fetch-blob-0.12.0.tgz#ec610d2f9b3f1065556b58ab9c106eeb256f3cba" + integrity sha512-+QnR7AsJ14zqpVVUbzbtAjq0iI8c9tCg49tIoKO2ezjzRunN7YL6zFSFSWZm6d+mE/l9r+OeDM3jmb2tBb2WbA== + dependencies: + base-64 "0.1.0" + glob "7.0.6" + +rsvp@^4.8.4: + version "4.8.5" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +rxjs@^7.2.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.6.0.tgz#361da5362b6ddaa691a2de0b4f2d32028f1eb5a2" + integrity sha512-DDa7d8TFNUalGC9VqXvQ1euWNN7sc63TrUCuM9J998+ViviahMIjKSOU7rfcgFOF+FCD71BhDRv4hrFz+ImDLQ== + dependencies: + tslib "^2.1.0" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sane@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== + dependencies: + "@cnakazawa/watch" "^1.0.3" + anymatch "^2.0.0" + capture-exit "^2.0.0" + exec-sh "^0.3.2" + execa "^1.0.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + +saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + +scheduler@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.22.0.tgz#83a5d63594edf074add9a7198b1bae76c3db01b8" + integrity sha512-6QAm1BgQI88NPYymgGQLCZgvep4FyePDWFpXVK+zNSUgHwlqpJy8VEh8Et0KxTACS4VWwMousBElAZOH9nkkoQ== + dependencies: + loose-envify "^1.1.0" + +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.2.1, semver@^7.3.2, semver@^7.3.5, semver@^7.3.7: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-error@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" + integrity sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw== + +serve-static@^1.13.1: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shallowequal@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@^1.6.1, shell-quote@^1.7.3: + version "1.7.4" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" + integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== + +shellwords@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" + integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== + dependencies: + is-arrayish "^0.3.1" + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.5.16, source-map-support@^0.5.6: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.3: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.12" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" + integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== + +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +stack-utils@^2.0.2: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +stackframe@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" + integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== + +stacktrace-parser@^0.1.3: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== + +string-hash-64@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string-hash-64/-/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322" + integrity sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw== + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.matchall@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" + integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.4.3" + side-channel "^1.0.4" + +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +stringify-entities@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-3.1.0.tgz#b8d3feac256d9ffcc9fa1fefdcf3ca70576ee903" + integrity sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg== + dependencies: + character-entities-html4 "^1.0.0" + character-entities-legacy "^1.0.0" + xtend "^4.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +sudo-prompt@^9.0.0: + version "9.2.1" + resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd" + integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-hyperlinks@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +svg-arc-to-cubic-bezier@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz#390c450035ae1c4a0104d90650304c3bc814abe6" + integrity sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g== + +svg-parser@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" + integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== + +svgo@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" + integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== + dependencies: + "@trysound/sax" "0.2.0" + commander "^7.2.0" + css-select "^4.1.3" + css-tree "^1.1.3" + csso "^4.2.0" + picocolors "^1.0.0" + stable "^0.1.8" + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +table@^6.0.9: + version "6.8.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +tar@^6.1.11: + version "6.1.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.13.tgz#46e22529000f612180601a6fe0680e7da508847b" + integrity sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^4.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +temp@0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.3.tgz#e0c6bc4d26b903124410e4fed81103014dfc1f59" + integrity sha512-jtnWJs6B1cZlHs9wPG7BrowKxZw/rf6+UpGAkr8AaYmiTyTO7zQlLoST8zx/8TcUPnZmeBoB+H8ARuHZaSijVw== + dependencies: + os-tmpdir "^1.0.0" + rimraf "~2.2.6" + +temp@^0.8.1, temp@^0.8.4: + version "0.8.4" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2" + integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg== + dependencies: + rimraf "~2.6.2" + +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +throat@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" + integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== + +through2@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tough-cookie@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" + integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + +tr46@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" + integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== + dependencies: + punycode "^2.1.1" + +tr46@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" + integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== + dependencies: + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +ts-toolbelt@^6.15.1: + version "6.15.5" + resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz#cb3b43ed725cb63644782c64fbcad7d8f28c0a83" + integrity sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A== + +tslib@^1.8.1, tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.1, tslib@^2.1.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" + integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== + +tsutils@^3.17.1, tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +tsyringe@^4.5.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/tsyringe/-/tsyringe-4.7.0.tgz#aea0a9d565385deebb6def60cda342b15016f283" + integrity sha512-ncFDM1jTLsok4ejMvSW5jN1VGPQD48y2tfAR0pdptWRKYX4bkbqPt92k7KJ5RFJ1KV36JEs/+TMh7I6OUgj74g== + dependencies: + tslib "^1.9.3" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typescript@^4.8.3: + version "4.9.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" + integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== + +uglify-es@^3.1.9: + version "3.3.9" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" + integrity sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ== + dependencies: + commander "~2.13.0" + source-map "~0.6.1" + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +update-browserslist-db@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urijs@^1.19.6: + version "1.19.11" + resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" + integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== + +url-parse@^1.4.7, url-parse@^1.5.10, url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +use-latest-callback@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.1.5.tgz#a4a836c08fa72f6608730b5b8f4bbd9c57c04f51" + integrity sha512-HtHatS2U4/h32NlkhupDsPlrbiD27gSH5swBdtXbCAlc6pfOFzaj0FehW/FO12rx8j2Vy4/lJScCiJyM01E+bQ== + +use-sync-external-store@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +usetimeout-react-hook@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/usetimeout-react-hook/-/usetimeout-react-hook-0.1.2.tgz#fdeaff9b8fe2b5e5b8d29a3ef9c4054368711c03" + integrity sha512-uHc8QsWDznEhWkK+ygX0xWxyObRjy72685EZ5wr3/ipNsK0EYntGnbenKxLNirPKKsng+1KW5CPTAk7qQDY8VQ== + +utf8@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utility-types@^3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" + integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@^8.3.0, uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +v8-to-istanbul@^7.0.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz#30898d1a7fa0c84d225a2c1434fb958f290883c1" + integrity sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +validator@^13.5.2: + version "13.7.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857" + integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw== + +varint@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0" + integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +vision-camera-code-scanner@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/vision-camera-code-scanner/-/vision-camera-code-scanner-0.2.0.tgz#8adc0694319a17f6a95f6dfacc02ab7ac29b4742" + integrity sha512-H5hVkXfbIcGdg9YlhuS8Y/xDX5e32Vo6eK5FyDQsE9AGVjlqEHMmSLHZg7BX8UUm4ADmiAZc8wzc4n8TUqGr0g== + +vlq@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468" + integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w== + +void-elements@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" + integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== + +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + +w3c-xmlserializer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz#06cdc3eefb7e4d0b20a560a5a3aeb0d2d9a65923" + integrity sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg== + dependencies: + xml-name-validator "^4.0.0" + +walker@^1.0.7, walker@~1.0.5: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +warn-once@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/warn-once/-/warn-once-0.1.1.tgz#952088f4fb56896e73fd4e6a3767272a3fccce43" + integrity sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q== + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + +web-did-resolver@^2.0.8: + version "2.0.21" + resolved "https://registry.yarnpkg.com/web-did-resolver/-/web-did-resolver-2.0.21.tgz#065797dee3e37cd9f19261d04a90144fe576e5df" + integrity sha512-vKYz0s9spYfYrKhrF88F44lkofS1yj6TCF40+i077a7boru2BNROl5VZEIVL9jJRUDsNzvmVSKkq3kS8kZnB2Q== + dependencies: + cross-fetch "^3.1.5" + did-resolver "^4.0.0" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-encoding@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" + integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== + dependencies: + iconv-lite "0.6.3" + +whatwg-fetch@^3.0.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" + integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-mimetype@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" + integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== + +whatwg-url@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-10.0.0.tgz#37264f720b575b4a311bd4094ed8c760caaa05da" + integrity sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w== + dependencies: + tr46 "^3.0.0" + webidl-conversions "^7.0.0" + +whatwg-url@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" + integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== + dependencies: + tr46 "^3.0.0" + webidl-conversions "^7.0.0" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +whatwg-url@^8.0.0, whatwg-url@^8.5.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" + integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== + dependencies: + lodash "^4.7.0" + tr46 "^2.1.0" + webidl-conversions "^6.1.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +word-wrap@^1.2.3, word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^2.3.0: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^6.1.4: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e" + integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw== + dependencies: + async-limiter "~1.0.0" + +ws@^7, ws@^7.4.6, ws@^7.5.1: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + +ws@^8.2.3: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" + integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xml-name-validator@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" + integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^1.10.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs@^15.1.0, yargs@^15.3.1, yargs@^15.4.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yargs@^16.1.1: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==