diff --git a/.github/workflows/account-migration.yml b/.github/workflows/account-migration.yml index 18b15e559c2d..e31cadfcfd41 100644 --- a/.github/workflows/account-migration.yml +++ b/.github/workflows/account-migration.yml @@ -30,8 +30,11 @@ jobs: - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches + with: + install-proto: true - name: install dependencies and build run: | diff --git a/.github/workflows/bot-portfolio-report.yml b/.github/workflows/bot-portfolio-report.yml index 026f64f8ebe1..08cb6c40107f 100644 --- a/.github/workflows/bot-portfolio-report.yml +++ b/.github/workflows/bot-portfolio-report.yml @@ -40,12 +40,15 @@ jobs: repository: LedgerHQ/coin-apps token: ${{ steps.generate-token.outputs.token }} path: coin-apps - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} + turbo-server-token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} - name: install and build run: | pnpm i --filter="live-cli..." --filter="ledger-live" diff --git a/.github/workflows/bot-super-report-custom.yml b/.github/workflows/bot-super-report-custom.yml index 1051d40ad93f..cfbd53a99e34 100644 --- a/.github/workflows/bot-super-report-custom.yml +++ b/.github/workflows/bot-super-report-custom.yml @@ -20,9 +20,11 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} diff --git a/.github/workflows/bot-super-report.yml b/.github/workflows/bot-super-report.yml index f2099f049c4b..b950ab3cffe2 100644 --- a/.github/workflows/bot-super-report.yml +++ b/.github/workflows/bot-super-report.yml @@ -12,9 +12,11 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} diff --git a/.github/workflows/build-and-test-pr.yml b/.github/workflows/build-and-test-pr.yml index 7aea53bd2b01..9c615c5467e3 100644 --- a/.github/workflows/build-and-test-pr.yml +++ b/.github/workflows/build-and-test-pr.yml @@ -72,11 +72,11 @@ jobs: uses: LedgerHQ/ledger-live/.github/workflows/test-design-system-reusable.yml@develop secrets: inherit - test-web-tools: - name: "Test Web Tools" + build-web-tools: + name: "Build Web Tools" needs: determine-affected if: ${{contains(needs.determine-affected.outputs.paths, 'apps/web-tools') && !github.event.pull_request.head.repo.fork}} - uses: LedgerHQ/ledger-live/.github/workflows/test-web-tools-reusable.yml@develop + uses: LedgerHQ/ledger-live/.github/workflows/build-web-tools-reusable.yml@develop secrets: inherit test-cli: @@ -97,7 +97,7 @@ jobs: - test-mobile-e2e - test-libraries - test-design-system - - test-web-tools + - build-web-tools - test-cli runs-on: ubuntu-22.04 if: always() && !cancelled() diff --git a/.github/workflows/build-and-test-push.yml b/.github/workflows/build-and-test-push.yml index d6723b6a511d..2cad88352f97 100644 --- a/.github/workflows/build-and-test-push.yml +++ b/.github/workflows/build-and-test-push.yml @@ -51,9 +51,9 @@ jobs: uses: LedgerHQ/ledger-live/.github/workflows/test-design-system-reusable.yml@develop secrets: inherit - test-web-tools: - name: "Test Web Tools" - uses: LedgerHQ/ledger-live/.github/workflows/test-web-tools-reusable.yml@develop + build-web-tools: + name: "Build Web Tools" + uses: LedgerHQ/ledger-live/.github/workflows/build-web-tools-reusable.yml@develop secrets: inherit test-cli: @@ -72,7 +72,7 @@ jobs: - test-mobile-e2e - test-libraries - test-design-system - - test-web-tools + - build-web-tools - test-cli runs-on: ubuntu-22.04 if: always() && !cancelled() diff --git a/.github/workflows/build-desktop-external-reusable.yml b/.github/workflows/build-desktop-external-reusable.yml index b3f309401999..2b586ce2aa1b 100644 --- a/.github/workflows/build-desktop-external-reusable.yml +++ b/.github/workflows/build-desktop-external-reusable.yml @@ -62,10 +62,11 @@ jobs: with: ruby-version: 3.3.0 bundler-cache: true - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: - upgrade_npm: ${{ matrix.config.name == 'win' }} + install-proto: true - name: Build desktop uses: LedgerHQ/ledger-live/tools/actions/composites/setup-build-desktop@develop id: build-desktop diff --git a/.github/workflows/build-desktop-reusable.yml b/.github/workflows/build-desktop-reusable.yml index 1940a191c2ff..8057033af4f9 100644 --- a/.github/workflows/build-desktop-reusable.yml +++ b/.github/workflows/build-desktop-reusable.yml @@ -54,27 +54,15 @@ jobs: - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - - name: Setup the toolchain - id: toolchain - if: ${{ matrix.config.name != 'linux' }} - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop - with: - accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} - roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} - region: ${{ secrets.AWS_CACHE_REGION }} - install-dotnet: ${{ matrix.config.dotnet }} - skip-turbo-cache: "false" - turbo-server-token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} - - name: Setup the caches - id: caches - if: ${{ matrix.config.name == 'linux' }} uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: ${{ matrix.config.name != 'linux' }} # ledger-live-4xlarge has proto pre-installed + skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} - skip-turbo-cache: "false" turbo-server-token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} - name: Build desktop @@ -85,7 +73,7 @@ jobs: - name: Build the app id: build-app - run: pnpm build:lld --api="http://127.0.0.1:${{ matrix.config.os == 'linux' && steps.caches.outputs.port || steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm build:lld --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" env: GENERATE_METAFILES: 1 diff --git a/.github/workflows/build-mobile-external-reusable.yml b/.github/workflows/build-mobile-external-reusable.yml index 944a8486575c..3e80e5d8054a 100644 --- a/.github/workflows/build-mobile-external-reusable.yml +++ b/.github/workflows/build-mobile-external-reusable.yml @@ -33,8 +33,11 @@ jobs: persist-credentials: false - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches + with: + install-proto: true - uses: ruby/setup-ruby@v1 with: ruby-version: 3.3.0 @@ -95,8 +98,11 @@ jobs: persist-credentials: false - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches + with: + install-proto: true - uses: ruby/setup-ruby@v1 with: ruby-version: 3.3.0 diff --git a/.github/workflows/build-mobile-reusable.yml b/.github/workflows/build-mobile-reusable.yml index 8b45a0c2d71b..0e569012edb9 100644 --- a/.github/workflows/build-mobile-reusable.yml +++ b/.github/workflows/build-mobile-reusable.yml @@ -92,9 +92,9 @@ jobs: ref: ${{ inputs.ref || github.sha }} - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - - name: Setup the toolchain + - name: Setup the caches uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop - id: caches + id: setup-caches with: accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} @@ -111,7 +111,7 @@ jobs: new_command_on_retry: rm -rf ~/.cocoapods/ && pnpm clean && pnpm i --filter="live-mobile..." --filter="ledger-live" --no-frozen-lockfile --unsafe-perm - name: bundle ios and android js run: | - pnpm build:llm:deps --api="http://127.0.0.1:${{ steps.caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + pnpm build:llm:deps --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" pnpm mobile bundle:ios:prod pnpm mobile bundle:android:prod pnpm mobile gen-metafile diff --git a/.github/workflows/test-web-tools-reusable.yml b/.github/workflows/build-web-tools-reusable.yml similarity index 81% rename from .github/workflows/test-web-tools-reusable.yml rename to .github/workflows/build-web-tools-reusable.yml index a092952082f2..fc92c3c04185 100644 --- a/.github/workflows/test-web-tools-reusable.yml +++ b/.github/workflows/build-web-tools-reusable.yml @@ -1,4 +1,4 @@ -name: "Web Tools Tests" +name: "Build Web Tools" on: workflow_call: @@ -16,8 +16,8 @@ permissions: contents: read jobs: - test-web-tools: - name: "Test web-tools" + build-web-tools: + name: "Build web-tools" env: NODE_OPTIONS: "--max-old-space-size=7168" FORCE_COLOR: 3 @@ -26,10 +26,11 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref || github.sha }} - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop - id: toolchain + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} @@ -38,10 +39,10 @@ jobs: - name: Install dependencies run: pnpm i -F "web-tools..." -F "ledger-live" - name: build web-tools - run: pnpm turbo run build --filter="@ledgerhq/web-tools" --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm turbo run build --filter="@ledgerhq/web-tools" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" report: - needs: test-web-tools + needs: build-web-tools if: ${{ !cancelled() && github.event_name == 'workflow_dispatch' }} runs-on: ubuntu-22.04 steps: @@ -57,15 +58,15 @@ jobs: const fs = require("fs"); const statuses = { tool: { - pass: ${{ needs.test-web-tools.result == 'success' }}, - status: "${{ needs.test-web-tools.result }}", + pass: ${{ needs.build-web-tools.result == 'success' }}, + status: "${{ needs.build-web-tools.result }}", } }; const summary = `### Common Tools - ${statuses.tool.pass ? "Common Tools are fine" : "Common Tools tests failed"} - - ${statuses.tool.pass ? "✅" : "❌"} **Common Tools* tests* ended with status \`${statuses.tool.status}\` + ${statuses.tool.pass ? "Common Tools are fine" : "Common Tools build failed"} + - ${statuses.tool.pass ? "✅" : "❌"} **Common Tools* build* ended with status \`${statuses.tool.status}\` `; const actions = []; diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 314c86f11a06..26f0db66531a 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -31,9 +31,12 @@ jobs: with: ref: ${{ inputs.ref }} fetch-depth: 0 - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true + skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} diff --git a/.github/workflows/regen-doc.yml b/.github/workflows/regen-doc.yml index ed1b4b1194b5..59d8ab6a57c5 100644 --- a/.github/workflows/regen-doc.yml +++ b/.github/workflows/regen-doc.yml @@ -52,19 +52,19 @@ jobs: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop - id: toolchain + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} turbo-server-token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} - skip-turbo-cache: "false" - name: Install dependencies run: pnpm i --filter="!./apps/**" - name: run doc - run: pnpm doc:ljs --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm doc:ljs --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" - name: status id: check-status run: echo "status=$(git status --porcelain | wc -l)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/regen-pods.yml b/.github/workflows/regen-pods.yml index 0e1619dfe95c..cb9e910b1ae2 100644 --- a/.github/workflows/regen-pods.yml +++ b/.github/workflows/regen-pods.yml @@ -55,10 +55,11 @@ jobs: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - - name: Setup the toolchain - id: toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} diff --git a/.github/workflows/release-create-hotfix.yml b/.github/workflows/release-create-hotfix.yml index 4484100be617..9ccc6bc55711 100644 --- a/.github/workflows/release-create-hotfix.yml +++ b/.github/workflows/release-create-hotfix.yml @@ -1,6 +1,18 @@ name: "[Release](Hotfix) Create Branch" on: workflow_dispatch: + inputs: + tag_version: + description: the tag/release version to hotfix + default: latest + required: false + application: + description: application (LLM | LLD) + required: true + type: choice + options: + - LLM + - LLD jobs: create-hotfix: @@ -15,17 +27,35 @@ jobs: with: app_id: ${{ secrets.GH_BOT_APP_ID }} private_key: ${{ secrets.GH_BOT_PRIVATE_KEY }} + + - name: Checkout composite actions + uses: actions/checkout@v4 + with: + ref: develop + sparse-checkout: tools/actions/composites + + - name: Generate ref/tag version to use during main checkout + uses: LedgerHQ/ledger-live/tools/actions/composites/generate-tag@develop + id: format-app-tag + with: + tag_version: ${{ github.event.inputs.tag_version }} + application: ${{ github.event.inputs.application }} + - uses: actions/checkout@v4 with: - ref: main + ref: ${{ steps.format-app-tag.outputs.main_ref }} token: ${{ steps.generate-token.outputs.token }} + - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - name: create hotfix branch run: | git checkout -b hotfix - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches + with: + install-proto: true - name: install dependencies run: pnpm i -F "ledger-live" - name: Move minor updates to patch for hotfix branch @@ -58,6 +88,10 @@ jobs: - name: push run: | git push origin hotfix - gh pr create --title ":fire: Hotfix ${{ steps.date.outputs.date }}" -F ./.github/templates/hotfix.md --base main --head hotfix + gh pr create \ + --title ":fire: Hotfix ${{ steps.date.outputs.date }} (targeting ${{ github.event.inputs.application }} ${{ github.event.inputs.tag_version }})"\ + -F ./.github/templates/hotfix.md \ + --base main \ + --head hotfix env: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} diff --git a/.github/workflows/release-create.yml b/.github/workflows/release-create.yml index ef912273256d..c59b3e3acee2 100644 --- a/.github/workflows/release-create.yml +++ b/.github/workflows/release-create.yml @@ -26,8 +26,11 @@ jobs: - name: create release branch run: | git checkout -b $RELEASE_BRANCH - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches + with: + install-proto: true - name: install dependencies run: pnpm i - name: Build libs diff --git a/.github/workflows/release-final-nightly.yml b/.github/workflows/release-final-nightly.yml index a69bc6dc46ff..d0d974c72b26 100644 --- a/.github/workflows/release-final-nightly.yml +++ b/.github/workflows/release-final-nightly.yml @@ -29,8 +29,12 @@ jobs: - name: merge develop run: | git merge origin/develop -X theirs - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches + with: + install-proto: true + skip-turbo-cache: "false" - uses: ruby/setup-ruby@v1 with: ruby-version: 3.3.0 @@ -56,6 +60,10 @@ jobs: run: | git add . git commit -m "chore(nightly): :rocket: nightly release" + - name: authenticate with npm + uses: actions/setup-node@v4 + with: + registry-url: "https://registry.npmjs.org" - name: publish nightly run: pnpm changeset publish --no-git-tag env: diff --git a/.github/workflows/release-final.yml b/.github/workflows/release-final.yml index 42a1275c2290..e9ac0fe15c25 100644 --- a/.github/workflows/release-final.yml +++ b/.github/workflows/release-final.yml @@ -12,6 +12,10 @@ on: - LLD - LLM - ALL + ref: + description: "the ref (branch) to release from" + required: false + default: main workflow_run: workflows: @@ -35,13 +39,16 @@ jobs: private_key: ${{ secrets.GH_BOT_PRIVATE_KEY }} - uses: actions/checkout@v4 with: - ref: main + ref: ${{ inputs.ref }} fetch-depth: 2 token: ${{ steps.generate-token.outputs.token }} - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches + with: + install-proto: true - uses: ruby/setup-ruby@v1 with: ruby-version: 3.3.0 @@ -57,6 +64,10 @@ jobs: run: pnpm i -F "ledger-live" -F "{libs/**}..." -F "@ledgerhq/live-cli" - name: build libs run: pnpm run build:libs + - name: authenticate with npm + uses: actions/setup-node@v4 + with: + registry-url: "https://registry.npmjs.org" - name: publish release run: pnpm changeset publish env: @@ -107,7 +118,7 @@ jobs: git tag live-mobile@${{ steps.mobile-version.outputs.version }} - name: push changes run: | - git push origin main --tags + git push origin ${{ inputs.ref }} --tags - name: create desktop github release if: ${{ steps.desktop-changed.outputs.status != 0 || github.event_name == 'workflow_dispatch' && contains(fromJson('["LLD", "ALL"]'), inputs.app) }} env: @@ -132,7 +143,7 @@ jobs: ref: "main", workflow_id: "release-desktop.yml", inputs: { - branch: "main" + branch: ${{ inputs.ref }} } }); - uses: actions/github-script@v7 @@ -147,6 +158,6 @@ jobs: ref: "main", workflow_id: "release-mobile.yml", inputs: { - ref: "main" + ref: ${{ inputs.ref }} } }); diff --git a/.github/workflows/release-prepare-hotfix.yml b/.github/workflows/release-prepare-hotfix.yml index 4aeb0bbf1821..8f3bd97271a8 100644 --- a/.github/workflows/release-prepare-hotfix.yml +++ b/.github/workflows/release-prepare-hotfix.yml @@ -7,6 +7,17 @@ on: description: the branch to release from default: hotfix required: true + tag_version: + description: version to hotfix (e.g. 2.91.0) + default: latest + required: false + application: + description: application (LLM | LLD) + required: true + type: choice + options: + - LLM + - LLD jobs: prepare-release: @@ -21,6 +32,19 @@ jobs: with: app_id: ${{ secrets.GH_BOT_APP_ID }} private_key: ${{ secrets.GH_BOT_PRIVATE_KEY }} + + - name: Checkout composite actions + uses: actions/checkout@v4 + with: + sparse-checkout: tools/actions/composites + + - name: Generate ref/tag version to use when running changeset status + uses: LedgerHQ/ledger-live/tools/actions/composites/generate-tag@develop + id: format-app-tag + with: + tag_version: ${{ github.event.inputs.tag_version }} + application: ${{ github.event.inputs.application }} + - name: Checkout Repo uses: actions/checkout@v4 with: @@ -30,8 +54,11 @@ jobs: - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches + with: + install-proto: true - name: install dependencies run: pnpm i -F "ledger-live" @@ -52,19 +79,21 @@ jobs: - name: push changes run: | git push origin ${{ inputs.ref }} - git fetch origin - name: fetch develop and main + if: ${{ github.event.inputs.tag_version == 'latest' }} run: | git fetch origin develop main - name: merge into main + if: ${{ github.event.inputs.tag_version == 'latest' }} run: | git checkout main git merge ${{ inputs.ref }} --no-ff git push origin main - name: create PR to develop + if: ${{ github.event.inputs.tag_version == 'latest' }} env: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} run: | @@ -74,6 +103,7 @@ jobs: gh pr create --title ":rotating_light: Hotfix merge conflicts" -F .github/templates/hotfix-conflicts.md --base develop --head support/hotfix-merge-conflicts - name: merge into release if present + if: ${{ github.event.inputs.tag_version == 'latest' }} env: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} run: | diff --git a/.github/workflows/release-prepare.yml b/.github/workflows/release-prepare.yml index 15feff24537f..47d5e484166e 100644 --- a/.github/workflows/release-prepare.yml +++ b/.github/workflows/release-prepare.yml @@ -30,8 +30,11 @@ jobs: - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches + with: + install-proto: true - name: install dependencies run: pnpm i -F "ledger-live" diff --git a/.github/workflows/release-prerelease.yml b/.github/workflows/release-prerelease.yml index 67d23446d494..36f1ecf747f4 100644 --- a/.github/workflows/release-prerelease.yml +++ b/.github/workflows/release-prerelease.yml @@ -32,11 +32,13 @@ jobs: with: ref: ${{ inputs.ref }} token: ${{ steps.generate-token.outputs.token }} - - name: Setup git user uses: LedgerHQ/ledger-live/tools/actions/composites/setup-git-user@develop - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches + with: + install-proto: true - uses: LedgerHQ/ledger-live/tools/actions/get-package-infos@develop id: desktop-version with: @@ -109,6 +111,10 @@ jobs: git add . git commit -m "chore(prerelease): :rocket: ${{ inputs.ref }} prerelease [LLD(${{ steps.post-desktop-version.outputs.version }}), LLM(${{ steps.post-mobile-version.outputs.version }})]" || echo "" + - name: authenticate with npm + uses: actions/setup-node@v4 + with: + registry-url: "https://registry.npmjs.org" - name: publish prerelease run: pnpm changeset publish --no-git-tag env: diff --git a/.github/workflows/test-bridge-pr.yml b/.github/workflows/test-bridge-pr.yml index 4057851a7bd7..e0006106673a 100644 --- a/.github/workflows/test-bridge-pr.yml +++ b/.github/workflows/test-bridge-pr.yml @@ -53,10 +53,11 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop - id: toolchain + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} @@ -69,7 +70,7 @@ jobs: - name: Install dependencies run: pnpm i --filter="live-common..." --filter="ledger-live" - name: Build - run: pnpm build:llc --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm build:llc --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" - name: Test shell: bash env: diff --git a/.github/workflows/test-cli-reusable.yml b/.github/workflows/test-cli-reusable.yml index 6b1b744691f9..38ea03d62ffc 100644 --- a/.github/workflows/test-cli-reusable.yml +++ b/.github/workflows/test-cli-reusable.yml @@ -29,26 +29,27 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref || github.sha }} - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop - id: toolchain + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true + skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} turbo-server-token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} - skip-turbo-cache: "false" - name: Install dependencies run: pnpm i -F "live-cli*..." -F "ledger-live" - name: build cli - run: pnpm build:cli --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm build:cli --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" - name: lint cli - run: pnpm lint --filter="@ledgerhq/live-cli" --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" -- --quiet + run: pnpm lint --filter="@ledgerhq/live-cli" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" -- --quiet - name: typecheck cli - run: pnpm typecheck --filter="@ledgerhq/live-cli" --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm typecheck --filter="@ledgerhq/live-cli" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" - name: test cli id: test - run: pnpm run test --filter="@ledgerhq/live-cli" --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm run test --filter="@ledgerhq/live-cli" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" - name: get diff id: diff run: | diff --git a/.github/workflows/test-design-system-reusable.yml b/.github/workflows/test-design-system-reusable.yml index 793cde1ef176..60ece428cd09 100644 --- a/.github/workflows/test-design-system-reusable.yml +++ b/.github/workflows/test-design-system-reusable.yml @@ -43,10 +43,11 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref || github.sha }} - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop - id: toolchain + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} @@ -56,7 +57,7 @@ jobs: run: pnpm i --filter="./libs/ui/**" - name: Build and Test affected libraries id: test-ui - run: pnpm run test --continue --filter="./libs/ui/**" --filter="!./apps/ledger-live*...[${{ inputs.since_branch && format('origin/{0}', inputs.since_branch) || 'HEAD^1' }}]" --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm run test --continue --filter="./libs/ui/**" --filter="!./apps/ledger-live*...[${{ inputs.since_branch && format('origin/{0}', inputs.since_branch) || 'HEAD^1' }}]" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" shell: bash - name: (On Failure) Upload react-ui test results uses: actions/upload-artifact@v4 diff --git a/.github/workflows/test-desktop-external-reusable.yml b/.github/workflows/test-desktop-external-reusable.yml index e4f7ff0e1525..89a605f43e5f 100644 --- a/.github/workflows/test-desktop-external-reusable.yml +++ b/.github/workflows/test-desktop-external-reusable.yml @@ -34,10 +34,11 @@ jobs: repository: ${{ inputs.repository }} token: ${{ secrets.GITHUB_TOKEN }} persist-credentials: false - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: - install-dotnet: true + install-proto: true - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-test-desktop@develop id: setup-test-desktop with: @@ -72,8 +73,11 @@ jobs: repository: ${{ inputs.repository }} token: ${{ secrets.GITHUB_TOKEN }} persist-credentials: false - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches + with: + install-proto: true - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-test-desktop@develop id: setup-test-desktop with: @@ -100,13 +104,11 @@ jobs: repository: ${{ inputs.repository }} token: ${{ secrets.GITHUB_TOKEN }} persist-credentials: false - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: - accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} - roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} - region: ${{ secrets.AWS_CACHE_REGION }} - turbo-server-token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} + install-proto: true - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-test-desktop@develop id: setup-test-desktop with: diff --git a/.github/workflows/test-desktop-reusable.yml b/.github/workflows/test-desktop-reusable.yml index bddb54e0ddee..799e65248cb9 100644 --- a/.github/workflows/test-desktop-reusable.yml +++ b/.github/workflows/test-desktop-reusable.yml @@ -40,11 +40,11 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref || github.sha }} - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop - id: toolchain + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: - install-dotnet: true + install-proto: true skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} @@ -54,9 +54,9 @@ jobs: id: setup-test-desktop with: skip_builds: true - turborepo-server-port: ${{ steps.toolchain.outputs.port }} + turborepo-server-port: ${{ steps.setup-caches.outputs.port }} - name: lint - run: pnpm desktop lint:ci -p ${{ steps.toolchain.outputs.port }} -t "${{ secrets.TURBOREPO_SERVER_TOKEN }}" + run: pnpm desktop lint:ci -p ${{ steps.setup-caches.outputs.port }} -t "${{ secrets.TURBOREPO_SERVER_TOKEN }}" - name: prettier run: pnpm desktop prettier:check - name: typecheck @@ -82,10 +82,11 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref || github.sha }} - - name: Setup the toolchain - id: toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} @@ -95,7 +96,7 @@ jobs: id: setup-test-desktop with: skip_builds: true - turborepo-server-port: ${{ steps.toolchain.outputs.port }} + turborepo-server-port: ${{ steps.setup-caches.outputs.port }} - name: Run unit tests run: pnpm desktop test:jest:coverage diff --git a/.github/workflows/test-integration-pr.yml b/.github/workflows/test-integration-pr.yml index 2f3d2069e002..310a47777130 100644 --- a/.github/workflows/test-integration-pr.yml +++ b/.github/workflows/test-integration-pr.yml @@ -55,12 +55,12 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop - id: toolchain + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true skip-turbo-cache: "false" - upgrade_npm: ${{ matrix.os == 'windows-2022' }} accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} @@ -72,7 +72,7 @@ jobs: - name: Install dependencies run: pnpm i --filter="live-common..." --filter="ledger-live" - name: Build - run: pnpm build:llc --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm build:llc --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" - name: Test shell: bash env: diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index 9922a675428e..20ab1e21ad10 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -40,12 +40,12 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref || github.sha }} - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop - id: toolchain + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true skip-turbo-cache: "false" - upgrade_npm: ${{ matrix.os == 'windows-2022' }} accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} @@ -57,7 +57,7 @@ jobs: - name: Install dependencies run: pnpm i --filter="live-common..." --filter="ledger-live" - name: Build - run: pnpm build:llc --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm build:llc --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" - name: Test shell: bash env: diff --git a/.github/workflows/test-libs-reusable.yml b/.github/workflows/test-libs-reusable.yml index e9787bdb296c..ff42e106611a 100644 --- a/.github/workflows/test-libs-reusable.yml +++ b/.github/workflows/test-libs-reusable.yml @@ -34,7 +34,7 @@ jobs: ref: ${{ inputs.ref || github.sha }} - name: Setup the caches uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop - id: cache + id: setup-caches with: skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} @@ -45,7 +45,7 @@ jobs: run: pnpm i --filter="!./apps/**" - name: Build and Test affected libraries id: test-libs - run: pnpm run test --continue --filter="!./apps/**" --filter="!./libs/ui/**" --filter="!./tools/**" --filter="!./apps/ledger-live*...[${{ inputs.since_branch && format('origin/{0}', inputs.since_branch) || 'HEAD^1' }}]" --api="http://127.0.0.1:${{ steps.cache.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm run test --continue --filter="!./apps/**" --filter="!./libs/ui/**" --filter="!./tools/**" --filter="!./apps/ledger-live*...[${{ inputs.since_branch && format('origin/{0}', inputs.since_branch) || 'HEAD^1' }}]" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" shell: bash - name: (On Failure) Upload live-common snapshots and source uses: actions/upload-artifact@v4 @@ -79,26 +79,27 @@ jobs: with: ref: ${{ inputs.ref || github.sha }} fetch-depth: 2 - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop - id: toolchain + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true + skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} turbo-server-token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} - skip-turbo-cache: "false" - name: Install dependencies run: pnpm i --filter="!./apps/**" - name: Lint affected libraries id: lint-libs - run: pnpm lint --continue --filter="!./apps/**" --filter="!./tools/**" --filter="!ledger-live*...[${{ inputs.since_branch && format('origin/{0}', inputs.since_branch) || 'HEAD^1' }}]" --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" -- --quiet + run: pnpm lint --continue --filter="!./apps/**" --filter="!./tools/**" --filter="!ledger-live*...[${{ inputs.since_branch && format('origin/{0}', inputs.since_branch) || 'HEAD^1' }}]" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" -- --quiet - name: Typecheck affected libraries id: typecheck-libs - run: pnpm typecheck --continue --filter="!./apps/**" --filter="!./tools/**" --filter="!ledger-live*...[${{ inputs.since_branch && format('origin/{0}', inputs.since_branch) || 'HEAD^1' }}]" --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm typecheck --continue --filter="!./apps/**" --filter="!./tools/**" --filter="!ledger-live*...[${{ inputs.since_branch && format('origin/{0}', inputs.since_branch) || 'HEAD^1' }}]" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" - name: Test unimported files id: unimported - run: pnpm unimported --continue --filter="!./apps/**" --filter="!./tools/**" --filter="!ledger-live*...[${{ inputs.since_branch && format('origin/{0}', inputs.since_branch) || 'HEAD^1' }}]" --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm unimported --continue --filter="!./apps/**" --filter="!./tools/**" --filter="!ledger-live*...[${{ inputs.since_branch && format('origin/{0}', inputs.since_branch) || 'HEAD^1' }}]" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" shell: bash - uses: actions/github-script@v6 if: ${{ !cancelled() }} @@ -124,19 +125,20 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref || github.sha }} - - name: Setup the toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop - id: toolchain + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true + skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} region: ${{ secrets.AWS_CACHE_REGION }} turbo-server-token: ${{ secrets.TURBOREPO_SERVER_TOKEN }} - skip-turbo-cache: "false" - name: Install dependencies run: pnpm i --filter="!./apps/**" - name: run doc - run: pnpm doc:ljs --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm doc:ljs --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" - name: get diff id: diff run: | diff --git a/.github/workflows/test-mobile-e2e-reusable.yml b/.github/workflows/test-mobile-e2e-reusable.yml index c6c192311443..01f93938de98 100644 --- a/.github/workflows/test-mobile-e2e-reusable.yml +++ b/.github/workflows/test-mobile-e2e-reusable.yml @@ -202,10 +202,11 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref || github.sha }} - - name: Setup the toolchain - id: toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} @@ -237,10 +238,10 @@ jobs: pnpm i --filter="live-mobile..." --filter="ledger-live" --filter="@ledgerhq/dummy-*-app..." --no-frozen-lockfile --unsafe-perm - name: Build dependencies run: | - pnpm build:llm:deps --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + pnpm build:llm:deps --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" - name: Build Dummy Live SDK and Dummy Wallet API apps for testing run: | - pnpm build:dummy-apps --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + pnpm build:dummy-apps --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" shell: bash - name: Build Android app for Detox test run run: | diff --git a/.github/workflows/test-mobile-reusable.yml b/.github/workflows/test-mobile-reusable.yml index db126e93fb13..7af9ec466441 100644 --- a/.github/workflows/test-mobile-reusable.yml +++ b/.github/workflows/test-mobile-reusable.yml @@ -36,10 +36,11 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref || github.sha }} - - name: Setup the toolchain - id: toolchain - uses: LedgerHQ/ledger-live/tools/actions/composites/setup-toolchain@develop + - name: Setup the caches + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop + id: setup-caches with: + install-proto: true skip-turbo-cache: "false" accountId: ${{ secrets.AWS_ACCOUNT_ID_PROD }} roleName: ${{ secrets.AWS_CACHE_ROLE_NAME }} @@ -51,12 +52,12 @@ jobs: - name: Install dependencies run: pnpm i --filter="live-mobile..." --filter="ledger-live" --no-frozen-lockfile --unsafe-perm - name: Run linter - run: pnpm lint --filter="live-mobile" --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" -- --format="json" -o="lint-mobile.json" + run: pnpm lint --filter="live-mobile" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" -- --format="json" -o="lint-mobile.json" - name: check for dead code run: pnpm mobile knip-check shell: bash - name: Run code checkers - run: pnpm typecheck --filter="live-mobile" --api="http://127.0.0.1:${{ steps.toolchain.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" + run: pnpm typecheck --filter="live-mobile" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo" - name: Run unit tests run: pnpm mobile test - uses: actions/upload-artifact@v4 diff --git a/.pnpmfile.cjs b/.pnpmfile.cjs index 2ae98589f2d5..2c92ace5264d 100644 --- a/.pnpmfile.cjs +++ b/.pnpmfile.cjs @@ -63,17 +63,8 @@ function readPackage(pkg, context) { webpack: "*", }), /* @celo/* packages */ - addDependencies(/@celo\/(?!base)+/, { "@celo/base": `^${pkg.version}` }), addDependencies("@celo/connect", { - "@celo/base": `^${pkg.version}`, - "web3-eth-contract": pkg.peerDependencies?.web3 ?? "*", - }), - addDependencies("@celo/contractkit", { - "web3-utils": pkg.dependencies?.["web3"], - }), - addDependencies("@celo/utils", { - "fp-ts": "*", - rlp: "*", + "web3": pkg.peerDependencies?.web3 ?? "1.10", }), /* @cosmjs/* packages */ addDependencies("@cosmjs/proto-signing", { diff --git a/CODEOWNERS b/CODEOWNERS index 6cb15f36c30e..464730176527 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -43,39 +43,40 @@ libs/ledgerjs/packages/hw-app-*/ @ledgerhq/live-blockcha libs/ledgerjs/packages/types-cryptoassets/ @ledgerhq/live-blockchain-support libs/live-config/ @ledgerhq/live-blockchain-support libs/live-network/ @ledgerhq/live-blockchain-support +libs/live-services/ @ledgerhq/live-blockchain-support # PTX team -apps/cli/src/commands/ptx @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/components/ProviderIcon/ @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/components/WebPTXPlayer/ @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/hooks/swap-migrations/ @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/drawers/SwapOperationDetails/ @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/modals/Platform/ @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/modals/StartStake/ @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/reducers/swap.ts @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/screens/earn/ @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/screens/exchange/ @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/screens/stake/ @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/screens/swapWeb/ @ledgerhq/ptx -apps/ledger-live-desktop/src/renderer/families/evm/StakeFlowModal @ledgerhq/ptx +apps/cli/src/commands/ptx @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/components/ProviderIcon/ @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/components/WebPTXPlayer/ @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/hooks/swap-migrations/ @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/drawers/SwapOperationDetails/ @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/modals/Platform/ @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/modals/StartStake/ @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/reducers/swap.ts @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/screens/earn/ @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/screens/exchange/ @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/screens/stake/ @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/screens/swapWeb/ @ledgerhq/ptx +apps/ledger-live-desktop/src/renderer/families/evm/StakeFlowModal @ledgerhq/ptx apps/ledger-live-desktop/src/renderer/families/evm/StakeFlowModal_deprecated @ledgerhq/ptx -apps/ledger-live-mobile/src/families/evm/StakingDrawer/ @ledgerhq/ptx -apps/ledger-live-mobile/src/families/evm/StakingDrawer_deprecated/ @ledgerhq/ptx -apps/ledger-live-mobile/src/actions/earn.ts @ledgerhq/ptx -apps/ledger-live-mobile/src/actions/swap.ts @ledgerhq/ptx -apps/ledger-live-mobile/src/components/ProviderIcon/ @ledgerhq/ptx -apps/ledger-live-mobile/src/components/Stake/ @ledgerhq/ptx -apps/ledger-live-mobile/src/components/WebPTXPlayer/ @ledgerhq/ptx -apps/ledger-live-mobile/src/reducers/earn.ts @ledgerhq/ptx -apps/ledger-live-mobile/src/reducers/swap.ts @ledgerhq/ptx -apps/ledger-live-mobile/src/screens/Exchange/ @ledgerhq/ptx -apps/ledger-live-mobile/src/screens/PTX/ @ledgerhq/ptx -apps/ledger-live-mobile/src/screens/Swap/ @ledgerhq/ptx -libs/ledger-live-common/src/exchange/ @ledgerhq/ptx -libs/exchange-module/ @ledgerhq/ptx -libs/wallet-api-acre-module/ @ledgerhq/ptx -libs/ledgerjs/packages/hw-app-exchange/ @ledgerhq/ptx -libs/ledger-live-common/src/cal/partners*.ts @ledgerhq/ptx +apps/ledger-live-mobile/src/families/evm/StakingDrawer/ @ledgerhq/ptx +apps/ledger-live-mobile/src/families/evm/StakingDrawer_deprecated/ @ledgerhq/ptx +apps/ledger-live-mobile/src/actions/earn.ts @ledgerhq/ptx +apps/ledger-live-mobile/src/actions/swap.ts @ledgerhq/ptx +apps/ledger-live-mobile/src/components/ProviderIcon/ @ledgerhq/ptx +apps/ledger-live-mobile/src/components/Stake/ @ledgerhq/ptx +apps/ledger-live-mobile/src/components/WebPTXPlayer/ @ledgerhq/ptx +apps/ledger-live-mobile/src/reducers/earn.ts @ledgerhq/ptx +apps/ledger-live-mobile/src/reducers/swap.ts @ledgerhq/ptx +apps/ledger-live-mobile/src/screens/Exchange/ @ledgerhq/ptx +apps/ledger-live-mobile/src/screens/PTX/ @ledgerhq/ptx +apps/ledger-live-mobile/src/screens/Swap/ @ledgerhq/ptx +libs/ledger-live-common/src/exchange/ @ledgerhq/ptx +libs/exchange-module/ @ledgerhq/ptx +libs/wallet-api-acre-module/ @ledgerhq/ptx +libs/ledgerjs/packages/hw-app-exchange/ @ledgerhq/ptx +libs/live-services/cal/src/partners/ @ledgerhq/ptx # Wallet API team @@ -91,7 +92,7 @@ libs/ledger-live-common/src/wallet-api/ @ledgerhq/wallet-api **/platformAdapter.ts @ledgerhq/wallet-api **/walletApiAdapter.ts @ledgerhq/wallet-api **/liveapp-sdk.spec.ts @ledgerhq/wallet-api -**/confirmTransaction.spec.ts @ledgerhq/wallet-api +**/confirmTransaction.spec.ts @ledgerhq/wallet-api **/wallet-api.spec.ts @ledgerhq/wallet-api **/wallet-api.spec.ts-snapshots/ @ledgerhq/wallet-api **/dapp.spec.ts @ledgerhq/wallet-api @@ -123,6 +124,7 @@ libs/ledger-live-common/src/device/ @ledgerhq/liv libs/ledger-live-common/src/deviceSDK/ @ledgerhq/live-devices libs/device-core/ @ledgerhq/live-devices libs/device-react/ @ledgerhq/live-devices +libs/live-dmk/ @ledgerhq/live-devices libs/speculos-transport/ @ledgerhq/live-devices @ledgerhq/qaa # Recover team diff --git a/apps/cli/CHANGELOG.md b/apps/cli/CHANGELOG.md index 75d38a248ed2..2e4ac50555a4 100644 --- a/apps/cli/CHANGELOG.md +++ b/apps/cli/CHANGELOG.md @@ -1,5 +1,57 @@ # @ledgerhq/live-cli +## 24.8.3 + +### Patch Changes + +- Updated dependencies [[`93f8f78`](https://github.com/LedgerHQ/ledger-live/commit/93f8f7885d1300208310599e743a4d1fae4ec2a4), [`40f1cd4`](https://github.com/LedgerHQ/ledger-live/commit/40f1cd4c22d17480dcf86c73e90a07866667b0ba), [`c45ee45`](https://github.com/LedgerHQ/ledger-live/commit/c45ee457a9f5500ae42f2a8fb7f0cfb7926f319b), [`1a388b9`](https://github.com/LedgerHQ/ledger-live/commit/1a388b946ce309c0a0e6e0c50b28af4e3c3a2cdb), [`995b771`](https://github.com/LedgerHQ/ledger-live/commit/995b771671b23931c6a85534841e8d88ca2acaf4), [`475b74c`](https://github.com/LedgerHQ/ledger-live/commit/475b74c1ba01b7e7a374cca14e274769a3c17476), [`faef7ed`](https://github.com/LedgerHQ/ledger-live/commit/faef7ed3b9954d2bbaf5c5a518e247fd441a73e7), [`16a4794`](https://github.com/LedgerHQ/ledger-live/commit/16a479420976c4c12fb8984dcba9cf572c576292), [`322fd58`](https://github.com/LedgerHQ/ledger-live/commit/322fd58ffcde6d592eb27af1fd93f8c45d33205c), [`2673c1d`](https://github.com/LedgerHQ/ledger-live/commit/2673c1d98788fafe7e95bd798be06a6b5e39e1c0), [`61aedb7`](https://github.com/LedgerHQ/ledger-live/commit/61aedb7bbd45e73d6bc2b53e55f562262d5c5fa7), [`224cc07`](https://github.com/LedgerHQ/ledger-live/commit/224cc07b86e8c5a6167ff77cfb99e42a1057813e), [`58beb75`](https://github.com/LedgerHQ/ledger-live/commit/58beb7504454b64cb5a955926ef27f811397aa6d)]: + - @ledgerhq/live-common@34.16.0 + - @ledgerhq/hw-app-btc@10.5.0 + - @ledgerhq/coin-framework@0.20.1 + - @ledgerhq/coin-bitcoin@0.8.10 + - @ledgerhq/device-core@0.4.9 + - @ledgerhq/live-countervalues@0.2.15 + - @ledgerhq/live-wallet@0.7.7 + +## 24.8.3-next.3 + +### Patch Changes + +- Updated dependencies [[`16a4794`](https://github.com/LedgerHQ/ledger-live/commit/16a479420976c4c12fb8984dcba9cf572c576292)]: + - @ledgerhq/live-common@34.16.0-next.3 + +## 24.8.3-next.2 + +### Patch Changes + +- Updated dependencies [[`61aedb7`](https://github.com/LedgerHQ/ledger-live/commit/61aedb7bbd45e73d6bc2b53e55f562262d5c5fa7)]: + - @ledgerhq/live-common@34.16.0-next.2 + - @ledgerhq/coin-framework@0.20.1-next.1 + - @ledgerhq/coin-bitcoin@0.8.10-next.1 + - @ledgerhq/device-core@0.4.9-next.1 + - @ledgerhq/live-countervalues@0.2.15-next.1 + - @ledgerhq/live-wallet@0.7.7-next.1 + +## 24.8.3-next.1 + +### Patch Changes + +- Updated dependencies []: + - @ledgerhq/live-common@34.16.0-next.1 + +## 24.8.3-next.0 + +### Patch Changes + +- Updated dependencies [[`93f8f78`](https://github.com/LedgerHQ/ledger-live/commit/93f8f7885d1300208310599e743a4d1fae4ec2a4), [`40f1cd4`](https://github.com/LedgerHQ/ledger-live/commit/40f1cd4c22d17480dcf86c73e90a07866667b0ba), [`c45ee45`](https://github.com/LedgerHQ/ledger-live/commit/c45ee457a9f5500ae42f2a8fb7f0cfb7926f319b), [`1a388b9`](https://github.com/LedgerHQ/ledger-live/commit/1a388b946ce309c0a0e6e0c50b28af4e3c3a2cdb), [`995b771`](https://github.com/LedgerHQ/ledger-live/commit/995b771671b23931c6a85534841e8d88ca2acaf4), [`475b74c`](https://github.com/LedgerHQ/ledger-live/commit/475b74c1ba01b7e7a374cca14e274769a3c17476), [`faef7ed`](https://github.com/LedgerHQ/ledger-live/commit/faef7ed3b9954d2bbaf5c5a518e247fd441a73e7), [`322fd58`](https://github.com/LedgerHQ/ledger-live/commit/322fd58ffcde6d592eb27af1fd93f8c45d33205c), [`2673c1d`](https://github.com/LedgerHQ/ledger-live/commit/2673c1d98788fafe7e95bd798be06a6b5e39e1c0), [`224cc07`](https://github.com/LedgerHQ/ledger-live/commit/224cc07b86e8c5a6167ff77cfb99e42a1057813e), [`58beb75`](https://github.com/LedgerHQ/ledger-live/commit/58beb7504454b64cb5a955926ef27f811397aa6d)]: + - @ledgerhq/live-common@34.16.0-next.0 + - @ledgerhq/hw-app-btc@10.5.0-next.0 + - @ledgerhq/coin-framework@0.20.1-next.0 + - @ledgerhq/coin-bitcoin@0.8.10-next.0 + - @ledgerhq/device-core@0.4.9-next.0 + - @ledgerhq/live-countervalues@0.2.15-next.0 + - @ledgerhq/live-wallet@0.7.7-next.0 + ## 24.8.2 ### Patch Changes diff --git a/apps/cli/package.json b/apps/cli/package.json index 3bc1f6e4e307..9b4a4481fb22 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,6 +1,6 @@ { "name": "@ledgerhq/live-cli", - "version": "24.8.2", + "version": "24.8.3", "description": "ledger-live CLI version", "repository": { "type": "git", @@ -76,6 +76,7 @@ "@types/command-line-args": "5.2.3", "@types/cors": "2.8.17", "@types/express": "4.17.21", + "@types/invariant": "2.2.37", "@types/lodash": "4.17.7", "@types/node": "20.12.12", "@types/pako": "2.0.3", diff --git a/apps/cli/src/live-common-setup.ts b/apps/cli/src/live-common-setup.ts index d4553dbfd0ec..02dc4dbb968a 100644 --- a/apps/cli/src/live-common-setup.ts +++ b/apps/cli/src/live-common-setup.ts @@ -64,8 +64,16 @@ registerTransportModule({ disconnect: () => Promise.resolve(), }); -if (process.env.DEVICE_PROXY_URL) { - const Tr = createTransportHttp(process.env.DEVICE_PROXY_URL.split("|")); +const { + SPECULOS_API_PORT, + SPECULOS_APDU_PORT, + SPECULOS_BUTTON_PORT, + SPECULOS_HOST, + DEVICE_PROXY_URL, +} = process.env; + +if (DEVICE_PROXY_URL) { + const Tr = createTransportHttp(DEVICE_PROXY_URL.split("|")); registerTransportModule({ id: "http", open: () => @@ -78,8 +86,6 @@ if (process.env.DEVICE_PROXY_URL) { }); } -const { SPECULOS_API_PORT, SPECULOS_APDU_PORT, SPECULOS_BUTTON_PORT, SPECULOS_HOST } = process.env; - if (SPECULOS_API_PORT) { registerSpeculosTransport(parseInt(SPECULOS_API_PORT, 10)); } else if (SPECULOS_APDU_PORT) { @@ -146,7 +152,7 @@ export function registerSpeculosTransport(apiPort: number) { LiveConfig.setConfig(liveConfig); -if (!process.env.CI && !SPECULOS_API_PORT) { +if (!process.env.CI && !SPECULOS_API_PORT && !DEVICE_PROXY_URL) { init(); } diff --git a/apps/ledger-live-desktop/CHANGELOG.md b/apps/ledger-live-desktop/CHANGELOG.md index f157f660376d..dde290710e9f 100644 --- a/apps/ledger-live-desktop/CHANGELOG.md +++ b/apps/ledger-live-desktop/CHANGELOG.md @@ -1,5 +1,209 @@ # ledger-live-desktop +## 2.94.0 + +### Minor Changes + +- [#8495](https://github.com/LedgerHQ/ledger-live/pull/8495) [`f0a34a0`](https://github.com/LedgerHQ/ledger-live/commit/f0a34a06461331ec44fa02b8093699fa001f94a0) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Rework Hiddencollections + +- [#8563](https://github.com/LedgerHQ/ledger-live/pull/8563) [`93f8f78`](https://github.com/LedgerHQ/ledger-live/commit/93f8f7885d1300208310599e743a4d1fae4ec2a4) Thanks [@Canestin](https://github.com/Canestin)! - add another ledger solana validator + +- [#8538](https://github.com/LedgerHQ/ledger-live/pull/8538) [`f6eefe9`](https://github.com/LedgerHQ/ledger-live/commit/f6eefe9f56c3eb5eb150a61b93d15d94bac1147a) Thanks [@sergiubreban](https://github.com/sergiubreban)! - enable /card deeplink + +- [#8550](https://github.com/LedgerHQ/ledger-live/pull/8550) [`40f1cd4`](https://github.com/LedgerHQ/ledger-live/commit/40f1cd4c22d17480dcf86c73e90a07866667b0ba) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Filter Currencies which are buyable/swappable in MarketWidget + +- [#8375](https://github.com/LedgerHQ/ledger-live/pull/8375) [`c45ee45`](https://github.com/LedgerHQ/ledger-live/commit/c45ee457a9f5500ae42f2a8fb7f0cfb7926f319b) Thanks [@Canestin](https://github.com/Canestin)! - add mev protection + +- [#8525](https://github.com/LedgerHQ/ledger-live/pull/8525) [`032a018`](https://github.com/LedgerHQ/ledger-live/commit/032a018e2410a4074c4d2075ce3bd205858732db) Thanks [@CremaFR](https://github.com/CremaFR)! - fix: default gas limit + +- [#8504](https://github.com/LedgerHQ/ledger-live/pull/8504) [`03c26f4`](https://github.com/LedgerHQ/ledger-live/commit/03c26f431c304075012cd40e4297a0f55b74276f) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Redirect Users to Corresponding Market Page When Clicking on Asset in Market Widget + +- [#8516](https://github.com/LedgerHQ/ledger-live/pull/8516) [`6d679f5`](https://github.com/LedgerHQ/ledger-live/commit/6d679f57ff33610cc660541711f857f6605f20d3) Thanks [@Couto](https://github.com/Couto)! - Ensure returnTo value is defined before tracking analytics + +- [#8586](https://github.com/LedgerHQ/ledger-live/pull/8586) [`87d298c`](https://github.com/LedgerHQ/ledger-live/commit/87d298cf99479ba1cab21665f5b1216dceba0da8) Thanks [@themooneer](https://github.com/themooneer)! - Add ICP memo field to first step of new memo flow , FF ON + +- [#8319](https://github.com/LedgerHQ/ledger-live/pull/8319) [`42e9d67`](https://github.com/LedgerHQ/ledger-live/commit/42e9d67cd5c99f10e6e760c6a657ca7a8e3d45fb) Thanks [@sergiubreban](https://github.com/sergiubreban)! - Handle close sidebar and notify widget app + +- [#8465](https://github.com/LedgerHQ/ledger-live/pull/8465) [`fc95133`](https://github.com/LedgerHQ/ledger-live/commit/fc9513365f85d80c4c0cfb6645c2d8ea86983a87) Thanks [@themooneer](https://github.com/themooneer)! - Make learn more cta dynamic per app name context + +- [#8523](https://github.com/LedgerHQ/ledger-live/pull/8523) [`90b2950`](https://github.com/LedgerHQ/ledger-live/commit/90b295032fed0420e44effc6446f8ca2e209c600) Thanks [@lpaquet-ledger](https://github.com/lpaquet-ledger)! - fix swap Id in history + +- [#8397](https://github.com/LedgerHQ/ledger-live/pull/8397) [`2a9e2de`](https://github.com/LedgerHQ/ledger-live/commit/2a9e2de3d14958123f702e4bde93eeb52967cddd) Thanks [@thesan](https://github.com/thesan)! - Re-implement the portfolio content cards with UI components + +- [#8514](https://github.com/LedgerHQ/ledger-live/pull/8514) [`b8b9f76`](https://github.com/LedgerHQ/ledger-live/commit/b8b9f767deea088ebf5cb7d976a1204f6c0d316f) Thanks [@ComradeAERGO](https://github.com/ComradeAERGO)! - Removed message fields for sign message modal for ACRE Withdrawals + +- [#8520](https://github.com/LedgerHQ/ledger-live/pull/8520) [`e341fa2`](https://github.com/LedgerHQ/ledger-live/commit/e341fa2888bfbbdd6588c8d62ee450b565acfacb) Thanks [@CremaFR](https://github.com/CremaFR)! - ui gas limit fixed for swap + +- [#8529](https://github.com/LedgerHQ/ledger-live/pull/8529) [`b8fdd1c`](https://github.com/LedgerHQ/ledger-live/commit/b8fdd1c32c46a9a3f10bc129f8ef66de3cda0b35) Thanks [@valpinkman](https://github.com/valpinkman)! - Fix IPC transport register + +- [#8511](https://github.com/LedgerHQ/ledger-live/pull/8511) [`73f65a7`](https://github.com/LedgerHQ/ledger-live/commit/73f65a7aa3e08565794471545b431b4278c954f8) Thanks [@adammino-ledger](https://github.com/adammino-ledger)! - Changed the Electron util that detects the locale for swapping Yield-Earn labels + +- [#8457](https://github.com/LedgerHQ/ledger-live/pull/8457) [`d45e871`](https://github.com/LedgerHQ/ledger-live/commit/d45e871ee6b7e98102a4ffbdf3d7581c8cf838d0) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Rework Hiddencollections + +- [#8596](https://github.com/LedgerHQ/ledger-live/pull/8596) [`40509e4`](https://github.com/LedgerHQ/ledger-live/commit/40509e4411af132a03e3d70f685dc8242c8d1031) Thanks [@Canestin](https://github.com/Canestin)! - fix: add mev protection on swap + +- [#8500](https://github.com/LedgerHQ/ledger-live/pull/8500) [`faef7ed`](https://github.com/LedgerHQ/ledger-live/commit/faef7ed3b9954d2bbaf5c5a518e247fd441a73e7) Thanks [@VicAlbr](https://github.com/VicAlbr)! - Fix Speculos CI + Update checks on receive and subAccount tests" + +- [#8503](https://github.com/LedgerHQ/ledger-live/pull/8503) [`322fd58`](https://github.com/LedgerHQ/ledger-live/commit/322fd58ffcde6d592eb27af1fd93f8c45d33205c) Thanks [@jiyuzhuang](https://github.com/jiyuzhuang)! - Remove `feature_recover_upsell_redirection` feature flag and unused components + +- [#8404](https://github.com/LedgerHQ/ledger-live/pull/8404) [`2901938`](https://github.com/LedgerHQ/ledger-live/commit/29019387955bbab5bc0adcd550bc9e32d08b4f72) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Fix undefined join on Spam filter + +- [#8540](https://github.com/LedgerHQ/ledger-live/pull/8540) [`aa7d44a`](https://github.com/LedgerHQ/ledger-live/commit/aa7d44a18b42d54c65585a6e6769571f51e5fd2f) Thanks [@valpinkman](https://github.com/valpinkman)! - Fix speculos transport + +- [#8601](https://github.com/LedgerHQ/ledger-live/pull/8601) [`61aedb7`](https://github.com/LedgerHQ/ledger-live/commit/61aedb7bbd45e73d6bc2b53e55f562262d5c5fa7) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Revery useNFTCOllections + +- [#8497](https://github.com/LedgerHQ/ledger-live/pull/8497) [`d7ae5ff`](https://github.com/LedgerHQ/ledger-live/commit/d7ae5ffc941dab74a5bcc6f52f8d2040e582757d) Thanks [@VicAlbr](https://github.com/VicAlbr)! - adding e2e test + +- [#8240](https://github.com/LedgerHQ/ledger-live/pull/8240) [`224cc07`](https://github.com/LedgerHQ/ledger-live/commit/224cc07b86e8c5a6167ff77cfb99e42a1057813e) Thanks [@Wozacosta](https://github.com/Wozacosta)! - chore: Upgrade @celo/\* dependencies for compatibility with Celo as Layer 2 + +- [#8524](https://github.com/LedgerHQ/ledger-live/pull/8524) [`8e11fb4`](https://github.com/LedgerHQ/ledger-live/commit/8e11fb49d5d3956230a004972e2b79a905b8a891) Thanks [@CremaFR](https://github.com/CremaFR)! - fix: stop saving fees when closing + +### Patch Changes + +- Updated dependencies [[`f0a34a0`](https://github.com/LedgerHQ/ledger-live/commit/f0a34a06461331ec44fa02b8093699fa001f94a0), [`93f8f78`](https://github.com/LedgerHQ/ledger-live/commit/93f8f7885d1300208310599e743a4d1fae4ec2a4), [`40f1cd4`](https://github.com/LedgerHQ/ledger-live/commit/40f1cd4c22d17480dcf86c73e90a07866667b0ba), [`c45ee45`](https://github.com/LedgerHQ/ledger-live/commit/c45ee457a9f5500ae42f2a8fb7f0cfb7926f319b), [`2a9e2de`](https://github.com/LedgerHQ/ledger-live/commit/2a9e2de3d14958123f702e4bde93eeb52967cddd), [`995b771`](https://github.com/LedgerHQ/ledger-live/commit/995b771671b23931c6a85534841e8d88ca2acaf4), [`e8fb7ec`](https://github.com/LedgerHQ/ledger-live/commit/e8fb7ec80f6c8f2eb813662f9e02bc1c2ebaf6a7), [`475b74c`](https://github.com/LedgerHQ/ledger-live/commit/475b74c1ba01b7e7a374cca14e274769a3c17476), [`d45e871`](https://github.com/LedgerHQ/ledger-live/commit/d45e871ee6b7e98102a4ffbdf3d7581c8cf838d0), [`faef7ed`](https://github.com/LedgerHQ/ledger-live/commit/faef7ed3b9954d2bbaf5c5a518e247fd441a73e7), [`16a4794`](https://github.com/LedgerHQ/ledger-live/commit/16a479420976c4c12fb8984dcba9cf572c576292), [`322fd58`](https://github.com/LedgerHQ/ledger-live/commit/322fd58ffcde6d592eb27af1fd93f8c45d33205c), [`2673c1d`](https://github.com/LedgerHQ/ledger-live/commit/2673c1d98788fafe7e95bd798be06a6b5e39e1c0), [`2901938`](https://github.com/LedgerHQ/ledger-live/commit/29019387955bbab5bc0adcd550bc9e32d08b4f72), [`ea3a175`](https://github.com/LedgerHQ/ledger-live/commit/ea3a17562ab1954b14803ff19ab575e4fcfc64c8), [`61aedb7`](https://github.com/LedgerHQ/ledger-live/commit/61aedb7bbd45e73d6bc2b53e55f562262d5c5fa7), [`224cc07`](https://github.com/LedgerHQ/ledger-live/commit/224cc07b86e8c5a6167ff77cfb99e42a1057813e), [`58beb75`](https://github.com/LedgerHQ/ledger-live/commit/58beb7504454b64cb5a955926ef27f811397aa6d)]: + - @ledgerhq/live-nft-react@0.5.0 + - @ledgerhq/live-nft@0.5.0 + - @ledgerhq/live-common@34.16.0 + - @ledgerhq/types-live@6.55.0 + - @ledgerhq/coin-evm@2.7.0 + - @ledgerhq/react-ui@0.18.0 + - @ledgerhq/live-dmk@0.2.0 + - @ledgerhq/coin-cosmos@0.3.0 + - @ledgerhq/coin-framework@0.20.1 + - @ledgerhq/coin-bitcoin@0.8.10 + - @ledgerhq/coin-filecoin@1.3.5 + - @ledgerhq/domain-service@1.2.14 + - @ledgerhq/live-countervalues@0.2.15 + - @ledgerhq/live-countervalues-react@0.2.15 + - @ledgerhq/live-wallet@0.7.7 + +## 2.94.0-next.6 + +### Patch Changes + +- Updated dependencies [[`16a4794`](https://github.com/LedgerHQ/ledger-live/commit/16a479420976c4c12fb8984dcba9cf572c576292)]: + - @ledgerhq/live-common@34.16.0-next.3 + +## 2.94.0-next.5 + +### Minor Changes + +- [#8628](https://github.com/LedgerHQ/ledger-live/pull/8628) [`3a9758f`](https://github.com/LedgerHQ/ledger-live/commit/3a9758f7642cea56e49b45a9e36dc5c4babc57ef) Thanks [@KVNLS](https://github.com/KVNLS)! - LLD: LIVE-15143 use a debounce on the memotag field + +## 2.94.0-next.4 + +### Minor Changes + +- [#8601](https://github.com/LedgerHQ/ledger-live/pull/8601) [`61aedb7`](https://github.com/LedgerHQ/ledger-live/commit/61aedb7bbd45e73d6bc2b53e55f562262d5c5fa7) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Revery useNFTCOllections + +### Patch Changes + +- Updated dependencies [[`61aedb7`](https://github.com/LedgerHQ/ledger-live/commit/61aedb7bbd45e73d6bc2b53e55f562262d5c5fa7)]: + - @ledgerhq/types-live@6.55.0-next.1 + - @ledgerhq/live-common@34.16.0-next.2 + - @ledgerhq/live-nft-react@0.5.0-next.1 + - @ledgerhq/coin-framework@0.20.1-next.1 + - @ledgerhq/coin-bitcoin@0.8.10-next.1 + - @ledgerhq/coin-cosmos@0.3.0-next.2 + - @ledgerhq/coin-evm@2.7.0-next.1 + - @ledgerhq/coin-filecoin@1.3.5-next.1 + - @ledgerhq/domain-service@1.2.14-next.1 + - @ledgerhq/live-countervalues@0.2.15-next.1 + - @ledgerhq/live-countervalues-react@0.2.15-next.1 + - @ledgerhq/live-nft@0.5.0-next.1 + - @ledgerhq/live-wallet@0.7.7-next.1 + +## 2.94.0-next.3 + +### Minor Changes + +- [#8596](https://github.com/LedgerHQ/ledger-live/pull/8596) [`40509e4`](https://github.com/LedgerHQ/ledger-live/commit/40509e4411af132a03e3d70f685dc8242c8d1031) Thanks [@Canestin](https://github.com/Canestin)! - fix: add mev protection on swap + +## 2.94.0-next.2 + +### Minor Changes + +- [#8586](https://github.com/LedgerHQ/ledger-live/pull/8586) [`87d298c`](https://github.com/LedgerHQ/ledger-live/commit/87d298cf99479ba1cab21665f5b1216dceba0da8) Thanks [@themooneer](https://github.com/themooneer)! - Add ICP memo field to first step of new memo flow , FF ON + +## 2.94.0-next.1 + +### Patch Changes + +- Updated dependencies [[`ea3a175`](https://github.com/LedgerHQ/ledger-live/commit/ea3a17562ab1954b14803ff19ab575e4fcfc64c8)]: + - @ledgerhq/coin-cosmos@0.3.0-next.1 + - @ledgerhq/live-common@34.16.0-next.1 + +## 2.94.0-next.0 + +### Minor Changes + +- [#8495](https://github.com/LedgerHQ/ledger-live/pull/8495) [`f0a34a0`](https://github.com/LedgerHQ/ledger-live/commit/f0a34a06461331ec44fa02b8093699fa001f94a0) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Rework Hiddencollections + +- [#8563](https://github.com/LedgerHQ/ledger-live/pull/8563) [`93f8f78`](https://github.com/LedgerHQ/ledger-live/commit/93f8f7885d1300208310599e743a4d1fae4ec2a4) Thanks [@Canestin](https://github.com/Canestin)! - add another ledger solana validator + +- [#8538](https://github.com/LedgerHQ/ledger-live/pull/8538) [`f6eefe9`](https://github.com/LedgerHQ/ledger-live/commit/f6eefe9f56c3eb5eb150a61b93d15d94bac1147a) Thanks [@sergiubreban](https://github.com/sergiubreban)! - enable /card deeplink + +- [#8550](https://github.com/LedgerHQ/ledger-live/pull/8550) [`40f1cd4`](https://github.com/LedgerHQ/ledger-live/commit/40f1cd4c22d17480dcf86c73e90a07866667b0ba) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Filter Currencies which are buyable/swappable in MarketWidget + +- [#8375](https://github.com/LedgerHQ/ledger-live/pull/8375) [`c45ee45`](https://github.com/LedgerHQ/ledger-live/commit/c45ee457a9f5500ae42f2a8fb7f0cfb7926f319b) Thanks [@Canestin](https://github.com/Canestin)! - add mev protection + +- [#8525](https://github.com/LedgerHQ/ledger-live/pull/8525) [`032a018`](https://github.com/LedgerHQ/ledger-live/commit/032a018e2410a4074c4d2075ce3bd205858732db) Thanks [@CremaFR](https://github.com/CremaFR)! - fix: default gas limit + +- [#8504](https://github.com/LedgerHQ/ledger-live/pull/8504) [`03c26f4`](https://github.com/LedgerHQ/ledger-live/commit/03c26f431c304075012cd40e4297a0f55b74276f) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Redirect Users to Corresponding Market Page When Clicking on Asset in Market Widget + +- [#8516](https://github.com/LedgerHQ/ledger-live/pull/8516) [`6d679f5`](https://github.com/LedgerHQ/ledger-live/commit/6d679f57ff33610cc660541711f857f6605f20d3) Thanks [@Couto](https://github.com/Couto)! - Ensure returnTo value is defined before tracking analytics + +- [#8319](https://github.com/LedgerHQ/ledger-live/pull/8319) [`42e9d67`](https://github.com/LedgerHQ/ledger-live/commit/42e9d67cd5c99f10e6e760c6a657ca7a8e3d45fb) Thanks [@sergiubreban](https://github.com/sergiubreban)! - Handle close sidebar and notify widget app + +- [#8465](https://github.com/LedgerHQ/ledger-live/pull/8465) [`fc95133`](https://github.com/LedgerHQ/ledger-live/commit/fc9513365f85d80c4c0cfb6645c2d8ea86983a87) Thanks [@themooneer](https://github.com/themooneer)! - Make learn more cta dynamic per app name context + +- [#8523](https://github.com/LedgerHQ/ledger-live/pull/8523) [`90b2950`](https://github.com/LedgerHQ/ledger-live/commit/90b295032fed0420e44effc6446f8ca2e209c600) Thanks [@lpaquet-ledger](https://github.com/lpaquet-ledger)! - fix swap Id in history + +- [#8397](https://github.com/LedgerHQ/ledger-live/pull/8397) [`2a9e2de`](https://github.com/LedgerHQ/ledger-live/commit/2a9e2de3d14958123f702e4bde93eeb52967cddd) Thanks [@thesan](https://github.com/thesan)! - Re-implement the portfolio content cards with UI components + +- [#8514](https://github.com/LedgerHQ/ledger-live/pull/8514) [`b8b9f76`](https://github.com/LedgerHQ/ledger-live/commit/b8b9f767deea088ebf5cb7d976a1204f6c0d316f) Thanks [@ComradeAERGO](https://github.com/ComradeAERGO)! - Removed message fields for sign message modal for ACRE Withdrawals + +- [#8520](https://github.com/LedgerHQ/ledger-live/pull/8520) [`e341fa2`](https://github.com/LedgerHQ/ledger-live/commit/e341fa2888bfbbdd6588c8d62ee450b565acfacb) Thanks [@CremaFR](https://github.com/CremaFR)! - ui gas limit fixed for swap + +- [#8529](https://github.com/LedgerHQ/ledger-live/pull/8529) [`b8fdd1c`](https://github.com/LedgerHQ/ledger-live/commit/b8fdd1c32c46a9a3f10bc129f8ef66de3cda0b35) Thanks [@valpinkman](https://github.com/valpinkman)! - Fix IPC transport register + +- [#8511](https://github.com/LedgerHQ/ledger-live/pull/8511) [`73f65a7`](https://github.com/LedgerHQ/ledger-live/commit/73f65a7aa3e08565794471545b431b4278c954f8) Thanks [@adammino-ledger](https://github.com/adammino-ledger)! - Changed the Electron util that detects the locale for swapping Yield-Earn labels + +- [#8457](https://github.com/LedgerHQ/ledger-live/pull/8457) [`d45e871`](https://github.com/LedgerHQ/ledger-live/commit/d45e871ee6b7e98102a4ffbdf3d7581c8cf838d0) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Rework Hiddencollections + +- [#8500](https://github.com/LedgerHQ/ledger-live/pull/8500) [`faef7ed`](https://github.com/LedgerHQ/ledger-live/commit/faef7ed3b9954d2bbaf5c5a518e247fd441a73e7) Thanks [@VicAlbr](https://github.com/VicAlbr)! - Fix Speculos CI + Update checks on receive and subAccount tests" + +- [#8503](https://github.com/LedgerHQ/ledger-live/pull/8503) [`322fd58`](https://github.com/LedgerHQ/ledger-live/commit/322fd58ffcde6d592eb27af1fd93f8c45d33205c) Thanks [@jiyuzhuang](https://github.com/jiyuzhuang)! - Remove `feature_recover_upsell_redirection` feature flag and unused components + +- [#8404](https://github.com/LedgerHQ/ledger-live/pull/8404) [`2901938`](https://github.com/LedgerHQ/ledger-live/commit/29019387955bbab5bc0adcd550bc9e32d08b4f72) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Fix undefined join on Spam filter + +- [#8540](https://github.com/LedgerHQ/ledger-live/pull/8540) [`aa7d44a`](https://github.com/LedgerHQ/ledger-live/commit/aa7d44a18b42d54c65585a6e6769571f51e5fd2f) Thanks [@valpinkman](https://github.com/valpinkman)! - Fix speculos transport + +- [#8497](https://github.com/LedgerHQ/ledger-live/pull/8497) [`d7ae5ff`](https://github.com/LedgerHQ/ledger-live/commit/d7ae5ffc941dab74a5bcc6f52f8d2040e582757d) Thanks [@VicAlbr](https://github.com/VicAlbr)! - adding e2e test + +- [#8240](https://github.com/LedgerHQ/ledger-live/pull/8240) [`224cc07`](https://github.com/LedgerHQ/ledger-live/commit/224cc07b86e8c5a6167ff77cfb99e42a1057813e) Thanks [@Wozacosta](https://github.com/Wozacosta)! - chore: Upgrade @celo/\* dependencies for compatibility with Celo as Layer 2 + +- [#8524](https://github.com/LedgerHQ/ledger-live/pull/8524) [`8e11fb4`](https://github.com/LedgerHQ/ledger-live/commit/8e11fb49d5d3956230a004972e2b79a905b8a891) Thanks [@CremaFR](https://github.com/CremaFR)! - fix: stop saving fees when closing + +### Patch Changes + +- Updated dependencies [[`f0a34a0`](https://github.com/LedgerHQ/ledger-live/commit/f0a34a06461331ec44fa02b8093699fa001f94a0), [`93f8f78`](https://github.com/LedgerHQ/ledger-live/commit/93f8f7885d1300208310599e743a4d1fae4ec2a4), [`40f1cd4`](https://github.com/LedgerHQ/ledger-live/commit/40f1cd4c22d17480dcf86c73e90a07866667b0ba), [`c45ee45`](https://github.com/LedgerHQ/ledger-live/commit/c45ee457a9f5500ae42f2a8fb7f0cfb7926f319b), [`2a9e2de`](https://github.com/LedgerHQ/ledger-live/commit/2a9e2de3d14958123f702e4bde93eeb52967cddd), [`995b771`](https://github.com/LedgerHQ/ledger-live/commit/995b771671b23931c6a85534841e8d88ca2acaf4), [`e8fb7ec`](https://github.com/LedgerHQ/ledger-live/commit/e8fb7ec80f6c8f2eb813662f9e02bc1c2ebaf6a7), [`475b74c`](https://github.com/LedgerHQ/ledger-live/commit/475b74c1ba01b7e7a374cca14e274769a3c17476), [`d45e871`](https://github.com/LedgerHQ/ledger-live/commit/d45e871ee6b7e98102a4ffbdf3d7581c8cf838d0), [`faef7ed`](https://github.com/LedgerHQ/ledger-live/commit/faef7ed3b9954d2bbaf5c5a518e247fd441a73e7), [`322fd58`](https://github.com/LedgerHQ/ledger-live/commit/322fd58ffcde6d592eb27af1fd93f8c45d33205c), [`2673c1d`](https://github.com/LedgerHQ/ledger-live/commit/2673c1d98788fafe7e95bd798be06a6b5e39e1c0), [`2901938`](https://github.com/LedgerHQ/ledger-live/commit/29019387955bbab5bc0adcd550bc9e32d08b4f72), [`224cc07`](https://github.com/LedgerHQ/ledger-live/commit/224cc07b86e8c5a6167ff77cfb99e42a1057813e), [`58beb75`](https://github.com/LedgerHQ/ledger-live/commit/58beb7504454b64cb5a955926ef27f811397aa6d)]: + - @ledgerhq/live-nft-react@0.5.0-next.0 + - @ledgerhq/live-nft@0.5.0-next.0 + - @ledgerhq/live-common@34.16.0-next.0 + - @ledgerhq/types-live@6.55.0-next.0 + - @ledgerhq/coin-evm@2.7.0-next.0 + - @ledgerhq/react-ui@0.18.0-next.0 + - @ledgerhq/live-dmk@0.2.0-next.0 + - @ledgerhq/coin-framework@0.20.1-next.0 + - @ledgerhq/coin-bitcoin@0.8.10-next.0 + - @ledgerhq/coin-cosmos@0.2.3-next.0 + - @ledgerhq/coin-filecoin@1.3.5-next.0 + - @ledgerhq/domain-service@1.2.14-next.0 + - @ledgerhq/live-countervalues@0.2.15-next.0 + - @ledgerhq/live-countervalues-react@0.2.15-next.0 + - @ledgerhq/live-wallet@0.7.7-next.0 + ## 2.93.0 ### Minor Changes diff --git a/apps/ledger-live-desktop/RELEASE_NOTES.md b/apps/ledger-live-desktop/RELEASE_NOTES.md index 7b068bc59037..99ecfeda3646 100644 --- a/apps/ledger-live-desktop/RELEASE_NOTES.md +++ b/apps/ledger-live-desktop/RELEASE_NOTES.md @@ -1,3 +1,7 @@ +# 2.94.0 + +This release includes small security improvements, UI tweaks, and minor bug fixes. + # 2.92.1 We've upgraded the sell feature to provide a more seamless and flexible experience. Users can now select their preferred payment method and easily compare quotes from different providers, ensuring they get the best deal possible. diff --git a/apps/ledger-live-desktop/package.json b/apps/ledger-live-desktop/package.json index c7fdd2bf13b9..87a46129ff69 100644 --- a/apps/ledger-live-desktop/package.json +++ b/apps/ledger-live-desktop/package.json @@ -13,7 +13,7 @@ "license": "MIT", "private": true, "main": "./.webpack/main.bundle.js", - "version": "2.93.0", + "version": "2.94.0", "scripts": { "start:prod": "electron ./.webpack/main.bundle.js", "start": "cross-env NODE_ENV=development node ./tools/main.js", @@ -73,6 +73,7 @@ "@ledgerhq/live-config": "workspace:^", "@ledgerhq/live-countervalues": "workspace:^", "@ledgerhq/live-countervalues-react": "workspace:^", + "@ledgerhq/live-dmk": "workspace:*", "@ledgerhq/live-env": "workspace:^", "@ledgerhq/live-network": "workspace:^", "@ledgerhq/live-nft": "workspace:^", @@ -204,6 +205,7 @@ "@vitejs/plugin-react": "3.1.0", "allure-playwright": "2.15.1", "axios": "1.7.7", + "buffer": "6.0.3", "chalk": "4.1.2", "cross-env": "7.0.3", "debug": "4.3.4", diff --git a/apps/ledger-live-desktop/src/config/urls.ts b/apps/ledger-live-desktop/src/config/urls.ts index 6203ebbcfcbe..62e6aa6607ce 100644 --- a/apps/ledger-live-desktop/src/config/urls.ts +++ b/apps/ledger-live-desktop/src/config/urls.ts @@ -154,6 +154,7 @@ export const urls = { solana: { staking: "https://support.ledger.com/article/4731749170461-zd", recipient_info: "https://support.ledger.com", + ledgerByChorusOneTC: "https://chorus.one/tos", ledgerByFigmentTC: "https://cdn.figment.io/legal/Current%20Ledger_Online%20Staking%20Delgation%20Services%20Agreement.pdf", }, diff --git a/apps/ledger-live-desktop/src/helpers/systemLocale.ts b/apps/ledger-live-desktop/src/helpers/systemLocale.ts index 67e90de78d0e..a06e1b8f819e 100644 --- a/apps/ledger-live-desktop/src/helpers/systemLocale.ts +++ b/apps/ledger-live-desktop/src/helpers/systemLocale.ts @@ -15,7 +15,15 @@ const parse = memoize(navLang => { * We don't use window.navigator.language directly as it doesn't always actually * follow the system language, it's unreliable. cf. https://stackoverflow.com/a/3335420 * */ -export const getSystemLocale = () => { +export const getAppLocale = () => { return new URLSearchParams(window.location.search).get("appLocale") || window.navigator.language; }; -export const getParsedSystemLocale = () => parse(getSystemLocale()); + +export const getSystemLocale = () => { + return ( + new URLSearchParams(window.location.search).get("systemLocale") || window.navigator.language + ); +}; + +export const getParsedSystemDeviceLocale = () => parse(getSystemLocale()); +export const getParsedSystemLocale = () => parse(getAppLocale()); diff --git a/apps/ledger-live-desktop/src/internal/jsdom.test.ts b/apps/ledger-live-desktop/src/internal/jsdom.test.ts new file mode 100644 index 000000000000..ae6ee6983f83 --- /dev/null +++ b/apps/ledger-live-desktop/src/internal/jsdom.test.ts @@ -0,0 +1,3 @@ +test("has Buffer & Uint8array equivalency", () => { + expect(Buffer.from("").subarray() instanceof Uint8Array).toBeTruthy(); +}); diff --git a/apps/ledger-live-desktop/src/main/window-lifecycle.ts b/apps/ledger-live-desktop/src/main/window-lifecycle.ts index 3d8a88cc5a63..272baddc4830 100644 --- a/apps/ledger-live-desktop/src/main/window-lifecycle.ts +++ b/apps/ledger-live-desktop/src/main/window-lifecycle.ts @@ -78,6 +78,8 @@ export const loadWindow = async () => { fullUrl.searchParams.append("appDirname", app.dirname || ""); fullUrl.searchParams.append("theme", theme || ""); fullUrl.searchParams.append("appLocale", app.getLocale()); + fullUrl.searchParams.append("systemLocale", app.getSystemLocale()); + await mainWindow.loadURL(fullUrl.href); } }; diff --git a/apps/ledger-live-desktop/src/newArch/components/ContextMenu/createContextMenuItems.ts b/apps/ledger-live-desktop/src/newArch/components/ContextMenu/createContextMenuItems.ts index ff1d8206cd96..5c546c1422be 100644 --- a/apps/ledger-live-desktop/src/newArch/components/ContextMenu/createContextMenuItems.ts +++ b/apps/ledger-live-desktop/src/newArch/components/ContextMenu/createContextMenuItems.ts @@ -45,6 +45,7 @@ export function createContextMenuItems({ openModal("MODAL_HIDE_NFT_COLLECTION", { collectionName: collectionName ?? collectionAddress, collectionId: `${account.id}|${collectionAddress}`, + blockchain: account.currency.id, onClose: () => { if (goBackToAccount) { setDrawer(); diff --git a/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/BreadCrumb/useBreadCrumbModel.tsx b/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/BreadCrumb/useBreadCrumbModel.tsx index ea7470522ba3..23fb8ec76a8d 100644 --- a/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/BreadCrumb/useBreadCrumbModel.tsx +++ b/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/BreadCrumb/useBreadCrumbModel.tsx @@ -2,27 +2,40 @@ import { useSelector } from "react-redux"; import { useHistory, useParams } from "react-router-dom"; import { State } from "~/renderer/reducers"; import { accountSelector } from "~/renderer/reducers/accounts"; +import { nftsByCollections } from "@ledgerhq/live-nft"; import { useCallback, useMemo } from "react"; import { ProtoNFT } from "@ledgerhq/types-live"; import { DropDownItemType } from "~/renderer/components/DropDownSelector"; import { setTrackingSource } from "~/renderer/analytics/TrackPage"; -import { useNftCollections } from "~/renderer/hooks/nfts/useNftCollections"; +import { useFeature } from "@ledgerhq/live-common/featureFlags/index"; +import { isThresholdValid, useNftGalleryFilter } from "@ledgerhq/live-nft-react"; const useBreadCrumbModel = () => { const history = useHistory(); const { id, collectionAddress } = useParams<{ id?: string; collectionAddress?: string }>(); + const nftsFromSimplehashFeature = useFeature("nftsFromSimplehash"); + const thresold = nftsFromSimplehashFeature?.params?.threshold; const account = useSelector((state: State) => - id ? accountSelector(state, { accountId: id }) : undefined, + id ? accountSelector(state, { accountId: id }) : null, ); - const { collections } = useNftCollections({ - account, + const { nfts } = useNftGalleryFilter({ + nftsOwned: account?.nfts || [], + addresses: String(account?.freshAddress), + chains: [String(account?.currency.id)], + threshold: isThresholdValid(thresold) ? Number(thresold) : 75, + enabled: nftsFromSimplehashFeature?.enabled || false, + staleTime: nftsFromSimplehashFeature?.params?.staleTime, }); + const collections = useMemo( + () => nftsByCollections(nftsFromSimplehashFeature?.enabled ? nfts : account?.nfts), + [account?.nfts, nfts, nftsFromSimplehashFeature], + ); const items: DropDownItemType[] = useMemo( () => - collections.map(([contract, nfts]: [string, ProtoNFT[]]) => ({ + Object.entries(collections).map(([contract, nfts]: [string, ProtoNFT[]]) => ({ key: contract, label: contract, content: nfts[0], diff --git a/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/Collections/useNftCollectionsModel.tsx b/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/Collections/useNftCollectionsModel.tsx index ae215c1c4490..ca45af9d5a57 100644 --- a/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/Collections/useNftCollectionsModel.tsx +++ b/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/Collections/useNftCollectionsModel.tsx @@ -3,8 +3,14 @@ import { Account, ProtoNFT } from "@ledgerhq/types-live"; import { useDispatch } from "react-redux"; import { useHistory } from "react-router-dom"; import { openModal } from "~/renderer/actions/modals"; -import { mapCollectionsToStructure } from "LLD/features/Collectibles/utils/collectionUtils"; -import { useNftCollections } from "~/renderer/hooks/nfts/useNftCollections"; +import { nftsByCollections } from "@ledgerhq/live-nft/index"; +import { useFeature } from "@ledgerhq/live-common/featureFlags/index"; +import { isThresholdValid, useNftGalleryFilter } from "@ledgerhq/live-nft-react"; +import { + filterHiddenCollections, + mapCollectionsToStructure, +} from "LLD/features/Collectibles/utils/collectionUtils"; +import { useNftCollectionsStatus } from "~/renderer/hooks/nfts/useNftCollectionsStatus"; type NftsInTheCollections = { contract: string; @@ -21,6 +27,9 @@ const INCREMENT = 5; export const useNftCollectionsModel = ({ account }: Props) => { const history = useHistory(); const dispatch = useDispatch(); + const nftsFromSimplehashFeature = useFeature("nftsFromSimplehash"); + const thresold = nftsFromSimplehashFeature?.params?.threshold; + const { hiddenNftCollections } = useNftCollectionsStatus(); const [numberOfVisibleCollections, setNumberOfVisibleCollections] = useState(INCREMENT); const [displayShowMore, setDisplayShowMore] = useState(false); @@ -44,26 +53,49 @@ export const useNftCollectionsModel = ({ account }: Props) => { history.push(`/account/${account.id}/nft-collection`); }, [account.id, history]); - const { fetchNextPage, hasNextPage, collections, collectionsLength } = useNftCollections({ - account, + const { nfts, fetchNextPage, hasNextPage } = useNftGalleryFilter({ + nftsOwned: account.nfts || [], + addresses: account.freshAddress, + chains: [account.currency.id], + threshold: isThresholdValid(thresold) ? Number(thresold) : 75, + enabled: nftsFromSimplehashFeature?.enabled || false, + staleTime: nftsFromSimplehashFeature?.params?.staleTime, }); + const collections = useMemo( + () => nftsByCollections(nftsFromSimplehashFeature?.enabled ? nfts : account.nfts), + [account.nfts, nfts, nftsFromSimplehashFeature], + ); + const onShowMore = useCallback(() => { - setNumberOfVisibleCollections(numberOfVisibleCollections => - Math.min(numberOfVisibleCollections + INCREMENT, collectionsLength), + setNumberOfVisibleCollections( + numberOfVisibleCollections => numberOfVisibleCollections + INCREMENT, ); if (hasNextPage) fetchNextPage(); - }, [collectionsLength, fetchNextPage, hasNextPage]); + }, [fetchNextPage, hasNextPage]); + const filteredCollections = useMemo( + () => filterHiddenCollections(collections, hiddenNftCollections, account.id), + [account.id, collections, hiddenNftCollections], + ); const nftsInTheCollection: NftsInTheCollections[] = useMemo( - () => mapCollectionsToStructure(collections, numberOfVisibleCollections, onOpenCollection), - [collections, numberOfVisibleCollections, onOpenCollection], + () => + mapCollectionsToStructure(filteredCollections, numberOfVisibleCollections, onOpenCollection), + [filteredCollections, numberOfVisibleCollections, onOpenCollection], ); useEffect(() => { - const moreToShow = numberOfVisibleCollections < collections.length; + const moreToShow = nftsFromSimplehashFeature?.enabled + ? filteredCollections.length <= numberOfVisibleCollections && hasNextPage + : numberOfVisibleCollections < filteredCollections.length; + setDisplayShowMore(moreToShow); - }, [numberOfVisibleCollections, collections.length]); + }, [ + numberOfVisibleCollections, + filteredCollections.length, + nftsFromSimplehashFeature?.enabled, + hasNextPage, + ]); return { nftsInTheCollection, diff --git a/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/screens/Gallery/useNftGalleryModel.tsx b/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/screens/Gallery/useNftGalleryModel.tsx index d58c3b864797..8aadcb582251 100644 --- a/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/screens/Gallery/useNftGalleryModel.tsx +++ b/apps/ledger-live-desktop/src/newArch/features/Collectibles/Nfts/screens/Gallery/useNftGalleryModel.tsx @@ -2,10 +2,14 @@ import { useHistory, useParams } from "react-router-dom"; import { useDispatch, useSelector } from "react-redux"; import { State } from "~/renderer/reducers"; import { accountSelector } from "~/renderer/reducers/accounts"; -import { useCallback, useEffect, useRef, useState } from "react"; +import { useNftGalleryFilter, isThresholdValid } from "@ledgerhq/live-nft-react"; +import { nftsByCollections } from "@ledgerhq/live-nft"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { openModal } from "~/renderer/actions/modals"; import { useOnScreen } from "LLD/hooks/useOnScreen"; -import { useNftCollections } from "~/renderer/hooks/nfts/useNftCollections"; +import useFeature from "@ledgerhq/live-common/featureFlags/useFeature"; +import { ChainsEnum } from "LLD/features/Collectibles/types/enum/Chains"; +import { useNftCollectionsStatus } from "~/renderer/hooks/nfts/useNftCollectionsStatus"; const defaultNumberOfVisibleNfts = 10; @@ -14,6 +18,9 @@ const useNftGalleryModel = () => { const history = useHistory(); const { id } = useParams<{ id: string }>(); + const nftsFromSimplehashFeature = useFeature("nftsFromSimplehash"); + const threshold = nftsFromSimplehashFeature?.params?.threshold; + const listFooterRef = useRef(null); const [maxVisibleNFTs, setMaxVisibleNFTs] = useState(defaultNumberOfVisibleNfts); @@ -21,10 +28,30 @@ const useNftGalleryModel = () => { account: accountSelector(state, { accountId: id }), })); - const { fetchNextPage, hasNextPage, collections, allNfts } = useNftCollections({ - account, + const { hiddenNftCollections } = useNftCollectionsStatus(); + + const INITIAL_INCREMENT = nftsFromSimplehashFeature?.enabled ? 50 : 5; + + const { nfts, fetchNextPage, hasNextPage } = useNftGalleryFilter({ + nftsOwned: account?.nfts || [], + addresses: account?.freshAddress || "", + chains: [account?.currency.id ?? ChainsEnum.ETHEREUM], + threshold: isThresholdValid(threshold) ? Number(threshold) : 75, + enabled: nftsFromSimplehashFeature?.enabled || false, + staleTime: nftsFromSimplehashFeature?.params?.staleTime, }); + const allNfts = useMemo( + () => (nftsFromSimplehashFeature?.enabled ? nfts : account?.nfts || []), + [account?.nfts, nfts, nftsFromSimplehashFeature?.enabled], + ); + + const collections = useMemo(() => { + return Object.entries(nftsByCollections(allNfts)).filter( + ([contract]) => !hiddenNftCollections.includes(`${account?.id}|${contract}`), + ); + }, [account?.id, allNfts, hiddenNftCollections]); + useEffect(() => { if (collections.length < 1) { history.push(`/account/${account?.id}/`); @@ -45,11 +72,11 @@ const useNftGalleryModel = () => { ); const updateMaxVisibleNtfs = useCallback(() => { - setMaxVisibleNFTs(prevMaxVisibleNFTs => prevMaxVisibleNFTs + 5); + setMaxVisibleNFTs(prevMaxVisibleNFTs => prevMaxVisibleNFTs + INITIAL_INCREMENT); if (hasNextPage) { fetchNextPage(); } - }, [hasNextPage, fetchNextPage]); + }, [hasNextPage, INITIAL_INCREMENT, fetchNextPage]); useOnScreen({ enabled: maxVisibleNFTs < allNfts?.length, @@ -72,6 +99,7 @@ const useNftGalleryModel = () => { return { account, + hiddenNftCollections, nftsByCollection, listFooterRef, collections, diff --git a/apps/ledger-live-desktop/src/newArch/features/Collectibles/hooks/useOpenHideCollectionModal.ts b/apps/ledger-live-desktop/src/newArch/features/Collectibles/hooks/useOpenHideCollectionModal.ts index 2d4febd2f122..802efd357d1f 100644 --- a/apps/ledger-live-desktop/src/newArch/features/Collectibles/hooks/useOpenHideCollectionModal.ts +++ b/apps/ledger-live-desktop/src/newArch/features/Collectibles/hooks/useOpenHideCollectionModal.ts @@ -29,8 +29,9 @@ export const useOpenHideCollectionModal = ( collectionName: collectionName as string, collectionId: `${account.id}|${nft.contract}`, onClose, + blockchain: account.currency.id, }), ), }; - }, [account.id, dispatch, metadata, nft.contract, onClose, t]); + }, [account.currency.id, account.id, dispatch, metadata, nft.contract, onClose, t]); }; diff --git a/apps/ledger-live-desktop/src/newArch/features/DynamicContent/__integrations__/PortfolioContentCards.test.tsx b/apps/ledger-live-desktop/src/newArch/features/DynamicContent/__integrations__/PortfolioContentCards.test.tsx new file mode 100644 index 000000000000..e3a409c0d39c --- /dev/null +++ b/apps/ledger-live-desktop/src/newArch/features/DynamicContent/__integrations__/PortfolioContentCards.test.tsx @@ -0,0 +1,122 @@ +import React from "react"; + +import { act, render, screen } from "tests/testUtils"; +import PortfolioContentCards from "../components/PortfolioContentCards"; + +// Mocked functions +import { logCardDismissal, logContentCardClick } from "@braze/web-sdk"; +import { track } from "~/renderer/analytics/segment"; + +jest.mock("@braze/web-sdk", () => ({ + getCachedContentCards: jest.fn(() => ({ + cards: Cards.map(({ id, ...extras }) => ({ id, extras })), + })), + logCardDismissal: jest.fn(), + logContentCardClick: jest.fn(), +})); + +jest.mock("~/renderer/analytics/segment", () => ({ + ...jest.requireActual("~/renderer/analytics/segment"), + track: jest.fn(), +})); + +const Cards = [ + { + id: "0", + title: "Foo", + description: "Lorem ipsum dolor sit amet.", + cta: "Click me", + tag: "New", + path: "ledger-live://deep-link", + }, + { + id: "1", + title: "Bar", + description: "Consectetur adipiscing elit.", + path: "ledger-live://deep-link", + }, +]; + +describe("PortfolioContentCards", () => { + test("render slides", async () => { + render(, { + initialState: { + dynamicContent: { portfolioCards: Cards }, + settings: { shareAnalytics: true, sharePersonalizedRecommandations: true }, + }, + }); + + // I'm not sure how to properly test logContentCardImpressions and track("contentcard_impression") + // because IntersectionObserver is not available in JSDOM and mocking it would defeat the purpose IMO. + + const title0 = await screen.findByText("Foo"); + const description0 = screen.getByText("Lorem ipsum dolor sit amet."); + const cta0 = screen.getByText("Click me"); + const tag0 = screen.getByText("New"); + const title1 = screen.getByText("Bar"); + const description1 = screen.getByText("Consectetur adipiscing elit."); + + // Due to the styling not being applied in the test all slides are visible from the start. + expect(title0).toBeVisible(); + expect(description0).toBeVisible(); + expect(cta0).toBeVisible(); + expect(tag0).toBeVisible(); + expect(title1).toBeVisible(); + expect(description1).toBeVisible(); + + // Test next and prev buttons + expect(track).not.toHaveBeenCalledWith("contentcard_slide", { + button: "prev", + page: "Portfolio", + type: "portfolio_carousel", + }); + expect(track).not.toHaveBeenCalledWith("contentcard_slide", { + button: "next", + page: "Portfolio", + type: "portfolio_carousel", + }); + + act(() => screen.getByTestId("carousel-arrow-next").click()); + expect(track).toHaveBeenCalledWith("contentcards_slide", { + button: "next", + page: "Portfolio", + type: "portfolio_carousel", + }); + act(() => screen.getByTestId("carousel-arrow-prev").click()); + expect(track).toHaveBeenCalledWith("contentcards_slide", { + button: "prev", + page: "Portfolio", + type: "portfolio_carousel", + }); + + // Test dismiss button + expect(logCardDismissal).not.toHaveBeenCalled(); + expect(track).not.toHaveBeenCalledWith("contentcard_dismissed", expect.any(Object)); + act(() => screen.getAllByTestId("portfolio-card-close-button")[1].click()); + expect(logCardDismissal).toHaveBeenCalledWith(asBrazeCard(Cards[1])); + expect(track).toHaveBeenCalledWith("contentcard_dismissed", { + card: "1", + page: "Portfolio", + type: "portfolio_carousel", + }); + expect(title1).not.toBeInTheDocument(); + expect(description1).not.toBeInTheDocument(); + + // Test click button + expect(logContentCardClick).not.toHaveBeenCalled(); + expect(track).not.toHaveBeenCalledWith("contentcard_clicked", expect.any(Object)); + act(() => cta0.click()); + expect(logContentCardClick).toHaveBeenCalledWith(asBrazeCard(Cards[0])); + expect(track).toHaveBeenCalledWith("contentcard_clicked", { + contentcard: "Foo", + link: "ledger-live://deep-link", + campaign: "0", + page: "Portfolio", + type: "portfolio_carousel", + }); + }); +}); + +function asBrazeCard({ id, ...extras }: (typeof Cards)[number]) { + return { id, extras }; +} diff --git a/apps/ledger-live-desktop/src/newArch/components/DynamicContent/LogContentCardWrapper.tsx b/apps/ledger-live-desktop/src/newArch/features/DynamicContent/components/LogContentCardWrapper.tsx similarity index 100% rename from apps/ledger-live-desktop/src/newArch/components/DynamicContent/LogContentCardWrapper.tsx rename to apps/ledger-live-desktop/src/newArch/features/DynamicContent/components/LogContentCardWrapper.tsx diff --git a/apps/ledger-live-desktop/src/newArch/features/DynamicContent/components/PortfolioContentCards/Slide.tsx b/apps/ledger-live-desktop/src/newArch/features/DynamicContent/components/PortfolioContentCards/Slide.tsx new file mode 100644 index 000000000000..7edb2ffe1416 --- /dev/null +++ b/apps/ledger-live-desktop/src/newArch/features/DynamicContent/components/PortfolioContentCards/Slide.tsx @@ -0,0 +1,53 @@ +import React, { memo } from "react"; +import { useHistory } from "react-router-dom"; + +import { PortfolioContentCard as Card } from "@ledgerhq/react-ui"; +import { openURL } from "~/renderer/linking"; +import type { PortfolioContentCard } from "~/types/dynamicContent"; +import type { CarouselActions } from "../../types"; +import LogContentCardWrapper from "../LogContentCardWrapper"; + +export default memo(Slide); + +type Props = PortfolioContentCard & CarouselActions & { index: number }; + +function Slide({ + id, + path, + url, + title, + cta, + description, + tag, + image, + index, + logSlideClick, + dismissCard, +}: Props) { + const history = useHistory(); + + const handleClose = () => dismissCard(index); + const handleClick = () => { + logSlideClick(id); + + if (path) { + history.push({ pathname: path, state: { source: "banner" } }); + } else if (url) { + openURL(url); + } + }; + + return ( + + + + ); +} diff --git a/apps/ledger-live-desktop/src/newArch/features/DynamicContent/components/PortfolioContentCards/index.tsx b/apps/ledger-live-desktop/src/newArch/features/DynamicContent/components/PortfolioContentCards/index.tsx new file mode 100644 index 000000000000..d5260f40e80f --- /dev/null +++ b/apps/ledger-live-desktop/src/newArch/features/DynamicContent/components/PortfolioContentCards/index.tsx @@ -0,0 +1,32 @@ +import React from "react"; + +import { Carousel } from "@ledgerhq/react-ui"; +import { track } from "~/renderer/analytics/segment"; +import { usePortfolioCards } from "../../hooks/usePortfolioCards"; +import Slide from "./Slide"; + +export default PortfolioContentCards; + +function PortfolioContentCards() { + const { portfolioCards, logSlideClick, dismissCard } = usePortfolioCards(); + const handlePrevButton = () => trackSlide("prev"); + const handleNextButton = () => trackSlide("next"); + + return ( + + {portfolioCards.map((card, index) => ( + + ))} + + ); +} + +function trackSlide(button: "prev" | "next") { + track("contentcards_slide", { button, page: "Portfolio", type: "portfolio_carousel" }); +} diff --git a/apps/ledger-live-desktop/src/newArch/features/DynamicContent/hooks/usePortfolioCards.ts b/apps/ledger-live-desktop/src/newArch/features/DynamicContent/hooks/usePortfolioCards.ts new file mode 100644 index 000000000000..38fefa564f38 --- /dev/null +++ b/apps/ledger-live-desktop/src/newArch/features/DynamicContent/hooks/usePortfolioCards.ts @@ -0,0 +1,77 @@ +import * as braze from "@braze/web-sdk"; +import { useCallback, useEffect, useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +import { track } from "~/renderer/analytics/segment"; +import { setPortfolioCards } from "~/renderer/actions/dynamicContent"; +import { setDismissedContentCards } from "~/renderer/actions/settings"; +import { portfolioContentCardSelector } from "~/renderer/reducers/dynamicContent"; +import { trackingEnabledSelector } from "~/renderer/reducers/settings"; +import type { PortfolioContentCard } from "~/types/dynamicContent"; +import type { CarouselActions } from "../types"; + +type UsePortfolioCards = { portfolioCards: PortfolioContentCard[] } & CarouselActions; + +export function usePortfolioCards(): UsePortfolioCards { + const [cachedContentCards, setCachedContentCards] = useState([]); + const portfolioCards = useSelector(portfolioContentCardSelector); + const isTrackedUser = useSelector(trackingEnabledSelector); + const dispatch = useDispatch(); + + useEffect(() => { + const cards = braze.getCachedContentCards().cards; + setCachedContentCards(cards); + }, []); + + const dismissCard = useCallback( + index => { + const slide = portfolioCards[index]; + if (!slide?.id) return; + + if (isTrackedUser) { + track("contentcard_dismissed", { + card: slide.id, + page: "Portfolio", + type: "portfolio_carousel", + }); + } + + const currentCard = cachedContentCards.find(card => card.id === slide.id); + if (currentCard) { + if (isTrackedUser) { + braze.logCardDismissal(currentCard); + } else if (currentCard.id) { + dispatch(setDismissedContentCards({ id: currentCard.id, timestamp: Date.now() })); + } + setCachedContentCards(cachedContentCards.filter(n => n.id !== currentCard.id)); + } + dispatch(setPortfolioCards(portfolioCards.filter(n => n.id !== slide.id))); + }, + [portfolioCards, cachedContentCards, isTrackedUser, dispatch], + ); + + const logSlideClick = useCallback( + cardId => { + if (!isTrackedUser) return; + + const slide = portfolioCards.find(card => card.id === cardId); + if (!slide) return; + + track("contentcard_clicked", { + contentcard: slide.title, + link: slide.path || slide.url, + campaign: cardId, + page: "Portfolio", + type: "portfolio_carousel", + }); + + const currentCard = cachedContentCards.find(card => card.id === cardId); + if (!currentCard) return; + + braze.logContentCardClick(currentCard); + }, + [portfolioCards, cachedContentCards, isTrackedUser], + ); + + return { portfolioCards, logSlideClick, dismissCard }; +} diff --git a/apps/ledger-live-desktop/src/newArch/features/DynamicContent/types.ts b/apps/ledger-live-desktop/src/newArch/features/DynamicContent/types.ts new file mode 100644 index 000000000000..b060de59ca62 --- /dev/null +++ b/apps/ledger-live-desktop/src/newArch/features/DynamicContent/types.ts @@ -0,0 +1,4 @@ +export type CarouselActions = { + logSlideClick: (cardId: string) => void; + dismissCard: (index: number) => void; +}; diff --git a/apps/ledger-live-desktop/src/newArch/features/MemoTag/components/MemoTagField.tsx b/apps/ledger-live-desktop/src/newArch/features/MemoTag/components/MemoTagField.tsx index 85cbae624eed..a6be608741a6 100644 --- a/apps/ledger-live-desktop/src/newArch/features/MemoTag/components/MemoTagField.tsx +++ b/apps/ledger-live-desktop/src/newArch/features/MemoTag/components/MemoTagField.tsx @@ -78,7 +78,9 @@ const MemoTagField = ({ autoFocus={autoFocus} data-testid="memo-tag-input" /> - {autoFocus && {t("MemoTagField.instruction")}} + {!warning && !error && autoFocus && ( + {t("MemoTagField.instruction")} + )} ); diff --git a/apps/ledger-live-desktop/src/renderer/App.tsx b/apps/ledger-live-desktop/src/renderer/App.tsx index 6f261193bc3b..f8a2d16c7c3e 100644 --- a/apps/ledger-live-desktop/src/renderer/App.tsx +++ b/apps/ledger-live-desktop/src/renderer/App.tsx @@ -5,6 +5,7 @@ import { HashRouter as Router } from "react-router-dom"; import { NftMetadataProvider } from "@ledgerhq/live-nft-react"; import { getCurrencyBridge } from "@ledgerhq/live-common/bridge/index"; import { getFeature } from "@ledgerhq/live-common/featureFlags/index"; +import { DeviceManagementKitProvider } from "@ledgerhq/live-dmk"; import "./global.css"; import "tippy.js/dist/tippy.css"; import "tippy.js/animations/shift-away.css"; @@ -79,30 +80,32 @@ const InnerApp = ({ initialCountervalues }: { initialCountervalues: CounterValue - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/ledger-live-desktop/src/renderer/actions/constants.ts b/apps/ledger-live-desktop/src/renderer/actions/constants.ts index 15bfbc465bff..09cf07655e5a 100644 --- a/apps/ledger-live-desktop/src/renderer/actions/constants.ts +++ b/apps/ledger-live-desktop/src/renderer/actions/constants.ts @@ -1,2 +1,7 @@ // Action types + +/** Settings --------- */ export const TOGGLE_MEMOTAG_INFO = "settings/toggleShouldDisplayMemoTagInfo"; +export const TOGGLE_MEV = "settings/toggleMEV"; +export const TOGGLE_MARKET_WIDGET = "settings/toggleMarketWidget"; +export const UPDATE_NFT_COLLECTION_STATUS = "settings/updateNftCollectionStatus"; diff --git a/apps/ledger-live-desktop/src/renderer/actions/marketperformance.ts b/apps/ledger-live-desktop/src/renderer/actions/marketperformance.ts index 3970eaaf9e03..dc0bd429c6f3 100644 --- a/apps/ledger-live-desktop/src/renderer/actions/marketperformance.ts +++ b/apps/ledger-live-desktop/src/renderer/actions/marketperformance.ts @@ -2,7 +2,10 @@ import { useMemo } from "react"; import { useSelector } from "react-redux"; import { useMarketcapIds, useTrackingPairsForTopCoins } from "@ledgerhq/live-countervalues-react"; import { TrackingPair } from "@ledgerhq/live-countervalues/types"; -import { selectedTimeRangeSelector } from "~/renderer/reducers/settings"; +import { + marketPerformanceWidgetSelector, + selectedTimeRangeSelector, +} from "~/renderer/reducers/settings"; import { getPortfolioRangeConfig } from "@ledgerhq/live-countervalues/portfolio"; import { Currency } from "@ledgerhq/types-cryptoassets"; import useFeature from "@ledgerhq/live-common/featureFlags/useFeature"; @@ -10,13 +13,16 @@ import { ABTestingVariants } from "@ledgerhq/types-live"; import { BASIC_REFETCH } from "../screens/market/utils"; export function useMarketPerformanceFeatureFlag() { + const marketPerformanceValue = useSelector(marketPerformanceWidgetSelector); const marketperformanceWidgetDesktop = useFeature("marketperformanceWidgetDesktop"); return { - enabled: marketperformanceWidgetDesktop?.enabled || false, + enabled: (marketperformanceWidgetDesktop?.enabled && marketPerformanceValue) || false, variant: marketperformanceWidgetDesktop?.params?.variant || ABTestingVariants.variantA, refreshRate: marketperformanceWidgetDesktop?.params?.refreshRate || BASIC_REFETCH, - top: marketperformanceWidgetDesktop?.params?.top || 50, + top: marketperformanceWidgetDesktop?.params?.top || 100, + limit: marketperformanceWidgetDesktop?.params?.limit || 100, supported: marketperformanceWidgetDesktop?.params?.supported || false, + enableNewFeature: marketperformanceWidgetDesktop?.params?.enableNewFeature || false, }; } @@ -31,6 +37,7 @@ export function useMarketPerformanceReferenceDate() { export function useMarketPerformanceTrackingPairs(countervalue: Currency): TrackingPair[] { const size = 50; const refDate = useMarketPerformanceReferenceDate(); + const marketPerformanceEnabled = useMarketPerformanceFeatureFlag().enabled; const marketcapIds = useMarketcapIds(); return useTrackingPairsForTopCoins( diff --git a/apps/ledger-live-desktop/src/renderer/actions/settings.ts b/apps/ledger-live-desktop/src/renderer/actions/settings.ts index 34cfd7e524ff..be1df1bef74c 100644 --- a/apps/ledger-live-desktop/src/renderer/actions/settings.ts +++ b/apps/ledger-live-desktop/src/renderer/actions/settings.ts @@ -25,7 +25,14 @@ import { import { useRefreshAccountsOrdering } from "~/renderer/actions/general"; import { Language, Locale } from "~/config/languages"; import { Layout } from "LLD/features/Collectibles/types/Layouts"; -import { TOGGLE_MEMOTAG_INFO } from "./constants"; +import { + TOGGLE_MARKET_WIDGET, + TOGGLE_MEMOTAG_INFO, + TOGGLE_MEV, + UPDATE_NFT_COLLECTION_STATUS, +} from "./constants"; +import { BlockchainsType } from "@ledgerhq/live-nft/supported"; +import { NftStatus } from "@ledgerhq/live-nft/types"; export type SaveSettings = (a: Partial) => { type: string; payload: Partial; @@ -215,15 +222,6 @@ export const blacklistToken = (tokenId: string) => ({ type: "BLACKLIST_TOKEN", payload: tokenId, }); -export const hideNftCollection = (collectionId: string) => ({ - type: "HIDE_NFT_COLLECTION", - payload: collectionId, -}); - -export const whitelistNftCollection = (collectionId: string) => ({ - type: "WHITELIST_NFT_COLLECTION", - payload: collectionId, -}); export const hideOrdinalsAsset = (inscriptionId: string) => ({ type: "HIDE_ORDINALS_ASSET", @@ -255,14 +253,16 @@ export const showToken = (tokenId: string) => ({ type: "SHOW_TOKEN", payload: tokenId, }); -export const unhideNftCollection = (collectionId: string) => ({ - type: "UNHIDE_NFT_COLLECTION", - payload: collectionId, -}); -export const unwhitelistNftCollection = (collectionId: string) => ({ - type: "UNWHITELIST_NFT_COLLECTION", - payload: collectionId, + +export const updateNftStatus = ( + blockchain: BlockchainsType, + collectionId: string, + status: NftStatus, +) => ({ + type: UPDATE_NFT_COLLECTION_STATUS, + payload: { blockchain, collectionId, status }, }); + export const unhideOrdinalsAsset = (inscriptionId: string) => ({ type: "UNHIDE_ORDINALS_ASSET", payload: inscriptionId, @@ -439,7 +439,12 @@ export const setLastOnboardedDevice = (payload: Device | null) => ({ payload, }); export const setMevProtection = (payload: boolean) => ({ - type: "SET_MEV_PROTECTION", + type: TOGGLE_MEV, + payload, +}); + +export const setMarketWidget = (payload: boolean) => ({ + type: TOGGLE_MARKET_WIDGET, payload, }); diff --git a/apps/ledger-live-desktop/src/renderer/analytics/segment.ts b/apps/ledger-live-desktop/src/renderer/analytics/segment.ts index 1fbde6811db2..079074319398 100644 --- a/apps/ledger-live-desktop/src/renderer/analytics/segment.ts +++ b/apps/ledger-live-desktop/src/renderer/analytics/segment.ts @@ -22,6 +22,7 @@ import { languageSelector, lastSeenDeviceSelector, localeSelector, + marketPerformanceWidgetSelector, mevProtectionSelector, shareAnalyticsSelector, sharePersonalizedRecommendationsSelector, @@ -61,11 +62,15 @@ export function setAnalyticsFeatureFlagMethod(method: typeof analyticsFeatureFla analyticsFeatureFlagMethod = method; } -const getMarketWidgetAnalytics = () => { +const getMarketWidgetAnalytics = (state: State) => { if (!analyticsFeatureFlagMethod) return false; const marketWidget = analyticsFeatureFlagMethod("marketperformanceWidgetDesktop"); - return !!marketWidget?.enabled; + const hasMarketWidgetActivated = marketPerformanceWidgetSelector(state); + + return { + hasMarketWidget: !marketWidget?.enabled ? "Null" : hasMarketWidgetActivated ? "Yes" : "No", + }; }; const getLedgerSyncAttributes = (state: State) => { @@ -159,8 +164,9 @@ const extraProperties = (store: ReduxStore) => { const accounts = accountsSelector(state); const ptxAttributes = getPtxAttributes(); - const ledgerSyncAtributes = getLedgerSyncAttributes(state); - const mevProtectionAtributes = getMEVAttributes(state); + const ledgerSyncAttributes = getLedgerSyncAttributes(state); + const mevProtectionAttributes = getMEVAttributes(state); + const marketWidgetAttributes = getMarketWidgetAnalytics(state); const deviceInfo = device ? { @@ -211,12 +217,12 @@ const extraProperties = (store: ReduxStore) => { blockchainsWithNftsOwned, hasGenesisPass, hasInfinityPass, - hasSeenMarketWidget: getMarketWidgetAnalytics(), modelIdList: devices, ...ptxAttributes, ...deviceInfo, - ...ledgerSyncAtributes, - ...mevProtectionAtributes, + ...ledgerSyncAttributes, + ...mevProtectionAttributes, + ...marketWidgetAttributes, }; }; diff --git a/apps/ledger-live-desktop/src/renderer/components/BalanceInfos/index.tsx b/apps/ledger-live-desktop/src/renderer/components/BalanceInfos/index.tsx index fab152c2e45e..70d95f055136 100644 --- a/apps/ledger-live-desktop/src/renderer/components/BalanceInfos/index.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/BalanceInfos/index.tsx @@ -46,6 +46,7 @@ export function BalanceDiff({ valueChange, unit, isAvailable, ...boxProps }: Pro return ( { const history = useHistory(); + const nftsFromSimplehashFeature = useFeature("nftsFromSimplehash"); + const thresold = nftsFromSimplehashFeature?.params?.threshold; const { id, collectionAddress } = useParams<{ id?: string; collectionAddress?: string }>(); const account = useSelector((state: State) => id @@ -45,20 +49,28 @@ const NFTCrumb = () => { : undefined, ); - const { collections } = useNftCollections({ - account, + const { nfts } = useNftGalleryFilter({ + nftsOwned: account?.nfts || [], + addresses: String(account?.freshAddress), + chains: [String(account?.currency.id)], + threshold: isThresholdValid(thresold) ? Number(thresold) : 75, + enabled: nftsFromSimplehashFeature?.enabled || false, + staleTime: nftsFromSimplehashFeature?.params?.staleTime, }); + const collections = useMemo( + () => nftsByCollections(nftsFromSimplehashFeature?.enabled ? nfts : account?.nfts), + [account?.nfts, nfts, nftsFromSimplehashFeature], + ); const items: DropDownItemType[] = useMemo( () => - collections.map(([contract, nfts]: [string, ProtoNFT[]]) => ({ + Object.entries(collections).map(([contract, nfts]: [string, ProtoNFT[]]) => ({ key: contract, label: contract, content: nfts[0], })), [collections], ); - const activeItem: DropDownItemType | undefined | null = useMemo( () => items.find(item => item.key === collectionAddress) || items[0], [collectionAddress, items], diff --git a/apps/ledger-live-desktop/src/renderer/components/Carousel/Slide.tsx b/apps/ledger-live-desktop/src/renderer/components/Carousel/Slide.tsx deleted file mode 100644 index f1ce3b434fb8..000000000000 --- a/apps/ledger-live-desktop/src/renderer/components/Carousel/Slide.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import React, { useCallback, useEffect, useRef } from "react"; -import styled from "styled-components"; -import { useSpring, animated } from "react-spring"; -import { openURL } from "~/renderer/linking"; -import Box from "~/renderer/components/Box"; -import Text from "~/renderer/components/Text"; -import { Wrapper, Label, IllustrationWrapper } from "~/renderer/components/Carousel"; -import { useHistory } from "react-router-dom"; -import Image from "../Image"; -import { track } from "~/renderer/analytics/segment"; -import { PortfolioContentCard } from "~/types/dynamicContent"; - -const Layer = styled(animated.div)<{ - image: string; - width: number; - height: number; -}>` - // prettier-ignore - background-image: url('${p => p.image}'); - background-size: contain; - background-position: center center; - background-repeat: no-repeat; - will-change: transform; - position: absolute; - width: ${p => p.width}px; - height: ${p => p.height}px; - transform-origin: top left; -`; - -const EllipsedText = styled(Text)` - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; -`; - -type Props = PortfolioContentCard; - -const Slide = ({ id, url, path, title, description, image, imgs, onClickOnSlide }: Props) => { - const history = useHistory(); - const [{ xy }, set] = useSpring<{ - xy: number[]; - config: { mass: number; tension: number; friction: number }; - }>(() => ({ - xy: [-120, -30], - config: { mass: 10, tension: 550, friction: 140 }, - })); - const getTransform = (offsetX: number, effectX: number, offsetY: number, effectY: number) => ({ - transform: xy.interpolate( - // @ts-expect-error react-spring types are broken - (x, y) => `translate3d(${x / effectX + offsetX}px,${y / effectY + offsetY}px, 0)`, - ), - }); - - const ref = useRef(null); - - // React to the user mouse movement inside the banner for parallax effect - const onMouseMove = (e: React.MouseEvent) => { - if (!ref.current) return; - const rect = ref.current.getBoundingClientRect(); - const x = e.clientX - rect.left; - const y = e.clientY - rect.top; - set({ xy: [x - rect.width / 2, y - rect.height / 2] }); - }; - - const onMouseLeave = () => set({ xy: [0, 0] }); - - const onClick = useCallback(() => { - if (onClickOnSlide) { - onClickOnSlide(id); - } - if (path) { - history.push({ pathname: path, state: { source: "banner" } }); - return; - } - if (url) { - openURL(url); - } - track("contentcard_clicked", { - contentcard: title, - link: path || url, - campaign: id, - page: "Portfolio", - type: "portfolio_carousel", - }); - }, [history, id, path, title, url, onClickOnSlide]); - - // After initial slide-in animation, set the offset to zero - useEffect(() => { - setTimeout(() => { - set({ xy: [0, 0] }); - }, 400); - }, [set]); - - return ( - - - - - {description} - - - {imgs && ( - - {imgs.map(({ source, transform, size }, i) => ( - - ))} - - )} - {image && ( - - - - )} - - ); -}; - -export default Slide; diff --git a/apps/ledger-live-desktop/src/renderer/components/Carousel/TimeBasedProgressBar.tsx b/apps/ledger-live-desktop/src/renderer/components/Carousel/TimeBasedProgressBar.tsx deleted file mode 100644 index ad4d45c99d97..000000000000 --- a/apps/ledger-live-desktop/src/renderer/components/Carousel/TimeBasedProgressBar.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import React, { useCallback, useEffect, useState } from "react"; -import { useSpring, animated } from "react-spring"; - -const easing = (t: number) => t; // linear easing function - -type Props = { - duration: number; - onComplete: () => void; - paused?: boolean; -}; - -const TimeBasedProgressBar = ({ duration, onComplete, paused }: Props) => { - const [outOfFocusPaused, setOutOfFocusPaused] = useState(false); - const progress = useSpring({ - from: { value: 0 }, - to: { value: 1 }, - config: { duration, easing }, - delay: duration, - pause: paused || outOfFocusPaused, - onRest: () => { - if (!outOfFocusPaused) { - onComplete(); - } - }, - }); - - const onWindowFocus = useCallback(() => { - setOutOfFocusPaused(false); - }, []); - - const onWindowBlur = useCallback(() => { - setOutOfFocusPaused(true); - }, []); - - useEffect(() => { - window.addEventListener("focus", onWindowFocus); - window.addEventListener("blur", onWindowBlur); - return () => { - window.removeEventListener("focus", onWindowFocus); - window.removeEventListener("blur", onWindowBlur); - }; - }, [onWindowFocus, onWindowBlur]); - - return ( -
- {!paused && !outOfFocusPaused && ( - `scaleX(${v})`), - transformOrigin: "left center", - }} - /> - )} -
- ); -}; - -export default TimeBasedProgressBar; diff --git a/apps/ledger-live-desktop/src/renderer/components/Carousel/helpers.tsx b/apps/ledger-live-desktop/src/renderer/components/Carousel/helpers.tsx deleted file mode 100644 index a3a4540ad8a1..000000000000 --- a/apps/ledger-live-desktop/src/renderer/components/Carousel/helpers.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import React, { useCallback, useEffect, useMemo, useState } from "react"; -import map from "lodash/map"; -import Slide from "./Slide"; -import { portfolioContentCardSelector } from "~/renderer/reducers/dynamicContent"; -import { useDispatch, useSelector } from "react-redux"; -import * as braze from "@braze/web-sdk"; -import { PortfolioContentCard } from "~/types/dynamicContent"; -import { setPortfolioCards } from "~/renderer/actions/dynamicContent"; -import { trackingEnabledSelector } from "~/renderer/reducers/settings"; -import { setDismissedContentCards } from "~/renderer/actions/settings"; - -export const getTransitions = (transition: "slide" | "flip", reverse = false) => { - const mult = reverse ? -1 : 1; - return { - flip: { - from: { - opacity: 1, - transform: `rotateX(${180 * mult}deg)`, - }, - enter: { - opacity: 1, - transform: "rotateX(0deg)", - }, - leave: { - opacity: 1, - transform: `rotateX(${-180 * mult}deg)`, - }, - config: { mass: 20, tension: 200, friction: 100 }, - }, - slide: { - from: { - opacity: 1, - transform: `translate3d(${100 * mult}%,0,0)`, - }, - enter: { - opacity: 1, - transform: "translate3d(0%,0,0)", - }, - leave: { - opacity: 1, - transform: `translate3d((${-100 * mult}%,0,0)`, - }, - initial: null, - }, - }[transition]; -}; - -type SlideRes = { - id: string; - Component: React.ComponentType<{}>; -}; - -export const useDefaultSlides = (): { - slides: SlideRes[]; - dismissCard: (index: number) => void; -} => { - const [cachedContentCards, setCachedContentCards] = useState([]); - const portfolioCards = useSelector(portfolioContentCardSelector); - const isTrackedUser = useSelector(trackingEnabledSelector); - const dispatch = useDispatch(); - - useEffect(() => { - const cards = braze.getCachedContentCards().cards; - setCachedContentCards(cards); - }, []); - - const dismissCard = useCallback( - (index: number) => { - if (portfolioCards && portfolioCards.length > index) { - const slide = portfolioCards[index]; - if (slide?.id) { - const currentCard = cachedContentCards.find(card => card.id === slide.id); - if (currentCard) { - isTrackedUser - ? braze.logCardDismissal(currentCard) - : currentCard.id && - dispatch(setDismissedContentCards({ id: currentCard.id, timestamp: Date.now() })); - setCachedContentCards(cachedContentCards.filter(n => n.id !== currentCard.id)); - } - dispatch(setPortfolioCards(portfolioCards.filter(n => n.id !== slide.id))); - } - } - }, - [portfolioCards, cachedContentCards, isTrackedUser, dispatch], - ); - const logSlideClick = useCallback( - (cardId: string) => { - const currentCard = cachedContentCards.find(card => card.id === cardId); - - if (currentCard) { - // For some reason braze won't log the click event if the card url is empty - // Setting it as the card id just to have a dummy non empty value - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - currentCard.url = currentCard.id; - isTrackedUser && braze.logContentCardClick(currentCard as braze.ClassicCard); - } - }, - [cachedContentCards, isTrackedUser], - ); - const slides = useMemo( - () => - map( - portfolioCards, - (slide): SlideRes => ({ - id: slide.id, - // eslint-disable-next-line react/display-name - Component: () => , - }), - ), - [portfolioCards, logSlideClick], - ); - - return { - slides, - dismissCard, - }; -}; diff --git a/apps/ledger-live-desktop/src/renderer/components/Carousel/index.tsx b/apps/ledger-live-desktop/src/renderer/components/Carousel/index.tsx deleted file mode 100644 index cb8a458e8123..000000000000 --- a/apps/ledger-live-desktop/src/renderer/components/Carousel/index.tsx +++ /dev/null @@ -1,266 +0,0 @@ -import React, { useCallback, useMemo, useState } from "react"; -import styled from "styled-components"; -import { useTransition, animated } from "react-spring"; -import IconArrowRight from "~/renderer/icons/ArrowRight"; -import { Card } from "~/renderer/components/Box"; -import Text from "~/renderer/components/Text"; -import TimeBasedProgressBar from "~/renderer/components/Carousel/TimeBasedProgressBar"; -import IconCross from "~/renderer/icons/Cross"; -import { getTransitions, useDefaultSlides } from "~/renderer/components/Carousel/helpers"; -import { track } from "~/renderer/analytics/segment"; -import LogContentCardWrapper from "LLD/components/DynamicContent/LogContentCardWrapper"; - -const CarouselWrapper = styled(Card)` - position: relative; - height: 100px; - margin: 20px 0; -`; - -const Close = styled.div` - position: absolute; - color: ${p => p.theme.colors.palette.text.shade30}; - top: 16px; - right: 16px; - cursor: pointer; - &:hover { - color: ${p => p.theme.colors.palette.text.shade100}; - } -`; - -const Previous = styled.div` - position: absolute; - color: ${p => p.theme.colors.palette.text.shade30}; - bottom: 16px; - right: 42px; - cursor: pointer; - transform: rotate(180deg); - &:hover { - color: ${p => p.theme.colors.palette.text.shade100}; - } -`; - -const Next = styled.div` - position: absolute; - color: ${p => p.theme.colors.palette.text.shade30}; - bottom: 11px; - right: 16px; - cursor: pointer; - &:hover { - color: ${p => p.theme.colors.palette.text.shade100}; - } -`; - -// NB left here because it handles the transitions -const ProgressBarWrapper = styled.div` - position: absolute; - bottom: 0; - z-index: 100; - width: 100%; - display: none; -`; - -const Bullets = styled.div<{ index: number }>` - position: absolute; - bottom: 16px; - left: 0; - right: 0; - display: flex; - justify-content: center; - & > div { - cursor: pointer; - & > span { - display: block; - border-radius: 6px; - height: 6px; - width: 6px; - background: ${p => p.theme.colors.palette.text.shade40}; - } - padding: 15px 5px; - margin-bottom: -15px; - &:nth-child(${p => p.index + 1}) > span { - background: ${p => p.theme.colors.palette.text.shade80}; - } - } -`; - -const Slides = styled.div` - width: 100%; - height: 100px; - border-radius: 4px; - perspective: 1000px; - overflow: hidden; - background: ${p => p.theme.colors.palette.background.paper}; - - & > div { - transform-origin: center right; - backface-visibility: hidden; - transform-style: preserve-3d; - position: absolute; - width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; - color: white; - font-weight: 800; - font-size: 8em; - will-change: transform, opacity; - } -`; - -export const Label = styled(Text)` - color: ${p => p.theme.colors.palette.text.shade100}; - margin-bottom: 8px; - text-transform: uppercase; - letter-spacing: 0.1em; - - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 1; - -webkit-box-orient: vertical; -`; - -export const IllustrationWrapper = styled.div` - width: 257px; - height: 100%; - pointer-events: none; - position: relative; - right: 0; - align-self: flex-end; -`; - -export const Wrapper = styled.div` - width: 100%; - height: 100px; - overflow: hidden; - display: flex; - flex-direction: row; - cursor: pointer; -`; - -const Carousel = ({ - withArrows = true, - controls = true, - speed = 6000, - type = "slide", -}: { - withArrows?: boolean; - controls?: boolean; - speed?: number; - type?: "slide" | "flip"; -}) => { - const { slides, dismissCard } = useDefaultSlides(); - const [index, setIndex] = useState(0); - const [paused, setPaused] = useState(false); - const [reverse, setReverse] = useState(false); - const transitions = useTransition(index, p => p, getTransitions(type, reverse)); - - const changeVisibleSlide = useCallback( - (newIndex: number) => { - if (index !== newIndex) { - setIndex(newIndex); - } - }, - [index], - ); - - const onChooseSlide = useCallback( - (newIndex: number) => { - setReverse(index > newIndex); - changeVisibleSlide(newIndex); - }, - [index, changeVisibleSlide], - ); - - const onDismiss = useCallback(() => { - track("contentcard_dismissed", { - card: slides[index].id, - page: "Portfolio", - type: "portfolio_carousel", - }); - dismissCard(index); - changeVisibleSlide(0); - }, [index, slides, dismissCard, changeVisibleSlide]); - - const onNext = useCallback(() => { - setReverse(false); - changeVisibleSlide((index + 1) % slides.length); - track("contentcards_slide", { - button: "next", - page: "Portfolio", - type: "portfolio_carousel", - }); - }, [index, slides.length, changeVisibleSlide]); - - const onPrev = useCallback(() => { - setReverse(true); - changeVisibleSlide(!index ? slides.length - 1 : index - 1); - track("contentcards_slide", { - button: "previous", - page: "Portfolio", - type: "portfolio_carousel", - }); - }, [index, slides.length, changeVisibleSlide]); - - const canceled = useMemo(() => slides.length === 1, [slides.length]); - - if (!slides.length) { - // No slides or dismissed, no problem - return null; - } - - const showControls = controls && slides.length > 1; - - return ( - setPaused(true)} - onMouseLeave={() => setPaused(false)} - > - - - - - {transitions.map(({ item, props, key }) => { - if (!slides?.[item]) return null; - const { Component, id } = slides[item]; - return ( - - - - - - ); - })} - - - - - {showControls ? ( - <> - {withArrows ? ( - <> - - - - - - - - ) : ( - - {slides.map((_, i) => ( -
onChooseSlide(i)}> - -
- ))} -
- )} - - ) : null} -
- ); -}; - -export default Carousel; diff --git a/apps/ledger-live-desktop/src/renderer/components/ContextMenu/NFTCollectionContextMenu.tsx b/apps/ledger-live-desktop/src/renderer/components/ContextMenu/NFTCollectionContextMenu.tsx index d0633a17ed5a..eee1c99ccbcd 100644 --- a/apps/ledger-live-desktop/src/renderer/components/ContextMenu/NFTCollectionContextMenu.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/ContextMenu/NFTCollectionContextMenu.tsx @@ -42,6 +42,7 @@ export default function NFTCollectionContextMenu({ history.replace(`account/${account.id}`); } }, + blockchain: account.currency.id, }), ), }, diff --git a/apps/ledger-live-desktop/src/renderer/components/CustomImage/NFTGallerySelector.tsx b/apps/ledger-live-desktop/src/renderer/components/CustomImage/NFTGallerySelector.tsx index 39b28538b99b..043fd87b27b4 100644 --- a/apps/ledger-live-desktop/src/renderer/components/CustomImage/NFTGallerySelector.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/CustomImage/NFTGallerySelector.tsx @@ -9,8 +9,10 @@ import NFTItem from "./NFTItem"; import { useTranslation } from "react-i18next"; import styled from "styled-components"; import { useOnScreen } from "~/renderer/screens/nft/useOnScreen"; +import { useFeature } from "@ledgerhq/live-common/featureFlags/index"; +import { isThresholdValid, useNftGalleryFilter } from "@ledgerhq/live-nft-react"; import { getEnv } from "@ledgerhq/live-env"; -import { useNftCollections } from "~/renderer/hooks/nfts/useNftCollections"; +import { State } from "~/renderer/reducers"; const ScrollContainer = styled(Flex).attrs({ flexDirection: "column", @@ -31,8 +33,14 @@ type Props = { const NFTGallerySelector = ({ handlePickNft, selectedNftId }: Props) => { const SUPPORTED_NFT_CURRENCIES = getEnv("NFT_CURRENCIES"); + const nftsFromSimplehashFeature = useFeature("nftsFromSimplehash"); + const threshold = nftsFromSimplehashFeature?.params?.threshold; const accounts = useSelector(accountsSelector); - const nftsOrdered = useSelector(orderedVisibleNftsSelector, isEqual); + const nftsOrdered = useSelector( + (state: State) => + orderedVisibleNftsSelector(state, Boolean(nftsFromSimplehashFeature?.enabled)), + isEqual, + ); const addresses = useMemo( () => @@ -44,19 +52,26 @@ const NFTGallerySelector = ({ handlePickNft, selectedNftId }: Props) => { [accounts], ); - const { fetchNextPage, hasNextPage, allNfts } = useNftCollections({ - nftsOwned: nftsOrdered, + const { + nfts: nftsFiltered, + fetchNextPage, + hasNextPage, + } = useNftGalleryFilter({ + nftsOwned: nftsOrdered || [], addresses: addresses, chains: SUPPORTED_NFT_CURRENCIES, + threshold: isThresholdValid(threshold) ? Number(threshold) : 75, + enabled: nftsFromSimplehashFeature?.enabled || false, }); + const nfts = nftsFromSimplehashFeature?.enabled ? nftsFiltered : nftsOrdered; const { t } = useTranslation(); const [displayedCount, setDisplayedCount] = useState(10); const content = useMemo( () => - allNfts.slice(0, displayedCount).map((nft, index) => { + nfts.slice(0, displayedCount).map((nft, index) => { const { id } = nft; return ( { /> ); }), - [allNfts, displayedCount, selectedNftId, handlePickNft], + [nfts, displayedCount, selectedNftId, handlePickNft], ); const loaderContainerRef = useRef(null); @@ -81,13 +96,13 @@ const NFTGallerySelector = ({ handlePickNft, selectedNftId }: Props) => { }; useOnScreen({ - enabled: displayedCount < allNfts.length, + enabled: displayedCount < nfts.length, onIntersect: updateDisplayable, target: loaderContainerRef, threshold: 0.5, }); - if (allNfts.length <= 0) return ; + if (nfts.length <= 0) return ; return ( @@ -98,7 +113,7 @@ const NFTGallerySelector = ({ handlePickNft, selectedNftId }: Props) => { {content} - {displayedCount < allNfts.length ? ( + {displayedCount < nfts.length ? ( diff --git a/apps/ledger-live-desktop/src/renderer/components/DeviceAction/NoSuchAppOnProviderErrorComponent.tsx b/apps/ledger-live-desktop/src/renderer/components/DeviceAction/NoSuchAppOnProviderErrorComponent.tsx index 2b741e9e1778..588b245c6bf0 100644 --- a/apps/ledger-live-desktop/src/renderer/components/DeviceAction/NoSuchAppOnProviderErrorComponent.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/DeviceAction/NoSuchAppOnProviderErrorComponent.tsx @@ -51,7 +51,9 @@ const StyledLinkLearnMoreButton = styled(Link)` const NoSuchAppOnProviderErrorComponent: React.FC<{ error: Error; productName: string; -}> = ({ error, productName }) => { + learnMoreLink?: string; + learnMoreTextKey?: string; +}> = ({ error, productName, learnMoreLink, learnMoreTextKey }) => { const theme = useTheme(); const handleOnOpenExternalLink = useCallback( @@ -95,12 +97,14 @@ const NoSuchAppOnProviderErrorComponent: React.FC<{ > - - - + {learnMoreLink && learnMoreTextKey && ( + + + + )} ); diff --git a/apps/ledger-live-desktop/src/renderer/components/DeviceAction/index.tsx b/apps/ledger-live-desktop/src/renderer/components/DeviceAction/index.tsx index eefcc43d6128..90bac8a9f312 100644 --- a/apps/ledger-live-desktop/src/renderer/components/DeviceAction/index.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/DeviceAction/index.tsx @@ -77,7 +77,7 @@ import { AppAndVersion } from "@ledgerhq/live-common/hw/connectApp"; import { Device } from "@ledgerhq/types-devices"; import { LedgerErrorConstructor } from "@ledgerhq/errors/lib/helpers"; import { TokenCurrency } from "@ledgerhq/types-cryptoassets"; -import { isDeviceNotOnboardedError } from "./utils"; +import { getNoSuchAppProviderLearnMoreMetadataPerApp, isDeviceNotOnboardedError } from "./utils"; import { useKeepScreenAwake } from "~/renderer/hooks/useKeepScreenAwake"; import { walletSelector } from "~/renderer/reducers/wallet"; @@ -483,6 +483,7 @@ export const DeviceActionDefaultRendering = ({ withOpenManager: true, withExportLogs: true, ...(device && { device }), + ...getNoSuchAppProviderLearnMoreMetadataPerApp((request as { appName: string })?.appName), }); } diff --git a/apps/ledger-live-desktop/src/renderer/components/DeviceAction/rendering.tsx b/apps/ledger-live-desktop/src/renderer/components/DeviceAction/rendering.tsx index 1b5e65dd3be1..7f03feb54a6a 100644 --- a/apps/ledger-live-desktop/src/renderer/components/DeviceAction/rendering.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/DeviceAction/rendering.tsx @@ -760,6 +760,8 @@ export const renderError = ({ device, inlineRetry = true, withDescription = true, + learnMoreLink, + learnMoreTextKey, Icon, }: { error: Error | ErrorConstructor; @@ -769,6 +771,8 @@ export const renderError = ({ withExportLogs?: boolean; list?: boolean; supportLink?: string; + learnMoreLink?: string; + learnMoreTextKey?: string; buyLedger?: string; warning?: boolean; info?: boolean; @@ -798,6 +802,8 @@ export const renderError = ({ ); } diff --git a/apps/ledger-live-desktop/src/renderer/components/DeviceAction/utils.ts b/apps/ledger-live-desktop/src/renderer/components/DeviceAction/utils.ts index 519c83b93760..e1e73e576d8c 100644 --- a/apps/ledger-live-desktop/src/renderer/components/DeviceAction/utils.ts +++ b/apps/ledger-live-desktop/src/renderer/components/DeviceAction/utils.ts @@ -1,5 +1,6 @@ import { TransportStatusError } from "@ledgerhq/errors"; import { DeviceNotOnboarded } from "@ledgerhq/live-common/errors"; +import { urls } from "~/config/urls"; // NB Until we find a better way, // remap the error if it's 6d06 (LNS, LNSP, LNX) or 6d07 (Stax) and we haven't fallen @@ -11,3 +12,18 @@ export function isDeviceNotOnboardedError(e: unknown) { (e.message.includes("0x6d06") || e.message.includes("0x6d07"))) ); } + +export function getNoSuchAppProviderLearnMoreMetadataPerApp(appName: string): { + learnMoreTextKey?: string; + learnMoreLink?: string; +} { + switch (appName) { + case "Ledger Sync": + return { + learnMoreLink: urls.learnMoreLedgerSync, + learnMoreTextKey: "errors.NoSuchAppOnProvider.learnMoreCTA", + }; + default: + return {}; + } +} diff --git a/apps/ledger-live-desktop/src/renderer/components/LiveAppDrawer.tsx b/apps/ledger-live-desktop/src/renderer/components/LiveAppDrawer.tsx index bb20bc94266d..eed9a68fed95 100644 --- a/apps/ledger-live-desktop/src/renderer/components/LiveAppDrawer.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/LiveAppDrawer.tsx @@ -31,6 +31,7 @@ import CompleteExchange, { import { ExchangeType } from "@ledgerhq/live-common/wallet-api/Exchange/server"; import { Exchange } from "@ledgerhq/live-common/exchange/types"; import { renderLoading } from "./DeviceAction/rendering"; +import { createCustomErrorClass } from "@ledgerhq/errors"; const Divider = styled(Box)` border: 1px solid ${p => p.theme.colors.palette.divider}; @@ -60,6 +61,8 @@ export function isStartExchangeData(data: unknown): data is StartExchangeData { return "exchangeType" in data; } +const DrawerClosedError = createCustomErrorClass("DrawerClosedError"); + export const LiveAppDrawer = () => { const [dismissDisclaimerChecked, setDismissDisclaimerChecked] = useState(false); const { t } = useTranslation(); @@ -192,6 +195,11 @@ export const LiveAppDrawer = () => { title={payload ? t(payload.title) : ""} isOpen={isOpen} onRequestClose={() => { + payload?.data?.onCancel?.({ + error: new DrawerClosedError("User closed the drawer"), + name: "DrawerClosedError", + message: "User closed the drawer", + }); dispatch(closePlatformAppDrawer()); }} direction="left" diff --git a/apps/ledger-live-desktop/src/renderer/components/SignMessageConfirm/index.tsx b/apps/ledger-live-desktop/src/renderer/components/SignMessageConfirm/index.tsx index 4cf243b57cd9..33ff61074568 100644 --- a/apps/ledger-live-desktop/src/renderer/components/SignMessageConfirm/index.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/SignMessageConfirm/index.tsx @@ -59,21 +59,12 @@ const SignMessageConfirm = ({ device, account, parentAccount, signMessageRequest const { currency } = mainAccount; const [messageFields, setMessageFields] = useState(null); - const isACREWithdraw = "type" in signMessageRequested && signMessageRequested.type === "Withdraw"; - useEffect(() => { if (signMessageRequested.standard === "EIP712") { const specific = getLLDCoinFamily(currency.family); specific?.message?.getMessageProperties(signMessageRequested).then(setMessageFields); - } else if (isACREWithdraw) { - setMessageFields( - Object.entries(signMessageRequested.message).map(([label, value]) => ({ - label, - value, - })), - ); } - }, [currency, isACREWithdraw, mainAccount, signMessageRequested]); + }, [currency, mainAccount, signMessageRequested]); if (!device) return null; @@ -97,12 +88,6 @@ const SignMessageConfirm = ({ device, account, parentAccount, signMessageRequest label: t("SignMessageConfirm.messageHash"), value: signMessageRequested.hashStruct, }); - } else if (!isACREWithdraw) { - fields.push({ - type: "text", - label: t("SignMessageConfirm.message"), - value: signMessageRequested.message, - }); } } diff --git a/apps/ledger-live-desktop/src/renderer/components/SyncOnboarding/Manual/BackupStep.tsx b/apps/ledger-live-desktop/src/renderer/components/SyncOnboarding/Manual/BackupStep.tsx deleted file mode 100644 index 71b4692e4304..000000000000 --- a/apps/ledger-live-desktop/src/renderer/components/SyncOnboarding/Manual/BackupStep.tsx +++ /dev/null @@ -1,234 +0,0 @@ -import { useFeature } from "@ledgerhq/live-common/featureFlags/index"; -import { Device } from "@ledgerhq/live-common/hw/actions/types"; -import { Flex, Icons, IconsLegacy, Link, Tag, Text } from "@ledgerhq/react-ui"; -import { StorylyInstanceID } from "@ledgerhq/types-live"; -import React, { ComponentProps, useCallback, useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import styled, { useTheme } from "styled-components"; -import { track } from "~/renderer/analytics/segment"; -import ButtonV3 from "../../ButtonV3"; -import TrackPage from "~/renderer/analytics/TrackPage"; -import { useStoryly } from "~/storyly/useStoryly"; - -import { StepText, StepSubtitleText } from "./shared"; -import { useCustomPath } from "@ledgerhq/live-common/hooks/recoverFeatureFlag"; -import { useDispatch } from "react-redux"; -import { useHistory } from "react-router"; -import { saveSettings } from "~/renderer/actions/settings"; - -type BackupStepProps = { - device: Device; - onPressKeepManualBackup(): void; -}; - -type ChoiceBodyProps = { - isOpened: boolean; - device: Device; - onPressKeepManualBackup(): void; -}; - -type Choice = { - id: "backup" | "keep_on_paper"; - icon: React.ReactNode; - getTitle: (selected?: boolean) => string; - tag?: React.ReactNode; - body: React.ComponentType; -}; - -const ChoiceText = styled(Text).attrs({ - variant: "paragraph", - color: "neutral.c70", -})``; - -const VideoLink: React.FC<{}> = () => { - const { t } = useTranslation(); - const { ref: storylyRef, dataRef } = useStoryly(StorylyInstanceID.backupRecoverySeed); - return ( - -
- {/* @ts-expect-error the `storyly-web` package doesn't provide any typings yet. */} - -
- { - track("button_clicked", { button: "How it works", flow: "Device onboarding" }); - storylyRef.current?.openStory({ - group: dataRef.current?.at(0)?.id.toString(10), - }); - }} - > - {t("syncOnboarding.manual.backup.backupChoice.howItWorksCta")} - -
- ); -}; - -const BackupBody: React.FC = ({ isOpened }) => { - const { t } = useTranslation(); - - const dispatch = useDispatch(); - const history = useHistory(); - - const servicesConfig = useFeature("protectServicesDesktop"); - - const recoverActivatePath = useCustomPath(servicesConfig, "activate", "lld-onboarding-24") || ""; - - const navigateToRecover = useCallback(() => { - console.log("recoverActivatePath", recoverActivatePath); - const [pathname, search] = recoverActivatePath.split("?"); - dispatch( - saveSettings({ - hasCompletedOnboarding: true, - }), - ); - history.push({ - pathname, - search: search ? `?${search}` : undefined, - state: { fromOnboarding: false }, - }); - }, [dispatch, history, recoverActivatePath]); - - return isOpened ? ( - - {t("syncOnboarding.manual.backup.backupChoice.description")} - - {t("syncOnboarding.manual.backup.backupChoice.tryCta")} - - - {t("syncOnboarding.manual.backup.backupChoice.redeemCodeCta")} - - - - ) : null; -}; - -const KeepOnPaperBody: React.FC = ({ isOpened, onPressKeepManualBackup }) => { - const { t } = useTranslation(); - return isOpened ? ( - - {t("syncOnboarding.manual.backup.manualBackup.description")} - - {t("syncOnboarding.manual.backup.manualBackup.cta")} - - - ) : null; -}; - -const WrappedTag: React.FC<{ text: string } & ComponentProps> = ({ - text, - ...props -}) => { - const { t } = useTranslation(); - return ( - - {t(text)} - - ); -}; - -const choices: Choice[] = [ - { - id: "backup", - getTitle: selected => - selected - ? "syncOnboarding.manual.backup.backupChoice.titleSelected" - : "syncOnboarding.manual.backup.backupChoice.title", - icon: , - tag: ( - - ), - body: BackupBody, - }, - { - id: "keep_on_paper", - getTitle: () => "syncOnboarding.manual.backup.manualBackup.title", - icon: , - body: KeepOnPaperBody, - }, -]; - -const BackupStep: React.FC = props => { - const { device, onPressKeepManualBackup } = props; - const [choice, setChoice] = useState(null); - const { radii } = useTheme(); - - const { t } = useTranslation(); - - useEffect(() => { - if (choice === "backup") { - track("button_clicked", { button: "Ledger Recover", flow: "Device onboarding" }); - } else if (choice === "keep_on_paper") { - track("button_clicked", { button: "Manual Backup", flow: "Device onboarding" }); - } - }, [choice]); - - return ( - - - {/* @ts-expect-error weird props issue with React 18 */} - {t("syncOnboarding.manual.backup.description")} - {choices.map(({ id, getTitle, icon, tag, body: Body }) => ( -
setChoice(id)}> - - - - {icon} - {/* @ts-expect-error weird props issue with React 18 */} - - {t(getTitle(choice === id))} - - - {tag ?? null} - - - -
- ))} -
- ); -}; - -export default BackupStep; diff --git a/apps/ledger-live-desktop/src/renderer/components/SyncOnboarding/Manual/SyncOnboardingCompanion.tsx b/apps/ledger-live-desktop/src/renderer/components/SyncOnboarding/Manual/SyncOnboardingCompanion.tsx index f7aff61d21af..4584d5ae3a42 100644 --- a/apps/ledger-live-desktop/src/renderer/components/SyncOnboarding/Manual/SyncOnboardingCompanion.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/SyncOnboarding/Manual/SyncOnboardingCompanion.tsx @@ -35,7 +35,6 @@ import { setDrawer } from "~/renderer/drawers/Provider"; import LockedDeviceDrawer from "./LockedDeviceDrawer"; import { LockedDeviceError } from "@ledgerhq/errors"; import { useRecoverRestoreOnboarding } from "~/renderer/hooks/useRecoverRestoreOnboarding"; -import BackupStep from "./BackupStep"; const READY_REDIRECT_DELAY_MS = 2000; const POLLING_PERIOD_MS = 1000; @@ -117,8 +116,6 @@ const SyncOnboardingCompanion: React.FC = ({ const [seedPathStatus, setSeedPathStatus] = useState("choice_new_or_restore"); const servicesConfig = useFeature("protectServicesDesktop"); - const recoverUpsellRedirection = useFeature("recoverUpsellRedirection"); - const hasBackupStep = !recoverUpsellRedirection?.enabled; const recoverRestoreStaxPath = useCustomPath(servicesConfig, "restore", "lld-onboarding-24"); @@ -192,22 +189,6 @@ const SyncOnboardingCompanion: React.FC = ({ ), }, - ...(hasBackupStep - ? [ - { - key: StepKey.Backup, - status: "inactive" as StepStatus, - title: t("syncOnboarding.manual.backup.title"), - titleCompleted: t("syncOnboarding.manual.backup.title"), - renderBody: () => ( - setStepKey(StepKey.Apps)} - /> - ), - }, - ] - : []), { key: StepKey.Apps, status: "inactive", @@ -237,7 +218,6 @@ const SyncOnboardingCompanion: React.FC = ({ [ t, deviceName, - hasBackupStep, hasAppLoader, productName, device, @@ -359,24 +339,16 @@ const SyncOnboardingCompanion: React.FC = ({ // When the device is seeded, there are 2 cases before triggering the application install step: // - the user came to the sync onboarding with an non-seeded device and did a full onboarding: onboarding flag `Ready` // - the user came to the sync onboarding with an already seeded device: onboarding flag `WelcomeScreen1` - if (deviceOnboardingState?.isOnboarded && !seededDeviceHandled.current) { - if (deviceOnboardingState?.currentOnboardingStep === DeviceOnboardingStep.Ready) { - // device was just seeded - setStepKey(hasBackupStep ? StepKey.Backup : StepKey.Apps); - seededDeviceHandled.current = true; - return; - } else if ( - deviceOnboardingState?.currentOnboardingStep === DeviceOnboardingStep.WelcomeScreen1 - ) { - // device was already seeded, switch to the apps step - if (hasBackupStep) { - __DEV__ ? setStepKey(StepKey.Backup) : setStepKey(StepKey.Apps); // for ease of testing in dev mode without having to reset the device - } else { - setStepKey(StepKey.Apps); - } - seededDeviceHandled.current = true; - return; - } + if ( + deviceOnboardingState?.isOnboarded && + !seededDeviceHandled.current && + [DeviceOnboardingStep.Ready, DeviceOnboardingStep.WelcomeScreen1].includes( + deviceOnboardingState.currentOnboardingStep, + ) + ) { + setStepKey(StepKey.Apps); + seededDeviceHandled.current = true; + return; } // case DeviceOnboardingStep.SafetyWarning not handled so the previous step (new seed, restore, recover) is kept @@ -427,7 +399,7 @@ const SyncOnboardingCompanion: React.FC = ({ default: break; } - }, [deviceOnboardingState, hasBackupStep, notifySyncOnboardingShouldReset]); + }, [deviceOnboardingState, notifySyncOnboardingShouldReset]); // When the user gets close to the seed generation step, sets the lost synchronization delay // and timers to a higher value. It avoids having a warning message while the connection is lost diff --git a/apps/ledger-live-desktop/src/renderer/components/TopBar/NotificationIndicator/AnnouncementPanel.tsx b/apps/ledger-live-desktop/src/renderer/components/TopBar/NotificationIndicator/AnnouncementPanel.tsx index 8984e3fc4307..4a26d6a32dbc 100644 --- a/apps/ledger-live-desktop/src/renderer/components/TopBar/NotificationIndicator/AnnouncementPanel.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/TopBar/NotificationIndicator/AnnouncementPanel.tsx @@ -15,7 +15,7 @@ import { useNotifications } from "~/renderer/hooks/useNotifications"; import TrackPage from "~/renderer/analytics/TrackPage"; import { urls } from "~/config/urls"; import { useDateFormatted } from "~/renderer/hooks/useDateFormatter"; -import LogContentCardWrapper from "LLD/components/DynamicContent/LogContentCardWrapper"; +import LogContentCardWrapper from "LLD/features/DynamicContent/components/LogContentCardWrapper"; const DateRowContainer = styled.div` padding: 4px 16px; diff --git a/apps/ledger-live-desktop/src/renderer/drawers/SwapOperationDetails/index.tsx b/apps/ledger-live-desktop/src/renderer/drawers/SwapOperationDetails/index.tsx index e917713c05ec..59424e618989 100644 --- a/apps/ledger-live-desktop/src/renderer/drawers/SwapOperationDetails/index.tsx +++ b/apps/ledger-live-desktop/src/renderer/drawers/SwapOperationDetails/index.tsx @@ -255,9 +255,9 @@ const SwapOperationDetails = ({ - + - {swapId} + diff --git a/apps/ledger-live-desktop/src/renderer/families/internet_computer/SendAmountFields.tsx b/apps/ledger-live-desktop/src/renderer/families/internet_computer/SendAmountFields.tsx index 1121538918e8..88de2fa29d5c 100644 --- a/apps/ledger-live-desktop/src/renderer/families/internet_computer/SendAmountFields.tsx +++ b/apps/ledger-live-desktop/src/renderer/families/internet_computer/SendAmountFields.tsx @@ -5,6 +5,7 @@ import { TransactionStatus, } from "@ledgerhq/live-common/families/internet_computer/types"; import { Account } from "@ledgerhq/types-live"; +import { useFeature } from "@ledgerhq/live-common/featureFlags/index"; const Root = (props: { account: Account; @@ -13,6 +14,10 @@ const Root = (props: { onChange: (a: Transaction) => void; trackProperties?: object; }) => { + const lldMemoTag = useFeature("lldMemoTag"); + + if (lldMemoTag?.enabled) return null; + return ; }; diff --git a/apps/ledger-live-desktop/src/renderer/families/internet_computer/SendRecipientFields.tsx b/apps/ledger-live-desktop/src/renderer/families/internet_computer/SendRecipientFields.tsx new file mode 100644 index 000000000000..31440a6b21f4 --- /dev/null +++ b/apps/ledger-live-desktop/src/renderer/families/internet_computer/SendRecipientFields.tsx @@ -0,0 +1,21 @@ +import React from "react"; +import Box from "~/renderer/components/Box"; +import MemoField from "./MemoField"; +import { useFeature } from "@ledgerhq/live-common/featureFlags/index"; +import { InternetComputerMemoFieldProps } from "./types"; + +const Root = (props: InternetComputerMemoFieldProps) => { + const lldMemoTag = useFeature("lldMemoTag"); + + if (!lldMemoTag?.enabled) return null; + + return ( + + + + ); +}; +export default { + component: Root, + fields: ["memo"], +}; diff --git a/apps/ledger-live-desktop/src/renderer/families/internet_computer/index.ts b/apps/ledger-live-desktop/src/renderer/families/internet_computer/index.ts index 08bd1a8dba79..662456918a11 100644 --- a/apps/ledger-live-desktop/src/renderer/families/internet_computer/index.ts +++ b/apps/ledger-live-desktop/src/renderer/families/internet_computer/index.ts @@ -8,11 +8,13 @@ import operationDetails from "./operationDetails"; import AccountSubHeader from "./AccountSubHeader"; import sendAmountFields from "./SendAmountFields"; import { Account } from "@ledgerhq/types-live"; +import sendRecipientFields from "./SendRecipientFields"; const family: LLDCoinFamily = { operationDetails, AccountSubHeader, sendAmountFields, + sendRecipientFields, }; export default family; diff --git a/apps/ledger-live-desktop/src/renderer/families/internet_computer/types.ts b/apps/ledger-live-desktop/src/renderer/families/internet_computer/types.ts new file mode 100644 index 000000000000..7b51f75d4fcb --- /dev/null +++ b/apps/ledger-live-desktop/src/renderer/families/internet_computer/types.ts @@ -0,0 +1,13 @@ +import { + Transaction, + TransactionStatus, +} from "@ledgerhq/live-common/families/internet_computer/types"; +import { Account } from "@ledgerhq/types-live"; + +export type InternetComputerMemoFieldProps = { + account: Account; + transaction: Transaction; + status: TransactionStatus; + onChange: (a: Transaction) => void; + trackProperties?: object; +}; diff --git a/apps/ledger-live-desktop/src/renderer/families/solana/DelegationActivateFlowModal/steps/StepValidator.tsx b/apps/ledger-live-desktop/src/renderer/families/solana/DelegationActivateFlowModal/steps/StepValidator.tsx index 4010646b7906..072f1402d32c 100644 --- a/apps/ledger-live-desktop/src/renderer/families/solana/DelegationActivateFlowModal/steps/StepValidator.tsx +++ b/apps/ledger-live-desktop/src/renderer/families/solana/DelegationActivateFlowModal/steps/StepValidator.tsx @@ -7,7 +7,7 @@ import Box from "~/renderer/components/Box"; import Button from "~/renderer/components/Button"; import ErrorBanner from "~/renderer/components/ErrorBanner"; import ErrorDisplay from "../../shared/components/ErrorDisplay"; -import LedgerByFigmentTC from "../../shared/components/LedgerByFigmentTCLink"; +import LedgerValidatorTCLink from "../../shared/components/LedgerValidatorTCLink"; import ValidatorsField from "../../shared/fields/ValidatorsField"; import { StepProps } from "../types"; export default function StepValidator({ @@ -72,7 +72,8 @@ export function StepValidatorFooter({ if (!transaction) return null; return ( <> - + + - @@ -145,7 +166,7 @@ const Collections = ({ account }: Props) => { )} - {collections.length > numberOfVisibleCollections ? ( + {filteredCollections.length > numberOfVisibleCollections ? ( diff --git a/apps/ledger-live-desktop/src/renderer/screens/nft/Gallery/Gallery.tsx b/apps/ledger-live-desktop/src/renderer/screens/nft/Gallery/Gallery.tsx index 3a2d838c84ed..0fbcd156f222 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/nft/Gallery/Gallery.tsx +++ b/apps/ledger-live-desktop/src/renderer/screens/nft/Gallery/Gallery.tsx @@ -4,6 +4,7 @@ import { useSelector, useDispatch } from "react-redux"; import { useTranslation } from "react-i18next"; import { accountSelector } from "~/renderer/reducers/accounts"; import { openModal } from "~/renderer/actions/modals"; +import { nftsByCollections } from "@ledgerhq/live-nft"; import styled from "styled-components"; import IconSend from "~/renderer/icons/Send"; import CollectionName from "~/renderer/components/Nft/CollectionName"; @@ -18,7 +19,9 @@ import { State } from "~/renderer/reducers"; import { ProtoNFT } from "@ledgerhq/types-live"; import theme from "@ledgerhq/react-ui/styles/theme"; import { useOnScreen } from "../useOnScreen"; -import { useNftCollections } from "~/renderer/hooks/nfts/useNftCollections"; +import { isThresholdValid, useNftGalleryFilter } from "@ledgerhq/live-nft-react"; +import { useFeature } from "@ledgerhq/live-common/featureFlags/index"; +import { useNftCollectionsStatus } from "~/renderer/hooks/nfts/useNftCollectionsStatus"; const SpinnerContainer = styled.div` display: flex; @@ -49,7 +52,8 @@ const Footer = styled.footer` `; const Gallery = () => { - const history = useHistory(); + const nftsFromSimplehashFeature = useFeature("nftsFromSimplehash"); + const thresold = nftsFromSimplehashFeature?.params?.threshold; const { t } = useTranslation(); const dispatch = useDispatch(); const { id } = useParams<{ id: string }>(); @@ -58,11 +62,27 @@ const Gallery = () => { accountId: id, }), ); + const history = useHistory(); + const { hiddenNftCollections } = useNftCollectionsStatus(); - const { fetchNextPage, hasNextPage, collections } = useNftCollections({ - account, + const { nfts, fetchNextPage, hasNextPage } = useNftGalleryFilter({ + nftsOwned: account?.nfts || [], + addresses: account?.freshAddress || "", + chains: [account?.currency.id ?? "ethereum"], + threshold: isThresholdValid(thresold) ? Number(thresold) : 75, + enabled: nftsFromSimplehashFeature?.enabled || false, + staleTime: nftsFromSimplehashFeature?.params?.staleTime, }); + const INITIAL_INCREMENT = nftsFromSimplehashFeature?.enabled ? 50 : 5; + + const collections = useMemo( + () => + Object.entries( + nftsByCollections(nftsFromSimplehashFeature?.enabled ? nfts : account?.nfts), + ).filter(([contract]) => !hiddenNftCollections.includes(`${account?.id}|${contract}`)), + [account?.id, account?.nfts, hiddenNftCollections, nfts, nftsFromSimplehashFeature?.enabled], + ); // Should redirect to the account page if there is not NFT anymore in the page. useEffect(() => { if (collections.length <= 0) { @@ -86,9 +106,9 @@ const Gallery = () => { [account?.id, history], ); const listFooterRef = useRef(null); - const [maxVisibleNFTs, setMaxVisibleNFTs] = useState(1); + const [maxVisibleNFTs, setMaxVisibleNFTs] = useState(INITIAL_INCREMENT); const updateMaxVisibleNtfs = () => { - setMaxVisibleNFTs(maxVisibleNFTs => maxVisibleNFTs + 5); + setMaxVisibleNFTs(maxVisibleNFTs => maxVisibleNFTs + INITIAL_INCREMENT); if (hasNextPage) { fetchNextPage(); } diff --git a/apps/ledger-live-desktop/src/renderer/screens/nft/Send/SelectNFT.tsx b/apps/ledger-live-desktop/src/renderer/screens/nft/Send/SelectNFT.tsx index fb95b323c5f0..9b760747d6c7 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/nft/Send/SelectNFT.tsx +++ b/apps/ledger-live-desktop/src/renderer/screens/nft/Send/SelectNFT.tsx @@ -1,10 +1,9 @@ import React, { useMemo, useEffect, useCallback, useState } from "react"; -import { useSelector } from "react-redux"; import { Account, NFT, ProtoNFT } from "@ledgerhq/types-live"; import { nftsByCollections } from "@ledgerhq/live-nft"; -import { hiddenNftCollectionsSelector } from "~/renderer/reducers/settings"; import Select from "~/renderer/components/Select"; import Option from "./Option"; +import { useNftCollectionsStatus } from "~/renderer/hooks/nfts/useNftCollectionsStatus"; const SelectNFT = ({ onSelect, maybeNFTId, @@ -19,7 +18,7 @@ const SelectNFT = ({ const [token, setToken] = useState(null); // @ts-expect-error impossible to type this, we need to bump react-select to v5 const getOptionValue = useCallback(item => item, []); - const hiddenNftCollections = useSelector(hiddenNftCollectionsSelector); + const { hiddenNftCollections } = useNftCollectionsStatus(); const filteredNFTs = useMemo( () => maybeNFTCollection diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Accounts/HiddenNFTCollections/index.tsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Accounts/HiddenNFTCollections/index.tsx index 3c8bbd83d1fa..71003e929148 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Accounts/HiddenNFTCollections/index.tsx +++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Accounts/HiddenNFTCollections/index.tsx @@ -2,8 +2,8 @@ import React, { useState, useCallback, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useTranslation } from "react-i18next"; import styled from "styled-components"; -import { unhideNftCollection, whitelistNftCollection } from "~/renderer/actions/settings"; -import { hiddenNftCollectionsSelector } from "~/renderer/reducers/settings"; +import { updateNftStatus } from "~/renderer/actions/settings"; +import { nftCollectionsStatusByNetworkSelector } from "~/renderer/reducers/settings"; import { SettingsSection as Section, SettingsSectionRow as Row } from "../../../SettingsSection"; import Box from "~/renderer/components/Box"; @@ -13,6 +13,8 @@ import ShowMore from "LLD/features/Collectibles/components/Collection/ShowMore"; import IconAngleDown from "~/renderer/icons/AngleDown"; import { HiddenNftCollectionRow } from "./row"; import { decodeCollectionId } from "@ledgerhq/live-nft-react"; +import { NftStatus } from "@ledgerhq/live-nft/types"; +import { BlockchainEVM, BlockchainsType } from "@ledgerhq/live-nft/supported"; // Styled components and layout @@ -39,14 +41,24 @@ export default function HiddenNftCollections() { const dispatch = useDispatch(); const [sectionVisible, setSectionVisible] = useState(false); - const hiddenNftCollections = useSelector(hiddenNftCollectionsSelector); + const collections = useSelector(nftCollectionsStatusByNetworkSelector); + + const hiddenNftCollections = useMemo( + () => + Object.values(collections).flatMap(network => + Object.keys(network).filter( + collection => + network[collection] === NftStatus.blacklisted || network[collection] === NftStatus.spam, + ), + ), + [collections], + ); const [numberOfVisibleCollections, setNumberOfVisibleCollections] = useState(INCREMENT); const onUnhideCollection = useCallback( - (collectionId: string) => { - dispatch(unhideNftCollection(collectionId)); - dispatch(whitelistNftCollection(collectionId)); + (collectionId: string, blockchain: BlockchainsType) => { + dispatch(updateNftStatus(blockchain, collectionId, NftStatus.whitelisted)); }, [dispatch], ); @@ -96,12 +108,16 @@ export default function HiddenNftCollections() { {visibleCollections.map(collectionId => { const { accountId, contractAddress } = decodeCollectionId(collectionId); + const network = (Object.keys(collections).find( + key => collections[key as BlockchainEVM][collectionId], + ) ?? BlockchainEVM.Ethereum) as BlockchainsType; return ( onUnhideCollection(collectionId)} + onUnhide={() => onUnhideCollection(collectionId, network)} + network={network} /> ); })} diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Accounts/HiddenNFTCollections/row.tsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Accounts/HiddenNFTCollections/row.tsx index 477f1958481f..044a39375610 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Accounts/HiddenNFTCollections/row.tsx +++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Accounts/HiddenNFTCollections/row.tsx @@ -15,15 +15,19 @@ import { Flex, Icons } from "@ledgerhq/react-ui"; import IconCross from "~/renderer/icons/Cross"; import styled from "styled-components"; import { splitAddress } from "./helpers"; +import { getCryptoCurrencyById } from "@ledgerhq/live-common/currencies/index"; +import CryptoCurrencyIcon from "~/renderer/components/CryptoCurrencyIcon"; export const HiddenNftCollectionRow = ({ contractAddress, accountId, onUnhide, + network, }: { contractAddress: string; accountId: string; onUnhide: () => void; + network: string; }) => { const { t } = useTranslation(); const account = useSelector((state: State) => accountSelector(state, { accountId })); @@ -74,10 +78,12 @@ export const HiddenNftCollectionRow = ({ - - {splitAddress(contractAddress, 8)} - - + + + {splitAddress(contractAddress, 8)} + + + {!copyFeedback ? ( ) : ( diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/BrazeTools/Hooks/useGenerateLocalBraze.ts b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/BrazeTools/Hooks/useGenerateLocalBraze.ts index 0f3e68bbdc2e..e652a3a78b06 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/BrazeTools/Hooks/useGenerateLocalBraze.ts +++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/BrazeTools/Hooks/useGenerateLocalBraze.ts @@ -22,6 +22,8 @@ const generateNewPortfolioCard = ( image: string, order?: number, url?: string, + cta?: string, + tag?: string, ): PortfolioContentCard => ({ id: String(Date.now()), title, @@ -29,10 +31,11 @@ const generateNewPortfolioCard = ( location: LocationContentCard.Portfolio, image, created: new Date(), - onClickOnSlide: () => {}, order, isMock: true, url, + cta, + tag, }); const generateNewActionCard = ( @@ -92,8 +95,10 @@ export const useGenerateLocalBraze = () => { image: string, order?: number, url?: string, + cta?: string, + tag?: string, ) => { - const newCard = generateNewPortfolioCard(title, description, image, order, url); + const newCard = generateNewPortfolioCard(title, description, image, order, url, cta, tag); dispatch(setPortfolioCards([...portfolioCards, newCard])); }; diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/BrazeTools/Modal/Body.tsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/BrazeTools/Modal/Body.tsx index 391d827ecac4..8b3159854a67 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/BrazeTools/Modal/Body.tsx +++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/BrazeTools/Modal/Body.tsx @@ -28,6 +28,7 @@ interface FormState { link: string; secondaryCta: string; cta: string; + tag?: string; url: string; path: string; order?: number; @@ -70,10 +71,10 @@ export const ModalBody: React.FC = () => { useGenerateLocalBraze(); const handleAddCard = () => { - const { title, description, image, mainCta, link, secondaryCta, cta, url, path, order } = + const { title, description, image, mainCta, link, secondaryCta, cta, tag, url, path, order } = formData; if (selectedTab === "PortfolioContentCard") { - addLocalPortfolioCard(title, description, image, order, url); + addLocalPortfolioCard(title, description, image, order, url, cta, tag); } else if (selectedTab === "ActionContentCard") { addLocalActionCard(title, description, image, mainCta, link, secondaryCta, order); } else if (selectedTab === "NotificationContentCard") { @@ -131,6 +132,16 @@ export const ModalBody: React.FC = () => { placeholder: "URL", label: t("settings.developer.brazeTools.modal.fields.url"), }, + { + field: "cta", + placeholder: "CTA", + label: t("settings.developer.brazeTools.modal.fields.cta"), + }, + { + field: "tag", + placeholder: "TAG", + label: t("settings.developer.brazeTools.modal.fields.tag"), + }, ], ActionContentCard: [ { diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/SimpleHashTools/SpamScore/index.tsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/SimpleHashTools/SpamScore/index.tsx index 76bc9e4cf834..c5a8b392cb99 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/SimpleHashTools/SpamScore/index.tsx +++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/SimpleHashTools/SpamScore/index.tsx @@ -72,7 +72,7 @@ export default function SpamScore(props: HookResult) { return (error as Error).message; }; - const getScore = (data?: SimpleHashResponse) => data?.nfts[0].collection.spam_score; + const getScore = (data?: SimpleHashResponse) => data?.nfts[0]?.collection.spam_score || 100; const text = checkSpamScore.isError ? getErrorText(checkSpamScore.error) diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/General/MarketPerformanceWidget.tsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/General/MarketPerformanceWidget.tsx index e2d736c72baa..afb8ef00822c 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/General/MarketPerformanceWidget.tsx +++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/General/MarketPerformanceWidget.tsx @@ -1,27 +1,44 @@ -import React from "react"; +import React, { useCallback } from "react"; import Switch from "~/renderer/components/Switch"; -import { useFeatureFlags } from "@ledgerhq/live-common/featureFlags/index"; import Track from "~/renderer/analytics/Track"; +import { useSelector, useDispatch } from "react-redux"; +import { setMarketWidget } from "~/renderer/actions/settings"; +import { track } from "~/renderer/analytics/segment"; +import { marketPerformanceWidgetSelector } from "~/renderer/reducers/settings"; + const MarketPerformanceWidgetRow = () => { - const featureFlagsProvider = useFeatureFlags(); + const marketWidgetValue = useSelector(marketPerformanceWidgetSelector); - const currentValue = Boolean( - featureFlagsProvider.getFeature("marketperformanceWidgetDesktop")?.enabled, - ); + const dispatch = useDispatch(); - const update = (value: boolean) => { - featureFlagsProvider.overrideFeature("marketperformanceWidgetDesktop", { enabled: value }); - }; + const toggle = useCallback( + (value: boolean) => { + dispatch(setMarketWidget(value)); + + track( + "toggle_clicked", + { + toggleAction: value ? "ON" : "OFF", + toggle: "MarketPerformanceWidget", + page: "Page Settings General", + }, + true, + ); + }, + [dispatch], + ); return ( <> - update(!currentValue)} /> + toggle(!marketWidgetValue)} /> ); }; diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/General/index.tsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/General/index.tsx index 4ec217924ca2..5e81b0d0437d 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/General/index.tsx +++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/General/index.tsx @@ -69,13 +69,15 @@ const SectionGeneral = () => { - - - + + + + + diff --git a/apps/ledger-live-desktop/src/types/dynamicContent.ts b/apps/ledger-live-desktop/src/types/dynamicContent.ts index f9be5782ecb1..8b19e2da390e 100644 --- a/apps/ledger-live-desktop/src/types/dynamicContent.ts +++ b/apps/ledger-live-desktop/src/types/dynamicContent.ts @@ -34,19 +34,9 @@ export type NotificationContentCard = ContentCard & { }; export type PortfolioContentCard = ContentCard & { - id: string; - location?: LocationContentCard; - imgs?: { - source: string; - transform: [number, number, number, number]; - size: { width: number; height: number }; - }[]; - title: React.ReactNode; - description: React.ReactNode; url?: string; path?: string; image?: string; - onClickOnSlide?: (cardId: string) => void; - order?: number; - created: Date; + cta?: string; + tag?: string; }; diff --git a/apps/ledger-live-desktop/static/i18n/ar/app.json b/apps/ledger-live-desktop/static/i18n/ar/app.json index 5ed951aaec68..9aa456e03f07 100644 --- a/apps/ledger-live-desktop/static/i18n/ar/app.json +++ b/apps/ledger-live-desktop/static/i18n/ar/app.json @@ -1139,7 +1139,7 @@ "send" : "إرسال", "swap" : "مبادلة", "stake" : "تكديس", - "earn" : "Earn", + "earn" : "اكسب", "yield" : "العائد", "buy" : "شراء", "sell" : "بيع", @@ -1486,7 +1486,7 @@ }, "earn" : { "title" : "تكديس", - "description" : "Get rewards on your crypto" + "description" : "احصل على مكافآت على أصولك المشفرة" } }, "recoverBanner" : { @@ -3037,6 +3037,7 @@ "validatorGroup" : { "title" : "مجموعة المدققين", "ledgerByFigmentTC" : "شروط وأحكام Ledger by Figment", + "ledgerByChorusOneTC" : "شروط وأحكام Ledger by Chorus One", "totalVotes" : "مجموع الأصوات", "commission" : "العمولة" } @@ -3626,6 +3627,7 @@ "withdrawableTitle" : "قابل للسحب", "statusUpdateNotice" : "ستُحدّث حالة التفويض عندما يتم تأكيد المعاملة.", "ledgerByFigmentTC" : "شروط وأحكام Ledger by Figment", + "ledgerByChorusOneTC" : "شروط وأحكام Ledger by Chorus One", "emptyState" : { "description" : "يمكنك كسب مكافآت SOL عن طريق تفويض أصولك.", "info" : "كيف يعمل التفويض", @@ -3880,6 +3882,7 @@ }, "validator" : { "title" : "المدققون", + "ledgerByChorusOneTC" : "شروط وأحكام Ledger by Chorus One", "ledgerByFigmentTC" : "شروط وأحكام Ledger by Figment" }, "connectDevice" : { @@ -4147,6 +4150,7 @@ "link" : "الرابط", "secondaryCta" : "CTA الثانوي", "cta" : "CTA", + "tag" : "علامة", "url" : "عنوان URL", "path" : "المسار" } diff --git a/apps/ledger-live-desktop/static/i18n/de/app.json b/apps/ledger-live-desktop/static/i18n/de/app.json index 707bbce1b6f1..49224a4d79c2 100644 --- a/apps/ledger-live-desktop/static/i18n/de/app.json +++ b/apps/ledger-live-desktop/static/i18n/de/app.json @@ -41,7 +41,7 @@ }, "banner" : { "title" : "Live-Apps-Katalog entdecken", - "description" : "Wir arbeiten hart daran, Ihnen Zugang zur Welt von DeFi, NFTs und mehr zu verschaffen, sicher, direkt in Ledger Live!" + "description" : "Mit Ledger Live erhältst du sicheren Zugriff auf DeFi, NFTs und mehr!" }, "twitterBanner" : { "description" : "Sag uns, welchen Service du dir als nächstes in Ledger Live wünschst – unter folgendem Hashtag:", @@ -66,7 +66,7 @@ "disclaimer" : { "title" : "Externe Anwendung", "description" : "Du wirst gleich zu einer Anwendung weitergeleitet, die nicht von Ledger betrieben wird.", - "legalAdvice" : "Diese Anwendung wird nicht von Ledger betrieben. Ledger ist nicht verantwortlich für den Verlust von Geldern oder die Qualität des Dienstes einer solchen Anwendung. \n\nAchte immer darauf, die auf deinem Gerät angezeigten Informationen sorgfältig zu überprüfen.", + "legalAdvice" : "Diese Anwendung wird nicht von Ledger betrieben. Ledger ist nicht verantwortlich für den Verlust von Vermögenswerten oder die Qualität des Dienstes einer solchen Anwendung. \n\nAchte immer darauf, die auf deinem Gerät angezeigten Informationen sorgfältig zu verifizieren.", "checkbox" : "Nicht erneut erinnern.", "CTA" : "Weiter" } @@ -143,7 +143,7 @@ }, "exchange" : "Umtauschen", "info" : "Informationen", - "connectDevice" : "Gerät verbinden", + "connectDevice" : "Verbinde dein Gerät", "add" : "Hinzufügen", "or" : "ODER", "clearAll" : "Alle löschen", @@ -246,7 +246,7 @@ "error" : { "notEnoughFundsToCancel" : "Die Stornierung der Transaktion ist nicht möglich, da dein Konto nicht genügend Guthaben aufweist.", "notEnoughFundsToSpeedup" : "Die Beschleunigung der Transaktion ist nicht möglich, da dein Konto nicht genügend Guthaben aufweist.", - "notlowestNonceToSpeedup" : "Die Funktion „Speed up“ (Beschleunigen) ist nicht verfügbar. Deine Transaktion ist ausstehend, da eine vorherige Transaktion zurzeit nicht reagiert. Du kannst auf die Bestätigung der Transaktion warten, sie beschleunigen oder sie stornieren." + "notlowestNonceToSpeedup" : "Die Funktion „Speed up“ (Beschleunigen) ist nicht verfügbar. Deine Transaktion ist ausstehend, da eine vorherige Transaktion zurzeit nicht reagiert. Du kannst auf die Bestätigung der Transaktion warten, sie beschleunigen oder sie abbrechen." } } }, @@ -313,7 +313,7 @@ "history" : "Verlauf" }, "form" : { - "changeCTA" : "Änderung", + "changeCTA" : "Ändern", "rates" : { "title" : "Preise", "registration" : "Anmeldung erforderlich ", @@ -330,7 +330,7 @@ }, "rate" : { "title" : "Wechselkurs", - "tooltip" : "Ein <0>variabler Wechselkurs<0> schwankt je nach den Marktbedingungen. Das bedeutet, dass du mehr oder weniger als geschätzt erhalten könntest.

Bei einem <0>Festkurs<0> dagegen wird der Betrag erzielt, der zu Beginn des Umtauschs angezeigt wird." + "tooltip" : "Ein <0>variabler Wechselkurs schwankt je nach den Marktbedingungen. Das bedeutet, dass du mehr oder weniger als geschätzt erhalten könntest.

Bei einem <0>Festkurs dagegen wird der Betrag erzielt, der zu Beginn des Umtauschs angezeigt wird." }, "receive" : { "title" : "Empfangen", @@ -405,10 +405,10 @@ "title" : "Swappen", "titleCrypto" : "{{currency}} tauschen", "whatIsSwap" : "Was bedeutet Swappen?", - "decentralizedSwapAvailable" : "Für einige Transaktionen kannst du dezentrales Swappen verwenden. Entdecke <0>ParaSwap und <1>1inch.", + "decentralizedSwapAvailable" : "Für einige Transaktionen kannst du den dezentralen Umtausch verwenden. Entdecke <0>ParaSwap und <1>1inch.", "paraswap" : { "cta" : " Mehr erfahren", - "description" : "Suchst du nach Paraswap? Es wurde auf den Entdecken-Tab verschoben." + "description" : "Suchst du nach ParaSwap? Das wurde auf den Entdecken-Tab verschoben." }, "tabs" : { "exchange" : "Umtauschen", @@ -482,7 +482,7 @@ "fixed" : "Fester Wechselkurs", "fixedUnavailable" : "Fester Kurs wird für diese Paarung nicht unterstützt", "floatDesc" : "Dein Betrag kann sich je nach Marktbedingungen möglicherweise ändern.", - "fixedDesc" : "Dein Betrag bleibt auch dann unverändert, wenn sich der Markt ändert. Aktualisiert alle 60 Sekunden.", + "fixedDesc" : "Dein Betrag bleibt auch dann unverändert, wenn sich der Markt ändert. Die Aktualisierung erfolgt alle 60 Sekunden.", "by" : "Bereitgestellt von" }, "exchange" : "Umtauschen", @@ -526,7 +526,7 @@ "finished" : { "title" : "Ausstehend", "subtitle" : "Swap-Übertragung erfolgreich ", - "swap" : "Ihre Swap-ID:", + "swap" : "Deine Swap-ID:", "seeDetails" : "Details ansehen", "disclaimer" : "Notiere dir die Swap-ID für den Fall, dass du Hilfe vom <0><0>{{provider}}<0>-Support<0> benötigst.", "description" : "Dein Swap wurde zur Bestätigung an das Netzwerk gesendet. Es kann bis zu einer Stunde dauern, bis du deine {{targetCurrency}} erhältst." @@ -622,7 +622,7 @@ "disconnectTitle" : "Full Node trennen", "steps" : { "landing" : { - "header" : "Starte deinen eigenen Full Node: Nicht vertrauen, überprüfen!", + "header" : "Starte deinen Full Node. Vertrauen ist gut, Kontrolle ist besser.", "description" : "Ein Bitcoin-Knoten (Full Node) ist ein Computer, der alle Transaktionen und Blöcke validiert. Er ermöglicht es Ihnen, Bitcoin ohne die Notwendigkeit vertrauenswürdiger Dritter zu nutzen und gleichzeitig zum Bitcoin-Netzwerk beizutragen.", "list" : { "item1" : "Bitcoin Core auf einem Gerät mit ausreichenden Ressourcen einrichten.", @@ -677,7 +677,7 @@ }, "success" : { "header" : "Konten zur Knotenkonfiguration hinzugefügt", - "description" : "Eine Konfigurationsdatei wurde im Benutzerdatenordner gespeichert. Sie ermöglicht es Ledger SatStack, sich mit deinem Knoten (Full Node) zu verbinden und ihn nach deinen Konten auf der Blockchain suchen zu lassen.", + "description" : "Eine Konfigurationsdatei wurde im Benutzerdatenordner gespeichert. Sie ermöglicht es Ledger SatStack, sich mit deinem Full Node zu verbinden und ihn nach deinen Konten auf der Blockchain suchen zu lassen.", "cta" : "Benutzerdaten anzeigen" } } @@ -687,15 +687,15 @@ "existing" : "Bestehende Konten zum Scannen", "toScan" : "Zu scannende Konten", "toScanDescription" : "Nach jedem Adresstyp zu durchsuchende Konten", - "toScanTooltip" : "Nur erhöhen, wenn du mindestens 10 BTC-Konten hast. Der anfängliche Scan wird langsamer sein. " + "toScanTooltip" : "Erhöhe den Wert nur, wenn du mehr als 10 BTC-Konten hast. Der Erstscan wird dann länger dauern. " }, "satstack" : { "title" : "SatStack", "connectionSteps" : { "notConnected" : { "header" : "Ledger SatStack herunterladen und ausführen", - "description" : "Ledger SatStack ist eine kleine Anwendung, die es Ledger Live ermöglicht, mit deinem Knoten (Full Node) zu kommunizieren. Bitte lade die Anwendung herunter und starte sie, bevor du den Vorgang fortsetzt.", - "disclaimer" : "SatStack muss ausgeführt werden, damit Ledger Live eine Verbindung zu deinem Knoten (Full Node) herstellen kann. Du könntest darüber nachdenken, SatStack so zu konfigurieren, dass es gemeinsam mit deinem Computer automatisch gestartet wird.", + "description" : "Ledger SatStack ist eine kleine Anwendung, die es Ledger Live ermöglicht, mit deinem Full Node zu kommunizieren. Bitte lade die Anwendung herunter und starte sie, bevor du den Vorgang fortsetzt.", + "disclaimer" : "SatStack muss ausgeführt werden, damit Ledger Live eine Verbindung mit deinem Full Node herstellen kann. Erwäge, SatStack so zu konfigurieren, dass es gemeinsam mit deinem Computer automatisch gestartet wird.", "cta" : "SatStack herunterladen" }, "satstack-disconnected" : { @@ -734,7 +734,7 @@ }, "disconnect" : { "cta" : "Trennen", - "description" : "Möchtest du den Vorgang wirklich fortsetzen? Das Trennen des Knotens (Full Node) entfernt alle Bitcoin-Konten. Du kannst deine Konten mit den Explorern von Ledger wieder hinzufügen." + "description" : "Möchtest du den Vorgang wirklich fortsetzen? Das Trennen des Full Node entfernt alle Bitcoin-Konten. Du kannst deine Konten mit den Explorern von Ledger wieder hinzufügen." } } } @@ -762,7 +762,7 @@ "emptyState" : { "title" : "Noch keine Krypto-Werte?", "desc" : "Stelle sicher, dass die <1><0>{{managerAppName}}-App installiert ist, und beginne mit dem Empfang von", - "descToken" : "Stelle sicher, dass die <1><0>{{managerAppName}}App installiert ist, und empfange <3><0>{{ticker}}und <5><0>{{tokenList}}Token", + "descToken" : "Stelle sicher, dass die <1><0>{{managerAppName}}App installiert ist, und empfange <3><0>{{ticker}}und <5><0>{{tokenList}}Token</5>", "buttons" : { "receiveFunds" : "Empfangen", "buy" : "Kaufen" @@ -789,41 +789,41 @@ "delegatedAssets" : "Delegierte Vermögenswerte", "undelegating" : "Delegierung aufheben", "availableBalanceTooltip" : "Dieser Betrag ist verfügbar.", - "frozenAssetsTooltip" : "Gesperrte Vermögenswerte werden bei der Tron-Abstimmung verwendet. Diese stellen Ihre Gesamtanzahl an Stimmen dar.", + "frozenAssetsTooltip" : "Gesperrte Vermögenswerte werden beim Tron-Voting verwendet. Dies ist die Gesamtzahl deiner Votes.", "bandwidthTooltip" : "Vermögenswerte sperren, um Bandbreite zu gewinnen", "energyTooltip" : "Vermögenswerte sperren, um Energie zu gewinnen", - "delegatedTooltip" : "Delegierte Vermögenswerte werden im Abstimmungsprozess verwendet. Dies entspricht Ihrer Gesamtzahl an Stimmen.", + "delegatedTooltip" : "Delegierte Vermögenswerte werden beim Voting-Prozess verwendet. Dies ist die Gesamtzahl deiner Votes.", "undelegatingTooltip" : "Nicht delegierte Vermögenswerte werden erst nach einer Sperrfrist von {{timelockInDays}} Tagen verfügbar.", "claimableRewards" : "Verfügbare Belohnungen", "claimableRewardsTooltip" : "Momentan können USDC-Belohnungen nicht eingefordert werden. Bitte nutze hierfür eine Wallet von einem Drittanbieter", "banner" : { "redelegation" : { "title" : "Schon gewusst?", - "description" : "Der Ledger-Validator erledigt das Staking zu einer günstigeren Provision als Ihr derzeitiger Validator.", + "description" : "Der Ledger-Validator erledigt das Staking zu einer günstigeren Provision als dein derzeitiger Validator.", "cta" : "Mit Ledger erneut delegieren", "linkText" : "Was ist eine Redelegation und wie lange dauert sie?", "solana" : { "title" : "Schon gewusst?", - "description" : "Ledger bietet einen niedrigeren Provisionssatz als Ihr Validator. Dieser Vorgang kann bis zu 4 Tage dauern." + "description" : "Ledger bietet einen niedrigeren Provisionssatz als dein Validator. Dieser Vorgang kann bis zu 4 Tage dauern." }, "near" : { "title" : "Schon gewusst?", - "description" : "Ledger bietet einen niedrigeren Provisionssatz als Ihr Validator. Dieser Vorgang kann bis zu 65 Stunden dauern." + "description" : "Ledger bietet einen niedrigeren Provisionssatz als dein Validator. Dieser Vorgang kann bis zu 65 Stunden dauern." }, "elrond" : { "title" : "Schon gewusst?", - "description" : "Ledger bietet einen niedrigeren Provisionssatz als Ihr Validator. Dieser Vorgang kann bis zu 10 Tage dauern." + "description" : "Ledger bietet einen niedrigeren Provisionssatz als dein Validator. Dieser Vorgang kann bis zu 10 Tage dauern." } }, "delegation" : { "title" : "Schon gewusst?", - "description" : "Der Ledger-Validator erledigt das Staking Ihrer {{asset}} zu einer Provision in Höhe von {{commission}} %.", + "description" : "Der Ledger-Validator erledigt das Staking deiner {{asset}} zu einer Provision in Höhe von {{commission}} %.", "cta" : "Mit Ledger staken", "linkText" : "Weitere Informationen", "ethereum" : { "lido" : { "title" : "Schon gewusst?", - "description" : "Stake deine Ethereum mit Lido und verdiene täglich Belohnungen. Keine Sperrfrist, keine Mindesteinlage.", + "description" : "Stake dein Ethereum mit Lido und verdiene täglich Prämien. Keine Sperrfrist. Keine Mindesteinzahlung.", "cta" : "Staking mit Lido" }, "kiln" : { @@ -892,7 +892,7 @@ "currencyAPY" : "Währung APY", "currencyAPYTooltip" : "Jährliche Rendite einer Einlage, die kontinuierlich aufgezinst wird", "accruedInterests" : "Aufgelaufene Zinsen", - "accruedInterestsTooltip" : "Zinserträge auf Ihr verliehenes Vermögen", + "accruedInterestsTooltip" : "Zinserträge auf dein verliehenes Vermögen", "interestEarned" : "Zinserträge", "interestEarnedTooltip" : "Zinsen, die du nach der Abhebung verdient hast", "openLoans" : "Offene Kredite", @@ -910,12 +910,12 @@ "cta" : "Wie funktioniert das Verleihen auf Compound?" }, "closed" : { - "title" : "Ihre abgeschlossenen Kredite werden hier angezeigt", + "title" : "Deine abgeschlossenen Darlehen werden hier angezeigt", "description" : "Du hast noch keine Darlehen vergeben.", "cta" : "Einzahlung" }, "opened" : { - "title" : "Ihre eröffneten Kredite werden hier angezeigt", + "title" : "Deine eröffneten Darlehen werden hier angezeigt", "description" : "Du hast noch keine Darlehen vergeben.", "cta" : "Einzahlung" }, @@ -936,7 +936,7 @@ "actions" : "Aktionen" }, "status" : { - "enablingTooltip" : "Ihre Transaktion wird übertragen", + "enablingTooltip" : "Deine Transaktion wird übertragen", "toSupplyTooltip" : "Du kannst nun deine Vermögenswerte bereitstellen" }, "types" : { @@ -986,7 +986,7 @@ }, "withdraw" : { "title" : "Abheben", - "description" : "Abheben von Vermögenswerten aus dem Protokoll auf Ihr Ledger-Konto." + "description" : "Abheben von Vermögenswerten aus dem Protokoll auf dein Ledger-Konto." } }, "enable" : { @@ -1015,11 +1015,11 @@ "title" : "Bestätigung", "success" : { "title" : "Aktion erfolgreich durchgeführt", - "text" : "Die Freigabe wurde zur Bestätigung an das Netzwerk gesendet. Sobald sie bestätigt ist, kannst du Darlehen vergeben.", + "text" : "Die Freigabe wurde zur Bestätigung an das Netzwerk gesendet. Sobald sie bestätigt ist, kannst du Kredite vergeben.", "done" : "Schließen", "info" : "Es kann einige Zeit dauern, bis Transaktionen in einem Explorer angezeigt und bestätigt werden." }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -1041,11 +1041,11 @@ "title" : "Bestätigung", "success" : { "title" : "Abhebung erfolgreich gesendet", - "text" : "Ihr Guthaben ist verfügbar, sobald das Netzwerk die Abhebung bestätigt hat.", + "text" : "Dein Guthaben ist verfügbar, sobald das Netzwerk die Abhebung bestätigt hat.", "done" : "Schließen", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst.", + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf.", "tooltip" : { "amountWithdrawn" : "Der entnommene Betrag wird in {{ tokenName }} angezeigt. {{ tokenName }} sind ERC20-Token, die du nach dem Verleihen von Vermögenswerten verdienst." } @@ -1101,7 +1101,7 @@ }, "noEthAccount" : { "title" : "Bitte erstelle ein ETH-Konto", - "description" : "<0>{{ asset }}({{ ticker }}) ist ein Ethereum-ERC-20 Token. Um {{ ticker }} zu verleihen, installiere die Ethereum-App und erstelle ein Ethereum-Konto", + "description" : "<0>{{ asset }} ({{ ticker }}) ist ein Ethereum-ERC-20 Token. Um {{ ticker }} zu verleihen, installiere die Ethereum-App und erstelle ein Ethereum-Konto", "cta" : "Konto hinzufügen" }, "emptyAccountDeposit" : { @@ -1139,7 +1139,6 @@ "send" : "Senden", "swap" : "Swappen", "stake" : "Staken", - "earn" : "Verdienen", "yield" : "Ertrag", "buy" : "Kaufen", "sell" : "Verkaufen", @@ -1199,7 +1198,7 @@ "continueOnDevice" : "Diese Aktion für {{productName}} durchführen", "pairedContent" : { "title" : "Dieses {{deviceName}}-Gerät ist echt", - "description" : "Die Verwendung dieses {{productName}} ist sicher. Du kannst mit dem Einrichten beginnen.", + "description" : "Die Verwendung dieses {{productName}}-Geräts ist sicher. Du kannst mit dem Einrichten fortfahren.", "continueOnDevice" : "Tippe auf dein {{productName}}-Gerät, um mit dem Einrichten zu beginnen" }, "pinContent" : { @@ -1217,12 +1216,12 @@ "selectionNewLedger" : "<0>Set up as a new Ledger (Als neues Ledger-Gerät einrichten) ermöglicht dir die Erstellung einer neuen Wallet. Hierbei wird eine neue geheime Wiederherstellungsphrase generiert.", "selectionRestore" : "<0>Restore (Wiederherstellen) erlaubt dir den Zugriff auf deine bestehenden Vermögenswerte mittels deiner geheimen Wiederherstellungsphrase oder durch Nutzung von Ledger Recover.", "selectionContinueOnDevice" : "Wähle die entsprechende Option auf deinem {{productName}}-Gerät aus", - "newSeedDescription1" : "Dein {{productName}}-Gerät generiert für dich eine individuelle 24-Wort-Wiederherstellungsphrase. Sie bildet die einzige Möglichkeit, deine Vermögenswerte wiederherzustellen, falls dein Ledger-Gerät gestohlen wird, verloren geht oder du deine PIN vergisst.", + "newSeedDescription1" : "Deine {{productName}} generiert für dich eine individuelle 24-Wort-Wiederherstellungsphrase. Diese bildet die einzige Möglichkeit, deine Vermögenswerte wiederherzustellen, falls dein Ledger-Gerät gestohlen wird, verloren geht oder du deine PIN vergisst.", "newSeedDescription2" : "<0>Sicher aufbewahren:\nDeine geheime Wiederherstellungsphrase erlaubt den Zugang zu deinen Vermögenswerten und ist unersetzlich. Wer immer diese Phrase kennt, hat die Kontrolle über dein Vermögen und kann es stehlen. Solltest du die Wiederherstellungsphrase verlieren, kann Ledger dir nicht helfen.", "newSeedDescription3" : "Sei vorsichtig, wenn eine Person oder Software nach deiner geheimen Wiederherstellungsphrase fragt. Dies ist in jedem Fall ein Betrugsversuch („Scam“). ", "newSeedDescription4" : "Der einzige Ort, an dem du deine geheime Wiederherstellungsphrase eingeben darfst, ist dein Ledger-Gerät.", "newSeedDescription5" : "Gib sie nicht weiter. Verliere sie nicht.", - "newSeedContinueOnDevice" : "Sieh dir die auf deinem {{productName}}-Gerät generierte geheime Wiederherstellungsphrase an und schreibe sie auf", + "newSeedContinueOnDevice" : "Sieh dir die auf deiner {{productName}} generierte geheime Wiederherstellungsphrase an und schreibe sie auf", "restoreChoiceContinueOnDevice" : "Wähle die entsprechende Option auf deinem {{productName}}-Gerät aus", "restoreChoiceSRPTitle" : "Wiederherstellung mit geheimer Wiederherstellungsphrase", "restoreChoiceSRPDescription" : "Für maximale Sicherheit verwende eine von einem Ledger-Gerät generierte geheime Wiederherstellungsphrase.", @@ -1255,7 +1254,7 @@ }, "exitWarningDrawer" : { "title" : "Echtheitsprüfung und Prüfung auf Betriebssystem-Update abbrechen?", - "description" : "Diese Echtheitsprüfung ist obligatorisch, um die Einrichtung deines {{productName}} mit der Ledger Live-App fortsetzen zu können.", + "description" : "Diese Echtheitsprüfung ist obligatorisch, um die Einrichtung deiner {{productName}} mit der Ledger Live-App fortsetzen zu können.", "cancelCheckCTA" : "Prüfungen abbrechen", "resumeCheckCTA" : "Prüfungen fortsetzen" }, @@ -1270,7 +1269,7 @@ }, "deviceNotGenuineError" : { "title" : "Dieses {{productName}}-Gerät ist nicht echt", - "description" : "Die Nutzung dieses {{productName}}-Geräts ist nicht sicher.\nBitte kontaktiere den Ledger-Kundenservice." + "description" : "Die Nutzung dieser {{productName}} ist nicht sicher.\nBitte kontaktiere den Ledger-Kundenservice." } }, "whyPerformChecksLink" : "Weitere Informationen zur Echtheitsprüfung", @@ -1312,7 +1311,7 @@ "titleCompleted" : "Apps auf dem {{productName}}-Gerät installiert", "install" : "Installieren", "skip" : "Das werde ich später machen", - "info" : "Apps auf {{deviceName}} werden zur Autorisierung von Transaktionen verwendet. Du kannst sie jederzeit hinzufügen oder entfernen." + "info" : "Apps auf der {{deviceName}} werden zur Autorisierung von Transaktionen verwendet. Du kannst sie jederzeit hinzufügen oder entfernen." }, "endOfSetup" : { "title" : "Einrichtung beendet", @@ -1366,7 +1365,7 @@ "actionCompletedPopupLabel" : "Gekaufte Krypto" }, "assetsTransfer" : { - "title" : "Vermögenswerte auf dein Ledger-Gerät übertragen", + "title" : "Übertrage deine Vermögenswerte in deine Ledger", "description" : "Von jeder Börse oder Wallet direkt zu deinem Ledger-Gerät.", "actionCompletedPopupLabel" : "Vermögenswerte übertragen" }, @@ -1404,7 +1403,7 @@ "cta" : "Cosmos jetzt verleihen" }, "buyCrypto" : { - "title" : "Krypto kaufen", + "title" : "Kryptos kaufen", "description" : "Kaufe Krypto-Vermögenswerte über unseren Partner und erhalte diese direkt auf dein Ledger-Konto", "cta" : "Jetzt kaufen" }, @@ -1443,7 +1442,7 @@ }, "vaultSigner" : { "title" : "Vault-Unterzeichnermodus", - "link" : "Vault-Hilf–Center" + "link" : "Vault-Hilfe-Center" } }, "signmessage" : { @@ -1473,10 +1472,10 @@ }, "recentActivity" : "Letzte Aktionen", "totalBalance" : "Gesamtsaldo", - "transactionsPendingConfirmation" : "Einige Transaktionen sind noch nicht bestätigt. Diese werden in Ihrem Guthaben angezeigt und können nach der Bestätigung verwendet werden.", + "transactionsPendingConfirmation" : "Einige Transaktionen sind noch nicht bestätigt. Diese werden in deinem Guthaben angezeigt und können nach der Bestätigung verwendet werden.", "featuredButtons" : { "buySell" : { - "title" : "Kaufen & Verkaufen", + "title" : "Kaufen/Verkaufen", "description" : "Bei vertrauenswürdigen Anbietern kaufen und verkaufen" }, "swap" : { @@ -1486,7 +1485,7 @@ }, "earn" : { "title" : "Staken", - "description" : "Prämien für deine Kryptos erhalten" + "description" : "Krypto mit Ledger staken" } }, "recoverBanner" : { @@ -1550,8 +1549,8 @@ }, "emptyState" : { "dashboard" : { - "title" : "Apps auf Ihrem Gerät installieren", - "desc" : "Gehe zu My Ledger, um Apps auf deinem Gerät zu installieren. Du kannst Konten hinzufügen, sobald du Apps auf deinem Gerät hast.", + "title" : "Apps auf deinem Gerät installieren", + "desc" : "Gehe zu My Ledger, um Apps auf deinem Gerät zu installieren. Nach der Installation der Apps kannst du Konten hinzufügen.", "buttons" : { "installApp" : "Zu My Ledger wechseln", "help" : "Hilfe" @@ -1568,7 +1567,7 @@ } }, "genuinecheck" : { - "deviceInBootloader" : "Das Gerät ist im Bootloader-Modus. Klicke auf <1>Weiter<1>, um es zu aktualisieren." + "deviceInBootloader" : "Das Gerät ist im Bootloader-Modus. Klicke auf <1>Continue<1> (Weiter), um es zu aktualisieren." }, "learn" : { "title" : "Lernen", @@ -1582,7 +1581,7 @@ "market" : { "title" : "Markt", "currency" : "Währung", - "rangeLabel" : "Uhrzeit", + "rangeLabel" : "Zeit", "goBack" : "Zurückgehen", "filters" : { "title" : "Filter", @@ -1733,7 +1732,7 @@ "import" : "Konten", "finish" : "Bestätigung" }, - "fullNodeReadyInfo" : "Die Konten werden über Ihren Bitcoin-Knoten (Full Node) hinzugefügt.", + "fullNodeReadyInfo" : "Die Konten werden über deinen Bitcoin-Full-Node hinzugefügt.", "fullNodeConfigure" : "Knoten konfigurieren", "tokensTip" : "{{token}} ({{ticker}}) ist ein {{tokenType}}-Token. Du kannst Token direkt auf einem {{currency}}-Konto empfangen.", "accountToImportSubtitle_plural" : "Bestehende Konten hinzufügen", @@ -1842,7 +1841,7 @@ }, "DeviceAction" : { "allowAppPermission" : "Öffne die {{wording}} App auf deinem Gerät", - "allowAppPermissionSubtitleToken" : "zum Verwalten Ihrer {{token}}-Tokens", + "allowAppPermissionSubtitleToken" : "zum Verwalten deiner {{token}}-Token", "allowManagerPermission" : "Sichere Verbindung zulassen", "allowRenaming" : "Umbenennen auf deinem Gerät zulassen", "loading" : "Lade Daten...", @@ -1853,19 +1852,19 @@ "quitApp" : "Beende die Anwendung auf deinem Gerät", "appNotInstalledTitle" : "Fehlende, erforderliche App", "appNotInstalledTitle_plural" : "Fehlende, erforderliche Apps", - "appNotInstalled" : "Die {{appName}}-App ist erforderlich, um diese Aktion durchzuführen. Bitte wechsle zu My Ledger und installiere sie auf deinem Gerät.", - "appNotInstalled_plural" : "Die {{appName}}-Apps sind erforderlich, um diese Aktion durchzuführen. Bitte wechsle zu My Ledger und installiere sie auf deinem Gerät.", + "appNotInstalled" : "Die {{appName}}-App ist erforderlich, um diese Aktion durchzuführen. Bitte gehe zu My Ledger und installiere sie auf deinem Gerät.", + "appNotInstalled_plural" : "Die {{appName}}-Apps sind erforderlich, um diese Aktion durchzuführen. Bitte gehe zu My Ledger und installiere sie auf deinem Gerät.", "openManager" : "My Ledger öffnen", "openOnboarding" : "Gerät einrichten", "outdated" : "App-Version veraltet", - "outdatedDesc" : "Für die {{appName}}-App auf deinem Gerät ist ein wichtiges Update verfügbar. Wechsle zu My Ledger, um sie zu aktualisieren.", + "outdatedDesc" : "Für die {{appName}}-App auf deinem Gerät ist ein wichtiges Update verfügbar. Bitte wechsle zu My Ledger, um sie zu aktualisieren.", "installApp" : "{{appName}} App-Installation", "installAppDescription" : "Bitte warte, bis die Installation beendet ist", "listApps" : "Prüfen von App-Abhängigkeiten", "listAppsDescription" : "Bitte warte, während wir sicherstellen, dass du alle erforderlichen Apps hast", "swap" : { "notice" : { - "default" : "Vor dem Senden der Swapping-Details musst du diese auf deinem Gerät verifizieren. Die Adressen musst du nicht verifizieren, da diese sicher ausgetauscht werden.", + "default" : "Vor dem Senden der Fondsdetails musst du diese auf deinem Gerät verifizieren. Die Adressen musst du nicht verifizieren, da diese sicher ausgetauscht werden.", "provider" : "Verifiziere die Swap-Details auf deinem Gerät, bevor du sie sendest. {{providerName}} muss möglicherweise eine zusätzliche Überprüfung für einige Transaktionen durchführen, was zu einer Verzögerung führen kann." }, "confirm" : "Swap-Transaktion bestätigen", @@ -1875,7 +1874,7 @@ "fees" : "Gebühren", "provider" : "Anbieter", "payoutNetworkFees" : "Auszahlungsgebühren", - "payoutNetworkFeesTooltip" : "Dieser Betrag wird nicht auf Ihrem Gerät angezeigt", + "payoutNetworkFeesTooltip" : "Dieser Betrag wird auf deinem Gerät nicht angezeigt.", "acceptTerms" : "Durch Validieren dieser Transaktion stimme ich den\n<0>Nutzungsbedingungen von {{provider}} zu.", "exodusAcceptTerms" : "Exodus greift bei der Abwicklung von Swaps auf Drittanbieter zurück.\nDurch Validieren dieser Transaktion stimme ich den <0>Nutzungsbedingungen von Exodus zu." }, @@ -1892,7 +1891,7 @@ "confirm" : "Transaktion bestätigen" }, "fund" : { - "notice" : "Vor dem Senden der Fondsdetails musst du diese auf deinem Gerät verifizieren. Die Adressen musst du nicht verifizieren, da diese sicher ausgetauscht werden.", + "notice" : "Vor dem Senden der Vermögenswerte musst du die Details auf deinem Gerät verifizieren. Die Adressen musst du nicht verifizieren, da diese sicher ausgetauscht werden.", "confirm" : "Fondstransaktion bestätigen" } }, @@ -1921,7 +1920,7 @@ }, "applist" : { "placeholder" : "Keine Übereinstimmung für die Suche mit den gewählten Filtern", - "placeholderNoAppsInstalled" : "Keine Apps auf Ihrem Gerät installiert", + "placeholderNoAppsInstalled" : "Keine Apps auf deinem Gerät installiert", "placeholderGoToCatalog" : "Gehe zum App-Katalog, um Apps zu installieren", "noResultsFound" : "Keine Ergebnisse gefunden", "noResultsDesc" : "Bitte überprüfe die Schreibweise und versuche es noch einmal", @@ -1974,7 +1973,7 @@ "learnMoreTooltip" : "Erfahre mehr über {{appName}}", "removeTooltip" : "{{appName}} deinstallieren", "useAppForToken" : "Möchtest du {{tokenType}}-Token verwalten?", - "tokenAppDisclaimer" : "Um {{tokenName}} zu verwalten {{tokenType}} Token zu verwalten, <1>installiere die {{appName}} App und vergewissern Sie sich bitte, dass Sie tatsächlich die <1>{{tokenType}} Version haben, bevor Sie <3>an dein {{appName}} Konto senden.", + "tokenAppDisclaimer" : "Zum Verwalten von {{tokenName}}-{{tokenType}}-Token <1>installiere die {{appName}}-App und vergewissere dich, dass du tatsächlich die <1>{{tokenType}}-Version hast, bevor du Beträge <3>an dein {{appName}}-Konto sendest.", "tokenAppDisclaimerInstalled" : "Zum Verwalten von <1>{{tokenName}} {{tokenType}}-Token vergewissere dich bitte, dass du tatsächlich die <1>{{tokenType}}-Version hast, bevor du Beträge <3>an dein {{appName}}-Konto sendest.", "goToAccounts" : "Zu den Konten gehen", "intallParentApp" : "{{appName}} App installieren", @@ -1998,7 +1997,7 @@ "dependencyUninstall" : { "title" : " {{app}} und seine zugehörigen Apps deinstallieren?", "showAll" : "Zu deinstallierende Apps anzeigen", - "description" : "Einige Ihrer installierten Apps sind mit der App {{app}} verknüpft. Diese werden ebenfalls deinstalliert.", + "description" : "Einige deiner installierten Apps sind mit der App {{app}} verknüpft. Diese werden ebenfalls deinstalliert.", "confirm" : "Deinstallieren von {{app}} und anderen Apps" } }, @@ -2054,7 +2053,7 @@ "progress" : "Update wird installiert", "progressStep" : "Update {{current}} von {{total}} wird installiert", "firmware" : "Firmware wird aktualisiert…", - "flash" : "Ihr Gerät vorbereiten ..." + "flash" : "Dein Gerät wird vorbereitet …" }, "confirmIdentifier" : "Kennung verifizieren", "confirmIdentifierText" : "Tippe auf „Installieren“, um\ndas Betriebssystem-Update zu starten", @@ -2075,7 +2074,7 @@ "sucessCTAApps" : "Apps wiederherstellen", "SuccessCTANoApps" : "Beenden", "resetSteps" : { - "first" : "1. Ihr Gerät zurücksetzen", + "first" : "1. Dein Gerät zurücksetzen", "connect" : "Schließe die {{deviceName}} über das USB-Kabel an deinen Computer an.", "turnOn" : "Drücke die Taste am Gerät, um es einzuschalten.", "falsePin" : "Gib drei falsche PINs ein, um das Gerät zurückzusetzen.", @@ -2087,7 +2086,7 @@ "third" : "3. Alle Apps deinstallieren", "openLive" : "Öffne My Ledger in Ledger Live.", "uninstall" : "Klicke auf das graue Papierkorbsymbol für alle derzeit auf der {{deviceName}} installierten Apps. Dies schafft Platz für das Firmware-Installationsprogramm.", - "disclaimer" : "Hinweis: Ihr Guthaben ist von diesem Vorgang nicht betroffen, die privaten Schlüssel zum Zugriff auf Ihr Krypto-Vermögen in der Blockchain bleiben sicher auf Ihrem Recovery Sheet." + "disclaimer" : "Hinweis: Dein Guthaben ist von diesem Vorgang nicht betroffen. Die privaten Schlüssel für den Zugriff auf dein Kryptovermögen auf der Blockchain verbleiben sicher auf deinem Wiederherstellungszettel." } } }, @@ -2096,7 +2095,7 @@ "steps" : { "rewards" : { "title" : "Prämien", - "description" : "Glückwunsch! Du hast <1>{{amount}} verdient, indem du für Validatoren gestimmt hast.", + "description" : "Glückwunsch! Du hast <1>{{amount}} verdient, indem du für Validatoren gevotet hast.", "info" : "Prämien können einmal alle 24 Stunden beansprucht werden." }, "connectDevice" : { @@ -2110,7 +2109,7 @@ "cta" : "Details anzeigen", "done" : "Fertig" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -2121,7 +2120,7 @@ "title" : "Betrag", "resourceInfo" : "Bandbreite oder Energie?", "bandwidthDescription" : "Bandbreiten-Punkte werden verwendet, um Transaktionen durchzuführen, ohne dass TRX für Netzwerkgebühren bezahlt. Wähle „Bandbreite“ aus, um die Zahl deiner täglichen kostenlosen Transaktionen zu erhöhen.", - "energyDescription" : "Energie-Punkte werden benötigt, um Smart Contracts auszuführen. Wenn du keine Smart Contracts ausführst, ist es nicht nötig, Prämien in Energie auszuwählen.", + "energyDescription" : "Energiepunkte werden benötigt, um Smart Contracts auszuführen. Wenn du keine Smart Contracts ausführst, ist es nicht nötig, Prämien in Energie auszuwählen.", "amountLabel" : "Betrag zum Sperren", "available" : "Verfügbar: {{amountAvailable}}", "info" : "Du kannst eingefrorene Vermögenswerte gleich entsperren, sie sind jedoch erst nach einer 14-tägigen Wartezeit zugänglich." @@ -2137,13 +2136,13 @@ "title" : "Bestätigung", "success" : { "title" : "", - "textNRG" : "Du beginnst mit dem Verdienen von Energie, sobald das Netzwerk das Einfrieren bestätigt hat. In Kürze kannst du für Superrepräsentanten abstimmen, um weitere Prämien zu verdienen.", - "text" : "Du beginnst mit dem Verdienen von Bandbreite, sobald das Netzwerk das Einfrieren bestätigt hat. In Kürze kannst du für Superrepräsentanten abstimmen, um weitere Prämien zu verdienen.", + "textNRG" : "Du beginnst mit dem Verdienen von Energie, sobald das Netzwerk das Einfrieren bestätigt hat. In Kürze kannst du für Superrepräsentanten voten, um weitere Prämien zu verdienen.", + "text" : "Du beginnst mit dem Verdienen von Bandbreite, sobald das Netzwerk das Einfrieren bestätigt hat. In Kürze kannst du für Superrepräsentanten voten, um weitere Prämien zu verdienen.", "votePending" : "Abstimmen in {{time}}", "vote" : "Abstimmen", "later" : "Später abstimmen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -2152,7 +2151,7 @@ "steps" : { "amount" : { "title" : "Entsperren", - "info" : "Durch das Aufheben der Sperrung werden Ihre {{resource}} verringert und Ihre Stimmen gelöscht." + "info" : "Durch das Aufheben der Sperrung wird deine {{resource}} verringert, und deine Votes werden verworfen." }, "connectDevice" : { "title" : "Gerät" @@ -2161,10 +2160,10 @@ "title" : "Bestätigung", "success" : { "title" : "", - "text" : "Ihr Vermögen wurde erfolgreich entsperrt Ihre {{resource}} Punkte werden reduziert und alle Ihre Stimmen werden storniert.", + "text" : "Deine Vermögenswerte wurden erfolgreich entsperrt. Deine Punkte für {{resource}} werden reduziert, und deine Votes werden verworfen.", "continue" : "Weiter" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -2191,11 +2190,11 @@ "confirmation" : { "title" : "Bestätigung", "success" : { - "title" : "Ihre Stimmen wurden erfolgreich abgegeben.", + "title" : "Deine Votes wurden erfolgreich abgegeben.", "text" : "", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -2204,7 +2203,7 @@ "titleCrypto" : "{{currency}} kaufen", "buyCTA" : "{{currencyTicker}} kaufen", "withoutDevice" : "Weiter ohne mein Gerät", - "connectWithoutDevice" : "Für eine optimale Sicherheit ist es besser, Ihr Gerät zu verwenden.", + "connectWithoutDevice" : "Für optimale Sicherheit ist es besser, dein Gerät zu verwenden.", "skipConnect" : "Weiter ohne mein Gerät" }, "sell" : { @@ -2251,16 +2250,16 @@ "stake" : "Staken mit {{provider}}" }, "cosmos" : { - "title" : "Vermehre deine ATOM. Stake mit Ledger Validator.", - "description" : "ATOM mit dem bewährten Ledger-Validator staken: Ihre Coins gehören stets Ihnen, dank der kompromisslosen Sicherheit von Ledger." + "title" : "ATOM vermehren. Mit Ledger Validator staken.", + "description" : "Stake deine ATOM mit dem bewährten Ledger-Validator. Deine Coins bleiben dein Eigentum, unterstützt durch die kompromisslose Sicherheit von Ledger." }, "osmo" : { "title" : "OSMO vermehren. Mit Ledger by Figment staken.", - "description" : "Stake deine OSMO mit dem dem Ledger by Figment-Validator. Er bietet die niedrigste Provisionsgebühr und eine Garantie gegen Slashing!" + "description" : "Stake deine OSMO mit dem Ledger by Figment-Validator. Er bietet die niedrigste Provisionsgebühr und eine Garantie gegen Slashing!" }, "solana" : { "title" : "SOL vermehren. Mit Ledger by Figment staken.", - "description" : "Stake deine SOL mit dem Ledger by Figment-Validator. Deine Coins gehören jederzeit dir, unterstützt durch die kompromisslose Sicherheit von Ledger." + "description" : "Stake deine SOL mit dem Ledger by Figment-Validator. Deine Coins bleiben dein Eigentum, unterstützt durch die kompromisslose Sicherheit von Ledger." }, "celo" : { "title" : "CELO vermehren. Mit Ledger by Figment staken.", @@ -2365,11 +2364,11 @@ "pending" : { "title" : "Sende Transaktion..." }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." }, "warning" : { "tezos" : { - "text" : "Der zu sendende Betrag wird vom Saldo Ihres delegierten Kontos abgezogen." + "text" : "Der zu sendende Betrag wird vom Saldo deines delegierten Kontos abgezogen." } } }, @@ -2441,8 +2440,8 @@ "description" : "{{deviceName}} und die Ledger Live-App in derselben Sprache verwenden?" }, "firmwareUpdatePrompt" : { - "title" : "Ihr {{deviceName}} auf {{language}} einstellen?", - "description" : "{{language}} ist jetzt für {{deviceName}} verfügbar. Du kannst die Sprache deines Geräts jetzt festlegen oder sie jederzeit über My Ledger ändern." + "title" : "Deine {{deviceName}} auf {{language}} umstellen?", + "description" : "{{language}} ist jetzt für {{deviceName}} verfügbar. Du kannst die Sprache deines Geräts jetzt festlegen und sie jederzeit über My Ledger ändern." }, "allowLanguageInstallation" : "Tippe auf „Allow“ (Erlauben), um\ndie Sprache zu installieren", "languageInstalled" : "Sprache umgestellt auf {{language}}", @@ -2534,7 +2533,11 @@ }, "starter" : { "description" : "Du kannst Belohnungen verdienen, indem du deine EGLD-Vermögenswerte an einen Staking-Anbieter delegierst.", - "bullet" : ["Du behältst das Eigentum an delegierten Vermögenswerten", "Mit deinem Ledger-Gerät delegieren", "Vermögenswerte sind 10 Tage nach Aufhebung der Delegierung verfügbar"], + "bullet" : [ + "Du behältst das Eigentum an delegierten Vermögenswerten", + "Mit deinem Ledger-Gerät delegieren", + "Vermögenswerte sind 10 Tage nach Aufhebung der Delegierung verfügbar" + ], "warning" : { "description" : "Wähle deinen Staking-Anbieter mit Bedacht aus: Derzeit besteht das einzige Risiko darin, aus verschiedenen Gründen keine Belohnungen zu erhalten. Daher solltest du einen Anbieter auswählen, bei dem Zuverlässigkeit, Kommunikation und Wirtschaftlichkeit stimmen." } @@ -2552,7 +2555,7 @@ "text" : "Dein Kontostand wird aktualisiert, wenn die Blockchain die Transaktion bestätigt.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -2567,7 +2570,7 @@ "claim" : "Prämien beanspruchen", "compoundOrClaim" : "Belohnungen zusammenlegen oder einfordern", "compoundDescription" : "Belohnungen werden zum delegierten Betrag hinzugefügt.", - "claimDescription" : "Belohnungen werden Ihrem verfügbaren Guthaben gutgeschrieben.", + "claimDescription" : "Prämien werden deinem verfügbaren Guthaben gutgeschrieben.", "compoundInfo" : "Du hast <0>{{amount}} verdient. Wenn du auf „Continue“ (Weiter) klickst, werden sie jetzt eingefordert und automatisch an denselben Staking-Anbieter delegiert.", "claimInfo" : "Du hast beim nachstehenden Staking-Anbieter <0>{{amount}} verdient. Wenn du auf „Continue“ (Weiter) klickst, werden sie jetzt eingefordert und automatisch zum verfügbaren Guthaben hinzugefügt.", "selectLabel" : "Delegation auswählen" @@ -2581,14 +2584,14 @@ "success" : { "title" : "Einfordern von Belohnungen war erfolgreich", "titleCompound" : "Erfolgreich zusammengerechnete Prämien", - "text" : "Die Belohnungen wurden zu Ihrem verfügbaren Guthaben hinzugefügt", - "textCompound" : "Ihre Transaktion für zusammengelegte Belohnungen von <0>{{amount}}EGLD an <0>{{validator}}wurde erfolgreich bearbeitet.", + "text" : "Die Prämien wurden deinem verfügbaren Guthaben gutgeschrieben.", + "textCompound" : "Deine Transaktion für Compound-Prämien von <0>{{amount}}EGLD an <0>{{validator}}wurde erfolgreich bearbeitet.", "cta" : "Details anzeigen" }, "pending" : { "title" : "Sende Transaktion..." }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -2606,7 +2609,7 @@ "amount" : { "title" : "Betrag", "subtitle" : "Der Prozess der Aufhebung der Delegierung dauert <0>10 Tage bis zum Abschluss.", - "warning" : "Prämien werden automatisch eingefordert. Die Aufhebung der Delegation ist ein zweistufiger Prozess: die Beantragung der Aufhebung der Delegierung, gefolgt von einer <0>10-tägigen Frist zur Aufhebung der Bindung, nach der du die Abhebung finalisieren kannst und der nicht mehr delegierte Betrag deinem verfügbaren Guthaben gutgeschrieben wird.", + "warning" : "Prämien werden automatisch eingefordert. Die Aufhebung der Delegierung ist ein zweistufiger Prozess: die Beantragung der Aufhebung der Delegierung, gefolgt von einer <0>10-tägigen Frist zur Aufhebung der Bindung, nach der du die Abhebung finalisieren kannst und der nicht mehr delegierte Betrag deinem verfügbaren Guthaben gutgeschrieben wird.", "fields" : { "validator" : "Staking-Anbieter", "amount" : "Nicht zu delegierender Betrag" @@ -2622,7 +2625,7 @@ "description" : "Die Delegierung von <0>{{amount}} wurde von <0>{{validator}} aufgehoben.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -2644,13 +2647,13 @@ "label" : "Bestätigung", "success" : { "title" : "Guthaben wurden erfolgreich abgehoben", - "text" : "Der Betrag <0>{{amount}}wurde wieder auf Ihren Kontostand zurücküberwiesen.", + "text" : "Der Betrag <0>{{amount}}wurde deinem Konto wieder gutgeschrieben.", "cta" : "Details anzeigen" }, "pending" : { "title" : "Sende Transaktion..." }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -2677,7 +2680,11 @@ "steps" : { "starter" : { "description" : "Du kannst Prämien verdienen, indem du deine ADA an einen Pool delegierst.", - "bullet" : ["Du behältst das Eigentum an delegierten Vermögenswerten", "Delegiere mit deinem Ledger-Gerät", "Vermögenswerte können an einen anderen Pool umdelegiert werden. Du kannst die Delegierung auch jederzeit aufheben."] + "bullet" : [ + "Du behältst das Eigentum an delegierten Vermögenswerten", + "Delegiere mit deinem Ledger-Gerät", + "Vermögenswerte können an einen anderen Pool umdelegiert werden. Du kannst die Delegierung auch jederzeit aufheben." + ] }, "validator" : { "title" : "Pools" @@ -2695,7 +2702,7 @@ "text" : "Dein Kontostand wird aktualisiert, wenn die Blockchain die Transaktion bestätigt.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -2719,7 +2726,7 @@ "text" : "Dein Kontostand wird aktualisiert, wenn die Blockchain die Transaktion bestätigt.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -2757,12 +2764,12 @@ "starter" : { "description" : "Sperre TRX, um Prämien zu verdienen und behalte trotzdem die volle Sicherheit und Kontrolle über dein Vermögen.", "bullet" : { - "delegate" : "Delegierte Vermögenswerte bleiben in Ihrem Besitz.", + "delegate" : "Delegierte Vermögenswerte bleiben dein Eigentum.", "access" : "Du kannst eingefrorene Vermögenswerte gleich entsperren, sie sind jedoch erst nach einer 14-tägigen Wartezeit zugänglich.", - "ledger" : "Sicher sperren und abstimmen mit Ihrem Ledger-Gerät." + "ledger" : "Sicher sperren und voten mit deinem Ledger-Gerät." }, "help" : "Wie die Abstimmung funktioniert", - "termsAndPrivacy" : "Das übertragen Ihrer Stimmrechte garantiert keine Prämien durch Ihren Super-Repräsentanten." + "termsAndPrivacy" : "Das Delegieren deiner Voting-Rechte garantiert keine Prämien durch deinen Superrepräsentanten." } } } @@ -2771,7 +2778,7 @@ "title" : "Vermögenswerte verwalten", "freeze" : { "title" : "Sperren", - "description" : "Sperre TRX, um Bandbreite oder Energie zu verdienen. Du kannst auch für Superrepräsentanten abstimmen." + "description" : "Sperre TRX, um Bandbreite oder Energie zu verdienen. Du kannst auch für Superrepräsentanten voten." }, "unfreeze" : { "title" : "Entsperren", @@ -2792,11 +2799,11 @@ "message" : "SR oder Kandidaten?", "superRepresentative" : { "title" : "Super-Repräsentanten (SR)", - "description" : "Superrepräsentanten spielen eine Schlüsselrolle bei der Verwaltung der TRON-Community, den sie stellen grundlegende Funktionen sicher, z. B. Blockerstellung und Buchhaltung." + "description" : "Superrepräsentanten spielen eine Schlüsselrolle bei der Verwaltung der TRON-Community, da sie grundlegende Funktionen sicherstellen, z. B. die Blockerstellung und die Buchhaltung." }, "candidates" : { "title" : "Kandidaten", - "description" : "127 Personen werden durch Abstimmung in der gesamten Tokeninhaber-Community gewählt. Die Votes werden alle 6 Stunden aktualisiert." + "description" : "127 Personen, die durch die Abstimmung der gesamten Token-Inhaber-Community gewählt werden. Die Abstimmungen werden alle 6 Stunden aktualisiert." } } } @@ -2820,7 +2827,7 @@ "replaceable" : "Ersetzbar", "cannotSelect" : { "unconfirmed" : "Du kannst keine Coins aus unbestätigten, austauschbaren Transaktionen auswählen.", - "pending" : "Du kannst keine Coins aus schwebenden Transaktionen auswählen. (außer deiner Wechselgeldausgabe)", + "pending" : "Du kannst keine Coins aus schwebenden Transaktionen auswählen (außer deiner Wechselgeldausgabe).", "last" : "Du benötigst mindestens eine ausgewählte Transaktion" }, "pending" : "Ausstehend", @@ -2881,7 +2888,7 @@ "titleWhenPendingRegistration" : "Kontoregistrierung steht aus", "lock" : { "title" : "Sperren", - "description" : "Zum Verdienen von Belohnungen musst du zunächst einen Betrag sperren. Dann musst du Votes für deine(n) Validator(en) abgeben." + "description" : "Zum Verdienen von Prämien musst du zunächst einen Betrag sperren. Dann musst du Votes für deine(n) Validator(en) abgeben." }, "unlock" : { "title" : "Entsperren", @@ -2893,8 +2900,8 @@ }, "vote" : { "title" : "Abstimmen", - "description" : "Gib ein Vote für Validatorgruppen ab. Achte dabei darauf, deine Stimmen zu aktivieren, um Belohnungen zu verdienen.", - "descriptionMaxVotes" : "Du kannst Votes für bis zu {{maxVotes}} Validatorgruppen abgeben. Wenn du für eine neue Validatorgruppe stimmen möchtest, kannst du eine frühere Stimme auch widerrufen." + "description" : "Gib Votes für Validatorgruppen ab. Achte dabei darauf, deine Votes zu aktivieren, um Prämien zu verdienen.", + "descriptionMaxVotes" : "Du kannst Votes für bis zu {{maxVotes}} Validatorgruppen abgeben. Wenn du für eine neue Validatorgruppe voten möchtest, kannst du ein früheres Vote auch widerrufen." }, "activate" : { "title" : "Stimmen aktivieren", @@ -2929,7 +2936,7 @@ "pending" : { "title" : "Vermögenswerte werden gesperrt..." }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -2958,7 +2965,7 @@ "pending" : { "title" : "Vermögenswerte werden entsperrt..." }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -2992,7 +2999,7 @@ "pending" : { "title" : "Sende Transaktion..." }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -3009,10 +3016,10 @@ "title" : "Bestätigung", "success" : { "title" : "", - "text" : "Ihre Vermögenswerte wurden erfolgreich abgehoben Der Abbuchungsbetrag wird Ihrem verfügbaren Guthaben gutgeschrieben.", + "text" : "Deine Vermögenswerte wurden erfolgreich abgehoben. Der Abbuchungsbetrag wird deinem verfügbaren Guthaben gutgeschrieben.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -3032,7 +3039,7 @@ "text" : "Du wirst deinen Vorgang bald in deinem Verlauf sehen.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." }, "validatorGroup" : { "title" : "Validator-Gruppe", @@ -3055,10 +3062,10 @@ "title" : "Bestätigung", "success" : { "title" : "", - "text" : "Ihre Stimme wurde erfolgreich aktiviert.", + "text" : "Dein Vote wurde erfolgreich aktiviert.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -3081,7 +3088,7 @@ "text" : "Du wirst deinen Vorgang bald in deinem Verlauf sehen.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." }, "vote" : { "title" : "Abstimmen", @@ -3126,7 +3133,11 @@ "steps" : { "starter" : { "description" : "Du kannst Belohnungen verdienen, indem du deine {{currencyTicker}}-Vermögenswerte an einen Validator delegierst.", - "bullet" : ["Du behältst das Eigentum an delegierten Vermögenswerten", "Mit deinem Ledger-Gerät delegieren", "Vermögenswerte sind {{numberOfDays}} Tage nach Aufhebung der Delegierung verfügbar"], + "bullet" : [ + "Du behältst das Eigentum an delegierten Vermögenswerten", + "Mit deinem Ledger-Gerät delegieren", + "Vermögenswerte sind {{numberOfDays}} Tage nach Aufhebung der Delegierung verfügbar" + ], "warning" : { "description" : "Wähle deinen Validator mit Bedacht: Ein Teil deiner delegierten Vermögenswerte kann unwiderruflich verloren gehen, wenn sich der Validator nicht ordnungsgemäß verhält." } @@ -3147,7 +3158,7 @@ "text" : "Dein Kontostand wird aktualisiert, wenn die Blockchain die Transaktion bestätigt.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -3163,8 +3174,8 @@ "compoundOrClaim" : "Zusammenlegen oder Einstreichen", "compoundDescription" : "Prämien werden dem delegierten Betrag hinzugefügt", "claimDescription" : "Die Prämien werden dem verfügbaren Guthaben hinzugefügt", - "compoundInfo" : "Du hast <0>{{amount}} verdient. Wenn du auf „Weiter“ klickst, werden sie jetzt beansprucht und automatisch an denselben Validator delegiert.", - "claimInfo" : "Du hast <0>{{amount}} vom unten stehenden Validator erhalten. Wenn du auf „Weiter“ klickst, werden sie jetzt beansprucht und automatisch zum verfügbaren Guthaben hinzugefügt.", + "compoundInfo" : "Du hast <0>{{amount}} verdient. Wenn du auf „Weiter“ klickst, werden sie jetzt eingefordert und automatisch an denselben Validator delegiert.", + "claimInfo" : "Du hast <0>{{amount}} vom unten stehenden Validator erhalten. Wenn du auf „Continue“ (Weiter) klickst, werden sie jetzt eingefordert und automatisch zum verfügbaren Guthaben hinzugefügt.", "selectLabel" : "Delegation auswählen" }, "connectDevice" : { @@ -3177,13 +3188,13 @@ "title" : "Erfolgreich eingelöste Prämien", "titleCompound" : "Erfolgreich zusammengerechnete Prämien", "text" : "Deine Prämien wurden zu deinem verfügbaren Guthaben hinzugefügt", - "textCompound" : "Ihre Prämien <0>{{amount}} wurden automatisch an <0>{{validator}} übertragen", + "textCompound" : "Deine Prämien <0>{{amount}} wurden automatisch an <0>{{validator}} delegiert.", "cta" : "Details anzeigen" }, "pending" : { "title" : "Sende Transaktion..." }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -3195,7 +3206,7 @@ "starter" : { "title" : "Erneute Delegierung", "description" : "Verwende die erneute Delegierung, um einfach von einem Validator zu einem anderen zu wechseln. Wenn du es dir jedoch noch einmal anders überlegst, musst du warten, da die erneute Delegierung eine {{ numberOfDays }}-tägige Sperrzeit auslöst.", - "warning" : "Wähle deinen Validator mit Bedacht: Ein Teil deiner delegierten Vermögenswerte kann unwiderruflich verloren gehen, wenn sich der Validator nicht ordnungsgemäß verhält. Du kannst maximal <0>7 ausstehende Redelegierungen durchführen.", + "warning" : "Wähle deinen Validator mit Bedacht: Ein Teil deiner delegierten Vermögenswerte kann unwiderruflich verloren gehen, wenn sich der Validator nicht angemessen verhält. Du kannst maximal <0>7 ausstehende Redelegierungen durchführen.", "howDelegationWorks" : "Wie funktioniert die Delegierung?" }, "validators" : { @@ -3216,7 +3227,7 @@ "text" : "Die erneute Übertragung wird aktualisiert, sobald die Blockchain die Transaktion bestätigt hat", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -3247,7 +3258,7 @@ "description" : "Die Delegierung von <0>{{amount}} wurde von <0>{{validator}} aufgehoben", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -3263,7 +3274,7 @@ "steps" : { "assets" : { "title" : "ASA (Vermögenswerte)", - "info" : "Das Hinzufügen eines Vermögenswerts erfordert das Senden einer Transaktion mit Mindestgebühren. Dies wird in Ihrem Transaktionsverlauf angezeigt", + "info" : "Das Hinzufügen eines Vermögenswerts erfordert das Senden einer Transaktion mit Mindestgebühren. Dies wird in deinem Transaktionsverlauf angezeigt.", "selectLabel" : "Wähle einen ASA (Vermögenswert)", "disabledTooltip" : "Du hast diesen ASA (Vermögenswert) bereits in deinem Algorand-Konto" }, @@ -3277,7 +3288,7 @@ "text" : "Du kannst jetzt <0>{{token}}-Vermögenswerte auf deinem Algorand-Konto empfangen und senden.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -3304,7 +3315,7 @@ }, "info" : { "title" : "Prämien", - "description" : "Glückwunsch! Du hast {{amount}} verdient. Klicke auf „Weiter“; um deine Prämien zu beanspruchen.", + "description" : "Glückwunsch! Du hast {{amount}} verdient. Klicke auf „Continue“ (Weiter), um deine Prämien zu beanspruchen.", "info" : "Du wirst aufgefordert, eine leere Transaktion auf deinem Konto zu erzeugen. Dadurch werden deine aktuellen Prämien zu den Transaktionsmindestgebühren deinem Guthaben hinzugefügt." }, "connectDevice" : { @@ -3317,7 +3328,7 @@ "text" : "Deine Prämien wurden zu deinem verfügbaren Guthaben hinzugefügt", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -3327,11 +3338,11 @@ "lockedBalance" : "Gebunden", "lockedTooltip" : "Vermögenswerte müssen an nominierte Validatoren gebunden werden, damit du Prämien erhältst.", "unlockingBalance" : "Entbinden", - "unlockingTooltip" : "Nicht gebundene Guthaben bleiben für 28 Tage gesperrt, bevor sie abgehoben werden können.", + "unlockingTooltip" : "Nicht gebundene Vermögenswerte bleiben für 28 Tage gesperrt, bevor sie abgehoben werden können.", "unlockedBalance" : "Entbunden", "unlockedTooltip" : "Nicht gebundene Vermögenswerte können jetzt mit der Aktion „Zurückziehen“ verschoben werden.", "networkFees" : "Die Netzwerkgebühren werden automatisch durch den Polkadot-Konsens festgelegt. Du kannst sie nicht auf deinem Gerät einsehen.", - "bondedBalanceBelowMinimum" : "Als Nominator brauchen Sie ein Mindestguthaben von {{minimumBondBalance}}, um eine Nominierungsabsicht mitzuteilen.", + "bondedBalanceBelowMinimum" : "Als Nominator brauchst du ein Mindestguthaben von {{minimumBondBalance}}, um eine Nominierungsabsicht mitzuteilen.", "nomination" : { "emptyState" : { "description" : "Du kannst Prämien verdienen, indem du Vermögenswerte bindest und dann deine(n) Validator(en) nominierst.", @@ -3345,9 +3356,9 @@ "amount" : "Gebundener Betrag", "commission" : "Provision", "active" : "Aktiv", - "activeTooltip" : "Dieser Validator ist gewählt und sammelt Prämien für Ihr gebundenes Vermögen.", + "activeTooltip" : "Dieser Validator ist gewählt und sammelt Prämien für dein gebundenes Vermögen.", "inactive" : "Inaktiv", - "inactiveTooltip" : "Dieser Validator ist gewählt, sammelt aber keine Prämien für Ihr gebundenes Vermögen.", + "inactiveTooltip" : "Dieser Validator ist gewählt, sammelt aber keine Prämien für dein gebundenes Vermögen.", "waiting" : "Nicht gewählt", "waitingTooltip" : "Dieser Validator ist nicht gewählt, sammelt also keine Prämien.", "notValidator" : "Kein Validator", @@ -3361,9 +3372,9 @@ "electionOpen" : "Die Wahl der neuen Validatoren ist derzeit im Gange. Daher sind die Einsätze für maximal 15 Minuten nicht verfügbar.", "electionOpenTooltip" : "Dieser Vorgang ist während der Wahl der Validatoren deaktiviert", "externalControllerTooltip" : "Dieses Konto wird von einem anderen Konto gesteuert.", - "externalControllerUnsupported" : "<0>Dieses Stash-Konto wird von einem separaten Konto gesteuert, dessen Adresse <0>{{controllerAddress}} ist. Um mit Ledger Live zu staken, musst du dieses Stash-Konto als eigenen Controller einrichten.", + "externalControllerUnsupported" : "<0>Dieses Stash-Konto wird von einem separaten Konto gesteuert, dessen Adresse <0>{{controllerAddress}} ist.<1>Um mit Ledger Live zu staken, musst du dieses Stash-Konto als eigenen Controller einrichten.", "externalStashTooltip" : "Dieses Konto steuert ein anderes Konto.", - "externalStashUnsupported" : "Dieses Konto ist der Controller eines separaten Stash-Kontos, dessen Adresse <0>{{stashAddress}} ist. Um mit Ledger Live zu staken, musst du dein Stash-Konto als eigenen Controller einrichten.", + "externalStashUnsupported" : "<0>Dieses Konto ist der Controller eines separaten Stash-Kontos, dessen Adresse <0>{{stashAddress}} ist.<1>Um mit Ledger Live zu staken, musst du dein Stash-Konto als eigenen Controller einstellen.", "showInactiveNominations" : "Alle Nominierungen anzeigen ({{count}})", "hideInactiveNominations" : "Nur aktive Nominierungen anzeigen", "noActiveNominations" : "Es sind keine aktiven Nominierungen vorhanden.", @@ -3374,7 +3385,7 @@ "header" : "Entbinden", "headerTooltip" : "Verfügbar nach der 28-tägigen Frist", "withdrawUnbonded" : "({{amount}}) Abheben", - "withdrawTooltip" : "Der nicht gebundene Betrag wird Ihrem verfügbaren Guthaben gutgeschrieben.", + "withdrawTooltip" : "Der nicht gebundene Betrag wird deinem verfügbaren Guthaben gutgeschrieben.", "noUnlockedWarning" : "Noch kein ungebundenes Guthaben zum Abheben.", "rebond" : "Erneut binden", "unbonded" : "Entbunden" @@ -3407,7 +3418,7 @@ "steps" : { "validators" : { "title" : "Validatoren", - "notValidatorsRemoved" : "Du hast {{count}} Adressen nominiert, die keine Validatoren mehr sind. Sie werden automatisch aus deiner Nominierungstransaktion entfernt.", + "notValidatorsRemoved" : "Du hast {{count}} Adressen nominiert, die keine Validatoren mehr sind. Sie werden automatisch aus deiner Nominierungstransaktion entfernt.", "maybeChill" : "Stattdessen Nominierungen löschen" }, "connectDevice" : { @@ -3424,7 +3435,7 @@ "pending" : { "title" : "Sende Transaktion..." }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -3433,16 +3444,20 @@ "rewardDestination" : { "label" : "Prämienziel", "stash" : "Verfügbares Guthaben", - "stashDescription" : "Die Prämien werden Ihrem verfügbaren Guthaben gutgeschrieben.", + "stashDescription" : "Die Prämien werden deinem verfügbaren Guthaben gutgeschrieben.", "staked" : "Gebundenes Guthaben", "stakedDescription" : "Prämien werden deinem Guthaben gutgeschrieben, sodass du mehr Geld verdienen kannst.", "optionTitle" : "Hinweis", - "optionDescription" : "Einmal eingestellt, ist die Option für die Lebensdauer dieser Anleihe festgelegt. Wenn du deine Meinung änderst, lies bitte den Artikel weiter unten" + "optionDescription" : "Einmal eingestellt, ist die Option für die Lebensdauer dieses Bonds festgelegt. Wenn du deine Meinung änderst, lies bitte den Artikel weiter unten." }, "steps" : { "starter" : { "description" : "Du kannst Prämien verdienen, indem du dein Vermögen bindest und dann deine Validatoren nominierst.", - "bullet" : ["Du behältst das Eigentum an gebundenen Vermögenswerten", "Nominiere mit deinem Ledger-Gerät", "Vermögenswerte sind 28 Tage nach Aufhebung der Bindung verfügbar"], + "bullet" : [ + "Du behältst das Eigentum an gebundenen Vermögenswerten", + "Nominiere mit deinem Ledger-Gerät", + "Vermögenswerte sind 28 Tage nach Aufhebung der Bindung verfügbar" + ], "help" : "Wie Nominierungen funktionieren", "warning" : "Wähle deinen Validator mit Bedacht: Ein Teil deiner gebundenen Vermögenswerte kann unwiderruflich verloren gehen, wenn sich der Validator nicht angemessen verhält." }, @@ -3473,7 +3488,7 @@ "pending" : { "title" : "Vermögenswerte werden gebunden ..." }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -3500,9 +3515,9 @@ "cta" : "Details anzeigen" }, "pending" : { - "title" : "Ihre Vermögenswerte neu binden ..." + "title" : "Deine Vermögenswerte werden neu gebunden …" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -3529,9 +3544,9 @@ "cta" : "Details anzeigen" }, "pending" : { - "title" : "Bindung Ihres Vermögens wird aufgehoben ..." + "title" : "Die Bindung deiner Vermögenswerte wird aufgehoben …" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, @@ -3571,7 +3586,7 @@ "pending" : { "title" : "Sende Transaktion..." }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -3582,7 +3597,7 @@ "steps" : { "assets" : { "title" : "Vermögenswert", - "info" : "Das Hinzufügen eines Vermögenswerts erfordert das Senden einer Transaktion mit Mindestgebühren. Dies wird in Ihrem Transaktionsverlauf angezeigt", + "info" : "Das Hinzufügen eines Vermögenswerts erfordert das Senden einer Transaktion mit Mindestgebühren. Dies wird in deinem Transaktionsverlauf angezeigt", "selectLabel" : "Wähle einen Vermögenswert aus", "disabledTooltip" : "Du hast diesen Vermögenswert bereits auf deinem Stellar-Konto" }, @@ -3596,14 +3611,14 @@ "text" : "Du kannst jetzt <0>{{token}}-Vermögenswerte auf deinem Stellar-Konto empfangen und senden.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } }, "solana" : { "common" : { - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst.", + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf.", "viewDetails" : "Details anzeigen", "connectDevice" : { "title" : "Gerät" @@ -3829,7 +3844,7 @@ "pendingBalance" : "Ausstehender Saldo", "pendingBalanceTooltip" : "Dieser Betrag wird nicht mehr gestaked, steht aber derzeit noch nicht zur Verfügung.", "storageUsageBalance" : "Minimales Guthaben", - "storageUsageBalanceTooltip" : "Dieser Betrag ist für Speicherungen und Transaktionen reserviert und ist das Mindestguthaben, das auf Ihrem Konto verfügbar sein muss, um aktiv zu bleiben.", + "storageUsageBalanceTooltip" : "Dieser Betrag ist für Speicherung und Transaktionen reserviert und ist das Mindestguthaben, das auf deinem Konto verfügbar sein muss, um aktiv zu bleiben.", "subHeader" : { "cardTitle" : "Powered by Figment", "moreInfo" : "Mehr Infos", @@ -3870,7 +3885,11 @@ "steps" : { "starter" : { "description" : "Du kannst durch Staking deiner NEAR-Werte bei einem Validator Belohnungen verdienen.", - "bullet" : ["Du behältst das Eigentum an den gestaketen Vermögenswerten.", "Staking mit Ihrem Ledger-Gerät", "Vermögenswerte sind 52 — 65 Stunden nach dem Aufheben des Staking-Prozesses verfügbar."], + "bullet" : [ + "Du behältst das Eigentum an den gestaketen Vermögenswerten.", + "Staking mit deinem Ledger-Gerät", + "Vermögenswerte sind 52 — 65 Stunden nach dem Aufheben des Staking-Prozesses verfügbar." + ], "warning" : { "description" : "Wähle deinen Validator mit Bedacht: Ein Teil deiner gestaketen Vermögenswerte kann unwiderruflich verloren gehen, wenn sich der Validator nicht angemessen verhält." } @@ -3892,7 +3911,7 @@ "text" : "Dein Kontostand wird aktualisiert, wenn die Blockchain die Transaktion bestätigt.", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -3921,7 +3940,7 @@ "description" : "<0>{{amount}} von <0>{{validator}} werden nicht mehr gestaket", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -3948,7 +3967,7 @@ "description" : "<0>{{amount}} von <0>{{validator}} wurden abgehoben", "cta" : "Details anzeigen" }, - "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe den Transaktionsverlauf, bevor du es noch einmal versuchst." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } } @@ -3981,9 +4000,9 @@ "title" : "Prämien für Einsätze verdienen", "description" : "Delegiere dein Tezos-Konto an einen externen Validator, um Einsatzprämien zu verdienen und trotzdem die volle Sicherheit und Kontrolle über deine Vermögenswerte zu behalten.", "bullet" : { - "delegate" : "Delegierte Konten bleiben Ihre.", - "access" : "Sie können jederzeit auf Ihre Vermögenswerte zugreifen.", - "ledger" : "Delegieren Sie sicher mit Ihrem Ledger-Gerät." + "delegate" : "Delegierte Konten bleiben dein Eigentum.", + "access" : "Du kannst jederzeit auf deine Vermögenswerte zugreifen.", + "ledger" : "Delegiere sicher mit deinem Ledger-Gerät." }, "button" : { "cta" : "Delegieren, um Prämien zu verdienen" @@ -4003,17 +4022,17 @@ "select" : "Auswählen", "yield" : "Geschätzter Ertrag {{amount}}", "randomly" : "Zufällig gewählter Validator", - "termsAndPrivacy" : "Das Delegieren Ihrer Stimmrechte garantiert keine Prämien durch Ihren Validator." + "termsAndPrivacy" : "Das Delegieren deiner Voting-Rechte garantiert keine Prämien durch deinen Validator." }, "validator" : { "title" : "Validator auswählen", - "description" : "Sie können einen Validator auswählen, indem Sie die geschätzten Prämienraten vergleichen", + "description" : "Du kannst einen Validator auswählen, indem du die geschätzten Prämienquoten vergleichst.", "customValidator" : "Benutzerdefinierter Validator", "providedBy" : "Ertragsraten bereitgestellt von <1><0>{{name}}" }, "custom" : { "title" : "Benutzerdefinierter Validator", - "text" : "Bitte geben Sie die Adresse des benutzerdefinierten Validators ein, an den Sie Ihr Konto übertragen möchten.", + "text" : "Bitte gib die Adresse des benutzerdefinierten Validators ein, an den du dein Konto delegieren möchtest.", "button" : "Validator verwenden" }, "undelegate" : { @@ -4025,15 +4044,15 @@ "success" : { "title" : "Delegierung gesendet", "titleUndelegated" : "Delegierung beenden", - "text" : "Die Delegierungstransaktion wurde erfolgreich übertragen. Sie sollten Ihre ersten Prämien innerhalb von etwa 40 Tagen verdienen, je nach Validator.", - "textUndelegated" : "Ihre Kontodelegierung endet, sobald der Vorgang bestätigt ist. Sie können Ihr Konto jederzeit erneut delegieren." + "text" : "Die Delegierungstransaktion wurde erfolgreich übertragen. Du solltest deine ersten Prämien abhängig vom Validator innerhalb von etwa 40 Tagen verdienen.", + "textUndelegated" : "Deine Kontodelegierung endet, sobald der Vorgang bestätigt ist. Du kannst dein Konto jederzeit erneut delegieren." }, - "broadcastError" : "Ihre Transaktion ist möglicherweise fehlgeschlagen. Bitte warten Sie einen Moment und prüfen Sie den Transaktionsverlauf, bevor Sie es erneut versuchen." + "broadcastError" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." } } }, "contextMenu" : { - "topUp" : "Erhalten Sie mehr", + "topUp" : "Mehr erhalten", "redelegate" : "Validator ändern", "stopDelegation" : "Delegierung beenden" } @@ -4064,33 +4083,33 @@ "export" : { "accounts" : { "title" : "Konten exportieren", - "desc" : "Fügen Sie Ihre Konten in Ledger Live Mobile hinzu. Ihre Konten werden nur mit der Blockchain synchronisiert, nicht zwischen Ihren mobilen und Desktop-Apps.", + "desc" : "Füge deine Konten in Ledger Live Mobile hinzu. Deine Konten werden nur mit der Blockchain synchronisiert, jedoch nicht zwischen der Mobil- und der Desktop-App.", "button" : "Exportieren" }, "operations" : { "title" : "Historie der Kontobewegungen", - "desc" : "Speichern Sie eine CSV-Datei mit Ihren Kontobewegungen auf Ihrem Computer." + "desc" : "Speichere eine CSV-Datei mit deinen Kontobewegungen auf deinem Computer." }, "modal" : { "button" : "Fertig", "title" : "Scannen zum Exportieren auf Mobile", "listTitle" : "In der Ledger Live Mobile App:", "step1" : "Tippe auf dem Hauptbildschirm auf Konto hinzufügen oder Alle Vermögenswerte anzeigen und dann auf die Schaltfläche +.", - "step2" : "Tippen Sie auf Desktop-Konten importieren", - "step3" : "Scannen Sie den LiveQR-Code, bis der Ladestand 100% erreicht" + "step2" : "Tippe auf Import desktop accounts (Desktopkonten importieren).", + "step3" : "Scanne den LiveQR-Code, bis ein Fortschritt von 100 % erreicht wurde." } }, "display" : { "language" : "Sprache", - "languageDesc" : "Stellen Sie die in Ledger Live angezeigte Sprache ein.", + "languageDesc" : "Stelle die Anzeigesprache für Ledger Live ein.", "theme" : "Design", "themeDesc" : "Design auswählen.", "counterValue" : "Bevorzugte Währung", - "counterValueDesc" : "Wählen Sie die Währung, die neben Ihrem Saldo und den Aktionen angezeigt wird.", + "counterValueDesc" : "Wähle die Währung, die neben deinem Saldo und den Aktionen angezeigt wird.", "region" : "Region", - "regionDesc" : "Wählen Sie Ihre Region, um Datums-, Zeit- und Währungsformate zu aktualisieren.", + "regionDesc" : "Wähle deine Region aus, um Datums-, Zeit- und Währungsformate zu aktualisieren.", "stock" : "Regionaler Marktindikator", - "stockDesc" : "Wählen Sie Westlich, um Marktsteigerungen in Blau anzuzeigen, oder Östlich, um sie in Rot anzuzeigen.", + "stockDesc" : "Wähle „Western“ (Westlich) aus, um Marktsteigerungen in Blau anzuzeigen, oder „Eastern“ (Östlich), um sie in Rot anzuzeigen.", "walletSync" : "Ledger Sync", "walletSyncDesc" : "Synchronisiere deine Ledger Live-Kryptokonten auf verschiedenen Smartphones und Computern.", "mevProtection" : "MEV-Schutz", @@ -4106,14 +4125,14 @@ "hide" : "Ausblenden", "show" : "Anzeigen", "toast" : { - "title" : "Sie sind jetzt ein Entwickler!", + "title" : "Jetzt bist du ein Entwickler!", "text" : "Willkommen im Wunderland" }, "userId" : "Benutzer-ID", "debugApps" : "Erlauben von Debug-Apps", "debugAppsDesc" : "Anzeigen und Öffnen von Debug-getaggten Plattform-Apps erlauben.", "debugReactQuery" : "Debuggen von ReactQuery erlauben", - "debugReactQueryDesc" : "Zeige die Konsole zum Debuggen von ReactQuery an und erlaube es, sie zu öffnen.", + "debugReactQueryDesc" : "Zeigt die Debug-Konsole für ReactQuery an und erlaubt es, sie zu öffnen.", "exchangeDeveloperMode" : { "title" : "Entwicklermodus für Börsen", "desc" : "Info des Börsenanbieters hinzufügen", @@ -4175,7 +4194,7 @@ "tokenIdDesc" : "Token-ID des gemeldeten NFTs", "eventType" : "Art des Ereignisses", "eventTypeDesc" : "Art der Meldung, die du machen möchtest", - "success" : "Meldung erfolgreich gesendet. Die Umsetzung dauert möglicherweise 5 bis 10 Minuten.", + "success" : "Meldung erfolgreich gesendet. Die Umsetzung kann zwischen 5 und 10 Minuten dauern.", "error" : "Beim Senden der Meldung ist ein Fehler aufgetreten. Versuche es bitte später noch einmal.", "reportType" : { "title" : "Was möchtest du melden?", @@ -4255,9 +4274,9 @@ "mockAppUpdate" : "Mock-App-Update", "mockAppUpdateDesc" : "Zeigt das verfügbare App-Update unter „My Ledger“ an. Dieselbe App-Version wird erneut installiert.", "catalogUrl" : "Anbieter Katalog-Apps festlegen", - "catalogUrlDesc" : "Geben Sie die benutzerdefinierte URL Ihres Kataloganbieters ein", + "catalogUrlDesc" : "Gib die benutzerdefinierte URL deines Kataloganbieters ein", "enablePlatformDevTools" : "Plattform-Entwicklungswerkzeuge aktivieren", - "enablePlatformDevToolsDesc" : "Aktivieren Sie das Öffnen des Entwicklerwerkzeug-Fensters für Plattform-Apps", + "enablePlatformDevToolsDesc" : "Aktiviert das Öffnen des DevTools-Fensters für Plattform-Apps", "customLockScreen" : "Individuelle Sperrbildschirm-Elemente", "customLockScreenDesc" : "Debuggen von individuellen Grafikelementen für den Sperrbildschirm", "customLockScreenCTA" : "Starten", @@ -4278,7 +4297,7 @@ }, "firebaseProject" : "Firebase-Projekt, auf das diese Entwicklung abzielt", "addLocalApp" : "Lokale App hinzufügen", - "addLocalAppDesc" : "Durchsuchen Sie lokale Dateien und fügen Sie eine lokale App mit einem lokalen Manifest hinzu", + "addLocalAppDesc" : "Durchsucht lokale Dateien und fügt eine lokale App mithilfe eines lokalen Manifests hinzu", "addLocalAppButton" : "Durchsuchen", "createLocalAppModal" : { "title" : { @@ -4294,39 +4313,39 @@ "runLocalAppDeleteButton" : "Löschen", "runLocalAppOpenButton" : "offen", "enableLearnStagingUrl" : "Staging-URL für Lernen-Seite", - "enableLearnStagingUrlDesc" : "Aktivieren Sie die Staging-URL für die Lernen-Seite.", + "enableLearnStagingUrlDesc" : "Aktiviere die Staging-URL für die Lernseite.", "enableStagingNftMetadataService" : "Staging-NFT-Metadatendienst", - "enableStagingNftMetadataServiceDesc" : "Aktivieren Sie den Staging-NFT-Metadatendienst und setzen Sie den NFT-Cache zurück", + "enableStagingNftMetadataServiceDesc" : "Aktiviere den Staging-NFT-Metadatendienst und setze den NFT-Cache zurück", "openOnboardingAppInstallDebug" : "Bildschirm zum Installieren der Debug-Anwendung der Onboarding-App öffnen", - "openOnboardingAppInstallDebugDesc" : "Öffnen Sie einen Bildschirm mit den Komponenten aus dem Installationsschritt der Sync-Onboarding-App" + "openOnboardingAppInstallDebugDesc" : "Öffne einen Bildschirm mit den Komponenten aus dem Installationsschritt der Sync-Onboarding-App" }, "currencies" : { "selectPlaceholder" : "Krypto-Vermögenswert auswählen", - "desc" : "Wählen Sie einen Krypto-Vermögenswert, um dessen Einstellungen zu bearbeiten.", + "desc" : "Wähle einen Kryptovermögenswert aus, um dessen Einstellungen zu bearbeiten.", "placeholder" : "Keine Einstellungen für diesen Vermögenswert", "confirmationsNb" : "Anzahl der Bestätigungen", - "confirmationsNbDesc" : "Legen Sie die Anzahl der Netzwerkbestätigungen für eine Transaktion fest, die als bestätigt markiert werden soll." + "confirmationsNbDesc" : "Legt die Anzahl der Netzwerkbestätigungen fest, die erforderlich sind, damit eine Transaktion als bestätigt gekennzeichnet wird." }, "profile" : { "password" : "Passwort-Sperre", - "passwordDesc" : "Legen Sie ein Passwort fest, um die Ledger Live-Daten auf Ihrem Computer zu schützen, einschließlich Kontonamen, Kontoständen, Transaktionen und öffentliche Adressen.", + "passwordDesc" : "Legt ein Passwort fest, um die Ledger Live-Daten auf deinem Computer (Kontonamen, Kontostände, Transaktionen, öffentliche Adressen) zu schützen.", "passwordAutoLock" : "Auto-Sperre", - "passwordAutoLockDesc" : "Sperren Sie Ledger Live automatisch bei Inaktivität.", + "passwordAutoLockDesc" : "Sperrt Ledger Live automatisch bei Inaktivität.", "changePassword" : "Passwort ändern", "softResetTitle" : "Cache löschen", - "softResetDesc" : "Löschen Sie den Ledger Live-Cache, um eine erneute Synchronisierung mit der Blockchain zu erzwingen.", + "softResetDesc" : "Löscht den Ledger Live-Cache, um eine erneute Synchronisierung mit der Blockchain zu erzwingen.", "softReset" : "Leeren", "resetThirdPartyData" : "Drittanbieterdaten zurücksetzen", - "resetThirdPartyDataDesc" : "Löschen Sie alle lokalen Drittanbieterdaten, die für den Zugriff auf Transaktionsservices von Drittanbietern verwendet wurden.", + "resetThirdPartyDataDesc" : "Löscht alle lokalen Drittanbieterdaten, die für den Zugriff auf Transaktionsservices von Drittanbietern verwendet wurden.", "hardResetTitle" : "Ledger Live zurücksetzen", - "hardResetDesc" : "Löschen Sie alle auf Ihrem Computer gespeicherten Ledger Live-Daten, einschließlich Ihrer Konten, Transaktionshistorien und Einstellungen.", + "hardResetDesc" : "Löscht alle auf deinem Computer gespeicherten Ledger Live-Daten (Konten, Transaktionshistorien, Einstellungen).", "hardReset" : "Zurücksetzen", "analytics" : "Analysen", - "analyticsDesc" : "Aktivieren Sie Analysen, um Ledger bei der Verbesserung der Benutzererfahrung zu helfen. Dazu gehören Klicks, Seitenbesuche, Weiterleitungen, Aktionen (Senden, Empfangen, Sperren usw.), Scrollen am Ende der Seite, (De-)Installieren und App-Version, Anzahl der Konten, Krypto-Vermögenswerte und Aktionen, Sitzungsdauer, der Ledger-Gerätetyp und die Firmware.", + "analyticsDesc" : "Aktiviert Analysen, um Ledger bei der Nutzungsoptimierung zu unterstützen. Dies umfasst Klicks, Seitenbesuche, Weiterleitungen, Aktionen (Senden, Empfangen, Sperren usw.), Scrollen zum Seitenende, (De-)Installieren und App-Version, Anzahl der Konten, Kryptovermögenswerte und Aktionen, Sitzungsdauern, Art des Ledger-Geräts und die Firmware.", "reportErrors" : "Fehlerberichte", "reportErrorsDesc" : "Berichte automatisch versenden, um Ledger bei der Verbesserung seiner Produkte zu unterstützen.", "launchOnboarding" : "Gerät einrichten", - "launchOnboardingDesc" : "Richten Sie ein neues Gerät ein oder stellen Sie ein vorhandenes Gerät wieder her. Konten und Einstellungen werden beibehalten." + "launchOnboardingDesc" : "Richtet ein neues Gerät ein bzw. stellt ein bestehendes Gerät wieder her. Konten und Einstellungen werden beibehalten." }, "help" : { "version" : "Version", @@ -4334,22 +4353,22 @@ "termsBtn" : "Lesen", "faq" : "Ledger Support", "chatbot" : "Ledger-Chatbot", - "faqDesc" : "Falls Sie ein Problem haben, nutzen Sie Ledger Live mit Ihrer Hardware-Wallet.", + "faqDesc" : "Falls ein Problem aufgetreten ist, erhältst du Hilfe über Ledger Live in Verbindung mit deiner Hardware-Wallet.", "terms" : "Nutzungsbedingungen", - "termsDesc" : "Durch die Nutzung von Ledger Live wird davon ausgegangen, dass Sie unsere Nutzungsbedingungen akzeptiert haben.", + "termsDesc" : "Die Nutzung von Ledger Live gilt als Annahme unserer Nutzungsbedingungen.", "privacy" : "Datenschutzrichtlinie", - "privacyDesc" : "In unseren Datenschutzrichtlinien erfahren Sie, welche persönlichen Daten wir erfassen, warum wir das tun und wie wir sie verwenden." + "privacyDesc" : "Unserer Datenschutzrichtlinie kannst du entnehmen, welche personenbezogenen Daten wir erheben und warum und wie wir sie nutzen." }, "experimental" : { - "disclaimer" : "Dies sind experimentelle Funktionen, die wir für unsere technisch versierte Community zum Testen bereitstellen. Sie können jederzeit geändert, abgebrochen oder entfernt werden. Dadurch, dass Sie sie aktivieren, erklären Sie sich damit einverstanden, sie auf eigenes Risiko zu nutzen.", - "provider" : "Die experimentelle Einstellung „My Ledger provider ({{forcedProvider}})“ zeigt möglicherweise nicht freigegebene Betriebssysteme und Apps an, was zu Kompatibilitätsproblemen führen kann. Sie können sie in den Einstellungen deaktivieren.", - "providerDevMode" : "Die experimentellen Einstellungen „My Ledger provider ({{forcedProvider}})“ und „Developer mode“ zeigen möglicherweise nicht freigegebene Betriebssysteme und Apps an, was zu Kompatibilitätsproblemen führen kann. Sie können sie daher in den Einstellungen deaktivieren.", - "devMode" : "Die experimentelle Einstellung „Developer mode“ zeigt möglicherweise nicht freigegebene Betriebssysteme und Apps an, was zu Kompatibilitätsproblemen führen kann. Sie können sie daher in den Einstellungen deaktivieren.", - "providerCTA" : "Gehen Sie zu Einstellungen", + "disclaimer" : "Hierbei handelt es sich um experimentelle Funktionen, die wir unserer technisch versierten Community zum Testen zur Verfügung stellen. Sie können jederzeit geändert, abgebrochen oder entfernt werden. Durch ihre Aktivierung erklärst du dich damit einverstanden, dass du sie auf eigenes Risiko nutzt.", + "provider" : "Die experimentelle Einstellung „My Ledger provider ({{forcedProvider}})“ zeigt möglicherweise nicht freigegebene Betriebssysteme und Apps an, was zu Kompatibilitätsproblemen führen kann. Du kannst sie daher in den Einstellungen deaktivieren.", + "providerDevMode" : "Die experimentellen Einstellungen „My Ledger provider ({{forcedProvider}})“ und „Developer mode“ zeigen möglicherweise nicht freigegebene Betriebssysteme und Apps an, was zu Kompatibilitätsproblemen führen kann. Du kannst sie daher in den Einstellungen deaktivieren.", + "devMode" : "Die experimentelle Einstellung „Developer mode“ zeigt möglicherweise nicht freigegebene Betriebssysteme und Apps an, was zu Kompatibilitätsproblemen führen kann. Du kannst sie in den Einstellungen deaktivieren.", + "providerCTA" : "Gehe zu den Einstellungen", "features" : { "experimentalCurrencies" : { "title" : "Experimentelle Integrationen", - "description" : "Verwenden Sie verfügbare experimentelle Integrationen für Krypto-Werte." + "description" : "Verwendet verfügbare experimentelle Integrationen für Kryptowerte." }, "experimentalLanguages" : { "title" : "Testen der Übersetzung", @@ -4357,7 +4376,7 @@ }, "managerDevMode" : { "title" : "Entwicklermodus", - "description" : "Zeigen Sie Entwickler- und Testnet-Apps in My Ledger an." + "description" : "Zeigt Entwickler- und Testnet-Apps in My Ledger an." }, "listAppsV2" : { "title" : "Experimentelle Apps-Liste für My Ledger", @@ -4365,28 +4384,28 @@ }, "scanForInvalidPaths" : { "title" : "Erweiterte Kontosuche", - "description" : "Suchen Sie nach Konten mit fehlerhaften Ableitungspfaden. Bitte senden Sie potenziell gefundene Vermögenswerte an ein reguläres Konto." + "description" : "Sucht nach Konten mit fehlerhaften Ableitungspfaden. Bitte sende potenziell gefundene Vermögenswerte an ein reguläres Konto." }, "experimentalExplorers" : { "title" : "Experimentelle Explorer-API", - "description" : "Probieren Sie eine kommende Version von Ledgers Blockchain-Explorern aus. Das Ändern dieser Einstellung kann den Kontostand und die Synchronisation sowie die Sendefunktion beeinflussen.\n(<0>)" + "description" : "Ermöglicht das Testen einer anstehenden Version der Blockchain-Explorer von Ledger. Das Ändern dieser Einstellung kann den Kontostand und die Synchronisation sowie die Sendefunktion beeinflussen.\n(<0>)" }, "keychainObservableRange" : { "title" : "Benutzerdefiniertes Lückenlimit", - "description" : "Benutzerdefiniertes Lückenlimit für alle Konten. Wenn Sie diesen Wert über den Standardwert (20) erhöhen, werden mehr ungenutzte öffentliche Adressen nach Coins durchsucht. Nur für fortgeschrittene Benutzer, dies kann die Kompatibilität beim Wiederherstellen Ihrer Konten beeinträchtigen." + "description" : "Benutzerdefiniertes Lückenlimit für alle Konten. Wenn du diesen Wert über den Standardwert (20) hinaus erhöhst, werden mehr ungenutzte öffentliche Adressen nach Coins durchsucht. Nur für fortgeschrittene Benutzer geeignet. Die Einstellung kann die Kompatibilität beim Wiederherstellen deiner Konten beeinträchtigen." }, "forceProvider" : { "title" : "Anbieter in My Ledger", - "description" : "Das Wechseln des App-Anbieters in My Ledger kann es unmöglich machen, Apps auf Ihrem Ledger-Gerät zu installieren oder zu deinstallieren." + "description" : "Das Wechseln des App-Anbieters in My Ledger kann es unmöglich machen, Apps auf deinem Ledger-Gerät zu installieren oder zu deinstallieren." }, "testAnimations" : { "title" : "Lottie-Animationen testen", - "description" : "Testen Sie alle Animationen, die in Ledger Live verwendet werden", + "description" : "Testet alle Animationen, die in Ledger Live verwendet werden.", "longDesc" : "Dieses wie besehen („as-is“) zur Verfügung gestellte Tool ermöglicht es dem Team, die in der App verwendeten Lottie-Animationen zu überprüfen." }, "testStories" : { "title" : "Storyly-Storys testen", - "description" : "Testen Sie alle in Ledger Live verwendeten Storys", + "description" : "Testet alle in Ledger Live verwendeten Storys.", "longDesc" : "Dieses wie besehen („as-is“) zur Verfügung gestellte Tool ermöglicht es dem Team, die in der App verwendeten Storily-Storys zu überprüfen." }, "testStaxPostonboarding" : { @@ -4403,15 +4422,15 @@ }, "vaultSigner" : { "title" : "Vault-Unterzeichner", - "description" : "Verwenden Sie Ledger Vault als Unterzeichner mit Ihrem Operator-API-Token" + "description" : "Verwende Ledger Vault als Unterzeichner mit deinem Operator-API-Token" }, "1559CustomPriorityLowerGate" : { "title" : "Benutzerdefinierte Grenze für Prioritätsgebühren", - "description" : "Passen Sie den Prozentsatz unserer voraussichtlichen Mindestprioritätsgebühr für eine erweiterte EIP1559-Transaktion an." + "description" : "Passt den Prozentsatz unserer voraussichtlichen Mindestprioritätsgebühr für eine erweiterte EIP1559-Transaktion an." }, "1559CustomBaseFeeMultiplier" : { "title" : "Benutzerdefinierten Faktor für Mindestgebühr eingeben", - "description" : "Passen Sie den für die Mindestgebühr verwendeten Multiplikationsfaktor an. Hieraus setzt sich die maxFeePerGas der EIP1559-Transaktion zusammen." + "description" : "Passe den für die Mindestgebühr verwendeten Multiplikationsfaktor an. Hieraus setzt sich die maxFeePerGas der EIP1559-Transaktion zusammen." }, "enableNetworkLogs" : { "title" : "Netzwerklogs aktivieren", @@ -4421,36 +4440,36 @@ }, "hardResetModal" : { "title" : "Ledger Live zurücksetzen", - "desc" : "Setzen Sie Ledger Live zurück, um alle Einstellungen und Konten auf Ihrem Computer zu löschen. Sie können dann Ihr Passwort wählen und Ihre Konten wieder mit Ihrem Ledger-Gerät hinzufügen. Die privaten Schlüssel, die Zugang zu Ihren Krypto-Vermögenswerten geben, bleiben sicher auf Ihrem Ledger-Gerät und werden durch Ihren Wiederherstellungssatz gesichert.", - "warning" : "Das Zurücksetzen von Ledger Live löscht Ihren Swap-Transaktionsverlauf für alle Ihre Konten." + "desc" : "Setzt Ledger Live zurück, um alle Einstellungen und Konten auf deinem Computer zu löschen. Du kannst dann dein Passwort auswählen und deine Konten wieder mit deinem Ledger-Gerät hinzufügen. Die privaten Schlüssel, die Zugang zu deinen Kryptovermögenswerten geben, verbleiben sicher auf deinem Ledger-Gerät und werden durch deine Wiederherstellungsphrase gesichert.", + "warning" : "Das Zurücksetzen von Ledger Live löscht die Swap-Transaktionsverläufe für alle deine Konten." }, "softResetModal" : { "title" : "Cache löschen", - "desc" : "Das Löschen des Caches erzwingt eine erneute Netzwerksynchronisation. Ihre Einstellungen und Konten bleiben erhalten. Die privaten Schlüssel für den Zugriff auf Ihre Krypto-Vermögenswerte bleiben sicher auf Ihrem Ledger-Gerät und dem Recovery Sheet." + "desc" : "Das Löschen des Caches erzwingt eine erneute Netzwerksynchronisation. Deine Einstellungen und Konten bleiben erhalten. Die privaten Schlüssel, die Zugang zu deinen Kryptovermögenswerten geben, verbleiben sicher auf deinem Ledger-Gerät und werden durch deine Wiederherstellungsphrase gesichert." }, "resetFallbackModal" : { "title" : "Benutzeraktion erforderlich", - "part1" : "Der Cache-Ordner konnte nicht gelöscht werden. Bitte löschen Sie den Ordner manuell:", - "part2" : "Klicken Sie auf die Schaltfläche Ordner öffnen, die ", + "part1" : "Der Cache-Ordner konnte nicht gelöscht werden. Bitte lösche den Ordner manuell:", + "part2" : "Klicke auf die Schaltfläche „Open folder“ (Ordner öffnen), die ", "part3" : "App wird geschlossen", - "part4" : "und löschen Sie den Ordner \"sqlite\" manuell.", - "part5" : "Danach können Sie die App normal neu starten." + "part4" : "und lösche den Ordner „sqlite“ manuell.", + "part5" : "Danach kannst du die App ganz normal neu starten." }, "removeAccountModal" : { "title" : "Konto entfernen", - "desc" : "Ihre Krypto-Vermögenswerte sind davon nicht betroffen. Bestehende Konten können jederzeit wieder hinzugefügt werden.", + "desc" : "Deine Kryptowerte sind davon nicht betroffen. Bestehende Konten können jederzeit wieder hinzugefügt werden.", "delete" : "Aus Portfolio entfernen", - "warning" : "Das Entfernen dieses Kontos löscht Ihren zugehörigen Swap-Transaktionsverlauf." + "warning" : "Das Entfernen dieses Kontos löscht deinen zugehörigen Swap-Transaktionsverlauf." }, "openUserDataDirectory" : { "title" : "Benutzerdaten anzeigen", - "desc" : "Zeigen Sie die auf Ihrem Computer gespeicherten Benutzerdaten an, einschließlich Ihrer Konten, Caches und Einstellungen.", + "desc" : "Zeigt die auf deinem Computer gespeicherten Benutzerdaten an, einschließlich deiner Konten, Caches und Einstellungen.", "btn" : "Anzeigen" }, "repairDevice" : { - "title" : "Reparieren Sie Ihr Ledger-Gerät", - "descSettings" : "Verwenden Sie dies, um Ihr Ledger-Gerät wiederherzustellen, wenn es während eines Firmware-Updates gesperrt wurde.", - "desc" : "Ledger Nano S-Benutzer wählen bitte den auf Ihrem Gerät angezeigten Status. Nano X- und Blue-Benutzer schauen bitte im Hilfe-Center nach.", + "title" : "Ledger-Gerät reparieren", + "descSettings" : "Verwende diese Option, um dein Ledger-Gerät wiederherzustellen, wenn es während eines Firmware-Updates abgestürzt sein sollte.", + "desc" : "Ledger Nano S-Benutzer wählen hierzu den auf dem Gerät angezeigten Status. Benutzer von Nano X und Blue sollten das Hilfe-Center zurate ziehen.", "button" : "Reparieren" }, "exportLogs" : { @@ -4460,7 +4479,7 @@ }, "troubleshootNetwork" : { "title" : "Fehlersuche im Netzwerk", - "desc" : "Führen Sie eine Checkliste aus, um die Netzwerkbedingungen für die Fehlersuche zu bewerten.", + "desc" : "Arbeitet eine Checkliste ab, um die Netzwerkbedingungen zur Fehlerbehebung zu bewerten.", "btn" : "Fehlersuche" }, "accounts" : { @@ -4470,13 +4489,13 @@ }, "tokenBlacklist" : { "title" : "Ausgeblendete Token", - "desc" : "Sie können Token ausblenden, indem Sie zum übergeordneten Konto gehen, dann mit der rechten Maustaste auf das Token klicken und „Token ausblenden“ wählen.", + "desc" : "Du kannst Token ausblenden. Hierzu gehst du zum übergeordneten Konto, klickst mit der rechten Maustaste auf das Token und wählst „Hide token“ (Token ausblenden) aus.", "count" : "1 Token", "count_other" : "{{count}} Token" }, "hiddenNftCollections" : { "title" : "Ausgeblendete NFT-Sammlungen", - "desc" : "Sie können NFT-Sammlungen ausblenden, indem Sie mit der rechten Maustaste auf den Namen der Sammlung klicken und \"NFT-Sammlung ausblenden\" auswählen.", + "desc" : "Du kannst NFT-Sammlungen ausblenden, indem du mit der rechten Maustaste auf den Namen der Sammlung klickst und „Hide NFT Collection“ (NFT-Sammlung ausblenden) auswählst.", "count" : "1 Sammlung", "count_other" : "{{count}} Sammlungen" }, @@ -4488,7 +4507,7 @@ }, "fullNode" : { "title" : "Bitcoin Full Node verbinden", - "desc" : "Richten Sie Ihren Bitcoin-Knoten (Full Node) ein, um Transaktionen zu synchronisieren und zu senden, ohne die Explorer von Ledger zu verwenden." + "desc" : "Richte deinen Bitcoin-Full-Node ein, um Transaktionen zu synchronisieren und zu senden, ohne die Explorer von Ledger zu verwenden." }, "filterTokenOperationsZeroAmount" : { "title" : "Token-Transaktionen ausblenden, wenn der Wert 0 ist", @@ -4510,16 +4529,16 @@ }, "changePassword" : { "title" : "Passwort-Sperre", - "subTitle" : "Ändern Sie Ihr Passwort" + "subTitle" : "Passwort ändern" }, "setPassword" : { "title" : "Passwort-Sperre", - "subTitle" : "Legen Sie das Passwort fest", - "desc" : "Bewahren Sie Ihr Passwort sicher auf. Wenn Sie es verlieren, müssen Sie Ledger Live zurücksetzen und die Konten erneut hinzufügen." + "subTitle" : "Passwort festlegen", + "desc" : "Bewahre dein Passwort sicher auf. Wenn du es verlierst, musst du Ledger Live zurücksetzen und die Konten noch einmal hinzufügen." }, "disablePassword" : { "title" : "Passwortsperre deaktivieren", - "desc" : "Die Daten von Ledger Live werden unverschlüsselt auf Ihrem Computer gespeichert. Dazu gehören Kontonamen, Transaktionen und öffentliche Adressen." + "desc" : "Die Daten von Ledger Live werden unverschlüsselt auf deinem Computer gespeichert. Dazu gehören Kontonamen, Transaktionen und öffentliche Adressen." } }, "update" : { @@ -4531,12 +4550,12 @@ "updateAvailable" : "Update auf Ledger Live Version {{version}} ist verfügbar", "error" : "Fehler beim Update. Bitte erneut herunterladen", "reDownload" : "Erneut herunterladen", - "nightlyWarning" : "Diese Version kann nicht automatisch aktualisiert werden. Bitte installieren Sie die neueste Version manuell" + "nightlyWarning" : "Diese Version kann nicht automatisch aktualisiert werden. Bitte installiere die neueste Version manuell." }, "crash" : { "title" : "Etwas ist schief gelaufen", - "description" : "Bitte prüfen Sie unsere Support-Artikel auf mögliche Lösungen. Wenn das Problem weiterhin besteht, speichern Sie die Protokolle über die Schaltfläche unten und stellen Sie sie dem Ledger-Support zur Verfügung.", - "troubleshooting" : "Klicken Sie hier für mögliche Lösungen", + "description" : "Bitte lies dir unsere Supportartikel durch, um mögliche Lösungen zu finden. Wenn das Problem weiterhin besteht, speichere die Protokolle über die nachstehende Schaltfläche und übermittle sie an den Ledger-Kundenservice.", + "troubleshooting" : "Klicke hier für mögliche Lösungen", "logs" : "Protokolle speichern", "dataFolder" : "Benutzerdaten anzeigen" }, @@ -4553,15 +4572,15 @@ }, "exportOperationsModal" : { "title" : "Historie der Kontobewegungen", - "desc" : "Wählen Sie die Konten aus, für die der Verlauf gespeichert werden soll", - "descSuccess" : "Die CSV-Datei Ihres Verlaufs wurde erfolgreich im gewählten Ordner gespeichert", + "desc" : "Wähle die Konten aus, für die der Verlauf gespeichert werden soll", + "descSuccess" : "Die CSV-Datei mit deinem Verlauf wurde im ausgewählten Ordner gespeichert", "titleSuccess" : "Verlauf erfolgreich gespeichert", "cta" : "Speichern", "ctaSuccess" : "Fertig", "noAccounts" : "Keine Konten zum Exportieren", "selectedAccounts" : "Einzuschließende Konten", "selectedAccounts_plural" : "Einzuschließende Konten ({{count}})", - "disclaimer" : "Die Gegenwerte im Export werden nur zu Informationszwecken bereitgestellt. Verlassen Sie sich nicht auf diese Daten für buchhalterische, steuerliche, regulatorische oder rechtliche Zwecke, da sie nur eine Schätzung des Preises der Vermögenswerte zum Zeitpunkt der Transaktionen und des Exports darstellen, gemäß den von unserem Dienstleister Kaiko bereitgestellten Bewertungsmethoden" + "disclaimer" : "Die im Export enthaltenen Gegenwerte sind nur zu Informationszwecken angegeben. Stütze dich bei Buchhaltungs-, Steuer-, Regulierungs- oder Rechtsfragen nicht auf diese Daten, da sie nur eine Schätzung des Preises für die Vermögenswerte zum Zeitpunkt der Transaktionen und des Exports auf Grundlage der Bewertungsmethoden unseres Dienstleisters Kaiko darstellen." }, "language" : { "system" : "Systemsprache verwenden", @@ -4591,7 +4610,7 @@ "achievement" : "Erfolge entsperrt" }, "groupedToast" : { - "text" : "Sie haben {{count}} ungelesene Benachrichtigungen", + "text" : "Du hast {{count}} ungelesene Benachrichtigungen", "cta" : "Details ansehen" } }, @@ -4608,7 +4627,7 @@ "serviceStatus" : { "statusOk" : { "title" : "Ledger Live ist eingerichtet und läuft", - "description" : "Haben Sie Probleme? Gehen Sie auf unsere <0>Hilfe-Seite" + "description" : "Hast du ein Problem? Dann rufe unsere <0>Hilfe-Seite auf." }, "statusNotOk" : { "title" : "Bei Ledger Live treten Probleme auf", @@ -4618,48 +4637,48 @@ "announcement" : { "emptyState" : { "title" : "Im Moment keine Neuigkeiten", - "desc" : "Hier finden Sie alle Neuigkeiten rund um Ledger und Ledger Live" + "desc" : "Hier findest du alle Neuigkeiten rund um Ledger und Ledger Live." } } }, "onboarding" : { "drawers" : { "pinHelp" : { - "title" : "Sicheren Sie Ihren PIN-Code", - "intro" : "Während des Einrichtungsprozesses wählen Sie einen PIN-Code aus.", + "title" : "Sichere deinen PIN-Code", + "intro" : "Während des Einrichtungsprozesses wählst du einen PIN-Code aus.", "rules" : { - "1" : "Wählen Sie einen PIN-Code immer selbst aus.", - "2" : "Geben Sie Ihren PIN-Code immer außer Sichtweite ein.", - "3" : "Sie können Ihren PIN-Code bei Bedarf ändern.", + "1" : "Wähle deine PIN <0>immer selbst aus.", + "2" : "Gib deine PIN <0>immer außerhalb der Sichtweite Dritter ein.", + "3" : "Du kannst deine PIN bei Bedarf ändern.", "4" : "Drei falsche PIN-Code-Eingaben hintereinander setzen das Gerät zurück.", - "5" : "Verwenden Sie niemals einen einfachen PIN-Code wie 0000, 123456 oder 55555555.", - "6" : "Geben Sie Ihren PIN-Code niemals an jemand anderen weiter. Auch nicht an Ledger.", - "7" : "Verwenden Sie niemals einen PIN-Code, den Sie nicht selbst gewählt haben.", - "8" : "Speichern Sie Ihren PIN-Code niemals auf einem Computer oder Telefon." + "5" : "Verwende <0>niemals einfache PINs wie 0000, 123456 oder 55555555.", + "6" : "Gib deine PIN <0>niemals an Dritte weiter. Auch nicht an Ledger.", + "7" : "Verwende <0>niemals eine PIN, die du nicht selbst gewählt hast.", + "8" : "Speichere deine PIN <0>niemals auf einem Computer oder Handy." } }, "recoverySeed" : { "title1" : "Wie funktioniert eine Phrase?", - "paragraph1" : "Ihre Wiederherstellungsphrase funktioniert wie ein einzigartiger Generalschlüssel. Ihr Ledger-Gerät verwendet sie, um private Schlüssel für jeden Krypto-Vermögenswert zu berechnen, den Sie besitzen.", - "paragraph2" : "Um den Zugriff auf Ihre Kryptos wiederherzustellen, kann jede Wallet die gleichen privaten Schlüssel aus Ihrem Wiederherstellungssatz berechnen.", + "paragraph1" : "Deine Wiederherstellungsphrase funktioniert wie ein eindeutiger Generalschlüssel. Dein Ledger-Gerät verwendet sie, um private Schlüssel für alle Kryptovermögenswerte zu berechnen, die du besitzt.", + "paragraph2" : "Damit du den Zugriff auf deine Krypto bei Bedarf wiederherstellen kannst, kann jede Wallet dieselben privaten Schlüssel aus deiner Wiederherstellungsphrase berechnen.", "link" : "Mehr zur Wiederherstellungsphrase", "title2" : "Was passiert, wenn ich den Zugriff auf meinen Nano verliere?", - "paragraph3" : "Machen Sie sich keine Sorgen und folgen Sie diesen Schritten:", - "paragraph4" : "Um den Zugriff auf Ihre Kryptos wiederherzustellen, kann jede Wallet die gleichen privaten Schlüssel aus Ihrem Wiederherstellungssatz berechnen.", + "paragraph3" : "Keine Sorge! Gehe wie folgt vor:", + "paragraph4" : "Um den Zugriff auf deine Kryptos wiederherzustellen, kann jede Wallet dieselben privaten Schlüssel aus deiner Wiederherstellungsphrase berechnen.", "points" : { - "1" : "Besorgen Sie sich eine neue Hardware-Wallet.", - "2" : "Wählen Sie „Wiederherstellungsphrase auf einem neuen Gerät wiederherstellen“ in der Ledger-App", - "3" : "Geben Sie Ihre Wiederherstellungsphrase auf Ihrem neuen Gerät ein, um den Zugriff auf Ihre Kryptos wiederherzustellen." + "1" : "Besorge dir eine neue Hardware-Wallet.", + "2" : "Wähle in der Ledger-App „Restore recovery phrase on a new device“ (Wiederherstellungsphrase auf einem neuen Gerät wiederherstellen) aus.", + "3" : "Gib deine Wiederherstellungsphrase auf deinem neuen Gerät ein, um den Zugriff auf deine Krypto wiederherzustellen." } }, "whereToHide" : { "title" : "Wo sollte ich meine Wiederherstellungsphrase aufbewahren?", "points" : { - "1" : "NIEMALS auf einem Computer, Telefon oder einem anderen Gerät eingeben! Machen Sie kein Foto davon.", - "2" : "Teilen Sie Ihre 24 Wörter NIEMALS mit jemand anderem.", - "3" : "Bewahren Sie sie IMMER an einem sicheren Ort auf, geschützt vor Blicken.", - "4" : "Ledger wird Sie niemals nach Ihrer Wiederherstellungsphrase fragen.", - "5" : "Wenn eine Person oder Anwendung danach fragt, gehen Sie davon aus, dass es sich um einen Betrug handelt!" + "1" : "<0>NIEMALS<0> darfst du sie auf einem Computer, einem Smartphone oder einem anderen Gerät eingeben! Mach auch kein Foto davon.", + "2" : "Gib deine 24 Wörter <0>NIEMALS an Dritte weiter.", + "3" : "Bewahre sie <0>IMMER an einem sicheren Ort auf, wo niemand einen Blick darauf werfen kann.", + "4" : "Ledger wird dich niemals nach deiner Wiederherstellungsphrase fragen.", + "5" : "Wenn eine Person oder eine App danach fragt, musst du davon ausgehen, dass es sich um einen Betrugsversuch handelt." } } }, @@ -4667,54 +4686,54 @@ "recoverySeedWarning" : { "contactSupportCTA" : "Support kontaktieren", "continueCTA" : "Weiter", - "title" : "Bitte überprüfen Sie den Inhalt der Box", - "description" : "Wenn Ihre {{device}} mit einem PIN-Code oder einer Wiederherstellungsphrase geliefert wurde, ist die Verwendung des Geräts nicht sicher und Sie sollten sich an den Ledger Support wenden.", - "alert" : "Verwenden Sie nur eine Wiederherstellungsphrase, die Ihr Gerät angezeigt hat, wenn es eingerichtet wurde" + "title" : "Lieferumfang prüfen", + "description" : "Wenn deine {{device}} mit bereits erstellter PIN oder Wiederherstellungsphrase ausgeliefert wurde, ist die Verwendung des Geräts nicht sicher. Wende dich in diesem Fall an den Ledger-Kundenservice.", + "alert" : "Verwende ausschließlich eine Wiederherstellungsphrase, die dein Gerät bei der Einrichtung angezeigt hat." } }, "alerts" : { "beCareful" : { - "title" : "Bitte seien Sie vorsichtig", - "descr" : "Stellen Sie sicher, dass Sie die Anweisungen dieser App bei jedem Schritt des Vorgangs befolgen.", + "title" : "Mit Umsicht handeln", + "descr" : "Befolge bei jedem Schritt des Prozesses unbedingt die Anweisungen in dieser App.", "gotIt" : "Verstanden" }, "useLedgerSeeds" : { "title" : "Wir empfehlen nur Ledger-Wiederherstellungsphrasen", - "descr" : "Ledger kann die Sicherheit von externen Wiederherstellungsphrasen nicht garantieren. Wir empfehlen, Ihren Nano als neues Gerät einzurichten, wenn Ihre Wiederherstellungsphrase nicht von einem Ledger generiert wurde.", + "descr" : "Ledger kann die Sicherheit externer Wiederherstellungsphrasen nicht garantieren. Wir empfehlen, deine Nano als neues Gerät einzurichten, falls deine Wiederherstellungsphrase nicht mit einem Ledger-Gerät erstellt wurde.", "gotIt" : "Verstanden" } }, "screens" : { "welcome" : { - "title" : "Die sicherste Wallet für Kryptowährungen & NFTs", - "description" : "Verwalten, kaufen und vermehren Sie Ihre Krypto und NFTs auf Ledger Live.", + "title" : "Das sicherste Wallet für Kryptos & NFTs", + "description" : "Ledger Live ermöglicht das sichere Verwalten, Kaufen und Vermehren von Kryptos und NFTs.", "nextButton" : "Erste Schritte", "noDevice" : "Kein Gerät?", - "buyLink" : "Kein Gerät? Kaufen Sie eine Ledger Nano X", - "byTapping" : "Indem Sie auf \"Erste Schritte\" tippen, erklären Sie sich einverstanden mit unseren ", - "termsAndConditions" : "Allgemeine Geschäftsbedingungen", - "and" : "Hinzu kommt:", + "buyLink" : "Kein Gerät? Kaufe ein Ledger Nano X", + "byTapping" : "Durch Tippen auf auf „Get Started\" (Loslegen) erklärst du dich einverstanden mit unseren", + "termsAndConditions" : "Allgemeinen Geschäftsbedingungen", + "and" : "und der", "privacyPolicy" : "Datenschutzrichtlinie", "steps" : { "0" : { - "title" : "Zugriff auf Ihre Kryptos", - "desc" : "Ihre Krypto-Vermögenswerte werden auf der Blockchain gespeichert. Verwenden Sie Ihren privaten Schlüssel, um auf sie zuzugreifen und sie zu verwalten" + "title" : "Deine Kryptos abrufen", + "desc" : "Deine Kryptovermögenswerte werden auf der Blockchain gespeichert. Verwende deinen privaten Schlüssel, um auf sie zuzugreifen und sie zu verwalten." }, "1" : { - "title" : "Achten Sie auf Ihren privaten Schlüssel", - "desc" : "Ihr privater Schlüssel ist in Ihrem Nano gespeichert. Achten Sie darauf, dass nur Sie Zugriff haben, um die volle Kontrolle über Ihr Geld zu behalten." + "title" : "Privaten Schlüssel sichern\n", + "desc" : "Dein privater Schlüssel ist auf deiner Nano gespeichert.Du musst die einzige Person in seinem Besitz sein, um die Kontrolle über dein Geld zu behalten." }, "2" : { "title" : "Offline bleiben", - "desc" : "Ihr Nano arbeitet als „Cold Storage“-Wallet.Das bedeutet, dass er Ihren privaten Schlüssel niemals online preisgibt, selbst wenn Sie die App verwenden." + "desc" : "Deine Nano fungiert als „Offline-Wallet“.\nSie macht deinen privaten Schlüssel niemals online zugänglich – auch nicht bei Verwendung der App." }, "3" : { "title" : "Transaktionen validieren", - "desc" : "Mit Ledger Live können Sie Krypto kaufen, verkaufen, verwalten, tauschen und verdienen und bleiben dabei geschützt.Sie werden jede Krypto-Transaktion mit Ihrem Nano validieren." + "desc" : "Mit Ledger Live kannst du Kryptos kaufen, verkaufen, verwalten, umtauschen und verdienen und bleibst dabei geschützt.Du wirst jede Kryptotransaktion mit deiner Nano validieren." }, "4" : { - "title" : "Lassen Sie uns Ihren Nano einrichten", - "desc" : "Wir beginnen mit der Einrichtung Ihrer Nano" + "title" : "Nano jetzt einrichten!", + "desc" : "Wir beginnen mit der Einrichtung deiner Nano" } } }, @@ -4736,7 +4755,7 @@ }, "3" : { "title" : "Wiederherstellen deiner Wiederherstellungsphrase auf einem neuen Gerät", - "description" : "Verwenden Sie eine vorhandene Wiederherstellungsphrase, um Ihre privaten Schlüssel auf einem neuen Nano wiederherzustellen!" + "description" : "Verwende eine vorhandene Wiederherstellungsphrase, um deine privaten Schlüssel auf einer neuen Nano wiederherzustellen!" }, "4" : { "title" : "Wiederherstellen mit Ledger Recover", @@ -4755,8 +4774,8 @@ "screens" : { "importYourRecoveryPhrase" : { "title" : "Wiederherstellen mit der Wiederherstellungsphrase", - "paragraph1" : "Stellen Sie Ihre Nano aus der Wiederherstellungsphrase wieder her, um Ihre Ledger-Hardware-Wallet wiederherzustellen, zu ersetzen oder zu sichern.", - "paragraph2" : "Ihr Nano wird Ihre privaten Schlüssel wiederherstellen und Sie werden in der Lage sein, auf Ihre Krypto zuzugreifen und diese zu verwalten.", + "paragraph1" : "Du kannst deine Nano mit der Wiederherstellungsphrase wiederherstellen. Dies ist notwendig, um deine Ledger-Hardware-Wallet wiederherzustellen oder zu ersetzen oder eine Sicherheitskopie zu erstellen.", + "paragraph2" : "Deine Nano stellt deine privaten Schlüssel wieder her, und danach kannst du wieder auf deine Krypto zugreifen und sie verwalten.", "buttons" : { "next" : "OK, ich bin bereit!", "prev" : "Vorheriger Schritt", @@ -4766,35 +4785,35 @@ "howToGetStarted" : { "title" : "Der beste Weg für den Anfang:", "rules" : { - "1" : "Planen Sie 30 Minuten ein und nehmen Sie sich Zeit.", - "2" : "Nehmen Sie einen Stift zum Schreiben.", - "3" : "Bleiben Sie allein, und wählen Sie eine sichere und ruhige Umgebung." + "1" : "Plane 30 Minuten ein und nimm dir Zeit.", + "2" : "Nimm einen Stift zum Schreiben zur Hand.", + "3" : "Erledige den gesamten Vorgang allein. Dazu wählst du am besten eine geschützte und ruhige Umgebung." }, "buttons" : { "next" : "OK, ich bin bereit!", "prev" : "Vorheriger Schritt" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } }, "deviceHowTo" : { "turnOn" : { "title" : "Nano einschalten", - "descr" : "Schließen Sie Ihr Gerät mit dem USB-Kabel an Ihren Computer an." + "descr" : "Schließe dein Gerät mit dem USB-Kabel an deinen Computer an." }, "browse" : { "title" : "Durchsuchen", - "descr" : "Erfahren Sie, wie Sie Ihr Gerät bedienen können, indem Sie die Anweisungen auf dem Bildschirm lesen." + "descr" : "Lies die Anweisungen auf dem Display, um herauszufinden, wie du dein Gerät bedienst." }, "select" : { - "title" : "Wählen Sie „Als neues Gerät einrichten“", - "descr" : "Drücken Sie beide Tasten gleichzeitig, um die Auswahl zu bestätigen." + "title" : "Wähle „Set up as new device“ (Als neues Gerät einrichten) aus.", + "descr" : "Drücke beide Tasten gleichzeitig, um die Auswahl zu bestätigen." }, "follow" : { "title" : "Anweisungen befolgen", - "descr" : "Kommen Sie hierher zurück, um den Anweisungen zu Ihrem PIN-Code zu folgen." + "descr" : "Kehre hierher zurück, um die Anweisungen zu deiner PIN zu befolgen." }, "buttons" : { "next" : "Nächster Schritt", @@ -4802,7 +4821,7 @@ "help" : "Hilfe benötigt" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } }, @@ -4810,19 +4829,19 @@ "title" : "Der beste Weg für den Anfang:", "turnOn" : { "title" : "Nano einschalten", - "descr" : "Schließen Sie Ihr Gerät mit dem USB-Kabel an Ihren Computer an." + "descr" : "Schließe dein Gerät mit dem USB-Kabel an deinen Computer an." }, "browse" : { "title" : "Durchsuchen", - "descr" : "Erfahren Sie, wie Sie Ihr Gerät bedienen können, indem Sie die Anweisungen auf dem Bildschirm lesen." + "descr" : "Lies die Anweisungen auf dem Display, um herauszufinden, wie du dein Gerät bedienst." }, "select" : { - "title" : "Wählen Sie „Wiederherstellungsphrase eingeben“", - "descr" : "Drücken Sie beide Tasten gleichzeitig, um die Auswahl zu bestätigen." + "title" : "Wähle „Enter your recovery phrase“ (Wiederherstellungsphrase eingeben) aus.", + "descr" : "Drücke beide Tasten gleichzeitig, um die Auswahl zu bestätigen." }, "follow" : { "title" : "Anweisungen befolgen", - "descr" : "Kommen Sie hierher zurück, um den Anweisungen zu Ihrem PIN-Code zu folgen." + "descr" : "Kehre hierher zurück, um die Anweisungen zu deiner PIN zu befolgen." }, "buttons" : { "next" : "Nächster Schritt", @@ -4830,13 +4849,13 @@ "help" : "Hilfe benötigt" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } }, "pinCode" : { "title" : "PIN-Code", - "paragraph" : "Ihr PIN-Code ist die erste Sicherheitsebene. Er sichert physisch den Zugang zu Ihrem privaten Schlüssel und Ihrer Nano. Ihr PIN-Code muss 4 bis 8 Ziffern lang sein.", + "paragraph" : "Deine PIN ist die erste Sicherheitsbarriere. Sie sichert den physischen Zugang zu deinem privaten Schlüssel und deiner Nano ab. Deine PIN muss 4 bis 8 Ziffern lang sein.", "disclaimer" : "Ich verstehe, dass ich meinen PIN-Code selbst wählen und ihn geheim halten muss.", "buttons" : { "next" : "PIN-Code einrichten", @@ -4844,13 +4863,13 @@ "help" : "Hilfe benötigt" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } }, "quizSuccess" : { - "title" : "Schon ein Profi!", - "paragraph" : "Sie sind startklar, Ihre Kryptos sicher zu verwalten. \n\nNur noch ein kleiner Schritt!", + "title" : "Und schon bist du Kryptoprofi!", + "paragraph" : "Jetzt kannst du deine Krypto sicher verwalten.\n\nEs fehlt nur noch ein kleiner Schritt!", "buttons" : { "next" : "Nächster Schritt", "prev" : "Vorheriger Schritt", @@ -4858,25 +4877,25 @@ } }, "quizFailure" : { - "title" : "Sie werden bald zum Profi ...", - "paragraph" : "Ledger ist der perfekte Begleiter was Ihre Krypto-Sicherheit betrifft. \n\nEs fehlt nur noch ein kleiner Schritt!", + "title" : "Bald bist du Kryptoprofi …", + "paragraph" : "Keine Sorge, Ledger steht bereit, um dich auf deiner Reise zu begleiten. Du wirst dich bald richtig gut fühlen, was deine Kryptosicherheit angeht. \n\nEs fehlt nur noch ein kleiner Schritt!", "buttons" : { "next" : "Nächster Schritt", "prev" : "Vorheriger Schritt" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } }, "pinCodeHowTo" : { "setUp" : { "title" : "PIN-Code auswählen", - "descr" : "Drücken Sie die linke oder rechte Taste, um Ziffern zu ändern. Drücken Sie beide Tasten, um eine Ziffer zu bestätigen. Wählen Sie <0> aus, um Ihren PIN-Code zu bestätigen. Wählen Sie <1> , um eine Ziffer zu löschen." + "descr" : "Drücke die linke oder rechte Taste, um die Ziffern zu wechseln. Zum Bestätigen einer Ziffer drückst du beide Tasten. Wähle <0> aus, um deine PIN zu bestätigen. Wähle <1> aus, um eine Ziffer zu löschen." }, "confirm" : { "title" : "PIN-Code bestätigen", - "descr" : "Geben Sie Ihren PIN-Code erneut ein, um ihn zu bestätigen." + "descr" : "Gib deine PIN zur Bestätigung noch einmal ein." }, "buttons" : { "next" : "Nächster Schritt", @@ -4884,33 +4903,33 @@ "help" : "Hilfe benötigt" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } }, "recoverHowTo" : { - "title" : "Wählen Sie „Restore using Ledger Recover“ (Mit Ledger Recover wiederherstellen)", + "title" : "Wähle „Restore using Ledger Recover“ (Mit Ledger Recover wiederherstellen) aus", "1" : { - "title" : "Wählen Sie „Restore“ (Wiederherstellen)", - "descr" : "Drücken Sie beide Tasten gleichzeitig, um auszuwählen." + "title" : "Wähle „Restore“ (Wiederherstellen) aus", + "descr" : "Drücke zum Auswählen beide Tasten gleichzeitig." }, "2" : { - "title" : "Wählen Sie „Restore using Ledger Recover“ (Mit Ledger Recover wiederherstellen)" + "title" : "Wähle „Restore using Ledger Recover“ (Mit Ledger Recover wiederherstellen) aus" }, "help" : { "iDontSee" : "Ich kann „Restore using Ledger Recover“ (Mit Ledger Recover wiederherstellen) nicht sehen", "modal" : { - "title" : "Das Betriebssystem auf Ihrem Ledger Nano X muss aktualisiert werden", - "subtitle" : " Sie können versuchen, das Betriebssystem zu aktualisieren oder den Ledger Kundenservice um Hilfe bitten.", - "learnHowToUpdate" : "Erfahren Sie, wie Sie aktualisieren können", + "title" : "Das Betriebssystem auf deiner Ledger Nano X muss aktualisiert werden", + "subtitle" : " Du kannst versuchen, das Betriebssystem zu aktualisieren, oder den Ledger-Kundenservice um Hilfe bitten.", + "learnHowToUpdate" : "Finde heraus, wie das Update abläuft", "contactLedgerSupport" : "Ledger-Kundenservice kontaktieren" } } }, "existingRecoveryPhrase" : { "title" : "Wiederherstellungsphrase eingeben", - "paragraph1" : "Ihr Wiederherstellungsphrase ist die geheime Liste von Wörtern, die Sie beim ersten Einrichten Ihrer Wallet gewählt haben.", - "paragraph2" : "Ledger bewahrt keine Kopie Ihrer Wiederherstellungsphrase auf.", + "paragraph1" : "Deine Wiederherstellungsphrase ist eine geheime Liste mit Wörtern, die du bei der Ersteinrichtung deiner Wallet ausgewählt hast.", + "paragraph2" : "Ledger speichert keine Kopie deiner Wiederherstellungsphrase.", "disclaimer" : "Ich verstehe, dass ich bei Verlust der Wiederherstellungsphrase nicht mehr auf meine Kryptos zugreifen kann, falls ich den Zugang zu meinem Nano verliere.", "buttons" : { "next" : "Wiederherstellungsphrase eingeben", @@ -4918,19 +4937,19 @@ "help" : "Hilfe benötigt" }, "warning" : { - "title" : "Verwenden Sie keinen Wiederherstellungssatz, den Sie nicht selbst erstellt haben.", - "desc" : "Der PIN-Code und die Wiederherstellungsphrase Ihrer Ledger-Hardware-Wallet sollten von Ihnen und nur von Ihnen erstellt werden. Falls Sie ein Gerät mit einem bereits existierendem Seed-Wort oder einem bereits initialisierten PIN-Code erhalten haben, verwenden Sie das Produkt bitte nicht und kontaktieren Sie unseren Kundendienst.", + "title" : "Verwende keine Wiederherstellungsphrase, die du nicht selbst erstellt hast.", + "desc" : "Nur du allein darfst den PIN-Code und die Wiederherstellungsphrase deiner Ledger-Hardware-Wallet erstellen! Falls du ein Gerät mit einem bereits existierendem Seed-Wort oder einem bereits initialisierten PIN-Code erhalten hast, verwende das Produkt bitte keinesfalls, sondern wende dich an unseren Kundenservice.", "supportLink" : "Kundensupport kontaktieren" } }, "useRecoverySheet" : { "takeYourRecoverySheet" : { - "title" : "Nehmen Sie Ihr Wiederherstellungsblatt", - "descr" : "Nimm den leeren Wiederherstellungszettel zur Hand, der deiner Nano beiliegt. Wende sich an den Ledger-Support, wenn der Wiederherstellungszettel nicht leer ausgeliefert wurde." + "title" : "Nimm deinen Wiederherstellungszettel zur Hand", + "descr" : "Nimm den leeren Wiederherstellungszettel zur Hand, der deiner Nano beiliegt. Wende dich an den Ledger-Kundenservice, wenn der Wiederherstellungszettel nicht leer ausgeliefert wurde." }, "writeDownWords" : { - "title" : "Schreiben Sie 24 Wörter auf", - "descr" : "Schreiben Sie das 1. Wort, das auf Ihrem Nano angezeigt wird, in Position 1 Ihres Wiederherstellungsblatts. Drücken Sie dann auf Ihrem Nano nach rechts, um Wort Nummer 2 anzuzeigen, und notieren Sie es in Position 2. Wiederholen Sie den Vorgang für alle Wörter und achten Sie dabei sorgfältig auf die Reihenfolge und die Rechtschreibung. Drücken Sie auf Ihrem Nano nach links, um eventuelle Fehler zu finden." + "title" : "24 Wörter notieren", + "descr" : "Notiere das erste auf deiner Nano angezeigte Wort auf Position 1 deines Wiederherstellungszettels. Drücke dann auf der Nano die Rechtstaste, um das zweite Wort anzuzeigen, und notiere es auf Position 2. Wiederhole den Vorgang für alle Wörter und achte dabei sorgfältig auf die Reihenfolge und die korrekte Schreibweise. Wenn du auf Fehler prüfen möchtest, drücke auf deiner Nano die Linkstaste." }, "buttons" : { "next" : "Nächster Schritt", @@ -4938,7 +4957,7 @@ "help" : "Hilfe benötigt" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } }, @@ -4953,28 +4972,28 @@ "help" : "Hilfe benötigt" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } }, "recoveryHowTo" : { "grabRecovery" : { - "title" : "Schnappen Sie sich Ihre Wiederherstellungsphrase" + "title" : "Nimm deine Wiederherstellungsphrase zur Hand" }, "selectLength" : { - "title" : "Wählen Sie die Länge der Wiederherstellungsphrase", - "descr" : "Ihre Wiederherstellungsphrasen können 12, 18 oder 24 Wörter haben. Sie müssen alle Wörter eingeben, um auf Ihre Kryptos zuzugreifen." + "title" : "Wähle die Länge der Wiederherstellungsphrase aus", + "descr" : "Deine Wiederherstellungsphrase kann 12, 18 oder 24 Wörter umfassen. Du musst alle Wörter eingeben, um auf deine Krypto zuzugreifen." }, "enterWord" : { "title" : "Wort 1 eingeben ...", - "descr" : "Geben Sie die ersten Buchstaben von Wort #1 ein, indem Sie mit der rechten oder linken Taste auswählen. Drücken Sie beide Tasten, um jeden Buchstaben zu bestätigen." + "descr" : "Gebe die ersten Buchstaben von Wort #1 ein, indem du mit der rechten oder linken Taste auswählst. Drücke beide Tasten, um jeden Buchstaben zu bestätigen." }, "validateWord" : { - "title" : "Bestätigen Sie Wort 1 ...", - "descr" : "Wählen Sie Wort 1 aus den Vorschlägen. Drücken Sie zum Bestätigen beide Tasten." + "title" : "Wort 1 bestätigen …", + "descr" : "Wähle Wort 1 aus den Vorschlägen aus. Drücke zum Bestätigen beide Tasten." }, "andNext" : { - "title" : "Wiederholen Sie dies für alle Wörter!" + "title" : "Wiederhole diesen Vorgang für alle Wörter." }, "buttons" : { "next" : "Nächster Schritt", @@ -4982,17 +5001,17 @@ "help" : "Hilfe benötigt" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } }, "recoveryHowTo3" : { "reEnterWord" : { - "title" : "Bestätigen Sie Ihre Wiederherstellungsphrase", - "descr" : "Blättern Sie durch die Wörter, bis Sie Wort 1 gefunden haben, indem Sie die rechte Taste drücken. Bestätigen Sie, indem Sie beide Tasten drücken." + "title" : "Wiederherstellungsphrase bestätigen", + "descr" : "Blättere mit der rechten Taste durch die Wörter, bis du Wort 1 gefunden hast. Bestätige die Auswahl, indem du beide Tasten drückst." }, "repeat" : { - "title" : "Wiederholen Sie dies für alle Wörter!" + "title" : "Wiederhole diesen Vorgang für alle Wörter." }, "buttons" : { "next" : "Nächster Schritt", @@ -5000,14 +5019,14 @@ "help" : "Hilfe benötigt" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } }, "genuineCheck" : { "success" : { - "title" : "Alles gut!", - "desc" : "Ihr Ledger {{deviceName}} ist echt und bereit zur Verwendung mit Ledger Live" + "title" : "Alles ok!", + "desc" : "Deine Ledger {{deviceName}} ist echt und kann mit Ledger Live verwendet werden." }, "buttons" : { "next" : "Weiter", @@ -5016,31 +5035,31 @@ } }, "hideRecoveryPhrase" : { - "title" : "Verstecken Sie Ihre Wiederherstellungsphrase", - "paragraph" : "Ihre Wiederherstellungsphrase ist die letzte Chance, auf Ihre Krypto zuzugreifen, falls Sie Ihren Nano nicht benutzen können. Sie müssen sie an einem sicheren Ort aufbewahren.", - "keepItOffline" : "Geben Sie diese Wörter nur auf einem Hardware-Wallet ein, nicht auf Computern oder Smartphones.", - "neverShowToAnyone" : "Teilen Sie Ihre 24 Worte niemals mit jemandem, auch nicht mit Ledger.", + "title" : "Wiederherstellungsphrase verbergen", + "paragraph" : "Deine Wiederherstellungsphrase ist dein Rettungsanker für den Zugriff auf deine Krypto, falls du deine Nano nicht mehr nutzen kannst. Daher musst du sie an einem sicheren Ort aufbewahren.", + "keepItOffline" : "Gib die Wörter ausschließlich auf einer Hardware-Wallet und niemals auf einem Computer oder Smartphone ein.", + "neverShowToAnyone" : "Vertraue deine 24 Wörter niemals Dritten an – auch Ledger nicht.", "buttons" : { "next" : "OK, ich bin fertig!", "prev" : "Vorheriger Schritt", "help" : "Hilfe benötigt", - "learn" : "Erfahren Sie wie man gut versteckt" + "learn" : "So versteckst du deine Phrase richtig" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } }, "pairMyNano" : { "title" : "Echtheitsprüfung", - "paragraph" : "Wir werden überprüfen, ob Ihr Nano echt ist. Das sollte schnell und einfach gehen!", + "paragraph" : "Wir prüfen kurz, ob deine Nano echt ist. Das geht ganz schnell und einfach!", "buttons" : { "next" : "Mein Gerät überprüfen", "prev" : "Vorheriger Schritt", "help" : "Hilfe benötigt" }, "help" : { - "help" : "Hilfe benötigt", + "help" : "Ich brauche Hilfe", "descr" : "Du weißt nicht, was du tun musst? Dann hol dir Hilfe, um diesen Schritt abzuschließen." } } @@ -5051,32 +5070,32 @@ "heading" : "Grundlagen", "screens" : { "accessYourCoins" : { - "title" : "Zugriff auf Ihre Kryptos", - "description" : "Ihre Krypto-Werte werden auf der Blockchain gespeichert. Mithilfe eines privaten Schlüssels können Sie darauf zugreifen und sie verwalten." + "title" : "Deine Krypto verwalten", + "description" : "Deine Kryptovermögenswerte werden auf der Blockchain gespeichert. Du brauchst einen privaten Schlüssel, um darauf zuzugreifen und sie zu verwalten." }, "ownYourPrivateKey" : { - "title" : "Achten Sie auf Ihren privaten Schlüssel", - "description" : "Ihr privater Schlüssel ist in Ihrem Nano gespeichert. Sie müssen der einzige sein, der ihn besitzt, um die Kontrolle über Ihr Geld zu haben." + "title" : "Privaten Schlüssel sichern\n", + "description" : "Dein privater Schlüssel ist auf deiner Nano gespeichert. Du musst die einzige Person in seinem Besitz sein, um die Kontrolle über dein Geld zu behalten." }, "stayOffline" : { "title" : "Offline bleiben", - "description" : "Ihr Nano fungiert als \"Cold Storage\"-Wallet. Er gibt Ihren privaten Schlüssel niemals online preis. Auch nicht bei Verwendung der App." + "description" : "Deine Nano fungiert als Offline-Wallet, d. h., sie wird deinen privaten Schlüssel auch bei Verwendung der App niemals online zugänglich machen." }, "validateTransactions" : { "title" : "Transaktionen validieren", - "description" : "Da Sie jede Krypto-Transaktion mit Ihrem Nano bestätigen, sind Sie beim Kaufen, Verkaufen, Verwalten, Tauschen und Verdienen von Kryptos immer bestens geschützt." + "description" : "Mit Ledger Live kannst du Krypto kaufen, verkaufen, verwalten, umtauschen und verdienen und bleibst dabei geschützt. Du wirst jede Kryptotransaktion mit deiner Nano validieren." }, "setUpNanoWallet" : { - "title" : "Lassen Sie uns Ihren Nano einrichten!", - "description" : "Wir beginnen mit der Einrichtung der Nano-Sicherheit.", + "title" : "Richten wir deine Nano ein!", + "description" : "Wir beginnen nun mit der Sicherheitseinrichtung deiner Nano.", "CTA" : "Packen wir's an!" } } }, "quizz" : { "heading" : "Quiz", - "title" : "Jetzt geht's los!", - "descr" : "Beantworten Sie 3 einfache Fragen, um häufige Missverständnisse über Ihre Hardware-Wallet zu vermeiden.", + "title" : "Los geht's!", + "descr" : "Beantworte 3 einfache Fragen, um häufige Unklarheiten zu deiner Hardware-Wallet zu vermeiden.", "buttons" : { "start" : "Los geht's mit dem Quiz", "next" : "Nächste Frage", @@ -5092,11 +5111,11 @@ "results" : { "success" : { "title" : "Glückwunsch!", - "text" : "Ihre Kryptos sind immer in der Blockchain gespeichert. Ihre Hardware-Wallet enthält nur Ihren privaten Schlüssel, der Ihnen Zugriff auf Ihre Kryptos gibt." + "text" : "Deine Kryptos sind immer auf der Blockchain gespeichert. Deine Hardware-Wallet enthält nur deinen privaten Schlüssel, der dir Zugriff auf deine Krypto gibt." }, "fail" : { "title" : "Falsch!", - "text" : "Ihre Kryptos sind immer in der Blockchain gespeichert. Ihre Hardware-Wallet enthält nur Ihren privaten Schlüssel, der Ihnen Zugriff auf Ihre Kryptos gibt." + "text" : "Deine Kryptos sind immer auf der Blockchain gespeichert. Deine Hardware-Wallet enthält nur deinen privaten Schlüssel, der dir Zugriff auf deine Krypto gibt." } } }, @@ -5109,11 +5128,11 @@ "results" : { "success" : { "title" : "Glückwunsch!", - "text" : "Jeder, der Ihre Wiederherstellungsphrase kennt, kann Ihr Krypto-Vermögen stehlen.Wenn Sie die Phrase verlieren, müssen Sie Ihre Kryptos schnell an einen sicheren Ort übertragen." + "text" : "Jeder, der deine Wiederherstellungsphrase kennt, kann dein Kryptovermögen stehlen.\nWenn du die Phrase verlierst, musst du deine Krypto schnell an einen sicheren Ort überführen." }, "fail" : { "title" : "Falsch!", - "text" : "Jeder, der Ihre Wiederherstellungsphrase kennt, kann Ihr Krypto-Vermögen stehlen.Wenn Sie die Phrase verlieren, müssen Sie Ihre Kryptos schnell an einen sicheren Ort übertragen." + "text" : "Jeder, der deine Wiederherstellungsphrase kennt, kann dein Kryptovermögen stehlen.\nWenn du die Phrase verlierst, musst du deine Krypto schnell an einen sicheren Ort überführen." } } }, @@ -5126,11 +5145,11 @@ "results" : { "success" : { "title" : "Glückwunsch!", - "text" : "Ihr privater Schlüssel bleibt immer offline in Ihrer Hardware-Wallet. Selbst wenn Sie mit Ihrem Nano verbunden sind, kann die Ledger-App nicht auf Ihren privaten Schlüssel zugreifen. Sie müssen jede Transaktion physisch auf Ihrem Gerät autorisieren." + "text" : "Dein privater Schlüssel bleibt immer offline in deiner Hardware-Wallet. Selbst wenn du mit deiner Nano verbunden bist, kann die Ledger-App nicht auf deinen privaten Schlüssel zugreifen. Du musst jede Transaktion physisch auf deinem Gerät autorisieren." }, "fail" : { "title" : "Falsch!", - "text" : "Ihr privater Schlüssel bleibt immer offline in Ihrer Hardware-Wallet. Selbst wenn Sie mit Ihrem Nano verbunden sind, kann die Ledger-App nicht auf Ihren privaten Schlüssel zugreifen. Sie müssen jede Transaktion physisch auf Ihrem Gerät autorisieren." + "text" : "Dein privater Schlüssel bleibt immer offline in deiner Hardware-Wallet. Selbst wenn du mit deiner Nano verbunden bist, kann die Ledger-App nicht auf deinen privaten Schlüssel zugreifen. Du musst jede Transaktion physisch auf deinem Gerät autorisieren." } } } @@ -5138,7 +5157,7 @@ } }, "connectTroubleshooting" : { - "desc" : "Haben Sie Probleme, Ihr Gerät zu verbinden?", + "desc" : "Hast du Probleme, dein Gerät zu verbinden?", "cta" : "Reparieren", "solution" : "Lösung #{{number}}", "applesInstructions" : "Apples Anweisungen", @@ -5152,68 +5171,68 @@ "steps" : { "entry" : { "title" : "Fehlerbehebung bei der USB-Verbindung", - "desc" : "Es scheint ein Problem beim Verbinden mit Ihrem Gerät zu geben. Keine Sorge, Sie können verschiedene Lösungen nacheinander ausprobieren, bis Ihr Gerät eine Verbindung herstellt!", + "desc" : "Offenbar liegt ein Problem beim Verbinden mit deinem Gerät vor. Keine Sorge, du kannst verschiedene Lösungen nacheinander ausprobieren, bis dein Gerät eine Verbindung herstellt.", "cta" : "Bringen wir es in Ordnung!", "back" : "Zurückgehen" }, "1" : { "windows" : { - "title" : "Starten Sie Ledger Live als Administrator", + "title" : "Starte Ledger Live als Administrator", "bullets" : { - "0" : "Beenden Sie Ledger Live.", - "1" : "Klicken Sie mit der rechten Maustaste auf die Anwendung Ledger Live.", - "2" : "Wählen Sie „Als Administrator ausführen“.", - "3" : "Schließen Sie Ihr Gerät an und entsperren Sie es, um zu sehen, ob es erkannt wird." + "0" : "Beende Ledger Live.", + "1" : "Klicke mit der rechten Maustaste auf die Ledger Live-App.", + "2" : "Wähle „Als Administrator ausführen“ aus.", + "3" : "Schließe dein Gerät an und entsperre es, um festzustellen, ob es erkannt wurde." } }, "linux" : { - "title" : "Aktualisieren Sie die udev-Regeln unter Linux", - "desc" : "Klicken Sie auf die Schaltfläche unten, um die udev-Regeln hinzuzufügen. Schließen Sie Ihr Gerät an und entsperren Sie es, um zu sehen, ob es erkannt wird.", + "title" : "Aktualisiere die udev-Regeln unter Linux", + "desc" : "Klicke auf die nachstehende Schaltfläche, um die udev-Regeln hinzuzufügen. Schließe dann dein Gerät an und entsperre es, um festzustellen, ob es erkannt wird.", "cta" : "Regeln festlegen", "bullets" : { - "0" : "Geben Sie den folgenden Befehl in ein Terminal ein, um die Regeln automatisch hinzuzufügen und udev neu zu laden.", - "1" : "Schließen Sie Ihr Gerät an und entsperren Sie es, um zu sehen, ob es erkannt wird." + "0" : "Gib den folgenden Befehl in ein Terminal ein, um die Regeln automatisch hinzuzufügen und udev neu zu laden.", + "1" : "Schließe dein Gerät an und entsperre es, um festzustellen, ob es erkannt wurde." } } }, "2" : { "usbPort" : { - "title" : "Versuchen Sie verschiedene USB-Anschlüsse", + "title" : "Probiere verschiedene USB-Anschlüsse aus", "bullets" : { - "0" : "Ändern Sie den an Ihrem Computer verwendeten USB-Anschluss.", - "1" : "Entfernen Sie alle USB-Dongles.", - "2" : "Schließen Sie Ihr Gerät an und entsperren Sie es, um zu sehen, ob es erkannt wird." + "0" : "Verwende einen anderen USB-Anschluss an deinem Computer.", + "1" : "Entferne alle vorhandenen USB-Dongles.", + "2" : "Schließe dein Gerät an und entsperre es, um festzustellen, ob es erkannt wurde." } }, "usbCable" : { - "title" : "Wechseln Sie das USB-Kabel", + "title" : "Verwende ein anderes USB-Kabel", "bullets" : { - "0" : "Verwenden Sie nach Möglichkeit das Original-USB-Kabel.", - "1" : "Versuchen Sie ein anderes USB-Kabel und stellen Sie sicher, dass es Datenübertragung unterstützt.", - "2" : "Schließen Sie Ihr Gerät an und entsperren Sie es, um zu sehen, ob es erkannt wird." + "0" : "Verwende nach Möglichkeit das USB-Kabel aus dem Lieferumfang.", + "1" : "Probiere ein anderes USB-Kabel aus. Achte dabei darauf, dass dieses eine Datenübertragung unterstützt.", + "2" : "Schließe dein Gerät an und entsperre es, um festzustellen, ob es erkannt wurde." } }, "restart" : { - "title" : "Starten Sie Ihren Computer neu", + "title" : "Starte deinen Computer neu", "bullets" : { - "0" : "Starten Sie Ihren Computer neu.", - "1" : "Starten Sie Ledger Live.", - "2" : "Schließen Sie Ihr Gerät an und entsperren Sie es, um zu sehen, ob es erkannt wird." + "0" : "Starte deinen Computer neu.", + "1" : "Starte Ledger Live.", + "2" : "Schließe dein Gerät an und entsperre es, um festzustellen, ob es erkannt wurde." } }, "antiVirus" : { - "title" : "Schalten Sie Antivirus und VPN aus", + "title" : "Deaktiviere Antivirenprogramme und VPNs", "bullets" : { - "0" : "Deaktivieren Sie jegliche Anti-Viren, Firewall und VPN-Software.", - "1" : "Schließen Sie Ihr Gerät an und entsperren Sie es, um zu sehen, ob es erkannt wird.", - "2" : "Geben Sie Ledger Live in Ihrem Antivirusprogramm frei, falls das funktioniert." + "0" : "Deaktiviere jegliche Antiviren-, Firewall- und VPN-Software.", + "1" : "Schließe dein Gerät an und entsperre es, um festzustellen, ob es erkannt wurde.", + "2" : "Falls das geht, setze die Ledger Live-App in deinem Antivirenprogramm auf die Positivliste." } }, "anotherComputer" : { - "title" : "Versuchen Sie es auf einem anderen Computer", + "title" : "Versuche es auf einem anderen Computer", "bullets" : { - "0" : "Gehen Sie zu <0>{{link}} auf einem anderen Computer, um Ledger Live herunterzuladen und zu installieren.", - "1" : "Schließen Sie Ihr Gerät an und entsperren Sie es, um zu sehen, ob es erkannt wird." + "0" : "Nutze einen anderen Computer, um <0>{{link}} aufzurufen und Ledger Live von dort herunterzuladen und zu installieren.", + "1" : "Schließe dein Gerät an und entsperre es, um festzustellen, ob es erkannt wurde." } } }, @@ -5222,27 +5241,27 @@ "title" : "USB-Gerätetreiber aktualisieren", "bullets" : { "0" : "<0>{{link}} besuchen", - "1" : "Folgen Sie den Anweisungen, um die USB-Gerätetreiber zu aktualisieren.", - "2" : "Schließen Sie Ihr Gerät an und entsperren Sie es, um zu sehen, ob es erkannt wird." + "1" : "Befolge die Anweisungen zum Aktualisieren der USB-Gerätetreiber.", + "2" : "Schließe dein Gerät an und entsperre es, um festzustellen, ob es erkannt wird." } }, "mac" : { "0" : { "title" : "Vollzugriff auf die Festplatte aktivieren", "bullets" : { - "0" : "Öffnen Sie „Systemeinstellungen“.", - "1" : "Gehen Sie zu „Sicherheit & Datenschutz“.", - "2" : "Gehen Sie auf der Registerkarte „Datenschutz“ in der linken Spalte auf „Voller Festplattenzugriff“.", - "3" : "Fügen Sie „Ledger Live“ hinzu.", - "4" : "Schließen Sie Ihr Gerät an und entsperren Sie es, um zu sehen, ob es erkannt wird." + "0" : "Öffne „Systemeinstellungen“.", + "1" : "Gehe zu „Datenschutz und Sicherheit“.", + "2" : "Gehe auf dem Tab „Datenschutz“ in der linken Spalte auf „Festplatten-Vollzugriff“.", + "3" : "Füge „Ledger Live“ hinzu.", + "4" : "Schließe dein Gerät an und entsperre es, um festzustellen, ob es erkannt wurde." } }, "1" : { "title" : "NVRAM zurücksetzen", "link" : "Apples Anweisungen", "bullets" : { - "0" : "Wenn Ihr Mac einen Intel-Prozessor hat, folgen Sie <0>{{link}}, um das NVRAM zurückzusetzen.", - "1" : "Schließen Sie Ihr Gerät an und entsperren Sie es, um zu sehen, ob es erkannt wird." + "0" : "Wenn dein Mac einen Intel-Prozessor hat, befolge die Anweisungen unter <0>{{link}}, um das NVRAM zurückzusetzen.", + "1" : "Schließe dein Gerät an und entsperre es, um festzustellen, ob es erkannt wurde." } } } @@ -5250,22 +5269,22 @@ "4" : { "deviceSelection" : { "title" : "Was für ein Gerät haben Sie?", - "desc" : "Wenn Sie versuchen, eine Nano S anzuschließen, wählen Sie den Status aus, der auf Ihrer Nano angezeigt wird. Wenn Sie versuchen, eine Nano S Plus oder Nano X zu verbinden, <0>besuchen Sie das Hilfe-Center" + "desc" : "Wenn du eine Nano S zu verbinden versuchst, wähle den Status aus, der auf deiner Nano angezeigt wird. Falls du hingegen eine Nano S Plus oder Nano X verbinden möchtest, <0>rufe das Hilfe-Center auf." }, "notFixed" : { "title" : " USB-Verbindungsproblem immer noch nicht behoben?", - "desc" : "Wenn Sie alle möglichen Lösungen ausprobiert haben, wenden Sie sich bitte an den Ledger-Support. Ansonsten folgen Sie bitte den Anweisungen jeder Lösung, die Sie noch nicht ausprobiert haben.", + "desc" : "Wenn du alle vorgeschlagenen Lösungen ausprobiert hast, wende dich bitte an den Ledger-Kundenservice. Andernfalls befolge bitte die Anweisungen für weitere Lösungen, die du noch nicht ausprobiert hast.", "back" : "Zurück zum Portfolio", "cta" : "Support kontaktieren", "cta2" : "Zurückgehen" }, "repair" : { - "title" : "Reparieren Sie Ihren Nano S", - "desc" : "Wie lautet die Meldung, die auf Ihrem Gerät angezeigt wird?", + "title" : "Repariere deine Nano S", + "desc" : "Welche Meldung wird auf deinem Gerät angezeigt?", "mcuOutdated" : "MCU firmware is outdated", "mcuNotGenuine" : "Keine MCU-Original-Firmware", - "repairInstructions" : "„Follow device repair instructions“ (Befolgen Sie die Anweisungen zur Gerätereparatur)", - "updateInstructions" : "Folgen Sie den Anweisungen zum Geräte-Update", + "repairInstructions" : "Anweisungen zur Gerätereparatur", + "updateInstructions" : "Befolge die Anweisungen zum Geräte-Update", "somethingElse" : "Etwas anderes" } } @@ -5278,34 +5297,33 @@ "message" : "Nachricht" }, "TransactionConfirm" : { - "title" : "Bitte bestätigen Sie den Vorgang auf Ihrem Gerät, um ihn abzuschließen", - "warning" : "Vergewissern Sie sich immer, dass die auf Ihrem Gerät angezeigte Adresse genau mit der Adresse übereinstimmt, die von {{recipientWording}} mitgeteilt wurde", - "secureContract" : "Überprüfen Sie die Einzahlungsdetails auf Ihrem Gerät, bevor Sie sie senden. Die Vertragsadresse wird sicher bereitgestellt, sodass Sie sie nicht verifizieren müssen.", - "verifyData" : "Überprüfen Sie immer die Aktivitätsdetails auf Ihrem Gerät.", + "title" : "Bestätige den Vorgang auf deinem Gerät, um ihn zum Abschluss zu bringen", + "warning" : "Vergewissere dich immer, dass die auf deinem Gerät angezeigte Adresse exakt mit der Adresse übereinstimmt, die von {{recipientWording}} mitgeteilt wurde.", + "secureContract" : "Verifiziere vor dem Senden die Einzahlungsdetails auf deinem Gerät. Die Vertragsadresse wird auf einem sicheren Weg bereitgestellt, weswegen du sie nicht verifizieren musst.", + "verifyData" : "Verifiziere grundsätzlich die Vorgangsdetails auf deinem Gerät.", "doubleCheck" : "Kontrolliere vor dem Signieren die Transaktionsdetails auf deinem Ledger-Gerät sorgfältig.", "termsAndConditions" : "Durch Signieren dieser Transaktion stimmst du den <0>{{appName}}-Nutzungsbedingungen zu.", - "warningWording" : { - }, + "warningWording" : {}, "titleWording" : { - "send" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "claimReward" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "freeze" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "unfreeze" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", + "send" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "claimReward" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "freeze" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "unfreeze" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", "withdrawExpireUnfreeze" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", "unDelegateResource" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", "legacyUnfreeze" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", - "vote" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "delegate" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "undelegate" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "redelegate" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "claimRewardCompound" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "nominate" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "chill" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "bond" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "unbond" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "rebond" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "withdrawUnbonded" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen", - "setController" : "Bitte bestätigen Sie auf Ihrem Gerät, um den Vorgang abzuschließen" + "vote" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "delegate" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "undelegate" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "redelegate" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "claimRewardCompound" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "nominate" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "chill" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "bond" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "unbond" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "rebond" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "withdrawUnbonded" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen", + "setController" : "Bitte bestätige den Vorgang auf deinem Gerät, um ihn abzuschließen" }, "recipientWording" : { "send" : "Empfänger", @@ -5334,20 +5352,24 @@ }, "Terms" : { "title" : "Nutzungsbedingungen", - "description" : "Bitte nehmen Sie sich etwas Zeit, um unsere Nutzungsbedingungen und Datenschutzrichtlinien zu lesen", + "description" : "Bitte nimm dir etwas Zeit, um unsere Nutzungsbedingungen und Datenschutzrichtlinien zu lesen.", "termsLabel" : "Allgemeine Geschäftsbedingungen", "privacyLabel" : "Datenschutzrichtlinie", "switchLabel" : "Ich habe die Nutzungsbedingungen und Datenschutzrichtlinien gelesen und akzeptiere sie", "cta" : "Zur Ledger-App", "termsCheckboxLabel" : "Ich habe die Nutzungsbedingungen gelesen und erkläre mich damit einverstanden", - "privacyCheckboxLabel" : "Ich habe die Datenschutzbestimmungen gelesen und erkläre mich damit einverstanden." + "privacyCheckboxLabel" : "Ich habe die Datenschutzrichtlinie gelesen und erkläre mich damit einverstanden." }, "updatedTerms" : { "title" : "Aktualisierung der Nutzungsbedingungen", "body" : { - "intro" : "Guten Tag! Wir haben unsere Ledger Live-Nutzungsbedingungen aktualisiert – zum einen, um sie klarer zu fassen, zum anderen, um die in Ledger Live neu verfügbaren Services und Funktionen abzudecken. Die wichtigsten Änderungen:", - "bulletPoints" : ["Erläuterung der verfügbaren Services und ihrer Funktionsweise", "Informationen rund um die für Services erhobenen Gebühren", "Optimierung unseres Benachrichtigungsprozesses, um sicherzustellen, dass Sie über neue Änderungen unserer Nutzungsbedingungen stets zuverlässig informiert sind"], - "agreement" : "Durch Klicken auf „Weiter“ bestätigen Sie, dass Sie die nachstehenden Nutzungsbedingungen gelesen haben und diesen zustimmen." + "intro" : "Hallo! Wir haben unsere Ledger Live-Nutzungsbedingungen aktualisiert – zum einen, um sie verständlicher zu formulieren, zum anderen, um auch die in Ledger Live neu verfügbaren Services und Funktionen darin zu behandeln. Hier sind die wichtigsten Änderungen:", + "bulletPoints" : [ + "Erläuterung der verfügbaren Services und ihrer Funktionsweise", + "Informationen rund um die für Services erhobenen Gebühren", + "Optimierung unseres Benachrichtigungsprozesses, um sicherzustellen, dass du über Änderungen unserer Nutzungsbedingungen stets zuverlässig informiert bist" + ], + "agreement" : "Durch Klicken auf „Weiter“ bestätigst du, dass du die nachstehenden Nutzungsbedingungen gelesen hast und ihnen zustimmst." }, "link" : "Nutzungsbedingungen", "cta" : "Weiter" @@ -5377,12 +5399,12 @@ "MEMO_HASH" : "Memo Hash", "MEMO_RETURN" : "Memo-Rückgabe" }, - "memoWarningText" : "Wenn Sie ein Memo verwenden, überprüfen Sie sorgfältig den verwendeten Typ mit dem Empfänger", + "memoWarningText" : "Wenn du ein Memo verwendest, überprüfe den beim Empfänger verwendeten Typ sorgfältig", "fee" : "Gebühren", - "feeInfoText" : "Für Transaktionen im Stellar-Netzwerk wird eine Mindesttransaktionsgebühr von 0,00001 XLM erhoben.", + "feeInfoText" : "Für Transaktionen im Stellar-Netzwerk wird eine Mindesttransaktionsgebühr von 0,00001 XLM erhoben.", "suggested" : "Empfohlen", "recommendedFee" : "Empfohlene Gebühren", - "recommenndedFeeInfo" : "Die Transaktion kann auch mit einer niedrigeren Gebühr als der empfohlenen eingereicht werden, aber sie wird möglicherweise nicht abgeschlossen.", + "recommenndedFeeInfo" : "Diese Transaktion kann zwar mit einer geringeren Gebühr als empfohlen eingereicht werden, wird dann aber möglicherweise nicht abgeschlossen.", "networkCongestion" : "Netzüberlastung", "networkCongestionLevel" : { "LOW" : "Niedrig", @@ -5410,14 +5432,14 @@ "learnMoreCTA" : "Weitere Informationen zu Ledger Sync" }, "PendingOperation" : { - "description" : "Sie haben eingehende Transaktionen ausstehend. Bitte bedenken Sie, dass ausstehende Transaktionen rückgängig gemacht werden können." + "description" : "Bei dir sind ausstehende Eingangstransaktionen vorhanden. Bitte bedenke, dass ausstehende Transaktionen rückgängig gemacht werden können." }, "countervaluesUnavailable" : { "title" : "Wir können derzeit keinen Gegenwert für diesen Vermögenswert angeben" }, "generic" : { "title" : "{{message}}", - "description" : "Etwas ist schief gelaufen Bitte versuchen Sie es erneut oder kontaktieren Sie den Ledger-Kundenservice." + "description" : "Ein Problem ist aufgetreten. Bitte versuche es noch einmal oder wende dich an den Ledger-Kundenservice." }, "AccountAwaitingSendPendingOperations" : { "title" : "Es gibt eine ausstehende Aktion für dieses Konto.", @@ -5425,15 +5447,15 @@ }, "AccountNameRequired" : { "title" : "Ein Kontoname ist erforderlich", - "description" : "Bitte geben Sie einen Kontonamen ein" + "description" : "Bitte gib einen Kontonamen ein" }, "AccountNeedResync" : { - "title" : "Bitte versuchen Sie es erneut", + "title" : "Bitte versuche es noch einmal", "description" : "Konto ist veraltet. Eine Synchronisierung ist erforderlich" }, "AccountNotSupported" : { "title" : "Konto wird nicht unterstützt.", - "description" : "Bitte versuchen Sie es erneut oder kontaktieren Sie den Support ({{reason}})" + "description" : "Bitte versuche es noch einmal oder wende dich an den Kundenservice ({{reason}})." }, "AlgorandASANotOptInInRecipient" : { "title" : "Das Empfängerkonto hat sich nicht für den gewählten ASA entschieden." @@ -5442,11 +5464,11 @@ "title" : "Erforderlicher Betrag" }, "NoAccessToCamera" : { - "title" : "Bitte stellen Sie sicher, dass Ihr System über eine Kamera verfügt, dass diese nicht von einer anderen Anwendung verwendet wird und dass Ledger Live die Erlaubnis hat, diese zu verwenden.", + "title" : "Stelle sicher, dass dein System über eine Kamera verfügt, diese gegenwärtig nicht von einer anderen Anwendung verwendet wird und Ledger Live die Berechtigung hat, sie zu nutzen.", "description" : "" }, "CeloAllFundsWarning" : { - "title" : "Stellen Sie sicher, dass Sie genug Guthaben für zukünftige Transaktionsgebühren übrig haben" + "title" : "Vergewissere dich, dass ausreichend Guthaben für künftige Transaktionsgebühren verbleibt" }, "ClaimRewardsFeesWarning" : { "title" : "Die Prämien sind kleiner als die geschätzten Gebühren, die anfallen, um diese zu beanspruchen", @@ -5454,15 +5476,15 @@ }, "CosmosBroadcastCodeInternal" : { "title" : "Etwas ist schief gelaufen (Fehler 1)", - "description" : "Bitte kontaktieren Sie den Ledger-Support" + "description" : "Bitte wende dich an den Ledger-Kundenservice" }, "CosmosBroadcastCodeTxDecode" : { "title" : "Etwas ist schief gelaufen (Fehler 2)", - "description" : "Bitte kontaktieren Sie den Ledger-Support" + "description" : "Bitte wende dich an den Ledger-Kundenservice" }, "CosmosBroadcastCodeInvalidSequence" : { "title" : "Ungültige Sequenz", - "description" : "Bitte versuchen Sie den Vorgang erneut" + "description" : "Bitte wiederhole den Vorgang" }, "CosmosBroadcastCodeUnauthorized" : { "title" : "Nicht autorisierte Signatur", @@ -5470,62 +5492,62 @@ }, "CosmosBroadcastCodeInsufficientFunds" : { "title" : "Unzureichendes Guthaben", - "description" : "Vergewissern Sie sich, dass das verwendete Konto über genügend Guthaben verfügt und versuchen Sie es erneut" + "description" : "Vergewissere dich, dass das verwendete Konto über ausreichendes Guthaben verfügt, und versuche es noch einmal" }, "CosmosBroadcastCodeUnknownRequest" : { "title" : "Etwas ist schief gelaufen (Fehler 6)", - "description" : "Bitte kontaktieren Sie den Ledger-Support" + "description" : "Bitte wende dich an den Ledger-Kundenservice" }, "CosmosBroadcastCodeInvalidAddress" : { "title" : "Ungültige Adresse", - "description" : "Bitte überprüfen Sie die Adresse und versuchen Sie es erneut" + "description" : "Bitte überprüfe die Adresse und versuche es noch einmal" }, "CosmosBroadcastCodeInvalidPubKey" : { "title" : "Etwas ist schief gelaufen (Fehler 8)", - "description" : "Bitte kontaktieren Sie den Ledger-Support" + "description" : "Bitte wende dich an den Ledger-Kundenservice" }, "CosmosBroadcastCodeUnknownAddress" : { "title" : "Unbekannte Adresse", - "description" : "Bitte überprüfen Sie die Adresse und versuchen Sie es erneut" + "description" : "Bitte überprüfe die Adresse und versuche es noch einmal" }, "CosmosBroadcastCodeInsufficientCoins" : { "title" : "Unzureichende Coins", - "description" : "Vergewissern Sie sich, dass das verwendete Konto über genügend Guthaben verfügt und versuchen Sie es erneut" + "description" : "Vergewissere dich, dass das verwendete Konto über ausreichendes Guthaben verfügt, und versuche es noch einmal" }, "CosmosBroadcastCodeInvalidCoins" : { "title" : "Etwas ist schief gelaufen (Fehler 11)", - "description" : "Bitte kontaktieren Sie den Ledger-Support" + "description" : "Bitte wende dich an den Ledger-Kundenservice" }, "CosmosBroadcastCodeOutOfGas" : { "title" : "Etwas ist schief gelaufen (Fehler 12)", - "description" : "Bitte kontaktieren Sie den Ledger-Support" + "description" : "Bitte wende dich an den Ledger-Kundenservice" }, "CosmosBroadcastCodeMemoTooLarge" : { "title" : "Das Memo-Feld ist zu lang", - "description" : "Bitte verkürzen Sie den Memotext und versuchen Sie es erneut" + "description" : "Bitte verkürze den Memotext und versuche es noch einmal" }, "CosmosBroadcastCodeInsufficientFee" : { "title" : "Etwas ist schief gelaufen (Fehler 14)", - "description" : "Bitte kontaktieren Sie den Ledger-Support" + "description" : "Bitte wende dich an den Ledger-Kundenservice" }, "CosmosBroadcastCodeTooManySignatures" : { "title" : "Etwas ist schief gelaufen (Fehler 15)", - "description" : "Bitte kontaktieren Sie den Ledger-Support" + "description" : "Bitte wende dich an den Ledger-Kundenservice" }, "CosmosBroadcastCodeGasOverflow" : { "title" : "Etwas ist schief gelaufen (Fehler 16)", - "description" : "Bitte kontaktieren Sie den Ledger-Support" + "description" : "Bitte wende dich an den Ledger-Kundenservice" }, "CosmosBroadcastCodeNoSignatures" : { "title" : "Etwas ist schief gelaufen (Fehler 17)", - "description" : "Bitte kontaktieren Sie den Ledger-Support" + "description" : "Bitte wende dich an den Ledger-Kundenservice" }, "CosmosDelegateAllFundsWarning" : { - "title" : "Stellen Sie sicher, dass Ihr Guthaben zur Deckung künftiger Transaktionsgebühren ausreicht" + "title" : "Stelle sicher, dass dein Guthaben zur Deckung künftiger Transaktionsgebühren ausreicht" }, "CurrencyNotSupported" : { "title" : "{{currencyName}} wird nicht unterstützt", - "description" : "Dieser Krypto-Vermögenswert wird noch nicht unterstützt. Bitte kontaktieren Sie den Ledger-Support" + "description" : "Dieser Kryptovermögenswert wird noch nicht unterstützt. Bitte kontaktiere den Ledger-Kundenservice." }, "DeviceAlreadySetup" : { "title" : "Auf deinem Gerät ({{device}}) ist bereits eine geheime Wiederherstellungsphrase eingerichtet", @@ -5536,28 +5558,28 @@ "description" : "Hilfe vom Ledger-Support anfordern" }, "DeviceGenuineSocketEarlyClose" : { - "title" : "Entschuldigung, versuchen Sie es erneut (echt-schließen)", + "title" : "Entschuldigung, bitte versuche es noch einmal (echt schließen)", "description" : null }, "DeviceInOSUExpected" : { "title" : "Sorry, Update fehlgeschlagen", - "description" : "Bitte versuchen Sie es erneut oder kontaktieren Sie den Ledger-Support" + "description" : "Bitte versuche es noch einmal oder wende dich an den Ledger-Kundenservice" }, "DeviceHalted" : { - "title" : "Bitte starten Sie Ihr Ledger-Gerät neu und versuchen Sie es erneut", - "description" : "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut" + "title" : "Bitte starte dein Ledger-Gerät neu und versuche es noch einmal", + "description" : "Ein unerwarteter Fehler ist aufgetreten. Bitte versuche es noch einmal" }, "DeviceNotOnboarded" : { - "title" : "Ihr Gerät kann noch nicht verwendet werden", - "description" : "Richten Sie Ihr Gerät ein, bevor Sie es mit Ledger Live verwenden." + "title" : "Dein Gerät kann noch nicht verwendet werden", + "description" : "Richte dein Gerät ein, bevor du es mit Ledger Live verwendest." }, "DeviceSocketFail" : { - "title" : "Bitte starten Sie Ihr Ledger-Gerät neu und versuchen Sie es erneut", - "description" : "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut. ({{message}})" + "title" : "Bitte starte dein Ledger-Gerät neu und versuche es noch einmal", + "description" : "Ein unerwarteter Fehler ist aufgetreten. Bitte versuche es noch einmal. ({{message}})" }, "DeviceSocketNoBulkStatus" : { "title" : "Die Verbindung ist fehlgeschlagen", - "description" : "Bitte versuchen Sie es erneut." + "description" : "Bitte versuche es noch einmal." }, "DisconnectedDevice" : { "title" : "Gerät nicht verbunden", @@ -5569,11 +5591,11 @@ }, "EConnReset" : { "title" : "Der Ledger Application Store kann nicht erreicht werden", - "description" : "Ihre Internetverbindung ist möglicherweise ausgefallen oder Sie verwenden eine ungewöhnliche Konfiguration. Überprüfen Sie zunächst, ob Ihre Verbindung blockiert wird (Proxy oder Firewall). Wenn das Problem weiterhin besteht, klicken Sie unten, um Lösungen zu erhalten, oder wenden Sie sich an unseren Kundensupport." + "description" : "Deine Internetverbindung ist möglicherweise ausgefallen, oder du verwendest eine ungewöhnliche Konfiguration. Überprüfe zunächst, ob deine Verbindung blockiert wird (etwa durch einen Proxy oder eine Firewall). Wenn das Problem weiterhin besteht, klicke unten, um mögliche Lösungen anzuzeigen, oder wende dich an unseren Kundenservice." }, "EnpointConfig" : { "title" : "Ungültiger Endpunkt", - "description" : "Bitte geben Sie einen gültigen Endpunkt an" + "description" : "Bitte gib einen gültigen Endpunkt an" }, "FeeEstimationFailed" : { "title" : "Sorry, Gebührenschätzung fehlgeschlagen", @@ -5581,7 +5603,7 @@ }, "FirmwareOrAppUpdateRequired" : { "title" : "Firmware- oder App-Update erforderlich", - "description" : "Deinstallieren Sie zunächst mithilfe von My Ledger alle Apps und prüfen Sie dann vor der Neuinstallation zunächst, ob ein Firmware-Update verfügbar ist." + "description" : "Deinstalliere zunächst mithilfe von My Ledger alle Apps und prüfe dann vor der Neuinstallation, ob ein Firmware-Update verfügbar ist." }, "LatestFirmwareVersionRequired" : { "title" : "Update der Geräte-Firmware", @@ -5594,7 +5616,7 @@ }, "HardResetFail" : { "title" : "Entschuldigung, die Verbindung konnte nicht zurückgesetzt werden", - "description" : "Bitte versuchen Sie es erneut oder wenden Sie sich an den Ledger Kundenservice, falls das Problem weiterhin besteht." + "description" : "Bitte versuche es noch einmal oder wende dich an den Ledger-Kundenservice, falls das Problem weiterhin besteht." }, "LanguageInstallRefusedOnDevice" : { "title" : "Sprachwiederherstellung\nauf dem Gerät wurde abgebrochen", @@ -5602,52 +5624,52 @@ }, "LanguageNotFound" : { "title" : "Die Sprache wurde nicht gefunden", - "description" : "Die Sprache, die Sie installieren möchten, wurde nicht gefunden. Bitte versuchen Sie, eine andere Sprache zu installieren." + "description" : "Die Sprache, die du installieren möchtest, wurde nicht gefunden. Bitte installiere eine andere Sprache." }, "LatestMCUInstalledError" : { "title" : "Entschuldigung, es gibt nichts zu aktualisieren", - "description" : "Bitte kontaktieren Sie den Ledger-Support, wenn Sie Ihr Gerät nicht verwenden können." + "description" : "Bitte kontaktiere den Ledger-Support, wenn du dein Gerät nicht verwenden kannst." }, "LedgerAPI4xx" : { "title" : "{{message}}", - "description" : "Bitte überprüfen Sie Ihre Verbindung und versuchen Sie es erneut oder wenden Sie sich an den Ledger-Kundenservice." + "description" : "Bitte überprüfe deine Verbindung und versuche es noch einmal oder wende dich an den Ledger-Kundenservice." }, "LedgerAPI5xx" : { - "title" : "Entschuldigung, versuchen Sie es erneut.", - "description" : "Der Server konnte Ihre Anfrage nicht bearbeiten. Bitte versuchen Sie es später erneut oder wenden Sie sich an den Ledger-Kundenservice. {{message}}" + "title" : "Entschuldigung, versuche es noch einmal.", + "description" : "Der Server konnte deine Anfrage nicht bearbeiten. Bitte versuche es später noch einmal oder wende dich an den Ledger-Kundenservice. {{message}}" }, "LedgerAPINotAvailable" : { "title" : "Sorry, {{currencyName}}-Dienste nicht verfügbar", - "description" : "Bitte versuchen Sie es erneut oder kontaktieren Sie den Ledger-Support" + "description" : "Bitte versuche es noch einmal oder wende dich an den Ledger-Kundenservice" }, "ManagerAppAlreadyInstalled" : { "title" : "Entschuldigung, das ist bereits installiert", - "description" : "Bitte prüfen Sie, welche Apps bereits auf Ihrem Gerät installiert sind." + "description" : "Bitte überprüfe, welche Apps bereits auf deinem Gerät installiert sind." }, "ManagerAppDepInstallRequired" : { "title" : "{{dependency}} App erforderlich", - "description" : "Falls die {{dependency}}-App bereits installiert ist, installieren Sie diese bitte mit der neuesten Version neu" + "description" : "Falls die {{dependency}}-App bereits installiert ist, installiere sie bitte in der aktuellen Version neu." }, "ManagerAppDepUninstallRequired" : { "title" : "Entschuldigung, diese App ist erforderlich", - "description" : "Sie müssen zuerst alle Apps deinstallieren, welche die {{appName}} App benötigen" + "description" : "Du musst zuerst alle Apps deinstallieren, die die {{appName}}-App benötigen." }, "ManagerDeviceLocked" : { - "title" : "Ihr Gerät ist gesperrt", - "description" : "Bitte entsperren Sie es" + "title" : "Dein Gerät ist gesperrt", + "description" : "Bitte entsperre es" }, "ManagerFirmwareNotEnoughSpace" : { - "title" : "Deinstallieren Sie alle Apps von Ihrem Gerät", - "description" : "Die privaten Schlüssel für den Zugriff auf Ihr Krypto-Vermögen bleiben sicher auf Ihrem Gerät und müssen auf Ihrem Wiederherstellungsblatt gesichert werden." + "title" : "Deinstalliere alle Apps von deinem Gerät", + "description" : "Die privaten Schlüssel für den Zugriff auf dein Kryptovermögen verbleiben sicher auf deinem Gerät. Du musst dazu eine Sicherheitskopie auf einem Wiederherstellungszettel erstellen." }, "ManagerNotEnoughSpace" : { "title" : "Sorry, nicht genug Speicherplatz übrig", - "description" : "Deinstallieren Sie einige Apps, um Speicherplatz freizugeben. Die privaten Schlüssel zum Zugriff auf Ihre Krypto-Vermögenswerte bleiben sicher auf Ihrem Gerät." + "description" : "Deinstalliere einige Apps, um Speicherplatz freizugeben. Die privaten Schlüssel für den Zugriff auf deine Kryptovermögenswerte verbleiben sicher auf deinem Gerät." }, "ManagerQuitPage" : { "install" : { "title" : "Abschluss App-Installation in Arbeit?", - "description" : "Wenn Sie My Ledger beenden, wird die Installation der App abgebrochen. Bitte stellen Sie die Installation fertig, um die Apps in der Warteschlange zu installieren.", + "description" : "Wenn du My Ledger beendest, wird die Installation der App abgebrochen. Bitte schließe die Installation vollständig ab, um die Apps in der Warteschlange zu installieren.", "stay" : "Installation beenden" }, "uninstall" : { @@ -5664,11 +5686,11 @@ }, "ManagerUninstallBTCDep" : { "title" : "Entschuldigung, diese App ist erforderlich", - "description" : "Deinstallieren Sie die Bitcoin- oder Ethereum-App zuletzt" + "description" : "Deinstalliere die Bitcoin- oder Ethereum-App zuletzt" }, "NetworkDown" : { "title" : "Entschuldigung, das Internet scheint ausgefallen zu sein", - "description" : "Bitte überprüfen Sie Ihre Internetverbindung." + "description" : "Bitte überprüfe deine Internetverbindung." }, "NetworkError" : { "title" : "Ein Netzwerkfehler ist aufgetreten", @@ -5676,11 +5698,11 @@ }, "NoAddressesFound" : { "title" : "Entschuldigung, es wurden keine Konten gefunden", - "description" : "Bei der Adressberechnung ist etwas schief gelaufen, versuchen Sie es erneut oder wenden Sie sich an den Ledger-Support" + "description" : "Bei der Adressberechnung ist etwas schief gelaufen, versuche es noch einmal oder wende dich an den Ledger-Kundenservice" }, "ElrondDecimalsLimitReached" : { "title" : "Maximale Dezimalstellengrenze erreicht", - "description" : "Bitte stellen Sie sicher, dass der angegebene Betrag 18 Dezimalstellen hat." + "description" : "Bitte stelle sicher, dass der angegebene Betrag 18 Dezimalstellen hat." }, "ElrondMinDelegatedAmountError" : { "title" : "Der delegierte Betrag muss mindestens {{formattedAmount}} betragen" @@ -5693,7 +5715,7 @@ }, "NotEnoughEGLDForFees" : { "title" : "Nicht genug EGLD, um die Transaktionsgebühren zu bezahlen", - "description" : "Bitte überweisen Sie einige EGLD auf Ihr Konto, um die Transaktionen zu bezahlen." + "description" : "Bitte überweise einige EGLD auf dein Konto, um die Transaktionen zu bezahlen." }, "NotEnoughVTHO" : { "title" : "Nicht genügend VTHO-Vermögenswerte verfügbar", @@ -5716,14 +5738,14 @@ }, "NotEnoughBalance" : { "title" : "Entschuldigung, Guthaben reicht nicht aus", - "description" : "Bitte stellen Sie sicher, dass das Konto ausreichend gedeckt ist." + "description" : "Bitte vergewissere dich, dass das Konto über ausreichende Deckung verfügt." }, "NotEnoughBalanceSwap" : { "title" : "Leider ist für den Betrag einschließlich der Netzwerkgebühren nicht genügend Guthaben vorhanden. Bitte Betrag ändern oder Guthaben verifizieren.", "description" : "Bitte vergewissere dich, dass das Konto über ausreichende Deckung verfügt." }, "NotEnoughBalanceBecauseDestinationNotCreated" : { - "title" : "Die Adresse des Empfängers ist inaktiv. Senden Sie mindestens {{minimalAmount}}, um sie zu aktivieren" + "title" : "Die Adresse des Empfängers ist inaktiv. Sende mindestens {{minimalAmount}}, um sie zu aktivieren." }, "NotEnoughGas" : { "title" : "Du brauchst {{fees}} {{ticker}} auf deinem Konto, um die Transaktionsgebühren für das {{cryptoName}}-Netzwerk zu bezahlen. Kaufe {{ticker}} oder zahle zusätzliche Mittel auf dein Konto ein." @@ -5738,16 +5760,16 @@ "title" : "Du brauchst mindestens 0,1 TRX, um dieses Tron-Konto aktiv zu halten, sowie 1,1 TRX für Netzwerkgebühren. Weitere Informationen" }, "OperatingSystemOutdated" : { - "title" : "Die Version Ihres Betriebssystems ist veraltet", - "description" : "Bitte aktualisieren Sie Ihr Betriebssystem und versuchen Sie es erneut. Sie können im folgenden Artikel nachlesen, warum Ledger Live auf der aktuellen Version Ihres Betriebssystems nicht unterstützt wird." + "title" : "Deine Betriebssystemversion ist veraltet", + "description" : "Bitte führe ein Upgrade deines Betriebssystems durch und versuche es dann noch einmal. Im folgenden Artikel erfährst du, warum Ledger Live unter deiner aktuellen Betriebssystemversion nicht unterstützt wird." }, "PasswordsDontMatch" : { "title" : "Die Passwörter stimmen nicht überein", - "description" : "Bitte versuchen Sie es erneut" + "description" : "Bitte versuche es noch einmal" }, "PasswordIncorrect" : { "title" : "Das eingegebene Passwort ist falsch", - "description" : "Bitte versuchen Sie es erneut" + "description" : "Bitte versuche es noch einmal" }, "QuantityNeedsToBePositive" : { "title" : "Die Menge muss größer als 0 sein" @@ -5756,7 +5778,7 @@ "title" : "Host ist erforderlich." }, "RPCHostInvalid" : { - "title" : "Geben Sie einen gültigen Host ein." + "title" : "Gib einen gültigen Host ein." }, "RPCUserRequired" : { "title" : "RPC-Benutzername ist erforderlich" @@ -5766,19 +5788,19 @@ }, "SatStackAccessDown" : { "title" : "Full Node kann nicht erreicht werden", - "description" : "Bitte überprüfen Sie, ob SatStack und Ihr Knoten/Node ausgeführt werden. Überprüfen Sie die vollständige Node-Einrichtung in den Einstellungen, wenn das Problem weiterhin besteht." + "description" : "Bitte überprüfe, ob SatStack und dein Knoten ausgeführt werden. Kontrolliere die Full-Node-Konfiguration in den Einstellungen, falls das Problem weiterhin besteht." }, "SatStackStillSyncing" : { "title" : "Knotensynchronisierung läuft...", - "description" : "Bitte warten Sie, während Ihr Node synchronisiert wird. Senden ist nicht möglich, da Ihr Bitcoin-Kontostand möglicherweise nicht korrekt ist." + "description" : "Bitte warte, bis die Synchronisierung deines Knotens abgeschlossen ist. Das Versenden ist derzeit nicht möglich, da dein Bitcoin-Kontostand möglicherweise nicht korrekt ist." }, "SatStackVersionTooOld" : { - "title" : "Bitte aktualisieren Sie SatStack", - "description" : "Die SatStack-Version, die Sie verwenden, ist zu alt und enthält möglicherweise Fehler oder Inkompatibilitäten." + "title" : "Bitte führe ein Upgrade von SatStack durch", + "description" : "Die SatStack-Version, die du verwendest, ist zu alt und enthält möglicherweise Fehler oder Inkompatibilitäten." }, "SatStackDescriptorNotImported" : { "title" : "Konto nicht von Knoten (Full Node) gescannt", - "description" : "Bitte konfigurieren Sie Ihren Full Node so, dass er nach den Konten sucht, die mit diesem Gerät verbunden sind. Ihr Full Node muss zuerst die Blockchain nach diesem Konto durchsuchen, bevor Sie es zu Ihrem Portfolio hinzufügen können." + "description" : "Bitte konfiguriere deinen Full Node so, dass er nach den Konten sucht, die mit diesem Gerät verknüpft sind. Dein Full Node muss zuerst die Blockchain nach diesem Konto durchsuchen, damit du es deinem Portfolio hinzufügen kannst." }, "SwapRateExpiredError" : { "title" : "Wechselkurs abgelaufen", @@ -5793,18 +5815,18 @@ }, "TimeoutError" : { "title" : "Entschuldigung, der Server hat zu lange für die Antwort gebraucht", - "description" : "Bitte versuchen Sie es erneut." + "description" : "Bitte versuche es noch einmal." }, "TimeoutTagged" : { "title" : "Entschuldigung, der Server hat zu lange gebraucht um zu antworten ({{tag}})", "description" : "Zeitüberschreitung aufgetreten." }, "TransportError" : { - "title" : "Etwas ist schief gelaufen. Bitte schließen Sie Ihr Gerät erneut an", + "title" : "Ein Problem ist aufgetreten. Bitte schließe dein Gerät erneut an.", "description" : "{{message}}" }, "TransportRaceCondition" : { - "title" : "Etwas ist schief gelaufen. Bitte schließen Sie Ihr Gerät erneut an", + "title" : "Ein Problem ist aufgetreten. Bitte schließe dein Gerät erneut an.", "description" : "Auf dem Ledger-Gerät war bereits eine Aktion ausstehend. Bitte ablehnen oder Verbindung neu herstellen." }, "UnresponsiveDeviceError" : { @@ -5812,7 +5834,7 @@ "description" : "Auf dein Gerät kann nicht zugegriffen werden.\nMöglicherweise ist ein Vorgang ausstehend. Bitte ablehnen oder Verbindung neu herstellen." }, "TransportStatusError" : { - "title" : "Etwas ist schief gelaufen Bitte schließen Sie Ihr Gerät erneut an", + "title" : "Ein Problem ist aufgetreten. Bitte schließe dein Gerät erneut an.", "description" : "{{message}}" }, "TrustchainEjected" : { @@ -5827,12 +5849,12 @@ "description" : "Bitte versuche es noch einmal oder wende dich an den Ledger-Kundenservice." }, "DeviceShouldStayInApp" : { - "title" : "Bitte öffnen Sie die {{appName}} App", - "description" : "Lassen Sie die App {{appName}} geöffnet, während wir Ihre Konten finden" + "title" : "Bitte öffne die {{appName}}-App", + "description" : "Lass die {{appName}}-App geöffnet, solange wir nach deinen Konten suchen." }, "UnexpectedBootloader" : { - "title" : "Entschuldigung, Ihr Gerät darf sich nicht im Bootloader-Modus befinden", - "description" : "Bitte starten Sie Ihr Gerät neu, ohne die Schaltflächen zu berühren, wenn das Logo erscheint. Kontaktieren Sie den Ledger Support, falls das Problem weiterhin besteht." + "title" : "Dein Gerät darf sich nicht im Bootloader-Modus befinden", + "description" : "Bitte starte dein Gerät neu, ohne die Schaltflächen zu berühren, wenn das Logo erscheint. Kontaktiere den Ledger-Kundenservice, falls das Problem weiterhin besteht." }, "UserRefusedAllowManager" : { "title" : "Sichere Verbindung abgelehnt auf Gerät" @@ -5851,19 +5873,19 @@ }, "TransactionRefusedOnDevice" : { "title" : "Aktion auf Gerät verweigert", - "description" : "Bitte versuchen Sie es erneut oder kontaktieren Sie im Zweifelsfall den Ledger-Support" + "description" : "Bitte versuche es noch einmal oder wende dich an im Zweifelsfall den Ledger-Kundenservice" }, "UserRefusedAddress" : { "title" : "Empfangsadresse abgelehnt", - "description" : "Bitte versuchen Sie es erneut oder wenden Sie sich im Zweifelsfall an den Ledger-Support" + "description" : "Bitte versuche es noch einmal oder wende dich im Zweifelsfall an den Ledger-Kundenservice" }, "UpdateYourApp" : { "title" : "App-Update erforderlich", - "description" : "Deinstallieren Sie die {{managerAppName}}-App in My Ledger und installieren Sie sie dann neu." + "description" : "Deinstalliere die {{managerAppName}}-App in My Ledger und installiere sie dann neu." }, "DeviceOnDashboardExpected" : { "title" : "Zurück zum Dashboard", - "description" : "Bitte navigieren Sie auf Ihrem Gerät zurück zum Dashboard" + "description" : "Navigiere auf deinem Gerät zurück zum Dashboard" }, "WebsocketConnectionError" : { "title" : "Netzwerkfehler", @@ -5875,7 +5897,7 @@ }, "WrongDeviceForAccount" : { "title" : "Etwas ist schief gelaufen", - "description" : "Bitte überprüfen Sie, ob Ihre Hardware-Wallet mit der Wiederherstellungsphrase oder Passphrase eingerichtet ist, die mit dem gewählten Konto verbunden ist." + "description" : "Kontrolliere, ob deine Hardware-Wallet mit der Wiederherstellungs- oder Passphrase für das ausgewählte Konto eingerichtet ist." }, "WrongDeviceForAccountPayout" : { "title" : "Etwas ist schief gelaufen", @@ -5887,7 +5909,7 @@ }, "DeviceAppVerifyNotSupported" : { "title" : "App-Update erforderlich", - "description" : "Deinstallieren Sie die {{managerAppName}}-App in My Ledger und installieren Sie sie dann neu." + "description" : "Deinstalliere die {{managerAppName}}-App in My Ledger und installiere sie dann neu." }, "InvalidAddress" : { "title" : "Dies ist keine gültige {{currencyName}} Adresse" @@ -5896,7 +5918,7 @@ "title" : "Nonce ist erforderlich" }, "InvalidAddressBecauseAlreadyDelegated" : { - "title" : "Ihr Konto wurde bereits an diesen Validator delegiert" + "title" : "Dein Konto wurde bereits an diesen Validator delegiert" }, "InvalidAddressBecauseDestinationIsAlsoSource" : { "title" : "Empfängeradresse ist die gleiche wie die Absenderadresse" @@ -5906,7 +5928,7 @@ }, "CantOpenDevice" : { "title" : "Entschuldigung, Verbindung fehlgeschlagen", - "description" : "Gerät erkannt, aber Verbindung fehlgeschlagen. Bitte versuchen Sie es erneut oder wenden Sie sich an den Ledger Kundenservice, falls das Problem weiterhin besteht." + "description" : "Gerät erkannt, aber Verbindung fehlgeschlagen. Bitte versuche es noch einmal oder wende dich an den Ledger-Kundenservice, falls das Problem weiterhin besteht." }, "CasperInvalidTransferId" : { "title" : "Die Transaktions-ID muss eine positive Zahl sein, die kleiner als {{maxTransferId}} ist" @@ -5918,12 +5940,12 @@ "title" : "Der nach dem Transfer auf deinem Konto verbleibende Betrag ist kleiner als der zum Senden benötigte Mindestbetrag von {{minAmount}}" }, "ETHAddressNonEIP" : { - "title" : "Automatische Verifizierung nicht verfügbar: Überprüfen Sie die Adresse sorgfältig", + "title" : "Die automatische Verifizierung ist nicht verfügbar. Verifiziere die Adresse daher sorgfältig.", "description" : null }, "EthAppNftNotSupported" : { "title" : "Vorgang auf diesem Gerät nicht verfügbar", - "description" : "Die Funktion zum Senden von NFTs ist nur für Nano X und Nano S+ verfügbar. Bitte besuchen Sie unsere Kunden-Support-Plattform, um herauszufinden, wie man ein NFT mit einem Nano S sendet." + "description" : "Die Funktion zum Senden von NFTs ist nur für Nano X und Nano S+ verfügbar. Bitte besuche unsere Kundenserviceplattform, um herauszufinden, wie man ein NFT mit einer Nano S sendet." }, "TransactionHasBeenValidatedError" : { "title" : "Beschleunigung oder Stornierung nicht möglich", @@ -5940,7 +5962,7 @@ "title" : "Dieser QR-Code konnte nicht gescannt werden: Auto-Verifizierung wird von dieser Adresse nicht unterstützt" }, "FeeNotLoaded" : { - "title" : "Es konnten keine Gebührensätze geladen werden. Bitte stellen Sie manuelle Gebühren ein" + "title" : "Es konnten keine Gebührensätze geladen werden. Bitte lege die Gebühren manuell fest." }, "FeeNotLoadedSwap" : { "title" : "Aus technischen Gründen ist die Schätzung der Netzwerkgebühr fehlgeschlagen. Versuche es noch einmal oder wechsle die Vermögenswerte." @@ -5955,7 +5977,7 @@ "title" : "Die Prioritätsgebühr ist niedriger als der empfohlene Wert" }, "PriorityFeeTooHigh" : { - "title" : "Die Prioritätsgebühr ist höher als nötig. Möglicherweise zahlen Sie zu viel" + "title" : "Die Prioritätsgebühr ist höher als nötig. Möglicherweise zahlst du zu viel" }, "MaxFeeTooLow" : { "title" : "Die Gebühr ist niedriger als der empfohlene Wert" @@ -5965,48 +5987,48 @@ }, "UnknownMCU" : { "title" : "Unbekannte MCU-Version", - "description" : "Bitte kontaktieren Sie den Ledger-Support" + "description" : "Bitte wende dich an den Ledger-Kundenservice" }, "MCUNotGenuineToDashboard" : { "title" : "Zum Dashboard gehen für Aktualisierung", "description" : "", "list" : { - "1" : "Trennen Sie das USB-Kabel ab und schließen Sie es wieder an, ohne eine Taste zu drücken.", - "2" : "Drücken Sie beide Tasten zusammen dreimal, um das Dashboard anzuzeigen.", - "3" : "Öffnen Sie My Ledger und klicken Sie auf „Firmware aktualisieren“." + "1" : "Trenne das USB-Kabel und schließe es wieder an, ohne eine Taste zu drücken.", + "2" : "Drücke beide Tasten gemeinsam dreimal, um das Dashboard anzuzeigen.", + "3" : "Öffne My Ledger und klicke auf „Update firmware“ (Firmware aktualisieren)." } }, "UnavailableTezosOriginatedAccountReceive" : { "title" : "Kann nicht in Unterkonten empfangen werden", - "description" : "Wenn Sie Geld erhalten möchten, verwenden Sie bitte das übergeordnete Konto" + "description" : "Zum Empfangen von Vermögenswerten verwende bitte das übergeordnete Konto" }, "UnavailableTezosOriginatedAccountSend" : { "title" : "Kann noch nicht von Unterkonten senden", "description" : "Diese Funktion wird zu einem späteren Zeitpunkt aufgrund von Änderungen, die kürzlich durch das Babylon-Update eingeführt wurden, hinzugefügt." }, "RecommendUndelegation" : { - "title" : "Bitte heben Sie die Übertragung des Kontos auf, bevor Sie es leeren" + "title" : "Bitte hebe die Delegierung des Kontos auf, bevor du es leerst" }, "RecommendSubAccountsToEmpty" : { - "title" : "Bitte leeren Sie zuerst alle Unterkonten" + "title" : "Bitte leere zuerst alle Unterkonten" }, "NotSupportedLegacyAddress" : { "title" : "Dieses alte Adressformat wird nicht mehr unterstützt" }, "BtcUnmatchedApp" : { "title" : "Das ist die falsche App", - "description" : "Öffnen Sie die App „{{managerAppName}}“ auf Ihrem Gerät" + "description" : "Öffne die {{managerAppName}}-App auf deinem Gerät" }, "DeviceNameInvalid" : { - "title" : "Bitte wählen Sie einen Gerätenamen ohne '{{invalidCharacters}}'" + "title" : "Bitte wähle einen Gerätenamen aus, der folgende Zeichen nicht enthält: {{invalidCharacters}}" }, "LedgerAPIErrorWithMessage" : { "title" : "{{message}}", - "description" : "Bitte versuchen Sie es erneut oder kontaktieren Sie den Ledger-Kundenservice." + "description" : "Bitte versuche es noch einmal oder wende dich an den Ledger-Kundenservice." }, "ManagerAppRelyOnBTC" : { "title" : "Bitcoin- und Ethereum-Apps erforderlich", - "description" : "Installieren Sie zuerst die neuesten Bitcoin- und Ethereum-Apps." + "description" : "Installiere zuerst die Bitcoin- und Ethereum-Apps in der aktuellen Version." }, "UserRefusedDeviceNameChange" : { "title" : "Umbenennen auf dem Gerät abgebrochen" @@ -6017,11 +6039,11 @@ }, "TronNoFrozenForBandwidth" : { "title" : "Keine Vermögenswerte zum Entsperren", - "description" : "Sie haben keine Vermögenswerte zum Entsperren, die mit Bandbreite verbunden sind" + "description" : "Du hast keine entsperrbaren Vermögenswerte, die mit Bandbreite verbunden sind" }, "TronNoFrozenForEnergy" : { "title" : "Keine Vermögenswerte zum Entsperren", - "description" : "Sie haben keine Vermögenswerte zum Entsperren im Zusammenhang mit Energie" + "description" : "Du hast keine entsperrbaren Vermögenswerte, die mit Energie verbunden sind" }, "TronLegacyUnfreezeNotExpired" : { "title" : "Entsperren ist noch nicht verfügbar", @@ -6032,11 +6054,11 @@ }, "TronInvalidVoteCount" : { "title" : "Abstimmungsformat ist falsch", - "description" : "Sie können nur mit runden Zahlen abstimmen" + "description" : "Du kannst nur mit ganzen Zahlen voten" }, "TronRewardNotAvailable" : { "title" : "Prämie ist noch nicht einforderbar", - "description" : "Sie müssen 24 Stunden zwischen den Ansprüchen warten" + "description" : "Zwischen den Beanspruchungen müssen 24 Stunden liegen." }, "TronNoReward" : { "title" : "Es gibt keine Prämie zu beanspruchen" @@ -6045,8 +6067,8 @@ "title" : "Der zu sperrende Betrag kann nicht kleiner als 1 sein" }, "TronSendTrc20ToNewAccountForbidden" : { - "title" : "Sie müssen zuerst mindestens 0,1 TRX an diese Adresse senden, um den Empfang von TRC20-Token zu aktivieren.", - "description" : "Das Empfängerkonto muss aktiviert werden, bevor Sie TRC20 an dieses senden. Senden Sie entweder TRX oder TRC10 an ein Konto, um es zu aktivieren." + "title" : "Du musst zunächst mindestens 0,1 TRX an diese Adresse senden, um den Empfang von TRC20-Token zu aktivieren.", + "description" : "Zum Senden von TRC20 an das Empfängerkonto muss dieses aktiviert sein. Zum Aktivieren eines Kontos kannst du entweder TRX oder TRC10 dorthin senden." }, "TronUnexpectedFees" : { "title" : "Es können zusätzliche Gebühren anfallen" @@ -6056,7 +6078,7 @@ }, "TronTransactionExpired" : { "title" : "Die Transaktion ist abgelaufen", - "description" : "Die Signatur muss innerhalb von 30 Sekunden angewendet werden. Bitte versuchen Sie es erneut." + "description" : "Die Signatur muss innerhalb von 30 Sekunden angewendet werden. Bitte versuche es noch einmal." }, "TronNotEnoughEnergy" : { "title" : "Energie ist niedriger als notwendig. Es können bis zu 50 TRX an Gebühren anfallen." @@ -6065,7 +6087,7 @@ "title" : "Keine entsperrten Vermögenswerte zum Abheben vorhanden" }, "TronInvalidUnDelegateResourceAmount" : { - "title" : "Nicht genügend delegierte Vermögenswerte" + "title" : "Nicht genügend delegierte Guthaben" }, "TronUnfreezeNotExpired" : { "title" : "Vermögenswerte noch nicht entsperrt", @@ -6073,7 +6095,7 @@ }, "PairingFailed" : { "title" : "Kopplung fehlgeschlagen", - "description" : "Bitte versuchen Sie es erneut oder wenden Sie sich im Zweifelsfall an den Ledger-Support." + "description" : "Bitte versuche es noch einmal oder wende dich im Zweifelsfall an den Ledger-Kundenservice." }, "GenuineCheckFailed" : { "title" : "Echtheitsprüfung fehlgeschlagen", @@ -6104,7 +6126,7 @@ "title" : "Kontostand darf nicht unter {{minimumAmount}} liegen" }, "WrongAppForCurrency" : { - "title" : "Bitte öffnen Sie die {{expected}} App" + "title" : "Bitte öffne die {{expected}}-App" }, "FeeTooHigh" : { "title" : "Die Netzwerkgebühren liegen über 10 % des Betrags" @@ -6113,7 +6135,7 @@ "title" : "Die Menge ist niedriger als das Staub (dust) -Limit" }, "SourceHasMultiSign" : { - "title" : "Bitte deaktivieren Sie Multisign um {{currencyName}} zu senden" + "title" : "Bitte deaktiviere Multisign, um {{currencyName}} zu senden" }, "SwapExchangeRateAmountTooLow" : { "title" : "Betrag muss größer sein als {{minAmountFromFormatted}}" @@ -6134,28 +6156,28 @@ "title" : "Alle gebundenen Vermögenswerte werden entbunden, wenn < 1 DOT" }, "PolkadotNoUnlockedBalance" : { - "title" : "Sie haben kein ungebundenes Vermögen" + "title" : "Du hast kein ungebundenes Vermögen" }, "PolkadotNoNominations" : { - "title" : "Sie haben keine Nominierungen" + "title" : "Du hast keine Nominierungen" }, "PolkadotAllFundsWarning" : { - "title" : "Stellen Sie sicher, dass Sie genug Guthaben für zukünftige Transaktionsgebühren übrig haben" + "title" : "Vergewissere dich, dass ausreichend Guthaben für künftige Transaktionsgebühren verbleibt" }, "PolkadotDoMaxSendInstead" : { "title" : "Kontostand darf nicht unter {{minimumBalance}} liegen. Maximalbetrag zu leerem Konto senden." }, "PolkadotBondMinimumAmount" : { - "title" : "Sie müssen eine Kaution von mindestens {{minimumBondAmount}} hinterlegen." + "title" : "Du musst Bonds in Höhe von mindestens {{minimumBondAmount}} hinterlegen." }, "PolkadotBondMinimumAmountWarning" : { - "title" : "Ihr gebundenes Guthaben sollte mindestens {{minimumBondBalance}} sein." + "title" : "Dein gebundenes Guthaben sollte mindestens {{minimumBondBalance}} betragen." }, "PolkadotMaxUnbonding" : { - "title" : "Sie haben das Entbindungslimit überschritten" + "title" : "Du hast das Limit für das Auflösen von Bonds überschritten" }, "PolkadotValidatorsRequired" : { - "title" : "Sie müssen mindestens einen Validator auswählen" + "title" : "Du musst mindestens einen Validator auswählen" }, "ServiceStatusWarning" : { "title" : "{{message}}", @@ -6174,22 +6196,22 @@ "title" : "Adresse aus ed25519 Kurve" }, "SolanaUseAllAmountStakeWarning" : { - "title" : "Stellen Sie sicher, dass Ihr Kontostand zur Deckung künftiger Transaktionsgebühren ausreicht" + "title" : "Stelle sicher, dass dein Guthaben zur Deckung künftiger Transaktionsgebühren ausreicht" }, "SolanaTxSimulationFailedWhilePendingOp" : { - "title" : "Ihre vorherige Transaktion wurde noch nicht verarbeitet. Bitte warten Sie einen Moment und prüfen Sie vor einem erneuten Versuch zunächst den Transaktionsverlauf." + "title" : "Deine vorherige Transaktion wurde noch nicht verarbeitet. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." }, "SolanaTxConfirmationTimeout" : { - "title" : "Ihre Transaktion ist möglicherweise fehlgeschlagen. Bitte warten Sie einen Moment und prüfen Sie vor einem erneuten Versuch zunächst den Transaktionsverlauf." + "title" : "Deine Transaktion ist möglicherweise fehlgeschlagen. Bitte warte einen Moment und prüfe vor einem erneuten Versuch zunächst den Transaktionsverlauf." }, "NotEnoughNftOwned" : { - "title" : "Sie haben die Anzahl der verfügbaren Token überschritten" + "title" : "Du hast die Anzahl der verfügbaren Token überschritten" }, "CardanoMinAmountError" : { "title" : "Der Mindestbetrag, der versendet werden kann, ist {{amount}} ADA" }, "CardanoNotEnoughFunds" : { - "title" : "Bitte vergewissern Sie sich, dass Sie genügend Geld für die Bezahlung der Gebühren haben" + "title" : "Bitte vergewissere dich, dass du genügend Geld für die Bezahlung der Gebühren hast" }, "CardanoStakeKeyDepositError" : { "title" : "Achte darauf, dass dir {{depositAmount}} ADA für die Einzahlung zur Verfügung stehen" @@ -6226,65 +6248,65 @@ }, "StellarNotEnoughNativeBalance" : { "title" : "Entschuldigung, Guthaben reicht nicht aus", - "description" : "Bitte vergewissern Sie sich, dass das Konto ausreichend gedeckt ist, um die Transaktionsgebühr zu decken." + "description" : "Bitte vergewissere dich, dass das Konto eine ausreichende Deckung aufweist, um die Transaktionsgebühr zu bezahlen." }, "StellarFeeSmallerThanRecommended" : { "title" : "Die gewählte Gebühr ist niedriger als die empfohlene Gebühr" }, "StellarFeeSmallerThanBase" : { - "title" : "Die Mindesttransaktionsgebühr beträgt 0,00001 XLM" + "title" : "Die Mindesttransaktionsgebühr beträgt 0,00001 XLM" }, "StellarNotEnoughNativeBalanceToAddTrustline" : { "title" : "Entschuldigung, Guthaben reicht nicht aus", - "description" : "Vergewissern Sie sich, dass das Konto genügend Deckung für die neue Trustline aufweist." + "description" : "Vergewissere dich, dass das Konto eine ausreichende Deckung für die neue Trustline aufweist." }, "StellarMuxedAccountNotExist" : { "title" : "Stellar-Konto existiert nicht" }, "StellarSourceHasMultiSign" : { - "title" : "Bitte deaktivieren Sie Multisign, um Stellar-Transaktionen durchzuführen" + "title" : "Bitte deaktiviere Multisign, um Stellar-Transaktionen durchzuführen" }, "StellarBurnAddressError" : { "title" : "Beim Versuch, ein Stellar-Konto hinzuzufügen, ist ein Problem aufgetreten" }, "HederaAddAccountError" : { - "title" : "Ihr Konto wurde nicht hinzugefügt. Bitte versuchen Sie es erneut." + "title" : "Dein Konto wurde nicht hinzugefügt. Bitte versuche es noch einmal." }, "ImageIncorrectFileTypeError" : { "title" : "Das Laden des Bildes aus einer Datei ist fehlgeschlagen.", - "description" : "Bitte versuchen Sie es erneut mit einem Bild." + "description" : "Bitte versuche es noch einmal mit einem Bild." }, "ImageLoadFromFileError" : { "title" : "Das Laden des Bildes aus einer Datei ist fehlgeschlagen", - "description" : "Bitte versuchen Sie es noch einmal mit einem anderen Bild" + "description" : "Bitte versuche es noch einmal mit einem anderen Bild" }, "ImageLoadFromNftError" : { "title" : "Das Bild konnte nicht aus dem NFT geladen werden", - "description" : "Bitte versuchen Sie es erneut mit einem anderen NFT" + "description" : "Bitte versuche es noch einmal mit einem anderen NFT" }, "ImageDownloadError" : { "title" : "Bilddownload fehlgeschlagen", - "description" : "Bitte versuchen Sie es noch einmal mit einem anderen Bild" + "description" : "Bitte versuche es noch einmal mit einem anderen Bild" }, "ImageTooLargeError" : { "title" : "Das Bild ist zu groß", - "description" : "Bitte versuchen Sie es mit einem kleineren Bild" + "description" : "Bitte versuche es mit einem kleineren Bild" }, "ImageCropError" : { "title" : "Das Zuschneiden des Bildes ist fehlgeschlagen", - "description" : "Bitte versuchen Sie es noch einmal mit einem anderen Bild" + "description" : "Bitte versuche es noch einmal mit einem anderen Bild" }, "ImageResizeError" : { "title" : "Die Größenänderung des Bildes ist fehlgeschlagen", - "description" : "Bitte versuchen Sie es noch einmal mit einem anderen Bild" + "description" : "Bitte versuche es noch einmal mit einem anderen Bild" }, "ImagePreviewError" : { "title" : "Die Vorschau des Bildes ist fehlgeschlagen", - "description" : "Bitte versuchen Sie es noch einmal mit einem anderen Bild" + "description" : "Bitte versuche es noch einmal mit einem anderen Bild" }, "ImageProcessingError" : { "title" : "Die Verarbeitung des Bildes ist fehlgeschlagen", - "description" : "Bitte versuchen Sie es noch einmal mit einem anderen Bild" + "description" : "Bitte versuche es noch einmal mit einem anderen Bild" }, "ImageCommitRefusedOnDevice" : { "title" : "Die Installation des Bildes für den Sperrbildschirm auf\n{{productName}} wurde abgebrochen", @@ -6308,7 +6330,7 @@ "title" : "Dieser Betrag deckt nicht die Speicherkosten über {{formattedNewAccountStorageCost}} ab." }, "NearUseAllAmountStakeWarning" : { - "title" : "Stellen Sie sicher, dass Sie genug Guthaben für zukünftige Transaktionsgebühren übrig haben" + "title" : "Vergewissere dich, dass ausreichend Guthaben für künftige Transaktionsgebühren verbleibt" }, "NearNotEnoughStaked" : { "title" : "Unzureichendes Guthaben, welches gestaked wurde" @@ -6317,32 +6339,32 @@ "title" : "Unzureichendes abhebbares Guthaben" }, "NearRecommendUnstake" : { - "title" : "Bitte heben Sie den Staking-Prozess auf und heben Sie Ihre Vermögenswerte ab, bevor Sie das Konto leeren" + "title" : "Bitte beende das Staking und hebe dein Guthaben ab, bevor du das Konto leerst" }, "NearStakingThresholdNotMet" : { "title" : "Der Betrag muss mindestens {{threshold}} betragen" }, "LockedDeviceError" : { - "title" : "Ihr Gerät ist gesperrt", - "description" : "Entsperren Sie Ihr Gerät und versuchen Sie es erneut.", - "descriptionWithProductName" : "Entsperren Sie Ihr {{ productName }} und versuchen Sie es erneut." + "title" : "Dein Gerät ist gesperrt", + "description" : "Entsperre dein Gerät und versuche es noch einmal.", + "descriptionWithProductName" : "Entsperre deine {{ productName }} und versuche es noch einmal." }, "DeviceNotOnboardedError" : { "title" : "Dein Ledger-Gerät ist nicht eingerichtet", - "description" : "Richte es für die Nutzung ein. Wir führen dich durch den Einrichtungsprozess.", + "description" : "Richte es für die Nutzung ein. Wir begleiten dich durch den Einrichtungsprozess.", "goToOnboardingButton" : "Mein Ledger-Gerät einrichten", - "goToOnboardingButtonWithProductName" : "Mein {{ productName }} einrichten" + "goToOnboardingButtonWithProductName" : "Meine {{ productName }} einrichten" }, "EtherscanAPIError" : { "title" : "Abruf der Transaktionen fehlgeschlagen", - "description" : "Bei den Explorern ist ein unerwarteter Fehler aufgetreten. Versuchen Sie es bitte später noch einmal" + "description" : "Bei den Explorern ist ein unerwarteter Fehler aufgetreten. Versuche es bitte später noch einmal" }, "GasEstimationError" : { "title" : "Gasgebührenschätzung fehlgeschlagen" }, "FailedToRetrieveFirmwareUpdateInfo" : { "title" : "Prüfung auf Betriebssystem-Update fehlgeschlagen", - "description" : "Ein Problem ist aufgetreten. Bitte versuche es noch einmal oder wende dich im Zweifelsfall an den Ledger-Kundenservice." + "description" : "Das hat leider nicht funktioniert. Bitte versuche es noch einmal oder wende dich im Zweifelsfall an den Ledger-Kundenservice." }, "TezosUnrevealedAccount" : { "title" : "Umtauschen nicht möglich: Erfordert initiales Senden/Delegieren bei Tezos-Konto oder Austausch des Paares." @@ -6399,21 +6421,21 @@ "cryptoOrg" : { "memo" : "Memo", "memoPlaceholder" : "Tag/Memo eingeben", - "memoWarningText" : "Bei Verwendung eines Memos sollten Sie alle Angaben sorgfältig beim Empfänger verifizieren." + "memoWarningText" : "Bei Verwendung eines Memos solltest du alle Angaben sorgfältig beim Empfänger verifizieren" }, "hedera" : { "name" : "Hedera", "createHederaAccountHelp" : { - "text" : "In diesem Supportartikel erhalten Sie weitere Informationen zum Thema", + "text" : "In diesem Supportartikel erhältst du weitere Informationen zum Thema", "link" : "Erstellen eines Hedera-Kontos" }, "currentAddress" : { - "messageIfVirtual" : "Ihre {{name}}-Adresse kann auf Ihrem Ledger-Gerät nicht bestätigt werden. Nutzung auf eigenes Risiko." + "messageIfVirtual" : "Deine {{name}}-Adresse kann auf deinem Ledger-Gerät nicht bestätigt werden. Die Nutzung erfolgt auf eigenes Risiko." }, "send" : { "memo" : { "label" : "Memo (Optional)", - "characterCount" : "{{memoLength}} / {{memoMaxLength}}" + "characterCount" : "{{memoLength}} von {{memoMaxLength}}" } } }, @@ -6434,15 +6456,15 @@ "steps" : { "choose" : { "stepLabel" : "Bild auswählen", - "description" : "Wählen Sie ein Bild, das als (...) festgelegt werden soll", + "description" : "Wähle ein Bild aus, das als (...) festgelegt werden soll", "pickFromNftGallery" : "Aus meiner NFT-Galerie auswählen", "myNfts" : "Meine NFTs", "upload" : "Vom Computer hochladen", - "chooseNft" : "Wählen Sie ein NFT", + "chooseNft" : "NFT wählen", "remove" : "Aktuelles Bild entfernen", "selectNft" : "NFT wählen", "nftEmptyStateTitle" : "Es können noch keine NFTs angezeigt werden", - "nftEmptyStateDescription" : "Fügen Sie NFTs zu Ihrer Wallet hinzu, um loszulegen." + "nftEmptyStateDescription" : "Füge NFTs zu deiner Wallet hinzu, um loszulegen." }, "adjust" : { "stepLabel" : "Zuschneiden", @@ -6461,7 +6483,7 @@ "loadingPicture" : "Installation in Bearbeitung …", "voila" : "Voilà!", "imageLoaded" : "Bild geladen auf {{productName}}", - "confirmPicture" : "Gefällt Ihnen, was Sie sehen?\nBehalten Sie es!", + "confirmPicture" : "Gefällt dir, was du siehst?\nBehalte es einfach!", "confirmRestorePicture" : "Tippe auf „Keep“ (Behalten), um\ndein Sperrbildschirm-Bild zu bestätigen", "doThisLater" : "Vielleicht später" } @@ -6478,46 +6500,46 @@ "restore" : { "title" : "Die gleichen Apps wie auf {{deviceName}} installieren?", "titleNoDeviceName" : "Die gleichen Apps wie auf dem vorherigen Ledger-Gerät installieren?", - "subtitle" : "Sie können Apps jederzeit installieren oder entfernen.", + "subtitle" : "Du kannst Apps jederzeit installieren oder entfernen.", "installCTA" : "Jetzt installieren", "skipCTA" : "Ich mache das später" }, "default" : { "title" : "Für {{ productName }} gibt es separate Apps. Diese sind zum Durchführen von Transaktionen erforderlich.", - "subtitle" : "So ist beispielsweise die Bitcoin-App für {{productName}} notwendig, um Bitcoin-Transaktionen zu signieren.\nInstalliere die Standard-Apps, um dein {{productName}}-Gerät für Transaktionen startklar zu machen.", + "subtitle" : "So ist beispielsweise die Bitcoin-App für {{productName}} notwendig, um Bitcoin-Transaktionen zu signieren.\n\nInstalliere die Standard-Apps, um deine {{productName}} für Transaktionen startklar zu machen.", "installCTA" : "Jetzt installieren", "skipCTA" : "Ich mache das später" }, "progress" : { "loading" : "Lade Daten...", - "progress" : "Bleiben Sie auf Ledger Live, während die Apps installiert werden.", - "disclaimer" : "Sie können jederzeit Apps aus Ledger Live hinzufügen oder entfernen.", - "skippedInfo" : "Einige Apps sind nicht verfügbar. Sie müssen noch entwickelt werden für {{ productName }}.", + "progress" : "Bleib in Ledger Live, während die Apps installiert werden.", + "disclaimer" : "Du kannst jederzeit Apps aus Ledger Live hinzufügen oder entfernen.", + "skippedInfo" : "Einige Apps sind nicht verfügbar. Sie müssen für die {{ productName }} noch entwickelt werden.", "skipped" : "Noch nicht verfügbar für {{ productName }}", "app" : "{{appName}}-App" }, "cancelled" : { "title" : "Die Installation der App wurde auf {{productName}} abgebrochen", - "subtitle" : "{{productName}} benötigt Blockchain-Apps, um Ihre Krypto- und NFT-Transaktionen zu genehmigen.", + "subtitle" : "{{productName}} benötigt Blockchain-Apps, um deine Krypto- und NFT-Transaktionen zu genehmigen.", "installCTA" : "Jetzt installieren", "skipCTA" : "Ich mache das später" }, "locked" : { - "title" : "Ihr {{productName}} ist gesperrt", - "subtitle" : "Geben Sie Ihren {{productName}} frei und starten Sie die Installation neu.", + "title" : "Deine {{productName}} ist gesperrt", + "subtitle" : "Entsperre deine {{productName}} und starte die Installation dann neu.", "installCTA" : "Installation neu starten" } }, "discoverProtect" : { - "title" : "Stellen Sie Ihre Schlüssel\nmithilfe Ihrer Identität wieder her", - "description" : "Ihre geheime Wiederherstellungsphrase wird nicht immer in Reichweite sein.\nSoft Launch exklusiv für Ledger Nano X: Kostenlos abonnieren bis 30. Juni 2023", + "title" : "Stelle deine Schlüssel\nmithilfe deiner Identität wieder her", + "description" : "Deine geheime Wiederherstellungsphrase wird nicht immer in Reichweite sein.\nSoft Launch exklusiv für Ledger Nano X: Kostenlos abonnieren bis 30. Juni 2023", "cta" : "Warum sollte ich abonnieren?", - "downloadLLM" : "Abonnieren Sie Ledger Recover über die Ledger Live Mobile-App" + "downloadLLM" : "Abonniere Ledger Recover über die Ledger Live Mobile-App" }, "webview" : { "networkError" : { "title" : "Netzwerkfehler", - "subtitle" : "Das hat leider nicht funktioniert. Bitte versuchen Sie es noch einmal. Wenn das Problem weiterhin besteht, speichern Sie Ihre Logdatei und kontaktieren Sie den Ledger-Kundenservice.", + "subtitle" : "Das hat leider nicht funktioniert. Bitte versuche es noch einmal. Wenn das Problem weiterhin besteht, speichere deine Logdatei und kontaktiere den Ledger-Kundenservice.", "contactSupport" : "Ledger-Kundenservice kontaktieren", "saveLog" : "Log speichern" }, diff --git a/apps/ledger-live-desktop/static/i18n/en/app.json b/apps/ledger-live-desktop/static/i18n/en/app.json index 2f4429528ffb..a04276a7f2b6 100644 --- a/apps/ledger-live-desktop/static/i18n/en/app.json +++ b/apps/ledger-live-desktop/static/i18n/en/app.json @@ -3045,6 +3045,7 @@ "validatorGroup": { "title": "Validator Group", "ledgerByFigmentTC": "Ledger by Figment T&Cs", + "ledgerByChorusOneTC": "Ledger by Chorus One T&Cs", "totalVotes": "Total Votes", "commission": "Commission" } @@ -3642,6 +3643,7 @@ "withdrawableTitle": "Withdrawable", "statusUpdateNotice": "The status of the delegation will be updated when the transaction is confirmed.", "ledgerByFigmentTC": "Ledger by Figment T&Cs", + "ledgerByChorusOneTC": "Ledger by Chorus One T&Cs", "emptyState": { "description": "You can earn SOL rewards by delegating your assets.", "info": "How Delegation works", @@ -3900,6 +3902,7 @@ }, "validator": { "title": "Validators", + "ledgerByChorusOneTC": "Ledger by Chorus One T&Cs", "ledgerByFigmentTC": "Ledger by Figment T&Cs" }, "connectDevice": { @@ -4167,6 +4170,7 @@ "link": "Link", "secondaryCta": "Secondary CTA", "cta": "CTA", + "tag": "Tag", "url": "URL", "path": "Path" } diff --git a/apps/ledger-live-desktop/static/i18n/es/app.json b/apps/ledger-live-desktop/static/i18n/es/app.json index 014e70071179..181e7d3ca2e8 100644 --- a/apps/ledger-live-desktop/static/i18n/es/app.json +++ b/apps/ledger-live-desktop/static/i18n/es/app.json @@ -3037,6 +3037,7 @@ "validatorGroup" : { "title" : "Grupo de validadores", "ledgerByFigmentTC" : "Términos y condiciones de Ledger by Figment", + "ledgerByChorusOneTC" : "Términos y condiciones de Ledger by Chorus One", "totalVotes" : "Total de votos", "commission" : "Comisión" } @@ -3626,6 +3627,7 @@ "withdrawableTitle" : "Puede retirarse", "statusUpdateNotice" : "El estado de la delegación se actualizará cuando se confirme la transacción.", "ledgerByFigmentTC" : "Términos y condiciones de Ledger by Figment", + "ledgerByChorusOneTC" : "Términos y condiciones de Ledger by Chorus One", "emptyState" : { "description" : "Puedes recibir recompensas SOL delegando tu activos.", "info" : "Cómo funciona la delegación", @@ -3880,6 +3882,7 @@ }, "validator" : { "title" : "Validadores", + "ledgerByChorusOneTC" : "Términos y condiciones de Ledger by Chorus One", "ledgerByFigmentTC" : "Términos y condiciones de Ledger by Figment" }, "connectDevice" : { @@ -4147,6 +4150,7 @@ "link" : "Enlace", "secondaryCta" : "CTA secundario", "cta" : "CTA", + "tag" : "Etiqueta", "url" : "URL", "path" : "Ruta" } diff --git a/apps/ledger-live-desktop/static/i18n/fr/app.json b/apps/ledger-live-desktop/static/i18n/fr/app.json index 5e84af5d5924..e83020f9fa7a 100644 --- a/apps/ledger-live-desktop/static/i18n/fr/app.json +++ b/apps/ledger-live-desktop/static/i18n/fr/app.json @@ -502,7 +502,7 @@ "to" : "À", "toExchange" : "Montant à envoyer", "toReceive" : "Montant à recevoir", - "terms" : "Conditions d’utilisation", + "terms" : "Conditions générales", "disclaimer" : { "description" : "En choisissant Confirmer, je reconnais et j’accepte que ce service soit exclusivement soumis aux Conditions d’utilisation de <0>{{provider}}.", "acceptedDescription" : "Ce service est exclusivement soumis aux Conditions d’utilisation de <0>{{provider}}." @@ -2344,7 +2344,7 @@ "ethereumMaxFee" : "Frais maximaux ({{unitName}})", "ethereumPriorityFee" : "Frais de priorité maximaux ({{unitName}})", "nextBlock" : "Bloc suivant", - "suggested" : "Suggérés", + "suggested" : "Suggéré", "unitPerByte" : "{{unit}} par byte", "nft" : "NFT", "nftQuantity" : "Nombre" @@ -3036,7 +3036,8 @@ }, "validatorGroup" : { "title" : "Groupe de validateurs", - "ledgerByFigmentTC" : "Conditions d’utilisation de Ledger by Figment", + "ledgerByFigmentTC" : "CG de Ledger by Figment", + "ledgerByChorusOneTC" : "CG de Ledger by Chorus One", "totalVotes" : "Total des votes", "commission" : "Commission" } @@ -3625,7 +3626,8 @@ "withdrawableInfoTooltip" : "Montant total pouvant être retiré des délégations", "withdrawableTitle" : "Disponible au retrait", "statusUpdateNotice" : "Le statut de la délégation sera mis à jour une fois la transaction confirmée.", - "ledgerByFigmentTC" : "Conditions d’utilisation de Ledger by Figment", + "ledgerByFigmentTC" : "CG de Ledger by Figment", + "ledgerByChorusOneTC" : "CG de Ledger by Chorus One", "emptyState" : { "description" : "Vous pouvez gagner des récompenses en SOL en déléguant vos actifs.", "info" : "Fonctionnement de la délégation", @@ -3880,7 +3882,8 @@ }, "validator" : { "title" : "Validateurs", - "ledgerByFigmentTC" : "Conditions d’utilisation de Ledger by Figment" + "ledgerByChorusOneTC" : "CG de Ledger by Chorus One", + "ledgerByFigmentTC" : "CG de Ledger by Figment" }, "connectDevice" : { "title" : "Appareil" @@ -4147,6 +4150,7 @@ "link" : "Lien", "secondaryCta" : "CTA secondaire", "cta" : "CTA", + "tag" : "Tag", "url" : "URL", "path" : "Chemin" } @@ -4692,7 +4696,7 @@ "noDevice" : "Pas encore d’appareil ?", "buyLink" : "Pas encore d’appareil ? Achetez un Ledger Nano X.", "byTapping" : "En appuyant sur Commencer, vous acceptez nos", - "termsAndConditions" : "Conditions d’utilisation", + "termsAndConditions" : "Conditions générales", "and" : "et", "privacyPolicy" : "Politique de confidentialité", "steps" : { @@ -5380,7 +5384,7 @@ "memoWarningText" : "Lorsque vous utilisez un mémo, vérifiez bien le type à utiliser auprès du bénéficiaire.", "fee" : "Frais", "feeInfoText" : "Des frais de transaction minimaux de 0,00001 XLM sont nécessaires pour effectuer une transaction sur Stellar.", - "suggested" : "Suggérés", + "suggested" : "Suggéré", "recommendedFee" : "Frais recommandés", "recommenndedFeeInfo" : "Vous pouvez émettre cette transaction avec des frais inférieurs à ceux recommandés, mais elle ne sera peut être pas traitée.", "networkCongestion" : "Activité sur le réseau", diff --git a/apps/ledger-live-desktop/static/i18n/ja/app.json b/apps/ledger-live-desktop/static/i18n/ja/app.json index e96052b2d94c..09f2baf7c951 100644 --- a/apps/ledger-live-desktop/static/i18n/ja/app.json +++ b/apps/ledger-live-desktop/static/i18n/ja/app.json @@ -3037,6 +3037,7 @@ "validatorGroup" : { "title" : "バリデーターグループ", "ledgerByFigmentTC" : "Ledger by Figment T&Cs", + "ledgerByChorusOneTC" : "Ledger by Chorus One 利用規約", "totalVotes" : "総投票数", "commission" : "コミッション" } @@ -3626,6 +3627,7 @@ "withdrawableTitle" : "引き出し可能", "statusUpdateNotice" : "処理が承認されると、デリゲートのステータスが更新されます。", "ledgerByFigmentTC" : "Ledger by Figment T&Cs", + "ledgerByChorusOneTC" : "Ledger by Chorus One 利用規約", "emptyState" : { "description" : "資産をデリゲートすることで、SOLで報酬を獲得できます。", "info" : "デリゲートの仕組み", @@ -3880,6 +3882,7 @@ }, "validator" : { "title" : "バリデーター", + "ledgerByChorusOneTC" : "Ledger by Chorus One 利用規約", "ledgerByFigmentTC" : "Ledger by Figment T&Cs" }, "connectDevice" : { @@ -4147,6 +4150,7 @@ "link" : "リンク", "secondaryCta" : "セカンダリCTA", "cta" : "CTA", + "tag" : "タグ", "url" : "URL", "path" : "パス" } diff --git a/apps/ledger-live-desktop/static/i18n/ko/app.json b/apps/ledger-live-desktop/static/i18n/ko/app.json index d848cc8f6514..1b029973cd41 100644 --- a/apps/ledger-live-desktop/static/i18n/ko/app.json +++ b/apps/ledger-live-desktop/static/i18n/ko/app.json @@ -3037,6 +3037,7 @@ "validatorGroup" : { "title" : "검증인 그룹", "ledgerByFigmentTC" : "Ledger by Figment 이용약관", + "ledgerByChorusOneTC" : "Ledger by Chorus One 이용약관", "totalVotes" : "총 투표수", "commission" : "커미션" } @@ -3626,6 +3627,7 @@ "withdrawableTitle" : "출금 가능", "statusUpdateNotice" : "거래 확인 후 위임 상태가 업데이트됩니다.", "ledgerByFigmentTC" : "Ledger by Figment 이용약관", + "ledgerByChorusOneTC" : "Ledger by Chorus One 이용약관", "emptyState" : { "description" : "자산을 위임하여 SOL 보상을 받을 수 있습니다.", "info" : "위임은 어떤 원리인가요?", @@ -3880,6 +3882,7 @@ }, "validator" : { "title" : "검증인", + "ledgerByChorusOneTC" : "Ledger by Chorus One 이용약관", "ledgerByFigmentTC" : "Ledger by Figment 이용약관" }, "connectDevice" : { @@ -4147,6 +4150,7 @@ "link" : "링크", "secondaryCta" : "보조 CTA", "cta" : "CTA", + "tag" : "태그", "url" : "URL", "path" : "경로" } diff --git a/apps/ledger-live-desktop/static/i18n/pt-BR/app.json b/apps/ledger-live-desktop/static/i18n/pt-BR/app.json index 0a6d37e20186..9c90d1784141 100644 --- a/apps/ledger-live-desktop/static/i18n/pt-BR/app.json +++ b/apps/ledger-live-desktop/static/i18n/pt-BR/app.json @@ -3037,6 +3037,7 @@ "validatorGroup" : { "title" : "Grupo de validadores", "ledgerByFigmentTC" : "Ledger por Figment T&Cs", + "ledgerByChorusOneTC" : "Termos e Condições da Ledger by Chorus One", "totalVotes" : "Total de votos", "commission" : "Comissão" } @@ -3626,6 +3627,7 @@ "withdrawableTitle" : "Sacáveis", "statusUpdateNotice" : "O status da delegação será atualizado quando a transação for confirmada.", "ledgerByFigmentTC" : "Ledger por Figment T&Cs", + "ledgerByChorusOneTC" : "Termos e Condições da Ledger by Chorus One", "emptyState" : { "description" : "Você pode ganhar recompensas em SOL delegando seus ativos.", "info" : "Como funciona a delegação", @@ -3880,6 +3882,7 @@ }, "validator" : { "title" : "Validadores", + "ledgerByChorusOneTC" : "Termos e Condições da Ledger by Chorus One", "ledgerByFigmentTC" : "Ledger por Figment T&Cs" }, "connectDevice" : { @@ -4147,6 +4150,7 @@ "link" : "Link", "secondaryCta" : "CTA secundário", "cta" : "CTA", + "tag" : "Etiqueta", "url" : "URL", "path" : "Path" } diff --git a/apps/ledger-live-desktop/static/i18n/ru/app.json b/apps/ledger-live-desktop/static/i18n/ru/app.json index e53867f33221..606cd4d12494 100644 --- a/apps/ledger-live-desktop/static/i18n/ru/app.json +++ b/apps/ledger-live-desktop/static/i18n/ru/app.json @@ -3037,6 +3037,7 @@ "validatorGroup" : { "title" : "Группа валидаторов", "ledgerByFigmentTC" : "Положения и условия Ledger by Figment", + "ledgerByChorusOneTC" : "Положения и условия Ledger by Chorus One", "totalVotes" : "Всего голосов", "commission" : "Комиссия" } @@ -3626,6 +3627,7 @@ "withdrawableTitle" : "Доступно для вывода", "statusUpdateNotice" : "Статус делегирования обновится, когда транзакция будет подтверждена.", "ledgerByFigmentTC" : "Положения и условия Ledger by Figment", + "ledgerByChorusOneTC" : "Положения и условия Ledger by Chorus One", "emptyState" : { "description" : "Вы можете зарабатывать вознаграждения в токенах SOL, делегируя активы.", "info" : "Как работает делегирование", @@ -3880,6 +3882,7 @@ }, "validator" : { "title" : "Валидаторы", + "ledgerByChorusOneTC" : "Положения и условия Ledger by Chorus One", "ledgerByFigmentTC" : "Положения и условия Ledger by Figment" }, "connectDevice" : { @@ -4147,6 +4150,7 @@ "link" : "Ссылка", "secondaryCta" : "Вторичный CTA", "cta" : "CTA", + "tag" : "Тег", "url" : "URL", "path" : "Путь" } diff --git a/apps/ledger-live-desktop/static/i18n/tr/app.json b/apps/ledger-live-desktop/static/i18n/tr/app.json index 340f61b45cef..88e169ff1e65 100644 --- a/apps/ledger-live-desktop/static/i18n/tr/app.json +++ b/apps/ledger-live-desktop/static/i18n/tr/app.json @@ -3037,6 +3037,7 @@ "validatorGroup" : { "title" : "Doğrulayıcı Grubu", "ledgerByFigmentTC" : "Ledger by Figment Hüküm ve Koşulları", + "ledgerByChorusOneTC" : "Ledger by Chorus One Hüküm ve Koşulları", "totalVotes" : "Toplam Oy", "commission" : "Komisyon" } @@ -3626,6 +3627,7 @@ "withdrawableTitle" : "Çekilebilir bakiye", "statusUpdateNotice" : "İşlem onaylandığında yetki devrinin durumu güncellenir.", "ledgerByFigmentTC" : "Ledger by Figment Hüküm ve Koşulları", + "ledgerByChorusOneTC" : "Ledger by Chorus One Hüküm ve Koşulları", "emptyState" : { "description" : "Varlıklarınızın yetkisini devrederek SOL ödülleri kazanabilirsiniz.", "info" : "Yetki Devri nasıl çalışır?", @@ -3880,6 +3882,7 @@ }, "validator" : { "title" : "Doğrulayıcılar", + "ledgerByChorusOneTC" : "Ledger by Chorus One Hüküm ve Koşulları", "ledgerByFigmentTC" : "Ledger by Figment Hüküm ve Koşulları" }, "connectDevice" : { @@ -4147,6 +4150,7 @@ "link" : "Bağlantı", "secondaryCta" : "İkincil Eylem Çağrısı", "cta" : "Eylem Çağrısı", + "tag" : "Etiket", "url" : "URL", "path" : "Yol" } diff --git a/apps/ledger-live-desktop/static/i18n/zh/app.json b/apps/ledger-live-desktop/static/i18n/zh/app.json index 940b38f109f6..4da0b55b5bb0 100644 --- a/apps/ledger-live-desktop/static/i18n/zh/app.json +++ b/apps/ledger-live-desktop/static/i18n/zh/app.json @@ -3037,6 +3037,7 @@ "validatorGroup" : { "title" : "验证者组", "ledgerByFigmentTC" : "Figment 在 Ledger 的条款与条件", + "ledgerByChorusOneTC" : "Ledger by Chorus One 条款与条件", "totalVotes" : "总投票数", "commission" : "佣金" } @@ -3626,6 +3627,7 @@ "withdrawableTitle" : "可提取", "statusUpdateNotice" : "交易确认后,委托状态将更新。", "ledgerByFigmentTC" : "Figment 在 Ledger 的条款与条件", + "ledgerByChorusOneTC" : "Ledger by Chorus One 条款与条件", "emptyState" : { "description" : "您可以通过委托资产赚取 SOL 奖励。", "info" : "委托机制如何运作", @@ -3880,6 +3882,7 @@ }, "validator" : { "title" : "验证者", + "ledgerByChorusOneTC" : "Ledger by Chorus One 条款与条件", "ledgerByFigmentTC" : "Figment 在 Ledger 的条款与条件" }, "connectDevice" : { @@ -4147,6 +4150,7 @@ "link" : "链接", "secondaryCta" : "次要号召性用语", "cta" : "号召性用语", + "tag" : "标签", "url" : "网址", "path" : "路径" } diff --git a/apps/ledger-live-desktop/tests/.eslintrc.js b/apps/ledger-live-desktop/tests/.eslintrc.js index e1fa9d6caec6..934a34437f38 100644 --- a/apps/ledger-live-desktop/tests/.eslintrc.js +++ b/apps/ledger-live-desktop/tests/.eslintrc.js @@ -17,4 +17,7 @@ module.exports = { "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-var-requires": "off", }, + globals: { + globalThis: "readonly", + }, }; diff --git a/apps/ledger-live-desktop/tests/fixtures/common.ts b/apps/ledger-live-desktop/tests/fixtures/common.ts index 67a8a1fa1cdd..60964fca7e2d 100644 --- a/apps/ledger-live-desktop/tests/fixtures/common.ts +++ b/apps/ledger-live-desktop/tests/fixtures/common.ts @@ -153,7 +153,7 @@ export const test = base.extend({ ...process.env, VERBOSE: true, MOCK: IS_NOT_MOCK ? undefined : true, - MOCK_COUNTERVALUES: true, + MOCK_COUNTERVALUES: IS_NOT_MOCK ? undefined : true, HIDE_DEBUG_MOCK: true, CI: process.env.CI || undefined, PLAYWRIGHT_RUN: true, @@ -162,7 +162,6 @@ export const test = base.extend({ FEATURE_FLAGS: JSON.stringify(featureFlags), MANAGER_DEV_MODE: IS_NOT_MOCK ? true : undefined, SPECULOS_API_PORT: IS_NOT_MOCK ? getEnv("SPECULOS_API_PORT")?.toString() : undefined, - DISABLE_TRANSACTION_BROADCAST: !IS_NOT_MOCK ? undefined : 1, }, env, ); diff --git a/apps/ledger-live-desktop/tests/jestSetup.js b/apps/ledger-live-desktop/tests/jestSetup.js index d46bde1896c6..233c52e23b92 100644 --- a/apps/ledger-live-desktop/tests/jestSetup.js +++ b/apps/ledger-live-desktop/tests/jestSetup.js @@ -94,3 +94,18 @@ jest.mock("src/sentry/renderer", () => ({ setTags: jest.fn(), getSentryIfAvailable: jest.fn().mockReturnValue(false), })); + +if (!globalThis.Buffer) { + // Note: this polyfill depends on the patch buffer@6.0.3 which adds the Uint8 + // subarray logic. It's the same as in ledger-live-mobile + // Furthermore, importing 'buffer' gets translated to 'node:buffer' so we're + // using a relative path here + const { Buffer } = require("../node_modules/buffer"); + Object.defineProperty(globalThis, "Buffer", { value: Buffer }); +} else { + // jsdom defines a global Buffer + if (!(globalThis.Buffer.prototype instanceof Uint8Array)) { + // jsdom does not define Buffer as an instance of Uint8Array, so we need to set it + Object.setPrototypeOf(globalThis.Buffer.prototype, Uint8Array.prototype); + } +} diff --git a/apps/ledger-live-desktop/tests/page/modal/add.account.modal.ts b/apps/ledger-live-desktop/tests/page/modal/add.account.modal.ts index b37b8c894ee1..cf81d312567c 100644 --- a/apps/ledger-live-desktop/tests/page/modal/add.account.modal.ts +++ b/apps/ledger-live-desktop/tests/page/modal/add.account.modal.ts @@ -18,6 +18,7 @@ export class AddAccountModal extends Modal { private selectAccountInList = (Currency: Currency) => this.page.getByRole("option", { name: `${Currency.name} (${Currency.ticker})`, + exact: true, }); private selectTokenNetwork = (SubAccount: Account) => this.page diff --git a/apps/ledger-live-desktop/tests/page/modal/receive.modal.ts b/apps/ledger-live-desktop/tests/page/modal/receive.modal.ts index afd6f1a40d82..906661a92827 100644 --- a/apps/ledger-live-desktop/tests/page/modal/receive.modal.ts +++ b/apps/ledger-live-desktop/tests/page/modal/receive.modal.ts @@ -34,6 +34,12 @@ export class ReceiveModal extends Modal { await this.skipDeviceButton.click(); } + @step("Retrieve fees amount value") + async getAddressDisplayed() { + const text = await this.addressDisplayedValue.textContent(); + return text ? text?.split(" ")[0] : ""; + } + @step("Verify receive address correctness $0") async expectValidReceiveAddress(address: string) { await expect(this.verifyAddressOnDeviceLabel).toBeVisible(); diff --git a/apps/ledger-live-desktop/tests/page/modal/send.modal.ts b/apps/ledger-live-desktop/tests/page/modal/send.modal.ts index b51ee208e248..c36ec22af909 100644 --- a/apps/ledger-live-desktop/tests/page/modal/send.modal.ts +++ b/apps/ledger-live-desktop/tests/page/modal/send.modal.ts @@ -81,8 +81,6 @@ export class SendModal extends Modal { if (tx.speed !== undefined) { await this.chooseFeeStrategy(tx.speed); } - - await this.countinueSendAmount(); } @step("Verify tx information before confirming") diff --git a/apps/ledger-live-desktop/tests/page/portfolio.page.ts b/apps/ledger-live-desktop/tests/page/portfolio.page.ts index 06118f495ef1..4c30a760fff5 100644 --- a/apps/ledger-live-desktop/tests/page/portfolio.page.ts +++ b/apps/ledger-live-desktop/tests/page/portfolio.page.ts @@ -19,7 +19,11 @@ export class PortfolioPage extends AppPage { private showAllButton = this.page.getByText("Show all"); private showMoreButton = this.page.getByText("Show more"); private assetRow = (asset: string) => this.page.getByTestId(`asset-row-${asset.toLowerCase()}`); + private assetRowValue = (asset: string) => + this.page.getByTestId(`asset-row-${asset.toLowerCase()}`).locator("//div[position()=5]"); private operationRows = this.page.locator("[data-testid^='operation-row-']"); + private totalBalance = this.page.getByTestId("total-balance"); + private balanceDiff = this.page.getByTestId("balance-diff"); @step("Open `Add account` modal") async openAddAccountModal() { @@ -104,4 +108,50 @@ export class PortfolioPage extends AppPage { expect(numberOfOperationsAfter).toBeGreaterThan(numberOfOperationsBefore); } } + + @step("Expect total balance to be visible") + async expectTotalBalanceToBeVisible() { + expect(this.totalBalance).toBeVisible(); + } + + @step("Expect total balance to have the correct counter value $0") + async expectTotalBalanceCounterValue(counterValue: string) { + await this.expectTotalBalanceToBeVisible(); + expect(this.totalBalance).toContainText(counterValue); + } + + @step("Expect balance diff to be visible") + async expectBalanceDiffToBeVisible() { + expect(this.balanceDiff).toBeVisible(); + } + + @step("Expect balance diff to have the correct counter value $0") + async expectBalanceDiffCounterValue(counterValue: string) { + await this.expectBalanceDiffToBeVisible(); + expect(this.balanceDiff).toContainText(counterValue); + } + + @step("Expect asset row $0 to be visible") + async expectAssetRowToBeVisible(asset: string) { + await this.assetRow(asset).isVisible(); + } + + @step("Expect asset row $0 to have the correct counter value $1") + async expectAssetRowCounterValue(asset: string, counterValue: string) { + await this.expectAssetRowToBeVisible(asset); + expect(this.assetRowValue(asset)).toContainText(counterValue); + } + + @step("Expect operation row to be visible") + async expectOperationRowToBeVisible() { + const operationRow = this.operationRows.first(); + await operationRow.isVisible(); + } + + @step("Expect operation to contain counter value $0") + async expectOperationCounterValue(counterValue: string) { + await this.expectOperationRowToBeVisible(); + const operationRow = this.operationRows.first(); + await expect(operationRow).toContainText(counterValue); + } } diff --git a/apps/ledger-live-desktop/tests/page/settings.page.ts b/apps/ledger-live-desktop/tests/page/settings.page.ts index 97f49ca455bc..aaf57ed961f1 100644 --- a/apps/ledger-live-desktop/tests/page/settings.page.ts +++ b/apps/ledger-live-desktop/tests/page/settings.page.ts @@ -1,5 +1,6 @@ import { AppPage } from "tests/page/abstractClasses"; import { step } from "tests/misc/reporters/step"; +import { expect } from "@playwright/test"; export class SettingsPage extends AppPage { private manageLedgerSyncButton = this.page.getByRole("button", { name: "Manage" }); @@ -57,12 +58,18 @@ export class SettingsPage extends AppPage { await this.experimentalDevModeToggle.click(); } - async changeCounterValue() { + @step("Change counter value to $0") + async changeCounterValue(currency: string) { await this.counterValueSelector.click(); - await this.counterValueSearchBar.fill("euro"); + await this.counterValueSearchBar.fill(currency); await this.counterValueropdownChoiceEuro.click(); } + @step("Expect counter value to be $0") + async expectCounterValue(currency: string) { + expect(this.counterValueSelector).toHaveText(currency); + } + async changeTheme() { await this.themeSelector.click(); // TODO: make this dynamic await this.themeChoiceLight.click(); diff --git a/apps/ledger-live-desktop/tests/page/speculos.page.ts b/apps/ledger-live-desktop/tests/page/speculos.page.ts index 65d3df1455e9..109b7d2c959d 100644 --- a/apps/ledger-live-desktop/tests/page/speculos.page.ts +++ b/apps/ledger-live-desktop/tests/page/speculos.page.ts @@ -28,7 +28,7 @@ import { delegateCosmos, sendCosmos } from "tests/families/cosmos"; import { delegateSolana, sendSolana } from "tests/families/solana"; export class SpeculosPage extends AppPage { @step("Verify receive address correctness on device") - async expectValidAddressDevice(account: Account) { + async expectValidAddressDevice(account: Account, addressDisplayed: string) { let deviceLabels: string[]; switch (account.currency) { @@ -46,7 +46,7 @@ export class SpeculosPage extends AppPage { await waitFor(deviceLabels[0]); const events = await pressUntilTextFound(deviceLabels[1]); - const isAddressCorrect = containsSubstringInEvent(account.address, events); + const isAddressCorrect = containsSubstringInEvent(addressDisplayed, events); expect(isAddressCorrect).toBeTruthy(); await pressBoth(); } diff --git a/apps/ledger-live-desktop/tests/specs/general/userParametersChange.spec.ts b/apps/ledger-live-desktop/tests/specs/general/userParametersChange.spec.ts index 7e6df76b514d..670c49b45425 100644 --- a/apps/ledger-live-desktop/tests/specs/general/userParametersChange.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/general/userParametersChange.spec.ts @@ -11,8 +11,8 @@ test("User able to update currency/language/theme in settings", async ({ page }) await test.step("user change currency", async () => { await layout.goToSettings(); - await settingsPage.changeCounterValue(); - await expect.soft(settingsPage.counterValueSelector).toHaveText("Euro - EUR"); + await settingsPage.changeCounterValue("euro"); + await settingsPage.expectCounterValue("Euro - EUR"); }); await test.step("user change language", async () => { diff --git a/apps/ledger-live-desktop/tests/specs/speculos/add.account.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/add.account.spec.ts index 187dc09ebfe7..5e5b002ad819 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/add.account.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/add.account.spec.ts @@ -46,10 +46,7 @@ for (const currency of currencies) { await app.addAccount.addAccounts(); await app.addAccount.done(); - // Todo: Remove 'if' when CounterValue is fixed for $TON - LIVE-13685 - if (currency.currency.name !== Currency.TON.name) { - await app.layout.expectBalanceVisibility(); - } + await app.layout.expectBalanceVisibility(); await app.portfolio.checkOperationHistory(); await app.layout.goToAccounts(); await app.accounts.navigateToAccountByName(firstAccountName); diff --git a/apps/ledger-live-desktop/tests/specs/speculos/delegate.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/delegate.spec.ts index 58034272350e..77ecf213f7c5 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/delegate.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/delegate.spec.ts @@ -50,8 +50,8 @@ const validators = [ test.describe("Delegate flows", () => { test.beforeAll(async () => { - process.env.ENABLE_TRANSACTION_BROADCAST = - new Date().getDay() === 1 && isRunningInScheduledWorkflow() ? "1" : "0"; + process.env.DISABLE_TRANSACTION_BROADCAST = + new Date().getDay() === 1 && isRunningInScheduledWorkflow() ? "0" : "1"; }); for (const account of e2eDelegationAccounts) { test.describe("Delegate", () => { diff --git a/apps/ledger-live-desktop/tests/specs/speculos/receive.address.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/receive.address.spec.ts index 6bb844f48edb..818ae768b4f2 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/receive.address.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/receive.address.spec.ts @@ -66,9 +66,10 @@ for (const account of accounts) { break; } await app.modal.continue(); - await app.receive.expectValidReceiveAddress(account.account.address); + const displayedAddress = await app.receive.getAddressDisplayed(); + await app.receive.expectValidReceiveAddress(displayedAddress); - await app.speculos.expectValidAddressDevice(account.account); + await app.speculos.expectValidAddressDevice(account.account, displayedAddress); await app.receive.expectApproveLabel(); }, ); diff --git a/apps/ledger-live-desktop/tests/specs/speculos/send.tx.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/send.tx.spec.ts index 829106f0d379..46541103cc22 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/send.tx.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/send.tx.spec.ts @@ -21,7 +21,7 @@ const transactionsAmountInvalid = [ xrayTicket: "B2CQA-2569", }, { - transaction: new Transaction(Account.XRP_1, Account.XRP_3, "1"), + transaction: new Transaction(Account.XRP_1, Account.XRP_3, "1", undefined, "noTag"), expectedErrorMessage: "Recipient address is inactive. Send at least 10 XRP to activate it", xrayTicket: "B2CQA-2571", }, @@ -213,8 +213,8 @@ const tokenTransactionInvalid = [ test.describe("Send flows", () => { test.beforeAll(async () => { - process.env.ENABLE_TRANSACTION_BROADCAST = - new Date().getDay() === 1 && isRunningInScheduledWorkflow() ? "1" : "0"; + process.env.DISABLE_TRANSACTION_BROADCAST = + new Date().getDay() === 1 && isRunningInScheduledWorkflow() ? "0" : "1"; }); //Warning 🚨: Test may fail due to the GetAppAndVersion issue - Jira: LIVE-12581 or insufficient funds @@ -263,6 +263,7 @@ test.describe("Send flows", () => { await app.account.clickSend(); await app.send.craftTx(transaction.transaction); + await app.send.countinueSendAmount(); await app.send.expectTxInfoValidity(transaction.transaction); await app.send.clickContinueToDevice(); @@ -455,11 +456,9 @@ test.describe("Send flows", () => { await app.accounts.navigateToAccountByName( transaction.transaction.accountToDebit.accountName, ); - await app.account.clickSend(); - await app.send.fillRecipient(transaction.transaction.accountToCredit.address); - await app.send.clickContinue(); - await app.send.fillAmount(transaction.transaction.amount); + + await app.send.craftTx(transaction.transaction); await app.send.checkContinueButtonDisabled(); await app.layout.checkErrorMessage(transaction.expectedErrorMessage); }, @@ -602,7 +601,7 @@ test.describe("Send flows", () => { } test.describe("send NFT to ENS address", () => { - const transaction = new NFTTransaction(Account.ETH_1, Account.ETH_MC, "NY la muse", Fee.SLOW); + const transaction = new NFTTransaction(Account.ETH_1, Account.ETH_MC, "Podium", Fee.SLOW); test.beforeAll(async () => { process.env.DISABLE_TRANSACTION_BROADCAST = "true"; }); @@ -647,6 +646,8 @@ test.describe("Send flows", () => { await app.send.expectTxSent(); await app.account.navigateToViewDetails(); await app.drawer.close(); + await app.layout.goToAccounts(); + await app.accounts.navigateToAccountByName(transaction.accountToDebit.accountName); await app.account.navigateToNFTOperation(); await app.sendDrawer.expectNftInfos(transaction); }, diff --git a/apps/ledger-live-desktop/tests/specs/speculos/settings.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/settings.spec.ts index 0551ea979b63..be183cc26793 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/settings.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/settings.spec.ts @@ -83,3 +83,45 @@ test.describe("Password", () => { }, ); }); + +test.describe("counter value selection", () => { + const account = Account.BTC_NATIVE_SEGWIT_1; + test.use({ + userdata: "skip-onboarding", + cliCommands: [ + { + command: commandCLI.liveData, + args: { + currency: account.currency.currencyId, + index: account.index, + appjson: "", + add: true, + }, + }, + ], + speculosApp: account.currency.speculosApp, + }); + + test( + "User can select a counter value to display amount", + { + annotation: { + type: "TMS", + description: "B2CQA-804", + }, + }, + async ({ app }) => { + await addTmsLink(getDescription(test.info().annotations).split(", ")); + await app.layout.goToSettings(); + await app.settings.changeCounterValue("euro"); + await app.settings.expectCounterValue("Euro - EUR"); + await app.layout.goToPortfolio(); + + await app.layout.waitForAccountsSyncToBeDone(); + await app.portfolio.expectTotalBalanceCounterValue("€"); + await app.portfolio.expectBalanceDiffCounterValue("€"); + await app.portfolio.expectAssetRowCounterValue(account.currency.name, "€"); + await app.portfolio.expectOperationCounterValue("€"); + }, + ); +}); diff --git a/apps/ledger-live-desktop/tests/specs/speculos/subAccount.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/subAccount.spec.ts index 329b8bee73c3..13289d392c6d 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/subAccount.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/subAccount.spec.ts @@ -84,9 +84,11 @@ for (const token of subAccountReceive) { await app.receive.selectToken(token.account); await app.modal.continue(); - await app.receive.expectValidReceiveAddress(token.account.address); - await app.speculos.expectValidAddressDevice(token.account); + const displayedAddress = await app.receive.getAddressDisplayed(); + await app.receive.expectValidReceiveAddress(displayedAddress); + + await app.speculos.expectValidAddressDevice(token.account, displayedAddress); await app.receive.expectApproveLabel(); }, ); diff --git a/apps/ledger-live-desktop/tests/specs/speculos/swap.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/swap.spec.ts index 2435553764d3..fd8e9e00b2b7 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/swap.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/swap.spec.ts @@ -186,7 +186,7 @@ for (const { swap, xrayTicket } of swaps) { test.beforeAll(async () => { process.env.SWAP_DISABLE_APPS_INSTALL = "true"; process.env.SWAP_API_BASE = "https://swap-stg.ledger-test.com/v5"; - process.env.DISABLE_TRANSACTION_BROADCAST = "true"; + process.env.DISABLE_TRANSACTION_BROADCAST = "1"; }); const accPair: string[] = [swap.accountToDebit, swap.accountToCredit].map(acc => diff --git a/apps/ledger-live-mobile/.eslintrc.js b/apps/ledger-live-mobile/.eslintrc.js index f7e157b37882..4e5c079471f0 100644 --- a/apps/ledger-live-mobile/.eslintrc.js +++ b/apps/ledger-live-mobile/.eslintrc.js @@ -76,7 +76,12 @@ module.exports = { "react/jsx-key": "warn", // TODO: delete to make it an error when we are ready "react/prop-types": "off", "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks - "react-hooks/exhaustive-deps": "error", // Checks effect dependencies + "react-hooks/exhaustive-deps": [ + "error", // Checks effect dependencies + { + additionalHooks: "useInViewContext", + }, + ], "jsx-a11y/no-autofocus": "off", "jsx-a11y/anchor-is-valid": [ "error", diff --git a/apps/ledger-live-mobile/CHANGELOG.md b/apps/ledger-live-mobile/CHANGELOG.md index 6b321d6f1804..08d125929cb1 100644 --- a/apps/ledger-live-mobile/CHANGELOG.md +++ b/apps/ledger-live-mobile/CHANGELOG.md @@ -1,5 +1,209 @@ # live-mobile +## 3.59.0 + +### Minor Changes + +- [#8552](https://github.com/LedgerHQ/ledger-live/pull/8552) [`0d7115c`](https://github.com/LedgerHQ/ledger-live/commit/0d7115c47317a28a53af1f6ae6b96947b9525c66) Thanks [@LucasWerey](https://github.com/LucasWerey)! - Rework reborn analytics + +- [#8466](https://github.com/LedgerHQ/ledger-live/pull/8466) [`5f7a799`](https://github.com/LedgerHQ/ledger-live/commit/5f7a7995e0ca2fa2d0c1203eda025bc9ae89150d) Thanks [@cgrellard-ledger](https://github.com/cgrellard-ledger)! - LLM - Ledger Sync improve error message when deleting backup on multiple instances at the same time + +- [#8495](https://github.com/LedgerHQ/ledger-live/pull/8495) [`f0a34a0`](https://github.com/LedgerHQ/ledger-live/commit/f0a34a06461331ec44fa02b8093699fa001f94a0) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Rework Hiddencollections + +- [#8635](https://github.com/LedgerHQ/ledger-live/pull/8635) [`177265d`](https://github.com/LedgerHQ/ledger-live/commit/177265de63038fa03b0cdc618c8cde0311c9cadd) Thanks [@thesan](https://github.com/thesan)! - Debounce memo tag changes + +- [#8464](https://github.com/LedgerHQ/ledger-live/pull/8464) [`8cc1438`](https://github.com/LedgerHQ/ledger-live/commit/8cc143873a40999578339ee56c375a60c2a3ff1e) Thanks [@LucasWerey](https://github.com/LucasWerey)! - Update entry points to reborn LP on read only mode + +- [#8532](https://github.com/LedgerHQ/ledger-live/pull/8532) [`f816c89`](https://github.com/LedgerHQ/ledger-live/commit/f816c89b0ca5885db94ebc994c855c28c37cad5b) Thanks [@ofreyssinet-ledger](https://github.com/ofreyssinet-ledger)! - Avoid triggering post onboarding for "Access your wallet" onboarding flow + +- [#8538](https://github.com/LedgerHQ/ledger-live/pull/8538) [`f6eefe9`](https://github.com/LedgerHQ/ledger-live/commit/f6eefe9f56c3eb5eb150a61b93d15d94bac1147a) Thanks [@sergiubreban](https://github.com/sergiubreban)! - enable /card deeplink + +- [#8377](https://github.com/LedgerHQ/ledger-live/pull/8377) [`e381081`](https://github.com/LedgerHQ/ledger-live/commit/e381081aa94d629ca1bee0802b0c95676aee7bdc) Thanks [@themooneer](https://github.com/themooneer)! - Prepare add account v2 reusable screens + +- [#8375](https://github.com/LedgerHQ/ledger-live/pull/8375) [`c45ee45`](https://github.com/LedgerHQ/ledger-live/commit/c45ee457a9f5500ae42f2a8fb7f0cfb7926f319b) Thanks [@Canestin](https://github.com/Canestin)! - add mev protection + +- [#8479](https://github.com/LedgerHQ/ledger-live/pull/8479) [`ea5c60c`](https://github.com/LedgerHQ/ledger-live/commit/ea5c60cb3a3c4727acafb4021224385dce2bc296) Thanks [@cgrellard-ledger](https://github.com/cgrellard-ledger)! - LLM - Ledger Sync improved error message when a removed member tries to remove another member + +- [#8509](https://github.com/LedgerHQ/ledger-live/pull/8509) [`9894ecc`](https://github.com/LedgerHQ/ledger-live/commit/9894eccddca137b46a3cfec63f29df2bebdeea0b) Thanks [@LucasWerey](https://github.com/LucasWerey)! - Fix layout issue on my ledger screen + +- [#8639](https://github.com/LedgerHQ/ledger-live/pull/8639) [`8851e59`](https://github.com/LedgerHQ/ledger-live/commit/8851e5980591854a1a1151f7f8e73d1c375be0c2) Thanks [@thesan](https://github.com/thesan)! - Fix the memo/tag drawer copy + +- [#8576](https://github.com/LedgerHQ/ledger-live/pull/8576) [`64ed0a4`](https://github.com/LedgerHQ/ledger-live/commit/64ed0a41e451a10b68ccfef2a4d8800c9adb68d3) Thanks [@thesan](https://github.com/thesan)! - Log content card impression when 50% of the card is shown + +- [#8318](https://github.com/LedgerHQ/ledger-live/pull/8318) [`208d94a`](https://github.com/LedgerHQ/ledger-live/commit/208d94acefccf97cc970e0efb8c9040d24bbd436) Thanks [@LucasWerey](https://github.com/LucasWerey)! - Polish of braze CC for LLM + support video and gif + +- [#8389](https://github.com/LedgerHQ/ledger-live/pull/8389) [`995b771`](https://github.com/LedgerHQ/ledger-live/commit/995b771671b23931c6a85534841e8d88ca2acaf4) Thanks [@sergiubreban](https://github.com/sergiubreban)! - add exchange dev mode setting + +- [#8514](https://github.com/LedgerHQ/ledger-live/pull/8514) [`b8b9f76`](https://github.com/LedgerHQ/ledger-live/commit/b8b9f767deea088ebf5cb7d976a1204f6c0d316f) Thanks [@ComradeAERGO](https://github.com/ComradeAERGO)! - Removed message fields for sign message modal for ACRE Withdrawals + +- [#8606](https://github.com/LedgerHQ/ledger-live/pull/8606) [`ffc2445`](https://github.com/LedgerHQ/ledger-live/commit/ffc2445bb2d90d59abde08c96bfa97ea2d36e9a4) Thanks [@LucasWerey](https://github.com/LucasWerey)! - Fix margin issue + +- [#8625](https://github.com/LedgerHQ/ledger-live/pull/8625) [`70ee295`](https://github.com/LedgerHQ/ledger-live/commit/70ee2959c9cbd750be7cc7ebfff0d3e5a64a205f) Thanks [@thesan](https://github.com/thesan)! - Truncate Cardano memos in the input to prevent the transaction validation errors + +- [#8624](https://github.com/LedgerHQ/ledger-live/pull/8624) [`16a4794`](https://github.com/LedgerHQ/ledger-live/commit/16a479420976c4c12fb8984dcba9cf572c576292) Thanks [@thesan](https://github.com/thesan)! - Truncate Stacks memos in the input to prevent the transaction validation from failing + +- [#8503](https://github.com/LedgerHQ/ledger-live/pull/8503) [`322fd58`](https://github.com/LedgerHQ/ledger-live/commit/322fd58ffcde6d592eb27af1fd93f8c45d33205c) Thanks [@jiyuzhuang](https://github.com/jiyuzhuang)! - Remove `feature_recover_upsell_redirection` feature flag and unused components + +- [#8477](https://github.com/LedgerHQ/ledger-live/pull/8477) [`306dec6`](https://github.com/LedgerHQ/ledger-live/commit/306dec68321ab4214287618cb7903a1ae37a54b2) Thanks [@cgrellard-ledger](https://github.com/cgrellard-ledger)! - LLM - Ledger Sync improved error message when an unauthorized member tries to delete a backup + +- [#8404](https://github.com/LedgerHQ/ledger-live/pull/8404) [`2901938`](https://github.com/LedgerHQ/ledger-live/commit/29019387955bbab5bc0adcd550bc9e32d08b4f72) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Fix undefined join on Spam filter + +- [#8601](https://github.com/LedgerHQ/ledger-live/pull/8601) [`61aedb7`](https://github.com/LedgerHQ/ledger-live/commit/61aedb7bbd45e73d6bc2b53e55f562262d5c5fa7) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Revery useNFTCOllections + +- [#8657](https://github.com/LedgerHQ/ledger-live/pull/8657) [`31764d0`](https://github.com/LedgerHQ/ledger-live/commit/31764d013c334b876af6bb46ac5e13b651465b4e) Thanks [@thesan](https://github.com/thesan)! - Prevent debounce from causing the memo tag not being saved + +### Patch Changes + +- Updated dependencies [[`f0a34a0`](https://github.com/LedgerHQ/ledger-live/commit/f0a34a06461331ec44fa02b8093699fa001f94a0), [`93f8f78`](https://github.com/LedgerHQ/ledger-live/commit/93f8f7885d1300208310599e743a4d1fae4ec2a4), [`40f1cd4`](https://github.com/LedgerHQ/ledger-live/commit/40f1cd4c22d17480dcf86c73e90a07866667b0ba), [`c45ee45`](https://github.com/LedgerHQ/ledger-live/commit/c45ee457a9f5500ae42f2a8fb7f0cfb7926f319b), [`995b771`](https://github.com/LedgerHQ/ledger-live/commit/995b771671b23931c6a85534841e8d88ca2acaf4), [`475b74c`](https://github.com/LedgerHQ/ledger-live/commit/475b74c1ba01b7e7a374cca14e274769a3c17476), [`d45e871`](https://github.com/LedgerHQ/ledger-live/commit/d45e871ee6b7e98102a4ffbdf3d7581c8cf838d0), [`faef7ed`](https://github.com/LedgerHQ/ledger-live/commit/faef7ed3b9954d2bbaf5c5a518e247fd441a73e7), [`16a4794`](https://github.com/LedgerHQ/ledger-live/commit/16a479420976c4c12fb8984dcba9cf572c576292), [`322fd58`](https://github.com/LedgerHQ/ledger-live/commit/322fd58ffcde6d592eb27af1fd93f8c45d33205c), [`2673c1d`](https://github.com/LedgerHQ/ledger-live/commit/2673c1d98788fafe7e95bd798be06a6b5e39e1c0), [`2901938`](https://github.com/LedgerHQ/ledger-live/commit/29019387955bbab5bc0adcd550bc9e32d08b4f72), [`ea3a175`](https://github.com/LedgerHQ/ledger-live/commit/ea3a17562ab1954b14803ff19ab575e4fcfc64c8), [`61aedb7`](https://github.com/LedgerHQ/ledger-live/commit/61aedb7bbd45e73d6bc2b53e55f562262d5c5fa7), [`224cc07`](https://github.com/LedgerHQ/ledger-live/commit/224cc07b86e8c5a6167ff77cfb99e42a1057813e), [`58beb75`](https://github.com/LedgerHQ/ledger-live/commit/58beb7504454b64cb5a955926ef27f811397aa6d)]: + - @ledgerhq/live-nft-react@0.5.0 + - @ledgerhq/live-nft@0.5.0 + - @ledgerhq/live-common@34.16.0 + - @ledgerhq/types-live@6.55.0 + - @ledgerhq/coin-evm@2.7.0 + - @ledgerhq/coin-stacks@0.3.0 + - @ledgerhq/coin-cosmos@0.3.0 + - @ledgerhq/coin-framework@0.20.1 + - @ledgerhq/coin-elrond@0.1.10 + - @ledgerhq/coin-filecoin@1.3.5 + - @ledgerhq/domain-service@1.2.14 + - @ledgerhq/live-countervalues@0.2.15 + - @ledgerhq/live-countervalues-react@0.2.15 + - @ledgerhq/live-wallet@0.7.7 + +## 3.59.0-next.9 + +### Minor Changes + +- [#8657](https://github.com/LedgerHQ/ledger-live/pull/8657) [`31764d0`](https://github.com/LedgerHQ/ledger-live/commit/31764d013c334b876af6bb46ac5e13b651465b4e) Thanks [@thesan](https://github.com/thesan)! - Prevent debounce from causing the memo tag not being saved + +## 3.59.0-next.8 + +### Minor Changes + +- [#8639](https://github.com/LedgerHQ/ledger-live/pull/8639) [`8851e59`](https://github.com/LedgerHQ/ledger-live/commit/8851e5980591854a1a1151f7f8e73d1c375be0c2) Thanks [@thesan](https://github.com/thesan)! - Fix the memo/tag drawer copy + +## 3.59.0-next.7 + +### Minor Changes + +- [#8625](https://github.com/LedgerHQ/ledger-live/pull/8625) [`70ee295`](https://github.com/LedgerHQ/ledger-live/commit/70ee2959c9cbd750be7cc7ebfff0d3e5a64a205f) Thanks [@thesan](https://github.com/thesan)! - Truncate Cardano memos in the input to prevent the transaction validation errors + +## 3.59.0-next.6 + +### Minor Changes + +- [#8635](https://github.com/LedgerHQ/ledger-live/pull/8635) [`177265d`](https://github.com/LedgerHQ/ledger-live/commit/177265de63038fa03b0cdc618c8cde0311c9cadd) Thanks [@thesan](https://github.com/thesan)! - Debounce memo tag changes + +## 3.59.0-next.5 + +### Minor Changes + +- [#8624](https://github.com/LedgerHQ/ledger-live/pull/8624) [`16a4794`](https://github.com/LedgerHQ/ledger-live/commit/16a479420976c4c12fb8984dcba9cf572c576292) Thanks [@thesan](https://github.com/thesan)! - Truncate Stacks memos in the input to prevent the transaction validation from failing + +### Patch Changes + +- Updated dependencies [[`16a4794`](https://github.com/LedgerHQ/ledger-live/commit/16a479420976c4c12fb8984dcba9cf572c576292)]: + - @ledgerhq/coin-stacks@0.3.0-next.2 + - @ledgerhq/live-common@34.16.0-next.3 + +## 3.59.0-next.4 + +### Minor Changes + +- [#8606](https://github.com/LedgerHQ/ledger-live/pull/8606) [`ffc2445`](https://github.com/LedgerHQ/ledger-live/commit/ffc2445bb2d90d59abde08c96bfa97ea2d36e9a4) Thanks [@LucasWerey](https://github.com/LucasWerey)! - Fix margin issue + +## 3.59.0-next.3 + +### Minor Changes + +- [#8601](https://github.com/LedgerHQ/ledger-live/pull/8601) [`61aedb7`](https://github.com/LedgerHQ/ledger-live/commit/61aedb7bbd45e73d6bc2b53e55f562262d5c5fa7) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Revery useNFTCOllections + +### Patch Changes + +- Updated dependencies [[`61aedb7`](https://github.com/LedgerHQ/ledger-live/commit/61aedb7bbd45e73d6bc2b53e55f562262d5c5fa7)]: + - @ledgerhq/types-live@6.55.0-next.1 + - @ledgerhq/live-common@34.16.0-next.2 + - @ledgerhq/live-nft-react@0.5.0-next.1 + - @ledgerhq/coin-framework@0.20.1-next.1 + - @ledgerhq/coin-cosmos@0.3.0-next.2 + - @ledgerhq/coin-elrond@0.1.10-next.1 + - @ledgerhq/coin-evm@2.7.0-next.1 + - @ledgerhq/coin-filecoin@1.3.5-next.1 + - @ledgerhq/coin-stacks@0.2.1-next.1 + - @ledgerhq/domain-service@1.2.14-next.1 + - @ledgerhq/live-countervalues@0.2.15-next.1 + - @ledgerhq/live-countervalues-react@0.2.15-next.1 + - @ledgerhq/live-nft@0.5.0-next.1 + - @ledgerhq/live-wallet@0.7.7-next.1 + +## 3.59.0-next.2 + +### Minor Changes + +- [#8576](https://github.com/LedgerHQ/ledger-live/pull/8576) [`64ed0a4`](https://github.com/LedgerHQ/ledger-live/commit/64ed0a41e451a10b68ccfef2a4d8800c9adb68d3) Thanks [@thesan](https://github.com/thesan)! - Log content card impression when 50% of the card is shown + +## 3.59.0-next.1 + +### Patch Changes + +- Updated dependencies [[`ea3a175`](https://github.com/LedgerHQ/ledger-live/commit/ea3a17562ab1954b14803ff19ab575e4fcfc64c8)]: + - @ledgerhq/coin-cosmos@0.3.0-next.1 + - @ledgerhq/live-common@34.16.0-next.1 + +## 3.59.0-next.0 + +### Minor Changes + +- [#8552](https://github.com/LedgerHQ/ledger-live/pull/8552) [`0d7115c`](https://github.com/LedgerHQ/ledger-live/commit/0d7115c47317a28a53af1f6ae6b96947b9525c66) Thanks [@LucasWerey](https://github.com/LucasWerey)! - Rework reborn analytics + +- [#8466](https://github.com/LedgerHQ/ledger-live/pull/8466) [`5f7a799`](https://github.com/LedgerHQ/ledger-live/commit/5f7a7995e0ca2fa2d0c1203eda025bc9ae89150d) Thanks [@cgrellard-ledger](https://github.com/cgrellard-ledger)! - LLM - Ledger Sync improve error message when deleting backup on multiple instances at the same time + +- [#8495](https://github.com/LedgerHQ/ledger-live/pull/8495) [`f0a34a0`](https://github.com/LedgerHQ/ledger-live/commit/f0a34a06461331ec44fa02b8093699fa001f94a0) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Rework Hiddencollections + +- [#8464](https://github.com/LedgerHQ/ledger-live/pull/8464) [`8cc1438`](https://github.com/LedgerHQ/ledger-live/commit/8cc143873a40999578339ee56c375a60c2a3ff1e) Thanks [@LucasWerey](https://github.com/LucasWerey)! - Update entry points to reborn LP on read only mode + +- [#8532](https://github.com/LedgerHQ/ledger-live/pull/8532) [`f816c89`](https://github.com/LedgerHQ/ledger-live/commit/f816c89b0ca5885db94ebc994c855c28c37cad5b) Thanks [@ofreyssinet-ledger](https://github.com/ofreyssinet-ledger)! - Avoid triggering post onboarding for "Access your wallet" onboarding flow + +- [#8538](https://github.com/LedgerHQ/ledger-live/pull/8538) [`f6eefe9`](https://github.com/LedgerHQ/ledger-live/commit/f6eefe9f56c3eb5eb150a61b93d15d94bac1147a) Thanks [@sergiubreban](https://github.com/sergiubreban)! - enable /card deeplink + +- [#8377](https://github.com/LedgerHQ/ledger-live/pull/8377) [`e381081`](https://github.com/LedgerHQ/ledger-live/commit/e381081aa94d629ca1bee0802b0c95676aee7bdc) Thanks [@themooneer](https://github.com/themooneer)! - Prepare add account v2 reusable screens + +- [#8375](https://github.com/LedgerHQ/ledger-live/pull/8375) [`c45ee45`](https://github.com/LedgerHQ/ledger-live/commit/c45ee457a9f5500ae42f2a8fb7f0cfb7926f319b) Thanks [@Canestin](https://github.com/Canestin)! - add mev protection + +- [#8479](https://github.com/LedgerHQ/ledger-live/pull/8479) [`ea5c60c`](https://github.com/LedgerHQ/ledger-live/commit/ea5c60cb3a3c4727acafb4021224385dce2bc296) Thanks [@cgrellard-ledger](https://github.com/cgrellard-ledger)! - LLM - Ledger Sync improved error message when a removed member tries to remove another member + +- [#8509](https://github.com/LedgerHQ/ledger-live/pull/8509) [`9894ecc`](https://github.com/LedgerHQ/ledger-live/commit/9894eccddca137b46a3cfec63f29df2bebdeea0b) Thanks [@LucasWerey](https://github.com/LucasWerey)! - Fix layout issue on my ledger screen + +- [#8318](https://github.com/LedgerHQ/ledger-live/pull/8318) [`208d94a`](https://github.com/LedgerHQ/ledger-live/commit/208d94acefccf97cc970e0efb8c9040d24bbd436) Thanks [@LucasWerey](https://github.com/LucasWerey)! - Polish of braze CC for LLM + support video and gif + +- [#8389](https://github.com/LedgerHQ/ledger-live/pull/8389) [`995b771`](https://github.com/LedgerHQ/ledger-live/commit/995b771671b23931c6a85534841e8d88ca2acaf4) Thanks [@sergiubreban](https://github.com/sergiubreban)! - add exchange dev mode setting + +- [#8514](https://github.com/LedgerHQ/ledger-live/pull/8514) [`b8b9f76`](https://github.com/LedgerHQ/ledger-live/commit/b8b9f767deea088ebf5cb7d976a1204f6c0d316f) Thanks [@ComradeAERGO](https://github.com/ComradeAERGO)! - Removed message fields for sign message modal for ACRE Withdrawals + +- [#8503](https://github.com/LedgerHQ/ledger-live/pull/8503) [`322fd58`](https://github.com/LedgerHQ/ledger-live/commit/322fd58ffcde6d592eb27af1fd93f8c45d33205c) Thanks [@jiyuzhuang](https://github.com/jiyuzhuang)! - Remove `feature_recover_upsell_redirection` feature flag and unused components + +- [#8477](https://github.com/LedgerHQ/ledger-live/pull/8477) [`306dec6`](https://github.com/LedgerHQ/ledger-live/commit/306dec68321ab4214287618cb7903a1ae37a54b2) Thanks [@cgrellard-ledger](https://github.com/cgrellard-ledger)! - LLM - Ledger Sync improved error message when an unauthorized member tries to delete a backup + +- [#8404](https://github.com/LedgerHQ/ledger-live/pull/8404) [`2901938`](https://github.com/LedgerHQ/ledger-live/commit/29019387955bbab5bc0adcd550bc9e32d08b4f72) Thanks [@mcayuelas-ledger](https://github.com/mcayuelas-ledger)! - Fix undefined join on Spam filter + +### Patch Changes + +- Updated dependencies [[`f0a34a0`](https://github.com/LedgerHQ/ledger-live/commit/f0a34a06461331ec44fa02b8093699fa001f94a0), [`93f8f78`](https://github.com/LedgerHQ/ledger-live/commit/93f8f7885d1300208310599e743a4d1fae4ec2a4), [`40f1cd4`](https://github.com/LedgerHQ/ledger-live/commit/40f1cd4c22d17480dcf86c73e90a07866667b0ba), [`c45ee45`](https://github.com/LedgerHQ/ledger-live/commit/c45ee457a9f5500ae42f2a8fb7f0cfb7926f319b), [`995b771`](https://github.com/LedgerHQ/ledger-live/commit/995b771671b23931c6a85534841e8d88ca2acaf4), [`475b74c`](https://github.com/LedgerHQ/ledger-live/commit/475b74c1ba01b7e7a374cca14e274769a3c17476), [`d45e871`](https://github.com/LedgerHQ/ledger-live/commit/d45e871ee6b7e98102a4ffbdf3d7581c8cf838d0), [`faef7ed`](https://github.com/LedgerHQ/ledger-live/commit/faef7ed3b9954d2bbaf5c5a518e247fd441a73e7), [`322fd58`](https://github.com/LedgerHQ/ledger-live/commit/322fd58ffcde6d592eb27af1fd93f8c45d33205c), [`2673c1d`](https://github.com/LedgerHQ/ledger-live/commit/2673c1d98788fafe7e95bd798be06a6b5e39e1c0), [`2901938`](https://github.com/LedgerHQ/ledger-live/commit/29019387955bbab5bc0adcd550bc9e32d08b4f72), [`224cc07`](https://github.com/LedgerHQ/ledger-live/commit/224cc07b86e8c5a6167ff77cfb99e42a1057813e), [`58beb75`](https://github.com/LedgerHQ/ledger-live/commit/58beb7504454b64cb5a955926ef27f811397aa6d)]: + - @ledgerhq/live-nft-react@0.5.0-next.0 + - @ledgerhq/live-nft@0.5.0-next.0 + - @ledgerhq/live-common@34.16.0-next.0 + - @ledgerhq/types-live@6.55.0-next.0 + - @ledgerhq/coin-evm@2.7.0-next.0 + - @ledgerhq/coin-framework@0.20.1-next.0 + - @ledgerhq/coin-cosmos@0.2.3-next.0 + - @ledgerhq/coin-elrond@0.1.10-next.0 + - @ledgerhq/coin-filecoin@1.3.5-next.0 + - @ledgerhq/coin-stacks@0.2.1-next.0 + - @ledgerhq/domain-service@1.2.14-next.0 + - @ledgerhq/live-countervalues@0.2.15-next.0 + - @ledgerhq/live-countervalues-react@0.2.15-next.0 + - @ledgerhq/live-wallet@0.7.7-next.0 + ## 3.58.0 ### Minor Changes diff --git a/apps/ledger-live-mobile/e2e/page/common.page.ts b/apps/ledger-live-mobile/e2e/page/common.page.ts index 89ef37a2710c..2c3a9419b07f 100644 --- a/apps/ledger-live-mobile/e2e/page/common.page.ts +++ b/apps/ledger-live-mobile/e2e/page/common.page.ts @@ -75,9 +75,8 @@ export default class CommonPage { await new DeviceAction(nano).accessManager(); } - async addSpeculos(nanoApp: string) { + async addSpeculos(nanoApp: string, speculosAddress = "localhost") { const proxyPort = await bridge.findFreePort(); - const speculosAddress = "localhost"; const speculosPort = await launchSpeculos(nanoApp, proxyPort); await launchProxy(proxyPort, speculosAddress, speculosPort); await bridge.addKnownSpeculos(`${proxyAddress}:${proxyPort}`); diff --git a/apps/ledger-live-mobile/e2e/page/index.ts b/apps/ledger-live-mobile/e2e/page/index.ts index a7a71163ac23..a65493cfa87d 100644 --- a/apps/ledger-live-mobile/e2e/page/index.ts +++ b/apps/ledger-live-mobile/e2e/page/index.ts @@ -29,15 +29,26 @@ import type { Account } from "@ledgerhq/types-live"; import { DeviceLike } from "~/reducers/types"; import { loadAccounts, loadBleState, loadConfig } from "../bridge/server"; import { AppInfos } from "@ledgerhq/live-common/e2e/enum/AppInfos"; +import { lastValueFrom, Observable } from "rxjs"; +import path from "path"; +import fs from "fs"; +import { getEnv } from "@ledgerhq/live-env"; type ApplicationOptions = { speculosApp?: AppInfos; + cliCommands?: (() => Observable | Promise | string)[]; userdata?: string; knownDevices?: DeviceLike[]; testAccounts?: Account[]; }; +export const getUserdataPath = (userdata: string) => { + return path.resolve("e2e", "userdata", `${userdata}.json`); +}; + export class Application { + public userdataSpeculos: string | undefined = undefined; + public userdataPath: string | undefined = undefined; public account = new AccountPage(); public accounts = new AccountsPage(); public addAccount = new AddAccountDrawer(); @@ -65,13 +76,46 @@ export class Application { public transfertMenu = new TransfertMenuDrawer(); public walletTabNavigator = new WalletTabNavigatorPage(); - static async init({ speculosApp, userdata, knownDevices, testAccounts }: ApplicationOptions) { - const app = new Application(); - userdata && (await loadConfig(userdata, true)); + constructor() { + if (!getEnv("MOCK")) { + // Create a temporary userdata file for Speculos tests + const originalUserdata = "onboardingcompleted"; + this.userdataSpeculos = `temp-userdata-${Date.now()}`; + this.userdataPath = getUserdataPath(this.userdataSpeculos); + const originalFilePath = getUserdataPath(originalUserdata); + fs.copyFileSync(originalFilePath, this.userdataPath); + } + } + + async init({ + speculosApp, + cliCommands, + userdata, + knownDevices, + testAccounts, + }: ApplicationOptions) { + let proxyPort = 0; + if (speculosApp) { + proxyPort = await this.common.addSpeculos(speculosApp.name); + process.env.DEVICE_PROXY_URL = `ws://localhost:${proxyPort}`; + require("@ledgerhq/live-cli/src/live-common-setup"); + } + + if (cliCommands?.length) { + for (const cmd of cliCommands) { + const promise = await cmd(); + const result = promise instanceof Observable ? await lastValueFrom(promise) : await promise; + // eslint-disable-next-line no-console + console.log("CLI result: ", result); + } + } + + if (this.userdataSpeculos) await loadConfig(this.userdataSpeculos, true); + else userdata && (await loadConfig(userdata, true)); knownDevices && (await loadBleState({ knownDevices })); testAccounts && (await loadAccounts(testAccounts)); - speculosApp && (await app.common.addSpeculos(speculosApp.name)); - return app; + const userdataSpeculosPath = getUserdataPath(this.userdataSpeculos!); + if (fs.existsSync(userdataSpeculosPath)) fs.unlinkSync(userdataSpeculosPath); } } diff --git a/apps/ledger-live-mobile/e2e/setup.ts b/apps/ledger-live-mobile/e2e/setup.ts index 92575443871a..dd9513e3e02a 100644 --- a/apps/ledger-live-mobile/e2e/setup.ts +++ b/apps/ledger-live-mobile/e2e/setup.ts @@ -11,7 +11,14 @@ import { setEnv } from "@ledgerhq/live-env"; const currentDate = new Date(); const date = format(currentDate, "MM-dd"); const directoryPath = `artifacts/${date}_LLM`; -setEnv("MOCK", process.env.MOCK == "0" ? "" : "1"); + +if (process.env.MOCK == "0") { + setEnv("MOCK", ""); + process.env.MOCK = ""; +} else { + setEnv("MOCK", "1"); + process.env.MOCK = "1"; +} beforeAll( async () => { diff --git a/apps/ledger-live-mobile/e2e/specs/addAccounts/addAccount.spec.ts b/apps/ledger-live-mobile/e2e/specs/addAccounts/addAccount.spec.ts index 844f0b7dbafb..e5ea0af31c02 100644 --- a/apps/ledger-live-mobile/e2e/specs/addAccounts/addAccount.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/addAccounts/addAccount.spec.ts @@ -2,7 +2,7 @@ import { knownDevices } from "../../models/devices"; import DeviceAction from "../../models/DeviceAction"; import { Application } from "../../page"; -let app: Application; +const app = new Application(); let deviceAction: DeviceAction; const testedCurrency = "bitcoin"; @@ -11,7 +11,7 @@ const knownDevice = knownDevices.nanoX; describe("Add account from modal", () => { beforeAll(async () => { - app = await Application.init({ + await app.init({ userdata: "onboardingcompleted", knownDevices: [knownDevice], }); diff --git a/apps/ledger-live-mobile/e2e/specs/deeplinks.spec.ts b/apps/ledger-live-mobile/e2e/specs/deeplinks.spec.ts index 2e34f96e2d24..d9ee4f4d02b3 100644 --- a/apps/ledger-live-mobile/e2e/specs/deeplinks.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/deeplinks.spec.ts @@ -1,7 +1,7 @@ import { Application } from "../page"; import { knownDevices } from "../models/devices"; -let app: Application; +const app = new Application(); const ethereumLong = "ethereum"; const bitcoinLong = "bitcoin"; @@ -11,7 +11,7 @@ const bobaLong = "boba"; $TmsLink("B2CQA-1837"); describe("DeepLinks Tests", () => { beforeAll(async () => { - app = await Application.init({ + await app.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse", knownDevices: [knownDevices.nanoX], }); diff --git a/apps/ledger-live-mobile/e2e/specs/delegate/cosmos.spec.ts b/apps/ledger-live-mobile/e2e/specs/delegate/cosmos.spec.ts index 38d0872c75bb..44fea07b4f2f 100644 --- a/apps/ledger-live-mobile/e2e/specs/delegate/cosmos.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/delegate/cosmos.spec.ts @@ -10,7 +10,7 @@ import { Application } from "../../page"; import DeviceAction from "../../models/DeviceAction"; import BigNumber from "bignumber.js"; -let app: Application; +const app = new Application(); let deviceAction: DeviceAction; const testedCurrency = "cosmos"; @@ -20,7 +20,7 @@ const knownDevice = knownDevices.nanoX; describe("Cosmos delegate flow", () => { beforeAll(async () => { - app = await Application.init({ + await app.init({ userdata: "onboardingcompleted", knownDevices: [knownDevice], testAccounts: [testAccount], diff --git a/apps/ledger-live-mobile/e2e/specs/languageChange.spec.ts b/apps/ledger-live-mobile/e2e/specs/languageChange.spec.ts index b3f70435fe50..343a79be2da2 100644 --- a/apps/ledger-live-mobile/e2e/specs/languageChange.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/languageChange.spec.ts @@ -1,6 +1,6 @@ import { Application } from "../page"; -let app: Application; +const app = new Application(); const langButtonText = [ { lang: "Français", localization: "Général" }, @@ -26,7 +26,7 @@ const verifyLanguageCanBeChanged = (l10n: { lang: string; localization: string } $TmsLink("B2CQA-2344"); describe("Change Language", () => { beforeAll(async () => { - app = await Application.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); + await app.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); await app.portfolio.waitForPortfolioPageToLoad(); }); diff --git a/apps/ledger-live-mobile/e2e/specs/manager.spec.ts b/apps/ledger-live-mobile/e2e/specs/manager.spec.ts index c250a9854992..6f3d6ebcf3d0 100644 --- a/apps/ledger-live-mobile/e2e/specs/manager.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/manager.spec.ts @@ -3,7 +3,7 @@ import { knownDevices } from "../models/devices"; import { deviceInfo155 as deviceInfo } from "@ledgerhq/live-common/apps/mock"; import { Application } from "../page"; -let app: Application; +const app = new Application(); let deviceAction: DeviceAction; const appDesc = ["Bitcoin", "Tron", "Litecoin", "Ethereum", "XRP", "Stellar"]; @@ -12,7 +12,7 @@ const knownDevice = knownDevices.nanoX; describe("Test My Ledger", () => { beforeAll(async () => { - app = await Application.init({ userdata: "onboardingcompleted" }); + await app.init({ userdata: "onboardingcompleted" }); deviceAction = new DeviceAction(knownDevice); await app.portfolio.waitForPortfolioPageToLoad(); diff --git a/apps/ledger-live-mobile/e2e/specs/market.spec.ts b/apps/ledger-live-mobile/e2e/specs/market.spec.ts index 6fdece52b615..d13add0d5612 100644 --- a/apps/ledger-live-mobile/e2e/specs/market.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/market.spec.ts @@ -1,11 +1,11 @@ import { Application } from "../page"; -let app: Application; +const app = new Application(); const asset = "Ethereum (ETH)"; describe("Market page for user with no device", () => { beforeAll(async () => { - app = await Application.init({ userdata: "1accountEth" }); + await app.init({ userdata: "1accountEth" }); await app.portfolio.waitForPortfolioPageToLoad(); }); diff --git a/apps/ledger-live-mobile/e2e/specs/nftGallery.spec.ts b/apps/ledger-live-mobile/e2e/specs/nftGallery.spec.ts index e30d7ee847f3..893daa7cc040 100644 --- a/apps/ledger-live-mobile/e2e/specs/nftGallery.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/nftGallery.spec.ts @@ -1,13 +1,13 @@ import { tapByElement } from "../helpers"; import { Application } from "../page"; -let app: Application; +const app = new Application(); const accountCurrency = "ethereum"; // To-Do Fix NFT not available in account describe.skip("NFT Gallery screen", () => { beforeAll(async () => { - app = await Application.init({ userdata: "1Account1NFTNotSpam" }); + await app.init({ userdata: "1Account1NFTNotSpam" }); await app.portfolio.waitForPortfolioPageToLoad(); await app.nftGallery.openViaDeeplink(); diff --git a/apps/ledger-live-mobile/e2e/specs/onboarding.spec.ts b/apps/ledger-live-mobile/e2e/specs/onboarding.spec.ts index 768c880ec3ce..a4f0f1e0e21d 100644 --- a/apps/ledger-live-mobile/e2e/specs/onboarding.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/onboarding.spec.ts @@ -2,15 +2,11 @@ import { device } from "detox"; import { isAndroid, launchApp } from "../helpers"; import { Application } from "../page"; -let app: Application; +const app = new Application(); let isFirstTest = true; describe("Onboarding", () => { - beforeAll(() => { - app = new Application(); - }); - beforeEach(async () => { if (!isFirstTest) { await device.uninstallApp(); diff --git a/apps/ledger-live-mobile/e2e/specs/onboardingReadOnly.spec.ts b/apps/ledger-live-mobile/e2e/specs/onboardingReadOnly.spec.ts index 3c08597936da..42adfc7cf4ed 100644 --- a/apps/ledger-live-mobile/e2e/specs/onboardingReadOnly.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/onboardingReadOnly.spec.ts @@ -1,13 +1,9 @@ import { device } from "detox"; import { Application } from "../page"; -let app: Application; +const app = new Application(); describe("Onboarding - Read Only", () => { - beforeAll(() => { - app = new Application(); - }); - $TmsLink("B2CQA-1752"); it("is able to buy a nano from the onboarding flow", async () => { await app.onboarding.startOnboarding(); diff --git a/apps/ledger-live-mobile/e2e/specs/password.spec.ts b/apps/ledger-live-mobile/e2e/specs/password.spec.ts index 01a35a9d9aeb..e9b546bc22c6 100644 --- a/apps/ledger-live-mobile/e2e/specs/password.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/password.spec.ts @@ -1,13 +1,13 @@ import { device } from "detox"; import { Application } from "../page"; -let app: Application; +const app = new Application(); const CORRECT_PASSWORD = "passWORD$123!"; describe("Password Lock Screen", () => { beforeAll(async () => { - app = await Application.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); + await app.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); await app.portfolio.waitForPortfolioPageToLoad(); }); diff --git a/apps/ledger-live-mobile/e2e/specs/receive/currencies.spec.ts b/apps/ledger-live-mobile/e2e/specs/receive/currencies.spec.ts index edd1ad3e23fc..620f4e847675 100644 --- a/apps/ledger-live-mobile/e2e/specs/receive/currencies.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/receive/currencies.spec.ts @@ -3,7 +3,7 @@ import { knownDevices } from "../../models/devices"; import { getCryptoCurrencyById } from "@ledgerhq/live-common/currencies/index"; import { Application } from "../../page"; -let app: Application; +const app = new Application(); let deviceAction: DeviceAction; let first = true; const knownDevice = knownDevices.nanoX; @@ -12,7 +12,7 @@ $TmsLink("B2CQA-651"); $TmsLink("B2CQA-1854"); describe("Receive different currency", () => { beforeAll(async () => { - app = await Application.init({ + await app.init({ userdata: "onboardingcompleted", knownDevices: [knownDevice], }); diff --git a/apps/ledger-live-mobile/e2e/specs/receive/receiveFlow.spec.ts b/apps/ledger-live-mobile/e2e/specs/receive/receiveFlow.spec.ts index 5c2f4d78ce15..8490a0f32167 100644 --- a/apps/ledger-live-mobile/e2e/specs/receive/receiveFlow.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/receive/receiveFlow.spec.ts @@ -2,7 +2,7 @@ import DeviceAction from "../../models/DeviceAction"; import { knownDevices } from "../../models/devices"; import { Application } from "../../page"; -let app: Application; +const app = new Application(); let deviceAction: DeviceAction; const btcReceiveAddress = "173ej2furpaB8mTtN5m9829MPGMD7kCgSPx"; let first = true; @@ -10,7 +10,7 @@ const knownDevice = knownDevices.nanoX; describe("Receive Flow", () => { beforeAll(async () => { - app = await Application.init({ + await app.init({ userdata: "EthAccountXrpAccountReadOnlyFalse", knownDevices: [knownDevice], }); diff --git a/apps/ledger-live-mobile/e2e/specs/send/currencies.spec.ts b/apps/ledger-live-mobile/e2e/specs/send/currencies.spec.ts index 33e16cf26f3e..e656daa7f901 100644 --- a/apps/ledger-live-mobile/e2e/specs/send/currencies.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/send/currencies.spec.ts @@ -10,7 +10,7 @@ import { } from "../../models/currencies"; import { Application } from "../../page"; -let app: Application; +const app = new Application(); let deviceAction: DeviceAction; let first = true; @@ -35,7 +35,7 @@ const knownDevice = knownDevices.nanoX; $TmsLink("B2CQA-1823"); describe("Send flow", () => { beforeAll(async () => { - app = await Application.init({ + await app.init({ userdata: "onboardingcompleted", knownDevices: [knownDevice], testAccounts: testAccounts, diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/addAccount.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/addAccount.spec.ts index 1fa55596fc27..1cb04dca12fa 100644 --- a/apps/ledger-live-mobile/e2e/specs/speculos/addAccount.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/speculos/addAccount.spec.ts @@ -1,6 +1,6 @@ import { Application } from "../../page"; -let app: Application; +const app = new Application(); const currencies = [ { currency: "bitcoin", nanoApp: "Bitcoin", tmsLink: "B2CQA-101" }, @@ -9,7 +9,7 @@ const currencies = [ describe("Add accounts", () => { beforeAll(async () => { - app = await Application.init({ userdata: "onboardingcompleted" }); + await app.init({ userdata: "onboardingcompleted" }); await app.portfolio.waitForPortfolioPageToLoad(); }); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/receive/receive.ts b/apps/ledger-live-mobile/e2e/specs/speculos/receive/receive.ts new file mode 100644 index 000000000000..09180f3f67f2 --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/receive/receive.ts @@ -0,0 +1,40 @@ +import { CLI } from "../../../utils/cliUtils"; +import { Application } from "../../../page"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; + +export async function runReceiveTest(account: Account, tmsLink: string) { + const app = new Application(); + + describe(`Receive - ${account.currency.name}`, () => { + beforeAll(async () => { + await app.init({ + speculosApp: account.currency.speculosApp, + cliCommands: [ + () => { + return CLI.liveData({ + currency: account.currency.currencyId, + index: account.index, + appjson: app.userdataPath, + add: true, + }); + }, + ], + }); + await app.portfolio.waitForPortfolioPageToLoad(); + }); + + $TmsLink(tmsLink); + it(`receive on ${account.currency.name} (through scanning)`, async () => { + await app.receive.openViaDeeplink(); + await app.common.performSearch(account.currency.name); + await app.receive.selectCurrency(account.currency.name); + await app.receive.selectAccount(account.accountName); + await app.receive.doNotVerifyAddress(); + await app.receive.expectReceivePageIsDisplayed(account.currency.ticker, account.accountName); + }); + + afterAll(async () => { + await app?.common.removeSpeculos(); + }); + }); +} diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/receive/receiveBTC.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/receive/receiveBTC.spec.ts new file mode 100644 index 000000000000..008c3e98822f --- /dev/null +++ b/apps/ledger-live-mobile/e2e/specs/speculos/receive/receiveBTC.spec.ts @@ -0,0 +1,4 @@ +import { runReceiveTest } from "./receive"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; + +runReceiveTest(Account.BTC_NATIVE_SEGWIT_1, "B2CQA-2559, B2CQA-2687"); diff --git a/apps/ledger-live-mobile/e2e/specs/swap/dexSwap.spec.ts b/apps/ledger-live-mobile/e2e/specs/swap/dexSwap.spec.ts index 7b6498feaf13..0660a86968d7 100644 --- a/apps/ledger-live-mobile/e2e/specs/swap/dexSwap.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/swap/dexSwap.spec.ts @@ -1,10 +1,10 @@ import { Application } from "../../page"; -let app: Application; +const app = new Application(); describe("DEX Swap", () => { beforeAll(async () => { - app = await Application.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); + await app.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); await app.portfolio.waitForPortfolioPageToLoad(); await app.swap.openViaDeeplink(); diff --git a/apps/ledger-live-mobile/e2e/specs/swap/swap.spec.ts b/apps/ledger-live-mobile/e2e/specs/swap/swap.spec.ts index 000658e9f72d..2d8a428f285b 100644 --- a/apps/ledger-live-mobile/e2e/specs/swap/swap.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/swap/swap.spec.ts @@ -1,10 +1,10 @@ import { Application } from "../../page"; -let app: Application; +const app = new Application(); describe("Swap", () => { beforeAll(async () => { - app = await Application.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); + await app.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); await app.portfolio.waitForPortfolioPageToLoad(); }); diff --git a/apps/ledger-live-mobile/e2e/specs/unknown-currency-resilience.spec.ts b/apps/ledger-live-mobile/e2e/specs/unknown-currency-resilience.spec.ts index 382dd923f7b5..01c51422a2e9 100644 --- a/apps/ledger-live-mobile/e2e/specs/unknown-currency-resilience.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/unknown-currency-resilience.spec.ts @@ -3,7 +3,7 @@ import { loadAccountsRaw } from "../bridge/server"; import { Application } from "../page"; import { initTestAccounts } from "../models/currencies"; -let app: Application; +const app = new Application(); const [badAccount1, badAccount2] = initTestAccounts(["bitcoin", "bitcoin"]).map(account => toAccountRaw(account), @@ -22,7 +22,7 @@ describe("Portfolio to load with unknown currency data in accounts", () => { { data: badAccount2, version: 0 }, ]); - app = await Application.init({ userdata: "onboardingcompleted" }); + await app.init({ userdata: "onboardingcompleted" }); }); it("opens to empty state", async () => { diff --git a/apps/ledger-live-mobile/e2e/specs/wallet-api.spec.ts b/apps/ledger-live-mobile/e2e/specs/wallet-api.spec.ts index fb4b1d3ae642..77b6b921af46 100644 --- a/apps/ledger-live-mobile/e2e/specs/wallet-api.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/wallet-api.spec.ts @@ -1,10 +1,10 @@ import { Application } from "../page"; -let app: Application; +const app = new Application(); describe("Wallet API methods", () => { beforeAll(async () => { - app = await Application.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); + await app.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); await app.dummyWalletApp.startApp(); await app.portfolio.waitForPortfolioPageToLoad(); diff --git a/apps/ledger-live-mobile/e2e/utils/cliUtils.ts b/apps/ledger-live-mobile/e2e/utils/cliUtils.ts new file mode 100644 index 000000000000..76ca73cea7cb --- /dev/null +++ b/apps/ledger-live-mobile/e2e/utils/cliUtils.ts @@ -0,0 +1,131 @@ +import bot from "@ledgerhq/live-cli/src/commands/blockchain/bot"; +import botPortfolio from "@ledgerhq/live-cli/src/commands/blockchain/botPortfolio"; +import botTransfer from "@ledgerhq/live-cli/src/commands/blockchain/botTransfer"; +import broadcast from "@ledgerhq/live-cli/src/commands/blockchain/broadcast"; +import confirmOp from "@ledgerhq/live-cli/src/commands/blockchain/confirmOp"; +import derivation from "@ledgerhq/live-cli/src/commands/blockchain/derivation"; +import estimateMaxSpendable from "@ledgerhq/live-cli/src/commands/blockchain/estimateMaxSpendable"; +import generateTestScanAccounts from "@ledgerhq/live-cli/src/commands/blockchain/generateTestScanAccounts"; +import generateTestTransaction from "@ledgerhq/live-cli/src/commands/blockchain/generateTestTransaction"; +import getAddress from "@ledgerhq/live-cli/src/commands/blockchain/getAddress"; +import getTransactionStatus from "@ledgerhq/live-cli/src/commands/blockchain/getTransactionStatus"; +import receive from "@ledgerhq/live-cli/src/commands/blockchain/receive"; +import satstack from "@ledgerhq/live-cli/src/commands/blockchain/satstack"; +import satstackStatus from "@ledgerhq/live-cli/src/commands/blockchain/satstackStatus"; +import scanDescriptors from "@ledgerhq/live-cli/src/commands/blockchain/scanDescriptors"; +import send from "@ledgerhq/live-cli/src/commands/blockchain/send"; +import signMessage from "@ledgerhq/live-cli/src/commands/blockchain/signMessage"; +import sync from "@ledgerhq/live-cli/src/commands/blockchain/sync"; +import testDetectOpCollision from "@ledgerhq/live-cli/src/commands/blockchain/testDetectOpCollision"; +import testGetTrustedInputFromTxHash from "@ledgerhq/live-cli/src/commands/blockchain/testGetTrustedInputFromTxHash"; +import app from "@ledgerhq/live-cli/src/commands/device/app"; +import appUninstallAll from "@ledgerhq/live-cli/src/commands/device/appUninstallAll"; +import appsCheckAllAppVersions from "@ledgerhq/live-cli/src/commands/device/appsCheckAllAppVersions"; +import appsInstallAll from "@ledgerhq/live-cli/src/commands/device/appsInstallAll"; +import appsUpdateTestAll from "@ledgerhq/live-cli/src/commands/device/appsUpdateTestAll"; +import cleanSpeculos from "@ledgerhq/live-cli/src/commands/device/cleanSpeculos"; +import customLockScreenFetch from "@ledgerhq/live-cli/src/commands/device/customLockScreenFetch"; +import customLockScreenFetchAndRestore from "@ledgerhq/live-cli/src/commands/device/customLockScreenFetchAndRestore"; +import customLockScreenFetchHash from "@ledgerhq/live-cli/src/commands/device/customLockScreenFetchHash"; +import customLockScreenLoad from "@ledgerhq/live-cli/src/commands/device/customLockScreenLoad"; +import customLockScreenRemove from "@ledgerhq/live-cli/src/commands/device/customLockScreenRemove"; +import devDeviceAppsScenario from "@ledgerhq/live-cli/src/commands/device/devDeviceAppsScenario"; +import deviceAppVersion from "@ledgerhq/live-cli/src/commands/device/deviceAppVersion"; +import deviceInfo from "@ledgerhq/live-cli/src/commands/device/deviceInfo"; +import deviceSDKFirmwareUpdate from "@ledgerhq/live-cli/src/commands/device/deviceSDKFirmwareUpdate"; +import deviceSDKGetBatteryStatuses from "@ledgerhq/live-cli/src/commands/device/deviceSDKGetBatteryStatuses"; +import deviceSDKGetDeviceInfo from "@ledgerhq/live-cli/src/commands/device/deviceSDKGetDeviceInfo"; +import deviceSDKToggleOnboardingEarlyCheck from "@ledgerhq/live-cli/src/commands/device/deviceSDKToggleOnboardingEarlyCheck"; +import deviceVersion from "@ledgerhq/live-cli/src/commands/device/deviceVersion"; +import discoverDevices from "@ledgerhq/live-cli/src/commands/device/discoverDevices"; +import firmwareRepair from "@ledgerhq/live-cli/src/commands/device/firmwareRepair"; +import firmwareUpdate from "@ledgerhq/live-cli/src/commands/device/firmwareUpdate"; +import genuineCheck from "@ledgerhq/live-cli/src/commands/device/genuineCheck"; +import getBatteryStatus from "@ledgerhq/live-cli/src/commands/device/getBatteryStatus"; +import getDeviceRunningMode from "@ledgerhq/live-cli/src/commands/device/getDeviceRunningMode"; +import i18n from "@ledgerhq/live-cli/src/commands/device/i18n"; +import listApps from "@ledgerhq/live-cli/src/commands/device/listApps"; +import managerListApps from "@ledgerhq/live-cli/src/commands/device/managerListApps"; +import proxy from "@ledgerhq/live-cli/src/commands/device/proxy"; +import reinstallConfigurationConsent from "@ledgerhq/live-cli/src/commands/device/reinstallConfigurationConsent"; +import repl from "@ledgerhq/live-cli/src/commands/device/repl"; +import speculosList from "@ledgerhq/live-cli/src/commands/device/speculosList"; +import balanceHistory from "@ledgerhq/live-cli/src/commands/live/balanceHistory"; +import countervalues from "@ledgerhq/live-cli/src/commands/live/countervalues"; +import envs from "@ledgerhq/live-cli/src/commands/live/envs"; +import exportAccounts from "@ledgerhq/live-cli/src/commands/live/exportAccounts"; +import ledgerKeyRingProtocol from "@ledgerhq/live-cli/src/commands/live/ledgerKeyRingProtocol"; +import ledgerSync from "@ledgerhq/live-cli/src/commands/live/ledgerSync"; +import liveData from "@ledgerhq/live-cli/src/commands/live/liveData"; +import portfolio from "@ledgerhq/live-cli/src/commands/live/portfolio"; +import synchronousOnboarding from "@ledgerhq/live-cli/src/commands/live/synchronousOnboarding"; +import user from "@ledgerhq/live-cli/src/commands/live/user"; +import version from "@ledgerhq/live-cli/src/commands/live/version"; +import swap from "@ledgerhq/live-cli/src/commands/ptx/swap"; + +export const CLI = { + bot: bot.job, + botPortfolio: botPortfolio.job, + botTransfer: botTransfer.job, + broadcast: broadcast.job, + confirmOp: confirmOp.job, + derivation: derivation.job, + estimateMaxSpendable: estimateMaxSpendable.job, + generateTestScanAccounts: generateTestScanAccounts.job, + generateTestTransaction: generateTestTransaction.job, + getAddress: getAddress.job, + getTransactionStatus: getTransactionStatus.job, + receive: receive.job, + satstack: satstack.job, + satstackStatus: satstackStatus.job, + scanDescriptors: scanDescriptors.job, + send: send.job, + signMessage: signMessage.job, + sync: sync.job, + testDetectOpCollision: testDetectOpCollision.job, + testGetTrustedInputFromTxHash: testGetTrustedInputFromTxHash.job, + app: app.job, + appUninstallAll: appUninstallAll.job, + appsCheckAllAppVersions: appsCheckAllAppVersions.job, + appsInstallAll: appsInstallAll.job, + appsUpdateTestAll: appsUpdateTestAll.job, + cleanSpeculos: cleanSpeculos.job, + customLockScreenFetch: customLockScreenFetch.job, + customLockScreenFetchAndRestore: customLockScreenFetchAndRestore.job, + customLockScreenFetchHash: customLockScreenFetchHash.job, + customLockScreenLoad: customLockScreenLoad.job, + customLockScreenRemove: customLockScreenRemove.job, + devDeviceAppsScenario: devDeviceAppsScenario.job, + deviceAppVersion: deviceAppVersion.job, + deviceInfo: deviceInfo.job, + deviceSDKFirmwareUpdate: deviceSDKFirmwareUpdate.job, + deviceSDKGetBatteryStatuses: deviceSDKGetBatteryStatuses.job, + deviceSDKGetDeviceInfo: deviceSDKGetDeviceInfo.job, + deviceSDKToggleOnboardingEarlyCheck: deviceSDKToggleOnboardingEarlyCheck.job, + deviceVersion: deviceVersion.job, + discoverDevices: discoverDevices.job, + firmwareRepair: firmwareRepair.job, + firmwareUpdate: firmwareUpdate.job, + genuineCheck: genuineCheck.job, + getBatteryStatus: getBatteryStatus.job, + getDeviceRunningMode: getDeviceRunningMode.job, + i18n: i18n.job, + listApps: listApps.job, + managerListApps: managerListApps.job, + proxy: proxy.job, + reinstallConfigurationConsent: reinstallConfigurationConsent.job, + repl: repl.job, + speculosList: speculosList.job, + balanceHistory: balanceHistory.job, + countervalues: countervalues.job, + envs: envs.job, + exportAccounts: exportAccounts.job, + ledgerKeyRingProtocol: ledgerKeyRingProtocol.job, + ledgerSync: ledgerSync.job, + liveData: liveData.job, + portfolio: portfolio.job, + synchronousOnboarding: synchronousOnboarding.job, + user: user.job, + version: version.job, + swap: swap.job, +}; diff --git a/apps/ledger-live-mobile/jest.config.js b/apps/ledger-live-mobile/jest.config.js index 933968e94a6d..8a32d07018f5 100644 --- a/apps/ledger-live-mobile/jest.config.js +++ b/apps/ledger-live-mobile/jest.config.js @@ -19,6 +19,7 @@ const transformIncludePatterns = [ "react-native-android-location-services-dialog-box", "react-native-vector-icons", "react-native-qrcode-svg", + "react-native-video", ]; /** @type {import('ts-jest').JestConfigWithTsJest} */ diff --git a/apps/ledger-live-mobile/package.json b/apps/ledger-live-mobile/package.json index 3b4210c1f001..9a3a861f47df 100644 --- a/apps/ledger-live-mobile/package.json +++ b/apps/ledger-live-mobile/package.json @@ -1,6 +1,6 @@ { "name": "live-mobile", - "version": "3.58.0", + "version": "3.59.0", "private": true, "scripts": { "postinstall": "zx ./scripts/post.mjs", @@ -238,6 +238,7 @@ "@babel/runtime": "7.24.1", "@jest/reporters": "29.7.0", "@ledgerhq/hw-transport-node-speculos-http": "workspace:^", + "@ledgerhq/live-cli": "workspace:^", "@ledgerhq/speculos-transport": "workspace:^", "@ledgerhq/test-utils": "workspace:^", "@react-native-community/cli": "13.6.1", diff --git a/apps/ledger-live-mobile/src/AppProviders.tsx b/apps/ledger-live-mobile/src/AppProviders.tsx index c0304ba4c966..959889b20911 100644 --- a/apps/ledger-live-mobile/src/AppProviders.tsx +++ b/apps/ledger-live-mobile/src/AppProviders.tsx @@ -12,6 +12,7 @@ import SnackbarContainer from "~/screens/NotificationCenter/Snackbar/SnackbarCon import PostOnboardingProviderWrapped from "~/logic/postOnboarding/PostOnboardingProviderWrapped"; import { CounterValuesStateRaw } from "@ledgerhq/live-countervalues/types"; import { CountervaluesMarketcap } from "@ledgerhq/live-countervalues-react/index"; +import { InViewContextProvider } from "LLM/contexts/InViewContext"; import { WalletSyncProvider } from "LLM/features/WalletSync/components/WalletSyncContext"; import { AppDataStorageProvider } from "~/hooks/storageProvider/useAppDataStorage"; @@ -37,7 +38,7 @@ function AppProviders({ initialCountervalues, children }: AppProvidersProps) { - {children} + {children} diff --git a/apps/ledger-live-mobile/src/actions/settings.ts b/apps/ledger-live-mobile/src/actions/settings.ts index b4dacc6fc6c6..f7c46acbf502 100755 --- a/apps/ledger-live-mobile/src/actions/settings.ts +++ b/apps/ledger-live-mobile/src/actions/settings.ts @@ -10,7 +10,6 @@ import { DangerouslyOverrideStatePayload, SettingsDismissBannerPayload, SettingsHideEmptyTokenAccountsPayload, - SettingsHideNftCollectionPayload, SettingsImportDesktopPayload, SettingsImportPayload, SettingsSetHasInstalledAnyAppPayload, @@ -41,7 +40,6 @@ import { SettingsSetSwapSelectableCurrenciesPayload, SettingsSetThemePayload, SettingsShowTokenPayload, - SettingsUnhideNftCollectionPayload, SettingsUpdateCurrencyPayload, SettingsActionTypes, SettingsSetWalletTabNavigatorLastVisitedTabPayload, @@ -71,9 +69,8 @@ import { SettingsRemoveStarredMarketcoinsPayload, SettingsSetFromLedgerSyncOnboardingPayload, SettingsSetHasBeenRedirectedToPostOnboardingPayload, - SettingsWhitelistNftCollectionPayload, - SettingsUnwhitelistNftCollectionPayload, SettingsSetMevProtectionPayload, + SettingsUpdateNftCollectionStatus, } from "./types"; import { ImageType } from "~/components/CustomImage/types"; @@ -144,19 +141,8 @@ export const blacklistToken = createAction( SettingsActionTypes.BLACKLIST_TOKEN, ); export const showToken = createAction(SettingsActionTypes.SHOW_TOKEN); -export const hideNftCollection = createAction( - SettingsActionTypes.HIDE_NFT_COLLECTION, -); -export const unhideNftCollection = createAction( - SettingsActionTypes.UNHIDE_NFT_COLLECTION, -); - -export const whitelistNftCollection = createAction( - SettingsActionTypes.WHITELIST_NFT_COLLECTION, -); - -export const unwhitelistNftCollection = createAction( - SettingsActionTypes.UNWHITELIST_NFT_COLLECTION, +export const updateNftStatus = createAction( + SettingsActionTypes.UPDATE_NFT_COLLECTION_STATUS, ); export const dismissBanner = createAction( diff --git a/apps/ledger-live-mobile/src/actions/types.ts b/apps/ledger-live-mobile/src/actions/types.ts index 862298861625..0370bc76596c 100644 --- a/apps/ledger-live-mobile/src/actions/types.ts +++ b/apps/ledger-live-mobile/src/actions/types.ts @@ -37,6 +37,8 @@ import type { Unpacked } from "../types/helpers"; import { HandlersPayloads } from "@ledgerhq/live-wallet/store"; import { ImportAccountsReduceInput } from "@ledgerhq/live-wallet/liveqr/importAccounts"; import { Steps } from "LLM/features/WalletSync/types/Activation"; +import { NftStatus } from "@ledgerhq/live-nft/types"; +import { BlockchainEVM } from "@ledgerhq/live-nft/supported"; // === ACCOUNTS ACTIONS === @@ -242,10 +244,7 @@ export enum SettingsActionTypes { SETTINGS_FILTER_TOKEN_OPERATIONS_ZERO_AMOUNT = "SETTINGS_FILTER_TOKEN_OPERATIONS_ZERO_AMOUNT", SHOW_TOKEN = "SHOW_TOKEN", BLACKLIST_TOKEN = "BLACKLIST_TOKEN", - HIDE_NFT_COLLECTION = "HIDE_NFT_COLLECTION", - UNHIDE_NFT_COLLECTION = "UNHIDE_NFT_COLLECTION", - UNWHITELIST_NFT_COLLECTION = "UNWHITELIST_NFT_COLLECTION", - WHITELIST_NFT_COLLECTION = "WHITELIST_NFT_COLLECTION", + UPDATE_NFT_COLLECTION_STATUS = "UPDATE_NFT_COLLECTION_STATUS", SETTINGS_DISMISS_BANNER = "SETTINGS_DISMISS_BANNER", SETTINGS_SET_AVAILABLE_UPDATE = "SETTINGS_SET_AVAILABLE_UPDATE", DANGEROUSLY_OVERRIDE_STATE = "DANGEROUSLY_OVERRIDE_STATE", @@ -324,10 +323,11 @@ export type SettingsFilterTokenOperationsZeroAmountPayload = SettingsState["filterTokenOperationsZeroAmount"]; export type SettingsShowTokenPayload = string; export type SettingsBlacklistTokenPayload = string; -export type SettingsHideNftCollectionPayload = string; -export type SettingsUnhideNftCollectionPayload = string; -export type SettingsWhitelistNftCollectionPayload = string; -export type SettingsUnwhitelistNftCollectionPayload = string; +export type SettingsUpdateNftCollectionStatus = { + blockchain: BlockchainEVM; + collection: string; + status: NftStatus; +}; export type SettingsDismissBannerPayload = string; export type SettingsSetAvailableUpdatePayload = SettingsState["hasAvailableUpdate"]; export type SettingsSetThemePayload = SettingsState["theme"]; @@ -425,10 +425,7 @@ export type SettingsPayload = | SettingsHideEmptyTokenAccountsPayload | SettingsShowTokenPayload | SettingsBlacklistTokenPayload - | SettingsHideNftCollectionPayload - | SettingsUnhideNftCollectionPayload - | SettingsWhitelistNftCollectionPayload - | SettingsUnwhitelistNftCollectionPayload + | SettingsUpdateNftCollectionStatus | SettingsDismissBannerPayload | SettingsSetAvailableUpdatePayload | SettingsSetThemePayload diff --git a/apps/ledger-live-mobile/src/analytics/segment.ts b/apps/ledger-live-mobile/src/analytics/segment.ts index ec34d59a7d72..a745b6acc57c 100644 --- a/apps/ledger-live-mobile/src/analytics/segment.ts +++ b/apps/ledger-live-mobile/src/analytics/segment.ts @@ -40,6 +40,7 @@ import { personalizedRecommendationsEnabledSelector, hasSeenAnalyticsOptInPromptSelector, mevProtectionSelector, + readOnlyModeEnabledSelector, } from "../reducers/settings"; import { knownDevicesSelector } from "../reducers/ble"; import { DeviceLike, State } from "../reducers/types"; @@ -171,7 +172,9 @@ const extraProperties = async (store: AppStore) => { modelId: lastDevice.modelId, } : {}; + const onboardingHasDevice = onboardingHasDeviceSelector(state); + const isReborn = readOnlyModeEnabledSelector(state); const notifications = notificationsSelector(state); const notificationsOptedIn = { notificationsAllowed: notifications.areNotificationsAllowed, @@ -227,6 +230,7 @@ const extraProperties = async (store: AppStore) => { devicesCount: devices.length, modelIdQtyList: aggregateData(devices), modelIdList: getUniqueModelIdList(devices), + isReborn, onboardingHasDevice, ...(satisfaction ? { diff --git a/apps/ledger-live-mobile/src/components/Carousel/CarouselCard.tsx b/apps/ledger-live-mobile/src/components/Carousel/CarouselCard.tsx index d17fa9a88a9b..9ad958534774 100644 --- a/apps/ledger-live-mobile/src/components/Carousel/CarouselCard.tsx +++ b/apps/ledger-live-mobile/src/components/Carousel/CarouselCard.tsx @@ -1,4 +1,4 @@ -import React, { memo, useCallback, useEffect } from "react"; +import React, { memo, useCallback } from "react"; import { Linking } from "react-native"; import { Flex, FullBackgroundCard } from "@ledgerhq/native-ui"; import { useTheme } from "styled-components/native"; @@ -15,15 +15,7 @@ type CarouselCardProps = { const CarouselCard = ({ id, cardProps, index, width }: CarouselCardProps) => { const { theme } = useTheme(); - const { logClickCard, logImpressionCard, dismissCard, trackContentCardEvent } = - useDynamicContent(); - - useEffect(() => { - if (cardProps) { - // Notify Braze that the card has been displayed to the user - logImpressionCard(cardProps.id); - } - }, [cardProps, logImpressionCard]); + const { logClickCard, dismissCard, trackContentCardEvent } = useDynamicContent(); const onPress = useCallback(() => { if (!cardProps) return; diff --git a/apps/ledger-live-mobile/src/components/Carousel/index.tsx b/apps/ledger-live-mobile/src/components/Carousel/index.tsx index 7a2ee838b342..b51b7519e7b3 100644 --- a/apps/ledger-live-mobile/src/components/Carousel/index.tsx +++ b/apps/ledger-live-mobile/src/components/Carousel/index.tsx @@ -1,5 +1,6 @@ import React, { memo, useMemo, useCallback, useRef, useState } from "react"; import { NativeScrollEvent, NativeSyntheticEvent, ScrollView } from "react-native"; +import LogContentCardWrapper from "LLM/features/DynamicContent/components/LogContentCardWrapper"; import useDynamicContent from "~/dynamicContent/useDynamicContent"; import { width } from "~/helpers/normalizeSize"; import CarouselCard from "./CarouselCard"; @@ -48,13 +49,9 @@ const Carousel = () => { decelerationRate={"fast"} > {walletCardsDisplayed.map((cardProps, index) => ( - + + + ))} ); diff --git a/apps/ledger-live-mobile/src/components/FabActions/index.tsx b/apps/ledger-live-mobile/src/components/FabActions/index.tsx index 7320f08870c4..36c319fdce70 100644 --- a/apps/ledger-live-mobile/src/components/FabActions/index.tsx +++ b/apps/ledger-live-mobile/src/components/FabActions/index.tsx @@ -12,6 +12,9 @@ import { useAnalytics } from "~/analytics"; import { WrappedButtonProps } from "../wrappedUi/Button"; import { NavigatorName } from "~/const"; import { useRoute } from "@react-navigation/native"; +import { useRebornFlow } from "LLM/features/Reborn/hooks/useRebornFlow"; +import { useSelector } from "react-redux"; +import { hasOrderedNanoSelector, readOnlyModeEnabledSelector } from "~/reducers/settings"; export type ModalOnDisabledClickComponentProps = { account?: AccountLike; @@ -96,6 +99,10 @@ export const FabButtonBarProvider = ({ const navigation = useNavigation>(); + const readOnlyModeEnabled = useSelector(readOnlyModeEnabledSelector); + const hasOrderedNano = useSelector(hasOrderedNanoSelector); + const { navigateToRebornFlow } = useRebornFlow(); + const router = useRoute(); const onNavigate = useCallback( @@ -134,6 +141,11 @@ export const FabButtonBarProvider = ({ (data: Omit) => { const { navigationParams, confirmModalProps, linkUrl, event, eventProperties, id } = data; + if (readOnlyModeEnabled && !hasOrderedNano) { + navigateToRebornFlow(); + return; + } + if (!confirmModalProps) { if (event) { track(event, { page: router.name, ...globalEventProperties, ...eventProperties }); @@ -157,7 +169,15 @@ export const FabButtonBarProvider = ({ setIsModalInfoOpened(true); } }, - [globalEventProperties, onNavigate, track, router.name], + [ + readOnlyModeEnabled, + hasOrderedNano, + navigateToRebornFlow, + track, + router.name, + globalEventProperties, + onNavigate, + ], ); const onContinue = useCallback(() => { diff --git a/apps/ledger-live-mobile/src/components/FabActions/modals/ZeroBalanceDisabledModalContent.tsx b/apps/ledger-live-mobile/src/components/FabActions/modals/ZeroBalanceDisabledModalContent.tsx index be4634e5f5cd..f704c380fc1b 100644 --- a/apps/ledger-live-mobile/src/components/FabActions/modals/ZeroBalanceDisabledModalContent.tsx +++ b/apps/ledger-live-mobile/src/components/FabActions/modals/ZeroBalanceDisabledModalContent.tsx @@ -14,6 +14,9 @@ import { } from "../../RootNavigator/types/helpers"; import { BaseNavigatorStackParamList } from "../../RootNavigator/types/BaseNavigator"; import QueuedDrawer from "../../QueuedDrawer"; +import { useRebornFlow } from "LLM/features/Reborn/hooks/useRebornFlow"; +import { useSelector } from "react-redux"; +import { readOnlyModeEnabledSelector, hasOrderedNanoSelector } from "~/reducers/settings"; function ZeroBalanceDisabledModalContent({ account, @@ -26,10 +29,17 @@ function ZeroBalanceDisabledModalContent({ const { t } = useTranslation(); const navigation = useNavigation>>(); + const { navigateToRebornFlow } = useRebornFlow(); + const readOnlyModeEnabled = useSelector(readOnlyModeEnabledSelector); + const hasOrderedNano = useSelector(hasOrderedNanoSelector); const actionCurrency = account ? getAccountCurrency(account) : currency; const goToBuy = useCallback(() => { + if (readOnlyModeEnabled && !hasOrderedNano) { + navigateToRebornFlow(); + return; + } navigation.navigate(NavigatorName.Exchange, { screen: ScreenName.ExchangeBuy, params: { @@ -38,9 +48,21 @@ function ZeroBalanceDisabledModalContent({ }, }); onClose(); - }, [account?.id, actionCurrency?.id, navigation, onClose]); + }, [ + account?.id, + actionCurrency?.id, + hasOrderedNano, + navigateToRebornFlow, + navigation, + onClose, + readOnlyModeEnabled, + ]); const goToReceive = useCallback(() => { + if (readOnlyModeEnabled && !hasOrderedNano) { + navigateToRebornFlow(); + return; + } if (account) { navigation.navigate(NavigatorName.ReceiveFunds, { screen: ScreenName.ReceiveConfirmation, @@ -60,7 +82,16 @@ function ZeroBalanceDisabledModalContent({ }); } onClose(); - }, [account, parentAccount?.id, actionCurrency, navigation, onClose]); + }, [ + readOnlyModeEnabled, + hasOrderedNano, + account, + onClose, + navigateToRebornFlow, + navigation, + actionCurrency, + parentAccount?.id, + ]); return ( (state => accountSelector(state, { accountId }), @@ -39,14 +38,17 @@ const HideNftDrawer = ({ nftId, nftContract, collection, isOpened, onClose }: Pr }); const collectionId = `${account?.id}|${nftContract}`; - if (whitelistedNftCollections.includes(collectionId)) { - dispatch(unwhitelistNftCollection(collectionId)); - } - dispatch(hideNftCollection(collectionId)); + dispatch( + updateNftStatus({ + collection: collectionId, + status: NftStatus.blacklisted, + blockchain: account?.currency.id as BlockchainEVM, + }), + ); onClose(); navigation.goBack(); - }, [account?.id, dispatch, navigation, nftContract, onClose, whitelistedNftCollections]); + }, [account?.currency.id, account?.id, dispatch, navigation, nftContract, onClose]); const onPressClose = useCallback(() => { track("button_clicked", { diff --git a/apps/ledger-live-mobile/src/components/Nft/NftCollectionOptionsMenu.tsx b/apps/ledger-live-mobile/src/components/Nft/NftCollectionOptionsMenu.tsx index 53ecf427db87..ce4cd590d3a5 100644 --- a/apps/ledger-live-mobile/src/components/Nft/NftCollectionOptionsMenu.tsx +++ b/apps/ledger-live-mobile/src/components/Nft/NftCollectionOptionsMenu.tsx @@ -1,12 +1,13 @@ import React, { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; import { Text, IconsLegacy, BoxedIcon, Button, Flex } from "@ledgerhq/native-ui"; import { Account, ProtoNFT } from "@ledgerhq/types-live"; import { useTranslation } from "react-i18next"; -import { hideNftCollection, unwhitelistNftCollection } from "~/actions/settings"; +import { updateNftStatus } from "~/actions/settings"; import QueuedDrawer from "../QueuedDrawer"; -import { whitelistedNftCollectionsSelector } from "~/reducers/settings"; +import { NftStatus } from "@ledgerhq/live-nft/types"; +import { BlockchainEVM } from "@ledgerhq/live-nft/supported"; type Props = { isOpen: boolean; @@ -19,17 +20,18 @@ const NftCollectionOptionsMenu = ({ isOpen, onClose, collection, account }: Prop const { t } = useTranslation(); const dispatch = useDispatch(); - const whitelistedNftCollections = useSelector(whitelistedNftCollectionsSelector); - const onConfirm = useCallback(() => { const collectionId = `${account.id}|${collection?.[0]?.contract}`; - if (whitelistedNftCollections.includes(collectionId)) { - dispatch(unwhitelistNftCollection(collectionId)); - } - dispatch(hideNftCollection(collectionId)); + dispatch( + updateNftStatus({ + collection: collectionId, + status: NftStatus.blacklisted, + blockchain: account.currency.id as BlockchainEVM, + }), + ); onClose(); - }, [account.id, collection, whitelistedNftCollections, dispatch, onClose]); + }, [account.id, account.currency.id, collection, dispatch, onClose]); return ( diff --git a/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.hook.ts b/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.hook.ts index 03b2a5a68400..f0764fffb126 100644 --- a/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.hook.ts +++ b/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.hook.ts @@ -7,14 +7,18 @@ import { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useDispatch, useSelector } from "react-redux"; import { BackHandler } from "react-native"; -import { hideNftCollection, unwhitelistNftCollection } from "~/actions/settings"; +import { updateNftStatus } from "~/actions/settings"; import { track } from "../../../analytics"; import { NavigatorName, ScreenName } from "~/const"; -import { updateMainNavigatorVisibility } from "~/actions/appstate"; -import { galleryFilterDrawerVisibleSelector, galleryChainFiltersSelector } from "~/reducers/nft"; -import { setGalleryChainFilter, setGalleryFilterDrawerVisible } from "~/actions/nft"; +import { updateMainNavigatorVisibility } from "../../../actions/appstate"; +import { + galleryFilterDrawerVisibleSelector, + galleryChainFiltersSelector, +} from "../../../reducers/nft"; +import { setGalleryChainFilter, setGalleryFilterDrawerVisible } from "../../../actions/nft"; import { NftGalleryChainFiltersState } from "../../../reducers/types"; -import { whitelistedNftCollectionsSelector } from "~/reducers/settings"; +import { NftStatus } from "@ledgerhq/live-nft/types"; +import { BlockchainEVM } from "@ledgerhq/live-nft/supported"; const TOAST_ID = "SUCCESS_HIDE"; @@ -28,8 +32,6 @@ export function useNftList({ nftList }: { nftList?: ProtoNFT[] }) { const isFilterDrawerVisible = useSelector(galleryFilterDrawerVisibleSelector); const chainFilters = useSelector(galleryChainFiltersSelector); - const whitelistedNftCollections = useSelector(whitelistedNftCollectionsSelector); - const [nftsToHide, setNftsToHide] = useState([]); // Multi Select ------------------------ @@ -67,11 +69,14 @@ export function useNftList({ nftList }: { nftList?: ProtoNFT[] }) { nftsToHide.forEach(nft => { const { accountId } = decodeNftId(nft.id ?? ""); const collectionId = `${accountId}|${nft.contract}`; - if (whitelistedNftCollections.includes(collectionId)) { - dispatch(unwhitelistNftCollection(collectionId)); - } - dispatch(hideNftCollection(collectionId)); + dispatch( + updateNftStatus({ + collection: collectionId, + status: NftStatus.blacklisted, + blockchain: nft.currencyId as BlockchainEVM, + }), + ); }); pushToast({ @@ -82,7 +87,7 @@ export function useNftList({ nftList }: { nftList?: ProtoNFT[] }) { count: nftsToHide.length, }), }); - }, [exitMultiSelectMode, nftsToHide, pushToast, t, whitelistedNftCollections, dispatch]); + }, [exitMultiSelectMode, nftsToHide, pushToast, t, dispatch]); const triggerMultiSelectMode = useCallback(() => { setNftsToHide([]); diff --git a/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.tsx b/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.tsx index 9ac51b523b72..70a6ff4bf4e1 100644 --- a/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.tsx +++ b/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.tsx @@ -31,6 +31,7 @@ const RefreshableCollapsibleHeaderFlatList = globalSyncRefreshControl void; + hasNextPage: boolean; isLoading: boolean; error: unknown; refetch: () => void; @@ -50,7 +51,7 @@ const NB_COLUMNS = 2; const keyExtractor = (item: ProtoNFT) => item.id; -const NftList = ({ data, fetchNextPage, isLoading }: Props) => { +const NftList = ({ data, hasNextPage, fetchNextPage, isLoading }: Props) => { const { space, colors } = useTheme(); const dataWithAdd = data.concat(ADD_NEW); @@ -171,14 +172,14 @@ const NftList = ({ data, fetchNextPage, isLoading }: Props) => { marginBottom: multiSelectModeEnabled ? 0 : space[3], }} ListFooterComponent={ - isLoading ? ( + !isLoading && hasNextPage ? ( ) : null } ListEmptyComponent={ - data.length === 0 && isLoading ? ( + isLoading ? ( diff --git a/apps/ledger-live-mobile/src/components/RootNavigator/BaseNavigator.tsx b/apps/ledger-live-mobile/src/components/RootNavigator/BaseNavigator.tsx index 904848ec7ee2..0d8c92420121 100644 --- a/apps/ledger-live-mobile/src/components/RootNavigator/BaseNavigator.tsx +++ b/apps/ledger-live-mobile/src/components/RootNavigator/BaseNavigator.tsx @@ -91,6 +91,9 @@ import CustomErrorNavigator from "./CustomErrorNavigator"; import WalletSyncNavigator from "LLM/features/WalletSync/WalletSyncNavigator"; import Web3HubNavigator from "LLM/features/Web3Hub/Navigator"; import { useFeature } from "@ledgerhq/live-common/featureFlags/index"; +import AddAccountsV2Navigator from "LLM/features/Accounts/Navigator"; +import DeviceSelectionNavigator from "LLM/features/DeviceSelection/Navigator"; +import AssetSelectionNavigator from "LLM/features/AssetSelection/Navigator"; const Stack = createStackNavigator(); @@ -109,6 +112,7 @@ export default function BaseNavigator() { const isAccountsEmpty = useSelector(hasNoAccountsSelector); const readOnlyModeEnabled = useSelector(readOnlyModeEnabledSelector) && isAccountsEmpty; const web3hub = useFeature("web3hub"); + const llmNetworkBasedAddAccountFlow = useFeature("llmNetworkBasedAddAccountFlow"); return ( <> @@ -267,11 +271,7 @@ export default function BaseNavigator() { component={ClaimRewardsNavigator} options={{ headerShown: false }} /> - +