diff --git a/.detoxrc.json b/.detoxrc.json index 271e099258..5f25c571ff 100644 --- a/.detoxrc.json +++ b/.detoxrc.json @@ -24,7 +24,7 @@ "build": "cd android && ENVFILE=.env.mock ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd ..", "type": "android.emulator", "device": { - "avdName": "Nexus_5X_API_29_x86" + "avdName": "Nexus_6_API_30" } }, "android.staging": { @@ -33,7 +33,16 @@ "build": "cd android && ENVFILE=.env.mock ./gradlew assembleStagingRelease assembleAndroidTest -DtestBuildType=stagingRelease && cd ..", "type": "android.emulator", "device": { - "avdName": "Nexus_5X_API_29_x86" + "avdName": "Nexus_6_API_30" + } + }, + "android.staging-ci": { + "binaryPath": "android/app/build/outputs/apk/stagingRelease/app-x86-stagingRelease.apk", + "testBinaryPath": "android/app/build/outputs/apk/androidTest/stagingRelease/app-stagingRelease-androidTest.apk", + "build": "cd android && ENVFILE=.env.mock ./gradlew assembleStagingRelease assembleAndroidTest -DtestBuildType=stagingRelease -PwithTestButler --warning-mode all && cd ..", + "type": "android.emulator", + "device": { + "avdName": "Nexus_6_API_30" } } } diff --git a/.github/workflows/detox-ci.yml b/.github/workflows/detox-ci.yml new file mode 100644 index 0000000000..d9aa957a2f --- /dev/null +++ b/.github/workflows/detox-ci.yml @@ -0,0 +1,76 @@ +name: Detox E2E CI + +on: + pull_request: + branches: + - "*" + workflow_dispatch: + inputs: + prNumber: + description: pr number to trigger on + required: true + schedule: + - cron: "0 0 * * *" + +jobs: + ios: + runs-on: macos-latest + steps: + - name: Checkout PR + uses: actions/checkout@v2 + with: + ref: ${{github.event.pull_request.head.ref}} + repository: ${{github.event.pull_request.head.repo.full_name}} + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 # Not needed with a .ruby-version file + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + + - name: Install applesimutils + run: | + brew tap wix/brew + brew install applesimutils + + - name: Setup Node + uses: actions/setup-node@v2 + with: + node-version: 14 + cache: 'yarn' + + - name: Has hash commit deps + uses: ledgerhq/actions/packages/has-hash-commit-deps@main + id: has-hash-commit-deps + with: + workspace: ${{ github.workspace }} + + - name: Install dependencies without network concurrency + if: ${{ steps.has-hash-commit-deps.outputs.has-hash-commit-deps == 'true' }} + env: + JOBS: max + run: yarn --prefer-offline --frozen-lockfile --network-timeout 100000 --network-concurrency 1 + + - name: Install dependencies with network concurrency + if: ${{ steps.has-hash-commit-deps.outputs.has-hash-commit-deps == 'false' }} + env: + JOBS: max + run: yarn --prefer-offline --frozen-lockfile --network-timeout 100000 + + - name: Rebuild detox + run: yarn detox clean-framework-cache && yarn detox build-framework-cache + + - name: Build iOS app for Detox test run + env: + NODE_OPTIONS: "--max-old-space-size=7168" + run: yarn e2e:build -c ios.staging + + - name: Test iOS app + timeout-minutes: 15 + run: yarn e2e:test -c ios.staging --loglevel verbose --record-logs failing --record-timeline all --take-screenshots all --record-videos failing --detectOpenHandles + - name: Upload test artifacts + if: always() + uses: actions/upload-artifact@v2 + with: + name: test-ios-artifacts + path: artifacts diff --git a/README.md b/README.md index c0ed11a638..0fab1bc7d3 100644 --- a/README.md +++ b/README.md @@ -22,14 +22,20 @@ It communicates with the [Ledger Nano X](https://www.ledger.com/pages/ledger-nan - Node LTS version - Yarn 1.10.1 or above +- [Full React Native environment setup instructions here, **under "React Native CLI Quickstart" tab**](https://reactnative.dev/docs/environment-setup) ### iOS - XCode +- Ruby 2.6.8 or above. The macOS built-in Ruby [does not work properly for installing dependencies of the iOS app](https://jeffreymorgan.io/articles/ruby-on-macos-with-rvm/), you have to install Ruby with for instance [Homebrew](https://brew.sh/) or [rvm](https://rvm.io/rvm/install) and make sure that `which ruby` points to that newly installed Ruby. ### Android - Android Studio +- JDK 11 +- Required SDK tools: (go to Android Studio > Tools > SDK Manager > SDK Tools > check "Show Package Details" at the bottom right) + - Android NDK 21.4.7075529 (in case this doc is outdated, check the version specified as `ndkVersion` in `android/build.gradle`) + - CMake 3.10.2 ## Scripts diff --git a/TERMS.es.md b/TERMS.es.md deleted file mode 100644 index f431e9de13..0000000000 --- a/TERMS.es.md +++ /dev/null @@ -1,220 +0,0 @@ -# Condiciones de uso de Ledger Live - -_10 de diciembre de 2019_ - -Estás a punto de utilizar la plataforma Ledger Live. ¡Nos alegramos por ti! Antes de empezar, es necesario que leas atentamente, entiendas y aceptes nuestras condiciones de uso (las o estas "Condiciones de uso"). - -Preámbulo - -Este acuerdo se celebra entre el usuario (el "Usuario" o "tú") y Ledger SAS ("Ledger", "nosotros" o la "Sociedad"). Al usar cualquiera de los servicios prestados por Ledger o sus filiales en relación con el software Ledger Live (los "Servicios de Ledger") o hacer clic en "Acepto" para cualquiera de dichos servicios, el Usuario reconoce haber leído atentamente y aceptar en su totalidad las condiciones de uso que se exponen a continuación. - -El uso de los Servicios de Ledger también está sujeto a su Política de privacidad, disponible en [**https://shop.ledger.com/pages/politica-de-privacidad**](https://shop.ledger.com/pages/politica-de-privacidad). - -ANTES DE HACER USO DE LOS SERVICIOS, PREPÁRATE PARA TOMAR DECISIONES INFORMADAS. EL VALOR DE LOS CRIPTOACTIVOS ES INESTABLE. LOS PRECIOS PUEDEN SUBIR Y BAJAR. EVALÚA CUIDADOSAMENTE TUS OBJETIVOS Y EL RIESGO FINANCIERO QUE ESTÁS DISPUESTO/A A ASUMIR. NO OLVIDES QUE LEDGER NO PROPORCIONA ASESORAMIENTO FINANCIERO, TRIBUTARIO O JURÍDICO. DEBES TOMAR LAS DECISIONES DE LLEVAR A CABO OPERACIONES CON CRIPTOACTIVOS BASÁNDOTE EN TUS PROPIOS CONOCIMIENTOS O EN LA OPINIÓN DE EXPERTOS FIABLES Y CUALIFICADOS. - -Definiciones - -Los términos siguientes tienen en este acuerdo el significado que se indica a continuación, quedando entendido, para evitar cualquier confusión, que en dichas definiciones el singular incluye el plural y viceversa, excepto si es manifiestamente impropio. - -" **Criptoa\*\*** ctivos\*\* -significa cualquier tipo de activo digital que puede transmitirse mediante tecnologías blockchain, como Bitcoin, Ethereum, Ripple, entre otros. - -" **Aplicación de dispositivo"** -hace referencia a una aplicación de software desarrollada por Ledger o por un tercero que incorpora una clave de firma criptográfica específica en el sistema operativo BOLOS, de Ledger, para crear una transacción en Ledger Live o en una aplicación de terceros, y permite firmar diferentes operaciones con un Dispositivo Ledger, en particular: transmisión de transacciones con criptoactivos, autenticación, gestión de contraseñas. - -" **Bifurcación**" -hace referencia a un cambio del protocolo subyacente de una red blockchain que lleva a varias versiones de un Criptoactivo, lo que puede dar lugar a una o varias versiones que ya no son compatibles con los Servicios de Ledger. - -" **Dispositivo Ledger"** -es un dispositivo electrónico desarrollado y distribuido por Ledger, generalmente conocido como "cartera hardware" y utilizado para gestionar y aportar seguridad a las Claves privadas de los Usuarios y demás secretos criptográficos, compatible con Ledger Live o con Carteras compatibles. - -" **Gestor Ledger Live"** -es un catálogo de Aplicaciones de dispositivo que se pueden descargar y permiten a los Usuarios actualizar el microprograma de su Dispositivo Ledger, instalar Aplicaciones de dispositivo y gestionar Criptoactivos compatibles. - -" **Contenidos"** -hace referencia a los contenidos, a la documentación del Servicio de Ledger, así como a los códigos fuente y códigos objeto de todos los programas integrados en Ledger Live y los Dispositivos Ledger. - -" **PIN"** -es el número de identificación personal escogido por el Usuario para abrir un Dispositivo Ledger. - -" **Clave privada"** -hace referencia a un conjunto crítico de datos que sirve para autorizar las transacciones salientes en las redes blockchain. - -" **Servicios" ** -hace referencia a uno o varios Servicios de Ledger o Servicios de terceros. - -" **Servicios de terceros"** -hace referencia a aplicaciones, programas u otros Contenidos albergados, desarrollados o explotados por un tercero, como por ejemplo intercambios de criptomoneda o proveedores de servicios de staking. - -" **Cartera"** -hace referencia a un programa que interactúa con varias redes blockchain para generar y gestionar conjuntos de claves privadas y públicas, configurar transacciones y controlar su saldo. - -" **Sitio web" ** -hace referencia a los sitios web que son propiedad de Ledger o que Ledger explota, incluido el sitio web de comercio electrónico y corporativo hospedado en ledger.com. - -" **Frase de recuperación de 24 palabras"** -significa una combinación confidencial de palabras directamente legibles por una persona, generada por Dispositivos Ledger, de la cual derivan las Claves privadas de los Usuarios. Sirven para archivar y recuperar el acceso a los Criptoactivos en otros Dispositivos Ledger o en Carteras compatibles. - -Admisibilidad - -Para poder utilizar los Servicios hay que haber cumplido 18 años o tener la condición de adulto en el país de residencia. Si utilizas los Servicios en nombre de una persona jurídica, tienes que declarar y garantizar además que: (a) la persona jurídica está debidamente constituida y en actividad de acuerdo con las leyes del país donde está registrada; (b) estás debidamente autorizado por dicha persona jurídica para actuar en su nombre. - -Solo puedes utilizar los Servicios si las leyes de tu país lo permiten. El Usuario deberá comprobar que estas Condiciones de uso son conformes a las leyes, reglamentos y normas que le son aplicables. - -Servicios de Ledger - -Ledger Live te proporciona, junto con los Dispositivos Ledger, una forma práctica y segura de gestionar tus Aplicaciones de dispositivo, así como de usar tus Claves privadas derivadas de tu Frase de recuperación de 24 palabras. - -Los Servicios de Ledger permiten al Usuario: - -- Actualizar el microprograma de su Dispositivo Ledger. -- Instalar y desinstalar Aplicaciones de dispositivo con el Gestor Ledger Live. -- Ver su cartera de Criptoactivos. -- Acceder a los sistemas para llevar a cabo operaciones en varias redes blockchain conforme a sus protocolos respectivos, como por ejemplo: enviar a Usuarios de una red blockchain específica y recibir de ellos Criptoactivos. -- Conectar con Servicios de terceros para acceder a servicios como la delegación de derechos de staking en blockchains con prueba de participación compatibles o comprar Criptoactivos. - -Ledger no presta servicios de custodia, lo cual significa que no conservamos en depósito ni tenemos acceso a tus Criptoactivos o Claves privadas. No recibimos ni mandamos Criptoactivos. Las transferencias de Criptoactivos se llevan a cabo en redes blockchain y no en una red propiedad de Ledger o controlada por Ledger. - -Ledger Live y los Dispositivos Ledger solo funcionan con determinados Criptoactivos. Una lista no exhaustiva de dichos Criptoactivos y de Carteras compatibles está disponible [aquí](about:blank#targetText=Ledger%20Live%20supports%2022%20crypto,as%20send%20and%20receive%20them.). Dicha lista podrá sufrir cambios. - -Riesgo - -Se considera que estás plenamente informado del conjunto de normas legales y limitaciones técnicas relativas a las cadenas de bloques (blockchains), sus pruebas de participación (PoS) y sus pruebas de trabajo (PoW), así como a los Servicios. Reconoces haber sido avisado de los siguientes riesgos asociados: - -**Cambios normativos.** Las tecnologías blockchain están sujetas a continuos cambios normativos y a controles en todo el mundo, lo que incluye, por ejemplo, las normativas financieras y de lucha contra el blanqueo de capitales. Reconoces que determinados Servicios, así como su disponibilidad, pueden verse afectados por una o varias exigencias normativas. - -**Régimen tributario.** Las transacciones con Criptoactivos, y en general cualquier hecho relacionado con Criptoactivos, como por ejemplo intercambios, _airdrops_, bifurcaciones y ganancias de staking, podrán ser considerados hechos imponibles de acuerdo con la legislación tributaria que te sea aplicable. Dichas normas pueden ser confusas o propensas a cambios, por lo que te recomendamos que consultes a tu propio asesor fiscal o contable antes de realizar movimientos con Criptoactivos. - -**Tecnología.** Los Usuarios entienden que las tecnologías utilizadas o puestas a disposición por los Servicios son nuevas, no probadas y ajenas al control de Ledger. Los progresos en materia de criptografía, u otros avances tecnológicos como el desarrollo de ordenadores cuánticos, pueden presentar riesgos para las redes blockchain que podrían conllevar robos o pérdidas de Criptoactivos. Otros cambios negativos en las fuerzas del mercado o en la tecnología, en su sentido amplio, pueden impedir o dificultar el funcionamiento de Ledger conforme a estas Condiciones de uso. - -**Ciberseguridad. ** Piratas informáticos u otros grupos u organizaciones podrían intentar interferir con los productos y sistemas de información de Ledger de distintas formas, en particular mediante ataques de denegación de servicio, ataques de canal lateral, suplantación de identidad, ataques smurf, programas malintencionados o ataques relacionados con los algoritmos de consenso. - -Pueden darse otros riesgos que no hemos previsto o identificado en estas Condiciones de uso. Antes de utilizar nuestros Servicios, te recomendamos encarecidamente que compruebes con atención si dicho uso es compatible con tu situación financiera y tu tolerancia al riesgo. - -Para evitar cualquier duda, y sin perjuicio de las estipulaciones generales de la cláusula de limitación de responsabilidad, por la presente admites que Ledger no será responsable de ninguna pérdida sufrida como consecuencia de los riesgos mencionados en esta cláusula. - -Ausencia de recuperación de Claves privadas. - -**La única copia de seguridad existente será la que tú poseas.** Ledger no archiva ni tiene acceso a las contraseñas, Frase de recuperación de 24 palabras, Claves privadas, frases de contraseña, historial de transacciones, PIN u otras credenciales asociadas a tu uso de los Servicios. No estamos en situación de ayudarte a recuperar tus credenciales. El Usuario será el único responsable de recordar, almacenar y conservar en lugar seguro sus credenciales, a salvo de miradas indiscretas. Cualquier tercero que conozca uno o varios elementos de tu Frase de recuperación de 24 palabras o PIN podrá conseguir hacerse con el control de las Claves privadas asociadas a tu Dispositivo Ledger o de tu Frase de recuperación de 24 palabras. - -**Conserva en lugar seguro tus credenciales** Al configurar tu Dispositivo Ledger, deberás: (a) crear y memorizar un PIN seguro que no utilizarás para ningún otro servicio; (b) proteger y mantener la seguridad y la confidencialidad de tu Frase de recuperación de 24 palabras; (c) proteger el acceso a tu Dispositivo Ledger. - -Uso aceptable - -Como Usuario de los Servicios de Ledger, te otorgamos una licencia limitada, personal, no comercial, no exclusiva, intransferible y revocable para el uso de los Servicios Ledger. Al utilizar los Servicios de Ledger, pedimos que acates determinadas reglas básicas: - -**No causar daños.** Te comprometes a (i) no difundir ningún virus ni otro código informático dañino a través de los sistemas de Ledger; (ii) no hacer uso de ningún robot, rastreador, recolector u otros medios automatizados o interfaz que no hayamos provisto para acceder a los Servicios de Ledger o extraer datos; (iii) no proporcionar información falsa, inexacta o engañosa; (iv) abstenerte de cualquier acción que suponga una carga excesiva o desproporcionada para nuestra infraestructura o la de un tercero proveedor. - -**No eludir nuestra seguridad.** Te comprometes a no burlar, eludir ni intentar burlar o eludir cualquiera de las medidas que tomamos para impedir o restringir el acceso a los Servicios de Ledger, en particular los Dispositivos Ledger conectados a los Servicios de Ledger, otras cuentas, sistemas de información o redes. - -**No infringir la ley.** Te comprometes a no transgredir ninguna ley al hacer uso de los Servicios de Ledger. Por ley entendemos cualquier norma local, provincial, estatal, federal, nacional o internacional que te sean aplicables. Asimismo, te comprometes a no recurrir a los Servicios de Ledger para financiar, apoyar o incurrir de alguna otra forma en actividades ilegales, como por ejemplo fraude, juego ilegal, blanqueo de capitales o actividades terroristas. Te comprometes además a no incitar ni inducir a terceros a llevar a cabo cualquiera de las actividades prohibidas en esta cláusula. - -**No interferir.** Te comprometes a no utilizar ni intentar utilizar la Cartera de otro usuario sin su permiso, y a no utilizar los Servicios de Ledger de ninguna forma que pueda impedir que otros Usuarios disfruten plenamente de los Servicios de Ledger, así como interrumpir, afectar o limitar dicho uso, o que pueda dañar, desactivar, sobrecargar o perturbar de cualquier forma el funcionamiento de los Servicios de Ledger. - -Cualquier uso de los Servicios de Ledger que no esté específicamente autorizado por estas Condiciones de uso sin nuestro permiso previo por escrito queda terminantemente prohibido y pondría fin a tu licencia de uso de los Servicios de Ledger. - -Garantías y exenciones - -Ledger hará lo posible movilizando su pericia y cuidado para que puedas tener acceso a los Servicios de Ledger conforme a estas Condiciones de uso, pero no puede garantizar que dicho acceso y prestaciones no sufrirán interrupciones o retrasos, fallos, errores, omisiones, degradaciones o pérdidas de la información transmitida. Los Servicios de Ledger se prestan «en su forma actual», sin garantía de ninguna índole, ya sea expresa o implícita, y en particular sin garantías implícitas de comerciabilidad, fiabilidad y adecuación a una finalidad dada. - -Disponibilidad de los Servicios de Ledger - -Podremos modificar, actualizar o suspender los Servicios, temporal o definitivamente, para llevar a cabo tareas como las siguientes: actualización de microprogramas y programas, tareas de mantenimiento, modificación de los servidores, corrección de errores, etc. Haremos lo posible para informarte por adelantado de cualquier interrupción significativa de los Servicios de Ledger. - -Ledger no garantiza el correcto funcionamiento de los Servicios en caso de instalación o uso de programas o aplicaciones que no sean conformes con las especificaciones y las normas técnicas del Servicio. - -Ten en cuenta que en caso de indisponibilidad o interrupción de un Servicio de Ledger, siempre podrás recuperar tus Claves privadas mediante tu Frase de recuperación de 24 palabras en una Cartera compatible. - -Protocolos blockchain subyacentes - -Todas las transacciones creadas con los Servicios de Ledger se confirman y registran en redes blockchain asociadas. Dichas redes son redes de pares descentralizadas y están gestionadas por terceros independientes, que Ledger no posee, controla ni explota. No controlamos las redes blockchain y, en consecuencia, no podemos garantizar ni garantizamos que las transacciones que emitas mediante los Servicios de Ledger serán confirmadas y procesadas. Reconoces que no conservamos, enviamos ni recibimos Criptoactivos y aceptas que las transacciones que configures mediante los Servicios de Ledger pueden fallar o sufrir retrasos importantes debido a las redes blockchain subyacentes. - -El protocolo blockchain de un determinado Criptoactivo podrá sufrir cambios en algún momento, lo que podrá tener consecuencias en sus características básicas, como su disponibilidad, nombre, seguridad, valoración o forma de operar. En caso de bifurcación los Criptoactivos afectados podrán desviarse o reproducirse. En tal caso, Ledger podrá decidir, a su entera discreción, suspender su apoyo al Criptoactivo afectado el tiempo que considere necesario. En tal caso, Ledger procurará avisarte por adelantado, aunque puede no estar en condiciones de hacerlo. Conviene que te mantengas informado de ese tipo de incidentes y tomes las decisiones necesarias. - -Aplicaciones de dispositivo - -Las Aplicaciones de dispositivo pueden descargarse desde elGestor Ledger Live, o instalarse aplicando nuestras [directrices](about:blank). Podrán ser desarrolladas porLedger o por cualquier tercero que lo desee, gracias al código fuente abierto disponible en el [repositorio en Github](about:blank) de Ledger. - -Los desarrolladores de Aplicaciones de Dispositivo son responsables de dichas aplicaciones y de su funcionamiento, y les incumbe proporcionar asistencia para las Aplicaciones de Dispositivo asociadas a un Dispositivo Ledger y a Ledger Live. Ledger puede llevar a cabo exámenes de códigos y auditorías de seguridad de las Aplicaciones de Dispositivo disponibles en el Gestor Ledger Live, lo cual no constituye habilitación alguna ni ninguna garantía de que dichas aplicaciones no entrañan riesgo. - -Ledger no garantiza que las Aplicaciones de Dispositivo serán mantenidas en el tiempo y se reserva el derecho de restringir o suspender el acceso a ellas a partir de los Servicios de Ledger por cualquier motivo si lo considera necesario. - -Propiedades experimentales - -Para responder a las solicitudes de los Usuarios confirmados y aportar nuevas propiedades y funcionalidades, hemos añadido varias propiedades experimentales a Ledger Live. Estas propiedades pueden no estar completas y no haber sido plenamente probadas, lo cual supone riesgos añadidos. Pueden contener errores o inexactitudes y causar fallos, degradaciones o pérdidas de datos o de información. Puedes considerar dichas propiedades como propiedades beta. Ledger no garantiza la estabilidad, funcionalidad o mantenimiento a largo plazo de dichas propiedades. No recomendamos el uso de dichas propiedades si no eres un Usuario confirmado con buenos conocimientos técnicos. Reconoces expresamente que el uso de Propiedades experimentales es por tu cuenta y riesgo. - -Detalles de las transacciones - -**No te fíes. Comprueba.** La integridad de un software, en particular en caso de conexión a internet, es muy difícil de comprobar. El modelo de seguridad de Ledger se basa en la confianza en lo que aparece en la pantalla. Por ello, es primordial comprobar la información que aparece en tu Dispositivo Ledger. Antes de aprobar una transacción, siempre tienes que comprobar por duplicado que la información que aparece en la pantalla de tu móvil u ordenador es correcta y corresponde a la que aparece en tu Dispositivo Ledger. Cuando mandas Criptoactivos, eres el único responsable de comprobar que la dirección del destinatario, el importe y los costes son correctos y que son iguales en tu ordenador o móvil y en la pantalla de tu Dispositivo Ledger. También reconoces que utilizar direcciones sin comprobar para recibir Criptoactivos corre por tu cuenta y riesgo. - -Servicios y Contenidos de terceros - -Ledger Live puede incorporar, hacer referencia o dar acceso a Servicios de terceros. - -El Usuario reconoce que el uso de Servicios de terceros está regido por otras condiciones pactadas entre él y el tercero identificado en Ledger Live. Ledger no se responsabiliza del funcionamiento o de los posibles fallos de los Servicios de terceros. Comprobar las condiciones de uso y las prácticas de los terceros antes de usar Servicios de terceros es tu responsabilidad. Algunos Servicios de terceros pueden exigir o exigen el acceso a tus datos personales. El tratamiento de dichos datos será llevado a cabo conforme a las normas de privacidad y a las buenas prácticas de dicho tercero pertinentes. - -Los Servicios de terceros pueden no funcionar adecuadamente con tu software o Dispositivo Ledger, y puede que no podamos prestar asistencia para problemas causados por Servicios de terceros. Si tienes preguntas o dudas en cuanto al funcionamiento de un Servicio de terceros o si necesitas asistencia, tienes que dirigirte directamente al tercero en cuestión. - -Recomendamos no compartir credenciales, contraseñas, Claves privadas, frases de contraseña ni ningún otro dato sensible con un Servicio de terceros antes de comprobar su legitimidad. - -Conservamos el derecho exclusivo de añadir, modificar o cancelar la disponibilidad de un Servicio de terceros por cualquier motivo y sin preaviso. - -Los siguientes Servicios están sujetos a normas y obligaciones específicas: - -**A. Servicios Buy Crypto** - -Los enlaces a servicios Buy Crypto son enlaces patrocinados. Un enlace a o desde uno de los Servicios de Ledger no constituye ni supone adhesión alguna a dichos servicios. - -**B. Delegación de derechos de staking** - -**Recompensas.** Confirmas de forma explícita que sabes que la delegación de derechos de staking a un validador de la lista de Ledger Live no te atribuye derecho alguno a pedir un pago de cualquier índole, sino únicamente el derecho potencial a compartir una recompensa recibida por el validador. Recuerda que los periodos de bloqueo dependen del validador y de los protocolos de la blockchain. - -**Validadores.** Ledger se reserva el derecho de modificar la lista de validadores registrados en cualquier momento, sin preaviso. - -Limitación de responsabilidad - -ENTIENDES Y ACEPTAS EXPRESAMENTE QUE LEDGER, ASÍ COMO SUS ADMINISTRADORES Y EMPLEADOS, NO PODRÁN SER CONSIDERADOS RESPONSABLES POR DAÑOS DIRECTOS, INDIRECTOS, INCIDENTES, ESPECIALES, CONSECUENTES O PUNITIVOS, LO QUE INCLUIRÁ, ENTRE OTROS, LOS DAÑOS POR LUCRO CESANTE, PÉRDIDAS DE FONDO DE COMERCIO, USO O DATOS, GASTOS DE ADQUISICIÓN DE BIENES O SERVICIOS DE SUSTITUCIÓN U OTROS DAÑOS INTANGIBLES, CAUSADOS POR: (I) EL USO O LA INDISPONIBILIDAD DE LOS SERVICIOS; (II) UN CAMBIO EN EL SERVICIO O SU SUSPENSIÓN TOTAL O PARCIAL; (III) EL ACCESO NO AUTORIZADO A TUS TRANSMISIONES O DATOS, O SU ALTERACIÓN; (IV) LA DESTRUCCIÓN, DEGRADACIÓN O IMPOSIBILIDAD DE ALMACENAR, MANDAR O RECIBIR TUS TRANSMISIONES O DATOS MEDIANTE EL SERVICIO; Y (V) CUALQUIER OTRA INCIDENCIA RELACIONADA CON EL SERVICIO. - -LAS LIMITACIONES ANTERIORES NO SERÁN DE APLICACIÓN EN CASO DE PÉRDIDAS CAUSADAS POR (A) FRAUDE, CONDUCTA DOLOSA O NEGLIGENCIA GRAVE DE LEDGER; O (B) FALLECIMIENTO O DAÑO CORPORAL. - -Propiedad intelectual - -Ledger respeta la propiedad intelectual de los terceros y pedimos lo mismo a nuestros Usuarios. Reconoces y aceptas que, excepto los Contenidos publicados o disponibles de alguna otra forma en virtud de acuerdos de licencia pública, fuente abierta, MIT y otros tipos de licencias de dominio público utilizados normalmente por la comunidad de Ledger, Ledger es la propietaria de todos los derechos de autor, marcas, conocimientos técnicos y cualesquiera otros derechos de propiedad intelectual relativos al programa, texto, vídeo, audio, grafismo, logotipo, diseño, así como al aspecto y las propiedades, de Ledger Live, las Aplicaciones de Dispositivo y el Sitio web. - -Puedes ver, imprimir y descargar una copia de los Contenidos con derechos de propiedad de los Servicios de Ledger en un ordenador individual para tu uso personal, informacional o no comercial, siempre que respetes todos los derechos de autor y demás avisos de derechos de propiedad. - -Las marcas, marcas de servicio y logotipos de Ledger y otros utilizados en los Servicios (las "Marcas") son propiedad de Ledger y de sus propietarios respectivos. Queda terminantemente prohibido utilizar las Marcas sin nuestro permiso expreso por escrito o el permiso expreso por escrito de terceros. - -Observaciones - -Agradecemos las observaciones, comentarios, ideas y sugerencias para mejorar los Servicios (las "Observaciones"). Nos concedes una licencia no exclusiva, mundial, perpetua, irrevocable, pagada, sin regalías, con posibilidad de sublicencia, y transferible sobre cualquier derecho de propiedad intelectual que poseas o controles, para usar, copiar, modificar, crear obras derivadas y explotar de cualquier modo las Observaciones. - -Conformidad y control de exportaciones - -El Usuario debe cumplir, por su cuenta, con todas las leyes que sean aplicables a sus obligaciones en virtud de estas Condiciones de uso o se deriven de las mismas. Al acceder y usar los Servicios, declaras y garantizas que no figuras en ninguna lista de sanciones comerciales o económicas, como por ejemplo la Lista de sanciones del Consejo de Seguridad de las Naciones Unidas, que no has sido considerado como un ciudadano especialmente designado (_Specially Designated National_) por el OFAC (_Office of Foreign Assets Control_ del Departamento del Tesoro de Estados Unidos) ni inscrito en la lista de personas no autorizadas (_Denied Persons List_) del Departamento de Comercio de EE. UU. - -Ledger se reserva el derecho de seleccionar los mercados y países donde desarrolle su actividad y podrá restringir o denegar el acceso a los Servicios de Ledger en determinados países, estados o territorios. - -Rescisión - -Podrás dejar de utilizar los Servicios en cualquier momento. Nos reservamos el derecho de suspender tu acceso a los Servicios de Ledger sin preaviso si consideramos que has infringido estas Condiciones de uso. En caso de rescisión de tu licencia de uso de Ledger, tus obligaciones en virtud de estas Condiciones de uso seguirán vigentes. - -El acceso a tus Carteras después de la rescisión dependerá del grado de seguridad con el que hayas protegido tus Claves privadas y la dirección de tu Cartera. - -Derecho aplicable - -Estas Condiciones de uso se rigen e interpretan conforme al derecho de Francia. - -Cualquier litigio, desavenencia, desacuerdo o reclamación en relación con estas Condiciones de uso en cuanto a su existencia, validez, interpretación, cumplimiento, incumplimiento o rescisión, o cualquier desacuerdo sobre obligaciones extracontractuales relacionado con estas Condiciones de uso o que se derive de las mismas, será de la competencia de los tribunales pertinentes de París, Francia. - -Cumplimiento y cesión de estas Condiciones de uso - -Estas Condiciones de uso constituyen la totalidad y exclusividad del entendimiento y del acuerdo entre Ledger y el Usuario en relación con los Servicios de Ledger, y sustituyen cualquier entendimiento o acuerdo anterior, ya sea oral o por escrito, entre dichas partes relativo a los Servicios de Ledger. Para usar o seguir usando los Servicios de Ledger tienes que leer y aceptar en su totalidad estas Condiciones de uso. - -Nos reservamos el derecho de modificar, enmendar o cambiar estas Condiciones de uso en cualquier momento, a nuestra exclusiva discreción. Te avisaremos de dichos cambios mediante la publicación de las Condiciones de uso modificadas a través de Ledger Live y actualizando la fecha de la "Última actualización" en el encabezamiento de estas Condiciones de uso. Las Condiciones de uso modificadas serán efectivas en cuanto se publiquen en Ledger Live. - -No puedes ceder tus derechos y obligaciones en virtud de estas Condiciones de uso, en su totalidad o en parte, a un tercero. - -Reconoces y aceptas que Ledger puede ceder sus derechos y obligaciones en virtud de estas Condiciones de uso y, en dicho contexto, compartir o ceder a terceros datos que hayas proporcionado al usar los Servicios de Ledger. - -Si alguna cláusula de estas Condiciones de uso o parte de ella es o resulta ser nula o inaplicable, se la considerará separable de las demás cláusulas y no tendrá incidencia alguna sobre la validez y la aplicación de las demás cláusulas. diff --git a/TERMS.fr.md b/TERMS.fr.md deleted file mode 100644 index c5cf202f58..0000000000 --- a/TERMS.fr.md +++ /dev/null @@ -1,209 +0,0 @@ -# Conditions d'utilisation de Ledger Live - -_LE 10 DÉCEMBRE 2019_ - -Vous vous apprêtez à utiliser la plateforme Ledger Live. Nous en sommes ravis pour vous ! Avant de commencer, nous vous recommandons de lire attentivement et de consentir à nos Conditions d'utilisation (les ou les présentes « Conditions »). - -Préambule - -Le présent accord est conclu entre vous (« vous », « votre » ou « Utilisateur ») et Ledger SAS (« Ledger », « nous », « notre » ou la « Société »). En utilisant ou en cliquant sur « J'accepte » les Services fournis par Ledger ou ses affiliées dans le cadre du logiciel Ledger Live (les « Services Ledger »), vous reconnaissez avoir lu attentivement et approuvé toutes les Conditions énoncées ci-après. - -Votre utilisation des Services Ledger est également soumise à la Politique de confidentialité de Ledger, qui est disponible à l'adresse [**https://shop.ledger.com/pages/politique-de-confidentialite**](https://shop.ledger.com/pages/politique-de-confidentialite). - -AVANT D'UTILISER LES SERVICES, VEUILLEZ VOUS INFORMER COMME IL SE DOIT AFIN DE PRENDRE DES DÉCISIONS EN CONNAISSANCE DE CAUSE. LES CRYPTO-ACTIFS SONT VOLATILS. LEURS PRIX PEUVENT FLUCTUER À LA HAUSSE OU À LA BAISSE. ÉVALUEZ AVEC ATTENTION VOS OBJECTIFS ET LE RISQUE FINANCIER QUE VOUS ÊTES DISPOSÉ(E) À PRENDRE. LEDGER NE DISPENSE PAS DE CONSEILS FINANCIERS, FISCAUX OU JURIDIQUES. LES DÉCISIONS PORTANT SUR DES OPÉRATIONS LIÉES À DES CRYPTO-ACTIFS DOIVENT ÊTRE PRISES PAR VOUS-MÊME OU SE FONDER SUR L'AVIS D'EXPERTS FIABLES ET QUALIFIÉS. - -Définitions - -Les termes suivants, utilisés dans le présent Accord, ont la signification qui leur est donnée ci-dessous, étant précisé que dans ces définitions, toute référence au singulier inclut le pluriel et inversement, sauf si cet usage est impropre. - -**« Crypto-actifs »** désigne les types d'actifs numériques pouvant être transmis au moyen de technologies blockchain, y compris notamment, les Bitcoin, Ethereum, Ripple. - -**« Application sur l'appareil »** désigne une application logicielle, développée par Ledger ou par des tiers, qui intègre une logique de signature cryptographique spécifique dans le système d'exploitation BOLOS de Ledger afin de créer une transaction, sur Ledger Live ou sur une application tierce, et signe des opérations avec un Appareil Ledger, y compris notamment : l'authentification, la gestion des mots de passe, la diffusion des transactions de Crypto-actifs. - -**« Fork »** - -désigne une modification du protocole sous-jacent d'un réseau de blockchain qui donne lieu à plusieurs versions d'un Crypto-actif, dont le résultat peut être une ou plusieurs versions qui ne sont pas prises en charge par les Services Ledger. - -**« Appareil Ledger »** désigne un appareil électronique, développé et distribué par Ledger, généralement dénommé « hardware wallet » (_portefeuille de cryptomonnaies physique_), utilisé pour gérer et sécuriser les Clés privées des Utilisateurs et autres secrets cryptographiques, compatible avec Ledger Live ou les Wallets compatibles. - -**« Ledger Live Manager »** désigne un catalogue d'Applications sur l'appareil disponibles en téléchargement, qui permet aux Utilisateurs de mettre à jour le firmware de leur Appareil Ledger, d'installer des Applications sur l'appareil et de gérer les Crypto-actifs supportés. - -**« Matériaux »** désigne le contenu, la documentation des Services Ledger ainsi que les codes source et objet de tous les logiciels intégrés dans Ledger Live et les Appareils Ledger. - -**« Code PIN »** désigne le mot de passe numérique choisi par l'Utilisateur pour déverrouiller un Appareil Ledger. - -**« Clés privées »** désigne une donnée essentielle utilisée pour autoriser les transactions sortantes sur les réseaux de blockchain. - -**« Services »** désigne un ou plusieurs Services Ledger ou des Services tiers. - -**« Services tiers »** désigne les applications, logiciels ou autres Matériaux qui sont hébergés, développés ou exploités par un tiers, y compris notamment les crypto-exchanges et prestataires de services sur actifs numériques ainsi que les prestataires de staking. - -**« Wallet »** désigne un logiciel qui interagit avec divers réseaux de blockchain pour générer et gérer des jeux de Clés privées et de Clés publiques, configurer des transactions et suivre leur solde. - -**« Site web »** désigne les sites web détenus et exploités par Ledger, y compris le site de e-commerce et de la Société hébergé sur ledger.com. - -**« Phrase de récupération de 24 mots »** désigne une combinaison confidentielle de mots lisibles par les utilisateurs, générée par des Appareils Ledger, d'où sont dérivées les Clés privées des Utilisateurs. Elles sont utilisées pour sauvegarder et rétablir l'accès aux Crypto-actifs sur d'autres Appareils Ledger ou des Wallets compatibles. - -Admissibilité - -Pour utiliser les Services, vous devez être âgé(e) d'au moins 18 ans ou être majeur(e) dans votre pays de résidence. Si vous utilisez nos Services pour le compte d'une personne morale, vous déclarez et garantissez ce qui suit : (a) la personne morale est dûment constituée et existe valablement en vertu des lois applicables de sa juridiction de constitution ; et (b) vous êtes dûment autorisé(e) par cette personne morale à intervenir en son nom. - -Vous ne pouvez utiliser les Services que si les lois de votre juridiction le permettent. Veuillez-vous assurer que les présentes Conditions se conforment à toutes les lois, règles et réglementations qui vous sont applicables. - -Services Ledger - -Ledger Live, en liaison avec les Appareils Ledger, vous propose un moyen pratique et sûr de gérer vos Applications sur l'appareil et d'utiliser des Clés privées dérivées de votre Phrase de récupération de 24 mots. - -Les Services Ledger permettent aux Utilisateurs : - -- d'actualiser le firmware de leur Appareil Ledger -- d'installer et désinstaller des Applications sur l'appareil avec Ledger Live Manager -- de consulter leur portefeuille de Crypto-actifs -- d'accéder aux moyens de réaliser des opérations sur divers réseaux de blockchain conformément aux règles de protocole applicables, telles que, notamment: envoyer et recevoir des Crypto-actifs à destination et en provenance des Utilisateurs d'un réseau de blockchain dédié ; -- de se connecter à des Services tiers, pour accéder à des services tels que la délégation de droits de staking sur des blockchains supportant la proof-of-stake ou l'achat de crypto. - -Ledger propose des Services sans dépôt. En conséquence, nous ne stockons pas et n'avons pas accès à vos Crypto-actifs et Clés privées. Nous n'envoyons pas et ne recevons pas de Crypto-actifs. Les transferts de Crypto-actifs interviennent sur des réseaux de blockchain et non sur un réseau détenu ou contrôlé par Ledger. - -Ledger Live et les Appareils Ledger ne peuvent prendre en charge que certains Crypto-actifs. Une liste non exhaustive des Crypto-actifs supportés et des Wallets compatibles est disponible [ici](about:blank). Cette liste peut faire l'objet de modifications. - -Risques - -Vous êtes réputé(e) avoir connaissance de toutes les normes légales et contraintes techniques liées aux blockchains avec proof of stake et avec proof-of-work, et aux Services. Vous reconnaissez avoir été averti(e) des risques associés énoncés ci-dessous : - -**Évolutions règlementaires.** Les technologies de blockchain font en permanence l'objet de contrôles et de modifications réglementaires dans le monde entier, notamment dans le cadre des réglementations financières et de lutte contre le blanchiment d'argent. Vous reconnaissez que les Services, ainsi que leur disponibilité, peuvent être impactés par des obligations réglementaires. - -**Fiscalité.** Les transactions en Crypto-actifs, ou plus généralement les opérations liées aux Crypto-actifs, et notamment, les échanges, les distributions de cryptomonnaies ou de jetons à titre gratuit, les Forks et les gains résultant du staking, peuvent être considérés comme des événements taxables par les législations auxquelles vous êtes soumis(e). Ces règles peuvent manquer de clarté ou évoluer, et nous vous recommandons en conséquence de consulter votre conseiller fiscal ou comptable avant toute transaction de Crypto-actifs. - -**Technologie.** Les Utilisateurs reconnaissent que certaines des technologies prises en charge ou mises à disposition au travers des Services sont nouvelles, non testées et non contrôlées par Ledger. Les progrès de la cryptographie, ou d'autres avancées techniques telles que le développement des calculateurs quantiques, peuvent présenter des risques pour les réseaux de blockchain, et entraîner le vol ou la perte de Crypto-actifs. D'autres changements défavorables des tendances du marché ou de la technologie, au sens large, peuvent empêcher ou compromettre l'exécution des présentes Conditions par Ledger. - -**Cybersécurité. ** Les pirates informatiques ou d'autres groupes ou organisations peuvent tenter de porter atteinte aux produits et systèmes d'information de Ledger de plusieurs manières, y compris notamment par des attaques par déni de service, des attaques par canal auxiliaire, des usurpations d'identité, des attaques par rebond, des logiciels malveillants ou des attaques dites"des 51 %". - -D'autres risques non prévus ou identifiés dans les présentes Conditions peuvent également se présenter. Avant d'utiliser nos Services, nous vous recommandons vivement d'évaluer avec précision si votre situation financière et votre tolérance au risque sont compatibles avec une telle utilisation. - -À titre de précision, et en dépit des stipulations générales de l'article intitulé Limitation de responsabilité, vous reconnaissez par les présentes que Ledger n'assume aucune responsabilité au titre de toute perte subie en conséquence des risques mentionnés dans le présent article. - -Non-récupération des Clés privées - -**Vous êtes en possession de la seule sauvegarde existante.** Ledger n'a pas accès et ne stocke pas les mots de passe, les phrases de récupération de 24 mots, les Clés privées, les phrases secrètes, les historiques des opérations, les Codes PIN ou autres informations d'identification associées à votre utilisation des Services. Nous ne sommes pas en mesure de vous aider à récupérer vos informations d'identification. Vous êtes seul(e) responsable de la mémorisation, du stockage et de la conservation de vos informations d'identification en un lieu sûr, à l'abri des regards indiscrets. Tout tiers ayant connaissance d'une ou plusieurs de vos phrases de récupération de 24 mots ou de votre Code PIN peut prendre le contrôle des Clés privées associées à votre Appareil Ledger ou de la phrase de récupération de 24 mots ; - -**Conservez vos informations d'identification en lieu sûr.** Lorsque vous installez votre Appareil Ledger, vous devez : (a) créer et mémoriser un Code PIN fort que vous n'utilisez pour aucun autre service ; (b) protéger, sécuriser et garder confidentielle votre phrase de récupération de 24 mots ; (c) protéger l'accès à votre Appareil Ledger ; - -Utilisation acceptable - -En tant qu'Utilisateur des Services Ledger, nous vous accordons une licence limitée, personnelle, non commerciale, non exclusive, non cessible et révocable vous permettant d'utiliser les Services Ledger. Lorsque vous utilisez les Services Ledger, il convient de suivre quelques règles de base : - -**Ne pas causer de tort.** Vous vous engagez à (i) ne pas diffuser de virus ou autres codes informatiques nuisibles par le biais des systèmes de Ledger, (ii) ne pas utiliser de robot, spider, crawler, scraper ou autres interfaces ou moyens automatisés que nous n'avons pas fournis pour accéder aux Services Ledger ou pour extraire des données, (iii) ne pas communiquer d'informations fausses, inexactes ou trompeuses, et (iv) ne pas prendre de mesures qui pourraient surcharger de manière disproportionnée notre infrastructure ou celle de fournisseurs tiers. - -**Ne pas contourner nos mesures de sécurité.** Vous vous engagez à ne pas contourner, ou tenter de contourner toute mesure que nous pourrions mettre en œuvre pour empêcher ou restreindre l'accès aux Services Ledger, et notamment aux Appareils Ledger connectés aux Services Ledger, à d'autres comptes, systèmes d'information ou réseaux. - -**Ne pas enfreindre la loi.** Vous vous engagez à n'enfreindre aucune loi lorsque vous utilisez les Services Ledger, à savoir toutes les lois et réglementations locales, provinciales, d'état, fédérales, nationales ou internationales qui pourraient vous être applicables. Vous vous engagez à ne pas utiliser les Services Ledger pour financer, soutenir ou vous livrer à des activités illégales, et notamment, la fraude, les jeux illicites, le blanchiment d'argent ou les activités terroristes. Vous vous engagez en outre à ne pas encourager ou inciter un tiers à se livrer à l'une des activités interdites en vertu du présent article. - -**Ne pas causer de perturbations.** Vous vous engagez à ne pas utiliser ou tenter d'utiliser le Wallet d'un autre Utilisateur sans autorisation, ou utiliser les Services Ledger d'une manière qui pourrait porter atteinte, perturber, affecter ou empêcher d'autres Utilisateurs de profiter pleinement des Services Ledger, ou qui pourrait endommager, désactiver, surcharger ou nuire au fonctionnement des Services Ledger de quelque manière que ce soit. - -Toute utilisation des Services Ledger autre que celle prévue dans les présentes Conditions, sans notre autorisation écrite préalable, est strictement interdite et mettra fin à votre licence d'utilisation des Services Ledger. - -Garanties et clauses de non-responsabilité - -Ledger est tenue par une obligation de moyen et doit s'assurer en conséquence que vous pouvez accéder aux Services Ledger conformément aux présentes Conditions d'utilisation. Toutefois, il n'est pas garanti que l'accès et les fonctionnalités seront ininterrompus ou qu'il n'y aura pas de retards, de défaillances, d'erreurs, d'omissions, de corruption ou de perte des informations transmises. Les Services Ledger sont fournis « en l'état » sans garantie d'aucune sorte, expresse ou tacite, et en particulier sans garantie tacite de qualité marchande, de fiabilité et d'adéquation à un usage particulier. - -Disponibilité des Services Ledger - -Nous pouvons modifier, actualiser ou suspendre les Services, sur une base temporaire ou illimitée, afin de procéder à des travaux, et notamment à des mises à jour de firmwares et de logiciels, des opérations de maintenance, des modifications de serveurs, des corrections de bogues, etc. Nous nous efforcerons de vous informer au préalable de toute perturbation importante des Services Ledger. - -Ledger ne garantit pas le bon fonctionnement des Services en cas d'installation ou d'utilisation de programmes ou d'applications qui ne sont pas conformes aux spécifications et aux normes techniques des Services. - -Veuillez noter qu'en cas d'indisponibilité ou de suspension d'un Service Ledger, il vous sera possible de récupérer vos Clés privées en utilisant votre phrase de récupération de 24 mots sur un Wallet compatible. - -Protocoles de blockchain sous-jacents - -Toutes les transactions créées par le biais des Services Ledger sont confirmées et enregistrées dans les réseaux de blockchain associés. Ces réseaux sont des réseaux de pair-à-pair décentralisés, gérés par des tiers indépendants, que Ledger ne possède, ne contrôle et n'exploite pas. Nous n'avons aucun contrôle sur les réseaux de blockchain et, par conséquent, nous ne sommes pas en mesure de garantir et ne garantissons pas que les transactions que vous diffusez sur les Services Ledger seront confirmées et traitées. Vous reconnaissez que nous ne stockons pas, n'envoyons pas et ne recevons pas de Crypto-actifs et vous acceptez que les transactions que vous configurez sur les Services Ledger peuvent échouer ou être considérablement retardées par les réseaux de blockchain sous-jacents. - -Il peut arriver que le protocole de blockchain d'un Crypto-actif donné change, ce qui peut avoir des conséquences sur ses principales caractéristiques, et notamment sur sa disponibilité, son nom, sa sécurité, sa valorisation ou son mode de fonctionnement. Les Forks impliquent que les Crypto-actifs bifurqués peuvent être mal dirigés ou reproduits. Dans de tels cas, Ledger peut décider, à sa discrétion, de suspendre la prise en charge du Crypto-actif concerné aussi longtemps que Ledger l'estime nécessaire. Si tel est le cas, Ledger s'efforcera de vous avertir préalablement, mais il est possible qu'elle ne puisse pas le faire. Vous devez vous tenir informé(e) de ces événements et prendre toutes les dispositions nécessaires. - -Applications sur l'appareil - -Les Applications sur l'appareil sont disponibles en téléchargement sur Ledger Live Manager, ou peuvent être installées en suivant nos[\*\* \*\*](about:blank)[lignes directrices](about:blank) et peuvent être développées soit par Ledger, soit par un tiers, grâce au code Open source disponible sur Ledger[\*\* \*\*](about:blank)[Github repository.](about:blank) - -Les développeurs d'Applications sur l'appareil sont responsables de ces applications et de leurs performances, et sont tenus de fournir une assistance pour les Applications sur l'appareil prises en charge sur un Appareil Ledger et sur Ledger Live. Ledger peut procéder à une révision des codes et mener des audits de sécurité des Applications sur l'appareil disponibles sur Ledger Live Manager, qui ne valent toutefois ni approbation ni garantie de l'absence de risques posés par ces applications. - -Ledger ne garantit pas le maintien dans le temps des Applications sur l'appareil et se réserve le droit de restreindre ou de suspendre l'accès à ces Applications à partir des Services Ledger pour toute raison et aussi longtemps qu'elle l'estime nécessaire. - -Fonctionnalités expérimentales - -Afin de répondre aux demandes des Utilisateurs avertis et de créer de nouvelles fonctionnalités, nous avons mis en place une série de fonctionnalités expérimentales sur Ledger Live. Ces fonctionnalités peuvent ne pas être finalisées et ne pas avoir été entièrement testées, ce qui peut présenter des risques accrus. Elles peuvent contenir des erreurs ou des inexactitudes susceptibles d'entraîner des défaillances ainsi que la corruption ou la perte de données et/ou d'informations. Ces fonctionnalités peuvent être considérées comme des fonctionnalités bêta. Ledger ne garantit pas la stabilité, le fonctionnement ou la prise en charge à long terme de ces fonctionnalités. Nous vous recommandons de ne pas utiliser ces fonctionnalités si vous n'êtes pas un Utilisateur averti disposant de solides compétences techniques. Vous reconnaissez et acceptez expressément que toute utilisation des Fonctionnalités expérimentales se fait à vos risques et périls. - -Informations relatives aux transactions - -**N'accordez pas d'office votre confiance. Vérifiez les informations.** L'intégrité des logiciels, en particulier lorsqu'ils sont connectés à Internet, est très difficile à vérifier. Le modèle de sécurité de Ledger repose sur un affichage fiable ; c'est la raison pour laquelle la vérification des informations contenues dans votre Appareil Ledger est primordiale. Avant d'approuver une opération, vous devez toujours contrôler que les informations affichées sur l'écran de votre téléphone portable ou de votre ordinateur sont correctes et correspondent à celles affichées sur votre Appareil Ledger. Lors de l'envoi de Crypto-actifs, vous êtes seul(e) responsable du contrôle de l'exactitude de l'adresse du destinataire, du montant et des frais, et devez vous assurer que les informations sont identiques sur l'écran de votre ordinateur ou de votre téléphone portable et sur l'écran de votre Appareil Ledger. Vous reconnaissez également que l'utilisation d'adresses non vérifiées pour recevoir des Crypto-actifs se fait à vos risques et périls. - -Services et Matériaux de tiers - -Ledger Live peut intégrer, référencer ou donner accès à des Services tiers. - -Vous convenez que votre utilisation des Services tiers est soumise à des conditions générales distinctes entre vous et le tiers identifié sur Ledger Live. Ledger n'est pas responsable de l'exécution ou du défaut d'exécution des Services tiers. Il vous incombe de lire les conditions et les politiques du tiers avant d'utiliser un Service tiers. Certains Services tiers peuvent nécessiter ou exiger l'accès à vos données personnelles. Le traitement de ces données sera effectué conformément à la politique de confidentialité et aux meilleures pratiques du tiers concerné. - -Les Services tiers peuvent ne pas fonctionner correctement avec votre logiciel ou votre Appareil Ledger, et il est possible que nous ne soyons pas en mesure de fournir une assistance pour les problèmes causés par les Services tiers. Pour toutes questions concernant le fonctionnement d'un Service tiers ou pour obtenir une assistance, il convient de contacter directement le tiers concerné. - -Nous vous conseillons de ne pas partager vos informations d'identification, mots de passe, Clés privées, phrases secrètes et autres informations sensibles avec un Service tiers sans en avoir préalablement validé la légitimité. - -Nous nous réservons le droit exclusif d'ajouter, de modifier ou d'annuler la disponibilité du Service tiers pour quelque raison que ce soit et sans préavis. - -Des règles et obligations spécifiques s'appliquent aux Services suivants : - -**A. Achat de Services Crypto** - -Les liens vers l'achat de Services Crypto sont des liens sponsorisés. L'existence d'un lien vers ou depuis un Service Ledger ne vaut pas approbation de ces Services. - -**B. Délégation des droits de staking** - -**Récompenses.** Vous reconnaissez expressément que la délégation de droits de staking à un opérateur validateur figurant sur Ledger Live ne vous donne aucun droit de demander un paiement de quelque nature qu'il soit, et vous octroie uniquement le droit potentiel de partager une récompense perçue par le validateur. Veuillez noter que les périodes de verrouillage dépendent du validateur et des protocoles de blockchain. - -**Validateurs.** Ledger se réserve le droit de modifier la liste des validateurs référencés à tout moment et sans préavis. - -Limitation de responsabilité - -VOUS CONVENEZ EXPRESSÉMENT QUE LEDGER ET SES DIRIGEANTS ET EMPLOYÉS NE SONT PAS RESPONSABLES ENVERS VOUS DE TOUT DOMMAGE DIRECT, INDIRECT, ACCESSOIRE, SPÉCIAL, CONSÉCUTIF OU PUNITIF, Y COMPRIS NOTAMMENT, LES DOMMAGES AU TITRE D'UNE PERTE DE CHANCE D'UN MANQUE À GAGNER, D'UNE PERTE DE CLIENTÈLE, D'UTILISATION, DE DONNÉES, LE COÛT D'ACQUISITION DE BIENS OU DE SERVICES DE REMPLACEMENT, OU AUTRES PERTES IMMATÉRIELLES, RÉSULTANT DE : (I) L'UTILISATION OU L'IMPOSSIBILITÉ D'UTILISER LES SERVICES (II) TOUTE MODIFICATION APPORTÉE AU SERVICE OU TOUTE SUSPENSION OU ARRÊT DE TOUT OU PARTIE DES SERVICES ; (III) L'ACCÈS NON AUTORISÉ À VOS TRANSMISSIONS OU DONNÉES OU LEUR MODIFICATION ; (IV) LA SUPPRESSION, LA CORRUPTION OU LE DÉFAUT DE STOCKAGE ET/OU D'ENVOI OU DE RÉCEPTION DE VOS TRANSMISSIONS OU DONNÉES SUR OU PAR LE BIAIS DU SERVICE ; ET (V) TOUTE AUTRE QUESTION RELATIVE AU SERVICE. - -LES LIMITATIONS CI-DESSUS NE S'APPLIQUENT PAS AUX PERTES RÉSULTANT (A) D'UNE FRAUDE, D'UNE FAUTE INTENTIONNELLE OU D'UNE FAUTE LOURDE DE LA PART DE LEDGER ; OU (B) D'UN DÉCÈS OU DE PRÉJUDICES CORPORELS. - -Propriété intellectuelle - -Ledger respecte la propriété intellectuelle des tiers et attend de ses Utilisateurs qu'ils en fassent de même. Vous reconnaissez et convenez qu'à l'exception des Matériaux publiés ou mis à disposition d'une quelque autre façon conformément à des accords de licence publique, de licences open source ou MIT ou d'autres systèmes de licence non exclusifs habituellement utilisés par la communauté Ledger, Ledger possède tous les droits d'auteur, marques de commerce, savoir-faire ou autres droits de propriété intellectuelle à l'égard des logiciels, du texte, de la vidéo, de l'audio, des illustrations, des logos, de la structure et de la présentation de Ledger Live, des Applications sur l'appareil et du site Web. - -Vous pouvez visualiser, imprimer et/ou télécharger une copie des Matériaux exclusifs des Services Ledger sur un seul ordinateur, uniquement pour votre usage personnel, à des fins d'information et/ou pour une utilisation non commerciale, sous réserve du respect de tous les avis de droits d'auteur et autres avis de propriété. - -Les marques de commerce, marques de service et logos de Ledger et de tiers utilisés dans le cadre des Services (les « Marques ») sont la propriété de Ledger et de leurs titulaires respectifs. Il est strictement interdit d'utiliser ces Marques sans notre autorisation écrite expresse ou sans l'autorisation écrite expresse de tout tiers. - -Recueil de commentaires de la part des utilisateurs - -Nous vous invitons à nous faire part de vos réactions, commentaires, idées et suggestions pour améliorer les Services (« Recueil de commentaires »). Vous nous accordez une licence non exclusive, mondiale, perpétuelle, irrévocable, entièrement payée, libre de droits, cessible et pouvant faire l'objet d'une sous-licence au titre de tous les droits de propriété intellectuelle que vous possédez ou contrôlez, pour utiliser, copier, modifier, créer des œuvres dérivées basées sur le Recueil de commentaires et l'exploiter à toutes fins utiles. - -Conformité et contrôle des exportations - -Les Utilisateurs s'engagent à se conformer, à leurs frais, à toutes les lois qui s'appliquent à leurs obligations en vertu des présentes Conditions ou qui en découlent. En accédant et en utilisant les Services, vous déclarez et garantissez que vous ne figurez sur aucune liste de sanctions commerciales ou économiques, telle que (notamment) la liste des sanctions du Conseil de sécurité des Nations unies, n'êtes pas désigné(e) en tant que « Specially Designated National » par l'OFAC (Office of Foreign Assets Control du département du Trésor américain) ni placé(e) sur la « Denied Persons List » du département du Commerce américain. - -Ledger se réserve le droit de sélectionner les marchés et les pays où elle exerce ses activités et peut restreindre ou refuser l'accès aux Services Ledger dans certains pays, états ou territoires. - -Résiliation - -Vous êtes en droit de mettre un terme à tout moment à l'utilisation des Services. Nous nous réservons le droit de suspendre votre accès aux Services Ledger sans préavis si nous estimons que vous avez enfreint les présentes Conditions. En cas de résiliation de votre licence d'utilisation Ledger, vos obligations en vertu des présentes Conditions resteront applicables. - -Après résiliation, votre accès à vos Wallets sera subordonné à la sauvegarde sécurisée de vos Clés privées et de l'adresse de vos Wallets. - -Droit applicable - -Les présentes Conditions seront régies et interprétées conformément au droit français. - -Tout litige, contestation, différend ou réclamation découlant des présentes ou s'y rapportant, en ce compris son existence, sa validité, son interprétation, son exécution, sa violation ou sa résiliation ou tout litige portant sur des obligations non contractuelles découlant du présent Accord ou s'y rapportant, sera soumis aux tribunaux compétents de Paris, en France, qui le trancheront avec force de chose jugée - -Mise à exécution et cession des Conditions - -Les présentes Conditions constituent l'accord intégral et exclusif entre vous-même et Ledger à l'égard des Services Ledger, et annulent et remplacent toute entente ou accord antérieur, sous forme orale ou écrite, entre Ledger et vous-même concernant les Services Ledger. À défaut de lire et d'approuver dans leur intégralité les présentes Conditions, vous ne serez pas en droit d'utiliser ou de continuer à utiliser les Services Ledger. - -Nous nous réservons le droit de modifier ponctuellement les présentes Conditions à notre entière discrétion. Nous vous informerons de ces modifications en publiant les Conditions modifiées sur Ledger Live et en actualisant la date de « Dernière mise à jour » au début des présentes Conditions. Les Conditions modifiées seront réputées prendre effet dès leur publication sur Ledger Live. - -Vous ne pouvez pas céder vos droits ou obligations en vertu des présentes Conditions d'utilisation, en tout ou en partie, à un tiers. - -Vous reconnaissez et acceptez que Ledger puisse céder ses droits et obligations en vertu des présentes Conditions d'utilisation et, dans ce contexte, partager ou transférer à un tiers les informations que vous avez fournies lors de l'utilisation des Services Ledger. - -Si tout ou partie des stipulations des présentes Conditions d'utilisation est ou devient invalide ou inapplicable, ces stipulations seront réputées dissociées des autres stipulations et n'auront aucune incidence sur la validité ou l'applicabilité des autres stipulations des présentes Conditions d'utilisation. diff --git a/TERMS.md b/TERMS.md index 53eb7af4b2..39ebd57bf5 100644 --- a/TERMS.md +++ b/TERMS.md @@ -1,232 +1,211 @@ -_December 10, 2019_ +**_May 10th, 2022_** -You are about to use the Ledger Live platform. We're excited for you! Before you get on, Ledger needs you to carefully read, understand and accept our Terms of Use (the or these "Terms"). +You are about to use Ledger Live. We’re excited for you! Before you get on, Ledger needs you to carefully read, understand and accept our Terms of Use (the or these “Terms”). -## Overview +## 1\. Overview -This agreement is between you ("you", "your", or "User") and Ledger SAS ("Ledger", "us", "we,'' "our", or the "Company"). By using or clicking "I agree" to any of the services provided by Ledger or its affiliates in connection with the Ledge Live software (the "Ledger Services"), you agree that you have carefully read and accept all of the below terms and conditions. +This agreement is between you (“you”, “your”, or “User”) and Ledger SAS (“Ledger”, “us”, “we,'' “our”, or the “Company”). Ledger is a simplified joint-stock company with a capital of 1 459 259 € with its registered offices is located at 1, rue du Mail,75002 Paris and registered with the Paris Trade and Companies Register under number 529 991 119 (intra-Community VAT number: FR03529991119). -Your use of Ledger Services is also subject to Ledger's Privacy Policy, which is available at [https://shop.ledger.com/pages/privacy-policy](https://shop.ledger.com/pages/privacy-policy). +By clicking “I agree”, “Get started”, or otherwise using any of the services provided by Ledger or any third party services made available through Ledger Live, you agree that you have carefully read and accepted all of the below terms and conditions. -BEFORE USING THE SERVICES, PLEASE EDUCATE YOURSELF TO MAKE INFORMED DECISIONS. CRYPTO ASSETS ARE VOLATILE. THE PRICES CAN GO UP AND DOWN. CAREFULLY EVALUATE YOUR GOALS AND THE FINANCIAL RISK YOU ARE WILLING TO TAKE. PLEASE BE AWARE THAT LEDGER DOES NOT PROVIDE FINANCIAL, TAX, OR LEGAL ADVICE. DECISIONS TO PERFORM OPERATIONS INVOLVING CRYPTO ASSETS SHOULD BE TAKEN ON YOUR OWN OR RELY ON OPINIONS OF RELIABLE AND QUALIFIED EXPERTS. +Your use of Ledger Live is also subject to Ledger’s Privacy Policy, which is available at [https://shop.ledger.com/pages/privacy-policy](https://shop.ledger.com/pages/privacy-policy). -## Definitions +BEFORE USING LEDGER LIVE, PLEASE EDUCATE YOURSELF TO MAKE INFORMED DECISIONS. LEDGER DOES NOT PROVIDE FINANCIAL, TAX, OR LEGAL ADVICE. LEDGER DOES NOT EXCHANGE, SEND, OR RECEIVE CRYPTO ASSETS FOR USERS.  LEDGER DOES NOT ADVISE OR MAKE RECOMMENDATIONS ABOUT ENGAGING IN CRYPTO ASSET TRANSACTIONS OR OPERATIONS. DECISIONS TO ENGAGE IN TRANSACTIONS OR PERFORM OPERATIONS INVOLVING CRYPTO ASSETS SHOULD BE TAKEN ON YOUR OWN OR RELY ON OPINIONS OF YOUR OWN RELIABLE AND QUALIFIED EXPERTS. -The following terms, when used in this Agreement, shall have the meanings described below, it being specified for the avoidance of doubt that in these definitions, reference to the singular includes a reference to the plural and vice versa, except when clearly inappropriate. +## 2\. Definitions -" **Crypto Assets**" +The following capitalized terms shall have the meanings described below when used in these Terms, it being specified for the avoidance of doubt that in these definitions, reference to the singular includes a reference to the plural and vice versa, except when clearly inappropriate. -means types of digital assets which can be transmitted with blockchain technologies, including but not limited to Bitcoin, Ethereum, Ripple. +**“Crypto Assets”** +means types of digital assets which can be transmitted with blockchain technologies. This includes cryptocurrencies as well as non-fungible tokens (“NFTs”). -**"Device Application"** +**“Device Application”** +means a software application, developed by Ledger or by third parties, which embeds a specific cryptographic signature logic within Ledger’s operating system BOLOS in order to create a transaction, on Ledger Live or a third party application, and sign various operations with a Ledger Device, including but not limited to: Crypto Assets transactions broadcast, authentication, password management. -means a software application, developed by Ledger or by third parties, which embeds a specific cryptographic signature logic within Ledger's operating system BOLOS in order to create a transaction, on Ledger Live or a third party application, and signs various operations with a Ledger Device, including but not limited to: Crypto Assets transactions broadcast, authentication, password management. +**“Fork”** +means a change to the underlying protocol of a blockchain network that results in more than one version of a Crypto Asset, the result of which may be one or more versions that are not supported by Ledger Live. -" **Fork**" +**“Ledger Device”** +means an electronic device, developed and distributed by Ledger, generally referred to as a “hardware wallet”, used to manage and secure Users’ Private Keys and other cryptographic secrets, compatible with Ledger Live or compatible Wallets. -means a change to the underlying protocol of a blockchain network that results in more than one version of a Crypto Asset, the result of which may be one or more versions that are not supported on Ledger Services. +**“Ledger Live”** +means the mobile and desktop software application which provides access to applications and Services, including services that can only be used in connection with a Ledger hardware wallet. -**"Ledger Device"** +**“Ledger Live Manager”** +means a catalog of Device Applications available for download, which enables Users to update their Ledger Device firmware, install Device Applications and manage supported Crypto Assets. -means an electronic device, developed and distributed by Ledger, generally referred to as a "hardware wallet", used to manage and secure Users' Private Keys and other cryptographic secrets, compatible with Ledger Live or compatible Wallets. - -" **Ledger Live Manager**" - -means a catalogue of Device Applications available for download, which enables Users to update their Ledger Device firmware, install Device Applications and manage supported Crypto Assets. - -**"Materials"** - -means content, Ledger Service documentation as well as source and object codes for all software embedded within Ledger Live and Ledger Devices. - -**"PIN"** +**“Materials”** +means content, documentation as well as source and object codes for all software embedded within Ledger Live and Ledger Devices. +**“PIN”** means the numeric password chosen by the User to unlock a Ledger Device. -**"Private Keys"** - +**“Private Keys”** means a critical piece of data used to authorize outgoing transactions on blockchain networks. -" **Services**" - -means one or more of the Ledger Services or Third Party Services. +**“Services”**  +means one or more of the services available within or through Ledger Live, including without limitation the Third Party Services. -" **Third Party Services"** - -refers to applications, softwares or other Materials that are hosted, developed or operated by a third party, including, but not limited to: cryptocurrency exchanges, staking service providers. - -" **Wallet**" +**“Third Party Services”** +refers to any services, applications, software or other Materials that are hosted, developed and/or operated by a third party, including, but not limited to: crypto to crypto exchanges (“swap”), staking, buying and selling cryptocurrencies, display of balance in FIAT, display of currency rates, decentralized financial applications allowing the exchange, lending or borrowing of cryptocurrencies, visualization of NFTs, minting, buying and selling of NFTs, etc. +**“Wallet”** means a software program which interacts with various blockchain networks to generate and manage sets of private keys and public keys, configure transactions and monitor their balance. -**"Website"** - +**“Website”**  means websites owned and operated by Ledger, including the e-commerce and corporate website hosted at ledger.com -**"24-word Recovery Phrase"** - -means a confidential combination of human readable words, generated by Ledger Devices, from which Users' Private Keys are derived. They are used to back-up and restore access to Crypto Assets on other Ledger Devices or compatible Wallets. - -## Eligibility - -To be eligible to use the Services, you must be at least 18 years old or qualify as an adult in your country of residence. If you are using our Services on behalf of a legal entity, you further represent and warrant that: (a) the legal entity is duly organized and validly existing under the applicable laws of the jurisdiction of its organization; and (b) you are duly authorized by such legal entity to act on its behalf. - -You can only use the Services if permitted under the laws of your jurisdiction. Please make sure that these Terms are in compliance with all laws, rules, and regulations that apply to you. +**“24-word Recovery Phrase”** +means a confidential combination of human readable words, generated by Ledger Devices, from which Users’ Private Keys are derived. They are used to back-up and restore access to Crypto Assets on other Ledger Devices or compatible Wallets. -## Ledger Services +## 3\. Eligibility -Ledger Live, in connection with Ledger Devices, provides you with a convenient and secure way to manage your Device Applications as well as use Private Keys derived from your 24-word Recovery Phrase. +To be eligible to use the Services, you must be at least 18 years old or qualify as an adult in your country of residence. If you are using the Services on behalf of a legal entity, you further represent and warrant that: (a) the legal entity is duly organized and validly existing under the applicable laws of the jurisdiction of its organization; and (b) you are duly authorized by such legal entity to act on its behalf. You can only use the Services if permitted under the laws of your jurisdiction. Please make sure that these Terms are in compliance with all laws, rules, and regulations that apply to you. -The Ledger Services allow Users to: +## 4. Risks and recommendations -- Update the firmware of their Ledger Device -- Install and uninstall Device Applications with the Ledger Live Manager -- View their portfolio of Crypto Assets -- Access the means to perform operations on various blockchain networks in accordance with their respective protocol rules, such as but not limited to: send and receive Crypto Assets to and from Users of a dedicated blockchain network; - -- Connect with Third Party Services, to access services such as the delegation of staking rights on supported proof-of-stake blockchains or buying crypto. - -Ledger operates non-custodial services, which means that we do not store, nor do we have access to your Crypto Assets nor your Private Keys. We do not send or receive Crypto Assets. Any Crypto Asset transfer occurs on blockchain networks and not on a network owned or controlled by Ledger. - -Ledger Live and Ledger Devices are only capable of supporting certain Crypto Assets. A non-exhaustive list of supported Crypto Assets and compatible Wallets is available [here](https://support.ledger.com/hc/en-us/articles/115005304449-Supported-crypto-assets#targetText=Ledger%20Live%20supports%2022%20crypto,as%20send%20and%20receive%20them.). This list is subject to variation. - -## Risk - -You are deemed to be fully aware of all the legal norms and technical constraints relating to the proof-of-stake and proof-of-work blockchains, and to the Services.You acknowledge that you have been warned of the following associated risks: - -**Regulatory changes.** Blockchain technologies are subject to continuous regulatory changes and scrutiny around the world, including but not limited to anti-money laundering and financial regulations. You acknowledge that certain Services, including their availability, could be impacted by one or more regulatory requirements. +You acknowledge that you are fully aware of all applicable laws and technical constraints relating to the proof-of-stake and proof-of-work blockchains, and to the Services. You acknowledge that you have been warned of the following associated risks and advised of the following recommendations: -**Tax.** Transactions in Crypto Assets, or more generally Crypto Assets events, including but not limited to exchanges, air-drops, forks, and gains arising from staking, may be considered tax events according to the legislations under which you are subject to taxation. These rules may be unclear or subject to change, and you are therefore encouraged to consult your own tax or accounting adviser before doing Crypto Assets events. +**4.1 Regulatory changes.** Blockchain technologies and related services are subject to continuous regulatory changes and scrutiny around the world, including but not limited to anti-money laundering and financial regulations. You acknowledge that certain Services, including their availability, could be impacted by one or more regulatory requirements. -**Technology**. Users understand that some of the technology supported or made available through the Services are new, untested and outside of Ledger's control. Advances in cryptography, or other technical advances such as the development of quantum computers, could present risks to blockchain networks which could result in the theft or loss of Crypto Assets. Other adverse changes in market forces or in the technology, broadly construed, may prevent or compromise Ledger's performance under these Terms. +**4.2 Tax.** Transactions or operations in Crypto Assets , or more generally Crypto Assets events, including but not limited to exchanges, air-drops, forks, and gains arising from staking, may be considered tax events according to the legislations law under which you are subject to taxation. These rules may be unclear or subject to change, and you are therefore encouraged to consult your own tax or accounting adviser before engaging into Crypto Assets activities. -**Cybersecurity**. Hackers or other groups or organizations may attempt to interfere with Ledger's products and information systems in several ways, including without limitation denial of service attacks, side-channel attacks, spoofing, smurfing, malware attacks, or consensus-based attacks. +**4.3 Technology.** Users understand that some of the technology supported or made available through the Services are new, untested and not provided by Ledger and therefore outside of Ledger’s control. Advances in cryptography, or other technical advances such as the development of quantum computers, could present risks to blockchain networks which could result in the theft or loss of Crypto Assets. Other adverse changes in market forces or in the technology, broadly construed, may prevent or compromise Ledger’s performance under these Terms. -There may be additional risks that we have not foreseen or identified in these Terms. Before you use our Services, you are strongly encouraged to carefully assess whether your financial situation and risk tolerance is compatible with such use. +**4.4 Cybersecurity.** Hackers or other groups or organizations may attempt to interfere with Ledger’s products and information systems in several ways, including without limitation denial of service attacks, side-channel attacks, spoofing, smurfing, malware attacks, or consensus-based attacks. -For the avoidance of doubt, and notwithstanding the generality of the Limitation of Liability section, you hereby agree that Ledger shall have no liability for any loss that incurs as a consequence of the risks highlighted in this section. +**4.5 Underlying blockchain protocols.** All transactions created through the Services are confirmed and recorded on blockchain networks. Such networks are decentralized peer-to-peer networks run by independent third parties, which Ledger does not own, control or operate. We have no control over blockchain networks and, therefore, cannot and do not ensure that the transactions you broadcast on the Services will be confirmed and processed. You acknowledge that we do not store, send, or receive Crypto Assets on your behalf and you agree that the transactions you configure through the Services may fail, or may be substantially delayed by the underlying blockchain networks. On occasions, the blockchain protocol of a given Crypto Asset may change, which may have consequences on its key characteristics including but not limited to their tits availability, name, security, valuation value or the way it operates. Forks entail that forked Crypto Assets may be misdirected or replicated. In any such events, Ledger may decide, at its discretion, to suspend support of the impacted Crypto Asset for as long as Ledger deems necessary. When it so decides, Ledger will endeavor to give you advance notice, but may not be able to. You should keep yourself apprised of such events and make all necessary arrangements. -## No retrieval of Private Keys +**4.6 No retrieval of Private Keys.** The only existing backup is with you. Ledger operates non-custodial services, which means that we do not store, nor do we have access to your Crypto Assets nor your Private Keys. Ledger does not have access to or store passwords, 24-word Recovery Phrase, Private Keys, passphrases, transaction history, PIN, or other credentials associated with your use of the Services. We are not in a position to help you retrieve your credentials. You are solely responsible for remembering, storing, and keeping your credentials in a secure location, away from prying eyes. Any third party with knowledge of one or more of your 24-word Recovery Phrase or PIN can gain control of the Private Keys associated with your Ledger Device or of the 24-word Recovery Phrase, and therefore steal your Crypto Assets, without any possibility for you or Ledger to retrieve them. -**The only existing backup is with you.** Ledger does not have access to or store passwords, 24-word Recovery Phrase, Private Keys, passphrases, transaction history, PIN, or other credentials associated with your use of the Services. We are not in a position to help you retrieve your credentials. You are solely responsible for remembering, storing, and keeping your credentials in a secure location, away from prying eyes. Any third party with knowledge of one or more of your 24-word Recovery Phrase or PIN can gain control of the Private Keys associated with your Ledger Device or of the 24-word Recovery Phrase; +**4.7 Keep your credentials safe.** When you set your Ledger Device up, you must: (a) create and remember a strong PIN that you do not use for any other service; (b) protect and keep your 24-word Recovery Phrase secure and confidential; (c) protect access to your Ledger Device; To learn more about how to use and secure your 24-word Recovery Phrase, we recommend that you visit ledger.com and in particular, or visit Ledger’s website and in particular, [this page](https://www.ledger.com/academy/crypto/what-is-a-recovery-phrase "Ledger Academy"), or the “Learn” section in Ledger Live and our support Website [here](https://support.ledger.com/hc/en-us/articles/360005514233?docs=true "Ledger Support"). -**Keep your credentials safe.** When you set your Ledger Device up, you must: (a) create and remember a strong PIN that you do not use for any other service; (b) protect and keep your 24-word Recovery Phrase secure and confidential; (c) protect access to your Ledger Device; +**4.8 Do not trust. Verify.** Software integrity, especially when connected to the Internet, is very hard to verify. Ledger’s security model relies on trusted display. This is why the verification of the information on your Ledger Device is paramount. Before you approve an operation, you must always double check that the information displayed on your mobile or desktop screen is correct and matches the information displayed on your Ledger Device. Upon sending Crypto Assets, you are solely responsible for verifying that the recipient address, amount and fees are correct and that they are the same on both your computer or mobile and on your Ledger Device’s screen. You also acknowledge that using unverified addresses to receive Crypto Assets comes at your own risk. -## Acceptable Use +**4.9 Learn more about crypto and the risks involved.** Before using Ledger Live or any of Ledger Devices, it’s important to learn and understand [how to use your Crypto Assets and the risks involved](https://www.ledger.com/academy "Ledger Academy"). To help you with that, Ledger recommends that you visit the [Ledger Academy](https://www.ledger.com/academy "Ledger Academy") before starting your crypto journey. -As a user of the Ledger Services, we grant you a limited, personal, non-commercial, non-exclusive, non-transferable, and revocable license to use the Ledger Services. When using Ledger Services, we ask that you follow some basic rules: +**4.10 No liability.** There may be additional risks that we have not foreseen or identified in these Terms. Before you use the Services, you are strongly encouraged to carefully assess whether your financial situation and risk tolerance is compatible with such use. For the avoidance of doubt, and notwithstanding the generality of the Limitation of Liability under these Terms, you hereby agree that Ledger shall have no liability for any loss that incurs as a consequence of the risks highlighted in this section and/or your failure to follow the recommendations herein. -**Do no harm.** You agree (i) not to distribute any virus or other harmful computer code through Ledger's systems, (ii) not to use any robot, spider, crawler, scraper or other automated means or interface not provided by us to access Ledger Services or to extract data, (iii) not to provide false, inaccurate, or misleading information, and (iv) not to take any action that may impose an unreasonable or disproportionately large load on our or any of our third party providers' infrastructure. +## 5\. Services and features -**Don't circumvent our security**. You agree not to bypass, circumvent, or attempt to bypass or circumvent any measures that we may use to prevent or restrict access to Ledger Services including, without limitation, Ledger Devices connected to Ledger Services, other accounts, information systems, or networks. +### 5.1 Services Overview -**Don't break the law**. You agree that you will not violate any laws when using Ledger Services. This includes any local, provincial, state, federal, national, or international laws that may apply to you. You agree that you will not use Ledger Services to pay for, support, or otherwise engage in any illegal activities including, but not limited to, fraud, illegal gambling, money laundering, or terrorist activities. You further agree not to encourage or induce any third party to engage in any of the activities prohibited under this section. +**5.1.1 Description.** Ledger Live, in connection with Ledger Devices, provides you with a convenient and secure way to manage your Device Applications, access and use Third Party Services, as well as use Private Keys derived from your 24-word Recovery Phrase. -**Don't interfere**. You agree that you will not use or attempt to use another user's Wallet without authorization, or use Ledger Services in any manner that could interfere with, disrupt, negatively affect, or inhibit other Users from fully enjoying Ledger Services, or that could damage, disable, overburden or impair the functioning of Ledger Services in any manner. +With Ledger Live, you can (including without limitation) -Any use of Ledger Services other than as specifically authorized in these Terms, without our prior written permission, is strictly prohibited and will terminate your license to use Ledger Services. - -## Warranties and Disclaimers - -Ledger will use reasonable level of skill and care to ensure that Ledger Services can be accessed by you in accordance with the present Terms of Use, but there are no guarantees that access and features will not be interrupted or that there will be no delays, failures, errors, omissions, corruption or loss of transmitted information. Ledger Services are provided "as is" without any warranty of any kind, either express or implied, and in particular without implied warranties of merchantability, reliability, and fitness for a particular purpose. - -### Availability of Ledger Services - -We may change, update or suspend the Services, temporarily or indefinitely, so as to carry out works including, but not limited to: firmware and software updates, maintenance operations, amendments to the servers, bug fixes etc. We will make reasonable efforts to give you prior notice of any significant disruption of Ledger Services. - -Ledger does not guarantee the correct functioning of the Services in the event of the installation or use of programs or applications that do not conform to Service specifications and technical standards. - -Please note that when a Ledger Service is unavailable or suspended, you can always recover your Private Keys using your 24-Recovery Phrase on any compatible Wallet. +- Update the firmware of your Ledger Device +- Install and uninstall Device Applications with the Ledger Live Manager +- View the balance of your portfolio of Crypto Assets that you hold in self-custody +- Manage your NFTs +- Learn about Crypto Assets, how to secure them and how to use them +- Keep track of cryptocurrency prices in real time +- Access the means to perform operations via our Third Party Services on various blockchain networks in accordance with their respective protocol rules, such as but not limited to: -### Underlying blockchain protocols +* Send and receive Crypto Assets to and from users of a dedicated blockchain network +* Stake your Crypto Assets on Proof-Of-Stake networks -All transactions created through Ledger Services are confirmed and recorded in associated blockchain networks. Such networks are decentralized peer-to-peer networks run by independent third parties, which Ledger does not own, control or operate. We have no control over blockchain networks and, therefore, cannot and do not ensure that the transactions you broadcast on Ledger Services will be confirmed and processed. You acknowledge that we do not store, send, or receive Crypto Assets and you agree that the transactions you configure on Ledger Services may fail, or may be substantially delayed by the underlying blockchain networks. +**5.1.2 Supported Crypto Assets.** Ledger Live and Ledger Devices are only capable of supporting certain Crypto Assets. A non-exhaustive list of supported Crypto Assets and compatible Wallets is available [here](https://support.ledger.com/hc/en-us/articles/115005304449-Supported-crypto-assets#targetText=Ledger%20Live%20supports%2022%20crypto,as%20send%20and%20receive%20them). This list is subject to change at the discretion of Ledger. -On occasions, the blockchain protocol of a given Crypto Asset may change, which may have consequences on its key characteristics including but not limited to their availability, name, security, valuation or the way it operates. Forks entail that forked Crypto Assets may be misdirected or replicated. In any such events, Ledger may decide, at its discretion, to suspend support of the impacted Crypto Asset for as long as Ledger deems necessary. When it so decides, Ledger will endeavor to give you advance notice, but may not be able to. You should keep yourself apprised of such events and make all necessary arrangements. +**5.1.3 Services availability.** We may change, update or suspend the Services, temporarily or indefinitely, so as to carry out works including, but not limited to: firmware and software updates, maintenance operations, amendments to the servers, bug fixes, etc. We will make reasonable efforts to give you prior notice of any significant disruption of the Services. Ledger does not guarantee the correct functioning of the Services in the event of the installation or use of programs or applications that do not conform to Service specifications and technical standards. Please note that when a Service is unavailable or suspended, you can always recover your Private Keys using your 24-Recovery Phrase on any compatible Wallet. -### Device Applications +**5.1.4 Connect with your Ledger Device.** Certain Services may be used without connecting your Ledger Device (such as access to learning content, monitoring cryptocurrency prices or view the balance of your portfolio) whereas other Services may only be used in connection with your Ledger Device, including without limitation send, buy, sell, swap and stake services. -Device Applications are available for download on Ledger Live Manager, or can be installed following our [guidelines](https://ledger.readthedocs.io/en/latest/userspace/getting_started.html) and may either be developed by Ledger, or by any willing third party, thanks to open source code available on Ledger [Github repository.](https://github.com/LedgerHQ) +**5.1.5 Device Applications.** Device Applications are available for download on Ledger Live Manager, or can be installed following our [guidelines](https://ledger.readthedocs.io/en/latest/userspace/getting_started.html) and may either be developed by Ledger, or by any willing third party, thanks to open source code available on Ledger [Github repository](https://github.com/LedgerHQ). Such third party developers of Device Applications are responsible for the said applications and their performance, and for providing support for Device Applications supported on a Ledger Device and on Ledger Live. Ledger may perform code reviews and conduct security audits of Device Applications available on Ledger Live Manager, which does not constitute any kind of endorsement nor any guarantee that those applications are risk-free. Ledger does not warranty that Device Applications will be maintained over time and reserves the right to restrict or suspend access to them from Ledger Live for any reason for as long as deemed necessary. -Developers of Device Applications are responsible for the said applications and their performance, and for providing support for Device Applications supported on a Ledger Device and on Ledger Live. Ledger may perform code reviews and conduct security audits of Device Applications available on Ledger Live Manager, which does not constitute any kind of endorsement nor any guarantee that those applications are risk-free. +**5.1.6 Experimental features.** In order to accommodate advanced Users’ requests and to build new features and functionalities, we may release a series of experimental features on Ledger Live from time to time. These features may not be complete and may have not been fully tested, which may present heightened risks. They may contain errors or inaccuracies that could cause failures, corruption or loss of data and/or information. You can think of these features as beta features. Ledger does not guarantee the stability, functionality, or long-term support of these features. We do not recommend to use these features unless you are an advanced User with strong technical skills. You expressly acknowledge and agree that use of the experimental features is at your sole risk. -Ledger does not warranty that Device Applications will be maintained over time and reserves the right to restrict or suspend access to them from Ledger Services for any reason for as long as deemed necessary. +### **5.2 Third Party Services** -### Experimental features +**5.2.1 Third Party Services terms and conditions.** Ledger Live may incorporate, reference and/or provide access to Third Party Services. For instance, buy, sell and crypto to crypto exchange (“swap”) services are Third Party Services. You agree that your use of Third Party Services is subject to separate terms and conditions between you and the third-party identified in Ledger Live. For ease of reference, a list of links to Third Party Services terms and conditions is available below. Ledger does not guarantee that such a list is comprehensive and it’s your responsibility to review and understand the applicable terms and conditions before using a Third Party Service: -In order to accommodate advanced Users' requests and to build new features and functionalities, we have released a series of experimental features on Ledger Live. These features may not be complete and have not been fully tested, which may present heightened risks. They may contain errors or inaccuracies that could cause failures, corruption or loss of data and/or information. You can think of these features as beta features. Ledger does not guarantee the stability, functionality, or long-term support of these features. We do not recommend to use these features unless you are an advanced User with strong technical skills. You expressly acknowledge and agree that all use of the Experimental Features is at your sole risk. +- [Coinify Terms and conditions](https://www.coinify.com/legal/) +- [Moonpay Terms of use](https://www.moonpay.com/legal/terms_of_use) +- [Ramp Terms of service](https://ramp.network/terms-of-service/) +- [BTC Direct User agreement](https://btcdirect.eu/media/4385/download/User%20agreement%20BTC%20Direct.pdf?v=1&inline=1) +- [Banxa Terms of use](https://banxa.com/terms-of-use/) +- [Transak Terms of service](https://www.notion.so/Transak-Terms-of-Service-6d89598211644402b3be63bc3f1468b4) +- [Mercuryo Legal terms](https://mercuryo.io/legal/terms/) +- [Wyre User agreement](https://www.sendwyre.com/user-agreement/) +- [Simplex Terms of use](https://www.simplex.com/terms-of-use) +- [Zerion Terms](https://zerion.io/terms.pdf) +- [Bitrefill Terms](https://www.bitrefill.com/terms/?hl=en) +- [Changelly Terms of use](https://changelly.com/terms-of-use) +- [FTX Terms of service](https://help.ftx.com/hc/en-us/articles/360024788391-FTX-Terms-of-Service) +- [Paraswap Terms of service](https://psdocs.fra1.digitaloceanspaces.com/tos_v2.pdf) -## Transaction details +**5.2.2 No warranty.** Ledger is not responsible for the content, accuracy, security, availability, any performance, or failure to perform of the Third Party Services or any issue in relation with the use of Third Party Services. Ledger does not provide any guarantees that access to Third Party Services will not be interrupted or that there will be no delays, failures, errors, omissions, corruption or loss of transmitted information, data or funds, and Ledger shall not be liable for any such Third Party Services. You agree to use the Third Party Services at your own risk. It is your responsibility to review the third party’s terms and policies before using a Third Party Service. Third Party Services may not be available in all languages and may not be appropriate or available for use in any particular location. To the extent you choose to use such Third Party Services, you are solely responsible for compliance with any applicable laws in relation to such use. In addition, Ledger reserves the right to block access to these Third Party Services through Ledger Live in particular, but not exclusively, in the event of non-compliance with the applicable regulations by the Third Party partner. We retain the exclusive right to suspend, remove, or cancel the availability of any such Third Party Service for any reason and without prior notice. -**Do not trust. Verify.** Software integrity, especially when connected to the Internet, is very hard to verify. Ledger's security model relies on trusted display.This is why the verification of the information on your Ledger Device is paramount. Before you approve an operation, you must always double check that the information displayed on your mobile or desktop screen is correct and matches the information displayed on your Ledger Device. Upon sending Crypto Assets, you are solely responsible for verifying that the recipient address, amount and fees are correct and that they are the same on both your computer or mobile and on your Ledger Device's screen. You also acknowledge that using unverified addresses to receive Crypto Assets comes at your own risk. +**5.2.3 Personal data.** Some Third Party Services may request or require access to your personal data. The processing of such data will be handled in accordance with the relevant Third Party’s privacy policy and best practices. -## Third Party Services and Materials +**5.2.4 Issues with Third Party Services.** Third Party Services may not work appropriately with your software or Ledger Device, and we may not be able to provide support for issues caused by Third Party Services as Ledger does not provide nor operate the Third Party Services. If you have questions or concerns about how a Third Party Service operates, or need support, please contact the relevant third party directly. -Ledger Live may incorporate, reference or provide access to Third Party Services. +**5.2.5 Decentralized financial applications.** Certain Third Party Services are not operated by identified entities, but can be accessed directly through an interaction between the User’s wallet (whether or not the User uses the Application DeviceDevice Application or the Ledger Device) and one or several programs that are solely deployed and accessible on a blockchain network (i.e. “smart contracts”). These Third Party Services allow you to benefit from various services (such as the exchange, lending or borrowing of Crypto Assets) without having to provide your personal information to an intermediary. By using these Third Party Services, you agree that their use may not be subject to terms and conditions nor any other kind of contractual relationship with the third party operating such operator of the service. To the extent you choose to use such Third Party Services, you acknowledge that Ledger is not responsible for any issue in relation with the use of such Third Party Services, including any loss of funds. -You agree that your use of Third Party Services is subject to separate terms and conditions between you and the third party identified in Ledger Live. Ledger is not responsible for any performance, or failure to perform the Third Party Services. It is your responsibility to review the third party's terms and policies before using a Third Party Service. Some Third Party Services may request or require access to your personal data. The processing of such data will be handled in accordance with the relevant Third Party's privacy policy and best practices. +**5.2.6 Fees.** The use of certain Third Party Services may be subject to transaction fees and/or other fees charged by such Third Party Services. On top of such fees, Ledger reserves the right to charge you fees for the secured and facilitated access provided by Ledger to use such Third Party Services through the Ledger Live (“Ledger Fees”). Ledger Fees may be charged directly to the User or indirectly if already included in the Third Party Fees and paid by the Third Party to Ledger on behalf of the User. In such event, Ledger will fully display all applicable fees and any applicable taxes. -Third Party Services may not work appropriately with your software or Ledger Device, and we may not be able to provide support for issues caused by Third Party Services. If you have questions or concerns about how a Third Party Service operates, or need support, please contact the relevant third party directly. +### 5.3 Staking -We advise not to share any credential, password, Private Key, passphrase, or any other sensitive information with any Third Party Service without validating their legitimacy first. +**5.3.1 General.** Through Ledger Live, you can stake specific assets to receive rewards for securing Proof-of-Stake (POS) networks. You may choose to stake your assets by delegating to a Ledger operated validator node or to a third-party validator node. If you choose to stake your assets with a third-party validator node (including the “Ledger by Figment” node or any other “Ledger by…” node), then such staking is subject to the third party’s staking terms and conditions. LEDGER DOES NOT PROVIDE ANY ADVICE OR MAKE ANY RECOMMENDATIONS ABOUT ENGAGING IN STAKING OR CHOOSING A VALIDATOR.  Ledger reserves the right to modify the list of referenced validators at any time without prior notice. -We retain the exclusive right to add to, modify, or cancel the availability of any such Third Party Service for any reason and without prior notice. +**5.3.2 Staking Rewards.** You explicitly confirm that you are aware that delegation of staking rights to a validator operator listed in Ledger Live does not grant to your benefit any right to request payment of any kind, but merely a potential right to share a reward perceived by the validator. If you stake your assets with a Ledger operated node, Ledger will be acting as a transaction validator on the applicable Proof-of-Stake (POS) network. If Ledger successfully validates a block of transactions in that network, you may receive staking rewards granted by such network and Ledger will receive validator fees (at the rate indicated to you when staking your assets with Ledger’s validator). Your reward will be determined by the protocols of the applicable network. Please be aware that some Proof-of-Stake networks require that a certain amount of staked assets be “locked” (restricted from any use, sale or transfer) for a certain period of time while staking. -Specific rules and obligations apply to the following Services: +**5.3.4 No custody.** Ledger will never take custody over any of your rewards or assets and Ledger has no responsibility or control over any Proof-of-Stake network on which Ledger may exercise validation rights delegated by you. -1. **Buy Crypto services** +**5.3.5 No guarantee of Rewards.** LEDGER DOES NOT GUARANTEE THAT YOU WILL RECEIVE STAKING REWARDS OR ANY STAKING REWARD RATES. SUCCESSFUL TRANSFER OF THE REWARDS IS SUBJECT TO THE PROOF-OF-STAKE NETWORKS AND IS NOT UNDER LEDGER’S CONTROL. -Links to Buy Crypto services are sponsored links. The existence of a link to or from one of Ledger Services does not represent or imply any endorsement of such services. +**5.3.6 Disclaimer.** Staking is provided “as is”. Ledger is not responsible in any way for any failure by any supported Proof-Of-Stake (POS) network to transfer rewards (including any risks of “slashing”) or for the loss, destruction, or transfer of rewards to the incorrect wallet address. Ledger does not guarantee uninterrupted or error-free operation of the staking services or that it will correct all defects or prevent third-party disruptions or unauthorized third party access. -1. **Delegation of staking rights** +## 6\. Acceptable Use  -**Rewards**. You explicitly confirm that you are aware that delegation of staking rights to a validator operator listed in Ledger Live does not grant to your benefit any right to request payment of any kind, but merely a potential right to share a reward perceived by the validator. Please note that lock-up periods depend on the validator and blockchain protocols. +**6.1 User License.** As a user of Ledger Services, we grant you a limited, personal, non-commercial, non-exclusive, non-transferable, and revocable license to use the Services. Any use of the Services other than as specifically authorized in these Terms, without our prior written permission, is strictly prohibited and may result in immediate termination of your license to use the Services. -**Validators**. Ledger reserves the right to modify the list of referenced validators at any time without prior notice. +**6.2 Do no harm.** You agree (i) not to distribute any virus or other harmful computer code through Ledger’s systems, (ii) not to use any robot, spider, crawler, scraper or other automated means or interface not provided by us to access the Services or to extract data, (iii) not to provide false, inaccurate, or misleading information, and (iv) not to take any action that may impose an unreasonable or disproportionately large load on our or any of our third party providers’ infrastructure. -## Limitation of liability +**6.3 Don’t circumvent our security\*\***.\*\* You agree not to bypass, circumvent, or attempt to bypass or circumvent any measures that we may use to prevent or restrict access to the Services including, without limitation, Ledger Devices connected to the Services, other accounts, information systems, or networks. -YOU EXPRESSLY UNDERSTAND AND AGREE THAT LEDGER AND ITS DIRECTORS AND EMPLOYEES SHALL NOT BE LIABLE TO YOU FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DAMAGES FOR LOSS OF PROFITS, GOODWILL, USE, DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR OTHER INTANGIBLE LOSSES, RESULTING FROM: (I) THE USE OR INABILITY TO USE THE SERVICES (II) ANY CHANGES MADE TO THE SERVICE OR ANY SUSPENSION OR CESSATION OF THE SERVICES OR ANY PART THEREOF; (III) THE UNAUTHORIZED ACCESS TO OR ALTERATION OF YOUR TRANSMISSIONS OR DATA; (IV) THE DELETION OF, CORRUPTION OF, OR FAILURE TO STORE AND/OR SEND OR RECEIVE YOUR TRANSMISSIONS OR DATA ON OR THROUGH THE SERVICE; AND (V) ANY OTHER MATTER RELATING TO THE SERVICE. +**6.4 Don’t break the law\*\***.\*\* You agree that you will not violate any laws when using the Services. This includes any local, provincial, state, federal, national, or international laws that may apply to you. You agree that you will not use the Services to pay for, support, or otherwise engage in any illegal activities including, but not limited to, fraud, illegal gambling, money laundering, or terrorist activities. You further agree not to encourage or induce any third party to engage in any of the activities prohibited under this section. -THE ABOVE LIMITATIONS DO NOT APPLY IN RESPECT OF LOSS RESULTING FROM (A) LEDGER'S FRAUD, WILFUL MISCONDUCT OR GROSS NEGLIGENCE, WILFUL MISCONDUCT OR FRAUD; OR (B) DEATH OR PERSONAL INJURY. +**6.5 Don’t interfere\*\***.\*\* You agree that you will not use or attempt to use another user’s Wallet without authorization, or use the Services in any manner that could interfere with, disrupt, negatively affect, or inhibit other Users from fully enjoying the Services, or that could damage, disable, overburden or impair the functioning of the Services in any manner. -## Intellectual Property +**6.6 Intellectual Property.** Ledger respects the intellectual property of others and we ask our Users to do the same. You acknowledge and agree that, with the exception of Materials released or anyway made available pursuant to public license agreements, open source, MIT, or other non-proprietary license schemes normally used by the Ledger community, Ledger owns all copyrights, trademarks, know-how or any other intellectual property rights in respect of the software, text, video, audio, artwork, logos, layout as well as the look and feel pertaining to Ledger Live, Device Applications, and the Website. You may view, print and/or download a copy of proprietary Materials from the Services on any single computer solely for your personal, informational and/or non-commercial use, provided you comply with all copyright and other proprietary notices. The trademarks, service marks and logos of Ledger and others used in the Services (“Trademarks”) are the property of Ledger and their respective owners. It is strictly prohibited to use these Trademarks without our express written authorisation or the express written authorisation of any third parties. -Ledger respects the intellectual property of others and we ask our Users to do the same. You acknowledge and agree that, with the exception of Materials released or anyway made available pursuant to public license agreements, open source, MIT, or other non-proprietary license schemes normally used by the Ledger community, Ledger owns all copyrights, trademarks, know-how or any other intellectual property rights in respect of the software, text, video, audio, artwork, logos, layout as well as the look and feel pertaining to Ledger Live, Device Applications, and the Website. +## 7\. Feedback -You may view, print and/or download a copy of proprietary Materials from Ledger Services on any single computer solely for your personal, informational and/or non-commercial use, provided you comply with all copyright and other proprietary notices. +We welcome feedback, comments, ideas, and suggestions for improvements to the Services (“Feedback”). You grant to us a non-exclusive, worldwide, perpetual, irrevocable, fully-paid, royalty-free, sublicensable and transferable license under any and all intellectual property rights that you own or control to use, copy, modify, create derivative works based upon and otherwise exploit the Feedback for any purpose. -The trademarks, service marks and logos of Ledger and others used in the Services ("Trademarks") are the property of Ledger and their respective owners. It is strictly prohibited to use these Trademarks without our express written authorisation or the express written authorisation of any third parties. +## 8\. Warranties and Disclaimers -## Feedback +**8.1 No warranty.** Ledger will use reasonable level of skill and care to ensure that the Services can be accessed by you in accordance with the present Terms of Use, but there are no guarantees that access and features will not be interrupted or that there will be no delays, failures, errors, omissions, corruption or loss of transmitted information. The Services are provided “as is” without any warranty of any kind, either express or implied, and in particular without implied warranties of merchantability, reliability, and fitness for a particular purpose. -We welcome feedback, comments, ideas, and suggestions for improvements to the Services ("Feedback"). You grant to us a non-exclusive, worldwide, perpetual, irrevocable, fully-paid, royalty-free, sublicensable and transferable license under any and all intellectual property rights that you own or control to use, copy, modify, create derivative works based upon and otherwise exploit the Feedback for any purpose. +**8.2 Limitation of Liability.** YOU EXPRESSLY UNDERSTAND AND AGREE THAT LEDGER AND ITS DIRECTORS AND EMPLOYEES SHALL NOT BE LIABLE TO YOU FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DAMAGES FOR LOSS OF PROFITS, GOODWILL, USE, DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR OTHER INTANGIBLE LOSSES, RESULTING FROM: (I) THE USE OR INABILITY TO USE THE SERVICES (II) ANY CHANGES MADE TO THE SERVICES OR ANY SUSPENSION OR CESSATION OF THE SERVICES OR ANY PART THEREOF; (III) THE UNAUTHORIZED ACCESS TO OR ALTERATION OF YOUR TRANSMISSIONS OR DATA; (IV) THE DELETION OF, CORRUPTION OF, OR FAILURE TO STORE AND/OR SEND OR RECEIVE YOUR TRANSMISSIONS OR DATA ON OR THROUGH THE SERVICES; AND (V) ANY OTHER MATTER RELATING TO THE SERVICES. SAVE FOR THIRD PARTY SERVICES WHICH ARE NOT OPERATED OR PROVIDED BY LEDGER, THE ABOVE LIMITATIONS DO NOT APPLY IN RESPECT OF LOSS RESULTING FROM (A) LEDGER’S FRAUD, WILFUL MISCONDUCT OR GROSS NEGLIGENCE, WILFUL MISCONDUCT OR FRAUD; OR (B) DEATH OR PERSONAL INJURY. -## Compliance and Export Control +## 9\. Compliance and Export Control -Users shall comply, at their own expense, with all laws that apply to or result from their obligations under these Terms. By accessing and using the Services, you represent and warrant that you are not on any trade or economic sanctions lists, such as (but not limited to) the UN Security Council Sanctions list, designated as a "Specially Designated National" by OFAC (Office of Foreign Assets Control of the U.S. Treasury Department) or placed on the U.S. Commerce Department's "Denied Persons List". +**9.1 Sanctions.** Users shall comply, at their own expense, with all laws that apply to or result from their obligations under these Terms. By accessing and using the Services, you represent and warrant that you are not on any trade or economic sanctions lists, such as (but not limited to) the UN Security Council Sanctions list, designated as a “Specially Designated National” by OFAC (Office of Foreign Assets Control of the U.S. Treasury Department) or placed on the U.S. Commerce Department’s “Denied Persons List”. -Ledger reserves the right to select the markets and jurisdictions where it operates and may restrict or deny access to Ledger Services in certain countries, states or territories. +**9.2 Territories.** Ledger reserves the right to select the markets and jurisdictions where it operates and may restrict or deny access to Services in certain countries, states or territories. -## Termination +## 10\. Termination - Suspension -You may stop using the Services at any time. We reserve the right to suspend your access to Ledger Services without notice if we believe you violated these Terms. In the event of termination concerning your license to use Ledger, your obligations under these Terms will continue. +**10.1 Termination rights.** You may stop using the Services at any time. We reserve the right to suspend or terminate your access to the Services without notice if we believe you violated these Terms. -Your access to your Wallets after termination will depend on whether you securely backed up your Private Keys and your Wallet address. +**10.2 Access to your Wallets upon termination.** Ledger does not control access to your Wallets. Please make sure that to securely back up your Private Keys and your Wallet address at all times to ensure access to your Crypto Assets after termination. -## Applicable law +## 11\. Governing law and jurisdiction -These Terms will be governed by and interpreted in accordance with the laws of France. +**11.1 Governing Law.** These Terms will be governed by and interpreted in accordance with the laws of France. -Any dispute, controversy, difference or claim arising out of or relating to this Agreement, including the existence, validity, interpretation, performance, breach or termination thereof or any dispute regarding non-contractual obligations arising out of or relating to it shall be referred to and finally resolved by the competent courts of Paris, France. +**11.2. Out-of-court settlement.** For Users residing in a member state of the European Union, in the event the claim would not be solved through our customer support or would remain without response within more than two (2) months after its reception by our customer support, the User may choose to submit the dispute to an out-of-court settlement procedure through the European platform for alternative and online dispute resolution [here](https://webgate.ec.europa.eu/odr/). -## Enforcement and Assignment of Terms +**11.3 Jurisdiction.** Any dispute, controversy, difference or claim arising out of or relating to this Agreement, including the existence, validity, interpretation, performance, breach or termination thereof or any dispute regarding non-contractual obligations arising out of or relating to it shall be referred to and finally resolved by the competent courts of Paris, France. -These Terms constitute the entire and exclusive understanding and agreement between Ledger and you regarding Ledger Services, and supersede and replace any and all prior oral or written understandings or agreements between Ledger and you regarding Ledger Services. If you do not read and accept the Terms in their entirety you should not use or continue using Ledger Services. +## 12. General -We reserve the right to alter, amend or modify these Terms from time to time, in our sole discretion. We will provide you with notice of such changes by posting the amended Terms via Ledger Live and updating the "Last Updated" date at the top of these Terms. The amended Terms will be deemed effective immediately upon posting on Ledger Live. +**12.1 Entire Agreement.** These Terms constitute the entire and exclusive understanding and agreement between Ledger and you regarding Ledger Live, and supersede and replace any and all prior oral or written understandings or agreements between Ledger and you regarding Ledger Live. If you do not read and accept the Terms in their entirety you should not use or continue using Ledger Services. -You may not assign your rights or obligations under these Terms of Use in whole or in part to any third party. +**12.2 Changes to the Terms.** We reserve the right to alter, amend or modify these Terms from time to time, in our sole discretion, due to legislative or regulatory measures, technical developments, any change or improvement of the Services including security reinforcement of the Services. We will provide you with notice of such changes through Ledger Live and such changes shall apply immediately upon your acceptance or within one (1) month upon notice of changes at the latest. In any case, if you do not accept the changes, you must cease to use the Services. -You acknowledge and agree that Ledger may assign its rights and obligations under these Terms of Use and, in such context, share or transfer information provided by you while using Ledger Services to a third party. +**12.3 Assignment.** You may not assign your rights or obligations under these Terms in whole or in part to any third party. You acknowledge and agree that Ledger may assign its rights and obligations under these Terms of Use and, in such context, share or transfer information provided by you while using the Services to a third party. -Would any provision of these Terms of Use or part thereof to any extent be or become invalid or unenforceable, such provision shall then be deemed separable from the remaining provisions of these Terms of Use and shall not affect or impair the validity or enforceability of the remaining provisions of these Terms of Use. +**12.4 Severability.** Should any provision of these Terms or part thereof to any extent be or become invalid or unenforceable, such provision shall then be deemed separable from the remaining provisions of these Terms and shall not affect or impair the validity or enforceability of the remaining provisions of these Terms. diff --git a/TERMS.ru.md b/TERMS.ru.md deleted file mode 100644 index 9f18088194..0000000000 --- a/TERMS.ru.md +++ /dev/null @@ -1,220 +0,0 @@ -# Условия использования Ledger Live - -_10 ДЕКАБРЯ 2019 Г._ - -Вы собираетесь воспользоваться платформой Ledger Live. Рады приветствовать! Прежде чем воспользоваться платформой Ledger, следует внимательно прочесть, осмыслить и принять наши Условия использования (далее — «Условия»). - -Обзор - -Это соглашение заключается между вами («вы», «ваш» или «Пользователь») и компанией Ledger SAS («Ledger», «нас», «мы», «наш» или «Компания»). Воспользовавшись любым из сервисов или нажав «Я согласен(-на)» для сервиса, предоставляемого компанией Ledger или ее дочерними предприятиями в связи с программным обеспечением Ledger Live (далее — «Сервисы Ledger»), вы подтверждаете, что внимательно прочитали и принимаете все указанные ниже условия. - -Использование Сервисов Ledger также регулируется Политикой конфиденциальности компании Ledger, доступной на странице [** https://shop.ledger.com/pages/nasha-politika-konfidentsialnosti**](https://shop.ledger.com/pages/nasha-politika-konfidentsialnosti). - -ПЕРЕД ИСПОЛЬЗОВАНИЕМ СЕРВИСОВ ИЗУЧИТЕ СООТВЕТСТВУЮЩУЮ ИНФОРМАЦИЮ ДЛЯ ПРИНЯТИЯ ОБОСНОВАННЫХ РЕШЕНИЙ. КРИПТОАКТИВЫ ВОЛАТИЛЬНЫ. ЦЕНЫ НА НИХ МОГУТ РАСТИ И ПАДАТЬ. ВНИМАТЕЛЬНО ОЦЕНИТЕ СВОИ ЦЕЛИ И ФИНАНСОВЫЙ РИСК, НА КОТОРЫЙ ВЫ ГОТОВЫ ПОЙТИ. ОБРАТИТЕ ВНИМАНИЕ: КОМПАНИЯ LEDGER НЕ ПРЕДОСТАВЛЯЕТ КОНСУЛЬТАЦИЙ ПО ФИНАНСОВЫМ, НАЛОГОВЫМ ИЛИ ЮРИДИЧЕСКИМ ВОПРОСАМ. РЕШЕНИЯ О ВЫПОЛНЕНИИ ОПЕРАЦИЙ С КРИПТОАКТИВАМИ СЛЕДУЕТ ПРИНИМАТЬ САМОСТОЯТЕЛЬНО ИЛИ НА ОСНОВАНИИ МНЕНИЯ НАДЕЖНЫХ И КВАЛИФИЦИРОВАННЫХ ЭКСПЕРТОВ. - -Определения - -В настоящем Договоре следующие термины будут иметь значения, определяемые ниже, причем во избежание неоднозначного толкования слова, обозначающие единственное число, включают также множественное число и наоборот, за исключением случаев, когда явно указано иное. - -**Криптоактивы** -Типы цифровых активов, которые могут передаваться посредством технологий блокчейна, включая, помимо прочего, Bitcoin, Ethereum и Ripple. - -**Приложение для устройства** -Программа, разработанная компанией Ledger или сторонними компаниями, которая добавляет определенную логическую последовательность криптографической подписи в операционную систему BOLOS от Ledger для создания транзакции в Ledger Live или стороннем приложении и позволяет подписывать различные операции на устройстве Ledger, включая, помимо прочего, трансляцию транзакций криптоактивов, аутентификацию и управление паролями. - -**Форк** -Изменение основного протокола сети блокчейна, в результате которого создается несколько версий криптоактива, причем одна или несколько версий могут не поддерживаться Сервисами Ledger. - -**Устройство Ledger** -Электронное устройство, разработанное и распространяемое компанией Ledger, обычно именуемое аппаратным кошельком, которое применяется для защиты закрытых ключей Пользователей и других секретных криптографических данных, совместимых с Ledger Live или соответствующими кошельками, а также для управления ими. - -**Диспетчер Ledger Live** -Каталог доступных для загрузки приложений для устройства, который позволяет Пользователям обновлять встроенное ПО устройства Ledger, устанавливать приложения для устройства и управлять поддерживаемыми криптоактивами. - -**Материалы** -Содержимое, документация в отношении Сервисов Ledger, а также исходный и объектный коды для всего встроенного программного обеспечения Ledger Live и устройств Ledger. - -**ПИН-код** -цифровой пароль, установленный Пользователем для разблокировки устройства Ledger. - -**Закрытые ключи** -Критически важные данные, используемые для авторизации исходящих транзакций в сетях блокчейна. - -**Сервисы** -Один или несколько Сервисов компании Ledger или сторонних компаний. - -**Сторонние сервисы** -Приложения, программное обеспечение или другие материалы, размещенные, разработанные или управляемые третьей стороной, включая, помимо прочего, биржи криптовалюты, поставщиков услуг так называемого стейкинга. - -**Кошелек** -Программа, которая взаимодействует с различными сетями блокчейна для создания наборов закрытых и открытых ключей и управления ими, настройки транзакций и мониторинга их баланса. - -**Веб-сайт** -Веб-сайты, принадлежащие компании Ledger и управляемые ею, включая веб-сайты интернет-магазинов и корпоративные веб-сайты, размещенные по адресу ledger.com. - -**Фраза восстановления из 24 слов** -Понятная для пользователя конфиденциальная комбинация слов, генерируемая устройствами Ledger, на основании которой создаются закрытые ключи пользователей. Они используются для создания резервных копий и восстановления доступа к криптоактивам на других устройствах Ledger или в совместимых кошельках. - -Право на использование - -Чтобы иметь право пользоваться Сервисами, вы должны достичь 18 лет или возраста совершеннолетия, установленного в стране вашего проживания. Если вы пользуетесь нашими Сервисами от имени юридического лица, вы заверяете и гарантируете, что: (а) юридическое лицо учреждено в надлежащем порядке и осуществляет свою деятельность в соответствии с применимым законодательством юрисдикции его регистрации и (б) вы должным образом уполномочены таким юридическим лицом действовать от его имени. - -Вы можете пользоваться Сервисами только в соответствии с законодательством вашей юрисдикции. Убедитесь, что эти Условия соответствуют всем применимым законам, правилам и постановлениям. - -Сервисы Ledger - -Платформа Ledger Live вместе с устройствами Ledger обеспечивает удобный и безопасный способ управления приложениями на вашем устройстве, а также использования закрытых ключей, полученных на основании фразы восстановления из 24 слов. - -Сервисы Ledger позволяют Пользователям: - -- обновлять встроенное ПО на устройстве Ledger; -- устанавливать приложения на устройство и удалять их с помощью диспетчера Ledger Live; -- просматривать портфель криптоактивов; -- получать доступ к средствам выполнения операций в различных сетях блокчейна, руководствуясь соответствующими правилами протоколов, включая, помимо прочего: отправку криптоактивов Пользователям и получение их от Пользователей специальной сети блокчейна; -- подключаться к сторонним сервисам, чтобы получить доступ к таким сервисам, как делегирование прав на стейкинг в поддерживаемых сетях блокчейна с защитой по методу доказательства владения или покупка криптовалюты. - -Компания Ledger предоставляет некастодиальные сервисы, то есть мы не храним ваши криптоактивы и закрытые ключи и не имеем к ним доступа. Мы не отправляем и не получаем криптоактивы. Любая передача криптоактивов происходит в сетях блокчейна, а не в сети, принадлежащей компании Ledger или контролируемой ею. - -Ledger Live и устройства Ledger поддерживают только определенные криптоактивы. Неисчерпывающий список поддерживаемых криптоактивов и совместимых кошельков доступен [здесь](about:blank#targetText=Ledger%20Live%20supports%2022%20crypto,as%20send%20and%20receive%20them.). В этот список могут быть внесены изменения. - -Риск - -Считается, что вы в полной мере осведомлены обо всех правовых нормах и технических ограничениях, связанных с сетями блокчейна с защитой по методу доказательства доли владения и доказательства выполнения работы, а также с Сервисами. Вы подтверждаете, что были предупреждены об описанных далее сопутствующих рисках. - -**Изменения в нормативной базе.** Технологии блокчейна адаптируются к постоянным изменениям в нормативной базе и подвергаются тщательным проверкам во всем мире, включая, помимо прочего, положения по борьбе с отмыванием денег и финансовое регулирование. Вы осознаете, что определенные Сервисы (включая их доступность) могут подпадать под действие одного или нескольких нормативных требований. - -**Налогообложение.** Транзакции с криптоактивами или, в более широком смысле, операции с криптоактивами, включая, помимо прочего, обмен, так называемые эйрдропы, форки и прибыль, возникающую в результате стейкинга, могут считаться налогообразующими случаями согласно законодательству, по которому происходит налогообложение. Эти правила могут быть непонятны или могут изменяться, поэтому рекомендуем обратиться к своему налоговому или финансовому консультанту, прежде чем проводить операции с криптоактивами. - -**Технология.** Пользователи понимают, что некоторые технологии, поддерживаемые или предоставляемые Сервисами, являются новыми, не до конца проверенными и неконтролируемыми компанией Ledger. Прогресс в области криптографии и другие технические достижения, например разработка квантовых компьютеров, могут представлять риски для сетей блокчейна, которые могут привести к краже или потере криптоактивов. Другие неблагоприятные изменения рыночных сил или технологий в целом могут поставить под угрозу работу компании Ledger в рамках настоящих Условий. - -**Кибербезопасность. ** Хакеры или другие группы и организации могут пытаться препятствовать работе продуктов и информационных систем компании Ledger различными способами, включая, помимо прочего, атаки типа «отказ в обслуживании», атаки по сторонним каналам, спуфинг, смурфинг, атаки вредоносного ПО или атаки на основе алгоритма консенсуса. - -Кроме того, могут возникнуть дополнительные риски, не предусмотренные или не определенные в настоящих Условиях. Прежде чем использовать наши Сервисы, настоятельно рекомендуется тщательно оценить, совместимы ли ваше финансовое положение и допустимый риск с таким использованием. - -Во избежание неоднозначного толкования и без ограничения общего характера раздела «Ограничение ответственности», настоящим вы соглашаетесь с тем, что компания Ledger не несет ответственности за какие-либо убытки, возникшие вследствие рисков, описанных в этом разделе. - -Запрет на восстановление закрытых ключей - -**Единственная резервная копия находится у вас.** Компания Ledger не имеет доступа к паролям, фразам для восстановления из 24 слов, закрытым ключам, парольным фразам, журналам транзакций, ПИН-кодам и другими учетным данным, связанным с использованием Сервисов, а также не хранит их. Мы не сможем помочь вам в восстановлении учетных данных. Вы несете исключительную ответственность за хранение своих учетных данных в безопасном месте, вдали от любопытных глаз. Любая третья сторона, знающая одну или несколько ваших фраз восстановления из 24 слов или ПИН-код, может завладеть закрытыми ключами, связанными с вашим устройством Ledger, или фразу восстановления из 24 слов. - -**Храните учетные данные в безопасном месте.** При настройке устройства Ledger необходимо: (а) создать и запомнить надежный ПИН-код, который не используется для других сервисов; (б) придумать фразу восстановления из 24 слов и сохранить ее в безопасном и конфиденциальном месте; (c) защитить доступ к устройству Ledger; - -Допустимое применение - -Пользователю Сервисов Ledger предоставляется ограниченная, личная, некоммерческая, неисключительная, непередаваемая и подлежащая аннулированию лицензия на использование Сервисов Ledger. При использовании Сервисов Ledger просим соблюдать определенные основные правила. - -**Не наносить вред.** Вы соглашаетесь (i) не распространять вирусы или другой вредоносный компьютерный код через системы Ledger, (ii) не использовать программы-роботы, программы-обходчики, поисковые боты, скрейперы или другие автоматизированные средства или интерфейсы, не предоставленные нами, для доступа к Сервисам Ledger или извлечения данных, (iii) не предоставлять ложную, неточную или вводящую в заблуждение информацию и (iv) не предпринимать действий, которые могут создать необоснованную или несоизмеримо большую нагрузку на нашу инфраструктуру или инфраструктуру сторонних поставщиков. - -**Не обходить нашу систему безопасности.** Вы обязуетесь не обходить и не предпринимать попыток обойти какие-либо меры, используемые для предотвращения или ограничения доступа к Сервисам Ledger, включая, помимо прочего, устройства Ledger, подключенные к Сервисам Ledger, другим учетным записям, информационным системам или сетям. - -**Не нарушать закон.** Вы обязуетесь не нарушать законодательство при использовании Сервисов Ledger. Это касается любых местных, провинциальных, государственных, федеральных, национальных и международных законов, которые могут быть к вам применимы. Вы обязуетесь не пользоваться Сервисами Ledger для оплаты, поддержки или иного участия в любых незаконных действиях, включая, помимо прочего, мошенничество, незаконные азартные игры, отмывание денег или террористическую деятельность. Вы также соглашаетесь не одобрять и не склонять третьи стороны к участию в каких-либо действиях, запрещенных в рамках данного раздела. - -**Не препятствовать.** Вы обязуетесь не использовать и не предпринимать попыток использовать кошелек другого пользователя без его разрешения или не использовать Сервисы Ledger каким-либо способом, который может помешать, нарушить, отрицательно повлиять или запретить другим Пользователям полноценно работать с Сервисами Ledger или который может нарушить или ухудшить работу Сервисов Ledger, отключить их или привести к перегрузке. - -Использование Сервисов Ledger, за исключением регламентированного настоящими Условиями, без нашего предварительного письменного разрешения строго запрещено и приведет к прекращению действия лицензии на использование Сервисов Ledger. - -Гарантии и отказ от ответственности - -Компания Ledger будет действовать добросовестно и на должном профессиональном уровне, чтобы предоставить вам доступ к Сервисам Ledger в соответствии с настоящими Условиями использования, но она не гарантирует, что доступ к Сервисам и их работа не будет прерываться, а также не гарантирует отсутствие задержек, сбоев, ошибок, упущений, повреждения или потери передаваемой информации. Сервисы Ledger предоставляются в существующем состоянии без гарантий любого рода, явных или подразумеваемых, в том числе без подразумеваемых гарантий в отношении пригодности для коммерческого использования, а также надежности и пригодности для конкретной цели. - -Доступность Сервисов Ledger - -Мы можем изменять и обновлять Сервисы, приостанавливать их работу, временно или на неопределенный срок, для проведения каких-либо работ, включая, помимо прочего, обновление встроенного ПО и программного обеспечения, операции по техническому обслуживанию, изменения на серверах, исправление ошибок и т. д. Мы приложим все обоснованные усилия, чтобы заранее сообщить вам о каких-либо значительных нарушениях в работе Сервисов Ledger. - -Компания Ledger не гарантирует правильного функционирования Сервисов в случае установки или использования программ или приложений, которые несовместимы со спецификациями и техническими стандартами Сервиса. - -Обратите внимание: если сервис Ledger недоступен или его работа приостановлена, вы всегда можете восстановить свои закрытые ключи, используя фразу восстановления из 24 слов в любом совместимом кошельке. - -Базовые протоколы блокчейна - -Все транзакции, созданные с помощью Сервисов Ledger, подтверждаются и записываются в соответствующих сетях блокчейна. Такие сети представляют собой децентрализованные одноранговые сети, контролируемые независимыми сторонними организациями. Они не являются собственностью компании Ledger, не управляются и не используются ею. Мы не контролируем сети блокчейна, поэтому не можем гарантировать подтверждение и обработку транзакций, которые вы транслируете в Сервисах Ledger. Вы подтверждаете осведомленность о том, что мы не храним, не отправляем и не получаем криптоактивы, а также соглашаетесь с тем, что транзакции, которые вы выполняете с помощью Сервисов Ledger, могут быть выполнены с ошибкой или со значительной задержкой в соответствующих сетях блокчейна. - -В некоторых случаях протокол блокчейна определенного криптоактива может измениться, что может повлиять на его ключевые характеристики, включая, помимо прочего, доступность, имя, безопасность, оценку или способ работы. Форки могут привести к неверным направлению или репликации ответвленных криптоактивов. Во всех таких случаях компания Ledger может по своему усмотрению приостановить поддержку соответствующего криптоактива на период, который компания Ledger сочтет необходимым. В таком случае компания Ledger постарается уведомить вас заранее, если возможно. Вы должны быть осведомлены о таких событиях и принять необходимые меры. - -Приложения для устройства - -Приложения для устройства доступны для скачивания в диспетчере Ledger Live. Их можно установить, следуя нашему**[ ](about:blank)**руководству. Эти приложения могут быть разработаны компанией Ledger или любыми другими сторонними компаниями, которые могут воспользоваться открытым исходным кодом, доступным в**[ ](about:blank)**хранилище Github компании Ledger. - -Разработчики приложений для устройства несут ответственность за упомянутые приложения и их работу, а также за поддержку этих приложений на устройстве Ledger и в Ledger Live, если таковая предусмотрена для этих устройств. Компания Ledger может выполнять проверки кода и аудит безопасности приложений для устройства, доступных в диспетчере Ledger Live, что не является каким-либо подтверждением или гарантией отсутствия рисков, сопряженных с использованием этих приложений. - -Компания Ledger не гарантирует, что приложения для устройства будут поддерживаться через определенное время, и оставляет за собой право на ограничение или приостановку доступа к ним со стороны Сервисов Ledger по любой причине, если это будет сочтено необходимым. - -Экспериментальные функции - -Чтобы удовлетворить запросы опытных Пользователей и создать новые функции и возможности, мы разработали ряд экспериментальных функций в Ledger Live. Эти функции могут быть незаконченными и не полностью проверенными, поэтому их использование может быть сопряжено с риском. Они могут содержать ошибки или неточности, которые могут приводить к сбоям, ошибкам и потере данных и (или) информации. Их следует рассматривать как бета-версию функций. Компания Ledger не гарантирует стабильность, полноценную техническую реализацию и долгосрочную поддержку этих функций. Неопытным Пользователям, не обладающим уверенными техническими навыками, не рекомендуется работать с этими функциями. Вы прямо подтверждаете свое согласие с тем, что используете экспериментальные функции исключительно под вашу ответственность. - -Детали транзакции - -**Не доверять, а проверять.** Целостность программного обеспечения, особенно при наличии подключения к Интернету, проверить очень сложно. Модель обеспечения безопасности компании Ledger основана на отображении надежных данных, поэтому проверка информации на вашем устройстве Ledger имеет первостепенное значение. Перед подтверждением операции необходимо удостовериться в том, что информация, отображаемая на экране вашего портативного или настольного компьютера, верна и совпадает с информацией, отображаемой на вашем устройстве Ledger. Отправляя криптоактивы, вы несете единоличную ответственность за проверку правильности адреса получателя, суммы и размера комиссии, а также за проверку того, что эти данные совпадают на компьютере, мобильном телефоне и на экране вашего устройства Ledger. Вы также подтверждаете, что использование непроверенных адресов для получения криптоактивов осуществляется исключительно под вашу ответственность. - -Сторонние сервисы и материалы - -Ledger Live может поддерживать сторонние сервисы, ссылаться на них или предоставлять к ним доступ. - -Вы соглашаетесь с тем, что использование сторонних сервисов регулируется отдельными положениями и условиями между вами и третьей стороной, указанной в Ledger Live. Компания Ledger не несет ответственности за работу или неисправность сторонних сервисов. Вы обязаны ознакомиться с условиями и положениями третьей стороны, прежде чем использовать сторонний сервис. Некоторые сторонние сервисы могут запрашивать или требовать доступ к вашим персональным данным. Обработка таких данных должна осуществляться в соответствии с политикой конфиденциальности и рекомендованными действиями соответствующей третьей стороны. - -Сторонние сервисы могут работать некорректно с вашим программным обеспечением или устройством Ledger, и мы не всегда можем оказывать поддержку в случае проблем, вызванных сторонними сервисами. Если у вас возникли вопросы или сомнения по поводу того, как работает сторонний сервис, или если вам нужна помощь, обратитесь напрямую к соответствующей третьей стороне. - -Рекомендуется не вводить учетные данные, пароли, закрытые ключи, парольную фразу и любые другие конфиденциальные данные в сторонних сервисах без предварительной проверки их легитимности. - -Мы сохраняем за собой исключительное право добавлять, изменять или аннулировать доступность любого стороннего сервиса по любой причине и без предварительного уведомления. - -Особые правила и обязательства применимы к перечисленным далее Сервисам. - -**A. Сервис «Купить крипто»** - -Ссылки на сервисы «Купить крипто» являются спонсируемыми ссылками. Наличие ссылки на один из Сервисов Ledger или ссылки с него не означает и не подразумевает их поддержку. - -**B. Делегирование прав на стейкинг** - -**Вознаграждения.** Вы в явной форме подтверждаете свою осведомленность о том, что делегирование прав на стейкинг оператору валидатора, указанному в Ledger Live, не дает вам никакого права запрашивать какие-либо выплаты, а лишь дает потенциальное право разделить вознаграждение, полученное валидатором. Обратите внимание, что периоды блокировки зависят от валидатора и протоколов блокчейна. - -**Валидаторы.** Компания Ledger оставляет за собой право в любое время изменять список указанных валидаторов без предварительного уведомления. - -Ограничение ответственности - -ВЫ В ЯВНОЙ ФОРМЕ ПОДТВЕРЖДАЕТЕ СВОЮ ОСВЕДОМЛЕННОСТЬ И ДАЕТЕ СОГЛАСИЕ НА ТО, ЧТО КОМПАНИЯ LEDGER, ЕЕ РУКОВОДИТЕЛИ И СОТРУДНИКИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ЗА КАКИЕ-ЛИБО ПРЯМЫЕ, ОПОСРЕДОВАННЫЕ, СЛУЧАЙНЫЕ, ФАКТИЧЕСКИЕ, КОСВЕННЫЕ ИЛИ ШТРАФНЫЕ УБЫТКИ, ВКЛЮЧАЯ, ПОМИМО ПРОЧЕГО, УБЫТКИ ОТ УТРАТЫ ПРИБЫЛИ, ПОТЕРИ ДЕЛОВОЙ РЕПУТАЦИИ, ИСПОЛЬЗОВАНИЯ ДАННЫХ, ЗАТРАТ НА ЗАКУПКУ ЗАМЕНИТЕЛЕЙ ТОВАРОВ ИЛИ СЕРВИСОВ ИЛИ ПОТЕРЮ ДРУГИХ НЕМАТЕРИАЛЬНЫХ ЦЕННОСТЕЙ, ВЫЗВАННЫЕ: (I) ИСПОЛЬЗОВАНИЕМ ИЛИ НЕВОЗМОЖНОСТЬЮ ИСПОЛЬЗОВАНИЯ СЕРВИСОВ, (II) ЛЮБЫМИ ИЗМЕНЕНИЯМИ, ВНЕСЕННЫМИ В СЕРВИСЫ, ПРИОСТАНОВЛЕНИЕМ ИЛИ ОТКЛЮЧЕНИЕМ СЕРВИСОВ ИЛИ КАКОЙ-ЛИБО ИХ ЧАСТИ; (III) НЕСАНКЦИОНИРОВАННЫМ ДОСТУПОМ ИЛИ ИЗМЕНЕНИЕМ ПЕРЕДАЧ ИЛИ ДАННЫХ; (IV) УДАЛЕНИЕМ, ПОВРЕЖДЕНИЕМ ИЛИ НЕВОЗМОЖНОСТЬЮ СОХРАНИТЬ И (ИЛИ) ОТПРАВИТЬ ИЛИ ПОЛУЧИТЬ ПЕРЕДАЧИ ИЛИ ДАННЫЕ В СЕРВИСЕ ИЛИ С ЕГО ПОМОЩЬЮ; (V) ЛЮБЫМИ ДРУГИМИ ДЕЙСТВИЯМИ, СВЯЗАННЫМИ С СЕРВИСОМ. - -УКАЗАННЫЕ ВЫШЕ ОГРАНИЧЕНИЯ НЕ ПРИМЕНЯЮТСЯ В ОТНОШЕНИИ УБЫТКОВ, ВОЗНИКШИХ В РЕЗУЛЬТАТЕ (А) МОШЕННИЧЕСТВА, УМЫШЛЕННОГО ПРОТИВОПРАВНОГО ДЕЙСТВИЯ ИЛИ ГРУБОЙ ХАЛАТНОСТИ, УМЫШЛЕННОГО ПРОТИВОПРАВНОГО ДЕЙСТВИЯ ИЛИ МОШЕННИЧЕСТВА КОМПАНИИ LEDGER; (B) СМЕРТИ ИЛИ ТРАВМЫ. - -Объекты интеллектуальной собственности - -Компания Ledger уважает право на интеллектуальную собственность других лиц и просит своих Пользователей поступать так же. Вы подтверждаете свое согласие с тем, что, за исключением материалов, выпущенных или иным способом предоставленных в соответствии с общедоступными лицензионными соглашениями, открытым исходным кодом, MIT или другими незапатентованными лицензионными схемами, обычно используемыми сообществом Ledger, компания Ledger владеет всеми авторскими правами, товарными знаками, ноу-хау или любыми другими правами на объекты интеллектуальной собственности в отношении программного обеспечения, текстов, видео, аудио, иллюстраций, логотипов, макетов, а также внешнего вида Ledger Live, приложений для устройства и веб-сайта. - -Вы можете просматривать, печатать и (или) скачивать копии патентованных материалов из Сервисов Ledger с помощью любого компьютера исключительно для личного, информационного и (или) некоммерческого использования при условии соблюдения всех положений об авторских правах и других указаний правообладателя. - -Товарные знаки, знаки обслуживания и логотипы компании Ledger и других компаний, используемые в Сервисах («Товарные знаки»), являются собственностью компании Ledger или их соответствующих владельцев. Категорически запрещено использовать эти товарные знаки без нашего явно выраженного письменного разрешения или письменного разрешения третьих сторон. - -Обратная связь - -Мы были бы очень рады получить обратную связь, комментарии, идеи и предложения по поводу улучшения Сервисов («Обратная связь»). Вы предоставляете нам неисключительную, действующую во всем мире, бессрочную, безотзывную, полностью оплаченную, не требующую лицензионных отчислений, сублицензируемую и переуступаемую лицензию на любые и все права на объекты интеллектуальной собственности, которыми вы владеете или управляете, на использование, копирование, изменение, создание производных продуктов на основе Обратной связи, а также ее использование иным образом для каких-либо целей. - -Нормативно-правовое соответствие и экспортный контроль - -Пользователи должны самостоятельно нести расходы, связанные с соблюдением всех законов, применимых к настоящим Условиям или вытекающих из них. Получая доступ к Сервисам и пользуясь ими, вы заверяете и гарантируете, что не внесены в какие-либо списки торговых или экономических санкций, такие как (среди прочего) санкционный перечень Совета Безопасности ООН, обозначенный OFAC (Управление по контролю за иностранными активами при Министерстве финансов США) как «Список граждан особых категорий и запрещенных лиц» или «Санкционный перечень» Министерства торговли США. - -Компания Ledger оставляет за собой право выбирать рынки и юрисдикции, в которых она работает, а также может ограничивать или запрещать доступ к Сервисам Ledger в определенных странах, штатах или регионах. - -Прекращение действия - -Вы можете прекратить использование Сервисов в любое время. Мы оставляем за собой право приостановить доступ к Сервисам Ledger без предварительного уведомления, если, по нашему мнению, вы нарушили настоящие Условия. В случае прекращения действия вашей лицензии на использование Сервисов Ledger ваши обязательства в рамках настоящих Условий сохраняются. - -Доступ к вашим кошелькам после прекращения действия лицензии зависит от того, сделали ли вы надежную резервную копию закрытых ключей и адресов своего кошелька. - -Применимое законодательство - -Эти Условия регулируются и толкуются в соответствии с законодательством Франции. - -Любые споры, конфликты, разногласия или претензии, возникающие в результате действия настоящего Соглашения или связанные с ним, включая наличие, срок действия, толкование, исполнение, нарушение или прекращение его действия, или любой спор, связанный с внедоговорными обязательствами, возникающими в связи с ним или связанными с ним, следует передать на рассмотрение суда надлежащей юрисдикции в г. Париж (Франция) для окончательного разрешения. - -Обеспечение исполнения обязательств и передача прав в рамках Условий - -Настоящие Условия представляют собой полное и исключительное соглашение и договоренность между компанией Ledger и вами в отношении Сервисов Ledger, а также заменяют все предыдущие устные или письменные договоренности или соглашения между компанией Ledger и вами в отношении Сервисов Ledger. Если вы не в полной мере прочитали и принимаете Условия, вам не следует использовать или продолжать использовать Сервисы Ledger. - -Мы оставляем за собой право иногда изменять, дополнять или вносить поправки в эти Условия исключительно по своему усмотрению. Мы сообщим вам о таких изменениях, предоставив измененные Условия через Ledger Live и обновив дату в заголовке «Последнее обновление» в верхней части настоящих Условий. Измененные Условия считаются вступившими в силу сразу после их размещения в Ledger Live. - -Вы не можете полностью или частично передавать свои права или обязательства какой-либо третьей стороне в рамках настоящих Условий использования. - -Вы подтверждаете свое согласие с тем, что компания Ledger может передавать свои права и обязательства третьим сторонам в рамках настоящих Условий использования и в таком контексте предоставлять или передавать сведения, предоставленные вами во время использования Сервисов Ledger. - -Если какое-либо положение настоящих Условий использования или их часть становится до какой-либо степени недействительным или не имеющим законной силы, то такое положение будет считаться отделяемым от остальных положений настоящих Условий использования и не будет влиять на действительность или законную силу остальных положений настоящих Условий использования. diff --git a/android/app/build.gradle b/android/app/build.gradle index ef085abb4f..7b49bab1d4 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -157,8 +157,8 @@ android { multiDexEnabled true minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 36176141 - versionName "3.0.8" + versionCode 36176151 + versionName "3.1.0" resValue "string", "build_config_package", "com.ledger.live" testBuildType System.getProperty('testBuildType', 'debug') testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' diff --git a/android/app/src/main/java/com/ledger/live/MainApplication.java b/android/app/src/main/java/com/ledger/live/MainApplication.java index 6c793993a6..7587bb7a74 100644 --- a/android/app/src/main/java/com/ledger/live/MainApplication.java +++ b/android/app/src/main/java/com/ledger/live/MainApplication.java @@ -23,15 +23,6 @@ public class MainApplication extends Application implements ReactApplication { - static { - try { - System.loadLibrary("ledger-core"); - } catch (UnsatisfiedLinkError e) { - System.err.println("ledger-core native library failed to load: " + e); - System.exit(1); - } - } - private final ReactNativeHost mReactNativeHost = new ReactNativeHostWrapper(this, new ReactNativeHost(this) { @Override diff --git a/android/build.gradle b/android/build.gradle index d04621d0b7..25d5df2478 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -50,7 +50,6 @@ allprojects { maven { url "$rootDir/../node_modules/expo-camera/android/maven" } - jcenter() } configurations.all { resolutionStrategy { diff --git a/docs/ONBOARDING_LINUX.md b/docs/ONBOARDING_LINUX.md new file mode 100644 index 0000000000..cc3d85a8de --- /dev/null +++ b/docs/ONBOARDING_LINUX.md @@ -0,0 +1,177 @@ + +## Github + +### Creating / Linking an account + +In the Ledger Live development team, we use Github for hosting our software development and version control. +You will therefore need a Github account. +You have 2 possibilities : +- Create a new Github account dedicated for Ledger using an account name that respects these constraints: All in lower case, First letter of your first name, your last name, dash, ledger. Ex: jdupont-ledger for Jean Dupont. + Then use this link to connect your newly created account to your Ledger's Google account : https://github.com/orgs/LedgerHQ/sso + +OR + +- Use your personal account, by connecting it to your Ledger's Google account : https://github.com/orgs/LedgerHQ/sso + +On [this page](https://github.com/settings/organizations), you can see that you have joined the Ledger Github organisation. + +### SSH and GPG keys + +- Generate and link SSH key to your Github account using this nice guide : https://jdblischak.github.io/2014-09-18-chicago/novice/git/05-sshkeys.html +- On the same page where you added the newly created SSH key, on the information card of the key you should see a "Configure SSO" button. Click on the button and follow the process. +- Generate and link a GPG key to your Github account and Git using this nice guide : https://gist.github.com/ankurk91/c4f0e23d76ef868b139f3c28bde057fc + +### Cloning +Clone the following Ledger Live repositories : + +`git clone https://github.com/LedgerHQ/ledger-live-mobile.git` +`git clone https://github.com/LedgerHQ/ledger-live-desktop.git` +`git clone https://github.com/LedgerHQ/ledger-live-common.git` + +> Small tip : You probably have Sentinel One on your computer. It is an antivirus that constantly scans all your files on your computer to ensure its security. However, it is not adapted to a development environment and will slow down your node package installations or builds enormously and thus kill your productivity. Contact me on Slack to have a solution to mitigate this problem :) + +## Node.js + +You should install a Node version manager, because you will regularly need to switch between node versions with Live. +Some recommand [NVM](https://github.com/nvm-sh/nvm#installing-and-updating), others recommand [N](https://github.com/tj/n#installation) + +You need to install [Yarn](https://classic.yarnpkg.com/en/), a node packet manager used by Live. +`npm install --global yarn` + +To be able to use executable installed from yarn, you will need to modify pour $PATH variable ([more info](https://linuxize.com/post/how-to-add-directory-to-path-in-linux/)) : +- Open your .bashrc with your favorite editor, ex: `nano ~/.bashrc` +- Add this line to the end of it : `export PATH="$PATH:$(yarn global bin)"` + +## Code editor + +The code editor used by the majority of developers in the Ledger Live team is **Visual Studio Code**. +You can install it using this guide : https://code.visualstudio.com/docs/setup/linux + +As an alternative, you can install [Webstorm](https://www.jetbrains.com/fr-fr/webstorm/) or [VSCodium](https://vscodium.com/#install). + +## Ledger Live + +### Ubuntu/Debian requirements + +First, you need to install theses packages : + +- libudev and libusb to communicate with the devices on your system, in our case the Nano. +- ruby and ruby-dev to install Bundler. + +`sudo apt-get update && sudo apt-get install libudev-dev libusb-1.0-0-dev ruby-dev ruby` + +Then you need to install [bundler](https://bundler.io/), that will be used to install gem packages + +`sudo gem install bundler` + +#### Udev Rules + +You need to set up udev rules : + +Go see: [ledger support doc](https://support.ledger.com/hc/en-us/articles/115005165269?utm_source=ledger_live_desktop&utm_medium=self_referral&utm_content=error_cantopendevice&support=true) + +Or directly do: `wget -q -O - https://raw.githubusercontent.com/LedgerHQ/udev-rules/master/add_udev_rules.sh | sudo bash` + +#### Metro watcher limits + +Linux uses the inotify package to observe filesystem events, individual files or directories. + +Since React / Angular hot-reloads and recompiles files on save it needs to keep track of all project's files. Increasing the inotify watch limit should hide the warning messages. + +``` +# insert the new value into the system config +echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p +​ +# check that the new value was applied +cat /proc/sys/fs/inotify/max_user_watches +``` + +### Ledger Live Mobile + +#### Android Studio + +The easiest way to setup your Android environment is to install Android Studio + +- Download Android Studio : https://developer.android.com/studio +- Unzip and launch the executable located in bin/studio.sh +- Tip: In the welcome window of Android Studio, in the bottom left corner, you can click on the "Add entry" little button to add a desktop entry to your Linux so you can easily open it again after. +- Open the ledger-mobile repository folder. + +#### Android Studio SDK Manager + +We will install all the Android necessary dependencies to build Ledger Live Mobile as well as additional tools. + +In the top navigation bar, open the Tools->SDK Manager. +In the *SDK Platforms* tab, be sure that at least one SDK is installed (Android 10 ? 11 ? As you wish). +In the *SDK Tools* tab, be sure sure that these components are installed : +- Android SDK Build-Tools +- NDK +- CMake +- Android Emulator +- Android SDK Platform-Tools + +#### Android Studio Emulator + +In this part, we will focus on the installation of the Android emulator, necessary for Android development without the use of a dedicated device. + +In the top navigation bar, open the Tools->Device Manager + +In the "Device Manager" section that just opened, click on the "Create device" button. + +I recommend that you take a phone that does not have a large screen or the latest version of Android, to be in line with most Ledger Live users. + +#### Linking it all together + +You need to modify your $PATH, like you have done with Yarn, so that your setup detects the SDK and the emulator : +- Open your .bashrc with your favorite editor, ex: `nano ~/.bashrc` +- Add theses lines to the end of it : +``` +export ANDROID_HOME=$HOME/Android/Sdk +export PATH=$PATH:$ANDROID_HOME/tools +export PATH=$PATH:$ANDROID_HOME/platform-tools +``` +- Reload your environment using this command: `source ~/.bashrc`​ + +#### (Not mandatory) Set up your phone + +If you prefer to use your Android phone rather than the emulator, you need to enable USB debugging. +To begin with, close any instance of the emulator you may have open. + +Please follow this guide to enable it : https://www.embarcadero.com/starthere/xe5/mobdevsetup/android/en/enabling_usb_debugging_on_an_android_device.html + +To verify that your phone is connected and recognized, you can launch this command : +`adb devices -l` +You should see a line at the bottom of "List of devices attached" containing the name of your phone. +If you don't see anything, try to launch again the command or check again the guide above. +If the command *adb* is not recognized, please verify that you have done every steps in the *Android Studio SDK Manager* (*adb* is contained in the *Android SDK Platform-Tools* module) and the *Linking it all together* chapters. + +#### Launch + +Launch these commands inside the ledger-live-mobile repository : + +- `yarn` to download the latest node packages +- `yarn start` to start *Metro*, the bundler for React-native ([More Info](https://facebook.github.io/metro/)) + +Since Metro is a watcher, open a new terminal and `yarn android` to build and install the development application to your device. It will launch the emulator if it's not started yet or if there is no physical device connected. + +After a few minutes, you should see Ledger Live Mobile start screen. Congrats ! 🎉 + +### Ledger Live Desktop + +#### Launch + +Launch these commands inside the ledger-live-desktop repository : + +- `yarn` to download the latest node packages +- `yarn start` to start the process + +After a few minutes, you should see Ledger Live Desktop start screen. Congrats ! + + +#### (Optional) Setup VSCode for debugging + +See [readme](https://github.com/LedgerHQ/ledger-live-desktop#debug) on Launch Configuration. + + + +*Thanks to Alexandre Magaud for being my test subject for this guide and for writing a good part of it and a huge amount of notes !* \ No newline at end of file diff --git a/e2e/engine/bridge/client.js b/e2e/bridge/client.js similarity index 85% rename from e2e/engine/bridge/client.js rename to e2e/bridge/client.js index dca7397d9a..0500499e87 100644 --- a/e2e/engine/bridge/client.js +++ b/e2e/bridge/client.js @@ -3,12 +3,12 @@ import { Platform } from "react-native"; import invariant from "invariant"; import { Subject } from "rxjs/Subject"; import type { AccountRaw } from "@ledgerhq/live-common/lib/types"; -import { store } from "../../../src/context/LedgerStore"; -import { importSettings } from "../../../src/actions/settings"; -import { setAccounts } from "../../../src/actions/accounts"; -import { acceptTerms } from "../../../src/logic/terms"; -import accountModel from "../../../src/logic/accountModel"; -import { navigate } from "../../../src/rootnavigation"; +import { store } from "../../src/context/LedgerStore"; +import { importSettings } from "../../src/actions/settings"; +import { setAccounts } from "../../src/actions/accounts"; +import { acceptTerms } from "../../src/logic/terms"; +import accountModel from "../../src/logic/accountModel"; +import { navigate } from "../../src/rootnavigation"; let ws: WebSocket; diff --git a/e2e/engine/bridge/server.js b/e2e/bridge/server.js similarity index 91% rename from e2e/engine/bridge/server.js rename to e2e/bridge/server.js index 1f79ad7e5a..1c072d6f7d 100644 --- a/e2e/engine/bridge/server.js +++ b/e2e/bridge/server.js @@ -3,8 +3,7 @@ import { Server } from "ws"; import path from "path"; import fs from "fs"; import type { E2EBridgeMessage } from "./client"; -import { $waitFor } from "../utils"; -import { NavigatorName } from "../../../src/const"; +import { NavigatorName } from "../../src/const"; let wss: Server; @@ -35,15 +34,12 @@ export async function loadConfig( const { data } = JSON.parse(f); postMessage({ type: "importSettngs", payload: data.settings }); + navigate(NavigatorName.Base); if (data.accounts.length) { postMessage({ type: "importAccounts", payload: data.accounts }); - await $waitFor("PortfolioAccountsList", -1, 10000); - return; } - - await $waitFor("PortfolioEmptyAccount"); } function navigate(name: string) { diff --git a/e2e/config.json b/e2e/config.json index 7c8421798e..8dbcb8b990 100644 --- a/e2e/config.json +++ b/e2e/config.json @@ -1,9 +1,11 @@ { + "globalSetup": "./global-setup.js", + "globalTeardown": "./global-teardown.js", + "setupFilesAfterEnv": ["./setup.js"], "testEnvironment": "./environment", "testRunner": "jest-circus/runner", - "testTimeout": 120000, + "testTimeout": 300000, "testRegex": "\\.spec\\.js$", "reporters": ["detox/runners/jest/streamlineReporter"], - "verbose": true, - "setupFilesAfterEnv": ["./init.js"] + "verbose": true } diff --git a/e2e/e2e-bridge-setup.js b/e2e/e2e-bridge-setup.js index 8da1f012cb..d91cd0b371 100644 --- a/e2e/e2e-bridge-setup.js +++ b/e2e/e2e-bridge-setup.js @@ -2,5 +2,5 @@ import Config from "react-native-config"; if (Config.MOCK) { - import("./engine/bridge/client").then(({ init }) => init()); + import("./bridge/client").then(({ init }) => init()); } diff --git a/e2e/engine/flows/index.js b/e2e/engine/flows/index.js deleted file mode 100644 index 2406d001cc..0000000000 --- a/e2e/engine/flows/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export * from "./onboarding"; diff --git a/e2e/engine/flows/onboarding.js b/e2e/engine/flows/onboarding.js deleted file mode 100644 index 9774d92109..0000000000 --- a/e2e/engine/flows/onboarding.js +++ /dev/null @@ -1,66 +0,0 @@ -// @flow -import * as bridge from "../bridge/server"; -import { $tap, $proceed, $, $scrollTill, $waitFor } from "../utils"; - -export function onboard(modelId: DeviceModelId, usecase: Usecase) { - getStarted(); - acceptTerms(); - selectUsecase(modelId, usecase); -} - -function getStarted() { - it("should go terms screen", async () => { - await $proceed(); - }); -} - -function acceptTerms() { - it("should check terms and policy", async () => { - await $tap("TermsAcceptSwitch"); - }); - - it("should enter Ledger App", async () => { - await $proceed(); - }); -} - -async function selectUsecase(modelId: DeviceModelId, usecase: Usecase) { - it(`should go connect screen for ${modelId}`, async () => { - await $tap(`Onboarding Device - Selection|${modelId}`); - }); - - switch (usecase) { - case "connect": - if (modelId === "nanoX") { - await connectViaBluetooth(modelId); - } - break; - default: - break; - } -} - -async function connectViaBluetooth(modelId: DeviceModelId) { - it("should pair Nano via Bluetooth", async () => { - const el = $(`Onboarding - Connect|${modelId}`); - await $scrollTill(el); - await $tap(el); - await $waitFor("Onboarding - Seed warning"); - const dismissSeedWarning = $("Onboarding - Seed warning"); - await $tap(dismissSeedWarning); - await $tap("OnboardingStemPairNewContinue"); - await $proceed(); - const [david] = bridge.addDevices(); - // TODO E2E: Android - await $waitFor(`DeviceItemEnter ${david}`); - await $tap(`DeviceItemEnter ${david}`); - bridge.setInstalledApps(); - bridge.open(); - await $proceed(); - await $tap("OnboardingFinish"); - }); -} - -type DeviceModelId = "nanoS" | "nanoX" | "blue"; - -type Usecase = "newDevice" | "import" | "restore" | "connect"; diff --git a/e2e/engine/index.js b/e2e/engine/index.js deleted file mode 100644 index 052d1a9e54..0000000000 --- a/e2e/engine/index.js +++ /dev/null @@ -1,6 +0,0 @@ -// @flow -import * as bridge from "./bridge/server"; - -export { bridge }; -export * from "./utils"; -export * from "./flows"; diff --git a/e2e/engine/utils.js b/e2e/engine/utils.js deleted file mode 100644 index 6cacc6235d..0000000000 --- a/e2e/engine/utils.js +++ /dev/null @@ -1,63 +0,0 @@ -// @flow -const { device, element, by, waitFor } = require("detox"); - -export function cleanLaunch() { - return device.launchApp({ delete: true }); -} - -export async function $proceed(): Promise { - const el = $("Proceed"); - await $waitFor(el); - await el.tap(); -} - -export function $(id: string) { - return element(by.id(id)); -} - -export function $byText(text: string) { - return element(by.text(text)); -} - -// specifing -1 as percentage would check just an existence -export function $waitFor( - q: Query, - percentage: number = 75, - timeout: number = 5000, -) { - const el = getElement(q); - return percentage < 0 - ? waitFor(el) - .toExist() - .withTimeout(timeout) - : waitFor(el) - .toBeVisible(percentage) - .withTimeout(timeout); -} - -export function $tap(q: Query) { - return getElement(q).tap(); -} - -export function $scrollTill( - visibleTarget: Query, - scrollViewId: string = "ScrollView", - pixel: number = 200, - direction: ScrollDirection = "down", -) { - const targetEl = getElement(visibleTarget); - return waitFor(targetEl) - .toBeVisible() - .whileElement(by.id(scrollViewId)) - .scroll(pixel, direction); -} - -type Element = any; - -type Query = string | Element; - -function getElement(q: Query): Element { - return typeof q === "string" ? $(q) : q; -} - -type ScrollDirection = "top" | "down" | "right" | "left"; diff --git a/e2e/global-setup.js b/e2e/global-setup.js new file mode 100644 index 0000000000..5b0f1ca4a1 --- /dev/null +++ b/e2e/global-setup.js @@ -0,0 +1,7 @@ +const detox = require("detox"); + +async function globalSetup() { + await detox.globalInit(); +} + +module.exports = globalSetup; diff --git a/e2e/global-teardown.js b/e2e/global-teardown.js new file mode 100644 index 0000000000..1926f701cb --- /dev/null +++ b/e2e/global-teardown.js @@ -0,0 +1,7 @@ +const detox = require("detox"); + +async function globalTeardown() { + await detox.globalCleanup(); +} + +module.exports = globalTeardown; diff --git a/e2e/helpers.js b/e2e/helpers.js new file mode 100644 index 0000000000..bec019a775 --- /dev/null +++ b/e2e/helpers.js @@ -0,0 +1,109 @@ +import { readFileSync } from "fs"; + +const DEFAULT_TIMEOUT = 30000; + +export function waitAndTap(elementId, timeout) { + waitFor(element(by.id(elementId))) + .toBeVisible() + .withTimeout(timeout || DEFAULT_TIMEOUT); + + return element(by.id(elementId)).tap(); +} + +export function waitForElement(elementId, timeout) { + return waitFor(element(by.id(elementId))) + .toBeVisible() + .withTimeout(timeout || DEFAULT_TIMEOUT); +} + +export function waitForElementByText(text, timeout) { + return waitFor(element(by.text(text))) + .toBeVisible() + .withTimeout(timeout || DEFAULT_TIMEOUT); +} + +export function tap(elementId) { + return element(by.id(elementId)).tap(); +} + +export function tapByText(text, index) { + return element(by.text(text)) + .atIndex(index || 0) + .tap(); +} + +export async function typeText(elementId, text, focus = true) { + if (focus) { + await tap(elementId); + } + return element(by.id(elementId)).typeText(text); +} + +export function clearField(elementId) { + element(by.id(elementId)).replaceText(""); +} + +export async function scrollToElementById( + elementToScrollToId, + parentElementId, + pixelsToScroll, + direction = "down", + startPositionXAxis = NaN, + startPositionYAxis = 0.5, +) { + await waitFor(element(by.id(elementToScrollToId))) + .toBeVisible() + .whileElement(by.id(parentElementId)) + .scroll(pixelsToScroll, direction, startPositionXAxis, startPositionYAxis); +} + +export async function retryAction(action, timeout) { + let shouldContinue = true; + const startTime = Date.now(); + + while (shouldContinue) { + shouldContinue = false; + + try { + await action(); + } catch { + shouldContinue = true; + } + + if (timeout && Date.now() - startTime > timeout) { + throw new Error("Timed out when waiting for action"); + } + + // eslint-disable-next-line no-console + console.log("Trying again..."); + } +} + +export async function verifyIsVisible(elementId) { + await delay(1000); + await expect(element(by.id(elementId))).toBeVisible(); +} + +export async function verifyTextIsVisible(text) { + await delay(1000); + await expect(element(by.text(text))).toBeVisible(); +} + +export function delay(ms) { + return new Promise(resolve => { + setTimeout(() => { + resolve("delay complete"); + }, ms); + }); +} + +// for future use for screenshot conmparison +export function expectBitmapsToBeEqual(imagePath, expectedImagePath) { + const bitmapBuffer = readFileSync(imagePath); + const expectedBitmapBuffer = readFileSync(expectedImagePath); + if (!bitmapBuffer.equals(expectedBitmapBuffer)) { + throw new Error( + `Expected image at ${imagePath} to be equal to image at ${expectedImagePath}, but it was different!`, + ); + } +} diff --git a/e2e/init.js b/e2e/init.js deleted file mode 100644 index 78643f69da..0000000000 --- a/e2e/init.js +++ /dev/null @@ -1,10 +0,0 @@ -// @flow -import { bridge } from "./engine"; - -beforeAll(async () => { - bridge.init(); -}); - -afterAll(() => { - bridge.close(); -}); diff --git a/e2e/models/onboarding/onboardingSteps.js b/e2e/models/onboarding/onboardingSteps.js new file mode 100644 index 0000000000..ce451a1b5f --- /dev/null +++ b/e2e/models/onboarding/onboardingSteps.js @@ -0,0 +1,62 @@ +import * as bridge from "../../bridge/server"; +import * as testHelpers from "../../helpers"; + +export default class OnboardingSteps { + static async waitForPageToBeVisible() { + await testHelpers.waitForElementByText("Get started"); + } + + static async startOnboarding() { + await testHelpers.tapByText("Get started"); + } + + // change to tap by text + static async chooseToSetupLedger() { + await testHelpers.tapByText("SET UP MY LEDGER"); + // await testHelpers.tap("Onboarding PostWelcome - Selection|SetupLedger"); + } + + static async selectYourDevice(device) { + await testHelpers.tapByText(device); + // await testHelpers.tap(`Onboarding Device - Selection|${device}`); + } + + static async chooseToConnectYourNano() { + await testHelpers.tapByText("Connect your Nano"); + } + + static async verifyContentsOfBoxAreChecked() { + await testHelpers.tapByText("Continue"); + } + + static async chooseToPairMyNano() { + await testHelpers.tapByText("Let’s pair my Nano"); + } + + static async selectPairWithBluetooth() { + await testHelpers.tapByText("Pair with bluetooth"); + } + + static async addDeviceViaBluetooth() { + bridge.addDevices(); + await testHelpers.delay(1000); // give time for devices to appear + await testHelpers.tapByText("Nano X de David"); + + bridge.setInstalledApps(); // tell LLM what apps the mock device has + + bridge.open(); // open ledger manager + + // Continue to welcome screen + // await waitFor( + // element(by.text("Device authentication check")), + // ).not.toBeVisible(); + // issue here: the 'Pairing Successful' text is 'visible' before it actually is, so it's failing at the continue step as continue isn't actually visible + // await waitFor(element(by.text("Pairing Successful"))).toBeVisible(); + + await testHelpers.delay(5000); // wait for flaky 'device authentication check screen' + } + + static async openLedgerLive() { + await testHelpers.tapByText("Continue"); + } +} diff --git a/e2e/models/passwordEntryPage.js b/e2e/models/passwordEntryPage.js new file mode 100644 index 0000000000..709cb8f2b5 --- /dev/null +++ b/e2e/models/passwordEntryPage.js @@ -0,0 +1,17 @@ +import * as testHelpers from "../helpers"; + +export default class PasswordEntryPage { + static async enterPassword(password) { + if (device.getPlatform() === "ios") { + await element(by.type("RCTUITextField")).typeText(password); + } + + if (device.getPlatform() === "android") { + await element(by.type("android.widget.TextView")).typeText(password); + } + } + + static async login() { + await testHelpers.tapByText("Log in"); + } +} diff --git a/e2e/models/portfolioPage.js b/e2e/models/portfolioPage.js new file mode 100644 index 0000000000..38e8f8ea9f --- /dev/null +++ b/e2e/models/portfolioPage.js @@ -0,0 +1,15 @@ +import * as testHelpers from "../helpers"; + +export default class PortfolioPage { + static async waitForPageToBeVisible() { + await testHelpers.waitForElement("settings-icon"); + } + + static async navigateToSettings() { + await testHelpers.tap("settings-icon"); + } + + static async emptyPortfolioIsVisible() { + await testHelpers.verifyTextIsVisible("Add asset"); + } +} diff --git a/e2e/models/settings/generalSettingsPage.js b/e2e/models/settings/generalSettingsPage.js new file mode 100644 index 0000000000..652e6ebd27 --- /dev/null +++ b/e2e/models/settings/generalSettingsPage.js @@ -0,0 +1,32 @@ +import * as testHelpers from "../../helpers"; + +export default class GeneralSettingsPage { + static async togglePassword() { + if (device.getPlatform() === "ios") { + await element(by.type("RCTSwitch")) + .atIndex(0) + .tap(); + } + + if (device.getPlatform() === "android") { + await element(by.type("android.widget.Switch")) + .atIndex(0) + .tap(); + } + } + + static async enterNewPassword(passwordText) { + if (device.getPlatform() === "ios") { + await element(by.type("RCTUITextField")).typeText(passwordText); + } + + if (device.getPlatform() === "android") { + await element(by.type("android.widget.TextView")).typeText(passwordText); + } + await testHelpers.tapByText("Confirm"); + } + + static async isVisible() { + await testHelpers.verifyTextIsVisible("Preferred currency"); + } +} diff --git a/e2e/models/settings/settingsPage.js b/e2e/models/settings/settingsPage.js new file mode 100644 index 0000000000..c7208b1113 --- /dev/null +++ b/e2e/models/settings/settingsPage.js @@ -0,0 +1,7 @@ +import * as testHelpers from "../../helpers"; + +export default class SettingsPage { + static async navigateToGeneralSettings() { + await testHelpers.tap("general-settings-card"); + } +} diff --git a/e2e/setup.js b/e2e/setup.js new file mode 100644 index 0000000000..2532c55493 --- /dev/null +++ b/e2e/setup.js @@ -0,0 +1,41 @@ +import { execSync } from "child_process"; +import * as bridge from "./bridge/server"; + +beforeAll(() => { + bridge.init(); + setupDemoModeForScreenshots(); +}); + +afterAll(() => { + bridge.close(); +}); + +function setupDemoModeForScreenshots() { + // set app to demo mode for screenshots + if (device.getPlatform() === "ios") { + execSync( + 'xcrun simctl status_bar "iPhone 11 Pro" override --time "12:00" --batteryState charged --batteryLevel 100 --wifiBars 3 --cellularMode active --cellularBars 4', + ); + } + + if (device.getPlatform() === "android") { + // enter demo mode + execSync("adb shell settings put global sysui_demo_allowed 1"); + // display time 12:00 + execSync( + "adb shell am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1200", + ); + // Display full mobile data with 4g type and no wifi + execSync( + "adb shell am broadcast -a com.android.systemui.demo -e command network -e mobile show -e level 4 -e datatype 4g -e wifi false", + ); + // Hide notifications + execSync( + "adb shell am broadcast -a com.android.systemui.demo -e command notifications -e visible false", + ); + // Show full battery but not in charging state + execSync( + "adb shell am broadcast -a com.android.systemui.demo -e command battery -e plugged false -e level 100", + ); + } +} diff --git a/e2e/setups/allLiveCoinsNoOperations.json b/e2e/setups/allLiveCoinsNoOperations.json new file mode 100644 index 0000000000..23bc865e79 --- /dev/null +++ b/e2e/setups/allLiveCoinsNoOperations.json @@ -0,0 +1,470 @@ +{ + "data": { + "settings": { + "hasCompletedOnboarding": true, + "counterValue": "EUR", + "preferredDeviceModel": "nanoX", + "language": null, + "theme": "dusk", + "region": null, + "orderAccounts": "name|asc", + "countervalueFirst": true, + "autoLockTimeout": 10, + "selectedTimeRange": "year", + "marketIndicator": "western", + "currenciesSettings": {}, + "pairExchanges": {}, + "developerMode": false, + "loaded": true, + "shareAnalytics": true, + "sentryLogs": true, + "lastUsedVersion": "2.3.2", + "dismissedBanners": [], + "accountsViewMode": "list", + "showAccountsHelperBanner": true, + "hideEmptyTokenAccounts": false, + "sidebarCollapsed": false, + "discreetMode": false, + "hasInstalledApps": true, + "blacklistedTokenIds": [] + }, + "user": { + "id": "9434c303-1d22-43a6-8fce-44c92d815ca8" + }, + "accounts": [ + { + "data": { + "id": "libcore:1:bitcoin:xpub6Bm5P7Xyx2UYrVBAgb54gEswXhbZaryZSWsPjeJ1jpb9K9S5UTD5z5cXW4EREkTqkNjSHQHxwHKZJVE7TFvftySnKabMAXAQCMSVJBdJxMC:", + "seedIdentifier": "04b9b3078fbdef02b5f5aa8bb400423d5170015da06c31ad7745160cbab1fa4cdc965f271b924c2999639211310f6d35029698749b38ea7e64608de3ebcdbaa46a", + "name": "Bitcoin 1 (legacy)", + "starred": false, + "derivationMode": "", + "index": 0, + "freshAddress": "1GaciDQKuhYMz5pcycBcBTwhRao8e4sfoK", + "freshAddressPath": "44'/0'/0'/0/112", + "freshAddresses": [ + { + "address": "1GaciDQKuhYMz5pcycBcBTwhRao8e4sfoK", + "derivationPath": "44'/0'/0'/0/112" + }, + { + "address": "1FJkd4ZQsz2GoaNhE7R3fDrKhPNm3MvSyw", + "derivationPath": "44'/0'/0'/0/113" + }, + { + "address": "1KskXU25MWGFb2dR9Y1nfUZ3SaU2Xkd5gZ", + "derivationPath": "44'/0'/0'/0/114" + }, + { + "address": "19W7vMG3MdEPrwdczh6QwT5bWZFnTM6rw7", + "derivationPath": "44'/0'/0'/0/115" + }, + { + "address": "1FZuY8soygaCxqbrSURTteVj8ZxBrV2ouz", + "derivationPath": "44'/0'/0'/0/116" + }, + { + "address": "17EutyEbazm1mWXWDfK2K5ejwYizPVq2gK", + "derivationPath": "44'/0'/0'/0/117" + }, + { + "address": "19bMyLBBq8FbTE4L7hFCJsbjYewPBNe6Lf", + "derivationPath": "44'/0'/0'/0/118" + }, + { + "address": "15jWmZ3ujDQCFzukYofW7LkCxerov5AAog", + "derivationPath": "44'/0'/0'/0/119" + }, + { + "address": "1Asii6uVSc5Pk4pwXn7rrourtkMrzVsfyL", + "derivationPath": "44'/0'/0'/0/120" + }, + { + "address": "1MY3Gsho5t3kkxa52FUYnXEJeuKiKZxSe5", + "derivationPath": "44'/0'/0'/0/121" + }, + { + "address": "1AXqhTrgoy7PFFraTiMoGb7XnK261THDny", + "derivationPath": "44'/0'/0'/0/122" + }, + { + "address": "1MErAsyj34SvUgdqJP5Xbs5kcrceETEBRo", + "derivationPath": "44'/0'/0'/0/123" + }, + { + "address": "1EihrhVvQ2DZb1LQ2in7ZgdWaTxJ5qmLJD", + "derivationPath": "44'/0'/0'/0/124" + }, + { + "address": "14TvLS3n8qEbVUfi8bPtLyiFrsecQR99in", + "derivationPath": "44'/0'/0'/0/125" + }, + { + "address": "18PQpXEJb8yRerzTHRgP3sNzZwYwPw3tak", + "derivationPath": "44'/0'/0'/0/126" + }, + { + "address": "1F5nBYmGfnFCUrHP6vgLh7Cr3rN5DmgEpb", + "derivationPath": "44'/0'/0'/0/127" + }, + { + "address": "1jA5Gkk4eSp4d3aUqw8kK1ZDWggAu9ibd", + "derivationPath": "44'/0'/0'/0/128" + }, + { + "address": "18nzNgCTonAxbG56Nu5ELfwyrGNch5vBQX", + "derivationPath": "44'/0'/0'/0/129" + }, + { + "address": "1Mw5HcE4Pnt9KSK1FKTFQEVyqLnvhTJLVe", + "derivationPath": "44'/0'/0'/0/130" + }, + { + "address": "1Epk9Hbsf8cEUZCjS6SvZWBqscX9mCZ4mj", + "derivationPath": "44'/0'/0'/0/131" + } + ], + "blockHeight": 628010, + "operationsCount": 219, + "operations": [], + "pendingOperations": [], + "currencyId": "bitcoin", + "unitMagnitude": 8, + "lastSyncDate": "", + "balance": "0", + "spendableBalance": "2578", + "xpub": "xpub6Bm5P7Xyx2UYrVBAgb54gEswXhbZaryZSWsPjeJ1jpb9K9S5UTD5z5cXW4EREkTqkNjSHQHxwHKZJVE7TFvftySnKabMAXAQCMSVJBdJxMC", + "balanceHistory": {}, + "subAccounts": [] + }, + "version": 1 + }, + { + "data": { + "id": "libcore:1:bitcoin:xpub6DVfEXXjv6nspJK6h7A57pRKgAStQDhEST2NNUUwmtGpatc2cEhvP4FbCYSmtF4DJoLHBPG5imcTNVxq8V2SDdENaf63HXPKgMkeZ7SEbsK:native_segwit", + "seedIdentifier": "04c2f0fe9c27396ba3e37558d71d8308572c5bba380cfe0a68450bc38039b781ce02f1ce14db54eed0ba56ed4aebba93338d3d0af82a6078ace90458f09069b125", + "name": "Bitcoin 1 (native segwit)", + "starred": false, + "derivationMode": "native_segwit", + "index": 0, + "freshAddress": "bc1qehatadheaph4jjxfph0fn5sc5vsk0fskch0x5t", + "freshAddressPath": "84'/0'/0'/0/52", + "freshAddresses": [ + { + "address": "bc1qehatadheaph4jjxfph0fn5sc5vsk0fskch0x5t", + "derivationPath": "84'/0'/0'/0/52" + }, + { + "address": "bc1qzaavs2djzt34n0jkvm0063z0cgml3mfcyu25m0", + "derivationPath": "84'/0'/0'/0/53" + }, + { + "address": "bc1qk0zcnpddv3z4eag68kt04d0e750kk4dq8exgqk", + "derivationPath": "84'/0'/0'/0/54" + }, + { + "address": "bc1qmter0ysa83gh8q5y8xnetmj0ncd85l975zfpg3", + "derivationPath": "84'/0'/0'/0/55" + }, + { + "address": "bc1qsh98tjaj7w5e88l5yzyyxz7kalsw3ar4amlpmy", + "derivationPath": "84'/0'/0'/0/56" + }, + { + "address": "bc1queyny73jh45y74fwhfx62hmtplhv4hjftd7ltd", + "derivationPath": "84'/0'/0'/0/57" + }, + { + "address": "bc1qlthx83tmu7kqjf4qt2ykspy0fs0u8mlslcjvje", + "derivationPath": "84'/0'/0'/0/58" + }, + { + "address": "bc1qgy0azhlqze9q4axns0pfskvwfue3aqc5ldvzkc", + "derivationPath": "84'/0'/0'/0/59" + }, + { + "address": "bc1qpqzqp3fmy456hfvatkw3akuq87ta7gn0q6wn7x", + "derivationPath": "84'/0'/0'/0/60" + }, + { + "address": "bc1qtzkz29ejg28udkwrckner8wvlcxnzzx2l55r6x", + "derivationPath": "84'/0'/0'/0/61" + }, + { + "address": "bc1qwrwgy6eddn4kmm4eac8y2tefrfk2ftfx854l3g", + "derivationPath": "84'/0'/0'/0/62" + }, + { + "address": "bc1qrfe9n6gfs066jp46w2negq99ytrdg2va6vvkq5", + "derivationPath": "84'/0'/0'/0/63" + }, + { + "address": "bc1qvlwgq9qmjuz2xdq76ygty0aafdvgauk08sezjw", + "derivationPath": "84'/0'/0'/0/64" + }, + { + "address": "bc1qrrpkpqwxjs6qumn0xmmls45hywck77psrw7wnp", + "derivationPath": "84'/0'/0'/0/65" + }, + { + "address": "bc1qpdkxswkqcqg8tge4l6tfhr7wjpkqv608quar9x", + "derivationPath": "84'/0'/0'/0/66" + }, + { + "address": "bc1q8jwdg7u33vw6m5q4h68dcyat3hlhr67w3uw90s", + "derivationPath": "84'/0'/0'/0/67" + }, + { + "address": "bc1q5n2gtsx782mdjq22gw4wyq2tsk9gehhg2zkwp3", + "derivationPath": "84'/0'/0'/0/68" + }, + { + "address": "bc1qp6j23np9l93vp7asgc4g7cupm5wvekxa95wgsq", + "derivationPath": "84'/0'/0'/0/69" + }, + { + "address": "bc1qpv55nkqalxweyphdse8nmqgwp6vuxaa9gpg7sh", + "derivationPath": "84'/0'/0'/0/70" + }, + { + "address": "bc1qssp0tza6wrnxzsd405d7t9d6m7jvshz0glfl67", + "derivationPath": "84'/0'/0'/0/71" + } + ], + "blockHeight": 628010, + "operationsCount": 117, + "operations": [], + "pendingOperations": [], + "currencyId": "bitcoin", + "unitMagnitude": 8, + "lastSyncDate": "", + "balance": "0", + "spendableBalance": "1700", + "xpub": "xpub6DVfEXXjv6nspJK6h7A57pRKgAStQDhEST2NNUUwmtGpatc2cEhvP4FbCYSmtF4DJoLHBPG5imcTNVxq8V2SDdENaf63HXPKgMkeZ7SEbsK", + "balanceHistory": {}, + "subAccounts": [] + }, + "version": 1 + }, + { + "data": { + "id": "libcore:1:komodo:v4PKUB9vPNEx9QFvX7SJkYhpX2QbsXdikCPFbeJLZK4hrFSD2XBJ2Ze7zC68e3Kfaia5Xzgey12HeqwSzF5itsprdyJghVxvrrMod6oMzS14oBVf:", + "seedIdentifier": "04fb0f483df5f252ff2ef489859d4f630bcd15ff6706fb3c8515f65f9faeedef1ab8ca4a561dc9366d5c3e456b2c4765e4c7b5098dcf3abd468cecba3ef0bdf270", + "name": "Komodo 1", + "starred": false, + "derivationMode": "", + "index": 0, + "freshAddress": "RJ8BdEPiYShsysUdYgDdVMRutkkTDgnu8w", + "freshAddressPath": "44'/141'/0'/0/48", + "freshAddresses": [ + { + "address": "RJ8BdEPiYShsysUdYgDdVMRutkkTDgnu8w", + "derivationPath": "44'/141'/0'/0/48" + }, + { + "address": "RXD42V42BhaGJtsxYr1YXdoUQnLHrPygbu", + "derivationPath": "44'/141'/0'/0/49" + }, + { + "address": "RTq6JkQ4gttGiViKKwkruojSX8BUdMeKfg", + "derivationPath": "44'/141'/0'/0/50" + }, + { + "address": "RVVZ32YuzimXokYkPFQveyf3nEfoMs981x", + "derivationPath": "44'/141'/0'/0/51" + }, + { + "address": "RFZbwN64jQ8KoHACCirMUx99nkKv4Bauq4", + "derivationPath": "44'/141'/0'/0/52" + }, + { + "address": "RVjjo4FATzgSUrmYwqbkU5brUKeXfhBhat", + "derivationPath": "44'/141'/0'/0/53" + }, + { + "address": "RSLjcDRremkb98xXLScGmBNWkCbbTYFEtb", + "derivationPath": "44'/141'/0'/0/54" + }, + { + "address": "RYQxTeUpWjFSTjvsg4jxAKXNjjjM34s2jE", + "derivationPath": "44'/141'/0'/0/55" + }, + { + "address": "RQZHBDLWNx2zUnTPoYeKUeMFbUbRGVKUy1", + "derivationPath": "44'/141'/0'/0/56" + }, + { + "address": "RQkUxunVMnJFSNMHZtMGzdKkLZhcmHKDyJ", + "derivationPath": "44'/141'/0'/0/57" + }, + { + "address": "RLGJf75BE1wKwWjPJseGgs6tgH98YwGBGp", + "derivationPath": "44'/141'/0'/0/58" + }, + { + "address": "RLf2gRk8MGwWnrXPGfRBxaUq3TrkrphDRN", + "derivationPath": "44'/141'/0'/0/59" + }, + { + "address": "RAs7DhvoUE22gy3n3vsfuNeWJbRZT3yfZ1", + "derivationPath": "44'/141'/0'/0/60" + }, + { + "address": "RByLBNDax7NscVf3egVVvPeAnVWetU8s3F", + "derivationPath": "44'/141'/0'/0/61" + }, + { + "address": "RVb7N1aKZSbT7SJ94YsZNQ1bNwpsEfb9W8", + "derivationPath": "44'/141'/0'/0/62" + }, + { + "address": "RPrgvcgR2piGZ4281YK8FqJqcXyFoCzV8b", + "derivationPath": "44'/141'/0'/0/63" + }, + { + "address": "RQJUD12DZipBGj2PfprBXznLvKR3jEPP7h", + "derivationPath": "44'/141'/0'/0/64" + }, + { + "address": "RETUiR3P5efnMiYiU9PiC3yad7VjYj6Hdg", + "derivationPath": "44'/141'/0'/0/65" + }, + { + "address": "RP4XM58vo8bakSCWdUZ7jmroStSZRocEp7", + "derivationPath": "44'/141'/0'/0/66" + }, + { + "address": "RTGK34H73gtrYspyMdtkCcHamhFi3dhN9W", + "derivationPath": "44'/141'/0'/0/67" + } + ], + "blockHeight": 1854558, + "operationsCount": 111, + "operations": [], + "pendingOperations": [], + "currencyId": "komodo", + "unitMagnitude": 8, + "lastSyncDate": "", + "balance": "0", + "spendableBalance": "233798275", + "balanceHistory": {}, + "xpub": "v4PKUB9vPNEx9QFvX7SJkYhpX2QbsXdikCPFbeJLZK4hrFSD2XBJ2Ze7zC68e3Kfaia5Xzgey12HeqwSzF5itsprdyJghVxvrrMod6oMzS14oBVf", + "subAccounts": [] + }, + "version": 1 + }, + { + "data": { + "id": "libcore:1:zcash:xpub6CEGMFW91HKTGhzxJjnTZ4mSrRkNqCAiArP14Dy8GhkpwHGzyMrxWgh3aT69bpi3t4RQSg5TtwKjzVcFdfyf86jMMxTABBF6e66UC1vMGze:", + "seedIdentifier": "04ddd8dc9459f1991eb8f4ae03f2095eb66511917de8076e5aa6974fe2cb527a03f2467654f038ecdd123d447de7bd4019870f6f24a6666dee47f456f82aa9b904", + "name": "Zcash 2", + "starred": false, + "derivationMode": "", + "index": 1, + "freshAddress": "t1fEuxn1xqTsxRev942RtWY5gn6AWrC9GpY", + "freshAddressPath": "44'/133'/1'/0/83", + "freshAddresses": [ + { + "address": "t1fEuxn1xqTsxRev942RtWY5gn6AWrC9GpY", + "derivationPath": "44'/133'/1'/0/83" + }, + { + "address": "t1Me9UKBpfrCiiosVDpNhVXzjWnsAG6cTS2", + "derivationPath": "44'/133'/1'/0/84" + }, + { + "address": "t1dRxwFjbpVUupmuR8iupykTF1wy33JJoG9", + "derivationPath": "44'/133'/1'/0/85" + }, + { + "address": "t1X8HcikGryH9ZZPgCiDAhdur5Upfd1ApSm", + "derivationPath": "44'/133'/1'/0/86" + }, + { + "address": "t1KCiKxLosdCLueGet6kwonPfvVJ8hg3N2q", + "derivationPath": "44'/133'/1'/0/87" + }, + { + "address": "t1KTw9ghcEpL1Hwq1zkHy3nkEx1j98Tg44r", + "derivationPath": "44'/133'/1'/0/88" + }, + { + "address": "t1KeC6nBJUg2oKbBv4Lb7qDXUcJDgXtQ7fs", + "derivationPath": "44'/133'/1'/0/89" + }, + { + "address": "t1dFWqa61wTE9bkNoR5qCGKq7rSQy11hFBx", + "derivationPath": "44'/133'/1'/0/90" + }, + { + "address": "t1MmT8DFhVQoapE6pCkPp7ec878zWnczNUX", + "derivationPath": "44'/133'/1'/0/91" + }, + { + "address": "t1Tsrmy181nmhhiTdALGSTP3dCNM18TXpEx", + "derivationPath": "44'/133'/1'/0/92" + }, + { + "address": "t1fERbygnTo8WafXrrU1YdVTdr6TaaJ7gp2", + "derivationPath": "44'/133'/1'/0/93" + }, + { + "address": "t1eRu5VPo6iGUqn2yxBHx1Cyv6mJyNcNPbE", + "derivationPath": "44'/133'/1'/0/94" + }, + { + "address": "t1Z3uPUb5wvWN27V9M2nehZc2nCiywne5mo", + "derivationPath": "44'/133'/1'/0/95" + }, + { + "address": "t1LADMvGe6euGonbwc77YPdMCgKkyT9VD2u", + "derivationPath": "44'/133'/1'/0/96" + }, + { + "address": "t1eFaYwmpDnPtHQEHqgExvxHA2yzKFhLm9T", + "derivationPath": "44'/133'/1'/0/97" + }, + { + "address": "t1S2V2idhSDvPtrCKqfMYWSBvuVBsACPoQc", + "derivationPath": "44'/133'/1'/0/98" + }, + { + "address": "t1czT6CaTrRUv4RuywwporncyjJCGCebv36", + "derivationPath": "44'/133'/1'/0/99" + }, + { + "address": "t1ajRwDpYGE1W7heZibg3MXkHDo7QiPjgPt", + "derivationPath": "44'/133'/1'/0/100" + }, + { + "address": "t1PXTyzjuuRUDRMgUJi8CRxX4ZSAW8nPmgg", + "derivationPath": "44'/133'/1'/0/101" + }, + { + "address": "t1f1iYgWkzQmYsrrAA7AnWaaPzzTijJXvP6", + "derivationPath": "44'/133'/1'/0/102" + } + ], + "blockHeight": 812636, + "operationsCount": 179, + "operations": [], + "pendingOperations": [], + "currencyId": "zcash", + "unitMagnitude": 8, + "lastSyncDate": "", + "balance": "0", + "spendableBalance": "0", + "balanceHistory": {}, + "xpub": "xpub6CEGMFW91HKTGhzxJjnTZ4mSrRkNqCAiArP14Dy8GhkpwHGzyMrxWgh3aT69bpi3t4RQSg5TtwKjzVcFdfyf86jMMxTABBF6e66UC1vMGze", + "subAccounts": [] + }, + "version": 1 + } + ], + "countervalues": { + "version": 2, + "daily": {}, + "hourly": {} + } + } +} diff --git a/e2e/setups/freshApp.json b/e2e/setups/freshApp.json new file mode 100644 index 0000000000..c9dd13aa40 --- /dev/null +++ b/e2e/setups/freshApp.json @@ -0,0 +1,89 @@ +{ + "data": { + "user": { + "id": "ff2b91f8-5513-448e-8b7c-ea02ca8478da" + }, + "settings": { + "hasCompletedOnboarding": false, + "counterValue": "USD", + "language": "en", + "theme": null, + "region": null, + "locale": "en-US", + "orderAccounts": "balance|desc", + "countervalueFirst": false, + "autoLockTimeout": 10, + "selectedTimeRange": "month", + "marketIndicator": "western", + "currenciesSettings": {}, + "pairExchanges": {}, + "developerMode": false, + "loaded": true, + "shareAnalytics": true, + "sentryLogs": true, + "lastUsedVersion": "2.40.0", + "dismissedBanners": [], + "accountsViewMode": "list", + "nftsViewMode": "list", + "showAccountsHelperBanner": true, + "hideEmptyTokenAccounts": false, + "sidebarCollapsed": false, + "discreetMode": false, + "preferredDeviceModel": "nanoS", + "hasInstalledApps": true, + "carouselVisibility": 0, + "lastSeenDevice": null, + "latestFirmware": null, + "blacklistedTokenIds": [], + "deepLinkUrl": null, + "firstTimeLend": false, + "showClearCacheBanner": false, + "fullNodeEnabled": false, + "allowDebugApps": false, + "allowExperimentalApps": false, + "enablePlatformDevTools": false, + "catalogProvider": "production", + "enableLearnPageStagingUrl": false, + "swap": { + "hasAcceptedIPSharing": false, + "acceptedProviders": [], + "selectableCurrencies": [], + "KYC": {} + }, + "starredMarketCoins": [] + }, + "announcements": { + "announcements": [ + { + "content": { + "title": "NFTs are now in Ledger!", + "text": "You can now manage, view, store, and enjoy your NFTs from your Ethereum accounts on Ledger Live. If you are already a Ledger Nano X user, you can even send your NFTs securely, without any blind signing. All you have to do is to make sure to update your Ledger Live app." + }, + "published_at": "2022-02-25T12:00:00.000Z", + "expired_at": "2022-03-16T23:00:00.000Z", + "icon": "info", + "level": "info", + "uuid": "f3772990-e45f-4b08-baa2-a09905df629a" + }, + { + "content": { + "title": "Manage your SOL in Ledger Live!", + "text": "You can now create a Solana account, buy, send, and receive SOL in your Ledger Live app. All this while enjoying the security of your Ledger device.", + "link": { + "href": "ledgerlive://accounts", + "label": "Create your SOL account" + } + }, + "published_at": "2022-03-11T11:00:00.000Z", + "expired_at": "2022-04-01T08:00:00.000Z", + "icon": "info", + "level": "info", + "uuid": "5fc85a93-8cbf-4393-a1ce-ec297db4ee67" + } + ], + "seenIds": [], + "lastUpdateTime": 1647449227606 + }, + "accounts": [] + } +} \ No newline at end of file diff --git a/e2e/specs/engine.spec.js b/e2e/specs/engine.spec.js deleted file mode 100644 index 44dc076905..0000000000 --- a/e2e/specs/engine.spec.js +++ /dev/null @@ -1,20 +0,0 @@ -// @flow -import { cleanLaunch, bridge } from "../engine"; - -describe("Mobile E2E Test Engine", () => { - describe("Bridge", () => { - describe("loadConfig", () => { - beforeAll(async () => { - await cleanLaunch(); - }); - - it("should import settings", async () => { - await bridge.loadConfig("onboardingcompleted", true); - }); - - it("should import accounts", async () => { - await bridge.loadConfig("1AccountBTC1AccountETH", true); - }); - }); - }); -}); diff --git a/e2e/specs/onboarding.spec.js b/e2e/specs/onboarding.spec.js index 1a3788f578..ee1b112e3d 100644 --- a/e2e/specs/onboarding.spec.js +++ b/e2e/specs/onboarding.spec.js @@ -1,29 +1,24 @@ -// @flow -import { it } from "jest-circus"; -import { cleanLaunch, onboard } from "../engine"; +import OnboardingSteps from "../models/onboarding/onboardingSteps"; +import PortfolioPage from "../models/portfolioPage"; describe("Onboarding", () => { - describe("Nano X", () => { - beforeAll(async () => { - await cleanLaunch(); - }); - - describe("New Device", () => {}); - - describe("Import", () => {}); - - describe("Restore", () => {}); - - describe("Connect", () => { - onboard("nanoX", "connect"); - }); + beforeAll(async () => { + await device.launchApp(); }); - describe("Nano S", () => { - it.todo("should run through Nano S onboarding"); - }); + it("should be able to connect a Nano X", async () => { + await OnboardingSteps.waitForPageToBeVisible(); + await OnboardingSteps.startOnboarding(); + await OnboardingSteps.chooseToSetupLedger(); + await OnboardingSteps.selectYourDevice("NANO X"); + await OnboardingSteps.chooseToConnectYourNano(); + await OnboardingSteps.verifyContentsOfBoxAreChecked(); + await OnboardingSteps.chooseToPairMyNano(); + await OnboardingSteps.selectPairWithBluetooth(); + await OnboardingSteps.addDeviceViaBluetooth(); + await OnboardingSteps.openLedgerLive(); - describe("Nano Blue", () => { - it.todo("should run through Nano blue onboarding"); + await PortfolioPage.waitForPageToBeVisible(); + await PortfolioPage.emptyPortfolioIsVisible(); }); }); diff --git a/e2e/specs/password.spec.js b/e2e/specs/password.spec.js new file mode 100644 index 0000000000..1311189254 --- /dev/null +++ b/e2e/specs/password.spec.js @@ -0,0 +1,31 @@ +import PortfolioPage from "../models/portfolioPage"; +import SettingsPage from "../models/settings/settingsPage"; +import GeneralSettingsPage from "../models/settings/generalSettingsPage"; +import PasswordEntryPage from "../models/passwordEntryPage"; +import { delay } from "../helpers"; +import { loadConfig } from "../bridge/server"; + +const CORRECT_PASSWORD = "passWORD$123!"; + +describe("Password Lock Screen", () => { + beforeAll(async () => { + await device.launchApp(); + }); + + it("should be able to enter the correct password", async () => { + await loadConfig("1AccountBTC1AccountETH", true); + + await PortfolioPage.waitForPageToBeVisible(); + await PortfolioPage.navigateToSettings(); + await SettingsPage.navigateToGeneralSettings(); + await GeneralSettingsPage.togglePassword(); + await GeneralSettingsPage.enterNewPassword(CORRECT_PASSWORD); + await GeneralSettingsPage.enterNewPassword(CORRECT_PASSWORD); // confirm password step + await device.sendToHome(); // leave LLM app and go to phone's home screen + await delay(60001); // password takes 60 seconds of app inactivity to activate + await device.launchApp(); // restart LLM + await PasswordEntryPage.enterPassword(CORRECT_PASSWORD); + await PasswordEntryPage.login(); + await GeneralSettingsPage.isVisible(); + }); +}); diff --git a/e2e/specs/perf-test.spec.js b/e2e/specs/perf-test.spec.js new file mode 100644 index 0000000000..87875cc4c6 --- /dev/null +++ b/e2e/specs/perf-test.spec.js @@ -0,0 +1,44 @@ +import { loadConfig } from "../bridge/server"; +import { delay, retryAction } from "../helpers"; + +const { device, element, by, waitFor } = require("detox"); + +describe.skip("Navigation while syncing - performance test", () => { + beforeAll(async () => { + await device.launchApp({ + delete: true, + launchArgs: { + detoxURLBlacklistRegex: ".*://explorers.api.live.ledger.com/.*", + }, + }); + }); + + it.skip("should import accounts", async () => { + const initialTime = Date.now(); + await device.disableSynchronization(); + + await retryAction(async () => { + await loadConfig("allLiveCoinsNoOperations", true); + }); + + await retryAction(async () => { + const accountTabButton = element(by.id("TabBarAccounts")); + await waitFor(accountTabButton).toBeVisible(); + await delay(1000); + await accountTabButton.tap(); + }); + + await retryAction(async () => { + const firstAccountButton = element(by.text("Komodo 1")); + await waitFor(firstAccountButton).toBeVisible(); + await firstAccountButton.tap(); + }); + + await device.enableSynchronization(); + + // eslint-disable-next-line no-console + console.log( + `Test finished, took ${(Date.now() - initialTime) / 1000}s to execute`, + ); + }); +}); diff --git a/fastlane/.env.staging b/fastlane/.env.staging new file mode 100644 index 0000000000..9787c2a4e7 --- /dev/null +++ b/fastlane/.env.staging @@ -0,0 +1,3 @@ +ENVFILE=.env.staging +APP_IDENTIFIER="com.ledger.live.dev.staging" +APP_NAME="LL DEV" diff --git a/index.js b/index.js index d203e18136..7483dc9881 100644 --- a/index.js +++ b/index.js @@ -22,14 +22,29 @@ import { getEnabled } from "./src/components/HookSentry"; import logReport from "./src/log-report"; import pkg from "./package.json"; -const blacklistErrorName = [ - "NetworkDown", +// we exclude errors related to user's environment, not fixable by us +const excludedErrorName = [ + // networking conditions + "DisconnectedError", "Network Error", + "NetworkDown", + "NotConnectedError", + "TimeoutError", "WebsocketConnectionError", - "DisconnectedDeviceDuringOperation", + // bad usage of device "BleError", + "EthAppPleaseEnableContractData", + "CantOpenDevice", + "DisconnectedDeviceDuringOperation", + "PairingFailed", ]; -const blacklistErrorDescription = [ +const excludedErrorDescription = [ + // networking + /timeout of .* exceeded/, + // base usage of device + /Device .* was disconnected/, + "Invalid channel", + // others "Transaction signing request was rejected by the user", ]; @@ -40,8 +55,8 @@ if (Config.SENTRY_DSN && !__DEV__ && !Config.MOCK) { // NB we do not need to explicitly set the release. we let the native side infers it. // release: `com.ledger.live@${pkg.version}+${VersionNumber.buildVersion}`, // dist: String(VersionNumber.buildVersion), - sampleRate: 0.05, - tracesSampleRate: 0.001, + sampleRate: 0.2, + tracesSampleRate: 0.02, integrations: [ new Sentry.ReactNativeTracing({ routingInstrumentation, @@ -49,7 +64,7 @@ if (Config.SENTRY_DSN && !__DEV__ && !Config.MOCK) { ], beforeSend(event: any) { if (!getEnabled()) return null; - // If the error matches blacklistErrorName or blacklistErrorDescription, + // If the error matches excludedErrorName or excludedErrorDescription, // we will not send it to Sentry. if (event && typeof event === "object") { const { exception } = event; @@ -59,13 +74,13 @@ if (Config.SENTRY_DSN && !__DEV__ && !Config.MOCK) { Array.isArray(exception.values) ) { const { values } = exception; - const shouldBlacklist = values.some(item => { + const shouldExclude = values.some(item => { if (item && typeof item === "object") { const { type, value } = item; return (typeof type === "string" && - blacklistErrorName.some(pattern => type.match(pattern))) || + excludedErrorName.some(pattern => type.match(pattern))) || (typeof value === "string" && - blacklistErrorDescription.some(pattern => + excludedErrorDescription.some(pattern => value.match(pattern), )) ? event @@ -73,7 +88,7 @@ if (Config.SENTRY_DSN && !__DEV__ && !Config.MOCK) { } return null; }); - if (shouldBlacklist) return null; + if (shouldExclude) return null; } } diff --git a/ios/Podfile b/ios/Podfile index 4e555afe23..f5962949fc 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -2,6 +2,8 @@ require File.join(File.dirname(`node --print "require.resolve('expo/package.json require_relative '../node_modules/react-native/scripts/react_native_pods' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' +source 'https://github.com/CocoaPods/Specs.git' + platform :ios, '12.0' flipperkit_version = '0.111.0' @@ -16,10 +18,6 @@ target 'ledgerlivemobile' do :hermes_enabled => true ) - pod 'djinni_objc', :path => '../node_modules/@ledgerhq/react-native-ledger-core' - pod 'ledger-core-objc', :path => '../node_modules/@ledgerhq/react-native-ledger-core' - pod 'RNLibLedgerCore', :path => '../node_modules/@ledgerhq/react-native-ledger-core' - pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text', :modular_headers => true target 'ledgerlivemobileTests' do diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 4037b329dd..67981c25f6 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -5,7 +5,6 @@ PODS: - Analytics (4.1.6) - boost (1.76.0) - CocoaAsyncSocket (7.6.5) - - djinni_objc (4.19.1) - DoubleConversion (1.1.6) - EXApplication (4.0.2): - ExpoModulesCore @@ -143,8 +142,6 @@ PODS: - GoogleUtilities/Logger - hermes-engine (0.9.0) - InputMask (6.1.0) - - ledger-core-objc (4.19.1): - - djinni_objc - libevent (2.1.12) - libwebp (1.2.1): - libwebp/demux (= 1.2.1) @@ -524,9 +521,6 @@ PODS: - React-Core - RNKeychain (7.0.0): - React-Core - - RNLibLedgerCore (4.19.1): - - ledger-core-objc - - React - RNLocalize (2.2.1): - React-Core - RNOS (1.2.6): @@ -562,7 +556,7 @@ PODS: - RNScreens (3.12.0): - React-Core - React-RCTImage - - RNSentry (3.4.0): + - RNSentry (3.4.1): - React-Core - Sentry (= 7.11.0) - RNShare (6.5.0): @@ -593,7 +587,6 @@ PODS: DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - - "djinni_objc (from `../node_modules/@ledgerhq/react-native-ledger-core`)" - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - EXApplication (from `../node_modules/expo-application/ios`) - EXBarCodeScanner (from `../node_modules/expo-barcode-scanner/ios`) @@ -631,7 +624,6 @@ DEPENDENCIES: - FlipperKit/SKIOSNetworkPlugin (= 0.99.0) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (~> 0.9.0) - - "ledger-core-objc (from `../node_modules/@ledgerhq/react-native-ledger-core`)" - libevent (~> 2.1.12) - lottie-ios (from `../node_modules/lottie-ios`) - lottie-react-native (from `../node_modules/lottie-react-native`) @@ -690,7 +682,6 @@ DEPENDENCIES: - "RNFBRemoteConfig (from `../node_modules/@react-native-firebase/remote-config`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - RNKeychain (from `../node_modules/react-native-keychain`) - - "RNLibLedgerCore (from `../node_modules/@ledgerhq/react-native-ledger-core`)" - RNLocalize (from `../node_modules/react-native-localize`) - RNOS (from `../node_modules/react-native-os`) - RNReanimated (from `../node_modules/react-native-reanimated`) @@ -703,7 +694,7 @@ DEPENDENCIES: - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: - trunk: + https://github.com/CocoaPods/Specs.git: - Adjust - Analytics - CocoaAsyncSocket @@ -742,8 +733,6 @@ SPEC REPOS: EXTERNAL SOURCES: boost: :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" - djinni_objc: - :path: "../node_modules/@ledgerhq/react-native-ledger-core" DoubleConversion: :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" EXApplication: @@ -774,8 +763,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/React/FBReactNativeSpec" glog: :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" - ledger-core-objc: - :path: "../node_modules/@ledgerhq/react-native-ledger-core" lottie-ios: :path: "../node_modules/lottie-ios" lottie-react-native: @@ -884,8 +871,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-gesture-handler" RNKeychain: :path: "../node_modules/react-native-keychain" - RNLibLedgerCore: - :path: "../node_modules/@ledgerhq/react-native-ledger-core" RNLocalize: :path: "../node_modules/react-native-localize" RNOS: @@ -912,7 +897,6 @@ SPEC CHECKSUMS: Analytics: eefe524436f904b8bb3f8c8c3425280e43b34efc boost: a7c83b31436843459a1961bfd74b96033dc77234 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 - djinni_objc: 54ab066f337b37aceaba6d020b1e6964eead00ba DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662 EXApplication: 54fe5bd6268d697771645e8f1aef8b806a65247a EXBarCodeScanner: e5ca0062d8ad1c4c1d2e386d6a308d5a32213020 @@ -948,7 +932,6 @@ SPEC CHECKSUMS: GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1 hermes-engine: bf7577d12ac6ccf53ab8b5af3c6ccf0dd8458c5c InputMask: 71d291dc54d2deaeac6512afb6ec2304228c0bb7 - ledger-core-objc: cc0290f7cf787ddf1d6a8f8e086acf55f24523a4 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 libwebp: 98a37e597e40bfdb4c911fc98f2c53d0b12d05fc lottie-ios: c058aeafa76daa4cf64d773554bccc8385d0150e @@ -1009,12 +992,11 @@ SPEC CHECKSUMS: RNFBRemoteConfig: 64d3a17b53c865cdb6a7af5fe28084d1b964a9fb RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211 RNKeychain: f75b8c8b2f17d3b2aa1f25b4a0ac5b83d947ff8f - RNLibLedgerCore: 6d8a54abc2dc2ffa38c33fbb70d5247b97a0091e RNLocalize: cbcb55d0e19c78086ea4eea20e03fe8000bbbced RNOS: 6f2f9a70895bbbfbdad7196abd952e7b01d45027 RNReanimated: 32c91e28f5780937b8efc07ddde1bab8d373fe0b RNScreens: 2559f98b0835103cbef3b26ba77fa61d4bb37ae7 - RNSentry: ec3c033c13bcb65c79f19d54ca54c514d1832bb5 + RNSentry: fbbdcd7213058e3de5fbaa452b25a06a16b4b382 RNShare: 047d42214f875d731bde73a2b67418638af85ad9 RNSVG: 551acb6562324b1d52a4e0758f7ca0ec234e278f RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4 @@ -1026,6 +1008,6 @@ SPEC CHECKSUMS: YogaKit: f782866e155069a2cca2517aafea43200b01fd5a ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: 46b645b965d32ccb1c1a230762f88cb783bf4771 +PODFILE CHECKSUM: 2aef56f42eb03d1fa531a77545e70759c36a9929 COCOAPODS: 1.11.2 diff --git a/ios/ledgerlivemobile.xcodeproj/project.pbxproj b/ios/ledgerlivemobile.xcodeproj/project.pbxproj index 19e048d47c..89cb79d802 100644 --- a/ios/ledgerlivemobile.xcodeproj/project.pbxproj +++ b/ios/ledgerlivemobile.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 00E356F31AD99517003FC87E /* ledgerlivemobileTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ledgerlivemobileTests.m */; }; + 0EC70FE5282B9CAA00E9E355 /* AdServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0EC70FE4282B9CAA00E9E355 /* AdServices.framework */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; @@ -52,6 +53,7 @@ 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 00E356F21AD99517003FC87E /* ledgerlivemobileTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ledgerlivemobileTests.m; sourceTree = ""; }; 09BC9C5402323A57C5327727 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-ledgerlivemobile/ExpoModulesProvider.swift"; sourceTree = ""; }; + 0EC70FE4282B9CAA00E9E355 /* AdServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdServices.framework; path = System/Library/Frameworks/AdServices.framework; sourceTree = SDKROOT; }; 0F189190C1964DD1B7E31BE6 /* 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 = ""; }; 13B07F961A680F5B00A75B9A /* ledgerlivemobile.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ledgerlivemobile.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ledgerlivemobile/AppDelegate.h; sourceTree = ""; }; @@ -136,6 +138,7 @@ BC25CCBE6BEA4D62BE203C17 /* libz.tbd in Frameworks */, CB46822924B04E80814C603E /* libPasscodeAuth.a in Frameworks */, 2372D3D5180104DBED4E22EE /* libPods-ledgerlivemobile.a in Frameworks */, + 0EC70FE5282B9CAA00E9E355 /* AdServices.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -292,6 +295,7 @@ 90B115AE643A42D1BF8AA6F4 /* Frameworks */ = { isa = PBXGroup; children = ( + 0EC70FE4282B9CAA00E9E355 /* AdServices.framework */, F837348622721A48009D747A /* JavaScriptCore.framework */, 5F63C9E4AC284203A95B417E /* libz.tbd */, 31C4672E151A9F9D4A18DB00 /* libPods-ledgerlivemobile.a */, @@ -587,14 +591,12 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-ledgerlivemobile/Pods-ledgerlivemobile-frameworks.sh", - "${PODS_ROOT}/../../node_modules/@ledgerhq/react-native-ledger-core/ios/Frameworks/universal/ledger-core.framework", "${PODS_XCFRAMEWORKS_BUILD_DIR}/Flipper-DoubleConversion/double-conversion.framework/double-conversion", "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL-Universal/OpenSSL.framework/OpenSSL", "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/hermes.framework/hermes", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ledger-core.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/double-conversion.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", @@ -648,11 +650,9 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-ledgerlivemobile/Pods-ledgerlivemobile-frameworks.sh", - "${PODS_ROOT}/../../node_modules/@ledgerhq/react-native-ledger-core/ios/Frameworks/universal/ledger-core.framework", "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL/OpenSSL.framework/OpenSSL", ); outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ledger-core.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework", ); runOnlyForDeploymentPostprocessing = 0; @@ -720,7 +720,6 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/@ledgerhq/react-native-ledger-core/support-lib/**", "$(SRCROOT)/../node_modules/@segment/analytics-react-native/ios/RNAnalytics", ); INFOPLIST_FILE = ledgerlivemobileTests/Info.plist; @@ -756,7 +755,6 @@ DEVELOPMENT_TEAM = X6LFS5BQKN; HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/@ledgerhq/react-native-ledger-core/support-lib/**", "$(SRCROOT)/../node_modules/@segment/analytics-react-native/ios/RNAnalytics", ); INFOPLIST_FILE = ledgerlivemobileTests/Info.plist; @@ -792,7 +790,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 374; + CURRENT_PROJECT_VERSION = 378; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = X6LFS5BQKN; ENABLE_BITCODE = NO; @@ -805,7 +803,6 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/@ledgerhq/react-native-ledger-core/support-lib/**", "$(SRCROOT)/../node_modules/@segment/analytics-react-native/ios/RNAnalytics", ); INFOPLIST_FILE = ledgerlivemobile/Info.plist; @@ -846,7 +843,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 374; + CURRENT_PROJECT_VERSION = 378; DEVELOPMENT_TEAM = X6LFS5BQKN; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; @@ -858,7 +855,6 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/@ledgerhq/react-native-ledger-core/support-lib/**", "$(SRCROOT)/../node_modules/@segment/analytics-react-native/ios/RNAnalytics", ); INFOPLIST_FILE = ledgerlivemobile/Info.plist; @@ -955,7 +951,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 374; + CURRENT_PROJECT_VERSION = 378; DEVELOPMENT_TEAM = X6LFS5BQKN; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; @@ -967,7 +963,6 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/@ledgerhq/react-native-ledger-core/support-lib/**", "$(SRCROOT)/../node_modules/@segment/analytics-react-native/ios/RNAnalytics", ); INFOPLIST_FILE = ledgerlivemobile/Info.plist; @@ -1004,7 +999,6 @@ DEVELOPMENT_TEAM = X6LFS5BQKN; HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/@ledgerhq/react-native-ledger-core/support-lib/**", "$(SRCROOT)/../node_modules/@segment/analytics-react-native/ios/RNAnalytics", ); INFOPLIST_FILE = ledgerlivemobileTests/Info.plist; diff --git a/ios/ledgerlivemobile/Info.plist b/ios/ledgerlivemobile/Info.plist index 7cadfa7470..7851791098 100644 --- a/ios/ledgerlivemobile/Info.plist +++ b/ios/ledgerlivemobile/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 3.0.8 + 3.1.0 CFBundleSignature ???? NSCameraUsageDescription @@ -38,7 +38,7 @@ CFBundleVersion - 374 + 378 ITSAppUsesNonExemptEncryption LSRequiresIPhoneOS diff --git a/ios/ledgerlivemobileTests/Info.plist b/ios/ledgerlivemobileTests/Info.plist index 20fd02aff1..de95a7c557 100644 --- a/ios/ledgerlivemobileTests/Info.plist +++ b/ios/ledgerlivemobileTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 3.0.8 + 3.1.0 CFBundleSignature ???? CFBundleVersion - 374 + 378 diff --git a/package.json b/package.json index 907c010c61..8e2c0c5fbb 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "node": ">=14" }, "name": "ledgerlivemobile", - "version": "3.0.8", + "version": "3.1.0", "private": true, "scripts": { "postinstall": "./scripts/post.sh", @@ -16,30 +16,30 @@ "e2e:build": "yarn detox build", "e2e:test": "yarn detox test", "prebeta": "bundle install", - "beta": "bundle exec fastlane beta --env production", + "beta": "bundle exec fastlane beta --env staging", "ios:staging": "ENVFILE=.env.staging react-native run-ios --configuration Staging", "preios:local:adhoc": "bundle install", "ios:local:adhoc": "bundle exec fastlane ios local_adhoc --env adhoc", "preoios:local:beta": "bundle install", - "ios:local:beta": "bundle exec fastlane ios local_beta --env production", + "ios:local:beta": "bundle exec fastlane ios local_beta --env staging", "preoios:local:nightly": "bundle install", - "ios:local:nightly": "bundle exec fastlane ios local_nightly --env production", + "ios:local:nightly": "bundle exec fastlane ios local_nightly --env staging", "preios:ci:testflight": "bundle install", "ios:ci:testflight": "bundle exec fastlane ios ci_testflight --env production", "preios:ci:adhoc": "bundle install", "ios:ci:adhoc": "bundle exec fastlane ios ci_adhoc --env adhoc", "preios:ci:nightly": "bundle install", - "ios:ci:nightly": "bundle exec fastlane ios ci_nightly --env production", + "ios:ci:nightly": "bundle exec fastlane ios ci_nightly --env staging", "preandroid:local:apk": "bundle install", - "android:local:apk": "bundle exec fastlane android apk", + "android:local:apk": "bundle exec fastlane android apk --env staging", "preandroid:local:beta": "bundle install", - "android:local:beta": "bundle exec fastlane android local_beta --env production", + "android:local:beta": "bundle exec fastlane android local_beta --env staging", "preandroid:local:nightly": "bundle install", - "android:local:nightly": "bundle exec fastlane android local_nightly --env production", + "android:local:nightly": "bundle exec fastlane android local_nightly --env staging", "preandroid:ci:playstore": "bundle install", "android:ci:playstore": "bundle exec fastlane android ci_playstore --env production", "preandroid:ci:nightly": "bundle install", - "android:ci:nightly": "bundle exec fastlane android ci_nightly --env production", + "android:ci:nightly": "bundle exec fastlane android ci_nightly --env staging", "android:hermes:staging": "export HERMES_ENABLED_ANDROID=true && yarn android:staging", "android:staging": "cd android && ./gradlew assembleStagingRelease", "android:install": "./scripts/install-and-run-apk.sh", @@ -54,7 +54,6 @@ "test": "yarn check --integrity && ./scripts/check-no-dups.sh && yarn lint --quiet", "sync-flowtyped": "NODE_OPTIONS=--max_old_space_size=10000 flow-typed install -s -o && rm flow-typed/npm/axios_*", "sync-locales": "./scripts/sync-locales.sh", - "hack-for-ios-simulator": "cd node_modules/@ledgerhq/react-native-ledger-core/ios/Frameworks && mv universal real_universal && cp -R x86 universal", "test-deep-links": "ws --spa ./deep-links-test-page.html" }, "jest": { @@ -71,16 +70,15 @@ "@formatjs/intl-locale": "^2.4.46", "@formatjs/intl-numberformat": "^7.4.2", "@formatjs/intl-pluralrules": "^4.3.2", - "@ledgerhq/devices": "6.24.1", + "@ledgerhq/devices": "6.27.1", "@ledgerhq/errors": "6.10.0", - "@ledgerhq/hw-transport": "6.24.1", - "@ledgerhq/hw-transport-http": "6.27.0", - "@ledgerhq/live-common": "21.36.2", + "@ledgerhq/hw-transport": "6.27.1", + "@ledgerhq/hw-transport-http": "6.27.1", + "@ledgerhq/live-common": "22.1.0", "@ledgerhq/logs": "6.10.0", - "@ledgerhq/native-ui": "^0.7.14", - "@ledgerhq/react-native-hid": "6.24.1", - "@ledgerhq/react-native-hw-transport-ble": "6.25.1", - "@ledgerhq/react-native-ledger-core": "4.19.1", + "@ledgerhq/native-ui": "^0.7.16", + "@ledgerhq/react-native-hid": "^6.28.2", + "@ledgerhq/react-native-hw-transport-ble": "6.27.1", "@ledgerhq/react-native-passcode-auth": "^2.1.0", "@polkadot/reactnative-identicon": "0.87.5", "@react-native-async-storage/async-storage": "^1.15.17", @@ -96,7 +94,7 @@ "@react-navigation/native": "^6.0.6", "@react-navigation/stack": "^6.0.11", "@segment/analytics-react-native": "^1.5.0", - "@sentry/react-native": "^3.4.0", + "@sentry/react-native": "^3.4.1", "@tradle/react-native-http": "^2.0.0", "assert": "^2.0.0", "async": "^3.2.1", @@ -210,10 +208,11 @@ "@types/jest": "^27.0.2", "@types/react": "^17.0.30", "@types/react-native": "^0.65.21", + "@types/react-native-video": "^5.0.13", "@types/react-test-renderer": "^17.0.1", "babel-jest": "^26.6.3", "babel-plugin-module-resolver": "^4.1.0", - "detox": "^18.2.1", + "detox": "^19.6.5", "eslint": "7.32.0", "eslint-config-airbnb": "^18.2.1", "eslint-config-prettier": "^8.3.0", @@ -228,8 +227,8 @@ "flipper-plugin-rn-performance-android": "^0.1.0", "flow-bin": "0.122.0", "flow-typed": "^2.6.2", - "jest": "^26.6.3", - "jest-circus": "^26.6.3", + "jest": "^27.5.1", + "jest-circus": "^27.5.1", "jetifier": "^1.6.6", "local-web-server": "^4.2.1", "metro": "0.66.2", @@ -251,7 +250,8 @@ "react-native-svg": "12.1.1", "d3-array": "2.3.3", "@polkadot/util": "8.0.6-8", - "@polkadot/util-crypto": "8.0.6-8" + "@polkadot/util-crypto": "8.0.6-8", + "hermes-engine": "0.10.0" }, "react-native": { "zlib": "browserify-zlib", diff --git a/patches/react-native-video+5.2.0.patch b/patches/react-native-video+5.2.0.patch new file mode 100644 index 0000000000..40d5d03415 --- /dev/null +++ b/patches/react-native-video+5.2.0.patch @@ -0,0 +1,22 @@ +diff --git a/node_modules/react-native-video/android-exoplayer/build.gradle b/node_modules/react-native-video/android-exoplayer/build.gradle +index d005a58..6a9922b 100644 +--- a/node_modules/react-native-video/android-exoplayer/build.gradle ++++ b/node_modules/react-native-video/android-exoplayer/build.gradle +@@ -28,7 +28,7 @@ android { + + dependencies { + implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" +- implementation('com.google.android.exoplayer:exoplayer:2.13.2') { ++ implementation('com.google.android.exoplayer:exoplayer:2.13.3') { + exclude group: 'com.android.support' + } + +@@ -37,7 +37,7 @@ dependencies { + implementation "androidx.core:core:1.1.0" + implementation "androidx.media:media:1.1.0" + +- implementation('com.google.android.exoplayer:extension-okhttp:2.13.2') { ++ implementation('com.google.android.exoplayer:extension-okhttp:2.13.3') { + exclude group: 'com.squareup.okhttp3', module: 'okhttp' + } + implementation 'com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}' diff --git a/scripts/RCTCoreOperationQuery.java.patch b/scripts/RCTCoreOperationQuery.java.patch deleted file mode 100644 index 85e869ceee..0000000000 --- a/scripts/RCTCoreOperationQuery.java.patch +++ /dev/null @@ -1,8 +0,0 @@ -175c175 -< public void offset(ReadableMap currentInstance, long from, Promise promise) { ---- -> public void offset(ReadableMap currentInstance, int from, Promise promise) { -203c203 -< public void limit(ReadableMap currentInstance, long count, Promise promise) { ---- -> public void limit(ReadableMap currentInstance, int count, Promise promise) { diff --git a/scripts/post.sh b/scripts/post.sh index 52ad36a4b5..5169d5e18a 100755 --- a/scripts/post.sh +++ b/scripts/post.sh @@ -4,7 +4,7 @@ cd $(dirname $0)/.. ./scripts/sync-families-dispatch.sh -patch --forward -i scripts/RCTCoreOperationQuery.java.patch node_modules/@ledgerhq/react-native-ledger-core/android/src/main/java/com/ledger/reactnative/RCTCoreOperationQuery.java +patch -N -i ./patches/react-native-video+5.2.0.patch node_modules/react-native-video/android-exoplayer/build.gradle rm -f 'third-party/glog-0.3.5/test-driver' @@ -19,6 +19,7 @@ rn-nodeify --hack # manually shim sed -i -- 's/require("crypto")/require("react-native-crypto")/g' node_modules/@walletconnect/randombytes/dist/cjs/node/index.js +patch -N node_modules/react-native-video/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java ./scripts/react-native-video.2575.patch || false # Create the dev .env file with APP_NAME if it doesn't exist if ! [ -f .env ]; then diff --git a/scripts/react-native-video.2575.patch b/scripts/react-native-video.2575.patch new file mode 100644 index 0000000000..36365a4efb --- /dev/null +++ b/scripts/react-native-video.2575.patch @@ -0,0 +1,5 @@ +950c950,951 +< if (decoderInitializationException.codecInfo.name == null) { +--- +> if (decoderInitializationException.codecInfo == null +> || decoderInitializationException.codecInfo.name == null) { diff --git a/scripts/sync-families-dispatch.sh b/scripts/sync-families-dispatch.sh index 8599e1c477..72f269e17d 100755 --- a/scripts/sync-families-dispatch.sh +++ b/scripts/sync-families-dispatch.sh @@ -27,7 +27,7 @@ genTarget () { t=$1 echo '// @flow' for family in $families; do - if [ -f "$family/$t".js ]; then + if [[ -f "$family/$t".js || -f "$family/$t".tsx ]]; then echo -n 'import '$family' from "' OIFS=$IFS IFS="/" @@ -42,7 +42,7 @@ genTarget () { echo echo 'export default {' for family in $families; do - if [ -f "$family/$t".js ]; then + if [[ -f "$family/$t".js || -f "$family/$t".tsx ]]; then echo ' '$family',' fi done diff --git a/scripts/v3clean.js b/scripts/v3clean.js new file mode 100644 index 0000000000..93d4b06cb0 --- /dev/null +++ b/scripts/v3clean.js @@ -0,0 +1,56 @@ +const { rm } = require("fs"); + +const exec = require("child_process").exec; + +/* eslint-disable no-console */ + +async function executeAsync(command) { + return new Promise((resolve, reject) => { + exec(command, (error, stdout, stderr) => { + if (error) { + reject(error); + } else if (stderr) { + reject(stderr); + } else { + resolve(stdout); + } + }); + }); +} + +async function listTsJsFilesPairs() { + const jsFilesPath = {}; + const jsTsPairs = []; + await executeAsync('git ls-files | grep -e ".\\.js$"').then(res => + res.split("\n").map(path => (jsFilesPath[path] = true)), + ); + return executeAsync('git ls-files | grep -e ".\\.ts$" -e ".\\.tsx$"') + .then(res => + res.split("\n").forEach(path => { + const beforeExtensionPath = path + .split(".") + .slice(0, -1) + .join("."); + const jsFilePath = `${beforeExtensionPath}.js`; + if (jsFilesPath[jsFilePath]) { + jsTsPairs.push({ + tsFilePath: path, + jsFilePath, + }); + } + }), + ) + .then(() => jsTsPairs); +} + +async function removeJS() { + const pairs = await listTsJsFilesPairs(); + + pairs.forEach(({ jsFilePath }) => { + rm(jsFilePath); + }); + + return true; +} + +removeJS().then(() => console.log("JS files removed")); diff --git a/src/actions/general.js b/src/actions/general.js index 1d41998dd7..80cb49d527 100644 --- a/src/actions/general.js +++ b/src/actions/general.js @@ -21,7 +21,6 @@ import { orderAccountsSelector, } from "../reducers/settings"; import { clearBridgeCache } from "../bridge/cache"; -import clearLibcore from "../helpers/clearLibcore"; import { flushAll } from "../components/DBSave"; const extraSessionTrackingPairsChanges: BehaviorSubject< @@ -105,7 +104,6 @@ export function useCleanCache() { dispatch({ type: "CLEAN_CACHE" }); dispatch({ type: "LEDGER_CV:WIPE" }); await clearBridgeCache(); - await clearLibcore(); wipe(); flushAll(); }, [dispatch, wipe]); diff --git a/src/actions/settings.js b/src/actions/settings.js index b0ee24afee..c7afa0231a 100755 --- a/src/actions/settings.js +++ b/src/actions/settings.js @@ -128,6 +128,16 @@ export const showToken = (tokenId: string) => ({ payload: tokenId, }); +export const hideNftCollection = (collectionId: string) => ({ + type: "HIDE_NFT_COLLECTION", + payload: collectionId, +}); + +export const unhideNftCollection = (collectionId: string) => ({ + type: "UNHIDE_NFT_COLLECTION", + payload: collectionId, +}); + export const dismissBanner = (bannerId: string) => ({ type: "SETTINGS_DISMISS_BANNER", payload: bannerId, @@ -226,7 +236,7 @@ export function useTimeRange() { }, [dispatch], ); - const ranges: PortfolioRange[] = ["day", "week", "month", "year", "all"]; + const ranges: PortfolioRange[] = ["all", "year", "month", "week", "day"]; const options = ranges.map(key => ({ key, value: t(`common:time.${key}`), diff --git a/src/analytics/TrackScreen.js b/src/analytics/TrackScreen.js deleted file mode 100644 index c8ebbf6f0d..0000000000 --- a/src/analytics/TrackScreen.js +++ /dev/null @@ -1,26 +0,0 @@ -// @flow -import { useEffect, useRef } from "react"; -import { useIsFocused } from "@react-navigation/native"; -import { screen } from "./segment"; - -type Props = { - category: string, - name?: string, -}; - -export default function TrackScreen({ category, name, ...props }: Props) { - const isFocused = useIsFocused(); - const isFocusedRef = useRef(); - - useEffect(() => { - if (isFocusedRef.current !== isFocused) { - isFocusedRef.current = isFocused; - - if (isFocusedRef.current) { - screen(category, name, props); - } - } - }, [category, name, props, isFocused]); - - return null; -} diff --git a/src/analytics/TrackScreen.tsx b/src/analytics/TrackScreen.tsx index 0edb6779cc..1f17124cf7 100644 --- a/src/analytics/TrackScreen.tsx +++ b/src/analytics/TrackScreen.tsx @@ -1,4 +1,3 @@ -// @flow import { useEffect, useRef } from "react"; import { useIsFocused } from "@react-navigation/native"; import { screen } from "./segment"; diff --git a/src/colors.js b/src/colors.js deleted file mode 100644 index bd8b927417..0000000000 --- a/src/colors.js +++ /dev/null @@ -1,154 +0,0 @@ -// @flow -import React from "react"; -import color from "color"; -import { useTheme } from "@react-navigation/native"; - -export const ensureContrast = (color1: string, color2: string) => { - const colorL1 = color(color1).luminosity() + 0.05; - const colorL2 = color(color2).luminosity() + 0.05; - - const lRatio = colorL1 > colorL2 ? colorL1 / colorL2 : colorL2 / colorL1; - - if (lRatio < 1.5) { - return color(color1) - .rotate(180) - .negate() - .string(); - } - return color1; -}; - -export const rgba = (c: string, a: number) => - color(c) - .alpha(a) - .rgb() - .toString(); - -export const darken = (c: string, a: number) => - color(c) - .darken(a) - .toString(); - -export const lighten = (c: string, a: number) => - color(c) - .lighten(a) - .toString(); - -export function withTheme(Component: React$ComponentType<*>) { - return (props: *) => { - const { colors } = useTheme(); - return ; - }; -} - -export const lightTheme = { - dark: false, - colors: { - primary: "hsla(247, 56%, 68%, 1)", - background: "hsla(0, 0%, 100%, 1)", - card: "hsla(0, 0%, 100%, 1)", - text: "rgb(28, 28, 30)", - border: "rgb(199, 199, 204)", - notification: "rgb(255, 69, 58)", - contrastBackground: "#142533", - contrastBackgroundText: "#ffffff", - /* MAIN */ - live: "#bdb3ff", - alert: "#ea2e49", - success: "#66BE54", - darkBlue: "#142533", - smoke: "#666666", - grey: "#999999", - fog: "#D8D8D8", - white: "#ffffff", - green: "rgb(102, 190, 84)", - ledgerGreen: "#41ccb4", - black: "#000000", - orange: "#ff7701", - yellow: "#ffd24a", - separator: "#ebebeb", - warning: "#ff9900", - darkWarning: "#E08700", - - /* DERIVATIVES */ - lightLive: "#bdb3ff19", - lightAlert: "#ea2e490c", - lightFog: "#EEEEEE", - lightGrey: "#F9F9F9", - lightOrange: "#FF984F", - translucentGreen: "rgba(102, 190, 84, 0.2)", - translucentGrey: "rgba(153, 153, 153, 0.2)", - lightLiveBg: "#e3dfff", - - errorBg: "#ff0042", - - /* PILLS */ - pillForeground: "#999999", - pillActiveBackground: rgba("#bdb3ff", 0.1), - pillActiveForeground: "#bdb3ff", - pillActiveDisabledForeground: "#999999", - - /** SNACKBAR */ - snackBarBg: "#142533", - snackBarColor: "#FFF", - - /** SKELETON */ - skeletonBg: "#E9EAEB", - }, -}; - -export const darkTheme = { - dark: true, - colors: { - primary: "hsla(247, 56%, 68%, 1)", - card: "#1C1D1F", - background: "#131415", - text: "#FFFFFF", - border: "rgba(255, 255, 255, 0.1)", - notification: "rgb(255, 69, 58)", - contrastBackground: "#223544", - contrastBackgroundText: "#ffffff", - /* MAIN */ - live: "#bdb3ff", - alert: "#ea2e49", - success: "#66BE54", - darkBlue: "#FAFAFA", - smoke: "#aaa", - grey: "#aaa", - fog: "#A8A8A8", - white: "#000000", - green: "rgb(102, 190, 84)", - ledgerGreen: "#41ccb4", - black: "#FFFFFF", - orange: "#ff7701", - yellow: "#ffd24a", - separator: "#ebebeb", - warning: "#ff9900", - darkWarning: "#E08700", - - /* DERIVATIVES */ - lightLive: "#bdb3ff19", - lightAlert: "#ea2e490c", - lightFog: "#1c202b", - lightGrey: "rgba(255,255,255, 0.05)", - lightOrange: "#FF984F", - translucentGreen: "rgba(102, 190, 84, 0.2)", - translucentGrey: "rgba(153, 153, 153, 0.2)", - lightLiveBg: "#222635", - - errorBg: "#ff0042", - - /* PILLS */ - pillForeground: "#999999", - pillActiveBackground: rgba("#bdb3ff", 0.1), - pillActiveForeground: "#bdb3ff", - pillActiveDisabledForeground: "#999999", - - /** SNACKBAR */ - snackBarBg: "#000000", - snackBarColor: "#FFF", - - /** SKELETON */ - skeletonBg: "#2a2d33", - }, -}; diff --git a/src/components/AccountCard.js b/src/components/AccountCard.js deleted file mode 100644 index d5bd5ca2fe..0000000000 --- a/src/components/AccountCard.js +++ /dev/null @@ -1,135 +0,0 @@ -// @flow -import { - getAccountName, - getAccountSpendableBalance, -} from "@ledgerhq/live-common/lib/account"; -import React, { PureComponent } from "react"; -import { View, StyleSheet } from "react-native"; -import type { AccountLike } from "@ledgerhq/live-common/lib/types"; -import { - getAccountCurrency, - getAccountUnit, -} from "@ledgerhq/live-common/lib/account/helpers"; -import { getTagDerivationMode } from "@ledgerhq/live-common/lib/derivation"; -import Card from "./Card"; -import CurrencyIcon from "./CurrencyIcon"; -import CurrencyUnitValue from "./CurrencyUnitValue"; -import LText from "./LText"; -import { withTheme } from "../colors"; - -type Props = { - account: AccountLike, - onPress?: () => void, - style?: any, - disabled?: boolean, - colors: *, - useFullBalance?: Boolean, - AccountSubTitle?: React$Node, -}; - -class AccountCard extends PureComponent { - render() { - const { - onPress, - account, - style, - disabled, - colors, - useFullBalance, - AccountSubTitle, - } = this.props; - const currency = getAccountCurrency(account); - const unit = getAccountUnit(account); - const tag = - account.derivationMode !== undefined && - account.derivationMode !== null && - // $FlowFixMe - getTagDerivationMode(currency, account.derivationMode); - - return ( - - - - - - {getAccountName(account)} - - {AccountSubTitle} - - - {tag ? ( - - - {tag} - - - ) : null} - - - - - - - - ); - } -} - -const styles = StyleSheet.create({ - card: { - flex: 1, - flexDirection: "row", - paddingVertical: 16, - alignItems: "center", - backgroundColor: "transparent", - }, - accountName: { - flexGrow: 1, - flexShrink: 1, - marginLeft: 8, - flexDirection: "row", - justifyContent: "space-between", - alignItems: "center", - }, - badgeContainer: { - paddingHorizontal: 4, - paddingVertical: 2, - borderRadius: 4, - borderWidth: 1, - justifyContent: "space-between", - alignItems: "center", - marginLeft: 16, - }, - badgeLabel: { fontSize: 7, textTransform: "uppercase" }, - accountNameText: { - fontSize: 14, - flexShrink: 1, - }, - balanceContainer: { - marginLeft: 16, - alignItems: "flex-end", - }, - accountNameContainer: { flexShrink: 1 }, -}); - -export default withTheme(AccountCard); diff --git a/src/components/AccountGraphCard.js b/src/components/AccountGraphCard.js deleted file mode 100644 index 1f04df408c..0000000000 --- a/src/components/AccountGraphCard.js +++ /dev/null @@ -1,267 +0,0 @@ -// @flow -import React, { useState, useCallback } from "react"; -import { useTheme } from "@react-navigation/native"; -import { View, StyleSheet, Platform } from "react-native"; -import type { - Unit, - Currency, - AccountLike, -} from "@ledgerhq/live-common/lib/types"; -import { - getAccountCurrency, - getAccountUnit, -} from "@ledgerhq/live-common/lib/account"; -import { getCurrencyColor } from "@ledgerhq/live-common/lib/currencies"; -import type { - ValueChange, - PortfolioRange, - BalanceHistoryWithCountervalue, -} from "@ledgerhq/live-common/lib/portfolio/v2/types"; - -import { ensureContrast } from "../colors"; -import getWindowDimensions from "../logic/getWindowDimensions"; -import { useTimeRange } from "../actions/settings"; -import Delta from "./Delta"; -import FormatDate from "./FormatDate"; -import Graph from "./Graph"; -import Pills from "./Pills"; -import TransactionsPendingConfirmationWarning from "./TransactionsPendingConfirmationWarning"; -import Card from "./Card"; -import LText from "./LText"; -import CurrencyUnitValue from "./CurrencyUnitValue"; -import Placeholder from "./Placeholder"; -import type { Item } from "./Graph/types"; -import DiscreetModeButton from "./DiscreetModeButton"; - -type Props = { - account: AccountLike, - range: PortfolioRange, - history: BalanceHistoryWithCountervalue, - valueChange: ValueChange, - countervalueAvailable: boolean, - counterValueCurrency: Currency, - useCounterValue?: boolean, - renderTitle?: ({ - useCounterValue?: boolean, - cryptoCurrencyUnit: Unit, - counterValueUnit: Unit, - item: Item, - }) => React$Node, - renderAccountSummary: () => ?React$Node, -}; - -export default function AccountGraphCard({ - account, - countervalueAvailable, - history, - range, - counterValueCurrency, - renderTitle, - useCounterValue, - valueChange, - renderAccountSummary, -}: Props) { - const { colors } = useTheme(); - const [hoveredItem, setHoverItem] = useState(); - const [, setTimeRange, timeRangeItems] = useTimeRange(); - const mapCryptoValue = useCallback(d => d.value || 0, []); - const mapCounterValue = useCallback( - d => (d.countervalue ? d.countervalue : 0), - [], - ); - - const isAvailable = !useCounterValue || countervalueAvailable; - - const currency = getAccountCurrency(account); - const unit = getAccountUnit(account); - const graphColor = ensureContrast( - getCurrencyColor(currency), - colors.background, - ); - - return ( - - - - - - - {renderAccountSummary && ( - {renderAccountSummary()} - )} - - ); -} - -function GraphCardHeader({ - useCounterValue, - cryptoCurrencyUnit, - counterValueUnit, - to, - hoveredItem, - renderTitle, - isLoading, - valueChange, - account, -}: { - account: AccountLike, - isLoading: boolean, - cryptoCurrencyUnit: Unit, - counterValueUnit: Unit, - to: Item, - hoveredItem: ?Item, - renderTitle?: ({ - useCounterValue?: boolean, - cryptoCurrencyUnit: Unit, - counterValueUnit: Unit, - item: Item, - }) => React$Node, - useCounterValue?: boolean, - valueChange: ValueChange, -}) { - const unit = useCounterValue ? counterValueUnit : cryptoCurrencyUnit; - const item = hoveredItem || to; - - return ( - - - - {renderTitle ? ( - renderTitle({ - counterValueUnit, - useCounterValue, - cryptoCurrencyUnit, - item, - }) - ) : ( - - - - - - - )} - - - {isLoading ? ( - <> - - - - ) : hoveredItem && hoveredItem.date ? ( - - - - ) : valueChange ? ( - - - - - ) : null} - - - - - ); -} - -const styles = StyleSheet.create({ - root: { - paddingVertical: 16, - margin: 16, - ...Platform.select({ - android: { - elevation: 1, - }, - ios: { - shadowOpacity: 0.03, - shadowRadius: 8, - shadowOffset: { - height: 4, - }, - }, - }), - }, - warningWrapper: { - display: "flex", - flexDirection: "row", - alignItems: "center", - }, - balanceTextContainer: { - marginBottom: 5, - alignItems: "center", - justifyContent: "center", - }, - balanceText: { - fontSize: 22, - }, - subtitleContainer: { - flexDirection: "row", - justifyContent: "center", - alignItems: "center", - marginTop: 10, - marginBottom: 20, - }, - pillsContainer: { - marginTop: 16, - alignItems: "center", - }, - accountSummary: { - marginTop: 16, - alignItems: "center", - paddingHorizontal: 16, - flexDirection: "row", - overflow: "hidden", - }, - deltaPercent: { - marginRight: 8, - }, - graphHeader: { - flexDirection: "row", - justifyContent: "space-between", - alignItems: "flex-start", - paddingHorizontal: 16, - flexWrap: "nowrap", - }, - graphHeaderBalance: { alignItems: "flex-start", flex: 1 }, - delta: { - height: 24, - flexDirection: "row", - flexWrap: "wrap", - }, -}); diff --git a/src/components/AccountGraphCard.tsx b/src/components/AccountGraphCard.tsx index 19029b1d37..4dea050225 100644 --- a/src/components/AccountGraphCard.tsx +++ b/src/components/AccountGraphCard.tsx @@ -8,10 +8,7 @@ import React, { } from "react"; import { useTheme } from "styled-components/native"; import { Unit, Currency, AccountLike } from "@ledgerhq/live-common/lib/types"; -import { - getAccountCurrency, - getAccountUnit, -} from "@ledgerhq/live-common/lib/account"; +import { getAccountUnit } from "@ledgerhq/live-common/lib/account"; import { ValueChange, PortfolioRange, @@ -29,14 +26,15 @@ import { import { useTranslation } from "react-i18next"; import { useTimeRange } from "../actions/settings"; import Delta from "./Delta"; -import FormatDate from "./FormatDate"; import CurrencyUnitValue from "./CurrencyUnitValue"; -import Placeholder from "./Placeholder"; import { Item } from "./Graph/types"; -import CurrencyRate from "./CurrencyRate"; import { useBalanceHistoryWithCountervalue } from "../actions/portfolio"; import getWindowDimensions from "../logic/getWindowDimensions"; import Graph from "./Graph"; +import Touchable from "./Touchable"; +import TransactionsPendingConfirmationWarning from "./TransactionsPendingConfirmationWarning"; +import { NoCountervaluePlaceholder } from "./CounterValue"; +import DiscreetModeButton from "./DiscreetModeButton"; const { width } = getWindowDimensions(); @@ -67,9 +65,11 @@ type Props = { counterValueCurrency: Currency; useCounterValue?: boolean; renderAccountSummary: () => ReactNode; + onSwitchAccountCurrency: () => void; }; const timeRangeMapped: any = { + all: "all", "1y": "year", "30d": "month", "7d": "week", @@ -83,6 +83,8 @@ function AccountGraphCard({ counterValueCurrency, useCounterValue, renderAccountSummary, + onSwitchAccountCurrency, + valueChange, }: Props) { const { colors } = useTheme(); const { t } = useTranslation(); @@ -97,7 +99,7 @@ function AccountGraphCard({ const ranges = useMemo( () => Object.keys(timeRangeMapped).map(r => ({ - label: t(`market.range.${r}`), + label: t(`common:time.${timeRangeMapped[r]}`), value: timeRangeMapped[r], })), [t], @@ -108,7 +110,6 @@ function AccountGraphCard({ const activeRangeIndex = ranges.findIndex(r => r.value === timeRange); const isAvailable = !useCounterValue || countervalueAvailable; - const unit = getAccountUnit(account); const updateRange = useCallback( index => { @@ -129,25 +130,30 @@ function AccountGraphCard({ const [hoveredItem, setHoverItem] = useState(); - const mapGraphValue = useCallback(d => d?.value || 0, []); + const mapCryptoValue = useCallback(d => d.value || 0, []); + const mapCounterValue = useCallback( + d => (d.countervalue ? d.countervalue : 0), + [], + ); return ( {!loading ? ( @@ -160,7 +166,7 @@ function AccountGraphCard({ width={width - 32} color={colors.primary.c80} data={history} - mapValue={mapGraphValue} + mapValue={useCounterValue ? mapCounterValue : mapCryptoValue} onItemHover={setHoverItem} verticalRangeRatio={10} /> @@ -172,7 +178,7 @@ function AccountGraphCard({ @@ -182,68 +188,85 @@ function AccountGraphCard({ ); } -function GraphCardHeader({ - counterValueUnit, - to, - hoveredItem, - isLoading, - valueChange, - account, -}: { +type HeaderTitleProps = { account: AccountLike; - isLoading: boolean; + countervalueAvailable: boolean; + onSwitchAccountCurrency: () => void; + valueChange: ValueChange; + useCounterValue?: boolean; cryptoCurrencyUnit: Unit; counterValueUnit: Unit; - to: Item; - hoveredItem?: Item; - useCounterValue?: boolean; - valueChange: ValueChange; -}) { - const currency = getAccountCurrency(account); - const item = hoveredItem || to; + item: Item; +}; + +const GraphCardHeader = ({ + account, + countervalueAvailable, + onSwitchAccountCurrency, + valueChange, + useCounterValue, + cryptoCurrencyUnit, + counterValueUnit, + item, +}: HeaderTitleProps) => { + const items = [ + { + unit: cryptoCurrencyUnit, + value: item.value, + }, + { + unit: counterValueUnit, + value: item.countervalue, + joinFragmentsSeparator: " ", + }, + ]; + + const shouldUseCounterValue = countervalueAvailable && useCounterValue; + if (shouldUseCounterValue) { + items.reverse(); + } return ( - - - {hoveredItem ? ( + + + + + + {typeof items[1]?.value === "number" ? ( + + ) : ( + + )} + + + - - - ) : ( - - )} - - - {isLoading ? ( - - ) : hoveredItem && hoveredItem.date ? ( - - + - ) : valueChange ? ( - - ) : null} - + + + + + + + + + + + ); -} +}; export default memo(AccountGraphCard); diff --git a/src/components/AccountSectionLabel.js b/src/components/AccountSectionLabel.js deleted file mode 100644 index c9701d08a9..0000000000 --- a/src/components/AccountSectionLabel.js +++ /dev/null @@ -1,56 +0,0 @@ -// @flow -import React from "react"; -import { View, TouchableOpacity, StyleSheet } from "react-native"; -import LText from "./LText"; - -type Props = { - name: string, - icon?: React$Node, - onPress?: () => void, - RightComponent?: React$Node, -}; - -export default function AccountSectionLabel({ - name, - icon, - onPress, - RightComponent, -}: Props) { - return ( - - - - {name} - - {icon} - - {!!RightComponent && ( - {RightComponent} - )} - - ); -} - -const styles = StyleSheet.create({ - container: { - flexDirection: "row", - alignItems: "center", - paddingVertical: 12, - }, - label: { - flex: 1, - flexDirection: "row", - alignItems: "center", - }, - labelText: { - fontSize: 18, - marginRight: 6, - }, - rightWrapper: { - alignSelf: "flex-end", - }, -}); diff --git a/src/components/Alert.js b/src/components/Alert.js deleted file mode 100644 index c7385921ee..0000000000 --- a/src/components/Alert.js +++ /dev/null @@ -1,361 +0,0 @@ -// @flow -import React, { useCallback, useMemo } from "react"; -import { Trans } from "react-i18next"; -import { - TouchableOpacity, - StyleSheet, - View, - Text, - Linking, -} from "react-native"; -import { useDispatch, useSelector } from "react-redux"; -import { useTheme } from "@react-navigation/native"; -import LText from "./LText"; -import { rgba } from "../colors"; -import { dismissBanner } from "../actions/settings"; -import { dismissedBannersSelector } from "../reducers/settings"; - -import IconInfo from "../icons/Info"; -import IconCheckCircle from "../icons/CheckCircle"; -import IconExclamationCircle from "../icons/ExclamationCircle"; -import IconWarning from "../icons/Warning"; -import IconCloseCircle from "../icons/CloseCircle"; -import IconHandShield from "../icons/HandShield"; -import IconLightBulb from "../icons/LightBulb"; -import IconExternalLink from "../icons/ExternalLink"; - -const HORIZONTAL_ICON_SIZE = 16; -const BIG_ICON_SIZE = 32; -const VERTICAL_ICON_SIZE = 32; - -const hitSlop = { - top: 0, - left: 0, - right: 0, - bottom: 0, -}; - -type AlertType = - | "primary" - | "secondary" - | "success" - | "warning" - | "error" - | "hint" - | "security" - | "help" - | "danger" - | "update"; - -type Props = { - id?: string, - type: AlertType, - children: React$Node, - left?: React$Node, - bottom?: React$Node, - title?: string, - vertical?: boolean, - noIcon?: boolean, - closeable?: boolean, - onLearnMore?: () => any, - learnMoreKey?: string, - learnMoreUrl?: string, - learnMoreIsInternal?: boolean, -}; - -function useAlertStyle(type: AlertType, vertical?: boolean) { - const { colors } = useTheme(); - - switch (type) { - case "primary": - return { - backgroundColor: colors.pillActiveBackground, - textColor: colors.live, - icon: ( - - ), - }; - case "hint": - return { - backgroundColor: colors.pillActiveBackground, - textColor: colors.live, - icon: ( - - ), - }; - case "success": - return { - backgroundColor: rgba(colors.success, 0.1), - textColor: colors.success, - icon: ( - - ), - }; - case "warning": - return { - backgroundColor: rgba(colors.orange, 0.1), - textColor: colors.orange, - icon: ( - - ), - }; - case "error": - return { - backgroundColor: rgba(colors.alert, 0.1), - textColor: colors.alert, - icon: ( - - ), - }; - case "update": - return { - backgroundColor: colors.orange, - textColor: "#FFF", - icon: ( - - ), - }; - case "security": - return { - backgroundColor: colors.card, - textColor: colors.text, - borderColor: colors.fog, - icon: ( - - ), - }; - case "help": - return { - backgroundColor: colors.card, - textColor: colors.text, - borderColor: colors.fog, - icon: ( - - ), - }; - case "danger": - return { - backgroundColor: colors.card, - textColor: colors.alert, - borderColor: colors.fog, - icon: ( - - ), - }; - case "secondary": - default: - return { - backgroundColor: rgba(colors.smoke, 0.1), - textColor: colors.smoke, - icon: ( - - ), - }; - } -} - -export default function Alert({ - id, - type = "secondary", - children: description, - left, - bottom, - title, - vertical, - noIcon, - closeable = false, - onLearnMore, - learnMoreUrl, - learnMoreKey, - learnMoreIsInternal = false, -}: Props) { - const dismissedBanners = useSelector(dismissedBannersSelector); - const dispatch = useDispatch(); - - const { - backgroundColor, - textColor, - borderColor = null, - icon, - } = useAlertStyle(type, vertical); - - const hasLearnMore = !!onLearnMore || !!learnMoreUrl; - const handleLearnMore = useCallback( - () => - onLearnMore - ? onLearnMore() - : learnMoreUrl - ? Linking.openURL(learnMoreUrl) - : undefined, - [onLearnMore, learnMoreUrl], - ); - - const learnMore = hasLearnMore && ( - - {" "} - - - - {!learnMoreIsInternal && ( - <> - {" "} - - - )} - - ); - - const onDismiss = useCallback(() => { - if (id) { - dispatch(dismissBanner(id)); - } - }, [id, dispatch]); - - const isDismissed = useMemo(() => dismissedBanners.includes(id), [ - dismissedBanners, - id, - ]); - - return ( - !isDismissed && ( - - - {left || (!noIcon && icon) ? ( - - {left || icon} - - ) : null} - - - {title ? ( - - {title} - - ) : null} - - - {description} - - {learnMore} - - - {closeable && ( - - - - )} - - {bottom ? {bottom} : null} - - ) - ); -} - -const styles = StyleSheet.create({ - root: { - width: "100%", - flexDirection: "column", - borderRadius: 4, - paddingVertical: 16, - paddingHorizontal: 16, - }, - container: { - flexDirection: "row", - alignItems: "center", - }, - vertical: { - width: "100%", - flexDirection: "column", - }, - withBorder: { - borderWidth: 1, - borderStyle: "dashed", - }, - leftContainer: { - marginRight: 16, - }, - topContainer: { - marginBottom: 16, - }, - bottomContainer: { - marginTop: 16, - }, - content: { - flex: 1, - alignItems: "flex-start", - }, - verticalContent: { - flex: 0, - alignItems: "center", - }, - textCentered: { - textAlign: "center", - }, - learnMore: { - textDecorationLine: "underline", - marginTop: 8, - }, - closeContainer: { - position: "absolute", - top: "-20%", - right: "-3%", - }, -}); diff --git a/src/components/BottomModal.js b/src/components/BottomModal.js deleted file mode 100644 index fc4f985f0f..0000000000 --- a/src/components/BottomModal.js +++ /dev/null @@ -1,124 +0,0 @@ -// @flow - -import React, { useEffect, useState } from "react"; -import { View, StyleSheet, Platform } from "react-native"; -import { useSelector } from "react-redux"; -import ReactNativeModal from "react-native-modal"; -import type { ViewStyleProp } from "react-native/Libraries/StyleSheet/StyleSheet"; -import { useTheme } from "@react-navigation/native"; -import TrackScreen from "../analytics/TrackScreen"; -import { isModalLockedSelector } from "../reducers/appstate"; -import StyledStatusBar from "./StyledStatusBar"; -import ButtonUseTouchable from "../context/ButtonUseTouchable"; -import getWindowDimensions from "../logic/getWindowDimensions"; - -let isModalOpenedref = false; - -export type Props = { - id?: string, - isOpened?: boolean, - onClose?: () => void, - onModalHide?: () => void, - children?: *, - style?: ViewStyleProp, - preventBackdropClick?: boolean, - containerStyle?: ViewStyleProp, - styles?: ViewStyleProp, -}; - -// Add some extra padding at the bottom of the modal -// and make it overflow the bottom of the screen -// so that the underlying UI doesn't show up -// when it gets the position wrong and display too high -// See Jira LL-451 and GitHub #617 -const EXTRA_PADDING_SAMSUNG_FIX = 100; - -const { width, height } = getWindowDimensions(); - -const BottomModal = ({ - isOpened, - onClose = () => {}, - children, - style, - preventBackdropClick, - id, - containerStyle, - styles: propStyles, - ...rest -}: Props) => { - const { colors } = useTheme(); - const [open, setIsOpen] = useState(false); - const isModalLocked = useSelector(isModalLockedSelector); - const backDropProps = preventBackdropClick - ? {} - : { - onBackdropPress: !isModalLocked ? onClose : undefined, - onBackButtonPress: !isModalLocked ? onClose : undefined, - }; - - // workaround to make sure no double modal can be opened at same time - useEffect( - () => () => { - isModalOpenedref = false; - }, - [], - ); - - useEffect(() => { - if (!!isModalOpenedref && isOpened) { - onClose(); - } else { - setIsOpen(isOpened); - } - isModalOpenedref = isOpened; - }, [isOpened]); // do not add onClose it might cause some issues on modals ie: filter manager modal - - return ( - - - - - {open && id ? : null} - - {children} - - - - ); -}; - -const styles = StyleSheet.create({ - root: { - justifyContent: "flex-end", - margin: 0, - }, - modal: { - borderTopLeftRadius: 10, - borderTopRightRadius: 10, - paddingTop: 8, - paddingBottom: EXTRA_PADDING_SAMSUNG_FIX + 24, - marginBottom: EXTRA_PADDING_SAMSUNG_FIX * -1, - }, -}); - -export default BottomModal; diff --git a/src/components/BottomModalChoice.js b/src/components/BottomModalChoice.js deleted file mode 100644 index be4ffffb63..0000000000 --- a/src/components/BottomModalChoice.js +++ /dev/null @@ -1,110 +0,0 @@ -// @flow - -import React, { memo } from "react"; -import { View, StyleSheet } from "react-native"; -import { useTheme } from "@react-navigation/native"; -import Touchable from "./Touchable"; - -import { rgba } from "../colors"; -import LText from "./LText"; - -const hitSlop = { - top: 0, - left: 0, - right: 0, - bottom: 0, -}; - -type Props = { - onPress: ?() => any, - Icon: React$ComponentType<*>, - title: string, - description?: string, - event: string, - eventProperties?: Object, -}; - -function BottomModalChoice({ - Icon, - title, - description, - onPress, - event, - eventProperties, -}: Props) { - const { colors } = useTheme(); - - return ( - - - {Icon ? : null} - - - - {title} - - {!!description && ( - - {description} - - )} - - - ); -} - -export default memo(BottomModalChoice); - -function IconWrapper({ - Icon, - color, -}: { - Icon: React$ComponentType<*>, - color: string, -}) { - const iconWrapperBg = rgba(color, 0.1); - return ( - - - - ); -} - -const styles = StyleSheet.create({ - root: { - flexDirection: "row", - paddingVertical: 20, - alignItems: "center", - }, - disabled: { - opacity: 0.3, - }, - left: { - paddingLeft: 24, - paddingRight: 16, - alignItems: "center", - justifyContent: "center", - }, - body: { - flexGrow: 1, - }, - title: { - fontSize: 16, - }, - description: { - fontSize: 14, - }, - iconWrapper: { - width: 32, - height: 32, - borderRadius: 32, - alignItems: "center", - justifyContent: "center", - }, -}); diff --git a/src/components/BottomModalChoice.tsx b/src/components/BottomModalChoice.tsx index 568faf9819..d80a59ff63 100644 --- a/src/components/BottomModalChoice.tsx +++ b/src/components/BottomModalChoice.tsx @@ -1,5 +1,3 @@ -// @flow - import React, { memo } from "react"; import styled from "styled-components/native"; import { Text, Icon, Flex } from "@ledgerhq/native-ui"; diff --git a/src/components/Button.js b/src/components/Button.js deleted file mode 100644 index 6f529949b9..0000000000 --- a/src/components/Button.js +++ /dev/null @@ -1,362 +0,0 @@ -/* @flow */ - -import React, { - useEffect, - useState, - useCallback, - memo, - useContext, - useMemo, -} from "react"; -import { RectButton } from "react-native-gesture-handler"; -import { - StyleSheet, - ActivityIndicator, - View, - Animated, - TouchableOpacity, -} from "react-native"; -import type { ViewStyleProp } from "react-native/Libraries/StyleSheet/StyleSheet"; -import { useTheme, useIsFocused } from "@react-navigation/native"; -import Config from "react-native-config"; -import LText from "./LText"; -import ButtonUseTouchable from "../context/ButtonUseTouchable"; -import { track } from "../analytics"; - -const WAIT_TIME_BEFORE_SPINNER = 150; -const BUTTON_HEIGHT = 48; -const ANIM_OFFSET = 20; -const ANIM_DURATION = 300; - -type ButtonType = - | "primary" - | "lightPrimary" - | "negativePrimary" - | "secondary" - | "lightSecondary" - | "darkSecondary" - | "greySecondary" - | "tertiary" - | "alert"; - -export type BaseButtonProps = { - type: ButtonType, - // when on press returns a promise, - // the button will toggle in a pending state and - // will wait the promise to complete before enabling the button again - // it also displays a spinner if it takes more than WAIT_TIME_BEFORE_SPINNER - onPress?: () => ?Promise | any, - // text of the button - title?: React$Node | string, - containerStyle?: ViewStyleProp, - titleStyle?: *, - IconLeft?: React$ComponentType<{ size: number, color: string }>, - IconRight?: React$ComponentType<{ size: number, color: string }>, - disabled?: boolean, - outline?: boolean, - // for analytics - event?: string, - eventProperties?: Object, - size?: number, - testID?: string, - pending?: boolean, -}; - -type Props = BaseButtonProps & { - useTouchable: boolean, - colors: *, - isFocused: boolean, -}; - -function ButtonWrapped(props: BaseButtonProps) { - const { colors } = useTheme(); - const isFocused = useIsFocused(); // @Warning be careful not to import the wrapped button outside of navigation context - const useTouchable = useContext(ButtonUseTouchable); - return ( - - ); -} - -export function BaseButton({ - // required props - title, - onPress, - titleStyle, - IconLeft, - IconRight, - disabled, - type, - useTouchable, - outline = true, - // everything else - containerStyle, - event, - eventProperties, - pending, - // $FlowFixMe - ...otherProps -}: Props) { - const { colors } = useTheme(); - const [spinnerOn, setSpinnerOn] = useState(); - const [anim] = useState(new Animated.Value(0)); - - useEffect(() => { - setSpinnerOn(pending); - }, [pending]); - - useEffect(() => { - if (spinnerOn) { - Animated.spring(anim, { - toValue: 1, - duration: ANIM_DURATION, - useNativeDriver: true, - delay: WAIT_TIME_BEFORE_SPINNER, - }).start(); - } else { - Animated.spring(anim, { - toValue: 0, - duration: ANIM_DURATION, - useNativeDriver: true, - }).start(); - } - }, [spinnerOn, anim]); - - const onPressHandler = useCallback(async () => { - if (!onPress) return; - if (event) { - track(event, eventProperties); - } - let isPromise; - try { - const res = onPress(); - isPromise = !!res && !!res.then; - if (isPromise) { - // it's a promise, we will use pending state - setSpinnerOn(true); - await res; - } - } finally { - if (isPromise) { - setSpinnerOn(false); - } - } - }, [event, eventProperties, onPress]); - - if (__DEV__ && "style" in otherProps) { - console.warn( - "Button props 'style' must not be used. Use 'containerStyle' instead.", - ); - } - - const theme = { - primaryContainer: { backgroundColor: colors.live }, - primaryTitle: { color: "white" }, - - lightPrimaryContainer: { backgroundColor: colors.lightLive }, - lightPrimaryTitle: { color: colors.live }, - - negativePrimaryContainer: { backgroundColor: "white" }, - negativePrimaryTitle: { color: colors.live }, - - secondaryContainer: { backgroundColor: "transparent" }, - secondaryTitle: { color: colors.grey }, - secondaryOutlineBorder: { borderColor: colors.fog }, - - lightSecondaryContainer: { backgroundColor: "transparent" }, - lightSecondaryTitle: { color: colors.live }, - - greySecondaryContainer: { backgroundColor: "transparent" }, - greySecondaryTitle: { color: colors.grey }, - - darkSecondaryContainer: { backgroundColor: "transparent" }, - darkSecondaryTitle: { color: colors.smoke }, - darkSecondaryOutlineBorder: { borderColor: colors.smoke }, - - tertiaryContainer: { backgroundColor: "transparent" }, - tertiaryTitle: { color: colors.live }, - tertiaryOutlineBorder: { borderColor: colors.live }, - - alertContainer: { backgroundColor: colors.alert }, - alertTitle: { color: "white" }, - - disabledContainer: { backgroundColor: colors.lightFog }, - disabledTitle: { color: colors.grey }, - }; - - const isDisabled = disabled || !onPress || spinnerOn; - - const needsBorder = - (type === "secondary" || type === "tertiary" || type === "darkSecondary") && - !isDisabled && - outline; - - const mainContainerStyle = [ - styles.container, - isDisabled ? theme.disabledContainer : theme[`${type}Container`], - containerStyle, - ]; - - const borderStyle = [styles.outlineBorder, theme[`${type}OutlineBorder`]]; - - const textStyle = [ - styles.title, - titleStyle, - isDisabled ? theme.disabledTitle : theme[`${type}Title`], - ]; - - const iconColor = isDisabled - ? theme.disabledTitle.color - : (theme[`${type}Title`] || {}).color; - - const titleSliderOffset = anim.interpolate({ - inputRange: [0, 1], - // $FlowFixMe - outputRange: [0, -ANIM_OFFSET], - }); - - const titleOpacity = anim.interpolate({ - inputRange: [0, 1], - // $FlowFixMe - outputRange: [1, 0], - }); - - const spinnerSliderOffset = anim.interpolate({ - inputRange: [0, 1], - // $FlowFixMe - outputRange: [ANIM_OFFSET, 0], - }); - - const titleSliderStyle = [ - styles.slider, - !Config.MOCK - ? { - opacity: titleOpacity, - transform: [{ translateY: titleSliderOffset }], - } - : undefined, - ]; - - const spinnerSliderStyle = [ - styles.spinnerSlider, - !Config.MOCK - ? { - opacity: anim, - transform: [{ translateY: spinnerSliderOffset }], - } - : undefined, - ]; - - const Container = useTouchable - ? disabled - ? View - : TouchableOpacity - : RectButton; - const containerSpecificProps = useTouchable ? {} : { enabled: !isDisabled }; - - function getTestID() { - // $FlowFixMe - if (isDisabled || !otherProps.isFocused) return undefined; - if (otherProps.testID) return otherProps.testID; - - switch (type) { - case "primary": - return "Proceed"; - default: - return event; - } - } - const testID = useMemo(getTestID, [ - isDisabled, - otherProps.isFocused, - otherProps.testID, - event, - type, - ]); - - return ( - // $FlowFixMe - - {needsBorder ? : null} - - - {IconLeft ? ( - - - - ) : null} - - {title ? ( - - {title} - - ) : null} - - {IconRight ? ( - - - - ) : null} - - - - - - - ); -} - -const styles = StyleSheet.create({ - container: { - height: BUTTON_HEIGHT, - alignItems: "center", - justifyContent: "center", - paddingHorizontal: 10, - borderRadius: 4, - overflow: "hidden", - }, - slider: { - flexDirection: "row", - alignItems: "center", - justifyContent: "center", - paddingHorizontal: 10, - }, - spinnerSlider: { - position: "absolute", - top: 0, - left: 0, - right: 0, - bottom: 0, - flexDirection: "row", - alignItems: "center", - justifyContent: "center", - paddingHorizontal: 10, - }, - title: { - fontSize: 16, - }, - outlineBorder: { - position: "absolute", - top: 0, - left: 0, - right: 0, - bottom: 0, - borderWidth: 1.5, - borderRadius: 4, - }, -}); - -export default memo(ButtonWrapped); diff --git a/src/components/CameraScreen/QRCodeBottomLayer.js b/src/components/CameraScreen/QRCodeBottomLayer.js deleted file mode 100644 index 6a219f23b8..0000000000 --- a/src/components/CameraScreen/QRCodeBottomLayer.js +++ /dev/null @@ -1,62 +0,0 @@ -// @flow -import React, { memo } from "react"; -import { View, StyleSheet } from "react-native"; -import { Trans } from "react-i18next"; - -import { rgba } from "../../colors"; - -import LText from "../LText"; -import QrCodeProgressBar from "./QRCodeProgressBar"; -import { softMenuBarHeight } from "../../logic/getWindowDimensions"; - -type Props = { - progress?: number, - viewFinderSize: number, - liveQrCode?: boolean, -}; - -function QrCodeBottomLayer({ progress, viewFinderSize, liveQrCode }: Props) { - return ( - - - - - - - - - ); -} - -const styles = StyleSheet.create({ - darken: { - flexGrow: 1, - paddingBottom: softMenuBarHeight(), - }, - text: { - fontSize: 16, - lineHeight: 24, - textAlign: "center", - color: "#fff", - }, - centered: { - flex: 1, - alignItems: "center", - paddingTop: 8, - paddingHorizontal: 16, - }, -}); - -export default memo(QrCodeBottomLayer); diff --git a/src/components/CameraScreen/QRCodeBottomLayer.tsx b/src/components/CameraScreen/QRCodeBottomLayer.tsx index 018ba878ea..4363cd7cd2 100644 --- a/src/components/CameraScreen/QRCodeBottomLayer.tsx +++ b/src/components/CameraScreen/QRCodeBottomLayer.tsx @@ -2,7 +2,7 @@ import React, { memo } from "react"; import { StyleSheet } from "react-native"; import { Trans } from "react-i18next"; -import { Flex, Text, ProgressBar, Alert } from "@ledgerhq/native-ui"; +import { Flex, Text, ProgressBar } from "@ledgerhq/native-ui"; import { rgba } from "../../colors"; import { softMenuBarHeight } from "../../logic/getWindowDimensions"; @@ -52,18 +52,6 @@ function QrCodeBottomLayer({ progress, liveQrCode, instruction }: Props) { )} - {liveQrCode ? ( - - - - - - - - - - - ) : null} ); diff --git a/src/components/CameraScreen/QRCodeTopLayer.js b/src/components/CameraScreen/QRCodeTopLayer.js deleted file mode 100644 index a89989c9cb..0000000000 --- a/src/components/CameraScreen/QRCodeTopLayer.js +++ /dev/null @@ -1,28 +0,0 @@ -// @flow -import React from "react"; -import { StyleSheet } from "react-native"; -import { Trans } from "react-i18next"; - -import LText from "../LText"; - -const QRCodeTopLayer = () => ( - <> - - - - - - - -); - -const styles = StyleSheet.create({ - text: { - fontSize: 16, - lineHeight: 32, - textAlign: "center", - color: "#fff", - }, -}); - -export default QRCodeTopLayer; diff --git a/src/components/CameraScreen/QRCodeTopLayer.tsx b/src/components/CameraScreen/QRCodeTopLayer.tsx index 59d87a6c84..3ec5b70550 100644 --- a/src/components/CameraScreen/QRCodeTopLayer.tsx +++ b/src/components/CameraScreen/QRCodeTopLayer.tsx @@ -1,3 +1,26 @@ -const QRCodeTopLayer = () => null; +import { Alert, Flex, Text } from "@ledgerhq/native-ui"; +import { Trans } from "react-i18next"; +import React from "react"; + +type Props = { + liveQrCode?: boolean; +}; + +const QRCodeTopLayer = ({ liveQrCode }: Props) => ( + + {liveQrCode ? ( + + + + + + + + + + + ) : null} + +); export default QRCodeTopLayer; diff --git a/src/components/CameraScreen/index.js b/src/components/CameraScreen/index.js index bb2ca8c35c..63ece11b70 100644 --- a/src/components/CameraScreen/index.js +++ b/src/components/CameraScreen/index.js @@ -39,7 +39,7 @@ export default function CameraScreen({ styles.topCell, ]} > - {typeof progress === "number" ? : null} + void, - children: any, - style?: any, - bg?: string, -}; - -export default function Card({ onPress, style, children, bg }: Props) { - const { colors } = useTheme(); - const backgroundStyle = { backgroundColor: colors[bg] || colors.card }; - return onPress ? ( - - {children} - - ) : ( - {children} - ); -} - -const styles = StyleSheet.create({ - root: { - borderRadius: 4, - }, -}); diff --git a/src/components/Carousel/Slide.js b/src/components/Carousel/Slide.js deleted file mode 100644 index ed3dc56d9f..0000000000 --- a/src/components/Carousel/Slide.js +++ /dev/null @@ -1,81 +0,0 @@ -// @flow - -import React, { useCallback } from "react"; -import { Linking, Image, View, StyleSheet } from "react-native"; -import getWindowDimensions from "../../logic/getWindowDimensions"; -import LText from "../LText"; -import Touchable from "../Touchable"; - -type PropType = { - url: string, - name: string, - title: *, - description: *, - image: *, - position: *, -}; - -const Slide = ({ - url, - name, - title, - description, - image, - position, -}: PropType) => { - const slideWidth = getWindowDimensions().width - 32; - const onClick = useCallback(() => { - Linking.openURL(url); - }, [url]); - return ( - - - - - - {title} - - - {description} - - - - - ); -}; - -const styles = StyleSheet.create({ - wrapper: { - width: "100%", - height: 100, - padding: 16, - paddingBottom: 0, - position: "relative", - }, - buttonWrapper: { - display: "flex", - flexDirection: "row", - }, - button: { - marginBottom: 16, - }, - label: { - textTransform: "uppercase", - letterSpacing: 1, - fontSize: 10, - lineHeight: 15, - marginRight: 100, - }, - description: { - fontSize: 13, - lineHeight: 19, - marginTop: 8, - marginBottom: 16, - marginRight: 100, - }, - layer: { - position: "absolute", - }, -}); - -export default Slide; diff --git a/src/components/Carousel/Slide.tsx b/src/components/Carousel/Slide.tsx index 3d9251cf58..ef67b6853e 100644 --- a/src/components/Carousel/Slide.tsx +++ b/src/components/Carousel/Slide.tsx @@ -3,27 +3,31 @@ import { Linking, Image } from "react-native"; import { Flex, Text, Link as TextLink, Icons } from "@ledgerhq/native-ui"; import { useTranslation } from "react-i18next"; import styled from "styled-components/native"; +import { useNavigation } from "@react-navigation/native"; import Touchable from "../Touchable"; import { track } from "../../analytics"; +import { SlideProps } from "./shared"; const StyledTouchable = styled(Touchable)` flex: 1; `; -type SlideProps = { +export type SlideProps = { url: string; + onPress?: (navigate: (...args: any) => void) => void; name: string; title: string; description: any; cta: any; - image: any; - icon: any; - position: any; - width: number; + image?: any; + width?: number; + icon?: any; + position?: any; }; const Slide = ({ url, + onPress, name, title, description, @@ -34,12 +38,17 @@ const Slide = ({ width, }: SlideProps) => { const { t } = useTranslation(); + const { navigate } = useNavigation(); const onClick = useCallback(() => { track("Portfolio Recommended OpenUrl", { url, }); - Linking.openURL(url); - }, [url]); + if (onPress) { + onPress(navigate); + } else { + Linking.openURL(url); + } + }, [onPress, navigate, url]); return ( , - description: , - image: require("../../images/banners/academy.png"), - position: { - bottom: 0, - right: 0, - width: 146, - height: 93, - }, - }, - { - url: "ledgerlive://buy", - name: "buyCrypto", - title: , - description: , - image: require("../../images/banners/buycrypto.png"), - position: { - bottom: 0, - right: 0, - width: 146, - height: 93, - }, - }, - { - url: "ledgerlive://swap", - name: "Swap", - title: , - description: , - image: require("../../images/banners/swap.png"), - position: { - bottom: 0, - right: 0, - width: 127, - height: 100, - }, - }, - { - url: urls.banners.familyPack, - name: "FamilyPack", - title: , - description: , - image: require("../../images/banners/familypack.png"), - position: { - bottom: 0, - right: 0, - width: 180, - height: 80, - }, - }, -]; - -export const getDefaultSlides = () => - map(SLIDES, slide => ({ - id: slide.name, - Component: () => ( - - ), - })); - -const hitSlop = { - top: 16, - left: 16, - right: 16, - bottom: 16, -}; - -export const CAROUSEL_NONCE: number = 4; - -const Carousel = () => { - const { colors } = useTheme(); - const dispatch = useDispatch(); - const hidden = useSelector(carouselVisibilitySelector); - const [showDismissConfirmation, setShowDismissConfirmation] = useState(false); - - let slides = getDefaultSlides(); - slides = slides.filter(slide => { - if (slide.start && slide.start > new Date()) { - return false; - } - if (slide.end && slide.end < new Date()) { - return false; - } - return true; - }); - - const onDismiss = useCallback(() => setShowDismissConfirmation(true), []); - - const onUndo = useCallback(() => setShowDismissConfirmation(false), []); - const onConfirm = useCallback( - () => dispatch(setCarouselVisibility(CAROUSEL_NONCE)), - [dispatch], - ); - - if (!slides.length || hidden >= CAROUSEL_NONCE) { - // No slides or dismissed, no problem - return null; - } - - return ( - - {showDismissConfirmation ? ( - - - - - - - - - + + ); +}; + +export default CheckTermOfUseUpdateModal; diff --git a/src/components/ChoiceButton.js b/src/components/ChoiceButton.js deleted file mode 100644 index 936ec3f809..0000000000 --- a/src/components/ChoiceButton.js +++ /dev/null @@ -1,115 +0,0 @@ -/* @flow */ -import React from "react"; -import { View, StyleSheet } from "react-native"; - -import { useTheme } from "@react-navigation/native"; -import LText from "./LText"; -import Touchable from "./Touchable"; - -type ChoiceButtonProps = { - disabled?: boolean, - onSelect: Function, - label: React$Node, - description?: React$Node, - Icon: any, - extra?: React$Node, - event: string, - eventProperties: *, - navigationParams?: any[], - enableActions?: string, -}; - -const ChoiceButton = ({ - event, - eventProperties, - disabled, - label, - description, - Icon, - extra, - onSelect, - navigationParams, - enableActions, -}: ChoiceButtonProps) => { - const { colors } = useTheme(); - return ( - onSelect({ navigationParams, enableActions })} - > - - - - - - - {label} - - {description && ( - - {description} - - )} - - {extra && {extra}} - - ); -}; - -export default ChoiceButton; - -const styles = StyleSheet.create({ - button: { - width: "100%", - height: "auto", - marginVertical: 8, - flexDirection: "row", - justifyContent: "flex-start", - alignItems: "center", - borderRadius: 4, - paddingVertical: 8, - paddingHorizontal: 8, - }, - buttonIcon: { - width: 50, - height: 50, - borderRadius: 50, - - justifyContent: "center", - alignItems: "center", - }, - buttonLabelContainer: { - flex: 1, - flexGrow: 1, - justifyContent: "center", - alignItems: "flex-start", - marginHorizontal: 10, - }, - buttonLabel: { - fontSize: 18, - lineHeight: 22, - }, - buttonDesc: { - fontSize: 13, - lineHeight: 16, - }, - extraButton: { - flexShrink: 1, - flexDirection: "row", - alignContent: "center", - justifyContent: "flex-end", - }, -}); diff --git a/src/components/ChoiceButton.tsx b/src/components/ChoiceButton.tsx index f9235af49f..65381d20a2 100644 --- a/src/components/ChoiceButton.tsx +++ b/src/components/ChoiceButton.tsx @@ -28,7 +28,7 @@ const ChoiceButton = ({ }: ChoiceButtonProps) => ( + + + + ); +}; + +export default React.memo(NftCollectionOptionsMenu); diff --git a/src/components/Nft/NftCollectionRow.js b/src/components/Nft/NftCollectionRow.js deleted file mode 100644 index f5c1691392..0000000000 --- a/src/components/Nft/NftCollectionRow.js +++ /dev/null @@ -1,87 +0,0 @@ -// @flow -import React from "react"; -import { View, StyleSheet } from "react-native"; -import { RectButton } from "react-native-gesture-handler"; -import { useNftMetadata } from "@ledgerhq/live-common/lib/nft"; -import type { CollectionWithNFT } from "@ledgerhq/live-common/lib/nft"; -import { useTheme } from "@react-navigation/native"; -import Skeleton from "../Skeleton"; -import NftImage from "./NftImage"; -import LText from "../LText"; - -type Props = { - collection: CollectionWithNFT, - onCollectionPress: () => void, -}; - -function NftCollectionRow({ collection, onCollectionPress }: Props) { - const { colors } = useTheme(); - const { contract, nfts } = collection; - const { status, metadata } = useNftMetadata(contract, nfts[0].tokenId); - const loading = status === "loading"; - - return ( - - - - - - - {metadata?.tokenName || collection.contract} - - - - {collection.nfts.length} - - - ); -} - -export default NftCollectionRow; - -const styles = StyleSheet.create({ - container: { - borderRadius: 4, - }, - innerContainer: { - paddingHorizontal: 12, - paddingVertical: 14, - flexDirection: "row", - alignItems: "center", - }, - inner: { - flexGrow: 1, - flexShrink: 1, - marginLeft: 16, - flexDirection: "column", - }, - collectionNameSkeleton: { - height: 8, - width: 113, - borderRadius: 4, - }, - collectionName: { - fontSize: 16, - marginBottom: 4, - maxWidth: 218, - }, - collectionImage: { - borderRadius: 4, - width: 36, - aspectRatio: 1, - overflow: "hidden", - }, -}); diff --git a/src/components/Nft/NftCollectionRow.tsx b/src/components/Nft/NftCollectionRow.tsx index 7c142f0319..b75fbac4f9 100644 --- a/src/components/Nft/NftCollectionRow.tsx +++ b/src/components/Nft/NftCollectionRow.tsx @@ -1,37 +1,50 @@ -import React from "react"; +import React, { memo } from "react"; import { StyleSheet } from "react-native"; -import { RectButton } from "react-native-gesture-handler"; import { + useNftCollectionMetadata, useNftMetadata, - CollectionWithNFT, } from "@ledgerhq/live-common/lib/nft"; +import { ProtoNFT } from "@ledgerhq/live-common/lib/types"; import { Flex, Text } from "@ledgerhq/native-ui"; -import { useTheme } from "styled-components/native"; import Skeleton from "../Skeleton"; import NftImage from "./NftImage"; +import Touchable from "../Touchable"; type Props = { - collection: CollectionWithNFT; + collection: ProtoNFT[]; onCollectionPress: () => void; + onLongPress: () => void; }; -function NftCollectionRow({ collection, onCollectionPress }: Props) { - const { colors } = useTheme(); - const { contract, nfts } = collection; - const { status, metadata } = useNftMetadata(contract, nfts[0].tokenId); - const loading = status === "loading"; +function NftCollectionRow({ + collection, + onCollectionPress, + onLongPress, +}: Props) { + const nft = collection[0]; + const { status: nftStatus, metadata: nftMetadata } = useNftMetadata( + nft?.contract, + nft?.tokenId, + nft?.currencyId, + ); + const { + status: collectionStatus, + metadata: collectionMetadata, + } = useNftCollectionMetadata(nft?.contract, nft?.currencyId); + + const loading = nftStatus === "loading" || collectionStatus === "loading"; return ( - @@ -41,7 +54,7 @@ function NftCollectionRow({ collection, onCollectionPress }: Props) { ellipsizeMode="tail" numberOfLines={2} > - {metadata?.tokenName || collection.contract} + {collectionMetadata?.tokenName || nft?.contract} @@ -51,19 +64,16 @@ function NftCollectionRow({ collection, onCollectionPress }: Props) { color={"neutral.c70"} ml={5} > - {collection.nfts.length} + {collection?.length} - + ); } -export default NftCollectionRow; +export default memo(NftCollectionRow); const styles = StyleSheet.create({ - container: { - borderRadius: 4, - }, collectionNameSkeleton: { height: 8, width: 113, diff --git a/src/components/Nft/NftImage.js b/src/components/Nft/NftImage.tsx similarity index 70% rename from src/components/Nft/NftImage.js rename to src/components/Nft/NftImage.tsx index 94059e8a8a..b40cf13210 100644 --- a/src/components/Nft/NftImage.js +++ b/src/components/Nft/NftImage.tsx @@ -1,41 +1,30 @@ -// @flow - import React, { useState } from "react"; - -import FastImage from "react-native-fast-image"; -import { Image, View, StyleSheet, Animated } from "react-native"; +import FastImage, { + OnLoadEvent, + FastImageProps, +} from "react-native-fast-image"; +import { View, StyleSheet, Animated } from "react-native"; import ImageNotFoundIcon from "../../icons/ImageNotFound"; import { withTheme } from "../../colors"; import Skeleton from "../Skeleton"; const ImageComponent = ({ - style, - source, - resizeMode, - onLoadEnd, - onLoad, + ...props }: { - style: Object, - source: { [string]: string }, - resizeMode: string, - onLoadEnd: () => *, - onLoad: () => *, -}) => ( - -); + style: Object; +} & FastImageProps) => + typeof props?.source === "object" && props?.source?.uri ? ( + + ) : ( + <> + ); const NotFound = ({ colors, onLayout, }: { - colors: Object, - onLayout: () => *, + colors: Object; + onLayout: () => void; }) => { const [iconWidth, setIconWidth] = useState(40); @@ -58,20 +47,22 @@ const NotFound = ({ }; type Props = { - style?: Object, - status: string, - src: string, - resizeMode?: string, - colors: any, + style?: Object; + status: string; + src: string; + resizeMode?: string; + colors: any; }; type State = { - loadError: boolean, + loadError: boolean; }; class NftImage extends React.PureComponent { state = { + beforeLoadDone: false, loadError: false, + contentType: null, }; opacityAnim = new Animated.Value(0); @@ -84,10 +75,24 @@ class NftImage extends React.PureComponent { }).start(); }; + onLoad = ({ nativeEvent }: OnLoadEvent) => { + if (!nativeEvent) { + this.setState({ loadError: true }); + } + }; + + onError = () => { + this.setState({ loadError: true }); + }; + render() { const { style, status, src, colors, resizeMode = "cover" } = this.props; const { loadError } = this.state; + const noData = status === "nodata"; + const metadataError = status === "error"; + const noSource = status === "loaded" && !src; + return ( @@ -99,10 +104,7 @@ class NftImage extends React.PureComponent { }, ]} > - {status === "nodata" || - status === "error" || - (status === "loaded" && !src) || - loadError ? ( + {noData || metadataError || noSource || loadError ? ( ) : ( { source={{ uri: src, }} - onLoad={({ nativeEvent }: Image.ImageLoadEvent) => { - if (!nativeEvent) { - this.setState({ loadError: true }); - } - }} + onLoad={this.onLoad} onLoadEnd={this.startAnimation} - onError={() => this.setState({ loadError: true })} + onError={this.onError} /> )} diff --git a/src/components/Nft/NftImageViewer.js b/src/components/Nft/NftImageViewer.tsx similarity index 84% rename from src/components/Nft/NftImageViewer.js rename to src/components/Nft/NftImageViewer.tsx index b23ec9f36a..cd276eeaca 100644 --- a/src/components/Nft/NftImageViewer.js +++ b/src/components/Nft/NftImageViewer.tsx @@ -1,6 +1,4 @@ -// @flow - -import React from "react"; +import React, { memo } from "react"; import { View, StyleSheet } from "react-native"; import NftImage from "./NftImage"; @@ -8,13 +6,13 @@ import NftImage from "./NftImage"; type Props = { route: { - params?: RouteParams, - }, + params?: RouteParams; + }; }; type RouteParams = { - media: string, - status: string, + media: string; + status: string; }; const NftViewer = ({ route }: Props) => { @@ -47,4 +45,4 @@ const styles = StyleSheet.create({ }, }); -export default NftViewer; +export default memo(NftViewer); diff --git a/src/components/Nft/NftLinksPanel.js b/src/components/Nft/NftLinksPanel.tsx similarity index 72% rename from src/components/Nft/NftLinksPanel.js rename to src/components/Nft/NftLinksPanel.tsx index 384a178922..07d1b7d610 100644 --- a/src/components/Nft/NftLinksPanel.js +++ b/src/components/Nft/NftLinksPanel.tsx @@ -1,11 +1,8 @@ -// @flow - -import React from "react"; +import React, { memo } from "react"; import { useTranslation } from "react-i18next"; import { useTheme } from "@react-navigation/native"; -import type { NFTMetadata } from "@ledgerhq/live-common/lib/nft"; +import { NFTMetadata } from "@ledgerhq/live-common/lib/types"; import { View, StyleSheet, TouchableOpacity, Linking } from "react-native"; - import ExternalLinkIcon from "../../icons/ExternalLink"; import OpenSeaIcon from "../../icons/OpenSea"; import RaribleIcon from "../../icons/Rarible"; @@ -15,9 +12,9 @@ import { rgba } from "../../colors"; import LText from "../LText"; type Props = { - links: $PropertyType, - isOpen: boolean, - onClose: () => void, + links: NFTMetadata["links"] | null; + isOpen: boolean; + onClose: () => void; }; const NftLink = ({ @@ -28,12 +25,12 @@ const NftLink = ({ subtitle, onPress, }: { - style?: Object, - leftIcon: React$Node, - rightIcon?: React$Node, - title: string, - subtitle?: string, - onPress?: () => any, + style?: Object; + leftIcon: React$Node; + rightIcon?: React$Node; + title: string; + subtitle?: string; + onPress?: () => any; }) => ( @@ -65,7 +62,7 @@ const NftLinksPanel = ({ links, isOpen, onClose }: Props) => { isOpened={isOpen} onClose={onClose} > - {!links.opensea ? null : ( + {!links?.opensea ? null : ( } @@ -75,7 +72,7 @@ const NftLinksPanel = ({ links, isOpen, onClose }: Props) => { /> )} - {!links.rarible ? null : ( + {!links?.rarible ? null : ( } title={`${t("nft.viewerModal.viewOn")} Rarible`} @@ -84,23 +81,27 @@ const NftLinksPanel = ({ links, isOpen, onClose }: Props) => { /> )} - + {!links?.explorer ? null : ( + <> + - - - - } - title={t("nft.viewerModal.viewInExplorer")} - rightIcon={} - onPress={() => Linking.openURL(links.etherscan)} - /> + + + + } + title={t("nft.viewerModal.viewInExplorer")} + rightIcon={} + onPress={() => Linking.openURL(links.explorer)} + /> + + )} ); }; @@ -152,4 +153,4 @@ const styles = StyleSheet.create({ }, }); -export default NftLinksPanel; +export default memo(NftLinksPanel); diff --git a/src/components/Nft/NftViewer.js b/src/components/Nft/NftViewer.tsx similarity index 80% rename from src/components/Nft/NftViewer.js rename to src/components/Nft/NftViewer.tsx index acb7e36fc1..868b14a558 100644 --- a/src/components/Nft/NftViewer.js +++ b/src/components/Nft/NftViewer.tsx @@ -1,5 +1,3 @@ -// @flow - import React, { useMemo, useState, useCallback } from "react"; import { @@ -9,21 +7,23 @@ import { Platform, TouchableOpacity, } from "react-native"; +import { + useNftMetadata, + decodeNftId, + getNftCapabilities, + useNftCollectionMetadata, +} from "@ledgerhq/live-common/lib/nft"; import { BigNumber } from "bignumber.js"; import { useSelector } from "react-redux"; +import { Button, Icons } from "@ledgerhq/native-ui"; import { useTranslation, Trans } from "react-i18next"; +import Clipboard from "@react-native-community/clipboard"; +import { ProtoNFT } from "@ledgerhq/live-common/lib/types"; import { useNavigation, useTheme } from "@react-navigation/native"; import { getAccountBridge } from "@ledgerhq/live-common/lib/bridge"; -import { useNftMetadata, decodeNftId } from "@ledgerhq/live-common/lib/nft"; - -import type { NFT, CollectionWithNFT } from "@ledgerhq/live-common/lib/nft"; -import Clipboard from "@react-native-community/clipboard"; - -import { Button, Icons } from "@ledgerhq/native-ui"; - import { accountSelector } from "../../reducers/accounts"; -import NftLinksPanel from "./NftLinksPanel"; import { ScreenName, NavigatorName } from "../../const"; +import NftLinksPanel from "./NftLinksPanel"; import { rgba } from "../../colors"; import Skeleton from "../Skeleton"; import NftImage from "./NftImage"; @@ -31,15 +31,16 @@ import LText from "../LText"; type Props = { route: { - params: RouteParams, - }, + params: RouteParams; + }; }; type RouteParams = { - nft: NFT, - collection: CollectionWithNFT, + nft: ProtoNFT; }; +type TimeoutReturn = ReturnType; + const Section = ({ title, value, @@ -48,15 +49,17 @@ const Section = ({ copyAvailable, copiedString, }: { - title: string, - value?: any, - style?: Object, - children?: React$Node, - copyAvailable?: boolean, - copiedString?: string, + title: string; + value?: any; + style?: Object; + children?: React$Node; + copyAvailable?: boolean; + copiedString?: string; }) => { const [copied, setCopied] = useState(false); - const [timeoutFunction, setTimeoutFunction] = useState(null); + const [timeoutFunction, setTimeoutFunction] = useState( + null, + ); const copy = useCallback(() => { Clipboard.setString(value); setCopied(true); @@ -65,7 +68,7 @@ const Section = ({ setCopied(false); }, 3000), ); - return clearTimeout(timeoutFunction); + return clearTimeout(timeoutFunction as TimeoutReturn); }, [value, timeoutFunction]); return ( @@ -101,23 +104,27 @@ const Section = ({ const NftViewer = ({ route }: Props) => { const { params } = route; - const { nft, collection } = params; - const { status, metadata } = useNftMetadata(collection.contract, nft.tokenId); + const { nft } = params; + const { status: nftStatus, metadata: nftMetadata } = useNftMetadata( + nft?.contract, + nft?.tokenId, + nft?.currencyId, + ); + const { + status: collectionStatus, + metadata: collectionMetadata, + } = useNftCollectionMetadata(nft?.contract, nft?.currencyId); const { colors } = useTheme(); const { t } = useTranslation(); const navigation = useNavigation(); - const { accountId } = decodeNftId(nft.id); + const { accountId } = decodeNftId(nft?.id); const account = useSelector(state => accountSelector(state, { accountId })); const [bottomModalOpen, setBottomModalOpen] = useState(false); - const isLoading = status === "loading"; + const isLoading = nftStatus === "loading" || collectionStatus === "loading"; - const defaultLinks = { - opensea: `https://opensea.io/assets/${collection.contract}/${nft.tokenId}`, - rarible: `https://rarible.com/token/${collection.contract}:${nft.tokenId}`, - etherscan: `https://etherscan.io/token/${collection.contract}?a=${nft.tokenId}`, - }; + const nftCapabilities = useMemo(() => getNftCapabilities(nft), [nft]); const closeModal = () => { setBottomModalOpen(false); @@ -128,10 +135,11 @@ const NftViewer = ({ route }: Props) => { let transaction = bridge.createTransaction(account); transaction = bridge.updateTransaction(transaction, { - tokenIds: [nft.tokenId], - quantities: [BigNumber(1)], - collection: collection.contract, - mode: `${collection.standard?.toLowerCase()}.transfer`, + tokenIds: [nft?.tokenId], + // Quantity is set to null first to allow the user to change it on the amount page + quantities: [nftCapabilities.hasQuantity ? null : new BigNumber(1)], + collection: nft?.contract, + mode: `${nft?.standard?.toLowerCase()}.transfer`, }); navigation.navigate(NavigatorName.SendFunds, { @@ -142,7 +150,7 @@ const NftViewer = ({ route }: Props) => { transaction, }, }); - }, [account, nft, collection, navigation]); + }, [account, nft, nftCapabilities.hasQuantity, navigation]); const properties = useMemo(() => { if (isLoading) { @@ -164,14 +172,14 @@ const NftViewer = ({ route }: Props) => { ); } - if (metadata?.properties?.length) { + if (nftMetadata?.properties?.length) { return ( - {metadata?.properties?.map?.((prop, i) => ( + {nftMetadata?.properties?.map?.((prop, i) => ( { } return null; - }, [colors, isLoading, metadata]); + }, [colors, isLoading, nftMetadata]); const description = useMemo(() => { if (isLoading) { @@ -205,19 +213,19 @@ const NftViewer = ({ route }: Props) => { ); } - if (metadata?.description) { - return {metadata.description}; + if (nftMetadata?.description) { + return {nftMetadata.description}; } return null; - }, [isLoading, metadata]); + }, [isLoading, nftMetadata]); const nftImage = ( ); @@ -229,7 +237,9 @@ const NftViewer = ({ route }: Props) => { style={[styles.tokenName, styles.tokenNameSkeleton]} loading={isLoading} > - {metadata?.tokenName || "-"} + + {collectionMetadata?.tokenName || "-"} + { loading={isLoading} > - {metadata?.nftName || "-"} + {nftMetadata?.nftName || "-"} - {metadata?.media ? ( + {nftMetadata?.media ? ( navigation.navigate(NavigatorName.NftNavigator, { screen: ScreenName.NftImageViewer, params: { - media: metadata.media, + media: nftMetadata.media, }, }) } @@ -271,13 +281,15 @@ const NftViewer = ({ route }: Props) => { - - - - ); -}; diff --git a/src/components/RequiresBLE/BluetoothDisabled.js b/src/components/RequiresBLE/BluetoothDisabled.js deleted file mode 100644 index 67b31a97f1..0000000000 --- a/src/components/RequiresBLE/BluetoothDisabled.js +++ /dev/null @@ -1,67 +0,0 @@ -// @flow - -import React, { memo, useEffect } from "react"; -import { View, StyleSheet, SafeAreaView, NativeModules } from "react-native"; -import { Trans } from "react-i18next"; -import Icon from "react-native-vector-icons/dist/Feather"; -import { useTheme } from "@react-navigation/native"; -import Alert from "../../icons/Alert"; - -import LText from "../LText"; -import InfoIcon from "../InfoIcon"; -import { deviceNames } from "../../wording"; - -function BluetoothDisabled() { - const { colors } = useTheme(); - - useEffect(() => { - // Prompts the user to enable bluetooth using native api calls when the component gets initially rendered. - NativeModules.BluetoothHelperModule.prompt().catch(() => { - /* ignore */ - }); - }, []); - - return ( - - } - floatingBg={colors.alert} - > - - - - - - - - - - - - - - ); -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - alignItems: "center", - justifyContent: "center", - }, - titleFont: { - fontSize: 18, - marginTop: 32, - }, - desc: { - marginTop: 16, - paddingHorizontal: 24, - }, - descFont: { - fontSize: 14, - textAlign: "center", - }, -}); - -export default memo<{}>(BluetoothDisabled); diff --git a/src/components/RootNavigator/AccountsNavigator.js b/src/components/RootNavigator/AccountsNavigator.js deleted file mode 100644 index 3dcd51b19a..0000000000 --- a/src/components/RootNavigator/AccountsNavigator.js +++ /dev/null @@ -1,62 +0,0 @@ -// @flow -import React, { useMemo } from "react"; -import { createStackNavigator } from "@react-navigation/stack"; -import { useTranslation } from "react-i18next"; -import { useTheme } from "styled-components/native"; -import { ScreenName } from "../../const"; -import Accounts from "../../screens/Accounts"; -import AccountOrder from "../../screens/Accounts/AccountOrder"; -import AddAccount from "../../screens/Accounts/AddAccount"; -import Account from "../../screens/Account"; -import NftCollection from "../../screens/Nft/NftCollection"; -import NftGallery from "../../screens/Nft/NftGallery"; -import NftCollectionHeaderTitle from "../../screens/Nft/NftCollection/NftCollectionHeaderTitle"; -import NftGalleryHeaderTitle from "../../screens/Nft/NftGallery/NftGalleryHeaderTitle"; -import { getStackNavigatorConfig } from "../../navigation/navigatorConfig"; -import AccountHeaderRight from "../../screens/Account/AccountHeaderRight"; -import AccountHeaderTitle from "../../screens/Account/AccountHeaderTitle"; - -export default function AccountsNavigator() { - const { t } = useTranslation(); - const { colors } = useTheme(); - const stackNavConfig = useMemo(() => getStackNavigatorConfig(colors), [ - colors, - ]); - return ( - - , - headerRight: () => , - }} - /> - , - headerRight: () => , - }} - /> - , - }} - /> - , - }} - /> - - ); -} - -const Stack = createStackNavigator(); diff --git a/src/components/RootNavigator/BaseNavigator.js b/src/components/RootNavigator/BaseNavigator.js deleted file mode 100644 index 745262479c..0000000000 --- a/src/components/RootNavigator/BaseNavigator.js +++ /dev/null @@ -1,556 +0,0 @@ -// @flow -import React, { useMemo } from "react"; -import { - createStackNavigator, - CardStyleInterpolators, - TransitionPresets, -} from "@react-navigation/stack"; -import { useTranslation } from "react-i18next"; -import { useTheme } from "styled-components/native"; -import { Flex, Icons } from "@ledgerhq/native-ui"; -import { useSelector } from "react-redux"; -import { ScreenName, NavigatorName } from "../../const"; -import * as families from "../../families"; -import OperationDetails, { - BackButton, - CloseButton, -} from "../../screens/OperationDetails"; -import PairDevices from "../../screens/PairDevices"; -import EditDeviceName from "../../screens/EditDeviceName"; -import Distribution from "../../screens/Distribution"; -import Asset, { HeaderTitle } from "../../screens/Asset"; -import ScanRecipient from "../../screens/SendFunds/ScanRecipient"; -import WalletConnectScan from "../../screens/WalletConnect/Scan"; -import WalletConnectConnect from "../../screens/WalletConnect/Connect"; -import WalletConnectDeeplinkingSelectAccount from "../../screens/WalletConnect/DeeplinkingSelectAccount"; -import FallbackCameraSend from "../FallbackCamera/FallbackCameraSend"; -import Main from "./MainNavigator"; -import { ErrorHeaderInfo } from "./BaseOnboardingNavigator"; -import SettingsNavigator from "./SettingsNavigator"; -import ReceiveFundsNavigator from "./ReceiveFundsNavigator"; -import SendFundsNavigator from "./SendFundsNavigator"; -import SignMessageNavigator from "./SignMessageNavigator"; -import SignTransactionNavigator from "./SignTransactionNavigator"; -import FreezeNavigator from "./FreezeNavigator"; -import UnfreezeNavigator from "./UnfreezeNavigator"; -import ClaimRewardsNavigator from "./ClaimRewardsNavigator"; -import AddAccountsNavigator from "./AddAccountsNavigator"; -import ExchangeBuyFlowNavigator from "./ExchangeBuyFlowNavigator"; -import ExchangeSellFlowNavigator from "./ExchangeSellFlowNavigator"; -import ExchangeNavigator from "./ExchangeNavigator"; -import FirmwareUpdateNavigator from "./FirmwareUpdateNavigator"; -import AccountSettingsNavigator from "./AccountSettingsNavigator"; -import ImportAccountsNavigator from "./ImportAccountsNavigator"; -import PasswordAddFlowNavigator from "./PasswordAddFlowNavigator"; -import PasswordModifyFlowNavigator from "./PasswordModifyFlowNavigator"; -import MigrateAccountsFlowNavigator from "./MigrateAccountsFlowNavigator"; -import SwapNavigator from "./SwapNavigator"; -import LendingNavigator from "./LendingNavigator"; -import LendingInfoNavigator from "./LendingInfoNavigator"; -import LendingEnableFlowNavigator from "./LendingEnableFlowNavigator"; -import LendingSupplyFlowNavigator from "./LendingSupplyFlowNavigator"; -import LendingWithdrawFlowNavigator from "./LendingWithdrawFlowNavigator"; -import NotificationCenterNavigator from "./NotificationCenterNavigator"; -// eslint-disable-next-line import/no-unresolved -import AnalyticsNavigator from "./AnalyticsNavigator"; -import NftNavigator from "./NftNavigator"; -import { getStackNavigatorConfig } from "../../navigation/navigatorConfig"; -import Account from "../../screens/Account"; -import TransparentHeaderNavigationOptions from "../../navigation/TransparentHeaderNavigationOptions"; -import styles from "../../navigation/styles"; -import HeaderRightClose from "../HeaderRightClose"; -import StepHeader from "../StepHeader"; -import AccountHeaderTitle from "../../screens/Account/AccountHeaderTitle"; -import AccountHeaderRight from "../../screens/Account/AccountHeaderRight"; -import PortfolioHistory from "../../screens/Portfolio/PortfolioHistory"; -import RequestAccountNavigator from "./RequestAccountNavigator"; -import VerifyAccount from "../../screens/VerifyAccount"; -import PlatformApp from "../../screens/Platform/App"; -import ManagerNavigator from "./ManagerNavigator"; - -import SwapFormSelectAccount from "../../screens/Swap/FormSelection/SelectAccountScreen"; -import SwapFormSelectCurrency from "../../screens/Swap/FormSelection/SelectCurrencyScreen"; -import SwapFormSelectFees from "../../screens/Swap/FormSelection/SelectFeesScreen"; -import SwapFormSelectProviderRate from "../../screens/Swap/FormSelection/SelectProviderRateScreen"; - -import BuyDeviceScreen from "../../screens/BuyDeviceScreen"; -import { readOnlyModeEnabledSelector } from "../../reducers/settings"; - -export default function BaseNavigator() { - const { t } = useTranslation(); - const { colors } = useTheme(); - const stackNavigationConfig = useMemo( - () => getStackNavigatorConfig(colors, true), - [colors], - ); - const readOnlyModeEnabled = useSelector(readOnlyModeEnabledSelector); - - return ( - - - - - - - ({ - headerBackImage: () => ( - - - - ), - headerStyle: styles.headerNoShadow, - title: route.params.name, - })} - /> - - - - ({ - headerTitle: () => ( - - ), - headerRight: null, - })} - /> - , - headerRight: null, - }} - /> - ( - - ), - headerRight: null, - }} - /> - ( - - ), - headerRight: null, - }} - /> - - - - - - - - - - ({ - beforeRemove: () => { - /** - react-navigation workaround try to fetch params from current route params - or fallback to child navigator route params - since this listener is on top of another navigator - */ - const onError = - route.params?.onError || route.params?.params?.onError; - // @TODO replace with correct error - if (onError && typeof onError === "function") - onError( - route.params.error || - new Error("Request account interrupted by user"), - ); - }, - })} - /> - ({ - beforeRemove: () => { - const onClose = - route.params?.onClose || route.params?.params?.onClose; - if (onClose && typeof onClose === "function") { - onClose(); - } - }, - })} - /> - - - - - { - if (route.params?.isSubOperation) { - return { - headerTitle: () => ( - - ), - headerLeft: () => , - headerRight: () => , - }; - } - - return { - headerTitle: () => ( - - ), - headerLeft: () => , - headerRight: null, - }; - }} - /> - - - ({ - title: null, - headerRight: () => ( - - ), - headerShown: true, - headerStyle: styles.headerNoShadow, - })} - /> - - - - - - - , - headerRight: null, - }} - /> - - ({ - headerLeft: () => ( - - ), - headerTitle: () => , - headerRight: () => , - })} - /> - ( - - ), - headerLeft: null, - }} - /> - ( - - ), - headerLeft: null, - }} - /> - , - headerLeft: null, - }} - /> - - - ({ - title: t("notificationCenter.title"), - headerStyle: styles.headerNoShadow, - headerLeft: null, - headerRight: () => , - cardStyleInterpolator: CardStyleInterpolators.forVerticalIOS, - })} - /> - - - {Object.keys(families).map(name => { - const { component, options } = families[name]; - return ( - - ); - })} - - ); -} - -const Stack = createStackNavigator(); diff --git a/src/components/RootNavigator/BaseNavigator.tsx b/src/components/RootNavigator/BaseNavigator.tsx index 1269c1a076..11be691a2a 100644 --- a/src/components/RootNavigator/BaseNavigator.tsx +++ b/src/components/RootNavigator/BaseNavigator.tsx @@ -467,7 +467,7 @@ export default function BaseNavigator() { name={ScreenName.PortfolioOperationHistory} component={PortfolioHistory} options={{ - headerTitle: t("tabs.portfolio"), + headerTitle: t("analytics.operations.title"), headerRight: null, }} /> @@ -545,11 +545,7 @@ export default function BaseNavigator() { ({ - title: null, - headerRight: null, - headerLeft: () => , - })} + options={{ headerShown: false }} /> (false); -const actionSubject = new BehaviorSubject(); - -export function useIsNavLocked(): boolean { - const [isLocked, setIsLocked] = useState(false); - - useEffect(() => { - const subscription = lockSubject.subscribe(val => { - setIsLocked(val); - }); - - return () => { - subscription.unsubscribe(); - }; - }, []); - - return isLocked; -} - -/** use Effect to trigger lock navigation updates and callback to retrieve catched navigation actions */ -export const useLockNavigation = ( - when: boolean, - callback: (...args: any[]) => void = () => {}, -) => { - useEffect(() => { - let sub; - lockSubject.next(when); - if (when) { - sub = actionSubject.subscribe(callback); - } else { - if (sub) sub.unsubscribe(); - actionSubject.next(null); - callback(null); - } - }, [callback, when]); -}; - -const Router = options => { - const router = TabRouter(options); - - return { - ...router, - getStateForAction(state, action, options) { - const result = router.getStateForAction(state, action, options); - - /** if action is of type NAVIGATE, not forced and the navigation is locked we catch the action and return the current state without changes */ - if ( - !action.force && - lockSubject.getValue() && - result != null && - action.type === "NAVIGATE" - ) { - // we catch the action in order to programatically dispatch somewhere else in a confirmation modal per instance - actionSubject.next(action); - // Returning the current state means that the action has been handled, but we don't have a new state - return state; - } - - // make sure we unlock navigation and reset the catched action state - lockSubject.next(false); - actionSubject.next(null); - return result; - }, - }; -}; - -function BottomTabNavigator({ - initialRouteName, - backBehavior, - children, - screenOptions, - ...rest -}: *) { - const { state, descriptors, navigation } = useNavigationBuilder(Router, { - initialRouteName, - backBehavior, - children, - screenOptions, - }); - - return ( - - ); -} - -export default createNavigatorFactory(BottomTabNavigator)(); diff --git a/src/components/RootNavigator/ExchangeNavigator.js b/src/components/RootNavigator/ExchangeNavigator.js deleted file mode 100644 index 0a468e24dd..0000000000 --- a/src/components/RootNavigator/ExchangeNavigator.js +++ /dev/null @@ -1,63 +0,0 @@ -// @flow -import React from "react"; -import { createMaterialTopTabNavigator } from "@react-navigation/material-top-tabs"; -import { useTranslation } from "react-i18next"; -import { useTheme } from "styled-components/native"; -import { ScreenName } from "../../const"; -import styles from "../../navigation/styles"; -import Sell from "../../screens/Exchange/Sell"; -import LText from "../LText"; -import BuyNavigator from "./BuyNavigator"; - -type TabLabelProps = { - focused: boolean, - color: string, -}; - -export default function ExchangeNavigator() { - const { t } = useTranslation(); - const { colors } = useTheme(); - - return ( - - ( - /** width has to be a little bigger to accomodate the switch in size between semibold to regular */ - - {t("exchange.buy.tabTitle")} - - ), - }} - /> - ( - /** width has to be a little bigger to accomodate the switch in size between semibold to regular */ - - {t("exchange.sell.tabTitle")} - - ), - }} - /> - - ); -} - -const Tab = createMaterialTopTabNavigator(); diff --git a/src/components/RootNavigator/ImportAccountsNavigator.js b/src/components/RootNavigator/ImportAccountsNavigator.js deleted file mode 100644 index 496506a25b..0000000000 --- a/src/components/RootNavigator/ImportAccountsNavigator.js +++ /dev/null @@ -1,56 +0,0 @@ -// @flow -import React, { useMemo } from "react"; -import { createStackNavigator } from "@react-navigation/stack"; -import { useTheme } from "styled-components/native"; -import { useTranslation } from "react-i18next"; -import { ScreenName } from "../../const"; -import ScanAccounts from "../../screens/ImportAccounts/Scan"; -import DisplayResult, { - BackButton, -} from "../../screens/ImportAccounts/DisplayResult"; -import FallBackCameraScreen from "../../screens/ImportAccounts/FallBackCameraScreen"; -import { getStackNavigatorConfig } from "../../navigation/navigatorConfig"; -import TransparentHeaderNavigationOptions from "../../navigation/TransparentHeaderNavigationOptions"; -import HeaderRightClose from "../HeaderRightClose"; - -export default function ImportAccountsNavigator() { - const { t } = useTranslation(); - const { colors } = useTheme(); - const stackNavigationConfig = useMemo( - () => getStackNavigatorConfig(colors, true), - [colors], - ); - return ( - - , - headerLeft: null, - headerTitleStyle: { color: "#fff" }, - }} - /> - , - }} - /> - - - ); -} - -const Stack = createStackNavigator(); diff --git a/src/components/RootNavigator/MainNavigator.js b/src/components/RootNavigator/MainNavigator.js deleted file mode 100644 index b0870420a6..0000000000 --- a/src/components/RootNavigator/MainNavigator.js +++ /dev/null @@ -1,145 +0,0 @@ -// @flow -import React from "react"; -import { Platform } from "react-native"; -import { useTheme } from "styled-components/native"; -import { Icons } from "@ledgerhq/native-ui"; -import useFeature from "@ledgerhq/live-common/lib/featureFlags/useFeature"; -import { ScreenName, NavigatorName } from "../../const"; -import Portfolio from "../../screens/Portfolio"; -import Transfer, { TransferTabIcon } from "../../screens/Transfer"; -import Learn from "../../screens/Learn"; -import AccountsNavigator from "./AccountsNavigator"; -import ManagerNavigator, { ManagerTabIcon } from "./ManagerNavigator"; -import TabIcon from "../TabIcon"; -import MarketNavigator from "./MarketNavigator"; -import Tab from "./CustomBlockRouterNavigator"; - -type RouteParams = { - hideTabNavigation?: boolean, -}; -export default function MainNavigator({ - route: { params }, -}: { - route: { params: RouteParams }, -}) { - const { colors } = useTheme(); - const { hideTabNavigation } = params || {}; - const learnFeature = useFeature("learn"); - - return ( - - ( - - ), - }} - /> - {learnFeature?.enabled ? ( - ( - - ), - }} - /> - ) : ( - ({ - tabPress: () => navigation.navigate(route.name), - })} - options={{ - unmountOnBlur: true, - tabBarIcon: (props: any) => ( - - ), - tabBarTestID: "TabBarAccounts", - }} - /> - )} - , - }} - /> - ( - - ), - }} - /> - {Platform.OS === "ios" ? ( - , - tabBarTestID: "TabBarManager", - }} - listeners={({ navigation }) => ({ - tabPress: e => { - e.preventDefault(); - // NB The default behaviour is not reset route params, leading to always having the same - // search query or preselected tab after the first time (ie from Swap/Sell) - // https://github.com/react-navigation/react-navigation/issues/6674#issuecomment-562813152 - navigation.navigate(NavigatorName.Manager, { - screen: ScreenName.Manager, - params: { - tab: undefined, - searchQuery: undefined, - updateModalOpened: undefined, - }, - }); - }, - })} - /> - ) : null} - - ); -} diff --git a/src/components/RootNavigator/ManagerNavigator.js b/src/components/RootNavigator/ManagerNavigator.js deleted file mode 100644 index 6c0a7c0737..0000000000 --- a/src/components/RootNavigator/ManagerNavigator.js +++ /dev/null @@ -1,106 +0,0 @@ -// @flow -import React, { useMemo } from "react"; -import { TouchableOpacity, View, StyleSheet } from "react-native"; -import { useTheme } from "styled-components/native"; -import { createStackNavigator } from "@react-navigation/stack"; -import { useSelector } from "react-redux"; -import { useTranslation } from "react-i18next"; -import { Icons } from "@ledgerhq/native-ui"; -import { ScreenName } from "../../const"; -import { hasAvailableUpdateSelector } from "../../reducers/settings"; -import Manager from "../../screens/Manager"; -import ManagerMain from "../../screens/Manager/Manager"; -import { getStackNavigatorConfig } from "../../navigation/navigatorConfig"; -import styles from "../../navigation/styles"; -import ReadOnlyTab from "../ReadOnlyTab"; -import { useIsNavLocked } from "./CustomBlockRouterNavigator"; - -const ManagerIconWithUpate = ({ - color, - size, -}: { - color: string, - size: number, -}) => { - const { colors } = useTheme(); - return ( - - - - - ); -}; - -export default function ManagerNavigator() { - const { t } = useTranslation(); - const { colors } = useTheme(); - const stackNavConfig = useMemo(() => getStackNavigatorConfig(colors), [ - colors, - ]); - return ( - - - - - ); -} - -const Stack = createStackNavigator(); - -export function ManagerTabIcon(props: any) { - const isNavLocked = useIsNavLocked(); - const hasAvailableUpdate = useSelector(hasAvailableUpdateSelector); - - const content = ( - - ); - - if (isNavLocked) { - return {}}>{content}; - } - - return content; -} - -const stylesLocal = StyleSheet.create({ - blueDot: { - top: 0, - right: -10, - position: "absolute", - width: 6, - height: 6, - borderRadius: 4, - }, - iconWrapper: { - position: "relative", - }, -}); diff --git a/src/components/RootNavigator/NftNavigator.js b/src/components/RootNavigator/NftNavigator.tsx similarity index 99% rename from src/components/RootNavigator/NftNavigator.js rename to src/components/RootNavigator/NftNavigator.tsx index 8ccc1b8a5d..7def41bc9a 100644 --- a/src/components/RootNavigator/NftNavigator.js +++ b/src/components/RootNavigator/NftNavigator.tsx @@ -1,5 +1,3 @@ -// @flow - import React, { useMemo } from "react"; import { useTheme } from "styled-components/native"; import { createStackNavigator } from "@react-navigation/stack"; diff --git a/src/components/RootNavigator/NotificationCenterNavigator.js b/src/components/RootNavigator/NotificationCenterNavigator.js deleted file mode 100644 index 108cf797b2..0000000000 --- a/src/components/RootNavigator/NotificationCenterNavigator.js +++ /dev/null @@ -1,70 +0,0 @@ -// @flow -import React, { useState } from "react"; -import { createMaterialTopTabNavigator } from "@react-navigation/material-top-tabs"; -import { useTranslation } from "react-i18next"; -import { useTheme } from "styled-components/native"; -import { useAnnouncements } from "@ledgerhq/live-common/lib/notifications/AnnouncementProvider"; -import { ScreenName } from "../../const"; -import styles from "../../navigation/styles"; -import NotificationCenterNews from "../../screens/NotificationCenter/News"; -import NotificationCenterStatus from "../../screens/NotificationCenter/Status"; -import LText from "../LText"; - -type TabLabelProps = { - focused: boolean, - color: string, -}; - -const Tab = createMaterialTopTabNavigator(); - -export default function NotificationCenterNavigator() { - const { t } = useTranslation(); - const { colors } = useTheme(); - const { allIds, seenIds } = useAnnouncements(); - const [notificationsCount] = useState(allIds.length - seenIds.length); - - return ( - - ( - // width has to be a little bigger to accomodate the switch in size between semibold to regular - - {t( - notificationsCount > 0 - ? "notificationCenter.news.titleCount" - : "notificationCenter.news.title", - { - count: notificationsCount, - }, - )} - - ), - }} - /> - ( - // width has to be a little bigger to accomodate the switch in size between semibold to regular - - {t("notificationCenter.status.title")} - - ), - }} - /> - - ); -} diff --git a/src/components/RootNavigator/OnboardingNavigator.js b/src/components/RootNavigator/OnboardingNavigator.js deleted file mode 100644 index c1dcd10c93..0000000000 --- a/src/components/RootNavigator/OnboardingNavigator.js +++ /dev/null @@ -1,121 +0,0 @@ -// @flow -import React, { useMemo } from "react"; -import { - createStackNavigator, - CardStyleInterpolators, -} from "@react-navigation/stack"; -import { useTheme } from "styled-components/native"; -import { ScreenName, NavigatorName } from "../../const"; -import PasswordAddFlowNavigator from "./PasswordAddFlowNavigator"; - -import OnboardingWelcome from "../../screens/Onboarding/steps/welcome"; -import OnboardingLanguage from "../../screens/Onboarding/steps/language"; -import OnboardingTerms from "../../screens/Onboarding/steps/terms"; -import OnboardingDeviceSelection from "../../screens/Onboarding/steps/deviceSelection"; -import OnboardingUseCase from "../../screens/Onboarding/steps/useCaseSelection"; -import OnboardingNewDeviceInfo from "../../screens/Onboarding/steps/newDeviceInfo"; -import OnboardingNewDevice from "../../screens/Onboarding/steps/setupDevice"; -import OnboardingRecoveryPhrase from "../../screens/Onboarding/steps/recoveryPhrase"; -import OnboardingInfoModal from "../OnboardingStepperView/OnboardingInfoModal"; - -import OnboardingPairNew from "../../screens/Onboarding/steps/pairNew"; -import OnboardingImportAccounts from "../../screens/Onboarding/steps/importAccounts"; -import OnboardingFinish from "../../screens/Onboarding/steps/finish"; -import OnboardingQuiz from "../../screens/Onboarding/OnboardingQuiz"; -import OnboardingQuizFinal from "../../screens/Onboarding/OnboardingQuizFinal"; - -import { getStackNavigatorConfig } from "../../navigation/navigatorConfig"; -import styles from "../../navigation/styles"; - -export default function OnboardingNavigator() { - const { colors } = useTheme(); - const stackNavigationConfig = useMemo( - () => getStackNavigatorConfig(colors, true), - [colors], - ); - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - ); -} - -const Stack = createStackNavigator(); diff --git a/src/components/RootNavigator/ReceiveFundsNavigator.js b/src/components/RootNavigator/ReceiveFundsNavigator.js deleted file mode 100644 index b4d816fe68..0000000000 --- a/src/components/RootNavigator/ReceiveFundsNavigator.js +++ /dev/null @@ -1,79 +0,0 @@ -// @flow -import React, { useMemo } from "react"; -import { Platform } from "react-native"; -import { createStackNavigator } from "@react-navigation/stack"; -import { useTranslation } from "react-i18next"; -import { useTheme } from "styled-components/native"; -import { ScreenName } from "../../const"; -import ReceiveConfirmation from "../../screens/ReceiveFunds/03-Confirmation"; -import ReceiveConnectDevice from "../../screens/ReceiveFunds/02-ConnectDevice"; -import ReceiveSelectAccount from "../../screens/ReceiveFunds/01-SelectAccount"; -import { getStackNavigatorConfig } from "../../navigation/navigatorConfig"; -import StepHeader from "../StepHeader"; - -const totalSteps = "3"; - -export default function ReceiveFundsNavigator() { - const { t } = useTranslation(); - const { colors } = useTheme(); - const stackNavigationConfig = useMemo( - () => getStackNavigatorConfig(colors, true), - [colors], - ); - return ( - - ( - - ), - }} - /> - ({ - headerTitle: () => ( - - ), - })} - /> - ( - - ), - }} - /> - - ); -} - -const Stack = createStackNavigator(); diff --git a/src/components/RootNavigator/SendFundsNavigator.js b/src/components/RootNavigator/SendFundsNavigator.js deleted file mode 100644 index 0e0d35368f..0000000000 --- a/src/components/RootNavigator/SendFundsNavigator.js +++ /dev/null @@ -1,191 +0,0 @@ -// @flow -import React, { useMemo } from "react"; -import { createStackNavigator } from "@react-navigation/stack"; -import { useTranslation } from "react-i18next"; -import { useTheme } from "styled-components/native"; -import { ScreenName } from "../../const"; -import SendCoin from "../../screens/SendFunds/01a-SelectAccount"; -import SendCollection from "../../screens/SendFunds/01b-SelectCollection"; -import SendNft from "../../screens/SendFunds/01c-SelectNft"; -import SendSelectRecipient from "../../screens/SendFunds/02-SelectRecipient"; -import SendAmountCoin from "../../screens/SendFunds/03a-AmountCoin"; -import SendAmountNft from "../../screens/SendFunds/03b-AmountNft"; -import SendSummary from "../../screens/SendFunds/04-Summary"; -import SelectDevice from "../../screens/SelectDevice"; -import SendConnectDevice from "../../screens/ConnectDevice"; -import SendValidationSuccess from "../../screens/SendFunds/07-ValidationSuccess"; -import SendValidationError from "../../screens/SendFunds/07-ValidationError"; -import { getStackNavigatorConfig } from "../../navigation/navigatorConfig"; -import StepHeader from "../StepHeader"; - -const totalSteps = "5"; - -export default function SendFundsNavigator() { - const { t } = useTranslation(); - const { colors } = useTheme(); - const stackNavigationConfig = useMemo( - () => getStackNavigatorConfig(colors, true), - [colors], - ); - return ( - - ( - - ), - }} - /> - ( - - ), - }} - /> - ( - - ), - }} - /> - ( - - ), - }} - /> - ( - - ), - }} - /> - ( - - ), - }} - /> - ( - - ), - }} - /> - ( - - ), - }} - /> - ( - - ), - }} - initialParams={{ - analyticsPropertyFlow: "send", - }} - /> - - - - ); -} - -const Stack = createStackNavigator(); diff --git a/src/components/RootNavigator/SettingsNavigator.js b/src/components/RootNavigator/SettingsNavigator.js deleted file mode 100644 index e2ff23ce9a..0000000000 --- a/src/components/RootNavigator/SettingsNavigator.js +++ /dev/null @@ -1,276 +0,0 @@ -// @flow -import React, { useMemo } from "react"; -import { createStackNavigator } from "@react-navigation/stack"; -import { useTranslation } from "react-i18next"; -import { useTheme } from "styled-components/native"; -import { ScreenName } from "../../const"; -import BenchmarkQRStream from "../../screens/BenchmarkQRStream"; -import DebugSwap from "../../screens/DebugSwap"; -import DebugBLE from "../../screens/DebugBLE"; -import DebugBLEBenchmark from "../../screens/DebugBLEBenchmark"; -import DebugCrash from "../../screens/DebugCrash"; -import DebugHttpTransport from "../../screens/DebugHttpTransport"; -import DebugIcons from "../../screens/DebugIcons"; -import DebugLottie from "../../screens/DebugLottie.js"; -import DebugLogs from "../../screens/DebugLogs.js"; -import DebugStore from "../../screens/DebugStore"; -import DebugEnv from "../../screens/DebugEnv"; -import DebugPlayground from "../../screens/DebugPlayground"; -import Settings from "../../screens/Settings"; -import AccountsSettings from "../../screens/Settings/Accounts"; -import AboutSettings from "../../screens/Settings/About"; -import Resources from "../../screens/Settings/Resources"; -import GeneralSettings from "../../screens/Settings/General"; -import CountervalueSettings from "../../screens/Settings/General/CountervalueSettings"; -import HelpSettings from "../../screens/Settings/Help"; -import RegionSettings from "../../screens/Settings/General/Region"; -import CurrenciesList from "../../screens/Settings/CryptoAssets/Currencies/CurrenciesList"; -import CurrencySettings from "../../screens/Settings/CryptoAssets/Currencies/CurrencySettings"; -import DebugSettings, { - DebugDevices, - DebugMocks, -} from "../../screens/Settings/Debug"; -import DebugExport from "../../screens/Settings/Debug/ExportAccounts"; -import ExperimentalSettings from "../../screens/Settings/Experimental"; -import DeveloperSettings, { - DeveloperCustomManifest, -} from "../../screens/Settings/Developer"; -import RepairDevice from "../../screens/RepairDevice"; -import { getStackNavigatorConfig } from "../../navigation/navigatorConfig"; -import Button from "../Button"; -import HelpButton from "../../screens/Settings/HelpButton"; - -export default function SettingsNavigator() { - const { t } = useTranslation(); - const { colors } = useTheme(); - const stackNavConfig = useMemo(() => getStackNavigatorConfig(colors), [ - colors, - ]); - return ( - - , - }} - /> - - - - - - - - - ({ - title: route.params.headerTitle, - headerRight: null, - })} - /> - - - - - - - - - - ({ - title: "Debug BLE", - headerRight: () => ( -